diff --git a/.github/workflows/install.yml b/.github/workflows/install.yml index ee097ee501..a7ab3a8f04 100644 --- a/.github/workflows/install.yml +++ b/.github/workflows/install.yml @@ -17,7 +17,6 @@ jobs: py: - "3.11" - "3.10" - - "3.9" env: - pip - conda diff --git a/.gitignore b/.gitignore index f9082380e0..b01c266e47 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,10 @@ c_*.c pufferlib/extensions.c pufferlib/puffernet.c +logs/ + +# Build dir +build/ # hipified cuda extensions dir [HIP/ROCM] pufferlib/extensions/hip/ @@ -18,6 +22,7 @@ cy_*.c # C extensions *.so +*.o # Distribution / packaging .Python @@ -162,3 +167,8 @@ pufferlib/ocean/impulse_wars/*-release/ pufferlib/ocean/impulse_wars/debug-*/ pufferlib/ocean/impulse_wars/release-*/ pufferlib/ocean/impulse_wars/benchmark/ + +# Data +resources/drive/data/* +resources/drive/binaries/* + diff --git a/MANIFEST.in b/MANIFEST.in deleted file mode 100644 index 14b53eb750..0000000000 --- a/MANIFEST.in +++ /dev/null @@ -1,19 +0,0 @@ -global-include *.pyx -global-include *.pxd -global-include *.h -global-include *.cpp -global-include *.cu -global-include *.py -recursive-include pufferlib/config *.ini -recursive-include pufferlib/resources * -recursive-exclude experiments * -recursive-exclude wandb * -recursive-exclude tests * -include raylib-5.5_linux_amd64/lib/libraylib.a -include raylib-5.5_macos/lib/libraylib.a -include box2d-linux-amd64/libbox2d.a -recursive-exclude box2d-web * -recursive-exclude raylib-5.5_webassembly * -recursive-exclude pufferlib/ocean/impulse_wars/debug* * -recursive-exclude pufferlib/ocean/impulse_wars/release* * -recursive-exclude box2d* * diff --git a/README.md b/README.md index dc1bfaa81f..b492d61cf0 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,11 @@ ![figure](https://pufferai.github.io/source/resource/header.png) -[![PyPI version](https://badge.fury.io/py/pufferlib.svg)](https://badge.fury.io/py/pufferlib) -![PyPI - Python Version](https://img.shields.io/pypi/pyversions/pufferlib) -![Github Actions](https://github.com/PufferAI/PufferLib/actions/workflows/install.yml/badge.svg) -[![](https://dcbadge.vercel.app/api/server/spT4huaGYV?style=plastic)](https://discord.gg/spT4huaGYV) -[![Twitter](https://img.shields.io/twitter/url/https/twitter.com/cloudposse.svg?style=social&label=Follow%20%40jsuarez5341)](https://twitter.com/jsuarez5341) +[![Discord](https://dcbadge.vercel.app/api/server/spT4huaGYV?style=plastic)](https://discord.gg/spT4huaGYV) +[![Twitter](https://img.shields.io/twitter/url/https/twitter.com/cloudposse.svg?style=social&label=Follow%20%40jsuarez)](https://twitter.com/jsuarez) -PufferLib is the reinforcement learning library I wish existed during my PhD. It started as a compatibility layer to make working with complex environments a breeze. Now, it's a high-performance toolkit for research and industry with optimized parallel simulation, environments that run and train at 1M+ steps/second, and tons of quality of life improvements for practitioners. All our tools are free and open source. We also offer priority service for companies, startups, and labs! +PufferLib is a fast and sane reinforcement learning library that can train tiny, super-human models in seconds. The included learning algorithm, hyperparameter tuning, and simulation methods are the product of our own research. All our tools are free and open source. Need a high performance environment for your application? We build them professionally and offer training + extended support. Contact jsuarez🐡puffer🐡ai. -![Trailer](https://github.com/PufferAI/puffer.ai/blob/main/docs/assets/puffer_2.gif?raw=true) - -All of our documentation is hosted at [puffer.ai](https://puffer.ai "PufferLib Documentation"). @jsuarez5341 on [Discord](https://discord.gg/puffer) for support -- post here before opening issues. We're always looking for new contributors, too! +All of our documentation is hosted at [puffer.ai](https://puffer.ai "PufferLib Documentation"). @jsuarez5341 on [Discord](https://discord.gg/puffer) for support. Post there before opening issues. We're always looking for new contributors! ## Star to puff up the project! diff --git a/build.sh b/build.sh new file mode 100755 index 0000000000..0a4664756d --- /dev/null +++ b/build.sh @@ -0,0 +1,300 @@ +#!/bin/bash +set -e + +# Usage: +# ./build.sh breakout # Build _C.so with breakout statically linked +# ./build.sh breakout --float # float32 precision (required for --slowly) +# ./build.sh breakout --cpu # CPU fallback, torch only +# ./build.sh breakout --debug # Debug build +# ./build.sh breakout --local # Standalone executable (debug, sanitizers) +# ./build.sh breakout --fast # Standalone executable (optimized) +# ./build.sh breakout --web # Emscripten web build +# ./build.sh breakout --profile # Kernel profiling binary +# ./build.sh all # Build all envs with default and --float + +if [ -z "$1" ]; then + echo "Usage: ./build.sh ENV_NAME [--float] [--debug] [--local|--fast|--web|--profile|--cpu|--all]" + exit 1 +fi +ENV=$1 +shift + +for arg in "$@"; do + case $arg in + --float) PRECISION="-DPRECISION_FLOAT" ;; + --debug) DEBUG=1 ;; + --local) MODE=local ;; + --fast) MODE=fast ;; + --web) MODE=web ;; + --profile) MODE=profile ;; + --cpu) MODE=cpu; PRECISION="-DPRECISION_FLOAT" ;; + *) echo "Error: unknown argument '$arg'" && exit 1 ;; + esac +done + +if [ "$ENV" = "all" ]; then + FAILED="" + for env_dir in ocean/*/; do + env=$(basename "$env_dir") + if bash "$0" "$env" && bash "$0" "$env" --float; then + echo "OK: $env" + else + echo "FAIL: $env" + FAILED="$FAILED\n $env" + fi + done + + if [ -n "$FAILED" ]; then + echo -e "\nFailed builds:$FAILED" + fi + exit 0 +fi + +# Linux/mac +PLATFORM="$(uname -s)" +if [ "$PLATFORM" = "Linux" ]; then + RAYLIB_NAME='raylib-5.5_linux_amd64' + OMP_LIB=-lomp5 + SANITIZE_FLAGS=(-fsanitize=address,undefined,bounds,pointer-overflow,leak -fno-omit-frame-pointer) + STANDALONE_LDFLAGS=(-lGL) + SHARED_LDFLAGS=(-Bsymbolic-functions) +else + RAYLIB_NAME='raylib-5.5_macos' + OMP_LIB=-lomp + SANITIZE_FLAGS=() + STANDALONE_LDFLAGS=(-framework Cocoa -framework IOKit -framework CoreVideo -framework OpenGL) + SHARED_LDFLAGS=(-framework Cocoa -framework OpenGL -framework IOKit -undefined dynamic_lookup) +fi + +CLANG_WARN=( + -Wall + -ferror-limit=3 + -Werror=incompatible-pointer-types + -Werror=return-type + -Wno-error=incompatible-pointer-types-discards-qualifiers + -Wno-incompatible-pointer-types-discards-qualifiers + -Wno-error=array-parameter +) + +download() { + local name=$1 url=$2 + [ -d "$name" ] && return + echo "Downloading $name..." + case "$url" in + *.zip) curl -sL "$url" -o "$name.zip" && unzip -q "$name.zip" && rm "$name.zip" ;; + *) curl -sL "$url" -o "$name.tar.gz" && tar xf "$name.tar.gz" && rm "$name.tar.gz" ;; + esac +} + +RAYLIB_URL="https://github.com/raysan5/raylib/releases/download/5.5" +if [ "$MODE" = "web" ]; then + RAYLIB_NAME='raylib-5.5_webassembly' + download "$RAYLIB_NAME" "$RAYLIB_URL/$RAYLIB_NAME.zip" +else + download "$RAYLIB_NAME" "$RAYLIB_URL/$RAYLIB_NAME.tar.gz" +fi + +RAYLIB_A="$RAYLIB_NAME/lib/libraylib.a" +INCLUDES=(-I./$RAYLIB_NAME/include -I./src -I./vendor) +LINK_ARCHIVES=("$RAYLIB_A") +EXTRA_SRC="" + +if [ "$ENV" = "constellation" ]; then + SRC_DIR="constellation" + EXTRA_SRC="vendor/cJSON.c" + OUTPUT_NAME="seethestars" +elif [ "$ENV" = "trailer" ]; then + SRC_DIR="trailer" + OUTPUT_NAME="trailer/trailer" +elif [ "$ENV" = "impulse_wars" ]; then + SRC_DIR="ocean/$ENV" + if [ "$MODE" = "web" ]; then BOX2D_NAME='box2d-web' + elif [ "$PLATFORM" = "Linux" ]; then BOX2D_NAME='box2d-linux-amd64' + else BOX2D_NAME='box2d-macos-arm64' + fi + BOX2D_URL="https://github.com/capnspacehook/box2d/releases/latest/download" + download "$BOX2D_NAME" "$BOX2D_URL/$BOX2D_NAME.tar.gz" + INCLUDES+=(-I./$BOX2D_NAME/include -I./$BOX2D_NAME/src) + LINK_ARCHIVES+=("./$BOX2D_NAME/libbox2d.a") +elif [ -d "ocean/$ENV" ]; then + SRC_DIR="ocean/$ENV" +else + echo "Error: environment '$ENV' not found" && exit 1 +fi + +OUTPUT_NAME=${OUTPUT_NAME:-$ENV} + +# Standalone environment build +if [ -n "$DEBUG" ] || [ "$MODE" = "local" ]; then + CLANG_OPT=(-g -O0 "${CLANG_WARN[@]}" "${SANITIZE_FLAGS[@]}") + NVCC_OPT="-O0 -g" + LINK_OPT="-g" +else + CLANG_OPT=(-O2 -DNDEBUG "${CLANG_WARN[@]}") + NVCC_OPT="-O2 --threads 0" + LINK_OPT="-O2" +fi +if [ "$MODE" = "local" ] || [ "$MODE" = "fast" ]; then + FLAGS=( + "${INCLUDES[@]}" + "$SRC_DIR/$ENV.c" $EXTRA_SRC -o "$OUTPUT_NAME" + "${LINK_ARCHIVES[@]}" + "${STANDALONE_LDFLAGS[@]}" + -lm -lpthread -fopenmp + -DPLATFORM_DESKTOP + ) + echo "Compiling $ENV..." + ${CC:-clang} "${CLANG_OPT[@]}" "${FLAGS[@]}" + echo "Built: ./$OUTPUT_NAME" + exit 0 +elif [ "$MODE" = "web" ]; then + mkdir -p "build/web/$ENV" + echo "Compiling $ENV for web..." + emcc \ + -o "build/web/$ENV/game.html" \ + "$SRC_DIR/$ENV.c" $EXTRA_SRC \ + -O3 -Wall \ + "${LINK_ARCHIVES[@]}" \ + "${INCLUDES[@]}" \ + -L. -L./$RAYLIB_NAME/lib \ + -sASSERTIONS=2 -gsource-map \ + -sUSE_GLFW=3 -sUSE_WEBGL2=1 -sASYNCIFY -sFILESYSTEM -sFORCE_FILESYSTEM=1 \ + --shell-file vendor/minshell.html \ + -sINITIAL_MEMORY=512MB -sALLOW_MEMORY_GROWTH -sSTACK_SIZE=512KB \ + -DNDEBUG -DPLATFORM_WEB -DGRAPHICS_API_OPENGL_ES3 \ + --preload-file resources/$ENV@resources/$ENV \ + --preload-file resources/shared@resources/shared + echo "Built: build/web/$ENV/game.html" + exit 0 +fi + +# Find cuDNN path +CUDA_HOME=${CUDA_HOME:-${CUDA_PATH:-$(dirname "$(dirname "$(which nvcc)")")}} +CUDNN_IFLAG="" +CUDNN_LFLAG="" +for dir in /usr/local/cuda/include /usr/include; do + if [ -f "$dir/cudnn.h" ]; then + CUDNN_IFLAG="-I$dir" + break + fi +done +for dir in /usr/local/cuda/lib64 /usr/lib/x86_64-linux-gnu; do + if [ -f "$dir/libcudnn.so" ]; then + CUDNN_LFLAG="-L$dir" + break + fi +done +if [ -z "$CUDNN_IFLAG" ]; then + CUDNN_IFLAG=$(python -c "import nvidia.cudnn, os; print('-I' + os.path.join(nvidia.cudnn.__path__[0], 'include'))" 2>/dev/null || echo "") +fi +if [ -z "$CUDNN_LFLAG" ]; then + CUDNN_LFLAG=$(python -c "import nvidia.cudnn, os; print('-L' + os.path.join(nvidia.cudnn.__path__[0], 'lib'))" 2>/dev/null || echo "") +fi + +export CCACHE_DIR="${CCACHE_DIR:-$HOME/.ccache}" +export CCACHE_BASEDIR="$(pwd)" +export CCACHE_COMPILERCHECK=content +NVCC="ccache $CUDA_HOME/bin/nvcc" +CC="${CC:-$(command -v ccache >/dev/null && echo 'ccache clang' || echo 'clang')}" +ARCH=${NVCC_ARCH:-native} + +PYTHON_INCLUDE=$(python -c "import sysconfig; print(sysconfig.get_path('include'))") +PYBIND_INCLUDE=$(python -c "import pybind11; print(pybind11.get_include())") +NUMPY_INCLUDE=$(python -c "import numpy; print(numpy.get_include())") +EXT_SUFFIX=$(python -c "import sysconfig; print(sysconfig.get_config_var('EXT_SUFFIX'))") +OUTPUT="pufferlib/_C${EXT_SUFFIX}" + +BINDING_SRC="$SRC_DIR/binding.c" +mkdir -p build +STATIC_OBJ="build/libstatic_${ENV}.o" +STATIC_LIB="build/libstatic_${ENV}.a" + +if [ ! -f "$BINDING_SRC" ]; then + echo "Error: $BINDING_SRC not found" + exit 1 +fi + +echo "Compiling static library for $ENV..." +${CC:-clang} -c "${CLANG_OPT[@]}" \ + -I. -Isrc -I$SRC_DIR -Ivendor \ + -I./$RAYLIB_NAME/include -I$CUDA_HOME/include \ + -DPLATFORM_DESKTOP \ + -fno-semantic-interposition -fvisibility=hidden \ + -fPIC -fopenmp \ + "$BINDING_SRC" -o "$STATIC_OBJ" +ar rcs "$STATIC_LIB" "$STATIC_OBJ" + +# Brittle hack: have to extract the tensor type from the static lib to build trainer +OBS_TENSOR_T=$(awk '/^#define OBS_TENSOR_T/{print $3}' "$BINDING_SRC") +if [ -z "$OBS_TENSOR_T" ]; then + echo "Error: Could not find OBS_TENSOR_T in $BINDING_SRC" + exit 1 +fi + +if [ -z "$MODE" ]; then + echo "Compiling CUDA ($ARCH) training backend..." + $NVCC -c -arch=$ARCH -Xcompiler -fPIC \ + -Xcompiler=-D_GLIBCXX_USE_CXX11_ABI=1 \ + -Xcompiler=-DNPY_NO_DEPRECATED_API=NPY_1_7_API_VERSION \ + -Xcompiler=-DPLATFORM_DESKTOP \ + -std=c++17 \ + -I. -Isrc \ + -I$PYTHON_INCLUDE -I$PYBIND_INCLUDE -I$NUMPY_INCLUDE \ + -I$CUDA_HOME/include $CUDNN_IFLAG -I$RAYLIB_NAME/include \ + -Xcompiler=-fopenmp \ + -DOBS_TENSOR_T=$OBS_TENSOR_T \ + -DENV_NAME=$ENV \ + $PRECISION $NVCC_OPT \ + src/bindings.cu -o build/bindings.o + + LINK_CMD=( + ${CXX:-g++} -shared -fPIC -fopenmp + build/bindings.o "$STATIC_LIB" "$RAYLIB_A" + -L$CUDA_HOME/lib64 $CUDNN_LFLAG + -lcudart -lnccl -lnvidia-ml -lcublas -lcusolver -lcurand -lcudnn + $OMP_LIB $LINK_OPT + "${SHARED_LDFLAGS[@]}" + -o "$OUTPUT" + ) + "${LINK_CMD[@]}" + echo "Built: $OUTPUT" + +elif [ "$MODE" = "cpu" ]; then + echo "Compiling CPU training backend..." + ${CXX:-g++} -c -fPIC -fopenmp \ + -D_GLIBCXX_USE_CXX11_ABI=1 \ + -DPLATFORM_DESKTOP \ + -std=c++17 \ + -I. -Isrc \ + -I$PYTHON_INCLUDE -I$PYBIND_INCLUDE \ + -DOBS_TENSOR_T=$OBS_TENSOR_T \ + -DENV_NAME=$ENV \ + $PRECISION $LINK_OPT \ + src/bindings_cpu.cpp -o build/bindings_cpu.o + LINK_CMD=( + ${CXX:-g++} -shared -fPIC -fopenmp + build/bindings_cpu.o "$STATIC_LIB" "$RAYLIB_A" + -lm -lpthread $OMP_LIB $LINK_OPT + "${SHARED_LDFLAGS[@]}" + -o "$OUTPUT" + ) + "${LINK_CMD[@]}" + echo "Built: $OUTPUT" + +elif [ "$MODE" = "profile" ]; then + echo "Compiling profile binary ($ARCH)..." + $NVCC $NVCC_OPT -arch=$ARCH -std=c++17 \ + -I. -Isrc -I$SRC_DIR -Ivendor \ + -I$CUDA_HOME/include $CUDNN_IFLAG -I$RAYLIB_NAME/include \ + -DOBS_TENSOR_T=$OBS_TENSOR_T \ + -DENV_NAME=$ENV \ + -Xcompiler=-DPLATFORM_DESKTOP \ + $PRECISION \ + -Xcompiler=-fopenmp \ + tests/profile_kernels.cu vendor/ini.c \ + "$STATIC_LIB" "$RAYLIB_A" \ + -lnccl -lnvidia-ml -lcublas -lcurand -lcudnn \ + -lGL -lm -lpthread $OMP_LIB \ + -o profile + echo "Built: ./profile" +fi diff --git a/config b/config deleted file mode 120000 index 662c3e7429..0000000000 --- a/config +++ /dev/null @@ -1 +0,0 @@ -pufferlib/config/ \ No newline at end of file diff --git a/pufferlib/config/ocean/asteroids.ini b/config/asteroids.ini similarity index 87% rename from pufferlib/config/ocean/asteroids.ini rename to config/asteroids.ini index 754d624184..1413b1d8af 100644 --- a/pufferlib/config/ocean/asteroids.ini +++ b/config/asteroids.ini @@ -1,8 +1,5 @@ [base] -package = ocean -env_name = puffer_asteroids -policy_name = Policy -rnn_name = Recurrent +env_name = asteroids [vec] num_envs = 8 @@ -17,7 +14,7 @@ adam_beta2 = 0.9999436458974764 adam_eps = 6.915036275112011e-08 anneal_lr = true batch_size = auto -bptt_horizon = 64 +horizon = 64 checkpoint_interval = 200 clip_coef = 0.18588778503512546 ent_coef = 0.0016620361911332262 diff --git a/pufferlib/config/ocean/battle.ini b/config/battle.ini similarity index 91% rename from pufferlib/config/ocean/battle.ini rename to config/battle.ini index dcb4baa0f5..ddf3bcd3f3 100644 --- a/pufferlib/config/ocean/battle.ini +++ b/config/battle.ini @@ -1,16 +1,9 @@ [base] -package = ocean -env_name = puffer_battle -policy_name = Policy -rnn_name = Recurrent +env_name = battle [policy] hidden_size = 512 -[rnn] -input_size = 512 -hidden_size = 512 - [vec] num_envs = 16 diff --git a/pufferlib/config/ocean/target.ini b/config/benchmark.ini similarity index 50% rename from pufferlib/config/ocean/target.ini rename to config/benchmark.ini index a65bdad32a..93c87684d5 100644 --- a/pufferlib/config/ocean/target.ini +++ b/config/benchmark.ini @@ -1,13 +1,13 @@ [base] -package = ocean -env_name = puffer_target -policy_name = Policy -rnn_name = Recurrent +env_name = benchmark [env] -num_envs = 512 -num_agents = 8 -num_goals = 4 +bandwidth = 512 +compute = 0 + +[vec] +total_agents = 8192 +num_buffers = 2 [train] total_timesteps = 100_000_000 diff --git a/pufferlib/config/ocean/blastar.ini b/config/blastar.ini similarity index 74% rename from pufferlib/config/ocean/blastar.ini rename to config/blastar.ini index ddde003969..c91bf130b8 100644 --- a/pufferlib/config/ocean/blastar.ini +++ b/config/blastar.ini @@ -1,11 +1,11 @@ [base] -package = ocean -env_name = puffer_blastar -policy_name = Policy -rnn_name = Recurrent +env_name = blastar + +[vec] +total_agents = 4096 [env] -num_envs = 4096 +num_obs = 10 [train] total_timesteps = 200_000_000 diff --git a/pufferlib/config/ocean/boids.ini b/config/boids.ini similarity index 90% rename from pufferlib/config/ocean/boids.ini rename to config/boids.ini index 2f8412d248..d685a42c6b 100644 --- a/pufferlib/config/ocean/boids.ini +++ b/config/boids.ini @@ -1,9 +1,5 @@ [base] -package = ocean -env_name = puffer_boids -policy_name = Boids -rnn_name = Recurrent -; rnn_name = None +env_name = boids [env] num_envs = 64 diff --git a/config/boxoban.ini b/config/boxoban.ini new file mode 100644 index 0000000000..f076ab74b6 --- /dev/null +++ b/config/boxoban.ini @@ -0,0 +1,44 @@ +[base] +env_name = boxoban + +[vec] +total_agents = 32768 +num_buffers = 4 +num_threads = 1 + +[env] +num_agents = 1 +difficulty = 2 +int_r_coeff = 0.25 +target_loss_pen_coeff = 0 +max_steps = 150 + +[policy] +hidden_size = 512 +num_layers = 3.32422 +expansion_factor = 1 + +[train] +gpus = 1 +seed = 42 +total_timesteps = 880580001 +learning_rate = 0.00134234 +anneal_lr = 1 +min_lr_ratio = 0.37872 +gamma = 0.989717 +gae_lambda = 0.759273 +replay_ratio = 1.6234 +clip_coef = 0.01 +vf_coef = 5 +vf_clip_coef = 5 +max_grad_norm = 1.20325 +ent_coef = 0.000188411 +beta1 = 0.995526 +beta2 = 0.999536 +eps = 1e-14 +minibatch_size = 32768 +horizon = 64 +vtrace_rho_clip = 3.13347 +vtrace_c_clip = 2.75328 +prio_alpha = 0.453827 +prio_beta0 = 0.765589 diff --git a/config/breakout.ini b/config/breakout.ini new file mode 100644 index 0000000000..7da69ca2b8 --- /dev/null +++ b/config/breakout.ini @@ -0,0 +1,125 @@ +[base] +env_name = breakout + +[vec] +total_agents = 4096 +num_buffers = 8 +num_threads = 8 + +[policy] +num_layers = 2 +hidden_size = 64 + +[env] +num_agents = 1 +frameskip = 4 +width = 576 +height = 330 +initial_paddle_width = 62 +paddle_width = 62 +paddle_height = 8 +ball_width = 32 +ball_height = 32 +brick_width = 32 +brick_height = 12 +brick_rows = 6 +brick_cols = 18 +initial_ball_speed = 256 +max_ball_speed = 448 +paddle_speed = 620 +continuous = 0 + +[train] +total_timesteps = 94_000_000 +beta1 = 0.7279714073125252 +beta2 = 0.9986265112492152 +clip_coef = 0.6746497927896418 +ent_coef = 0.0033240721522812535 +eps = 0.00008339460257113628 +gae_lambda = 0.948721675814334 +gamma = 0.9721246598992744 +learning_rate = 0.1 +max_grad_norm = 1.8109182724544075 +minibatch_size = 65_536 +prio_alpha = 0.1 +prio_beta0 = 0.8247156461060179 +replay_ratio = 1.4242098997083206 +vf_clip_coef = 1.2291681640124468 +vf_coef = 1.2195502588297364 +vtrace_c_clip = 1.0830442742115065 +vtrace_rho_clip = 2.1017317041552603 + +#total_timesteps = 50_000_000 +#learning_rate = 0.045759 +#beta1 = 0.9542662897340632 +#beta2 = 0.9999020741216518 +#gamma = 0.998997162035256 +#gae_lambda = 0.5999999999999999 +#replay_ratio = 1.087305 +#clip_coef = 0.290339 +#vf_coef = 3.503804 +#vf_clip_coef = 1.700646 +#max_grad_norm = 0.269836 +#ent_coef = 0.013233 +#eps = 0.000012 +#minibatch_size = 32768.000000 +#horizon = 64.000000 +#vtrace_rho_clip = 5.000000 +#vtrace_c_clip = 4.825702 +#prio_alpha = 0.9804697934777868 +#prio_beta0 = 0.09999999999999998 + +#total_timesteps = 120_000_000 +#adam_beta1 = 0.8166332218104871 +#adam_beta2 = 0.9984879989750705 +#adam_eps = 0.0001 +#batch_size = auto +#horizon = 64 +#clip_coef = 0.42526610231849393 +#ent_coef = 0.0026822968018267775 +#gae_lambda = 0.995 +#gamma = 0.9731819086255716 +#learning_rate = 0.04301709139429238 +#max_grad_norm = 0.7029618837611082 +#minibatch_size = 16384 +#prio_alpha = 0.09999999999999998 +#prio_beta0 = 0.8437844355214735 +#vf_clip_coef = 0.807798225723059 +#vf_coef = 2.9089121311247554 +#vtrace_c_clip = 1.6205569942514606 +#vtrace_rho_clip = 1.1777184656786774 + +#total_timesteps = 40_000_000 +#adam_beta1 = 0.9389740236912132 +#adam_beta2 = 0.9998225039929157 +#adam_eps = 1.0267361590791064e-8 +#batch_size = auto +#horizon = 64 +#clip_coef = 0.01557913923814178 +#ent_coef = 0.0031759371032913 +#gae_lambda = 0.916681264452842 +#gamma = 0.9997053654668936 +#learning_rate = 0.012744235594115342 +#max_grad_norm = 1.8013800046071862 +#num_minibatches = 8 +#minibatch_size = 4096 +#prio_alpha = 0.9500430793857082 +#prio_beta0 = 0.9436845548994959 +#vf_clip_coef = 0.1 +#vf_coef = 2.5994729835919834 +#vtrace_c_clip = 2.878171091654008 +#vtrace_rho_clip = 1.3235791596831579 + +[sweep.train.total_timesteps] +distribution = log_normal +min = 3e7 +max = 2e8 +mean = 8e7 +scale = auto + +[sweep.env.frameskip] +distribution = int_uniform +min = 1 +max = 8 +mean = 4 +scale = 2.0 diff --git a/config/cartpole.ini b/config/cartpole.ini new file mode 100644 index 0000000000..8de0ad6147 --- /dev/null +++ b/config/cartpole.ini @@ -0,0 +1,57 @@ +[base] +env_name = cartpole + +[vec] +total_agents = 4096 +num_buffers = 4.78896 +num_threads = 16 + +[env] +cart_mass = 1 +pole_mass = 0.1 +pole_length = 0.5 +gravity = 9.8 +force_mag = 10 +dt = 0.02 +continuous = 0 + +[policy] +hidden_size = 32 +num_layers = 2.11327 +expansion_factor = 1 + +[train] +gpus = 1 +seed = 42 +total_timesteps = 5642560 +learning_rate = 0.1 +anneal_lr = 1 +min_lr_ratio = 0 +gamma = 0.8 +gae_lambda = 0.922151 +replay_ratio = 0.381289 +clip_coef = 0.143548 +vf_coef = 1.77975 +vf_clip_coef = 3.90833 +max_grad_norm = 0.329667 +ent_coef = 0.0367726 +beta1 = 0.942691 +beta2 = 0.907572 +eps = 4.6046e-09 +minibatch_size = 16384 +horizon = 32 +vtrace_rho_clip = 2.91145 +vtrace_c_clip = 1.66148 +prio_alpha = 0.786776 +prio_beta0 = 0.348617 +use_rnn = 1 + +[sweep] +method = Protein +metric = perf + +[sweep.train.total_timesteps] +distribution = log_normal +min = 5e6 +max = 2e7 +mean = 1e7 diff --git a/config/chain_mdp.ini b/config/chain_mdp.ini new file mode 100644 index 0000000000..5361efdb4a --- /dev/null +++ b/config/chain_mdp.ini @@ -0,0 +1,17 @@ +[base] +env_name = chain_mdp + +[vec] +num_envs = 8 + +[env] +num_envs = 512 +size = 128 + +[policy] +hidden_size = 128 + +[train] +total_timesteps = 5_000_000 +horizon = 64 +entropy_coef = 0.1 \ No newline at end of file diff --git a/pufferlib/config/ocean/checkers.ini b/config/checkers.ini similarity index 61% rename from pufferlib/config/ocean/checkers.ini rename to config/checkers.ini index 91eb417f5a..63cdfd5fcc 100644 --- a/pufferlib/config/ocean/checkers.ini +++ b/config/checkers.ini @@ -1,8 +1,5 @@ [base] -package = ocean -env_name = puffer_checkers -policy_name = Policy -rnn_name = Recurrent +env_name = checkers [env] num_envs = 4096 diff --git a/config/connect4.ini b/config/connect4.ini new file mode 100644 index 0000000000..c7cf7d7e24 --- /dev/null +++ b/config/connect4.ini @@ -0,0 +1,50 @@ +[base] +env_name = connect4 + +[vec] +total_agents = 4096 +num_buffers = 8 +num_threads = 2 + +[env] +num_agents = 1 +player_pieces = 0 +env_pieces = 0 + +[policy] +hidden_size = 256 +num_layers = 1 +expansion_factor = 1 + +[train] +gpus = 1 +seed = 42 +total_timesteps = 13272299 +learning_rate = 0.00847027 +anneal_lr = 1 +min_lr_ratio = 0 +gamma = 0.8 +gae_lambda = 0.962627 +replay_ratio = 3.16619 +clip_coef = 0.511829 +vf_coef = 5 +vf_clip_coef = 1.99178 +max_grad_norm = 0.552251 +ent_coef = 3.24222e-05 +beta1 = 0.878636 +beta2 = 0.986336 +eps = 3.02623e-07 +minibatch_size = 8192 +horizon = 32 +vtrace_rho_clip = 2.49786 +vtrace_c_clip = 1.52028 +prio_alpha = 1 +prio_beta0 = 0.746205 +use_rnn = 1 + +[sweep.train.total_timesteps] +distribution = log_normal +min = 1e7 +max = 2e8 +mean = 3e7 +scale = 0.5 diff --git a/pufferlib/config/ocean/continuous.ini b/config/continuous.ini similarity index 78% rename from pufferlib/config/ocean/continuous.ini rename to config/continuous.ini index fd35cd4854..3e63b3b899 100644 --- a/pufferlib/config/ocean/continuous.ini +++ b/config/continuous.ini @@ -1,6 +1,5 @@ [base] -package = ocean -env_name = puffer_continuous +env_name = continuous [train] total_timesteps = 1_000_000 diff --git a/pufferlib/config/ocean/convert.ini b/config/convert.ini similarity index 63% rename from pufferlib/config/ocean/convert.ini rename to config/convert.ini index 53c91519e7..05b98568a1 100644 --- a/pufferlib/config/ocean/convert.ini +++ b/config/convert.ini @@ -1,15 +1,13 @@ [base] -package = ocean -env_name = puffer_convert -policy_name = Policy -rnn_name = Recurrent +env_name = convert [vec] -num_envs = 16 +total_agents = 16384 [env] -num_envs = 1 num_agents = 1024 +width = 1920 +height = 1080 num_factories = 32 num_resources = 8 diff --git a/pufferlib/config/ocean/convert_circle.ini b/config/convert_circle.ini similarity index 72% rename from pufferlib/config/ocean/convert_circle.ini rename to config/convert_circle.ini index 60dfd34677..f4eeb7c880 100644 --- a/pufferlib/config/ocean/convert_circle.ini +++ b/config/convert_circle.ini @@ -1,8 +1,5 @@ [base] -package = ocean -env_name = puffer_convert_circle -policy_name = Policy -rnn_name = Recurrent +env_name = convert_circle [vec] num_envs = 16 diff --git a/pufferlib/config/default.ini b/config/default.ini similarity index 59% rename from pufferlib/config/default.ini rename to config/default.ini index be6fe354d5..fd53bf7d95 100644 --- a/pufferlib/config/default.ini +++ b/config/default.ini @@ -1,62 +1,65 @@ [base] -package = None env_name = None -policy_name = Policy -rnn_name = None + +# Multi-GPU (single GPU defaults) +rank = 0 +world_size = 1 +gpu_id = 0 +nccl_id = 'None' +profile = False +checkpoint_dir = checkpoints +log_dir = logs +checkpoint_interval = 200 +eval_episodes = 10000 + +# Epoch at which to capture CUDA graphs. -1 to disable. +cudagraphs = 10 +seed = 73 + +# Whether to reset the LSTM state between epochs. We only use +# this for evals and have not tested it for training. +reset_state = True [vec] -backend = Multiprocessing -num_envs = 2 -num_workers = auto -batch_size = auto -zero_copy = True -seed = 42 +total_agents = 4096 +num_buffers = 2 +num_threads = 16 +# Args used by your env's binding.c go here [env] + [policy] -[rnn] +hidden_size = 128 +num_layers = 4 +expansion_factor = 1 -[train] -name = pufferai -project = ablations +[torch] +network = MinGRU +encoder = DefaultEncoder +decoder = DefaultDecoder +[train] +gpus = 1 seed = 42 -torch_deterministic = True -cpu_offload = False -device = cuda -optimizer = muon -precision = float32 total_timesteps = 10_000_000 learning_rate = 0.015 -anneal_lr = True +anneal_lr = 1 min_lr_ratio = 0.0 gamma = 0.995 gae_lambda = 0.90 -update_epochs = 1 +replay_ratio = 1.0 clip_coef = 0.2 vf_coef = 2.0 vf_clip_coef = 0.2 max_grad_norm = 1.5 ent_coef = 0.001 -adam_beta1 = 0.95 -adam_beta2 = 0.999 -adam_eps = 1e-12 - -data_dir = experiments -checkpoint_interval = 200 -batch_size = auto +beta1 = 0.95 +beta2 = 0.999 +eps = 1e-12 minibatch_size = 8192 - -# Accumulate gradients above this size -max_minibatch_size = 32768 -bptt_horizon = 64 -compile = False -compile_mode = max-autotune-no-cudagraphs -compile_fullgraph = True - +horizon = 64 vtrace_rho_clip = 1.0 vtrace_c_clip = 1.0 - prio_alpha = 0.8 prio_beta0 = 0.2 @@ -66,33 +69,52 @@ metric = score metric_distribution = linear goal = maximize max_suggestion_cost = 3600 +max_runs = 1200 +gpus = 0 downsample = 5 use_gpu = True prune_pareto = True early_stop_quantile = 0.3 -#[sweep.vec.num_envs] -#distribution = uniform_pow2 -#min = 1 -#max = 16 -#scale = auto - -# TODO: Elim from base [sweep.train.total_timesteps] distribution = log_normal min = 3e7 -max = 1e10 +max = 1e11 scale = time -[sweep.train.bptt_horizon] +[sweep.policy.hidden_size] +distribution = uniform_pow2 +min = 32 +max = 1024 +scale = auto + +[sweep.policy.num_layers] +distribution = uniform +min = 1 +max = 8 +scale = auto + +[sweep.vec.total_agents] +distribution = uniform_pow2 +min = 256 +max = 16384 +scale = auto + +[sweep.vec.num_buffers] +distribution = uniform +min = 1 +max = 8 +scale = auto + +[sweep.train.horizon] distribution = uniform_pow2 -min = 16 -max = 64 +min = 8 +max = 1024 scale = auto [sweep.train.minibatch_size] distribution = uniform_pow2 -min = 8192 +min = 4096 max = 65536 scale = auto @@ -102,12 +124,6 @@ min = 0.00001 max = 0.1 scale = 0.5 -[sweep.train.min_lr_ratio] -distribution = uniform -min = 0.0 -max = 0.5 -scale = auto - [sweep.train.ent_coef] distribution = log_normal min = 0.00001 @@ -122,7 +138,8 @@ scale = auto [sweep.train.gae_lambda] distribution = logit_normal -min = 0.6 +min = 0.2 +#min = 0.6 max = 0.995 scale = auto @@ -138,14 +155,15 @@ min = 0.1 max = 5.0 scale = auto -#[sweep.train.update_epochs] -#distribution = int_uniform -#min = 1 -#max = 8 -#scale = 2.0 +[sweep.train.replay_ratio] +distribution = uniform +min = 0.25 +max = 4.0 +scale = auto [sweep.train.clip_coef] distribution = uniform +# Lower clip is sometimes better but less stable min = 0.01 max = 1.0 scale = auto @@ -154,7 +172,7 @@ scale = auto # but this results in jank unstable runs [sweep.train.vf_clip_coef] distribution = uniform -min = 0.1 +min = 0.01 max = 5.0 scale = auto @@ -170,32 +188,32 @@ min = 0.1 max = 5.0 scale = auto -[sweep.train.adam_beta1] +[sweep.train.beta1] distribution = logit_normal min = 0.5 max = 0.999 scale = auto -[sweep.train.adam_beta2] +[sweep.train.beta2] distribution = logit_normal min = 0.9 max = 0.99999 scale = auto -[sweep.train.adam_eps] +[sweep.train.eps] distribution = log_normal min = 1e-14 max = 1e-4 scale = auto [sweep.train.prio_alpha] -distribution = logit_normal -min = 0.1 -max = 0.99 +distribution = uniform +min = 0.0 +max = 1.0 scale = auto [sweep.train.prio_beta0] -distribution = logit_normal -min = 0.1 -max = 0.99 +distribution = uniform +min = 0.0 +max = 1.0 scale = auto diff --git a/config/drive.ini b/config/drive.ini new file mode 100644 index 0000000000..6a9670c8d6 --- /dev/null +++ b/config/drive.ini @@ -0,0 +1,77 @@ +[base] +env_name = drive + +[vec] +total_agents = 8192 +num_buffers = 2 +num_threads = 2 + +[env] +width = 1280 +height = 1024 +human_agent_idx = 0 +reward_vehicle_collision = -0.2 +reward_offroad_collision = -0.2 +reward_goal_post_respawn = 0 +reward_vehicle_collision_post_respawn = 0 +resample_frequency = 10000 +num_maps = 500 + +[policy] +hidden_size = 256 +num_layers = 4 +expansion_factor = 1 + +[train] +gpus = 1 +seed = 42 +total_timesteps = 1667760009 +learning_rate = 0.001 +anneal_lr = 1 +min_lr_ratio = 0 +gamma = 0.98 +gae_lambda = 0.95 +replay_ratio = 1 +clip_coef = 0.2 +vf_coef = 2 +vf_clip_coef = 0.2 +max_grad_norm = 1.5 +ent_coef = 0.005 +beta1 = 0.95 +beta2 = 0.999 +eps = 1e-12 +minibatch_size = 8192 +horizon = 128 +vtrace_rho_clip = 1 +vtrace_c_clip = 1 +prio_alpha = 0.8 +prio_beta0 = 0.2 + +[sweep.train.total_timesteps] +distribution = log_normal +min = 3e8 +max = 3e9 +mean = 1e9 +scale = auto + +[sweep.env.reward_vehicle_collision] +distribution = uniform +min = -1.0 +max = 0.0 +mean = -0.2 +scale = auto + +[sweep.env.reward_offroad_collision] +distribution = uniform +min = -1.0 +max = 0.0 +mean = -0.2 +scale = auto + +[sweep.env.reward_goal_post_respawn] +distribution = uniform +min = 0.0 +max = 1.0 +mean = 0.5 +scale = auto + diff --git a/config/drone.ini b/config/drone.ini new file mode 100644 index 0000000000..13811e882a --- /dev/null +++ b/config/drone.ini @@ -0,0 +1,85 @@ +[base] +env_name = drone + +[vec] +total_agents = 2048 +num_buffers = 8 +num_threads = 1 + +[env] +task = 1 +num_drones = 64 +max_rings = 10 +alpha_dist = 0.782192 +alpha_hover = 0.071445 +alpha_omega = 0.00135588 +alpha_shaping = 3.9754 +hover_target_dist = 5 +hover_dist = 0.1 +hover_omega = 0.1 +hover_vel = 0.1 + +[policy] +hidden_size = 128 +num_layers = 3.80354 +expansion_factor = 1 + +[train] +gpus = 1 +seed = 42 +total_timesteps = 40000000 +learning_rate = 0.00975033 +anneal_lr = 1 +min_lr_ratio = 0 +gamma = 0.981094 +gae_lambda = 0.883828 +replay_ratio = 2.25498 +clip_coef = 0.067834 +vf_coef = 4.42222 +vf_clip_coef = 3.42278 +max_grad_norm = 0.692201 +ent_coef = 9.62597e-05 +beta1 = 0.914207 +beta2 = 0.99988 +eps = 1e-14 +minibatch_size = 8192 +horizon = 32 +vtrace_rho_clip = 3.32822 +vtrace_c_clip = 4.37219 +prio_alpha = 0.427293 +prio_beta0 = 1 + +[sweep.train.total_timesteps] +distribution = log_normal +min = 4e7 +max = 3e8 +mean = 1e8 +scale = auto + +[sweep.env.alpha_dist] +distribution = log_normal +min = 0.1 +max = 100.0 +mean = 1.0 +scale = auto + +[sweep.env.alpha_omega] +distribution = log_normal +min = 0.0001 +max = 1.0 +mean = 0.001 +scale = auto + +[sweep.env.alpha_hover] +distribution = log_normal +min = 0.001 +max = 1.0 +mean = 0.01 +scale = auto + +[sweep.env.alpha_shaping] +distribution = log_normal +min = 0.01 +max = 10.0 +mean = 1.0 +scale = auto diff --git a/config/enduro.ini b/config/enduro.ini new file mode 100644 index 0000000000..2a8236b202 --- /dev/null +++ b/config/enduro.ini @@ -0,0 +1,57 @@ +[base] +env_name = enduro + +[vec] +total_agents = 256 +num_buffers = 4.00702 +num_threads = 2 + +[env] +width = 152 +height = 210 +car_width = 16 +car_height = 11 +max_enemies = 10 +continuous = 0 + +[policy] +hidden_size = 128 +num_layers = 2.68359 +expansion_factor = 1 + +[train] +gpus = 1 +seed = 42 +total_timesteps = 58957801 +learning_rate = 0.0136314 +anneal_lr = 1 +min_lr_ratio = 0 +gamma = 0.979826 +gae_lambda = 0.908362 +replay_ratio = 1.54521 +clip_coef = 0.915672 +vf_coef = 0.977532 +vf_clip_coef = 1.75503 +max_grad_norm = 1.08789 +ent_coef = 0.00246004 +beta1 = 0.840696 +beta2 = 0.999975 +eps = 1.78423e-12 +minibatch_size = 16384 +horizon = 64 +vtrace_rho_clip = 2.58586 +vtrace_c_clip = 5 +prio_alpha = 1 +prio_beta0 = 0.161561 +max_minibatch_size = 32768 +use_rnn = 1 + +[sweep] +metric = days_completed + +[sweep.train.total_timesteps] +distribution = log_normal +min = 2e8 +max = 6e8 +mean = 4e8 +scale = auto diff --git a/config/freeway.ini b/config/freeway.ini new file mode 100644 index 0000000000..5d3ea33f6c --- /dev/null +++ b/config/freeway.ini @@ -0,0 +1,68 @@ +[base] +env_name = freeway + +[vec] +total_agents = 16384 +num_buffers = 6.8738 +num_threads = 2 +num_agents = 4096 + +[env] +frameskip = 4 +width = 1216 +height = 720 +player_width = 64 +player_height = 64 +car_width = 64 +car_height = 40 +lane_size = 64 +difficulty = 0 +level = -1 +enable_human_player = 0 +env_randomization = 1 +use_dense_rewards = 1 + +[policy] +hidden_size = 128 +num_layers = 7.44076 +expansion_factor = 1 +num_units = 64 + +[legacy] +torch_deterministic = 1 +cpu_offload = 0 +compile = 0 +compile_fullgraph = 1 + +[train] +gpus = 1 +seed = 42 +total_timesteps = 403702026 +learning_rate = 0.00357256 +anneal_lr = 1 +min_lr_ratio = 0 +gamma = 0.988734 +gae_lambda = 0.759081 +replay_ratio = 2.08083 +clip_coef = 0.168047 +vf_coef = 3.51248 +vf_clip_coef = 0.179612 +max_grad_norm = 5 +ent_coef = 0.00023521 +beta1 = 0.973725 +beta2 = 0.99942 +eps = 4.24651e-14 +minibatch_size = 32768 +horizon = 64 +vtrace_rho_clip = 2.3679 +vtrace_c_clip = 1.29213 +prio_alpha = 0.741968 +prio_beta0 = 0.654176 +use_rnn = 1 + +[sweep.train.total_timesteps] +distribution = log_normal +min = 3e8 +max = 6e8 +mean = 4e8 +scale = auto diff --git a/config/g2048.ini b/config/g2048.ini new file mode 100644 index 0000000000..3ef22c31f5 --- /dev/null +++ b/config/g2048.ini @@ -0,0 +1,66 @@ +[base] +env_name = g2048 + +[vec] +total_agents = 8192 +num_buffers = 2.8239 +num_threads = 0 +seed = 73 + +[env] +scaffolding_ratio = 0.384917 + +[policy] +hidden_size = 512 +num_layers = 4.07473 +expansion_factor = 1 + +[train] +gpus = 1 +seed = 42 +total_timesteps = 1443360107 +learning_rate = 0.00224872 +anneal_lr = 1 +min_lr_ratio = 0 +gamma = 0.99816 +gae_lambda = 0.696214 +replay_ratio = 2.2381 +clip_coef = 0.01 +vf_coef = 0.1 +vf_clip_coef = 0.01 +max_grad_norm = 1.14364 +ent_coef = 0.0208185 +beta1 = 0.981226 +beta2 = 0.994178 +eps = 1.82223e-06 +minibatch_size = 32768 +horizon = 64 +vtrace_rho_clip = 3.24229 +vtrace_c_clip = 3.95664 +prio_alpha = 1 +prio_beta0 = 0.555562 +env = 0 + +[sweep] +max_suggestion_cost = 7200 + +[sweep.env.scaffolding_ratio] +distribution = uniform +min = 0.1 +mean = 0.5 +max = 0.8 +scale = auto + +[sweep.train.learning_rate] +distribution = uniform +min = 0.0001 +mean = 0.0005 +max = 0.0030 +scale = 0.5 + +[sweep.train.max_grad_norm] +distribution = uniform +min = 0.1 +mean = 0.5 +max = 2.0 +scale = 0.5 diff --git a/config/go.ini b/config/go.ini new file mode 100644 index 0000000000..e108178f23 --- /dev/null +++ b/config/go.ini @@ -0,0 +1,89 @@ +[base] +env_name = go + +[vec] +total_agents = 256 +num_buffers = 4.61143 +num_threads = 2 + +[env] +width = 950 +height = 750 +grid_size = 9 +board_width = 600 +board_height = 600 +grid_square_size = 64 +moves_made = 0 +komi = 7.5 +last_capture_position = -1 +reward_move_pass = -0.518441 +reward_move_valid = 0 +reward_move_invalid = -0.0864746 +reward_opponent_capture = -0.102283 +reward_player_capture = 0.553628 +selfplay = 0 + +[policy] +hidden_size = 512 +num_layers = 1.6302 +expansion_factor = 1 + +[train] +gpus = 1 +seed = 42 +total_timesteps = 146817001 +learning_rate = 0.00034529 +anneal_lr = 1 +min_lr_ratio = 0 +gamma = 0.925771 +gae_lambda = 0.983152 +replay_ratio = 3.75422 +clip_coef = 0.465704 +vf_coef = 3.58533 +vf_clip_coef = 2.38262 +max_grad_norm = 0.1 +ent_coef = 7.39777e-05 +beta1 = 0.995692 +beta2 = 0.999933 +eps = 2.93928e-09 +minibatch_size = 16384 +horizon = 128 +vtrace_rho_clip = 2.18666 +vtrace_c_clip = 0.638156 +prio_alpha = 0 +prio_beta0 = 0.809042 + +[sweep.train.total_timesteps] +distribution = log_normal +min = 1e8 +max = 1e9 +mean = 3e8 +scale = auto + +[sweep.env.reward_move_invalid] +distribution = uniform +min = -1.0 +max = 0.0 +mean = -0.5 +scale = 0.5 + +[sweep.env.reward_move_pass] +distribution = uniform +min = -1.0 +max = 0.0 +mean = -0.5 +scale = 0.5 + +[sweep.env.reward_player_capture] +distribution = uniform +min = 0.0 +max = 1.0 +mean = 0.5 +scale = 0.5 + +[sweep.env.reward_opponent_capture] +distribution = uniform +min = -1.0 +max = 0.0 +mean = -0.5 +scale = 0.5 diff --git a/config/hex.ini b/config/hex.ini new file mode 100644 index 0000000000..1a8673d43e --- /dev/null +++ b/config/hex.ini @@ -0,0 +1,50 @@ +[base] +env_name = hex + +[vec] +total_agents = 4096 +num_buffers = 8 +num_threads = 2 + +[env] +random_opponent = 0 + +[policy] +hidden_size = 256 +num_layers = 1 +expansion_factor = 1 + +[train] +gpus = 1 +seed = 1 +total_timesteps = 20_000_000 +learning_rate = 1e-2 +anneal_lr = 1 +min_lr_ratio = 0.01 +gamma = 0.8 +gae_lambda = 0.962627 +replay_ratio = 1. +clip_coef = 0.511829 +vf_coef = 5 +vf_clip_coef = 1.99178 +max_grad_norm = 0.552251 +ent_coef = 1e-4 +beta1 = 0.878636 +beta2 = 0.986336 +eps = 3.02623e-07 +minibatch_size = 8192 +horizon = 16 +vtrace_rho_clip = 2.49786 +vtrace_c_clip = 1.52028 +prio_alpha = 1 +prio_beta0 = 0.746205 +use_rnn = 0 + +[sweep.train.total_timesteps] +distribution = log_normal +min = 1e7 +max = 2e8 +mean = 3e7 +scale = 0.5 + + diff --git a/pufferlib/config/ocean/impulse_wars.ini b/config/impulse_wars.ini similarity index 66% rename from pufferlib/config/ocean/impulse_wars.ini rename to config/impulse_wars.ini index c4b3bdcc19..3e7c7f7bbb 100644 --- a/pufferlib/config/ocean/impulse_wars.ini +++ b/config/impulse_wars.ini @@ -1,14 +1,11 @@ [base] -package = ocean -env_name = puffer_impulse_wars -policy_name = ImpulseWarsPolicy -rnn_name = ImpulseWarsLSTM +env_name = impulse_wars + max_suggestion_cost = 10_800 [policy] -cnn_channels = 64 -input_size = 512 hidden_size = 512 +cnn_channels = 64 # These must match what's set in env below continuous = False @@ -16,12 +13,12 @@ num_drones = 2 is_training = True [vec] -num_envs = 16 -num_workers = 16 -batch_size = 4 +num_envs = 4 +#num_workers = 4 +#batch_size = 4 [env] -num_envs = 256 +num_envs = 1024 num_drones = 2 num_agents = 1 enable_teams = False @@ -38,12 +35,16 @@ learning_rate = 0.005 compile = False compile_mode = reduce-overhead compile_fullgraph = False -device = cuda + + +[sweep] +downsample = 10 +max_cost = 900 [sweep.env.num_envs] distribution = uniform_pow2 -min = 16 -max = 512 +min = 1 +max = 1024 mean = 128 scale = auto @@ -133,58 +134,10 @@ max = 1_048_576 mean = 262_144 scale = auto -[sweep.train.bptt_horizon] +[sweep.train.horizon] distribution = uniform_pow2 min = 64 max = 256 mean = 128 scale = auto -[sweep.train.minibatch_size] -distribution = uniform_pow2 -min = 1024 -max = 262_144 -mean = 16_384 -scale = auto - -[sweep.train.learning_rate] -distribution = log_normal -min = 0.00001 -mean = 0.001 -max = 0.1 -scale = 0.5 - -[sweep.train.ent_coef] -distribution = log_normal -min = 0.000001 -mean = 0.001 -max = 0.2 -scale = auto - -[sweep.train.gamma] -distribution = logit_normal -min = 0.8 -mean = 0.98 -max = 0.99999 -scale = auto - -[sweep.train.gae_lambda] -distribution = logit_normal -min = 0.6 -mean = 0.93 -max = 0.995 -scale = auto - -[sweep.train.vf_coef] -distribution = uniform -min = 0.0 -max = 5.0 -mean = 1.0 -scale = auto - -[sweep.train.max_grad_norm] -distribution = uniform -min = 0.0 -mean = 1.0 -max = 5.0 -scale = auto diff --git a/config/lightsout.ini b/config/lightsout.ini new file mode 100644 index 0000000000..e7f0682f28 --- /dev/null +++ b/config/lightsout.ini @@ -0,0 +1,8 @@ +[base] +env_name = lightsout + +[env] +max_steps = 100 + +[train] +total_timesteps = 200_000_000 diff --git a/pufferlib/config/ocean/matsci.ini b/config/matsci.ini similarity index 67% rename from pufferlib/config/ocean/matsci.ini rename to config/matsci.ini index 9183c27fa0..5b24d5e304 100644 --- a/pufferlib/config/ocean/matsci.ini +++ b/config/matsci.ini @@ -1,7 +1,5 @@ [base] -package = ocean -env_name = puffer_matsci -policy_name = Policy +env_name = matsci [vec] num_envs = 8 diff --git a/config/maze.ini b/config/maze.ini new file mode 100644 index 0000000000..1289bf08ab --- /dev/null +++ b/config/maze.ini @@ -0,0 +1,55 @@ +[base] +package = ocean +env_name = maze + +[vec] +total_agents = 512 +num_buffers = 5.96311 +num_threads = 2 + +[env] +max_size = 47 +num_maps = 8192 +map_size = -1 + +[policy] +hidden_size = 512 +num_layers = 5.88042 +expansion_factor = 1 + +[train] +gpus = 1 +seed = 42 +total_timesteps = 337903991 +learning_rate = 0.000755471 +anneal_lr = 1 +min_lr_ratio = 0 +gamma = 0.993628 +gae_lambda = 0.942137 +replay_ratio = 2.85958 +clip_coef = 0.1304 +vf_coef = 3.03966 +vf_clip_coef = 3.48152 +max_grad_norm = 1.41109 +ent_coef = 1e-05 +beta1 = 0.994379 +beta2 = 0.991022 +eps = 4.95035e-07 +minibatch_size = 16384 +horizon = 256 +vtrace_rho_clip = 5 +vtrace_c_clip = 2.33779 +prio_alpha = 0.998067 +prio_beta0 = 0.884829 +use_rnn = 1 +env = 0 + +[sweep] +downsample = 5 + +[sweep.train.total_timesteps] +distribution = log_normal +min = 1e8 +max = 1e9 +mean = 3e8 +scale = time diff --git a/pufferlib/config/ocean/memory.ini b/config/memory.ini similarity index 57% rename from pufferlib/config/ocean/memory.ini rename to config/memory.ini index 2bb5abeb81..6c7a77b7f7 100644 --- a/pufferlib/config/ocean/memory.ini +++ b/config/memory.ini @@ -1,8 +1,5 @@ [base] -package = ocean -env_name = puffer_memory -policy_name = Policy -rnn_name = Recurrent +env_name = memory [env] num_envs = 1024 diff --git a/config/moba.ini b/config/moba.ini new file mode 100644 index 0000000000..b8779ff2fb --- /dev/null +++ b/config/moba.ini @@ -0,0 +1,70 @@ +[base] +env_name = moba + +[vec] +total_agents = 2048 +num_buffers = 2.24842 +num_threads = 16 + +[env] +vision_range = 5 +agent_speed = 1 +script_opponents = 1 +reward_death = -0.163764 +reward_xp = 0.00665677 +reward_distance = 0 +reward_tower = 0.642119 + +[policy] +hidden_size = 64 +num_layers = 5.61447 +expansion_factor = 1 + +[train] +gpus = 1 +seed = 42 +total_timesteps = 39056098 +learning_rate = 0.00343957 +anneal_lr = 1 +min_lr_ratio = 0 +gamma = 0.991949 +gae_lambda = 0.945677 +replay_ratio = 0.832202 +clip_coef = 0.565744 +vf_coef = 3.37665 +vf_clip_coef = 1.27302 +max_grad_norm = 1.08622 +ent_coef = 0.00109913 +beta1 = 0.837952 +beta2 = 0.943593 +eps = 1.89701e-12 +minibatch_size = 8192 +horizon = 64 +vtrace_rho_clip = 1.76073 +vtrace_c_clip = 1.32578 +prio_alpha = 1 +prio_beta0 = 0.5692 + +[sweep] +downsample = 10 + +[sweep.env.reward_death] +distribution = uniform +min = -1.0 +max = 0 +mean = 0 +scale = auto + +[sweep.env.reward_xp] +distribution = uniform +min = 0.0 +max = 0.05 +mean = 0.0015 +scale = auto + +[sweep.env.reward_tower] +distribution = uniform +min = 0.0 +max = 1.0 +mean = 1.0 +scale = auto diff --git a/pufferlib/config/ocean/nmmo3.ini b/config/nmmo3.ini similarity index 60% rename from pufferlib/config/ocean/nmmo3.ini rename to config/nmmo3.ini index c04c77dc39..376f965253 100644 --- a/pufferlib/config/ocean/nmmo3.ini +++ b/config/nmmo3.ini @@ -1,50 +1,62 @@ [base] -package = ocean -env_name = puffer_nmmo3 -policy_name = NMMO3 -rnn_name = NMMO3LSTM +env_name = nmmo3 [vec] -num_envs = 8 +total_agents = 8192 +num_buffers = 4 +num_threads = 4 [env] +num_agents = 1024 +width = 512 +height = 512 +num_enemies = 2048 +num_resources = 2048 +num_weapons = 1024 +num_gems = 512 +tiers = 5 +levels = 40 +teleportitis_prob = 0.001 +enemy_respawn_ticks = 2 +item_respawn_ticks = 100 +x_window = 7 +y_window = 5 reward_combat_level = 1.0 reward_prof_level = 1.0 reward_item_level = 1.0 reward_market = 0.0 reward_death = -1.0 -num_envs = 1 + +[policy] +hidden_size = 512 [train] -total_timesteps = 107000000000 -checkpoint_interval = 1000 +#total_timesteps = 642_000_000_000 +total_timesteps = 20_000_000_000 +checkpoint_interval = 10000 learning_rate = 0.0004573146765703167 gamma = 0.7647543366891623 gae_lambda = 0.996005622445478 -ent_coef = 0.01210084358004069 max_grad_norm = 0.6075578331947327 vf_coef = 0.3979089612467003 -bptt_horizon = 64 -batch_size = 524288 +horizon = 64 +ent_coef = 0.01210084358004069 minibatch_size = 32768 -max_minibatch_size = 32768 [sweep] -metric = min_comb_prof - -[sweep.env.num_envs] -distribution = uniform_pow2 -min = 1 -max = 8 -mean = 4 -scale = 0.5 +downsample = 50 [sweep.train.total_timesteps] distribution = log_normal -min = 2e8 -max = 1e9 -mean = 5e8 -scale = 0.5 +min = 5e9 +max = 5e10 +scale = time + +[sweep.vec.total_agents] +distribution = uniform_pow2 +min = 1024 +max = 16384 +scale = auto [sweep.env.reward_combat_level] distribution = uniform diff --git a/pufferlib/config/ocean/drive.ini b/config/ocean/drive.ini similarity index 75% rename from pufferlib/config/ocean/drive.ini rename to config/ocean/drive.ini index 6358ad2457..497bbd9881 100644 --- a/pufferlib/config/ocean/drive.ini +++ b/config/ocean/drive.ini @@ -1,14 +1,12 @@ [base] package = ocean env_name = puffer_drive -policy_name = Drive +policy_name = MinGRU rnn_name = Recurrent [vec] -num_workers = 8 -num_envs = 8 -batch_size = 2 -#backend = Serial +total_agents = 8192 +num_buffers = 8 [policy] input_size = 64 @@ -19,24 +17,24 @@ input_size = 256 hidden_size = 256 [env] -num_agents = 1024 -reward_vehicle_collision = -0.5 -reward_offroad_collision = -0.2 +width = 1280 +height = 1024 +human_agent_idx = 0 +reward_vehicle_collision = 0 +reward_offroad_collision = 0 spawn_immunity_timer = 50 -reward_goal_post_respawn = 0.25 -reward_vehicle_collision_post_respawn = -0.5 +reward_goal_post_respawn = 0.0 +reward_vehicle_collision_post_respawn = 0.0 resample_frequency = 910 -num_maps = 80000 +num_maps = 10000 [train] total_timesteps = 2_000_000_000 -#learning_rate = 0.02 -#gamma = 0.985 anneal_lr = True -batch_size = 745472 -minibatch_size = 11648 -max_minibatch_size = 11648 -bptt_horizon = 91 +batch_size = auto +minibatch_size = 32768 +num_minibatches = 16 +horizon = 128 adam_beta1 = 0.9 adam_beta2 = 0.999 adam_eps = 1e-8 @@ -44,7 +42,7 @@ clip_coef = 0.2 ent_coef = 0.001 gae_lambda = 0.95 gamma = 0.98 -learning_rate = 0.001 +learning_rate = 0.005 max_grad_norm = 1 prio_alpha = 0.8499999999999999 prio_beta0 = 0.8499999999999999 diff --git a/config/ocean/drmario.ini b/config/ocean/drmario.ini new file mode 100644 index 0000000000..a127e38a26 --- /dev/null +++ b/config/ocean/drmario.ini @@ -0,0 +1,15 @@ +[base] +env_name = drmario + +[vec] +total_agents = 8192 +num_buffers = 4 +num_threads = 4 + +[env] +n_rows = 16 +n_cols = 8 +n_init_viruses = 4 + +[train] +total_timesteps = 200_000_000 diff --git a/pufferlib/config/ocean/oldgrid.ini b/config/oldgrid.ini similarity index 85% rename from pufferlib/config/ocean/oldgrid.ini rename to config/oldgrid.ini index 3cae63aa94..795c59e2c0 100644 --- a/pufferlib/config/ocean/oldgrid.ini +++ b/config/oldgrid.ini @@ -1,17 +1,10 @@ [base] -package = ocean -env_name = puffer_oldgrid +env_name = oldgrid vec = multiprocessing -policy_name = Policy -rnn_name = Recurrent #[policy] #hidden_size = 512 -#[rnn] -#input_size = 512 -#hidden_size = 512 - [env] #map_size = 31 max_map_size = 31 @@ -32,11 +25,10 @@ num_envs = 1 num_workers = 1 env_batch_size = 1 update_epochs = 4 -bptt_horizon = 16 +horizon = 16 batch_size = 131072 minibatch_size = 16384 compile = False -device = cuda e3b_coef = 0.01 [sweep] diff --git a/pufferlib/config/ocean/onestateworld.ini b/config/onestateworld.ini similarity index 65% rename from pufferlib/config/ocean/onestateworld.ini rename to config/onestateworld.ini index 82b6cb4b11..cdf0b3bc64 100644 --- a/pufferlib/config/ocean/onestateworld.ini +++ b/config/onestateworld.ini @@ -1,8 +1,5 @@ [base] -package = ocean -env_name = puffer_onestateworld -policy_name = Policy -rnn_name = None +env_name = onestateworld [vec] num_envs = 8 diff --git a/pufferlib/config/ocean/onlyfish.ini b/config/onlyfish.ini similarity index 65% rename from pufferlib/config/ocean/onlyfish.ini rename to config/onlyfish.ini index 443f185652..4ff4b518a4 100644 --- a/pufferlib/config/ocean/onlyfish.ini +++ b/config/onlyfish.ini @@ -1,8 +1,5 @@ [base] -package = ocean -env_name = puffer_onlyfish -policy_name = Policy -rnn_name = Recurrent +env_name = onlyfish [env] num_envs = 512 diff --git a/config/overcooked.ini b/config/overcooked.ini new file mode 100644 index 0000000000..e8136566d1 --- /dev/null +++ b/config/overcooked.ini @@ -0,0 +1,29 @@ +[base] +env_name = overcooked + +[vec] +total_agents = 8192 + +[env] +num_agents = 2 +layout = 0 +grid_size = 100 +reward_dish_served_whole_team = 1.0 +reward_dish_served_agent = 0.0 +reward_pot_started = 0.15 +reward_ingredient_added = 0.15 +reward_ingredient_picked = 0.05 +reward_plate_picked = 0.05 +reward_soup_plated = 0.20 +reward_wrong_dish_served = 0.0 +reward_step_penalty = 0.0 + +[train] +total_timesteps = 100_000_000 +learning_rate = 0.01 +minibatch_size = 32768 +gamma = 0.99 +ent_coef = 0.02 +gae_lambda = 0.97 +clip_coef = 0.15 +anneal_lr = 1 diff --git a/config/pacman.ini b/config/pacman.ini new file mode 100644 index 0000000000..7dc54a2b6f --- /dev/null +++ b/config/pacman.ini @@ -0,0 +1,59 @@ +[base] +env_name = pacman + +[vec] +total_agents = 8192 +num_buffers = 5.26923 +num_threads = 2 +num_envs = 4096 + +[env] +randomize_starting_position = 1 +min_start_timeout = 0 +max_start_timeout = 49 +frightened_time = 35 +max_mode_changes = 6 +scatter_mode_length = 70 +chase_mode_length = 140 + +[policy] +hidden_size = 256 +num_layers = 6.05812 +expansion_factor = 1 + +[train] +gpus = 1 +seed = 42 +total_timesteps = 204996994 +learning_rate = 0.00972151 +anneal_lr = 1 +min_lr_ratio = 0 +gamma = 0.996185 +gae_lambda = 0.970583 +replay_ratio = 1.78296 +clip_coef = 0.126507 +vf_coef = 0.1 +vf_clip_coef = 3.6265 +max_grad_norm = 0.604348 +ent_coef = 0.2 +beta1 = 0.894473 +beta2 = 0.993218 +eps = 0.0001 +minibatch_size = 16384 +horizon = 64 +vtrace_rho_clip = 2.07372 +vtrace_c_clip = 0.465232 +prio_alpha = 0.58347 +prio_beta0 = 0.415454 +use_rnn = 1 + +[sweep] +downsample = 10 + +[sweep.train.total_timesteps] +distribution = log_normal +min = 5e7 +max = 5e8 +mean = 1e8 +scale = auto + diff --git a/config/pong.ini b/config/pong.ini new file mode 100644 index 0000000000..51319e2923 --- /dev/null +++ b/config/pong.ini @@ -0,0 +1,65 @@ +[base] +env_name = pong + +[vec] +total_agents = 1024 +num_buffers = 1 +num_threads = 16 + +[env] +width = 500 +height = 640 +paddle_width = 20 +paddle_height = 70 +ball_width = 32 +ball_height = 32 +paddle_speed = 8 +ball_initial_speed_x = 10 +ball_initial_speed_y = 1 +ball_speed_y_increment = 3 +ball_max_speed_y = 13 +max_score = 21 +frameskip = 8 +continuous = 0 + +[policy] +hidden_size = 32 +num_layers = 1 + +[train] +gpus = 1 +seed = 42 +total_timesteps = 5000000 +learning_rate = 0.1 +anneal_lr = 1 +min_lr_ratio = 0 +gamma = 0.934713 +gae_lambda = 0.991989 +replay_ratio = 3.05148 +clip_coef = 0.822764 +vf_coef = 5 +vf_clip_coef = 4.95789 +max_grad_norm = 0.752747 +ent_coef = 0.000402915 +beta1 = 0.5 +beta2 = 0.947709 +eps = 0.0001 +minibatch_size = 32768 +horizon = 32 +vtrace_rho_clip = 4.87841 +vtrace_c_clip = 1.48608 +prio_alpha = 0.242089 +prio_beta0 = 0.807575 +use_rnn = 1 + +[sweep.train.total_timesteps] +distribution = log_normal +min = 5e6 +max = 5e7 +scale = auto + +[sweep.env.frameskip] +distribution = int_uniform +min = 1 +max = 8 +scale = 2.0 diff --git a/pufferlib/config/ocean/pysquared.ini b/config/pysquared.ini similarity index 70% rename from pufferlib/config/ocean/pysquared.ini rename to config/pysquared.ini index 7ff0653bc4..889d50747c 100644 --- a/pufferlib/config/ocean/pysquared.ini +++ b/config/pysquared.ini @@ -1,8 +1,5 @@ [base] -package = ocean -env_name = puffer_pysquared -policy_name = Policy -rnn_name = Recurrent +env_name = pysquared # Set up to match our C version defaults for speed comparison [vec] diff --git a/config/rware.ini b/config/rware.ini new file mode 100644 index 0000000000..36cc3ac561 --- /dev/null +++ b/config/rware.ini @@ -0,0 +1,23 @@ +[base] +env_name = rware +policy_name = MinGRU +rnn_name = Recurrent + +[vec] +total_agents = 4096 + +[env] +num_envs = 256 +num_agents = 8 +map_choice = 2 +num_requested_shelves = 8 +grid_square_size = 64 +human_agent_idx = 0 +reward_type = 1 +width = 1280 +height = 640 + +[train] +total_timesteps = 100_000_000 +learning_rate = 0.05 +minibatch_size = 32768 diff --git a/pufferlib/config/ocean/sanity.ini b/config/sanity.ini similarity index 63% rename from pufferlib/config/ocean/sanity.ini rename to config/sanity.ini index 7d7abc40b0..d82cb9dbbc 100644 --- a/pufferlib/config/ocean/sanity.ini +++ b/config/sanity.ini @@ -1,8 +1,5 @@ [base] -package = ocean -env_name = puffer_bandit puffer_memory puffer_multiagent puffer_password puffer_spaces puffer_stochastic -policy_name = Policy -rnn_name = Recurrent +env_name = bandit memory multiagent password spaces stochastic [train] total_timesteps = 50_000 @@ -12,8 +9,8 @@ num_workers = 2 env_batch_size = 8 batch_size = 1024 minibatch_size = 128 -bptt_horizon = 4 -device = cpu +horizon = 4 + [sweep.train.batch_size] distribution = uniform diff --git a/pufferlib/config/ocean/shared_pool.ini b/config/shared_pool.ini similarity index 89% rename from pufferlib/config/ocean/shared_pool.ini rename to config/shared_pool.ini index 36a9c5bfe3..a0ffdc1e4c 100644 --- a/pufferlib/config/ocean/shared_pool.ini +++ b/config/shared_pool.ini @@ -1,7 +1,5 @@ [base] -package = ocean -env_name = puffer_shared_pool -rnn_name = Recurrent +env_name = shared_pool [env] num_envs = 512 @@ -15,7 +13,7 @@ food_base_spawn_rate = 2e-3 [train] total_timesteps = 60_000_000 -bptt_horizon = 16 +horizon = 16 checkpoint_interval = 200 learning_rate = 0.0008524 gamma = 0.9989 diff --git a/config/slimevolley.ini b/config/slimevolley.ini new file mode 100644 index 0000000000..9354ee9a52 --- /dev/null +++ b/config/slimevolley.ini @@ -0,0 +1,52 @@ +[base] +env_name = slimevolley + +[vec] +total_agents = 16384 +num_buffers = 4.25408 +num_threads = 2 + +[env] +num_agents = 1 +gamma = 0.99 + +[policy] +hidden_size = 128 +num_layers = 3.90792 +expansion_factor = 1 + +[train] +gpus = 1 +seed = 42 +total_timesteps = 91750396 +learning_rate = 0.00296777 +anneal_lr = 1 +min_lr_ratio = 0 +gamma = 0.987692 +gae_lambda = 0.979432 +replay_ratio = 2.4235 +clip_coef = 0.112093 +vf_coef = 4.99645 +vf_clip_coef = 1.77049 +max_grad_norm = 0.1 +ent_coef = 0.00194179 +beta1 = 0.964621 +beta2 = 0.997724 +eps = 8.28081e-12 +minibatch_size = 8192 +horizon = 16 +vtrace_rho_clip = 2.23002 +vtrace_c_clip = 3.50115 +prio_alpha = 0.544741 +prio_beta0 = 0.189603 +use_rnn = 1 + +[sweep] +downsample = 5 + +[sweep.train.total_timesteps] +distribution = log_normal +min = 1e8 +max = 2e9 +mean = 3e8 +scale = time diff --git a/config/snake.ini b/config/snake.ini new file mode 100644 index 0000000000..f11b879248 --- /dev/null +++ b/config/snake.ini @@ -0,0 +1,61 @@ +[base] +env_name = snake + +[env] +width = 640 +height = 360 +num_agents = 256 +num_food = 4096 +vision = 5 +leave_corpse_on_death = True +reward_food = 0.1 +reward_corpse = 0.1 +reward_death = -1.0 +max_snake_length = 1024 +cell_size = 2 + +[vec] +total_agents = 4096 + +[train] +total_timesteps = 500_000_000 +gamma = 0.99 +minibatch_size = 32768 + +[sweep] +max_cost = 500 + +[sweep.env.reward_food] +distribution = uniform +min = 0.0 +max = 1.0 +mean = 0.0 +scale = auto + +[sweep.env.reward_death] +distribution = uniform +min = -1.0 +max = 0.0 +mean = 0.0 +scale = auto + +[sweep.train.total_timesteps] +distribution = log_normal +min = 2e7 +max = 5e8 +mean = 1e8 +scale = auto + +[sweep.policy.hidden_size] +distribution = uniform_pow2 +min = 16 +max = 1024 +mean = 128 +scale = auto + +[sweep.env.num_envs] +distribution = uniform_pow2 +min = 1 +max = 32 +mean = 8 +scale = auto diff --git a/config/squared.ini b/config/squared.ini new file mode 100644 index 0000000000..75b724beb5 --- /dev/null +++ b/config/squared.ini @@ -0,0 +1,20 @@ +[base] +env_name = squared squared_continuous + +[vec] +total_agents = 4096 +backend = Serial + +[policy] +hidden_size = 128 +num_layers = 1 + +[env] +size = 11 + +[train] +total_timesteps = 100_000_000 +gamma = 0.99 +learning_rate = 0.005 +minibatch_size = 32768 +ent_coef = 0.01 diff --git a/config/tactical.ini b/config/tactical.ini new file mode 100644 index 0000000000..afb68ef08e --- /dev/null +++ b/config/tactical.ini @@ -0,0 +1,2 @@ +[base] +env_name = tactical diff --git a/config/target.ini b/config/target.ini new file mode 100644 index 0000000000..31b6fff4a0 --- /dev/null +++ b/config/target.ini @@ -0,0 +1,14 @@ +[base] +env_name = target + +[vec] +total_agents = 4096 +num_buffers = 2 + +[train] +total_timesteps = 100_000_000 +gamma = 0.99 +learning_rate = 0.015 +minibatch_size = 32768 +ent_coef = 0.02 + diff --git a/pufferlib/config/ocean/template.ini b/config/template.ini similarity index 51% rename from pufferlib/config/ocean/template.ini rename to config/template.ini index 4784c83e73..b1d681549a 100644 --- a/pufferlib/config/ocean/template.ini +++ b/config/template.ini @@ -1,7 +1,5 @@ [base] -package = ocean -env_name = puffer_template -policy_name = Policy +env_name = template [env] num_envs = 4096 diff --git a/config/terraform.ini b/config/terraform.ini new file mode 100644 index 0000000000..ce9ac32042 --- /dev/null +++ b/config/terraform.ini @@ -0,0 +1,73 @@ +[base] +env_name = terraform + +[vec] +total_agents = 2048 +num_buffers = 4.40297 +num_threads = 2 + +[env] +num_envs = 1024 +num_agents = 1 +size = 64 +reset_frequency = 1024 +reward_scale = 0.0907157 + +[policy] +hidden_size = 512 +num_layers = 5.46436 +expansion_factor = 1 + +[rnn] +input_size = 256 +hidden_size = 256 + +[train] +gpus = 1 +seed = 42 +total_timesteps = 234873016 +learning_rate = 0.00551772 +anneal_lr = 1 +min_lr_ratio = 0 +gamma = 0.89571 +gae_lambda = 0.2 +replay_ratio = 1.78841 +clip_coef = 0.01 +vf_coef = 5 +vf_clip_coef = 1.19287 +max_grad_norm = 2.21317 +ent_coef = 0.0079761 +beta1 = 0.965804 +beta2 = 0.999389 +eps = 0.0001 +minibatch_size = 16384 +horizon = 256 +vtrace_rho_clip = 4.24942 +vtrace_c_clip = 2.12831 +prio_alpha = 0.451327 +prio_beta0 = 0.676252 +adam_beta1 = 0.879231 +adam_beta2 = 0.998046 +adam_eps = 6.00018e-06 +use_rnn = 1 + +[sweep.train.total_timesteps] +distribution = log_normal +min = 2e8 +max = 6e8 +mean = 4e8 +scale = time + +#[sweep.env.reset_frequency] +#distribution = int_uniform +#min = 1024 +#max = 16384 +#mean = 8192 +#scale = auto + +[sweep.env.reward_scale] +distribution = log_normal +min = 0.01 +max = 1 +mean = 0.5 +scale = auto diff --git a/config/tetris.ini b/config/tetris.ini new file mode 100644 index 0000000000..9cada14e66 --- /dev/null +++ b/config/tetris.ini @@ -0,0 +1,62 @@ +[base] +env_name = tetris + +[vec] +total_agents = 4096 +num_buffers = 5.20054 +num_threads = 2 + +[env] +n_rows = 20 +n_cols = 10 +use_deck_obs = 1 +n_init_garbage = 4 +n_noise_obs = 0 + +[policy] +hidden_size = 512 +num_layers = 2.20258 +expansion_factor = 1 + +[legacy] +torch_deterministic = 1 +cpu_offload = 0 +compile = 0 +compile_fullgraph = 1 + +[train] +gpus = 1 +seed = 42 +total_timesteps = 1924140014 +learning_rate = 0.0031086 +anneal_lr = 1 +min_lr_ratio = 0 +gamma = 0.992822 +gae_lambda = 0.703161 +replay_ratio = 2.74669 +clip_coef = 0.0220916 +vf_coef = 2.6876 +vf_clip_coef = 1.63454 +max_grad_norm = 3.15904 +ent_coef = 0.0184801 +beta1 = 0.97197 +beta2 = 0.999989 +eps = 6.21415e-08 +minibatch_size = 65536 +horizon = 128 +vtrace_rho_clip = 2.65161 +vtrace_c_clip = 2.23837 +prio_alpha = 0.354858 +prio_beta0 = 0.950642 +use_rnn = 1 + +[sweep] +metric = score +goal = maximize + +[sweep.train.total_timesteps] +distribution = log_normal +min = 30_000_000 +max = 3_000_000_000 +mean = 200_000_000 +scale = auto diff --git a/pufferlib/config/ocean/tmaze.ini b/config/tmaze.ini similarity index 50% rename from pufferlib/config/ocean/tmaze.ini rename to config/tmaze.ini index c6808538ca..e5a42a6999 100644 --- a/pufferlib/config/ocean/tmaze.ini +++ b/config/tmaze.ini @@ -1,8 +1,5 @@ [base] -package = ocean -env_name = puffer_tmaze -policy_name = Policy -rnn_name = Recurrent +env_name = tmaze [vec] num_envs = 8 @@ -14,11 +11,7 @@ size = 16 [policy] hidden_size = 128 -[rnn] -input_size = 128 -hidden_size = 128 - [train] total_timesteps = 5_000_000 -bptt_horizon = 32 +horizon = 32 ; entropy_coef = 0.01 \ No newline at end of file diff --git a/config/tower_climb.ini b/config/tower_climb.ini new file mode 100644 index 0000000000..37e1a752be --- /dev/null +++ b/config/tower_climb.ini @@ -0,0 +1,82 @@ +[base] +env_name = tower_climb + +[vec] +total_agents = 8192 +num_buffers = 5.1101 +num_threads = 2 + +[env] +num_envs = 1024 +num_maps = 50 +reward_climb_row = 0.205371 +reward_fall_row = 0 +reward_illegal_move = -0.00397522 +reward_move_block = 0 + +[policy] +hidden_size = 256 +num_layers = 5.09602 +expansion_factor = 1 + +[train] +gpus = 1 +seed = 42 +total_timesteps = 447742034 +learning_rate = 0.017405 +anneal_lr = 1 +min_lr_ratio = 0.1 +gamma = 0.933042 +gae_lambda = 0.755604 +replay_ratio = 0.707762 +clip_coef = 0.0890744 +vf_coef = 4.7512 +vf_clip_coef = 5 +max_grad_norm = 4.98401 +ent_coef = 0.2 +beta1 = 0.745044 +beta2 = 0.99774 +eps = 1e-14 +minibatch_size = 32768 +horizon = 128 +vtrace_rho_clip = 4.06891 +vtrace_c_clip = 3.13193 +prio_alpha = 1 +prio_beta0 = 1 +adam_beta1 = 0.81 +adam_beta2 = 0.95 +adam_eps = 1e-08 + +[sweep] +metric = perf +metric_distribution = percentile + +[sweep.train.total_timesteps] +distribution = uniform +min = 100_000_000 +max = 2_000_000_000 +scale = 0.5 + +[sweep.env.reward_climb_row] +distribution = uniform +min = 0.0 +max = 1.0 +scale = auto + +[sweep.env.reward_fall_row] +distribution = uniform +min = -1.0 +max = 0.0 +scale = auto + +[sweep.env.reward_illegal_move] +distribution = uniform +min = -1e-2 +max = -1e-4 +scale = auto + +[sweep.env.reward_move_block] +distribution = uniform +min = 0.0 +max = 1.0 +scale = auto diff --git a/config/trash_pickup.ini b/config/trash_pickup.ini new file mode 100644 index 0000000000..8418c8eba3 --- /dev/null +++ b/config/trash_pickup.ini @@ -0,0 +1,54 @@ +[base] +env_name = trash_pickup + +[vec] +total_agents = 4096 +num_buffers = 2.05803 +num_threads = 2 + +[env] +grid_size = 20 +num_agents = 8 +num_trash = 40 +num_bins = 2 +max_steps = 500 +report_interval = 32 +agent_sight_range = 5 + +[policy] +hidden_size = 128 +num_layers = 2.92514 +expansion_factor = 1 + +[train] +gpus = 1 +seed = 42 +total_timesteps = 15728600 +learning_rate = 0.0147993 +anneal_lr = 1 +min_lr_ratio = 0 +gamma = 0.930484 +gae_lambda = 0.972618 +replay_ratio = 1.83493 +clip_coef = 0.0627967 +vf_coef = 3.9924 +vf_clip_coef = 0.01 +max_grad_norm = 0.1 +ent_coef = 0.000193757 +beta1 = 0.87893 +beta2 = 0.999989 +eps = 1e-14 +minibatch_size = 16384 +horizon = 16 +vtrace_rho_clip = 3.43692 +vtrace_c_clip = 3.0755 +prio_alpha = 0.58438 +prio_beta0 = 0.416024 +use_rnn = 1 + +[sweep.train.total_timesteps] +distribution = log_normal +min = 3e7 +max = 2e8 +mean = 1e8 +scale = 0.5 diff --git a/config/tripletriad.ini b/config/tripletriad.ini new file mode 100644 index 0000000000..bd77d60bfa --- /dev/null +++ b/config/tripletriad.ini @@ -0,0 +1,52 @@ +[base] +env_name = tripletriad + +[vec] +total_agents = 4096 +num_buffers = 4.5243 +num_threads = 2 +num_agents = 4096 + +[env] +width = 990 +height = 690 +card_width = 192 +card_height = 224 + +[policy] +hidden_size = 256 +num_layers = 2.46396 +expansion_factor = 1 + +[train] +gpus = 1 +seed = 42 +total_timesteps = 34537498 +learning_rate = 0.0017548 +anneal_lr = 1 +min_lr_ratio = 0 +gamma = 0.955398 +gae_lambda = 0.98264 +replay_ratio = 3.5804 +clip_coef = 0.253448 +vf_coef = 2.14518 +vf_clip_coef = 3.87724 +max_grad_norm = 4.65825 +ent_coef = 0.000501928 +beta1 = 0.944088 +beta2 = 0.999153 +eps = 1.83574e-12 +minibatch_size = 8192 +horizon = 16 +vtrace_rho_clip = 4.86264 +vtrace_c_clip = 1.79853 +prio_alpha = 0.293554 +prio_beta0 = 0.17102 +use_rnn = 1 + +[sweep.train.total_timesteps] +distribution = log_normal +min = 1e7 +max = 2e8 +mean = 1e8 +scale = time diff --git a/pufferlib/config/ocean/whisker_racer.ini b/config/whisker_racer.ini similarity index 90% rename from pufferlib/config/ocean/whisker_racer.ini rename to config/whisker_racer.ini index b7dd87f11f..1b7dd97b8d 100644 --- a/pufferlib/config/ocean/whisker_racer.ini +++ b/config/whisker_racer.ini @@ -1,8 +1,5 @@ [base] -package = ocean -env_name = puffer_whisker_racer -policy_name = Policy -rnn_name = Recurrent +env_name = whisker_racer [vec] num_envs = 8 @@ -17,32 +14,32 @@ num_radial_sectors = 180 num_points = 16 bezier_resolution = 4 turn_pi_frac = 40 -w_ang = 0.777 # 0.586 # 0.523 +maxv = 5 +w_ang = 0.777 +max_whisker_length = 100 reward_yellow = 0.2 reward_green = -0.001 -corner_thresh = 0.5 # dot product for hairpins -ftmp1 = 0.5 #0.9 -ftmp2 = 3.0 #1.05 -ftmp3 = 0.3 # 0.2 +gamma = 0.9 +corner_thresh = 0.5 +ftmp1 = 0.5 +ftmp2 = 3.0 +ftmp3 = 0.3 ftmp4 = 0.0 mode7 = 0 render_many = 0 rng = 6 method = 2 +continuous = 0 [policy] hidden_size = 128 -[rnn] -input_size = 128 -hidden_size = 128 - [train] adam_beta1 = 0.9446160612709289 adam_beta2 = 0.9898294105500932 adam_eps = 3.599894131847621e-14 batch_size = auto -bptt_horizon = 64 +horizon = 64 clip_coef = 0.18182501031893042 ent_coef = 0.014660408908451323 gae_lambda = 0.9560790493173461 diff --git a/constellation/cache_data.py b/constellation/cache_data.py new file mode 100644 index 0000000000..174b520575 --- /dev/null +++ b/constellation/cache_data.py @@ -0,0 +1,251 @@ +# Merges log files + filters to pareto-optimal points wrt steps, wall-clock, and score. Comment that if you want the full dataset. Also does TSNE, which is why I haven't bothered porting to C. +import numpy as np + +import json +import glob +import os + +HYPERS = [ + 'train/learning_rate', + 'train/ent_coef', + 'train/gamma', + 'train/gae_lambda', + 'train/vtrace_rho_clip', + 'train/vtrace_c_clip', + 'train/clip_coef', + 'train/vf_clip_coef', + 'train/vf_coef', + 'train/max_grad_norm', + 'train/beta1', + 'train/beta2', + 'train/eps', + 'train/prio_alpha', + 'train/prio_beta0', + 'train/horizon', + 'train/replay_ratio', + 'train/minibatch_size', + 'policy/hidden_size', + 'vec/total_agents', +] + +METRICS = [ + 'agent_steps', + 'uptime', + 'env/score', + 'env/perf', + 'tsne1', + 'tsne2', +] + +ALL_KEYS = HYPERS + METRICS + +def unroll_nested_dict(d): + if not isinstance(d, dict): + return d + + for k, v in d.items(): + if isinstance(v, dict): + for k2, v2 in unroll_nested_dict(v): + yield f"{k}/{k2}", v2 + else: + yield k, v + + +def pareto_idx(steps, costs, scores): + idxs = [] + for i in range(len(steps)): + better = [scores[j] >= scores[i] and + costs[j] < costs[i] and steps[j] < steps[i] + for j in range(len(scores))] + if not any(better): + idxs.append(i) + + return idxs + +def cached_load(path, env_name, cache, full_dataset=False): + data = {} + num_metrics = 0 + metric_keys = [] + for fpath in glob.glob(path): + if fpath in cache: + exp = cache[fpath] + else: + with open(fpath, 'r') as f: + try: + exp = json.load(f) + except json.decoder.JSONDecodeError: + print(f'Skipping {fpath}') + continue + + cache[fpath] = exp + + if 'metrics' not in exp: + print(f'Skipping {fpath} (no metrics)') + continue + + # Temporary: Some experiments are missing loss keys + for k in list(exp['metrics'].keys()): + if 'loss' in k: + del exp['metrics'][k] + + if num_metrics == 0: + num_metrics = len(exp['metrics']) + metric_keys = list(exp['metrics'].keys()) + + skip = False + metrics = exp['metrics'] + + if len(metrics) != num_metrics: + print(f'Skipping {fpath} (num_metrics={len(metrics)} != {num_metrics})') + continue + + n = len(metrics['agent_steps']) + + for k, v in metrics.items(): + if len(v) != n: + skip = True + break + + if k not in data: + data[k] = [] + + if np.isnan(v).any(): + skip = True + break + + if skip: + print(f'Skipping {fpath} (bad data)') + continue + + for k, v in metrics.items(): + data[k].append(v) + if len(data[k]) != len(data['SPS']): + pass + + sweep_metadata = exp['sweep'] + + for k, v in unroll_nested_dict(exp): + if k == 'env/score': + continue + + if k not in data: + data[k] = [] + + data[k].append([v]*n) + + for hyper in HYPERS: + prefix, suffix = hyper.split('/') + group = sweep_metadata[prefix] + key = f'{prefix}/{suffix}_norm' + if key not in data: + data[key] = [] + + if suffix in group: + param = group[suffix] + mmin = param['min'] + mmax = param['max'] + dist = param['distribution'] + val = exp[prefix][suffix] + + if 'log' in dist or 'pow2' in dist: + mmin = np.log(mmin) + mmax = np.log(mmax) + val = np.log(val) + + norm = (val - mmin) / (mmax - mmin) + data[key].append([norm]*n) + else: + data[key].append([1]*n) + + for k, v in data.items(): + data[k] = [item for sublist in v for item in sublist] + + for k in list(data.keys()): + if 'sweep' in k: + del data[k] + + # Format im millions to avoid overfloat in C + data['agent_steps'] = [e/1e6 for e in data['agent_steps']] + data['train/total_timesteps'] = [e/1e6 for e in data['train/total_timesteps']] + del data['metrics/agent_steps'] + + # Filter to pareto + if not full_dataset: + steps = data['agent_steps'] + costs = data['uptime'] + scores = data['env/score'] + + idxs = pareto_idx(steps, costs, scores) + for k in data: + try: + data[k] = [data[k][i] for i in idxs] + except IndexError: + continue + + data['sweep'] = sweep_metadata + return data + +def compute_tsne(full_dataset=False): + all_data = {} + normed = {} + + cache = {} + cache_file = os.path.join('cache.json') + if os.path.exists(cache_file): + cache = json.load(open(cache_file, 'r')) + + env_names = sorted(os.listdir('logs')) + for env in env_names: + print('Loading: ', env) + all_data[env] = cached_load(f'logs/{env}/*.json', env, cache, full_dataset) + + with open(cache_file, 'w') as f: + json.dump(cache, f) + + for env in env_names: + env_data = all_data[env] + normed_env = [] + for key in HYPERS: + norm_key = f'{key}_norm' + normed_env.append(np.array(env_data[norm_key])) + + normed[env] = np.stack(normed_env, axis=1) + + normed = np.concatenate(list(normed.values()), axis=0) + + from sklearn.manifold import TSNE + proj = TSNE(n_components=2) + reduced = proj.fit_transform(normed) + + row = 0 + for env in env_names: + sz = len(all_data[env]['agent_steps']) + all_data[env]['tsne1'] = reduced[row:row+sz, 0].tolist() + all_data[env]['tsne2'] = reduced[row:row+sz, 1].tolist() + + row += sz + + for env in all_data: + dat = all_data[env] + dat = {k: v for k, v in dat.items() if isinstance(v, list) + and len(v) > 0 and isinstance(v[0], (int, float)) + and (k == 'train/max_grad_norm' or not k.endswith('_norm'))} + all_data[env] = dat + print(f"Env {env} has {len(dat['env/perf'])} points") + for k, v in dat.items(): + if 'env/perf' in k or 'score' in k: + print(f'{env}/{k}: min={min(v)}, max={max(v)}') + + for env in all_data: + for k, v in all_data[env].items(): + if isinstance(v, list): + all_data[env][k] = ','.join([f'{x:.6g}' for x in v]) + + json.dump(all_data, open('resources/constellation/experiments.json', 'w')) + +if __name__ == '__main__': + import argparse + parser = argparse.ArgumentParser() + parser.add_argument('--full', action='store_true', help='Include full dataset (no pareto filtering)') + args = parser.parse_args() + compute_tsne(full_dataset=args.full) diff --git a/constellation/constellation.c b/constellation/constellation.c new file mode 100644 index 0000000000..c05e08a46c --- /dev/null +++ b/constellation/constellation.c @@ -0,0 +1,1246 @@ +#include +#include +#include +#include + +#include "cJSON.h" +#include "raylib.h" + +#define RAYGUI_IMPLEMENTATION +#include "raygui.h" +#include "rcamera.h" + +#if defined(PLATFORM_DESKTOP) || defined(PLATFORM_DESKTOP_SDL) + #if defined(GRAPHICS_API_OPENGL_ES2) + #include "glad_gles2.h" // Required for: OpenGL functionality + #define glGenVertexArrays glGenVertexArraysOES + #define glBindVertexArray glBindVertexArrayOES + #define glDeleteVertexArrays glDeleteVertexArraysOES + #define GLSL_VERSION 100 + #else + #if defined(__APPLE__) + #define GL_SILENCE_DEPRECATION // Silence Opengl API deprecation warnings + #include // OpenGL 3 library for OSX + #include // OpenGL 3 extensions library for OSX + #else + #include "glad.h" // Required for: OpenGL functionality + #endif + #define GLSL_VERSION 330 + #endif +#else // PLATFORM_ANDROID, PLATFORM_WEB + #include + #define GLSL_VERSION 100 +#endif + +#include "rlgl.h" +#include "raymath.h" + +#define CAMERA_ORBITAL_SPEED 0.05f +void CustomUpdateCamera(Camera *camera, float orbitSpeed) { + float cameraOrbitalSpeed = CAMERA_ORBITAL_SPEED*GetFrameTime(); + Matrix rotation = MatrixRotate(GetCameraUp(camera), cameraOrbitalSpeed); + Vector3 view = Vector3Subtract(camera->position, camera->target); + view = Vector3Transform(view, rotation); + camera->position = Vector3Add(camera->target, view); + CameraMoveToTarget(camera, -GetMouseWheelMove()); + if (IsKeyPressed(KEY_KP_SUBTRACT)) CameraMoveToTarget(camera, 2.0f); + if (IsKeyPressed(KEY_KP_ADD)) CameraMoveToTarget(camera, -2.0f); +} + +#define SETTINGS_HEIGHT 20 +#define SEP 8 +#define SPACER 25 +#define TOGGLE_WIDTH 70 +#define DROPDOWN_WIDTH 125 + +#define LINEAR 0 +#define LOG 1 +#define LOGIT 2 + +const Color PUFF_CYAN = (Color){0, 187, 187, 255}; +const Color PUFF_WHITE = (Color){241, 241, 241, 241}; +const Color PUFF_BACKGROUND = (Color){6, 24, 24, 255}; + +int hyper_count = 25; +char *hyper_key[25] = { + "agent_steps", + "uptime", + "env/perf", + "env/score", + "train/learning_rate", + "train/ent_coef", + "train/gamma", + "train/gae_lambda", + "train/vtrace_rho_clip", + "train/vtrace_c_clip", + "train/clip_coef", + "train/vf_clip_coef", + "train/vf_coef", + "train/max_grad_norm", + "train/beta1", + "train/beta2", + "train/eps", + "train/prio_alpha", + "train/prio_beta0", + "train/horizon", + "train/replay_ratio", + "train/minibatch_size", + "policy/hidden_size", + "policy/num_layers", + "vec/total_agents", +}; + +typedef struct Glyph { + float x; + float y; + float i; + float r; + float g; + float b; + float a; +} Glyph; + +typedef struct Point { + float x; + float y; + float z; + float c; +} Point; + +typedef struct { + float click_x; + float click_y; + float x; + float y; + int env_idx; + int ary_idx; + bool active; +} Tooltip; + +typedef struct { + char *key; + float *ary; + int n; +} Hyper; + +typedef struct { + char *key; + Hyper *hypers; + int n; +} Env; + +typedef struct { + Env *envs; + int n; +} Dataset; + +typedef struct PlotArgs { + float mmin[4]; + float mmax[4]; + int scale[4]; + int width; + int height; + int title_font_size; + int axis_font_size; + int axis_tick_font_size; + int legend_font_size; + int line_width; + int tick_length; + int top_margin; + int bottom_margin; + int left_margin; + int right_margin; + int tick_margin; + Color font_color; + Color background_color; + Color axis_color; + char* x_label; + char* y_label; + char* z_label; + Font font; + Font font_small; + Camera3D camera; +} PlotArgs; + +PlotArgs DEFAULT_PLOT_ARGS = { + .mmin = {0.0f, 0.0f, 0.0f, 0.0f}, + .mmax = {0.0f, 0.0f, 0.0f, 0.0f}, + .scale = {0, 0, 0, 0}, + .width = 960, + .height = 540 - SETTINGS_HEIGHT, + .title_font_size = 32, + .axis_font_size = 32, + .axis_tick_font_size = 16, + .legend_font_size = 12, + .line_width = 2, + .tick_length = 8, + .tick_margin = 8, + .top_margin = 70, + .bottom_margin = 70, + .left_margin = 100, + .right_margin = 100, + .font_color = PUFF_WHITE, + .background_color = PUFF_BACKGROUND, + .axis_color = PUFF_WHITE, + .x_label = "Cost", + .y_label = "Score", + .z_label = "Train/Learning Rate", +}; + + +Hyper* get_hyper(Dataset *data, char *env, char* hyper) { + for (int i = 0; i < data->n; i++) { + if (strcmp(data->envs[i].key, env) != 0) { + continue; + } + for (int j = 0; j < data->envs[i].n; j++) { + if (strcmp(data->envs[i].hypers[j].key, hyper) == 0) { + return &data->envs[i].hypers[j]; + } + } + } + printf("Error: hyper %s not found in env %s\n", hyper, env); + exit(1); + return NULL; +} + +float safe_log10(float x) { + if (x <= 0) { + return x; + } + return log10(x); +} + +float scale_val(int scale, float val) { + if (scale == LINEAR) { + return val; + } else if (scale == LOG) { + return safe_log10(val); + } else if (scale == LOGIT) { + return safe_log10(1 - val); + } else { + return val; + } +} + +float unscale_val(int scale, float val) { + if (scale == LINEAR) { + return val; + } else if (scale == LOG) { + return powf(10, val); + } else if (scale == LOGIT) { + return 1 / (1 + powf(10, val)); + } + return val; +} + +Color rgb(float h) { + return ColorFromHSV(120*(1.0 + h), 0.8f, 0.15f); +} + +void draw_axes(PlotArgs args) { + DrawLine(args.left_margin, args.top_margin, + args.left_margin, args.height - args.bottom_margin, PUFF_WHITE); + DrawLine(args.left_margin, args.height - args.bottom_margin, + args.width - args.right_margin, args.height - args.bottom_margin, PUFF_WHITE); +} + +const char* format_tick_label(double value) { + static char buffer[32]; + + if (fabs(value) < 1e-10) { + strcpy(buffer, "0"); + return buffer; + } + + if (fabs(value) < 0.001 || fabs(value) > 10000) { + snprintf(buffer, sizeof(buffer), "%.3e", value); + } else { + snprintf(buffer, sizeof(buffer), "%.3f", value); + } + + return buffer; +} + +void label_ticks(char ticks[][32], PlotArgs args, int axis_idx, int tick_n) { + float mmin = scale_val(args.scale[axis_idx], args.mmin[axis_idx]); + float mmax = scale_val(args.scale[axis_idx], args.mmax[axis_idx]); + for (int i=0; iary; + float mmin = ary[0]; + float mmax = ary[0]; + for (int j=0; jn; j++) { + if (filter != NULL && !filter[j]) { + continue; + } + mmin = fmin(mmin, ary[j]); + mmax = fmax(mmax, ary[j]); + } + + mmin = scale_val(x_scale, mmin); + mmax = scale_val(x_scale, mmax); + + float left = args.left_margin + (mmin - x_min)/(x_max - x_min)*plot_width; + float right = args.left_margin + (mmax - x_min)/(x_max - x_min)*plot_width; + + // TODO - rough patch + left = fminf(fmax(left, args.left_margin), width - args.right_margin); + right = fmaxf(fmin(right, width - args.right_margin), 0); + DrawRectangle(left, args.top_margin + i*dy, right - left, dy, color); +} + +void plot_gl(Glyph* glyphs, int size, Shader* shader) { + int n = size; + + GLuint vao = 0; + GLuint vbo = 0; + glGenVertexArrays(1, &vao); + glBindVertexArray(vao); + glGenBuffers(1, &vbo); + glBindBuffer(GL_ARRAY_BUFFER, vbo); + glBufferData(GL_ARRAY_BUFFER, n*sizeof(Glyph), glyphs, GL_STATIC_DRAW); + glVertexAttribPointer(shader->locs[SHADER_LOC_VERTEX_POSITION], 3, GL_FLOAT, GL_FALSE, sizeof(Glyph), 0); + glEnableVertexAttribArray(shader->locs[SHADER_LOC_VERTEX_POSITION]); + int vertexColorLoc = shader->locs[SHADER_LOC_VERTEX_COLOR]; + glVertexAttribPointer(vertexColorLoc, 4, GL_FLOAT, GL_FALSE, sizeof(Glyph), (void*)(3*sizeof(float))); + glEnableVertexAttribArray(vertexColorLoc); + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindVertexArray(0); + + rlDrawRenderBatchActive(); + rlSetBlendFactors(GL_ONE, GL_ONE, GL_MAX); + rlSetBlendMode(RL_BLEND_CUSTOM); + int currentTimeLoc = GetShaderLocation(*shader, "currentTime"); + glUseProgram(shader->id); + glUniform1f(currentTimeLoc, GetTime()); + Matrix modelViewProjection = MatrixMultiply(rlGetMatrixModelview(), rlGetMatrixProjection()); + glUniformMatrix4fv(shader->locs[SHADER_LOC_MATRIX_MVP], 1, false, MatrixToFloat(modelViewProjection)); + glBindVertexArray(vao); + glDrawArrays(GL_POINTS, 0, n); + glBindVertexArray(0); + glUseProgram(0); + glDeleteBuffers(1, &vbo); + glDeleteVertexArrays(1, &vao); + rlSetBlendMode(RL_BLEND_ALPHA); +} + +void GuiDropdownFilter(int x, int y, char* options, int *selection, bool *dropdown_active, + Vector2 focus, char *text1, float *text1_val, char *text2, float *text2_val) { + Rectangle rect = {x, y, DROPDOWN_WIDTH, SETTINGS_HEIGHT}; + if (GuiDropdownBox(rect, options, selection, *dropdown_active)) { + *dropdown_active = !*dropdown_active; + } + Rectangle text1_rect = {x + DROPDOWN_WIDTH, y, TOGGLE_WIDTH, SETTINGS_HEIGHT}; + bool text1_active = CheckCollisionPointRec(focus, text1_rect); + if (GuiTextBox(text1_rect, text1, 32, text1_active)) { + *text1_val = atof(text1); + } + Rectangle text2_rect = {x + DROPDOWN_WIDTH + TOGGLE_WIDTH, y, TOGGLE_WIDTH, SETTINGS_HEIGHT}; + bool text2_active = CheckCollisionPointRec(focus, text2_rect); + if (GuiTextBox(text2_rect, text2, 32, text2_active)) { + *text2_val = atof(text2); + } +} + +void apply_filter(bool* filter, Hyper* param, float min, float max) { + for (int i=0; in; i++) { + float val = param->ary[i]; + if (val < min || val > max) { + filter[i] = false; + } + } +} + +void autoscale(Point* points, int size, PlotArgs *args) { + float mmin[4] = {FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX}; + float mmax[4] = {-FLT_MAX, -FLT_MAX, -FLT_MAX, -FLT_MAX}; + for (int i=0; i mmax[j]) mmax[j] = val; + } + } + for (int j=0; j<4; j++) { + args->mmin[j] = mmin[j]; + args->mmax[j] = mmax[j]; + } +} + +void toPx(Point *points, Glyph* glyphs, int size, PlotArgs args) { + float mmin[4]; + float mmax[4]; + float delta[4]; + for (int j=0; j<4; j++) { + mmin[j] = scale_val(args.scale[j], args.mmin[j]); + mmax[j] = scale_val(args.scale[j], args.mmax[j]); + delta[j] = mmax[j] - mmin[j]; + } + + for (int i = 0; i < size; i++) { + Point p = points[i]; + float xi = scale_val(args.scale[0], p.x); + float yi = scale_val(args.scale[1], p.y); + float zi = scale_val(args.scale[2], p.z); + float px, py; + + if (args.mmin[2] != 0 || args.mmax[2] != 0) { + Vector3 v = (Vector3){ + (xi - mmin[0])/delta[0], + (yi - mmin[1])/delta[1], + (zi - mmin[2])/delta[2] + }; + assert(args.camera.fovy != 0); + Vector2 screen_pos = GetWorldToScreenEx(v, args.camera, args.width, args.height); + px = screen_pos.x; + py = screen_pos.y; + } else { + // TODO: Check margins + px = args.left_margin + (xi - mmin[0]) / delta[0] * (args.width - args.left_margin - args.right_margin); + py = args.height - args.bottom_margin - (yi - mmin[1]) / delta[1] * (args.height - args.top_margin - args.bottom_margin); + } + + float cmap = points[i].c; + cmap = scale_val(args.scale[3], cmap); + float c_min = mmin[3]; + float c_max = mmax[3]; + if (c_min != c_max) { + cmap = (cmap - c_min)/(c_max - c_min); + } + Color c = rgb(cmap); + glyphs[i] = (Glyph){ + px, + py, + i, + c.r/255.0f, + c.g/255.0f, + c.b/255.0f, + c.a/255.0f, + }; + } +} + +void update_closest(Tooltip* tooltip, Vector2 *indices, Glyph* glyphs, int size, float x_offset, float y_offset) { + float dx = tooltip->click_x - tooltip->x; + float dy = tooltip->click_y - tooltip->y; + float dist = sqrt(dx*dx + dy*dy); + + for (int i=0; iclick_x; + dy = y_offset + glyphs[i].y - tooltip->click_y; + float d = sqrt(dx*dx + dy*dy); + if (d < dist) { + dist = d; + tooltip->x = x_offset + glyphs[i].x; + tooltip->y = y_offset + glyphs[i].y; + tooltip->env_idx = indices[i].x; + tooltip->ary_idx = indices[i].y; + } + } +} + +void copy_hypers_to_clipboard(Env *env, char* buffer, int ary_idx) { + char* start = buffer; + char* prefix = NULL; + int prefix_len = 0; + for (int hyper_idx = 0; hyper_idx < env->n; hyper_idx++) { + Hyper *hyper = &env->hypers[hyper_idx]; + char *slash = strchr(hyper->key, '/'); + if (!slash) { + continue; + } + + if (prefix == NULL || strncmp(prefix, hyper->key, prefix_len) != 0) { + if (prefix != NULL) { + buffer += sprintf(buffer, "\n"); + } + prefix = hyper->key; + prefix_len = slash - prefix; + buffer += sprintf(buffer, "["); + snprintf(buffer, prefix_len+1, "%s", prefix); + buffer += prefix_len; + buffer += sprintf(buffer, "]\n"); + } + + char* suffix = slash + 1; + double val = hyper->ary[ary_idx]; + if (strcmp(suffix, "total_timesteps") == 0) { + // Use agent_steps (training-only) instead of total_timesteps (train+eval) + for (int k = 0; k < env->n; k++) { + if (strcmp(env->hypers[k].key, "agent_steps") == 0) { + val = env->hypers[k].ary[ary_idx]; + break; + } + } + buffer += sprintf(buffer, "%s = %lld\n", suffix, (long long)(val * 1e6)); + } else if (strcmp(suffix, "agent_steps") == 0) { + buffer += sprintf(buffer, "%s = %lld\n", suffix, (long long)(val * 1e6)); + } else if (val == (long long)val) { + buffer += sprintf(buffer, "%s = %lld\n", suffix, (long long)val); + } else { + buffer += sprintf(buffer, "%s = %g\n", suffix, val); + } + } + buffer[0] = '\0'; + SetClipboardText(start); +} + +//strof bottlenecks loads +float fast_atof(char **s) { + char *p = *s; + float sign = 1.0f; + if (*p == '-') { + sign = -1.0f; p++; + } + float val = 0.0f; + while (*p >= '0' && *p <= '9') { + val = val * 10.0f + (*p++ - '0'); + } + if (*p == '.') { + p++; + float frac = 0.1f; + while (*p >= '0' && *p <= '9') { + val += (*p++ - '0') * frac; frac *= 0.1f; + } + } + if (*p == 'e' || *p == 'E') { + p++; + int esign = 1; + if (*p == '-') { + esign = -1; p++; + } else if (*p == '+') { + p++; + } + int exp = 0; + while (*p >= '0' && *p <= '9') { + exp = exp * 10 + (*p++ - '0'); + } + val *= powf(10.0f, esign * exp); + } + *s = p; + return sign * val; +} + +int main(void) { + FILE *file = fopen("resources/constellation/experiments.json", "r"); + if (!file) { + printf("Error opening file\n"); + return 1; + } + + // Read in file + fseek(file, 0, SEEK_END); + long file_size = ftell(file); + fseek(file, 0, SEEK_SET); + char *json_str = malloc(file_size + 1); + fread(json_str, 1, file_size, file); + json_str[file_size] = '\0'; + fclose(file); + cJSON *root = cJSON_Parse(json_str); + if (!root) { + printf("JSON parse error: %.100s\n", cJSON_GetErrorPtr()); + free(json_str); + return 1; + } + if (!cJSON_IsObject(root)) { + printf("Error: Root is not an object\n"); + return 1; + } + + // Load in dataset + Dataset data = {NULL, 0}; + cJSON *json_env = root->child; + while (json_env) { + data.n++; + json_env = json_env->next; + } + + Env *envs = calloc(data.n, sizeof(Env)); + data.envs = envs; + json_env = root->child; + int max_data_points = 0; + for (int i=0; ichild; + while (json_hyper) { + envs[i].n++; + json_hyper = json_hyper->next; + } + envs[i].key = json_env->string; + envs[i].hypers = calloc(envs[i].n, sizeof(Hyper)); + json_hyper = json_env->child; + for (int j=0; jnext) { + envs[i].hypers[j].key = json_hyper->string; + int capacity = 1; + for (char* p = json_hyper->valuestring; *p; p++) { + if (*p == ',') { + capacity++; + } + } + if (capacity > max_data_points) { + max_data_points = capacity; + } + envs[i].hypers[j].ary = calloc(capacity, sizeof(float)); + + int n = 0; + char* s = json_hyper->valuestring; + while (*s) { + envs[i].hypers[j].ary[n++] = fast_atof(&s); + if (*s == ',') { + s++; + } + } + envs[i].hypers[j].n = n; + } + json_env = json_env->next; + } + int total_points = 0; + for (int i=0; i 0) strcat(options, ";"); + strcat(options, hyper_key[i]); + } + + // Options with extra "env_name;" + char* extra = "env_name;"; + char *env_hyper_options = malloc(options_len + strlen(extra)); + strcpy(env_hyper_options, extra); + strcat(env_hyper_options, options); + + // Env names as semi-colon-separated string + size_t env_options_len = 4; + for (int i = 0; i < data.n; i++) { + env_options_len += strlen(data.envs[i].key) + 1; + } + char *env_options = malloc(env_options_len); + strcpy(env_options, "all;"); + env_options[4] = '\0'; + for (int i = 0; i < data.n; i++) { + if (i > 0) strcat(env_options, ";"); + strcat(env_options, data.envs[i].key); + } + + char* clipboard = malloc(16384); + + // Points + printf("total points: %d", total_points); + Point* points = calloc(total_points, sizeof(Point)); + Glyph* glyphs = calloc(total_points, sizeof(Glyph)); + Vector2* env_indices = calloc(total_points, sizeof(Vector2)); + + // Initialize Raylib + SetConfigFlags(FLAG_MSAA_4X_HINT); + InitWindow(2*DEFAULT_PLOT_ARGS.width, 2*DEFAULT_PLOT_ARGS.height + 2*SETTINGS_HEIGHT, "Puffer Constellation"); + Texture2D puffer = LoadTexture("resources/shared/puffers.png"); + + DEFAULT_PLOT_ARGS.font = LoadFontEx("resources/shared/JetBrainsMono-SemiBold.ttf", 32, NULL, 255); + DEFAULT_PLOT_ARGS.font_small = LoadFontEx("resources/shared/JetBrainsMono-SemiBold.ttf", 16, NULL, 255); + Font gui_font = LoadFontEx("resources/shared/JetBrainsMono-SemiBold.ttf", 14, NULL, 255); + + GuiLoadStyle("resources/constellation/puffer.rgs"); + GuiSetFont(gui_font); + ClearBackground(PUFF_BACKGROUND); + SetTargetFPS(60); + + Shader shader = LoadShader( + TextFormat("resources/constellation/point_particle_%i.vs", GLSL_VERSION), + TextFormat("resources/constellation/point_particle_%i.fs", GLSL_VERSION) + ); + Shader blur_shader = LoadShader( + TextFormat("resources/constellation/blur_%i.vs", GLSL_VERSION), + TextFormat("resources/constellation/blur_%i.fs", GLSL_VERSION) + ); + + // Allows the vertex shader to set the point size of each particle individually + #ifndef GRAPHICS_API_OPENGL_ES2 + glEnable(GL_PROGRAM_POINT_SIZE); + #endif + + PlotArgs args1 = DEFAULT_PLOT_ARGS; + args1.camera = (Camera3D){ 0 }; + args1.camera.position = (Vector3){ 1.5f, 1.25f, 1.5f }; + args1.camera.target = (Vector3){ 0.5f, 0.5f, 0.5f }; + args1.camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; + args1.camera.fovy = 45.0f; + args1.camera.projection = CAMERA_PERSPECTIVE; + args1.scale[0] = 1; + args1.scale[2] = 1; + RenderTexture2D fig1 = LoadRenderTexture(args1.width, args1.height); + RenderTexture2D fig1_overlay = LoadRenderTexture(args1.width, args1.height); + int fig_env_idx = 0; + bool fig_env_active = false; + bool fig_x_active = false; + int fig_x_idx = 1; + bool fig_xscale_active = false; + bool fig_y_active = false; + int fig_y_idx = 2; + bool fig_yscale_active = false; + bool fig_z_active = false; + int fig_z_idx = 0; + bool fig_zscale_active = false; + int fig_color_idx = 0; + bool fig_color_active = false; + bool fig_colorscale_active = false; + bool fig_range1_active = false; + int fig_range1_idx = 2; + char fig_range1_min[32] = {0}; + char fig_range1_max[32] = {0}; + float fig_range1_min_val = 0; + float fig_range1_max_val = FLT_MAX; + bool fig_range2_active = false; + int fig_range2_idx = 1; + char fig_range2_min[32] = {0}; + char fig_range2_max[32] = {0}; + float fig_range2_min_val = FLT_MIN; + float fig_range2_max_val = FLT_MAX; + int fig_box_idx = LOG; + bool fig_box_active = false; + + char* scale_options = "linear;log;logit"; + + PlotArgs args2 = DEFAULT_PLOT_ARGS; + RenderTexture2D fig2 = LoadRenderTexture(args2.width, args2.height); + args2.right_margin = 50; + args2.scale[0] = 1; + + PlotArgs args3 = DEFAULT_PLOT_ARGS; + RenderTexture2D fig3 = LoadRenderTexture(args3.width, args3.height); + RenderTexture2D fig3_overlay = LoadRenderTexture(args1.width, args1.height); + args3.left_margin = 10; + args3.right_margin = 10; + args3.top_margin = 10; + args3.bottom_margin = 10; + args3.x_label = "tsne1"; + args3.y_label = "tsne2"; + + PlotArgs args4 = DEFAULT_PLOT_ARGS; + RenderTexture2D fig4 = LoadRenderTexture(args4.width, args4.height); + args4.x_label = "Value"; + args4.y_label = "Hyperparameter"; + args4.left_margin = 170; + args4.right_margin = 50; + args4.top_margin = 10; + args4.bottom_margin = 50; + + Hyper* x; + Hyper* y; + Hyper* z; + Hyper* c; + char* x_label; + char* y_label; + char* z_label; + + bool *filter = calloc(max_data_points, sizeof(bool)); + + Tooltip tooltip = {0}; + + Vector2 focus = {0, 0}; + + while (!WindowShouldClose()) { + bool right_clicked = false; + + BeginDrawing(); + ClearBackground(PUFF_BACKGROUND); + + if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) { + focus = GetMousePosition(); + tooltip.active = false; + } + if (IsMouseButtonPressed(MOUSE_RIGHT_BUTTON)) { + Vector2 mouse_pos = GetMousePosition(); + right_clicked = true; + tooltip.active = true; + tooltip.click_x = mouse_pos.x; + tooltip.click_y = mouse_pos.y; + } + + // Figure 1 + x_label = hyper_key[fig_x_idx]; + y_label = hyper_key[fig_y_idx]; + z_label = hyper_key[fig_z_idx]; + args1.x_label = x_label; + args1.y_label = y_label; + args1.z_label = z_label; + int start = 0; + int end = data.n; + if (fig_env_idx != 0) { + start = fig_env_idx - 1; + end = fig_env_idx; + } + BeginTextureMode(fig1); + ClearBackground(PUFF_BACKGROUND); + + int size = 0; + for (int i=start; in; j++) { + filter[j] = true; + } + Hyper* filter_param_1 = get_hyper(&data, env, hyper_key[fig_range1_idx]); + apply_filter(filter, filter_param_1, fig_range1_min_val, fig_range1_max_val); + Hyper* filter_param_2 = get_hyper(&data, env, hyper_key[fig_range2_idx]); + apply_filter(filter, filter_param_2, fig_range2_min_val, fig_range2_max_val); + + for (int j=0; jn; j++) { + if (!filter[j]) { + continue; + } + points[size] = (Point){ + x->ary[j], + y->ary[j], + z->ary[j], + (fig_color_idx == 0) ? i/(float)data.n : c->ary[j], + }; + env_indices[size] = (Vector2){i, j}; + size++; + } + } + autoscale(points, size, &args1); + toPx(points, glyphs, size, args1); + update_closest(&tooltip, env_indices, glyphs, size, 0, 2*SETTINGS_HEIGHT); + plot_gl(glyphs, size, &shader); + + BeginMode3D(args1.camera); + CustomUpdateCamera(&args1.camera, CAMERA_ORBITAL_SPEED); + draw_axes3(); + EndMode3D(); + EndTextureMode(); + + // Figure 2 + x_label = hyper_key[fig_x_idx]; + y_label = hyper_key[fig_y_idx]; + args2.scale[0] = args1.scale[0]; + args2.scale[1] = args1.scale[1]; + args2.x_label = x_label; + args2.y_label = y_label; + args2.top_margin = 20; + args2.left_margin = 100; + BeginTextureMode(fig2); + ClearBackground(PUFF_BACKGROUND); + + autoscale(points, size, &args2); + args2.mmin[2] = 0.0f; + args2.mmax[2] = 0.0f; + toPx(points, glyphs, size, args2); + update_closest(&tooltip, env_indices, glyphs, size, fig1.texture.width, 2*SETTINGS_HEIGHT); + plot_gl(glyphs, size, &shader); + draw_axes(args2); + draw_all_ticks(args2); + EndTextureMode(); + + // Figure 3 + BeginTextureMode(fig3); + ClearBackground(PUFF_BACKGROUND); + size = 0; + for (int i=0; in; j++) { + filter[j] = true; + } + Hyper* filter_param_1 = get_hyper(&data, env, hyper_key[fig_range1_idx]); + apply_filter(filter, filter_param_1, fig_range1_min_val, fig_range1_max_val); + Hyper* filter_param_2 = get_hyper(&data, env, hyper_key[fig_range2_idx]); + apply_filter(filter, filter_param_2, fig_range2_min_val, fig_range2_max_val); + + for (int j=0; jn; j++) { + if (!filter[j]) { + continue; + } + points[size] = (Point){ + x->ary[j], + y->ary[j], + 0.0f, + i/(float)data.n + }; + env_indices[size] = (Vector2){i, j}; + size++; + } + } + autoscale(points, size, &args3); + toPx(points, glyphs, size, args3); + update_closest(&tooltip, env_indices, glyphs, size, 0, fig1.texture.height + 2*SETTINGS_HEIGHT); + plot_gl(glyphs, size, &shader); + + //draw_axes(args3); + EndTextureMode(); + + // Figure 4 + args4.scale[0] = fig_box_idx; + if (args4.scale[0] == LINEAR) { + args4.mmin[0] = 0.0f; + args4.mmax[0] = 5.0f; + } else if (args4.scale[0] == LOG) { + args4.mmin[0] = 1.0e-5f; + args4.mmax[0] = 1.0e5f; + } else if (args4.scale[0] == LOGIT) { + args4.mmin[0] = 0.5f; + args4.mmax[0] = 0.999f; + } + BeginTextureMode(fig4); + ClearBackground(PUFF_BACKGROUND); + rlSetBlendFactorsSeparate(0x0302, 0x0303, 1, 0x0303, 0x8006, 0x8006); + BeginBlendMode(BLEND_CUSTOM_SEPARATE); + Color color = Fade(PUFF_CYAN, 1.0f / (float)(end - start)); + for (int i=start; ikey, hyper_key[fig_range1_idx]); + Hyper* filter_param_2 = get_hyper(&data, env->key, hyper_key[fig_range2_idx]); + for (int j=0; jkey, hyper_key[j]); + for (int k=0; kn; k++) { + filter[k] = true; + } + apply_filter(filter, filter_param_1, fig_range1_min_val, fig_range1_max_val); + apply_filter(filter, filter_param_2, fig_range2_min_val, fig_range2_max_val); + boxplot(hyper, args4.scale[0], j, hyper_count, args4, color, filter); + } + } + EndBlendMode(); + draw_axes(args4); + draw_box_ticks(hyper_key, hyper_count, args4); + EndTextureMode(); + + // Figure 1-4 + DrawTextureRec( + fig1.texture, + (Rectangle){0, 0, fig1.texture.width, -fig1.texture.height }, + (Vector2){ 0, 2*SETTINGS_HEIGHT }, WHITE + ); + BeginShaderMode(blur_shader); + rlSetBlendMode(RL_BLEND_ADDITIVE); + DrawTextureRec( + fig1_overlay.texture, + (Rectangle){0, 0, fig1_overlay.texture.width, -fig1_overlay.texture.height }, + (Vector2){ 0, 2*SETTINGS_HEIGHT }, WHITE + ); + rlSetBlendMode(RL_BLEND_ALPHA); + EndShaderMode(); + DrawTextureRec( + fig2.texture, + (Rectangle){ 0, 0, fig2.texture.width, -fig2.texture.height }, + (Vector2){ fig1.texture.width, 2*SETTINGS_HEIGHT }, WHITE + ); + DrawTextureRec( + fig3.texture, + (Rectangle){ 0, 0, fig3.texture.width, -fig3.texture.height }, + (Vector2){ 0, 2*SETTINGS_HEIGHT + fig1.texture.height }, WHITE + ); + BeginShaderMode(blur_shader); + rlSetBlendMode(RL_BLEND_ADDITIVE); + DrawTextureRec( + fig3_overlay.texture, + (Rectangle){0, 0, fig3_overlay.texture.width, -fig3_overlay.texture.height }, + (Vector2){ 0, 2*SETTINGS_HEIGHT + fig1.texture.height }, WHITE + ); + rlSetBlendMode(RL_BLEND_ALPHA); + EndShaderMode(); + DrawTextureRec( + fig4.texture, + (Rectangle){ 0, 0, fig4.texture.width, -fig4.texture.height }, + (Vector2){ fig1.texture.width, fig1.texture.height + 2*SETTINGS_HEIGHT }, WHITE + ); + + // UI + float y = SEP + SETTINGS_HEIGHT/2.0f - MeasureTextEx(args1.font_small, "Env", args1.axis_tick_font_size, 0).y/2.0f; + float x = SEP; + DrawTextEx(args1.font_small, "Env", (Vector2){x, y}, args1.axis_tick_font_size, 0, WHITE); + x += MeasureTextEx(args1.font_small, "Env", args1.axis_tick_font_size, 0).x + SEP; + + Rectangle fig_env_rect = {x, SEP, DROPDOWN_WIDTH, SETTINGS_HEIGHT}; + x += DROPDOWN_WIDTH + SPACER; + if (GuiDropdownBox(fig_env_rect, env_options, &fig_env_idx, fig_env_active)){ + fig_env_active = !fig_env_active; + } + + // X axis + DrawTextEx(args1.font_small, "X", (Vector2){x, y}, args1.axis_tick_font_size, 0, RED); + x += MeasureTextEx(args1.font_small, "X", args1.axis_tick_font_size, 0).x + SEP; + + Rectangle fig_x_rect = {x, SEP, DROPDOWN_WIDTH, SETTINGS_HEIGHT}; + x += DROPDOWN_WIDTH; + if (GuiDropdownBox(fig_x_rect, options, &fig_x_idx, fig_x_active)){ + fig_x_active = !fig_x_active; + } + Rectangle fig_xscale_rect = {x, SEP, TOGGLE_WIDTH, SETTINGS_HEIGHT}; + x += TOGGLE_WIDTH + SPACER; + if (GuiDropdownBox(fig_xscale_rect, scale_options, &args1.scale[0], fig_xscale_active)){ + fig_xscale_active = !fig_xscale_active; + } + + // Y axis + DrawTextEx(args1.font_small, "Y", (Vector2){x, y}, args1.axis_tick_font_size, 0, GREEN); + x += MeasureTextEx(args1.font_small, "Y", args1.axis_tick_font_size, 0).x + SEP; + + Rectangle fig_y_rect = {x, SEP, DROPDOWN_WIDTH, SETTINGS_HEIGHT}; + x += DROPDOWN_WIDTH; + if (GuiDropdownBox(fig_y_rect, options, &fig_y_idx, fig_y_active)){ + fig_y_active = !fig_y_active; + } + Rectangle fig_yscale_rect = {x, SEP, TOGGLE_WIDTH, SETTINGS_HEIGHT}; + x += TOGGLE_WIDTH + SPACER; + if (GuiDropdownBox(fig_yscale_rect, scale_options, &args1.scale[1], fig_yscale_active)){ + fig_yscale_active = !fig_yscale_active; + } + + // Z axis + DrawTextEx(args1.font_small, "Z", (Vector2){x, y}, args1.axis_tick_font_size, 0, BLUE); + x += MeasureTextEx(args1.font_small, "Z", args1.axis_tick_font_size, 0).x + SEP; + + Rectangle fig_z_rect = {x, SEP, DROPDOWN_WIDTH, SETTINGS_HEIGHT}; + x += DROPDOWN_WIDTH; + if (GuiDropdownBox(fig_z_rect, options, &fig_z_idx, fig_z_active)){ + fig_z_active = !fig_z_active; + } + Rectangle fig_zscale_rect = {x, SEP, TOGGLE_WIDTH, SETTINGS_HEIGHT}; + x += TOGGLE_WIDTH + SPACER; + if (GuiDropdownBox(fig_zscale_rect, scale_options, &args1.scale[2], fig_zscale_active)){ + fig_zscale_active = !fig_zscale_active; + } + + // Color + DrawTextEx(args1.font_small, "C", (Vector2){x, y}, args1.axis_tick_font_size, 0, WHITE); + x += MeasureTextEx(args1.font_small, "C", args1.axis_tick_font_size, 0).x + SEP; + + Rectangle fig_color_rect = {x, SEP, DROPDOWN_WIDTH, SETTINGS_HEIGHT}; + x += DROPDOWN_WIDTH; + if (GuiDropdownBox(fig_color_rect, env_hyper_options, &fig_color_idx, fig_color_active)){ + fig_color_active = !fig_color_active; + } + Rectangle fig_colorscale_rect = {x, SEP, TOGGLE_WIDTH, SETTINGS_HEIGHT}; + x += TOGGLE_WIDTH + SPACER; + if (GuiDropdownBox(fig_colorscale_rect, scale_options, &args1.scale[3], fig_colorscale_active)){ + fig_colorscale_active = !fig_colorscale_active; + } + + // Temp hack + args2.scale[3] = args1.scale[3]; + args3.scale[3] = args1.scale[3]; + args4.scale[3] = args1.scale[3]; + + // Filters + DrawTextEx(args1.font_small, "F1", (Vector2){x, y}, args1.axis_tick_font_size, 0, WHITE); + x += MeasureTextEx(args1.font_small, "F1", args1.axis_tick_font_size, 0).x + SEP; + + GuiDropdownFilter(x, SEP, options, + &fig_range1_idx, &fig_range1_active, focus, fig_range1_min, + &fig_range1_min_val, fig_range1_max, &fig_range1_max_val); + x += DROPDOWN_WIDTH + 2*TOGGLE_WIDTH + SPACER; + + DrawTextEx(args1.font_small, "F2", (Vector2){x, y}, args1.axis_tick_font_size, 0, WHITE); + x += MeasureTextEx(args1.font_small, "F2", args1.axis_tick_font_size, 0).x + SEP; + + GuiDropdownFilter(x, SEP, options, + &fig_range2_idx, &fig_range2_active, focus, fig_range2_min, + &fig_range2_min_val, fig_range2_max, &fig_range2_max_val); + x += DROPDOWN_WIDTH + 2*TOGGLE_WIDTH + SPACER; + + // Box + DrawTextEx(args1.font_small, "Box", (Vector2){x, y}, args1.axis_tick_font_size, 0, WHITE); + x += MeasureTextEx(args1.font_small, "Box", args1.axis_tick_font_size, 0).x + SEP; + + Rectangle box_rect = {x, SEP, TOGGLE_WIDTH, SETTINGS_HEIGHT}; + if (GuiDropdownBox(box_rect, scale_options, &fig_box_idx, fig_box_active)) { + fig_box_active = !fig_box_active; + } + + // Puffer + float width = GetScreenWidth(); + DrawTexturePro( + puffer, + (Rectangle){0, 128, 128, 128}, + (Rectangle){width - 48, -8, 48, 48}, + (Vector2){0, 0}, + 0, + WHITE + ); + + // Tooltip + int env_idx = tooltip.env_idx; + int ary_idx = tooltip.ary_idx; + Env* env = &data.envs[env_idx]; + char* env_key = env->key; + + float cost = get_hyper(&data, env_key, "uptime")->ary[ary_idx]; + float score = get_hyper(&data, env_key, "env/score")->ary[ary_idx]; + float steps = get_hyper(&data, env_key, "agent_steps")->ary[ary_idx]; + if (tooltip.active) { + const char* text = TextFormat("%s\nscore = %f\ncost = %f\nsteps = %f", env_key, score, cost, steps); + Vector2 text_size = MeasureTextEx(args1.font_small, text, args1.axis_tick_font_size, 0); + float x = tooltip.x; + float y = tooltip.y; + if (x + text_size.x + 4 > GetScreenWidth()) { + x = x - text_size.x - 4; + } + if (y + text_size.y + 4 > GetScreenHeight()) { + y = y - text_size.y - 4; + } + DrawRectangle(x, y, text_size.x + 4, text_size.y + 4, PUFF_BACKGROUND); + DrawCircle(tooltip.x, tooltip.y, 2, PUFF_CYAN); + DrawTextEx(args1.font_small, text, (Vector2){x + 2, y + 2}, args1.axis_tick_font_size, 0, WHITE); + } + EndDrawing(); + + // Copy hypers to clipboard + if (right_clicked) { + copy_hypers_to_clipboard(env, clipboard, ary_idx); + } + } + + // Cleanup + for (int i = 0; i < data.n; i++) { + for (int j = 0; j < envs[i].n; j++) { + free(envs[i].hypers[j].ary); + } + free(envs[i].hypers); + } + free(envs); + cJSON_Delete(root); + free(json_str); + free(options); + free(env_hyper_options); + free(env_options); + free(clipboard); + free(points); + free(glyphs); + free(env_indices); + free(filter); + + // Raylib resources + UnloadShader(shader); + UnloadShader(blur_shader); + UnloadRenderTexture(fig1); + UnloadRenderTexture(fig1_overlay); + UnloadRenderTexture(fig2); + UnloadRenderTexture(fig3); + UnloadRenderTexture(fig3_overlay); + UnloadRenderTexture(fig4); + CloseWindow(); + return 0; +} diff --git a/examples/vectorization.py b/examples/vectorization.py index 4a6ff2ecb0..3e614bde5a 100644 --- a/examples/vectorization.py +++ b/examples/vectorization.py @@ -72,7 +72,7 @@ def close(self): try: vecenv = pufferlib.vector.make(SamplePufferEnv, num_envs=1, num_workers=2, batch_size=3, backend=pufferlib.vector.Multiprocessing) - except pufferlib.APIUsageError: + except (AssertionError, ValueError): #Make sure num_envs divides num_workers, and both num_envs and num_workers should divide batch_size pass diff --git a/pufferlib/ocean/asteroids/asteroids.c b/ocean/asteroids/asteroids.c similarity index 100% rename from pufferlib/ocean/asteroids/asteroids.c rename to ocean/asteroids/asteroids.c diff --git a/pufferlib/ocean/asteroids/asteroids.h b/ocean/asteroids/asteroids.h similarity index 100% rename from pufferlib/ocean/asteroids/asteroids.h rename to ocean/asteroids/asteroids.h diff --git a/pufferlib/ocean/asteroids/binding.c b/ocean/asteroids/binding.c similarity index 100% rename from pufferlib/ocean/asteroids/binding.c rename to ocean/asteroids/binding.c diff --git a/pufferlib/ocean/battle/battle.c b/ocean/battle/battle.c similarity index 99% rename from pufferlib/ocean/battle/battle.c rename to ocean/battle/battle.c index c6193318fb..ca46049485 100644 --- a/pufferlib/ocean/battle/battle.c +++ b/ocean/battle/battle.c @@ -14,7 +14,7 @@ int main() { // Weights are exported by running puffer export - //Weights* weights = load_weights("resources/puffer_battle_weights.bin", 137743); + //Weights* weights = load_weights("resources/puffer_battle_weights.bin"); //int logit_sizes[2] = {9, 5}; //LinearLSTM* net = make_linearlstm(weights, num_agents, num_obs, logit_sizes, 2); diff --git a/pufferlib/ocean/battle/battle.h b/ocean/battle/battle.h similarity index 100% rename from pufferlib/ocean/battle/battle.h rename to ocean/battle/battle.h diff --git a/pufferlib/ocean/battle/binding.c b/ocean/battle/binding.c similarity index 100% rename from pufferlib/ocean/battle/binding.c rename to ocean/battle/binding.c diff --git a/pufferlib/ocean/battle/rlights.h b/ocean/battle/rlights.h similarity index 100% rename from pufferlib/ocean/battle/rlights.h rename to ocean/battle/rlights.h diff --git a/pufferlib/ocean/battle/simplex.h b/ocean/battle/simplex.h similarity index 100% rename from pufferlib/ocean/battle/simplex.h rename to ocean/battle/simplex.h diff --git a/ocean/benchmark/benchmark.c b/ocean/benchmark/benchmark.c new file mode 100644 index 0000000000..4c9abaaf95 --- /dev/null +++ b/ocean/benchmark/benchmark.c @@ -0,0 +1,100 @@ +#include +#include +#include +#include +#include "benchmark.h" + +int main(int argc, char** argv) { + int num_envs = argc > 1 ? atoi(argv[1]) : 1; + int threads = argc > 2 ? atoi(argv[2]) : 1; + int compute = argc > 3 ? atoi(argv[3]) : 0; + int bandwidth = argc > 4 ? atoi(argv[4]) : 1000; + int timeout = argc > 5 ? atoi(argv[5]) : 3; + + if (argc == 1) { + printf("Usage: %s [num_envs] [threads] [compute] [bandwidth] [timeout]\n", argv[0]); + printf(" num_envs: number of parallel environments (default: 1)\n"); + printf(" threads: OpenMP threads (default: 1)\n"); + printf(" compute: sinf() iterations per step (default: 0)\n"); + printf(" bandwidth: bytes written per step (default: 1000)\n"); + printf(" timeout: test duration in seconds (default: 3)\n\n"); + } + + if (threads > 0) { + omp_set_num_threads(threads); + } + + printf("Benchmark: envs=%d, threads=%d, compute=%d, bandwidth=%d\n", + num_envs, threads, compute, bandwidth); + + unsigned char* observations = (unsigned char*)calloc(num_envs*bandwidth, sizeof(unsigned char)); + double* actions = (double*)calloc(num_envs, sizeof(double)); + float* rewards = (float*)calloc(num_envs, sizeof(float)); + float* terminals = (float*)calloc(num_envs, sizeof(float)); + + // Allocate env array with pointers into contiguous buffers + Benchmark* envs = (Benchmark*)calloc(num_envs, sizeof(Benchmark)); + for (int i = 0; i < num_envs; i++) { + envs[i].bandwidth = bandwidth; + envs[i].compute = compute; + envs[i].observations = observations + i * bandwidth; + envs[i].actions = actions + i; + envs[i].rewards = rewards + i; + envs[i].terminals = terminals + i; + c_reset(&envs[i]); + } + + // Warmup + for (int w = 0; w < 10; w++) { + if (threads > 0) { + #pragma omp parallel for schedule(static) + for (int i = 0; i < num_envs; i++) { + c_step(&envs[i]); + } + } else { + for (int i = 0; i < num_envs; i++) { + c_step(&envs[i]); + } + } + } + + int start = time(NULL); + long num_steps = 0; + while (time(NULL) - start < timeout) { + if (threads > 0) { + #pragma omp parallel for schedule(static) + for (int i = 0; i < num_envs; i++) { + c_step(&envs[i]); + } + } else { + for (int i = 0; i < num_envs; i++) { + c_step(&envs[i]); + } + } + num_steps += num_envs; + } + + int elapsed = time(NULL) - start; + double sps = (double)num_steps / elapsed; + double bytes_per_sec = sps * bandwidth; + + // Checksum to prevent optimization + unsigned char checksum = 0; + for (int i = 0; i < num_envs; i++) { + checksum ^= envs[i].observations[0]; + } + + printf("Checksum: %d\n", checksum); + printf(" steps=%ld, elapsed=%ds\n", num_steps, elapsed); + printf(" throughput: %.2f M steps/s\n", sps / 1e6); + printf(" bandwidth: %.2f GB/s\n", bytes_per_sec / 1e9); + + // Cleanup + free(observations); + free(actions); + free(rewards); + free(terminals); + free(envs); + + return 0; +} diff --git a/ocean/benchmark/benchmark.h b/ocean/benchmark/benchmark.h new file mode 100644 index 0000000000..8ee3819d3e --- /dev/null +++ b/ocean/benchmark/benchmark.h @@ -0,0 +1,34 @@ +#include +#include + +typedef struct { + float perf; + float score; + float n; +} Log; + +typedef struct { + Log log; + unsigned char* observations; + double* actions; + float* rewards; + float* terminals; + int num_agents; + int bandwidth; + int compute; +} Benchmark; + +void c_reset(Benchmark* env) {} + +void c_step(Benchmark* env) { + float result = 0; + for (int i=0; icompute; i++) { + result = sinf(result + 0.1f); + } + + //memset(env->observations, result, env->bandwidth); +} + +void c_render(Benchmark* env) { } + +void c_close(Benchmark* env) { } diff --git a/ocean/benchmark/binding.c b/ocean/benchmark/binding.c new file mode 100644 index 0000000000..946d1811ec --- /dev/null +++ b/ocean/benchmark/binding.c @@ -0,0 +1,20 @@ +#include "benchmark.h" +#define OBS_SIZE 512 // TODO: Current API forces you to edit this per obs size +#define NUM_ATNS 1 +#define ACT_SIZES {2} +#define OBS_TYPE UNSIGNED_CHAR +#define ACT_TYPE DOUBLE + +#define Env Benchmark +#include "vecenv.h" + +void my_init(Env* env, Dict* kwargs) { + env->num_agents = 1; + env->compute = dict_get(kwargs, "compute")->value; + env->bandwidth = dict_get(kwargs, "bandwidth")->value; +} + +void my_log(Log* log, Dict* out) { + dict_set(out, "perf", log->perf); + dict_set(out, "score", log->score); +} diff --git a/ocean/blastar/binding.c b/ocean/blastar/binding.c new file mode 100644 index 0000000000..b1fc45284d --- /dev/null +++ b/ocean/blastar/binding.c @@ -0,0 +1,28 @@ +#include "blastar.h" +#define OBS_SIZE 10 +#define NUM_ATNS 1 +#define ACT_SIZES {6} +#define OBS_TYPE FLOAT +#define ACT_TYPE DOUBLE + +#define Env Blastar +#include "vecenv.h" + +void my_init(Env* env, Dict* kwargs) { + env->num_agents = 1; + int num_obs = dict_get(kwargs, "num_obs")->value; + init(env, num_obs); +} + +void my_log(Log* log, Dict* out) { + dict_set(out, "perf", log->perf); + dict_set(out, "score", log->score); + dict_set(out, "episode_return", log->episode_return); + dict_set(out, "episode_length", log->episode_length); + dict_set(out, "lives", log->lives); + dict_set(out, "vertical_closeness_rew", log->vertical_closeness_rew); + dict_set(out, "fired_bullet_rew", log->fired_bullet_rew); + dict_set(out, "kill_streak", log->kill_streak); + dict_set(out, "hit_enemy_with_bullet_rew", log->hit_enemy_with_bullet_rew); + dict_set(out, "avg_score_difference", log->avg_score_difference); +} diff --git a/pufferlib/ocean/blastar/blastar.c b/ocean/blastar/blastar.c similarity index 97% rename from pufferlib/ocean/blastar/blastar.c rename to ocean/blastar/blastar.c index a4400288d0..8c5d322f56 100644 --- a/pufferlib/ocean/blastar/blastar.c +++ b/ocean/blastar/blastar.c @@ -27,7 +27,7 @@ void get_input(Blastar* env) { } int demo() { - Weights* weights = load_weights(WEIGHTS_PATH, NUM_WEIGHTS); + Weights* weights = load_weights(WEIGHTS_PATH); int logit_sizes[1] = {ACTIONS_SIZE}; LinearLSTM* net = make_linearlstm(weights, 1, OBSERVATIONS_SIZE, logit_sizes, 1); Blastar env = { diff --git a/pufferlib/ocean/blastar/blastar.h b/ocean/blastar/blastar.h similarity index 98% rename from pufferlib/ocean/blastar/blastar.h rename to ocean/blastar/blastar.h index 7020c0c1c2..6bea710e4f 100644 --- a/pufferlib/ocean/blastar/blastar.h +++ b/ocean/blastar/blastar.h @@ -85,9 +85,10 @@ typedef struct Blastar { Player player; Enemy enemy; float* observations; - int* actions; + double* actions; float* rewards; - unsigned char* terminals; + float* terminals; + int num_agents; Log log; } Blastar; @@ -151,9 +152,9 @@ void init(Blastar* env, int num_obs) { void allocate(Blastar* env, int num_obs) { init(env, num_obs); env->observations = (float*)calloc(env->num_obs, sizeof(float)); - env->actions = (int*)calloc(1, sizeof(int)); + env->actions = (double*)calloc(1, sizeof(double)); env->rewards = (float*)calloc(1, sizeof(float)); - env->terminals = (unsigned char*)calloc(1, sizeof(unsigned char)); + env->terminals = (float*)calloc(1, sizeof(float)); } void free_allocated(Blastar* env) { diff --git a/pufferlib/ocean/boids/binding.c b/ocean/boids/binding.c similarity index 100% rename from pufferlib/ocean/boids/binding.c rename to ocean/boids/binding.c diff --git a/pufferlib/ocean/boids/boids.c b/ocean/boids/boids.c similarity index 100% rename from pufferlib/ocean/boids/boids.c rename to ocean/boids/boids.c diff --git a/pufferlib/ocean/boids/boids.h b/ocean/boids/boids.h similarity index 100% rename from pufferlib/ocean/boids/boids.h rename to ocean/boids/boids.h diff --git a/ocean/boxoban/binding.c b/ocean/boxoban/binding.c new file mode 100644 index 0000000000..86c6b341d8 --- /dev/null +++ b/ocean/boxoban/binding.c @@ -0,0 +1,29 @@ +#define BOXOBAN_MAPS_IMPLEMENTATION //enables mmap +#include "boxoban.h" +#define OBS_SIZE 400 +#define NUM_ATNS 1 +#define ACT_SIZES {5} +#define OBS_TENSOR_T ByteTensor + + +#define Env Boxoban +#include "vecenv.h" + + +void my_init(Env* env, Dict* kwargs) { + env->difficulty_id = (int)dict_get(kwargs, "difficulty")->value; + env->size = 10; + env->num_agents = 1; + env->max_steps = (int)dict_get(kwargs, "max_steps")->value; + env->int_r_coeff = (float)dict_get(kwargs, "int_r_coeff")->value; + env->target_loss_pen_coeff = (float)dict_get(kwargs, "target_loss_pen_coeff")->value; + init(env); +} + +void my_log(Log* log, Dict* out) { + dict_set(out, "perf", log->perf); + dict_set(out, "score", log->score); + dict_set(out, "episode_return", log->episode_return); + dict_set(out, "episode_length", log->episode_length); + dict_set(out, "targets_hit", log->on_targets); +} diff --git a/ocean/boxoban/boxoban.c b/ocean/boxoban/boxoban.c new file mode 100644 index 0000000000..c52d8054ec --- /dev/null +++ b/ocean/boxoban/boxoban.c @@ -0,0 +1,195 @@ +/* Pure C demo file for Boxoban. Usage: + * bash scripts/build_ocean.sh boxoban + * ./boxoban [difficulty|path_to_bin] + * + * If you pass one of the known difficulty names (basic, easy, medium, + * hard, unfiltered) the demo looks for pufferlib/ocean/boxoban/boxoban_maps_.bin + * Otherwise the argument is treated as an explicit path to a bin file. + */ + +#define BOXOBAN_MAPS_IMPLEMENTATION +#include +#include "boxoban.h" + +static int is_named_difficulty(const char* arg) { + return strcmp(arg, "basic") == 0 || + strcmp(arg, "easy") == 0 || + strcmp(arg, "medium") == 0 || + strcmp(arg, "hard") == 0 || + strcmp(arg, "unfiltered") == 0; +} + +static const char* resolve_map_path(int argc, char** argv, char* buffer, size_t buf_sz) { + const char* arg = argc > 1 ? argv[1] : NULL; + if (arg == NULL) { + if (boxoban_prepare_maps_for_difficulty("easy", buffer, buf_sz) != 0) { + return NULL; + } + return buffer; + } + if (strchr(arg, '/')) { + return arg; + } + if (is_named_difficulty(arg)) { + if (boxoban_prepare_maps_for_difficulty(arg, buffer, buf_sz) != 0) { + return NULL; + } + return buffer; + } + snprintf(buffer, buf_sz, "pufferlib/ocean/boxoban/boxoban_maps_%s.bin", arg); + return buffer; +} + + +int demo(int argc, char** argv) { + char path_buffer[512]; + const char* chosen_path = resolve_map_path(argc, argv, path_buffer, sizeof(path_buffer)); + if (chosen_path == NULL) { + fprintf(stderr, "Failed to prepare map path\n"); + return 1; + } + if (boxoban_set_map_path(chosen_path) != 0) { + fprintf(stderr, "Failed to set map path: %s\n", chosen_path); + return 1; + } + + Boxoban env = { + .size = 10, + .observations = NULL, + .actions = NULL, + .rewards = NULL, + .terminals = NULL, + .max_steps = 500, + .int_r_coeff = 0.1f, + .target_loss_pen_coeff = 0.5f, + .tick = 0, + .agent_x = 0, + .agent_y = 0, + .intermediate_rewards = NULL, + .on_target = 0, + .n_boxes = 0, + .win = 0, + .difficulty_id = -1, + .client = NULL, + .n_targets = 0, + + }; + + size_t obs_count = 4u * (size_t)env.size * (size_t)env.size; + env.observations = calloc(obs_count, sizeof(unsigned char)); + env.actions = calloc(1, sizeof(int)); + env.rewards = calloc(1, sizeof(float)); + env.terminals = calloc(1, sizeof(unsigned char)); + + init(&env); + c_reset(&env); + c_render(&env); + while (!WindowShouldClose()) { + if (IsKeyPressed(KEY_LEFT_SHIFT) || IsKeyPressed(KEY_RIGHT_SHIFT)) { + TraceLog(LOG_INFO, "Shift key pressed"); + } + bool manual = IsKeyDown(KEY_LEFT_SHIFT) || IsKeyDown(KEY_RIGHT_SHIFT); + bool stepped = false; + if (manual) { + int new_action = -1; + if (IsKeyDown(KEY_UP) || IsKeyDown(KEY_W)) new_action = UP; + if (IsKeyDown(KEY_DOWN) || IsKeyDown(KEY_S)) new_action = DOWN; + if (IsKeyDown(KEY_LEFT) || IsKeyDown(KEY_A)) new_action = LEFT; + if (IsKeyDown(KEY_RIGHT) || IsKeyDown(KEY_D)) new_action = RIGHT; + + if (new_action >= 0) { + env.actions[0] = new_action; + c_step(&env); + stepped = true; + } + } else { + env.actions[0] = rand() % 5; + c_step(&env); + stepped = true; + } + + if (!stepped) { + // Manual mode with no direction: stay paused + } + c_render(&env); + } + free(env.observations); + free(env.actions); + free(env.rewards); + free(env.terminals); + c_close(&env); + return 0; +} + +void test_performance(int argc, char** argv, int timeout) { + char path_buffer[512]; + const char* chosen_path = resolve_map_path(argc, argv, path_buffer, sizeof(path_buffer)); + if (chosen_path == NULL) { + fprintf(stderr, "Failed to prepare map path\n"); + return; + } + if (boxoban_set_map_path(chosen_path) != 0) { + fprintf(stderr, "Failed to set map path: %s\n", chosen_path); + return; + } + printf("Loaded map: %s\n", chosen_path); + + Boxoban env = { + .size = 10, + .observations = NULL, + .actions = NULL, + .rewards = NULL, + .terminals = NULL, + .max_steps = 500, + .int_r_coeff = 0.1f, + .target_loss_pen_coeff = 0.5f, + .tick = 0, + .agent_x = 0, + .agent_y = 0, + .intermediate_rewards = NULL, + .on_target = 0, + .n_boxes = 0, + .win = 0, + .difficulty_id = -1, + .client = NULL, + .n_targets = 0, + }; + + size_t obs_count = 4u * (size_t)env.size * (size_t)env.size; + env.observations = calloc(obs_count, sizeof(unsigned char)); + env.actions = calloc(1, sizeof(int)); + env.rewards = calloc(1, sizeof(float)); + env.terminals = calloc(1, sizeof(unsigned char)); + + printf("Initializing...\n"); + init(&env); + printf("Resetting...\n"); + c_reset(&env); + printf("Starting test...\n"); + + int start = time(NULL); + int num_steps = 0; + while (time(NULL) - start < timeout) { + env.actions[0] = rand() % 5; + c_step(&env); + num_steps++; + } + + int end = time(NULL); + float sps = num_steps / (end - start); + printf("Test Environment SPS: %f\n", sps); + free(env.observations); + free(env.actions); + free(env.rewards); + free(env.terminals); + c_close(&env); +} + +int main(int argc, char** argv) { + demo(argc, argv); + setbuf(stdout, NULL); + fprintf(stderr, "Entered main\n"); + fflush(stderr); + //test_performance(argc, argv,10); + return 0; +} diff --git a/ocean/boxoban/boxoban.h b/ocean/boxoban/boxoban.h new file mode 100644 index 0000000000..35b61a2529 --- /dev/null +++ b/ocean/boxoban/boxoban.h @@ -0,0 +1,409 @@ +#include +#include +#include +#include +#include "raylib.h" +#include "boxoban_maps.h" + +const unsigned char NOOP = 0; +const unsigned char DOWN = 1; +const unsigned char UP = 2; +const unsigned char LEFT = 3; +const unsigned char RIGHT = 4; + +const unsigned char AGENT = 0; +const unsigned char WALLS = 1; +const unsigned char BOXES = 2; +const unsigned char TARGET = 3; + +// Required struct. Only use floats! +typedef struct { + float perf; // Recommended 0-1 normalized single real number perf metric + float score; // Recommended unnormalized single real number perf metric + float episode_return; // Recommended metric: sum of agent rewards over episode + float episode_length; // Recommended metric: number of steps of agent episode + // Any extra fields you add here may be exported to Python in binding.c + float on_targets; // Number of targets currently boxed + float n; // Required as the last field +} Log; + +typedef struct { + Texture2D wall; + Texture2D box; + Texture2D target; + Texture2D floor; + Texture2D agent; + Texture2D box_on_target; +} Client; + +// Required that you have some struct for your env +// Recommended that you name it the same as the env file +typedef struct { + Log log; // Required field. Env binding code uses this to aggregate logs + unsigned char* observations; // Required. You can use any obs type, but make sure it matches in Python! + float* actions; // Required. int* for discrete/multidiscrete, float* for box + float* rewards; // Required + float* terminals; // Required. We don't yet have truncations as standard yet + unsigned int rng; + int size; + int num_agents; + int tick; + int max_steps; + int agent_x; + int agent_y; + bool initialized; + unsigned char* intermediate_rewards; + float int_r_coeff; + float target_loss_pen_coeff; + int on_target; //num targets currently boxed + int n_boxes; //boxes in map + int n_targets; //targets in map + int difficulty_id; // 0=basic,1=easy,2=medium,3=hard,4=unfiltered + Client* client; + int win; + float episode_return; +} Boxoban; + +void ensure_map_loaded(void); + +static int boxoban_configure_maps_from_env(Boxoban* env) { + if (env->difficulty_id == -1) { + return 0; + } + + if (env->difficulty_id < -1) { + fprintf(stderr, "Invalid Boxoban difficulty id %d\n", env->difficulty_id); + return -1; + } + + const char* difficulty_name = boxoban_difficulty_name_from_id(env->difficulty_id); + if (difficulty_name == NULL) { + fprintf(stderr, "Invalid Boxoban difficulty id %d\n", env->difficulty_id); + return -1; + } + char prepared_path[512]; + if (boxoban_prepare_maps_for_difficulty(difficulty_name, prepared_path, sizeof(prepared_path)) != 0) { + return -1; + } + + return 0; +} + +//Entity,x,y convention y moves top to bottom + +static inline void set_entity(Boxoban *env, int entity, int x, int y, unsigned char value) { + env->observations[(entity)*env->size*env->size + (y)*env->size + (x)] = value; +} + +static inline unsigned char get_entity(Boxoban *env, int entity, int x, int y) { + return env->observations[(entity)*env->size*env->size + (y)*env->size + (x)]; +} + +static inline void set_intermediate_reward(Boxoban *env, int x, int y, unsigned char value) { + env->intermediate_rewards[(y)*env->size + (x)] = value; +} + +static inline unsigned char get_intermediate_reward_status(Boxoban *env, int x, int y) { + return env->intermediate_rewards[(y)*env->size + (x)]; +} + +static inline const uint32_t get_random_puzzle_idx(const Boxoban *env) { + int idx = rand_r(&env->rng) % PUZZLE_COUNT; + return idx; +} + + +void init (Boxoban* env) { + static int boxoban_maps_ready = 0; + if (!boxoban_maps_ready) { + if (boxoban_configure_maps_from_env(env) != 0) { + fprintf(stderr, "Failed to configure Boxoban maps\n"); + abort(); + } + ensure_map_loaded(); + boxoban_maps_ready = 1; + } + env->intermediate_rewards = calloc(env->size*env->size, sizeof(unsigned char)); + env->win = 0; + env->initialized = false; + } + + +void add_log(Boxoban* env) { + float denom = (float)env->n_boxes; + float num = (float)env->on_target; + float perf = (env->win== 1) ? 1.0f : 0.0f; + env->log.perf += perf; + env->log.score += perf; + env->log.episode_length += env->tick; + env->log.episode_return += env->episode_return; + env->log.on_targets += env->on_target; + env->log.n++; +} + + +bool clear(Boxoban* env, int x, int y) { + if (x < 0 || y < 0 || x >= env->size || y >= env->size) { + return false; + } + return (get_entity(env, WALLS, x, y) == 0) && (get_entity(env, BOXES, x, y) == 0); +} + +// Required function +void c_reset(Boxoban* env) { + const uint32_t i = get_random_puzzle_idx(env); + const uint8_t* puzzle = MAP_BASE + (size_t)i * PUZZLE_SIZE; + memcpy(env->observations, puzzle, PUZZLE_OBS_BYTES); + + const uint8_t* meta = puzzle + PUZZLE_OBS_BYTES; + env->agent_x = (int)meta[0]; + env->agent_y = (int)meta[1]; + env->n_boxes = (int)meta[2]; + env->n_targets = (int)meta[3]; + env->on_target = (int)meta[4]; + + memcpy(env->intermediate_rewards, + env->observations + TARGET * env->size * env->size,env->size * env->size); + + env->tick = 0; + env->win = 0; + env->episode_return = 0; + + if (!env->initialized) { + env->tick = rand_r(&env->rng) % env->max_steps; + env->initialized = true; + } +} + +//Updates OBS for moved entity +void move_entity(Boxoban* env,unsigned char entity,int x, int y, int dx, int dy) { + set_entity(env, entity, x, y, 0); + set_entity(env, entity, x + dx, y + dy, 1); +} + +//Updates state and intermediate reward array in place +int take_action(Boxoban* env, int action) { + + int dx = 0; + int dy = 0; + int int_r = 0; + + if (action == NOOP) { + return 0; + } + else if (action == DOWN) { + dy = 1; + } + else if (action == UP) { + dy = -1; + } + else if (action == LEFT) { + dx = -1; + } + else if (action == RIGHT) { + dx = 1; + } + + //if move space is clear, move agent + if (clear(env, env->agent_x + dx, env->agent_y + dy)) { + + move_entity(env, AGENT, env->agent_x, env->agent_y, dx, dy); + env->agent_y += dy; + env->agent_x += dx; + return 0; + } + //if its not clear, but its a box and box is clear to move, move both + else if (clear(env, env->agent_x+ 2*dx, env->agent_y + 2*dy) + && get_entity(env, BOXES, env->agent_x + dx, env->agent_y + dy) == 1) { + + //if box is on target currently, remove from on_target count + if (get_entity(env, TARGET, env->agent_x + dx, env->agent_y + dy) == 1) { + + env->on_target -= 1; + } + //move both entities + move_entity(env, BOXES, env->agent_x + dx, env->agent_y + dy, dx, dy); + move_entity(env, AGENT, env->agent_x, env->agent_y, dx, dy); + env->agent_y += dy; + env->agent_x += dx; + + //if box is now on target, add to on_target count + //if its a new target recieve intermediate reward and zero out intermediate reward + if (get_entity(env, TARGET, env->agent_x + dx, env->agent_y + dy) == 1) { + + env->on_target += 1; + int_r = get_intermediate_reward_status(env, env->agent_x + dx, env->agent_y + dy); + set_intermediate_reward(env, env->agent_x + dx, env->agent_y + dy, 0); + } + return int_r; + } + return 0; +} + +// Required function +void c_step(Boxoban* env) { + env->tick += 1; + env->terminals[0] = 0; + env->rewards[0] = 0.0; + + int action = (int)env->actions[0]; + + float on_target = env->on_target; + int int_r = take_action(env, action); //int_r _new_ tgts covered, modifies observations in place + float on_target_after = env->on_target; + + env->rewards[0] += (float)int_r * env->int_r_coeff; //coeff in .ini + + if (on_target_after < on_target) { //target loss penalty + env->rewards[0] -= env->target_loss_pen_coeff; //coeff in .ini + } + + //Terminals + if (env->on_target == env->n_targets) { + env->terminals[0] = 1; + env->rewards[0] += 1.0; + env->win = 1; + env->episode_return += env->rewards[0]; + add_log(env); + c_reset(env); + return; + } + + if (env->tick >= env->max_steps) { + env->terminals[0] = 1; + env->rewards[0] -= 1.0; + env->episode_return += env->rewards[0]; + add_log(env); + c_reset(env); + return; + } + env->episode_return += env->rewards[0]; + +} + +Client* c_create(Boxoban* env) { + Client* client = calloc(1,sizeof(Client)); + client->wall = LoadTexture("resources/boxoban/Wall_Black.jpg"); + client->box = LoadTexture("resources/boxoban/Crate_Black.jpg"); + client->target = LoadTexture("resources/boxoban/EndPoint_Black.jpg"); + client->floor = LoadTexture("resources/boxoban/GroundGravel_Concrete.jpg"); + client->box_on_target = LoadTexture("resources/boxoban/EndPoint_Blue.jpg"); + client->agent = LoadTexture("resources/shared/puffers_128.png"); + env-> client = client; + return client; +} + +#define TILE 32 + +Texture2D choose_sprite(Client *c, Boxoban *env, int x, int y) { + int a = get_entity(env, AGENT, x, y); + int w = get_entity(env, WALLS, x, y); + int b = get_entity(env, BOXES, x, y); + int t = get_entity(env, TARGET, x, y); + + if (w) return c->wall; + if (b && t) return c->box_on_target; + if (b) return c->box; + if (a) return c->agent; + if (t) return c->target; + + return c->floor; +} + +void draw_tile(Boxoban *env, int x, int y) { + Client *c = env->client; + Rectangle dest = {x * TILE, y * TILE, TILE, TILE}; + + // Always lay down the base tile + DrawTexturePro( + c->floor, + (Rectangle){0, 0, (float)c->floor.width, (float)c->floor.height}, + dest, + (Vector2){0, 0}, + 0.0f, + WHITE); + + if (get_entity(env, TARGET, x, y)) { + DrawTexturePro( + c->target, + (Rectangle){0, 0, (float)c->target.width, (float)c->target.height}, + dest, + (Vector2){0, 0}, + 0.0f, + WHITE); + } + if (get_entity(env, BOXES, x, y)) { + Texture2D tex = get_entity(env, TARGET, x, y) ? c->box_on_target : c->box; + DrawTexturePro( + tex, + (Rectangle){0, 0, (float)tex.width, (float)tex.height}, + dest, + (Vector2){0, 0}, + 0.0f, + WHITE); + } + if (get_entity(env, WALLS, x, y)) { + DrawTexturePro( + c->wall, + (Rectangle){0, 0, (float)c->wall.width, (float)c->wall.height}, + dest, + (Vector2){0, 0}, + 0.0f, + WHITE); + } + if (get_entity(env, AGENT, x, y)) { + Rectangle src = {0, 0, c->agent.width / 2.0f, (float)c->agent.height}; + DrawTexturePro(c->agent, src, dest, (Vector2){0, 0}, 0.0f, WHITE); + } + } + + +// Required function. Should handle creating the client on first call +void c_render(Boxoban* env) { + if (!IsWindowReady()) { + InitWindow(TILE*env->size, TILE*env->size, "PufferLib Boxoban"); + SetTargetFPS(10); + } + + // Standard across our envs so exiting is always the same + if (IsKeyDown(KEY_ESCAPE)) { + exit(0); + } + + if (env->client == NULL) { + env->client = c_create(env); + } + + BeginDrawing(); + ClearBackground((Color){6, 24, 24, 255}); + + for (int y = 0; y < env->size; y++) { + for (int x = 0; x < env->size; x++) { + draw_tile(env, x, y); + } + } + + + EndDrawing(); +} + +// Required function. Should clean up anything you allocated +// Do not free env->observations, actions, rewards, terminals +void c_close(Boxoban* env) { + if (env->intermediate_rewards) { + free(env->intermediate_rewards); + env->intermediate_rewards = NULL; + } + if (IsWindowReady()) { + if (env->client) { + UnloadTexture(env->client->wall); + UnloadTexture(env->client->box); + UnloadTexture(env->client->target); + UnloadTexture(env->client->floor); + UnloadTexture(env->client->agent); + free(env->client); + env->client = NULL; + } + CloseWindow(); + } +} diff --git a/ocean/boxoban/boxoban_maps.h b/ocean/boxoban/boxoban_maps.h new file mode 100644 index 0000000000..c633c37307 --- /dev/null +++ b/ocean/boxoban/boxoban_maps.h @@ -0,0 +1,453 @@ +#ifndef PUFFERLIB_OCEAN_BOXOBAN_MAPS_H +#define PUFFERLIB_OCEAN_BOXOBAN_MAPS_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "generate_maps.h" +#include "parse_maps.h" + +/* +Maps are stored in binary files keyed by difficulty. +If the bin does not exist it is created on the fly, then mmapped and shared by envs. +*/ + +extern uint8_t *MAP_BASE; +extern size_t MAP_FILESIZE; +extern size_t PUZZLE_COUNT; +extern size_t PUZZLE_SIZE; +extern size_t PUZZLE_OBS_BYTES; + +int boxoban_prepare_maps_for_difficulty(const char* difficulty, char* out_path, size_t out_cap); +int boxoban_set_map_path(const char *path); +int boxoban_difficulty_id_from_name(const char* difficulty_name); +const char* boxoban_difficulty_name_from_id(int difficulty_id); +void ensure_map_loaded(void); + +#ifdef BOXOBAN_MAPS_IMPLEMENTATION + +uint8_t *MAP_BASE = NULL; +size_t MAP_FILESIZE = 0; +size_t PUZZLE_COUNT = 0; +size_t PUZZLE_SIZE = BOXOBAN_PUZZLE_BYTES; +size_t PUZZLE_OBS_BYTES = BOXOBAN_PUZZLE_OBS_BYTES; +static char* BOXOBAN_MAP_PATH = NULL; +static const char* BOXOBAN_LEVEL_ROOT = "resources/boxoban/levels"; + +typedef struct { + char** items; + size_t count; + size_t cap; +} BoxobanPathList; + +static int boxoban_cmp_strings(const void* a, const void* b) { + const char* const* sa = (const char* const*)a; + const char* const* sb = (const char* const*)b; + return strcmp(*sa, *sb); +} + +static void boxoban_path_list_free(BoxobanPathList* list) { + for (size_t i = 0; i < list->count; i++) { + free(list->items[i]); + } + free(list->items); + list->items = NULL; + list->count = 0; + list->cap = 0; +} + +static int boxoban_path_list_append(BoxobanPathList* list, const char* path) { + if (list->count == list->cap) { + size_t next_cap = list->cap == 0 ? 64 : list->cap * 2; + char** next = (char**)realloc(list->items, next_cap * sizeof(char*)); + if (next == NULL) { + return -1; + } + list->items = next; + list->cap = next_cap; + } + char* copied = (char*)malloc(strlen(path) + 1); + if (copied == NULL) { + return -1; + } + strcpy(copied, path); + list->items[list->count++] = copied; + return 0; +} + +static int boxoban_has_txt_suffix(const char* name) { + size_t len = strlen(name); + return len >= 4 && strcmp(name + len - 4, ".txt") == 0; +} + +int boxoban_difficulty_id_from_name(const char* difficulty_name) { + if (difficulty_name == NULL) { + return -1; + } + + if (strcmp(difficulty_name, "basic") == 0) { + return 0; + } + if (strcmp(difficulty_name, "easy") == 0) { + return 1; + } + if (strcmp(difficulty_name, "medium") == 0) { + return 2; + } + if (strcmp(difficulty_name, "hard") == 0) { + return 3; + } + if (strcmp(difficulty_name, "unfiltered") == 0) { + return 4; + } + + return -1; +} + +const char* boxoban_difficulty_name_from_id(int difficulty_id) { + switch (difficulty_id) { + case 0: + return "basic"; + case 1: + return "easy"; + case 2: + return "medium"; + case 3: + return "hard"; + case 4: + return "unfiltered"; + default: + return NULL; + } +} + +static int boxoban_dir_has_txt(const char* dir_path) { + DIR* dir = opendir(dir_path); + if (dir == NULL) { + return 0; + } + struct dirent* ent; + while ((ent = readdir(dir)) != NULL) { + if (boxoban_has_txt_suffix(ent->d_name)) { + closedir(dir); + return 1; + } + } + closedir(dir); + return 0; +} + +static int boxoban_collect_sorted_txt_paths_in_dir(const char* dir_path, BoxobanPathList* out_paths) { + DIR* dir = opendir(dir_path); + if (dir == NULL) { + fprintf(stderr, "Missing level directory %s\n", dir_path); + return -1; + } + + BoxobanPathList names = {0}; + struct dirent* ent; + while ((ent = readdir(dir)) != NULL) { + if (!boxoban_has_txt_suffix(ent->d_name)) { + continue; + } + if (boxoban_path_list_append(&names, ent->d_name) != 0) { + boxoban_path_list_free(&names); + closedir(dir); + return -1; + } + } + closedir(dir); + + qsort(names.items, names.count, sizeof(char*), boxoban_cmp_strings); + for (size_t i = 0; i < names.count; i++) { + char full_path[1400]; + snprintf(full_path, sizeof(full_path), "%s/%s", dir_path, names.items[i]); + if (boxoban_path_list_append(out_paths, full_path) != 0) { + boxoban_path_list_free(&names); + return -1; + } + } + boxoban_path_list_free(&names); + return 0; +} + +static int boxoban_collect_maps_from_dir(const char* rel_path, BoxobanPathList* out_paths) { + char level_dir[1400]; + struct stat st; + + snprintf(level_dir, sizeof(level_dir), "%s/%s", BOXOBAN_LEVEL_ROOT, rel_path); + if (stat(level_dir, &st) != 0 || !S_ISDIR(st.st_mode)) { + fprintf(stderr, "Missing level directory %s\n", level_dir); + return -1; + } + + return boxoban_collect_sorted_txt_paths_in_dir(level_dir, out_paths); +} + +static int boxoban_collect_maps(const char* difficulty, BoxobanPathList* out_paths) { + if (strcmp(difficulty, "basic") == 0) { + return boxoban_collect_maps_from_dir("basic/train", out_paths); + } + if (strcmp(difficulty, "easy") == 0) { + return boxoban_collect_maps_from_dir("easy/train", out_paths); + } + if (strcmp(difficulty, "medium") == 0) { + return boxoban_collect_maps_from_dir("medium/train", out_paths); + } + if (strcmp(difficulty, "hard") == 0) { + return boxoban_collect_maps_from_dir("hard", out_paths); + } + if (strcmp(difficulty, "unfiltered") == 0) { + return boxoban_collect_maps_from_dir("unfiltered/train", out_paths); + } + + fprintf(stderr, "Invalid difficulty '%s'\n", difficulty); + return -1; +} + +static int boxoban_download_text_maps(const char* difficulty) { + char zip_url[512]; + snprintf(zip_url, sizeof(zip_url), + "https://raw.githubusercontent.com/TBBristol/pufferlib_boxoban_levels/main/%s.zip", + difficulty); + fprintf(stdout, "[Boxoban] Downloading %s maps from %s\n", difficulty, zip_url); + + char tmp_template[] = "/tmp/boxoban_maps_XXXXXX"; + char* tmp_dir = mkdtemp(tmp_template); + if (tmp_dir == NULL) { + return -1; + } + + char zip_path[1400]; + snprintf(zip_path, sizeof(zip_path), "%s/%s.zip", tmp_dir, difficulty); + + char cmd[4096]; + snprintf(cmd, sizeof(cmd), "curl -L --fail -o '%s' '%s' > /dev/null 2>&1", zip_path, zip_url); + if (system(cmd) != 0) { + fprintf(stderr, "Failed to download Boxoban maps with curl\n"); + return -1; + } + + snprintf(cmd, sizeof(cmd), "unzip -q '%s' -d '%s'", zip_path, tmp_dir); + if (system(cmd) != 0) { + fprintf(stderr, "Failed to unzip Boxoban maps archive\n"); + return -1; + } + + char extracted_root[1400] = {0}; + char find_cmd[4096]; + snprintf(find_cmd, sizeof(find_cmd), "find '%s' -type d -name '%s' | head -n 1", tmp_dir, difficulty); + FILE* find_pipe = popen(find_cmd, "r"); + if (find_pipe == NULL) { + return -1; + } + if (fgets(extracted_root, sizeof(extracted_root), find_pipe) == NULL) { + pclose(find_pipe); + fprintf(stderr, "Downloaded zip missing '%s' directory\n", difficulty); + return -1; + } + pclose(find_pipe); + extracted_root[strcspn(extracted_root, "\r\n")] = '\0'; + + char dest_root[1400]; + snprintf(dest_root, sizeof(dest_root), "%s/%s", BOXOBAN_LEVEL_ROOT, difficulty); + if (boxoban_mkdir_p(dest_root) != 0) { + return -1; + } + + snprintf(cmd, sizeof(cmd), "cp -R '%s/.' '%s/'", extracted_root, dest_root); + if (system(cmd) != 0) { + fprintf(stderr, "Failed to copy downloaded maps into %s\n", dest_root); + return -1; + } + return 0; +} + +static int boxoban_ensure_text_maps(const char* difficulty) { + if (strcmp(difficulty, "basic") == 0) { + char output_dir[1400]; + snprintf(output_dir, sizeof(output_dir), "%s/basic/train", BOXOBAN_LEVEL_ROOT); + if (boxoban_dir_has_txt(output_dir)) { + return 0; + } + fprintf(stdout, "[Boxoban] Generating basic maps at %s\n", output_dir); + return boxoban_generate_basic_maps(output_dir, 0); + } + if (strcmp(difficulty, "easy") == 0) { + char output_dir[1400]; + snprintf(output_dir, sizeof(output_dir), "%s/easy/train", BOXOBAN_LEVEL_ROOT); + if (boxoban_dir_has_txt(output_dir)) { + return 0; + } + fprintf(stdout, "[Boxoban] Generating easy maps at %s\n", output_dir); + return boxoban_generate_easy_maps(output_dir, 0); + } + if (strcmp(difficulty, "medium") == 0) { + char level_dir[1400]; + snprintf(level_dir, sizeof(level_dir), "%s/medium/train", BOXOBAN_LEVEL_ROOT); + if (boxoban_dir_has_txt(level_dir)) { + return 0; + } + return boxoban_download_text_maps(difficulty); + } + if (strcmp(difficulty, "hard") == 0) { + char level_dir[1400]; + snprintf(level_dir, sizeof(level_dir), "%s/hard", BOXOBAN_LEVEL_ROOT); + if (boxoban_dir_has_txt(level_dir)) { + return 0; + } + return boxoban_download_text_maps(difficulty); + } + if (strcmp(difficulty, "unfiltered") == 0) { + char level_dir[1400]; + snprintf(level_dir, sizeof(level_dir), "%s/unfiltered/train", BOXOBAN_LEVEL_ROOT); + if (boxoban_dir_has_txt(level_dir)) { + return 0; + } + return boxoban_download_text_maps(difficulty); + } + + return boxoban_download_text_maps(difficulty); +} + +static int boxoban_bin_path(const char* difficulty, char* out_path, size_t out_cap) { + int written = snprintf(out_path, out_cap, "resources/boxoban/boxoban_maps_%s.bin", difficulty); + if (written <= 0 || (size_t)written >= out_cap) { + return -1; + } + return 0; +} + +int boxoban_prepare_maps_for_difficulty(const char* difficulty, char* out_path, size_t out_cap) { + if (difficulty == NULL || out_path == NULL) { + return -1; + } + if (boxoban_difficulty_id_from_name(difficulty) < 0) { + return -1; + } + if (boxoban_bin_path(difficulty, out_path, out_cap) != 0) { + return -1; + } + + if (access(out_path, F_OK) != 0) { + if (boxoban_ensure_text_maps(difficulty) != 0) { + return -1; + } + + BoxobanPathList maps = {0}; + size_t puzzle_count = 0; + if (boxoban_collect_maps(difficulty, &maps) != 0) { + boxoban_path_list_free(&maps); + return -1; + } + + if (boxoban_write_bin_from_files((const char* const*)maps.items, maps.count, out_path, 0, &puzzle_count) != 0) { + boxoban_path_list_free(&maps); + return -1; + } + boxoban_path_list_free(&maps); + fprintf(stdout, "[Boxoban] Generated %zu puzzles for '%s' at %s\n", puzzle_count, difficulty, out_path); + } + + if (boxoban_set_map_path(out_path) != 0) { + return -1; + } + return 0; +} + +static void reset_map_cache(void) { + if (MAP_BASE != NULL && MAP_BASE != MAP_FAILED && MAP_FILESIZE > 0) { + munmap(MAP_BASE, MAP_FILESIZE); + } + MAP_BASE = NULL; + MAP_FILESIZE = 0; + PUZZLE_COUNT = 0; +} + +int boxoban_set_map_path(const char *path) { + if (path == NULL) { + return -1; + } + if (BOXOBAN_MAP_PATH != NULL && strcmp(BOXOBAN_MAP_PATH, path) == 0) { + return 0; + } + + char* copied = malloc(strlen(path) + 1); + if (copied == NULL) { + return -1; + } + strcpy(copied, path); + + reset_map_cache(); + free(BOXOBAN_MAP_PATH); + BOXOBAN_MAP_PATH = copied; + return 0; +} + +static const char* get_default_map_path(void) { + const char* env_path = getenv("BOXOBAN_MAP_BIN"); + if (env_path != NULL) { + return env_path; + } + return NULL; +} + +void ensure_map_loaded(void) { + if (MAP_BASE != NULL) { + return; + } + + if (BOXOBAN_MAP_PATH == NULL) { + const char* default_path = get_default_map_path(); + if (default_path != NULL) { + if (boxoban_set_map_path(default_path) != 0) { + fprintf(stderr, "Failed to set default Boxoban map path\n"); + abort(); + } + } else { + char prepared_path[512]; + if (boxoban_prepare_maps_for_difficulty("basic", prepared_path, sizeof(prepared_path)) != 0) { + fprintf(stderr, "Failed to prepare default Boxoban maps\n"); + abort(); + } + } + } + + int fd = open(BOXOBAN_MAP_PATH, O_RDONLY); + if (fd < 0) { + perror("open"); + abort(); + } + struct stat st; + if (fstat(fd, &st) != 0) { + perror("fstat"); + abort(); + } + + MAP_FILESIZE = st.st_size; + if (MAP_FILESIZE % PUZZLE_SIZE != 0) { + fprintf(stderr, "Invalid Boxoban map file size %zu (expected multiple of %zu)\n", + MAP_FILESIZE, PUZZLE_SIZE); + abort(); + } + PUZZLE_COUNT = MAP_FILESIZE / PUZZLE_SIZE; + + MAP_BASE = mmap(NULL, MAP_FILESIZE, PROT_READ, MAP_PRIVATE, fd, 0); + close(fd); + + if (MAP_BASE == MAP_FAILED) { + perror("mmap"); + abort(); + } +} + +#endif + +#endif diff --git a/ocean/boxoban/generate_maps.h b/ocean/boxoban/generate_maps.h new file mode 100644 index 0000000000..cdd39a10b7 --- /dev/null +++ b/ocean/boxoban/generate_maps.h @@ -0,0 +1,368 @@ +#ifndef PUFFERLIB_OCEAN_BOXOBAN_GENERATE_MAPS_H +#define PUFFERLIB_OCEAN_BOXOBAN_GENERATE_MAPS_H + +#include +#include +#include +#include +#include +#include +#include + +#define BOXOBAN_GEN_AGENT '@' +#define BOXOBAN_GEN_WALL '#' +#define BOXOBAN_GEN_BOX '$' +#define BOXOBAN_GEN_TARGET '.' +#define BOXOBAN_GEN_FLOOR ' ' + +typedef struct { + int r; + int c; +} BoxobanCell; + +typedef struct { + uint64_t state; +} BoxobanRandom; + +static int boxoban_mkdir_p(const char* dir_path) { + char tmp[1024]; + size_t len = strlen(dir_path); + if (len >= sizeof(tmp)) { + return -1; + } + + memcpy(tmp, dir_path, len + 1); + for (size_t i = 1; i < len; i++) { + if (tmp[i] == '/') { + tmp[i] = '\0'; + if (mkdir(tmp, 0777) != 0 && errno != EEXIST) { + return -1; + } + tmp[i] = '/'; + } + } + if (mkdir(tmp, 0777) != 0 && errno != EEXIST) { + return -1; + } + return 0; +} + +static void boxoban_seed(BoxobanRandom* rng, uint64_t seed) { + rng->state = seed ? seed : 0x9e3779b97f4a7c15ULL; +} + +static uint64_t boxoban_next_u64(BoxobanRandom* rng) { + uint64_t x = rng->state; + x ^= x >> 12; + x ^= x << 25; + x ^= x >> 27; + rng->state = x; + return x * 2685821657736338717ULL; +} + +static uint32_t boxoban_randbelow(BoxobanRandom* rng, uint32_t n) { + if (n == 0) { + return 0; + } + + uint64_t threshold = (uint64_t)(-(int64_t)n) % (uint64_t)n; + for (;;) { + uint64_t r = boxoban_next_u64(rng); + if (r >= threshold) { + return (uint32_t)(r % n); + } + } +} + +static int boxoban_randint(BoxobanRandom* rng, int a, int b) { + return a + (int)boxoban_randbelow(rng, (uint32_t)(b - a + 1)); +} + +static int boxoban_choice_index(BoxobanRandom* rng, int n) { + return (int)boxoban_randbelow(rng, (uint32_t)n); +} + +static int boxoban_sample_indices(BoxobanRandom* rng, int n, int k, int* out_indices) { + int* pool = (int*)malloc((size_t)n * sizeof(int)); + if (pool == NULL) { + return -1; + } + + for (int i = 0; i < n; i++) { + pool[i] = i; + } + + for (int i = 0; i < k; i++) { + int j = i + (int)boxoban_randbelow(rng, (uint32_t)(n - i)); + int tmp = pool[i]; + pool[i] = pool[j]; + pool[j] = tmp; + out_indices[i] = pool[i]; + } + + free(pool); + return 0; +} + +static inline int boxoban_grid_idx(int size, int r, int c) { + return r * size + c; +} + +static int boxoban_is_inside(int size, int x, int y) { + return x >= 0 && x < size && y >= 0 && y < size; +} + +static int boxoban_is_pushable(const char* grid, int size, int x, int y) { + static const int dirs[4][2] = {{1,0}, {-1,0}, {0,1}, {0,-1}}; + for (int d = 0; d < 4; d++) { + int dx = dirs[d][0]; + int dy = dirs[d][1]; + int px = x - dx; + int py = y - dy; + int tx = x + dx; + int ty = y + dy; + if (!boxoban_is_inside(size, px, py) || !boxoban_is_inside(size, tx, ty)) { + continue; + } + char pre = grid[boxoban_grid_idx(size, py, px)]; + char post = grid[boxoban_grid_idx(size, ty, tx)]; + if ((pre == BOXOBAN_GEN_FLOOR || pre == BOXOBAN_GEN_TARGET) && + (post == BOXOBAN_GEN_FLOOR || post == BOXOBAN_GEN_TARGET)) { + return 1; + } + } + return 0; +} + +static void boxoban_build_border_grid(char* grid, int size) { + for (int r = 0; r < size; r++) { + for (int c = 0; c < size; c++) { + grid[boxoban_grid_idx(size, r, c)] = BOXOBAN_GEN_FLOOR; + } + } + for (int i = 0; i < size; i++) { + grid[boxoban_grid_idx(size, 0, i)] = BOXOBAN_GEN_WALL; + grid[boxoban_grid_idx(size, size - 1, i)] = BOXOBAN_GEN_WALL; + grid[boxoban_grid_idx(size, i, 0)] = BOXOBAN_GEN_WALL; + grid[boxoban_grid_idx(size, i, size - 1)] = BOXOBAN_GEN_WALL; + } +} + +static int boxoban_build_cells(int size, int margin, BoxobanCell* out_cells) { + int count = 0; + int start = 1 + margin; + int end = size - 1 - margin; + for (int r = start; r < end; r++) { + for (int c = start; c < end; c++) { + out_cells[count].r = r; + out_cells[count].c = c; + count++; + } + } + return count; +} + +static int boxoban_make_puzzle( + int size, + BoxobanRandom* rng, + int num_boxes, + int max_attempts, + const BoxobanCell* agent_choices, + int agent_count, + const BoxobanCell* confined, + int confined_count, + int interior_count, + char* grid +) { + if (num_boxes < 1) { + fprintf(stderr, "num_boxes must be at least 1\n"); + return -1; + } + + int needed = num_boxes * 2 + 1; + if (needed > interior_count) { + fprintf(stderr, "Grid interior only has %d cells, cannot place %d objects\n", interior_count, needed); + return -1; + } + + BoxobanCell* box_candidates = (BoxobanCell*)malloc((size_t)confined_count * sizeof(BoxobanCell)); + BoxobanCell* box_positions = (BoxobanCell*)malloc((size_t)num_boxes * sizeof(BoxobanCell)); + BoxobanCell* agent_candidates = (BoxobanCell*)malloc((size_t)agent_count * sizeof(BoxobanCell)); + int* sampled_idx = (int*)malloc((size_t)num_boxes * sizeof(int)); + uint8_t* occupied = (uint8_t*)calloc((size_t)size * (size_t)size, sizeof(uint8_t)); + if (box_candidates == NULL || box_positions == NULL || agent_candidates == NULL || sampled_idx == NULL || occupied == NULL) { + free(box_candidates); + free(box_positions); + free(agent_candidates); + free(sampled_idx); + free(occupied); + return -1; + } + + for (int attempt = 0; attempt < max_attempts; attempt++) { + boxoban_build_border_grid(grid, size); + memset(occupied, 0, (size_t)size * (size_t)size); + + if (boxoban_sample_indices(rng, confined_count, num_boxes, sampled_idx) != 0) { + free(box_candidates); + free(box_positions); + free(agent_candidates); + free(sampled_idx); + free(occupied); + return -1; + } + + for (int i = 0; i < num_boxes; i++) { + BoxobanCell cell = confined[sampled_idx[i]]; + grid[boxoban_grid_idx(size, cell.r, cell.c)] = BOXOBAN_GEN_TARGET; + occupied[boxoban_grid_idx(size, cell.r, cell.c)] = 1; + } + + int box_candidate_count = 0; + for (int i = 0; i < confined_count; i++) { + BoxobanCell cell = confined[i]; + if (!occupied[boxoban_grid_idx(size, cell.r, cell.c)]) { + box_candidates[box_candidate_count++] = cell; + } + } + if (box_candidate_count < num_boxes) { + continue; + } + + if (boxoban_sample_indices(rng, box_candidate_count, num_boxes, sampled_idx) != 0) { + free(box_candidates); + free(box_positions); + free(agent_candidates); + free(sampled_idx); + free(occupied); + return -1; + } + for (int i = 0; i < num_boxes; i++) { + BoxobanCell cell = box_candidates[sampled_idx[i]]; + box_positions[i] = cell; + grid[boxoban_grid_idx(size, cell.r, cell.c)] = BOXOBAN_GEN_BOX; + occupied[boxoban_grid_idx(size, cell.r, cell.c)] = 1; + } + + int agent_candidate_count = 0; + for (int i = 0; i < agent_count; i++) { + BoxobanCell cell = agent_choices[i]; + if (!occupied[boxoban_grid_idx(size, cell.r, cell.c)]) { + agent_candidates[agent_candidate_count++] = cell; + } + } + if (agent_candidate_count == 0) { + continue; + } + + BoxobanCell agent_cell = agent_candidates[boxoban_choice_index(rng, agent_candidate_count)]; + grid[boxoban_grid_idx(size, agent_cell.r, agent_cell.c)] = BOXOBAN_GEN_AGENT; + + int all_pushable = 1; + for (int i = 0; i < num_boxes; i++) { + BoxobanCell cell = box_positions[i]; + if (!boxoban_is_pushable(grid, size, cell.c, cell.r)) { + all_pushable = 0; + break; + } + } + + if (all_pushable) { + free(box_candidates); + free(box_positions); + free(agent_candidates); + free(sampled_idx); + free(occupied); + return 0; + } + } + + free(box_candidates); + free(box_positions); + free(agent_candidates); + free(sampled_idx); + free(occupied); + fprintf(stderr, "Failed to sample a solvable puzzle after many attempts\n"); + return -1; +} + +static int boxoban_generate_maps( + const char* output_dir, + int num_files, + int puzzles_per_file, + int size, + int num_boxes, + int min_boxes, + int max_boxes, + uint64_t seed +) { + if (boxoban_mkdir_p(output_dir) != 0) { + return -1; + } + + BoxobanRandom rng; + boxoban_seed(&rng, seed); + + int max_cells = (size - 2) * (size - 2); + BoxobanCell* agent_choices = (BoxobanCell*)malloc((size_t)max_cells * sizeof(BoxobanCell)); + BoxobanCell* confined = (BoxobanCell*)malloc((size_t)max_cells * sizeof(BoxobanCell)); + char* grid = (char*)malloc((size_t)size * (size_t)size); + if (agent_choices == NULL || confined == NULL || grid == NULL) { + free(agent_choices); + free(confined); + free(grid); + return -1; + } + + int interior_count = (size - 2) * (size - 2); + int agent_count = boxoban_build_cells(size, 0, agent_choices); + int confined_count = boxoban_build_cells(size, 1, confined); + + for (int file_idx = 0; file_idx < num_files; file_idx++) { + char out_path[1200]; + snprintf(out_path, sizeof(out_path), "%s/%03d.txt", output_dir, file_idx); + FILE* out = fopen(out_path, "w"); + if (out == NULL) { + free(agent_choices); + free(confined); + free(grid); + return -1; + } + + for (int puzzle_idx = 0; puzzle_idx < puzzles_per_file; puzzle_idx++) { + int box_count = num_boxes >= 1 ? num_boxes : boxoban_randint(&rng, min_boxes, max_boxes); + if (boxoban_make_puzzle( + size, &rng, box_count, 200, agent_choices, agent_count, confined, confined_count, interior_count, grid) != 0) { + fclose(out); + free(agent_choices); + free(confined); + free(grid); + return -1; + } + + fprintf(out, "; %d\n", puzzle_idx); + for (int r = 0; r < size; r++) { + fwrite(&grid[boxoban_grid_idx(size, r, 0)], 1, (size_t)size, out); + fputc('\n', out); + } + fputc('\n', out); + } + + fclose(out); + } + + free(agent_choices); + free(confined); + free(grid); + return 0; +} + +static int boxoban_generate_easy_maps(const char* output_dir, uint64_t seed) { + return boxoban_generate_maps(output_dir, 300, 1000, 10, -1, 1, 4, seed); +} + +static int boxoban_generate_basic_maps(const char* output_dir, uint64_t seed) { + return boxoban_generate_maps(output_dir, 300, 1000, 10, 1, 1, 4, seed); +} + +#endif diff --git a/ocean/boxoban/parse_maps.h b/ocean/boxoban/parse_maps.h new file mode 100644 index 0000000000..79e79ed8e1 --- /dev/null +++ b/ocean/boxoban/parse_maps.h @@ -0,0 +1,252 @@ +#ifndef PUFFERLIB_OCEAN_BOXOBAN_PARSE_MAPS_H +#define PUFFERLIB_OCEAN_BOXOBAN_PARSE_MAPS_H + +#include +#include +#include +#include +#include +#include + +#define BOXOBAN_AGENT_CHAR '@' +#define BOXOBAN_WALL_CHAR '#' +#define BOXOBAN_BOX_CHAR '$' +#define BOXOBAN_TARGET_CHAR '.' +#define BOXOBAN_BOX_ON_TARGET_CHAR '*' +#define BOXOBAN_AGENT_ON_TARGET_CHAR '+' + +#define BOXOBAN_EXPECTED_ROWS 10 +#define BOXOBAN_EXPECTED_COLS 10 +#define BOXOBAN_PUZZLE_OBS_BYTES (4 * BOXOBAN_EXPECTED_ROWS * BOXOBAN_EXPECTED_COLS) +#define BOXOBAN_PUZZLE_META_BYTES 5 +#define BOXOBAN_PUZZLE_BYTES (BOXOBAN_PUZZLE_OBS_BYTES + BOXOBAN_PUZZLE_META_BYTES) + +typedef struct { + char rows[BOXOBAN_EXPECTED_ROWS][BOXOBAN_EXPECTED_COLS]; + int row_lengths[BOXOBAN_EXPECTED_ROWS]; + int row_count; +} BoxobanPuzzleDraft; + +static int boxoban_is_blank_line(const char* line) { + const unsigned char* p = (const unsigned char*)line; + while (*p != '\0') { + if (!isspace(*p)) { + return 0; + } + p++; + } + return 1; +} + +static int boxoban_validate_shape(const BoxobanPuzzleDraft* draft, char* reason, size_t reason_cap) { + if (draft->row_count != BOXOBAN_EXPECTED_ROWS) { + snprintf(reason, reason_cap, "expected %d rows, got %d", BOXOBAN_EXPECTED_ROWS, draft->row_count); + return -1; + } + + for (int r = 0; r < BOXOBAN_EXPECTED_ROWS; r++) { + if (draft->row_lengths[r] != BOXOBAN_EXPECTED_COLS) { + snprintf(reason, reason_cap, "row %d expected %d cols, got %d", + r, BOXOBAN_EXPECTED_COLS, draft->row_lengths[r]); + return -1; + } + } + + reason[0] = '\0'; + return 0; +} + +static int boxoban_encode_and_write_puzzle(const BoxobanPuzzleDraft* draft, FILE* out, char* reason, size_t reason_cap) { + uint8_t agent[BOXOBAN_EXPECTED_ROWS * BOXOBAN_EXPECTED_COLS] = {0}; + uint8_t walls[BOXOBAN_EXPECTED_ROWS * BOXOBAN_EXPECTED_COLS] = {0}; + uint8_t boxes[BOXOBAN_EXPECTED_ROWS * BOXOBAN_EXPECTED_COLS] = {0}; + uint8_t targets[BOXOBAN_EXPECTED_ROWS * BOXOBAN_EXPECTED_COLS] = {0}; + uint8_t meta[BOXOBAN_PUZZLE_META_BYTES] = {0}; + + int agent_x = -1; + int agent_y = -1; + int n_boxes = 0; + int n_targets = 0; + int on_target = 0; + + int idx = 0; + for (int r = 0; r < BOXOBAN_EXPECTED_ROWS; r++) { + for (int c = 0; c < BOXOBAN_EXPECTED_COLS; c++, idx++) { + char ch = draft->rows[r][c]; + + int is_agent = (ch == BOXOBAN_AGENT_CHAR || ch == BOXOBAN_AGENT_ON_TARGET_CHAR); + int is_wall = (ch == BOXOBAN_WALL_CHAR); + int is_box = (ch == BOXOBAN_BOX_CHAR || ch == BOXOBAN_BOX_ON_TARGET_CHAR); + int is_target = (ch == BOXOBAN_TARGET_CHAR || ch == BOXOBAN_BOX_ON_TARGET_CHAR || ch == BOXOBAN_AGENT_ON_TARGET_CHAR); + + if (is_agent) { + if (agent_x != -1) { + snprintf(reason, reason_cap, "Puzzle has multiple agents"); + return -1; + } + agent_x = c; + agent_y = r; + } + + n_boxes += is_box; + n_targets += is_target; + on_target += (is_box && is_target); + + agent[idx] = (uint8_t)is_agent; + walls[idx] = (uint8_t)is_wall; + boxes[idx] = (uint8_t)is_box; + targets[idx] = (uint8_t)is_target; + } + } + + if (agent_x == -1) { + snprintf(reason, reason_cap, "Puzzle has no agent"); + return -1; + } + + meta[0] = (uint8_t)agent_x; + meta[1] = (uint8_t)agent_y; + meta[2] = (uint8_t)n_boxes; + meta[3] = (uint8_t)n_targets; + meta[4] = (uint8_t)on_target; + + if (fwrite(agent, 1, sizeof(agent), out) != sizeof(agent)) return -1; + if (fwrite(walls, 1, sizeof(walls), out) != sizeof(walls)) return -1; + if (fwrite(boxes, 1, sizeof(boxes), out) != sizeof(boxes)) return -1; + if (fwrite(targets, 1, sizeof(targets), out) != sizeof(targets)) return -1; + if (fwrite(meta, 1, sizeof(meta), out) != sizeof(meta)) return -1; + + reason[0] = '\0'; + return 0; +} + +static int boxoban_finalize_puzzle( + BoxobanPuzzleDraft* draft, + FILE* out, + const char* src_path, + size_t* puzzle_idx, + size_t* written_count +) { + char reason[128]; + size_t idx = *puzzle_idx; + (*puzzle_idx)++; + + if (boxoban_validate_shape(draft, reason, sizeof(reason)) != 0) { + fprintf(stdout, "[Boxoban] Skipping malformed puzzle in %s puzzle#%zu: %s\n", src_path, idx, reason); + draft->row_count = 0; + return 0; + } + + if (boxoban_encode_and_write_puzzle(draft, out, reason, sizeof(reason)) != 0) { + if (reason[0] == '\0') { + return -1; + } + fprintf(stdout, "[Boxoban] Skipping malformed puzzle in %s puzzle#%zu: %s\n", src_path, idx, reason); + draft->row_count = 0; + return 0; + } + + (*written_count)++; + draft->row_count = 0; + return 0; +} + +static int boxoban_write_bin_from_files( + const char* const* files, + size_t file_count, + const char* out_path, + int verbose, + size_t* out_puzzle_count +) { + FILE* out = fopen(out_path, "wb"); + if (out == NULL) { + return -1; + } + + size_t puzzle_count = 0; + + for (size_t file_idx = 0; file_idx < file_count; file_idx++) { + const char* src_path = files[file_idx]; + FILE* in = fopen(src_path, "r"); + if (in == NULL) { + fclose(out); + return -1; + } + + char* line = NULL; + size_t line_cap = 0; + ssize_t line_len; + BoxobanPuzzleDraft draft; + memset(&draft, 0, sizeof(draft)); + size_t puzzle_idx = 0; + + while ((line_len = getline(&line, &line_cap, in)) != -1) { + if (line_len > 0 && line[line_len - 1] == '\n') { + line[--line_len] = '\0'; + } + + if (line[0] == ';') { + if (draft.row_count > 0) { + if (boxoban_finalize_puzzle(&draft, out, src_path, &puzzle_idx, &puzzle_count) != 0) { + free(line); + fclose(in); + fclose(out); + return -1; + } + } + continue; + } + + if (boxoban_is_blank_line(line)) { + continue; + } + + if (draft.row_count < BOXOBAN_EXPECTED_ROWS) { + int dst_row = draft.row_count; + int copy_len = line_len < BOXOBAN_EXPECTED_COLS ? (int)line_len : BOXOBAN_EXPECTED_COLS; + memcpy(draft.rows[dst_row], line, (size_t)copy_len); + draft.row_lengths[dst_row] = (int)line_len; + draft.row_count++; + } + + if (draft.row_count == BOXOBAN_EXPECTED_ROWS) { + if (boxoban_finalize_puzzle(&draft, out, src_path, &puzzle_idx, &puzzle_count) != 0) { + free(line); + fclose(in); + fclose(out); + return -1; + } + } + } + + free(line); + fclose(in); + } + + if (fflush(out) != 0) { + fclose(out); + return -1; + } + + long bytes_written = ftell(out); + fclose(out); + if (bytes_written < 0) { + return -1; + } + + size_t expected = puzzle_count * BOXOBAN_PUZZLE_BYTES; + if ((size_t)bytes_written != expected) { + fprintf(stderr, "Wrong output size: got %ld expected %zu\n", bytes_written, expected); + return -1; + } + + if (verbose) { + fprintf(stdout, "Wrote %zu puzzles to %s\n", puzzle_count, out_path); + } + if (out_puzzle_count != NULL) { + *out_puzzle_count = puzzle_count; + } + return 0; +} + +#endif diff --git a/ocean/breakout/binding.c b/ocean/breakout/binding.c new file mode 100644 index 0000000000..471e78b9c9 --- /dev/null +++ b/ocean/breakout/binding.c @@ -0,0 +1,35 @@ +#include "breakout.h" +#define OBS_SIZE 118 +#define NUM_ATNS 1 +#define ACT_SIZES {3} +#define OBS_TENSOR_T FloatTensor + +#define Env Breakout +#include "vecenv.h" + +void my_init(Env* env, Dict* kwargs) { + env->num_agents = 1; + env->frameskip = dict_get(kwargs, "frameskip")->value; + env->width = dict_get(kwargs, "width")->value; + env->height = dict_get(kwargs, "height")->value; + env->initial_paddle_width = dict_get(kwargs, "paddle_width")->value; + env->paddle_height = dict_get(kwargs, "paddle_height")->value; + env->ball_width = dict_get(kwargs, "ball_width")->value; + env->ball_height = dict_get(kwargs, "ball_height")->value; + env->brick_width = dict_get(kwargs, "brick_width")->value; + env->brick_height = dict_get(kwargs, "brick_height")->value; + env->brick_rows = dict_get(kwargs, "brick_rows")->value; + env->brick_cols = dict_get(kwargs, "brick_cols")->value; + env->initial_ball_speed = dict_get(kwargs, "initial_ball_speed")->value; + env->max_ball_speed = dict_get(kwargs, "max_ball_speed")->value; + env->paddle_speed = dict_get(kwargs, "paddle_speed")->value; + env->continuous = dict_get(kwargs, "continuous")->value; + init(env); +} + +void my_log(Log* log, Dict* out) { + dict_set(out, "perf", log->perf); + dict_set(out, "score", log->score); + dict_set(out, "episode_return", log->episode_return); + dict_set(out, "episode_length", log->episode_length); +} diff --git a/pufferlib/ocean/breakout/breakout.c b/ocean/breakout/breakout.c similarity index 61% rename from pufferlib/ocean/breakout/breakout.c rename to ocean/breakout/breakout.c index da51a09ff7..840297402e 100644 --- a/pufferlib/ocean/breakout/breakout.c +++ b/ocean/breakout/breakout.c @@ -3,14 +3,15 @@ #include "puffernet.h" void demo() { - Weights* weights = load_weights("resources/breakout/breakout_weights.bin", 147844); + Weights* weights = load_weights("resources/breakout/breakout_weights.bin"); int logit_sizes[1] = {3}; - LinearLSTM* net = make_linearlstm(weights, 1, 118, logit_sizes, 1); + PufferNet* net = make_puffernet(weights, 1, 118, 64, 2, logit_sizes, 1); Breakout env = { .frameskip = 1, .width = 576, .height = 330, + .initial_paddle_width = 62, .paddle_width = 62, .paddle_height = 8, .ball_width = 32, @@ -45,53 +46,19 @@ void demo() { } } else if (frame % 4 == 0) { // Apply frameskip outside the env for smoother rendering - int* actions = (int*)env.actions; - forward_linearlstm(net, env.observations, actions); - env.actions[0] = actions[0]; + forward_puffernet(net, env.observations, env.actions); } frame = (frame + 1) % 4; c_step(&env); c_render(&env); } - free_linearlstm(net); + free_puffernet(net); free(weights); free_allocated(&env); close_client(env.client); } -void test_performance(int timeout) { - Breakout env = { - .width = 512, - .height = 512, - .paddle_width = 20, - .paddle_height = 70, - .ball_width = 10, - .ball_height = 15, - .brick_width = 10, - .brick_height = 10, - .brick_rows = 5, - .brick_cols = 10, - .continuous = 0, - }; - allocate(&env); - c_reset(&env); - - int start = time(NULL); - int num_steps = 0; - while (time(NULL) - start < timeout) { - env.actions[0] = rand() % 3; - c_step(&env); - num_steps++; - } - - int end = time(NULL); - float sps = num_steps / (end - start); - printf("Test Environment SPS: %f\n", sps); - free_allocated(&env); -} - int main() { demo(); - //test_performance(10); } diff --git a/pufferlib/ocean/breakout/breakout.h b/ocean/breakout/breakout.h similarity index 89% rename from pufferlib/ocean/breakout/breakout.h rename to ocean/breakout/breakout.h index 8366b50658..a4a1dad425 100644 --- a/pufferlib/ocean/breakout/breakout.h +++ b/ocean/breakout/breakout.h @@ -42,7 +42,8 @@ typedef struct Breakout { float* observations; float* actions; float* rewards; - unsigned char* terminals; + float* terminals; + int num_agents; int score; float paddle_x; float paddle_y; @@ -78,6 +79,7 @@ typedef struct Breakout { int frameskip; unsigned char hit_brick; int continuous; + unsigned int rng; } Breakout; typedef struct CollisionInfo CollisionInfo; @@ -121,7 +123,7 @@ void allocate(Breakout* env) { env->observations = (float*)calloc(11 + env->num_bricks, sizeof(float)); env->actions = (float*)calloc(1, sizeof(float)); env->rewards = (float*)calloc(1, sizeof(float)); - env->terminals = (unsigned char*)calloc(1, sizeof(unsigned char)); + env->terminals = (float*)calloc(1, sizeof(float)); } void c_close(Breakout* env) { @@ -157,9 +159,7 @@ void compute_observations(Breakout* env) { env->observations[7] = env->score / 864.0f; env->observations[8] = env->num_balls / 5.0f; env->observations[9] = env->paddle_width / (2.0f * HALF_PADDLE_WIDTH); - for (int i = 0; i < env->num_bricks; i++) { - env->observations[10 + i] = env->brick_states[i]; - } + memcpy(env->observations + 10, env->brick_states, sizeof(float) * env->num_bricks); } // Collision of a stationary vertical line segment (xw,yw) to (xw,yw+hw) @@ -167,8 +167,8 @@ void compute_observations(Breakout* env) { static inline bool calc_vline_collision(float xw, float yw, float hw, float x, float y, float vx, float vy, float h, CollisionInfo* col) { float t_new = (xw - x) / vx; - float topmost = fmin(yw + hw, y + h + vy * t_new); - float botmost = fmax(yw, y + vy * t_new); + float topmost = fminf(yw + hw, y + h + vy * t_new); + float botmost = fmaxf(yw, y + vy * t_new); float overlap_new = topmost - botmost; // Collision finds the smallest time of collision with the greatest overlap @@ -246,26 +246,52 @@ static inline void calc_brick_collision(Breakout* env, int idx, } } static inline int column_index(Breakout* env, float x) { - return (int)(floorf(x / env->brick_width)); + return (int)(x / env->brick_width); } static inline int row_index(Breakout* env, float y) { - return (int)(floorf((y - Y_OFFSET) / env->brick_height)); + return (int)((y - Y_OFFSET) / env->brick_height); } void calc_all_brick_collisions(Breakout* env, CollisionInfo* collision_info) { - int column_from = column_index(env, fminf(env->ball_x + env->ball_vx, env->ball_x)); - column_from = fmaxf(column_from, 0); - int column_to = column_index(env, fmaxf(env->ball_x + env->ball_width + env->ball_vx, env->ball_x + env->ball_width)); - column_to = fminf(column_to, env->brick_cols - 1); - int row_from = row_index(env, fminf(env->ball_y + env->ball_vy, env->ball_y)); - row_from = fmaxf(row_from, 0); - int row_to = row_index(env, fmaxf(env->ball_y + env->ball_height + env->ball_vy, env->ball_y + env->ball_height)); - row_to = fminf(row_to, env->brick_rows - 1); + float ball_x = env->ball_x; + float ball_x_dst = ball_x + env->ball_vx; + float ball_y = env->ball_y; + float ball_y_dst = ball_y + env->ball_vy; + float ball_width = env->ball_width; + float ball_height = env->ball_height; + + int row_from = row_index(env, ball_y < ball_y_dst ? ball_y : ball_y_dst); + if (row_from < 0) { + row_from = 0; + } + + if (row_from > env->brick_rows) { + return; + } + + int column_from = column_index(env, ball_x < ball_x_dst ? ball_x : ball_x_dst); + if (column_from < 0) { + column_from = 0; + } + + float ball_x_end = ball_x + ball_width; + float ball_x_dst_end = ball_x_dst + ball_width; + int column_to = column_index(env, ball_x_dst_end > ball_x_end ? ball_x_dst_end : ball_x_end); + if (column_to >= env->brick_cols) { + column_to = env->brick_cols - 1; + } + + float ball_y_end = ball_y + ball_height; + float ball_y_dst_end = ball_y_dst + ball_height; + int row_to = row_index(env, ball_y_dst_end > ball_y_end ? ball_y_dst_end : ball_y_end); + if (row_to >= env->brick_rows) { + row_to = env->brick_rows - 1; + } for (int row = row_from; row <= row_to; row++) { for (int column = column_from; column <= column_to; column++) { int brick_index = row * env->brick_cols + column; - if (env->brick_states[brick_index] == 0.0) + if (env->brick_states[brick_index] == 0.0f) calc_brick_collision(env, brick_index, collision_info); } } @@ -295,8 +321,8 @@ bool calc_paddle_ball_collisions(Breakout* env, CollisionInfo* collision_info) { float relative_intersection = ( (env->ball_x + env->ball_width / 2) - env->paddle_x) / env->paddle_width; float angle = -base_angle + relative_intersection * 2 * base_angle; - env->ball_vx = sin(angle) * env->ball_speed * TICK_RATE; - env->ball_vy = -cos(angle) * env->ball_speed * TICK_RATE; + env->ball_vx = sinf(angle) * env->ball_speed * TICK_RATE; + env->ball_vy = -cosf(angle) * env->ball_speed * TICK_RATE; env->hits += 1; if (env->hits % 4 == 0 && env->ball_speed < env->max_ball_speed) { env->ball_speed += 64; @@ -428,9 +454,9 @@ void step_frame(Breakout* env, float action) { env->balls_fired = 1; float direction = M_PI / 3.25f; - env->ball_vy = cos(direction) * env->ball_speed * TICK_RATE; - env->ball_vx = sin(direction) * env->ball_speed * TICK_RATE; - if (rand() % 2 == 0) { + env->ball_vy = cosf(direction) * env->ball_speed * TICK_RATE; + env->ball_vx = sinf(direction) * env->ball_speed * TICK_RATE; + if (rand_r(&env->rng) % 2 == 0) { env->ball_vx = -env->ball_vx; } } diff --git a/ocean/cartpole/binding.c b/ocean/cartpole/binding.c new file mode 100644 index 0000000000..16776c376d --- /dev/null +++ b/ocean/cartpole/binding.c @@ -0,0 +1,30 @@ +#include "cartpole.h" +#define OBS_SIZE 4 +#define NUM_ATNS 1 +#define ACT_SIZES {2} +#define OBS_TENSOR_T FloatTensor + +#define Env Cartpole +#include "vecenv.h" + +void my_init(Env* env, Dict* kwargs) { + env->num_agents = 1; + env->cart_mass = dict_get(kwargs, "cart_mass")->value; + env->pole_mass = dict_get(kwargs, "pole_mass")->value; + env->pole_length = dict_get(kwargs, "pole_length")->value; + env->gravity = dict_get(kwargs, "gravity")->value; + env->force_mag = dict_get(kwargs, "force_mag")->value; + env->tau = dict_get(kwargs, "dt")->value; + env->continuous = dict_get(kwargs, "continuous")->value; + init(env); +} + +void my_log(Log* log, Dict* out) { + dict_set(out, "score", log->score); + dict_set(out, "perf", log->perf); + dict_set(out, "episode_length", log->episode_length); + dict_set(out, "x_threshold_termination", log->x_threshold_termination); + dict_set(out, "pole_angle_termination", log->pole_angle_termination); + dict_set(out, "max_steps_termination", log->max_steps_termination); + dict_set(out, "n", log->n); +} diff --git a/pufferlib/ocean/cartpole/cartpole.c b/ocean/cartpole/cartpole.c similarity index 61% rename from pufferlib/ocean/cartpole/cartpole.c rename to ocean/cartpole/cartpole.c index 20e834b372..9078b121d4 100644 --- a/pufferlib/ocean/cartpole/cartpole.c +++ b/ocean/cartpole/cartpole.c @@ -8,59 +8,58 @@ #include "cartpole.h" #include "puffernet.h" -#define NUM_WEIGHTS 133123 #define OBSERVATIONS_SIZE 4 #define ACTIONS_SIZE 2 #define CONTINUOUS 0 const char* WEIGHTS_PATH = "resources/cartpole/cartpole_weights.bin"; -float movement(int discrete_action, int userControlMode) { +float movement(float action, int userControlMode) { if (userControlMode) { return (IsKeyDown(KEY_RIGHT) || IsKeyDown(KEY_D)) ? 1.0f : -1.0f; } else { - return (discrete_action == 1) ? 1.0f : -1.0f; + return (action > 0.5f) ? 1.0f : -1.0f; } } void demo() { - Weights* weights = load_weights(WEIGHTS_PATH, NUM_WEIGHTS); - LinearLSTM* net; + Weights* weights = load_weights(WEIGHTS_PATH); int logit_sizes[1] = {ACTIONS_SIZE}; - net = make_linearlstm(weights, 1, OBSERVATIONS_SIZE, logit_sizes, 1); - Cartpole env = {0}; - env.continuous = CONTINUOUS; + PufferNet* net = make_puffernet(weights, 1, OBSERVATIONS_SIZE, 32, 2, logit_sizes, 1); + + Cartpole env = { + .continuous = CONTINUOUS, + .cart_mass = 1.0f, + .pole_mass = 0.1f, + .pole_length = 0.5f, + .gravity = 9.8f, + .force_mag = 10.0f, + .tau = 0.02f, + }; allocate(&env); c_reset(&env); c_render(&env); - SetTargetFPS(60); - while (!WindowShouldClose()) { int userControlMode = IsKeyDown(KEY_LEFT_SHIFT); if (!userControlMode) { - int action_value; - forward_linearlstm(net, env.observations, &action_value); - env.actions[0] = movement(action_value, 0); + forward_puffernet(net, env.observations, env.actions); + env.actions[0] = movement(env.actions[0], 0); } else { env.actions[0] = movement(env.actions[0], userControlMode); } c_step(&env); - - BeginDrawing(); - ClearBackground(RAYWHITE); c_render(&env); - EndDrawing(); - if (env.terminals[0]) { + if (env.terminals[0] > 0.5f) { c_reset(&env); } } - free_linearlstm(net); + free_puffernet(net); free(weights); free_allocated(&env); } diff --git a/pufferlib/ocean/cartpole/cartpole.h b/ocean/cartpole/cartpole.h similarity index 84% rename from pufferlib/ocean/cartpole/cartpole.h rename to ocean/cartpole/cartpole.h index 7d87e11d6c..0f189ca1ab 100644 --- a/pufferlib/ocean/cartpole/cartpole.h +++ b/ocean/cartpole/cartpole.h @@ -33,9 +33,10 @@ struct Cartpole { float* observations; float* actions; float* rewards; - unsigned char* terminals; + float* terminals; unsigned char* truncations; Log log; + int num_agents; Client* client; float x; float x_dot; @@ -50,6 +51,7 @@ struct Cartpole { float tau; int continuous; float episode_return; + unsigned int rng; }; void add_log(Cartpole* env) { @@ -76,7 +78,7 @@ void allocate(Cartpole* env) { env->observations = (float*)calloc(4, sizeof(float)); env->actions = (float*)calloc(1, sizeof(float)); env->rewards = (float*)calloc(1, sizeof(float)); - env->terminals = (unsigned char*)calloc(1, sizeof(unsigned char)); + env->terminals = (float*)calloc(1, sizeof(float)); } void free_allocated(Cartpole* env) { @@ -141,34 +143,17 @@ void compute_observations(Cartpole* env) { void c_reset(Cartpole* env) { env->episode_return = 0.0f; - env->x = ((float)rand() / (float)RAND_MAX) * 0.08f - 0.04f; - env->x_dot = ((float)rand() / (float)RAND_MAX) * 0.08f - 0.04f; - env->theta = ((float)rand() / (float)RAND_MAX) * 0.08f - 0.04f; - env->theta_dot = ((float)rand() / (float)RAND_MAX) * 0.08f - 0.04f; + env->x = ((float)rand_r(&env->rng) / (float)RAND_MAX) * 0.08f - 0.04f; + env->x_dot = ((float)rand_r(&env->rng) / (float)RAND_MAX) * 0.08f - 0.04f; + env->theta = ((float)rand_r(&env->rng) / (float)RAND_MAX) * 0.08f - 0.04f; + env->theta_dot = ((float)rand_r(&env->rng) / (float)RAND_MAX) * 0.08f - 0.04f; env->tick = 0; compute_observations(env); } void c_step(Cartpole* env) { - // float force = 0.0; - // if (env->continuous) { - // force = env->actions[0] * FORCE_MAG; - // } else { - // force = (env->actions[0] > 0.5f) ? FORCE_MAG : -FORCE_MAG; - // } - float a = env->actions[0]; - - /* ===== runtime sanity check –– delete after debugging ===== */ - if (!isfinite(a) || a < -1.0001f || a > 1.0001f) { - fprintf(stderr, - "[BAD ACTION] tick=%d raw=%.6f\n", - env->tick, a); - fflush(stderr); - } - /* ========================================================== */ - if (!isfinite(a)) { a = 0.0f; } @@ -176,7 +161,7 @@ void c_step(Cartpole* env) { env->actions[0] = a; float force = env->continuous ? a * env->force_mag - : (a > 0.5f ? env->force_mag: -env->force_mag); + : (a > 0.5f ? env->force_mag: -env->force_mag); float costheta = cosf(env->theta); float sintheta = sinf(env->theta); diff --git a/pufferlib/ocean/chain_mdp/binding.c b/ocean/chain_mdp/binding.c similarity index 100% rename from pufferlib/ocean/chain_mdp/binding.c rename to ocean/chain_mdp/binding.c diff --git a/pufferlib/ocean/chain_mdp/chain_mdp.c b/ocean/chain_mdp/chain_mdp.c similarity index 100% rename from pufferlib/ocean/chain_mdp/chain_mdp.c rename to ocean/chain_mdp/chain_mdp.c diff --git a/pufferlib/ocean/chain_mdp/chain_mdp.h b/ocean/chain_mdp/chain_mdp.h similarity index 100% rename from pufferlib/ocean/chain_mdp/chain_mdp.h rename to ocean/chain_mdp/chain_mdp.h diff --git a/pufferlib/ocean/checkers/binding.c b/ocean/checkers/binding.c similarity index 100% rename from pufferlib/ocean/checkers/binding.c rename to ocean/checkers/binding.c diff --git a/pufferlib/ocean/checkers/checkers.c b/ocean/checkers/checkers.c similarity index 100% rename from pufferlib/ocean/checkers/checkers.c rename to ocean/checkers/checkers.c diff --git a/pufferlib/ocean/checkers/checkers.h b/ocean/checkers/checkers.h similarity index 100% rename from pufferlib/ocean/checkers/checkers.h rename to ocean/checkers/checkers.h diff --git a/ocean/connect4/binding.c b/ocean/connect4/binding.c new file mode 100644 index 0000000000..4c68006442 --- /dev/null +++ b/ocean/connect4/binding.c @@ -0,0 +1,23 @@ +#include "connect4.h" +#define OBS_SIZE 42 +#define NUM_ATNS 1 +#define ACT_SIZES {7} +#define OBS_TENSOR_T FloatTensor + +#define Env Connect4 +#include "vecenv.h" + +void my_init(Env* env, Dict* kwargs) { + env->num_agents = 1; + env->player_pieces = dict_get(kwargs, "player_pieces")->value; + env->env_pieces = dict_get(kwargs, "env_pieces")->value; + init(env); +} + +void my_log(Log* log, Dict* out) { + dict_set(out, "perf", log->perf); + dict_set(out, "score", log->score); + dict_set(out, "episode_return", log->episode_return); + dict_set(out, "episode_length", log->episode_length); + dict_set(out, "n", log->n); +} diff --git a/pufferlib/ocean/connect4/connect4.c b/ocean/connect4/connect4.c similarity index 56% rename from pufferlib/ocean/connect4/connect4.c rename to ocean/connect4/connect4.c index cf617b7afe..df7059e24f 100644 --- a/pufferlib/ocean/connect4/connect4.c +++ b/ocean/connect4/connect4.c @@ -4,19 +4,17 @@ const unsigned char NOOP = 8; -void interactive() { - Weights* weights = load_weights("resources/connect4/connect4_weights.bin", 138632); +void demo() { + Weights* weights = load_weights("resources/connect4/connect4_weights.bin"); int logit_sizes[] = {7}; - LinearLSTM* net = make_linearlstm(weights, 1, 42, logit_sizes, 1); + PufferNet* net = make_puffernet(weights, 1, 42, 256, 1, logit_sizes, 1); - CConnect4 env = { + Connect4 env = { }; allocate_cconnect4(&env); c_reset(&env); env.client = make_client(); - float observations[42] = {0}; - int actions[1] = {0}; int tick = 0; while (!WindowShouldClose()) { @@ -31,11 +29,7 @@ void interactive() { if(IsKeyPressed(KEY_SIX)) env.actions[0] = 5; if(IsKeyPressed(KEY_SEVEN)) env.actions[0] = 6; } else if (tick % 30 == 0) { - for (int i = 0; i < 42; i++) { - observations[i] = env.observations[i]; - } - forward_linearlstm(net, (float*)&observations, (int*)&actions); - env.actions[0] = actions[0]; + forward_puffernet(net, env.observations, env.actions); } tick = (tick + 1) % 60; @@ -45,33 +39,13 @@ void interactive() { c_render(&env); } - free_linearlstm(net); + free_puffernet(net); free(weights); close_client(env.client); free_allocated_cconnect4(&env); } -void performance_test() { - long test_time = 10; - CConnect4 env = { - }; - allocate_cconnect4(&env); - c_reset(&env); - - long start = time(NULL); - int i = 0; - while (time(NULL) - start < test_time) { - env.actions[0] = rand() % 7; - c_step(&env); - i++; - } - long end = time(NULL); - printf("SPS: %ld\n", i / (end - start)); - free_allocated_cconnect4(&env); -} - int main() { - // performance_test(); - interactive(); + demo(); return 0; } diff --git a/pufferlib/ocean/connect4/connect4.h b/ocean/connect4/connect4.h similarity index 89% rename from pufferlib/ocean/connect4/connect4.h rename to ocean/connect4/connect4.h index dde12a4a16..5fe2d1d5e4 100644 --- a/pufferlib/ocean/connect4/connect4.h +++ b/ocean/connect4/connect4.h @@ -7,8 +7,6 @@ #define WIN_CONDITION 4 const int PLAYER_WIN = 1.0; const int ENV_WIN = -1.0; -const unsigned char DONE = 1; -const unsigned char NOT_DONE = 0; const int ROWS = 6; const int COLUMNS = 7; const int WIDTH = 672; @@ -30,13 +28,14 @@ struct Log { }; typedef struct Client Client; -typedef struct CConnect4 CConnect4; -struct CConnect4 { +typedef struct Connect4 Connect4; +struct Connect4 { // Pufferlib inputs / outputs float* observations; - int* actions; + float* actions; float* rewards; - unsigned char* terminals; + float* terminals; + int num_agents; Log log; Client* client; @@ -47,35 +46,36 @@ struct CConnect4 { uint64_t env_pieces; int tick; + int end_game; + unsigned int rng; }; -void allocate_cconnect4(CConnect4* env) { +void allocate_cconnect4(Connect4* env) { env->observations = (float*)calloc(42, sizeof(float)); - env->actions = (int*)calloc(1, sizeof(int)); - env->terminals = (unsigned char*)calloc(1, sizeof(unsigned char)); + env->actions = (float*)calloc(1, sizeof(float)); + env->terminals = (float*)calloc(1, sizeof(float)); env->rewards = (float*)calloc(1, sizeof(float)); } -void free_allocated_cconnect4(CConnect4* env) { +void free_allocated_cconnect4(Connect4* env) { free(env->actions); free(env->observations); free(env->terminals); free(env->rewards); } -void c_close(CConnect4* env) { +void c_close(Connect4* env) { } -void add_log(CConnect4* env) { +void add_log(Connect4* env) { env->log.perf += (float)(env->rewards[0] == PLAYER_WIN); env->log.score += env->rewards[0]; env->log.episode_return += env->rewards[0]; - env->log.episode_length += env->log.episode_length; + env->log.episode_length += env->tick; env->log.n += 1; } -void init(CConnect4* env) { - env->log = (Log){0}; +void init(Connect4* env) { env->tick = 0; } @@ -162,7 +162,7 @@ float negamax(uint64_t pieces, uint64_t other_pieces, int depth) { return value; } -int compute_env_move(CConnect4* env) { +int compute_env_move(Connect4* env) { uint64_t piece_mask = env->player_pieces | env->env_pieces; uint64_t hash = env->player_pieces + piece_mask + c_bottom(); @@ -205,7 +205,8 @@ int compute_env_move(CConnect4* env) { } } //printf("Values: %f, %f, %f, %f, %f, %f, %f\n", values[0], values[1], values[2], values[3], values[4], values[5], values[6]); - int best_tie = rand() % num_ties; + //int best_tie = rand() % num_ties; + int best_tie = rand_r(&env->rng) % num_ties; for (uint64_t column = 0; column < 7; column ++) { if (values[column] == best_value) { if (best_tie == 0) { @@ -218,7 +219,7 @@ int compute_env_move(CConnect4* env) { return 0; } -void compute_observation(CConnect4* env) { +void compute_observation(Connect4* env) { // Populate observations from bitstring game representation // http://blog.gamesolver.org/solving-connect-four/06-bitboard/ uint64_t player_pieces = env->player_pieces; @@ -243,9 +244,10 @@ void compute_observation(CConnect4* env) { } } -void c_reset(CConnect4* env) { - env->log = (Log){0}; - env->terminals[0] = NOT_DONE; +void c_reset(Connect4* env) { + env->end_game = 0; + env->tick=0; + env->terminals[0] = 0; env->player_pieces = 0; env->env_pieces = 0; for (int i = 0; i < 42; i ++) { @@ -253,24 +255,25 @@ void c_reset(CConnect4* env) { } } -void finish_game(CConnect4* env, float reward) { +void finish_game(Connect4* env, float reward) { env->rewards[0] = reward; - env->terminals[0] = DONE; + env->terminals[0] = 1; add_log(env); - compute_observation(env); + env->end_game = 1; } -void c_step(CConnect4* env) { - env->log.episode_length += 1; +void c_step(Connect4* env) { + env->tick+=1; env->rewards[0] = 0.0; + env->terminals[0] = 0; - if (env->terminals[0] == DONE) { + if(env->end_game == 1) { c_reset(env); return; } // Player action (PLAYER_WIN) - uint64_t column = env->actions[0]; + uint64_t column = (uint64_t)env->actions[0]; uint64_t piece_mask = env->player_pieces | env->env_pieces; if (invalid_move(column, piece_mask)) { finish_game(env, ENV_WIN); @@ -324,7 +327,7 @@ Client* make_client() { return client; } -void c_render(CConnect4* env) { +void c_render(Connect4* env) { if (IsKeyDown(KEY_ESCAPE)) { exit(0); } diff --git a/ocean/convert/binding.c b/ocean/convert/binding.c new file mode 100644 index 0000000000..4209a27e06 --- /dev/null +++ b/ocean/convert/binding.c @@ -0,0 +1,25 @@ +#include "convert.h" +#define OBS_SIZE 28 +#define NUM_ATNS 2 +#define ACT_SIZES {9, 5} +#define OBS_TYPE FLOAT +#define ACT_TYPE DOUBLE + +#define Env Convert +#include "vecenv.h" + +void my_init(Env* env, Dict* kwargs) { + env->num_agents = dict_get(kwargs, "num_agents")->value; + env->width = dict_get(kwargs, "width")->value; + env->height = dict_get(kwargs, "height")->value; + env->num_factories = dict_get(kwargs, "num_factories")->value; + env->num_resources = dict_get(kwargs, "num_resources")->value; + init(env); +} + +void my_log(Log* log, Dict* out) { + dict_set(out, "perf", log->perf); + dict_set(out, "score", log->score); + dict_set(out, "episode_return", log->episode_return); + dict_set(out, "episode_length", log->episode_length); +} diff --git a/pufferlib/ocean/convert/convert.c b/ocean/convert/convert.c similarity index 98% rename from pufferlib/ocean/convert/convert.c rename to ocean/convert/convert.c index 09f0d41f43..327dd807f5 100644 --- a/pufferlib/ocean/convert/convert.c +++ b/ocean/convert/convert.c @@ -17,7 +17,7 @@ int main() { env.rewards = calloc(env.num_agents, sizeof(float)); env.terminals = calloc(env.num_agents, sizeof(unsigned char)); - Weights* weights = load_weights("resources/convert/convert_weights.bin", 137743); + Weights* weights = load_weights("resources/convert/convert_weights.bin"); int logit_sizes[2] = {9, 5}; LinearLSTM* net = make_linearlstm(weights, env.num_agents, num_obs, logit_sizes, 2); diff --git a/pufferlib/ocean/convert/convert.h b/ocean/convert/convert.h similarity index 99% rename from pufferlib/ocean/convert/convert.h rename to ocean/convert/convert.h index d7d6828bdf..c3cf3305c3 100644 --- a/pufferlib/ocean/convert/convert.h +++ b/ocean/convert/convert.h @@ -43,12 +43,12 @@ typedef struct { Agent* agents; Factory* factories; float* observations; - int* actions; + double* actions; float* rewards; - unsigned char* terminals; + float* terminals; + int num_agents; int width; int height; - int num_agents; int num_factories; int num_resources; } Convert; diff --git a/pufferlib/ocean/convert_circle/binding.c b/ocean/convert_circle/binding.c similarity index 100% rename from pufferlib/ocean/convert_circle/binding.c rename to ocean/convert_circle/binding.c diff --git a/pufferlib/ocean/convert_circle/convert_circle.c b/ocean/convert_circle/convert_circle.c similarity index 94% rename from pufferlib/ocean/convert_circle/convert_circle.c rename to ocean/convert_circle/convert_circle.c index d889361081..bd8784d2bb 100644 --- a/pufferlib/ocean/convert_circle/convert_circle.c +++ b/ocean/convert_circle/convert_circle.c @@ -23,7 +23,7 @@ int main() { env.terminals = calloc(env.num_agents, sizeof(unsigned char)); Weights *weights = - load_weights("resources/convert/convert_weights.bin", 137743); + load_weights("resources/convert/convert_weights.bin"); int logit_sizes[2] = {9, 5}; LinearLSTM *net = make_linearlstm(weights, env.num_agents, num_obs, logit_sizes, 2); diff --git a/pufferlib/ocean/convert_circle/convert_circle.h b/ocean/convert_circle/convert_circle.h similarity index 100% rename from pufferlib/ocean/convert_circle/convert_circle.h rename to ocean/convert_circle/convert_circle.h diff --git a/ocean/drive/binding.c b/ocean/drive/binding.c new file mode 100644 index 0000000000..e68a04448e --- /dev/null +++ b/ocean/drive/binding.c @@ -0,0 +1,155 @@ +#include "drive.h" +#define NUM_ATNS 2 +#define ACT_SIZES {7, 13} +#define OBS_TENSOR_T FloatTensor + +#define MAP_BINARY_DIR "drive_data/binaries" + +#define MY_VEC_INIT +#define Env Drive +#include "vecenv.h" + +Env* my_vec_init(int* num_envs_out, int* buffer_env_starts, int* buffer_env_counts, Dict* vec_kwargs, Dict* env_kwargs) { + int total_agents = (int)dict_get(vec_kwargs, "total_agents")->value; + int num_buffers = (int)dict_get(vec_kwargs, "num_buffers")->value; + int num_maps = (int)dict_get(env_kwargs, "num_maps")->value; + int agents_per_buffer = total_agents / num_buffers; + + float reward_vehicle_collision = dict_get(env_kwargs, "reward_vehicle_collision")->value; + float reward_offroad_collision = dict_get(env_kwargs, "reward_offroad_collision")->value; + float reward_goal_post_respawn = dict_get(env_kwargs, "reward_goal_post_respawn")->value; + float reward_vehicle_collision_post_respawn = dict_get(env_kwargs, "reward_vehicle_collision_post_respawn")->value; + int human_agent_idx = (int)dict_get(env_kwargs, "human_agent_idx")->value; + + // Verify that the path has valid binaries + char first_map[512]; + snprintf(first_map, sizeof(first_map), "%s/map_%03d.bin", MAP_BINARY_DIR, 0); + FILE* test_fp = fopen(first_map, "rb"); + if (!test_fp) { + printf("ERROR: Cannot find map files at %s/\n", MAP_BINARY_DIR); + *num_envs_out = 0; + return NULL; + } + fclose(test_fp); + + // Scan all maps for agent counts; collect valid (>0) ones + int agents_per_map[num_maps]; + int valid_map_ids[num_maps]; + int num_valid_maps = 0; + for (int m = 0; m < num_maps; m++) { + char map_file[512]; + snprintf(map_file, sizeof(map_file), "%s/map_%03d.bin", MAP_BINARY_DIR, m); + Env temp_env = {0}; + temp_env.map_name = map_file; + init(&temp_env); + agents_per_map[m] = temp_env.active_agent_count < MAX_AGENTS + ? temp_env.active_agent_count : MAX_AGENTS; + c_close(&temp_env); + if (agents_per_map[m] > 0) { + valid_map_ids[num_valid_maps++] = m; + } + } + printf("Scanned %d maps from %s/, %d valid\n", num_maps, MAP_BINARY_DIR, num_valid_maps); + + if (num_valid_maps == 0) { + printf("ERROR: No valid maps found\n"); + *num_envs_out = 0; + return NULL; + } + + // Build per-env layout. Each buffer advances the global cursor so different + // buffers get different maps. If the next full map would overflow a buffer, + // pack remaining slots with 1-agent envs advancing the cursor each time. + int max_envs = agents_per_buffer * num_buffers; // upper bound (all 1-agent) + int* env_map_ids = (int*)malloc(max_envs * sizeof(int)); + int* env_max_agents = (int*)malloc(max_envs * sizeof(int)); + int total_envs = 0; + int cursor = 0; // advances across buffers + + for (int b = 0; b < num_buffers; b++) { + buffer_env_starts[b] = total_envs; + int buffer_agents = 0; + while (buffer_agents < agents_per_buffer) { + int m = valid_map_ids[cursor % num_valid_maps]; + int cap = agents_per_map[m]; + int remaining = agents_per_buffer - buffer_agents; + if (cap <= remaining) { + // Full map fits + env_map_ids[total_envs] = m; + env_max_agents[total_envs] = cap; + buffer_agents += cap; + total_envs++; + cursor++; + } else { + // Pack remaining slots as 1-agent envs, one map each + while (buffer_agents < agents_per_buffer) { + int mm = valid_map_ids[cursor % num_valid_maps]; + env_map_ids[total_envs] = mm; + env_max_agents[total_envs] = 1; + buffer_agents++; + total_envs++; + cursor++; + } + } + } + buffer_env_counts[b] = total_envs - buffer_env_starts[b]; + } + + printf("total envs: %d (%d maps cycled)\n", total_envs, cursor); + + // Initialize all envs + Env* envs = (Env*)calloc(total_envs, sizeof(Env)); + for (int i = 0; i < total_envs; i++) { + char map_file[512]; + snprintf(map_file, sizeof(map_file), "%s/map_%03d.bin", MAP_BINARY_DIR, env_map_ids[i]); + Env* env = &envs[i]; + memset(env, 0, sizeof(Env)); + env->map_name = strdup(map_file); + env->human_agent_idx = human_agent_idx; + env->reward_vehicle_collision = reward_vehicle_collision; + env->reward_offroad_collision = reward_offroad_collision; + env->reward_goal_post_respawn = reward_goal_post_respawn; + env->reward_vehicle_collision_post_respawn = reward_vehicle_collision_post_respawn; + env->max_agents = env_max_agents[i]; + init(env); + env->num_agents = env->active_agent_count; + } + + free(env_map_ids); + free(env_max_agents); + + printf("Created %d envs, %d total agents (target %d)\n", + total_envs, total_agents, total_agents); + + *num_envs_out = total_envs; + return envs; +} + +void my_init(Env* env, Dict* kwargs) { + env->human_agent_idx = dict_get(kwargs, "human_agent_idx")->value; + env->reward_vehicle_collision = dict_get(kwargs, "reward_vehicle_collision")->value; + env->reward_offroad_collision = dict_get(kwargs, "reward_offroad_collision")->value; + env->reward_goal_post_respawn = dict_get(kwargs, "reward_goal_post_respawn")->value; + env->reward_vehicle_collision_post_respawn = dict_get(kwargs, "reward_vehicle_collision_post_respawn")->value; + int map_id = dict_get(kwargs, "map_id")->value; + int max_agents = dict_get(kwargs, "max_agents")->value; + + char map_file[512]; + snprintf(map_file, sizeof(map_file), "%s/map_%03d.bin", MAP_BINARY_DIR, map_id); + env->num_agents = max_agents; + env->map_name = strdup(map_file); + init(env); +} + +void my_log(Log* log, Dict* out) { + dict_set(out, "perf", log->perf); + dict_set(out, "score", log->score); + dict_set(out, "episode_return", log->episode_return); + dict_set(out, "episode_length", log->episode_length); + dict_set(out, "offroad_rate", log->offroad_rate); + dict_set(out, "collision_rate", log->collision_rate); + dict_set(out, "dnf_rate", log->dnf_rate); + dict_set(out, "n", log->n); + dict_set(out, "completion_rate", log->completion_rate); + dict_set(out, "clean_collision_rate", log->clean_collision_rate); +} diff --git a/ocean/drive/dataset.py b/ocean/drive/dataset.py new file mode 100644 index 0000000000..bf59f27705 --- /dev/null +++ b/ocean/drive/dataset.py @@ -0,0 +1,279 @@ +"""Convert Waymo Open Motion Dataset (WOMD) JSON maps to binary format for PufferLib drive env. + +Step 0: Download the preprocessed JSON scenarios from HuggingFace e.g., + https://huggingface.co/datasets/daphne-cornelisse/pufferdrive_womd_train_1000 + + uv pip install huggingface_hub + python -c "from huggingface_hub import snapshot_download; snapshot_download(repo_id='daphne-cornelisse/pufferdrive_womd_train_1000', repo_type='dataset', local_dir='drive_data')" + +Step 1: Unzip to get folder with .json files + mkdir -p drive_data/training + tar xzf drive_data/pufferdrive_womd_train_1000.tar.gz --strip-components=1 -C drive_data/training/ + +Step 2: Process to map binaries + python ocean/drive/dataset.py --data_folder drive_data/training --output_dir drive_data/binaries +""" + +import json +import struct +import os +from multiprocessing import Pool, cpu_count +from pathlib import Path +from tqdm import tqdm + +TRAJECTORY_LENGTH = 91 + + +def calculate_area(p1, p2, p3): + """Calculate the area of the triangle using the determinant method.""" + return 0.5 * abs( + (p1["x"] - p3["x"]) * (p2["y"] - p1["y"]) + - (p1["x"] - p2["x"]) * (p3["y"] - p1["y"]) + ) + + +def dist(a, b): + dx = a["x"] - b["x"] + dy = a["y"] - b["y"] + return dx * dx + dy * dy + + +def simplify_polyline(geometry, polyline_reduction_threshold, max_segment_length): + """Simplify the given polyline using a method inspired by Visvalingham-Whyatt.""" + num_points = len(geometry) + if num_points < 3: + return geometry + + skip = [False] * num_points + skip_changed = True + + while skip_changed: + skip_changed = False + k = 0 + while k < num_points - 1: + k_1 = k + 1 + while k_1 < num_points - 1 and skip[k_1]: + k_1 += 1 + if k_1 >= num_points - 1: + break + + k_2 = k_1 + 1 + while k_2 < num_points and skip[k_2]: + k_2 += 1 + if k_2 >= num_points: + break + + point1 = geometry[k] + point2 = geometry[k_1] + point3 = geometry[k_2] + area = calculate_area(point1, point2, point3) + if ( + area < polyline_reduction_threshold + and dist(point1, point3) <= max_segment_length + ): + skip[k_1] = True + skip_changed = True + k = k_2 + else: + k = k_1 + + return [geometry[i] for i in range(num_points) if not skip[i]] + + +def save_map_binary(map_data, output_file, unique_map_id): + """Save map data in a binary format readable by C.""" + with open(output_file, "wb") as f: + num_objects = len(map_data.get("objects", [])) + num_roads = len(map_data.get("roads", [])) + f.write(struct.pack("i", num_objects)) + f.write(struct.pack("i", num_roads)) + + # Write objects + for obj in map_data.get("objects", []): + obj_type = obj.get("type", 1) + if obj_type == "vehicle": + obj_type = 1 + elif obj_type == "pedestrian": + obj_type = 2 + elif obj_type == "cyclist": + obj_type = 3 + f.write(struct.pack("i", obj_type)) + f.write(struct.pack("i", TRAJECTORY_LENGTH)) + + positions = obj.get("position", []) + for coord in ["x", "y", "z"]: + for i in range(TRAJECTORY_LENGTH): + pos = ( + positions[i] + if i < len(positions) + else {"x": 0.0, "y": 0.0, "z": 0.0} + ) + f.write(struct.pack("f", float(pos.get(coord, 0.0)))) + + velocities = obj.get("velocity", []) + for coord in ["x", "y", "z"]: + for i in range(TRAJECTORY_LENGTH): + vel = ( + velocities[i] + if i < len(velocities) + else {"x": 0.0, "y": 0.0, "z": 0.0} + ) + f.write(struct.pack("f", float(vel.get(coord, 0.0)))) + + headings = obj.get("heading", []) + f.write( + struct.pack( + f"{TRAJECTORY_LENGTH}f", + *[ + float(headings[i]) if i < len(headings) else 0.0 + for i in range(TRAJECTORY_LENGTH) + ], + ) + ) + + valids = obj.get("valid", []) + f.write( + struct.pack( + f"{TRAJECTORY_LENGTH}i", + *[ + int(valids[i]) if i < len(valids) else 0 + for i in range(TRAJECTORY_LENGTH) + ], + ) + ) + + f.write(struct.pack("f", float(obj.get("width", 0.0)))) + f.write(struct.pack("f", float(obj.get("length", 0.0)))) + f.write(struct.pack("f", float(obj.get("height", 0.0)))) + goal_pos = obj.get("goalPosition", {"x": 0, "y": 0, "z": 0}) + f.write(struct.pack("f", float(goal_pos.get("x", 0.0)))) + f.write(struct.pack("f", float(goal_pos.get("y", 0.0)))) + f.write(struct.pack("f", float(goal_pos.get("z", 0.0)))) + f.write(struct.pack("i", obj.get("mark_as_expert", 0))) + + # Write roads + for road in map_data.get("roads", []): + geometry = road.get("geometry", []) + road_type = road.get("map_element_id", 0) + road_type_word = road.get("type", 0) + if road_type_word == "lane": + road_type = 2 + elif road_type_word == "road_edge": + road_type = 15 + + if len(geometry) > 10 and road_type <= 16: + geometry = simplify_polyline(geometry, 0.1, 250) + size = len(geometry) + + if 0 <= road_type <= 3: + road_type = 4 + elif 5 <= road_type <= 13: + road_type = 5 + elif 14 <= road_type <= 16: + road_type = 6 + elif road_type == 17: + road_type = 7 + elif road_type == 18: + road_type = 8 + elif road_type == 19: + road_type = 9 + elif road_type == 20: + road_type = 10 + + f.write(struct.pack("i", road_type)) + f.write(struct.pack("i", size)) + + for coord in ["x", "y", "z"]: + for point in geometry: + f.write(struct.pack("f", float(point.get(coord, 0.0)))) + + f.write(struct.pack("f", float(road.get("width", 0.0)))) + f.write(struct.pack("f", float(road.get("length", 0.0)))) + f.write(struct.pack("f", float(road.get("height", 0.0)))) + goal_pos = road.get("goalPosition", {"x": 0, "y": 0, "z": 0}) + f.write(struct.pack("f", float(goal_pos.get("x", 0.0)))) + f.write(struct.pack("f", float(goal_pos.get("y", 0.0)))) + f.write(struct.pack("f", float(goal_pos.get("z", 0.0)))) + f.write(struct.pack("i", road.get("mark_as_expert", 0))) + + +def _process_single_map(args): + """Worker function to process a single map file.""" + i, map_path, binary_path = args + try: + with open(map_path, "r") as f: + map_data = json.load(f) + save_map_binary(map_data, str(binary_path), i) + return (i, map_path.name, True, None) + except Exception as e: + return (i, map_path.name, False, str(e)) + + +def process_all_maps( + data_folder, + output_dir, + max_maps=50_000, + num_workers=None, +): + """Process JSON map files into binary format using multiprocessing. + + Args: + data_folder: Path to the folder containing JSON map files. + output_dir: Path to the directory where binary files will be written. + max_maps: Maximum number of maps to process. + num_workers: Number of parallel workers (defaults to cpu_count()). + """ + if num_workers is None: + num_workers = cpu_count() + + data_dir = Path(data_folder) + binary_dir = Path(output_dir) + binary_dir.mkdir(parents=True, exist_ok=True) + + json_files = sorted(data_dir.glob("*.json")) + if not json_files: + print(f"No JSON files found in {data_dir}") + return + + tasks = [] + for i, map_path in enumerate(json_files[:max_maps]): + binary_path = binary_dir / f"map_{i:03d}.bin" + tasks.append((i, map_path, binary_path)) + + with Pool(num_workers) as pool: + results = list( + tqdm( + pool.imap(_process_single_map, tasks), + total=len(tasks), + desc="Processing maps", + unit="map", + ) + ) + + successful = sum(1 for _, _, success, _ in results if success) + failed = sum(1 for _, _, success, _ in results if not success) + + print(f"\nProcessed {successful}/{len(results)} maps successfully.") + if failed > 0: + print(f"Failed {failed}/{len(results)} files:") + for i, name, success, error in results: + if not success: + print(f" {name}: {error}") + + +if __name__ == "__main__": + import argparse + + parser = argparse.ArgumentParser(description="Convert JSON map files to binary format.") + parser.add_argument("--data_folder", type=str, required=True, help="Path to folder containing JSON map files.") + parser.add_argument("--output_dir", type=str, required=True, help="Path to output directory for binary files.") + parser.add_argument("--max_maps", type=int, default=50_000, help="Maximum number of maps to process.") + parser.add_argument("--num_workers", type=int, default=None, help="Number of parallel workers.") + args = parser.parse_args() + + process_all_maps( + data_folder=args.data_folder, + output_dir=args.output_dir, + max_maps=args.max_maps, + num_workers=args.num_workers, + ) \ No newline at end of file diff --git a/ocean/drive/drive.c b/ocean/drive/drive.c new file mode 100644 index 0000000000..48a3ddf7b7 --- /dev/null +++ b/ocean/drive/drive.c @@ -0,0 +1,89 @@ +#include +#include +#include "drive.h" +#include "puffernet.h" + +void demo() { + Drive env = { + .dynamics_model = CLASSIC, + .human_agent_idx = 0, + .reward_vehicle_collision = -0.1f, + .reward_offroad_collision = -0.1f, + .map_name = "resources/drive/map_010.bin", + }; + allocate(&env); + c_reset(&env); + c_render(&env); + Weights* weights = load_weights("resources/drive/drive_weights.bin"); + int logit_sizes[2] = {7, 13}; + PufferNet* net = make_puffernet(weights, env.active_agent_count, OBS_SIZE, 256, 4, logit_sizes, 2); + int accel_delta = 2; + int steer_delta = 4; + while (!WindowShouldClose()) { + float (*actions)[2] = (float(*)[2])env.actions; + forward_puffernet(net, env.observations, env.actions); + if (IsKeyDown(KEY_LEFT_SHIFT)) { + actions[env.human_agent_idx][0] = 3; + actions[env.human_agent_idx][1] = 6; + if(IsKeyDown(KEY_UP) || IsKeyDown(KEY_W)){ + actions[env.human_agent_idx][0] += accel_delta; + if(actions[env.human_agent_idx][0] > 6) actions[env.human_agent_idx][0] = 6; + } + if(IsKeyDown(KEY_DOWN) || IsKeyDown(KEY_S)){ + actions[env.human_agent_idx][0] -= accel_delta; + if(actions[env.human_agent_idx][0] < 0) actions[env.human_agent_idx][0] = 0; + } + if(IsKeyDown(KEY_LEFT) || IsKeyDown(KEY_A)){ + actions[env.human_agent_idx][1] += steer_delta; + if(actions[env.human_agent_idx][1] < 0) actions[env.human_agent_idx][1] = 0; + } + if(IsKeyDown(KEY_RIGHT) || IsKeyDown(KEY_D)){ + actions[env.human_agent_idx][1] -= steer_delta; + if(actions[env.human_agent_idx][1] > 12) actions[env.human_agent_idx][1] = 12; + } + if(IsKeyPressed(KEY_TAB)){ + env.human_agent_idx = (env.human_agent_idx + 1) % env.active_agent_count; + } + } + c_step(&env); + c_render(&env); + } + + close_client(env.client); + free_allocated(&env); + free_puffernet(net); + free(weights); +} + +void performance_test() { + long test_time = 10; + Drive env = { + .dynamics_model = CLASSIC, + .human_agent_idx = 0, + .map_name = "resources/drive/map_942.bin", + }; + allocate(&env); + c_reset(&env); + + Weights* weights = load_weights("resources/drive/drive_weights.bin"); + int logit_sizes[2] = {7, 13}; + PufferNet* net = make_puffernet(weights, env.active_agent_count, OBS_SIZE, 256, 4, logit_sizes, 2); + + long start = time(NULL); + int i = 0; + while (time(NULL) - start < test_time) { + forward_puffernet(net, env.observations, env.actions); + c_step(&env); + i++; + } + long end = time(NULL); + printf("SPS: %ld\n", (long)(i*env.active_agent_count) / (end - start)); + free_allocated(&env); + free_puffernet(net); + free(weights); +} + +int main() { + demo(); + return 0; +} diff --git a/ocean/drive/drive.h b/ocean/drive/drive.h new file mode 100644 index 0000000000..931e04d1fe --- /dev/null +++ b/ocean/drive/drive.h @@ -0,0 +1,1590 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include "raylib.h" +#include "raymath.h" +#include "rlgl.h" +#include + +// Entity Types +#define NONE 0 +#define VEHICLE 1 +#define PEDESTRIAN 2 +#define CYCLIST 3 +#define ROAD_LANE 4 +#define ROAD_LINE 5 +#define ROAD_EDGE 6 +#define STOP_SIGN 7 +#define CROSSWALK 8 +#define SPEED_BUMP 9 +#define DRIVEWAY 10 + +#define INVALID_POSITION -10000.0f + +// Simulation constants +#define TRAJECTORY_LENGTH 91 // Discretized Waymo scenarios +#define SIM_DT 0.1f + +// Agent limits +#ifndef MAX_AGENTS +#define MAX_AGENTS 64 +#endif + +// Dynamics models +#define CLASSIC 0 + +// Collision State +#define NO_COLLISION 0 +#define VEHICLE_COLLISION 1 +#define OFFROAD 2 + +// Grid Map +#define GRID_CELL_SIZE 5.0f +#define MAX_ENTITIES_PER_CELL 10 +#define SLOTS_PER_CELL (MAX_ENTITIES_PER_CELL * 2 + 1) +#define VISION_RANGE 21 + +// Observation Space +#define MAX_ROAD_SEGMENT_OBSERVATIONS 75 + +#define PARTNER_FEATURES 7 +#define EGO_FEATURES 7 +#define ROAD_FEATURES 7 + +#define OBS_SIZE (EGO_FEATURES + PARTNER_FEATURES * (MAX_AGENTS - 1) + ROAD_FEATURES * MAX_ROAD_SEGMENT_OBSERVATIONS) + +// Observation normalization +#define MAX_SPEED 100.0f +#define MAX_VEH_LEN 30.0f +#define MAX_VEH_WIDTH 15.0f +#define MAX_VEH_HEIGHT 10.0f +#define MAX_ROAD_SCALE 100.0f +#define MAX_ROAD_SEGMENT_LENGTH 100.0f + +// Observation scaling factors +#define OBS_GOAL_SCALE 0.005f +#define OBS_SPEED_SCALE 0.01f +#define OBS_POSITION_SCALE 0.02f + +// Distance thresholds +#define MIN_DISTANCE_TO_GOAL 5.0f +#define COLLISION_DIST_SQ 225.0f +#define OBS_DIST_SQ 2500.0f +#define COLLISION_BOX_SCALE 0.7f + +// Action space +#define NUM_ACCEL_BINS 7 +#define NUM_STEER_BINS 13 + +static const float ACCELERATION_VALUES[NUM_ACCEL_BINS] = { + -4.0000f, -2.6670f, -1.3330f, -0.0000f, 1.3330f, 2.6670f, 4.0000f +}; + +static const float STEERING_VALUES[NUM_STEER_BINS] = { + -1.000f, -0.833f, -0.667f, -0.500f, -0.333f, -0.167f, 0.000f, + 0.167f, 0.333f, 0.500f, 0.667f, 0.833f, 1.000f +}; + +// Geometry helpers +static const float offsets[4][2] = { + {-1, 1}, // top-left + { 1, 1}, // top-right + { 1, -1}, // bottom-right + {-1, -1} // bottom-left +}; + +static const int collision_offsets[25][2] = { + {-2, -2}, {-1, -2}, {0, -2}, {1, -2}, {2, -2}, + {-2, -1}, {-1, -1}, {0, -1}, {1, -1}, {2, -1}, + {-2, 0}, {-1, 0}, {0, 0}, {1, 0}, {2, 0}, + {-2, 1}, {-1, 1}, {0, 1}, {1, 1}, {2, 1}, + {-2, 2}, {-1, 2}, {0, 2}, {1, 2}, {2, 2} +}; + +// Rendering Colors +const Color STONE_GRAY = (Color){80, 80, 80, 255}; +const Color PUFF_RED = (Color){187, 0, 0, 255}; +const Color PUFF_CYAN = (Color){0, 187, 187, 255}; +const Color PUFF_WHITE = (Color){241, 241, 241, 241}; +const Color PUFF_BACKGROUND = (Color){6, 24, 24, 255}; +const Color PUFF_BACKGROUND2 = (Color){18, 72, 72, 255}; +const Color ROAD_COLOR = (Color){35, 35, 37, 255}; + +// Forward declarations +typedef struct Drive Drive; +typedef struct Client Client; +typedef struct Log Log; +typedef struct Entity Entity; + +struct Log { + float episode_return; + float episode_length; + float perf; + float score; + float offroad_rate; + float collision_rate; + float clean_collision_rate; + float completion_rate; + float dnf_rate; + float n; +}; + +struct Entity { + int type; + int array_size; + float* traj_x; + float* traj_y; + float* traj_z; + float* traj_vx; + float* traj_vy; + float* traj_vz; + float* traj_heading; + int* traj_valid; + float width; + float length; + float height; + float goal_position_x; + float goal_position_y; + float goal_position_z; + int mark_as_expert; + int collision_state; + float x; + float y; + float z; + float vx; + float vy; + float vz; + float heading; + float heading_x; + float heading_y; + int valid; + int reached_goal; + int respawn_timestep; + int collided_before_goal; + int reached_goal_this_episode; + int active_agent; +}; + +void free_entity(Entity* entity) { + free(entity->traj_x); + free(entity->traj_y); + free(entity->traj_z); + free(entity->traj_vx); + free(entity->traj_vy); + free(entity->traj_vz); + free(entity->traj_heading); + free(entity->traj_valid); +} + +// Utility +float relative_distance_2d(float x1, float y1, float x2, float y2) { + float dx = x2 - x1; + float dy = y2 - y1; + return sqrtf(dx * dx + dy * dy); +} + +float clipSpeed(float speed) { + if (speed > MAX_SPEED) return MAX_SPEED; + if (speed < -MAX_SPEED) return -MAX_SPEED; + return speed; +} + +float normalize_heading(float heading) { + if (heading > M_PI) heading -= 2 * M_PI; + if (heading < -M_PI) heading += 2 * M_PI; + return heading; +} + +struct Drive { + Client* client; + float* observations; + float* actions; + float* rewards; + float* terminals; + Log log; + Log* logs; + int num_agents; + int max_agents; + int active_agent_count; + int* active_agent_indices; + int human_agent_idx; + Entity* entities; + int num_entities; + int num_actors; // Total agents (active + static) + int num_objects; + int num_roads; + int static_agent_count; + int* static_agent_indices; + int expert_static_agent_count; + int* expert_static_agent_indices; + int timestep; + int dynamics_model; + float* map_corners; + int* grid_cells; + int grid_cols; + int grid_rows; + int vision_range; + int* neighbor_offsets; + int* neighbor_cache_entities; + int* neighbor_cache_indices; + float reward_vehicle_collision; + float reward_offroad_collision; + char* map_name; + float world_mean_x; + float world_mean_y; + float reward_goal_post_respawn; + float reward_vehicle_collision_post_respawn; + unsigned int rng; +}; + +void add_log(Drive* env) { + for (int i = 0; i < env->active_agent_count; i++) { + Entity* e = &env->entities[env->active_agent_indices[i]]; + if (e->reached_goal_this_episode) { + env->log.completion_rate += 1.0f; + } + int offroad = env->logs[i].offroad_rate; + env->log.offroad_rate += env->logs[i].offroad_rate; + int collided = env->logs[i].collision_rate; + env->log.collision_rate += collided; + int clean_collided = env->logs[i].clean_collision_rate; + env->log.clean_collision_rate += clean_collided; + if (e->reached_goal_this_episode && !e->collided_before_goal) { + env->log.score += 1.0f; + env->log.perf += 1.0f; + } + if (!offroad && !collided && !e->reached_goal_this_episode) { + env->log.dnf_rate += 1.0f; + } + env->log.episode_length += env->logs[i].episode_length; + env->log.episode_return += env->logs[i].episode_return; + env->log.n += 1; + } +} + +// Map loading +Entity* load_map_binary(const char* filename, Drive* env) { + FILE* file = fopen(filename, "rb"); + if (!file) return NULL; + + fread(&env->num_objects, sizeof(int), 1, file); + fread(&env->num_roads, sizeof(int), 1, file); + env->num_entities = env->num_objects + env->num_roads; + + Entity* entities = (Entity*)malloc(env->num_entities * sizeof(Entity)); + for (int i = 0; i < env->num_entities; i++) { + // Read base entity data + fread(&entities[i].type, sizeof(int), 1, file); + fread(&entities[i].array_size, sizeof(int), 1, file); + // Allocate arrays based on type + int size = entities[i].array_size; + entities[i].traj_x = (float*)malloc(size * sizeof(float)); + entities[i].traj_y = (float*)malloc(size * sizeof(float)); + entities[i].traj_z = (float*)malloc(size * sizeof(float)); + + int is_actor = (entities[i].type == VEHICLE || + entities[i].type == PEDESTRIAN || + entities[i].type == CYCLIST); + if (is_actor) { + // Allocate arrays for object-specific data + entities[i].traj_vx = (float*)malloc(size * sizeof(float)); + entities[i].traj_vy = (float*)malloc(size * sizeof(float)); + entities[i].traj_vz = (float*)malloc(size * sizeof(float)); + entities[i].traj_heading = (float*)malloc(size * sizeof(float)); + entities[i].traj_valid = (int*)malloc(size * sizeof(int)); + } else { + // Roads don't use these arrays + entities[i].traj_vx = NULL; + entities[i].traj_vy = NULL; + entities[i].traj_vz = NULL; + entities[i].traj_heading = NULL; + entities[i].traj_valid = NULL; + } + // Read array data + fread(entities[i].traj_x, sizeof(float), size, file); + fread(entities[i].traj_y, sizeof(float), size, file); + fread(entities[i].traj_z, sizeof(float), size, file); + if (is_actor) { + fread(entities[i].traj_vx, sizeof(float), size, file); + fread(entities[i].traj_vy, sizeof(float), size, file); + fread(entities[i].traj_vz, sizeof(float), size, file); + fread(entities[i].traj_heading, sizeof(float), size, file); + fread(entities[i].traj_valid, sizeof(int), size, file); + } + // Read remaining scalar fields + fread(&entities[i].width, sizeof(float), 1, file); + fread(&entities[i].length, sizeof(float), 1, file); + fread(&entities[i].height, sizeof(float), 1, file); + fread(&entities[i].goal_position_x, sizeof(float), 1, file); + fread(&entities[i].goal_position_y, sizeof(float), 1, file); + fread(&entities[i].goal_position_z, sizeof(float), 1, file); + fread(&entities[i].mark_as_expert, sizeof(int), 1, file); + } + fclose(file); + return entities; +} + +// Position initialization +void set_start_position(Drive* env) { + for (int i = 0; i < env->num_entities; i++) { + int is_active = 0; + for (int j = 0; j < env->active_agent_count; j++) { + if (env->active_agent_indices[j] == i) { + is_active = 1; + break; + } + } + Entity* e = &env->entities[i]; + e->x = e->traj_x[0]; + e->y = e->traj_y[0]; + e->z = e->traj_z[0]; + + if (e->type > CYCLIST || e->type == NONE) { + continue; + } + if (!is_active) { + e->vx = 0; + e->vy = 0; + e->vz = 0; + e->reached_goal = 0; + e->collided_before_goal = 0; + } else { + e->vx = e->traj_vx[0]; + e->vy = e->traj_vy[0]; + e->vz = e->traj_vz[0]; + } + e->heading = e->traj_heading[0]; + e->heading_x = cosf(e->heading); + e->heading_y = sinf(e->heading); + e->valid = e->traj_valid[0]; + e->collision_state = NO_COLLISION; + e->respawn_timestep = -1; + } +} + +// Grid Map +int getGridIndex(Drive* env, float x1, float y1) { + if (env->map_corners[0] >= env->map_corners[2] || + env->map_corners[1] >= env->map_corners[3]) { + return -1; + } + float relativeX = x1 - env->map_corners[0]; + float relativeY = y1 - env->map_corners[1]; + int gridX = (int)(relativeX / GRID_CELL_SIZE); + int gridY = (int)(relativeY / GRID_CELL_SIZE); + if (gridX < 0 || gridX >= env->grid_cols || gridY < 0 || gridY >= env->grid_rows) { + return -1; + } + return (gridY * env->grid_cols) + gridX; +} + +void add_entity_to_grid(Drive* env, int grid_index, int entity_idx, int geometry_idx) { + if (grid_index == -1) return; + + int base_index = grid_index * SLOTS_PER_CELL; + int count = env->grid_cells[base_index]; + if (count >= MAX_ENTITIES_PER_CELL) return; + + env->grid_cells[base_index + count * 2 + 1] = entity_idx; + env->grid_cells[base_index + count * 2 + 2] = geometry_idx; + env->grid_cells[base_index] = count + 1; +} + +void init_grid_map(Drive* env) { + float top_left_x, top_left_y, bottom_right_x, bottom_right_y; + int first_valid_point = 0; + + for (int i = 0; i < env->num_entities; i++) { + if (env->entities[i].type >= ROAD_LANE && env->entities[i].type <= ROAD_EDGE) { + Entity* e = &env->entities[i]; + for (int j = 0; j < e->array_size; j++) { + if (e->traj_x[j] == INVALID_POSITION) continue; + if (e->traj_y[j] == INVALID_POSITION) continue; + if (!first_valid_point) { + top_left_x = bottom_right_x = e->traj_x[j]; + top_left_y = bottom_right_y = e->traj_y[j]; + first_valid_point = 1; + continue; + } + if (e->traj_x[j] < top_left_x) top_left_x = e->traj_x[j]; + if (e->traj_x[j] > bottom_right_x) bottom_right_x = e->traj_x[j]; + if (e->traj_y[j] < top_left_y) top_left_y = e->traj_y[j]; + if (e->traj_y[j] > bottom_right_y) bottom_right_y = e->traj_y[j]; + } + } + } + + env->map_corners = (float*)calloc(4, sizeof(float)); + env->map_corners[0] = top_left_x; + env->map_corners[1] = top_left_y; + env->map_corners[2] = bottom_right_x; + env->map_corners[3] = bottom_right_y; + + float grid_width = bottom_right_x - top_left_x; + float grid_height = bottom_right_y - top_left_y; + env->grid_cols = ceil(grid_width / GRID_CELL_SIZE); + env->grid_rows = ceil(grid_height / GRID_CELL_SIZE); + int grid_cell_count = env->grid_cols * env->grid_rows; + env->grid_cells = (int*)calloc(grid_cell_count * SLOTS_PER_CELL, sizeof(int)); + + for (int i = 0; i < env->num_entities; i++) { + if (env->entities[i].type >= ROAD_LANE && env->entities[i].type <= ROAD_EDGE) { + for (int j = 0; j < env->entities[i].array_size - 1; j++) { + float x_center = (env->entities[i].traj_x[j] + env->entities[i].traj_x[j + 1]) / 2; + float y_center = (env->entities[i].traj_y[j] + env->entities[i].traj_y[j + 1]) / 2; + int grid_index = getGridIndex(env, x_center, y_center); + add_entity_to_grid(env, grid_index, i, j); + } + } + } +} + +void init_neighbor_offsets(Drive* env) { + int vr = env->vision_range; + env->neighbor_offsets = (int*)calloc(vr * vr * 2, sizeof(int)); + + int dx[] = {1, 0, -1, 0}; + int dy[] = {0, 1, 0, -1}; + int x = 0, y = 0, dir = 0; + int steps_to_take = 1, steps_taken = 0, segments_completed = 0; + int total = 0, max_offsets = vr * vr; + int curr_idx = 0; + + env->neighbor_offsets[curr_idx++] = 0; + env->neighbor_offsets[curr_idx++] = 0; + total++; + + while (total < max_offsets) { + x += dx[dir]; + y += dy[dir]; + if (abs(x) <= vr / 2 && abs(y) <= vr / 2) { + env->neighbor_offsets[curr_idx++] = x; + env->neighbor_offsets[curr_idx++] = y; + total++; + } + steps_taken++; + if (steps_taken != steps_to_take) continue; + steps_taken = 0; + dir = (dir + 1) % 4; + segments_completed++; + if (segments_completed % 2 == 0) { + steps_to_take++; + } + } +} + +void cache_neighbor_offsets(Drive* env) { + int vr = env->vision_range; + int count = 0; + int cell_count = env->grid_cols * env->grid_rows; + + for (int i = 0; i < cell_count; i++) { + int cell_x = i % env->grid_cols; + int cell_y = i / env->grid_cols; + env->neighbor_cache_indices[i] = count; + for (int j = 0; j < vr * vr; j++) { + int x = cell_x + env->neighbor_offsets[j * 2]; + int y = cell_y + env->neighbor_offsets[j * 2 + 1]; + if (x < 0 || x >= env->grid_cols || y < 0 || y >= env->grid_rows) continue; + int grid_index = env->grid_cols * y + x; + count += env->grid_cells[grid_index * SLOTS_PER_CELL] * 2; + } + } + env->neighbor_cache_indices[cell_count] = count; + env->neighbor_cache_entities = (int*)calloc(count, sizeof(int)); + + for (int i = 0; i < cell_count; i++) { + int neighbor_cache_base_index = 0; + int cell_x = i % env->grid_cols; + int cell_y = i / env->grid_cols; + for (int j = 0; j < vr * vr; j++) { + int x = cell_x + env->neighbor_offsets[j * 2]; + int y = cell_y + env->neighbor_offsets[j * 2 + 1]; + if (x < 0 || x >= env->grid_cols || y < 0 || y >= env->grid_rows) continue; + int grid_index = env->grid_cols * y + x; + int grid_count = env->grid_cells[grid_index * SLOTS_PER_CELL]; + int base_index = env->neighbor_cache_indices[i]; + int src_idx = grid_index * SLOTS_PER_CELL + 1; + int dst_idx = base_index + neighbor_cache_base_index; + memcpy(&env->neighbor_cache_entities[dst_idx], + &env->grid_cells[src_idx], + grid_count * 2 * sizeof(int)); + neighbor_cache_base_index += grid_count * 2; + } + } +} + +int get_neighbor_cache_entities(Drive* env, int cell_idx, int* entities, int max_entities) { + if (cell_idx < 0 || cell_idx >= (env->grid_cols * env->grid_rows)) { + return 0; + } + int base_index = env->neighbor_cache_indices[cell_idx]; + int end_index = env->neighbor_cache_indices[cell_idx + 1]; + int count = end_index - base_index; + int pairs = count / 2; + if (pairs > max_entities) { + pairs = max_entities; + count = pairs * 2; + } + memcpy(entities, env->neighbor_cache_entities + base_index, count * sizeof(int)); + return pairs; +} + +// Mean Centering +void set_means(Drive* env) { + float mean_x = 0.0f; + float mean_y = 0.0f; + int64_t point_count = 0; + + for (int i = 0; i < env->num_entities; i++) { + if (env->entities[i].type == VEHICLE) { + for (int j = 0; j < env->entities[i].array_size; j++) { + if (env->entities[i].traj_valid[j]) { + point_count++; + mean_x += (env->entities[i].traj_x[j] - mean_x) / point_count; + mean_y += (env->entities[i].traj_y[j] - mean_y) / point_count; + } + } + } else if (env->entities[i].type >= ROAD_LANE) { + for (int j = 0; j < env->entities[i].array_size; j++) { + point_count++; + mean_x += (env->entities[i].traj_x[j] - mean_x) / point_count; + mean_y += (env->entities[i].traj_y[j] - mean_y) / point_count; + } + } + } + env->world_mean_x = mean_x; + env->world_mean_y = mean_y; + + for (int i = 0; i < env->num_entities; i++) { + if (env->entities[i].type == VEHICLE || env->entities[i].type >= ROAD_LANE) { + for (int j = 0; j < env->entities[i].array_size; j++) { + if (env->entities[i].traj_x[j] == INVALID_POSITION) continue; + env->entities[i].traj_x[j] -= mean_x; + env->entities[i].traj_y[j] -= mean_y; + } + env->entities[i].goal_position_x -= mean_x; + env->entities[i].goal_position_y -= mean_y; + } + } +} + +// Expert Movement +void move_expert(Drive* env, float* actions, int agent_idx) { + Entity* agent = &env->entities[agent_idx]; + int t = env->timestep; + if (t < 0 || t >= agent->array_size) { + agent->x = INVALID_POSITION; + agent->y = INVALID_POSITION; + return; + } + agent->x = agent->traj_x[t]; + agent->y = agent->traj_y[t]; + agent->z = agent->traj_z[t]; + agent->heading = agent->traj_heading[t]; + agent->heading_x = cosf(agent->heading); + agent->heading_y = sinf(agent->heading); +} + +// Collision Detection +bool check_line_intersection(float p1[2], float p2[2], float q1[2], float q2[2]) { + if (fmax(p1[0], p2[0]) < fmin(q1[0], q2[0]) || fmin(p1[0], p2[0]) > fmax(q1[0], q2[0]) || + fmax(p1[1], p2[1]) < fmin(q1[1], q2[1]) || fmin(p1[1], p2[1]) > fmax(q1[1], q2[1])) + return false; + + float dx1 = p2[0] - p1[0]; + float dy1 = p2[1] - p1[1]; + float dx2 = q2[0] - q1[0]; + float dy2 = q2[1] - q1[1]; + float cross = dx1 * dy2 - dy1 * dx2; + if (cross == 0) return false; + + float dx3 = p1[0] - q1[0]; + float dy3 = p1[1] - q1[1]; + float s = (dx1 * dy3 - dy1 * dx3) / cross; + float t = (dx2 * dy3 - dy2 * dx3) / cross; + return (s >= 0 && s <= 1 && t >= 0 && t <= 1); +} + +int checkNeighbors(Drive* env, float x, float y, int* entity_list, int max_size, + const int (*local_offsets)[2], int offset_size) { + int index = getGridIndex(env, x, y); + if (index == -1) return 0; + int cellsX = env->grid_cols; + int gridX = index % cellsX; + int gridY = index / cellsX; + int entity_list_count = 0; + + for (int i = 0; i < offset_size; i++) { + int nx = gridX + local_offsets[i][0]; + int ny = gridY + local_offsets[i][1]; + if (nx < 0 || nx >= env->grid_cols || ny < 0 || ny >= env->grid_rows) continue; + int neighborIndex = (ny * env->grid_cols + nx) * SLOTS_PER_CELL; + int count = env->grid_cells[neighborIndex]; + for (int j = 0; j < count && entity_list_count < max_size; j++) { + entity_list[entity_list_count] = env->grid_cells[neighborIndex + 1 + j * 2]; + entity_list[entity_list_count + 1] = env->grid_cells[neighborIndex + 2 + j * 2]; + entity_list_count += 2; + } + } + return entity_list_count; +} + +int check_aabb_collision(Entity* car1, Entity* car2) { + float cos1 = car1->heading_x, sin1 = car1->heading_y; + float cos2 = car2->heading_x, sin2 = car2->heading_y; + float hl1 = car1->length * 0.5f, hw1 = car1->width * 0.5f; + float hl2 = car2->length * 0.5f, hw2 = car2->width * 0.5f; + + float car1_corners[4][2] = { + {car1->x + (hl1 * cos1 - hw1 * sin1), car1->y + (hl1 * sin1 + hw1 * cos1)}, + {car1->x + (hl1 * cos1 + hw1 * sin1), car1->y + (hl1 * sin1 - hw1 * cos1)}, + {car1->x + (-hl1 * cos1 - hw1 * sin1), car1->y + (-hl1 * sin1 + hw1 * cos1)}, + {car1->x + (-hl1 * cos1 + hw1 * sin1), car1->y + (-hl1 * sin1 - hw1 * cos1)} + }; + + float car2_corners[4][2] = { + {car2->x + (hl2 * cos2 - hw2 * sin2), car2->y + (hl2 * sin2 + hw2 * cos2)}, + {car2->x + (hl2 * cos2 + hw2 * sin2), car2->y + (hl2 * sin2 - hw2 * cos2)}, + {car2->x + (-hl2 * cos2 - hw2 * sin2), car2->y + (-hl2 * sin2 + hw2 * cos2)}, + {car2->x + (-hl2 * cos2 + hw2 * sin2), car2->y + (-hl2 * sin2 - hw2 * cos2)} + }; + + float axes[4][2] = { + {cos1, sin1}, {-sin1, cos1}, + {cos2, sin2}, {-sin2, cos2} + }; + + for (int i = 0; i < 4; i++) { + float min1 = INFINITY, max1 = -INFINITY; + float min2 = INFINITY, max2 = -INFINITY; + for (int j = 0; j < 4; j++) { + float proj1 = car1_corners[j][0] * axes[i][0] + car1_corners[j][1] * axes[i][1]; + min1 = fminf(min1, proj1); + max1 = fmaxf(max1, proj1); + float proj2 = car2_corners[j][0] * axes[i][0] + car2_corners[j][1] * axes[i][1]; + min2 = fminf(min2, proj2); + max2 = fmaxf(max2, proj2); + } + if (max1 < min2 || min1 > max2) return 0; + } + return 1; +} + +int collision_check(Drive* env, int agent_idx) { + Entity* agent = &env->entities[agent_idx]; + if (agent->x == INVALID_POSITION) return -1; + + float half_length = agent->length / 2.0f; + float half_width = agent->width / 2.0f; + float cos_heading = cosf(agent->heading); + float sin_heading = sinf(agent->heading); + float corners[4][2]; + for (int i = 0; i < 4; i++) { + corners[i][0] = agent->x + (offsets[i][0] * half_length * cos_heading - offsets[i][1] * half_width * sin_heading); + corners[i][1] = agent->y + (offsets[i][0] * half_length * sin_heading + offsets[i][1] * half_width * cos_heading); + } + + int collided = NO_COLLISION; + int car_collided_with_index = -1; + + // Check road edge collisions via grid + int entity_list[MAX_ENTITIES_PER_CELL * 2 * 25]; + int list_size = checkNeighbors(env, agent->x, agent->y, entity_list, + MAX_ENTITIES_PER_CELL * 2 * 25, collision_offsets, 25); + for (int i = 0; i < list_size; i += 2) { + if (entity_list[i] == -1 || entity_list[i] == agent_idx) continue; + Entity* entity = &env->entities[entity_list[i]]; + if (entity->type != ROAD_EDGE) continue; + int geometry_idx = entity_list[i + 1]; + float start[2] = {entity->traj_x[geometry_idx], entity->traj_y[geometry_idx]}; + float end[2] = {entity->traj_x[geometry_idx + 1], entity->traj_y[geometry_idx + 1]}; + for (int k = 0; k < 4; k++) { + int next = (k + 1) % 4; + if (check_line_intersection(corners[k], corners[next], start, end)) { + collided = OFFROAD; + break; + } + } + if (collided == OFFROAD) break; + } + + // Check vehicle-vehicle collisions + for (int i = 0; i < MAX_AGENTS; i++) { + int index = -1; + if (i < env->active_agent_count) { + index = env->active_agent_indices[i]; + } else if (i < env->num_actors) { + index = env->static_agent_indices[i - env->active_agent_count]; + } + if (index == -1 || index == agent_idx) continue; + Entity* entity = &env->entities[index]; + float dx = entity->x - agent->x; + float dy = entity->y - agent->y; + if ((dx * dx + dy * dy) > COLLISION_DIST_SQ) continue; + if (check_aabb_collision(agent, entity)) { + collided = VEHICLE_COLLISION; + car_collided_with_index = index; + break; + } + } + + agent->collision_state = collided; + + // Spawn immunity: agent just respawned + if (collided == VEHICLE_COLLISION && agent->active_agent == 1 && + agent->respawn_timestep != -1) { + agent->collision_state = NO_COLLISION; + } + + if (collided == OFFROAD) return -1; + if (car_collided_with_index == -1) return -1; + + // Spawn immunity: collided-with agent just respawned + if (env->entities[car_collided_with_index].respawn_timestep != -1) { + agent->collision_state = NO_COLLISION; + } + + return car_collided_with_index; +} + +// Agent Selection +int valid_active_agent(Drive* env, int agent_idx) { + if (agent_idx < 0 || agent_idx >= env->num_entities) return 0; + Entity* e = &env->entities[agent_idx]; + if (e->type != VEHICLE || e->traj_valid[0] != 1) return 0; + float cos_heading = cosf(e->traj_heading[0]); + float sin_heading = sinf(e->traj_heading[0]); + float goal_x = e->goal_position_x - e->traj_x[0]; + float goal_y = e->goal_position_y - e->traj_y[0]; + float rel_goal_x = goal_x * cos_heading + goal_y * sin_heading; + float rel_goal_y = -goal_x * sin_heading + goal_y * cos_heading; + float distance_to_goal = relative_distance_2d(0, 0, rel_goal_x, rel_goal_y); + + e->width *= COLLISION_BOX_SCALE; + e->length *= COLLISION_BOX_SCALE; + + if (distance_to_goal >= MIN_DISTANCE_TO_GOAL && + e->mark_as_expert == 0 && + env->active_agent_count < env->max_agents) { + return distance_to_goal; + } + return 0; +} + +void set_active_agents(Drive* env) { + env->active_agent_count = 0; + env->static_agent_count = 0; + env->num_actors = 1; + env->expert_static_agent_count = 0; + + int active_agent_indices[MAX_AGENTS]; + int static_agent_indices[MAX_AGENTS]; + int expert_static_agent_indices[MAX_AGENTS]; + + if (env->max_agents == 0) { + env->max_agents = MAX_AGENTS; + } + + // First agent: last object (SDC equivalent) + int first_agent_id = env->num_objects - 1; + float distance_to_goal = valid_active_agent(env, first_agent_id); + if (distance_to_goal) { + env->active_agent_count = 1; + active_agent_indices[0] = first_agent_id; + env->entities[first_agent_id].active_agent = 1; + env->num_actors = 1; + } else { + env->active_agent_count = 0; + env->num_actors = 0; + } + + for (int i = 0; i < env->num_objects - 1 && env->num_actors < MAX_AGENTS; i++) { + if (env->entities[i].type != VEHICLE) continue; + if (env->entities[i].traj_valid[0] != 1) continue; + env->num_actors++; + + float dist = valid_active_agent(env, i); + if (dist > 0) { + active_agent_indices[env->active_agent_count] = i; + env->active_agent_count++; + env->entities[i].active_agent = 1; + } else { + static_agent_indices[env->static_agent_count] = i; + env->static_agent_count++; + env->entities[i].active_agent = 0; + if (env->entities[i].mark_as_expert == 1 || + (dist >= MIN_DISTANCE_TO_GOAL && env->active_agent_count == env->max_agents)) { + expert_static_agent_indices[env->expert_static_agent_count] = i; + env->expert_static_agent_count++; + env->entities[i].mark_as_expert = 1; + } + } + } + + env->active_agent_indices = (int*)malloc(env->active_agent_count * sizeof(int)); + env->static_agent_indices = (int*)malloc(env->static_agent_count * sizeof(int)); + env->expert_static_agent_indices = (int*)malloc(env->expert_static_agent_count * sizeof(int)); + memcpy(env->active_agent_indices, active_agent_indices, env->active_agent_count * sizeof(int)); + memcpy(env->static_agent_indices, static_agent_indices, env->static_agent_count * sizeof(int)); + memcpy(env->expert_static_agent_indices, expert_static_agent_indices, env->expert_static_agent_count * sizeof(int)); +} + +// Trajectory Validation +void remove_bad_trajectories(Drive* env) { + set_start_position(env); + int collided_agents[env->active_agent_count]; + int collided_with_indices[env->active_agent_count]; + memset(collided_agents, 0, env->active_agent_count * sizeof(int)); + + for (int t = 0; t < TRAJECTORY_LENGTH; t++) { + for (int i = 0; i < env->active_agent_count; i++) { + move_expert(env, env->actions, env->active_agent_indices[i]); + } + for (int i = 0; i < env->expert_static_agent_count; i++) { + int expert_idx = env->expert_static_agent_indices[i]; + if (env->entities[expert_idx].x == INVALID_POSITION) continue; + move_expert(env, env->actions, expert_idx); + } + for (int i = 0; i < env->active_agent_count; i++) { + int agent_idx = env->active_agent_indices[i]; + env->entities[agent_idx].collision_state = NO_COLLISION; + int collided_with = collision_check(env, agent_idx); + if (env->entities[agent_idx].collision_state > NO_COLLISION && collided_agents[i] == 0) { + collided_agents[i] = 1; + collided_with_indices[i] = collided_with; + } + } + env->timestep++; + } + + for (int i = 0; i < env->active_agent_count; i++) { + if (collided_with_indices[i] == -1) continue; + for (int j = 0; j < env->static_agent_count; j++) { + int static_idx = env->static_agent_indices[j]; + if (static_idx != collided_with_indices[i]) continue; + env->entities[static_idx].traj_x[0] = INVALID_POSITION; + env->entities[static_idx].traj_y[0] = INVALID_POSITION; + } + } + env->timestep = 0; +} + +// Initialization / Cleanup +void init(Drive* env) { + env->human_agent_idx = 0; + env->timestep = 0; + env->entities = load_map_binary(env->map_name, env); + env->dynamics_model = CLASSIC; + set_means(env); + init_grid_map(env); + env->vision_range = VISION_RANGE; + init_neighbor_offsets(env); + env->neighbor_cache_indices = (int*)calloc((env->grid_cols * env->grid_rows) + 1, sizeof(int)); + cache_neighbor_offsets(env); + set_active_agents(env); + remove_bad_trajectories(env); + set_start_position(env); + env->logs = (Log*)calloc(env->active_agent_count, sizeof(Log)); +} + +void c_close(Drive* env) { + for (int i = 0; i < env->num_entities; i++) { + free_entity(&env->entities[i]); + } + free(env->entities); + free(env->active_agent_indices); + free(env->logs); + free(env->map_corners); + free(env->grid_cells); + free(env->neighbor_offsets); + free(env->neighbor_cache_entities); + free(env->neighbor_cache_indices); + free(env->static_agent_indices); + free(env->expert_static_agent_indices); +} + +void allocate(Drive* env) { + init(env); + env->observations = (float*)calloc(env->active_agent_count * OBS_SIZE, sizeof(float)); + env->actions = (float*)calloc(env->active_agent_count * 2, sizeof(float)); + env->rewards = (float*)calloc(env->active_agent_count, sizeof(float)); + env->terminals = (float*)calloc(env->active_agent_count, sizeof(float)); +} + +void free_allocated(Drive* env) { + free(env->observations); + free(env->actions); + free(env->rewards); + free(env->terminals); + c_close(env); +} + +// Dynamics +void move_dynamics(Drive* env, int action_idx, int agent_idx) { + if (env->dynamics_model != CLASSIC) return; + + Entity* agent = &env->entities[agent_idx]; + float (*action_array)[2] = (float(*)[2])env->actions; + int acceleration_index = action_array[action_idx][0]; + int steering_index = action_array[action_idx][1]; + float acceleration = ACCELERATION_VALUES[acceleration_index]; + float steering = STEERING_VALUES[steering_index]; + + float x = agent->x; + float y = agent->y; + float heading = agent->heading; + float speed = sqrtf(agent->vx * agent->vx + agent->vy * agent->vy); + + speed = speed + 0.5f * acceleration * SIM_DT; + speed = clipSpeed(speed); + + float beta = tanh(0.5 * tanf(steering)); + float yaw_rate = (speed * cosf(beta) * tanf(steering)) / agent->length; + float new_vx = speed * cosf(heading + beta); + float new_vy = speed * sinf(heading + beta); + + x += new_vx * SIM_DT; + y += new_vy * SIM_DT; + heading += yaw_rate * SIM_DT; + + agent->x = x; + agent->y = y; + agent->heading = heading; + agent->heading_x = cosf(heading); + agent->heading_y = sinf(heading); + agent->vx = new_vx; + agent->vy = new_vy; +} + +// Observations +void compute_observations(Drive* env) { + memset(env->observations, 0, OBS_SIZE * env->active_agent_count * sizeof(float)); + float (*observations)[OBS_SIZE] = (float(*)[OBS_SIZE])env->observations; + + for (int i = 0; i < env->active_agent_count; i++) { + float* obs = &observations[i][0]; + Entity* ego = &env->entities[env->active_agent_indices[i]]; + if (ego->type > CYCLIST) break; + + if (ego->respawn_timestep != -1) { + obs[6] = 1; + } + + float cos_h = ego->heading_x; + float sin_h = ego->heading_y; + float ego_speed = sqrtf(ego->vx * ego->vx + ego->vy * ego->vy); + + // Goal in ego frame + float goal_x = ego->goal_position_x - ego->x; + float goal_y = ego->goal_position_y - ego->y; + float rel_goal_x = goal_x * cos_h + goal_y * sin_h; + float rel_goal_y = -goal_x * sin_h + goal_y * cos_h; + + // Ego features + obs[0] = rel_goal_x * OBS_GOAL_SCALE; + obs[1] = rel_goal_y * OBS_GOAL_SCALE; + obs[2] = ego_speed * OBS_SPEED_SCALE; + obs[3] = ego->width / MAX_VEH_WIDTH; + obs[4] = ego->length / MAX_VEH_LEN; + obs[5] = (ego->collision_state > NO_COLLISION) ? 1 : 0; + + // Partner observations + int obs_idx = EGO_FEATURES; + int cars_seen = 0; + for (int j = 0; j < MAX_AGENTS; j++) { + int index = -1; + if (j < env->active_agent_count) { + index = env->active_agent_indices[j]; + } else if (j < env->num_actors) { + index = env->static_agent_indices[j - env->active_agent_count]; + } + if (index == -1) continue; + if (env->entities[index].type > CYCLIST) break; + if (index == env->active_agent_indices[i]) continue; + + Entity* other = &env->entities[index]; + if (ego->respawn_timestep != -1) continue; + if (other->respawn_timestep != -1) continue; + + float dx = other->x - ego->x; + float dy = other->y - ego->y; + if ((dx * dx + dy * dy) > OBS_DIST_SQ) continue; + + float rel_x = dx * cos_h + dy * sin_h; + float rel_y = -dx * sin_h + dy * cos_h; + + obs[obs_idx + 0] = rel_x * OBS_POSITION_SCALE; + obs[obs_idx + 1] = rel_y * OBS_POSITION_SCALE; + obs[obs_idx + 2] = other->width / MAX_VEH_WIDTH; + obs[obs_idx + 3] = other->length / MAX_VEH_LEN; + obs[obs_idx + 4] = other->heading_x * ego->heading_x + other->heading_y * ego->heading_y; + obs[obs_idx + 5] = other->heading_y * ego->heading_x - other->heading_x * ego->heading_y; + float other_speed = sqrtf(other->vx * other->vx + other->vy * other->vy); + obs[obs_idx + 6] = other_speed / MAX_SPEED; + cars_seen++; + obs_idx += PARTNER_FEATURES; + } + int remaining_partner_obs = (MAX_AGENTS - 1 - cars_seen) * PARTNER_FEATURES; + memset(&obs[obs_idx], 0, remaining_partner_obs * sizeof(float)); + obs_idx += remaining_partner_obs; + + // Road observations + int entity_list[MAX_ROAD_SEGMENT_OBSERVATIONS * 2]; + int grid_idx = getGridIndex(env, ego->x, ego->y); + int list_size = get_neighbor_cache_entities(env, grid_idx, entity_list, MAX_ROAD_SEGMENT_OBSERVATIONS); + + for (int k = 0; k < list_size; k++) { + int entity_idx = entity_list[k * 2]; + int geometry_idx = entity_list[k * 2 + 1]; + Entity* entity = &env->entities[entity_idx]; + + float start_x = entity->traj_x[geometry_idx]; + float start_y = entity->traj_y[geometry_idx]; + float end_x = entity->traj_x[geometry_idx + 1]; + float end_y = entity->traj_y[geometry_idx + 1]; + float mid_x = (start_x + end_x) / 2.0f; + float mid_y = (start_y + end_y) / 2.0f; + float rel_x = mid_x - ego->x; + float rel_y = mid_y - ego->y; + float x_obs = rel_x * cos_h + rel_y * sin_h; + float y_obs = -rel_x * sin_h + rel_y * cos_h; + float length = relative_distance_2d(mid_x, mid_y, end_x, end_y); + + float dx = end_x - mid_x; + float dy = end_y - mid_y; + float hypot = sqrtf(dx * dx + dy * dy); + float dx_norm = dx, dy_norm = dy; + if (hypot > 0) { dx_norm /= hypot; dy_norm /= hypot; } + + float cos_angle = dx_norm * cos_h + dy_norm * sin_h; + float sin_angle = -dx_norm * sin_h + dy_norm * cos_h; + + obs[obs_idx + 0] = x_obs * OBS_POSITION_SCALE; + obs[obs_idx + 1] = y_obs * OBS_POSITION_SCALE; + obs[obs_idx + 2] = length / MAX_ROAD_SEGMENT_LENGTH; + obs[obs_idx + 3] = 0.1f / MAX_ROAD_SCALE; + obs[obs_idx + 4] = cos_angle; + obs[obs_idx + 5] = sin_angle; + obs[obs_idx + 6] = entity->type - (float)ROAD_LANE; + obs_idx += ROAD_FEATURES; + } + int remaining_obs = (MAX_ROAD_SEGMENT_OBSERVATIONS - list_size) * ROAD_FEATURES; + memset(&obs[obs_idx], 0, remaining_obs * sizeof(float)); + } +} + +void c_reset(Drive* env) { + env->timestep = 0; + set_start_position(env); + for (int x = 0; x < env->active_agent_count; x++) { + env->logs[x] = (Log){0}; + int agent_idx = env->active_agent_indices[x]; + env->entities[agent_idx].respawn_timestep = -1; + env->entities[agent_idx].reached_goal = 0; + env->entities[agent_idx].collided_before_goal = 0; + env->entities[agent_idx].reached_goal_this_episode = 0; + + collision_check(env, agent_idx); + } + compute_observations(env); +} + +void respawn_agent(Drive* env, int agent_idx) { + Entity* e = &env->entities[agent_idx]; + e->x = e->traj_x[0]; + e->y = e->traj_y[0]; + e->heading = e->traj_heading[0]; + e->heading_x = cosf(e->heading); + e->heading_y = sinf(e->heading); + e->vx = e->traj_vx[0]; + e->vy = e->traj_vy[0]; + e->reached_goal = 0; + e->respawn_timestep = env->timestep; +} + +void c_step(Drive* env) { + memset(env->rewards, 0, env->active_agent_count * sizeof(float)); + memset(env->terminals, 0, env->active_agent_count * sizeof(float)); + env->timestep++; + + if (env->timestep == TRAJECTORY_LENGTH) { + add_log(env); + c_reset(env); + return; + } + + // Move expert static agents + for (int i = 0; i < env->expert_static_agent_count; i++) { + int expert_idx = env->expert_static_agent_indices[i]; + if (env->entities[expert_idx].x == INVALID_POSITION) continue; + move_expert(env, env->actions, expert_idx); + } + + // Apply dynamics for active agents + for (int i = 0; i < env->active_agent_count; i++) { + env->logs[i].score = 0.0f; + env->logs[i].episode_length += 1; + int agent_idx = env->active_agent_indices[i]; + env->entities[agent_idx].collision_state = NO_COLLISION; + move_dynamics(env, i, agent_idx); + } + + // Collision detection and rewards + for (int i = 0; i < env->active_agent_count; i++) { + int agent_idx = env->active_agent_indices[i]; + env->entities[agent_idx].collision_state = NO_COLLISION; + collision_check(env, agent_idx); + int collision_state = env->entities[agent_idx].collision_state; + + if (collision_state > NO_COLLISION) { + if (collision_state == VEHICLE_COLLISION && env->entities[agent_idx].respawn_timestep == -1) { + env->rewards[i] = env->reward_vehicle_collision; + env->logs[i].episode_return += env->reward_vehicle_collision; + env->logs[i].clean_collision_rate = 1.0f; + env->logs[i].collision_rate = 1.0f; + } else if (collision_state == OFFROAD) { + env->rewards[i] = env->reward_offroad_collision; + env->logs[i].offroad_rate = 1.0f; + env->logs[i].episode_return += env->reward_offroad_collision; + } + if (!env->entities[agent_idx].reached_goal_this_episode) { + env->entities[agent_idx].collided_before_goal = 1; + } + } + + float distance_to_goal = relative_distance_2d( + env->entities[agent_idx].x, env->entities[agent_idx].y, + env->entities[agent_idx].goal_position_x, env->entities[agent_idx].goal_position_y); + + if (distance_to_goal < MIN_DISTANCE_TO_GOAL) { + if (env->entities[agent_idx].respawn_timestep != -1) { + env->rewards[i] += env->reward_goal_post_respawn; + env->logs[i].episode_return += env->reward_goal_post_respawn; + } else { + env->rewards[i] += 1.0f; + env->logs[i].episode_return += 1.0f; + } + env->entities[agent_idx].reached_goal = 1; + env->entities[agent_idx].reached_goal_this_episode = 1; + } + } + + // Respawn agents that reached goal + for (int i = 0; i < env->active_agent_count; i++) { + int agent_idx = env->active_agent_indices[i]; + if (env->entities[agent_idx].reached_goal) { + respawn_agent(env, agent_idx); + } + } + + compute_observations(env); +} + +struct Client { + float width; + float height; + Texture2D puffers; + Vector3 camera_target; + float camera_zoom; + Camera3D camera; + Model cars[6]; + int car_assignments[MAX_AGENTS]; + Vector3 default_camera_position; + Vector3 default_camera_target; +}; + +Client* make_client(Drive* env) { + Client* client = (Client*)calloc(1, sizeof(Client)); + client->width = 1280; + client->height = 704; + SetConfigFlags(FLAG_MSAA_4X_HINT); + InitWindow(client->width, client->height, "PufferLib Ray GPU Drive"); + SetTargetFPS(30); + client->puffers = LoadTexture("resources/puffers_128.png"); + client->cars[0] = LoadModel("resources/drive/RedCar.glb"); + client->cars[1] = LoadModel("resources/drive/WhiteCar.glb"); + client->cars[2] = LoadModel("resources/drive/BlueCar.glb"); + client->cars[3] = LoadModel("resources/drive/YellowCar.glb"); + client->cars[4] = LoadModel("resources/drive/GreenCar.glb"); + client->cars[5] = LoadModel("resources/drive/GreyCar.glb"); + for (int i = 0; i < MAX_AGENTS; i++) { + client->car_assignments[i] = (rand_r(&env->rng) % 4) + 1; + } + // Get initial target position from first active agent + float map_center_x = (env->map_corners[0] + env->map_corners[2]) / 2.0f; + float map_center_y = (env->map_corners[1] + env->map_corners[3]) / 2.0f; + Vector3 target_pos = { + 0, + 0, // Y is up + 1 // Z is depth + }; + + // Set up camera to look at target from above and behind + client->default_camera_position = (Vector3){ + 0, // Same X as target + 120.0f, // 20 units above target + 175.0f // 20 units behind target + }; + client->default_camera_target = target_pos; + client->camera.position = client->default_camera_position; + client->camera.target = client->default_camera_target; + client->camera.up = (Vector3){ 0.0f, -1.0f, 0.0f }; // Y is up + client->camera.fovy = 45.0f; + client->camera.projection = CAMERA_PERSPECTIVE; + client->camera_zoom = 1.0f; + return client; +} + +// Camera control functions +void handle_camera_controls(Client* client) { + static Vector2 prev_mouse_pos = {0}; + static bool is_dragging = false; + float camera_move_speed = 0.5f; + + // Handle mouse drag for camera movement + if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) { + prev_mouse_pos = GetMousePosition(); + is_dragging = true; + } + + if (IsMouseButtonReleased(MOUSE_BUTTON_LEFT)) { + is_dragging = false; + } + + if (is_dragging) { + Vector2 current_mouse_pos = GetMousePosition(); + Vector2 delta = { + (current_mouse_pos.x - prev_mouse_pos.x) * camera_move_speed, + -(current_mouse_pos.y - prev_mouse_pos.y) * camera_move_speed + }; + + // Update camera position (only X and Y) + client->camera.position.x += delta.x; + client->camera.position.y += delta.y; + + // Update camera target (only X and Y) + client->camera.target.x += delta.x; + client->camera.target.y += delta.y; + + prev_mouse_pos = current_mouse_pos; + } + + // Handle mouse wheel for zoom + float wheel = GetMouseWheelMove(); + if (wheel != 0) { + float zoom_factor = 1.0f - (wheel * 0.1f); + // Calculate the current direction vector from target to position + Vector3 direction = { + client->camera.position.x - client->camera.target.x, + client->camera.position.y - client->camera.target.y, + client->camera.position.z - client->camera.target.z + }; + + // Scale the direction vector by the zoom factor + direction.x *= zoom_factor; + direction.y *= zoom_factor; + direction.z *= zoom_factor; + client->camera.position.x = client->camera.target.x + direction.x; + client->camera.position.y = client->camera.target.y + direction.y; + client->camera.position.z = client->camera.target.z + direction.z; + } +} + +void draw_agent_obs(Drive* env, int agent_index) { + float diamond_height = 3.0f; + float diamond_width = 1.5f; + float diamond_z = 8.0f; + + Vector3 top = {0, 0, diamond_z + diamond_height / 2}; + Vector3 bot = {0, 0, diamond_z - diamond_height / 2}; + Vector3 fwd = {0, diamond_width / 2, diamond_z}; + Vector3 bck = {0, -diamond_width / 2, diamond_z}; + Vector3 lft = {-diamond_width / 2, 0, diamond_z}; + Vector3 rgt = {diamond_width / 2, 0, diamond_z}; + + DrawTriangle3D(top, fwd, rgt, PUFF_CYAN); + DrawTriangle3D(top, rgt, bck, PUFF_CYAN); + DrawTriangle3D(top, bck, lft, PUFF_CYAN); + DrawTriangle3D(top, lft, fwd, PUFF_CYAN); + DrawTriangle3D(bot, rgt, fwd, PUFF_CYAN); + DrawTriangle3D(bot, bck, rgt, PUFF_CYAN); + DrawTriangle3D(bot, lft, bck, PUFF_CYAN); + DrawTriangle3D(bot, fwd, lft, PUFF_CYAN); + + if (!IsKeyDown(KEY_LEFT_CONTROL)) return; + + float (*observations)[OBS_SIZE] = (float(*)[OBS_SIZE])env->observations; + float* agent_obs = &observations[agent_index][0]; + + // Draw goal + float goal_x = agent_obs[0] / OBS_GOAL_SCALE; + float goal_y = agent_obs[1] / OBS_GOAL_SCALE; + DrawSphere((Vector3){goal_x, goal_y, 1}, 0.5f, GREEN); + + // Draw partner observations + int obs_idx = EGO_FEATURES; + for (int j = 0; j < MAX_AGENTS - 1; j++) { + if (agent_obs[obs_idx] == 0 || agent_obs[obs_idx + 1] == 0) { + obs_idx += PARTNER_FEATURES; + continue; + } + float x = agent_obs[obs_idx] / OBS_POSITION_SCALE; + float y = agent_obs[obs_idx + 1] / OBS_POSITION_SCALE; + DrawLine3D((Vector3){0, 0, 0}, (Vector3){x, y, 1}, ORANGE); + + float theta_x = agent_obs[obs_idx + 4]; + float theta_y = agent_obs[obs_idx + 5]; + float angle = atan2f(theta_y, theta_x); + // Draw an arrow above the car pointing in the direction that the partner is going + float arrow_length = 7.5f; + + float ax = x + arrow_length * cosf(angle); + float ay = y + arrow_length * sinf(angle); + DrawLine3D((Vector3){x, y, 1}, (Vector3){ax, ay, 1}, PUFF_WHITE); + + float arrow_size = 2.0f; + float dx = ax - x, dy = ay - y; + float len = sqrtf(dx * dx + dy * dy); + if (len > 0) { + dx /= len; dy /= len; + float px = -dy * arrow_size, py = dx * arrow_size; + DrawLine3D((Vector3){ax, ay, 1}, (Vector3){ax - dx * arrow_size + px, ay - dy * arrow_size + py, 1}, PUFF_WHITE); + DrawLine3D((Vector3){ax, ay, 1}, (Vector3){ax - dx * arrow_size - px, ay - dy * arrow_size - py, 1}, PUFF_WHITE); + } + obs_idx += PARTNER_FEATURES; + } + + // Draw road edge observations + int map_start_idx = EGO_FEATURES + PARTNER_FEATURES * (MAX_AGENTS - 1); + for (int k = 0; k < MAX_ROAD_SEGMENT_OBSERVATIONS; k++) { + int idx = map_start_idx + k * ROAD_FEATURES; + if (agent_obs[idx] == 0 && agent_obs[idx + 1] == 0) continue; + int entity_type = (int)agent_obs[idx + 6]; + if (entity_type + ROAD_LANE != ROAD_EDGE) continue; + + float x_mid = agent_obs[idx] / OBS_POSITION_SCALE; + float y_mid = agent_obs[idx + 1] / OBS_POSITION_SCALE; + float rel_angle = atan2f(agent_obs[idx + 5], agent_obs[idx + 4]); + float seg_len = agent_obs[idx + 2] * MAX_ROAD_SEGMENT_LENGTH; + + float x_start = x_mid - seg_len * cosf(rel_angle); + float y_start = y_mid - seg_len * sinf(rel_angle); + float x_end = x_mid + seg_len * cosf(rel_angle); + float y_end = y_mid + seg_len * sinf(rel_angle); + + DrawLine3D((Vector3){0, 0, 0}, (Vector3){x_mid, y_mid, 1}, PUFF_CYAN); + DrawCube((Vector3){x_mid, y_mid, 1}, 0.5f, 0.5f, 0.5f, PUFF_CYAN); + DrawLine3D((Vector3){x_start, y_start, 1}, (Vector3){x_end, y_end, 1}, BLUE); + } +} + +void draw_road_edge(Drive* env, float start_x, float start_y, float end_x, float end_y) { + Color CURB_TOP = (Color){220, 220, 220, 255}; + Color CURB_SIDE = (Color){180, 180, 180, 255}; + Color CURB_BOTTOM = (Color){160, 160, 160, 255}; + float curb_height = 0.5f; + float curb_width = 0.3f; + + Vector3 direction = {end_x - start_x, end_y - start_y, 0}; + float length = sqrtf(direction.x * direction.x + direction.y * direction.y); + Vector3 nd = {direction.x / length, direction.y / length, 0}; + Vector3 perp = {-nd.y, nd.x, 0}; + + Vector3 b1 = {start_x - perp.x * curb_width / 2, start_y - perp.y * curb_width / 2, 1.0f}; + Vector3 b2 = {start_x + perp.x * curb_width / 2, start_y + perp.y * curb_width / 2, 1.0f}; + Vector3 b3 = {end_x + perp.x * curb_width / 2, end_y + perp.y * curb_width / 2, 1.0f}; + Vector3 b4 = {end_x - perp.x * curb_width / 2, end_y - perp.y * curb_width / 2, 1.0f}; + + DrawTriangle3D(b1, b2, b3, CURB_BOTTOM); + DrawTriangle3D(b1, b3, b4, CURB_BOTTOM); + + Vector3 t1 = {b1.x, b1.y, b1.z + curb_height}; + Vector3 t2 = {b2.x, b2.y, b2.z + curb_height}; + Vector3 t3 = {b3.x, b3.y, b3.z + curb_height}; + Vector3 t4 = {b4.x, b4.y, b4.z + curb_height}; + DrawTriangle3D(t1, t3, t2, CURB_TOP); + DrawTriangle3D(t1, t4, t3, CURB_TOP); + + DrawTriangle3D(b1, t1, b2, CURB_SIDE); DrawTriangle3D(t1, t2, b2, CURB_SIDE); + DrawTriangle3D(b2, t2, b3, CURB_SIDE); DrawTriangle3D(t2, t3, b3, CURB_SIDE); + DrawTriangle3D(b3, t3, b4, CURB_SIDE); DrawTriangle3D(t3, t4, b4, CURB_SIDE); + DrawTriangle3D(b4, t4, b1, CURB_SIDE); DrawTriangle3D(t4, t1, b1, CURB_SIDE); +} + +void c_render(Drive* env) { + if (env->client == NULL) { + env->client = make_client(env); + } + Client* client = env->client; + BeginDrawing(); + ClearBackground(ROAD_COLOR); + BeginMode3D(client->camera); + handle_camera_controls(client); + + // Map bounds + DrawLine3D((Vector3){env->map_corners[0], env->map_corners[1], 0}, (Vector3){env->map_corners[2], env->map_corners[1], 0}, PUFF_CYAN); + DrawLine3D((Vector3){env->map_corners[0], env->map_corners[1], 0}, (Vector3){env->map_corners[0], env->map_corners[3], 0}, PUFF_CYAN); + DrawLine3D((Vector3){env->map_corners[2], env->map_corners[1], 0}, (Vector3){env->map_corners[2], env->map_corners[3], 0}, PUFF_CYAN); + DrawLine3D((Vector3){env->map_corners[0], env->map_corners[3], 0}, (Vector3){env->map_corners[2], env->map_corners[3], 0}, PUFF_CYAN); + + for (int i = 0; i < env->num_entities; i++) { + // Draw vehicles + if (env->entities[i].type == VEHICLE || env->entities[i].type == PEDESTRIAN) { + bool is_active_agent = false; + bool is_static_agent = false; + int agent_index = -1; + for (int j = 0; j < env->active_agent_count; j++) { + if (env->active_agent_indices[j] == i) { + is_active_agent = true; + agent_index = j; + break; + } + } + for (int j = 0; j < env->static_agent_count; j++) { + if (env->static_agent_indices[j] == i) { + is_static_agent = true; + break; + } + } + + if ((!is_active_agent && !is_static_agent) || env->entities[i].respawn_timestep != -1) { + continue; + } + + Vector3 position = {env->entities[i].x, env->entities[i].y, 1}; + float heading = env->entities[i].heading; + Vector3 size = {env->entities[i].length, env->entities[i].width, env->entities[i].height}; + + rlPushMatrix(); + rlTranslatef(position.x, position.y, position.z); + rlRotatef(heading * RAD2DEG, 0.0f, 0.0f, 1.0f); + + Model car_model = client->cars[5]; + if (is_active_agent) { + car_model = client->cars[client->car_assignments[i % MAX_AGENTS]]; + } + if (agent_index == env->human_agent_idx) { + // Human-controlled agent uses default model + } + if (is_active_agent && env->entities[i].collision_state > NO_COLLISION) { + car_model = client->cars[0]; + } + + if (agent_index == env->human_agent_idx && !env->entities[agent_index].reached_goal) { + draw_agent_obs(env, agent_index); + } + + BoundingBox bounds = GetModelBoundingBox(car_model); + Vector3 model_size = { + bounds.max.x - bounds.min.x, + bounds.max.y - bounds.min.y, + bounds.max.z - bounds.min.z + }; + Vector3 scale = {size.x / model_size.x, size.y / model_size.y, size.z / model_size.z}; + DrawModelEx(car_model, (Vector3){0, 0, 0}, (Vector3){1, 0, 0}, 90.0f, scale, WHITE); + rlPopMatrix(); + + // Draw collision box + float cos_h = env->entities[i].heading_x; + float sin_h = env->entities[i].heading_y; + float hl = env->entities[i].length * 0.5f; + float hw = env->entities[i].width * 0.5f; + Vector3 corners[4] = { + {position.x + (hl * cos_h - hw * sin_h), position.y + (hl * sin_h + hw * cos_h), position.z}, + {position.x + (hl * cos_h + hw * sin_h), position.y + (hl * sin_h - hw * cos_h), position.z}, + {position.x + (-hl * cos_h - hw * sin_h), position.y + (-hl * sin_h + hw * cos_h), position.z}, + {position.x + (-hl * cos_h + hw * sin_h), position.y + (-hl * sin_h - hw * cos_h), position.z} + }; + for (int j = 0; j < 4; j++) { + DrawLine3D(corners[j], corners[(j + 1) % 4], PURPLE); + } + + // FPV camera + if (IsKeyDown(KEY_SPACE) && env->human_agent_idx == agent_index) { + if (env->entities[agent_index].reached_goal) { + env->human_agent_idx = rand_r(&env->rng) % env->active_agent_count; + } + client->camera.position = (Vector3){ + position.x - 25.0f * cosf(heading), + position.y - 25.0f * sinf(heading), + position.z + 15 + }; + client->camera.target = (Vector3){ + position.x + 40.0f * cosf(heading), + position.y + 40.0f * sinf(heading), + position.z - 5.0f + }; + client->camera.up = (Vector3){0, 0, 1}; + } + if (IsKeyReleased(KEY_SPACE)) { + client->camera.position = client->default_camera_position; + client->camera.target = client->default_camera_target; + client->camera.up = (Vector3){0, 0, 1}; + } + + if (!is_active_agent || env->entities[i].valid == 0) continue; + if (!IsKeyDown(KEY_LEFT_CONTROL)) { + DrawSphere((Vector3){env->entities[i].goal_position_x, env->entities[i].goal_position_y, 1}, 0.5f, DARKGREEN); + } + } + + // Draw road elements + if (env->entities[i].type < ROAD_LANE || env->entities[i].type > ROAD_EDGE) { + continue; + } + for (int j = 0; j < env->entities[i].array_size - 1; j++) { + if (env->entities[i].type != ROAD_EDGE) continue; + if (!IsKeyDown(KEY_LEFT_CONTROL)) { + draw_road_edge(env, + env->entities[i].traj_x[j], env->entities[i].traj_y[j], + env->entities[i].traj_x[j + 1], env->entities[i].traj_y[j + 1]); + } + } + } + + // Grid overlay + float grid_start_x = env->map_corners[0]; + float grid_start_y = env->map_corners[1]; + for (int i = 0; i < env->grid_cols; i++) { + for (int j = 0; j < env->grid_rows; j++) { + float x = grid_start_x + i * GRID_CELL_SIZE; + float y = grid_start_y + j * GRID_CELL_SIZE; + DrawCubeWires( + (Vector3){x + GRID_CELL_SIZE / 2, y + GRID_CELL_SIZE / 2, 1}, + GRID_CELL_SIZE, GRID_CELL_SIZE, 0.1f, PUFF_BACKGROUND2); + } + } + EndMode3D(); + + // Draw debug info + DrawText(TextFormat("Camera Position: (%.2f, %.2f, %.2f)", + client->camera.position.x, client->camera.position.y, client->camera.position.z), 10, 10, 20, PUFF_WHITE); + DrawText(TextFormat("Camera Target: (%.2f, %.2f, %.2f)", + client->camera.target.x, client->camera.target.y, client->camera.target.z), 10, 30, 20, PUFF_WHITE); + DrawText(TextFormat("Timestep: %d", env->timestep), 10, 50, 20, PUFF_WHITE); + int human_idx = env->active_agent_indices[env->human_agent_idx]; + DrawText(TextFormat("Controlling Agent: %d", env->human_agent_idx), 10, 70, 20, PUFF_WHITE); + DrawText(TextFormat("Agent Index: %d", human_idx), 10, 90, 20, PUFF_WHITE); + DrawText("Controls: W/S - Accelerate/Brake, A/D - Steer, 1-4 - Switch Agent", + 10, client->height - 30, 20, PUFF_WHITE); + DrawText(TextFormat("Acceleration: %d", env->actions[env->human_agent_idx * 2]), 10, 110, 20, PUFF_WHITE); + DrawText(TextFormat("Steering: %d", env->actions[env->human_agent_idx * 2 + 1]), 10, 130, 20, PUFF_WHITE); + DrawText(TextFormat("Grid Rows: %d", env->grid_rows), 10, 150, 20, PUFF_WHITE); + DrawText(TextFormat("Grid Cols: %d", env->grid_cols), 10, 170, 20, PUFF_WHITE); + EndDrawing(); +} + +void close_client(Client* client) { + for (int i = 0; i < 6; i++) { + UnloadModel(client->cars[i]); + } + UnloadTexture(client->puffers); + CloseWindow(); + free(client); +} diff --git a/ocean/drmario/binding.c b/ocean/drmario/binding.c new file mode 100644 index 0000000000..a9287fc6aa --- /dev/null +++ b/ocean/drmario/binding.c @@ -0,0 +1,25 @@ +#include "drmario.h" + +#define OBS_SIZE 394 +#define NUM_ATNS 1 +#define ACT_SIZES {7} +#define OBS_TENSOR_T FloatTensor + +#define Env DrMario +#include "vecenv.h" + +void my_init(Env* env, Dict* kwargs) { + env->num_agents=1; + env->n_rows = dict_get(kwargs, "n_rows")->value; + env->n_cols = dict_get(kwargs, "n_cols")->value; + env->n_init_viruses = dict_get(kwargs, "n_init_viruses")->value; + c_init(env); +} + +void my_log(Log* log, Dict* out) { + dict_set(out, "perf", log->perf); + dict_set(out, "score", log->score); + dict_set(out, "episode_return", log->episode_return); + dict_set(out, "episode_length", log->episode_length); + dict_set(out, "viruses_cleared", log->viruses_cleared); +} diff --git a/ocean/drmario/drmario.h b/ocean/drmario/drmario.h new file mode 100644 index 0000000000..450569dc66 --- /dev/null +++ b/ocean/drmario/drmario.h @@ -0,0 +1,624 @@ + +#include +#include +#include "raylib.h" +#include +#include + +#define SQUARE_SIZE 32 +#define TICKS_PER_FALL 3 + +#define REWARD_SOFT_DROP 50.0f +#define REWARD_HARD_DROP 50.0f +#define REWARD_KILL_VIRUS 400.0f +#define REWARd_PLACE_NEXT_TO_VIRUS 100.0f + +#define ROTATION_0 0 +#define ROTATION_90 1 +#define ROTATION_180 2 +#define ROTATION_270 3 + +#define ACTION_NO_OP 0 +#define ACTION_LEFT 1 +#define ACTION_RIGHT 2 +#define ACTION_DOWN 3 +#define ACTION_ROTATE_LEFT 4 +#define ACTION_ROTATE_RIGHT 5 +#define ACTION_DROP 6 + +#define N_SCALAR_OBS 10 +#define N_OBS_PLANES 3 + +// Required struct. Only use floats! +typedef struct { + float perf; // Recommended 0-1 normalized single real number perf metric + float score; // Recommended unnormalized single real number perf metric + float episode_return; // Recommended metric: sum of agent rewards over episode + float episode_length; // Recommended metric: number of steps of agent episode + // Any extra fields you add here may be exported in binding.c + float viruses_cleared; + + float n; // Required as the last field +} Log; + +// Required that you have some struct for your env +typedef struct { + int total_rows; + int total_columns; +} Client; + +typedef struct { + Client *client; + Log log; + + float *observations; + float *actions; + float *rewards; + float *terminals; + int dim_obs; + + int num_agents; + + int n_rows; + int n_cols; + int *grid; + + int cap_color_a; + int cap_color_b; + int cap_orient; + int cap_row_1; + int cap_col_1; + int cap_row_2; + int cap_col_2; + + bool cap_colliding_left; + bool cap_colliding_right; + bool cap_colliding_down; + bool cap_colliding_up; + + bool cap_colliding_left_virus; + bool cap_colliding_right_virus; + bool cap_colliding_down_virus; + bool cap_colliding_up_virus; + + int tick; + int tick_fall; + int ticks_per_fall; + + int score; + int stage; + + int viruses_remaining; + int n_init_viruses; + + float episode_return; + int viruses_cleared; + + int atn_count_soft_drop; + int atn_count_hard_drop; + int atn_count_rotate; + + unsigned int rng; +} DrMario; + + +void c_init(DrMario *env) +{ + env->grid=(int*)calloc(env->n_rows*env->n_cols,sizeof(int)); + if(env->grid==NULL) + { + exit(1); + } + env->stage=0; +} + +void allocate(DrMario *env) +{ + c_init(env); + env->dim_obs = env->n_rows * env->n_cols * N_OBS_PLANES + N_SCALAR_OBS; + env->observations = (float *)calloc(env->dim_obs, sizeof(float)); + if(env->observations == NULL) + { + exit(1); + } + env->actions = (float *)calloc(1, sizeof(float)); + if(env->actions == NULL) + { + exit(1); + } + env->rewards = (float *)calloc(1, sizeof(float)); + if(env->rewards == NULL) + { + exit(1); + } + env->terminals = (float *)calloc(1, sizeof(float)); + if(env->terminals == NULL) + { + exit(1); + } +} + +void c_close(DrMario *env) +{ + free(env->grid); + if(IsWindowReady()) + { + CloseWindow(); + } +} + +void free_allocated(DrMario *env) { + free(env->actions); + free(env->observations); + free(env->terminals); + free(env->rewards); + c_close(env); +} + + +void add_log(DrMario *env) { + env->log.perf += env->viruses_cleared / (float)env->n_init_viruses; + env->log.score += env->score; + env->log.episode_length += env->tick; + env->log.episode_return += env->episode_return; + env->log.viruses_cleared += env->viruses_cleared; + env->log.n++; +} + + +void compute_observations(DrMario *env) +{ + int cells = env->n_rows * env->n_cols; + + float* plane_occupied = env->observations; + float* plane_viruses = env->observations + cells; + float* plane_colors = env->observations + 2 * cells; + + for (int i = 0; i < cells; i++) { + int cell = env->grid[i]; + plane_occupied[i] = cell != 0 ? 1.0f : 0.0f; + plane_viruses[i] = cell < 0 ? 1.0f : 0.0f; + plane_colors[i] = cell != 0 ? abs(cell) / 3.0f : 0.0f; + } + + int r1 = env->cap_row_1, c1 = env->cap_col_1; + int r2 = env->cap_row_2, c2 = env->cap_col_2; + if (r1 >= 0 && r1 < env->n_rows && c1 >= 0 && c1 < env->n_cols) { + int i = r1 * env->n_cols + c1; + plane_occupied[i] = 1.0f; + plane_viruses[i] = 0.0f; + plane_colors[i] = env->cap_color_a / 3.0f; + } + if (r2 >= 0 && r2 < env->n_rows && c2 >= 0 && c2 < env->n_cols) { + int i = r2 * env->n_cols + c2; + plane_occupied[i] = 1.0f; + plane_viruses[i] = 0.0f; + plane_colors[i] = env->cap_color_b / 3.0f; + } + + int off = cells * N_OBS_PLANES; + float safe_r1 = (r1 < 0) ? 0.0f : r1 / (float)(env->n_rows - 1); + float safe_r2 = (r2 < 0) ? 0.0f : r2 / (float)(env->n_rows - 1); + env->observations[off + 0] = env->cap_color_a / 3.0f; + env->observations[off + 1] = env->cap_color_b / 3.0f; + env->observations[off + 2] = env->cap_orient / 3.0f; + env->observations[off + 3] = safe_r1; + env->observations[off + 4] = c1 / (float)(env->n_cols - 1); + env->observations[off + 5] = safe_r2; + env->observations[off + 6] = c2 / (float)(env->n_cols - 1); + env->observations[off + 7] = env->viruses_remaining / (float)env->n_init_viruses; + env->observations[off + 8] = env->score / 10000.0f; + env->observations[off + 9] = env->tick / 1000.0f; +} + +void place_viruses(DrMario *env) { + env->viruses_remaining = 0; + int placed = 0; + int attempts = 0; + + while (placed < env->n_init_viruses && attempts < 1000) { + attempts++; + int r = (rand_r(&env->rng) % 8) + 8; + int c = rand_r(&env->rng) % env->n_cols; + int idx = r * env->n_cols + c; + + if (env->grid[idx] != 0) continue; + + int color = (rand_r(&env->rng) % 3) + 1; + env->grid[idx] = -color; + placed++; + env->viruses_remaining++; + } +} + +void spawn_capsule(DrMario *env) { + env->cap_color_a = rand_r(&env->rng) % 3 + 1; + env->cap_color_b = rand_r(&env->rng) % 3 + 1; + env->cap_orient = ROTATION_0; + env->cap_row_1 = -1; + env->cap_col_1 = env->n_cols / 2; + env->cap_row_2 = env->cap_row_1; + env->cap_col_2 = env->cap_col_1 + 1; + env->tick_fall = 0; +} + +void c_reset(DrMario *env) { + memset(env->grid, 0, env->n_rows * env->n_cols * sizeof(int)); + env->score = 0; + env->stage += 1; + env->tick = 0; + env->tick_fall = 0; + + env->ticks_per_fall = TICKS_PER_FALL; + env->viruses_remaining = env->n_init_viruses; + + env->episode_return = 0; + env->viruses_cleared = 0; + env->atn_count_soft_drop = 0; + env->atn_count_hard_drop = 0; + env->atn_count_rotate = 0; + place_viruses(env); + spawn_capsule(env); + compute_observations(env); +} + +void get_collisions(DrMario* env){ + env->cap_colliding_left = false; + env->cap_colliding_right = false; + env->cap_colliding_down = false; + env->cap_colliding_up = false; + + // i feel like it might be good to reward the agent for + // colliding with viruses, colliding with same color viruses/blocks + // and clearing lines + env->cap_colliding_left_virus = false; + env->cap_colliding_right_virus = false; + env->cap_colliding_down_virus = false; + env->cap_colliding_up_virus = false; + + if (env->cap_row_1 < 0 || env->cap_row_2 < 0) { + return; + } + + if(env->grid[(env->cap_row_1+1) * env->n_cols + env->cap_col_1] != 0 + || env->grid[(env->cap_row_2+1) * env->n_cols + env->cap_col_2] != 0 + || env->cap_row_1 == env->n_rows - 1 + || env->cap_row_2 == env->n_rows - 1) { + env->cap_colliding_down = true; + } + + if(env->grid[(env->cap_row_1+1) * env->n_cols + env->cap_col_1] < 0 + || env->grid[(env->cap_row_2+1) * env->n_cols + env->cap_col_2] < 0) { + env->cap_colliding_down_virus = true; + } + + if(env->grid[(env->cap_row_1-1) * env->n_cols + env->cap_col_1] != 0 + || env->grid[(env->cap_row_2-1) * env->n_cols + env->cap_col_2] != 0) { + env->cap_colliding_up = true; + } + + if(env->grid[(env->cap_row_1-1) * env->n_cols + env->cap_col_1] < 0 + || env->grid[(env->cap_row_2-1) * env->n_cols + env->cap_col_2] < 0) { + env->cap_colliding_up_virus = true; + } + + if(env->grid[env->cap_row_1 * env->n_cols + env->cap_col_1 + 1] != 0 + || env->grid[env->cap_row_2 * env->n_cols + env->cap_col_2 + 1] != 0 + || env->cap_col_1 == env->n_cols - 1 + || env->cap_col_2 == env->n_cols - 1) { + env->cap_colliding_right = true; + } + + if(env->grid[env->cap_row_1 * env->n_cols + env->cap_col_1 + 1] < 0 + || env->grid[env->cap_row_2 * env->n_cols + env->cap_col_2 + 1] < 0) { + env->cap_colliding_right_virus = true; + } + + if(env->grid[env->cap_row_1 * env->n_cols + env->cap_col_1 - 1] != 0 + || env->grid[env->cap_row_2 * env->n_cols + env->cap_col_2 - 1] != 0 + || env->cap_col_1 == 0 + || env->cap_col_2 == 0) { + env->cap_colliding_left = true; + } + + if(env->grid[env->cap_row_1 * env->n_cols + env->cap_col_1 - 1] < 0 + || env->grid[env->cap_row_2 * env->n_cols + env->cap_col_2 - 1] < 0) { + env->cap_colliding_left_virus = true; + } +} + +void rotate_cap(DrMario* env){ + int old_orient = env->cap_orient; + int old_cap_row_2 = env->cap_row_2; + int old_cap_col_2 = env->cap_col_2; + + if(env->actions[0] == ACTION_ROTATE_LEFT) { + env->cap_orient = (env->cap_orient + 1) % 4; + } else if(env->actions[0] == ACTION_ROTATE_RIGHT) { + env->cap_orient = (env->cap_orient + 3) % 4; + } else { + return; + } + + env->cap_row_2 = env->cap_row_1; + if(env->cap_orient == ROTATION_90) { + env->cap_row_2 -= 1; + } else if(env->cap_orient == ROTATION_270) { + env->cap_row_2 += 1; + } + + env->cap_col_2 = env->cap_col_1; + if(env->cap_orient == ROTATION_0) { + env->cap_col_2 += 1; + } else if(env->cap_orient == ROTATION_180) { + env->cap_col_2 -= 1; + } + + if(env->grid[env->cap_row_2 * env->n_cols + env->cap_col_2] != 0 + || env->cap_row_2 < 0 || env->cap_row_2 >= env->n_rows + || env->cap_col_2 < 0 || env->cap_col_2 >= env->n_cols) { + env->cap_orient = old_orient; + env->cap_row_2 = old_cap_row_2; + env->cap_col_2 = old_cap_col_2; + } +} + +void move_cap(DrMario* env){ + env->tick_fall += 1; + if(env->tick_fall >= env->ticks_per_fall) + { + env->tick_fall = 0; + if(!env->cap_colliding_down) { + env->cap_row_1 += 1; + env->cap_row_2 += 1; + } + return; + } + + if(env->cap_row_1 < 0 || env->cap_row_2 < 0) { + return; + } + + if(env->actions[0] == ACTION_LEFT && !env->cap_colliding_left) { + env->cap_col_1 -= 1; + env->cap_col_2 -= 1; + } else if(env->actions[0] == ACTION_RIGHT && !env->cap_colliding_right) { + env->cap_col_1 += 1; + env->cap_col_2 += 1; + } else if(env->actions[0] == ACTION_DOWN && !env->cap_colliding_down) { + env->cap_row_1 += 1; + env->cap_row_2 += 1; + + env->atn_count_soft_drop += 1; + env->score += REWARD_SOFT_DROP; + } else if (env->actions[0] == ACTION_DROP) { + if(!env->cap_colliding_down) { + env->atn_count_hard_drop += 1; + env->score += REWARD_HARD_DROP; + do{ + env->cap_row_1 += 1; + env->cap_row_2 += 1; + get_collisions(env); + } while (!env->cap_colliding_down); + } + } +} + +float clear_lines(DrMario* env) { + bool *to_clear = (bool*)calloc(env->n_rows * env->n_cols, sizeof(bool)); + if (!to_clear) return 0.0f; + + for (int r = 0; r < env->n_rows; r++) { + for(int c = 0; c < env->n_cols; c++) { + int cell = env->grid[r * env->n_cols + c]; + if (cell == 0) { + continue; + } + int color = abs(cell); + int c_end = c + 1; + while(c_end < env->n_cols && abs(env->grid[r * env->n_cols + c_end]) == color) { + c_end += 1; + } + if(c_end - c >= 4){ + for(int i = c; i < c_end; i++) { + to_clear[r * env->n_cols + i] = true; + } + } + c = c_end-1; + } + } + + for(int c = 0; c < env->n_cols; c++) { + for(int r = 0; r < env->n_rows; r++) { + int cell = env->grid[r * env->n_cols + c]; + if (cell == 0) { + continue; + } + int color = abs(cell); + int r_end = r + 1; + while(r_end < env->n_rows && abs(env->grid[r_end * env->n_cols + c]) == color) { + r_end += 1; + } + if(r_end - r >= 4){ + for(int i = r; i < r_end; i++) { + to_clear[i * env->n_cols + c] = true; + } + } + r = r_end-1; + } + } + + bool any_cleared = false; + for (int i = 0; i < env->n_rows * env->n_cols; i++) { + if (to_clear[i]) { + any_cleared = true; + break; + } + } + + if (!any_cleared) { + free(to_clear); + return 0.0f; + } + + int viruses_cleared_this_pass = 0; + for (int i = 0; i < env->n_rows * env->n_cols; i++) { + if (to_clear[i]) { + if (env->grid[i] < 0) { + env->viruses_remaining--; + env->viruses_cleared++; + viruses_cleared_this_pass++; + } + env->grid[i] = 0; + } + } + + bool falling = true; + while (falling) { + falling = false; + for (int r = env->n_rows - 2; r >= 0; r--) { + for (int c = 0; c < env->n_cols; c++) { + int cell = env->grid[r * env->n_cols + c]; + if (cell <= 0 || env->grid[(r + 1) * env->n_cols + c] != 0){ + continue; + } + + if((r < env->n_rows - 2 && to_clear[(r+1) * env->n_cols + c]) + || (r > 0 && to_clear[(r-1) * env->n_cols + c]) + || (c < env->n_cols - 1 && to_clear[r * env->n_cols + c + 1]) + || (c > 0 && to_clear[r * env->n_cols + c - 1])) { + to_clear[r * env->n_cols + c] = true; + } + + if(to_clear[r * env->n_cols + c]) { + env->grid[(r + 1) * env->n_cols + c] = cell; + env->grid[r * env->n_cols + c] = 0; + falling = true; + } + } + } + } + + free(to_clear); + int total_viruses_cleared = viruses_cleared_this_pass + clear_lines(env); + return total_viruses_cleared; +} + +void spawn_new_cap(DrMario* env) { + if(env->cap_colliding_down) { + + if(env->cap_colliding_down_virus + || env->cap_colliding_left_virus + || env->cap_colliding_right_virus + || env->cap_colliding_up_virus) { + env->score += REWARd_PLACE_NEXT_TO_VIRUS; + env->rewards[0] += 0.5f; + } + + env->grid[env->cap_row_1 * env->n_cols + env->cap_col_1] = env->cap_color_a; + env->grid[env->cap_row_2 * env->n_cols + env->cap_col_2] = env->cap_color_b; + + int viruses_cleared = clear_lines(env); + if(viruses_cleared > 0){ + float base = viruses_cleared / env->n_init_viruses; + float mult = 1.0f + 0.5f * (viruses_cleared - 1); + env->rewards[0] += base * mult; + env->score += base * mult * REWARD_KILL_VIRUS; + } else { + env->rewards[0] -= 0.01f; + } + + spawn_capsule(env); + } +} + +void end_game_check(DrMario* env) { + if(env->viruses_remaining <= 0) { + float speed_bonus = 1.0f / (1.0f + env->tick * 0.001f); + env->rewards[0] += 1.0f + speed_bonus; + env->terminals[0] = 1; + add_log(env); + c_reset(env); + } + + if(env->cap_colliding_down && (env->cap_row_1 <= 0 || env->cap_row_2 <= 0)) { + float fraction_remaining = env->viruses_remaining / (float)env->n_init_viruses; + env->rewards[0] -= 1.0f + fraction_remaining * 0.5f; + env->terminals[0] = 1; + add_log(env); + c_reset(env); + } +} + +void c_step(DrMario *env) { + env->tick += 1; + env->terminals[0] = 0; + env->rewards[0] = 0; + + get_collisions(env); + + if(!env->cap_colliding_down) { + rotate_cap(env); + get_collisions(env); + } + + move_cap(env); + get_collisions(env); + + end_game_check(env); + + spawn_new_cap(env); + + env->episode_return += env->rewards[0]; + + compute_observations(env); +} + +void c_render(DrMario *env) { + if (!IsWindowReady()) { + InitWindow(SQUARE_SIZE * env->n_cols, SQUARE_SIZE * env->n_rows, "Dr Mario"); + SetTargetFPS(30); + } + if (IsKeyDown(KEY_ESCAPE)) exit(0); + + BeginDrawing(); + ClearBackground(BLACK); + + for (int r = 0; r < env->n_rows; r++) { + for (int c = 0; c < env->n_cols; c++) { + int cell = env->grid[r * env->n_cols + c]; + int x = c * SQUARE_SIZE; + int y = r * SQUARE_SIZE; + if (cell == 0) continue; + + Color color; + if (cell == 1 || cell == -1) color = RED; + else if (cell == 2 || cell == -2) color = BLUE; + else color = YELLOW; + + if (cell < 0) { + DrawCircle(x + SQUARE_SIZE/2, y + SQUARE_SIZE/2, + SQUARE_SIZE/2 - 2, color); + } else { + DrawRectangle(x + 2, y + 2, + SQUARE_SIZE - 4, SQUARE_SIZE - 4, color); + } + } + } + + // draw active capsule + int x1 = env->cap_col_1 * SQUARE_SIZE; + int y1 = env->cap_row_1 * SQUARE_SIZE; + int x2 = env->cap_col_2 * SQUARE_SIZE; + int y2 = env->cap_row_2 * SQUARE_SIZE; + Color ca = (env->cap_color_a == 1) ? RED : (env->cap_color_a == 2) ? BLUE : YELLOW; + Color cb = (env->cap_color_b == 1) ? RED : (env->cap_color_b == 2) ? BLUE : YELLOW; + + DrawRectangle(x1 + 2, y1 + 2, SQUARE_SIZE - 4, SQUARE_SIZE - 4, ca); + DrawRectangle(x2 + 2, y2 + 2, SQUARE_SIZE - 4, SQUARE_SIZE - 4, cb); + + DrawText(TextFormat("Viruses: %d", env->viruses_remaining), 4, 4, 14, WHITE); + DrawText(TextFormat("Score: %d", env->score), 4, 20, 14, WHITE); + + EndDrawing(); +} diff --git a/ocean/drone/binding.c b/ocean/drone/binding.c new file mode 100644 index 0000000000..a033d4445f --- /dev/null +++ b/ocean/drone/binding.c @@ -0,0 +1,40 @@ +#include "drone.h" +#include "render.h" + +#define OBS_SIZE 23 +#define NUM_ATNS 4 +#define ACT_SIZES {1, 1, 1, 1} +#define OBS_TENSOR_T FloatTensor + +#define Env DroneEnv +#include "vecenv.h" + +void my_init(Env* env, Dict* kwargs) { + env->num_agents = (int)dict_get(kwargs, "num_drones")->value; + env->task = (int)dict_get(kwargs, "task")->value; + env->max_rings = (int)dict_get(kwargs, "max_rings")->value; + env->alpha_dist = dict_get(kwargs, "alpha_dist")->value; + env->alpha_hover = dict_get(kwargs, "alpha_hover")->value; + env->alpha_shaping = dict_get(kwargs, "alpha_shaping")->value; + env->alpha_omega = dict_get(kwargs, "alpha_omega")->value; + env->hover_target_dist = dict_get(kwargs, "hover_target_dist")->value; + env->hover_dist = dict_get(kwargs, "hover_dist")->value; + env->hover_omega = dict_get(kwargs, "hover_omega")->value; + env->hover_vel = dict_get(kwargs, "hover_vel")->value; + init(env); +} + +void my_log(Log* log, Dict* out) { + dict_set(out, "perf", log->perf); + dict_set(out, "score", log->score); + dict_set(out, "rings_passed", log->rings_passed); + dict_set(out, "ring_collisions", log->ring_collision); + dict_set(out, "collisions", log->collisions); + dict_set(out, "oob", log->oob); + dict_set(out, "timeout", log->timeout); + dict_set(out, "episode_return", log->episode_return); + dict_set(out, "episode_length", log->episode_length); + dict_set(out, "ema_dist", log->ema_dist); + dict_set(out, "ema_vel", log->ema_vel); + dict_set(out, "ema_omega", log->ema_omega); +} diff --git a/ocean/drone/drone.c b/ocean/drone/drone.c new file mode 100644 index 0000000000..eabd8d778a --- /dev/null +++ b/ocean/drone/drone.c @@ -0,0 +1,90 @@ +#include "drone.h" +#include "puffernet.h" +#include "render.h" +#include + +#ifdef __EMSCRIPTEN__ +#include +#endif + +#ifdef __EMSCRIPTEN__ +typedef struct { + DroneEnv* env; + PufferNet* net; + Weights* weights; +} WebRenderArgs; + +void emscriptenStep(void* e) { + WebRenderArgs* args = (WebRenderArgs*)e; + DroneEnv* env = args->env; + PufferNet* net = args->net; + + forward_puffernet(net, env->observations, env->actions); + c_step(env); + c_render(env); +} + +WebRenderArgs* web_args = NULL; +#endif + +int main() { + srand(time(NULL)); + + DroneEnv* env = calloc(1, sizeof(DroneEnv)); + size_t obs_size = 23; + + env->num_agents = 16; + env->max_rings = 10; + env->task = HOVER; + env->alpha_dist = 0.782192f; + env->alpha_hover = 0.071445f; + env->alpha_shaping = 3.9754f; + env->alpha_omega = 0.00135588f; + env->hover_target_dist = 5.0f; + env->hover_dist = 0.1f; + env->hover_omega = 0.1f; + env->hover_vel = 0.1f; + + env->observations = (float*)calloc(env->num_agents * obs_size, sizeof(float)); + env->actions = (float*)calloc(env->num_agents * 4, sizeof(float)); + env->rewards = (float*)calloc(env->num_agents, sizeof(float)); + env->terminals = (float*)calloc(env->num_agents, sizeof(float)); + + Weights* weights = load_weights("resources/drone/drone_weights.bin"); + int logit_sizes[4] = {1, 1, 1, 1}; + // make_puffernet(weights, num_agents, obs_size, hidden_size, num_layers, logit_sizes, num_actions) + PufferNet* net = make_puffernet(weights, env->num_agents, obs_size, 128, 3, logit_sizes, 4); + + init(env); + c_reset(env); + +#ifdef __EMSCRIPTEN__ + WebRenderArgs* args = calloc(1, sizeof(WebRenderArgs)); + args->env = env; + args->net = net; + args->weights = weights; + web_args = args; + + emscripten_set_main_loop_arg(emscriptenStep, args, 0, true); +#else + c_render(env); + SetTargetFPS(60); + + while (!WindowShouldClose()) { + forward_puffernet(net, env->observations, env->actions); + c_step(env); + c_render(env); + } + + c_close(env); + free_puffernet(net); + free(weights); + free(env->observations); + free(env->actions); + free(env->rewards); + free(env->terminals); + free(env); +#endif + + return 0; +} diff --git a/ocean/drone/drone.h b/ocean/drone/drone.h new file mode 100644 index 0000000000..e79db2c7fb --- /dev/null +++ b/ocean/drone/drone.h @@ -0,0 +1,201 @@ +// Originally made by Sam Turner and Finlay Sanders, 2025. +// Included in pufferlib under the original project's MIT license. +// https://github.com/tensaur/drone + +#pragma once + +#include +#include +#include +#include + +#include "dronelib.h" +#include "tasks.h" + +#define HORIZON 1024 + +typedef struct Client Client; +typedef struct DroneEnv DroneEnv; + +struct DroneEnv { + Log log; + float* observations; + float* actions; + float* rewards; + float* terminals; + int num_agents; + unsigned int rng; + + int tick; + DroneTask task; + Drone* agents; + + int max_rings; + Target* ring_buffer; + + Client* client; + + // reward scaling + float alpha_dist; + float alpha_hover; + float alpha_shaping; + float alpha_omega; + + // hover task parameters + float hover_target_dist; + float hover_dist; + float hover_omega; + float hover_vel; +}; + +void init(DroneEnv* env) { + env->agents = (Drone*)calloc(env->num_agents, sizeof(Drone)); + env->ring_buffer = (Target*)calloc(env->max_rings, sizeof(Target)); + + for (int i = 0; i < env->num_agents; i++) { + env->agents[i].target = (Target*)calloc(1, sizeof(Target)); + env->agents[i].buffer_idx = 0; + } + + env->log = (Log){0}; + env->tick = 0; +} + +void add_log(DroneEnv* env, int idx, bool oob, bool timeout) { + Drone* agent = &env->agents[idx]; + + env->log.episode_return += agent->episode_return; + env->log.episode_length += agent->episode_length; + env->log.collisions += agent->collisions; + + if (oob) env->log.oob += 1.0f; + if (timeout) env->log.timeout += 1.0f; + + env->log.score += agent->hover_score; + env->log.perf += agent->hover_ema; + env->log.rings_passed += agent->rings_passed; + env->log.ema_dist += agent->ema_dist; + env->log.ema_vel += agent->ema_vel; + env->log.ema_omega += agent->ema_omega; + + env->log.n += 1.0f; + + agent->episode_length = 0; + agent->episode_return = 0.0f; + agent->collisions = 0.0f; + agent->score = 0.0f; + agent->rings_passed = 0.0f; +} + +void compute_observations(DroneEnv* env) { + for (int i = 0; i < env->num_agents; i++) { + compute_drone_observations(&env->agents[i], env->observations + i*23); + } +} + +void reset_agent(DroneEnv* env, Drone* agent, int idx) { + agent->episode_return = 0.0f; + agent->episode_length = 0; + agent->collisions = 0.0f; + agent->rings_passed = 0; + agent->score = 0.0f; + agent->hover_score = 0.0f; + agent->hover_ema = 0.0f; + agent->ema_dist = 0.0f; + agent->ema_vel = 0.0f; + agent->ema_omega = 0.0f; + + agent->buffer = env->ring_buffer; + agent->buffer_size = env->max_rings; + + init_drone(agent, &env->rng, 0.05f); + + agent->state.pos = + (Vec3){rndf(-MARGIN_X, MARGIN_X, &env->rng), rndf(-MARGIN_Y, MARGIN_Y, &env->rng), rndf(-MARGIN_Z, MARGIN_Z, &env->rng)}; + + if (env->task == RACE) { + while (norm3(sub3(agent->state.pos, env->ring_buffer[0].pos)) < 2.0f * RING_RADIUS) { + agent->state.pos = (Vec3){rndf(-MARGIN_X, MARGIN_X, &env->rng), rndf(-MARGIN_Y, MARGIN_Y, &env->rng), + rndf(-MARGIN_Z, MARGIN_Z, &env->rng)}; + } + } + + agent->prev_pos = agent->state.pos; + agent->prev_potential = hover_potential(agent, env->hover_dist, env->hover_omega, env->hover_vel); +} + +void c_reset(DroneEnv* env) { + if (env->task == RACE) { + reset_rings(&env->rng, env->ring_buffer, env->max_rings); + } + + for (int i = 0; i < env->num_agents; i++) { + Drone* agent = &env->agents[i]; + reset_agent(env, agent, i); + set_target(&env->rng, env->task, env->agents, i, env->num_agents, env->hover_target_dist); + } + + compute_observations(env); +} + +void c_step(DroneEnv* env) { + env->tick = (env->tick + 1) % HORIZON; + + for (int i = 0; i < env->num_agents; i++) { + Drone* agent = &env->agents[i]; + + agent->prev_pos = agent->state.pos; + move_drone(agent, &env->actions[4 * i]); + agent->episode_length++; + + bool oob = norm3(sub3(agent->target->pos, agent->state.pos)) > (env->hover_target_dist + 1.0f); + bool timeout = (agent->episode_length >= HORIZON); + + float curr = hover_potential(agent, env->hover_dist, env->hover_omega, env->hover_vel); + float prev_dist = norm3(sub3(agent->target->pos, agent->prev_pos)); + float curr_dist = norm3(sub3(agent->target->pos, agent->state.pos)); + float omega = norm3(agent->state.omega); + + float reward = env->alpha_dist * (prev_dist - curr_dist) + + env->alpha_hover * curr + + env->alpha_shaping * (curr - agent->prev_potential) + - env->alpha_omega * omega; + + agent->prev_potential = curr; + + float h = check_hover(agent, env->hover_dist, env->hover_omega, env->hover_vel); + agent->hover_score += h; + agent->hover_ema = (1.0f - 0.02f) * agent->hover_ema + 0.02f * h; + agent->ema_dist = 0.99f * agent->ema_dist + 0.01f * curr_dist; + agent->ema_vel = 0.99f * agent->ema_vel + 0.01f * norm3(agent->state.vel); + agent->ema_omega = 0.99f * agent->ema_omega + 0.01f * omega; + agent->episode_return += reward; + env->rewards[i] = reward; + + bool reset = oob || timeout; + env->terminals[i] = reset ? 1.0f : 0.0f; + + if (reset) { + add_log(env, i, oob, timeout); + reset_agent(env, agent, i); + set_target(&env->rng, env->task, env->agents, i, env->num_agents, env->hover_target_dist); + } + } + + compute_observations(env); +} + +void c_close_client(Client* client); + +void c_close(DroneEnv* env) { + for (int i = 0; i < env->num_agents; i++) { + free(env->agents[i].target); + } + + free(env->agents); + free(env->ring_buffer); + + if (env->client != NULL) { + c_close_client(env->client); + } +} diff --git a/ocean/drone/dronelib.h b/ocean/drone/dronelib.h new file mode 100644 index 0000000000..a0446c0092 --- /dev/null +++ b/ocean/drone/dronelib.h @@ -0,0 +1,607 @@ +// Originally made by Sam Turner and Finlay Sanders, 2025. +// Included in pufferlib under the original project's MIT license. +// https://github.com/tensaur/drone + +#pragma once + +#include +#include +#include +#include + +// Visualisation properties +#define WIDTH 1080 +#define HEIGHT 720 +#define TRAIL_LENGTH 50 + +// Crazyflie Physical Constants +// https://github.com/arplaboratory/learning-to-fly +#define BASE_MASS 0.027f // kg +#define BASE_IXX 3.85e-6f // kgm² +#define BASE_IYY 3.85e-6f // kgm² +#define BASE_IZZ 5.9675e-6f // kgm² +#define BASE_ARM_LEN 0.0396f // m +#define BASE_K_THRUST 3.16e-10f // thrust coefficient +#define BASE_K_DRAG 0.005964552f // yaw moment constant +#define BASE_GRAVITY 9.81f // m/s^2 +#define BASE_MAX_RPM 21702.0f // RPM +#define BASE_K_MOT 0.15f // s (RPM time constant) + +#define BASE_K_ANG_DAMP 0.0f // angular damping coefficient +#define BASE_B_DRAG 0.0f // linear drag coefficient +#define BASE_MAX_VEL 20.0f // m/s +#define BASE_MAX_OMEGA 20.0f // rad/s + +// Simulation properties +#define GRID_X 30.0f +#define GRID_Y 30.0f +#define GRID_Z 10.0f +#define MARGIN_X (GRID_X - 1) +#define MARGIN_Y (GRID_Y - 1) +#define MARGIN_Z (GRID_Z - 1) +#define RING_RADIUS 2.0f +#define V_TARGET 0.05f + +// Core Parameters +#define DT 0.002f // 500 Hz +#define ACTION_SUBSTEPS 5 +#define ACTION_DT (DT * (float)ACTION_SUBSTEPS) // 100 Hz + +#define DT_RNG 0.0f + +// Corner to corner distance +#define MAX_DIST \ + sqrtf((2 * GRID_X) * (2 * GRID_X) + (2 * GRID_Y) * (2 * GRID_Y) + (2 * GRID_Z) * (2 * GRID_Z)) + +typedef struct Log Log; +struct Log { + float episode_return; + float episode_length; + float rings_passed; + float collisions; + float oob; + float ring_collision; + float timeout; + float score; + float perf; + float ema_dist; + float ema_vel; + float ema_omega; + float n; +}; + +typedef struct { + float w, x, y, z; +} Quat; + +typedef struct { + float x, y, z; +} Vec3; + +typedef struct { + Vec3 pos; + Vec3 vel; + Quat orientation; + Vec3 normal; + float radius; +} Target; + +typedef struct { + Vec3 pos[TRAIL_LENGTH]; + int index; + int count; +} Trail; + +typedef struct { + Vec3 pos; // global position (x, y, z) + Vec3 vel; // linear velocity (u, v, w) + Quat quat; // roll/pitch/yaw (phi/theta/psi) as a quaternion + Vec3 omega; // angular velocity (p, q, r) + float rpms[4]; // motor RPMs +} State; + +typedef struct { + Vec3 vel; // Derivative of position + Vec3 v_dot; // Derivative of velocity + Quat q_dot; // Derivative of quaternion + Vec3 w_dot; // Derivative of angular velocity + float rpm_dot[4]; // Derivative of motor RPMs +} StateDerivative; + +typedef struct { + float mass; // kg + float ixx; // kgm^2 + float iyy; // kgm^2 + float izz; // kgm^2 + float arm_len; // m + float k_thrust; // thrust coefficient (T = k * rpm^2) + float k_ang_damp; // angular damping coefficient + float k_drag; // yaw moment constant (torque-to-thrust ratio style) + float b_drag; // linear drag coefficient + float gravity; // m/s^2 (positive, world gravity points -z) + float max_rpm; // RPM + float max_vel; // m/s (observation clamp) + float max_omega; // rad/s (observation clamp) + float k_mot; // s (motor RPM time constant) +} Params; + +typedef struct { + // core state and parameters + State state; + Params params; + Vec3 prev_pos; + + // current target + Target* target; + + // target buffer + Target* buffer; + int buffer_idx; + int buffer_size; + + // logging utils + float last_dist_reward; + float episode_return; + int episode_length; + float score; + float collisions; + int rings_passed; + float hover_score; + float prev_potential; + float hover_ema; + float ema_dist; + float ema_vel; + float ema_omega; +} Drone; + +static inline float clampf(float v, float min, float max) { + if (v < min) return min; + if (v > max) return max; + return v; +} + +static inline float rndf(float a, float b, unsigned int* rng) { + return a + ((float)rand_r(rng) / (float)RAND_MAX) * (b - a); +} + +static inline Vec3 add3(Vec3 a, Vec3 b) { return (Vec3){a.x + b.x, a.y + b.y, a.z + b.z}; } +static inline Vec3 sub3(Vec3 a, Vec3 b) { return (Vec3){a.x - b.x, a.y - b.y, a.z - b.z}; } +static inline Vec3 scalmul3(Vec3 a, float b) { return (Vec3){a.x * b, a.y * b, a.z * b}; } + +static inline Quat add_quat(Quat a, Quat b) { + return (Quat){a.w + b.w, a.x + b.x, a.y + b.y, a.z + b.z}; +} +static inline Quat scalmul_quat(Quat a, float b) { + return (Quat){a.w * b, a.x * b, a.y * b, a.z * b}; +} + +static inline float dot3(Vec3 a, Vec3 b) { return a.x * b.x + a.y * b.y + a.z * b.z; } +static inline float norm3(Vec3 a) { return sqrtf(dot3(a, a)); } + +static inline void clamp3(Vec3* vec, float min, float max) { + vec->x = clampf(vec->x, min, max); + vec->y = clampf(vec->y, min, max); + vec->z = clampf(vec->z, min, max); +} + +static inline void clamp4(float a[4], float min, float max) { + a[0] = clampf(a[0], min, max); + a[1] = clampf(a[1], min, max); + a[2] = clampf(a[2], min, max); + a[3] = clampf(a[3], min, max); +} + +static inline Quat quat_mul(Quat q1, Quat q2) { + Quat out; + out.w = q1.w * q2.w - q1.x * q2.x - q1.y * q2.y - q1.z * q2.z; + out.x = q1.w * q2.x + q1.x * q2.w + q1.y * q2.z - q1.z * q2.y; + out.y = q1.w * q2.y - q1.x * q2.z + q1.y * q2.w + q1.z * q2.x; + out.z = q1.w * q2.z + q1.x * q2.y - q1.y * q2.x + q1.z * q2.w; + return out; +} + +static inline void quat_normalize(Quat* q) { + float n = sqrtf(q->w * q->w + q->x * q->x + q->y * q->y + q->z * q->z); + if (n > 0.0f) { + q->w /= n; + q->x /= n; + q->y /= n; + q->z /= n; + } +} + +static inline Vec3 quat_rotate(Quat q, Vec3 v) { + Quat qv = (Quat){0.0f, v.x, v.y, v.z}; + Quat tmp = quat_mul(q, qv); + Quat q_conj = (Quat){q.w, -q.x, -q.y, -q.z}; + Quat res = quat_mul(tmp, q_conj); + return (Vec3){res.x, res.y, res.z}; +} + +static inline Quat quat_inverse(Quat q) { return (Quat){q.w, -q.x, -q.y, -q.z}; } + +static inline Quat rndquat(unsigned int* rng) { + float u1 = rndf(0.0f, 1.0f, rng); + float u2 = rndf(0.0f, 1.0f, rng); + float u3 = rndf(0.0f, 1.0f, rng); + + float sqrt_1_minus_u1 = sqrtf(1.0f - u1); + float sqrt_u1 = sqrtf(u1); + + float pi_2_u2 = 2.0f * (float)M_PI * u2; + float pi_2_u3 = 2.0f * (float)M_PI * u3; + + Quat q; + q.w = sqrt_1_minus_u1 * sinf(pi_2_u2); + q.x = sqrt_1_minus_u1 * cosf(pi_2_u2); + q.y = sqrt_u1 * sinf(pi_2_u3); + q.z = sqrt_u1 * cosf(pi_2_u3); + return q; +} + +static inline Quat quat_from_axis_angle(Vec3 axis, float angle) { + float half = angle * 0.5f; + float s = sinf(half); + return (Quat){cosf(half), axis.x * s, axis.y * s, axis.z * s}; +} + +static inline Target rndring(unsigned int* rng, float radius) { + Target ring = (Target){0}; + + ring.pos.x = rndf(-GRID_X + 2 * radius, GRID_X - 2 * radius, rng); + ring.pos.y = rndf(-GRID_Y + 2 * radius, GRID_Y - 2 * radius, rng); + ring.pos.z = rndf(-GRID_Z + 2 * radius, GRID_Z - 2 * radius, rng); + + ring.orientation = rndquat(rng); + + Vec3 base_normal = (Vec3){0.0f, 0.0f, 1.0f}; + ring.normal = quat_rotate(ring.orientation, base_normal); + + ring.radius = radius; + return ring; +} + +static inline float rpm_hover(const Params* p) { + // total thrust = m*g = 4 * k_thrust * rpm^2 + return sqrtf((p->mass * p->gravity) / (4.0f * p->k_thrust)); +} + +static inline float rpm_min_for_centered_hover(const Params* p) { + // choose min_rpm so that action=0 -> (min+max)/2 == hover + float min_rpm = 2.0f * rpm_hover(p) - p->max_rpm; + if (min_rpm < 0.0f) min_rpm = 0.0f; + if (min_rpm > p->max_rpm) min_rpm = p->max_rpm; + return min_rpm; +} + +static inline void init_drone(Drone* drone, unsigned int* rng, float dr) { + drone->params.arm_len = BASE_ARM_LEN * rndf(1.0f - dr, 1.0f + dr, rng); + drone->params.mass = BASE_MASS * rndf(1.0f - dr, 1.0f + dr, rng); + drone->params.ixx = BASE_IXX * rndf(1.0f - dr, 1.0f + dr, rng); + drone->params.iyy = BASE_IYY * rndf(1.0f - dr, 1.0f + dr, rng); + drone->params.izz = BASE_IZZ * rndf(1.0f - dr, 1.0f + dr, rng); + drone->params.k_thrust = BASE_K_THRUST * rndf(1.0f - dr, 1.0f + dr, rng); + drone->params.k_ang_damp = BASE_K_ANG_DAMP * rndf(1.0f - dr, 1.0f + dr, rng); + drone->params.k_drag = BASE_K_DRAG * rndf(1.0f - dr, 1.0f + dr, rng); + drone->params.b_drag = BASE_B_DRAG * rndf(1.0f - dr, 1.0f + dr, rng); + drone->params.gravity = BASE_GRAVITY * rndf(0.99f, 1.01f, rng); + + drone->params.max_rpm = BASE_MAX_RPM; + drone->params.max_vel = BASE_MAX_VEL; + drone->params.max_omega = BASE_MAX_OMEGA; + + drone->params.k_mot = BASE_K_MOT * rndf(1.0f - dr, 1.0f + dr, rng); + + float hover = rpm_hover(&drone->params); + for (int i = 0; i < 4; i++) + drone->state.rpms[i] = hover; + + drone->state.pos = (Vec3){0.0f, 0.0f, 0.0f}; + drone->prev_pos = drone->state.pos; + drone->state.vel = (Vec3){0.0f, 0.0f, 0.0f}; + drone->state.omega = (Vec3){0.0f, 0.0f, 0.0f}; + drone->state.quat = (Quat){1.0f, 0.0f, 0.0f, 0.0f}; +} + +static inline void compute_derivatives(State* state, Params* params, float* actions, + StateDerivative* derivatives) { + float min_rpm = rpm_min_for_centered_hover(params); + + float target_rpms[4]; + for (int i = 0; i < 4; i++) { + float u = (actions[i] + 1.0f) * 0.5f; // [0,1] + target_rpms[i] = min_rpm + u * (params->max_rpm - min_rpm); + } + + float rpm_dot[4]; + for (int i = 0; i < 4; i++) { + rpm_dot[i] = (1.0f / params->k_mot) * (target_rpms[i] - state->rpms[i]); + } + + // motor thrusts + float T[4]; + for (int i = 0; i < 4; i++) { + float rpm = state->rpms[i]; + if (rpm < 0.0f) rpm = 0.0f; + T[i] = params->k_thrust * rpm * rpm; + } + + // body frame net force + Vec3 F_prop_body = (Vec3){0.0f, 0.0f, T[0] + T[1] + T[2] + T[3]}; + + // body frame force -> world frame force + Vec3 F_prop = quat_rotate(state->quat, F_prop_body); + + // world frame linear drag + Vec3 F_aero; + F_aero.x = -params->b_drag * state->vel.x; + F_aero.y = -params->b_drag * state->vel.y; + F_aero.z = -params->b_drag * state->vel.z; + + // linear acceleration + Vec3 v_dot; + v_dot.x = (F_prop.x + F_aero.x) / params->mass; + v_dot.y = (F_prop.y + F_aero.y) / params->mass; + v_dot.z = ((F_prop.z + F_aero.z) / params->mass) - params->gravity; + + // quaternion rates + Quat omega_q = (Quat){0.0f, state->omega.x, state->omega.y, state->omega.z}; + Quat q_dot = quat_mul(state->quat, omega_q); + q_dot.w *= 0.5f; + q_dot.x *= 0.5f; + q_dot.y *= 0.5f; + q_dot.z *= 0.5f; + + // body frame torques (plus copter) + // Vec3 Tau_prop; + // Tau_prop.x = params->arm_len*(T[1] - T[3]); + // Tau_prop.y = params->arm_len*(T[2] - T[0]); + // Tau_prop.z = params->k_drag*(T[0] - T[1] + T[2] - T[3]); + + // body frame torques (cross copter) + // M1=FR, M2=BR, M3=BL, M4=FL + // https://www.bitcraze.io/documentation/hardware/crazyflie_2_1_brushless/crazyflie_2_1_brushless-datasheet.pdf + float arm_factor = params->arm_len / sqrtf(2.0f); + Vec3 Tau_prop; + Tau_prop.x = arm_factor * ((T[2] + T[3]) - (T[0] + T[1])); + Tau_prop.y = arm_factor * ((T[1] + T[2]) - (T[0] + T[3])); + Tau_prop.z = params->k_drag * (-T[0] + T[1] - T[2] + T[3]); + + // torque from angular damping + Vec3 Tau_aero; + Tau_aero.x = -params->k_ang_damp * state->omega.x; + Tau_aero.y = -params->k_ang_damp * state->omega.y; + Tau_aero.z = -params->k_ang_damp * state->omega.z; + + // gyroscopic torque + Vec3 Tau_iner; + Tau_iner.x = (params->iyy - params->izz) * state->omega.y * state->omega.z; + Tau_iner.y = (params->izz - params->ixx) * state->omega.z * state->omega.x; + Tau_iner.z = (params->ixx - params->iyy) * state->omega.x * state->omega.y; + + // angular velocity rates + Vec3 w_dot; + w_dot.x = (Tau_prop.x + Tau_aero.x + Tau_iner.x) / params->ixx; + w_dot.y = (Tau_prop.y + Tau_aero.y + Tau_iner.y) / params->iyy; + w_dot.z = (Tau_prop.z + Tau_aero.z + Tau_iner.z) / params->izz; + + derivatives->vel = state->vel; + derivatives->v_dot = v_dot; + derivatives->q_dot = q_dot; + derivatives->w_dot = w_dot; + for (int i = 0; i < 4; i++) { + derivatives->rpm_dot[i] = rpm_dot[i]; + } +} + +static inline void step(State* initial, StateDerivative* deriv, float dt, State* output) { + output->pos = add3(initial->pos, scalmul3(deriv->vel, dt)); + output->vel = add3(initial->vel, scalmul3(deriv->v_dot, dt)); + output->quat = add_quat(initial->quat, scalmul_quat(deriv->q_dot, dt)); + output->omega = add3(initial->omega, scalmul3(deriv->w_dot, dt)); + for (int i = 0; i < 4; i++) { + output->rpms[i] = initial->rpms[i] + deriv->rpm_dot[i] * dt; + } + quat_normalize(&output->quat); +} + +static inline void rk4_step(State* state, Params* params, float* actions, float dt) { + StateDerivative k1, k2, k3, k4; + State temp_state; + + compute_derivatives(state, params, actions, &k1); + + step(state, &k1, dt * 0.5f, &temp_state); + compute_derivatives(&temp_state, params, actions, &k2); + + step(state, &k2, dt * 0.5f, &temp_state); + compute_derivatives(&temp_state, params, actions, &k3); + + step(state, &k3, dt, &temp_state); + compute_derivatives(&temp_state, params, actions, &k4); + + float dt_6 = dt / 6.0f; + + state->pos.x += (k1.vel.x + 2.0f * k2.vel.x + 2.0f * k3.vel.x + k4.vel.x) * dt_6; + state->pos.y += (k1.vel.y + 2.0f * k2.vel.y + 2.0f * k3.vel.y + k4.vel.y) * dt_6; + state->pos.z += (k1.vel.z + 2.0f * k2.vel.z + 2.0f * k3.vel.z + k4.vel.z) * dt_6; + + state->vel.x += (k1.v_dot.x + 2.0f * k2.v_dot.x + 2.0f * k3.v_dot.x + k4.v_dot.x) * dt_6; + state->vel.y += (k1.v_dot.y + 2.0f * k2.v_dot.y + 2.0f * k3.v_dot.y + k4.v_dot.y) * dt_6; + state->vel.z += (k1.v_dot.z + 2.0f * k2.v_dot.z + 2.0f * k3.v_dot.z + k4.v_dot.z) * dt_6; + + state->quat.w += (k1.q_dot.w + 2.0f * k2.q_dot.w + 2.0f * k3.q_dot.w + k4.q_dot.w) * dt_6; + state->quat.x += (k1.q_dot.x + 2.0f * k2.q_dot.x + 2.0f * k3.q_dot.x + k4.q_dot.x) * dt_6; + state->quat.y += (k1.q_dot.y + 2.0f * k2.q_dot.y + 2.0f * k3.q_dot.y + k4.q_dot.y) * dt_6; + state->quat.z += (k1.q_dot.z + 2.0f * k2.q_dot.z + 2.0f * k3.q_dot.z + k4.q_dot.z) * dt_6; + + state->omega.x += (k1.w_dot.x + 2.0f * k2.w_dot.x + 2.0f * k3.w_dot.x + k4.w_dot.x) * dt_6; + state->omega.y += (k1.w_dot.y + 2.0f * k2.w_dot.y + 2.0f * k3.w_dot.y + k4.w_dot.y) * dt_6; + state->omega.z += (k1.w_dot.z + 2.0f * k2.w_dot.z + 2.0f * k3.w_dot.z + k4.w_dot.z) * dt_6; + + for (int i = 0; i < 4; i++) { + state->rpms[i] += + (k1.rpm_dot[i] + 2.0f * k2.rpm_dot[i] + 2.0f * k3.rpm_dot[i] + k4.rpm_dot[i]) * dt_6; + } + + quat_normalize(&state->quat); +} + +static inline void move_drone(Drone* drone, float* actions) { + clamp4(actions, -1.0f, 1.0f); + + for (int s = 0; s < ACTION_SUBSTEPS; s++) { + rk4_step(&drone->state, &drone->params, actions, DT); + + clamp3(&drone->state.vel, -drone->params.max_vel, drone->params.max_vel); + clamp3(&drone->state.omega, -drone->params.max_omega, drone->params.max_omega); + + for (int i = 0; i < 4; i++) { + drone->state.rpms[i] = clampf(drone->state.rpms[i], 0.0f, drone->params.max_rpm); + } + } +} + +static inline void reset_rings(unsigned int* rng, Target* ring_buffer, int num_rings) { + ring_buffer[0] = rndring(rng, RING_RADIUS); + + // ensure rings are spaced at least 2*ring_radius apart + for (int i = 1; i < num_rings; i++) { + do { + ring_buffer[i] = rndring(rng, RING_RADIUS); + } while (norm3(sub3(ring_buffer[i].pos, ring_buffer[i - 1].pos)) < 2.0f * RING_RADIUS); + } +} + +static inline Drone* nearest_drone(Drone* agent, Drone* others, int num_agents) { + float min_dist = FLT_MAX; + Drone* nearest = NULL; + + for (int i = 0; i < num_agents; i++) { + Drone* other = &others[i]; + if (other == agent) continue; + + float dist = norm3(sub3(agent->state.pos, other->state.pos)); + + if (dist < min_dist) { + min_dist = dist; + nearest = other; + } + } + + return nearest; +} + +static inline int check_ring(Drone* drone, Target* ring) { + // previous dot product negative if on the 'entry' side of the ring's plane + float prev_dot = dot3(sub3(drone->prev_pos, ring->pos), ring->normal); + float new_dot = dot3(sub3(drone->state.pos, ring->pos), ring->normal); + + bool valid_dir = (prev_dot < 0.0f && new_dot > 0.0f); + bool invalid_dir = (prev_dot > 0.0f && new_dot < 0.0f); + + // if we have crossed the plane of the ring + if (valid_dir || invalid_dir) { + // find intesection with ring's plane + Vec3 dir = sub3(drone->state.pos, drone->prev_pos); + float denom = dot3(ring->normal, dir); + if (fabsf(denom) < 1e-9f) return 0; + + float t = -prev_dot / denom; + Vec3 intersection = add3(drone->prev_pos, scalmul3(dir, t)); + float dist = norm3(sub3(intersection, ring->pos)); + + if (dist < (ring->radius - 0.5f) && valid_dir) { + return 1; + } else if (dist < ring->radius + 0.5f) { + return -1; + } + } + + return 0; +} + +static inline bool check_collision(Drone* agent, Drone* others, int num_agents) { + if (num_agents <= 1) return false; + + Drone* nearest = nearest_drone(agent, others, num_agents); + Vec3 to_nearest = sub3(agent->state.pos, nearest->state.pos); + float nearest_dist = norm3(to_nearest); + + return nearest_dist < 0.1f; +} + +float hover_potential(Drone* agent, float hover_dist, float hover_omega, float hover_vel) { + float dist = norm3(sub3(agent->target->pos, agent->state.pos)); + float vel = norm3(agent->state.vel); + float omega = norm3(agent->state.omega); + + float d = 1.0f / (1.0f + dist / hover_dist); + float v = 1.0f / (1.0f + vel / hover_vel); + float w = 1.0f / (1.0f + omega / hover_omega); + + return d * (0.7f + 0.15f * v + 0.15f * w); +} + +float check_hover(Drone* agent, float hover_dist, float hover_omega, float hover_vel) { + float dist = norm3(sub3(agent->target->pos, agent->state.pos)); + float vel = norm3(agent->state.vel); + float omega = norm3(agent->state.omega); + + float d = dist / (hover_dist * 10.0f); + float v = vel / (hover_vel * 10.0f); + float w = omega / (hover_omega * 10.0f); + + float score = 1.0f - 0.7f * d - 0.15f * v - 0.15f * w; + return score > 0.0f ? score : 0.0f; +} + +void compute_drone_observations(Drone* agent, float* observations) { + int idx = 0; + + // choose the hemisphere with w >= 0 + // to avoid observation sign ambiguity + Quat q = agent->state.quat; + //if (q.w < 0.0f) {q.w=-q.w; q.x=-q.x; q.y=-q.y; q.z=-q.z;} + + Quat q_inv = quat_inverse(q); + Vec3 linear_vel_body = quat_rotate(q_inv, agent->state.vel); + Vec3 to_target_world = sub3(agent->target->pos, agent->state.pos); + Vec3 to_target = quat_rotate(q_inv, to_target_world); + + // we should probably clamp the overall velocity + float denom = agent->params.max_vel * 1.7320508f; // sqrt(3) + observations[idx++] = linear_vel_body.x / denom; + observations[idx++] = linear_vel_body.y / denom; + observations[idx++] = linear_vel_body.z / denom; + + observations[idx++] = agent->state.omega.x / agent->params.max_omega; + observations[idx++] = agent->state.omega.y / agent->params.max_omega; + observations[idx++] = agent->state.omega.z / agent->params.max_omega; + + observations[idx++] = q.w; + observations[idx++] = q.x; + observations[idx++] = q.y; + observations[idx++] = q.z; + + // this is body frame so we have to be careful about scaling + // because distances are relative to the drone orientation + observations[idx++] = tanhf(to_target.x * 0.1f); + observations[idx++] = tanhf(to_target.y * 0.1f); + observations[idx++] = tanhf(to_target.z * 0.1f); + + observations[idx++] = tanhf(to_target.x * 10.0f); + observations[idx++] = tanhf(to_target.y * 10.0f); + observations[idx++] = tanhf(to_target.z * 10.0f); + + Vec3 normal_body = quat_rotate(q_inv, agent->target->normal); + observations[idx++] = normal_body.x; + observations[idx++] = normal_body.y; + observations[idx++] = normal_body.z; + + // rpms should always be last in the obs + observations[idx++] = agent->state.rpms[0] / agent->params.max_rpm; + observations[idx++] = agent->state.rpms[1] / agent->params.max_rpm; + observations[idx++] = agent->state.rpms[2] / agent->params.max_rpm; + observations[idx++] = agent->state.rpms[3] / agent->params.max_rpm; +} \ No newline at end of file diff --git a/ocean/drone/render.h b/ocean/drone/render.h new file mode 100644 index 0000000000..96e4439bfd --- /dev/null +++ b/ocean/drone/render.h @@ -0,0 +1,700 @@ +// Originally made by Sam Turner and Finlay Sanders, 2025. +// Included in pufferlib under the original project's MIT license. +// https://github.com/tensaur/drone + +#pragma once + +#include + +#include "drone.h" +#include "dronelib.h" +#include "raylib.h" +#include "raymath.h" + +#define R (Color){255, 0, 0, 255} +#define W (Color){255, 255, 255, 255} +#define B (Color){0, 0, 255, 255} +Color COLORS[64] = {W, B, B, R, R, B, B, W, B, W, B, R, R, B, W, B, B, B, W, R, R, W, + B, B, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, R, B, B, W, R, + R, W, B, B, B, W, B, R, R, B, W, B, W, B, B, R, R, B, B, W}; +#undef R +#undef W +#undef B + +// 3D model config +#define MODEL_SCALE_DEFAULT 5.0f +#define MODEL_SCALE_NORMAL 1.0f +#define NUM_PROPELLERS 4 +static const int PROP_MESH_IDX[NUM_PROPELLERS] = {8, 6, 5, 7}; +static const float PROP_DIRS[NUM_PROPELLERS] = {1.0f, -1.0f, 1.0f, -1.0f}; + +typedef struct Client Client; + +struct Client { + Camera3D camera; + float width; + float height; + + float camera_distance; + float camera_azimuth; + float camera_elevation; + bool is_dragging; + Vector2 last_mouse_pos; + + Trail* trails; + + int selected_drone; + bool inspect_mode; + bool follow_mode; + int target_fps; + + // Drone 3D model + Model drone_model; + bool model_loaded; + bool use_3d_model; + float* prop_angles; + Vec3 prop_centers[NUM_PROPELLERS]; + float model_scale; + int render_mode; // 0 = default (5.0x), 1 = normal (1.0x), 2 = minimal (sphere only) +}; + +// Convert dronelib Quat to raylib Matrix +static inline Matrix quat_to_matrix(Quat q) { + float xx = q.x * q.x, yy = q.y * q.y, zz = q.z * q.z; + float xy = q.x * q.y, xz = q.x * q.z, yz = q.y * q.z; + float wx = q.w * q.x, wy = q.w * q.y, wz = q.w * q.z; + + Matrix m = {0}; + m.m0 = 1.0f - 2.0f * (yy + zz); + m.m1 = 2.0f * (xy + wz); + m.m2 = 2.0f * (xz - wy); + m.m4 = 2.0f * (xy - wz); + m.m5 = 1.0f - 2.0f * (xx + zz); + m.m6 = 2.0f * (yz + wx); + m.m8 = 2.0f * (xz + wy); + m.m9 = 2.0f * (yz - wx); + m.m10 = 1.0f - 2.0f * (xx + yy); + m.m15 = 1.0f; + return m; +} + +void c_close_client(Client* client) { + if (client->model_loaded) { + UnloadModel(client->drone_model); + } + + if (client->prop_angles) { + free(client->prop_angles); + } + + CloseWindow(); + free(client->trails); + free(client); +} + +static void update_camera_position(Client* c, Vec3 target_pos) { + float r = c->camera_distance; + float az = c->camera_azimuth; + float el = c->camera_elevation; + + float x = r * cosf(el) * cosf(az); + float y = r * cosf(el) * sinf(az); + float z = r * sinf(el); + + if (c->follow_mode) { + c->camera.target = (Vector3){target_pos.x, target_pos.y, target_pos.z}; + c->camera.position = (Vector3){target_pos.x + x, target_pos.y + y, target_pos.z + z}; + } else { + c->camera.target = (Vector3){0, 0, 0}; + c->camera.position = (Vector3){x, y, z}; + } +} + +void handle_camera_controls(Client* client, Vec3 target_pos, float min_zoom) { + Vector2 mouse_pos = GetMousePosition(); + + if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) { + client->is_dragging = true; + client->last_mouse_pos = mouse_pos; + } + + if (IsMouseButtonReleased(MOUSE_BUTTON_LEFT)) { + client->is_dragging = false; + } + + if (client->is_dragging && IsMouseButtonDown(MOUSE_BUTTON_LEFT)) { + Vector2 mouse_delta = {mouse_pos.x - client->last_mouse_pos.x, + mouse_pos.y - client->last_mouse_pos.y}; + + float sensitivity = 0.005f; + + client->camera_azimuth -= mouse_delta.x * sensitivity; + + client->camera_elevation += mouse_delta.y * sensitivity; + client->camera_elevation = + clampf(client->camera_elevation, -PI / 2.0f + 0.1f, PI / 2.0f - 0.1f); + + client->last_mouse_pos = mouse_pos; + + update_camera_position(client, target_pos); + } + + float wheel = GetMouseWheelMove(); + if (wheel != 0) { + client->camera_distance -= wheel * 2.0f; + client->camera_distance = clampf(client->camera_distance, min_zoom, 100.0f); + update_camera_position(client, target_pos); + } +} + +void handle_drone_selection(Client* client, int num_agents, float dt) { + static float repeat_timer = 0; + static bool key_held = false; + + if (IsKeyDown(KEY_D) || IsKeyDown(KEY_A)) { + if (!key_held || repeat_timer <= 0) { + if (IsKeyDown(KEY_D)) { + client->selected_drone = (client->selected_drone + 1) % num_agents; + } + + if (IsKeyDown(KEY_A)) { + client->selected_drone = (client->selected_drone - 1 + num_agents) % num_agents; + } + + repeat_timer = key_held ? 0.05f : 0.3f; + key_held = true; + } + + repeat_timer -= dt; + } else { + key_held = false; + repeat_timer = 0; + } +} + +void handle_fps_control(Client* client, float dt) { + static float repeat_timer = 0; + static bool key_held = false; + + if (IsKeyDown(KEY_W) || IsKeyDown(KEY_S)) { + if (!key_held || repeat_timer <= 0) { + if (IsKeyDown(KEY_W)) { + client->target_fps += 10; + if (client->target_fps > 240) client->target_fps = 240; + } + + if (IsKeyDown(KEY_S)) { + client->target_fps -= 10; + if (client->target_fps < 10) client->target_fps = 10; + } + + SetTargetFPS(client->target_fps); + repeat_timer = key_held ? 0.05f : 0.3f; + key_held = true; + } + + repeat_timer -= dt; + } else { + key_held = false; + repeat_timer = 0; + } +} + +// Compute center of mesh from vertices +static Vec3 compute_mesh_center(Mesh* mesh) { + Vec3 center = {0, 0, 0}; + + for (int v = 0; v < mesh->vertexCount; v++) { + center.x += mesh->vertices[v * 3 + 0]; + center.y += mesh->vertices[v * 3 + 1]; + center.z += mesh->vertices[v * 3 + 2]; + } + + return scalmul3(center, 1.0f / mesh->vertexCount); +} + +Client* make_client(DroneEnv* env) { + Client* client = (Client*)calloc(1, sizeof(Client)); + + client->width = WIDTH; + client->height = HEIGHT; + + SetConfigFlags(FLAG_MSAA_4X_HINT); + InitWindow(WIDTH, HEIGHT, "PufferLib Drone"); + +#ifndef __EMSCRIPTEN__ + SetTargetFPS(60); +#endif + + if (!IsWindowReady()) { + TraceLog(LOG_ERROR, "Window failed to initialize\n"); + free(client); + return NULL; + } + + client->camera_distance = 40.0f; + client->camera_azimuth = 0.0f; + client->camera_elevation = PI / 10.0f; + client->is_dragging = false; + client->last_mouse_pos = (Vector2){0.0f, 0.0f}; + + client->camera.up = (Vector3){0.0f, 0.0f, 1.0f}; + client->camera.fovy = 45.0f; + client->camera.projection = CAMERA_PERSPECTIVE; + + Vec3 origin = {0, 0, 0}; + update_camera_position(client, origin); + + // Initialize trail buffer + client->trails = (Trail*)calloc(env->num_agents, sizeof(Trail)); + for (int i = 0; i < env->num_agents; i++) { + Trail* trail = &client->trails[i]; + trail->index = 0; + trail->count = 0; + for (int j = 0; j < TRAIL_LENGTH; j++) { + trail->pos[j] = env->agents[i].state.pos; + } + } + + client->selected_drone = 0; + client->inspect_mode = false; + client->follow_mode = false; + client->target_fps = 100; + client->model_loaded = false; + client->model_scale = MODEL_SCALE_DEFAULT; + client->render_mode = 0; + + // Load 3D model + const char* model_paths[] = {"resources/crazyflie.glb", "resources/drone/crazyflie.glb", + "crazyflie.glb", NULL}; + + for (int i = 0; model_paths[i] != NULL; i++) { + if (FileExists(model_paths[i])) { + client->drone_model = LoadModel(model_paths[i]); + + if (client->drone_model.meshCount > 0) { + client->model_loaded = true; + TraceLog(LOG_INFO, "Loaded drone model: %s", model_paths[i]); + + // Cache propeller centers + for (int p = 0; p < NUM_PROPELLERS; p++) { + int idx = PROP_MESH_IDX[p]; + + if (idx < client->drone_model.meshCount) { + client->prop_centers[p] = + compute_mesh_center(&client->drone_model.meshes[idx]); + } + } + + break; + } + } + } + + client->use_3d_model = client->model_loaded; + client->prop_angles = (float*)calloc(env->num_agents * NUM_PROPELLERS, sizeof(float)); + + return client; +} + +const Color PUFF_RED = (Color){187, 0, 0, 255}; +const Color PUFF_CYAN = (Color){0, 187, 187, 255}; +const Color PUFF_WHITE = (Color){241, 241, 241, 241}; +const Color PUFF_BACKGROUND = (Color){6, 24, 24, 255}; +const Color PUFF_GREEN = (Color){0, 220, 80, 255}; + +void DrawRing3D(Target ring, float thickness, Color entryColor, Color exitColor) { + float half_thick = thickness / 2.0f; + + Vector3 center_pos = {ring.pos.x, ring.pos.y, ring.pos.z}; + + Vector3 entry_start_pos = {center_pos.x - half_thick * ring.normal.x, + center_pos.y - half_thick * ring.normal.y, + center_pos.z - half_thick * ring.normal.z}; + + DrawCylinderWiresEx(entry_start_pos, center_pos, ring.radius, ring.radius, 32, entryColor); + + Vector3 exit_end_pos = {center_pos.x + half_thick * ring.normal.x, + center_pos.y + half_thick * ring.normal.y, + center_pos.z + half_thick * ring.normal.z}; + + DrawCylinderWiresEx(center_pos, exit_end_pos, ring.radius, ring.radius, 32, exitColor); +} + +void DrawDroneModel(Client* client, Drone* agent, int drone_idx, float dt, Color body_color) { + if (!client->model_loaded) return; + + Model* model = &client->drone_model; + float* angles = &client->prop_angles[drone_idx * NUM_PROPELLERS]; + + // Update propeller angles from RPM + for (int p = 0; p < NUM_PROPELLERS; p++) { + float rpm = agent->state.rpms[p]; + angles[p] += rpm * (2.0f * PI / 60.0f) * dt * PROP_DIRS[p]; + + if (angles[p] > 2.0f * PI) angles[p] -= 2.0f * PI; + if (angles[p] < 0.0f) angles[p] += 2.0f * PI; + } + + // Build world transform matrices using client's model_scale + float scale = client->model_scale; + Matrix mScale = MatrixScale(scale, scale, scale); + Matrix mRot = quat_to_matrix(agent->state.quat); + Matrix mTrans = MatrixTranslate(agent->state.pos.x, agent->state.pos.y, agent->state.pos.z); + + Matrix droneWorld = MatrixMultiply(MatrixMultiply(mScale, mRot), mTrans); + + // Draw each mesh + for (int m = 0; m < model->meshCount; m++) { + Matrix meshWorld = droneWorld; + + // Check if this mesh is a propeller + bool is_prop = false; + for (int p = 0; p < NUM_PROPELLERS; p++) { + if (m == PROP_MESH_IDX[p]) { + is_prop = true; + Vec3 c = client->prop_centers[p]; + Matrix toOrigin = MatrixTranslate(-c.x, -c.y, -c.z); + Matrix spin = MatrixRotateZ(angles[p]); + Matrix fromOrigin = MatrixTranslate(c.x, c.y, c.z); + Matrix propLocal = MatrixMultiply(MatrixMultiply(toOrigin, spin), fromOrigin); + meshWorld = MatrixMultiply(propLocal, droneWorld); + break; + } + } + + Material mat = model->materials[model->meshMaterial[m]]; + + Color origColor = mat.maps[MATERIAL_MAP_DIFFUSE].color; + int brightness = (origColor.r + origColor.g + origColor.b) / 3; + + if (is_prop || brightness > 64) { + mat.maps[MATERIAL_MAP_DIFFUSE].color = body_color; + } else { + mat.maps[MATERIAL_MAP_DIFFUSE].color = origColor; + } + + DrawMesh(model->meshes[m], mat, meshWorld); + } +} + +void DrawDronePrimitive(Client* client, Drone* agent, float* actions, Color body_color) { + const float scale = client->model_scale; + + DrawSphere((Vector3){agent->state.pos.x, agent->state.pos.y, agent->state.pos.z}, 0.06f * scale, + body_color); + + const float rotor_radius = 0.03f * scale; + const float arm_len = 0.15f * scale; + const float diag = arm_len * 0.7071f; // 1/sqrt(2) + + Vec3 rotor_offsets[4] = { + {+diag, +diag, 0.0f}, {+diag, -diag, 0.0f}, {-diag, -diag, 0.0f}, {-diag, +diag, 0.0f}}; + + for (int j = 0; j < 4; j++) { + Vec3 world_off = quat_rotate(agent->state.quat, rotor_offsets[j]); + + Vector3 rotor_pos = {agent->state.pos.x + world_off.x, agent->state.pos.y + world_off.y, + agent->state.pos.z + world_off.z}; + + float rpm = (actions[j] + 1.0f) * 0.5f * agent->params.max_rpm; + float intensity = 0.75f + 0.25f * (rpm / agent->params.max_rpm); + + Color rotor_color = (Color){(unsigned char)(body_color.r * intensity), + (unsigned char)(body_color.g * intensity), + (unsigned char)(body_color.b * intensity), 255}; + + DrawSphere(rotor_pos, rotor_radius, rotor_color); + DrawCylinderEx((Vector3){agent->state.pos.x, agent->state.pos.y, agent->state.pos.z}, + rotor_pos, 0.004f * scale, 0.004f * scale, 8, BLACK); + } +} + +void c_render(DroneEnv* env) { + if (env->client == NULL) { + env->client = make_client(env); + + if (env->client == NULL) { + TraceLog(LOG_ERROR, "Failed to initialize client for rendering\n"); + return; + } + } + + if (WindowShouldClose() || IsKeyDown(KEY_ESCAPE)) { + c_close(env); + exit(0); + } + + if (IsKeyPressed(KEY_SPACE)) { + env->task = (DroneTask)((env->task + 1) % TASK_N); + + if (env->task == RACE) { + reset_rings(&env->rng, env->ring_buffer, env->max_rings); + } + + for (int i = 0; i < env->num_agents; i++) { + set_target(&env->rng, env->task, env->agents, i, env->num_agents, env->hover_target_dist); + } + } + + Client* client = env->client; + float dt = GetFrameTime(); + + // Get selected drone position for camera + Vec3 drone_pos = env->agents[client->selected_drone].state.pos; + + // Calculate min zoom based on render mode and hover_dist + float min_zoom = (client->render_mode == 2) ? env->hover_dist + : (client->render_mode == 1) ? 1.0f + : 5.0f; + + handle_camera_controls(client, drone_pos, min_zoom); + handle_drone_selection(client, env->num_agents, dt); + handle_fps_control(client, dt); + + if (IsKeyPressed(KEY_TAB)) { + client->inspect_mode = !client->inspect_mode; + // When entering inspect mode, turn on follow mode by default + if (client->inspect_mode) { + client->follow_mode = true; + update_camera_position(client, drone_pos); + } else { + // When exiting inspect mode, turn off follow mode + client->follow_mode = false; + update_camera_position(client, drone_pos); + } + } + + if (IsKeyPressed(KEY_M) && client->model_loaded) { + client->use_3d_model = !client->use_3d_model; + } + + if (IsKeyPressed(KEY_F)) { + client->follow_mode = !client->follow_mode; + } + + if (IsKeyPressed(KEY_Z)) { + client->render_mode = (client->render_mode + 1) % 3; + if (client->render_mode == 0) { + client->model_scale = MODEL_SCALE_DEFAULT; + } else if (client->render_mode == 1) { + client->model_scale = MODEL_SCALE_NORMAL; + } + // render_mode 2 = minimal, drone hidden + + float new_min_zoom = (client->render_mode == 2) ? env->hover_dist + : (client->render_mode == 1) ? 1.0f + : 5.0f; + if (client->camera_distance < new_min_zoom) { + client->camera_distance = new_min_zoom; + update_camera_position(client, drone_pos); + } + } + + // Update camera position every frame when in follow mode + if (client->follow_mode) { + update_camera_position(client, drone_pos); + } + + bool inspect_mode = client->inspect_mode; + + // Update trails + for (int i = 0; i < env->num_agents; i++) { + Drone* agent = &env->agents[i]; + Trail* trail = &client->trails[i]; + trail->pos[trail->index] = agent->state.pos; + trail->index = (trail->index + 1) % TRAIL_LENGTH; + if (trail->count < TRAIL_LENGTH) { + trail->count++; + } + if (env->terminals[i]) { + trail->index = 0; + trail->count = 0; + } + } + + BeginDrawing(); + ClearBackground(PUFF_BACKGROUND); + BeginMode3D(client->camera); + + // Bounding cube + DrawCubeWires((Vector3){0, 0, 0}, GRID_X * 2.0f, GRID_Y * 2.0f, GRID_Z * 2.0f, WHITE); + + // Draw drones + for (int i = 0; i < env->num_agents; i++) { + Drone* agent = &env->agents[i]; + bool is_selected = (i == client->selected_drone); + Color body_color = (inspect_mode && is_selected) ? PUFF_GREEN : COLORS[i % 64]; + + if (client->render_mode == 2) { + // Minimal mode: draw small sphere matching hover_dist size + float sphere_size = env->hover_dist; + // Use a distinct color (yellow/orange) to differentiate from target + Color drone_sphere_color = (inspect_mode && is_selected) ? (Color){255, 200, 0, 255} + : (Color){255, 165, 0, 200}; + DrawSphere((Vector3){agent->state.pos.x, agent->state.pos.y, agent->state.pos.z}, + sphere_size, drone_sphere_color); + } else if (client->use_3d_model && client->model_loaded) { + DrawDroneModel(client, agent, i, dt, body_color); + } else { + DrawDronePrimitive(client, agent, &env->actions[4 * i], body_color); + } + + // Velocity vector + if (norm3(agent->state.vel) > 0.1f) { + Vec3 p = agent->state.pos; + Vec3 v = scalmul3(agent->state.vel, 0.1f); + DrawLine3D((Vector3){p.x, p.y, p.z}, (Vector3){p.x + v.x, p.y + v.y, p.z + v.z}, + MAGENTA); + } + + // Target line (shown in inspect mode) + if (inspect_mode && is_selected) { + Vec3 p = agent->state.pos; + Vec3 t = agent->target->pos; + DrawLine3D((Vector3){p.x, p.y, p.z}, (Vector3){t.x, t.y, t.z}, + ColorAlpha(PUFF_GREEN, 0.5f)); + } + + // Draw trailing path for each drone + Trail* trail = &client->trails[i]; + if (trail->count > 2) { + Color trail_color = (inspect_mode && is_selected) ? PUFF_GREEN : PUFF_CYAN; + + for (int j = 0; j < trail->count - 1; j++) { + int idx0 = (trail->index - j - 1 + TRAIL_LENGTH) % TRAIL_LENGTH; + int idx1 = (trail->index - j - 2 + TRAIL_LENGTH) % TRAIL_LENGTH; + + float alpha = (float)(TRAIL_LENGTH - j) / (float)trail->count * 0.8f; + Vec3 p0 = trail->pos[idx0], p1 = trail->pos[idx1]; + + DrawLine3D((Vector3){p0.x, p0.y, p0.z}, (Vector3){p1.x, p1.y, p1.z}, + ColorAlpha(trail_color, alpha)); + } + } + } + + // Rings if in race mode + if (env->task == RACE) { + for (int i = 0; i < env->max_rings; i++) { + DrawRing3D(env->ring_buffer[i], 0.2f, GREEN, BLUE); + } + } + + // Targets (shown in inspect mode) - size based on render mode + if (inspect_mode) { + float target_size; + if (client->render_mode == 2) { + // Minimal mode: target size matches hover_dist + target_size = env->hover_dist; + } else if (client->render_mode == 1) { + // 1.0x scale: target proportional to drone at normal scale + target_size = 0.1f; + } else { + // 5.0x scale: target proportional to drone at default scale + target_size = 0.5f; + } + + for (int i = 0; i < env->num_agents; i++) { + Vec3 t = env->agents[i].target->pos; + bool is_selected = (i == client->selected_drone); + float size = is_selected ? target_size * 1.1f : target_size; + DrawSphere((Vector3){t.x, t.y, t.z}, size, + is_selected ? (Color){0, 255, 100, 180} : (Color){0, 255, 255, 100}); + } + } + + EndMode3D(); + + // Heads up display + int y = 10; + DrawText(TextFormat("Task: %s", TASK_NAMES[env->task]), 10, y, 20, WHITE); + y += 25; + DrawText(TextFormat("Tick: %d / %d", env->tick, HORIZON), 10, y, 20, WHITE); + y += 25; + DrawText(TextFormat("FPS: %d (W/S to adjust)", client->target_fps), 10, y, 18, WHITE); + y += 22; + if (client->model_loaded) { + DrawText(TextFormat("Render: %s (M)", client->use_3d_model ? "3D Model" : "Primitive"), 10, + y, 18, client->use_3d_model ? PUFF_GREEN : LIGHTGRAY); + y += 22; + const char* mode_names[] = {"5.0x", "1.0x", "Minimal"}; + Color mode_color = (client->render_mode == 2) ? YELLOW + : (client->render_mode == 1) ? PUFF_GREEN + : LIGHTGRAY; + DrawText(TextFormat("Scale: %s (Z)", mode_names[client->render_mode]), 10, y, 18, + mode_color); + } + y += 22; + DrawText(TextFormat("Follow: %s (F)", client->follow_mode ? "ON" : "OFF"), 10, y, 18, + client->follow_mode ? PUFF_GREEN : LIGHTGRAY); + y += 30; + + // Inspect mode stats + if (inspect_mode) { + int idx = client->selected_drone; + Drone* agent = &env->agents[idx]; + + DrawText(TextFormat("Drone: %d / %d (A/D to switch)", idx, env->num_agents - 1), 10, y, 20, + PUFF_GREEN); + y += 30; + DrawText(TextFormat("Pos: (%.1f, %.1f, %.1f)", agent->state.pos.x, agent->state.pos.y, + agent->state.pos.z), + 10, y, 18, WHITE); + y += 20; + DrawText(TextFormat("Vel: %.2f m/s", norm3(agent->state.vel)), 10, y, 18, WHITE); + y += 20; + DrawText(TextFormat("Omega: (%.1f, %.1f, %.1f)", agent->state.omega.x, agent->state.omega.y, + agent->state.omega.z), + 10, y, 18, WHITE); + y += 25; + + // Motor RPM bars + DrawText("Motor RPMs:", 10, y, 18, WHITE); + y += 22; + int bar_w = 150, bar_h = 14; + Color motor_colors[4] = {ORANGE, PURPLE, LIME, SKYBLUE}; + const char* motor_names[4] = {"M1", "M2", "M3", "M4"}; + + for (int m = 0; m < 4; m++) { + float pct = clampf(agent->state.rpms[m] / agent->params.max_rpm, 0.0f, 1.0f); + int fill_w = (int)(pct * bar_w); + + // Label + DrawText(motor_names[m], 10, y, 16, motor_colors[m]); + + // Bar background + DrawRectangle(35, y, bar_w, bar_h, (Color){40, 40, 40, 255}); + + // Bar fill + DrawRectangle(35, y, fill_w, bar_h, motor_colors[m]); + + // Bar outline + DrawRectangleLines(35, y, bar_w, bar_h, LIGHTGRAY); + + // RPM value text + DrawText(TextFormat("%.0f", agent->state.rpms[m]), 35 + bar_w + 5, y, 14, WHITE); + + y += bar_h + 4; + } + + y += 10; + + DrawText(TextFormat("Episode Return: %.4f", agent->episode_return), 10, y, 18, WHITE); + y += 20; + DrawText(TextFormat("Episode Length: %d", agent->episode_length), 10, y, 18, WHITE); + y += 30; + } + + // Controls (always visible) + DrawText("Left click + drag: Rotate camera", 10, y, 16, LIGHTGRAY); + y += 18; + DrawText("Mouse wheel: Zoom in/out", 10, y, 16, LIGHTGRAY); + y += 18; + DrawText("Space: Change task", 10, y, 16, LIGHTGRAY); + y += 18; + DrawText(TextFormat("Tab: Inspect mode [%s]", inspect_mode ? "ON" : "OFF"), 10, y, 16, + inspect_mode ? PUFF_GREEN : LIGHTGRAY); + + EndDrawing(); +} diff --git a/ocean/drone/tasks.h b/ocean/drone/tasks.h new file mode 100644 index 0000000000..b0bd35939d --- /dev/null +++ b/ocean/drone/tasks.h @@ -0,0 +1,157 @@ +// Originally made by Sam Turner and Finlay Sanders, 2025. +// Included in pufferlib under the original project's MIT license. +// https://github.com/tensaur/drone + +#pragma once + +#include +#include +#include + +#include "dronelib.h" + +typedef enum { + IDLE, + HOVER, + ORBIT, + FOLLOW, + CUBE, + CONGO, + FLAG, + RACE, + TASK_N // Should always be last +} DroneTask; + +static char const* TASK_NAMES[TASK_N] = {"idle", "hover", "orbit", "follow", + "cube", "congo", "flag", "race"}; + +DroneTask get_task(char* task_name) { + for (size_t i = 0; i < TASK_N; i++) { + if (strcasecmp(TASK_NAMES[i], task_name) == 0) { + return (DroneTask)i; + } + } + + return HOVER; +} + +void move_target(Drone* agent) { + agent->target->pos.x += agent->target->vel.x; + agent->target->pos.y += agent->target->vel.y; + agent->target->pos.z += agent->target->vel.z; + + if (agent->target->pos.x < -MARGIN_X || agent->target->pos.x > MARGIN_X) { + agent->target->vel.x = -agent->target->vel.x; + } + if (agent->target->pos.y < -MARGIN_Y || agent->target->pos.y > MARGIN_Y) { + agent->target->vel.y = -agent->target->vel.y; + } + if (agent->target->pos.z < -MARGIN_Z || agent->target->pos.z > MARGIN_Z) { + agent->target->vel.z = -agent->target->vel.z; + } +} + +void set_target_idle(unsigned int* rng, Drone* agent) { + agent->target->pos = + (Vec3){rndf(-MARGIN_X, MARGIN_X, rng), rndf(-MARGIN_Y, MARGIN_Y, rng), rndf(-MARGIN_Z, MARGIN_Z, rng)}; + agent->target->vel = + (Vec3){rndf(-V_TARGET, V_TARGET, rng), rndf(-V_TARGET, V_TARGET, rng), rndf(-V_TARGET, V_TARGET, rng)}; +} + +void set_target_hover(unsigned int* rng, Drone* agent, float hover_target_dist) { + // uniform direction on sphere + float u = rndf(0.0f, 1.0f, rng); + float v = rndf(0.0f, 1.0f, rng); + float z = 2.0f * v - 1.0f; + float a = 2.0f * (float)M_PI * u; + float r_xy = sqrtf(fmaxf(0.0f, 1.0f - z * z)); + Vec3 dir = (Vec3){r_xy * cosf(a), r_xy * sinf(a), z}; + + // uniform radius in ball + float rad = hover_target_dist * cbrtf(rndf(0.0f, 1.0f, rng)); + Vec3 p = add3(agent->state.pos, scalmul3(dir, rad)); + + // clamp to grid bounds + agent->target->pos = (Vec3){ + clampf(p.x, -MARGIN_X, MARGIN_X), + clampf(p.y, -MARGIN_Y, MARGIN_Y), + clampf(p.z, -MARGIN_Z, MARGIN_Z) + }; + agent->target->vel = (Vec3){0.0f, 0.0f, 0.0f}; +} + +void set_target_orbit(Drone* agent, int idx, int num_agents) { + // Fibbonacci sphere algorithm + float R = 8.0f; + float phi = M_PI * (sqrt(5.0f) - 1.0f); + float y = 1.0f - 2 * ((float)idx / (float)num_agents); + float radius = sqrtf(1.0f - y * y); + + float theta = phi * idx; + float x = cos(theta) * radius; + float z = sin(theta) * radius; + + agent->target->pos = (Vec3){R * x, R * z, R * y}; // convert to z up + agent->target->vel = (Vec3){0.0f, 0.0f, 0.0f}; +} + +void set_target_follow(unsigned int* rng, Drone* agents, int idx) { + Drone* agent = &agents[idx]; + + if (idx == 0) { + set_target_idle(rng, agent); + } else { + agent->target->pos = agents[0].target->pos; + agent->target->vel = agents[0].target->vel; + } +} + +void set_target_cube(Drone* agent, int idx) { + float z = idx / 16; + idx = idx % 16; + float x = (float)(idx % 4); + float y = (float)(idx / 4); + agent->target->pos = (Vec3){4 * x - 6, 4 * y - 6, 4 * z - 6}; + agent->target->vel = (Vec3){0.0f, 0.0f, 0.0f}; +} + +void set_target_congo(unsigned int* rng, Drone* agents, int idx) { + if (idx == 0) { + set_target_idle(rng, &agents[0]); + return; + } + + Drone* follow = &agents[idx - 1]; + Drone* lead = &agents[idx]; + lead->target->pos = follow->target->pos; + lead->target->vel = follow->target->vel; + + // TODO: Slow hack + for (int i = 0; i < 40; i++) { + move_target(lead); + } +} + +void set_target_flag(Drone* agent, int idx) { + float x = (float)(idx % 8); + float y = (float)(idx / 8); + x = 2.0f * x - 7; + y = 5 - 1.5f * y; + agent->target->pos = (Vec3){0.0f, x, y}; + agent->target->vel = (Vec3){0.0f, 0.0f, 0.0f}; +} + +void set_target_race(Drone* agent) { *agent->target = agent->buffer[agent->buffer_idx]; } + +void set_target(unsigned int* rng, DroneTask task, Drone* agents, int idx, int num_agents, float hover_target_dist) { + Drone* agent = &agents[idx]; + + if (task == IDLE) set_target_idle(rng, agent); + else if (task == HOVER) set_target_hover(rng, agent, hover_target_dist); + else if (task == ORBIT) set_target_orbit(agent, idx, num_agents); + else if (task == FOLLOW) set_target_follow(rng, agents, idx); + else if (task == CUBE) set_target_cube(agent, idx); + else if (task == CONGO) set_target_congo(rng, agents, idx); + else if (task == FLAG) set_target_flag(agent, idx); + else if (task == RACE) set_target_race(agent); +} diff --git a/ocean/enduro/binding.c b/ocean/enduro/binding.c new file mode 100644 index 0000000000..e49da0b6b5 --- /dev/null +++ b/ocean/enduro/binding.c @@ -0,0 +1,36 @@ +#include "enduro.h" +#define OBS_SIZE 68 +#define NUM_ATNS 1 +#define ACT_SIZES {9} +#define OBS_TENSOR_T FloatTensor + +#define Env Enduro +#include "vecenv.h" + +void my_init(Env* env, Dict* kwargs) { + env->num_agents = 1; + env->width = dict_get(kwargs, "width")->value; + env->height = dict_get(kwargs, "height")->value; + env->car_width = dict_get(kwargs, "car_width")->value; + env->car_height = dict_get(kwargs, "car_height")->value; + env->max_enemies = dict_get(kwargs, "max_enemies")->value; + env->continuous = dict_get(kwargs, "continuous")->value; + init(env); +} + +void my_log(Log* log, Dict* out) { + dict_set(out, "perf", log->perf); + dict_set(out, "score", log->score); + dict_set(out, "episode_return", log->episode_return); + dict_set(out, "episode_length", log->episode_length); + dict_set(out, "reward", log->reward); + dict_set(out, "step_rew_car_passed_no_crash", log->step_rew_car_passed_no_crash); + dict_set(out, "crashed_penalty", log->crashed_penalty); + dict_set(out, "passed_cars", log->passed_cars); + dict_set(out, "passed_by_enemy", log->passed_by_enemy); + dict_set(out, "cars_to_pass", log->cars_to_pass); + dict_set(out, "days_completed", log->days_completed); + dict_set(out, "days_failed", log->days_failed); + dict_set(out, "collisions_player_vs_car", log->collisions_player_vs_car); + dict_set(out, "collisions_player_vs_road", log->collisions_player_vs_road); +} diff --git a/pufferlib/ocean/enduro/enduro.c b/ocean/enduro/enduro.c similarity index 74% rename from pufferlib/ocean/enduro/enduro.c rename to ocean/enduro/enduro.c index 01cbe15fa7..ec496febe0 100644 --- a/pufferlib/ocean/enduro/enduro.c +++ b/ocean/enduro/enduro.c @@ -33,9 +33,9 @@ void get_input(Enduro* env) { } int demo() { - Weights* weights = load_weights("resources/enduro/enduro_weights.bin", 142218); + Weights* weights = load_weights("resources/enduro/enduro_weights.bin"); int logit_sizes[1] = {9}; - LinearLSTM* net = make_linearlstm(weights, 1, 68, logit_sizes, 1); + PufferNet* net = make_puffernet(weights, 1, 68, 128, 2, logit_sizes, 1); Enduro env = { .num_envs = 1, @@ -53,45 +53,20 @@ int demo() { if (IsKeyDown(KEY_LEFT_SHIFT)) { get_input(&env); } else { - forward_linearlstm(net, env.observations, env.actions); + forward_puffernet(net, env.observations, env.actions); } c_step(&env); c_render(&env); } - free_linearlstm(net); + free_puffernet(net); free(weights); free_allocated(&env); return 0; } -void perftest(float test_time) { - Enduro env = { - .num_envs = 1, - .max_enemies = MAX_ENEMIES, - .obs_size = OBSERVATIONS_MAX_SIZE - }; - - allocate(&env); - init(&env); - c_reset(&env); - - int start = time(NULL); - int i = 0; - while (time(NULL) - start < test_time) { - env.actions[0] = rand()%9; - c_step(&env); - i++; - } - - int end = time(NULL); - printf("SPS: %f\n", i / (float)(end - start)); - free_allocated(&env); -} - int main() { demo(); - //perftest(10.0f); return 0; } diff --git a/pufferlib/ocean/enduro/enduro.h b/ocean/enduro/enduro.h similarity index 98% rename from pufferlib/ocean/enduro/enduro.h rename to ocean/enduro/enduro.h index 0961caf3c4..1fa4759668 100644 --- a/pufferlib/ocean/enduro/enduro.h +++ b/ocean/enduro/enduro.h @@ -181,9 +181,10 @@ typedef struct Enduro { Client* client; Log log; float* observations; - int* actions; + float* actions; float* rewards; - unsigned char* terminals; + float* terminals; + int num_agents; size_t obs_size; int num_envs; float width; @@ -271,6 +272,7 @@ typedef struct Enduro { int currentDayTimeIndex; int previousDayTimeIndex; // RNG + unsigned int rng; unsigned int rng_state; int reset_count; // Rewards @@ -689,10 +691,7 @@ void init(Enduro* env) { env->parallaxFactor = 1.0f; env->dayCompleted = 0; env->lane = 1; - env->terminals[0] = 0; - // Reset rewards and logs - env->rewards[0] = 0.0f; // Initialize tracking variables env->tracking_episode_return = 0.0f; env->tracking_episode_length = 0.0f; @@ -707,28 +706,13 @@ void init(Enduro* env) { env->tracking_days_failed = 0.0f; env->tracking_collisions_player_vs_car = 0.0f; env->tracking_collisions_player_vs_road = 0.0f; - - env->log.episode_return = 0.0f; - env->log.episode_length = 0.0f; - env->log.score = 0.0f; - env->log.reward = 0.0f; - env->log.step_rew_car_passed_no_crash = 0.0f; - env->log.crashed_penalty = 0.0f; - env->log.passed_cars = 0.0f; - env->log.passed_by_enemy = 0.0f; - env->log.cars_to_pass = INITIAL_CARS_TO_PASS; - env->log.days_completed = 0; - env->log.days_failed = 0; - env->log.collisions_player_vs_car = 0.0f; - env->log.collisions_player_vs_road = 0.0f; - env->log.n = 0.0f; } void allocate(Enduro* env) { env->observations = (float*)calloc(env->obs_size, sizeof(float)); - env->actions = (int*)calloc(1, sizeof(int)); + env->actions = (float*)calloc(1, sizeof(float)); env->rewards = (float*)calloc(1, sizeof(float)); - env->terminals = (unsigned char*)calloc(1, sizeof(unsigned char)); + env->terminals = (float*)calloc(1, sizeof(float)); } void free_allocated(Enduro* env) { @@ -929,9 +913,9 @@ void add_enemy_car(Enduro* env) { } // Randomly select a lane - int lane = possible_lanes[rand() % num_possible_lanes]; + int lane = possible_lanes[rand_r(&env->rng) % num_possible_lanes]; // Preferentially spawn in the last_spawned_lane 30% of the time - if (rand() % 100 < 60 && env->last_spawned_lane != -1) { + if (rand_r(&env->rng) % 100 < 60 && env->last_spawned_lane != -1) { lane = env->last_spawned_lane; } env->last_spawned_lane = lane; @@ -943,14 +927,14 @@ void add_enemy_car(Enduro* env) { .last_x = car_x_in_lane(env, lane, VANISHING_POINT_Y), .last_y = VANISHING_POINT_Y, .passed = false, - .colorIndex = rand() % 6 + .colorIndex = rand_r(&env->rng) % 6 }; // Ensure minimum spacing between cars in the same lane float depth = (car.y - VANISHING_POINT_Y) / (PLAYABLE_AREA_BOTTOM - VANISHING_POINT_Y); float scale = fmax(0.1f, 0.9f * depth + 0.1f); float scaled_car_length = CAR_HEIGHT * scale; // Randomize min spacing between 1.0f and 6.0f car lengths - float dynamic_spacing_factor = (rand() / (float)RAND_MAX) * 6.0f + 0.5f; + float dynamic_spacing_factor = (rand_r(&env->rng) / (float)RAND_MAX) * 6.0f + 0.5f; float min_spacing = dynamic_spacing_factor * scaled_car_length; for (int i = 0; i < env->numEnemies; i++) { Car* existing_car = &env->enemyCars[i]; @@ -1374,8 +1358,8 @@ void c_step(Enduro* env) { int num_to_spawn = 1; // Randomly decide to spawn more cars in a clump - if ((rand() / (float)RAND_MAX) < clump_probability) { - num_to_spawn = 1 + rand() % 2; // Spawn 1 to 3 cars + if ((rand_r(&env->rng) / (float)RAND_MAX) < clump_probability) { + num_to_spawn = 1 + rand_r(&env->rng) % 2; // Spawn 1 to 3 cars } // Track occupied lanes to prevent over-blocking @@ -1385,7 +1369,7 @@ void c_step(Enduro* env) { // Find an unoccupied lane int lane; do { - lane = rand() % NUM_LANES; + lane = rand_r(&env->rng) % NUM_LANES; } while (occupied_lanes[lane]); // Mark the lane as occupied @@ -1611,14 +1595,14 @@ void update_road_curve(Enduro* env) { for (int i = 0; i < 3; i++) { // Generate random step thresholds - step_thresholds[i] = 1500 + rand() % 3801; // Random value between 1500 and 3800 + step_thresholds[i] = 1500 + rand_r(&env->rng) % 3801; // Random value between 1500 and 3800 // Generate a random curve direction (-1, 0, 1) with rules int direction_choices[] = {-1, 0, 1}; int next_direction; do { - next_direction = direction_choices[rand() % 3]; + next_direction = direction_choices[rand_r(&env->rng) % 3]; } while ((last_direction == -1 && next_direction == 1) || (last_direction == 1 && next_direction == -1)); curve_directions[i] = next_direction; diff --git a/ocean/freeway/binding.c b/ocean/freeway/binding.c new file mode 100644 index 0000000000..1f6b6e112e --- /dev/null +++ b/ocean/freeway/binding.c @@ -0,0 +1,35 @@ +#include "freeway.h" +#define OBS_SIZE 34 +#define NUM_ATNS 1 +#define ACT_SIZES {3} +#define OBS_TENSOR_T FloatTensor + +#define Env Freeway +#include "vecenv.h" + +void my_init(Env* env, Dict* kwargs) { + env->num_agents = 1; + env->frameskip = dict_get(kwargs, "frameskip")->value; + env->width = dict_get(kwargs, "width")->value; + env->height = dict_get(kwargs, "height")->value; + env->player_width = dict_get(kwargs, "player_width")->value; + env->player_height = dict_get(kwargs, "player_height")->value; + env->car_width = dict_get(kwargs, "car_width")->value; + env->car_height = dict_get(kwargs, "car_height")->value; + env->lane_size = dict_get(kwargs, "lane_size")->value; + env->difficulty = dict_get(kwargs, "difficulty")->value; + env->level = dict_get(kwargs, "level")->value; + env->enable_human_player = dict_get(kwargs, "enable_human_player")->value; + env->env_randomization = dict_get(kwargs, "env_randomization")->value; + env->use_dense_rewards = dict_get(kwargs, "use_dense_rewards")->value; + init(env); +} + +void my_log(Log* log, Dict* out) { + dict_set(out, "perf", log->perf); + dict_set(out, "score", log->score); + dict_set(out, "episode_return", log->episode_return); + dict_set(out, "episode_length", log->episode_length); + dict_set(out, "up_action_frac", log->up_action_frac); + dict_set(out, "hits", log->hits); +} diff --git a/pufferlib/ocean/freeway/freeway.c b/ocean/freeway/freeway.c similarity index 76% rename from pufferlib/ocean/freeway/freeway.c rename to ocean/freeway/freeway.c index f36f2f9c8b..bb1c2ab0cf 100644 --- a/pufferlib/ocean/freeway/freeway.c +++ b/ocean/freeway/freeway.c @@ -1,12 +1,12 @@ #include #include "freeway.h" #include "puffernet.h" -#include +#include -int main() { - Weights* weights = load_weights("resources/freeway/freeway_weights.bin", 137092); +void demo() { + Weights* weights = load_weights("resources/freeway/freeway_weights.bin"); int logit_sizes[1] = {3}; - LinearLSTM* net = make_linearlstm(weights, 1, 34, logit_sizes, 1); + PufferNet* net = make_puffernet(weights, 1, 34, 128, 7, logit_sizes, 1); Freeway env = { .frameskip=4, @@ -28,15 +28,22 @@ int main() { env.client = make_client(&env); c_reset(&env); + SetTargetFPS(60); while (!WindowShouldClose()) { - forward_linearlstm(net, env.observations, env.actions); + forward_puffernet(net, env.observations, env.actions); env.human_actions[0] = 0; if (IsKeyDown(KEY_UP) || IsKeyDown(KEY_W)) env.human_actions[0] = 1; if (IsKeyDown(KEY_DOWN) || IsKeyDown(KEY_S)) env.human_actions[0] = 2; c_step(&env); c_render(&env); - } + free_puffernet(net); + free(weights); free_allocated(&env); close_client(env.client); } + +int main() { + demo(); + return 0; +} diff --git a/pufferlib/ocean/freeway/freeway.h b/ocean/freeway/freeway.h similarity index 97% rename from pufferlib/ocean/freeway/freeway.h rename to ocean/freeway/freeway.h index c132fcab69..70b32aaa76 100644 --- a/pufferlib/ocean/freeway/freeway.h +++ b/ocean/freeway/freeway.h @@ -70,10 +70,11 @@ struct Freeway { Client* client; Log log; float* observations; - int* actions; + float* actions; int* human_actions; float* rewards; - unsigned char* terminals; + float* terminals; + int num_agents; FreewayPlayer ai_player; // Player-Related FreewayPlayer human_player; @@ -101,6 +102,7 @@ struct Freeway { int use_dense_rewards; int env_randomization; int enable_human_player; + unsigned int rng; }; void load_level(Freeway* env, int level) { @@ -152,7 +154,7 @@ void init(Freeway* env) { env->enemies = (FreewayEnemy*)calloc(NUM_LANES*MAX_ENEMIES_PER_LANE, sizeof(FreewayEnemy)); env->human_actions = (int*)calloc(1, sizeof(int)); if ((env->level < 0) || (env->level >= NUM_LEVELS)) { - env->level = rand() % NUM_LEVELS; + env->level = rand_r(&env->rng) % NUM_LEVELS; } load_level(env, env->level); } @@ -160,9 +162,9 @@ void init(Freeway* env) { void allocate(Freeway* env) { init(env); env->observations = (float*)calloc(4 + NUM_LANES*MAX_ENEMIES_PER_LANE, sizeof(float)); - env->actions = (int*)calloc(1, sizeof(int)); + env->actions = (float*)calloc(1, sizeof(float)); env->rewards = (float*)calloc(1, sizeof(float)); - env->terminals = (unsigned char*)calloc(1, sizeof(unsigned char)); + env->terminals = (float*)calloc(1, sizeof(float)); } void c_close(Freeway* env) { @@ -213,7 +215,7 @@ void spawn_enemies(Freeway* env) { float lane_offset_x; FreewayEnemy* enemy; for (int lane = 0; lane < NUM_LANES; lane++) { - lane_offset_x = env->width * (rand() / (float) RAND_MAX); + lane_offset_x = env->width * (rand_r(&env->rng) / (float) RAND_MAX); for (int i = 0; i < MAX_ENEMIES_PER_LANE; i++){ enemy = &env->enemies[lane * MAX_ENEMIES_PER_LANE + i]; if (enemy->is_enabled){ @@ -294,10 +296,10 @@ void clip_enemy_position(Freeway* env, FreewayEnemy* enemy){ void randomize_enemy_speed(Freeway* env) { FreewayEnemy* enemy; for (int lane = 0; lane < NUM_LANES; lane++) { - int delta_speed = (rand() % 3) - 1; // Randomly increase or decrease speed + int delta_speed = (rand_r(&env->rng) % 3) - 1; // Randomly increase or decrease speed for (int i = 0; i < MAX_ENEMIES_PER_LANE; i++) { + enemy = &env->enemies[lane*MAX_ENEMIES_PER_LANE + i]; if (enemy->speed_randomization) { - enemy = &env->enemies[lane*MAX_ENEMIES_PER_LANE + i]; enemy->current_speed_idx = min(max(enemy->initial_speed_idx-2, enemy->current_speed_idx), enemy->initial_speed_idx+2); enemy->current_speed_idx = min(max(0, enemy->current_speed_idx + delta_speed), 5); enemy->enemy_vx = enemy->lane_idx < NUM_LANES/2 ? SPEED_VALUES[enemy->current_speed_idx] * TICK_RATE * env->width: -SPEED_VALUES[enemy->current_speed_idx] * TICK_RATE * env->width; diff --git a/pufferlib/ocean/freeway/freeway_levels.h b/ocean/freeway/freeway_levels.h similarity index 100% rename from pufferlib/ocean/freeway/freeway_levels.h rename to ocean/freeway/freeway_levels.h diff --git a/ocean/g2048/binding.c b/ocean/g2048/binding.c new file mode 100644 index 0000000000..e931ae7ee4 --- /dev/null +++ b/ocean/g2048/binding.c @@ -0,0 +1,27 @@ +#include "g2048.h" +#define OBS_SIZE 16 +#define NUM_ATNS 1 +#define ACT_SIZES {4} +#define OBS_TENSOR_T ByteTensor + +#define Env Game +#include "vecenv.h" + +void my_init(Env* env, Dict* kwargs) { + env->num_agents = 1; + env->scaffolding_ratio = dict_get(kwargs, "scaffolding_ratio")->value; + init(env); +} + +void my_log(Log* log, Dict* out) { + dict_set(out, "perf", log->perf); + dict_set(out, "score", log->score); + dict_set(out, "merge_score", log->merge_score); + dict_set(out, "episode_return", log->episode_return); + dict_set(out, "episode_length", log->episode_length); + dict_set(out, "lifetime_max_tile", log->lifetime_max_tile); + dict_set(out, "reached_16384", log->reached_16384); + dict_set(out, "reached_32768", log->reached_32768); + dict_set(out, "reached_65536", log->reached_65536); + dict_set(out, "reached_131072", log->reached_131072); +} diff --git a/ocean/g2048/g2048.c b/ocean/g2048/g2048.c new file mode 100644 index 0000000000..e99eb13e61 --- /dev/null +++ b/ocean/g2048/g2048.c @@ -0,0 +1,57 @@ +#include "g2048.h" +#include "puffernet.h" + +void demo() { + Weights* weights = load_weights("resources/g2048/g2048_weights.bin"); + int logit_sizes[1] = {4}; + PufferNet* net = make_puffernet(weights, 1, 16, 512, 4, logit_sizes, 1); + + Game env = { + .scaffolding_ratio = 0.0, + }; + init(&env); + + unsigned char observations[16] = {0}; + float actions[1] = {0}; + float rewards[1] = {0}; + float terminals[1] = {0}; + + env.observations = observations; + env.actions = actions; + env.rewards = rewards; + env.terminals = terminals; + + c_reset(&env); + c_render(&env); + + while (!WindowShouldClose()) { + // User can take control + if (IsKeyDown(KEY_LEFT_SHIFT)) { + bool pressed = false; + if (IsKeyPressed(KEY_UP) || IsKeyPressed(KEY_W)) { env.actions[0] = 0; pressed = true; } + else if (IsKeyPressed(KEY_DOWN) || IsKeyPressed(KEY_S)) { env.actions[0] = 1; pressed = true; } + else if (IsKeyPressed(KEY_LEFT) || IsKeyPressed(KEY_A)) { env.actions[0] = 2; pressed = true; } + else if (IsKeyPressed(KEY_RIGHT) || IsKeyPressed(KEY_D)) { env.actions[0] = 3; pressed = true; } + + if (pressed) { + c_step(&env); + } + } else { + float obs_f[16]; + for (int i = 0; i < 16; i++) obs_f[i] = (float)env.observations[i]; + forward_puffernet(net, obs_f, env.actions); + c_step(&env); + } + + c_render(&env); + } + + free_puffernet(net); + free(weights); + c_close(&env); +} + +int main() { + demo(); + return 0; +} diff --git a/ocean/g2048/g2048.h b/ocean/g2048/g2048.h new file mode 100644 index 0000000000..e221188d54 --- /dev/null +++ b/ocean/g2048/g2048.h @@ -0,0 +1,502 @@ +#include +#include +#include +#include +#include +#include +#include "raylib.h" + +static inline int min(int a, int b) { return a < b ? a : b; } +static inline int max(int a, int b) { return a > b ? a : b; } + +#define SIZE 4 +#define EMPTY 0 +#define UP 1 +#define DOWN 2 +#define LEFT 3 +#define RIGHT 4 +#define BASE_MAX_TICKS 1000 + +// Reward constants +#define MERGE_BASE_REWARD 0.05f +#define MERGE_REWARD_SCALE 0.03f +#define INVALID_MOVE_PENALTY -0.05f +#define GAME_OVER_PENALTY -1.0f + +// Pow 1.5 lookup table for tiles 128+ (index = row[i] - 6) +// Index: 1=128, 2=256, 3=512, 4=1024, 5=2048, 6=4096, 7=8192, 8=16384, 9=32768, 10=65536, 11=131k +static const float pow15_table[12] = { + 0.0f, 1.0f, 2.83f, 5.20f, 8.0f, 11.18f, 14.70f, 18.52f, 22.63f, 27.0f, 31.62f, 36.48f, +}; + +static inline float calculate_perf(unsigned char max_tile) { + // Reaching 131k -> 1.0, 65k -> 0.8, 32k -> 0.4, 16k -> 0.2, 8k -> 0.1 + float perf = 0.8f * (float)(1 << max_tile) / 65536.0f; + if (perf > 1.0f) perf = 1.0f; + return perf; +} + +typedef struct Log { + float perf; + float score; + float merge_score; + float episode_return; + float episode_length; + float lifetime_max_tile; + float reached_16384; + float reached_32768; + float reached_65536; + float reached_131072; + float n; +} Log; + +typedef struct Game { + Log log; // Required + unsigned char* observations; // Cheaper in memory if encoded in uint_8 + float* actions; // Required + float* rewards; // Required + float* terminals; // Required + int num_agents; // Required for env_binding + + float scaffolding_ratio; // The ratio for "scaffolding" runs, in which higher blocks are spawned + bool is_scaffolding_episode; + + int score; + int tick; + unsigned char grid[SIZE][SIZE]; + unsigned char lifetime_max_tile; + unsigned char max_tile; // Episode max tile + float episode_reward; // Accumulate episode reward + int moves_made; + int max_episode_ticks; // Dynamic max_ticks based on score + + // Cached values to avoid recomputation + int empty_count; + bool game_over_cached; + bool grid_changed; + unsigned int rng; +} Game; + +// Precomputed color table for rendering optimization +const Color PUFF_BACKGROUND = (Color){6, 24, 24, 255}; +const Color PUFF_WHITE = (Color){241, 241, 241, 241}; +const Color PUFF_RED = (Color){187, 0, 0, 255}; +const Color PUFF_CYAN = (Color){0, 187, 187, 255}; + +static Color tile_colors[17] = { + {6, 24, 24, 255}, // Empty/background + {187, 187, 187, 255}, // 2 + {170, 187, 187, 255}, // 4 + {150, 187, 187, 255}, // 8 + {130, 187, 187, 255}, // 16 + {110, 187, 187, 255}, // 32 + {90, 187, 187, 255}, // 64 (Getting more cyan) + {70, 187, 187, 255}, // 128 + {50, 187, 187, 255}, // 256 + {30, 187, 187, 255}, // 512 + {0, 187, 187, 255}, // 1024 (PUFF_CYAN) + {0, 150, 187, 255}, // 2048 + {0, 110, 187, 255}, // 4096 + {0, 70, 187, 255}, // 8192 + {187, 0, 0, 255}, // 16384 (PUFF_RED) + {204, 173, 17, 255}, // 32768 (Gold) + {6, 24, 24, 255}, // 65536+ (Invisible) +}; + +// --- Logging --- +void add_log(Game* game); + +// --- Required functions for env_binding.h --- +void c_reset(Game* game); +void c_step(Game* game); +void c_render(Game* game); +void c_close(Game* game); + +void init(Game* game) { + game->lifetime_max_tile = 0; + memset(game->grid, EMPTY, SIZE * SIZE); +} + +void update_observations(Game* game) { + memcpy(game->observations, game->grid, SIZE * SIZE); +} + +void add_log(Game* game) { + // Scaffolding runs will distort stats, so skip logging + if (game->is_scaffolding_episode) return; + + // Update the lifetime best + if (game->max_tile > game->lifetime_max_tile) { + game->lifetime_max_tile = game->max_tile; + } + + game->log.score += (float)(1 << game->max_tile); + game->log.perf += calculate_perf(game->max_tile); + game->log.merge_score += (float)game->score; + game->log.episode_length += game->tick; + game->log.episode_return += game->episode_reward; + game->log.lifetime_max_tile += (float)(1 << game->lifetime_max_tile); + game->log.reached_16384 += (game->max_tile >= 14); + game->log.reached_32768 += (game->max_tile >= 15); + game->log.reached_65536 += (game->max_tile >= 16); + game->log.reached_131072 += (game->max_tile >= 17); + game->log.n += 1; +} + +static inline unsigned char get_new_tile(Game* game) { + // 10% chance of 2, 90% chance of 1 + return (rand_r(&game->rng) % 10 == 0) ? 2 : 1; +} + +static inline void place_tile_at_random_cell(Game* game, unsigned char tile) { + if (game->empty_count == 0) return; + + int target = rand_r(&game->rng) % game->empty_count; + int pos = 0; + for (int i = 0; i < SIZE; i++) { + for (int j = 0; j < SIZE; j++) { + if (game->grid[i][j] == EMPTY) { + if (pos == target) { + game->grid[i][j] = tile; + game->empty_count--; + return; + } + pos++; + } + } + } +} + +void set_scaffolding_curriculum(Game* game) { + if (game->lifetime_max_tile < 14) { + // Spawn one high tile from 8192 to 65536 + int curriculum = rand_r(&game->rng) % 5; + unsigned char high_tile = max(12 + curriculum, game->lifetime_max_tile); + place_tile_at_random_cell(game, high_tile); + + } else { + // base=14 until 65536 reached, then base=15 for 131072 practice + // All random placement, 1-2 tiles max + unsigned char base = (game->lifetime_max_tile >= 16) ? 15 : 14; + int curriculum = rand_r(&game->rng) % 4; + + if (curriculum == 0) { + place_tile_at_random_cell(game, base); + } else if (curriculum == 1) { + place_tile_at_random_cell(game, base + 1); + } else if (curriculum == 2) { + place_tile_at_random_cell(game, base); + place_tile_at_random_cell(game, base - 1); + } else { + place_tile_at_random_cell(game, base + 1); + place_tile_at_random_cell(game, base); + } + } +} + +void c_reset(Game* game) { + memset(game->grid, EMPTY, SIZE * SIZE); + game->score = 0; + game->tick = 0; + game->episode_reward = 0; + game->empty_count = SIZE * SIZE; + game->game_over_cached = false; + game->grid_changed = true; + game->moves_made = 0; + game->max_episode_ticks = BASE_MAX_TICKS; + game->max_tile = 0; + + // Higher tiles are spawned in scaffolding episodes + // Having high tiles saves moves to get there, allowing agents to experience it faster + game->is_scaffolding_episode = (rand_r(&game->rng) / (float)RAND_MAX) < game->scaffolding_ratio; + if (game->is_scaffolding_episode) { + set_scaffolding_curriculum(game); + + } else { + // Add two random tiles at the start + for (int i = 0; i < 2; i++) { + place_tile_at_random_cell(game, get_new_tile(game)); + } + } + + update_observations(game); +} + +// Optimized slide and merge with fewer memory operations +static inline bool slide_and_merge(Game* game, unsigned char* row, float* reward, float* score_increase) { + bool moved = false; + int write_pos = 0; + + // Single pass: slide and identify merge candidates + for (int read_pos = 0; read_pos < SIZE; read_pos++) { + if (row[read_pos] != EMPTY) { + if (write_pos != read_pos) { + row[write_pos] = row[read_pos]; + row[read_pos] = EMPTY; + moved = true; + } + write_pos++; + } + } + + // Merge pass + for (int i = 0; i < SIZE - 1; i++) { + if (row[i] != EMPTY && row[i] == row[i + 1]) { + row[i]++; + // Tiles 2-64 (row[i] 1-6): base reward only + // Tiles 128+ (row[i] 7+): base + pow1.5 scaled bonus + if (row[i] <= 6) { + *reward += MERGE_BASE_REWARD; + } else { + *reward += MERGE_BASE_REWARD + pow15_table[row[i] - 6] * MERGE_REWARD_SCALE; + } + *score_increase += (float)(1 << (int)row[i]); + // Shift remaining elements left + for (int j = i + 1; j < SIZE - 1; j++) { + row[j] = row[j + 1]; + } + row[SIZE - 1] = EMPTY; + moved = true; + } + } + + return moved; +} + +bool move(Game* game, int direction, float* reward, float* score_increase) { + bool moved = false; + unsigned char temp[SIZE]; + + if (direction == UP || direction == DOWN) { + for (int col = 0; col < SIZE; col++) { + // Extract column + for (int i = 0; i < SIZE; i++) { + int idx = (direction == UP) ? i : SIZE - 1 - i; + temp[i] = game->grid[idx][col]; + } + + if (slide_and_merge(game, temp, reward, score_increase)) { + moved = true; + // Write back column + for (int i = 0; i < SIZE; i++) { + int idx = (direction == UP) ? i : SIZE - 1 - i; + game->grid[idx][col] = temp[i]; + } + } + } + } else { + for (int row = 0; row < SIZE; row++) { + // Extract row + for (int i = 0; i < SIZE; i++) { + int idx = (direction == LEFT) ? i : SIZE - 1 - i; + temp[i] = game->grid[row][idx]; + } + + if (slide_and_merge(game, temp, reward, score_increase)) { + moved = true; + // Write back row + for (int i = 0; i < SIZE; i++) { + int idx = (direction == LEFT) ? i : SIZE - 1 - i; + game->grid[row][idx] = temp[i]; + } + } + } + } + + if (moved) { + game->grid_changed = true; + game->game_over_cached = false; // Invalidate cache + } + + return moved; +} + +bool is_game_over(Game* game) { + // Use cached result if grid hasn't changed + if (!game->grid_changed) { + return game->game_over_cached; + } + + // Quick check: if there are empty cells, game is not over + if (game->empty_count > 0) { + game->game_over_cached = false; + game->grid_changed = false; + return false; + } + + // Check for possible merges + for (int i = 0; i < SIZE; i++) { + for (int j = 0; j < SIZE; j++) { + unsigned char current = game->grid[i][j]; + if (i < SIZE - 1 && current == game->grid[i + 1][j]) { + game->game_over_cached = false; + game->grid_changed = false; + return false; + } + if (j < SIZE - 1 && current == game->grid[i][j + 1]) { + game->game_over_cached = false; + game->grid_changed = false; + return false; + } + } + } + + game->game_over_cached = true; + game->grid_changed = false; + return true; +} + +void update_stats(Game* game) { + int empty_count = 0; + unsigned char max_tile = 0; + + for (int i = 0; i < SIZE; i++) { + for (int j = 0; j < SIZE; j++) { + unsigned char val = game->grid[i][j]; + // Update empty count and max tile + if (val == EMPTY) empty_count++; + if (val > max_tile) { + max_tile = val; + } + } + } + + game->empty_count = empty_count; + game->max_tile = max_tile; +} + +void c_step(Game* game) { + float reward = 0.0f; + float score_add = 0.0f; + bool did_move = move(game, game->actions[0] + 1, &reward, &score_add); + game->tick++; + + if (did_move) { + game->moves_made++; + // Refresh empty_count after merges so spawning uses the correct count. + update_stats(game); + place_tile_at_random_cell(game, get_new_tile(game)); + game->score += score_add; + + // Observations only change if the grid changes + update_observations(game); + + // This is to limit infinite invalid moves during eval (happens for noob agents) + // Don't need to be tight. Don't need to show to human player. + int tick_multiplier = max(1, game->lifetime_max_tile - 8); // practically no limit for competent agent + game->max_episode_ticks = max(BASE_MAX_TICKS * tick_multiplier, game->score / 4); + + } else { + reward = INVALID_MOVE_PENALTY; + // No need to update observations if the grid hasn't changed + } + + bool game_over = is_game_over(game); + bool max_ticks_reached = game->tick >= game->max_episode_ticks; + game->terminals[0] = (game_over || max_ticks_reached) ? 1 : 0; + + // Game over penalty overrides other rewards + if (game_over) { + reward += GAME_OVER_PENALTY; + } + + game->rewards[0] = reward; + game->episode_reward += reward; + + if (game->terminals[0]) { + add_log(game); + c_reset(game); + } +} + +// Stepping for client/eval: no reward, no reset +void step_without_reset(Game* game) { + float score_add = 0.0f; + float reward = 0.0f; + bool did_move = move(game, game->actions[0] + 1, &reward, &score_add); + game->tick++; + + if (did_move) { + game->moves_made++; + + // Refresh empty_count after merges so spawning uses the correct count. + update_stats(game); + place_tile_at_random_cell(game, get_new_tile(game)); + game->score += score_add; + + // Observations only change if the grid changes + update_observations(game); + } + + bool game_over = is_game_over(game); + game->terminals[0] = (game_over) ? 1 : 0; +} + +// Rendering optimizations +void c_render(Game* game) { + static bool window_initialized = false; + static char score_text[32]; + static const int px = 100; + + if (!window_initialized) { + InitWindow(px * SIZE, px * SIZE + 50, "2048"); + SetTargetFPS(30); + window_initialized = true; + } + + if (IsKeyDown(KEY_ESCAPE)) { + CloseWindow(); + exit(0); + } + + BeginDrawing(); + ClearBackground(PUFF_BACKGROUND); + + // Draw grid + for (int i = 0; i < SIZE; i++) { + for (int j = 0; j < SIZE; j++) { + int val = game->grid[i][j]; + + // Use precomputed colors + int color_idx = min(val, 16); // Cap at the max index of our color array + Color color = tile_colors[color_idx]; + + DrawRectangle(j * px, i * px, px - 5, px - 5, color); + + if (val > 0) { + int display_val = 1 << val; // Power of 2 + // Pre-format text to avoid repeated formatting + snprintf(score_text, sizeof(score_text), "%d", display_val); + + int font_size = 32; + int x_offset = 20; // Default for 4-digit numbers + if (display_val < 10) x_offset = 40; // 1-digit + else if (display_val < 100) x_offset = 35; // 2-digit + else if (display_val < 1000) x_offset = 25; // 3-digit + else if (display_val < 10000) x_offset = 15; // 4-digit + else if (display_val < 100000) x_offset = 2; // 5-digit + else { + font_size = 24; + x_offset = 5; + } + + DrawText(score_text, j * px + x_offset, i * px + 34, font_size, PUFF_WHITE); + } + } + } + + // Draw score (format once per frame) + snprintf(score_text, sizeof(score_text), "Score: %d", game->score); + DrawText(score_text, 10, px * SIZE + 10, 24, PUFF_WHITE); + + snprintf(score_text, sizeof(score_text), "Moves: %d", game->moves_made); + DrawText(score_text, 210, px * SIZE + 10, 24, PUFF_WHITE); + + EndDrawing(); +} + +void c_close(Game* game) { + if (IsWindowReady()) { + CloseWindow(); + } +} diff --git a/ocean/go/binding.c b/ocean/go/binding.c new file mode 100644 index 0000000000..c63516794f --- /dev/null +++ b/ocean/go/binding.c @@ -0,0 +1,38 @@ +#include "go.h" +// 9x9 - obs 326, act 82 +// 13x13 - obs 678, act 170 +// 19x19 - obs 1446, act 362 +#define OBS_SIZE 326 +#define NUM_ATNS 1 +#define ACT_SIZES {82} +#define OBS_TENSOR_T FloatTensor + +#define Env CGo +#include "vecenv.h" + +void my_init(Env* env, Dict* kwargs) { + env->num_agents = 1; + env->side = (rand_r(&env->rng) % 2) + 1; + env->selfplay = dict_get(kwargs, "selfplay")->value; + env->width = dict_get(kwargs, "width")->value; + env->height = dict_get(kwargs, "height")->value; + env->grid_size = dict_get(kwargs, "grid_size")->value; + env->board_width = dict_get(kwargs, "board_width")->value; + env->board_height = dict_get(kwargs, "board_height")->value; + env->grid_square_size = dict_get(kwargs, "grid_square_size")->value; + env->komi = dict_get(kwargs, "komi")->value; + env->reward_move_pass = dict_get(kwargs, "reward_move_pass")->value; + env->reward_move_invalid = dict_get(kwargs, "reward_move_invalid")->value; + env->reward_move_valid = dict_get(kwargs, "reward_move_valid")->value; + env->reward_player_capture = dict_get(kwargs, "reward_player_capture")->value; + env->reward_opponent_capture = dict_get(kwargs, "reward_opponent_capture")->value; + init(env); +} + +void my_log(Log* log, Dict* out) { + dict_set(out, "perf", log->perf); + dict_set(out, "score", log->score); + dict_set(out, "episode_length", log->episode_length); + dict_set(out, "episode_return", log->episode_return); + dict_set(out, "n", log->n); +} diff --git a/ocean/go/go.c b/ocean/go/go.c new file mode 100644 index 0000000000..e4af73bb2b --- /dev/null +++ b/ocean/go/go.c @@ -0,0 +1,91 @@ +#include +#include "go.h" +#include "puffernet.h" + +void demo(int grid_size) { + + CGo env = { + .width = 950, + .height = 750, + .grid_size = grid_size, + .board_width = 600, + .board_height = 600, + .grid_square_size = 64, + .komi = 7.5, + .reward_move_pass = -0.518441, + .reward_move_valid = 0, + .reward_move_invalid = -0.0864746, + .reward_player_capture = 0.553628, + .reward_opponent_capture = -0.102283, + .selfplay = 0, + .side = 1, + }; + + Weights* weights = load_weights("resources/go/go_weights.bin"); + int logit_sizes[1] = {grid_size * grid_size + 1}; + int obs_size = grid_size * grid_size * 4 + 2; + PufferNet* net = make_puffernet(weights, 1, obs_size, 512, 1, logit_sizes, 1); + allocate(&env); + c_reset(&env); + c_render(&env); + + int tick = 0; + while (!WindowShouldClose()) { + if(tick % 3 == 0) { + tick = 0; + int human_action = env.actions[0]; + forward_puffernet(net, env.observations, env.actions); + if (IsKeyDown(KEY_LEFT_SHIFT)) { + env.actions[0] = human_action; + } + c_step(&env); + if (IsKeyDown(KEY_LEFT_SHIFT)) { + env.actions[0] = -1; + } + } + tick++; + if (IsKeyDown(KEY_LEFT_SHIFT)) { + if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) { + Vector2 mousePos = GetMousePosition(); + + // Calculate the offset for the board + int boardOffsetX = env.grid_square_size; + int boardOffsetY = env.grid_square_size; + + // Adjust mouse position relative to the board + int relativeX = mousePos.x - boardOffsetX; + int relativeY = mousePos.y - boardOffsetY; + + // Calculate cell indices for the corners + int cellX = (relativeX + env.grid_square_size / 2) / env.grid_square_size; + int cellY = (relativeY + env.grid_square_size / 2) / env.grid_square_size; + + // Ensure the click is within the game board + if (cellX >= 0 && cellX <= env.grid_size && cellY >= 0 && cellY <= env.grid_size) { + // Calculate the point index (1-19) based on the click position + int pointIndex = cellY * (env.grid_size) + cellX + 1; + env.actions[0] = (unsigned short)pointIndex; + } + // Check if pass button is clicked + int passButtonX = env.width - 300; + int passButtonY = 200; + int passButtonWidth = 100; + int passButtonHeight = 50; + + if (mousePos.x >= passButtonX && mousePos.x <= passButtonX + passButtonWidth && + mousePos.y >= passButtonY && mousePos.y <= passButtonY + passButtonHeight) { + env.actions[0] = 0; // Send action 0 for pass + } + } + } + c_render(&env); + } + free_puffernet(net); + free(weights); + free_allocated(&env); +} + +int main() { + demo(9); + return 0; +} diff --git a/pufferlib/ocean/go/go.h b/ocean/go/go.h similarity index 60% rename from pufferlib/ocean/go/go.h rename to ocean/go/go.h index f96864ae02..03c2224e0d 100644 --- a/pufferlib/ocean/go/go.h +++ b/ocean/go/go.h @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -11,6 +12,7 @@ #define NUM_DIRECTIONS 4 #define ENV_WIN -1 #define PLAYER_WIN 1 +#define MAX_CHANGED_PER_MOVE 362 static const int DIRECTIONS[NUM_DIRECTIONS][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}}; // LD_LIBRARY_PATH=raylib/lib ./go @@ -21,6 +23,11 @@ struct Log { float episode_return; float episode_length; float n; + float illegal_move_count; + float legal_move_count; + float pass_move_count; + float white_wins; + float black_wins; }; typedef struct Group Group; @@ -64,11 +71,12 @@ typedef struct CGo CGo; struct CGo { Client* client; float* observations; - int* actions; + float* actions; float* rewards; - unsigned char* terminals; + float* terminals; Log log; float score; + int num_agents; int width; int height; int* board_x; @@ -77,14 +85,14 @@ struct CGo { int board_height; int grid_square_size; int grid_size; - int* board_states; - int* previous_board_state; + uint8_t* board_states; + uint8_t* previous_board_state; int last_capture_position; - int* temp_board_states; int moves_made; int* capture_count; float komi; - int* visited; + uint8_t* visited; + uint8_t current_version; Group* groups; Group* temp_groups; float reward_move_pass; @@ -93,25 +101,56 @@ struct CGo { float reward_player_capture; float reward_opponent_capture; float tick; + int selfplay; + int turn; + int side; + int legal_move_count; + int illegal_move_count; + int pass_move_count; + int previous_move; + int human_play; + // undo stack + int changed_pos[MAX_CHANGED_PER_MOVE]; + uint8_t old_board_values[MAX_CHANGED_PER_MOVE]; + int changed_count; + int old_capture_count[2]; + float old_reward; + float old_episode_return; + unsigned int rng; }; void add_log(CGo* env) { env->log.episode_length += env->tick; // Calculate perf as a win rate (1.0 if win, 0.0 if loss) - float win_value = 0.0; - if (env->score > 0) { - win_value = 1.0; // Win - } - else if (env->score < 0) { - win_value = 0.0; // Loss - } - else { - win_value = 0.0; // Tie + float win_value = (env->score > 0) ? 1.0f : (env->score < 0) ? 0.0f : 0.5f; + float black_win = 0.0; + float white_win = 0.0; + if(env->score > 0){ + if(env->side == 1){ + black_win = 1.0; + } + else{ + white_win = 1.0; + } } - - env->log.perf = (env->log.perf * env->log.n + win_value) / (env->log.n + 1.0); - + else if (env->score < 0){ + if(env->side == 1){ + white_win = 1.0; + } + else{ + black_win = 1.0; + } + } else { + black_win = 0.5; + white_win = 0.5; + } + env->log.illegal_move_count += env->illegal_move_count; + env->log.legal_move_count += env->legal_move_count; + env->log.pass_move_count += env->pass_move_count; + env->log.perf += win_value; + env->log.black_wins += black_win; + env->log.white_wins += white_win; env->log.score += env->score; env->log.episode_return += env->rewards[0]; env->log.n += 1.0; @@ -140,10 +179,10 @@ void init(CGo* env) { int grid_size = env->grid_size*env->grid_size; env->board_x = (int*)calloc(board_render_size, sizeof(int)); env->board_y = (int*)calloc(board_render_size, sizeof(int)); - env->board_states = (int*)calloc(grid_size, sizeof(int)); - env->visited = (int*)calloc(grid_size, sizeof(int)); - env->previous_board_state = (int*)calloc(grid_size, sizeof(int)); - env->temp_board_states = (int*)calloc(grid_size, sizeof(int)); + env->board_states = (uint8_t*)calloc(grid_size, sizeof(uint8_t)); + env->visited = (uint8_t*)calloc(grid_size, sizeof(uint8_t)); + env->current_version = 1; + env->previous_board_state = (uint8_t*)calloc(grid_size, sizeof(uint8_t)); env->capture_count = (int*)calloc(2, sizeof(int)); env->groups = (Group*)calloc(grid_size, sizeof(Group)); env->temp_groups = (Group*)calloc(grid_size, sizeof(Group)); @@ -153,10 +192,16 @@ void init(CGo* env) { void allocate(CGo* env) { init(env); - env->observations = (float*)calloc((env->grid_size)*(env->grid_size)*2 + 2, sizeof(float)); - env->actions = (int*)calloc(1, sizeof(int)); + if(env->selfplay){ + env->observations = (float*)calloc(2*((env->grid_size)*(env->grid_size)*4 +2), sizeof(float)); + env->actions = (float*)calloc(2, sizeof(float)); + } else{ + // +2 correct? + env->observations = (float*)calloc((env->grid_size)*(env->grid_size)*4 +2, sizeof(float)); + env->actions = (float*)calloc(1, sizeof(float)); + } env->rewards = (float*)calloc(1, sizeof(float)); - env->terminals = (unsigned char*)calloc(1, sizeof(unsigned char)); + env->terminals = (float*)calloc(1, sizeof(float)); } void c_close(CGo* env) { @@ -165,7 +210,6 @@ void c_close(CGo* env) { free(env->board_states); free(env->visited); free(env->previous_board_state); - free(env->temp_board_states); free(env->capture_count); free(env->temp_groups); free(env->groups); @@ -179,38 +223,60 @@ void free_allocated(CGo* env) { c_close(env); } -void compute_observations(CGo* env) { - int observation_indx=0; - for (int i = 0; i < (env->grid_size)*(env->grid_size); i++) { - if(env->board_states[i] ==1 ){ - env->observations[observation_indx] = 1.0; - } - else { - env->observations[observation_indx] = 0.0; - } - observation_indx++; +static inline void increment_version(CGo* env) { + env->current_version++; + if (env->current_version == 0) { + memset(env->visited, 0, (env->grid_size) * (env->grid_size)); + env->current_version = 1; } - for (int i = 0; i < (env->grid_size)*(env->grid_size); i++) { - if(env->board_states[i] ==2 ){ - env->observations[observation_indx] = 1.0; - } - else { - env->observations[observation_indx] = 0.0; +} + +void compute_observations(CGo* env) { + int obs_len = env->grid_size * env->grid_size * 4 + 2; + int N = env->grid_size * env->grid_size; + int iterations = env->selfplay ? 2 : 1; + + for(int i = 0; i < iterations; i++){ + float* current_obs = env->observations + (i * obs_len); + + int self, opp; + if (i == 0) { + self = env->side; + opp = 3 - self; + } else { + // Flip perspective for selfplay + self = 3 - env->side; + opp = env->side; + } + int turn = env->turn + 1 == self ? 1 : 0; + + // Memory Layout: [Current Self][Current Opp][Prev Self][Prev Opp] + float* plane_self = current_obs; + float* plane_opp = current_obs + N; + float* plane_prev_self = current_obs + (2 * N); + float* plane_prev_opp = current_obs + (3 * N); + + for (int idx = 0; idx < N; idx++) { + int val = env->board_states[idx]; + int prev_val = env->previous_board_state[idx]; + + plane_self[idx] = (float)(val == self); + plane_opp[idx] = (float)(val == opp); + + plane_prev_self[idx] = (float)(prev_val == self); + plane_prev_opp[idx] = (float)(prev_val == opp); } - observation_indx++; - } - env->observations[observation_indx] = env->capture_count[0]; - env->observations[observation_indx+1] = env->capture_count[1]; + // Set the color bit at the very end + current_obs[4 * N] = (float)(self - 1); + current_obs[4 * N + 1] = (float)(turn); + } } int is_valid_position(CGo* env, int x, int y) { return (x >= 0 && x < env->grid_size && y >= 0 && y < env->grid_size); } -void reset_visited(CGo* env) { - memset(env->visited, 0, sizeof(int) * (env->grid_size) * (env->grid_size)); -} void flood_fill(CGo* env, int x, int y, int* territory, int player) { if (!is_valid_position(env, x, y)) { @@ -218,10 +284,10 @@ void flood_fill(CGo* env, int x, int y, int* territory, int player) { } int pos = y * (env->grid_size) + x; - if (env->visited[pos] || env->board_states[pos] != 0) { + if (env->visited[pos] == env->current_version || env->board_states[pos] != 0) { return; } - env->visited[pos] = 1; + env->visited[pos] = env->current_version; territory[player]++; // Check adjacent positions for (int i = 0; i < 4; i++) { @@ -232,17 +298,18 @@ void flood_fill(CGo* env, int x, int y, int* territory, int player) { void compute_score_tromp_taylor(CGo* env) { int player_score = 0; int opponent_score = 0; - reset_visited(env); - + int player = env->side; + int opponent = 3 - player; + increment_version(env); // Queue for BFS int queue_size = (env->grid_size) * (env->grid_size); int queue[queue_size]; // First count stones for (int i = 0; i < queue_size; i++) { - if (env->board_states[i] == 1) { + if (env->board_states[i] == player) { player_score++; - } else if (env->board_states[i] == 2) { + } else if (env->board_states[i] == opponent) { opponent_score++; } } @@ -250,7 +317,7 @@ void compute_score_tromp_taylor(CGo* env) { // Then process empty territories for (int start_pos = 0; start_pos < queue_size; start_pos++) { // Skip if not empty or already visited - if (env->board_states[start_pos] != 0 || env->visited[start_pos]) { + if (env->board_states[start_pos] != 0 || env->visited[start_pos] == env->current_version) { continue; } @@ -260,7 +327,7 @@ void compute_score_tromp_taylor(CGo* env) { int bordering_player = 0; // 0=neutral, 1=player1, 2=player2, 3=mixed queue[rear++] = start_pos; - env->visited[start_pos] = 1; + env->visited[start_pos] = env->current_version; // Process connected empty points while (front < rear) { @@ -279,29 +346,32 @@ void compute_score_tromp_taylor(CGo* env) { } int npos = ny * env->grid_size + nx; - - if (env->board_states[npos] == 0 && !env->visited[npos]) { + int neighbor_color = env->board_states[npos]; + if (neighbor_color ==0) { // Add unvisited empty points to queue - queue[rear++] = npos; - env->visited[npos] = 1; + if(env->visited[npos] != env->current_version) { + queue[rear++] = npos; + env->visited[npos] = env->current_version; + } } else if (bordering_player == 0) { - bordering_player = env->board_states[npos]; - } else if (bordering_player != env->board_states[npos]) { + bordering_player = neighbor_color; + } else if (bordering_player != neighbor_color) { bordering_player = 3; // Mixed territory } } } // Assign territory points - if (bordering_player == 1) { + if (bordering_player == player) { player_score += territory_size; - } else if (bordering_player == 2) { + } else if (bordering_player == opponent) { opponent_score += territory_size; } // Mixed territories (bordering_player == 3) are neutral and not counted } - - env->score = (float)player_score - (float)opponent_score - env->komi; + float komi = (env->side == 2) ? env->komi : -env->komi; + env->score = (float)player_score - (float)opponent_score + komi; + //printf("Score: %f\n", env->score); } int find_in_group(int* group, int group_size, int value) { @@ -314,26 +384,28 @@ int find_in_group(int* group, int group_size, int value) { } -void capture_group(CGo* env, int* board, int root, int* affected_groups, int* affected_count) { - // Reset visited array - reset_visited(env); - +void capture_group(CGo* env, uint8_t* board, int root, int* affected_groups, int* affected_count) { + increment_version(env); // Use a queue for BFS int queue_size = (env->grid_size) * (env->grid_size); int queue[queue_size]; int front = 0, rear = 0; int captured_player = board[root]; // Player whose stones are being captured + if (captured_player != 1 && captured_player !=2) return; int capturing_player = 3 - captured_player; // Player who captures queue[rear++] = root; - env->visited[root] = 1; + env->visited[root] = env->current_version; while (front != rear) { int pos = queue[front++]; + env->old_board_values[env->changed_count] = board[pos]; // captured_player + env->changed_pos[env->changed_count] = pos; + env->changed_count++; board[pos] = 0; // Remove stone env->capture_count[capturing_player - 1]++; // Update capturing player's count - if(capturing_player-1 == 0){ + if(capturing_player == env->side){ env->rewards[0] += env->reward_player_capture; env->log.episode_return += env->reward_player_capture; } else{ @@ -352,8 +424,8 @@ void capture_group(CGo* env, int* board, int root, int* affected_groups, int* af continue; } - if (board[npos] == captured_player && !env->visited[npos]) { - env->visited[npos] = 1; + if (board[npos] == captured_player && env->visited[npos]!=env->current_version) { + env->visited[npos] = env->current_version; queue[rear++] = npos; } else if (board[npos] == capturing_player) { @@ -369,14 +441,14 @@ void capture_group(CGo* env, int* board, int root, int* affected_groups, int* af } -int count_liberties(CGo* env, int root, int* queue) { - reset_visited(env); +int count_liberties(CGo* env, int root, int* queue, uint8_t* board) { + increment_version(env); int liberties = 0; int front = 0; int rear = 0; queue[rear++] = root; - env->visited[root] = 1; + env->visited[root] = env->current_version; while (front < rear) { int pos = queue[front++]; int x = pos % (env->grid_size); @@ -390,44 +462,46 @@ int count_liberties(CGo* env, int root, int* queue) { } int npos = ny * (env->grid_size) + nx; - if (env->visited[npos]) { + if (env->visited[npos]== env->current_version) { continue; } - int temp_npos = env->temp_board_states[npos]; + int temp_npos = board[npos]; if (temp_npos == 0) { liberties++; - env->visited[npos] = 1; - } else if (temp_npos == env->temp_board_states[root]) { + env->visited[npos] = env->current_version; + } else if (temp_npos == board[root]) { queue[rear++] = npos; - env->visited[npos] = 1; + env->visited[npos] = env->current_version; } } } return liberties; } -int is_ko(CGo* env) { - for (int i = 0; i < (env->grid_size) * (env->grid_size); i++) { - if (env->temp_board_states[i] != env->previous_board_state[i]) { - return 0; // Not a ko - } - } - return 1; // Is a ko -} - int make_move(CGo* env, int pos, int player){ int x = pos % (env->grid_size); int y = pos / (env->grid_size); // cannot place stone on occupied tile if (env->board_states[pos] != 0) { + if(player == env->side){ + env->illegal_move_count+=1; + } return 0 ; } + env->old_capture_count[0] = env->capture_count[0]; + env->old_capture_count[1] = env->capture_count[1]; + env->old_reward = env->rewards[0]; + env->old_episode_return = env->log.episode_return; + + env->changed_count = 0; + + env->old_board_values[env->changed_count] = env->board_states[pos]; + env->changed_pos[env->changed_count++] = pos; + env->board_states[pos] = player; // temp structures - memcpy(env->temp_board_states, env->board_states, sizeof(int) * (env->grid_size) * (env->grid_size)); memcpy(env->temp_groups, env->groups, sizeof(Group) * (env->grid_size) * (env->grid_size)); // create new group - env->temp_board_states[pos] = player; env->temp_groups[pos].parent = pos; env->temp_groups[pos].rank = 0; env->temp_groups[pos].size = 1; @@ -448,10 +522,10 @@ int make_move(CGo* env, int pos, int player){ if (!is_valid_position(env, nx, ny)) { continue; } - if (env->temp_board_states[npos] == player) { + if (env->board_states[npos] == player) { union_groups(env->temp_groups, pos, npos); affected_groups[affected_count++] = npos; - } else if (env->temp_board_states[npos] == 3 - player) { + } else if (env->board_states[npos] == 3 - player) { affected_groups[affected_count++] = npos; } } @@ -459,15 +533,15 @@ int make_move(CGo* env, int pos, int player){ // Recalculate liberties only for affected groups for (int i = 0; i < affected_count; i++) { int root = find(env->temp_groups, affected_groups[i]); - env->temp_groups[root].liberties = count_liberties(env, root, queue); + env->temp_groups[root].liberties = count_liberties(env, root, queue, env->board_states); } // Check for captures bool captured = false; for (int i = 0; i < affected_count; i++) { int root = find(env->temp_groups, affected_groups[i]); - if (env->temp_board_states[root] == 3 - player && env->temp_groups[root].liberties == 0) { - capture_group(env, env->temp_board_states, root, affected_groups, &affected_count); + if (env->board_states[root] == 3 - player && env->temp_groups[root].liberties == 0) { + capture_group(env, env->board_states, root, affected_groups, &affected_count); captured = true; } } @@ -475,26 +549,43 @@ int make_move(CGo* env, int pos, int player){ if (captured) { for (int i = 0; i < affected_count; i++) { int root = find(env->temp_groups, affected_groups[i]); - env->temp_groups[root].liberties = count_liberties(env, root, queue); + env->temp_groups[root].liberties = count_liberties(env, root, queue, env->board_states); } // Check for ko rule violation - if(is_ko(env)) { - return 0; - } } + // self capture int root = find(env->temp_groups, pos); if (env->temp_groups[root].liberties == 0) { - return 0; + goto rollback; } - memcpy(env->board_states, env->temp_board_states, sizeof(int) * (env->grid_size) * (env->grid_size)); + + if(captured && memcmp(env->board_states, env->previous_board_state, env->grid_size*env->grid_size*sizeof(uint8_t)) == 0){ + goto rollback; + } + memcpy(env->previous_board_state, env->board_states, sizeof(uint8_t) * (env->grid_size) * (env->grid_size)); memcpy(env->groups, env->temp_groups, sizeof(Group) * (env->grid_size) * (env->grid_size)); + for(int i = 0; i < env->changed_count; i++){ + env->previous_board_state[env->changed_pos[i]] = env->old_board_values[i]; + } return 1; +rollback: + for (int i = 0; i < env->changed_count; i++) { + env->board_states[env->changed_pos[i]] = env->old_board_values[i]; + } + env->capture_count[0] = env->old_capture_count[0]; + env->capture_count[1] = env->old_capture_count[1]; + env->rewards[0] = env->old_reward; + env->log.episode_return = env->old_episode_return; + + if (player == env->side) env->illegal_move_count++; + + return 0; } -void enemy_random_move(CGo* env){ +void enemy_random_move(CGo* env, int side){ int num_positions = (env->grid_size)*(env->grid_size); int positions[num_positions]; int count = 0; @@ -507,27 +598,29 @@ void enemy_random_move(CGo* env){ } // Shuffle the positions for(int i = count - 1; i > 0; i--){ - int j = rand() % (i + 1); + int j = rand_r(&env->rng) % (i + 1); int temp = positions[i]; positions[i] = positions[j]; positions[j] = temp; } // Try to make a move in a random empty position for(int i = 0; i < count; i++){ - if(make_move(env, positions[i], 2)){ + if(make_move(env, positions[i], side)){ + env->previous_move = positions[i] + 1; return; } } // If no move is possible, pass or end the game + env->previous_move = 0; env->terminals[0] = 1; } int find_group_liberty(CGo* env, int root){ - reset_visited(env); + increment_version(env); int queue[(env->grid_size)*(env->grid_size)]; int front = 0, rear = 0; queue[rear++] = root; - env->visited[root] = 1; + env->visited[root] = env->current_version; while(front < rear){ int pos = queue[front++]; @@ -543,8 +636,8 @@ int find_group_liberty(CGo* env, int root){ } if(env->board_states[npos] == 0){ return npos; // Found a liberty - } else if(env->board_states[npos] == env->board_states[root] && !env->visited[npos]){ - env->visited[npos] = 1; + } else if(env->board_states[npos] == env->board_states[root] && env->visited[npos] != env->current_version){ + env->visited[npos] = env->current_version; queue[rear++] = npos; } } @@ -552,7 +645,9 @@ int find_group_liberty(CGo* env, int root){ return -1; // Should not happen if liberties > 0 } -void enemy_greedy_hard(CGo* env){ +void enemy_greedy_hard(CGo* env, int side){ + + int opp = 3 - side; // Attempt to capture opponent stones in atari int liberties[4][(env->grid_size) * (env->grid_size)]; int liberty_counts[4] = {0}; @@ -560,14 +655,14 @@ void enemy_greedy_hard(CGo* env){ if(env->board_states[i]==0){ continue; } - if (env->board_states[i]==1){ + if (env->board_states[i]==opp){ int root = find(env->groups, i); int group_liberties = env->groups[root].liberties; if (group_liberties >= 1 && group_liberties <= 4) { int liberty = find_group_liberty(env, root); liberties[group_liberties - 1][liberty_counts[group_liberties - 1]++] = liberty; } - } else if (env->board_states[i]==2){ + } else if (env->board_states[i]==side){ int root = find(env->groups, i); int group_liberties = env->groups[root].liberties; if (group_liberties==1) { @@ -579,16 +674,18 @@ void enemy_greedy_hard(CGo* env){ // make move to attack or defend for (int priority = 0; priority < 4; priority++) { for (int i = 0; i < liberty_counts[priority]; i++) { - if (make_move(env, liberties[priority][i], 2)) { + if (make_move(env, liberties[priority][i], side)) { + env->previous_move = liberties[priority][i]+1; return; } } } + // random move - enemy_random_move(env); + enemy_random_move(env, side); } -void enemy_greedy_easy(CGo* env){ +void enemy_greedy_easy(CGo* env, int side){ // Attempt to capture opponent stones in atari for(int i = 0; i < (env->grid_size)*(env->grid_size); i++){ if(env->board_states[i] != 1){ @@ -617,17 +714,20 @@ void enemy_greedy_easy(CGo* env){ } } // Play a random legal move - enemy_random_move(env); + enemy_random_move(env, side); } void c_reset(CGo* env) { env->tick = 0; + env->illegal_move_count = 0; + env->legal_move_count = 0; + env->pass_move_count = 0; + env->turn = 0; + env->previous_move = -1; // We don't reset the log struct - leave it accumulating like in Pong - env->terminals[0] = 0; env->score = 0; for (int i = 0; i < (env->grid_size)*(env->grid_size); i++) { env->board_states[i] = 0; - env->temp_board_states[i] = 0; env->visited[i] = 0; env->previous_board_state[i] = 0; env->groups[i].parent = i; @@ -642,6 +742,15 @@ void c_reset(CGo* env) { compute_observations(env); } +void clip_rewards(CGo* env){ + if(env->rewards[0] > 1){ + env->rewards[0] = 1; + } + if(env->rewards[0] < -1){ + env->rewards[0] = -1; + } +} + void end_game(CGo* env){ compute_score_tromp_taylor(env); if (env->score > 0) { @@ -653,60 +762,139 @@ void end_game(CGo* env){ else { env->rewards[0] = 0.0; } + //env->rewards[0] = env->score / 10.0f; + clip_rewards(env); + env->terminals[0] = 1; add_log(env); c_reset(env); } +void human_play(CGo* env){ + int indx=1; + if(!env->selfplay || !env->human_play){ + return; + } + if(env->selfplay && env->turn + 1 != env->side){ + env->actions[indx] = -1; + } + if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) { + Vector2 mousePos = GetMousePosition(); + + // Calculate the offset for the board + int boardOffsetX = env->grid_square_size; + int boardOffsetY = env->grid_square_size; + + // Adjust mouse position relative to the board + int relativeX = mousePos.x - boardOffsetX; + int relativeY = mousePos.y - boardOffsetY; + + // Calculate cell indices for the corners + int cellX = (relativeX + env->grid_square_size / 2) / env->grid_square_size; + int cellY = (relativeY + env->grid_square_size / 2) / env->grid_square_size; + + // Ensure the click is within the game board + if (cellX >= 0 && cellX <= env->grid_size && cellY >= 0 && cellY <= env->grid_size) { + // Calculate the point index (1-19) based on the click position + int pointIndex = cellY * (env->grid_size) + cellX + 1; + env->actions[indx] = (unsigned short)pointIndex; + } + // Check if pass button is clicked + int left = (env->grid_size + 1)*env->grid_square_size; + int top = env->grid_square_size; + int passButtonX = left; + int passButtonY = top + 90; + int passButtonWidth = 100; + int passButtonHeight = 50; + + if (mousePos.x >= passButtonX && mousePos.x <= passButtonX + passButtonWidth && + mousePos.y >= passButtonY && mousePos.y <= passButtonY + passButtonHeight) { + env->actions[indx] = 0; // Send action 0 for pass + } + } + +} + void c_step(CGo* env) { env->tick += 1; env->rewards[0] = 0.0; - int action = (int)env->actions[0]; + env->terminals[0] = 0; + int action = 0; + int bot_side = 3 - env->side; + int is_legal = 0; + if(env->human_play){ + human_play(env); + } + if(env->selfplay){ + action = (env->turn +1 == env->side) ? (int)env->actions[0] : (int)env->actions[1]; + } else { + action = (int)env->actions[0]; + } + if(action == -1){ + compute_observations(env); + return; + } // useful for training , can prob be a hyper param. Recommend to increase with larger board size float max_moves = 3 * env->grid_size * env->grid_size; - if (env->tick > max_moves) { + if (env->tick > max_moves && !env->human_play) { env->terminals[0] = 1; end_game(env); compute_observations(env); return; } - if(action == NOOP){ - env->rewards[0] = env->reward_move_pass; - env->log.episode_return += env->reward_move_pass; - enemy_greedy_hard(env); + // play against bots + if(!env->selfplay && env->turn == (bot_side - 1)){ + enemy_greedy_hard(env, bot_side); if (env->terminals[0] == 1) { end_game(env); + } + compute_observations(env); + clip_rewards(env); + env->turn = (env->turn + 1) % 2; + return; + } + // process action + if(action == NOOP){ + if(env->turn + 1 == env->side){ + //printf("Pass\n"); + env->legal_move_count +=1; + env->rewards[0] = env->reward_move_pass; + env->log.episode_return += env->reward_move_pass; + env->pass_move_count += 1; + } + if (env->terminals[0] == 1 || env->previous_move == NOOP) { + end_game(env); return; } + env->previous_move = NOOP; + env->turn = (env->turn+1)%2; compute_observations(env); return; } if (action >= MOVE_MIN && action <= (env->grid_size)*(env->grid_size)) { - memcpy(env->previous_board_state, env->board_states, sizeof(int) * (env->grid_size) * (env->grid_size)); - if(make_move(env, action-1, 1)) { + is_legal = make_move(env, action - 1, env->turn + 1); + if(is_legal) { env->moves_made++; - env->rewards[0] = env->reward_move_valid; - env->log.episode_return += env->reward_move_valid; - enemy_greedy_hard(env); - + if(env->turn + 1 == env->side){ + env->legal_move_count +=1; + env->rewards[0] += env->reward_move_valid; + env->log.episode_return += env->reward_move_valid; + } } else { - env->rewards[0] = env->reward_move_invalid; - env->log.episode_return += env->reward_move_invalid; + if(env->turn + 1 == env->side){ + env->rewards[0] = env->reward_move_invalid; + env->log.episode_return += env->reward_move_invalid; + } } - compute_observations(env); - } - - if(env->rewards[0] > 1){ - env->rewards[0] = 1; - } - if(env->rewards[0] < -1){ - env->rewards[0] = -1; } + env->previous_move = action; if (env->terminals[0] == 1) { end_game(env); return; } - + if(is_legal){ + env->turn = (env->turn + 1) % 2; + } compute_observations(env); } @@ -727,10 +915,11 @@ Client* make_client(int width, int height) { client->width = width; client->height = height; InitWindow(width, height, "PufferLib Ray Go"); - SetTargetFPS(60); + SetTargetFPS(10); return client; } + void c_render(CGo* env) { if (env->client == NULL) { env->client = make_client(env->width, env->height); @@ -792,14 +981,28 @@ void c_render(CGo* env) { int top = env->grid_square_size; DrawRectangle(left, top + 90, 100, 50, GRAY); DrawText("Pass", left + 25, top + 105, 20, PUFF_WHITE); - - // show capture count for both players DrawText( - TextFormat("Player 1 Capture Count: %d", env->capture_count[0]), + TextFormat("Tick: %d", (int)env->tick), + left, top + 150, 20, PUFF_WHITE + ); + if(env->side == 1){ + DrawText( + TextFormat("Agent: black"), + left, top + 170, 20, PUFF_WHITE + ); + } + else { + DrawText( + TextFormat("Agent: white"), + left, top + 170, 20, PUFF_WHITE + ); + } + DrawText( + TextFormat("Black Capture Count: %d", env->capture_count[0]), left, top, 20, PUFF_WHITE ); DrawText( - TextFormat("Player 2 Capture Count: %d", env->capture_count[1]), + TextFormat("White Capture Count: %d", env->capture_count[1]), left, top + 40, 20, PUFF_WHITE ); EndDrawing(); diff --git a/ocean/hex/binding.c b/ocean/hex/binding.c new file mode 100644 index 0000000000..34bed40557 --- /dev/null +++ b/ocean/hex/binding.c @@ -0,0 +1,22 @@ +#include "hex.h" +#define OBS_SIZE 2*TOTAL_CELLS +#define NUM_ATNS 1 +#define ACT_SIZES {TOTAL_CELLS} +#define OBS_TENSOR_T FloatTensor + +#define Env Hex +#include "vecenv.h" + +void my_init(Env* env, Dict* kwargs) { + env->num_agents = 1; + env->random_opponent=dict_get(kwargs, "random_opponent")->value; + init(env); +} + +void my_log(Log* log, Dict* out) { + dict_set(out, "perf", log->perf); + dict_set(out, "score", log->score); + dict_set(out, "episode_return", log->episode_return); + dict_set(out, "episode_length", log->episode_length); + dict_set(out, "n", log->n); +} diff --git a/ocean/hex/hex.c b/ocean/hex/hex.c new file mode 100644 index 0000000000..f134d1b175 --- /dev/null +++ b/ocean/hex/hex.c @@ -0,0 +1,91 @@ +#include "hex.h" +#include +#include +#include + +void allocate(Hex* env) { + env->observations = (float*)calloc(2 * TOTAL_CELLS, sizeof(float)); + env->actions = (float*)calloc(1, sizeof(float)); + env->terminals = (float*)calloc(1, sizeof(float)); + env->rewards = (float*)calloc(1, sizeof(float)); +} + +void free_allocated(Hex* env) { + free(env->actions); + free(env->observations); + free(env->terminals); + free(env->rewards); +} + +void demo() { + Hex env = {0}; + allocate(&env); + c_reset(&env); + c_render(&env); + env.random_opponent = false; + + while(!WindowShouldClose()) { + bool move_made = false; + + if(IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) { + Vector2 mouse = GetMousePosition(); + + int screen_width = GetScreenWidth(); + int screen_height = GetScreenHeight(); + float radius = 22.0f; + float sqrt3 = 1.73205f; + float hex_width = sqrt3 * radius; + float hex_height = 2.0f * radius; + + float total_width = hex_width * BOARD_SIZE + hex_width * 0.5f * BOARD_SIZE; + float total_height = hex_height * 0.75f * BOARD_SIZE; + + float start_x = screen_width / 2.0f - total_width / 2.0f + hex_width / 2.0f; + float start_y = screen_height / 2.0f - total_height / 2.0f + hex_height / 2.0f; + + // Inverse map: + int r = (int)roundf((mouse.y - start_y) / (hex_height * 0.75f)); + int c = (int)roundf((mouse.x - start_x) / hex_width - r * 0.5f); + + if(r >= 0 && r < BOARD_SIZE && c >= 0 && c < BOARD_SIZE) { + env.actions[0] = r * BOARD_SIZE + c; + move_made = true; + } + } + + if(move_made) { + c_step(&env); + } + + c_render(&env); + } + + free_allocated(&env); + c_close(&env); +} + +void speed_test() { + Hex env = {0}; + allocate(&env); + c_reset(&env); + clock_t start = clock(); + + int num_steps = 1000000; + for(int i = 0; i < num_steps; i++) { + env.actions[0] = compute_legal_move(&env); + c_step(&env); + } + clock_t end = clock(); + double elapsed = (double)(end - start) / CLOCKS_PER_SEC; + printf("Time for %d steps: %.2f seconds\n", num_steps, elapsed); + printf("SPS: %.2fM\n", num_steps / elapsed / 1e6); + + free_allocated(&env); + c_close(&env); +} + +int main() { + demo(); + // speed_test(); + return 0; +} diff --git a/ocean/hex/hex.h b/ocean/hex/hex.h new file mode 100644 index 0000000000..a7d16037e6 --- /dev/null +++ b/ocean/hex/hex.h @@ -0,0 +1,324 @@ +#include "raylib.h" +#include +#include +#include +#include +#include + +#define BOARD_SIZE 11 +#define TOTAL_CELLS (BOARD_SIZE * BOARD_SIZE) +#define PLAYER_COLOR 1 +#define ENV_COLOR -1 + +// Virtual nodes for incremental connection tracking +#define TOP_NODE TOTAL_CELLS +#define BOTTOM_NODE (TOTAL_CELLS + 1) +#define LEFT_NODE (TOTAL_CELLS + 2) +#define RIGHT_NODE (TOTAL_CELLS + 3) +#define TOTAL_NODES (TOTAL_CELLS + 4) + +const int dr[] = { -1, -1, 0, 0, 1, 1 }; +const int dc[] = { 0, 1, -1, 1, -1, 0 }; + +typedef struct { + float perf; + float score; + float episode_return; + float episode_length; + float n; +} Log; + +typedef struct { + Log log; + float* observations; + float* actions; + float* rewards; + float* terminals; + int num_agents; + int tick; + int current_player; + int8_t board[TOTAL_CELLS]; + bool random_opponent; + + // Disjoint Set Union (Union-Find) tracking arrays + int parent[TOTAL_NODES]; + int size[TOTAL_NODES]; + + unsigned int rng; +} Hex; + +void init(Hex* env) { env->tick = 0; } + +void add_log(Hex* env) { + env->log.perf += (env->rewards[0] > 0) ? 1 : 0; + env->log.score += env->rewards[0]; + env->log.episode_length += env->tick; + env->log.episode_return += env->rewards[0]; + env->log.n++; +} + +// --- Union-Find (Disjoint Set) Logic --- +void uf_init(Hex* env) { + for (int i = 0; i < TOTAL_NODES; i++) { + env->parent[i] = i; + env->size[i] = 1; + } +} + +int uf_find(Hex* env, int i) { + int root = i; + while (root != env->parent[root]) { + root = env->parent[root]; + } + // Path compression + int curr = i; + while (curr != root) { + int nxt = env->parent[curr]; + env->parent[curr] = root; + curr = nxt; + } + return root; +} + +void uf_union(Hex* env, int i, int j) { + int root_i = uf_find(env, i); + int root_j = uf_find(env, j); + if (root_i != root_j) { + // Union by size + if (env->size[root_i] < env->size[root_j]) { + env->parent[root_i] = root_j; + env->size[root_j] += env->size[root_i]; + } else { + env->parent[root_j] = root_i; + env->size[root_i] += env->size[root_j]; + } + } +} +// --- End Union-Find Logic --- + +void c_reset(Hex* env) { + // set board to empty board + memset(env->board, 0, sizeof(env->board)); + env->current_player = 0; + env->tick = 0; + env->terminals[0] = 0; + + uf_init(env); + + for (int i = 0; i < 2 * TOTAL_CELLS; i++) { + env->observations[i] = 0; + } +} + +bool invalid_move(int action, const int8_t* board) { + if (action < 0 || action >= TOTAL_CELLS) { + return true; // Out of bounds + } + if (board[action] != 0) { + return true; // Cell already occupied + } + return false; +} + +int compute_legal_move(Hex* env) { + // Naive random move for the environment + int action; + do { + action = rand_r(&env->rng) % TOTAL_CELLS; + } while (invalid_move(action, env->board)); + + return action; +} + +int compute_env_move(Hex* env, int player_last_action) { + + // Get the coordinates of the player's last move. + int r = player_last_action / BOARD_SIZE; + int c = player_last_action % BOARD_SIZE; + + int arr[6]; + for (int i = 0; i < 6; i++) { + arr[i] = i; + } + + for (int i = 6 - 1; i > 0; i--) { + int j = rand_r(&env->rng) % (i + 1); + int temp = arr[i]; + arr[i] = arr[j]; + arr[j] = temp; + } + + int action = -1; + for (int j = 0; j < 6; j++) { + int i = arr[j]; + int nr = r + dr[i]; + int nc = c + dc[i]; + int n_idx = nr * BOARD_SIZE + nc; + if (nr >= 0 && nr < BOARD_SIZE && nc >= 0 && nc < BOARD_SIZE) { + if (env->board[n_idx] == 0) { + action = n_idx; + break; + } + } + } + if (action == -1) { + action = compute_legal_move(env); + } + return action; +} + +// Places a stone, merges components, and returns true if the player won +bool place_stone_and_check_win(Hex* env, int action, int player) { + env->board[action] = player; + int offset = 0; + if (player == ENV_COLOR) { + offset = TOTAL_CELLS; + } + env->observations[action + offset] = 1; + + int r = action / BOARD_SIZE; + int c = action % BOARD_SIZE; + + // 1. Connect to adjacent stones of the same color + for (int i = 0; i < 6; i++) { + int nr = r + dr[i]; + int nc = c + dc[i]; + + if (nr >= 0 && nr < BOARD_SIZE && nc >= 0 && nc < BOARD_SIZE) { + int n_idx = nr * BOARD_SIZE + nc; + if (env->board[n_idx] == player) { + uf_union(env, action, n_idx); + } + } + } + + // 2. Connect to virtual edges and check for a winner + if (player == PLAYER_COLOR) { + if (r == 0) + uf_union(env, action, TOP_NODE); + if (r == BOARD_SIZE - 1) + uf_union(env, action, BOTTOM_NODE); + + return uf_find(env, TOP_NODE) == uf_find(env, BOTTOM_NODE); + } else { + if (c == 0) + uf_union(env, action, LEFT_NODE); + if (c == BOARD_SIZE - 1) + uf_union(env, action, RIGHT_NODE); + + return uf_find(env, LEFT_NODE) == uf_find(env, RIGHT_NODE); + } +} + +void c_step(Hex* env) { + env->tick += 1; + int action = (int)env->actions[0]; + + if (invalid_move(action, env->board)) { + env->rewards[0] = -1; + env->terminals[0] = 1; + add_log(env); + c_reset(env); + return; + } + + // Player move and incremental win check + if (place_stone_and_check_win(env, action, PLAYER_COLOR)) { + env->rewards[0] = 1; + env->terminals[0] = 1; + + add_log(env); + c_reset(env); + return; + } + int env_action; + + if (env->random_opponent) { + env_action = compute_legal_move(env); + + } else { + env_action = compute_env_move(env, action); + } + + if (place_stone_and_check_win(env, env_action, ENV_COLOR)) { + env->rewards[0] = -1; + env->terminals[0] = 1; + + add_log(env); + c_reset(env); + return; + } +} + +void c_render(Hex* env) { + int screen_width = 800; + int screen_height = 600; + + if (!IsWindowReady()) { + InitWindow(screen_width, screen_height, "PufferLib Hex"); + SetTargetFPS(60); + } + + if (IsKeyDown(KEY_ESCAPE)) { + exit(0); + } + + BeginDrawing(); + ClearBackground((Color) { 6, 24, 24, 255 }); + + float radius = 22.0f; + float sqrt3 = 1.73205f; + float hex_width = sqrt3 * radius; + float hex_height = 2.0f * radius; + + float total_width = hex_width * BOARD_SIZE + hex_width * 0.5f * BOARD_SIZE; + float total_height = hex_height * 0.75f * BOARD_SIZE; + + float start_x = screen_width / 2.0f - total_width / 2.0f + hex_width / 2.0f; + float start_y = screen_height / 2.0f - total_height / 2.0f + hex_height / 2.0f; + + // Draw borders to show player targets (Red connects Top/Bottom, Blue connects Left/Right) + for (int r = 0; r < BOARD_SIZE; r++) { + float left_x = start_x + (0 + r * 0.5f) * hex_width - hex_width * 0.8f; + float right_x = start_x + (BOARD_SIZE - 1 + r * 0.5f) * hex_width + hex_width * 0.8f; + float cy = start_y + r * hex_height * 0.75f; + DrawCircle(left_x, cy, radius * 0.3f, BLUE); + DrawCircle(right_x, cy, radius * 0.3f, BLUE); + } + + for (int c = 0; c < BOARD_SIZE; c++) { + float cx_top = start_x + (c + 0 * 0.5f) * hex_width; + float cy_top = start_y + 0 * hex_height * 0.75f - hex_height * 0.6f; + float cx_bot = start_x + (c + (BOARD_SIZE - 1) * 0.5f) * hex_width; + float cy_bot = start_y + (BOARD_SIZE - 1) * hex_height * 0.75f + hex_height * 0.6f; + DrawCircle(cx_top, cy_top, radius * 0.3f, RED); + DrawCircle(cx_bot, cy_bot, radius * 0.3f, RED); + } + + for (int r = 0; r < BOARD_SIZE; r++) { + for (int c = 0; c < BOARD_SIZE; c++) { + int idx = r * BOARD_SIZE + c; + int owner = env->board[idx]; + + Color color = DARKGRAY; + if (owner == PLAYER_COLOR) + color = RED; + else if (owner == ENV_COLOR) + color = BLUE; + + float cx = start_x + (c + r * 0.5f) * hex_width; + float cy = start_y + r * hex_height * 0.75f; + + DrawPoly((Vector2) { cx, cy }, 6, radius - 1.0f, 30.0f, color); + DrawPolyLines((Vector2) { cx, cy }, 6, radius - 1.0f, 30.0f, BLACK); + } + } + + EndDrawing(); +} + +void c_close(Hex* env) { + if (IsWindowReady()) { + CloseWindow(); + } +} diff --git a/pufferlib/ocean/impulse_wars/benchmark.c b/ocean/impulse_wars/benchmark.c similarity index 100% rename from pufferlib/ocean/impulse_wars/benchmark.c rename to ocean/impulse_wars/benchmark.c diff --git a/pufferlib/ocean/impulse_wars/binding.c b/ocean/impulse_wars/binding.c similarity index 100% rename from pufferlib/ocean/impulse_wars/binding.c rename to ocean/impulse_wars/binding.c diff --git a/pufferlib/ocean/impulse_wars/env.h b/ocean/impulse_wars/env.h similarity index 100% rename from pufferlib/ocean/impulse_wars/env.h rename to ocean/impulse_wars/env.h diff --git a/pufferlib/ocean/impulse_wars/game.h b/ocean/impulse_wars/game.h similarity index 100% rename from pufferlib/ocean/impulse_wars/game.h rename to ocean/impulse_wars/game.h diff --git a/pufferlib/ocean/impulse_wars/helpers.h b/ocean/impulse_wars/helpers.h similarity index 100% rename from pufferlib/ocean/impulse_wars/helpers.h rename to ocean/impulse_wars/helpers.h diff --git a/pufferlib/ocean/impulse_wars/impulse_wars.c b/ocean/impulse_wars/impulse_wars.c similarity index 100% rename from pufferlib/ocean/impulse_wars/impulse_wars.c rename to ocean/impulse_wars/impulse_wars.c diff --git a/pufferlib/ocean/impulse_wars/map.h b/ocean/impulse_wars/map.h similarity index 100% rename from pufferlib/ocean/impulse_wars/map.h rename to ocean/impulse_wars/map.h diff --git a/pufferlib/ocean/impulse_wars/render.h b/ocean/impulse_wars/render.h similarity index 99% rename from pufferlib/ocean/impulse_wars/render.h rename to ocean/impulse_wars/render.h index 5eee861033..d4300d5538 100644 --- a/pufferlib/ocean/impulse_wars/render.h +++ b/ocean/impulse_wars/render.h @@ -5,7 +5,7 @@ #include "rlgl.h" #define RLIGHTS_IMPLEMENTATION -#include "include/rlights.h" +#include "rlights.h" #include "helpers.h" diff --git a/pufferlib/ocean/impulse_wars/scripted_agent.h b/ocean/impulse_wars/scripted_agent.h similarity index 100% rename from pufferlib/ocean/impulse_wars/scripted_agent.h rename to ocean/impulse_wars/scripted_agent.h diff --git a/pufferlib/ocean/impulse_wars/settings.h b/ocean/impulse_wars/settings.h similarity index 100% rename from pufferlib/ocean/impulse_wars/settings.h rename to ocean/impulse_wars/settings.h diff --git a/pufferlib/ocean/impulse_wars/types.h b/ocean/impulse_wars/types.h similarity index 100% rename from pufferlib/ocean/impulse_wars/types.h rename to ocean/impulse_wars/types.h diff --git a/ocean/lightsout/binding.c b/ocean/lightsout/binding.c new file mode 100644 index 0000000000..68b7953b02 --- /dev/null +++ b/ocean/lightsout/binding.c @@ -0,0 +1,33 @@ +#include "lightsout.h" + +#define GRID_SIZE 5 +#define OBS_SIZE (GRID_SIZE * GRID_SIZE) +#define NUM_ATNS 1 +#define ACT_SIZES {GRID_SIZE * GRID_SIZE} +#define OBS_TENSOR_T ByteTensor + +#define Env LightsOut +#include "vecenv.h" + +void my_init(Env* env, Dict* kwargs) { + env->grid_size = GRID_SIZE; + env->cell_size = 1280 / GRID_SIZE; + if (1280 % GRID_SIZE != 0) env->cell_size++; // ceil + env->max_steps = (int)dict_get(kwargs, "max_steps")->value; + env->observation_size = OBS_SIZE; + env->num_agents = 1; + + env->ema = 0.5f; + env->score_ema = 0.0f; + env->scramble_prob = 0.15f; + + init_lightsout(env); +} + +void my_log(Log* log, Dict* out) { + dict_set(out, "perf", log->perf); + dict_set(out, "score", log->score); + dict_set(out, "episode_return", log->episode_return); + dict_set(out, "episode_length", log->episode_length); + dict_set(out, "scramble_p", log->scramble_p); +} diff --git a/ocean/lightsout/lightsout.c b/ocean/lightsout/lightsout.c new file mode 100644 index 0000000000..e27b0fc9ee --- /dev/null +++ b/ocean/lightsout/lightsout.c @@ -0,0 +1,53 @@ +#include +#include +#include "lightsout.h" + +static LightsOut* g_env = NULL; + +static void demo_cleanup(void) { + if (g_env == NULL) { + return; + } + free(g_env->observations); + free(g_env->actions); + free(g_env->rewards); + free(g_env->terminals); + c_close(g_env); + g_env = NULL; +} + +int demo(){ + srand((unsigned)time(NULL)); + LightsOut env = {.grid_size = 5, .cell_size = 100, .client = NULL}; + g_env = &env; + atexit(demo_cleanup); + env.observations = (unsigned char*)calloc(env.grid_size * env.grid_size, sizeof(unsigned char)); + env.actions = (float*)calloc(1, sizeof(float)); + env.rewards = (float*)calloc(1, sizeof(float)); + env.terminals = (float*)calloc(1, sizeof(float)); + + c_reset(&env); + env.client = make_client(env.cell_size, env.grid_size); + + while (!WindowShouldClose()) { + if (IsKeyPressed(KEY_UP) || IsKeyPressed(KEY_W)) env.client->cursor_row = (env.client->cursor_row - 1 + env.grid_size) % env.grid_size; + if (IsKeyPressed(KEY_DOWN) || IsKeyPressed(KEY_S)) env.client->cursor_row = (env.client->cursor_row + 1) % env.grid_size; + if (IsKeyPressed(KEY_LEFT) || IsKeyPressed(KEY_A)) env.client->cursor_col = (env.client->cursor_col - 1 + env.grid_size) % env.grid_size; + if (IsKeyPressed(KEY_RIGHT) || IsKeyPressed(KEY_D)) env.client->cursor_col = (env.client->cursor_col + 1) % env.grid_size; + if (IsKeyPressed(KEY_SPACE)) { + int idx = env.client->cursor_row * env.grid_size + env.client->cursor_col; + env.actions[0] = (float)idx; + c_step(&env); + } else if (IsKeyPressed(KEY_R)) { + c_reset(&env); + } + c_render(&env); + } + + demo_cleanup(); + return 0; +} +int main(void) { + demo(); + return 0; +} diff --git a/ocean/lightsout/lightsout.h b/ocean/lightsout/lightsout.h new file mode 100644 index 0000000000..508e12f5a6 --- /dev/null +++ b/ocean/lightsout/lightsout.h @@ -0,0 +1,231 @@ +#include +#include +#include +#include "raylib.h" + +// Only use floats. +typedef struct { + float perf; + float score; + float episode_return; + float episode_length; + float scramble_p; + float n; // Required as the last field. +} Log; + +typedef struct Client { + int cell_size; + int cursor_row; + int cursor_col; +} Client; + +typedef struct { + Log log; // Required field. + unsigned char* observations; // Required field. Ensure type matches in .py and .c. + float* actions; // Required field. Ensure type matches in .py and .c. + float* rewards; // Required field. + float* terminals; // Required field. + int grid_size; + int cell_size; + int max_steps; + int step_count; + int lights_on; + int prev_action; + int last_action; + float episode_return; + float ema; + float score_ema; + float scramble_prob; + unsigned char* grid; + Client* client; + int num_agents; + int observation_size; + unsigned int rng; +} LightsOut; + +void step_grid(LightsOut* env, int idx) { + if (idx < 0 || idx >= env->grid_size * env->grid_size) return; + int row = idx/env->grid_size; + int col = idx%env->grid_size; + + static const int dirs[5][2] = {{0,0}, {1,0}, {0,1}, {-1,0}, {0,-1}}; + for (int i = 0; i < 5; i++) { + int dr = dirs[i][0]; + int dc = dirs[i][1]; + int r = row + dr; + int c = col + dc; + if (r >= 0 && r < env->grid_size && c >= 0 && c < env->grid_size) { + int offset = r*env->grid_size + c; + unsigned char old = env->grid[offset]; + env->grid[offset] = (unsigned char)!old; + env->lights_on += old ? -1 : 1; + } + } +} + +void init_lightsout(LightsOut* env) { + int n = env->grid_size * env->grid_size; + if (env->grid == NULL) { + env->grid = (unsigned char*)calloc(n, sizeof(unsigned char)); + } else { + memset(env->grid, 0, n * sizeof(unsigned char)); + } + + if (env->ema > 0.7f && env->score_ema > 0.0f) { + env->scramble_prob = fminf(0.5f, env->scramble_prob + 0.01f); // Increase scramble prob if EMA is high + } else if (env->ema < 0.3f) { + env->scramble_prob = fmaxf(0.15f, env->scramble_prob - 0.01f); // Decrease scramble prob if EMA is low + } + + env->step_count = 0; + env->lights_on = 0; + env->prev_action = -1; + env->last_action = -1; + env->episode_return = 0.0f; + + for (int i = 0; i < n; i++) { + float u = (float)rand_r(&env->rng) / (float)RAND_MAX; + if (u < env->scramble_prob) { + step_grid(env, i); + } + } +} + +void c_close(LightsOut* env) { + free(env->grid); + env->grid = NULL; + if (env->client != NULL) { + if (IsWindowReady()) { + CloseWindow(); + } + free(env->client); + env->client = NULL; + } +} + +void compute_observations(LightsOut* env) { + for (int i = 0; i < env->grid_size * env->grid_size; i++) { + env->observations[i] = env->grid[i]; + } +} + +void c_reset(LightsOut* env) { + env->rewards[0] = 0.0f; + env->terminals[0] = 0.0f; + init_lightsout(env); + compute_observations(env); +} + +void c_step(LightsOut* env) { + int num_cells = env->grid_size * env->grid_size; + int atn = env->actions[0]; + env->terminals[0] = 0.0f; + + float reward = -0.02 * (36.0 / (env->grid_size * env->grid_size)); // Base step penalty. + int prev_on = env->lights_on; + if (atn < 0 || atn >= num_cells) { + reward -= 0.5f; // Invalid action penalty. + } else { + if (atn == env->last_action) { + reward -= 0.03f; // Penalty for pressing the same cell twice in a row. + } else if (atn == env->prev_action) { + reward -= 0.02f; // Penalty for 2-step loop (A,B,A). + } + if (env->client != NULL) { + env->client->cursor_row = atn / env->grid_size; + env->client->cursor_col = atn % env->grid_size; + } + step_grid(env, atn); + env->prev_action = env->last_action; + env->last_action = atn; + int next_on = env->lights_on; + reward += 0.005f * (float)(prev_on - next_on); // Dense shaping: improve when lights decrease. + } + env->step_count += 1; + + if (env->lights_on == 0) { + reward = 2.0f; // Solved reward. + env->ema = 0.85f * env->ema + 0.15f; // Update EMA of steps to solve. + env->terminals[0] = 1.0f; + } else if (env->client == NULL && env->step_count >= env->max_steps) { + reward -= 0.5f; // Timeout penalty during training. + env->ema = 0.85f * env->ema; // Decay EMA since we failed to solve. + env->terminals[0] = 1.0f; + } + + env->rewards[0] = reward; + env->episode_return += reward; + + if (env->terminals[0] > 0.0f) { + env->log.episode_return += env->episode_return; + env->log.episode_length += (float)env->step_count; + env->log.n += 1.0f; + env->log.perf += (env->lights_on == 0) ? 1.0f : 0.0f; + env->log.score += env->episode_return; + env->log.scramble_p += env->scramble_prob; + + env->score_ema = 0.9f * env->score_ema + 0.1f * env->episode_return; + init_lightsout(env); + } + + compute_observations(env); +} + +// Raylib client +static const Color COLORS[] = { + (Color){6, 24, 24, 255}, + (Color){0, 0, 255, 255}, + (Color){255, 255, 255, 255} +}; + +Client* make_client(int cell_size, int grid_size) { + Client* client= (Client*)malloc(sizeof(Client)); + client->cell_size = cell_size; + client->cursor_row = 0; + client->cursor_col = 0; + InitWindow(grid_size*cell_size, grid_size*cell_size, "PufferLib LightsOut"); + SetTargetFPS(5); + return client; +} + +void c_render(LightsOut* env) { + if (IsWindowReady() && (WindowShouldClose() || IsKeyPressed(KEY_ESCAPE))) { + c_close(env); + exit(0); + } + + if (env->client == NULL) { + env->client = make_client(env->cell_size, env->grid_size); + } + + Client* client = env->client; + + BeginDrawing(); + ClearBackground(COLORS[0]); + int sz = client->cell_size; + for (int y = 0; y < env->grid_size; y++) { + for (int x = 0; x < env->grid_size; x++){ + int tile = env->grid[y*env->grid_size + x]; + if (tile != 0) + DrawRectangle(x*sz, y*sz, sz, sz, COLORS[tile]); + } + } + DrawRectangleLinesEx( + (Rectangle){client->cursor_col * sz, client->cursor_row * sz, sz, sz}, + 3.0f, + COLORS[2] + ); + + if (env->terminals[0] > 0.0f) { + const char* msg = "Solved"; + int font_size = 48; + int text_w = MeasureText(msg, font_size); + int screen_w = env->grid_size * env->cell_size; + int screen_h = env->grid_size * env->cell_size; + + DrawRectangle(0, 0, screen_w, screen_h, (Color){0, 0, 0, 120}); // dim overlay + DrawText(msg, (screen_w - text_w) / 2, (screen_h - font_size) / 2, font_size, RAYWHITE); + } + + EndDrawing(); +} diff --git a/pufferlib/ocean/matsci/binding.c b/ocean/matsci/binding.c similarity index 100% rename from pufferlib/ocean/matsci/binding.c rename to ocean/matsci/binding.c diff --git a/pufferlib/ocean/matsci/matsci.c b/ocean/matsci/matsci.c similarity index 100% rename from pufferlib/ocean/matsci/matsci.c rename to ocean/matsci/matsci.c diff --git a/pufferlib/ocean/matsci/matsci.h b/ocean/matsci/matsci.h similarity index 100% rename from pufferlib/ocean/matsci/matsci.h rename to ocean/matsci/matsci.h diff --git a/ocean/maze/binding.c b/ocean/maze/binding.c new file mode 100644 index 0000000000..b91ae98999 --- /dev/null +++ b/ocean/maze/binding.c @@ -0,0 +1,105 @@ +#include "maze.h" +#define OBS_SIZE 121 +#define NUM_ATNS 1 +#define ACT_SIZES {5} +#define OBS_TENSOR_T ByteTensor + +#define MY_VEC_INIT +#define MY_VEC_CLOSE +#define Env Grid +#include "vecenv.h" + +Env* my_vec_init(int* num_envs_out, int* buffer_env_starts, int* buffer_env_counts, + Dict* vec_kwargs, Dict* env_kwargs) { + int total_agents = (int)dict_get(vec_kwargs, "total_agents")->value; + int num_buffers = (int)dict_get(vec_kwargs, "num_buffers")->value; + int agents_per_buffer = total_agents / num_buffers; + int num_envs = total_agents; + + int max_size = (int)dict_get(env_kwargs, "max_size")->value; + int num_maps = (int)dict_get(env_kwargs, "num_maps")->value; + int map_size = (int)dict_get(env_kwargs, "map_size")->value; + + if (max_size <= 5) { + *num_envs_out = 0; + return NULL; + } + + // Generate maze levels (shared across all envs) + State* levels = calloc(num_maps, sizeof(State)); + + // Temporary env used to generate maps + Grid temp_env; + temp_env.max_size = max_size; + init_maze(&temp_env); + + unsigned int map_rng = 42; + for (int i = 0; i < num_maps; i++) { + int sz = map_size; + if (map_size == -1) { + sz = 5 + (rand_r(&map_rng) % (max_size - 5)); + } + + if (sz % 2 == 0) { + sz -= 1; + } + + float difficulty = (float)rand_r(&map_rng) / (float)(RAND_MAX); + create_maze_level(&temp_env, sz, sz, difficulty, i); + init_state(&levels[i], max_size, 1); + get_state(&temp_env, &levels[i]); + } + + // Free temp env internal allocations + free(temp_env.maze); + free(temp_env.counts); + free(temp_env.agents); + + // Allocate all environments + Env* envs = (Env*)calloc(num_envs, sizeof(Env)); + + int buf = 0; + int buf_agents = 0; + buffer_env_starts[0] = 0; + buffer_env_counts[0] = 0; + + for (int i = 0; i < num_envs; i++) { + Env* env = &envs[i]; + env->rng = i; + env->max_size = max_size; + env->num_maps = num_maps; + env->num_agents = 1; + env->levels = levels; + init_maze(env); + + buf_agents += env->num_agents; + buffer_env_counts[buf]++; + if (buf_agents >= agents_per_buffer && buf < num_buffers - 1) { + buf++; + buffer_env_starts[buf] = i + 1; + buffer_env_counts[buf] = 0; + buf_agents = 0; + } + } + + *num_envs_out = num_envs; + return envs; +} + +void my_vec_close(Env* envs) { + free(envs[0].levels); +} + +void my_init(Env* env, Dict* kwargs) { + env->max_size = (int)dict_get(kwargs, "max_size")->value; + env->num_maps = (int)dict_get(kwargs, "num_maps")->value; + env->num_agents = 1; + init_maze(env); +} + +void my_log(Log* log, Dict* out) { + dict_set(out, "perf", log->perf); + dict_set(out, "score", log->score); + dict_set(out, "episode_return", log->episode_return); + dict_set(out, "episode_length", log->episode_length); +} diff --git a/ocean/maze/maze.c b/ocean/maze/maze.c new file mode 100644 index 0000000000..6c49af92b9 --- /dev/null +++ b/ocean/maze/maze.c @@ -0,0 +1,81 @@ +#include "maze.h" +#include "puffernet.h" + +void demo() { + Weights* weights = load_weights("resources/maze/maze_weights.bin"); + int logit_sizes[1] = {5}; + PufferNet* net = make_puffernet(weights, 1, 121, 512, 5, logit_sizes, 1); + + int max_size = 47; + int num_maps = 64; + int num_agents = 1; + int horizon = 256; + float speed = 1; + int vision = 5; + bool discretize = true; + + Grid* env = allocate_maze(max_size, num_agents, horizon, + vision, speed, discretize); + + // Generate maps matching binding.c: random odd sizes, random difficulty + State* levels = calloc(num_maps, sizeof(State)); + Grid temp_env; + temp_env.max_size = max_size; + init_maze(&temp_env); + unsigned int map_rng = 42; + for (int i = 0; i < num_maps; i++) { + int sz = 5 + (rand_r(&map_rng) % (max_size - 5)); + if (sz % 2 == 0) sz -= 1; + float difficulty = (float)rand_r(&map_rng) / (float)(RAND_MAX); + create_maze_level(&temp_env, sz, sz, difficulty, i); + init_state(&levels[i], max_size, num_agents); + get_state(&temp_env, &levels[i]); + } + free(temp_env.maze); + + env->num_maps = num_maps; + env->levels = levels; + + c_reset(env); + c_render(env); + while (!WindowShouldClose()) { + env->actions[0] = ATN_PASS; + Agent* agent = &env->agents[0]; + + if (IsKeyDown(KEY_LEFT_SHIFT)) { + if (IsKeyDown(KEY_UP) || IsKeyDown(KEY_W)){ + agent->direction = 3.0*PI/2.0; + env->actions[0] = ATN_FORWARD; + } else if (IsKeyDown(KEY_DOWN) || IsKeyDown(KEY_S)) { + agent->direction = PI/2.0; + env->actions[0] = ATN_FORWARD; + } else if (IsKeyDown(KEY_LEFT) || IsKeyDown(KEY_A)) { + agent->direction = PI; + env->actions[0] = ATN_FORWARD; + } else if (IsKeyDown(KEY_RIGHT) || IsKeyDown(KEY_D)) { + agent->direction = 0; + env->actions[0] = ATN_FORWARD; + } else { + env->actions[0] = ATN_PASS; + } + } else { + float obs[121]; + for (int i = 0; i < 121; i++) obs[i] = env->observations[i]; + forward_puffernet(net, obs, env->actions); + } + + c_step(env); + c_render(env); + } + + free_puffernet(net); + free(weights); + free_allocated_maze(env); + for (int i = 0; i < num_maps; i++) free_state(&levels[i]); + free(levels); +} + +int main() { + demo(); + return 0; +} diff --git a/pufferlib/ocean/grid/grid.h b/ocean/maze/maze.h similarity index 82% rename from pufferlib/ocean/grid/grid.h rename to ocean/maze/maze.h index c82001d750..55b4b200d3 100644 --- a/pufferlib/ocean/grid/grid.h +++ b/ocean/maze/maze.h @@ -46,8 +46,8 @@ struct Log { bool is_agent(int idx) { return idx >= AGENT && idx < AGENT + 8; } -int rand_color() { - return AGENT + rand()%8; +int rand_color(unsigned int* rng) { + return AGENT + rand_r(rng)%8; } // 6 unique keys and doors @@ -95,28 +95,29 @@ struct Grid{ int max_size; bool discretize; Log log; + unsigned int rng; Agent* agents; - unsigned char* grid; + unsigned char* maze; int* counts; unsigned char* observations; float* actions; float* rewards; - unsigned char* terminals; + float* terminals; }; -void init_grid(Grid* env) { +void init_maze(Grid* env) { env->num_agents = 1; env->vision = 5; env->speed = 1; env->discretize = true; env->obs_size = 2*env->vision + 1; int env_mem= env->max_size * env->max_size; - env->grid = calloc(env_mem, sizeof(unsigned char)); + env->maze = calloc(env_mem, sizeof(unsigned char)); env->counts = calloc(env_mem, sizeof(int)); env->agents = calloc(env->num_agents, sizeof(Agent)); } -Grid* allocate_grid(int max_size, int num_agents, int horizon, +Grid* allocate_maze(int max_size, int num_agents, int horizon, int vision, float speed, bool discretize) { Grid* env = (Grid*)calloc(1, sizeof(Grid)); env->max_size = max_size; @@ -128,21 +129,20 @@ Grid* allocate_grid(int max_size, int num_agents, int horizon, int obs_size = 2*vision + 1; env->observations = calloc( num_agents*obs_size*obs_size, sizeof(unsigned char)); - env->actions = calloc(num_agents, sizeof(float)); + env->actions = calloc(num_agents, sizeof(double)); env->rewards = calloc(num_agents, sizeof(float)); - env->terminals = calloc(num_agents, sizeof(unsigned char)); - init_grid(env); + env->terminals = calloc(num_agents, sizeof(float)); + init_maze(env); return env; } void c_close(Grid* env) { - free(env->grid); + free(env->maze); free(env->counts); free(env->agents); - free(env); } -void free_allocated_grid(Grid* env) { +void free_allocated_maze(Grid* env) { free(env->observations); free(env->actions); free(env->rewards); @@ -155,7 +155,7 @@ bool in_bounds(Grid* env, int y, int c) { && c >= 0 && c <= env->width); } -int grid_offset(Grid* env, int y, int x) { +int maze_offset(Grid* env, int y, int x) { return y*env->max_size + x; } @@ -199,8 +199,8 @@ void compute_observations(Grid* env) { int r_idx = r - y + env->vision; int c_idx = c - x + env->vision; int obs_adr = obs_offset + r_idx*env->obs_size + c_idx; - int adr = grid_offset(env, r, c); - env->observations[obs_adr] = env->grid[adr]; + int adr = maze_offset(env, r, c); + env->observations[obs_adr] = env->maze[adr]; } } /* @@ -218,16 +218,16 @@ void compute_observations(Grid* env) { void make_border(Grid*env) { for (int r = 0; r < env->height; r++) { - int adr = grid_offset(env, r, 0); - env->grid[adr] = WALL; - adr = grid_offset(env, r, env->width-1); - env->grid[adr] = WALL; + int adr = maze_offset(env, r, 0); + env->maze[adr] = WALL; + adr = maze_offset(env, r, env->width-1); + env->maze[adr] = WALL; } for (int c = 0; c < env->width; c++) { - int adr = grid_offset(env, 0, c); - env->grid[adr] = WALL; - adr = grid_offset(env, env->height-1, c); - env->grid[adr] = WALL; + int adr = maze_offset(env, 0, c); + env->maze[adr] = WALL; + adr = maze_offset(env, env->height-1, c); + env->maze[adr] = WALL; } } @@ -236,15 +236,15 @@ void spawn_agent(Grid* env, int idx, int x, int y) { int spawn_y = y; int spawn_x = x; assert(in_bounds(env, spawn_y, spawn_x)); - int adr = grid_offset(env, spawn_y, spawn_x); - assert(env->grid[adr] == EMPTY); + int adr = maze_offset(env, spawn_y, spawn_x); + assert(env->maze[adr] == EMPTY); agent->spawn_y = spawn_y; agent->spawn_x = spawn_x; agent->y = agent->spawn_y; agent->x = agent->spawn_x; agent->prev_y = agent->y; agent->prev_x = agent->x; - env->grid[adr] = agent->color; + env->maze[adr] = agent->color; agent->direction = 0; agent->held = -1; agent->color = AGENT; @@ -255,17 +255,17 @@ struct State { int height; int num_agents; Agent* agents; - unsigned char* grid; + unsigned char* maze; }; void init_state(State* state, int max_size, int num_agents) { state->agents = calloc(num_agents, sizeof(Agent)); - state->grid = calloc(max_size*max_size, sizeof(unsigned char)); + state->maze = calloc(max_size*max_size, sizeof(unsigned char)); } void free_state(State* state) { free(state->agents); - free(state->grid); + free(state->maze); free(state); } @@ -274,7 +274,7 @@ void get_state(Grid* env, State* state) { state->height = env->height; state->num_agents = env->num_agents; memcpy(state->agents, env->agents, env->num_agents*sizeof(Agent)); - memcpy(state->grid, env->grid, env->max_size*env->max_size); + memcpy(state->maze, env->maze, env->max_size*env->max_size); } void set_state(Grid* env, State* state) { @@ -283,14 +283,14 @@ void set_state(Grid* env, State* state) { env->horizon = 2*env->width*env->height; env->num_agents = state->num_agents; memcpy(env->agents, state->agents, env->num_agents*sizeof(Agent)); - memcpy(env->grid, state->grid, env->max_size*env->max_size); + memcpy(env->maze, state->maze, env->max_size*env->max_size); } void c_reset(Grid* env) { - memset(env->grid, 0, env->max_size*env->max_size); + memset(env->maze, 0, env->max_size*env->max_size); memset(env->counts, 0, env->max_size*env->max_size*sizeof(int)); env->tick = 0; - int idx = rand() % env->num_maps; + int idx = rand_r(&env->rng) % env->num_maps; set_state(env, &env->levels[idx]); compute_observations(env); } @@ -301,13 +301,13 @@ int move_to(Grid* env, int agent_idx, float y, float x) { return 1; } - int adr = grid_offset(env, round(y), round(x)); - int dest = env->grid[adr]; + int adr = maze_offset(env, round(y), round(x)); + int dest = env->maze[adr]; if (dest == WALL) { return 1; } else if (dest == REWARD || dest == GOAL) { env->rewards[agent_idx] = 1.0; - env->terminals[agent_idx] = 1; + env->terminals[agent_idx] = 1.0f; add_log(env, agent_idx); } else if (is_key(dest)) { if (agent->held != -1) { @@ -317,15 +317,15 @@ int move_to(Grid* env, int agent_idx, float y, float x) { } else if (is_locked_door(dest)) { if (!is_correct_key(agent->held, dest)) { return 1; } agent->held = -1; - env->grid[adr] = EMPTY; + env->maze[adr] = EMPTY; } int start_y = round(agent->y); int start_x = round(agent->x); - int start_adr = grid_offset(env, start_y, start_x); - env->grid[start_adr] = EMPTY; + int start_adr = maze_offset(env, start_y, start_x); + env->maze[start_adr] = EMPTY; - env->grid[adr] = agent->color; + env->maze[adr] = agent->color; agent->y = y; agent->x = x; return 0; @@ -336,7 +336,7 @@ bool step_agent(Grid* env, int idx) { agent->prev_y = agent->y; agent->prev_x = agent->x; - float atn = env->actions[idx]; + double atn = env->actions[idx]; float direction = agent->direction; if (env->discretize) { @@ -397,7 +397,7 @@ bool step_agent(Grid* env, int idx) { int x_int = agent->x; int y_int = agent->y; - int adr = grid_offset(env, y_int, x_int); + int adr = maze_offset(env, y_int, x_int); env->counts[adr]++; //env->rewards[idx] += 0.01 / (float)env->counts[adr]; //env->log.episode_return += 0.01 / (float)env->counts[adr]; @@ -405,7 +405,7 @@ bool step_agent(Grid* env, int idx) { } void c_step(Grid* env) { - memset(env->terminals, 0, env->num_agents); + memset(env->terminals, 0, env->num_agents * sizeof(float)); memset(env->rewards, 0, env->num_agents*sizeof(float)); env->tick++; @@ -429,7 +429,7 @@ void c_step(Grid* env) { if (done) { c_reset(env); - int idx = rand() % env->num_maps; + int idx = rand_r(&env->rng) % env->num_maps; set_state(env, &env->levels[idx]); compute_observations(env); } @@ -508,7 +508,7 @@ void c_render(Grid* env) { Agent* agent = &env->agents[0]; int r = agent->y; int c = agent->x; - int adr = grid_offset(env, r, c); + int adr = maze_offset(env, r, c); //renderer->overlay[adr] = overlay; //renderer->overlay[adr] -= 0.1; //renderer->overlay[adr] = -1 + 1.0/(float)env->counts[adr]; @@ -519,8 +519,8 @@ void c_render(Grid* env) { int ts = renderer->cell_size; for (int r = 0; r < env->height; r++) { for (int c = 0; c < env->width; c++){ - adr = grid_offset(env, r, c); - int tile = env->grid[adr]; + adr = maze_offset(env, r, c); + int tile = env->maze[adr]; if (tile == EMPTY) { continue; overlay = renderer->overlay[adr]; @@ -598,46 +598,46 @@ void generate_locked_room(Grid* env) { make_border(env); for (int r = 0; r < env->height; r++) { - int adr = grid_offset(env, r, 7); - env->grid[adr] = WALL; - adr = grid_offset(env, r, 11); - env->grid[adr] = WALL; + int adr = maze_offset(env, r, 7); + env->maze[adr] = WALL; + adr = maze_offset(env, r, 11); + env->maze[adr] = WALL; } for (int c = 0; c < 7; c++) { - int adr = grid_offset(env, 6, c); - env->grid[adr] = WALL; - adr = grid_offset(env, 12, c); - env->grid[adr] = WALL; + int adr = maze_offset(env, 6, c); + env->maze[adr] = WALL; + adr = maze_offset(env, 12, c); + env->maze[adr] = WALL; } for (int c = 11; c < env->width; c++) { - int adr = grid_offset(env, 6, c); - env->grid[adr] = WALL; - adr = grid_offset(env, 12, c); - env->grid[adr] = WALL; + int adr = maze_offset(env, 6, c); + env->maze[adr] = WALL; + adr = maze_offset(env, 12, c); + env->maze[adr] = WALL; } - int adr = grid_offset(env, 3, 7); - env->grid[adr] = DOOR_OPEN; - adr = grid_offset(env, 9, 7); - env->grid[adr] = DOOR_OPEN + 1; - adr = grid_offset(env, 15, 7); - env->grid[adr] = DOOR_OPEN + 2; - adr = grid_offset(env, 3, 11); - env->grid[adr] = DOOR_OPEN + 3; - adr = grid_offset(env, 9, 11); - env->grid[adr] = DOOR_OPEN + 4; - adr = grid_offset(env, 15, 11); - env->grid[adr] = DOOR_LOCKED + 5; - - adr = grid_offset(env, 4, 15); - env->grid[adr] = KEY + 5; - - adr = grid_offset(env, 16, 17); - env->grid[adr] = GOAL; + int adr = maze_offset(env, 3, 7); + env->maze[adr] = DOOR_OPEN; + adr = maze_offset(env, 9, 7); + env->maze[adr] = DOOR_OPEN + 1; + adr = maze_offset(env, 15, 7); + env->maze[adr] = DOOR_OPEN + 2; + adr = maze_offset(env, 3, 11); + env->maze[adr] = DOOR_OPEN + 3; + adr = maze_offset(env, 9, 11); + env->maze[adr] = DOOR_OPEN + 4; + adr = maze_offset(env, 15, 11); + env->maze[adr] = DOOR_LOCKED + 5; + + adr = maze_offset(env, 4, 15); + env->maze[adr] = KEY + 5; + + adr = maze_offset(env, 16, 17); + env->maze[adr] = GOAL; } -void generate_growing_tree_maze(unsigned char* grid, +void generate_growing_tree_maze(unsigned char* maze, int width, int height, int max_size, float difficulty, int seed) { - srand(seed); + unsigned int rng = seed; int dx[4] = {-1, 0, 1, 0}; int dy[4] = {0, 1, 0, -1}; int dirs[4] = {0, 1, 2, 3}; @@ -647,18 +647,18 @@ void generate_growing_tree_maze(unsigned char* grid, bool visited[width*height]; memset(visited, false, width*height); - memset(grid, WALL, max_size*height); + memset(maze, WALL, max_size*height); for (int r = 0; r < height; r++) { for (int c = 0; c < width; c++) { int adr = r*max_size + c; if (r % 2 == 1 && c % 2 == 1) { - grid[adr] = EMPTY; + maze[adr] = EMPTY; } } } - int x_init = rand() % (width - 1); - int y_init = rand() % (height - 1); + int x_init = rand_r(&rng) % (width - 1); + int y_init = rand_r(&rng) % (height - 1); if (x_init % 2 == 0) { x_init++; @@ -677,8 +677,8 @@ void generate_growing_tree_maze(unsigned char* grid, //SetTargetFPS(60); while (num_cells > 0) { - if (rand() % 1000 > 1000*difficulty) { - int i = rand() % num_cells; + if (rand_r(&rng) % 1000 > 1000*difficulty) { + int i = rand_r(&rng) % num_cells; int tmp_x = cells[2*num_cells - 2]; int tmp_y = cells[2*num_cells - 1]; cells[2*num_cells - 2] = cells[2*i]; @@ -695,7 +695,7 @@ void generate_growing_tree_maze(unsigned char* grid, // In-place direction shuffle for (int i = 0; i < 4; i++) { - int ii = i + rand() % (4 - i); + int ii = i + rand_r(&rng) % (4 - i); int tmp = dirs[i]; dirs[i] = dirs[ii]; dirs[ii] = tmp; @@ -724,7 +724,7 @@ void generate_growing_tree_maze(unsigned char* grid, ny = y + dy[dir]; int adr = ny*max_size + nx; - grid[adr] = EMPTY; + maze[adr] = EMPTY; num_cells++; made_path = true; @@ -739,7 +739,7 @@ void generate_growing_tree_maze(unsigned char* grid, for (int r = 0; r < height; r++) { for (int c = 0; c < width; c++){ int adr = r*max_size + c; - int tile = grid[adr]; + int tile = maze[adr]; if (tile == WALL) { DrawRectangle(c*cell, r*cell, cell, cell, color); } @@ -759,9 +759,9 @@ void generate_growing_tree_maze(unsigned char* grid, void create_maze_level(Grid* env, int width, int height, float difficulty, int seed) { env->width = width; env->height = height; - generate_growing_tree_maze(env->grid, width, height, env->max_size, difficulty, seed); + generate_growing_tree_maze(env->maze, width, height, env->max_size, difficulty, seed); make_border(env); spawn_agent(env, 0, 1, 1); - int goal_adr = grid_offset(env, env->height - 2, env->width - 2); - env->grid[goal_adr] = GOAL; + int goal_adr = maze_offset(env, env->height - 2, env->width - 2); + env->maze[goal_adr] = GOAL; } diff --git a/pufferlib/ocean/memory/binding.c b/ocean/memory/binding.c similarity index 100% rename from pufferlib/ocean/memory/binding.c rename to ocean/memory/binding.c diff --git a/pufferlib/ocean/memory/memory.c b/ocean/memory/memory.c similarity index 100% rename from pufferlib/ocean/memory/memory.c rename to ocean/memory/memory.c diff --git a/pufferlib/ocean/memory/memory.h b/ocean/memory/memory.h similarity index 100% rename from pufferlib/ocean/memory/memory.h rename to ocean/memory/memory.h diff --git a/ocean/moba/binding.c b/ocean/moba/binding.c new file mode 100644 index 0000000000..6a73652fae --- /dev/null +++ b/ocean/moba/binding.c @@ -0,0 +1,121 @@ +#include "moba.h" +#define OBS_SIZE 510 +#define NUM_ATNS 6 +#define ACT_SIZES {7, 7, 3, 2, 2, 2} +#define OBS_TENSOR_T ByteTensor + +#define MY_VEC_INIT +#define MY_VEC_CLOSE +#define Env MOBA +#include "vecenv.h" + +void my_vec_close(Env* envs) { + free(envs[0].ai_paths); +} + +Env* my_vec_init(int* num_envs_out, int* buffer_env_starts, int* buffer_env_counts, + Dict* vec_kwargs, Dict* env_kwargs) { + int num_envs = (int)dict_get(vec_kwargs, "total_agents")->value; + int num_buffers = (int)dict_get(vec_kwargs, "num_buffers")->value; + + int vision_range = (int)dict_get(env_kwargs, "vision_range")->value; + float agent_speed = dict_get(env_kwargs, "agent_speed")->value; + float reward_death = dict_get(env_kwargs, "reward_death")->value; + float reward_xp = dict_get(env_kwargs, "reward_xp")->value; + float reward_distance = dict_get(env_kwargs, "reward_distance")->value; + float reward_tower = dict_get(env_kwargs, "reward_tower")->value; + int script_opponents = (int)dict_get(env_kwargs, "script_opponents")->value; + + + + // ai_paths (256 MB) is shared — same map, so BFS results are identical across envs. + // ai_path_buffer (1.5 MB) must be per-env: bfs() uses it as a scratch queue + // starting from index 0 on every call, so concurrent BFS calls corrupt each other. + unsigned char* ai_paths = calloc(128*128*128*128, sizeof(unsigned char)); + for (int i = 0; i < 128*128*128*128; i++) { + ai_paths[i] = 255; + } + + // Calculate agents per env based on script_opponents + int agents_per_env = script_opponents ? 5 : 10; + int total_envs = num_envs / agents_per_env; + + Env* envs = (Env*)calloc(total_envs, sizeof(Env)); + + for (int i = 0; i < total_envs; i++) { + Env* env = &envs[i]; + env->num_agents = agents_per_env; + env->vision_range = vision_range; + env->agent_speed = agent_speed; + env->reward_death = reward_death; + env->reward_xp = reward_xp; + env->reward_distance = reward_distance; + env->reward_tower = reward_tower; + env->script_opponents = script_opponents; + env->ai_path_buffer = calloc(3*8*128*128, sizeof(int)); + env->ai_paths = ai_paths; + init_moba(env, game_map_npy); + } + + int agents_per_buffer = num_envs / num_buffers; + int buf = 0; + int buf_agents = 0; + buffer_env_starts[0] = 0; + buffer_env_counts[0] = 0; + for (int i = 0; i < total_envs; i++) { + buf_agents += envs[i].num_agents; + buffer_env_counts[buf]++; + if (buf_agents >= agents_per_buffer && buf < num_buffers - 1) { + buf++; + buffer_env_starts[buf] = i + 1; + buffer_env_counts[buf] = 0; + buf_agents = 0; + } + } + + *num_envs_out = total_envs; + return envs; +} + +void my_init(Env* env, Dict* kwargs) { + env->vision_range = dict_get(kwargs, "vision_range")->value; + env->agent_speed = dict_get(kwargs, "agent_speed")->value; + env->reward_death = dict_get(kwargs, "reward_death")->value; + env->reward_xp = dict_get(kwargs, "reward_xp")->value; + env->reward_distance = dict_get(kwargs, "reward_distance")->value; + env->reward_tower = dict_get(kwargs, "reward_tower")->value; + env->script_opponents = dict_get(kwargs, "script_opponents")->value; + env->num_agents = env->script_opponents ? 5 : 10; +} + +void my_log(Log* log, Dict* out) { + dict_set(out, "perf", log->perf); + dict_set(out, "score", log->score); + dict_set(out, "episode_return", log->episode_return); + dict_set(out, "episode_length", log->episode_length); + dict_set(out, "radiant_victory", log->radiant_victory); + dict_set(out, "dire_victory", log->dire_victory); + dict_set(out, "radiant_level", log->radiant_level); + dict_set(out, "dire_level", log->dire_level); + dict_set(out, "radiant_towers_alive", log->radiant_towers_alive); + dict_set(out, "dire_towers_alive", log->dire_towers_alive); + dict_set(out, "radiant_support_episode_return", log->radiant_support_episode_return); + dict_set(out, "radiant_support_reward_death", log->radiant_support_reward_death); + dict_set(out, "radiant_support_reward_xp", log->radiant_support_reward_xp); + dict_set(out, "radiant_support_reward_distance", log->radiant_support_reward_distance); + dict_set(out, "radiant_support_reward_tower", log->radiant_support_reward_tower); + dict_set(out, "radiant_support_level", log->radiant_support_level); + dict_set(out, "radiant_support_kills", log->radiant_support_kills); + dict_set(out, "radiant_support_deaths", log->radiant_support_deaths); + dict_set(out, "radiant_support_damage_dealt", log->radiant_support_damage_dealt); + dict_set(out, "radiant_support_damage_received", log->radiant_support_damage_received); + dict_set(out, "radiant_support_healing_dealt", log->radiant_support_healing_dealt); + dict_set(out, "radiant_support_healing_received", log->radiant_support_healing_received); + dict_set(out, "radiant_support_creeps_killed", log->radiant_support_creeps_killed); + dict_set(out, "radiant_support_neutrals_killed", log->radiant_support_neutrals_killed); + dict_set(out, "radiant_support_towers_killed", log->radiant_support_towers_killed); + dict_set(out, "radiant_support_usage_auto", log->radiant_support_usage_auto); + dict_set(out, "radiant_support_usage_q", log->radiant_support_usage_q); + dict_set(out, "radiant_support_usage_w", log->radiant_support_usage_w); + dict_set(out, "radiant_support_usage_e", log->radiant_support_usage_e); +} diff --git a/pufferlib/ocean/moba/game_map.h b/ocean/moba/game_map.h similarity index 100% rename from pufferlib/ocean/moba/game_map.h rename to ocean/moba/game_map.h diff --git a/ocean/moba/moba.c b/ocean/moba/moba.c new file mode 100644 index 0000000000..721d7eada5 --- /dev/null +++ b/ocean/moba/moba.c @@ -0,0 +1,43 @@ +#include "moba.h" +#include "puffernet.h" + +void demo() { + // encoder(64x510=32640) + decoder(24x64=1536) + 5x mingru(192x64=12288) = 95616 + Weights* weights = load_weights("resources/moba/moba_weights.bin"); + + int logit_sizes[6] = {7, 7, 3, 2, 2, 2}; + PufferNet* net = make_puffernet(weights, 5, 510, 64, 5, logit_sizes, 6); + + MOBA env = { + .vision_range = 5, + .agent_speed = 1.0, + .reward_death = -0.163764, + .reward_xp = 0.00665677, + .reward_distance = 0, + .reward_tower = 0.642119, + .script_opponents = true, + }; + allocate_moba(&env); + c_reset(&env); + + float obs_f[5 * 510]; + c_render(&env); + int frame = 1; + while (!WindowShouldClose()) { + if (frame % 12 == 0) { + for (int i = 0; i < 5 * 510; i++) + obs_f[i] = (float)env.observations[i]; + forward_puffernet(net, obs_f, env.actions); + c_step(&env); + } + c_render(&env); + frame = (frame + 1) % 12; + } + free_puffernet(net); + free(weights); + free_allocated_moba(&env); +} + +int main() { + demo(); +} diff --git a/pufferlib/ocean/moba/moba.h b/ocean/moba/moba.h similarity index 96% rename from pufferlib/ocean/moba/moba.h rename to ocean/moba/moba.h index bfe399f83c..532d08cc97 100644 --- a/pufferlib/ocean/moba/moba.h +++ b/ocean/moba/moba.h @@ -4,7 +4,8 @@ #include #include #include -#include // xxd -i game_map.npy > game_map.h #include "game_map.h" +#include // xxd -i game_map.npy > game_map.h +#include "game_map.h" #include "raylib.h" @@ -341,7 +342,6 @@ struct MOBA { GameRenderer* client; int vision_range; float agent_speed; - bool discretize; bool script_opponents; int obs_size; int creep_idx; @@ -353,10 +353,11 @@ struct MOBA { unsigned char* ai_paths; int* ai_path_buffer; unsigned char* observations; - int* actions; + float* actions; float* rewards; - unsigned char* terminals; + float* terminals; unsigned char* truncations; + int num_agents; Entity* entities; Reward* reward_components; Log log; @@ -381,6 +382,7 @@ struct MOBA { void add_log(MOBA* env, int radiant_victory, int dire_victory) { Log* log = &env->log; + int num_agents = env->script_opponents ? 5 : NUM_PLAYERS; log->n += 1; log->score += radiant_victory; log->perf += radiant_victory; @@ -402,6 +404,15 @@ void add_log(MOBA* env, int radiant_victory, int dire_victory) { } } + for (int i = 0; i < num_agents; i++) { + PlayerLog* pl = &env->player_logs[i]; + log->episode_return += pl->episode_return; + log->reward_death += pl->reward_death; + log->reward_xp += pl->reward_xp; + log->reward_distance += pl->reward_distance; + log->reward_tower += pl->reward_tower; + } + PlayerLog* radiant_support = &env->player_logs[0]; log->radiant_support_episode_return = radiant_support->episode_return; log->radiant_support_reward_death = radiant_support->reward_death; @@ -425,24 +436,24 @@ void add_log(MOBA* env, int radiant_victory, int dire_victory) { } void c_close(MOBA* env) { + free(env->entities); free(env->reward_components); free(env->map->grid); + free(env->map->pids); free(env->map); free(env->orig_grid); free(env->rng->rng); free(env->rng); + free(env->ai_path_buffer); } void free_allocated_moba(MOBA* env) { free(env->rewards); - free(env->map->pids); - free(env->ai_path_buffer); free(env->ai_paths); free(env->observations); free(env->actions); free(env->terminals); free(env->truncations); - free(env->entities); c_close(env); } @@ -466,30 +477,30 @@ void compute_observations(MOBA* env) { int x = player->x; // TODO: Add bounds debug checks asserts - obs_extra[0] = 2*x; - obs_extra[1] = 2*y; - obs_extra[2] = 255*player->level/30.0; - obs_extra[3] = 255*player->health/player->max_health; - obs_extra[4] = 255*player->mana/player->max_mana; - obs_extra[5] = player->damage / 4.0; - obs_extra[6] = 100*player->move_speed; - obs_extra[7] = player->move_modifier*100; - obs_extra[8] = 2*player->stun_timer; - obs_extra[9] = 2*player->move_timer; - obs_extra[10] = 2*player->q_timer; - obs_extra[11] = 2*player->w_timer; - obs_extra[12] = 2*player->e_timer; - obs_extra[13] = 50*player->basic_attack_timer; - obs_extra[14] = 50*player->basic_attack_cd; - obs_extra[15] = 255*player->is_hit; - obs_extra[16] = 255*player->team; - obs_extra[17 + player->hero_type] = 255; + obs_extra[0] = x; + obs_extra[1] = y; + obs_extra[2] = player->level; + obs_extra[3] = 10*player->health/player->max_health; + obs_extra[4] = 10*player->mana/player->max_mana; + obs_extra[5] = player->damage / 50.0; + obs_extra[6] = player->move_speed; + obs_extra[7] = player->move_modifier; + obs_extra[8] = player->stun_timer; + obs_extra[9] = player->move_timer; + obs_extra[10] = player->q_timer; + obs_extra[11] = player->w_timer; + obs_extra[12] = player->e_timer; + obs_extra[13] = player->basic_attack_timer; + obs_extra[14] = player->basic_attack_cd; + obs_extra[15] = player->is_hit; + obs_extra[16] = player->team; + obs_extra[17 + player->hero_type] = 1; // Assumes scaled between -1 and 1, else overflows - obs_extra[22] = (reward->death == 0) ? 0 : 255; - obs_extra[23] = (reward->xp == 0) ? 0 : 255; - obs_extra[24] = (reward->distance == 0) ? 0 : 255; - obs_extra[25] = (reward->tower == 0) ? 0 : 255; + obs_extra[22] = (reward->death == 0) ? 0 : 1; + obs_extra[23] = (reward->xp == 0) ? 0 : 1; + obs_extra[24] = (reward->distance == 0) ? 0 : 1; + obs_extra[25] = (reward->tower == 0) ? 0 : 1; for (int dy = -vis; dy <= vis; dy++) { for (int dx = -vis; dx <= vis; dx++) { @@ -511,11 +522,11 @@ void compute_observations(MOBA* env) { continue; Entity* target = &env->entities[target_pid]; - obs_map[map_idx+1] = 255*target->health/target->max_health; + obs_map[map_idx+1] = 10*target->health/target->max_health; if (target->max_mana > 0) { // Towers do not have mana - obs_map[map_idx+2] = 255*target->mana/target->max_mana; + obs_map[map_idx+2] = 10*target->mana/target->max_mana; } - obs_map[map_idx+3] = target->level/30.0; + obs_map[map_idx+3] = target->level; } } } @@ -1489,21 +1500,21 @@ void step_players(MOBA* env) { } */ } else { - int (*actions)[6] = (int(*)[6])env->actions; + float (*actions)[6] = (float(*)[6])env->actions; //float vel_y = (actions[pid][0] > 0) ? 1 : -1; //float vel_x = (actions[pid][1] > 0) ? 1 : -1; - float vel_y = actions[pid][0] / 300.0f; - float vel_x = actions[pid][1] / 300.0f; + float vel_y = (actions[pid][0] - 3.0f) / 3.0f; + float vel_x = (actions[pid][1] - 3.0f) / 3.0f; float mag = sqrtf(vel_y*vel_y + vel_x*vel_x); if (mag > 1) { vel_y /= mag; vel_x /= mag; } - int attack_target = actions[pid][2]; - bool use_q = actions[pid][3]; - bool use_w = actions[pid][4]; - bool use_e = actions[pid][5]; + int attack_target = (int)actions[pid][2]; + bool use_q = (int)actions[pid][3]; + bool use_w = (int)actions[pid][4]; + bool use_e = (int)actions[pid][5]; if (attack_target == 1 || attack_target == 0) { // Scan everything @@ -1788,12 +1799,11 @@ MOBA* allocate_moba(MOBA* env) { // TODO: Don't hardcode sizes int agents = (env->script_opponents) ? NUM_PLAYERS/2 : NUM_PLAYERS; env->observations = calloc(agents*(11*11*4 + 26), sizeof(unsigned char)); - env->actions = calloc(agents*6, sizeof(int)); + env->actions = calloc(agents*6, sizeof(float)); env->rewards = calloc(agents, sizeof(float)); - env->terminals = calloc(agents, sizeof(unsigned char)); + env->terminals = calloc(agents, sizeof(float)); env->truncations = calloc(agents, sizeof(unsigned char)); - unsigned char* game_map_npy = read_file("resources/moba/game_map.npy"); env->ai_path_buffer = calloc(3*8*128*128, sizeof(int)); env->ai_paths = calloc(128*128*128*128, sizeof(unsigned char)); for (int i = 0; i < 128*128*128*128; i++) { @@ -1801,7 +1811,6 @@ MOBA* allocate_moba(MOBA* env) { } init_moba(env, game_map_npy); - free(game_map_npy); return env; } @@ -2115,9 +2124,7 @@ GameRenderer* init_game_renderer(int cell_size, int width, int height) { return renderer; } -//def render(self, grid, pids, entities, obs_players, actions, discretize, frames): #define FRAMES 12 - void draw_bars(Entity* entity, int x, int y, int width, int height, bool draw_text) { float health_bar = entity->health / entity->max_health; float mana_bar = entity->mana / entity->max_mana; @@ -2192,16 +2199,16 @@ int c_render(MOBA* env) { int human = renderer->human_player; bool HUMAN_CONTROL = IsKeyDown(KEY_LEFT_SHIFT); - int (*actions)[6] = (int(*)[6])env->actions; + float (*actions)[6] = (float(*)[6])env->actions; // Clears so as to not let the nn spam actions if (HUMAN_CONTROL && frame % 12 == 0) { - actions[human][0] = 0; - actions[human][1] = 0; - actions[human][2] = 0; - actions[human][3] = 0; - actions[human][4] = 0; - actions[human][5] = 0; + actions[human][0] = 0.0; + actions[human][1] = 0.0; + actions[human][2] = 0.0; + actions[human][3] = 0.0; + actions[human][4] = 0.0; + actions[human][5] = 0.0; } // TODO: better way to null clicks? @@ -2216,10 +2223,10 @@ int c_render(MOBA* env) { renderer->last_click_x = -1; renderer->last_click_y = -1; } - + if (HUMAN_CONTROL) { - actions[human][0] = 300*dy; - actions[human][1] = 300*dx; + actions[human][0] = 300.0*dy; + actions[human][1] = 300.0*dx; } } if (IsKeyDown(KEY_ESCAPE)) { @@ -2227,16 +2234,16 @@ int c_render(MOBA* env) { } if (HUMAN_CONTROL) { if (IsKeyDown(KEY_Q) || IsKeyPressed(KEY_Q)) { - actions[human][3] = 1; + actions[human][3] = 1.0; } if (IsKeyDown(KEY_W) || IsKeyPressed(KEY_W)) { - actions[human][4] = 1; + actions[human][4] = 1.0; } if (IsKeyDown(KEY_E) || IsKeyPressed(KEY_E)) { - actions[human][5] = 1; + actions[human][5] = 1.0; } if (IsKeyDown(KEY_LEFT_SHIFT)) { - actions[human][2] = 2; // Target heroes + actions[human][2] = 2.0; // Target heroes } } // Num keys toggle selected player diff --git a/ocean/nmmo3/binding.c b/ocean/nmmo3/binding.c new file mode 100644 index 0000000000..b2d5fb4100 --- /dev/null +++ b/ocean/nmmo3/binding.c @@ -0,0 +1,52 @@ +#include "nmmo3.h" +#define OBS_SIZE 1707 +#define NUM_ATNS 1 +#define ACT_SIZES {26} +#define OBS_TENSOR_T ByteTensor + +#define Env MMO +#include "vecenv.h" + +void my_init(Env* env, Dict* kwargs) { + env->width = dict_get(kwargs, "width")->value; + env->height = dict_get(kwargs, "height")->value; + env->num_agents = dict_get(kwargs, "num_agents")->value; + env->num_enemies = dict_get(kwargs, "num_enemies")->value; + env->num_resources = dict_get(kwargs, "num_resources")->value; + env->num_weapons = dict_get(kwargs, "num_weapons")->value; + env->num_gems = dict_get(kwargs, "num_gems")->value; + env->tiers = dict_get(kwargs, "tiers")->value; + env->levels = dict_get(kwargs, "levels")->value; + env->teleportitis_prob = dict_get(kwargs, "teleportitis_prob")->value; + env->enemy_respawn_ticks = dict_get(kwargs, "enemy_respawn_ticks")->value; + env->item_respawn_ticks = dict_get(kwargs, "item_respawn_ticks")->value; + env->x_window = dict_get(kwargs, "x_window")->value; + env->y_window = dict_get(kwargs, "y_window")->value; + env->reward_combat_level = dict_get(kwargs, "reward_combat_level")->value; + env->reward_prof_level = dict_get(kwargs, "reward_prof_level")->value; + env->reward_item_level = dict_get(kwargs, "reward_item_level")->value; + env->reward_market = dict_get(kwargs, "reward_market")->value; + env->reward_death = dict_get(kwargs, "reward_death")->value; + init(env); +} + +void my_log(Log* log, Dict* out) { + dict_set(out, "perf", log->perf); + dict_set(out, "score", log->score); + dict_set(out, "episode_return", log->episode_return); + dict_set(out, "episode_length", log->episode_length); + dict_set(out, "return_comb_lvl", log->return_comb_lvl); + dict_set(out, "return_prof_lvl", log->return_prof_lvl); + dict_set(out, "return_item_atk_lvl", log->return_item_atk_lvl); + dict_set(out, "return_item_def_lvl", log->return_item_def_lvl); + dict_set(out, "return_market_buy", log->return_market_buy); + dict_set(out, "return_market_sell", log->return_market_sell); + dict_set(out, "return_death", log->return_death); + dict_set(out, "min_comb_prof", log->min_comb_prof); + dict_set(out, "purchases", log->purchases); + dict_set(out, "sales", log->sales); + dict_set(out, "equip_attack", log->equip_attack); + dict_set(out, "equip_defense", log->equip_defense); + dict_set(out, "r", log->r); + dict_set(out, "c", log->c); +} diff --git a/pufferlib/ocean/nmmo3/nmmo3.c b/ocean/nmmo3/nmmo3.c similarity index 74% rename from pufferlib/ocean/nmmo3/nmmo3.c rename to ocean/nmmo3/nmmo3.c index 4a3b08763b..0bbff7d345 100644 --- a/pufferlib/ocean/nmmo3/nmmo3.c +++ b/ocean/nmmo3/nmmo3.c @@ -4,16 +4,9 @@ #include "puffernet.h" #include "nmmo3.h" -// Only rens a few agents in the C -// version, and reduces for web. +// Only run 1 agent in the C version // You can run the full 1024 on GPU -// with PyTorch. -#if defined(PLATFORM_WEB) - #define NUM_AGENTS 4 -#else - #define NUM_AGENTS 16 -#endif - +#define NUM_AGENTS 1 typedef struct MMONet MMONet; struct MMONet { @@ -27,12 +20,10 @@ struct MMONet { Conv2D* map_conv2; Embedding* player_embed; float* proj_buffer; - Linear* proj; + Affine* proj; ReLU* proj_relu; - LayerNorm* layer_norm; - LSTM* lstm; - Linear* actor; - Linear* value_fn; + Linear* decoder; + MinGRU* mingru; Multidiscrete* multidiscrete; }; @@ -49,12 +40,10 @@ MMONet* init_mmonet(Weights* weights, int num_agents) { net->map_conv2 = make_conv2d(weights, num_agents, 4, 3, 128, 128, 3, 1); net->player_embed = make_embedding(weights, num_agents*47, 128, 32); net->proj_buffer = calloc(num_agents*1817, sizeof(float)); - net->proj = make_linear(weights, num_agents, 1817, hidden); + net->proj = make_affine(weights, num_agents, 1817, hidden); net->proj_relu = make_relu(num_agents, hidden); - net->layer_norm = make_layernorm(weights, num_agents, hidden); - net->actor = make_linear(weights, num_agents, hidden, 26); - net->value_fn = make_linear(weights, num_agents, hidden, 1); - net->lstm = make_lstm(weights, num_agents, hidden, hidden); + net->decoder = make_linear(weights, num_agents, hidden, 26 + 1); + net->mingru = make_mingru(weights, num_agents, hidden, 4); int logit_sizes[1] = {26}; net->multidiscrete = make_multidiscrete(num_agents, logit_sizes, 1); return net; @@ -72,15 +61,21 @@ void free_mmonet(MMONet* net) { free(net->proj_buffer); free(net->proj); free(net->proj_relu); - free(net->layer_norm); - free(net->actor); - free(net->value_fn); - free(net->lstm); + free(net->decoder); + free_mingru(net->mingru); free(net->multidiscrete); free(net); } -void forward(MMONet* net, unsigned char* observations, int* actions) { +void forward(MMONet* net, unsigned char* observations, float* terminals, float* actions) { + for (int b = 0; b < net->num_agents; b++) { + if (terminals[b] > 0.5f) { + for (int l = 0; l < net->mingru->num_layers; l++) { + memset(net->mingru->state + l * net->mingru->batch_size * net->mingru->hidden_size + b * net->mingru->hidden_size, 0, net->mingru->hidden_size * sizeof(float)); + } + terminals[b] = 0.0f; + } + } memset(net->ob_map, 0, net->num_agents*11*15*59*sizeof(float)); // DUMMY INPUT FOR TESTING @@ -147,46 +142,47 @@ void forward(MMONet* net, unsigned char* observations, int* actions) { } } - linear(net->proj, net->proj_buffer); + affine(net->proj, net->proj_buffer); relu(net->proj_relu, net->proj->output); - lstm(net->lstm, net->proj_relu->output); - layernorm(net->layer_norm, net->lstm->state_h); - - linear(net->actor, net->layer_norm->output); - linear(net->value_fn, net->layer_norm->output); + mingru(net->mingru, net->proj_relu->output); + linear(net->decoder, net->mingru->output); - softmax_multidiscrete(net->multidiscrete, net->actor->output, actions); + softmax_multidiscrete(net->multidiscrete, net->decoder->output, actions); } void demo(int num_players) { - srand(time(NULL)); - Weights* weights = load_weights("resources/nmmo3/nmmo3_weights.bin", 3387547); + Weights* weights = load_weights("resources/nmmo3/nmmo3_weights.bin"); MMONet* net = init_mmonet(weights, num_players); MMO env = { .client = NULL, .width = 512, .height = 512, - .num_players = num_players, + .num_agents = num_players, .num_enemies = 2048, .num_resources = 2048, .num_weapons = 1024, .num_gems = 512, .tiers = 5, .levels = 40, - .teleportitis_prob = 0.0, + .teleportitis_prob = 0.001, .enemy_respawn_ticks = 2, .item_respawn_ticks = 100, .x_window = 7, .y_window = 5, + .reward_combat_level = 1.0, + .reward_prof_level = 1.0, + .reward_item_level = 1.0, + .reward_market = 0.0, + .reward_death = -1.0, }; allocate_mmo(&env); c_reset(&env); c_render(&env); - int human_action = ATN_NOOP; + float human_action = ATN_NOOP; bool human_mode = false; int i = 1; while (!WindowShouldClose()) { @@ -194,7 +190,7 @@ void demo(int num_players) { human_mode = !human_mode; } if (i % 36 == 0) { - forward(net, env.observations, env.actions); + forward(net, env.observations, env.terminals, env.actions); if (human_mode) { env.actions[0] = human_action; } @@ -216,13 +212,13 @@ void demo(int num_players) { } void test_mmonet_performance(int num_players, int timeout) { - Weights* weights = load_weights("nmmo3_weights.bin", 1101403); + Weights* weights = load_weights("nmmo3_weights.bin"); MMONet* net = init_mmonet(weights, num_players); MMO env = { .width = 512, .height = 512, - .num_players = num_players, + .num_agents = num_players, .num_enemies = 128, .num_resources = 32, .num_weapons = 32, @@ -241,7 +237,7 @@ void test_mmonet_performance(int num_players, int timeout) { int start = time(NULL); int num_steps = 0; while (time(NULL) - start < timeout) { - forward(net, env.observations, env.actions); + forward(net, env.observations, env.terminals, env.actions); c_step(&env); num_steps++; } @@ -323,15 +319,16 @@ void test_perlin_noise(int width, int height, } void test_flood_fill(int width, int height, int colors) { + unsigned int rng = 42; unsigned char unfilled[width][height]; memset(unfilled, 0, width*height); // Draw some squares for (int i = 0; i < 32; i++) { - int w = rand() % width/4; - int h = rand() % height/4; - int start_r = rand() % (3*height/4); - int start_c = rand() % (3*width/4); + int w = rand_r(&rng) % width/4; + int h = rand_r(&rng) % height/4; + int start_r = rand_r(&rng) % (3*height/4); + int start_c = rand_r(&rng) % (3*width/4); int end_r = start_r + h; int end_c = start_c + w; for (int r = start_r; r < end_r; r++) { @@ -346,7 +343,7 @@ void test_flood_fill(int width, int height, int colors) { char filled[width*height]; flood_fill((unsigned char*)unfilled, (char*)filled, - width, height, colors, width*height); + width, height, colors, width*height, &rng); // Cast and colorize unsigned char output[width*height]; @@ -365,6 +362,7 @@ void test_flood_fill(int width, int height, int colors) { } void test_cellular_automata(int width, int height, int colors, int max_fill) { + unsigned int rng = 42; char grid[width][height]; for (int r = 0; r < height; r++) { for (int c = 0; c < width; c++) { @@ -374,13 +372,13 @@ void test_cellular_automata(int width, int height, int colors, int max_fill) { // Fill some squares for (int i = 0; i < 32; i++) { - int w = rand() % width/4; - int h = rand() % height/4; - int start_r = rand() % (3*height/4); - int start_c = rand() % (3*width/4); + int w = rand_r(&rng) % width/4; + int h = rand_r(&rng) % height/4; + int start_r = rand_r(&rng) % (3*height/4); + int start_c = rand_r(&rng) % (3*width/4); int end_r = start_r + h; int end_c = start_c + w; - int color = rand() % colors; + int color = rand_r(&rng) % colors; for (int r = start_r; r < end_r; r++) { for (int c = start_c; c < end_c; c++) { grid[r][c] = color; @@ -388,7 +386,7 @@ void test_cellular_automata(int width, int height, int colors, int max_fill) { } } - cellular_automata((char*)grid, width, height, colors, max_fill); + cellular_automata((char*)grid, width, height, colors, max_fill, &rng); // Colorize unsigned char output[width*height]; @@ -409,7 +407,7 @@ void test_cellular_automata(int width, int height, int colors, int max_fill) { void test_generate_terrain(int width, int height, int x_border, int y_border) { char terrain[width][height]; unsigned char rendered[width][height][3]; - generate_terrain((char*)terrain, (unsigned char*)rendered, width, height, x_border, y_border); + unsigned int rng = 42; generate_terrain((char*)terrain, (unsigned char*)rendered, width, height, x_border, y_border, &rng); // Colorize @@ -434,7 +432,7 @@ void test_performance(int num_players, int timeout) { MMO env = { .width = 512, .height = 512, - .num_players = num_players, + .num_agents = num_players, .num_enemies = 128, .num_resources = 32, .num_weapons = 32, @@ -454,7 +452,7 @@ void test_performance(int num_players, int timeout) { int num_steps = 0; while (time(NULL) - start < timeout) { for (int i = 0; i < num_players; i++) { - env.actions[i] = rand() % 23; + env.actions[i] = rand_r(&env.rng) % 23; } c_step(&env); num_steps++; @@ -466,6 +464,64 @@ void test_performance(int num_players, int timeout) { free_allocated_mmo(&env); } +void test_no_render_log(int num_players, int target_episodes) { + Weights* weights = load_weights("resources/nmmo3/nmmo3_weights.bin"); + MMONet* net = init_mmonet(weights, num_players); + + MMO env = { + .client = NULL, + .width = 512, + .height = 512, + .num_agents = num_players, + .num_enemies = 2048, + .num_resources = 2048, + .num_weapons = 1024, + .num_gems = 512, + .tiers = 5, + .levels = 40, + .teleportitis_prob = 0.001, + .enemy_respawn_ticks = 2, + .item_respawn_ticks = 100, + .x_window = 7, + .y_window = 5, + .reward_combat_level = 1.0, + .reward_prof_level = 1.0, + .reward_item_level = 1.0, + .reward_market = 0.0, + .reward_death = -1.0, + }; + allocate_mmo(&env); + c_reset(&env); + + int num_steps = 0; + int prev_n = 0; + float prev_mcp = 0.0f; + while ((int)env.log.n < target_episodes) { + forward(net, env.observations, env.terminals, env.actions); + c_step(&env); + num_steps++; + + int curr_n = (int)env.log.n; + if (curr_n > prev_n) { + float ep_mcp = env.log.min_comb_prof - prev_mcp; + float running_mean = env.log.min_comb_prof / (float)curr_n; + printf("Episode %d: min_comb_prof=%.3f running_mean=%.4f (step %d)\n", + curr_n, ep_mcp, running_mean, num_steps); + prev_n = curr_n; + prev_mcp = env.log.min_comb_prof; + } + } + + printf("\n--- C eval summary (%d episodes, %d steps) ---\n", + prev_n, num_steps); + printf("mean min_comb_prof = %.4f\n", + env.log.min_comb_prof / (float)prev_n); + + free_allocated_mmo(&env); + free_mmonet(net); + free(weights); +} + int main() { /* @@ -480,6 +536,6 @@ int main() { test_generate_terrain(width, height, 8, 8); */ //test_performance(64, 10); + //test_no_render_log(1, 100); demo(NUM_AGENTS); - //test_mmonet_performance(1024, 10); } diff --git a/pufferlib/ocean/nmmo3/nmmo3.h b/ocean/nmmo3/nmmo3.h similarity index 96% rename from pufferlib/ocean/nmmo3/nmmo3.h rename to ocean/nmmo3/nmmo3.h index b1d5c22c46..c48c93e567 100644 --- a/pufferlib/ocean/nmmo3/nmmo3.h +++ b/ocean/nmmo3/nmmo3.h @@ -174,17 +174,17 @@ void range(int* array, int n) { } } -void shuffle(int* array, int n) { +void shuffle(int* array, int n, unsigned int* rng) { for (int i = 0; i < n; i++) { - int j = rand() % n; + int j = rand_r(rng) % n; int temp = array[i]; array[i] = array[j]; array[j] = temp; } } -double sample_exponential(double halving_rate) { - double u = (double)rand() / RAND_MAX; // Random number u in [0, 1) +double sample_exponential(double halving_rate, unsigned int* rng) { + double u = (double)rand_r(rng) / RAND_MAX; // Random number u in [0, 1) return 1 + halving_rate*(-log(1 - u) / log(2)); } @@ -275,7 +275,7 @@ void perlin_noise(float* map, int width, int height, } void flood_fill(unsigned char* input, char* output, - int width, int height, int n, int max_fill) { + int width, int height, int n, int max_fill, unsigned int* rng) { for (int r = 0; r < height; r++) { for (int c = 0; c < width; c++) { @@ -285,7 +285,7 @@ void flood_fill(unsigned char* input, char* output, int* pos = calloc(width*height, sizeof(int)); range((int*)pos, width*height); - shuffle((int*)pos, width*height); + shuffle((int*)pos, width*height, rng); short queue[2*max_fill]; for (int i = 0; i < 2*max_fill; i++) { @@ -301,7 +301,7 @@ void flood_fill(unsigned char* input, char* output, continue; } - int color = rand() % n; + int color = rand_r(rng) % n; output[adr] = color; queue[0] = r; queue[1] = c; @@ -366,7 +366,7 @@ void flood_fill(unsigned char* input, char* output, } void cellular_automata(char* grid, - int width, int height, int colors, int max_fill) { + int width, int height, int colors, int max_fill, unsigned int* rng) { int* pos = calloc(2*width*height, sizeof(int)); int pos_sz = 0; @@ -389,7 +389,7 @@ void cellular_automata(char* grid, for (int i = 0; i < pos_sz; i+=2) { int r = pos[i]; int c = pos[i + 1]; - int adr = rand() % pos_sz; + int adr = rand_r(rng) % pos_sz; if (adr % 2 == 1) { adr--; } @@ -450,7 +450,7 @@ void cellular_automata(char* grid, } int idx = 0; - int winner = rand() % num_ties; + int winner = rand_r(rng) % num_ties; for (int j = 0; j < colors; j++) { if (counts[j] == max_count) { if (idx == winner) { @@ -469,12 +469,12 @@ void cellular_automata(char* grid, } void generate_terrain(char* terrain, unsigned char* rendered, - int R, int C, int x_border, int y_border) { + int R, int C, int x_border, int y_border, unsigned int* rng) { // Perlin noise for the base terrain // TODO: Not handling octaves correctly float* perlin_map = calloc(R*C, sizeof(float)); - int offset_x = rand() % 100000; - int offset_y = rand() % 100000; + int offset_x = rand_r(rng) % 100000; + int offset_y = rand_r(rng) % 100000; perlin_noise(perlin_map, C, R, 1.0/64.0, 2, offset_x, offset_y); // Flood fill connected components to determine biomes @@ -486,10 +486,10 @@ void generate_terrain(char* terrain, unsigned char* rendered, } } char *biomes = calloc(R*C, sizeof(char)); - flood_fill(ridges, biomes, R, C, 4, 4000); + flood_fill(ridges, biomes, R, C, 4, 4000, rng); // Cellular automata to cover unfilled ridges - cellular_automata(biomes, R, C, 4, 4000); + cellular_automata(biomes, R, C, 4, 4000, rng); unsigned char (*rendered_ary)[C][3] = (unsigned char(*)[C][3])rendered; @@ -680,7 +680,7 @@ struct MMO { Client* client; int width; int height; - int num_players; + int num_agents; int num_enemies; int num_resources; int num_weapons; @@ -697,7 +697,7 @@ struct MMO { float* terminals; Reward* reward_struct; Reward* returns; - int* actions; + float* actions; int tick; int tiers; int levels; @@ -714,6 +714,7 @@ struct MMO { RespawnBuffer* enemy_respawn_buffer; RespawnBuffer* drop_respawn_buffer; Log log; + unsigned int rng; float reward_combat_level; float reward_prof_level; float reward_item_level; @@ -722,10 +723,10 @@ struct MMO { }; Entity* get_entity(MMO* env, int pid) { - if (pid < env->num_players) { + if (pid < env->num_agents) { return &env->players[pid]; } else { - return &env->enemies[pid - env->num_players]; + return &env->enemies[pid - env->num_agents]; } } @@ -758,6 +759,9 @@ void add_player_log(MMO* env, int pid) { log->perf = log->min_comb_prof / (float)env->levels; log->n++; *ret = (Reward){0}; + if (pid < env->num_agents) { + env->terminals[pid] = 1.0f; + } } void init(MMO* env) { @@ -778,9 +782,9 @@ void init(MMO* env) { env->num_enemies, env->enemy_respawn_ticks); env->drop_respawn_buffer = make_respawn_buffer(2*env->num_enemies, 20); - env->returns = calloc(env->num_players, sizeof(Reward)); - env->reward_struct = calloc(env->num_players, sizeof(Reward)); - env->players = calloc(env->num_players, sizeof(Entity)); + env->returns = calloc(env->num_agents, sizeof(Reward)); + env->reward_struct = calloc(env->num_agents, sizeof(Reward)); + env->players = calloc(env->num_agents, sizeof(Entity)); env->enemies = calloc(env->num_enemies, sizeof(Entity)); // TODO: Figure out how to cast to array. Size is static @@ -790,10 +794,10 @@ void init(MMO* env) { void allocate_mmo(MMO* env) { // TODO: Not hardcode - env->observations = calloc(env->num_players*(11*15*10+47+10), sizeof(unsigned char)); - env->rewards = calloc(env->num_players, sizeof(float)); - env->terminals = calloc(env->num_players, sizeof(float)); - env->actions = calloc(env->num_players, sizeof(int)); + env->observations = calloc(env->num_agents*(11*15*10+47+10), sizeof(unsigned char)); + env->rewards = calloc(env->num_agents, sizeof(float)); + env->terminals = calloc(env->num_agents, sizeof(float)); + env->actions = calloc(env->num_agents, sizeof(float)); init(env); } @@ -920,7 +924,7 @@ float sell_price(int idx) { } void compute_all_obs(MMO* env) { - for (int pid = 0; pid < env->num_players; pid++) { + for (int pid = 0; pid < env->num_agents; pid++) { Entity* player = get_entity(env, pid); int r = player->r; int c = player->c; @@ -1020,7 +1024,7 @@ int safe_tile(MMO* env, int delta) { int idx; while (!valid) { valid = true; - idx = rand() % (env->width * env->height); + idx = rand_r(&env->rng) % (env->width * env->height); char tile = env->terrain[idx]; if (!is_grass(tile)) { valid = false; @@ -1089,7 +1093,7 @@ void spawn(MMO* env, Entity* entity) { entity->is_equipped[idx] = 0; } - entity->goal = (rand() % 2) == 0; + entity->goal = (rand_r(&env->rng) % 2) == 0; memset(entity->min_comb_prof, 0, sizeof(entity->min_comb_prof)); entity->min_comb_prof_idx = 0; } @@ -1099,8 +1103,8 @@ void give_starter_gear(MMO* env, int pid, int tier) { assert(tier <= env->tiers); Entity* player = &env->players[pid]; - int idx = (rand() % 6) + 1; - tier = (rand() % tier) + 1; + int idx = (rand_r(&env->rng) % 6) + 1; + tier = (rand_r(&env->rng) % tier) + 1; player->inventory[0] = item_index(idx, tier); player->gold += 50; } @@ -1174,7 +1178,7 @@ void pickup_item(MMO* env, int pid) { // Some items are different on the ground and in inventory if (ground_type == I_ORE) { - int armor_id = I_HELM + rand() % 3; + int armor_id = I_HELM + rand_r(&env->rng) % 3; ground_id = item_index(armor_id, ground_tier); } else if (ground_type == I_HILT) { ground_id = item_index(I_SWORD, ground_tier); @@ -1264,7 +1268,7 @@ void wander(MMO* env, int pid) { } // Move randomly - int direction = rand() % 4; + int direction = rand_r(&env->rng) % 4; if (direction == ATN_UP) { end_r -= 1; } else if (direction == ATN_DOWN) { @@ -1574,7 +1578,7 @@ void enemy_ai(MMO* env, int pid) { for (int cc = c-NPC_AGGRO_RANGE; cc <= c+NPC_AGGRO_RANGE; cc++) { int adr = map_offset(env, rr, cc); int target_id = env->pids[adr]; - if (target_id == -1 || target_id >= env->num_players) { + if (target_id == -1 || target_id >= env->num_agents) { continue; } @@ -1643,7 +1647,7 @@ void c_reset(MMO* env) { // TODO: Check width/height args! generate_terrain(env->terrain, env->rendered, env->width, env->height, - env->x_window, env->y_window); + env->x_window, env->y_window, &env->rng); for (int i = 0; i < env->width*env->height; i++) { env->pids[i] = -1; @@ -1666,7 +1670,7 @@ void c_reset(MMO* env) { // Randomly generate spawn candidates int *spawn_cands = calloc(env->width*env->height, sizeof(int)); range((int*)spawn_cands, env->width*env->height); - shuffle((int*)spawn_cands, env->width*env->height); + shuffle((int*)spawn_cands, env->width*env->height, &env->rng); for (int cand_idx = 0; cand_idx < env->width*env->height; cand_idx++) { int cand = spawn_cands[cand_idx]; @@ -1721,7 +1725,7 @@ void c_reset(MMO* env) { //int tier = 1 + env->tiers*level/env->levels; int tier = 0; while (tier < 1 || tier > env->tiers) { - tier = sample_exponential(1); + tier = sample_exponential(1, &env->rng); } if (spawned) { @@ -1750,7 +1754,7 @@ void c_reset(MMO* env) { } if ( - player_count == env->num_players && + player_count == env->num_agents && enemy_count == env->num_enemies && ore_count == env->num_resources && herb_count == env->num_resources && @@ -1776,7 +1780,7 @@ void c_reset(MMO* env) { free(spawn_cands); //int distance = abs(r - env->height/2); - for (int player_count = 0; player_count < env->num_players; player_count++) { + for (int player_count = 0; player_count < env->num_agents; player_count++) { int pid = player_count; Entity* player = &env->players[pid]; player->type = ENTITY_PLAYER; @@ -1797,9 +1801,9 @@ void c_reset(MMO* env) { for (int enemy_count = 0; enemy_count < env->num_enemies; enemy_count++) { int level = 0; while (level < 1 || level > env->levels) { - level = sample_exponential(8); + level = sample_exponential(8, &env->rng); } - if (rand() % 8 == 0) { + if (rand_r(&env->rng) % 8 == 0) { level = 1; } //if (distance > 8 && r < env->height/2 && enemy_count < env->num_enemies) { @@ -1828,7 +1832,7 @@ void c_reset(MMO* env) { enemy->element = element; enemy->ranged = ranged; - env->pids[adr] = env->num_players + enemy_count; + env->pids[adr] = env->num_agents + enemy_count; enemy->comb_lvl = level; } @@ -1875,7 +1879,7 @@ void c_step(MMO* env) { } } - for (int pid = 0; pid < env->num_players + env->num_enemies; pid++) { + for (int pid = 0; pid < env->num_agents + env->num_enemies; pid++) { Entity* entity = get_entity(env, pid); entity->time_alive += 1; int entity_type = entity->type; @@ -1901,7 +1905,7 @@ void c_step(MMO* env) { // Teleportitis: Randomly teleport players and enemies // to a safe tile. This prevents players from clumping // and messing up training dynamics - double prob = (double)rand() / RAND_MAX; + double prob = (double)rand_r(&env->rng) / RAND_MAX; if (prob < env->teleportitis_prob) { r = entity->r; c = entity->c; @@ -2117,7 +2121,7 @@ void c_step(MMO* env) { } } compute_all_obs(env); - for (int pid = 0; pid < env->num_players; pid++) { + for (int pid = 0; pid < env->num_agents; pid++) { Reward* reward = &env->reward_struct[pid]; env->rewards[pid] = ( reward->death + reward->comb_lvl @@ -2330,7 +2334,7 @@ Animation ANIMATIONS[7] = { #define STONE_OFFSET OFF * 1 #define DIRT_OFFSET 0 -void render_conversion(char* flat_tiles, int* flat_converted, int R, int C) { +void render_conversion(char* flat_tiles, int* flat_converted, int R, int C, unsigned int* rng) { char* tex_codes = tile_atlas; char (*tiles)[C] = (char(*)[C])flat_tiles; int (*converted)[C] = (int(*)[C])flat_converted; @@ -2374,11 +2378,11 @@ void render_conversion(char* flat_tiles, int* flat_converted, int R, int C) { int idx = code; if (code == TEX_FULL) { if (is_dirt(tile)) { - idx = DIRT_OFFSET + rand() % 5; + idx = DIRT_OFFSET + rand_r(rng) % 5; } else if (is_stone(tile)) { - idx = STONE_OFFSET + rand() % 5; + idx = STONE_OFFSET + rand_r(rng) % 5; } else if (is_water(tile)) { - idx = WATER_OFFSET + rand() % 5; + idx = WATER_OFFSET + rand_r(rng) % 5; } } else if (is_dirt(tile)) { idx += DIRT_OFFSET + 5; @@ -2426,13 +2430,13 @@ void render_conversion(char* flat_tiles, int* flat_converted, int R, int C) { } else { int lookup = (1000*num_spring + 100*num_summer + 10*num_autumn + num_winter); - int offset = (rand() % 4) * 714; // num_lerps; + int offset = (rand_r(rng) % 4) * 714; // num_lerps; idx = lerps[lookup] + offset + 240 + 5*4*3*4; } } if (code == TEX_FULL && is_water(tile)) { - int variant = (rand() % 5); - int anim = rand() % 3; + int variant = (rand_r(rng) % 5); + int anim = rand_r(rng) % 3; idx = 240 + 3*4*4*variant + 4*4*anim; if (tile == TILE_SPRING_WATER) { idx += 0; @@ -2459,7 +2463,7 @@ Client* make_client(MMO* env) { client->command_len = 0; client->terrain = calloc(env->height*env->width, sizeof(int)); - render_conversion(env->terrain, client->terrain, env->height, env->width); + render_conversion(env->terrain, client->terrain, env->height, env->width, &env->rng); client->shader = LoadShader("", TextFormat("resources/nmmo3/map_shader_%i.fs", GLSL_VERSION)); @@ -2883,7 +2887,7 @@ void render_centered(Client* client, MMO* env, int pid, int action, float delta) start_r, end_c-start_c, end_r-start_r, env->width, env->height, 1, delta); - for (int pid = 0; pid < env->num_players+env->num_enemies; pid++) { + for (int pid = 0; pid < env->num_agents+env->num_enemies; pid++) { draw_entity(client, env, pid, delta); } @@ -3045,7 +3049,7 @@ void render_fixed(Client* client, MMO* env, float delta) { draw_min(client, env, start_c, start_r, end_c-start_c, end_r-start_r, env->width, env->height, 1, delta); - for (int pid = 0; pid < env->num_players+env->num_enemies; pid++) { + for (int pid = 0; pid < env->num_agents+env->num_enemies; pid++) { draw_entity(client, env, pid, delta); } @@ -3095,7 +3099,7 @@ void process_command_input(Client* client, MMO* env) { char* pid = command + 7; pid = pid; int pid = atoi(pid); - if (pid < 0 || pid > env->num_players) { + if (pid < 0 || pid > env->num_agents) { client->command = "Invalid player id"; } client->my_player = pid; diff --git a/pufferlib/ocean/nmmo3/simplex.h b/ocean/nmmo3/simplex.h similarity index 100% rename from pufferlib/ocean/nmmo3/simplex.h rename to ocean/nmmo3/simplex.h diff --git a/pufferlib/ocean/nmmo3/tile_atlas.h b/ocean/nmmo3/tile_atlas.h similarity index 100% rename from pufferlib/ocean/nmmo3/tile_atlas.h rename to ocean/nmmo3/tile_atlas.h diff --git a/pufferlib/ocean/onestateworld/binding.c b/ocean/onestateworld/binding.c similarity index 100% rename from pufferlib/ocean/onestateworld/binding.c rename to ocean/onestateworld/binding.c diff --git a/pufferlib/ocean/onestateworld/onestateworld.c b/ocean/onestateworld/onestateworld.c similarity index 100% rename from pufferlib/ocean/onestateworld/onestateworld.c rename to ocean/onestateworld/onestateworld.c diff --git a/pufferlib/ocean/onestateworld/onestateworld.h b/ocean/onestateworld/onestateworld.h similarity index 100% rename from pufferlib/ocean/onestateworld/onestateworld.h rename to ocean/onestateworld/onestateworld.h diff --git a/pufferlib/ocean/onlyfish/binding.c b/ocean/onlyfish/binding.c similarity index 100% rename from pufferlib/ocean/onlyfish/binding.c rename to ocean/onlyfish/binding.c diff --git a/pufferlib/ocean/onlyfish/onlyfish.c b/ocean/onlyfish/onlyfish.c similarity index 97% rename from pufferlib/ocean/onlyfish/onlyfish.c rename to ocean/onlyfish/onlyfish.c index 27d257a3ee..297d0a46b6 100644 --- a/pufferlib/ocean/onlyfish/onlyfish.c +++ b/ocean/onlyfish/onlyfish.c @@ -41,7 +41,7 @@ int main() { if (len > 4 && strcmp(entry->d_name + len - 4, ".bin") == 0) { char fullpath[256]; sprintf(fullpath, "%s%s", dirpath, entry->d_name); - Weights* weights = load_weights(fullpath, 136847); + Weights* weights = load_weights(fullpath); int logit_sizes[2] = {9, 5}; nets[idx] = make_linearlstm(weights, 1, 21, logit_sizes, 2); diff --git a/pufferlib/ocean/onlyfish/onlyfish.h b/ocean/onlyfish/onlyfish.h similarity index 100% rename from pufferlib/ocean/onlyfish/onlyfish.h rename to ocean/onlyfish/onlyfish.h diff --git a/ocean/overcooked/README.md b/ocean/overcooked/README.md new file mode 100644 index 0000000000..bcb146c56e --- /dev/null +++ b/ocean/overcooked/README.md @@ -0,0 +1,247 @@ +# Overcooked Environment + +A multi-agent cooking coordination environment where agents cooperate to prepare and serve onion soup. Based on the popular Overcooked video game, this environment tests agents' ability to coordinate, divide labor, and work together efficiently. + +## File Structure + +``` +overcooked/ +├── overcooked.h # Main entry point (init, reset, step, close) +├── overcooked_types.h # Constants, enums, and struct definitions +├── overcooked_items.h # Item and cooking pot management +├── overcooked_obs.h # Observation computation +├── overcooked_logic.h # Game logic (interaction, movement, cooking) +├── overcooked_render.h # Rendering and texture management +├── binding.c # Python bindings +└── overcooked.py # Python environment wrapper +``` + +## Observation Space + +**39-dimensional vector per agent** — *see [compute_observations](overcooked_obs.h#L81)* + +### Player Features (34 dims) +- **Orientation** (4): One-hot encoding of facing direction — [overcooked_obs.h:101-103](overcooked_obs.h#L101-L103) +- **Held Object** (4): One-hot encoding (onion, plated_soup, plate, empty) — [overcooked_obs.h:105-116](overcooked_obs.h#L105-L116) +- **Proximity Features** (12): Normalized (dx, dy) to nearest — [overcooked_obs.h:118-167](overcooked_obs.h#L118-L167): + - Onion source (ingredient box) + - Dish source (plate box) + - Plated soup on counter + - Serving area + - Empty counter + - Pot (stove) +- **Nearest Soup Ingredients** (2): Onion/tomato counts in nearest plated soup or held soup (normalized) — [overcooked_obs.h:169-179](overcooked_obs.h#L169-L179) +- **Pot Soup Ingredients** (2): Onion/tomato counts in nearest pot (normalized) — [overcooked_obs.h:181-202](overcooked_obs.h#L181-L202) +- **Pot Existence** (1): Binary flag for reachable pot — [overcooked_obs.h:205](overcooked_obs.h#L205) +- **Pot State** (4): Binary flags (empty, full, cooking, ready) — [overcooked_obs.h:207-215](overcooked_obs.h#L207-L215) +- **Cooking Time** (1): Remaining cook time (normalized) — [overcooked_obs.h:217-223](overcooked_obs.h#L217-L223) +- **Wall Detection** (4): Binary flags for walls/obstacles (up, down, left, right) — [overcooked_obs.h:225-235](overcooked_obs.h#L225-L235) + +### Spatial Features (4 dims) +- **Teammate Relative Position** (2): Normalized (dx, dy) to other agent — [overcooked_obs.h:237-248](overcooked_obs.h#L237-L248) +- **Absolute Position** (2): Normalized (x, y) coordinates — [overcooked_obs.h:250-252](overcooked_obs.h#L250-L252) + +### Context (1 dim) +- **Reward** (1): Current step reward — [overcooked_obs.h:255](overcooked_obs.h#L255) + +## Action Space + +**6 discrete actions** — *see [c_step](overcooked.h#L77)* +- 0: No-op — [ACTION_NOOP](overcooked_types.h#L43) +- 1: Move up — [ACTION_UP](overcooked_types.h#L44) +- 2: Move down — [ACTION_DOWN](overcooked_types.h#L45) +- 3: Move left — [ACTION_LEFT](overcooked_types.h#L46) +- 4: Move right — [ACTION_RIGHT](overcooked_types.h#L47) +- 5: Interact (pick up/place items, use equipment) — [ACTION_INTERACT](overcooked_types.h#L48) + +## Reward System + +*See [evaluate_dish_served](overcooked_logic.h#L229) and [handle_interaction](overcooked_logic.h#L106)* + +### Main Rewards +- **Correct dish served** (3 onions): +1.0 (shared), +0.0 (server bonus) — [overcooked_logic.h:237-241](overcooked_logic.h#L237-L241) +- **Wrong dish served** (incorrect recipe): +0.0 (shared) — [overcooked_logic.h:252-258](overcooked_logic.h#L252-L258) +- **Step penalty**: 0.0 — [overcooked.h:80](overcooked.h#L80) + +### Intermediate Rewards +- **Pick up ingredient**: +0.05 — [overcooked_logic.h:221](overcooked_logic.h#L221) +- **Add onion to pot**: +0.15 — [overcooked_logic.h:133](overcooked_logic.h#L133) +- **Start cooking** (3 onions in pot): +0.15 — [overcooked_logic.h:145-147](overcooked_logic.h#L145-L147) +- **Plate cooked soup**: +0.20 — [overcooked_logic.h:159](overcooked_logic.h#L159) + +## Recipe + +The correct recipe requires **exactly 3 onions** in the soup. Agents must: +1. Pick up onions from ingredient boxes +2. Add 3 onions to a pot +3. Start cooking (interact with pot when empty-handed) +4. Wait for soup to cook (20 steps) +5. Pick up a plate from plate box +6. Plate the cooked soup (interact with pot while holding plate) +7. Deliver plated soup to serving area + +## Configuration + +*See [Overcooked class](overcooked.py#L14)* + +```python +env = Overcooked( + num_envs=1, # Number of parallel environments + layout="cramped_room", # Layout name (see Available Layouts) + num_agents=2, # Agents per environment + render_mode=None, # Set to enable rendering + log_interval=128, # Steps between log aggregation + grid_size=32, # Render tile size in pixels + + # Reward configuration (from config/ocean/overcooked.ini) + reward_dish_served_whole_team=1.0, # Shared reward for correct dish + reward_dish_served_agent=0.0, # Bonus for serving agent + reward_pot_started=0.15, # Starting correct recipe + reward_ingredient_added=0.15, # Adding onion to pot + reward_ingredient_picked=0.05, # Picking up ingredient + reward_soup_plated=0.20, # Plating cooked soup + reward_wrong_dish_served=0.0, # Serving incorrect dish + reward_step_penalty=0.0, # Per-step penalty +) +``` + +## Game Constants + +- **Cooking time**: 20 steps — [COOKING_TIME](overcooked_types.h#L39) +- **Max ingredients per pot**: 3 — [MAX_INGREDIENTS](overcooked_types.h#L40) +- **Max episode steps**: 400 (default) +- **Max dynamic items**: 20 — [overcooked.h:19](overcooked.h#L19) + +## Available Layouts + +*See [LAYOUTS](overcooked_types.h#L244-L259)* + +### cramped_room (5x5) + +``` ++---+---+---+---+---+ +| W | C | P | C | W | W = Wall ++---+---+---+---+---+ C = Counter +| I | | | | I | P = Pot (Stove) ++---+---+---+---+---+ I = Ingredient Box (Onions) +| C | | | | C | D = Dish/Plate Box ++---+---+---+---+---+ S = Serving Area +| C | | | | C | ++---+---+---+---+---+ +| W | D | C | S | W | ++---+---+---+---+---+ +``` +Spawns: (1,2) and (3,2) + +### asymmetric_advantages (9x5) + +``` ++---+---+---+---+---+---+---+---+---+ +| W | C | W | W | W | W | W | C | W | ++---+---+---+---+---+---+---+---+---+ +| I | | C | S | W | I | C | | S | ++---+---+---+---+---+---+---+---+---+ +| C | | | | P | | | | C | ++---+---+---+---+---+---+---+---+---+ +| C | | | | P | | | | C | ++---+---+---+---+---+---+---+---+---+ +| W | C | C | D | W | D | C | C | W | ++---+---+---+---+---+---+---+---+---+ +``` +Spawns: (1,2) and (7,2) + +### forced_coordination (5x5) + +``` ++---+---+---+---+---+ +| W | C | W | P | W | W = Wall ++---+---+---+---+---+ C = Counter +| I | | C | | P | P = Pot (Stove) ++---+---+---+---+---+ I = Ingredient Box (Onions) +| I | | C | | C | D = Dish/Plate Box ++---+---+---+---+---+ S = Serving Area +| D | | C | | C | ++---+---+---+---+---+ +| W | C | W | S | W | ++---+---+---+---+---+ +``` +Spawns: (1,2) and (3,2) + +A challenging layout with a center wall dividing the kitchen. Agents must coordinate through limited passage points. + +### coordination_ring (5x5) + +``` ++---+---+---+---+---+ +| W | C | C | P | W | W = Wall ++---+---+---+---+---+ C = Counter +| C | | | | P | P = Pot (Stove) ++---+---+---+---+---+ I = Ingredient Box (Onions) +| D | | C | | C | D = Dish/Plate Box ++---+---+---+---+---+ S = Serving Area +| I | | | | C | ++---+---+---+---+---+ +| W | I | S | C | W | ++---+---+---+---+---+ +``` +Spawns: (1,2) and (3,2) + +Ring-shaped layout with a center counter obstacle. Agents must navigate around the center to coordinate ingredient pickup and soup delivery. + +### counter_circuit (8x5) + +``` ++---+---+---+---+---+---+---+---+ +| W | C | C | P | P | C | C | W | ++---+---+---+---+---+---+---+---+ +| C | | | | | | | C | ++---+---+---+---+---+---+---+---+ +| D | | C | C | C | C | | S | ++---+---+---+---+---+---+---+---+ +| C | | | | | | | C | ++---+---+---+---+---+---+---+---+ +| W | C | C | I | I | C | C | W | ++---+---+---+---+---+---+---+---+ +``` +Spawns: (1,1) and (6,3) + +Circuit-shaped layout with a center counter island. Agents must coordinate around the obstacle to efficiently transport ingredients and serve dishes. Features dual pots and dual ingredient boxes for parallel cooking. + +## Logging Metrics + +*See [Log struct](overcooked_types.h#L65-L78)* + +| Metric | Description | +|--------|-------------| +| perf | Normalized performance (correct dishes served) | +| score | Raw score (correct dishes served) | +| episode_return | Sum of rewards over episode | +| episode_length | Number of steps in episode | +| dishes_served | Total dishes served (correct + wrong) | +| correct_dishes | Number of 3-onion dishes served | +| wrong_dishes | Number of incorrect dishes served | +| ingredients_picked | Total ingredients picked up | +| pots_started | Number of cooking sessions started | +| items_dropped | Number of items placed on counters | +| agent_collisions | Number of agent collision attempts | + +## Agent Reset Mechanism + +If an agent goes 512 steps without receiving a reward, it is automatically reset to its starting position with no held item. This prevents agents from getting stuck — [c_step](overcooked.h#L114-L133) + +## Building + +```bash +# Build the environment +python setup.py build_overcooked --inplace + +# Run standalone test +python pufferlib/ocean/overcooked/overcooked.py + +# Run standalone demo with specific layout +./overcooked cramped_room +./overcooked asymmetric_advantages +./overcooked forced_coordination +./overcooked coordination_ring +./overcooked counter_circuit +``` diff --git a/ocean/overcooked/binding.c b/ocean/overcooked/binding.c new file mode 100644 index 0000000000..e809a81687 --- /dev/null +++ b/ocean/overcooked/binding.c @@ -0,0 +1,42 @@ +#include "overcooked.h" + +#define OBS_SIZE 43 +#define NUM_ATNS 1 +#define ACT_SIZES {6} +#define OBS_TENSOR_T FloatTensor + +#define Env Overcooked +#include "vecenv.h" + +void my_init(Env* env, Dict* kwargs) { + env->layout_id = (LayoutType)dict_get(kwargs, "layout")->value; + env->num_agents = (int)dict_get(kwargs, "num_agents")->value; + env->grid_size = (int)dict_get(kwargs, "grid_size")->value; + env->observation_size = OBS_SIZE; + + env->rewards_config.dish_served_whole_team = dict_get(kwargs, "reward_dish_served_whole_team")->value; + env->rewards_config.dish_served_agent = dict_get(kwargs, "reward_dish_served_agent")->value; + env->rewards_config.pot_started = dict_get(kwargs, "reward_pot_started")->value; + env->rewards_config.ingredient_added = dict_get(kwargs, "reward_ingredient_added")->value; + env->rewards_config.ingredient_picked = dict_get(kwargs, "reward_ingredient_picked")->value; + env->rewards_config.plate_picked = dict_get(kwargs, "reward_plate_picked")->value; + env->rewards_config.soup_plated = dict_get(kwargs, "reward_soup_plated")->value; + env->rewards_config.wrong_dish_served = dict_get(kwargs, "reward_wrong_dish_served")->value; + env->rewards_config.step_penalty = dict_get(kwargs, "reward_step_penalty")->value; + + init(env); +} + +void my_log(Log* log, Dict* out) { + dict_set(out, "perf", log->perf); + dict_set(out, "score", log->score); + dict_set(out, "episode_return", log->episode_return); + dict_set(out, "episode_length", log->episode_length); + dict_set(out, "dishes_served", log->dishes_served); + dict_set(out, "correct_dishes", log->correct_dishes); + dict_set(out, "wrong_dishes", log->wrong_dishes); + dict_set(out, "ingredients_picked", log->ingredients_picked); + dict_set(out, "pots_started", log->pots_started); + dict_set(out, "items_dropped", log->items_dropped); + dict_set(out, "agent_collisions", log->agent_collisions); +} diff --git a/ocean/overcooked/overcooked.c b/ocean/overcooked/overcooked.c new file mode 100644 index 0000000000..5d6e875b00 --- /dev/null +++ b/ocean/overcooked/overcooked.c @@ -0,0 +1,84 @@ +#include +#include "overcooked.h" +#include "puffernet.h" + +int main(int argc, char** argv) { + LayoutType layout_id = LAYOUT_CRAMPED_ROOM; + if (argc > 1) { + layout_id = get_layout_by_name(argv[1]); + } + + int num_agents = 2; + int num_obs = 43; + + // Select weights file and size based on layout + const char* weights_file; + int weights_size; + if (layout_id == LAYOUT_ASYMMETRIC_ADVANTAGES) { + weights_file = "resources/overcooked/puffer_overcooked_weights_aa.bin"; + weights_size = 138631; + } else if (layout_id == LAYOUT_FORCED_COORDINATION) { + weights_file = "resources/overcooked/puffer_overcooked_weights_fc.bin"; + weights_size = 138631; + } else if (layout_id == LAYOUT_COORDINATION_RING) { + weights_file = "resources/overcooked/puffer_overcooked_weights_cor.bin"; + weights_size = 138631; + } else if (layout_id == LAYOUT_COUNTER_CIRCUIT) { + weights_file = "resources/overcooked/puffer_overcooked_weights_cc.bin"; + weights_size = 138631; + } else { + weights_file = "resources/overcooked/puffer_overcooked_weights_cr.bin"; + weights_size = 138631; + } + + // Weights* weights = load_weights(weights_file); + // int logit_sizes[] = {6}; + // LinearLSTM* net = make_linearlstm(weights, num_agents, num_obs, logit_sizes, 1); + + Overcooked env = { + .layout_id = layout_id, + .num_agents = num_agents, + .grid_size = 100, + .rewards_config = { + .dish_served_whole_team = 1.0f, + .dish_served_agent = 0.0f, + .pot_started = 0.15f, + .ingredient_added = 0.15f, + .ingredient_picked = 0.05f, + .plate_picked = 0.05f, + .soup_plated = 0.20f, + .wrong_dish_served = 0.0f, + .step_penalty = 0.0f + }, + .observation_size = num_obs + }; + + env.observations = (float*)calloc(num_obs * num_agents, sizeof(float)); + env.actions = (float*)calloc(num_agents, sizeof(float)); + env.rewards = (float*)calloc(num_agents, sizeof(float)); + env.terminals = (float*)calloc(num_agents, sizeof(float)); + + init(&env); + c_reset(&env); + c_render(&env); + + srand(time(NULL)); + + while (!WindowShouldClose()) { + // forward_linearlstm(net, env.observations, env.actions); + for (int i = 0; i < num_agents; i++) { + env.actions[i] = rand() % 6; + } + c_step(&env); + c_render(&env); + } + + // free_linearlstm(net); + free(env.observations); + free(env.actions); + free(env.rewards); + free(env.terminals); + c_close(&env); + + return 0; +} diff --git a/ocean/overcooked/overcooked.h b/ocean/overcooked/overcooked.h new file mode 100644 index 0000000000..6ff3cdf7f3 --- /dev/null +++ b/ocean/overcooked/overcooked.h @@ -0,0 +1,154 @@ +/* Overcooked: a multi-agent cooking coordination environment. + * Agents can walk around, pick up items, and put down items. + */ + +#ifndef OVERCOOKED_H +#define OVERCOOKED_H + +#include "overcooked_types.h" +#include "overcooked_items.h" +#include "overcooked_obs.h" +#include "overcooked_logic.h" +#include "overcooked_render.h" + +static void init(Overcooked* env) { + const LayoutInfo* layout = get_layout_info(env->layout_id); + env->width = layout->width; + env->height = layout->height; + env->grid = calloc(env->width * env->height, sizeof(char)); + env->max_items = 20; + env->items = calloc(env->max_items, sizeof(Item)); + env->num_items = 0; + env->agents = calloc(env->num_agents, sizeof(Agent)); + parse_grid(env); + init_static_cache(env); + init_cooking_pots(env); + init_pot_indices(env); + init_item_grid(env); + env->client = NULL; + + memset(&env->log, 0, sizeof(Log)); +} + +void c_reset(Overcooked* env) { + env->num_items = 0; + reset_item_grid(env); + parse_grid(env); + + for (int i = 0; i < env->num_stoves; i++) { + CookingPot* pot = &env->cooking_pots[i]; + pot->cooking_state = NOT_COOKING; + pot->cooking_progress = 0; + pot->ingredient_count = 0; + pot->num_onions = 0; + pot->num_tomatoes = 0; + for (int j = 0; j < MAX_INGREDIENTS; j++) { + pot->ingredient_types[j] = NO_ITEM; + } + } + + const LayoutInfo* layout = get_layout_info(env->layout_id); + for (int i = 0; i < env->num_agents; i++) { + if (i < layout->num_spawns) { + env->agents[i].x = layout->spawn_positions[i * 2]; + env->agents[i].y = layout->spawn_positions[i * 2 + 1]; + } else { + env->agents[i].x = 1 + (i % (env->width - 2)); + env->agents[i].y = 1 + (i / (env->width - 2)); + } + env->agents[i].held_item = NO_ITEM; + env->agents[i].facing_direction = 0; + env->agents[i].held_soup_onions = 0; + env->agents[i].held_soup_tomatoes = 0; + env->agents[i].held_soup_total = 0; + env->agents[i].ticks_since_reward = 0; + + env->rewards[i] = 0.0f; + env->terminals[i] = 0; + } + + env->agent_position_mask = 0; + for (int i = 0; i < env->num_agents; i++) { + set_agent_position(env, env->agents[i].x, env->agents[i].y); + } + + compute_observations(env); +} + +void c_step(Overcooked* env) { + for (int i = 0; i < env->num_agents; i++) { + int action = env->actions[i]; + env->rewards[i] = env->rewards_config.step_penalty; + env->agents[i].ticks_since_reward++; + + Agent* agent = &env->agents[i]; + int new_x = agent->x; + int new_y = agent->y; + + switch (action) { + case ACTION_UP: new_y -= 1; agent->facing_direction = 0; break; + case ACTION_DOWN: new_y += 1; agent->facing_direction = 1; break; + case ACTION_LEFT: new_x -= 1; agent->facing_direction = 2; break; + case ACTION_RIGHT: new_x += 1; agent->facing_direction = 3; break; + case ACTION_INTERACT: handle_interaction(env, i); break; + } + + if (action != ACTION_INTERACT && action != ACTION_NOOP) { + if (is_valid_position(env, new_x, new_y, i)) { + clear_agent_position(env, agent->x, agent->y); + agent->x = new_x; + agent->y = new_y; + set_agent_position(env, new_x, new_y); + } else { + for (int j = 0; j < env->num_agents; j++) { + if (j != i && (int)env->agents[j].x == new_x && (int)env->agents[j].y == new_y) { + env->log.agent_collisions++; + break; + } + } + } + } + } + + update_cooking(env); + + const LayoutInfo* layout = get_layout_info(env->layout_id); + for (int i = 0; i < env->num_agents; i++) { + if (env->agents[i].ticks_since_reward % 512 == 0 && env->agents[i].ticks_since_reward > 0) { + clear_agent_position(env, env->agents[i].x, env->agents[i].y); + if (i < layout->num_spawns) { + env->agents[i].x = layout->spawn_positions[i * 2]; + env->agents[i].y = layout->spawn_positions[i * 2 + 1]; + } else { + env->agents[i].x = 1 + (i % (env->width - 2)); + env->agents[i].y = 1 + (i / (env->width - 2)); + } + set_agent_position(env, env->agents[i].x, env->agents[i].y); + env->agents[i].held_item = NO_ITEM; + env->agents[i].held_soup_onions = 0; + env->agents[i].held_soup_tomatoes = 0; + env->agents[i].held_soup_total = 0; + } + } + + for (int i = 0; i < env->num_agents; i++) { + env->log.episode_return += env->rewards[i]; + } + + compute_observations(env); +} + +void c_close(Overcooked* env) { + free(env->grid); + free(env->items); + free(env->agents); + free(env->cooking_pots); + free(env->pot_index_grid); + free(env->item_grid); + if (env->client != NULL) { + unload_textures(env->client); + free(env->client); + } +} + +#endif // OVERCOOKED_H \ No newline at end of file diff --git a/ocean/overcooked/overcooked_items.h b/ocean/overcooked/overcooked_items.h new file mode 100644 index 0000000000..980bef2c8c --- /dev/null +++ b/ocean/overcooked/overcooked_items.h @@ -0,0 +1,123 @@ +/* Overcooked Items: Item and cooking pot management functions. + */ + +#ifndef OVERCOOKED_ITEMS_H +#define OVERCOOKED_ITEMS_H + +#include "overcooked_types.h" + +static inline Item* get_item_at(Overcooked* env, int x, int y) { + int idx = env->item_grid[y * env->width + x]; + return (idx >= 0) ? &env->items[idx] : NULL; +} + +static void add_item(Overcooked* env, int type, int x, int y) { + if (env->num_items < env->max_items) { + int idx = env->num_items; + env->items[idx].type = type; + env->items[idx].x = x; + env->items[idx].y = y; + env->items[idx].state = 0; + env->items[idx].num_onions = 0; + env->items[idx].num_tomatoes = 0; + env->items[idx].total_ingredients = 0; + env->item_grid[y * env->width + x] = idx; + env->num_items++; + } +} + +static void remove_item(Overcooked* env, int x, int y) { + int idx = env->item_grid[y * env->width + x]; + if (idx < 0) return; + + env->item_grid[y * env->width + x] = -1; + + if (idx < env->num_items - 1) { + Item* last = &env->items[env->num_items - 1]; + env->items[idx] = *last; + env->item_grid[last->y * env->width + last->x] = idx; + } + env->num_items--; +} + +static void init_cooking_pots(Overcooked* env) { + env->num_stoves = 0; + for (int i = 0; i < env->width * env->height; i++) { + if (env->grid[i] == STOVE) { + env->num_stoves++; + } + } + + env->cooking_pots = calloc(env->num_stoves, sizeof(CookingPot)); + + int pot_index = 0; + for (int y = 0; y < env->height; y++) { + for (int x = 0; x < env->width; x++) { + if (env->grid[y * env->width + x] == STOVE) { + CookingPot* pot = &env->cooking_pots[pot_index]; + pot->cooking_state = NOT_COOKING; + pot->cooking_progress = 0; + pot->ingredient_count = 0; + pot->num_onions = 0; + pot->num_tomatoes = 0; + for (int i = 0; i < MAX_INGREDIENTS; i++) { + pot->ingredient_types[i] = NO_ITEM; + } + pot_index++; + } + } + } +} + +static void init_pot_indices(Overcooked* env) { + // Allocate pot index grid (same size as main grid) + env->pot_index_grid = calloc(env->width * env->height, sizeof(int)); + + // Initialize all cells to -1 (not a stove) + for (int i = 0; i < env->width * env->height; i++) { + env->pot_index_grid[i] = -1; + } + + // Map stove cells to their pot indices (same order as init_cooking_pots) + int pot_idx = 0; + for (int y = 0; y < env->height; y++) { + for (int x = 0; x < env->width; x++) { + if (env->grid[y * env->width + x] == STOVE) { + env->pot_index_grid[y * env->width + x] = pot_idx++; + } + } + } +} + +// O(1) pot lookup using precomputed index grid +static inline CookingPot* get_pot_at(Overcooked* env, int x, int y) { + int idx = env->pot_index_grid[y * env->width + x]; + return (idx >= 0) ? &env->cooking_pots[idx] : NULL; +} + +static void init_item_grid(Overcooked* env) { + env->item_grid = calloc(env->width * env->height, sizeof(int)); + for (int i = 0; i < env->width * env->height; i++) { + env->item_grid[i] = -1; + } +} + +static void reset_item_grid(Overcooked* env) { + for (int i = 0; i < env->width * env->height; i++) { + env->item_grid[i] = -1; + } +} + +static void update_cooking(Overcooked* env) { + for (int i = 0; i < env->num_stoves; i++) { + CookingPot* pot = &env->cooking_pots[i]; + if (pot->cooking_state == COOKING) { + pot->cooking_progress++; + if (pot->cooking_progress >= COOKING_TIME) { + pot->cooking_state = COOKED; + } + } + } +} + +#endif // OVERCOOKED_ITEMS_H diff --git a/ocean/overcooked/overcooked_logic.h b/ocean/overcooked/overcooked_logic.h new file mode 100644 index 0000000000..a2f5a58a6e --- /dev/null +++ b/ocean/overcooked/overcooked_logic.h @@ -0,0 +1,255 @@ +/* Overcooked Logic: Game logic functions (parsing, interaction, movement). + */ + +#ifndef OVERCOOKED_LOGIC_H +#define OVERCOOKED_LOGIC_H + +#include "overcooked_types.h" +#include "overcooked_items.h" + +// Forward declaration for circular dependency +static void evaluate_dish_served(Overcooked* env, Agent* agent, int agent_idx); + +static void parse_grid(Overcooked* env) { + const LayoutInfo* layout = get_layout_info(env->layout_id); + for (int y = 0; y < env->height; y++) { + for (int x = 0; x < env->width; x++) { + char tile = get_layout_tile(layout, x, y); + int idx = y * env->width + x; + switch (tile) { + case '#': env->grid[idx] = WALL; break; + case '1': env->grid[idx] = COUNTER; break; + case '2': env->grid[idx] = STOVE; break; + case '3': env->grid[idx] = CUTTING_BOARD; break; + case '4': env->grid[idx] = INGREDIENT_BOX; break; + case '5': env->grid[idx] = SERVING_AREA; break; + case '6': env->grid[idx] = WALL; break; + case '7': env->grid[idx] = PLATE_BOX; break; + default: env->grid[idx] = EMPTY; break; + } + } + } +} + +static void init_static_cache(Overcooked* env) { + // Precompute normalization factors + env->cache.inv_width = 1.0f / env->width; + env->cache.inv_height = 1.0f / env->height; + + // Reset counts + env->cache.ingredient_box_count = 0; + env->cache.plate_box_count = 0; + env->cache.serving_area_count = 0; + env->cache.stove_count = 0; + env->cache.counter_count = 0; + + // Scan grid once and cache all static tile positions + for (int y = 0; y < env->height; y++) { + for (int x = 0; x < env->width; x++) { + int tile = env->grid[y * env->width + x]; + switch (tile) { + case INGREDIENT_BOX: + env->cache.ingredient_box_positions[env->cache.ingredient_box_count * 2] = x; + env->cache.ingredient_box_positions[env->cache.ingredient_box_count * 2 + 1] = y; + env->cache.ingredient_box_count++; + break; + case PLATE_BOX: + env->cache.plate_box_positions[env->cache.plate_box_count * 2] = x; + env->cache.plate_box_positions[env->cache.plate_box_count * 2 + 1] = y; + env->cache.plate_box_count++; + break; + case SERVING_AREA: + env->cache.serving_area_positions[env->cache.serving_area_count * 2] = x; + env->cache.serving_area_positions[env->cache.serving_area_count * 2 + 1] = y; + env->cache.serving_area_count++; + break; + case STOVE: + env->cache.stove_positions[env->cache.stove_count * 2] = x; + env->cache.stove_positions[env->cache.stove_count * 2 + 1] = y; + env->cache.stove_count++; + break; + case COUNTER: + env->cache.counter_positions[env->cache.counter_count * 2] = x; + env->cache.counter_positions[env->cache.counter_count * 2 + 1] = y; + env->cache.counter_count++; + break; + } + } + } +} + +static inline void set_agent_position(Overcooked* env, int x, int y) { + env->agent_position_mask |= (1ULL << (y * env->width + x)); +} + +static inline void clear_agent_position(Overcooked* env, int x, int y) { + env->agent_position_mask &= ~(1ULL << (y * env->width + x)); +} + +static inline int is_agent_at(Overcooked* env, int x, int y) { + return (env->agent_position_mask >> (y * env->width + x)) & 1; +} + +static int is_valid_position(Overcooked* env, int x, int y, int excluding_agent) { + (void)excluding_agent; + if (x < 0 || x >= env->width || y < 0 || y >= env->height) { + return 0; + } + if (env->grid[y * env->width + x] != EMPTY) { + return 0; + } + if (is_agent_at(env, x, y)) { + return 0; + } + return 1; +} + +static void handle_interaction(Overcooked* env, int agent_idx) { + Agent* agent = &env->agents[agent_idx]; + int target_x = agent->x; + int target_y = agent->y; + + switch (agent->facing_direction) { + case 0: target_y -= 1; break; // Up + case 1: target_y += 1; break; // Down + case 2: target_x -= 1; break; // Left + case 3: target_x += 1; break; // Right + } + + if (target_x < 0 || target_x >= env->width || target_y < 0 || target_y >= env->height) { + return; + } + + int tile = env->grid[target_y * env->width + target_x]; + Item* item = get_item_at(env, target_x, target_y); + CookingPot* pot = get_pot_at(env, target_x, target_y); + + if (tile == STOVE && pot != NULL) { + if (agent->held_item == ONION || agent->held_item == TOMATO) { + if (pot->cooking_state == NOT_COOKING && pot->ingredient_count < MAX_INGREDIENTS) { + pot->ingredient_types[pot->ingredient_count] = agent->held_item; + pot->ingredient_count++; + if (agent->held_item == ONION) { + pot->num_onions++; + env->rewards[agent_idx] += env->rewards_config.ingredient_added; + } else if (agent->held_item == TOMATO) { + pot->num_tomatoes++; + } + agent->held_item = NO_ITEM; + } + } + else if (agent->held_item == NO_ITEM && pot->ingredient_count > 0) { + if (pot->cooking_state == NOT_COOKING) { + pot->cooking_state = COOKING; + pot->cooking_progress = 0; + env->log.pots_started++; + if (pot->num_onions == 3) { + env->rewards[agent_idx] += env->rewards_config.pot_started; + } + } + else if (pot->cooking_state == COOKED) { + return; + } + } + else if (agent->held_item == PLATE && pot->cooking_state == COOKED) { + agent->held_item = PLATED_SOUP; + agent->held_soup_onions = pot->num_onions; + agent->held_soup_tomatoes = pot->num_tomatoes; + agent->held_soup_total = pot->ingredient_count; + + env->rewards[agent_idx] += env->rewards_config.soup_plated; + + pot->cooking_state = NOT_COOKING; + pot->cooking_progress = 0; + pot->ingredient_count = 0; + pot->num_onions = 0; + pot->num_tomatoes = 0; + for (int i = 0; i < MAX_INGREDIENTS; i++) { + pot->ingredient_types[i] = NO_ITEM; + } + } + return; + } + + if (tile == SERVING_AREA && agent->held_item == PLATED_SOUP) { + evaluate_dish_served(env, agent, agent_idx); + + agent->held_item = NO_ITEM; + agent->held_soup_onions = 0; + agent->held_soup_tomatoes = 0; + agent->held_soup_total = 0; + return; + } + + if (agent->held_item != NO_ITEM) { + if ((tile == COUNTER || tile == CUTTING_BOARD) && item == NULL) { + if (agent->held_item == PLATED_SOUP) { + add_item(env, agent->held_item, target_x, target_y); + Item* placed_soup = get_item_at(env, target_x, target_y); + if (placed_soup) { + placed_soup->num_onions = agent->held_soup_onions; + placed_soup->num_tomatoes = agent->held_soup_tomatoes; + placed_soup->total_ingredients = agent->held_soup_total; + } + agent->held_soup_onions = 0; + agent->held_soup_tomatoes = 0; + agent->held_soup_total = 0; + } else { + add_item(env, agent->held_item, target_x, target_y); + } + agent->held_item = NO_ITEM; + env->log.items_dropped++; + } else if ((tile == EMPTY) && item == NULL) { + agent->held_item = NO_ITEM; + env->log.items_dropped++; + } + } + else { + if (item != NULL) { + if (item->type == PLATED_SOUP) { + agent->held_soup_onions = item->num_onions; + agent->held_soup_tomatoes = item->num_tomatoes; + agent->held_soup_total = item->total_ingredients; + } + agent->held_item = item->type; + remove_item(env, target_x, target_y); + } + else if (tile == INGREDIENT_BOX) { + // TODO @mmbajo: What if we have Tomatoes as well? + // Add logs for each ingredient type + agent->held_item = ONION; // Always gives onions for now + env->log.ingredients_picked++; + env->rewards[agent_idx] += env->rewards_config.ingredient_picked; + } + else if (tile == PLATE_BOX) { + agent->held_item = PLATE; + env->rewards[agent_idx] += env->rewards_config.plate_picked; + } + } +} + +static void evaluate_dish_served(Overcooked* env, Agent* agent, int agent_idx) { + int is_correct_recipe = (agent->held_soup_onions == 3); + + if (is_correct_recipe) { + env->rewards[agent_idx] += env->rewards_config.dish_served_agent; + for (int i = 0; i < env->num_agents; i++) { + env->rewards[i] += env->rewards_config.dish_served_whole_team; + } + env->log.episode_length += agent->ticks_since_reward; + env->log.score += 25.0 / agent->ticks_since_reward; + env->log.perf += 25.0 / agent->ticks_since_reward; + agent->ticks_since_reward = 0; + env->log.correct_dishes++; + env->log.n++; + } else { + env->rewards[agent_idx] += env->rewards_config.wrong_dish_served; + for (int i = 0; i < env->num_agents; i++) { + env->rewards[i] += env->rewards_config.wrong_dish_served; + } + env->log.wrong_dishes++; + } + env->log.dishes_served++; +} + +#endif // OVERCOOKED_LOGIC_H diff --git a/ocean/overcooked/overcooked_obs.h b/ocean/overcooked/overcooked_obs.h new file mode 100644 index 0000000000..c349a71f1e --- /dev/null +++ b/ocean/overcooked/overcooked_obs.h @@ -0,0 +1,292 @@ +/* Overcooked Observations: Observation computation functions. + */ + +#ifndef OVERCOOKED_OBS_H +#define OVERCOOKED_OBS_H + +#include "overcooked_types.h" +#include "overcooked_items.h" + +static Item* find_nearest_plated_soup(Overcooked* env, Agent* agent, float* dx, float* dy) { + *dx = 0.0f; + *dy = 0.0f; + + if (agent->held_item == PLATED_SOUP) return NULL; + + Item* nearest = NULL; + float min_dist = 1000.0f; + for (int i = 0; i < env->num_items; i++) { + if (env->items[i].type == PLATED_SOUP) { + float dist = (float)(abs(env->items[i].x - (int)agent->x) + abs(env->items[i].y - (int)agent->y)); + if (dist < min_dist) { + min_dist = dist; + nearest = &env->items[i]; + *dx = (env->items[i].x - agent->x) * env->cache.inv_width; + *dy = (env->items[i].y - agent->y) * env->cache.inv_height; + } + } + } + return nearest; +} + +static void find_nearest_item_by_type(Overcooked* env, Agent* agent, + int item_type, float* dx, float* dy) { + *dx = 0.0f; + *dy = 0.0f; + + if (agent->held_item == item_type) return; + + float min_dist = 1000.0f; + for (int i = 0; i < env->num_items; i++) { + if (env->items[i].type == item_type) { + float dist = (float)(abs(env->items[i].x - (int)agent->x) + + abs(env->items[i].y - (int)agent->y)); + if (dist < min_dist) { + min_dist = dist; + *dx = (env->items[i].x - agent->x) * env->cache.inv_width; + *dy = (env->items[i].y - agent->y) * env->cache.inv_height; + } + } + } +} + +// Cached version: iterate over precomputed tile positions instead of scanning grid +static void compute_tile_proximity_cached(Overcooked* env, Agent* agent, + int* positions, int count, + float* dx, float* dy) { + *dx = 0.0f; + *dy = 0.0f; + + int min_dist = 1000; + int best_x = 0, best_y = 0; + + for (int i = 0; i < count; i++) { + int x = positions[i * 2]; + int y = positions[i * 2 + 1]; + int dist = abs(x - (int)agent->x) + abs(y - (int)agent->y); + if (dist < min_dist) { + min_dist = dist; + best_x = x; + best_y = y; + } + } + + if (min_dist < 1000) { + *dx = (best_x - agent->x) * env->cache.inv_width; + *dy = (best_y - agent->y) * env->cache.inv_height; + } +} + + +static void find_nearest_empty_counter(Overcooked* env, int agent_x, int agent_y, float* dx, float* dy) { + *dx = 0.0f; + *dy = 0.0f; + int min_dist = 1000; + + // Iterate cached counter positions instead of scanning entire grid + for (int i = 0; i < env->cache.counter_count; i++) { + int x = env->cache.counter_positions[i * 2]; + int y = env->cache.counter_positions[i * 2 + 1]; + + if (env->item_grid[y * env->width + x] < 0) { + int dist = abs(x - agent_x) + abs(y - agent_y); + if (dist < min_dist) { + min_dist = dist; + *dx = (x - agent_x) * env->cache.inv_width; + *dy = (y - agent_y) * env->cache.inv_height; + } + } + } +} + +static void compute_observations(Overcooked* env) { + // 43-dimensional observation vector for each agent + // Structure per agent: + // - Player features: 38 dims (4 orientation + 4 held + 16 proximity + 2 nearest soup ingredients + 2 pot soup ingredients + 1 pot exist + 4 pot state + 1 cook time + 4 walls) + // - Teammate relative position: 2 dims + // - Absolute position: 2 dims + // - Reward: 1 dim + // Total: 43 dims + // Proximity: onion box, plate box, plated soup, serving, empty counter, pot, pickable onion, pickable plate + + for (int agent_idx = 0; agent_idx < env->num_agents; agent_idx++) { + Agent* agent = &env->agents[agent_idx]; + float* obs = &env->observations[agent_idx * env->observation_size]; + int obs_idx = 0; + + memset(obs, 0, env->observation_size * sizeof(float)); + + // === PLAYER-SPECIFIC FEATURES (28 dims) === + + // 1. Orientation (one-hot, 4 dims) + obs[obs_idx + agent->facing_direction] = 1.0f; + obs_idx += 4; + + // 2. Held object (one-hot: onion, soup, dish, tomato, empty - 5 dims but we use 4) + if (agent->held_item == NO_ITEM) { + obs[obs_idx + 3] = 1.0f; // Empty + } else if (agent->held_item == ONION) { + obs[obs_idx + 0] = 1.0f; + } else if (agent->held_item == PLATED_SOUP) { + obs[obs_idx + 1] = 1.0f; // Soup + } else if (agent->held_item == PLATE) { + obs[obs_idx + 2] = 1.0f; // Dish + } + // Note: We don't use tomatoes in this version, keeping slot for compatibility + obs_idx += 4; + + // 3. Proximity to key objects (dx, dy for each, 16 dims total) + float dx, dy; + + // Nearest onion source (ingredient box) - returns (0,0) if holding onion + if (agent->held_item == ONION) { + dx = 0.0f; + dy = 0.0f; + } else { + compute_tile_proximity_cached(env, agent, + env->cache.ingredient_box_positions, env->cache.ingredient_box_count, + &dx, &dy); + } + obs[obs_idx++] = dx; + obs[obs_idx++] = dy; + + // Nearest dish (plate box) - returns (0,0) if holding plate + if (agent->held_item == PLATE) { + dx = 0.0f; + dy = 0.0f; + } else { + compute_tile_proximity_cached(env, agent, + env->cache.plate_box_positions, env->cache.plate_box_count, + &dx, &dy); + } + obs[obs_idx++] = dx; + obs[obs_idx++] = dy; + + // Nearest soup (plated soup) - returns (0,0) if holding soup or none exists + Item* nearest_soup = find_nearest_plated_soup(env, agent, &dx, &dy); + obs[obs_idx++] = dx; + obs[obs_idx++] = dy; + + // Nearest serving area + compute_tile_proximity_cached(env, agent, + env->cache.serving_area_positions, env->cache.serving_area_count, + &dx, &dy); + obs[obs_idx++] = dx; + obs[obs_idx++] = dy; + + // Nearest empty counter - special case, needs custom handling + find_nearest_empty_counter(env, agent->x, agent->y, &dx, &dy); + obs[obs_idx++] = dx; + obs[obs_idx++] = dy; + + // Nearest pot (stove) + compute_tile_proximity_cached(env, agent, + env->cache.stove_positions, env->cache.stove_count, + &dx, &dy); + obs[obs_idx++] = dx; + obs[obs_idx++] = dy; + + // Nearest pickable onion on counter (not in box) + find_nearest_item_by_type(env, agent, ONION, &dx, &dy); + obs[obs_idx++] = dx; + obs[obs_idx++] = dy; + + // Nearest pickable plate on counter (not in box) + find_nearest_item_by_type(env, agent, PLATE, &dx, &dy); + obs[obs_idx++] = dx; + obs[obs_idx++] = dy; + + // 4. Nearest soup ingredients (2 dims: onions, tomatoes in nearest plated soup or held soup) + if (agent->held_item == PLATED_SOUP) { + obs[obs_idx++] = agent->held_soup_onions / (float)MAX_INGREDIENTS; + obs[obs_idx++] = agent->held_soup_tomatoes / (float)MAX_INGREDIENTS; + } else if (nearest_soup) { + obs[obs_idx++] = nearest_soup->num_onions / (float)MAX_INGREDIENTS; + obs[obs_idx++] = nearest_soup->num_tomatoes / (float)MAX_INGREDIENTS; + } else { + obs[obs_idx++] = 0.0f; + obs[obs_idx++] = 0.0f; + } + + // 5. Pot soup ingredients (2 dims: onion count, always 0 for tomatoes in nearest pot) + // Find nearest pot using cached stove positions + int min_pot_dist = 1000; + CookingPot* nearest_pot = NULL; + + for (int i = 0; i < env->cache.stove_count; i++) { + int x = env->cache.stove_positions[i * 2]; + int y = env->cache.stove_positions[i * 2 + 1]; + int dist = abs(x - (int)agent->x) + abs(y - (int)agent->y); + if (dist < min_pot_dist) { + min_pot_dist = dist; + nearest_pot = get_pot_at(env, x, y); + } + } + + if (nearest_pot) { + obs[obs_idx++] = nearest_pot->num_onions / (float)MAX_INGREDIENTS; + obs[obs_idx++] = 0.0f; // No tomatoes in our version + } else { + obs[obs_idx++] = 0.0f; + obs[obs_idx++] = 0.0f; + } + + // 6. Reachable pot existence (1 dim) + obs[obs_idx++] = (nearest_pot != NULL) ? 1.0f : 0.0f; + + // 7. Pot state flags (4 dims: empty, full, cooking, ready) + if (nearest_pot) { + obs[obs_idx++] = (nearest_pot->ingredient_count == 0) ? 1.0f : 0.0f; // Empty + obs[obs_idx++] = (nearest_pot->ingredient_count == MAX_INGREDIENTS) ? 1.0f : 0.0f; // Full (exactly MAX_INGREDIENTS) + obs[obs_idx++] = (nearest_pot->cooking_state == COOKING) ? 1.0f : 0.0f; // Cooking + obs[obs_idx++] = (nearest_pot->cooking_state == COOKED) ? 1.0f : 0.0f; // Ready + } else { + obs_idx += 4; // Skip pot state if no pot found + } + + // 8. Remaining cooking time (1 dim) + if (nearest_pot && nearest_pot->cooking_state == COOKING) { + float remaining = (COOKING_TIME - nearest_pot->cooking_progress) / (float)COOKING_TIME; + obs[obs_idx++] = remaining; + } else { + obs[obs_idx++] = 0.0f; + } + + // 9. Wall detection (4 dims: up, down, left, right) + // Check each direction for any non-EMPTY tile (walls, stoves, counters, serving area, ingredient box, plate box, cutting board - all are non-walkable) + int wall_up = (agent->y > 0) ? env->grid[((int)agent->y - 1) * env->width + (int)agent->x] : WALL; + int wall_down = (agent->y < env->height - 1) ? env->grid[((int)agent->y + 1) * env->width + (int)agent->x] : WALL; + int wall_left = (agent->x > 0) ? env->grid[(int)agent->y * env->width + ((int)agent->x - 1)] : WALL; + int wall_right = (agent->x < env->width - 1) ? env->grid[(int)agent->y * env->width + ((int)agent->x + 1)] : WALL; + + obs[obs_idx++] = (wall_up != EMPTY) ? 1.0f : 0.0f; + obs[obs_idx++] = (wall_down != EMPTY) ? 1.0f : 0.0f; + obs[obs_idx++] = (wall_left != EMPTY) ? 1.0f : 0.0f; + obs[obs_idx++] = (wall_right != EMPTY) ? 1.0f : 0.0f; + + // === TEAMMATE RELATIVE POSITION (2 dims) === + // Find teammate (other agent) + int teammate_idx = (agent_idx == 0) ? 1 : 0; + if (teammate_idx < env->num_agents) { + Agent* teammate = &env->agents[teammate_idx]; + obs[obs_idx++] = (teammate->x - agent->x) / (float)env->width; + obs[obs_idx++] = (teammate->y - agent->y) / (float)env->height; + } else { + // No teammate, set relative position to 0 + obs[obs_idx++] = 0.0f; + obs[obs_idx++] = 0.0f; + } + + // === ABSOLUTE POSITION (2 dims) === + obs[obs_idx++] = agent->x / (float)env->width; + obs[obs_idx++] = agent->y / (float)env->height; + + // === REWARD (1 dim) === + obs[obs_idx++] = env->rewards[agent_idx]; + + // Total should be 43 dims (38 player features + 2 teammate relative position + 2 absolute position + 1 reward) + // Debug check removed - was only useful on first step + } +} + +#endif // OVERCOOKED_OBS_H diff --git a/ocean/overcooked/overcooked_render.h b/ocean/overcooked/overcooked_render.h new file mode 100644 index 0000000000..043c716e23 --- /dev/null +++ b/ocean/overcooked/overcooked_render.h @@ -0,0 +1,511 @@ +/* Overcooked Render: All rendering and texture management functions. + */ + + #ifndef OVERCOOKED_RENDER_H + #define OVERCOOKED_RENDER_H + + #include "overcooked_types.h" + #include "overcooked_items.h" + + static Color get_agent_color(int held_item) { + switch (held_item) { + case NO_ITEM: + return BLUE; // Blue when empty-handed + case TOMATO: + return (Color){200, 50, 50, 255}; // Dark red when holding tomato + case ONION: + return (Color){255, 200, 100, 255}; // Light orange when holding onion + case PLATE: + return (Color){200, 200, 220, 255}; // Light blue-gray when holding plate + case SOUP: + return (Color){255, 140, 0, 255}; // Orange when holding soup + case PLATED_SOUP: + return (Color){255, 165, 0, 255}; // Brighter orange when holding plated soup + default: + return BLUE; // Default to blue + } + } + + static void unload_textures(Client* client) { + UnloadTexture(client->floor); + UnloadTexture(client->counter); + UnloadTexture(client->pot); + UnloadTexture(client->serve); + UnloadTexture(client->onions_box); + UnloadTexture(client->tomatoes_box); + UnloadTexture(client->dishes_box); + UnloadTexture(client->wall); + + UnloadTexture(client->onion); + UnloadTexture(client->tomato); + UnloadTexture(client->dish); + UnloadTexture(client->soup_onion); + UnloadTexture(client->soup_tomato); + UnloadTexture(client->soup_onion_dish); + UnloadTexture(client->soup_tomato_dish); + + UnloadTexture(client->soup_onion_cooking_1); + UnloadTexture(client->soup_onion_cooking_2); + UnloadTexture(client->soup_onion_cooking_3); + UnloadTexture(client->soup_onion_cooked); + UnloadTexture(client->soup_tomato_cooking_1); + UnloadTexture(client->soup_tomato_cooking_2); + UnloadTexture(client->soup_tomato_cooking_3); + UnloadTexture(client->soup_tomato_cooked); + + UnloadTexture(client->chef_north); + UnloadTexture(client->chef_south); + UnloadTexture(client->chef_east); + UnloadTexture(client->chef_west); + UnloadTexture(client->chef_north_onion); + UnloadTexture(client->chef_south_onion); + UnloadTexture(client->chef_east_onion); + UnloadTexture(client->chef_west_onion); + UnloadTexture(client->chef_north_tomato); + UnloadTexture(client->chef_south_tomato); + UnloadTexture(client->chef_east_tomato); + UnloadTexture(client->chef_west_tomato); + UnloadTexture(client->chef_north_dish); + UnloadTexture(client->chef_south_dish); + UnloadTexture(client->chef_east_dish); + UnloadTexture(client->chef_west_dish); + UnloadTexture(client->chef_north_soup_onion); + UnloadTexture(client->chef_south_soup_onion); + UnloadTexture(client->chef_east_soup_onion); + UnloadTexture(client->chef_west_soup_onion); + UnloadTexture(client->chef_north_soup_tomato); + UnloadTexture(client->chef_south_soup_tomato); + UnloadTexture(client->chef_east_soup_tomato); + UnloadTexture(client->chef_west_soup_tomato); + + CloseWindow(); + } + + void c_render(Overcooked* env) { + if (env->client == NULL) { + int window_width = env->width * env->grid_size + 350; + int window_height = env->height * env->grid_size + 80; + InitWindow(window_width, window_height, "PufferLib Overcooked"); + SetTargetFPS(16); + env->client = (Client*)calloc(1, sizeof(Client)); + + env->client->floor = LoadTexture("resources/overcooked/terrain/floor.png"); + env->client->counter = LoadTexture("resources/overcooked/terrain/counter.png"); + env->client->pot = LoadTexture("resources/overcooked/terrain/pot.png"); + env->client->serve = LoadTexture("resources/overcooked/terrain/serve.png"); + env->client->onions_box = LoadTexture("resources/overcooked/terrain/onions.png"); + env->client->tomatoes_box = LoadTexture("resources/overcooked/terrain/tomatoes.png"); + env->client->dishes_box = LoadTexture("resources/overcooked/terrain/dishes.png"); + env->client->wall = LoadTexture("resources/overcooked/terrain/counter.png"); + + env->client->onion = LoadTexture("resources/overcooked/objects/onion.png"); + env->client->tomato = LoadTexture("resources/overcooked/objects/tomato.png"); + env->client->dish = LoadTexture("resources/overcooked/objects/dish.png"); + env->client->soup_onion = LoadTexture("resources/overcooked/objects/soup-onion-cooked.png"); + env->client->soup_tomato = LoadTexture("resources/overcooked/objects/soup-tomato-cooked.png"); + env->client->soup_onion_dish = LoadTexture("resources/overcooked/objects/soup-onion-dish.png"); + env->client->soup_tomato_dish = LoadTexture("resources/overcooked/objects/soup-tomato-dish.png"); + + env->client->soup_onion_cooking_1 = LoadTexture("resources/overcooked/objects/soup-onion-1-cooking.png"); + env->client->soup_onion_cooking_2 = LoadTexture("resources/overcooked/objects/soup-onion-2-cooking.png"); + env->client->soup_onion_cooking_3 = LoadTexture("resources/overcooked/objects/soup-onion-3-cooking.png"); + env->client->soup_onion_cooked = LoadTexture("resources/overcooked/objects/soup-onion-cooked.png"); + env->client->soup_tomato_cooking_1 = LoadTexture("resources/overcooked/objects/soup-tomato-1-cooking.png"); + env->client->soup_tomato_cooking_2 = LoadTexture("resources/overcooked/objects/soup-tomato-2-cooking.png"); + env->client->soup_tomato_cooking_3 = LoadTexture("resources/overcooked/objects/soup-tomato-3-cooking.png"); + env->client->soup_tomato_cooked = LoadTexture("resources/overcooked/objects/soup-tomato-cooked.png"); + + env->client->chef_north = LoadTexture("resources/overcooked/chefs/NORTH.png"); + env->client->chef_south = LoadTexture("resources/overcooked/chefs/SOUTH.png"); + env->client->chef_east = LoadTexture("resources/overcooked/chefs/EAST.png"); + env->client->chef_west = LoadTexture("resources/overcooked/chefs/WEST.png"); + env->client->chef_north_onion = LoadTexture("resources/overcooked/chefs/NORTH-onion.png"); + env->client->chef_south_onion = LoadTexture("resources/overcooked/chefs/SOUTH-onion.png"); + env->client->chef_east_onion = LoadTexture("resources/overcooked/chefs/EAST-onion.png"); + env->client->chef_west_onion = LoadTexture("resources/overcooked/chefs/WEST-onion.png"); + env->client->chef_north_tomato = LoadTexture("resources/overcooked/chefs/NORTH-tomato.png"); + env->client->chef_south_tomato = LoadTexture("resources/overcooked/chefs/SOUTH-tomato.png"); + env->client->chef_east_tomato = LoadTexture("resources/overcooked/chefs/EAST-tomato.png"); + env->client->chef_west_tomato = LoadTexture("resources/overcooked/chefs/WEST-tomato.png"); + env->client->chef_north_dish = LoadTexture("resources/overcooked/chefs/NORTH-dish.png"); + env->client->chef_south_dish = LoadTexture("resources/overcooked/chefs/SOUTH-dish.png"); + env->client->chef_east_dish = LoadTexture("resources/overcooked/chefs/EAST-dish.png"); + env->client->chef_west_dish = LoadTexture("resources/overcooked/chefs/WEST-dish.png"); + + env->client->chef_north_soup_onion = LoadTexture("resources/overcooked/chefs/NORTH-soup-onion.png"); + env->client->chef_south_soup_onion = LoadTexture("resources/overcooked/chefs/SOUTH-soup-onion.png"); + env->client->chef_east_soup_onion = LoadTexture("resources/overcooked/chefs/EAST-soup-onion.png"); + env->client->chef_west_soup_onion = LoadTexture("resources/overcooked/chefs/WEST-soup-onion.png"); + env->client->chef_north_soup_tomato = LoadTexture("resources/overcooked/chefs/NORTH-soup-tomato.png"); + env->client->chef_south_soup_tomato = LoadTexture("resources/overcooked/chefs/SOUTH-soup-tomato.png"); + env->client->chef_east_soup_tomato = LoadTexture("resources/overcooked/chefs/EAST-soup-tomato.png"); + env->client->chef_west_soup_tomato = LoadTexture("resources/overcooked/chefs/WEST-soup-tomato.png"); + } + + if (IsKeyDown(KEY_ESCAPE)) exit(0); + + BeginDrawing(); + ClearBackground((Color){240, 240, 240, 255}); + + DrawText(TextFormat("Correct Dishes: %d", (int)env->log.n), 10, 10, 20, BLACK); + DrawText(TextFormat("Total Dishes: %d", (int)env->log.dishes_served), 10, 35, 20, BLACK); + DrawText("Recipe: 3 Onions", 10, 60, 16, DARKGRAY); + + int grid_offset_y = 80; + for (int y = 0; y < env->height; y++) { + for (int x = 0; x < env->width; x++) { + int idx = y * env->width + x; + Rectangle dest = {x * env->grid_size, y * env->grid_size + grid_offset_y, env->grid_size, env->grid_size}; + + if (env->client->floor.id != 0) { + DrawTexturePro(env->client->floor, + (Rectangle){0, 0, env->client->floor.width, env->client->floor.height}, + dest, (Vector2){0, 0}, 0, WHITE); + } + + Texture2D* texture = NULL; + switch (env->grid[idx]) { + case COUNTER: + texture = &env->client->counter; + break; + case STOVE: + texture = &env->client->pot; + break; + case CUTTING_BOARD: + texture = &env->client->counter; + break; + case INGREDIENT_BOX: + texture = &env->client->onions_box; + break; + case SERVING_AREA: + texture = &env->client->serve; + break; + case PLATE_BOX: + texture = &env->client->dishes_box; + break; + case WALL: + texture = &env->client->wall; + break; + } + + if (texture && texture->id != 0) { + DrawTexturePro(*texture, + (Rectangle){0, 0, texture->width, texture->height}, + dest, (Vector2){0, 0}, 0, WHITE); + } + + if (env->grid[idx] == STOVE) { + CookingPot* pot = get_pot_at(env, x, y); + if (pot && pot->ingredient_count > 0) { + Texture2D* cooking_texture = NULL; + + bool is_onion_soup = (pot->num_onions >= pot->num_tomatoes); + if (is_onion_soup) { + if (pot->ingredient_count <= 1) { + cooking_texture = &env->client->soup_onion_cooking_1; + } else if (pot->ingredient_count == 2) { + cooking_texture = &env->client->soup_onion_cooking_2; + } else { + cooking_texture = &env->client->soup_onion_cooking_3; + } + } else { + if (pot->ingredient_count <= 1) { + cooking_texture = &env->client->soup_tomato_cooking_1; + } else if (pot->ingredient_count == 2) { + cooking_texture = &env->client->soup_tomato_cooking_2; + } else { + cooking_texture = &env->client->soup_tomato_cooking_3; + } + } + + if (pot->cooking_state == COOKING) { + float progress = (float)pot->cooking_progress / COOKING_TIME; + + DrawRectangle(x * env->grid_size + 5, + y * env->grid_size + grid_offset_y + env->grid_size - 10, + (env->grid_size - 10) * progress, 3, GREEN); + DrawRectangleLines(x * env->grid_size + 5, + y * env->grid_size + grid_offset_y + env->grid_size - 10, + env->grid_size - 10, 3, BLACK); + } + else if (pot->cooking_state == COOKED) { + cooking_texture = is_onion_soup ? &env->client->soup_onion_cooked : + &env->client->soup_tomato_cooked; + DrawText("READY!", x * env->grid_size + 5, + y * env->grid_size + grid_offset_y + env->grid_size - 10, + 8, GREEN); + } + + if (cooking_texture && cooking_texture->id != 0) { + Rectangle pot_dest = { + x * env->grid_size, + y * env->grid_size + grid_offset_y, + env->grid_size, + env->grid_size + }; + DrawTexturePro(*cooking_texture, + (Rectangle){0, 0, cooking_texture->width, cooking_texture->height}, + pot_dest, (Vector2){0, 0}, 0, WHITE); + } + } + } + } + } + + for (int i = 0; i < env->num_items; i++) { + Texture2D* texture = NULL; + switch (env->items[i].type) { + case TOMATO: + texture = &env->client->tomato; + break; + case ONION: + texture = &env->client->onion; + break; + case PLATE: + texture = &env->client->dish; + break; + case SOUP: + texture = &env->client->soup_onion; + break; + case PLATED_SOUP: + if (env->items[i].num_onions >= env->items[i].num_tomatoes) { + texture = &env->client->soup_onion_dish; + } else { + texture = &env->client->soup_tomato_dish; + } + break; + } + + if (texture && texture->id != 0) { + Rectangle dest = { + env->items[i].x * env->grid_size + env->grid_size/4, + env->items[i].y * env->grid_size + grid_offset_y + env->grid_size/4, + env->grid_size/2, + env->grid_size/2 + }; + DrawTexturePro(*texture, + (Rectangle){0, 0, texture->width, texture->height}, + dest, (Vector2){0, 0}, 0, WHITE); + } else { + Color item_color = GRAY; + switch (env->items[i].type) { + case TOMATO: item_color = RED; break; + case ONION: item_color = YELLOW; break; + case PLATE: item_color = WHITE; break; + case SOUP: item_color = ORANGE; break; + case PLATED_SOUP: item_color = ORANGE; break; + } + DrawCircle( + env->items[i].x * env->grid_size + env->grid_size/2, + env->items[i].y * env->grid_size + grid_offset_y + env->grid_size/2, + env->grid_size/4, + item_color + ); + } + } + + for (int agent_idx = 0; agent_idx < env->num_agents; agent_idx++) { + Agent* agent = &env->agents[agent_idx]; + Texture2D* chef_texture = NULL; + + if (agent->held_item == NO_ITEM) { + switch (agent->facing_direction) { + case 0: chef_texture = &env->client->chef_north; break; + case 1: chef_texture = &env->client->chef_south; break; + case 2: chef_texture = &env->client->chef_west; break; + case 3: chef_texture = &env->client->chef_east; break; + } + } else if (agent->held_item == ONION) { + switch (agent->facing_direction) { + case 0: chef_texture = &env->client->chef_north_onion; break; + case 1: chef_texture = &env->client->chef_south_onion; break; + case 2: chef_texture = &env->client->chef_west_onion; break; + case 3: chef_texture = &env->client->chef_east_onion; break; + } + } else if (agent->held_item == TOMATO) { + switch (agent->facing_direction) { + case 0: chef_texture = &env->client->chef_north_tomato; break; + case 1: chef_texture = &env->client->chef_south_tomato; break; + case 2: chef_texture = &env->client->chef_west_tomato; break; + case 3: chef_texture = &env->client->chef_east_tomato; break; + } + } else if (agent->held_item == PLATE) { + switch (agent->facing_direction) { + case 0: chef_texture = &env->client->chef_north_dish; break; + case 1: chef_texture = &env->client->chef_south_dish; break; + case 2: chef_texture = &env->client->chef_west_dish; break; + case 3: chef_texture = &env->client->chef_east_dish; break; + } + } else if (agent->held_item == PLATED_SOUP) { + bool is_onion_soup = (agent->held_soup_onions >= agent->held_soup_tomatoes); + if (is_onion_soup) { + switch (agent->facing_direction) { + case 0: chef_texture = &env->client->chef_north_soup_onion; break; + case 1: chef_texture = &env->client->chef_south_soup_onion; break; + case 2: chef_texture = &env->client->chef_west_soup_onion; break; + case 3: chef_texture = &env->client->chef_east_soup_onion; break; + } + } else { + switch (agent->facing_direction) { + case 0: chef_texture = &env->client->chef_north_soup_tomato; break; + case 1: chef_texture = &env->client->chef_south_soup_tomato; break; + case 2: chef_texture = &env->client->chef_west_soup_tomato; break; + case 3: chef_texture = &env->client->chef_east_soup_tomato; break; + } + } + } + + if (chef_texture && chef_texture->id != 0) { + Rectangle dest = { + agent->x * env->grid_size, + agent->y * env->grid_size + grid_offset_y, + env->grid_size, + env->grid_size + }; + Color tint = WHITE; + if (agent_idx == 0) { + tint = (Color){255, 255, 255, 255}; // White for player 1 + } else if (agent_idx == 1) { + tint = (Color){200, 200, 255, 255}; // Light blue tint for player 2 + } else { + tint = (Color){255, 200, 200, 255}; // Light red tint for other players + } + DrawTexturePro(*chef_texture, + (Rectangle){0, 0, chef_texture->width, chef_texture->height}, + dest, (Vector2){0, 0}, 0, tint); + } else { + Color agent_color = get_agent_color(agent->held_item); + if (agent_idx == 1) { + agent_color = (Color){agent_color.r * 0.8, agent_color.g * 0.8, agent_color.b, agent_color.a}; + } + DrawRectangle( + agent->x * env->grid_size + env->grid_size/4, + agent->y * env->grid_size + grid_offset_y + env->grid_size/4, + env->grid_size/2, + env->grid_size/2, + agent_color + ); + + int dir_x = agent->x * env->grid_size + env->grid_size/2; + int dir_y = agent->y * env->grid_size + grid_offset_y + env->grid_size/2; + int end_x = dir_x, end_y = dir_y; + switch (agent->facing_direction) { + case 0: end_y -= env->grid_size/4; break; // Up + case 1: end_y += env->grid_size/4; break; // Down + case 2: end_x -= env->grid_size/4; break; // Left + case 3: end_x += env->grid_size/4; break; // Right + } + DrawLine(dir_x, dir_y, end_x, end_y, BLACK); + + DrawText(TextFormat("%d", agent_idx + 1), + agent->x * env->grid_size + 2, + agent->y * env->grid_size + grid_offset_y + 2, + 10, BLACK); + } + } + + int obs_panel_x = env->width * env->grid_size + 10; + int obs_panel_y = grid_offset_y; + + if (env->num_agents > 0) { + float* obs = &env->observations[0]; + + DrawText("=== OBSERVATION ARRAY (43 dims) ===", obs_panel_x, obs_panel_y, 11, BLACK); + obs_panel_y += 18; + + DrawText("-- PLAYER (0-33) --", obs_panel_x, obs_panel_y, 10, DARKGREEN); + obs_panel_y += 13; + + DrawText(TextFormat("[0-3] Orient: %.0f %.0f %.0f %.0f", + obs[0], obs[1], obs[2], obs[3]), + obs_panel_x, obs_panel_y, 9, BLACK); + obs_panel_y += 11; + + DrawText(TextFormat("[4-7] Held: %.0f %.0f %.0f %.0f", + obs[4], obs[5], obs[6], obs[7]), + obs_panel_x, obs_panel_y, 9, BLACK); + obs_panel_y += 11; + + DrawText(TextFormat("[8-9] Onion: %.2f, %.2f", obs[8], obs[9]), + obs_panel_x, obs_panel_y, 9, BLACK); + obs_panel_y += 10; + DrawText(TextFormat("[10-11] Dish: %.2f, %.2f", obs[10], obs[11]), + obs_panel_x, obs_panel_y, 9, BLACK); + obs_panel_y += 10; + DrawText(TextFormat("[12-13] Soup: %.2f, %.2f", obs[12], obs[13]), + obs_panel_x, obs_panel_y, 9, BLACK); + obs_panel_y += 10; + DrawText(TextFormat("[14-15] Serve: %.2f, %.2f", obs[14], obs[15]), + obs_panel_x, obs_panel_y, 9, BLACK); + obs_panel_y += 10; + DrawText(TextFormat("[16-17] Empty: %.2f, %.2f", obs[16], obs[17]), + obs_panel_x, obs_panel_y, 9, BLACK); + obs_panel_y += 10; + DrawText(TextFormat("[18-19] Pot: %.2f, %.2f", obs[18], obs[19]), + obs_panel_x, obs_panel_y, 9, BLACK); + obs_panel_y += 10; + + DrawText(TextFormat("[20-21] PickOnion: %.2f, %.2f", obs[20], obs[21]), + obs_panel_x, obs_panel_y, 9, BLACK); + obs_panel_y += 10; + + DrawText(TextFormat("[22-23] PickPlate: %.2f, %.2f", obs[22], obs[23]), + obs_panel_x, obs_panel_y, 9, BLACK); + obs_panel_y += 10; + + DrawText(TextFormat("[24-25] SoupIngr: %.2f, %.2f", obs[24], obs[25]), + obs_panel_x, obs_panel_y, 9, BLACK); + obs_panel_y += 10; + + DrawText(TextFormat("[26-27] PotIngr: %.2f, %.2f", obs[26], obs[27]), + obs_panel_x, obs_panel_y, 9, BLACK); + obs_panel_y += 10; + + DrawText(TextFormat("[28] PotExists: %.0f", obs[28]), + obs_panel_x, obs_panel_y, 9, BLACK); + obs_panel_y += 10; + + DrawText(TextFormat("[29-32] PotState: %.0f %.0f %.0f %.0f", + obs[29], obs[30], obs[31], obs[32]), + obs_panel_x, obs_panel_y, 9, BLACK); + obs_panel_y += 10; + + DrawText(TextFormat("[33] CookTime: %.2f", obs[33]), + obs_panel_x, obs_panel_y, 9, BLACK); + obs_panel_y += 10; + + DrawText(TextFormat("[34-37] Walls: %.0f %.0f %.0f %.0f", + obs[34], obs[35], obs[36], obs[37]), + obs_panel_x, obs_panel_y, 9, BLACK); + obs_panel_y += 13; + + DrawText("-- TEAMMATE (38-39) --", obs_panel_x, obs_panel_y, 10, DARKBLUE); + obs_panel_y += 13; + + if (env->num_agents > 1) { + DrawText(TextFormat("[38-39] T.RelPos: %.2f, %.2f", obs[38], obs[39]), + obs_panel_x, obs_panel_y, 9, BLACK); + obs_panel_y += 10; + } else { + DrawText("No teammate", obs_panel_x, obs_panel_y, 9, GRAY); + obs_panel_y += 10; + } + + obs_panel_y += 3; + DrawText("-- MISC (40-42) --", obs_panel_x, obs_panel_y, 10, DARKGRAY); + obs_panel_y += 13; + + DrawText(TextFormat("[40-41] AbsPos: %.3f, %.3f", obs[40], obs[41]), + obs_panel_x, obs_panel_y, 9, BLACK); + obs_panel_y += 10; + + DrawText(TextFormat("[42] Reward: %.2f", obs[42]), + obs_panel_x, obs_panel_y, 9, BLACK); + obs_panel_y += 10; + } + + EndDrawing(); + } + + #endif // OVERCOOKED_RENDER_H + \ No newline at end of file diff --git a/ocean/overcooked/overcooked_types.h b/ocean/overcooked/overcooked_types.h new file mode 100644 index 0000000000..5e46abcec1 --- /dev/null +++ b/ocean/overcooked/overcooked_types.h @@ -0,0 +1,327 @@ +/* Overcooked Types: Constants, enums, and struct definitions. + */ + +#ifndef OVERCOOKED_TYPES_H +#define OVERCOOKED_TYPES_H + +#include +#include +#include +#include +#include +#include "raylib.h" + +// Tile types +#define EMPTY 0 +#define COUNTER 1 +#define STOVE 2 +#define CUTTING_BOARD 3 +#define INGREDIENT_BOX 4 +#define SERVING_AREA 5 +#define WALL 6 +#define PLATE_BOX 7 +#define AGENT 8 + +// Item types +#define NO_ITEM 10 +#define TOMATO 11 +#define ONION 12 +#define PLATE 13 +#define SOUP 14 +#define PLATED_SOUP 15 + +// Cooking states +#define NOT_COOKING 0 +#define COOKING 1 +#define COOKED 2 + +// Cooking parameters +#define COOKING_TIME 20 +#define MAX_INGREDIENTS 3 + +// Actions +#define ACTION_NOOP 0 +#define ACTION_UP 1 +#define ACTION_DOWN 2 +#define ACTION_LEFT 3 +#define ACTION_RIGHT 4 +#define ACTION_INTERACT 5 + +// Agent states +#define AGENT_EMPTY_HANDED 0 +#define AGENT_HOLDING_ITEM 1 + +#define MAX_SPAWN_POSITIONS 8 + +typedef enum { + LAYOUT_CRAMPED_ROOM = 0, + LAYOUT_ASYMMETRIC_ADVANTAGES = 1, + LAYOUT_FORCED_COORDINATION = 2, + LAYOUT_COORDINATION_RING = 3, + LAYOUT_COUNTER_CIRCUIT = 4, + LAYOUT_COUNT +} LayoutType; + +typedef struct { + const char* name; + int width; + int height; + const char* grid; + int spawn_positions[MAX_SPAWN_POSITIONS]; + int num_spawns; +} LayoutInfo; + +typedef struct { + float dish_served_whole_team; + float dish_served_agent; + float pot_started; + float ingredient_added; + float ingredient_picked; + float plate_picked; + float soup_plated; + float wrong_dish_served; + float step_penalty; +} RewardConfig; + +typedef struct { + float perf; // Recommended 0-1 normalized single real number perf metric + float score; // Recommended unnormalized single real number perf metric + float episode_return; // Recommended metric: sum of agent rewards over episode + float episode_length; // Recommended metric: number of steps of agent episode + float dishes_served; // Number of dishes successfully served + float correct_dishes; // Number of correct 3-onion dishes + float wrong_dishes; // Number of wrong dishes submitted + float ingredients_picked; // Total ingredients picked up + float pots_started; // Number of cooking sessions started + float items_dropped; // Number of items dropped/placed + float agent_collisions; // Number of times agents tried to move to same spot + float n; // Required as the last field +} Log; + +typedef struct { + Texture2D floor; + Texture2D counter; + Texture2D pot; + Texture2D serve; + Texture2D onions_box; + Texture2D tomatoes_box; + Texture2D dishes_box; + Texture2D wall; + + Texture2D onion; + Texture2D tomato; + Texture2D dish; + Texture2D soup_onion; + Texture2D soup_tomato; + + Texture2D soup_onion_cooking_1; + Texture2D soup_onion_cooking_2; + Texture2D soup_onion_cooking_3; + Texture2D soup_onion_cooked; + Texture2D soup_tomato_cooking_1; + Texture2D soup_tomato_cooking_2; + Texture2D soup_tomato_cooking_3; + Texture2D soup_tomato_cooked; + + Texture2D chef_north; + Texture2D chef_south; + Texture2D chef_east; + Texture2D chef_west; + Texture2D chef_north_onion; + Texture2D chef_south_onion; + Texture2D chef_east_onion; + Texture2D chef_west_onion; + Texture2D chef_north_tomato; + Texture2D chef_south_tomato; + Texture2D chef_east_tomato; + Texture2D chef_west_tomato; + Texture2D chef_north_dish; + Texture2D chef_south_dish; + Texture2D chef_east_dish; + Texture2D chef_west_dish; + Texture2D chef_north_soup_onion; + Texture2D chef_south_soup_onion; + Texture2D chef_east_soup_onion; + Texture2D chef_west_soup_onion; + Texture2D chef_north_soup_tomato; + Texture2D chef_south_soup_tomato; + Texture2D chef_east_soup_tomato; + Texture2D chef_west_soup_tomato; + + Texture2D soup_onion_dish; + Texture2D soup_tomato_dish; +} Client; + +typedef struct __attribute__((aligned(32))) { + float x; + float y; + int facing_direction; + int held_item; + int held_soup_onions; + int held_soup_tomatoes; + int held_soup_total; + int ticks_since_reward; +} Agent; + +typedef struct __attribute__((aligned(32))) { + int x; + int y; + int type; + int state; + int num_onions; + int num_tomatoes; + int total_ingredients; +} Item; + +typedef struct { + int cooking_state; // NOT_COOKING, COOKING, COOKED + int cooking_progress; // Steps since cooking started + int ingredient_types[MAX_INGREDIENTS]; // Types of ingredients added + int ingredient_count; // Number of ingredients in pot + int num_onions; // Count of onions + int num_tomatoes; // Count of tomatoes +} CookingPot; + +// Cache for static tile positions (computed once at init, never changes) +typedef struct { + // Static tile positions stored as x,y pairs: [x0, y0, x1, y1, ...] + int ingredient_box_positions[20]; // Max 10 ingredient boxes + int ingredient_box_count; + int plate_box_positions[20]; // Max 10 plate boxes + int plate_box_count; + int serving_area_positions[20]; // Max 10 serving areas + int serving_area_count; + int stove_positions[20]; // Max 10 stoves + int stove_count; + int counter_positions[100]; // Max 50 counters + int counter_count; + + // Precomputed normalization factors + float inv_width; // 1.0f / width + float inv_height; // 1.0f / height +} StaticCache; + +typedef struct { + Log log; // Required field. Env binding code uses this to aggregate logs + Client* client; + LayoutType layout_id; + char* grid; + Item* items; // Dynamic items in the kitchen + int num_items; + int max_items; + Agent* agents; // Array of agents + int num_agents; + uint64_t agent_position_mask; // Bit (y * width + x) set if agent present + CookingPot* cooking_pots; // Array of cooking pots (one per stove) + int num_stoves; + int* pot_index_grid; // Maps grid cell to pot index (-1 if not a stove) + int* item_grid; // Maps grid cell to item index (-1 if empty) + float* observations; // Required. You can use any obs type, but make sure it matches in Python! + float* actions; // Required. int* for discrete/multidiscrete, float* for box + float* rewards; // Required + float* terminals; // Required. We don't yet have truncations as standard yet + int width; + int height; + int grid_size; + RewardConfig rewards_config; + int observation_size; + StaticCache cache; // Cached static tile positions for O(1) lookup + unsigned int rng; +} Overcooked; + +// Grid layout +static const char CRAMPED_ROOM[5][5] = { + {'6', '1', '2', '1', '6'}, + {'4', ' ', ' ', ' ', '4'}, + {'1', ' ', ' ', ' ', '1'}, + {'1', ' ', ' ', ' ', '1'}, + {'6', '7', '1', '5', '6'} +}; + +static const char ASYMMETRIC_ADVANTAGES[5][9] = { + {'6','1','6','6','6','6','6','1','6'}, + {'4',' ','1','5','6','4','1',' ','5'}, + {'1',' ',' ',' ','2',' ',' ',' ','1'}, + {'1',' ',' ',' ','2',' ',' ',' ','1'}, + {'6','1','1','7','6','7','1','1','6'} +}; + +static const char COORDINATION_RING[5][5] = { + {'6', '1', '1', '2', '6'}, + {'1', ' ', ' ', ' ', '2'}, + {'7', ' ', '1', ' ', '1'}, + {'4', ' ', ' ', ' ', '1'}, + {'6', '4', '5', '1', '6'} +}; + +static const char FORCED_COORDINATION[5][5] = { + {'6', '1', '6', '2', '6'}, + {'4', ' ', '1', ' ', '2'}, + {'4', ' ', '1', ' ', '1'}, + {'7', ' ', '1', ' ', '1'}, + {'6', '1', '6', '5', '6'} +}; + +static const char COUNTER_CIRCUIT[5][8] = { + {'6','1','1','2','2','1','1','6'}, + {'1',' ',' ',' ',' ',' ',' ','1'}, + {'7',' ','1','1','1','1',' ','5'}, + {'1',' ',' ',' ',' ',' ',' ','1'}, + {'6','1','1','4','4','1','1','6'} +}; + +static const LayoutInfo LAYOUTS[LAYOUT_COUNT] = { + { + "cramped_room", + 5, 5, + (const char*)CRAMPED_ROOM, + {1, 2, 3, 2}, + 2 + }, + { + "asymmetric_advantages", + 9, 5, + (const char*)ASYMMETRIC_ADVANTAGES, + {1, 2, 7, 2}, + 2 + }, + { + "forced_coordination", + 5, 5, + (const char*)FORCED_COORDINATION, + {1, 2, 3, 2}, + 2 + }, + { + "coordination_ring", + 5, 5, + (const char*)COORDINATION_RING, + {1, 2, 3, 2}, + 2 + }, + { + "counter_circuit", + 8, 5, + (const char*)COUNTER_CIRCUIT, + {1, 1, 6, 3}, + 2 + } +}; + +static inline const LayoutInfo* get_layout_info(LayoutType id) { + if (id < 0 || id >= LAYOUT_COUNT) return &LAYOUTS[0]; + return &LAYOUTS[id]; +} + +static inline char get_layout_tile(const LayoutInfo* info, int x, int y) { + return info->grid[y * info->width + x]; +} + +static inline LayoutType get_layout_by_name(const char* name) { + for (int i = 0; i < LAYOUT_COUNT; i++) { + if (strcmp(LAYOUTS[i].name, name) == 0) return (LayoutType)i; + } + return LAYOUT_CRAMPED_ROOM; +} + +#endif // OVERCOOKED_TYPES_H diff --git a/ocean/pacman/binding.c b/ocean/pacman/binding.c new file mode 100644 index 0000000000..06e36ceb4d --- /dev/null +++ b/ocean/pacman/binding.c @@ -0,0 +1,27 @@ +#include "pacman.h" +#define OBS_SIZE 291 +#define NUM_ATNS 1 +#define ACT_SIZES {4} +#define OBS_TENSOR_T FloatTensor + +#define Env PacmanEnv +#include "vecenv.h" + +void my_init(Env* env, Dict* kwargs) { + env->num_agents = 1; + env->randomize_starting_position = dict_get(kwargs, "randomize_starting_position")->value; + env->min_start_timeout = dict_get(kwargs, "min_start_timeout")->value; + env->max_start_timeout = dict_get(kwargs, "max_start_timeout")->value; + env->frightened_time = dict_get(kwargs, "frightened_time")->value; + env->max_mode_changes = dict_get(kwargs, "max_mode_changes")->value; + env->scatter_mode_length = dict_get(kwargs, "scatter_mode_length")->value; + env->chase_mode_length = dict_get(kwargs, "chase_mode_length")->value; + init(env); +} + +void my_log(Log* log, Dict* out) { + dict_set(out, "perf", log->perf); + dict_set(out, "score", log->score); + dict_set(out, "episode_return", log->episode_return); + dict_set(out, "episode_length", log->episode_length); +} diff --git a/pufferlib/ocean/pacman/helpers.h b/ocean/pacman/helpers.h similarity index 100% rename from pufferlib/ocean/pacman/helpers.h rename to ocean/pacman/helpers.h diff --git a/pufferlib/ocean/pacman/pacman.c b/ocean/pacman/pacman.c similarity index 69% rename from pufferlib/ocean/pacman/pacman.c rename to ocean/pacman/pacman.c index a1a9d599ad..0a8acacbb6 100644 --- a/pufferlib/ocean/pacman/pacman.c +++ b/ocean/pacman/pacman.c @@ -4,9 +4,9 @@ void demo() { // printf("OBSERVATIONS_COUNT: %d\n", OBSERVATIONS_COUNT); - Weights* weights = load_weights("resources/pacman/pacman_weights.bin", 170117); + Weights* weights = load_weights("resources/pacman/pacman_weights.bin"); int logit_sizes[1] = {4}; - LinearLSTM* net = make_linearlstm(weights, 1, OBSERVATIONS_COUNT, logit_sizes, 1); + PufferNet* net = make_puffernet(weights, 1, OBSERVATIONS_COUNT, 256, 6, logit_sizes, 1); PacmanEnv env = { .randomize_starting_position = false, @@ -35,11 +35,11 @@ void demo() { } if (!human_control) { - forward_linearlstm(net, env.observations, env.actions); + forward_puffernet(net, env.observations, env.actions); } c_step(&env); - if (env.terminals[0]) { + if (env.terminals[0] > 0.5f) { c_reset(&env); } @@ -47,32 +47,13 @@ void demo() { c_render(&env); } } - free_linearlstm(net); + free_puffernet(net); free(weights); free_allocated(&env); close_client(client); } -void performance_test() { - long test_time = 10; - PacmanEnv env = {}; - allocate(&env); - c_reset(&env); - - long start = time(NULL); - int i = 0; - while (time(NULL) - start < test_time) { - env.actions[0] = rand() % 4; - c_step(&env); - i++; - } - long end = time(NULL); - printf("SPS: %ld\n", i / (end - start)); - free_allocated(&env); -} - int main() { - //performance_test(); demo(); return 0; } diff --git a/pufferlib/ocean/pacman/pacman.h b/ocean/pacman/pacman.h similarity index 98% rename from pufferlib/ocean/pacman/pacman.h rename to ocean/pacman/pacman.h index b00c7002c1..5ca0bf8f5e 100644 --- a/pufferlib/ocean/pacman/pacman.h +++ b/ocean/pacman/pacman.h @@ -32,6 +32,7 @@ struct Log { float episode_return; float episode_length; float score; + float perf; float n; }; @@ -118,9 +119,10 @@ typedef struct PacmanEnv { int chase_mode_length; float *observations; - int *actions; + float *actions; float *rewards; - char *terminals; + float *terminals; + int num_agents; Log log; int step_count; @@ -149,10 +151,12 @@ typedef struct PacmanEnv { bool player_caught; Ghost ghosts[NUM_GHOSTS]; + unsigned int rng; } PacmanEnv; void add_log(PacmanEnv *env) { env->log.score += env->score; + env->log.perf += (float)env->score / NUM_DOTS; env->log.episode_return += env->score; env->log.episode_length = env->step_count; env->log.n++; @@ -227,9 +231,9 @@ void init(PacmanEnv *env) { void allocate(PacmanEnv *env) { init(env); env->observations = (float *)calloc(OBSERVATIONS_COUNT, sizeof(float)); - env->actions = (int *)calloc(1, sizeof(int)); + env->actions = (float *)calloc(1, sizeof(float)); env->rewards = (float *)calloc(1, sizeof(float)); - env->terminals = (char *)calloc(1, sizeof(char)); + env->terminals = (float *)calloc(1, sizeof(float)); } void c_close(PacmanEnv *env) { @@ -327,7 +331,7 @@ static inline void reset_round(PacmanEnv *env) { } if (env->randomize_starting_position) { - int player_randomizer = rand() % NUM_DOTS; + int player_randomizer = rand_r(&env->rng) % NUM_DOTS; env->player_pos = env->possible_spawn_pos[player_randomizer]; } else { env->player_pos = env->player_spawn_pos; @@ -424,7 +428,7 @@ static inline int ghost_direction(PacmanEnv *env, Ghost *ghost) { } if (ghost->frightened) { - int random_index = rand() % option_count; + int random_index = rand_r(&env->rng) % option_count; return directions[random_index]; } diff --git a/ocean/pong/binding.c b/ocean/pong/binding.c new file mode 100644 index 0000000000..93eae1dd4c --- /dev/null +++ b/ocean/pong/binding.c @@ -0,0 +1,34 @@ +#include "pong.h" +#define OBS_SIZE 8 +#define NUM_ATNS 1 +#define ACT_SIZES {3} +#define OBS_TENSOR_T FloatTensor + +#define Env Pong +#include "vecenv.h" + +void my_init(Env* env, Dict* kwargs) { + env->num_agents = 1; + env->width = dict_get(kwargs, "width")->value; + env->height = dict_get(kwargs, "height")->value; + env->paddle_width = dict_get(kwargs, "paddle_width")->value; + env->paddle_height = dict_get(kwargs, "paddle_height")->value; + env->ball_width = dict_get(kwargs, "ball_width")->value; + env->ball_height = dict_get(kwargs, "ball_height")->value; + env->paddle_speed = dict_get(kwargs, "paddle_speed")->value; + env->ball_initial_speed_x = dict_get(kwargs, "ball_initial_speed_x")->value; + env->ball_initial_speed_y = dict_get(kwargs, "ball_initial_speed_y")->value; + env->ball_max_speed_y = dict_get(kwargs, "ball_max_speed_y")->value; + env->ball_speed_y_increment = dict_get(kwargs, "ball_speed_y_increment")->value; + env->max_score = dict_get(kwargs, "max_score")->value; + env->frameskip = dict_get(kwargs, "frameskip")->value; + env->continuous = dict_get(kwargs, "continuous")->value; + init(env); +} + +void my_log(Log* log, Dict* out) { + dict_set(out, "perf", log->perf); + dict_set(out, "score", log->score); + dict_set(out, "episode_return", log->episode_return); + dict_set(out, "episode_length", log->episode_length); +} diff --git a/ocean/pong/pong.c b/ocean/pong/pong.c new file mode 100644 index 0000000000..698b93efb7 --- /dev/null +++ b/ocean/pong/pong.c @@ -0,0 +1,66 @@ +#include +#include "pong.h" +#include "puffernet.h" + +void demo() { + // Weight count: encoder(32x8=256) + decoder(4x32=128) + 1x mingru(3x32x32=3072) = 3456 + Weights* weights = load_weights("resources/pong/pong_weights.bin"); + + int logit_sizes[1] = {3}; + PufferNet* net = make_puffernet(weights, 1, 8, 32, 1, logit_sizes, 1); + + Pong env = { + .width = 500, + .height = 640, + .paddle_width = 20, + .paddle_height = 70, + .ball_width = 32, + .ball_height = 32, + .paddle_speed = 8, + .ball_initial_speed_x = 10, + .ball_initial_speed_y = 1, + .ball_speed_y_increment = 3, + .ball_max_speed_y = 13, + .max_score = 21, + .frameskip = 1, + .continuous = 0, + }; + + allocate(&env); + c_reset(&env); + c_render(&env); + SetTargetFPS(60); + int frame = 0; + while (!WindowShouldClose()) { + // User can take control of the paddle + if (IsKeyDown(KEY_LEFT_SHIFT)) { + if(env.continuous) { + float move = GetMouseWheelMove(); + float clamped_wheel = fmaxf(-1.0f, fminf(1.0f, move)); + env.actions[0] = clamped_wheel; + printf("Mouse wheel move: %f\n", env.actions[0]); + } else { + env.actions[0] = 0.0; + if (IsKeyDown(KEY_UP) || IsKeyDown(KEY_W)) env.actions[0] = 1.0; + if (IsKeyDown(KEY_DOWN) || IsKeyDown(KEY_S)) env.actions[0] = 2.0; + } + } else if (frame == 0) { + forward_puffernet(net, env.observations, env.actions); + } + + frame = (frame + 1) % 8; + c_step(&env); + // Reset frame counter on score so policy fires immediately next + // iteration, matching training's early-return-from-frameskip behavior + if (env.rewards[0] != 0.0f) frame = 0; + c_render(&env); + } + free_puffernet(net); + free(weights); + free_allocated(&env); + close_client(env.client); +} + +int main() { + demo(); +} diff --git a/pufferlib/ocean/pong/pong.h b/ocean/pong/pong.h similarity index 97% rename from pufferlib/ocean/pong/pong.h rename to ocean/pong/pong.h index f4e718c2c0..ae6e3eb5a6 100644 --- a/pufferlib/ocean/pong/pong.h +++ b/ocean/pong/pong.h @@ -20,7 +20,8 @@ struct Pong { float* observations; float* actions; float* rewards; - unsigned char* terminals; + float* terminals; + int num_agents; float paddle_yl; float paddle_yr; float ball_x; @@ -49,6 +50,7 @@ struct Pong { int win; int frameskip; int continuous; + unsigned int rng; }; void init(Pong* env) { @@ -69,7 +71,7 @@ void allocate(Pong* env) { env->observations = (float*)calloc(8, sizeof(float)); env->actions = (float*)calloc(1, sizeof(float)); env->rewards = (float*)calloc(1, sizeof(float)); - env->terminals = (unsigned char*)calloc(1, sizeof(unsigned char)); + env->terminals = (float*)calloc(1, sizeof(float)); } void free_allocated(Pong* env) { @@ -108,7 +110,7 @@ void reset_round(Pong* env) { env->ball_x = env->width / 5; env->ball_y = env->height / 2 - env->ball_height / 2; env->ball_vx = env->ball_initial_speed_x; - env->ball_vy = (rand() % 2 - 1) * env->ball_initial_speed_y; + env->ball_vy = (rand_r(&env->rng) % 2 - 1) * env->ball_initial_speed_y; env->tick = 0; env->n_bounces = 0; } @@ -181,6 +183,7 @@ void c_step(Pong* env) { return; } else { reset_round(env); + compute_observations(env); return; } } @@ -193,7 +196,6 @@ void c_step(Pong* env) { // collision with paddle env->ball_vx = -env->ball_vx; env->n_bounces += 1; - env->rewards[0] = 0.1; // agent bounced the ball // ball speed change env->ball_vy += env->ball_speed_y_increment * env->paddle_dir; env->ball_vy = fminf(fmaxf(env->ball_vy, -env->ball_max_speed_y), env->ball_max_speed_y); @@ -212,6 +214,7 @@ void c_step(Pong* env) { return; } else { reset_round(env); + compute_observations(env); return; } } diff --git a/ocean/rware/binding.c b/ocean/rware/binding.c new file mode 100644 index 0000000000..5e48c9ed51 --- /dev/null +++ b/ocean/rware/binding.c @@ -0,0 +1,26 @@ +#include "rware.h" +#define OBS_SIZE 27 +#define NUM_ATNS 1 +#define ACT_SIZES {5} +#define OBS_TENSOR_T FloatTensor + +#define Env CRware +#include "vecenv.h" + +void my_init(Env* env, Dict* kwargs) { + env->width = dict_get(kwargs, "width")->value; + env->height = dict_get(kwargs, "height")->value; + env->map_choice = dict_get(kwargs, "map_choice")->value; + env->num_agents = dict_get(kwargs, "num_agents")->value; + env->num_requested_shelves = dict_get(kwargs, "num_requested_shelves")->value; + env->grid_square_size = dict_get(kwargs, "grid_square_size")->value; + env->human_agent_idx = dict_get(kwargs, "human_agent_idx")->value; + init(env); +} + +void my_log(Log* log, Dict* out) { + dict_set(out, "perf", log->perf); + dict_set(out, "score", log->score); + dict_set(out, "episode_return", log->episode_return); + dict_set(out, "episode_length", log->episode_length); +} diff --git a/pufferlib/ocean/rware/rware.c b/ocean/rware/rware.c similarity index 99% rename from pufferlib/ocean/rware/rware.c rename to ocean/rware/rware.c index 4afa285083..94f23a4c03 100644 --- a/pufferlib/ocean/rware/rware.c +++ b/ocean/rware/rware.c @@ -32,7 +32,7 @@ void demo(int map_choice) { .human_agent_idx = 0, .reward_type = 2 }; - Weights* weights = load_weights("resources/rware/rware_weights.bin", 136454); + Weights* weights = load_weights("resources/rware/rware_weights.bin"); int logit_sizes[1] = {5}; LinearLSTM* net = make_linearlstm(weights, env.num_agents, 27, logit_sizes, 1); diff --git a/pufferlib/ocean/rware/rware.h b/ocean/rware/rware.h similarity index 92% rename from pufferlib/ocean/rware/rware.h rename to ocean/rware/rware.h index 20d5728c28..8fb59a66c6 100644 --- a/pufferlib/ocean/rware/rware.h +++ b/ocean/rware/rware.h @@ -151,9 +151,9 @@ struct MovementGraph { struct CRware { Client* client; float* observations; - int* actions; + float* actions; float* rewards; - unsigned char* terminals; + float* terminals; Log* agent_logs; Log log; float* scores; @@ -172,6 +172,7 @@ struct CRware { int grid_square_size; int* original_shelve_locations; MovementGraph* movement_graph; + unsigned int rng; }; void add_log(CRware* env, Log* agent_log) { @@ -197,7 +198,7 @@ void place_agent(CRware* env, int agent_idx) { int found_valid_position = 0; while (!found_valid_position) { - int random_pos = rand() % map_size; + int random_pos = rand_r(&env->rng) % map_size; // Skip if position is not empty if (env->warehouse_states[random_pos] != EMPTY) { @@ -213,7 +214,7 @@ void place_agent(CRware* env, int agent_idx) { // Position is valid, place the agent env->old_agent_locations[agent_idx] = random_pos; env->agent_locations[agent_idx] = random_pos; - env->agent_directions[agent_idx] = rand() % 4; + env->agent_directions[agent_idx] = rand_r(&env->rng) % 4; env->agent_states[agent_idx] = 0; found_valid_position = 1; } @@ -232,7 +233,7 @@ int request_new_shelf(CRware* env) { total_shelves = 144; shelf_locations = medium_shelf_locations; } - int random_index = rand() % total_shelves; + int random_index = rand_r(&env->rng) % total_shelves; int shelf_location = shelf_locations[random_index]; if (env->warehouse_states[shelf_location] == SHELF ) { env->warehouse_states[shelf_location] = REQUESTED_SHELF; @@ -296,9 +297,9 @@ void init(CRware* env) { void allocate(CRware* env) { init(env); env->observations = (float*)calloc(env->num_agents*(SELF_OBS+VISION_OBS), sizeof(float)); - env->actions = (int*)calloc(env->num_agents, sizeof(int)); + env->actions = (float*)calloc(env->num_agents, sizeof(float)); env->rewards = (float*)calloc(env->num_agents, sizeof(float)); - env->terminals = (unsigned char*)calloc(env->num_agents, sizeof(unsigned char)); + env->terminals = (float*)calloc(env->num_agents, sizeof(float)); } void c_close(CRware* env) { @@ -529,26 +530,14 @@ void calculate_weights(CRware* env) { } } -void update_movement_graph(CRware* env, int agent_idx) { +void reset_movement_graph(CRware* env) { MovementGraph* graph = env->movement_graph; - int new_position = get_new_position(env, agent_idx); - if (new_position == -1) { - return; - } - graph->target_positions[agent_idx] = new_position; - - // reset cycle and weights for (int i = 0; i < env->num_agents; i++) { + graph->target_positions[i] = -1; graph->cycle_ids[i] = -1; graph->weights[i] = 0; } graph->num_cycles = 0; - - // detect cycles with Floyd algorithm - detect_cycles(env); - - // calculate weights for tree - calculate_weights(env); } void move_agent(CRware* env, int agent_idx) { @@ -585,7 +574,6 @@ void move_agent(CRware* env, int agent_idx) { env->warehouse_states[new_position] = SHELF; } env->agent_locations[agent_idx] = new_position; - env->movement_graph->target_positions[agent_idx] = -1; } void pickup_shelf(CRware* env, int agent_idx) { @@ -620,10 +608,24 @@ void pickup_shelf(CRware* env, int agent_idx) { env->rewards[agent_idx] = 0.5; env->agent_logs[agent_idx].episode_return += 0.5; env->agent_logs[agent_idx].score = 1.0; + // Try random selection first, then fall back to linear scan to avoid infinite loop + // when all shelves are currently being carried (warehouse_states == EMPTY). + int total_shelves; + const int* shelf_locations; + if (env->map_choice == 1) { total_shelves = 32; shelf_locations = tiny_shelf_locations; } + else if (env->map_choice == 2) { total_shelves = 80; shelf_locations = small_shelf_locations; } + else { total_shelves = 144; shelf_locations = medium_shelf_locations; } int shelf_count = 0; - while (shelf_count < 1) { + for (int attempt = 0; attempt < total_shelves && !shelf_count; attempt++) { shelf_count += request_new_shelf(env); } + if (shelf_count) return; + for (int i = 0; i < total_shelves && !shelf_count; i++) { + if (env->warehouse_states[shelf_locations[i]] == SHELF) { + env->warehouse_states[shelf_locations[i]] = REQUESTED_SHELF; + shelf_count = 1; + } + } } } @@ -652,7 +654,7 @@ void process_cycle_movements(CRware* env, MovementGraph* graph) { if (!can_move_cycle) continue; for (int i = 0; i < env->num_agents; i++) { if (graph->cycle_ids[i] != cycle) continue; - if (env->actions[i] != FORWARD) continue; + if ((int)env->actions[i] != FORWARD) continue; move_agent(env, i); } } @@ -669,7 +671,7 @@ void process_tree_movements(CRware* env, MovementGraph* graph) { for (int weight = max_weight; weight > 0; weight--) { for (int i = 0; i < env->num_agents; i++) { if (graph->cycle_ids[i] != -1 || graph->weights[i] != weight) continue; - if (env->actions[i] != FORWARD) continue; + if ((int)env->actions[i] != FORWARD) continue; int new_pos = get_new_position(env, i); if (new_pos == -1) continue; @@ -684,12 +686,17 @@ void process_tree_movements(CRware* env, MovementGraph* graph) { void c_step(CRware* env) { memset(env->rewards, 0, env->num_agents * sizeof(float)); MovementGraph* graph = env->movement_graph; + + // Reset movement graph so stale targets from previous steps don't + // create phantom cycles in Floyd's detection or the weight propagation loop. + reset_movement_graph(env); + + int is_movement = 0; for (int i = 0; i < env->num_agents; i++) { env->old_agent_locations[i] = env->agent_locations[i]; env->agent_logs[i].episode_length += 1; - int action = env->actions[i]; - - // Handle direction changes and non-movement actions + int action = (int)env->actions[i]; + if (action != NOOP && action != TOGGLE_LOAD) { env->agent_directions[i] = get_direction(env, action, i); } @@ -697,17 +704,20 @@ void c_step(CRware* env) { pickup_shelf(env, i); } if (action == FORWARD) { - update_movement_graph(env, i); + int new_pos = get_new_position(env, i); + if (new_pos != -1) { + graph->target_positions[i] = new_pos; + is_movement++; + } } } - int is_movement=0; - for(int i=0; inum_agents; i++) { - if (env->actions[i] == FORWARD) is_movement++; - } - if (is_movement>=1) { - // Process movements in cycles first + + if (is_movement >= 1) { + // Run cycle detection and weight calculation once with the complete graph. + // Per-agent incremental updates caused stale intermediate state. + detect_cycles(env); + calculate_weights(env); process_cycle_movements(env, graph); - // process tree movements process_tree_movements(env, graph); } diff --git a/ocean/scape/binding.c b/ocean/scape/binding.c new file mode 100644 index 0000000000..8687ddb49d --- /dev/null +++ b/ocean/scape/binding.c @@ -0,0 +1,23 @@ +#include "scape.h" +#define OBS_SIZE 28 +#define NUM_ATNS 2 +#define ACT_SIZES {9, 5} +#define OBS_TENSOR_T FloatTensor + +#define Env Scape +#include "vecenv.h" + +void my_init(Env* env, Dict* kwargs) { + env->width = dict_get(kwargs, "width")->value; + env->height = dict_get(kwargs, "height")->value; + env->num_agents = 8; + env->num_goals = 4; + init(env); +} + +void my_log(Log* log, Dict* out) { + dict_set(out, "perf", log->perf); + dict_set(out, "score", log->score); + dict_set(out, "episode_return", log->episode_return); + dict_set(out, "episode_length", log->episode_length); +} diff --git a/ocean/scape/scape.c b/ocean/scape/scape.c new file mode 100644 index 0000000000..59bae1c32d --- /dev/null +++ b/ocean/scape/scape.c @@ -0,0 +1,49 @@ +/* Pure C demo file for Scape. Build it with: + * bash scripts/build_ocean.sh scape local (debug) + * bash scripts/build_ocean.sh scape fast + * We suggest building and debugging your env in pure C first. You + * get faster builds and better error messages + */ +#include "scape.h" + +int main() { + int num_agents = 1; + int num_obs = 1; + + Scape env = { + .width = 1080, + .height = 720, + .num_agents = 1 + }; + init(&env); + + // Allocate these manually since they aren't being passed from Python + env.observations = calloc(env.num_agents*num_obs, sizeof(float)); + env.actions = calloc(env.num_agents, sizeof(double)); + env.rewards = calloc(env.num_agents, sizeof(float)); + env.terminals = calloc(env.num_agents, sizeof(double)); + + // Always call reset and render first + c_reset(&env); + c_render(&env); + + // while(True) will break web builds + while (!WindowShouldClose()) { + for (int i=0; i +#include +#include +#include +#include "raylib.h" +#include "rlgl.h" + +static float offset_x = -6.5f; +static float offset_z = 12.5f; + +static Vector3 scene_pos = (Vector3){-6.5, -2.5, 60.5}; + +// Required struct. Only use floats! +typedef struct { + float perf; // Recommended 0-1 normalized single real number perf metric + float score; // Recommended unnormalized single real number perf metric + float episode_return; // Recommended metric: sum of agent rewards over episode + float episode_length; // Recommended metric: number of steps of agent episode + // Any extra fields you add here may be exported to Python in binding.c + float n; // Required as the last field +} Log; + +typedef struct { + Texture2D puffer; + Camera3D camera; + Model scene; + Model player; +} Client; + +typedef struct { + float x; + float y; + float dest_x; + float dest_y; + int size; + int height; + Color color; +} Entity; + +typedef struct { + float x; + float y; +} Goal; + +// Required that you have some struct for your env +// Recommended that you name it the same as the env file +typedef struct { + Log log; // Required field. Env binding code uses this to aggregate logs + Client* client; + Entity* entities; + Goal* goals; + float* observations; // Required. You can use any obs type, but make sure it matches in Python! + double* actions; // Required. double* for discrete/multidiscrete, float* for box + float* rewards; // Required + float* terminals; // Required. We don't yet have truncations as standard yet + int width; + int height; + int num_agents; + int num_npcs; +} Scape; + +Vector3 to_world(Vector2 pos) { + return (Vector3){ + .x = pos.x - 6.5f, + .y = -2.5f, + .z = pos.y + 12.5f + }; +} + +Vector2 from_world(Vector3 pos) { + return (Vector2){ + .x = pos.x + 6.5f, + .y = pos.z - 12.5f + }; +} + +float clampf(float x, float min, float max) { + if (x < min) return min; + if (x > max) return max; + return x; +} + +void move_agent(Scape* env) { + float dx = env->entities[0].dest_x - env->entities[0].x; + float dy = env->entities[0].dest_y - env->entities[0].y; + env->entities[0].x += clampf(dx, -2, 2); + env->entities[0].y += clampf(dy, -2, 2); +} + +bool overlaps(Entity* a, Entity* b) { + return a->x < b->x + b->size && b->x < a->x + a->size + && a->y > b->y - b->size && b->y > a->y - a->size; +} + +void move_npc(Scape* env, int idx) { + Entity* player = &env->entities[0]; + Entity* npc = &env->entities[idx]; + float x = npc->x; + float y = npc->y; + + bool collide_x = false; + bool collide_y = false; + + int dst_x = npc->x - clampf(x - npc->dest_x, -1, 1); + int dst_y = npc->y - clampf(y - npc->dest_y, -1, 1); + + npc->x = dst_x; + npc->y = dst_y; + if (overlaps(npc, player)) { + collide_y = true; + } + npc->x = x; + npc->y = y; + + npc->y = dst_y; + for (int i=1; inum_npcs + env->num_agents; i++) { + Entity* other = &env->entities[i]; + if (npc == other) { + continue; + } + if (overlaps(npc, other)) { + env->entities[idx].y = y; + collide_y = true; + break; + } + } + npc->y = y; + + npc->x = dst_x; + for (int i=1; inum_npcs + env->num_agents; i++) { + Entity* other = &env->entities[i]; + if (npc == other) { + continue; + } + if (overlaps(npc, other)) { + env->entities[idx].x = x; + collide_x = true; + break; + } + } + npc->x = x; + + if (!collide_x) { + npc->x = dst_x; + } + if (!collide_y) { + npc->y = dst_y; + } +} + +/* Recommended to have an init function of some kind if you allocate + * extra memory. This should be freed by c_close. Don't forget to call + * this in binding.c! + */ +void init(Scape* env) { + env->num_agents = 1; + env->num_npcs = 6; + env->entities = calloc(env->num_agents + env->num_npcs, sizeof(Entity)); +} + +/* Recommended to have an observation function of some kind because + * you need to compute agent observations in both reset and in step. + * If using float obs, try to normalize to roughly -1 to 1 by dividing + * by an appropriate constant. + */ +void compute_observations(Scape* env) { +} + +// Required function +void c_reset(Scape* env) { + env->entities[0].x = 28; + env->entities[0].dest_x = 28; + env->entities[0].y = 17; + env->entities[0].dest_y = 17; + env->entities[0].size = 1; + env->entities[0].height = 2; + env->entities[0].color = WHITE; + + // South pillar + env->entities[1].x = 21; + env->entities[1].dest_x = 21; + env->entities[1].y = 37; + env->entities[1].dest_y = 37; + env->entities[1].size = 3; + env->entities[1].height = 3; + env->entities[1].color = YELLOW; + + // West pillar + env->entities[2].x = 11; + env->entities[2].dest_x = 11; + env->entities[2].y = 23; + env->entities[2].dest_y = 23; + env->entities[2].size = 3; + env->entities[2].height = 3; + env->entities[2].color = YELLOW; + + // North pillar + env->entities[3].x = 28; + env->entities[3].dest_x = 28; + env->entities[3].y = 21; + env->entities[3].dest_y = 21; + env->entities[3].size = 3; + env->entities[3].height = 3; + env->entities[3].color = YELLOW; + + // Test enemy + env->entities[4].x = 12; + env->entities[4].y = 19; + env->entities[4].size = 4; + env->entities[4].height = 2; + env->entities[4].color = RED; + + env->entities[5].x = 26; + env->entities[5].y = 42; + env->entities[5].size = 4; + env->entities[5].height = 2; + env->entities[5].color = BLUE; + + env->entities[6].x = 14; + env->entities[6].y = 25; + env->entities[6].size = 3; + env->entities[6].height = 2; + env->entities[6].color = GREEN; + + compute_observations(env); +} + +// Required function +void c_step(Scape* env) { + move_agent(env); + + // Set npc target to player pos + for (int i=4; inum_agents + env->num_npcs; i++) { + Entity* npc = &env->entities[i]; + npc->dest_x = env->entities[0].x; + npc->dest_y = env->entities[0].y; + } + + for (int i=env->num_agents; inum_agents + env->num_npcs; i++) { + move_npc(env, i); + } + compute_observations(env); +} + +void handle_camera_controls(Client* client) { + static Vector2 prev_mouse_pos = {0}; + static bool is_dragging = false; + float camera_move_speed = 0.5f; + + // Handle mouse drag for camera movement + if (IsMouseButtonPressed(MOUSE_BUTTON_MIDDLE)) { + prev_mouse_pos = GetMousePosition(); + is_dragging = true; + } + + if (IsMouseButtonReleased(MOUSE_BUTTON_MIDDLE)) { + is_dragging = false; + } + + if (is_dragging) { + Vector2 current_mouse_pos = GetMousePosition(); + Vector2 delta = { + -(current_mouse_pos.x - prev_mouse_pos.x) * camera_move_speed, + (current_mouse_pos.y - prev_mouse_pos.y) * camera_move_speed + }; + + // Apply 45-degree rotation to the movement + // For a -45 degree rotation (clockwise) + float cos45 = -0.7071f; // cos(-45°) + float sin45 = 0.7071f; // sin(-45°) + Vector2 rotated_delta = { + delta.x * cos45 - delta.y * sin45, + delta.x * sin45 + delta.y * cos45 + }; + + // Update camera position (only X and Y) + client->camera.position.z += rotated_delta.x; + client->camera.position.x += rotated_delta.y; + + // Update camera target (only X and Y) + client->camera.target.z += rotated_delta.x; + client->camera.target.x += rotated_delta.y; + + prev_mouse_pos = current_mouse_pos; + } + + // Handle mouse wheel for zoom + float wheel = GetMouseWheelMove(); + if (wheel != 0) { + float zoom_factor = 1.0f - (wheel * 0.1f); + // Calculate the current direction vector from target to position + Vector3 direction = { + client->camera.position.x - client->camera.target.x, + client->camera.position.y - client->camera.target.y, + client->camera.position.z - client->camera.target.z + }; + + // Scale the direction vector by the zoom factor + direction.x *= zoom_factor; + direction.y *= zoom_factor; + direction.z *= zoom_factor; + + // Update the camera position based on the scaled direction + client->camera.position.x = client->camera.target.x + direction.x; + client->camera.position.y = client->camera.target.y + direction.y; + client->camera.position.z = client->camera.target.z + direction.z; + } +} + +Vector2 get_hovered_tile(Camera3D* camera) { + Ray ray = GetMouseRay(GetMousePosition(), *camera); + float plane_y = -0.5f; + float t = (plane_y - ray.position.y) / ray.direction.y; + Vector3 floor_pos = { + .x = ray.position.x + ray.direction.x*t, + .y = plane_y, + .z = ray.position.z + ray.direction.z*t + }; + return (Vector2){ + .x = floorf(floor_pos.x + 0.5f), + .y = floorf(floor_pos.z + 0.5f) + }; +} + +Vector3 tile_to_mesh_pos(float x, float y) { + return (Vector3){ + .x = x, + .y = -0.49f, + .z = y + }; +} + +void draw_tile(Client* client, Vector2 hovered_tile) { + Vector3 corner = tile_to_mesh_pos(hovered_tile.x, hovered_tile.y); + + Vector3 w00 = (Vector3){corner.x - 0.5, corner.y, corner.z + 0.5}; + Vector3 w01 = (Vector3){corner.x + 0.5, corner.y, corner.z + 0.5}; + Vector3 w10 = (Vector3){corner.x + 0.5, corner.y, corner.z - 0.5}; + Vector3 w11 = (Vector3){corner.x - 0.5, corner.y, corner.z - 0.5}; + + Vector2 s00 = GetWorldToScreen(w00, client->camera); + Vector2 s01 = GetWorldToScreen(w01, client->camera); + Vector2 s10 = GetWorldToScreen(w10, client->camera); + Vector2 s11 = GetWorldToScreen(w11, client->camera); + + DrawLineEx(s00, s01, 2.0f, RED); + DrawLineEx(s00, s11, 2.0f, RED); + DrawLineEx(s10, s11, 2.0f, RED); + DrawLineEx(s10, s01, 2.0f, RED); +} + + +// Required function. Should handle creating the client on first call +void c_render(Scape* env) { + Client* client = env->client; + if (client == NULL) { + InitWindow(env->width, env->height, "PufferLib Scape"); + SetTargetFPS(60); + + client = (Client*)calloc(1, sizeof(Client)); + env->client = client; + + // Don't do this before calling InitWindow + client->puffer = LoadTexture("resources/shared/puffers_128.png"); + + Camera3D camera = { 0 }; + camera.position = (Vector3){ 28.0f, 10.0f, 12.0f }; + camera.target = (Vector3){ 28.0f, -0.5, 17.0f }; + //camera.position = (Vector3){ 25.0f, 20.0f, 0.0f }; + //camera.target = (Vector3){ 25.0f, 0.0, 28.0f }; + camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; + camera.fovy = 70.0f; + camera.projection = CAMERA_PERSPECTIVE; + client->camera = camera; + client->scene = LoadModel("resources/scape/inferno_compress.glb"); + client->player = LoadModel("resources/scape/player_twisted_bow_decompressed.glb"); + } + + handle_camera_controls(client); + + if (IsKeyDown(KEY_RIGHT)) offset_x += 0.1f; + if (IsKeyDown(KEY_LEFT)) offset_x -= 0.1f; + if (IsKeyDown(KEY_UP)) offset_z -= 0.1f; + if (IsKeyDown(KEY_DOWN)) offset_z += 0.1f; + + // Standard across our envs so exiting is always the same + if (IsKeyDown(KEY_ESCAPE)) { + exit(0); + } + + BeginDrawing(); + ClearBackground((Color){6, 24, 24, 255}); + + BeginMode3D(client->camera); + Vector2 origin = (Vector2){0.0f, 57.0f}; + //DrawModel(env->client->scene, to_world(origin), 1.0f, WHITE); + if (IsKeyPressed(KEY_W)) scene_pos.x += 1.0f; + if (IsKeyPressed(KEY_S)) scene_pos.x -= 1.0f; + if (IsKeyPressed(KEY_A)) scene_pos.z -= 1.0f; + if (IsKeyPressed(KEY_D)) scene_pos.z += 1.0f; + + DrawModel(env->client->scene, (Vector3)scene_pos, 1.0f, WHITE); + /* + rlDisableBackfaceCulling(); + DrawModelEx(env->client->scene, + (Vector3){ -6.0f, -2.5f, 12.0f }, + (Vector3){ 1.0f, 0.0f, 1.0f }, + 0.0f, + (Vector3){ 1.0f, 1.0f, -1.0f }, + WHITE); + rlEnableBackfaceCulling(); + */ + //DrawModel(env->client->player, (Vector3){ 32.0f, 10.0f, -26.0f }, 1.0f, WHITE); + + + //Vector2 spawn = (Vector2){28.0f, 17.0f}; + //Vector3 player_pos = to_world(spawn); + Vector3 player_pos = (Vector3){env->entities[0].x, 0, env->entities[0].y}; + DrawCube(player_pos, 1.0f, 1.0f, 1.0f, RED); + + for (int i=0; inum_agents + env->num_npcs; i++) { + Entity* entity = &env->entities[i]; + float entity_x = entity->x + entity->size/2.0f - 0.5f; + float entity_y = entity->y - entity->size/2.0f + 0.5f; + Vector3 entity_pos = (Vector3){entity_x, 0, entity_y}; + DrawCube(entity_pos, entity->size, 2*entity->height, entity->size, entity->color); + } + + // Draw axes + DrawLine3D((Vector3){0, 0, 0}, (Vector3){50, 0, 0}, RED); + DrawLine3D((Vector3){0, 0, 0}, (Vector3){0, 0, 50}, BLUE); + DrawLine3D((Vector3){0, 0, 0}, (Vector3){0, 50, 0}, GREEN); + + EndMode3D(); + + Vector2 hovered_tile = get_hovered_tile(&client->camera); + draw_tile(client, hovered_tile); + + if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) { + env->entities[0].dest_x = hovered_tile.x; + env->entities[0].dest_y = hovered_tile.y; + } + + DrawText(TextFormat("scene_pos.x: %f scene_pos.z: %f", scene_pos.x, scene_pos.z), 10, 30, 20, RAYWHITE); + DrawText(TextFormat("offset_x: %f offset_z: %f", offset_x, offset_z), 10, 10, 20, RAYWHITE); + + EndDrawing(); +} + +// Required function. Should clean up anything you allocated +// Do not free env->observations, actions, rewards, terminals +void c_close(Scape* env) { + free(env->entities); + if (env->client != NULL) { + Client* client = env->client; + UnloadTexture(client->puffer); + CloseWindow(); + free(client); + } +} diff --git a/pufferlib/ocean/shared_pool/binding.c b/ocean/shared_pool/binding.c similarity index 100% rename from pufferlib/ocean/shared_pool/binding.c rename to ocean/shared_pool/binding.c diff --git a/pufferlib/ocean/shared_pool/grid.h b/ocean/shared_pool/grid.h similarity index 100% rename from pufferlib/ocean/shared_pool/grid.h rename to ocean/shared_pool/grid.h diff --git a/pufferlib/ocean/shared_pool/shared_pool.c b/ocean/shared_pool/shared_pool.c similarity index 99% rename from pufferlib/ocean/shared_pool/shared_pool.c rename to ocean/shared_pool/shared_pool.c index fc85e4ca59..f6c5cae060 100644 --- a/pufferlib/ocean/shared_pool/shared_pool.c +++ b/ocean/shared_pool/shared_pool.c @@ -18,7 +18,7 @@ int main() { c_reset(&env); c_render(&env); - Weights* weights = load_weights("resources/cpr/cpr_weights.bin", 139270); + Weights* weights = load_weights("resources/cpr/cpr_weights.bin"); int logit_sizes[] = {5}; LinearLSTM* net = make_linearlstm(weights, env.num_agents, 49, logit_sizes, 1); diff --git a/pufferlib/ocean/shared_pool/shared_pool.h b/ocean/shared_pool/shared_pool.h similarity index 100% rename from pufferlib/ocean/shared_pool/shared_pool.h rename to ocean/shared_pool/shared_pool.h diff --git a/ocean/slimevolley/binding.c b/ocean/slimevolley/binding.c new file mode 100644 index 0000000000..2446085b1b --- /dev/null +++ b/ocean/slimevolley/binding.c @@ -0,0 +1,20 @@ +#include "slimevolley.h" +#define OBS_SIZE 12 +#define NUM_ATNS 3 +#define ACT_SIZES {2, 2, 2} +#define OBS_TENSOR_T FloatTensor + +#define Env SlimeVolley +#include "vecenv.h" + +void my_init(Env* env, Dict* kwargs) { + env->num_agents = dict_get(kwargs, "num_agents")->value; + init(env); +} + +void my_log(Log* log, Dict* out) { + dict_set(out, "perf", log->perf); + dict_set(out, "score", log->score); + dict_set(out, "episode_return", log->episode_return); + dict_set(out, "episode_length", log->episode_length); +} diff --git a/pufferlib/ocean/slimevolley/slimevolley.c b/ocean/slimevolley/slimevolley.c similarity index 76% rename from pufferlib/ocean/slimevolley/slimevolley.c rename to ocean/slimevolley/slimevolley.c index cd1260c268..5f8def79aa 100644 --- a/pufferlib/ocean/slimevolley/slimevolley.c +++ b/ocean/slimevolley/slimevolley.c @@ -5,6 +5,7 @@ * get faster builds and better error messages */ #include "slimevolley.h" +#include "puffernet.h" #include @@ -19,13 +20,8 @@ void abranti_simple_policy(float* obs, float* action) { action[2] = 1.0f; // always jump } -void random_policy(float* obs, float* action) { - action[0] = 2*randf() - 1; - action[1] = 2*randf() - 1; - action[2] = 2*randf() - 1; -} -int main() { +void demo() { int num_obs = 12; int num_actions = 3; SlimeVolley env = {.num_agents = 1}; @@ -33,7 +29,12 @@ int main() { env.observations = (float*)calloc(env.num_agents*num_obs, sizeof(float)); env.actions = (float*)calloc(num_actions*env.num_agents, sizeof(float)); env.rewards = (float*)calloc(env.num_agents, sizeof(float)); - env.terminals = (unsigned char*)calloc(env.num_agents, sizeof(unsigned char)); + env.terminals = (float*)calloc(env.num_agents, sizeof(float)); + + Weights* weights = load_weights("resources/slimevolley/slimevolley_weights.bin"); + int logit_sizes[3] = {2, 2, 2}; + PufferNet* net = make_puffernet(weights, 1, num_obs, 128, 3, logit_sizes, 3); + // Always call reset and render first c_reset(&env); c_render(&env); @@ -41,13 +42,13 @@ int main() { fprintf(stderr, "num agents: %d\n", env.num_agents); while (!WindowShouldClose()) { - env.actions[0] = 0.0; - env.actions[1] = 0.0; - env.actions[2] = 0.0; + env.actions[0] = 0.0f; + env.actions[1] = 0.0f; + env.actions[2] = 0.0f; if (IsKeyDown(KEY_LEFT_SHIFT)) { - if (IsKeyDown(KEY_RIGHT) || IsKeyDown(KEY_D)) env.actions[0] = 1.0; - if (IsKeyDown(KEY_LEFT) || IsKeyDown(KEY_A)) env.actions[1] = 1.0; - if (IsKeyDown(KEY_UP) || IsKeyDown(KEY_W) || IsKeyDown(KEY_SPACE)) env.actions[2] = 1.0; + if (IsKeyDown(KEY_RIGHT) || IsKeyDown(KEY_D)) env.actions[0] = 1.0f; + if (IsKeyDown(KEY_LEFT) || IsKeyDown(KEY_A)) env.actions[1] = 1.0f; + if (IsKeyDown(KEY_UP) || IsKeyDown(KEY_W) || IsKeyDown(KEY_SPACE)) env.actions[2] = 1.0f; } else { abranti_simple_policy(env.observations, env.actions); } @@ -55,6 +56,9 @@ int main() { c_render(&env); } + free_puffernet(net); + free(weights); + // Try to clean up after yourself free(env.observations); free(env.actions); @@ -62,3 +66,8 @@ int main() { free(env.terminals); c_close(&env); } + +int main() { + demo(); + return 0; +} diff --git a/pufferlib/ocean/slimevolley/slimevolley.h b/ocean/slimevolley/slimevolley.h similarity index 97% rename from pufferlib/ocean/slimevolley/slimevolley.h rename to ocean/slimevolley/slimevolley.h index e424ad2835..859d523f9e 100644 --- a/pufferlib/ocean/slimevolley/slimevolley.h +++ b/ocean/slimevolley/slimevolley.h @@ -67,10 +67,6 @@ float to_y_pixel(float y){ return WINDOW_HEIGHT - y * FACTOR; } -float randf() { - return (float)rand() / (float)RAND_MAX; -} - // OBJECTS typedef struct { float x; @@ -389,16 +385,20 @@ typedef struct { Ball* ball; int delay_frames; // frames to wait before starting float* observations; // Required. You can use any obs type, but make sure it matches in Python! - float* actions; // Required. int* for discrete/multidiscrete, float* for box + float* actions; // Required. float* rewards; // Required - unsigned char* terminals; // Required. We don't yet have truncations as standard yet + float* terminals; // Required int num_agents; // Number of agents being trained. Either 1 or 2. If 1, the first agent is trained and the second is a bot. float* bot_observations; // Optional, for bot control float* bot_actions; // Optional, for bot control int tick; Texture2D puffers; + unsigned int rng; } SlimeVolley; +float randf(SlimeVolley* env) { + return (float)rand_r(&env->rng) / (float)RAND_MAX; +} /* Recommended to have an init function of some kind if you allocate * extra memory. This should be freed by c_close. Don't forget to call @@ -423,8 +423,8 @@ void init(SlimeVolley* env) { void c_reset(SlimeVolley* env) { env->tick = 0; env->delay_frames = INIT_DELAY_FRAMES; - float ball_vx = 40.0f*randf() - 20.0f; - float ball_vy = 15.0f*randf() + 10.0f; + float ball_vx = 40.0f*randf(env) - 20.0f; + float ball_vy = 15.0f*randf(env) + 10.0f; *env->ball = (Ball){ .x = 0, .y = REF_W/4, @@ -470,8 +470,8 @@ float clip(float val, float min, float max) { } void new_match(SlimeVolley* env) { - float ball_vx = 40.0f*randf() - 20.0f; - float ball_vy = 15.0f*randf() + 10.0f; + float ball_vx = 40.0f*randf(env) - 20.0f; + float ball_vy = 15.0f*randf(env) + 10.0f; *env->ball = (Ball){ .x = 0, .y = REF_W/4, diff --git a/ocean/snake/binding.c b/ocean/snake/binding.c new file mode 100644 index 0000000000..8a63e6e39b --- /dev/null +++ b/ocean/snake/binding.c @@ -0,0 +1,32 @@ +#include "snake.h" +#define OBS_SIZE 121 +#define NUM_ATNS 1 +#define ACT_SIZES {4} +#define OBS_TYPE CHAR +#define ACT_TYPE DOUBLE + +#define Env CSnake +#include "vecenv.h" + +void my_init(Env* env, Dict* kwargs) { + env->width = dict_get(kwargs, "width")->value; + env->height = dict_get(kwargs, "height")->value; + env->num_agents = dict_get(kwargs, "num_agents")->value; + env->vision = dict_get(kwargs, "vision")->value; + env->leave_corpse_on_death = dict_get(kwargs, "leave_corpse_on_death")->value; + env->food = dict_get(kwargs, "num_food")->value; + env->reward_food = dict_get(kwargs, "reward_food")->value; + env->reward_corpse = dict_get(kwargs, "reward_corpse")->value; + env->reward_death = dict_get(kwargs, "reward_death")->value; + env->max_snake_length = dict_get(kwargs, "max_snake_length")->value; + env->cell_size = dict_get(kwargs, "cell_size")->value; + init_csnake(env); +} + +void my_log(Log* log, Dict* out) { + dict_set(out, "perf", log->perf); + dict_set(out, "score", log->score); + dict_set(out, "episode_return", log->episode_return); + dict_set(out, "episode_length", log->episode_length); + dict_set(out, "n", log->n); +} diff --git a/pufferlib/ocean/snake/snake.c b/ocean/snake/snake.c similarity index 75% rename from pufferlib/ocean/snake/snake.c rename to ocean/snake/snake.c index 1e2112c842..9bd62f20da 100644 --- a/pufferlib/ocean/snake/snake.c +++ b/ocean/snake/snake.c @@ -4,7 +4,7 @@ int demo() { CSnake env = { - .num_snakes = 256, + .num_agents = 256, .width = 640, .height = 360, .max_snake_length = 200, @@ -18,9 +18,9 @@ int demo() { allocate_csnake(&env); c_reset(&env); - Weights* weights = load_weights("resources/snake/snake_weights.bin", 256773); + Weights* weights = load_weights("resources/snake/snake_weights.bin"); int logit_sizes[] = {4}; - LinearLSTM* net = make_linearlstm(weights, env.num_snakes, 968, logit_sizes, 1); + LinearLSTM* net = make_linearlstm(weights, env.num_agents, 968, logit_sizes, 1); env.client = make_client(2, env.width, env.height); while (!WindowShouldClose()) { @@ -31,12 +31,17 @@ int demo() { if (IsKeyDown(KEY_LEFT) || IsKeyDown(KEY_A)) env.actions[0] = 2; if (IsKeyDown(KEY_RIGHT) || IsKeyDown(KEY_D)) env.actions[0] = 3; } else { - memset(net->obs, 0, env.num_snakes*968*sizeof(float)); - for (int i = 0; i < env.num_snakes*121; i++) { + memset(net->obs, 0, env.num_agents*968*sizeof(float)); + for (int i = 0; i < env.num_agents*121; i++) { int obs = env.observations[i]; net->obs[i*8 + obs] = 1.0f; } - forward_linearlstm(net, net->obs, env.actions); + int* actions = (int*)calloc(env.num_agents, sizeof(int)); + forward_linearlstm(net, net->obs, actions); + for (int i = 0; i < env.num_agents; i++) { + env.actions[i] = actions[i]; + } + free(actions); } c_step(&env); c_render(&env); @@ -50,7 +55,7 @@ int demo() { void test_performance(float test_time) { CSnake env = { - .num_snakes = 1024, + .num_agents = 1024, .width = 1280, .height = 720, .max_snake_length = 200, @@ -67,7 +72,7 @@ void test_performance(float test_time) { int start = time(NULL); int i = 0; while (time(NULL) - start < test_time) { - for (int j = 0; j < env.num_snakes; j++) { + for (int j = 0; j < env.num_agents; j++) { env.actions[j] = rand()%4; } c_step(&env); @@ -75,7 +80,7 @@ void test_performance(float test_time) { } int end = time(NULL); free_csnake(&env); - printf("SPS: %f\n", (float)env.num_snakes*i / (end - start)); + printf("SPS: %f\n", (float)env.num_agents*i / (end - start)); } int main() { diff --git a/pufferlib/ocean/snake/snake.h b/ocean/snake/snake.h similarity index 89% rename from pufferlib/ocean/snake/snake.h rename to ocean/snake/snake.h index 30a9a4d40e..6d5cfb1bd0 100644 --- a/pufferlib/ocean/snake/snake.h +++ b/ocean/snake/snake.h @@ -22,9 +22,9 @@ typedef struct Client Client; typedef struct CSnake CSnake; struct CSnake { char* observations; - int* actions; + double* actions; float* rewards; - unsigned char* terminals; + float* terminals; Log log; Log* snake_logs; char* grid; @@ -33,7 +33,7 @@ struct CSnake { int* snake_ptr; int* snake_lifetimes; int* snake_colors; - int num_snakes; + int num_agents; int width; int height; int max_snake_length; @@ -65,16 +65,16 @@ void add_log(CSnake* env, int snake_id) { void init_csnake(CSnake* env) { env->grid = (char*)calloc(env->width*env->height, sizeof(char)); - env->snake = (int*)calloc(env->num_snakes*2*env->max_snake_length, sizeof(int)); - env->snake_lengths = (int*)calloc(env->num_snakes, sizeof(int)); - env->snake_ptr = (int*)calloc(env->num_snakes, sizeof(int)); - env->snake_lifetimes = (int*)calloc(env->num_snakes, sizeof(int)); - env->snake_colors = (int*)calloc(env->num_snakes, sizeof(int)); - env->snake_logs = (Log*)calloc(env->num_snakes, sizeof(Log)); + env->snake = (int*)calloc(env->num_agents*2*env->max_snake_length, sizeof(int)); + env->snake_lengths = (int*)calloc(env->num_agents, sizeof(int)); + env->snake_ptr = (int*)calloc(env->num_agents, sizeof(int)); + env->snake_lifetimes = (int*)calloc(env->num_agents, sizeof(int)); + env->snake_colors = (int*)calloc(env->num_agents, sizeof(int)); + env->snake_logs = (Log*)calloc(env->num_agents, sizeof(Log)); env->tick = 0; env->client = NULL; env->snake_colors[0] = 7; - for (int i = 1; inum_snakes; i++) + for (int i = 1; inum_agents; i++) env->snake_colors[i] = i%4 + 4; // Randomize snake colors } @@ -89,9 +89,10 @@ void c_close(CSnake* env) { } void allocate_csnake(CSnake* env) { int obs_size = (2*env->vision + 1) * (2*env->vision + 1); - env->observations = (char*)calloc(env->num_snakes*obs_size, sizeof(char)); - env->actions = (int*)calloc(env->num_snakes, sizeof(int)); - env->rewards = (float*)calloc(env->num_snakes, sizeof(float)); + env->observations = (char*)calloc(env->num_agents*obs_size, sizeof(char)); + env->actions = (double*)calloc(env->num_agents, sizeof(double)); + env->rewards = (float*)calloc(env->num_agents, sizeof(float)); + env->terminals = (float*)calloc(env->num_agents, sizeof(float)); init_csnake(env); } @@ -103,7 +104,7 @@ void free_csnake(CSnake* env) { } void compute_observations(CSnake* env) { - for (int i = 0; i < env->num_snakes; i++) { + for (int i = 0; i < env->num_agents; i++) { int head_ptr = i*2*env->max_snake_length + 2*env->snake_ptr[i]; int r_offset = env->snake[head_ptr] - env->vision; int c_offset = env->snake[head_ptr+1] - env->vision; @@ -173,7 +174,7 @@ void c_reset(CSnake* env) { env->tick = 0; env->log = (Log){0}; - for (int i = 0; i < env->num_snakes; i++) + for (int i = 0; i < env->num_agents; i++) env->snake_logs[i] = (Log){0}; for (int r = 0; r < env->vision; r++) { @@ -190,7 +191,7 @@ void c_reset(CSnake* env) { for (int c = env->width - env->vision; c < env->width; c++) env->grid[r*env->width + c] = WALL; } - for (int i = 0; i < env->num_snakes; i++) + for (int i = 0; i < env->num_agents; i++) spawn_snake(env, i); for (int i = 0; i < env->food; i++) spawn_food(env); @@ -199,6 +200,7 @@ void c_reset(CSnake* env) { } void step_snake(CSnake* env, int i) { + env->terminals[i] = 0; env->snake_logs[i].episode_length += 1; int atn = env->actions[i]; int dr = 0; @@ -230,9 +232,10 @@ void step_snake(CSnake* env, int i) { int tile = env->grid[next_r*env->width + next_c]; if (tile >= WALL) { env->rewards[i] = env->reward_death; + //env->terminals[i] = 1; env->snake_logs[i].episode_return += env->reward_death; env->snake_logs[i].score = env->snake_lengths[i]; - env->snake_logs[i].perf = env->snake_logs[i].score / env->snake_logs[i].episode_length; + env->snake_logs[i].perf = fminf(env->snake_logs[i].score/120.0f, 1.0f); add_log(env, i); spawn_snake(env, i); return; @@ -281,7 +284,7 @@ void step_snake(CSnake* env, int i) { void c_step(CSnake* env){ env->tick++; - for (int i = 0; i < env->num_snakes; i++) + for (int i = 0; i < env->num_agents; i++) step_snake(env, i); compute_observations(env); diff --git a/ocean/squared/binding.c b/ocean/squared/binding.c new file mode 100644 index 0000000000..47e5c5fbe4 --- /dev/null +++ b/ocean/squared/binding.c @@ -0,0 +1,20 @@ +#include "squared.h" +#define OBS_SIZE 121 +#define NUM_ATNS 1 +#define ACT_SIZES {5} +#define OBS_TENSOR_T ByteTensor + +#define Env Squared +#include "vecenv.h" + +void my_init(Env* env, Dict* kwargs) { + env->num_agents = 1; + env->size = dict_get(kwargs, "size")->value; +} + +void my_log(Log* log, Dict* out) { + dict_set(out, "perf", log->perf); + dict_set(out, "score", log->score); + dict_set(out, "episode_return", log->episode_return); + dict_set(out, "episode_length", log->episode_length); +} diff --git a/pufferlib/ocean/squared/squared.c b/ocean/squared/squared.c similarity index 66% rename from pufferlib/ocean/squared/squared.c rename to ocean/squared/squared.c index a8b66185d8..d16651d6c0 100644 --- a/pufferlib/ocean/squared/squared.c +++ b/ocean/squared/squared.c @@ -7,29 +7,40 @@ */ #include "squared.h" +#include "puffernet.h" -int main() { +void demo() { Squared env = {.size = 11}; env.observations = (unsigned char*)calloc(env.size*env.size, sizeof(unsigned char)); - env.actions = (int*)calloc(1, sizeof(int)); + env.actions = (float*)calloc(1, sizeof(float)); env.rewards = (float*)calloc(1, sizeof(float)); - env.terminals = (unsigned char*)calloc(1, sizeof(unsigned char)); + env.terminals = (float*)calloc(1, sizeof(float)); + + Weights* weights = load_weights("resources/squared/squared_weights.bin"); + int logit_sizes[1] = {5}; + PufferNet* net = make_puffernet(weights, 1, 121, 128, 1, logit_sizes, 1); c_reset(&env); c_render(&env); while (!WindowShouldClose()) { if (IsKeyDown(KEY_LEFT_SHIFT)) { - env.actions[0] = 0; + env.actions[0] = 0.0f; if (IsKeyDown(KEY_UP) || IsKeyDown(KEY_W)) env.actions[0] = UP; if (IsKeyDown(KEY_DOWN) || IsKeyDown(KEY_S)) env.actions[0] = DOWN; if (IsKeyDown(KEY_LEFT) || IsKeyDown(KEY_A)) env.actions[0] = LEFT; if (IsKeyDown(KEY_RIGHT) || IsKeyDown(KEY_D)) env.actions[0] = RIGHT; } else { - env.actions[0] = rand() % 5; + float obs_f[121]; + for(int i=0; i<121; i++) obs_f[i] = (float)env.observations[i]; + forward_puffernet(net, obs_f, env.actions); } c_step(&env); c_render(&env); } + + free_puffernet(net); + free(weights); + free(env.observations); free(env.actions); free(env.rewards); @@ -37,3 +48,7 @@ int main() { c_close(&env); } +int main() { + demo(); + return 0; +} diff --git a/pufferlib/ocean/squared/squared.h b/ocean/squared/squared.h similarity index 89% rename from pufferlib/ocean/squared/squared.h rename to ocean/squared/squared.h index 512d95d250..497448df23 100644 --- a/pufferlib/ocean/squared/squared.h +++ b/ocean/squared/squared.h @@ -24,22 +24,23 @@ typedef struct { float score; // Recommended unnormalized single real number perf metric float episode_return; // Recommended metric: sum of agent rewards over episode float episode_length; // Recommended metric: number of steps of agent episode - // Any extra fields you add here may be exported to Python in binding.c - float n; // Required as the last field + // Any extra fields you add here may be exported in binding.c + float n; // Required as the last field } Log; // Required that you have some struct for your env -// Recommended that you name it the same as the env file typedef struct { Log log; // Required field. Env binding code uses this to aggregate logs unsigned char* observations; // Required. You can use any obs type, but make sure it matches in Python! - int* actions; // Required. int* for discrete/multidiscrete, float* for box + float* actions; // Required float* rewards; // Required - unsigned char* terminals; // Required. We don't yet have truncations as standard yet + float* terminals; // Required + int num_agents; int size; int tick; int r; int c; + unsigned int rng; } Squared; void add_log(Squared* env) { @@ -58,9 +59,9 @@ void c_reset(Squared* env) { env->r = env->size/2; env->c = env->size/2; env->tick = 0; - int target_idx; + int target_idx = 0; // Deterministic for testing do { - target_idx = rand() % tiles; + target_idx = rand_r(&env->rng) % tiles; } while (target_idx == tiles/2); env->observations[target_idx] = TARGET; } @@ -69,7 +70,7 @@ void c_reset(Squared* env) { void c_step(Squared* env) { env->tick += 1; - int action = env->actions[0]; + int action = (int)env->actions[0]; env->terminals[0] = 0; env->rewards[0] = 0; @@ -85,7 +86,7 @@ void c_step(Squared* env) { env->c -= 1; } - if (env->tick > 3*env->size + if (env->tick > 3*env->size || env->r < 0 || env->c < 0 || env->r >= env->size diff --git a/ocean/squared_continuous/binding.c b/ocean/squared_continuous/binding.c new file mode 100644 index 0000000000..81ef20eece --- /dev/null +++ b/ocean/squared_continuous/binding.c @@ -0,0 +1,20 @@ +#include "squared_continuous.h" +#define OBS_SIZE 121 +#define NUM_ATNS 2 +#define ACT_SIZES {1, 1} // Continuous: 2 dimensions, each size 1 +#define OBS_TENSOR_T ByteTensor + +#define Env Squared +#include "vecenv.h" + +void my_init(Env* env, Dict* kwargs) { + env->num_agents = 1; + env->size = dict_get(kwargs, "size")->value; +} + +void my_log(Log* log, Dict* out) { + dict_set(out, "perf", log->perf); + dict_set(out, "score", log->score); + dict_set(out, "episode_return", log->episode_return); + dict_set(out, "episode_length", log->episode_length); +} diff --git a/ocean/squared_continuous/squared_continuous.c b/ocean/squared_continuous/squared_continuous.c new file mode 100644 index 0000000000..2f9e764615 --- /dev/null +++ b/ocean/squared_continuous/squared_continuous.c @@ -0,0 +1,52 @@ +/* Pure C demo file for Squared Continuous. Build it with: + * bash scripts/build_ocean.sh squared_continuous local (debug) + * bash scripts/build_ocean.sh squared_continuous fast + */ + +#include "squared_continuous.h" +#include "puffernet.h" + +void demo() { + Squared env = {.size = 11}; + env.observations = (unsigned char*)calloc(env.size*env.size, sizeof(unsigned char)); + env.actions = (float*)calloc(2, sizeof(float)); + env.rewards = (float*)calloc(1, sizeof(float)); + env.terminals = (float*)calloc(1, sizeof(float)); + + Weights* weights = load_weights("resources/squared_continuous/squared_continuous_weights.bin"); + int logit_sizes[2] = {1, 1}; + PufferNet* net = make_puffernet(weights, 1, 121, 128, 1, logit_sizes, 2); + + c_reset(&env); + c_render(&env); + while (!WindowShouldClose()) { + if (IsKeyDown(KEY_LEFT_SHIFT)) { + env.actions[0] = 0.0f; + env.actions[1] = 0.0f; + if (IsKeyDown(KEY_UP) || IsKeyDown(KEY_W)) env.actions[0] = -1.0f; + if (IsKeyDown(KEY_DOWN) || IsKeyDown(KEY_S)) env.actions[0] = 1.0f; + if (IsKeyDown(KEY_LEFT) || IsKeyDown(KEY_A)) env.actions[1] = -1.0f; + if (IsKeyDown(KEY_RIGHT) || IsKeyDown(KEY_D)) env.actions[1] = 1.0f; + } else { + float obs_f[121]; + for(int i=0; i<121; i++) obs_f[i] = (float)env.observations[i]; + forward_puffernet(net, obs_f, env.actions); + } + c_step(&env); + c_render(&env); + } + + free_puffernet(net); + free(weights); + + free(env.observations); + free(env.actions); + free(env.rewards); + free(env.terminals); + c_close(&env); +} + +int main() { + demo(); + return 0; +} diff --git a/ocean/squared_continuous/squared_continuous.h b/ocean/squared_continuous/squared_continuous.h new file mode 100644 index 0000000000..b25cbc1a79 --- /dev/null +++ b/ocean/squared_continuous/squared_continuous.h @@ -0,0 +1,160 @@ +/* Squared Continuous: continuous action version of squared. + * 2 continuous action dimensions: vertical and horizontal. + * Actions are clamped to [-1, 1] and thresholded at 0.25 magnitude. + */ + +#include +#include +#include "raylib.h" + +const unsigned char NOOP = 0; +const unsigned char DOWN = 1; +const unsigned char UP = 2; +const unsigned char LEFT = 3; +const unsigned char RIGHT = 4; + +const unsigned char EMPTY = 0; +const unsigned char AGENT = 1; +const unsigned char TARGET = 2; + +// Required struct. Only use floats! +typedef struct { + float perf; // Recommended 0-1 normalized single real number perf metric + float score; // Recommended unnormalized single real number perf metric + float episode_return; // Recommended metric: sum of agent rewards over episode + float episode_length; // Recommended metric: number of steps of agent episode + // Any extra fields you add here may be exported to Python in binding.c + float n; // Required as the last field +} Log; + +// Required that you have some struct for your env +// Recommended that you name it the same as the env file +typedef struct { + Log log; // Required field. Env binding code uses this to aggregate logs + unsigned char* observations; // Required. You can use any obs type, but make sure it matches in Python! + float* actions; // Required + float* rewards; // Required + float* terminals; // Required + int num_agents; + int size; + int tick; + int r; + int c; + unsigned int rng; +} Squared; + +void add_log(Squared* env) { + env->log.perf += (env->rewards[0] > 0) ? 1 : 0; + env->log.score += env->rewards[0]; + env->log.episode_length += env->tick; + env->log.episode_return += env->rewards[0]; + env->log.n++; +} + +// Required function +void c_reset(Squared* env) { + int tiles = env->size*env->size; + memset(env->observations, 0, tiles*sizeof(unsigned char)); + env->observations[tiles/2] = AGENT; + env->r = env->size/2; + env->c = env->size/2; + env->tick = 0; + int target_idx = 0; // Deterministic for testing + do { + target_idx = rand_r(&env->rng) % tiles; + } while (target_idx == tiles/2); + env->observations[target_idx] = TARGET; +} + +// Clamp value to [-1, 1] +static inline float clamp_action(float x) { + return x < -1.0f ? -1.0f : (x > 1.0f ? 1.0f : x); +} + +// Required function +void c_step(Squared* env) { + env->tick += 1; + + // Continuous actions: clamp to [-1, 1] then threshold to get discrete movement + // action[0]: vertical (positive = down, negative = up) + // action[1]: horizontal (positive = right, negative = left) + float vert = clamp_action(env->actions[0]); + float horiz = clamp_action(env->actions[1]); + env->terminals[0] = 0; + env->rewards[0] = 0; + + env->observations[env->r*env->size + env->c] = EMPTY; + + // Threshold at 0.25 magnitude to determine direction (allows stationary) + if (vert > 0.25) { + env->r += 1; // DOWN + } else if (vert < -0.25) { + env->r -= 1; // UP + } + if (horiz > 0.25) { + env->c += 1; // RIGHT + } else if (horiz < -0.25) { + env->c -= 1; // LEFT + } + + if (env->tick > 3*env->size + || env->r < 0 + || env->c < 0 + || env->r >= env->size + || env->c >= env->size) { + env->terminals[0] = 1; + env->rewards[0] = -1.0; + add_log(env); + c_reset(env); + return; + } + + int pos = env->r*env->size + env->c; + if (env->observations[pos] == TARGET) { + env->terminals[0] = 1; + env->rewards[0] = 1.0; + add_log(env); + c_reset(env); + return; + } + + env->observations[pos] = AGENT; +} + +// Required function. Should handle creating the client on first call +void c_render(Squared* env) { + if (!IsWindowReady()) { + InitWindow(64*env->size, 64*env->size, "PufferLib Squared Continuous"); + SetTargetFPS(5); + } + + // Standard across our envs so exiting is always the same + if (IsKeyDown(KEY_ESCAPE)) { + exit(0); + } + + BeginDrawing(); + ClearBackground((Color){6, 24, 24, 255}); + + int px = 64; + for (int i = 0; i < env->size; i++) { + for (int j = 0; j < env->size; j++) { + int tex = env->observations[i*env->size + j]; + if (tex == EMPTY) { + continue; + } + Color color = (tex == AGENT) ? (Color){0, 187, 187, 255} : (Color){187, 0, 0, 255}; + DrawRectangle(j*px, i*px, px, px, color); + } + } + + EndDrawing(); +} + +// Required function. Should clean up anything you allocated +// Do not free env->observations, actions, rewards, terminals +void c_close(Squared* env) { + if (IsWindowReady()) { + CloseWindow(); + } +} diff --git a/pufferlib/ocean/tactical/binding.c b/ocean/tactical/binding.c similarity index 100% rename from pufferlib/ocean/tactical/binding.c rename to ocean/tactical/binding.c diff --git a/pufferlib/ocean/tactical/maps.h b/ocean/tactical/maps.h similarity index 100% rename from pufferlib/ocean/tactical/maps.h rename to ocean/tactical/maps.h diff --git a/pufferlib/ocean/tactical/tactical.c b/ocean/tactical/tactical.c similarity index 100% rename from pufferlib/ocean/tactical/tactical.c rename to ocean/tactical/tactical.c diff --git a/pufferlib/ocean/tactical/tactical.h b/ocean/tactical/tactical.h similarity index 100% rename from pufferlib/ocean/tactical/tactical.h rename to ocean/tactical/tactical.h diff --git a/ocean/target/binding.c b/ocean/target/binding.c new file mode 100644 index 0000000000..8f765ffa8d --- /dev/null +++ b/ocean/target/binding.c @@ -0,0 +1,23 @@ +#include "target.h" +#define OBS_SIZE 28 // num_goals*2 + num_agents*2 + 4 = 4*2 + 8*2 + 4 +#define NUM_ATNS 2 +#define ACT_SIZES {9, 5} +#define OBS_TENSOR_T FloatTensor + +#define Env Target +#include "vecenv.h" + +void my_init(Env* env, Dict* kwargs) { + env->width = 952; + env->height = 592; + env->num_agents = 8; + env->num_goals = 4; + init(env); +} + +void my_log(Log* log, Dict* out) { + dict_set(out, "perf", log->perf); + dict_set(out, "score", log->score); + dict_set(out, "episode_return", log->episode_return); + dict_set(out, "episode_length", log->episode_length); +} diff --git a/ocean/target/target.c b/ocean/target/target.c new file mode 100644 index 0000000000..e0edc3655a --- /dev/null +++ b/ocean/target/target.c @@ -0,0 +1,44 @@ +#include "target.h" +#include "puffernet.h" + +void demo() { + // encoder(128x28=3584) + decoder(15x128=1920) + 4x mingru(384x128=49152) = 202112 + Weights* weights = load_weights("resources/target/target_weights.bin"); + + int logit_sizes[2] = {9, 5}; + PufferNet* net = make_puffernet(weights, 8, 28, 128, 4, logit_sizes, 2); + + float observations[8*28] = {0}; + float actions[8*2] = {0}; + float rewards[8] = {0}; + float terminals[8] = {0}; + Agent agents[8] = {0}; + Goal goals[4] = {0}; + + Target env = { + .width = 952, + .height = 592, + .num_agents = 8, + .num_goals = 4, + .observations = observations, + .actions = actions, + .rewards = rewards, + .terminals = terminals, + .agents = agents, + .goals = goals, + }; + + c_reset(&env); + c_render(&env); + while (!WindowShouldClose()) { + forward_puffernet(net, env.observations, env.actions); + c_step(&env); + c_render(&env); + } + free_puffernet(net); + free(weights); +} + +int main() { + demo(); +} diff --git a/pufferlib/ocean/target/target.h b/ocean/target/target.h similarity index 63% rename from pufferlib/ocean/target/target.h rename to ocean/target/target.h index a2d7ff2ac8..016f198f5f 100644 --- a/pufferlib/ocean/target/target.h +++ b/ocean/target/target.h @@ -16,7 +16,7 @@ typedef struct { float episode_return; // Recommended metric: sum of agent rewards over episode float episode_length; // Recommended metric: number of steps of agent episode // Any extra fields you add here may be exported to Python in binding.c - float n; // Required as the last field + float n; // Required as the last field } Log; typedef struct { @@ -45,16 +45,17 @@ typedef struct { Agent* agents; Goal* goals; float* observations; // Required. You can use any obs type, but make sure it matches in Python! - int* actions; // Required. int* for discrete/multidiscrete, float* for box + float* actions; // Required float* rewards; // Required - unsigned char* terminals; // Required. We don't yet have truncations as standard yet + float* terminals; // Required int width; int height; int num_agents; int num_goals; + unsigned int rng; } Target; -/* Recommended to have an init function of some kind if you allocate +/* Recommended to have an init function of some kind if you allocate * extra memory. This should be freed by c_close. Don't forget to call * this in binding.c! */ @@ -64,22 +65,22 @@ void init(Target* env) { } void update_goals(Target* env) { - for (int a=0; anum_agents; a++) { + for (int a = 0; a < env->num_agents; a++) { Agent* agent = &env->agents[a]; - for (int g=0; gnum_goals; g++) { + for (int g = 0; g < env->num_goals; g++) { Goal* goal = &env->goals[g]; - float dx = (goal->x - agent->x); - float dy = (goal->y - agent->y); - float dist = sqrt(dx*dx + dy*dy); - if (dist > 32) { + float dx = goal->x - agent->x; + float dy = goal->y - agent->y; + float dist = sqrtf(dx*dx + dy*dy); + if (dist > 64) { continue; } - goal->x = rand() % env->width; - goal->y = rand() % env->height; + goal->x = rand_r(&env->rng) % env->width; + goal->y = rand_r(&env->rng) % env->height; env->rewards[a] = 1.0f; - env->log.perf += 1.0f; env->log.score += 1.0f; env->log.episode_length += agent->ticks_since_reward; + env->log.perf += fmaxf(0.0f, 1.0f - 0.01f * agent->ticks_since_reward); agent->ticks_since_reward = 0; env->log.episode_return += 1.0f; env->log.n++; @@ -94,70 +95,69 @@ void update_goals(Target* env) { */ void compute_observations(Target* env) { int obs_idx = 0; - for (int a=0; anum_agents; a++) { + for (int a = 0; a < env->num_agents; a++) { Agent* agent = &env->agents[a]; - for (int g=0; gnum_goals; g++) { + for (int g = 0; g < env->num_goals; g++) { Goal* goal = &env->goals[g]; - env->observations[obs_idx++] = (goal->x - agent->x)/env->width; - env->observations[obs_idx++] = (goal->y - agent->y)/env->height; + env->observations[obs_idx++] = (goal->x - agent->x) / env->width; + env->observations[obs_idx++] = (goal->y - agent->y) / env->height; } - for (int a=0; anum_agents; a++) { - Agent* other = &env->agents[a]; - env->observations[obs_idx++] = (other->x - agent->x)/env->width; - env->observations[obs_idx++] = (other->y - agent->y)/env->height; + for (int b = 0; b < env->num_agents; b++) { + Agent* other = &env->agents[b]; + env->observations[obs_idx++] = (other->x - agent->x) / env->width; + env->observations[obs_idx++] = (other->y - agent->y) / env->height; } - env->observations[obs_idx++] = agent->heading/(2*PI); + env->observations[obs_idx++] = agent->heading / (2*PI); env->observations[obs_idx++] = env->rewards[a]; - env->observations[obs_idx++] = agent->x/env->width; - env->observations[obs_idx++] = agent->y/env->height; + env->observations[obs_idx++] = agent->x / env->width; + env->observations[obs_idx++] = agent->y / env->height; } } // Required function void c_reset(Target* env) { - for (int i=0; inum_agents; i++) { - env->agents[i].x = rand() % env->width; - env->agents[i].y = rand() % env->height; + for (int i = 0; i < env->num_agents; i++) { + env->agents[i].x = rand_r(&env->rng) % env->width; + env->agents[i].y = rand_r(&env->rng) % env->height; env->agents[i].ticks_since_reward = 0; } - for (int i=0; inum_goals; i++) { - env->goals[i].x = rand() % env->width; - env->goals[i].y = rand() % env->height; + for (int i = 0; i < env->num_goals; i++) { + env->goals[i].x = rand_r(&env->rng) % env->width; + env->goals[i].y = rand_r(&env->rng) % env->height; } compute_observations(env); } -float clip(float val, float min, float max) { - if (val < min) { - return min; - } else if (val > max) { - return max; - } +static inline float clipf(float val, float min, float max) { + if (val < min) return min; + if (val > max) return max; return val; } // Required function void c_step(Target* env) { - for (int i=0; inum_agents; i++) { + for (int i = 0; i < env->num_agents; i++) { env->rewards[i] = 0; Agent* agent = &env->agents[i]; agent->ticks_since_reward += 1; - agent->heading += ((float)env->actions[2*i] - 4.0f)/12.0f; - agent->heading = clip(agent->heading, 0, 2*PI); + // action[2*i]: heading adjustment (0-8, center=4) + // action[2*i+1]: speed adjustment (0-4, center=2) + agent->heading += (env->actions[2*i] - 4.0f) / 12.0f; + agent->heading = clipf(agent->heading, 0, 2*PI); - agent->speed += 1.0f*((float)env->actions[2*i + 1] - 2.0f); - agent->speed = clip(agent->speed, -20.0f, 20.0f); + agent->speed += env->actions[2*i + 1] - 2.0f; + agent->speed = clipf(agent->speed, -20.0f, 20.0f); - agent->x += agent->speed*cosf(agent->heading); - agent->x = clip(agent->x, 0, env->width); + agent->x += agent->speed * cosf(agent->heading); + agent->x = clipf(agent->x, 0, env->width); - agent->y += agent->speed*sinf(agent->heading); - agent->y = clip(agent->y, 0, env->height); + agent->y += agent->speed * sinf(agent->heading); + agent->y = clipf(agent->y, 0, env->height); if (agent->ticks_since_reward % 512 == 0) { - env->agents[i].x = rand() % env->width; - env->agents[i].y = rand() % env->height; + agent->x = rand_r(&env->rng) % env->width; + agent->y = rand_r(&env->rng) % env->height; } } update_goals(env); @@ -167,13 +167,11 @@ void c_step(Target* env) { // Required function. Should handle creating the client on first call void c_render(Target* env) { if (env->client == NULL) { - InitWindow(env->width, env->height, "PufferLib Target"); + InitWindow(1080, 720, "PufferLib Target"); SetTargetFPS(60); env->client = (Client*)calloc(1, sizeof(Client)); - - // Don't do this before calling InitWindow env->client->puffer = LoadTexture("resources/shared/puffers_128.png"); - env->client->star = LoadTexture("resources/target/star.png"); + env->client->star = LoadTexture("resources/shared/star.png"); } // Standard across our envs so exiting is always the same @@ -184,17 +182,12 @@ void c_render(Target* env) { BeginDrawing(); ClearBackground((Color){6, 24, 24, 255}); - for (int i=0; inum_goals; i++) { + for (int i = 0; i < env->num_goals; i++) { Goal* goal = &env->goals[i]; - DrawTexture( - env->client->star, - goal->x - 32, - goal->y - 32, - WHITE - ); + DrawTexture(env->client->star, (int)goal->x, (int)goal->y, WHITE); } - for (int i=0; inum_agents; i++) { + for (int i = 0; i < env->num_agents; i++) { Agent* agent = &env->agents[i]; float heading = agent->heading; DrawTexturePro( @@ -204,8 +197,8 @@ void c_render(Target* env) { 0, 128, 128, }, (Rectangle){ - agent->x - 64, - agent->y - 64, + agent->x, + agent->y, 128, 128 }, diff --git a/pufferlib/ocean/template/binding.c b/ocean/template/binding.c similarity index 100% rename from pufferlib/ocean/template/binding.c rename to ocean/template/binding.c diff --git a/pufferlib/ocean/template/template.c b/ocean/template/template.c similarity index 100% rename from pufferlib/ocean/template/template.c rename to ocean/template/template.c diff --git a/pufferlib/ocean/template/template.h b/ocean/template/template.h similarity index 100% rename from pufferlib/ocean/template/template.h rename to ocean/template/template.h diff --git a/ocean/terraform/binding.c b/ocean/terraform/binding.c new file mode 100644 index 0000000000..d3c065388c --- /dev/null +++ b/ocean/terraform/binding.c @@ -0,0 +1,24 @@ +#include "terraform.h" +#define OBS_SIZE 319 +#define NUM_ATNS 3 +#define ACT_SIZES {5, 5, 3} +#define OBS_TENSOR_T FloatTensor + +#define Env Terraform +#include "vecenv.h" + +void my_init(Env* env, Dict* kwargs) { + env->num_agents = dict_get(kwargs, "num_agents")->value; + env->size = dict_get(kwargs, "size")->value; + env->reset_frequency = dict_get(kwargs, "reset_frequency")->value; + env->reward_scale = dict_get(kwargs, "reward_scale")->value; + init(env); +} + +void my_log(Log* log, Dict* out) { + dict_set(out, "perf", log->perf); + dict_set(out, "score", log->score); + dict_set(out, "episode_return", log->episode_return); + dict_set(out, "episode_length", log->episode_length); + dict_set(out, "quadrant_progress", log->quadrant_progress); +} diff --git a/pufferlib/ocean/terraform/simplex.h b/ocean/terraform/simplex.h similarity index 100% rename from pufferlib/ocean/terraform/simplex.h rename to ocean/terraform/simplex.h diff --git a/ocean/terraform/terraform.c b/ocean/terraform/terraform.c new file mode 100644 index 0000000000..ee623f9a36 --- /dev/null +++ b/ocean/terraform/terraform.c @@ -0,0 +1,59 @@ +#include "terraform.h" +#include "puffernet.h" +#include + +void allocate(Terraform* env) { + env->observations = (float*)calloc(env->num_agents*319, sizeof(float)); + env->actions = (float*)calloc(3*env->num_agents, sizeof(float)); + env->rewards = (float*)calloc(env->num_agents, sizeof(float)); + env->terminals = (float*)calloc(env->num_agents, sizeof(float)); + init(env); +} + +void free_allocated(Terraform* env) { + free(env->observations); + free(env->actions); + free(env->rewards); + free(env->terminals); + free_initialized(env); +} + +void demo() { + Weights* weights = load_weights("resources/terraform/terraform_weights.bin"); + int logit_sizes[3] = {5, 5, 3}; + PufferNet* net = make_puffernet(weights, 1, 319, 512, 5, logit_sizes, 3); + srand(time(NULL)); + Terraform env = {.size = 64, .num_agents = 1, .reset_frequency = 8192, .reward_scale = 0.04f}; + allocate(&env); + + c_reset(&env); + c_render(&env); + while (!WindowShouldClose()) { + forward_puffernet(net, env.observations, env.actions); + + if(IsKeyDown(KEY_LEFT_SHIFT)) { + // When shift is held, stop the dozer + env.actions[0] = 2; // Stop vertical movement + env.actions[1] = 2; // Stop horizontal movement + env.actions[2] = 0; // no scoop or drop + // Override with keyboard controls if keys are pressed + if (IsKeyPressed(KEY_UP) || IsKeyPressed(KEY_W)) env.actions[0] = 4; + if (IsKeyPressed(KEY_DOWN) || IsKeyPressed(KEY_S)) env.actions[0] = 0; + if (IsKeyDown(KEY_LEFT) || IsKeyDown(KEY_A)) env.actions[1] = 0; + if (IsKeyDown(KEY_RIGHT) || IsKeyDown(KEY_D)) env.actions[1] = 4; + if (IsKeyPressed(KEY_SPACE)) env.actions[2] = 1; + if (IsKeyPressed(KEY_ENTER)) env.actions[2] = 2; + } + c_step(&env); + c_render(&env); + } + free_allocated(&env); + close_client(env.client); + free_puffernet(net); + free(weights); +} + +int main() { + demo(); + return 0; +} diff --git a/pufferlib/ocean/terraform/terraform.h b/ocean/terraform/terraform.h similarity index 97% rename from pufferlib/ocean/terraform/terraform.h rename to ocean/terraform/terraform.h index 21a2147218..2d1ce5b1b8 100644 --- a/pufferlib/ocean/terraform/terraform.h +++ b/ocean/terraform/terraform.h @@ -41,8 +41,6 @@ const unsigned char TARGET = 2; #define OBSERVATION_SIZE (2*VISION + 1) #define TOTAL_OBS (OBSERVATION_SIZE*OBSERVATION_SIZE + 4) #define DOZER_STEP_HEIGHT 5.0f -struct timespec ts; - typedef struct Log Log; struct Log { float perf; @@ -76,16 +74,16 @@ typedef struct Terraform { Client* client; Dozer* dozers; float* observations; - int* actions; + float* actions; float* rewards; float* returns; - unsigned char* terminals; + float* terminals; + int num_agents; int size; int tick; float* orig_map; float* map; float* target_map; - int num_agents; int reset_frequency; float reward_scale; float initial_total_delta; @@ -102,10 +100,11 @@ typedef struct Terraform { float* volume_deltas; float* quadrant_volume_deltas; float* quadrant_centroids; + unsigned int rng; } Terraform; -float randf(float min, float max) { - return min + (max - min)*(float)rand()/(float)RAND_MAX; +float randf(unsigned int* rng, float min, float max) { + return min + (max - min)*(float)rand_r(rng)/(float)RAND_MAX; } void perlin_noise(float* map, int width, int height, @@ -265,22 +264,16 @@ void init(Terraform* env) { env->dozers[i].quadrant_progress = 0.0f; env->dozers[i].highest_quadrant_progress = 0.0f; } - clock_gettime(CLOCK_REALTIME, &ts); - unsigned int base_seed = (unsigned int)(ts.tv_nsec ^ ts.tv_sec ^ getpid()); - unsigned int seed1 = base_seed; - unsigned int seed2 = base_seed + 99991; - srand(seed1); - int offset_x1 = rand() % 10000; - int offset_y1 = rand() % 10000; - srand(seed2); - int offset_x2 = rand() % 10000; - int offset_y2 = rand() % 10000; + int offset_x1 = rand_r(&env->rng) % 10000; + int offset_y1 = rand_r(&env->rng) % 10000; + int offset_x2 = rand_r(&env->rng) % 10000; + int offset_y2 = rand_r(&env->rng) % 10000; perlin_noise(env->orig_map, env->size, env->size, 1.0/(env->size / 4.0), 8, offset_x1, offset_y1, MAX_DIRT_HEIGHT+20); // perlin_noise(env->target_map, env->size, env->size, 1.0/(env->size / 4.0), 8, offset_x2, offset_y2, MAX_DIRT_HEIGHT+55); env->returns = calloc(env->num_agents, sizeof(float)); calculate_total_delta(env); env->stuck_count = calloc(env->num_agents, sizeof(int)); - env->tick = rand() % 512; + env->tick = rand_r(&env->rng) % 512; env->quadrants_solved = 0.0f; } @@ -386,7 +379,7 @@ void c_reset(Terraform* env) { memcpy(env->quadrant_volume_deltas, env->volume_deltas, env->num_quadrants*sizeof(float)); memset(env->complete_quadrants, 0, env->num_quadrants*sizeof(int)); - int num_quadrants_to_precomplete = rand() % 5 + 25; // e.g. 30 to 34 + int num_quadrants_to_precomplete = rand_r(&env->rng) % 5 + 25; // e.g. 30 to 34 // Create array of available quadrants int available[env->num_quadrants]; @@ -451,8 +444,8 @@ void c_reset(Terraform* env) { temp.load_indices = env->dozers[i].load_indices; env->dozers[i] = temp; do { - env->dozers[i].x = rand() % env->size; - env->dozers[i].y = rand() % env->size; + env->dozers[i].x = rand_r(&env->rng) % env->size; + env->dozers[i].y = rand_r(&env->rng) % env->size; } while (env->map[map_idx(env, env->dozers[i].x, env->dozers[i].y)] != 0.0f); for (int j = 0; j < (2*SCOOP_SIZE + 1)*(2*SCOOP_SIZE + 1); j++) { env->dozers[i].load_indices[j] = -1; @@ -576,16 +569,16 @@ void c_step(Terraform* env) { return; } - memset(env->terminals, 0, env->num_agents*sizeof(unsigned char)); + memset(env->terminals, 0, env->num_agents*sizeof(float)); memset(env->rewards, 0, env->num_agents*sizeof(float)); - int (*actions)[3] = (int(*)[3])env->actions; + float (*actions)[3] = (float(*)[3])env->actions; for (int i = 0; i < env->num_agents; i++) { env->agent_logs[i].episode_length = env->tick; Dozer* dozer = &env->dozers[i]; - int* atn = actions[i]; - float accel = ((float)atn[0] - 2.0f) / 2.0f; // Discrete(5) -> [-1, 1] - float steer = ((float)atn[1] - 2.0f) / 10.0f; // Discrete(5) -> [-0.2, 0.2] - int bucket_atn = atn[2]; + float* atn = actions[i]; + float accel = (atn[0] - 2.0) / 2.0; // Discrete(5) -> [-1, 1] + float steer = (atn[1] - 2.0) / 10.0; // Discrete(5) -> [-0.2, 0.2] + int bucket_atn = (int)atn[2]; float cx = dozer->x + BUCKET_OFFSET*cosf(dozer->heading); float cy = dozer->y + BUCKET_OFFSET*sinf(dozer->heading); @@ -676,8 +669,8 @@ void c_step(Terraform* env) { // Teleportitis if (env->tick % 512 == 0) { do { - env->dozers[i].x = rand() % env->size; - env->dozers[i].y = rand() % env->size; + env->dozers[i].x = rand_r(&env->rng) % env->size; + env->dozers[i].y = rand_r(&env->rng) % env->size; env->stuck_count[i] = 0; } while (env->map[map_idx(env, env->dozers[i].x, env->dozers[i].y)] != 0.0f); } diff --git a/ocean/tetris/binding.c b/ocean/tetris/binding.c new file mode 100644 index 0000000000..057b1bcb7f --- /dev/null +++ b/ocean/tetris/binding.c @@ -0,0 +1,33 @@ +#include "tetris.h" +#define OBS_SIZE 234 +#define NUM_ATNS 1 +#define ACT_SIZES {7} +#define OBS_TENSOR_T FloatTensor + +#define Env Tetris +#include "vecenv.h" + +void my_init(Env* env, Dict* kwargs) { + env->num_agents = 1; + env->n_cols = dict_get(kwargs, "n_cols")->value; + env->n_rows = dict_get(kwargs, "n_rows")->value; + env->use_deck_obs = dict_get(kwargs, "use_deck_obs")->value; + env->n_noise_obs = dict_get(kwargs, "n_noise_obs")->value; + env->n_init_garbage = dict_get(kwargs, "n_init_garbage")->value; + init(env); +} + +void my_log(Log* log, Dict* out) { + dict_set(out, "perf", log->perf); + dict_set(out, "score", log->score); + dict_set(out, "episode_return", log->episode_return); + dict_set(out, "episode_length", log->episode_length); + dict_set(out, "lines_deleted", log->lines_deleted); + dict_set(out, "avg_combo", log->avg_combo); + dict_set(out, "atn_frac_soft_drop", log->atn_frac_soft_drop); + dict_set(out, "atn_frac_hard_drop", log->atn_frac_hard_drop); + dict_set(out, "atn_frac_rotate", log->atn_frac_rotate); + dict_set(out, "atn_frac_hold", log->atn_frac_hold); + dict_set(out, "game_level", log->game_level); + dict_set(out, "ticks_per_line", log->ticks_per_line); +} diff --git a/ocean/tetris/tetris.c b/ocean/tetris/tetris.c new file mode 100644 index 0000000000..3461468ad7 --- /dev/null +++ b/ocean/tetris/tetris.c @@ -0,0 +1,73 @@ +#include +#include "tetris.h" +#include "puffernet.h" + +void demo() { + Tetris env = { + .n_rows = 20, + .n_cols = 10, + .use_deck_obs = true, + .n_noise_obs = 0, + .n_init_garbage = 0, + }; + allocate(&env); + env.client = make_client(&env); + c_reset(&env); + + Weights* weights = load_weights("resources/tetris/tetris_weights.bin"); + int logit_sizes[1] = {7}; + PufferNet* net = make_puffernet(weights, 1, 234, 512, 2, logit_sizes, 1); + + static bool rotate_key_was_down = false; + static bool hard_drop_key_was_down = false; + static bool swap_key_was_down = false; + + int frame = 0; + env.actions[0] = 0; + while (!WindowShouldClose()) { + bool process_logic = true; + frame++; + + if (IsKeyDown(KEY_LEFT_SHIFT)) { + if (frame % 3 != 0) { + process_logic = false; + } else { + if (IsKeyDown(KEY_LEFT) || IsKeyDown(KEY_A)) { + env.actions[0] = 1; + } else if (IsKeyDown(KEY_RIGHT) || IsKeyDown(KEY_D)) { + env.actions[0] = 2; + } else if (IsKeyDown(KEY_DOWN) || IsKeyDown(KEY_S)) { + env.actions[0] = 4; + } else if ((IsKeyDown(KEY_UP) || IsKeyDown(KEY_W)) && !rotate_key_was_down) { + env.actions[0] = 3; + } else if (IsKeyDown(KEY_SPACE) && !hard_drop_key_was_down) { + env.actions[0] = 5; + } else if (IsKeyDown(KEY_C) && !swap_key_was_down) { + env.actions[0] = 6; + } + } + } else { + forward_puffernet(net, env.observations, env.actions); + } + + if (process_logic) { + rotate_key_was_down = IsKeyDown(KEY_UP) || IsKeyDown(KEY_W); + hard_drop_key_was_down = IsKeyDown(KEY_SPACE); + swap_key_was_down = IsKeyDown(KEY_C); + c_step(&env); + env.actions[0] = 0; + } + + c_render(&env); + } + + free_puffernet(net); + free(weights); + free_allocated(&env); + close_client(env.client); +} + +int main() { + demo(); + return 0; +} diff --git a/pufferlib/ocean/tetris/tetris.h b/ocean/tetris/tetris.h similarity index 94% rename from pufferlib/ocean/tetris/tetris.h rename to ocean/tetris/tetris.h index 4b40efdd5f..ebde3eebf6 100644 --- a/pufferlib/ocean/tetris/tetris.h +++ b/ocean/tetris/tetris.h @@ -45,8 +45,8 @@ const float REWARD_COMBO[5] = {0, 0.1, 0.3, 0.5, 1.0}; typedef struct Log { float perf; float score; - float ep_length; - float ep_return; + float episode_length; + float episode_return; float lines_deleted; float avg_combo; float atn_frac_soft_drop; @@ -71,9 +71,10 @@ typedef struct Tetris { Client *client; Log log; float *observations; - int *actions; + float *actions; float *rewards; - unsigned char *terminals; + float *terminals; + int num_agents; int dim_obs; int num_float_obs; @@ -100,7 +101,7 @@ typedef struct Tetris { int cur_tetromino_col; int cur_tetromino_rot; - float ep_return; + float episode_return; int lines_deleted; int count_combos; int game_level; @@ -109,6 +110,7 @@ typedef struct Tetris { int atn_count_rotate; int atn_count_hold; int tetromino_counts[NUM_TETROMINOES]; + unsigned int rng; } Tetris; void init(Tetris *env) { @@ -127,9 +129,9 @@ void allocate(Tetris *env) { // grid, 6 floats, 4 one-hot tetrominoes encode (current, previews, hold) + self-inflicting noisy action bits env->dim_obs = env->n_cols * env->n_rows + NUM_FLOAT_OBS + NUM_TETROMINOES * (NUM_PREVIEW + 2) + env->n_noise_obs; env->observations = (float *)calloc(env->dim_obs, sizeof(float)); - env->actions = (int *)calloc(1, sizeof(int)); + env->actions = (float *)calloc(1, sizeof(float)); env->rewards = (float *)calloc(1, sizeof(float)); - env->terminals = (unsigned char *)calloc(1, sizeof(unsigned char)); + env->terminals = (float *)calloc(1, sizeof(float)); } void c_close(Tetris *env) { @@ -148,8 +150,8 @@ void free_allocated(Tetris *env) { void add_log(Tetris *env) { env->log.score += env->score; env->log.perf += env->score / ((float)PERSONAL_BEST); - env->log.ep_length += env->tick; - env->log.ep_return += env->ep_return; + env->log.episode_length += env->tick; + env->log.episode_return += env->episode_return; env->log.lines_deleted += env->lines_deleted; env->log.avg_combo += env->count_combos > 0 ? ((float)env->lines_deleted) / ((float)env->count_combos) : 1.0f; env->log.atn_frac_hard_drop += env->atn_count_hard_drop / ((float)env->tick); @@ -205,13 +207,13 @@ void compute_observations(Tetris *env) { // Turn off noise bits, one-by-one. if (env->n_noise_obs > 0) { - env->observations[offset + rand() % env->n_noise_obs] = 0; + env->observations[offset + rand_r(&env->rng) % env->n_noise_obs] = 0; } } void restore_grid(Tetris *env) { memset(env->grid, 0, env->n_rows * env->n_cols * sizeof(int)); } -void refill_and_shuffle(int *array) { +void refill_and_shuffle(Tetris* env, int *array) { // Hold can change the deck distribution, so need to refill for (int i = 0; i < NUM_TETROMINOES; i++) { array[i] = i; @@ -219,7 +221,7 @@ void refill_and_shuffle(int *array) { // Fisher-Yates shuffle for (int i = NUM_TETROMINOES - 1; i > 0; i--) { - int j = rand() % (i + 1); + int j = rand_r(&env->rng) % (i + 1); int temp = array[i]; array[i] = array[j]; array[j] = temp; @@ -228,8 +230,8 @@ void refill_and_shuffle(int *array) { void initialize_deck(Tetris *env) { // Implements a 7-bag system. The deck is composed of two bags. - refill_and_shuffle(env->tetromino_deck); // First bag - refill_and_shuffle(env->tetromino_deck + NUM_TETROMINOES); // Second bag + refill_and_shuffle(env, env->tetromino_deck); // First bag + refill_and_shuffle(env, env->tetromino_deck + NUM_TETROMINOES); // Second bag env->cur_position_in_deck = 0; env->cur_tetromino = env->tetromino_deck[env->cur_position_in_deck]; } @@ -241,10 +243,10 @@ void spawn_new_tetromino(Tetris *env) { if (env->cur_position_in_deck == 0) { // Now using the first bag, so shuffle the second bag - refill_and_shuffle(env->tetromino_deck + NUM_TETROMINOES); + refill_and_shuffle(env, env->tetromino_deck + NUM_TETROMINOES); } else if (env->cur_position_in_deck == NUM_TETROMINOES) { // Now using the second bag, so shuffle the first bag - refill_and_shuffle(env->tetromino_deck); + refill_and_shuffle(env, env->tetromino_deck); } env->cur_tetromino_col = env->n_cols / 2; @@ -390,7 +392,7 @@ void add_garbage_lines(Tetris *env, int num_lines, int num_holes) { for (int r = env->n_rows - num_lines; r < env->n_rows; r++) { // First, fill the entire row with garbage for (int c = 0; c < env->n_cols; c++) { - env->grid[r * env->n_cols + c] = -(rand() % NUM_TETROMINOES + 1); + env->grid[r * env->n_cols + c] = -(rand_r(&env->rng) % NUM_TETROMINOES + 1); } // Create holes by selecting distinct columns @@ -400,7 +402,7 @@ void add_garbage_lines(Tetris *env, int num_lines, int num_holes) { } // Shuffle column indices for (int i = env->n_cols - 1; i > 0; i--) { - int j = rand() % (i + 1); + int j = rand_r(&env->rng) % (i + 1); int temp = cols[i]; cols[i] = cols[j]; cols[j] = temp; @@ -425,7 +427,7 @@ void c_reset(Tetris *env) { env->tick_garbage = 0; env->can_swap = 1; - env->ep_return = 0.0; + env->episode_return = 0.0; env->count_combos = 0; env->lines_deleted = 0; env->atn_count_hard_drop = 0; @@ -477,7 +479,7 @@ void place_tetromino(Tetris *env) { env->lines_deleted += lines_deleted; env->score += SCORE_COMBO[lines_deleted]; env->rewards[0] += REWARD_COMBO[lines_deleted]; - env->ep_return += REWARD_COMBO[lines_deleted]; + env->episode_return += REWARD_COMBO[lines_deleted]; // These determine the game difficulty. Consider making them args. env->game_level = 1 + env->lines_deleted / LINES_PER_LEVEL; @@ -505,7 +507,7 @@ void c_step(Tetris *env) { env->cur_tetromino_col -= 1; } else { env->rewards[0] += REWARD_INVALID_ACTION; - env->ep_return += REWARD_INVALID_ACTION; + env->episode_return += REWARD_INVALID_ACTION; } } if (action == ACTION_RIGHT) { @@ -513,7 +515,7 @@ void c_step(Tetris *env) { env->cur_tetromino_col += 1; } else { env->rewards[0] += REWARD_INVALID_ACTION; - env->ep_return += REWARD_INVALID_ACTION; + env->episode_return += REWARD_INVALID_ACTION; } } if (action == ACTION_ROTATE) { @@ -521,10 +523,10 @@ void c_step(Tetris *env) { if (can_rotate(env)) { env->cur_tetromino_rot = (env->cur_tetromino_rot + 1) % NUM_ROTATIONS; env->rewards[0] += REWARD_ROTATE; - env->ep_return += REWARD_ROTATE; + env->episode_return += REWARD_ROTATE; } else { env->rewards[0] += REWARD_INVALID_ACTION; - env->ep_return += REWARD_INVALID_ACTION; + env->episode_return += REWARD_INVALID_ACTION; } } if (action == ACTION_SOFT_DROP) { @@ -533,10 +535,10 @@ void c_step(Tetris *env) { env->cur_tetromino_row += 1; env->score += SCORE_SOFT_DROP; // env->rewards[0] += REWARD_SOFT_DROP; - // env->ep_return += REWARD_SOFT_DROP; + // env->episode_return += REWARD_SOFT_DROP; } else { env->rewards[0] += REWARD_INVALID_ACTION; - env->ep_return += REWARD_INVALID_ACTION; + env->episode_return += REWARD_INVALID_ACTION; } } if (action == ACTION_HOLD) { @@ -560,7 +562,7 @@ void c_step(Tetris *env) { } } else { env->rewards[0] += REWARD_INVALID_ACTION; - env->ep_return += REWARD_INVALID_ACTION; + env->episode_return += REWARD_INVALID_ACTION; } } if (action == ACTION_HARD_DROP) { @@ -569,7 +571,7 @@ void c_step(Tetris *env) { env->cur_tetromino_row += 1; // NOTE: this seems to be a super effective reward trick env->rewards[0] += REWARD_HARD_DROP; - env->ep_return += REWARD_HARD_DROP; + env->episode_return += REWARD_HARD_DROP; } env->score += SCORE_HARD_DROP; place_tetromino(env); diff --git a/pufferlib/ocean/tetris/tetrominoes.h b/ocean/tetris/tetrominoes.h similarity index 100% rename from pufferlib/ocean/tetris/tetrominoes.h rename to ocean/tetris/tetrominoes.h diff --git a/pufferlib/ocean/tmaze/binding.c b/ocean/tmaze/binding.c similarity index 100% rename from pufferlib/ocean/tmaze/binding.c rename to ocean/tmaze/binding.c diff --git a/pufferlib/ocean/tmaze/tmaze.c b/ocean/tmaze/tmaze.c similarity index 100% rename from pufferlib/ocean/tmaze/tmaze.c rename to ocean/tmaze/tmaze.c diff --git a/pufferlib/ocean/tmaze/tmaze.h b/ocean/tmaze/tmaze.h similarity index 100% rename from pufferlib/ocean/tmaze/tmaze.h rename to ocean/tmaze/tmaze.h diff --git a/ocean/tower_climb/binding.c b/ocean/tower_climb/binding.c new file mode 100644 index 0000000000..891364167a --- /dev/null +++ b/ocean/tower_climb/binding.c @@ -0,0 +1,86 @@ +#include "tower_climb.h" +#define OBS_SIZE 228 +#define NUM_ATNS 1 +#define ACT_SIZES {6} +#define OBS_TENSOR_T ByteTensor + +#define MY_VEC_INIT +#define Env CTowerClimb +#include "vecenv.h" + +Env* my_vec_init(int* num_envs_out, int* buffer_env_starts, int* buffer_env_counts, + Dict* vec_kwargs, Dict* env_kwargs) { + int num_envs = (int)dict_get(vec_kwargs, "total_agents")->value; + int num_buffers = (int)dict_get(vec_kwargs, "num_buffers")->value; + + float reward_climb_row = dict_get(env_kwargs, "reward_climb_row")->value; + float reward_fall_row = dict_get(env_kwargs, "reward_fall_row")->value; + float reward_illegal_move = dict_get(env_kwargs, "reward_illegal_move")->value; + float reward_move_block = dict_get(env_kwargs, "reward_move_block")->value; + + const char* path = "resources/tower_climb/maps.bin"; + int num_maps = 0; + + Level* levels = load_levels_from_file(&num_maps, path); + if (levels == NULL) { + *num_envs_out = 0; + return NULL; + } + + PuzzleState* puzzle_states = calloc(num_maps, sizeof(PuzzleState)); + for (int i = 0; i < num_maps; i++) { + init_puzzle_state(&puzzle_states[i]); + levelToPuzzleState(&levels[i], &puzzle_states[i]); + } + + Env* envs = (Env*)calloc(num_envs, sizeof(Env)); + + for (int i = 0; i < num_envs; i++) { + Env* env = &envs[i]; + env->rng = i; + env->num_agents = 1; + env->reward_climb_row = reward_climb_row; + env->reward_fall_row = reward_fall_row; + env->reward_illegal_move = reward_illegal_move; + env->reward_move_block = reward_move_block; + env->all_levels = levels; + env->all_puzzles = puzzle_states; + env->num_maps = num_maps; + init(env); + } + + int agents_per_buffer = num_envs / num_buffers; + int buf = 0; + int buf_agents = 0; + buffer_env_starts[0] = 0; + buffer_env_counts[0] = 0; + for (int i = 0; i < num_envs; i++) { + buf_agents += envs[i].num_agents; + buffer_env_counts[buf]++; + if (buf_agents >= agents_per_buffer && buf < num_buffers - 1) { + buf++; + buffer_env_starts[buf] = i + 1; + buffer_env_counts[buf] = 0; + buf_agents = 0; + } + } + + *num_envs_out = num_envs; + return envs; +} + +void my_init(Env* env, Dict* kwargs) { + env->num_agents = 1; + env->reward_climb_row = dict_get(kwargs, "reward_climb_row")->value; + env->reward_fall_row = dict_get(kwargs, "reward_fall_row")->value; + env->reward_illegal_move = dict_get(kwargs, "reward_illegal_move")->value; + env->reward_move_block = dict_get(kwargs, "reward_move_block")->value; + init(env); +} + +void my_log(Log* log, Dict* out) { + dict_set(out, "perf", log->perf); + dict_set(out, "score", log->score); + dict_set(out, "episode_return", log->episode_return); + dict_set(out, "episode_length", log->episode_length); +} diff --git a/ocean/tower_climb/tower_climb.c b/ocean/tower_climb/tower_climb.c new file mode 100644 index 0000000000..a393d3376d --- /dev/null +++ b/ocean/tower_climb/tower_climb.c @@ -0,0 +1,130 @@ +#include +#include +#include "tower_climb.h" +#include "puffernet.h" + +void demo() { + Weights* weights = load_weights("resources/tower_climb/tower_climb_weights.bin"); + int logit_sizes[1] = {6}; + PufferNet* net = make_puffernet(weights, 1, 228, 256, 5, logit_sizes, 1); + const char* path = "resources/tower_climb/maps.bin"; + + int num_maps = 0; + Level* levels = load_levels_from_file(&num_maps, path); + if (levels == NULL || num_maps == 0) { + fprintf(stderr, "Failed to load maps for demo. Pre-generate maps with generate_maps.py and put maps.bin under resources/tower_climb.\n"); + return; + } + + PuzzleState* puzzle_states = calloc(num_maps, sizeof(PuzzleState)); + + srand(time(NULL)); + + for (int i = 0; i < num_maps; i++) { + init_puzzle_state(&puzzle_states[i]); + levelToPuzzleState(&levels[i], &puzzle_states[i]); + } + + CTowerClimb* env = allocate(); + env->num_maps = num_maps; + env->all_levels = levels; + env->all_puzzles = puzzle_states; + c_reset(env); + c_render(env); + Client* client = env->client; + client->enable_animations = 1; + int tick = 0; + while (!WindowShouldClose()) { + if (tick % 6 == 0 && !client->isMoving) { + tick = 0; + int human_action = env->actions[0]; + + // Convert unsigned char observations to float + for (int i = 0; i < 228; i++) { + net->obs[i] = (float)env->observations[i]; + } + forward_puffernet(net, net->obs, env->actions); + + if (IsKeyDown(KEY_LEFT_SHIFT)) { + env->actions[0] = human_action; + } + c_step(env); + if (IsKeyDown(KEY_LEFT_SHIFT)) { + env->actions[0] = NOOP; + } + } + tick++; + if (IsKeyDown(KEY_LEFT_SHIFT)) { + // Camera controls + if (IsKeyPressed(KEY_UP)) { // || IsKeyPressed(KEY_W)) { + env->actions[0] = UP; + } + if (IsKeyPressed(KEY_LEFT)) { //|| IsKeyPressed(KEY_A)) { + env->actions[0] = LEFT; + } + if (IsKeyPressed(KEY_RIGHT)) { //|| IsKeyPressed(KEY_D)) { + env->actions[0] = RIGHT; + } + if (IsKeyPressed(KEY_DOWN)) { //|| IsKeyPressed(KEY_S)){ + env->actions[0] = DOWN; + } + if (IsKeyPressed(KEY_SPACE)){ + env->actions[0] = GRAB; + } + if (IsKeyPressed(KEY_RIGHT_SHIFT)){ + env->actions[0] = DROP; + } + } + c_render(env); + + // Handle delayed level reset after puffer animation finishes + if (env->pending_reset) { + bool shouldReset = false; + + if (env->celebrationStarted) { + // Wait for full celebration sequence: 0.8s climbing + 0.4s beam + 0.7s banner = 1.9s total + float celebrationDuration = GetTime() - env->celebrationStartTime; + shouldReset = (celebrationDuration >= 1.9f); + } else { + // No celebration; reset when banner finishes + shouldReset = (!client->showBanner || client->bannerType != 1); + } + + if (shouldReset) { + env->pending_reset = false; + c_reset(env); + } + } + } + close_client(client); + free_allocated(env); + free_puffernet(net); + free(weights); + for (int i = 0; i < num_maps; i++) { + free(levels[i].map); + } + free(levels); + free(puzzle_states); +} + +void performance_test() { + long test_time = 10; + CTowerClimb* env = allocate(); + int seed = 0; + init_random_level(env, 8, 25, 15, seed); + long start = time(NULL); + int i = 0; + while (time(NULL) - start < test_time) { + env->actions[0] = rand() % 5; + c_step(env); + i++; + } + long end = time(NULL); + printf("SPS: %ld\n", i / (end - start)); + free_allocated(env); +} + +int main() { + demo(); + return 0; +} diff --git a/pufferlib/ocean/tower_climb/tower_climb.h b/ocean/tower_climb/tower_climb.h similarity index 96% rename from pufferlib/ocean/tower_climb/tower_climb.h rename to ocean/tower_climb/tower_climb.h index e865724931..2485e4e987 100644 --- a/pufferlib/ocean/tower_climb/tower_climb.h +++ b/ocean/tower_climb/tower_climb.h @@ -57,7 +57,7 @@ #define TEST_BIT(mask, i) ( ((mask)[(i)/8] & (1 << ((i)%8))) != 0 ) // BFS -#define MAX_BFS_SIZE 10000000 +#define MAX_BFS_SIZE 40000000 #define MAX_NEIGHBORS 6 // based on action space // hash table @@ -89,7 +89,7 @@ static const int wrap_orientation[4][2] = { typedef struct Level Level; struct Level { - int* map; + unsigned char* map; int rows; int cols; int size; @@ -99,7 +99,7 @@ struct Level { }; void init_level(Level* lvl){ - lvl->map = calloc(1000,sizeof(unsigned int)); + lvl->map = calloc(BLOCK_BYTES, sizeof(unsigned char)); lvl->rows = 10; lvl->cols = 10; lvl->size = 100; @@ -111,7 +111,7 @@ void init_level(Level* lvl){ void reset_level(Level* lvl){ lvl->goal_location = 999; lvl->spawn_location = 0; - memset(lvl->map, 0, 1000 * sizeof(unsigned int)); + memset(lvl->map, 0, BLOCK_BYTES * sizeof(unsigned char)); } void free_level(Level* lvl){ @@ -153,10 +153,11 @@ void trigger_banner(Client* client, int type); struct CTowerClimb { Client* client; unsigned char* observations; - int* actions; + float* actions; float* rewards; - unsigned char* terminals; + float* terminals; unsigned char* truncations; + int num_agents; Log log; Log buffer; float score; @@ -181,6 +182,7 @@ struct CTowerClimb { float visitedTimes[100]; // Time when each position was visited int visitedCount; int visitedIndex; + unsigned int rng; }; void add_log(CTowerClimb* env) { @@ -193,12 +195,7 @@ void add_log(CTowerClimb* env) { } void levelToPuzzleState(Level* level, PuzzleState* state) { - memset(state->blocks, 0, BLOCK_BYTES); - for (int i = 0; i < level->total_length; i++) { - if (level->map[i] == 1) { - SET_BIT(state->blocks, i); - } - } + memcpy(state->blocks, level->map, BLOCK_BYTES); state->robot_position = level->spawn_location; state->robot_orientation = UP; state->robot_state = 0; @@ -227,7 +224,7 @@ void setPuzzle(CTowerClimb* env, PuzzleState* src, Level* lvl){ env->state->robot_orientation = src->robot_orientation; env->state->robot_state = src->robot_state; env->state->block_grabbed = src->block_grabbed; - memcpy(env->level->map, lvl->map, lvl->total_length * sizeof(int)); + memcpy(env->level->map, lvl->map, BLOCK_BYTES); env->level->rows = lvl->rows; env->level->cols = lvl->cols; env->level->size = lvl->size; @@ -240,16 +237,15 @@ CTowerClimb* allocate() { CTowerClimb* env = (CTowerClimb*)calloc(1, sizeof(CTowerClimb)); init(env); env->observations = (unsigned char*)calloc(OBS_VISION+PLAYER_OBS, sizeof(unsigned char)); - env->actions = (int*)calloc(1, sizeof(int)); + env->actions = (float*)calloc(1, sizeof(float)); env->rewards = (float*)calloc(1, sizeof(float)); - env->terminals = (unsigned char*)calloc(1, sizeof(unsigned char)); + env->terminals = (float*)calloc(1, sizeof(float)); return env; } void c_close(CTowerClimb* env) { - free_level(env->level); - free_puzzle_state(env->state); - free(env); + free_level(env->level); + free_puzzle_state(env->state); } void free_allocated(CTowerClimb* env) { @@ -258,6 +254,7 @@ void free_allocated(CTowerClimb* env) { free(env->terminals); free(env->rewards); c_close(env); + free(env); } void calculate_window_bounds(int* bounds, int center_pos, int window_size, int max_size) { @@ -330,7 +327,7 @@ void compute_observations(CTowerClimb* env) { } void c_reset(CTowerClimb* env) { - env->terminals[0] = 0; + env->terminals[0] = 0.0f; env->rows_cleared = 0; env->goal_reached = false; env->celebrationStarted = false; @@ -345,14 +342,14 @@ void c_reset(CTowerClimb* env) { // Always use pre-generated maps (ensure at least 1 exists during initialization) // printf("num maps: %d\n", env->num_maps); if (env->num_maps > 0) { - int idx = rand() % env->num_maps; + int idx = rand_r(&env->rng) % env->num_maps; setPuzzle(env, &env->all_puzzles[idx], &env->all_levels[idx]); } else { // Emergency fallback: use a simple default level env->level->goal_location = 999; env->level->spawn_location = 0; - memset(env->level->map, 0, env->level->total_length * sizeof(int)); - env->level->map[0] = 1; // Ground block + memset(env->level->map, 0, BLOCK_BYTES); + SET_BIT(env->level->map, 0); // Ground block levelToPuzzleState(env->level, env->state); } @@ -1086,6 +1083,11 @@ int bfs(PuzzleState* start, int maxDepth, Level* lvl, int min_moves) { for (int i = 0; i < nCount; i++) { PuzzleState* nxt = &neighbors[i].state; if (!isVisited(nxt)) { + if (back >= MAX_BFS_SIZE) { + printf("BFS queue overflow on add! Aborting search for this level.\n"); + free(nxt->blocks); // Free the state we are not adding + continue; // Skip adding more neighbors + } markVisited(nxt); neighbors[i].depth = current.depth + 1; neighbors[i].parent = currentIndex; @@ -1129,7 +1131,7 @@ int verify_level(Level* level, int max_moves, int min_moves){ return solvable; } -void gen_level(Level* lvl, int goal_level) { +void gen_level(Level* lvl, int goal_level, unsigned int* rng) { // Initialize an illegal level in case we need to return early int legal_width_size = 8; int legal_depth_size = 8; @@ -1145,24 +1147,23 @@ void gen_level(Level* lvl, int goal_level) { int within_legal_bounds = x>=1 && x < legal_width_size && z >= 1 && z < legal_depth_size && y>=1 && y < goal_level; int allowed_block_placement = within_legal_bounds && (z <= (legal_depth_size - y)); if (allowed_block_placement){ - int chance = (rand() % 2 ==0) ? 1 : 0; - lvl->map[block_index] = chance; + int chance = (rand_r(rng) % 2 ==0) ? 1 : 0; + if (chance) SET_BIT(lvl->map, block_index); // create spawn point above an existing block - if (spawn_created == 0 && y == 2 && lvl->map[block_index - area] == 1){ + if (spawn_created == 0 && y == 2 && TEST_BIT(lvl->map, block_index - area)){ spawn_created = 1; spawn_index = block_index; - lvl->map[spawn_index] = 0; + CLEAR_BIT(lvl->map, spawn_index); } } if (!goal_created && y == goal_level && - (lvl->map[block_index + col_max - area] == 1 || - lvl->map[block_index - 1 - area] == 1 || - lvl->map[block_index + 1 - area] == 1)) { + (TEST_BIT(lvl->map, block_index + col_max - area) || + TEST_BIT(lvl->map, block_index - 1 - area) || + TEST_BIT(lvl->map, block_index + 1 - area))) { // 33% chance to place goal here, unless we're at the last valid position - if (rand() % 3 == 0 || (x == col_max-1 && z == 0)) { + if (rand_r(rng) % 3 == 0 || (x == col_max-1 && z == 0)) { goal_created = 1; goal_index = block_index; - lvl->map[goal_index] = 2; } } } @@ -1183,25 +1184,23 @@ void gen_level(Level* lvl, int goal_level) { } void init_random_level(CTowerClimb* env, int goal_level, int max_moves, int min_moves, int seed) { - time_t t; - srand((unsigned) time(&t) + seed); // Increment seed for each level reset_level(env->level); - gen_level(env->level, goal_level); + gen_level(env->level, goal_level, &env->rng); // guarantee a map is created while(env->level->spawn_location == 0 || env->level->goal_location == 999 || verify_level(env->level,max_moves, min_moves) == 0){ reset_level(env->level); - gen_level(env->level,goal_level); + gen_level(env->level, goal_level, &env->rng); } levelToPuzzleState(env->level, env->state); } void cy_init_random_level(Level* level, int goal_level, int max_moves, int min_moves, int seed) { - time_t t; - srand((unsigned) time(&t) + seed); // Increment seed for each level - gen_level(level, goal_level); + unsigned int rng = (unsigned int)seed; + gen_level(level, goal_level, &rng); // guarantee a map is created while(level->spawn_location == 0 || level->goal_location == 999 || verify_level(level,max_moves, min_moves) == 0){ - gen_level(level, goal_level); + reset_level(level); + gen_level(level, goal_level, &rng); } } @@ -2135,6 +2134,47 @@ void c_render(CTowerClimb* env) { render_scene(client, env); } +Level* load_levels_from_file(int* num_maps, const char* path) { + FILE* fp = fopen(path, "rb"); + if (fp == NULL) { + perror("Failed to open file for reading"); + *num_maps = 0; + return NULL; + } + + if (fread(num_maps, sizeof(int), 1, fp) != 1) { + fprintf(stderr, "Failed to read map count from %s\n", path); + fclose(fp); + *num_maps = 0; + return NULL; + } + + Level* levels = calloc(*num_maps, sizeof(Level)); + if (levels == NULL) { + fprintf(stderr, "Failed to allocate memory for levels\n"); + fclose(fp); + *num_maps = 0; + return NULL; + } + + for (int i = 0; i < *num_maps; i++) { + // Read struct fields individually to match the save order + fread(&levels[i].rows, sizeof(int), 1, fp); + fread(&levels[i].cols, sizeof(int), 1, fp); + fread(&levels[i].size, sizeof(int), 1, fp); + fread(&levels[i].total_length, sizeof(int), 1, fp); + fread(&levels[i].goal_location, sizeof(int), 1, fp); + fread(&levels[i].spawn_location, sizeof(int), 1, fp); + + // Allocate and read the map data + levels[i].map = calloc(BLOCK_BYTES, sizeof(unsigned char)); + fread(levels[i].map, sizeof(unsigned char), BLOCK_BYTES, fp); + } + + fclose(fp); + return levels; +} + void close_client(Client* client) { // First unload all animations UnloadModelAnimations(client->animations, 8); // We know we have 8 animations diff --git a/ocean/trash_pickup/binding.c b/ocean/trash_pickup/binding.c new file mode 100644 index 0000000000..8b74f4e539 --- /dev/null +++ b/ocean/trash_pickup/binding.c @@ -0,0 +1,26 @@ +#include "trash_pickup.h" +#define OBS_SIZE 605 +#define NUM_ATNS 1 +#define ACT_SIZES {4} +#define OBS_TENSOR_T ByteTensor + +#define Env CTrashPickupEnv +#include "vecenv.h" + +void my_init(Env* env, Dict* kwargs) { + env->num_agents = dict_get(kwargs, "num_agents")->value; + env->grid_size = dict_get(kwargs, "grid_size")->value; + env->num_trash = dict_get(kwargs, "num_trash")->value; + env->num_bins = dict_get(kwargs, "num_bins")->value; + env->max_steps = dict_get(kwargs, "max_steps")->value; + env->agent_sight_range = dict_get(kwargs, "agent_sight_range")->value; + initialize_env(env); +} + +void my_log(Log* log, Dict* out) { + dict_set(out, "perf", log->perf); + dict_set(out, "score", log->score); + dict_set(out, "episode_return", log->episode_return); + dict_set(out, "episode_length", log->episode_length); + dict_set(out, "trash_collected", log->trash_collected); +} diff --git a/ocean/trash_pickup/trash_pickup.c b/ocean/trash_pickup/trash_pickup.c new file mode 100644 index 0000000000..b3b885b7e7 --- /dev/null +++ b/ocean/trash_pickup/trash_pickup.c @@ -0,0 +1,53 @@ +#include +#include "trash_pickup.h" +#include "puffernet.h" + +void demo() { + CTrashPickupEnv env = { + .grid_size = 20, + .num_agents = 8, + .num_trash = 40, + .num_bins = 2, + .max_steps = 300, + .agent_sight_range = 5, + .do_human_control = true + }; + + Weights* weights = load_weights("resources/trash_pickup/trash_pickup_weights.bin"); + int logit_sizes[1] = {4}; + PufferNet* net = make_puffernet(weights, env.num_agents, 605, 128, 2, logit_sizes, 1); + + allocate(&env); + c_reset(&env); + c_render(&env); + + int tick = 0; + while (!WindowShouldClose()) { + if (tick % 2 == 0) { + for (int e = 0; e < env.num_agents * 605; e++) { + net->obs[e] = env.observations[e]; + } + forward_puffernet(net, net->obs, env.actions); + + if (IsKeyDown(KEY_LEFT_SHIFT)) { + if (IsKeyDown(KEY_UP) || IsKeyDown(KEY_W)) env.actions[0] = ACTION_UP; + if (IsKeyDown(KEY_LEFT) || IsKeyDown(KEY_A)) env.actions[0] = ACTION_LEFT; + if (IsKeyDown(KEY_RIGHT) || IsKeyDown(KEY_D)) env.actions[0] = ACTION_RIGHT; + if (IsKeyDown(KEY_DOWN) || IsKeyDown(KEY_S)) env.actions[0] = ACTION_DOWN; + } + + c_step(&env); + } + tick++; + c_render(&env); + } + + free_puffernet(net); + free(weights); + free_allocated(&env); +} + +int main() { + demo(); + return 0; +} diff --git a/pufferlib/ocean/trash_pickup/trash_pickup.h b/ocean/trash_pickup/trash_pickup.h similarity index 97% rename from pufferlib/ocean/trash_pickup/trash_pickup.h rename to ocean/trash_pickup/trash_pickup.h index ebafd4445a..308e675ca0 100644 --- a/pufferlib/ocean/trash_pickup/trash_pickup.h +++ b/ocean/trash_pickup/trash_pickup.h @@ -51,13 +51,13 @@ typedef struct { // Interface for PufferLib Client* client; char* observations; - int* actions; + float* actions; float* rewards; - unsigned char* terminals; + float* terminals; + int num_agents; Log log; int grid_size; - int num_agents; int num_trash; int num_bins; int max_steps; @@ -75,6 +75,7 @@ typedef struct { Entity* entities; // Indicies (0 - num_agents) for agents, (num_agents - num_bins) for bins, (num_bins - num_trash) for trash. bool do_human_control; + unsigned int rng; } CTrashPickupEnv; void add_log(CTrashPickupEnv* env, Log* log) { @@ -190,8 +191,8 @@ void place_random_entities(CTrashPickupEnv* env, int count, int item_type, int g int placed = 0; while (placed < count) { - int x = rand() % env->grid_size; - int y = rand() % env->grid_size; + int x = rand_r(&env->rng) % env->grid_size; + int y = rand_r(&env->rng) % env->grid_size; GridCell* gridCell = &env->grid[get_grid_index(env, x, y)]; @@ -361,15 +362,15 @@ void initialize_env(CTrashPickupEnv* env) { void allocate(CTrashPickupEnv* env) { initialize_env(env); env->observations = (char*)calloc(env->total_num_obs, sizeof(char)); - env->actions = (int*)calloc(env->num_agents, sizeof(int)); + env->actions = (float*)calloc(env->num_agents, sizeof(float)); env->rewards = (float*)calloc(env->num_agents, sizeof(float)); - env->terminals = (unsigned char*)calloc(env->num_agents, sizeof(unsigned char)); + env->terminals = (float*)calloc(env->num_agents, sizeof(float)); } void c_step(CTrashPickupEnv* env) { // Reset reward for each agent memset(env->rewards, 0, sizeof(float) * env->num_agents); - memset(env->terminals, 0, sizeof(unsigned char) * env->num_agents); + memset(env->terminals, 0, sizeof(float) * env->num_agents); for (int i = 0; i < env->num_agents; i++) { move_agent(env, i, env->actions[i]); @@ -377,9 +378,11 @@ void c_step(CTrashPickupEnv* env) { } env->current_step++; - if (env->current_step >= env->max_steps || is_episode_over(env)) + if (env->current_step >= env->max_steps || is_episode_over(env)) { - memset(env->terminals, 1, sizeof(unsigned char) * env->num_agents); + for (int i = 0; i < env->num_agents; i++) { + env->terminals[i] = 1.0f; + } Log log = {0}; diff --git a/ocean/tripletriad/binding.c b/ocean/tripletriad/binding.c new file mode 100644 index 0000000000..3e40ee2cc9 --- /dev/null +++ b/ocean/tripletriad/binding.c @@ -0,0 +1,25 @@ +#include "tripletriad.h" +#define OBS_SIZE 114 +#define NUM_ATNS 1 +#define ACT_SIZES {14} +#define OBS_TENSOR_T FloatTensor + +#define Env CTripleTriad +#include "vecenv.h" + +void my_init(Env* env, Dict* kwargs) { + env->num_agents = 1; + env->width = dict_get(kwargs, "width")->value; + env->height = dict_get(kwargs, "height")->value; + env->card_width = dict_get(kwargs, "card_width")->value; + env->card_height = dict_get(kwargs, "card_height")->value; + init_ctripletriad(env); +} + +void my_log(Log* log, Dict* out) { + dict_set(out, "perf", log->perf); + dict_set(out, "score", log->score); + dict_set(out, "episode_return", log->episode_return); + dict_set(out, "episode_length", log->episode_length); + dict_set(out, "n", log->n); +} diff --git a/pufferlib/ocean/tripletriad/tripletriad.c b/ocean/tripletriad/tripletriad.c similarity index 52% rename from pufferlib/ocean/tripletriad/tripletriad.c rename to ocean/tripletriad/tripletriad.c index 3fa7862544..a8d661d009 100644 --- a/pufferlib/ocean/tripletriad/tripletriad.c +++ b/ocean/tripletriad/tripletriad.c @@ -4,10 +4,10 @@ #define NOOP -1 -void interactive() { - Weights* weights = load_weights("resources/tripletriad/tripletriad_weights.bin", 148751); +void demo() { + Weights* weights = load_weights("resources/tripletriad/tripletriad_weights.bin"); int logit_sizes[1] = {14}; - LinearLSTM* net = make_linearlstm(weights, 1, 114, logit_sizes, 1); + PufferNet* net = make_puffernet(weights, 1, 114, 256, 2, logit_sizes, 1); CTripleTriad env = { .width = 990, @@ -26,41 +26,28 @@ void interactive() { while (!WindowShouldClose()) { action = NOOP; - // User can take control of the player if (IsKeyDown(KEY_LEFT_SHIFT)) { - // Handle Card Selection ( 1-5 for selecting a card) if (IsKeyPressed(KEY_ONE)) action = SELECT_CARD_1; if (IsKeyPressed(KEY_TWO)) action = SELECT_CARD_2; if (IsKeyPressed(KEY_THREE)) action = SELECT_CARD_3; if (IsKeyPressed(KEY_FOUR)) action = SELECT_CARD_4; if (IsKeyPressed(KEY_FIVE)) action = SELECT_CARD_5; - // Handle Card Placement ( 1-9 for placing a card) if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) { Vector2 mousePos = GetMousePosition(); - - // Calculate the offset for the board - int boardOffsetX = 196 + 10; // 196 from the DrawRectangle call in render(), plus 10 for padding - int boardOffsetY = 30; // From the DrawRectangle call in render() - - // Adjust mouse position relative to the board + int boardOffsetX = 196 + 10; + int boardOffsetY = 30; int relativeX = mousePos.x - boardOffsetX; int relativeY = mousePos.y - boardOffsetY; - - // Calculate cell indices int cellX = relativeX / env.card_width; int cellY = relativeY / env.card_height; - - // Calculate the cell index (1-9) based on the click position - int cellIndex = cellY * 3 + cellX+1; - - // Ensure the click is within the game board + int cellIndex = cellY * 3 + cellX + 1; if (cellX >= 0 && cellX < 3 && cellY >= 0 && cellY < 3) { action = cellIndex + 4; } } } else if (tick % 45 == 0) { - forward_linearlstm(net, env.observations, env.actions); + forward_puffernet(net, env.observations, env.actions); action = env.actions[0]; } @@ -73,38 +60,13 @@ void interactive() { c_render(&env); } - free_linearlstm(net); + free_puffernet(net); free(weights); close_client(env.client); free_allocated_ctripletriad(&env); } -void performance_test() { - long test_time = 10; - CTripleTriad env = { - .width = 990, - .height = 690, - .card_width = 576 / 3, - .card_height = 672 / 3, - .game_over = 0, - .num_cards = 10, - }; - allocate_ctripletriad(&env); - c_reset(&env); - - long start = time(NULL); - int i = 0; - while (time(NULL) - start < test_time) { - c_step(&env); - i++; - } - long end = time(NULL); - printf("SPS: %ld\n", i / (end - start)); - free_allocated_ctripletriad(&env); -} - int main() { - // performance_test(); - interactive(); + demo(); return 0; } diff --git a/pufferlib/ocean/tripletriad/tripletriad.h b/ocean/tripletriad/tripletriad.h similarity index 97% rename from pufferlib/ocean/tripletriad/tripletriad.h rename to ocean/tripletriad/tripletriad.h index 1e39cf2e65..c61d394bf2 100644 --- a/pufferlib/ocean/tripletriad/tripletriad.h +++ b/ocean/tripletriad/tripletriad.h @@ -40,9 +40,10 @@ typedef struct Client Client; typedef struct CTripleTriad CTripleTriad; struct CTripleTriad { float* observations; - int* actions; + float* actions; float* rewards; - unsigned char* terminals; + float* terminals; + int num_agents; Log log; int card_width; int card_height; @@ -64,6 +65,7 @@ struct CTripleTriad { float episode_return; float episode_length; Client* client; + unsigned int rng; }; void add_log(CTripleTriad* env) { @@ -88,7 +90,7 @@ void generate_cards_in_hand(CTripleTriad* env) { for(int i=0; i< 2; i++) { for(int j=0; j< 5; j++) { for(int k=0; k< 4; k++) { - env->cards_in_hand[i][j][k] = (rand() % 7) + 1; + env->cards_in_hand[i][j][k] = (rand_r(&env->rng) % 7) + 1; } } } @@ -171,9 +173,9 @@ void init_ctripletriad(CTripleTriad* env) { } void allocate_ctripletriad(CTripleTriad* env) { - env->actions = (int*)calloc(1, sizeof(int)); + env->actions = (float*)calloc(1, sizeof(float)); env->observations = (float*)calloc(env->width*env->height, sizeof(float)); - env->terminals = (unsigned char*)calloc(1, sizeof(unsigned char)); + env->terminals = (float*)calloc(1, sizeof(float)); env->rewards = (float*)calloc(1, sizeof(float)); init_ctripletriad(env); } @@ -264,7 +266,7 @@ void c_reset(CTripleTriad* env) { for(int i=0; i< 2; i++) { for(int j=0; j< 5; j++) { for(int k=0; k< 4; k++) { - env->cards_in_hand[i][j][k] = (rand() % 7) + 1; + env->cards_in_hand[i][j][k] = (rand_r(&env->rng) % 7) + 1; } } } @@ -378,7 +380,7 @@ int get_bot_card_placement(CTripleTriad* env) { // Randomly select a valid placement if (num_valid_placements > 0) { - return valid_placements[rand() % num_valid_placements]; + return valid_placements[rand_r(&env->rng) % num_valid_placements]; } // If no valid placements, return 0 (this should not happen in a normal game) @@ -398,7 +400,7 @@ int get_bot_card_selection(CTripleTriad* env) { // Randomly select a valid card if (num_valid_selections > 0) { - return valid_selections[rand() % num_valid_selections]; + return valid_selections[rand_r(&env->rng) % num_valid_selections]; } // If no valid selections, return 0 (this should not happen in a normal game) diff --git a/ocean/whisker_racer/binding.c b/ocean/whisker_racer/binding.c new file mode 100644 index 0000000000..d5fda89f66 --- /dev/null +++ b/ocean/whisker_racer/binding.c @@ -0,0 +1,51 @@ +#include "whisker_racer.h" +#define OBS_SIZE 3 +#define NUM_ATNS 1 +#define ACT_SIZES {3} +#define OBS_TYPE FLOAT +#define ACT_TYPE DOUBLE + +#define Env WhiskerRacer +#include "vecenv.h" + +void my_init(Env* env, Dict* kwargs) { + env->num_agents = 1; + env->frameskip = dict_get(kwargs, "frameskip")->value; + env->width = dict_get(kwargs, "width")->value; + env->height = dict_get(kwargs, "height")->value; + env->llw_ang = dict_get(kwargs, "llw_ang")->value; + env->flw_ang = dict_get(kwargs, "flw_ang")->value; + env->frw_ang = dict_get(kwargs, "frw_ang")->value; + env->rrw_ang = dict_get(kwargs, "rrw_ang")->value; + env->max_whisker_length = dict_get(kwargs, "max_whisker_length")->value; + env->turn_pi_frac = dict_get(kwargs, "turn_pi_frac")->value; + env->maxv = dict_get(kwargs, "maxv")->value; + env->render = dict_get(kwargs, "render")->value; + env->continuous = dict_get(kwargs, "continuous")->value; + env->reward_yellow = dict_get(kwargs, "reward_yellow")->value; + env->reward_green = dict_get(kwargs, "reward_green")->value; + env->gamma = dict_get(kwargs, "gamma")->value; + env->track_width = dict_get(kwargs, "track_width")->value; + env->num_radial_sectors = dict_get(kwargs, "num_radial_sectors")->value; + env->num_points = dict_get(kwargs, "num_points")->value; + env->bezier_resolution = dict_get(kwargs, "bezier_resolution")->value; + env->w_ang = dict_get(kwargs, "w_ang")->value; + env->corner_thresh = dict_get(kwargs, "corner_thresh")->value; + env->ftmp1 = dict_get(kwargs, "ftmp1")->value; + env->ftmp2 = dict_get(kwargs, "ftmp2")->value; + env->ftmp3 = dict_get(kwargs, "ftmp3")->value; + env->ftmp4 = dict_get(kwargs, "ftmp4")->value; + env->mode7 = dict_get(kwargs, "mode7")->value; + env->render_many = dict_get(kwargs, "render_many")->value; + env->rng = dict_get(kwargs, "rng")->value; + env->method = dict_get(kwargs, "method")->value; + env->i = dict_get(kwargs, "i")->value; + init(env); +} + +void my_log(Log* log, Dict* out) { + dict_set(out, "perf", log->perf); + dict_set(out, "score", log->score); + dict_set(out, "episode_return", log->episode_return); + dict_set(out, "episode_length", log->episode_length); +} diff --git a/pufferlib/ocean/whisker_racer/whisker_racer.c b/ocean/whisker_racer/whisker_racer.c similarity index 98% rename from pufferlib/ocean/whisker_racer/whisker_racer.c rename to ocean/whisker_racer/whisker_racer.c index 9be82283b4..5a7f7a27d0 100644 --- a/pufferlib/ocean/whisker_racer/whisker_racer.c +++ b/ocean/whisker_racer/whisker_racer.c @@ -4,7 +4,7 @@ void demo() { printf("demo\n"); - Weights* weights = load_weights("resources/whisker_racer/puffer_whisker_racer_weights.bin", 133124); + Weights* weights = load_weights("resources/whisker_racer/puffer_whisker_racer_weights.bin"); int logit_sizes[1] = {3}; LinearLSTM* net = make_linearlstm(weights, 1, 3, logit_sizes, 1); diff --git a/pufferlib/ocean/whisker_racer/whisker_racer.h b/ocean/whisker_racer/whisker_racer.h similarity index 99% rename from pufferlib/ocean/whisker_racer/whisker_racer.h rename to ocean/whisker_racer/whisker_racer.h index 5dcdff5630..f22c2d5235 100644 --- a/pufferlib/ocean/whisker_racer/whisker_racer.h +++ b/ocean/whisker_racer/whisker_racer.h @@ -58,9 +58,10 @@ typedef struct WhiskerRacer { Client* client; Log log; float* observations; - float* actions; + double* actions; float* rewards; - unsigned char* terminals; + float* terminals; + int num_agents; int i; int debug; @@ -948,9 +949,9 @@ void init(WhiskerRacer* env) { void allocate(WhiskerRacer* env) { init(env); env->observations = (float*)calloc(3, sizeof(float)); - env->actions = (float*)calloc(1, sizeof(float)); + env->actions = (double*)calloc(1, sizeof(double)); env->rewards = (float*)calloc(1, sizeof(float)); - env->terminals = (unsigned char*)calloc(1, sizeof(unsigned char)); + env->terminals = (float*)calloc(1, sizeof(float)); } void step_frame(WhiskerRacer* env, float action) { diff --git a/profile.sh b/profile.sh new file mode 100644 index 0000000000..f069a030ad --- /dev/null +++ b/profile.sh @@ -0,0 +1,30 @@ +nsys profile --force-overwrite true --capture-range=cudaProfilerApi --cuda-graph-trace=node --sample=none -o profile python -m pufferlib.pufferl train breakout --vec.num-buffers 1 --profile True +echo "All kernels" +nsys stats --report cuda_gpu_kern_sum:base --force-export=true profile.nsys-rep +echo "NVTX tags" +nsys stats --report nvtx_sum --force-export=true profile.nsys-rep +echo "Kernel groups" +nsys export --type=sqlite --force-overwrite=true -o profile.sqlite profile.nsys-rep +sqlite3 -header -column profile.sqlite " + SELECT + CASE + WHEN s.value LIKE '%gemm%' OR s.value LIKE '%Kernel2%' OR s.value LIKE '%splitKreduce%' THEN 'matmul' + WHEN s.value LIKE '%ppo_loss%' OR s.value LIKE '%ppo_var_mean%' THEN 'ppo_loss' + WHEN s.value LIKE '%mingru%' THEN 'mingru' + WHEN s.value LIKE '%muon%' THEN 'muon' + WHEN s.value LIKE '%cast%' OR s.value LIKE '%select_copy%' OR s.value LIKE '%index_copy%' OR s.value LIKE '%transpose%' THEN 'copy' + WHEN s.value LIKE '%sample_logits%' OR s.value LIKE '%multinomial%' THEN 'sample' + WHEN s.value LIKE '%puff_advantage%' THEN 'advantage' + WHEN s.value LIKE '%prio%' THEN 'prio_replay' + WHEN s.value LIKE '%assemble_decoder%' THEN 'decoder_grad' + ELSE s.value + END AS group_name, + COUNT(*) AS count, + ROUND(100.0 * SUM(k.end - k.start) / (SELECT SUM(end - start) FROM CUPTI_ACTIVITY_KIND_KERNEL), 1) AS 'time_%', + ROUND(SUM(k.end - k.start) / 1e6, 2) AS total_ms, + ROUND(AVG(k.end - k.start) / 1e3, 2) AS avg_us + FROM CUPTI_ACTIVITY_KIND_KERNEL k + JOIN StringIds s ON k.shortName = s.id + GROUP BY group_name + ORDER BY total_ms DESC; +" diff --git a/pufferlib/__init__.py b/pufferlib/__init__.py index f86643a4e8..e6002945e9 100644 --- a/pufferlib/__init__.py +++ b/pufferlib/__init__.py @@ -1,32 +1 @@ -__version__ = 3.0 - -import os -path = __path__[0] -link_to = os.path.join(path, 'resources') -try: - os.symlink(link_to, 'resources') -except FileExistsError: - pass - -# Silence noisy dependencies -import warnings -warnings.filterwarnings("ignore", category=DeprecationWarning) - -# Silence noisy packages -import sys -original_stdout = sys.stdout -original_stderr = sys.stderr -sys.stdout = open(os.devnull, 'w') -sys.stderr = open(os.devnull, 'w') -try: - import gymnasium - import pygame -except ImportError: - pass -sys.stdout.close() -sys.stderr.close() -sys.stdout = original_stdout -sys.stderr = original_stderr - -from pufferlib.pufferlib import * -from pufferlib import environments +__version__ = 4.0 diff --git a/pufferlib/cleanrl_ppo_atari.py b/pufferlib/cleanrl_ppo_atari.py deleted file mode 100644 index 595f62ab24..0000000000 --- a/pufferlib/cleanrl_ppo_atari.py +++ /dev/null @@ -1,337 +0,0 @@ -# docs and experiment results can be found at https://docs.cleanrl.dev/rl-algorithms/ppo/#ppo_ataripy -import os -import random -import time -from dataclasses import dataclass - -import gymnasium as gym -import numpy as np -import torch -import torch.nn as nn -import torch.optim as optim -import tyro -from torch.distributions.categorical import Categorical -from torch.utils.tensorboard import SummaryWriter - -from stable_baselines3.common.atari_wrappers import ( # isort:skip - ClipRewardEnv, - EpisodicLifeEnv, - FireResetEnv, - MaxAndSkipEnv, - NoopResetEnv, -) - -@dataclass -class Args: - exp_name: str = 'cleanrl_ppo_atari' - """the name of this experiment""" - seed: int = 1 - """seed of the experiment""" - torch_deterministic: bool = True - """if toggled, `torch.backends.cudnn.deterministic=False`""" - cuda: bool = True - """if toggled, cuda will be enabled by default""" - track: bool = False - """if toggled, this experiment will be tracked with Weights and Biases""" - wandb_project_name: str = "cleanRL" - """the wandb's project name""" - wandb_entity: str = None - """the entity (team) of wandb's project""" - capture_video: bool = False - """whether to capture videos of the agent performances (check out `videos` folder)""" - - # Algorithm specific arguments - env_id: str = "breakout" - """the id of the environment""" - total_timesteps: int = 10000000 - """total timesteps of the experiments""" - learning_rate: float = 2.5e-4 - """the learning rate of the optimizer""" - num_envs: int = 8 - """the number of parallel game environments""" - num_steps: int = 128 - """the number of steps to run in each environment per policy rollout""" - anneal_lr: bool = True - """Toggle learning rate annealing for policy and value networks""" - gamma: float = 0.99 - """the discount factor gamma""" - gae_lambda: float = 0.95 - """the lambda for the general advantage estimation""" - num_minibatches: int = 4 - """the number of mini-batches""" - update_epochs: int = 4 - """the K epochs to update the policy""" - norm_adv: bool = True - """Toggles advantages normalization""" - clip_coef: float = 0.1 - """the surrogate clipping coefficient""" - clip_vloss: bool = True - """Toggles whether or not to use a clipped loss for the value function, as per the paper.""" - ent_coef: float = 0.01 - """coefficient of the entropy""" - vf_coef: float = 0.5 - """coefficient of the value function""" - max_grad_norm: float = 0.5 - """the maximum norm for the gradient clipping""" - target_kl: float = None - """the target KL divergence threshold""" - - # to be filled in runtime - batch_size: int = 0 - """the batch size (computed in runtime)""" - minibatch_size: int = 0 - """the mini-batch size (computed in runtime)""" - num_iterations: int = 0 - """the number of iterations (computed in runtime)""" - - -def make_env(env_id, idx, capture_video, run_name): - def thunk(): - if capture_video and idx == 0: - env = gym.make(env_id, render_mode="rgb_array") - env = gym.wrappers.RecordVideo(env, f"videos/{run_name}") - else: - env = gym.make(env_id) - env = gym.wrappers.RecordEpisodeStatistics(env) - if capture_video: - if idx == 0: - env = gym.wrappers.RecordVideo(env, f"videos/{run_name}") - env = NoopResetEnv(env, noop_max=30) - env = MaxAndSkipEnv(env, skip=4) - env = EpisodicLifeEnv(env) - if "FIRE" in env.unwrapped.get_action_meanings(): - env = FireResetEnv(env) - env = ClipRewardEnv(env) - env = gym.wrappers.ResizeObservation(env, (84, 84)) - env = gym.wrappers.GrayScaleObservation(env) - env = gym.wrappers.FrameStack(env, 4) - return env - - return thunk - - -def layer_init(layer, std=np.sqrt(2), bias_const=0.0): - torch.nn.init.orthogonal_(layer.weight, std) - torch.nn.init.constant_(layer.bias, bias_const) - return layer - - -class Agent(nn.Module): - def __init__(self, envs): - super().__init__() - self.network = nn.Sequential( - layer_init(nn.Conv2d(4, 32, 8, stride=4)), - nn.ReLU(), - layer_init(nn.Conv2d(32, 64, 4, stride=2)), - nn.ReLU(), - layer_init(nn.Conv2d(64, 64, 3, stride=1)), - nn.ReLU(), - nn.Flatten(), - layer_init(nn.Linear(64 * 6 * 9, 512)), - nn.ReLU(), - ) - self.actor = layer_init(nn.Linear(512, envs.single_action_space.n), std=0.01) - self.critic = layer_init(nn.Linear(512, 1), std=1) - - def get_value(self, x): - x = x.permute(0, 2, 1, 3) - return self.critic(self.network(x / 255.0)) - - def get_action_and_value(self, x, action=None): - x = x.permute(0, 2, 1, 3) - hidden = self.network(x / 255.0) - logits = self.actor(hidden) - probs = Categorical(logits=logits) - if action is None: - action = probs.sample() - return action, probs.log_prob(action), probs.entropy(), self.critic(hidden) - - -if __name__ == "__main__": - args, _ = tyro.cli(Args, return_unknown_args=True) - args.batch_size = int(args.num_envs * args.num_steps) - args.minibatch_size = int(args.batch_size // args.num_minibatches) - args.num_iterations = args.total_timesteps // args.batch_size - run_name = f"{args.env_id}__{args.exp_name}__{args.seed}__{int(time.time())}" - if args.track: - import wandb - - wandb.init( - project=args.wandb_project_name, - entity=args.wandb_entity, - sync_tensorboard=True, - config=vars(args), - name=run_name, - monitor_gym=True, - save_code=True, - ) - writer = SummaryWriter(f"runs/{run_name}") - writer.add_text( - "hyperparameters", - "|param|value|\n|-|-|\n%s" % ("\n".join([f"|{key}|{value}|" for key, value in vars(args).items()])), - ) - - # TRY NOT TO MODIFY: seeding - random.seed(args.seed) - np.random.seed(args.seed) - torch.manual_seed(args.seed) - torch.backends.cudnn.deterministic = args.torch_deterministic - - device = torch.device("cuda" if torch.cuda.is_available() and args.cuda else "cpu") - - # PufferLib vectorization makes CleanRL ~65% faster! - import pufferlib.vector - import pufferlib.environments.atari - envs = pufferlib.vector.make( - pufferlib.environments.atari.env_creator(args.env_id), - env_kwargs=dict(framestack=4), - backend=pufferlib.vector.Multiprocessing, - num_envs=args.num_envs, - ) - - agent = Agent(envs).to(device) - optimizer = optim.Adam(agent.parameters(), lr=args.learning_rate, eps=1e-5) - - # ALGO Logic: Storage setup - obs = torch.zeros((args.num_steps, args.num_envs) + envs.single_observation_space.shape).to(device) - actions = torch.zeros((args.num_steps, args.num_envs) + envs.single_action_space.shape).to(device) - logprobs = torch.zeros((args.num_steps, args.num_envs)).to(device) - rewards = torch.zeros((args.num_steps, args.num_envs)).to(device) - dones = torch.zeros((args.num_steps, args.num_envs)).to(device) - values = torch.zeros((args.num_steps, args.num_envs)).to(device) - - # TRY NOT TO MODIFY: start the game - global_step = 0 - start_time = time.time() - next_obs, _ = envs.reset(seed=args.seed) - next_obs = torch.Tensor(next_obs).to(device) - next_done = torch.zeros(args.num_envs).to(device) - - for iteration in range(1, args.num_iterations + 1): - # Annealing the rate if instructed to do so. - if args.anneal_lr: - frac = 1.0 - (iteration - 1.0) / args.num_iterations - lrnow = frac * args.learning_rate - optimizer.param_groups[0]["lr"] = lrnow - - for step in range(0, args.num_steps): - global_step += args.num_envs - obs[step] = next_obs - dones[step] = next_done - - # ALGO LOGIC: action logic - with torch.no_grad(): - action, logprob, _, value = agent.get_action_and_value(next_obs) - values[step] = value.flatten() - actions[step] = action - logprobs[step] = logprob - - # TRY NOT TO MODIFY: execute the game and log data. - next_obs, reward, terminations, truncations, infos = envs.step(action.cpu().numpy()) - next_done = np.logical_or(terminations, truncations) - rewards[step] = torch.tensor(reward).to(device).view(-1) - next_obs, next_done = torch.from_numpy(next_obs).to(device), torch.from_numpy(next_done).to(device).float() - - for item in infos: - if "episode" in item.keys(): - print(f"global_step={global_step}, episodic_return={item['episode']['r']}") - writer.add_scalar("charts/episodic_return", item["episode"]["r"], global_step) - writer.add_scalar("charts/episodic_length", item["episode"]["l"], global_step) - break - - # bootstrap value if not done - with torch.no_grad(): - next_value = agent.get_value(next_obs).reshape(1, -1) - advantages = torch.zeros_like(rewards).to(device) - lastgaelam = 0 - for t in reversed(range(args.num_steps)): - if t == args.num_steps - 1: - nextnonterminal = 1.0 - next_done - nextvalues = next_value - else: - nextnonterminal = 1.0 - dones[t + 1] - nextvalues = values[t + 1] - delta = rewards[t] + args.gamma * nextvalues * nextnonterminal - values[t] - advantages[t] = lastgaelam = delta + args.gamma * args.gae_lambda * nextnonterminal * lastgaelam - returns = advantages + values - - # flatten the batch - b_obs = obs.reshape((-1,) + envs.single_observation_space.shape) - b_logprobs = logprobs.reshape(-1) - b_actions = actions.reshape((-1,) + envs.single_action_space.shape) - b_advantages = advantages.reshape(-1) - b_returns = returns.reshape(-1) - b_values = values.reshape(-1) - - # Optimizing the policy and value network - b_inds = np.arange(args.batch_size) - clipfracs = [] - for epoch in range(args.update_epochs): - np.random.shuffle(b_inds) - for start in range(0, args.batch_size, args.minibatch_size): - end = start + args.minibatch_size - mb_inds = b_inds[start:end] - - _, newlogprob, entropy, newvalue = agent.get_action_and_value(b_obs[mb_inds], b_actions.long()[mb_inds]) - logratio = newlogprob - b_logprobs[mb_inds] - ratio = logratio.exp() - - with torch.no_grad(): - # calculate approx_kl http://joschu.net/blog/kl-approx.html - old_approx_kl = (-logratio).mean() - approx_kl = ((ratio - 1) - logratio).mean() - clipfracs += [((ratio - 1.0).abs() > args.clip_coef).float().mean().item()] - - mb_advantages = b_advantages[mb_inds] - if args.norm_adv: - mb_advantages = (mb_advantages - mb_advantages.mean()) / (mb_advantages.std() + 1e-8) - - # Policy loss - pg_loss1 = -mb_advantages * ratio - pg_loss2 = -mb_advantages * torch.clamp(ratio, 1 - args.clip_coef, 1 + args.clip_coef) - pg_loss = torch.max(pg_loss1, pg_loss2).mean() - - # Value loss - newvalue = newvalue.view(-1) - if args.clip_vloss: - v_loss_unclipped = (newvalue - b_returns[mb_inds]) ** 2 - v_clipped = b_values[mb_inds] + torch.clamp( - newvalue - b_values[mb_inds], - -args.clip_coef, - args.clip_coef, - ) - v_loss_clipped = (v_clipped - b_returns[mb_inds]) ** 2 - v_loss_max = torch.max(v_loss_unclipped, v_loss_clipped) - v_loss = 0.5 * v_loss_max.mean() - else: - v_loss = 0.5 * ((newvalue - b_returns[mb_inds]) ** 2).mean() - - entropy_loss = entropy.mean() - loss = pg_loss - args.ent_coef * entropy_loss + v_loss * args.vf_coef - - optimizer.zero_grad() - loss.backward() - nn.utils.clip_grad_norm_(agent.parameters(), args.max_grad_norm) - optimizer.step() - - if args.target_kl is not None and approx_kl > args.target_kl: - break - - y_pred, y_true = b_values.cpu().numpy(), b_returns.cpu().numpy() - var_y = np.var(y_true) - explained_var = np.nan if var_y == 0 else 1 - np.var(y_true - y_pred) / var_y - - # TRY NOT TO MODIFY: record rewards for plotting purposes - writer.add_scalar("charts/learning_rate", optimizer.param_groups[0]["lr"], global_step) - writer.add_scalar("losses/value_loss", v_loss.item(), global_step) - writer.add_scalar("losses/policy_loss", pg_loss.item(), global_step) - writer.add_scalar("losses/entropy", entropy_loss.item(), global_step) - writer.add_scalar("losses/old_approx_kl", old_approx_kl.item(), global_step) - writer.add_scalar("losses/approx_kl", approx_kl.item(), global_step) - writer.add_scalar("losses/clipfrac", np.mean(clipfracs), global_step) - writer.add_scalar("losses/explained_variance", explained_var, global_step) - print("SPS:", int(global_step / (time.time() - start_time))) - writer.add_scalar("charts/SPS", int(global_step / (time.time() - start_time)), global_step) - - envs.close() - writer.close() diff --git a/pufferlib/config/atari.ini b/pufferlib/config/atari.ini deleted file mode 100644 index 75d1557abe..0000000000 --- a/pufferlib/config/atari.ini +++ /dev/null @@ -1,49 +0,0 @@ -[base] -package = atari - -env_name = adventure air_raid alien amidar assault asterix asteroids atlantis2 atlantis backgammon bank_heist basic_math battle_zone beam_rider berzerk blackjack bowling boxing breakout carnival casino centipede chopper_command combat crazy_climber crossbow darkchambers defender demon_attack donkey_kong double_dunk earthworld elevator_action enduro entombed et fishing_derby flag_capture freeway frogger frostbite galaxian gopher gravitar hangman haunted_house hero human_cannonball ice_hockey jamesbond journey_escape joust kaboom kangaroo keystone_kapers king_kong klax koolaid krull kung_fu_master laser_gates lost_luggage mario_bros maze_craze miniature_golf montezuma_revenge mr_do ms_pacman name_this_game othello pacman phoenix pitfall2 pitfall pong pooyan private_eye qbert riverraid road_runner robotank seaquest sir_lancelot skiing solaris space_invaders space_war star_gunner superman surround tennis tetris tic_tac_toe_3d time_pilot trondead turmoil tutankham up_n_down venture video_checkers video_chess video_cube video_pinball warlords wizard_of_wor word_zapper yars_revenge zaxxon - -policy_name = Policy -rnn_name = Recurrent - -[vec] -num_envs = 128 -num_workers = 16 -batch_size = 64 - -[train] -batch_size = 8192 -minibatch_size = 2048 -update_epochs = 1 -bptt_horizon = 64 -total_timesteps = 10_000_000 -anneal_lr = False - -[env] -frameskip = 1 -repeat_action_probability = 0.0 - -[sweep.parameters.env.parameters.frameskip] -distribution = uniform -min = 1 -max = 10 - -#[sweep.parameters.env.parameters.repeat_action_probability] -#distribution = uniform -#min = 0 -#max = 1 - -[sweep.parameters.train.parameters.total_timesteps] -distribution = uniform -min = 5_000_000 -max = 200_000_000 - -[sweep.parameters.train.parameters.batch_size] -distribution = uniform -min = 16384 -max = 65536 - -[sweep.parameters.train.parameters.minibatch_size] -distribution = uniform -min = 512 -max = 8192 diff --git a/pufferlib/config/box2d.ini b/pufferlib/config/box2d.ini deleted file mode 100644 index a87ae3627a..0000000000 --- a/pufferlib/config/box2d.ini +++ /dev/null @@ -1,11 +0,0 @@ -[base] -package = box2d -env_name = car-racing - -[train] -num_envs = 48 -num_workers = 24 -env_batch_size = 48 -zero_copy = False -batch_size = 16384 -minibatch_size = 2048 diff --git a/pufferlib/config/bsuite.ini b/pufferlib/config/bsuite.ini deleted file mode 100644 index bab5154669..0000000000 --- a/pufferlib/config/bsuite.ini +++ /dev/null @@ -1,7 +0,0 @@ -[base] -package = bsuite -env_name = bandit/0 - -[train] -total_timesteps = 1_000_000 -num_envs = 1 diff --git a/pufferlib/config/butterfly.ini b/pufferlib/config/butterfly.ini deleted file mode 100644 index a616c2917c..0000000000 --- a/pufferlib/config/butterfly.ini +++ /dev/null @@ -1,3 +0,0 @@ -[base] -package = butterfly -env_name = cooperative_pong_v5 diff --git a/pufferlib/config/classic_control.ini b/pufferlib/config/classic_control.ini deleted file mode 100644 index 8bc4f44e40..0000000000 --- a/pufferlib/config/classic_control.ini +++ /dev/null @@ -1,8 +0,0 @@ -[base] -package = classic_control -env_name = cartpole mountaincar - -[train] -total_timesteps = 500_000 -num_envs = 64 -env_batch_size = 64 diff --git a/pufferlib/config/classic_control_continuous.ini b/pufferlib/config/classic_control_continuous.ini deleted file mode 100644 index cd0603c2eb..0000000000 --- a/pufferlib/config/classic_control_continuous.ini +++ /dev/null @@ -1,8 +0,0 @@ -[base] -package = classic_control_continuous -env_name = mountaincar-continuous - -[train] -total_timesteps = 500_000 -num_envs = 64 -env_batch_size = 64 diff --git a/pufferlib/config/cogames.ini b/pufferlib/config/cogames.ini deleted file mode 100644 index 674b48e2e6..0000000000 --- a/pufferlib/config/cogames.ini +++ /dev/null @@ -1,21 +0,0 @@ -[base] -package = cogames -env_name = cogames.cogs_v_clips.training_facility.harvest cogames.cogs_v_clips.training_facility.assemble cogames.cogs_v_clips.machina_1.open_world -policy_name = Policy -rnn_name = Recurrent - -[vec] -num_envs = 64 -num_workers = 16 -batch_size = auto -zero_copy = True - -[env] -render_mode = none -variants = heart_chorus inventory_heart_tune - -[train] -total_timesteps = 50_000_000 -batch_size = auto -minibatch_size = 1024 -bptt_horizon = 64 diff --git a/pufferlib/config/craftax.ini b/pufferlib/config/craftax.ini deleted file mode 100644 index 2c5b2023f9..0000000000 --- a/pufferlib/config/craftax.ini +++ /dev/null @@ -1,24 +0,0 @@ -[base] -package = craftax -env_name = Craftax-Symbolic-v1 Craftax-Classic-Symbolic-v1 -policy_name = Policy -rnn_name = Recurrent - -[env] -num_envs = 1024 - -[vec] -num_envs = 1 -num_workers = 1 -batch_size = 1 - -[train] -total_timesteps = 100_000_000 -checkpoint_interval = 200 -update_epochs = 4 -batch_size = 131072 -minibatch_size = 8192 -learning_rate = 0.0002 -gamma = 0.99 -gae_lambda = 0.8 -ent_coef = 0.01 diff --git a/pufferlib/config/crafter.ini b/pufferlib/config/crafter.ini deleted file mode 100644 index d462608895..0000000000 --- a/pufferlib/config/crafter.ini +++ /dev/null @@ -1,10 +0,0 @@ -[base] -package = crafter -env_name = crafter - -[train] -num_envs = 96 -num_workers = 24 -env_batch_size = 48 -zero_copy = False -batch_size = 6144 diff --git a/pufferlib/config/dm_control.ini b/pufferlib/config/dm_control.ini deleted file mode 100644 index 8cce146e1e..0000000000 --- a/pufferlib/config/dm_control.ini +++ /dev/null @@ -1,3 +0,0 @@ -[base] -package = dm_control -env_name = dmc diff --git a/pufferlib/config/dm_lab.ini b/pufferlib/config/dm_lab.ini deleted file mode 100644 index 8350696dee..0000000000 --- a/pufferlib/config/dm_lab.ini +++ /dev/null @@ -1,3 +0,0 @@ -[base] -package = dm_lab -env_name = dml diff --git a/pufferlib/config/doom.ini b/pufferlib/config/doom.ini deleted file mode 100644 index 62cf850e76..0000000000 --- a/pufferlib/config/doom.ini +++ /dev/null @@ -1,12 +0,0 @@ -[base] -package = vizdoom -env_name = doom - -[train] -num_envs = 144 -num_workers = 24 -env_batch_size = 48 -zero_copy = False -batch_size = 8192 -minibatch_size = 2048 -update_epochs = 1 diff --git a/pufferlib/config/gpudrive.ini b/pufferlib/config/gpudrive.ini deleted file mode 100644 index 41052ecfed..0000000000 --- a/pufferlib/config/gpudrive.ini +++ /dev/null @@ -1,46 +0,0 @@ -[base] -package = gpudrive -env_name = gpudrive -policy_name = Policy -rnn_name = Recurrent - -[env] -num_worlds = 512 - -[train] -total_timesteps = 10_000_000 -num_envs = 1 -num_workers = 1 -env_batch_size = 1 -zero_copy = False -batch_size = 262_144 -update_epochs = 5 -minibatch_size = 32768 -bptt_horizon = 4 -anneal_lr = False -gae_lambda = 0.95 -gamma = 0.99 -clip_coef = 0.2 -vf_coef = 0.5 -vf_clip_coef = 0.2 -max_grad_norm = 0.5 -ent_coef = 0.00 -learning_rate = 0.0003 -checkpoint_interval = 1000 -device = cuda - -[sweep.metric] -goal = maximize -name = environment/goal_achieved - -[sweep.parameters.train.parameters.batch_size] -distribution = uniform -min = 32768 -max = 524288 - -[sweep.parameters.train.parameters.minibatch_size] -distribution = uniform -min = 2048 -max = 32768 - - diff --git a/pufferlib/config/griddly.ini b/pufferlib/config/griddly.ini deleted file mode 100644 index ab23d7ba80..0000000000 --- a/pufferlib/config/griddly.ini +++ /dev/null @@ -1,3 +0,0 @@ -[base] -package = griddly -env_name = spiders diff --git a/pufferlib/config/gvgai.ini b/pufferlib/config/gvgai.ini deleted file mode 100644 index 21459bca55..0000000000 --- a/pufferlib/config/gvgai.ini +++ /dev/null @@ -1,36 +0,0 @@ -[base] -package = gvgai -env_name = zelda -policy_name = Policy -rnn_name = Recurrent - -[train] -total_timesteps = 1_000_000 -checkpoint_interval = 1000 -learning_rate = 0.00024290984560207393 -num_envs = 96 -num_workers = 24 -env_batch_size = 32 -update_epochs = 1 -zero_copy = False -bptt_horizon = 16 -batch_size = 4096 -minibatch_size = 1024 -compile = False -anneal_lr = False -device = cuda - -[sweep.metric] -goal = maximize -name = environment/reward - -[sweep.parameters.train.parameters.total_timesteps] -distribution = log_uniform_values -min = 500_000_000 -max = 10_000_000_000 - -[sweep.parameters.train.parameters.batch_size] -values = [4096, 8192, 16384] - -[sweep.parameters.train.parameters.minibatch_size] -values = [512, 1024, 2048, 4096] diff --git a/pufferlib/config/kinetix.ini b/pufferlib/config/kinetix.ini deleted file mode 100644 index e9f6e02ac0..0000000000 --- a/pufferlib/config/kinetix.ini +++ /dev/null @@ -1,53 +0,0 @@ -[base] -package = kinetix -env_name = kinetix-pixels-discrete kinetix-symbolic-discrete -policy_name = PixelsPolicy -rnn_name = Recurrent - -[env] -num_envs = 2048 - -[train] -total_timesteps = 100_000_000 -checkpoint_interval = 200 -num_envs = 1 -num_workers = 1 -env_batch_size = 1 -update_epochs = 8 -batch_size = 131072 -minibatch_size = 4096 -learning_rate = 0.0003 -gamma = 0.995 -gae_lambda = 0.9 -ent_coef = 0.01 - -[sweep] -method = protein -name = sweep - -[sweep.metric] -goal = maximize -name = GoalR -min = 0 -max = None - -[sweep.train.total_timesteps] -distribution = log_normal -min = 5e6 -max = 1e9 -mean = 1e7 -scale = auto - -[sweep.train.batch_size] -distribution = uniform_pow2 -min = 32768 -max = 131072 -mean = 65536 -scale = auto - -[sweep.train.minibatch_size] -distribution = uniform_pow2 -min = 1024 -max = 32768 -mean = 8192 -scale = auto diff --git a/pufferlib/config/magent.ini b/pufferlib/config/magent.ini deleted file mode 100644 index 0df7336f83..0000000000 --- a/pufferlib/config/magent.ini +++ /dev/null @@ -1,3 +0,0 @@ -[base] -package = magent -env_name = battle_v4 diff --git a/pufferlib/config/mani_skill.ini b/pufferlib/config/mani_skill.ini deleted file mode 100644 index 56e990d415..0000000000 --- a/pufferlib/config/mani_skill.ini +++ /dev/null @@ -1,69 +0,0 @@ - -[base] -package = mani_skill -env_name = mani_pickcube mani_pushcube mani_stackcube mani_peginsertion -policy_name = Policy -rnn_name = Recurrent - -[env] -num_envs = 4096 -sim_steps_per_control = 5 -control_freq = 100 -solver_position_iterations = 15 - -[vec] -backend = PufferEnv -num_envs = 1 - -[train] -total_timesteps = 15_000_000 -adam_beta1 = 0.9832254546070032 -adam_beta2 = 0.9996089758513379 -adam_eps = 0.0000024542110227211678 -bptt_horizon = 64 -clip_coef = 0.6609987983481933 -ent_coef = 0.001194131610607018 -gae_lambda = 0.968478898646462 -gamma = 0.8880001899050386 -learning_rate = 0.04729013902338006 -max_grad_norm = 1.9301595176438802 -minibatch_size = 32768 -prio_alpha = 0.9531362058849446 -prio_beta0 = 0.8285186322612919 -vf_clip_coef = 0.2581908677409054 -vf_coef = 2.6102252379894217 -vtrace_c_clip = 2.008516783867587 -vtrace_rho_clip = 0.7482202150166445 - -[sweep] -method = Protein -metric = success_once -downsample = 0 - -[sweep.train.total_timesteps] -distribution = log_normal -min = 2e7 -max = 5e7 -mean = 4e7 -scale = time - -[sweep.env.sim_steps_per_control] -distribution = int_uniform -min = 1 -max = 10 -mean = 5 -scale = auto - -[sweep.env.control_freq] -distribution = int_uniform -min = 10 -max = 100 -mean = 20 -scale = auto - -[sweep.env.solver_position_iterations] -distribution = int_uniform -min = 4 -max = 30 -mean = 15 -scale = auto diff --git a/pufferlib/config/metta.ini b/pufferlib/config/metta.ini deleted file mode 100644 index 355e2b3a27..0000000000 --- a/pufferlib/config/metta.ini +++ /dev/null @@ -1,67 +0,0 @@ -[base] -package = metta -env_name = metta -policy_name = Policy -rnn_name = Recurrent - -[vec] -num_envs = 64 -num_workers = 16 - -[env] -render_mode = auto -ore_reward = 0.17088483842567775 -battery_reward = 0.9882859711234822 -heart_reward = 1.0 - -[train] -total_timesteps = 300_000_000 -batch_size = auto -adam_beta1 = 0.8923106632311335 -adam_beta2 = 0.9632470625784862 -adam_eps = 1.3537431449843922e-7 -clip_coef = 0.14919147162017737 -ent_coef = 0.016700174334611493 -gae_lambda = 0.8443676864928215 -gamma = 0.997950174315581 -learning_rate = 0.018470110879570414 -max_grad_norm = 2.572849891206465 -minibatch_size = 32768 -bptt_horizon = 64 -prio_alpha = 0.7918451491719373 -prio_beta0 = 0.5852686803034238 -vf_clip_coef = 0.1569624916309049 -vf_coef = 3.2211333828684454 -vtrace_c_clip = 2.134490283650365 -vtrace_rho_clip = 2.296343917695581 - -[sweep] -metric = agent/heart.gained - -[sweep.train.total_timesteps] -distribution = log_normal -min = 1e8 -max = 5e8 -mean = 3e8 -scale = auto - -[sweep.env.ore_reward] -distribution = uniform -min = 0.0 -mean = 0.25 -max = 1.0 -scale = auto - -[sweep.env.battery_reward] -distribution = uniform -min = 0.0 -mean = 0.5 -max = 1.0 -scale = auto - -[sweep.env.heart_reward] -distribution = uniform -min = 0.0 -mean = 1.0 -max = 1.0 -scale = auto diff --git a/pufferlib/config/microrts.ini b/pufferlib/config/microrts.ini deleted file mode 100644 index 3c1da0f247..0000000000 --- a/pufferlib/config/microrts.ini +++ /dev/null @@ -1,3 +0,0 @@ -[base] -package = microrts -env_name = GlobalAgentCombinedRewardEnv diff --git a/pufferlib/config/minerl.ini b/pufferlib/config/minerl.ini deleted file mode 100644 index 25190f698f..0000000000 --- a/pufferlib/config/minerl.ini +++ /dev/null @@ -1,3 +0,0 @@ -[base] -package = minerl -env_name = MineRLNavigateDense-v0 diff --git a/pufferlib/config/minigrid.ini b/pufferlib/config/minigrid.ini deleted file mode 100644 index c44178d9fb..0000000000 --- a/pufferlib/config/minigrid.ini +++ /dev/null @@ -1,19 +0,0 @@ -[base] -package = minigrid -env_name = minigrid - -[vec] -num_envs = 48 -num_workers = 6 -batch_size = 48 - -[train] -total_timesteps = 1_000_000 -batch_size = 6144 -minibatch_size = 768 -update_epochs = 4 -anneal_lr = False -gae_lambda = 0.95 -gamma = 0.95 -ent_coef = 0.025 -learning_rate = 2.5e-4 diff --git a/pufferlib/config/minihack.ini b/pufferlib/config/minihack.ini deleted file mode 100644 index e356a55183..0000000000 --- a/pufferlib/config/minihack.ini +++ /dev/null @@ -1,15 +0,0 @@ -[base] -package = minihack -env_name = minihack - -[vec] -num_envs = 128 -num_workers = 16 -batch_size = 64 - -[train] -batch_size = 8192 -minibatch_size = 2048 -update_epochs = 1 -bptt_horizon = 64 -total_timesteps = 10_000_000 diff --git a/pufferlib/config/mujoco.ini b/pufferlib/config/mujoco.ini deleted file mode 100644 index 9de3495a19..0000000000 --- a/pufferlib/config/mujoco.ini +++ /dev/null @@ -1,29 +0,0 @@ -[base] -package = mujoco -env_name = HalfCheetah-v4 Hopper-v4 Swimmer-v4 Walker2d-v4 Ant-v4 Humanoid-v4 Reacher-v4 InvertedPendulum-v4 InvertedDoublePendulum-v4 Pusher-v4 HumanoidStandup-v4 -policy_name = Policy -rnn_name = Recurrent - -[env] -render_mode = rgb_array - -[vec] -num_envs = 512 -num_workers = 16 -batch_size = auto - -[train] -total_timesteps = 5_000_000 -learning_rate = 3e-4 -gamma = 0.99 -gae_lambda = 0.95 -update_epochs = 10 -clip_coef = 0.2 -vf_coef = 0.5 -vf_clip_coef = 0.2 -max_grad_norm = 0.5 -ent_coef = 0.0 -checkpoint_interval = 200 -batch_size = 32768 -minibatch_size = 4096 -bptt_horizon = 64 diff --git a/pufferlib/config/nethack.ini b/pufferlib/config/nethack.ini deleted file mode 100644 index 39e1bc24b1..0000000000 --- a/pufferlib/config/nethack.ini +++ /dev/null @@ -1,31 +0,0 @@ -[base] -package = nethack -env_name = nethack -policy_name = Policy -rnn_name = Recurrent - -[vec] -num_envs = 8192 -num_workers = 16 -batch_size = 4096 - -[train] -total_timesteps = 90_000_000 -adam_beta1 = 0.8946507418260217 -adam_beta2 = 0.9 -adam_eps = 0.0001 -batch_size = auto -bptt_horizon = 64 -clip_coef = 0.19696765958267629 -ent_coef = 0.0005690816545012474 -gae_lambda = 0.747650023961198 -gamma = 0.9997053654668936 -learning_rate = 0.044482546441415506 -max_grad_norm = 2.2356112188495723 -minibatch_size = 32768 -prio_alpha = 0.98967001208896 -prio_beta0 = 0.09999999999999998 -vf_clip_coef = 2.178492167689251 -vf_coef = 1.6832989594296321 -vtrace_c_clip = 2.878171091654008 -vtrace_rho_clip = 0.7876748061547312 diff --git a/pufferlib/config/nmmo.ini b/pufferlib/config/nmmo.ini deleted file mode 100644 index 4a4f419cad..0000000000 --- a/pufferlib/config/nmmo.ini +++ /dev/null @@ -1,10 +0,0 @@ -[base] -package = nmmo -env_name = nmmo - -[train] -num_envs = 4 -env_batch_size = 4 -num_workers = 4 -batch_size = 4096 -minibatch_size = 2048 diff --git a/pufferlib/config/ocean/breakout.ini b/pufferlib/config/ocean/breakout.ini deleted file mode 100644 index 0aa59d5794..0000000000 --- a/pufferlib/config/ocean/breakout.ini +++ /dev/null @@ -1,70 +0,0 @@ -[base] -package = ocean -env_name = puffer_breakout -policy_name = Policy -rnn_name = Recurrent - -[vec] -num_envs = 8 - -[env] -num_envs = 1024 -frameskip = 4 -width = 576 -height = 330 -paddle_width = 62 -paddle_height = 8 -ball_width = 32 -ball_height = 32 -brick_width = 32 -brick_height = 12 -brick_rows = 6 -brick_cols = 18 -initial_ball_speed = 256 -max_ball_speed = 448 -paddle_speed = 620 -continuous = 0 - -[policy] -hidden_size = 128 - -[rnn] -input_size = 128 -hidden_size = 128 - -[train] -total_timesteps = 90_000_000 -adam_beta1 = 0.8946507418260217 -adam_beta2 = 0.9 -adam_eps = 0.0001 -batch_size = auto -bptt_horizon = 64 -clip_coef = 0.19696765958267629 -ent_coef = 0.0005690816545012474 -gae_lambda = 0.747650023961198 -gamma = 0.9997053654668936 -learning_rate = 0.044482546441415506 -max_grad_norm = 2.2356112188495723 -minibatch_size = 32768 -prio_alpha = 0.98967001208896 -prio_beta0 = 0.09999999999999998 -vf_clip_coef = 2.178492167689251 -vf_coef = 1.6832989594296321 -vtrace_c_clip = 2.878171091654008 -vtrace_rho_clip = 0.7876748061547312 - -[sweep] - -[sweep.train.total_timesteps] -distribution = log_normal -min = 3e7 -max = 2e8 -mean = 8e7 -scale = auto - -[sweep.env.frameskip] -distribution = int_uniform -min = 1 -max = 8 -mean = 4 -scale = 2.0 diff --git a/pufferlib/config/ocean/cartpole.ini b/pufferlib/config/ocean/cartpole.ini deleted file mode 100644 index 15bd65ef31..0000000000 --- a/pufferlib/config/ocean/cartpole.ini +++ /dev/null @@ -1,31 +0,0 @@ -[base] -package = ocean -env_name = puffer_cartpole -policy_name = Policy -rnn_name = Recurrent - -[env] -num_envs = 4096 -cart_mass = 1.0 -pole_mass = 0.1 -pole_length = 0.5 -gravity = 9.8 -force_mag = 10.0 -dt = 0.02 - -[train] -total_timesteps = 20_000_000 -gamma = 0.95 -learning_rate = 0.05 -minibatch_size = 32768 - -[sweep] -method = Protein -metric = episode_length - -[sweep.train.total_timesteps] -distribution = log_normal -min = 1e6 -max = 1e7 -mean = 5e6 -scale = 0.5 diff --git a/pufferlib/config/ocean/chain_mdp.ini b/pufferlib/config/ocean/chain_mdp.ini deleted file mode 100644 index 12a87df889..0000000000 --- a/pufferlib/config/ocean/chain_mdp.ini +++ /dev/null @@ -1,24 +0,0 @@ -[base] -package = ocean -env_name = puffer_chain_mdp -policy_name = Policy -; rnn_name = Recurrent - -[vec] -num_envs = 8 - -[env] -num_envs = 512 -size = 128 - -[policy] -hidden_size = 128 - -; [rnn] -; input_size = 128 -; hidden_size = 128 - -[train] -total_timesteps = 5_000_000 -bptt_horizon = 64 -entropy_coef = 0.1 \ No newline at end of file diff --git a/pufferlib/config/ocean/connect4.ini b/pufferlib/config/ocean/connect4.ini deleted file mode 100644 index 252b79350c..0000000000 --- a/pufferlib/config/ocean/connect4.ini +++ /dev/null @@ -1,37 +0,0 @@ -[base] -package = ocean -env_name = puffer_connect4 -policy_name = Policy -rnn_name = Recurrent - -[env] -num_envs = 1024 - -[vec] -num_envs = 8 - -[train] -total_timesteps = 22_000_000 -adam_beta1 = 0.7332525176640032 -adam_beta2 = 0.9992588002434659 -adam_eps = 0.0001 -clip_coef = 0.3344358533613167 -ent_coef = 0.00004214003802569246 -gae_lambda = 0.8969790930039623 -gamma = 0.9945932652529774 -learning_rate = 0.1 -max_grad_norm = 1.0219144411399215 -minibatch_size = 32768 -prio_alpha = 0.9057091953725436 -prio_beta0 = 0.6320607520016285 -vf_clip_coef = 1.9948775471721416 -vf_coef = 2.3734839181925462 -vtrace_c_clip = 0.5659747235622431 -vtrace_rho_clip = 1.4499061438546799 - -[sweep.train.total_timesteps] -distribution = log_normal -min = 1e7 -max = 2e8 -mean = 3e7 -scale = 0.5 diff --git a/pufferlib/config/ocean/drone.ini b/pufferlib/config/ocean/drone.ini deleted file mode 100644 index 26d1ce3476..0000000000 --- a/pufferlib/config/ocean/drone.ini +++ /dev/null @@ -1,57 +0,0 @@ -[base] -package = ocean -env_name = puffer_drone -policy_name = Policy -rnn_name = Recurrent - -[policy] -hidden_size = 128 - -[rnn] -input_size = 128 -hidden_size = 128 - -[vec] -num_envs = 8 - -[env] -num_envs = 16 -num_drones = 64 -max_rings = 10 - -[train] -adam_beta1 = 0.9610890980775877 -adam_beta2 = 0.9999260775286266 -adam_eps = 7.782906079040132e-10 -anneal_lr = true -batch_size = auto -bptt_horizon = 64 -checkpoint_interval = 200 -clip_coef = 0.05982655642208556 -ent_coef = 0.002465076521024325 -gae_lambda = 0.9641173414828333 -gamma = 0.997472126425902 -learning_rate = 0.010933756713881205 -#learning_rate = 0.005 -max_grad_norm = 1.6317688647793107 -max_minibatch_size = 32768 -minibatch_size = 32768 -prio_alpha = 0.8968873016577552 -prio_beta0 = 0.8672928227817938 -total_timesteps = 500_000_000 -update_epochs = 1 -#use_rnn = false -vf_clip_coef = 0.5869845581530236 -vf_coef = 2.1319065538539963 -vtrace_c_clip = 2.714930379733876 -vtrace_rho_clip = 3.8183814893708057 - -[sweep] -downsample = 0 - -[sweep.train.total_timesteps] -distribution = log_normal -min = 2e8 -max = 4e8 -mean = 2e8 -scale = time diff --git a/pufferlib/config/ocean/enduro.ini b/pufferlib/config/ocean/enduro.ini deleted file mode 100644 index 6586183fb5..0000000000 --- a/pufferlib/config/ocean/enduro.ini +++ /dev/null @@ -1,42 +0,0 @@ -[base] -package = ocean -env_name = puffer_enduro -policy_name = Policy -rnn_name = Recurrent - -[env] -num_envs = 1024 - -[vec] -num_envs = 1 - -[train] -total_timesteps = 400_000_000 -adam_beta1 = 0.9602226117399812 -adam_beta2 = 0.999983918771099 -adam_eps = 2.109767652202695e-9 -bptt_horizon = 64 -clip_coef = 0.5716251062832933 -ent_coef = 0.009778379693175061 -gae_lambda = 0.9924829173144767 -gamma = 0.9433427558493771 -learning_rate = 0.014263349414255656 -max_grad_norm = 0.42249653686869115 -max_minibatch_size = 32768 -minibatch_size = 65536 -prio_alpha = 0.22253503344197678 -prio_beta0 = 0.7866639848626998 -vf_clip_coef = 0.01 -vf_coef = 3.2952964839081016 -vtrace_c_clip = 3.060525785199293 -vtrace_rho_clip = 5 - -[sweep] -metric = days_completed - -[sweep.train.total_timesteps] -distribution = log_normal -min = 5e7 -max = 4e8 -mean = 2e8 -scale = auto diff --git a/pufferlib/config/ocean/freeway.ini b/pufferlib/config/ocean/freeway.ini deleted file mode 100644 index 2acceb7a03..0000000000 --- a/pufferlib/config/ocean/freeway.ini +++ /dev/null @@ -1,27 +0,0 @@ -[base] -package = ocean -env_name = puffer_freeway -policy_name = Policy -rnn_name = Recurrent - -[vec] -num_envs = 8 - -[env] -num_envs = 1024 -frameskip = 4 -use_dense_rewards = True -env_randomization = True -difficulty = 0 -level = -1 - -[train] -total_timesteps = 500_000_000 -minibatch_size = 32768 - -[sweep.train.total_timesteps] -distribution = log_normal -min = 3e8 -max = 4e8 -mean = 3e8 -scale = auto diff --git a/pufferlib/config/ocean/g2048.ini b/pufferlib/config/ocean/g2048.ini deleted file mode 100644 index 3ca7f4e8ce..0000000000 --- a/pufferlib/config/ocean/g2048.ini +++ /dev/null @@ -1,167 +0,0 @@ -[base] -package = ocean -env_name = puffer_g2048 -policy_name = G2048 -rnn_name = Recurrent - -[policy] -hidden_size = 512 - -[rnn] -input_size = 512 -hidden_size = 512 - -[vec] -num_envs = 4 - -[env] -num_envs = 4096 -reward_scaler = 0.67 -endgame_env_prob = 0.05 -scaffolding_ratio = 0.67 -use_heuristic_rewards = True -snake_reward_weight = 0.0005 - -[train] -# 512 hidden: https://wandb.ai/kywch/pufferlib/runs/5thsjr61?nw=nwuserkywch -total_timesteps = 6_767_676_767 -anneal_lr = True -min_lr_ratio = 0.15 -batch_size = auto -bptt_horizon = 64 -minibatch_size = 32768 - -clip_coef = 0.067 -ent_coef = 0.0267 -gae_lambda = 0.67 -gamma = 0.99567 -vf_clip_coef = 0.167 -vf_coef = 2.0 - -learning_rate = 0.000467 -max_grad_norm = 0.5 - - -# These are newer puffer PPO params. Need more sweeping. -adam_beta1 = 0.99 -adam_beta2 = 0.9999 -adam_eps = 0.0001 -prio_alpha = 0.8 -prio_beta0 = 0.1 -vtrace_c_clip = 2.0 -vtrace_rho_clip = 1.1 - - -### Targeted sweep - -[sweep] -metric = score -goal = maximize -max_suggestion_cost = 7200 -sweep_only = endgame_env_prob, scaffolding_ratio, snake_reward_weight, learning_rate, max_grad_norm -downsample = 1 - -[sweep.env.endgame_env_prob] -distribution = uniform -min = 0.0 -mean = 0.03 -max = 0.2 -scale = auto - -[sweep.env.scaffolding_ratio] -distribution = uniform -min = 0.1 -mean = 0.5 -max = 0.8 -scale = auto - -[sweep.env.snake_reward_weight] -distribution = uniform -min = 0.0001 -mean = 0.0007 -max = 0.0050 -scale = auto - -[sweep.train.learning_rate] -distribution = uniform -min = 0.0001 -mean = 0.0005 -max = 0.0030 -scale = 0.5 - -[sweep.train.max_grad_norm] -distribution = uniform -min = 0.1 -mean = 0.5 -max = 2.0 -scale = 0.5 - -[sweep.train.vf_clip_coef] -distribution = uniform -min = 0.05 -max = 0.5 -mean = 0.2 -scale = auto - - -### Broad sweep - -; [sweep] -; metric = score -; goal = maximize - -; [sweep.env.reward_scaler] -; distribution = uniform -; min = 0.1 -; mean = 0.5 -; max = 1.0 -; scale = auto - -; [sweep.env.scaffolding_ratio] -; distribution = uniform -; min = 0.0 -; mean = 0.5 -; max = 0.8 -; scale = auto - -; [sweep.env.snake_reward_weight] -; distribution = uniform -; min = 0.00001 -; mean = 0.00005 -; max = 0.0002 -; scale = auto - -; [sweep.train.total_timesteps] -; distribution = log_normal -; min = 3e8 -; max = 1e10 -; mean = 1e9 -; scale = time - -; [sweep.train.learning_rate] -; distribution = log_normal -; min = 0.00001 -; mean = 0.001 -; max = 0.1 -; scale = 0.5 - -; [sweep.train.gamma] -; distribution = logit_normal -; min = 0.8 -; mean = 0.995 -; max = 0.9999 -; scale = auto - -; [sweep.train.gae_lambda] -; distribution = logit_normal -; min = 0.01 -; mean = 0.7 -; max = 0.995 -; scale = auto - -; [sweep.train.clip_coef] -; distribution = log_normal -; min = 0.001 -; max = 0.5 -; mean = 0.05 -; scale = auto \ No newline at end of file diff --git a/pufferlib/config/ocean/go.ini b/pufferlib/config/ocean/go.ini deleted file mode 100644 index fdf6867d40..0000000000 --- a/pufferlib/config/ocean/go.ini +++ /dev/null @@ -1,72 +0,0 @@ -[base] -package = ocean -env_name = puffer_go -policy_name = Policy -rnn_name = Recurrent - -[env] -num_envs = 1024 -reward_move_pass = -0.6026362603175613 -reward_move_valid = 0 -reward_move_invalid = -0.5393516480382454 -reward_opponent_capture = -0.3152783593705354 -reward_player_capture = 0.42122681325442923 -grid_size = 7 - -[vec] -num_envs = 8 - -[train] -total_timesteps = 100_000_000 -adam_beta1 = 0.5686370767889766 -adam_beta2 = 0.9999454817221638 -adam_eps = 2.007252656207671e-12 -bptt_horizon = 64 -clip_coef = 0.17930104885238807 -ent_coef = 0.0018946598458748304 -gae_lambda = 0.9831319174802507 -gamma = 0.9480351741863737 -learning_rate = 0.031603809039284864 -max_grad_norm = 1.320177349287771 -minibatch_size = 8192 -prio_alpha = 0.6979639079178326 -prio_beta0 = 0.5614257332458639 -vf_clip_coef = 1.1755607092687304 -vf_coef = 1.6195967557187005 -vtrace_c_clip = 0 -vtrace_rho_clip = 4.060318960532289 - -[sweep.train.total_timesteps] -distribution = log_normal -min = 1e8 -max = 5e8 -mean = 2e8 -scale = 0.25 - -[sweep.env.reward_move_invalid] -distribution = uniform -min = -1.0 -max = 0.0 -mean = -0.5 -scale = 0.5 - -[sweep.env.reward_move_pass] -distribution = uniform -min = -1.0 -max = 0.0 -mean = -0.5 -scale = 0.5 - -[sweep.env.reward_player_capture] -distribution = uniform -min = 0.0 -max = 1.0 -mean = 0.5 -scale = 0.5 - -[sweep.env.reward_opponent_capture] -distribution = uniform -min = -1.0 -max = 0.0 -mean = -0.5 -scale = 0.5 diff --git a/pufferlib/config/ocean/grid.ini b/pufferlib/config/ocean/grid.ini deleted file mode 100644 index 65bd540b68..0000000000 --- a/pufferlib/config/ocean/grid.ini +++ /dev/null @@ -1,72 +0,0 @@ -[base] -package = ocean -env_name = puffer_grid -policy_name = Policy -rnn_name = Recurrent - -[policy] -hidden_size = 512 - -[rnn] -input_size = 512 -hidden_size = 512 - -[vec] -#num_envs = 8 -num_envs = 1 - -[env] -max_size = 47 -num_envs = 1024 -#num_envs = 4096 -num_maps = 8192 - -[train] -# Best params -#total_timesteps = 435_000_000 -#adam_beta1 = 0.9801350114303844 -#adam_beta2 = 0.9931056135397744 -#adam_eps = 6.024885743259763e-8 -#clip_coef = 0.283658795325587 -#ent_coef = 0.007885530106105381 -#gae_lambda = 0.9574676436577135 -#gamma = 0.9961782334639131 -#learning_rate = 0.0007890771333884192 -#max_grad_norm = 2.5271346931510053 -#minibatch_size = 8192 -#prio_alpha = 0.8735470630752789 -#prio_beta0 = 0.6533958384978629 -#vf_clip_coef = 1.9338563232919095 -#vf_coef = 3.915248046963283 -#vtrace_c_clip = 1.018588814067991 -#vtrace_rho_clip = 2.4215244529216466 - -# New sweep best params -total_timesteps = 435_000_000 -adam_beta1 = 0.9493079570168755 -adam_beta2 = 0.9998213228757207 -adam_eps = 2.16720639574209e-8 -bptt_horizon = 64 -clip_coef = 0.399530686596841 -ent_coef = 0.0017271288609381147 -gae_lambda = 0.9491722822649111 -gamma = 0.9877360824574745 -learning_rate = 0.0012892859713461897 -max_grad_norm = 3.016348031602564 -minibatch_size = 8192 -prio_alpha = 0.8219794821639037 -prio_beta0 = 0.9447478232810274 -vf_clip_coef = 0.6051579400844748 -vf_coef = 2.323141961227481 -vtrace_c_clip = 1.2499497264614237 -vtrace_rho_clip = 4.7398234531013985 - -[sweep] -downsample = 0 - -[sweep.train.total_timesteps] -distribution = log_normal -min = 3e8 -max = 6e8 -mean = 3e8 -scale = time diff --git a/pufferlib/config/ocean/moba.ini b/pufferlib/config/ocean/moba.ini deleted file mode 100644 index 2e0e8cea38..0000000000 --- a/pufferlib/config/ocean/moba.ini +++ /dev/null @@ -1,46 +0,0 @@ -[base] -package = ocean -env_name = puffer_moba -policy_name = MOBA -rnn_name = Recurrent - -[env] -reward_death = 0.0 -reward_xp = 0.0016926873475313188 -reward_distance = 0.0 -reward_tower = 4.525112152099609 -num_envs = 128 - -[vec] -num_envs = 8 - -[train] -total_timesteps = 150_000_000 - -[sweep.train.total_timesteps] -distribution = log_normal -min = 2e7 -max = 2e8 -mean = 1e8 -scale = auto - -[sweep.env.reward_death] -distribution = uniform -min = -1.0 -max = 0 -mean = 0 -scale = auto - -[sweep.env.reward_xp] -distribution = uniform -min = 0.0 -max = 0.05 -mean = 0.0015 -scale = auto - -[sweep.env.reward_tower] -distribution = uniform -min = 0.0 -max = 1.0 -mean = 1.0 -scale = auto diff --git a/pufferlib/config/ocean/pacman.ini b/pufferlib/config/ocean/pacman.ini deleted file mode 100644 index 45055e79bc..0000000000 --- a/pufferlib/config/ocean/pacman.ini +++ /dev/null @@ -1,33 +0,0 @@ -[base] -package = ocean -env_name = puffer_pacman -policy_name = Policy -rnn_name = Recurrent - -[vec] -num_envs = 8 - -[env] -num_envs = 1024 -randomize_starting_position = 1 - -[train] -total_timesteps = 110_000_000 -adam_beta1 = 0.9038605017693528 -adam_beta2 = 0.9974184818428597 -adam_eps = 0.000023302187415940045 -bptt_horizon = 64 -clip_coef = 0.08819998793159559 -ent_coef = 0.003877776836171818 -gae_lambda = 0.9548561279014964 -gamma = 0.9808956918725869 -learning_rate = 0.07834293253084383 -max_grad_norm = 1.4336515067572169 -minibatch_size = 32768 -prio_alpha = 0.912262602688309 -prio_beta0 = 0.8868847849454541 -vf_clip_coef = 0.2143010707893266 -vf_coef = 0.31518694995467555 -vtrace_c_clip = 0.30575543665366217 -vtrace_rho_clip = 1.5301756939690652 - diff --git a/pufferlib/config/ocean/pong.ini b/pufferlib/config/ocean/pong.ini deleted file mode 100644 index a0bf24d93a..0000000000 --- a/pufferlib/config/ocean/pong.ini +++ /dev/null @@ -1,46 +0,0 @@ -[base] -package = ocean -env_name = puffer_pong -policy_name = Policy -rnn_name = Recurrent - -[vec] -num_envs = 4 - -[env] -num_envs = 1024 -frameskip = 8 - -[train] -total_timesteps = 12_000_000 -adam_beta1 = 0.9766295300012044 -adam_beta2 = 0.9998113167362397 -adam_eps = 6.301709731262074e-9 -bptt_horizon = 64 -clip_coef = 0.22131450913204256 -ent_coef = 0.0020310049268479863 -gae_lambda = 0.8854219852971792 -gamma = 0.9608378504980243 -learning_rate = 0.07109386062895108 -max_grad_norm = 1.7820203601055993 -minibatch_size = 32768 -prio_alpha = 0.09999999999999998 -prio_beta0 = 0.7475661360032159 -vf_clip_coef = 2.7025841941932303 -vf_coef = 1.9960893747329385 -vtrace_c_clip = 1.0873122745787867 -vtrace_rho_clip = 2.784150207139061 - -[sweep.train.total_timesteps] -distribution = log_normal -min = 1e7 -max = 2e8 -mean = 8e7 -scale = auto - -[sweep.env.frameskip] -distribution = int_uniform -min = 1 -max = 8 -mean = 4 -scale = 2.0 diff --git a/pufferlib/config/ocean/rware.ini b/pufferlib/config/ocean/rware.ini deleted file mode 100644 index 705e0af3ee..0000000000 --- a/pufferlib/config/ocean/rware.ini +++ /dev/null @@ -1,26 +0,0 @@ -[base] -package = ocean -env_name = puffer_rware -policy_name = Policy -rnn_name = Recurrent - -[vec] -num_envs = 8 - -[env] -num_envs = 128 -map_choice = 2 -num_agents = 8 -num_requested_shelves = 8 - -[train] -total_timesteps = 100_000_000 -learning_rate = 0.05 -minibatch_size = 32768 - -[sweep.train.total_timesteps] -distribution = log_normal -min = 3e7 -max = 3e8 -mean = 1e8 -scale = 0.25 diff --git a/pufferlib/config/ocean/slimevolley.ini b/pufferlib/config/ocean/slimevolley.ini deleted file mode 100644 index 1889a74054..0000000000 --- a/pufferlib/config/ocean/slimevolley.ini +++ /dev/null @@ -1,12 +0,0 @@ -[base] -package = ocean -env_name = puffer_slimevolley -policy_name = Policy - -[env] -; 1 for single-agent (vs bot), 2 for two-agent (self-play) -num_agents=1 -num_envs=4096 - -[train] -total_timesteps = 100_000_000 diff --git a/pufferlib/config/ocean/snake.ini b/pufferlib/config/ocean/snake.ini deleted file mode 100644 index 3827b02527..0000000000 --- a/pufferlib/config/ocean/snake.ini +++ /dev/null @@ -1,62 +0,0 @@ -[base] -package = ocean -env_name = puffer_snake -policy_name = Snake -#policy_name = Policy -rnn_name = Recurrent - -[env] -num_envs = 4 -width = 640 -height = 360 -num_snakes = 256 -num_food = 4096 -vision = 5 -leave_corpse_on_death = True -reward_food = 0.1 -reward_corpse = 0.1 -reward_death = -1.0 - -[vec] -num_envs = 16 - -[train] -total_timesteps = 500_000_000 -adam_beta1 = 0.6762060389098516 -adam_beta2 = 0.9 -adam_eps = 0.000002764249390410885 -bptt_horizon = 64 -clip_coef = 0.7379459916127813 -ent_coef = 0.010507292602201058 -gae_lambda = 0.6006253996849398 -gamma = 0.9997067226101388 -learning_rate = 0.016779905178021273 -max_grad_norm = 0.6504710763256233 -minibatch_size = 32768 -prio_alpha = 0.6082618023318664 -prio_beta0 = 0.447524297405661 -vf_clip_coef = 2.830994746057568 -vf_coef = 3.9655925817980053 -vtrace_c_clip = 0 -vtrace_rho_clip = 0.9285200248552337 - -[sweep.env.reward_food] -distribution = uniform -min = 0.0 -max = 1.0 -mean = 0.0 -scale = auto - -[sweep.env.reward_death] -distribution = uniform -min = -1.0 -max = 0.0 -mean = 0.0 -scale = auto - -[sweep.train.total_timesteps] -distribution = log_normal -min = 5e7 -max = 2e8 -mean = 1e8 -scale = auto diff --git a/pufferlib/config/ocean/squared.ini b/pufferlib/config/ocean/squared.ini deleted file mode 100644 index ac9f69d0fd..0000000000 --- a/pufferlib/config/ocean/squared.ini +++ /dev/null @@ -1,14 +0,0 @@ -[base] -package = ocean -env_name = puffer_squared -policy_name = Policy -rnn_name = Recurrent - -[env] -num_envs = 4096 - -[train] -total_timesteps = 20_000_000 -gamma = 0.95 -learning_rate = 0.05 -minibatch_size = 32768 diff --git a/pufferlib/config/ocean/tactical.ini b/pufferlib/config/ocean/tactical.ini deleted file mode 100644 index 762cd10059..0000000000 --- a/pufferlib/config/ocean/tactical.ini +++ /dev/null @@ -1,3 +0,0 @@ -[base] -package = ocean -env_name = puffer_tactical diff --git a/pufferlib/config/ocean/terraform.ini b/pufferlib/config/ocean/terraform.ini deleted file mode 100644 index b64d19dc09..0000000000 --- a/pufferlib/config/ocean/terraform.ini +++ /dev/null @@ -1,61 +0,0 @@ -[base] -package = ocean -env_name = puffer_terraform -policy_name = Terraform -rnn_name = Recurrent - -[vec] -num_envs = 8 -#backend = Serial -[env] -num_envs = 1024 -num_agents = 1 -reset_frequency = 1024 -reward_scale = 0.11 - -[policy] -hidden_size = 256 - -[rnn] -input_size = 256 -hidden_size = 256 - -[train] -total_timesteps = 1_000_000_000 -adam_beta1 = 0.8792313963264954 -adam_beta2 = 0.9980457691558037 -adam_eps = 0.0000060001757672174796 -bptt_horizon = 64 -ent_coef = 0.007047731279570716 -gae_lambda = 0.95 -gamma = 0.98 -learning_rate = 0.005 -max_grad_norm = 1.1870216773228415 -minibatch_size = 32768 -prio_alpha = 0.498348178927537 -prio_beta0 = 0.7687009564385903 -vf_clip_coef = 1.4509861770544443 -vf_coef = 3.175722544969796 -vtrace_c_clip = 0.937506506536413 -vtrace_rho_clip = 1.208308436542831 - -[sweep.train.total_timesteps] -distribution = log_normal -min = 2e8 -max = 6e8 -mean = 4e8 -scale = time - -#[sweep.env.reset_frequency] -#distribution = int_uniform -#min = 1024 -#max = 16384 -#mean = 8192 -#scale = auto - -[sweep.env.reward_scale] -distribution = log_normal -min = 0.01 -max = 1 -mean = 0.5 -scale = auto diff --git a/pufferlib/config/ocean/tetris.ini b/pufferlib/config/ocean/tetris.ini deleted file mode 100644 index 5aab214224..0000000000 --- a/pufferlib/config/ocean/tetris.ini +++ /dev/null @@ -1,80 +0,0 @@ -[base] -package = ocean -env_name = puffer_tetris -policy_name = Policy -rnn_name = Recurrent - -[vec] -num_envs = 8 - -[env] -num_envs = 2048 -n_rows = 20 -n_cols = 10 -use_deck_obs = True -n_init_garbage = 4 -# This is experimental. Sometimes it works. -n_noise_obs = 0 - -[policy] -hidden_size = 256 - -[rnn] -input_size = 256 -hidden_size = 256 - -[train] -# https://wandb.ai/kywch/pufferlib/runs/era6a8p6?nw=nwuserkywch -total_timesteps = 3_000_000_000 -batch_size = auto -bptt_horizon = 64 -minibatch_size = 65536 - -adam_beta1 = 0.95 -adam_beta2 = 0.9999 -adam_eps = 1e-10 -clip_coef = 0.1 -ent_coef = 0.02 -gae_lambda = 0.55 -gamma = 0.995 -learning_rate = 0.012 -max_grad_norm = 5 -prio_alpha = 0.99 -prio_beta0 = 0.91 -vf_clip_coef = 1.5 -vf_coef = 4.74 -vtrace_c_clip = 1.29 -vtrace_rho_clip = 0.70 - - -[sweep] -metric = score -goal = maximize - -[sweep.train.total_timesteps] -distribution = log_normal -min = 30_000_000 -max = 3_000_000_000 -mean = 200_000_000 -scale = auto - -[sweep.train.gae_lambda] -distribution = logit_normal -min = 0.01 -mean = 0.6 -max = 0.995 -scale = auto - -[sweep.train.clip_coef] -distribution = uniform -min = 0.01 -max = 1.0 -mean = 0.1 -scale = auto - -[sweep.train.adam_beta1] -distribution = logit_normal -min = 0.5 -mean = 0.95 -max = 0.999 -scale = auto diff --git a/pufferlib/config/ocean/tower_climb.ini b/pufferlib/config/ocean/tower_climb.ini deleted file mode 100644 index 70d486b84e..0000000000 --- a/pufferlib/config/ocean/tower_climb.ini +++ /dev/null @@ -1,76 +0,0 @@ -[base] -package = ocean -env_name = puffer_tower_climb -policy_name = TowerClimb -rnn_name = TowerClimbLSTM - -[vec] -num_envs = 4 - -[env] -num_envs = 1024 -num_maps = 200 -reward_climb_row = 0.27 -reward_fall_row = 0 -reward_illegal_move = 0 -reward_move_block = 0.18 - -[train] -# https://wandb.ai/kywch/pufferlib/runs/8r3l9l1h?nw=nwuserkywch -total_timesteps = 30_000_000 -anneal_lr = True -batch_size = auto -bptt_horizon = 64 -minibatch_size = 65536 - -clip_coef = 1.0 -ent_coef = 0.2 -gae_lambda = 0.96 -gamma = 0.92 -vf_clip_coef = 0.1 -vf_coef = 0.34 - -learning_rate = 0.029 -max_grad_norm = 0.8 - -adam_beta1 = 0.89 -adam_beta2 = 0.999 -adam_eps = 2e-11 -prio_alpha = 0.86 -prio_beta0 = 0.30 -vtrace_c_clip = 0.92 -vtrace_rho_clip = 1.44 - -[sweep] -metric = perf -metric_distribution = percentile - -[sweep.train.total_timesteps] -distribution = uniform -min = 10_000_000 -max = 200_000_000 -scale = 0.5 - -[sweep.env.reward_climb_row] -distribution = uniform -min = 0.0 -max = 1.0 -scale = auto - -[sweep.env.reward_fall_row] -distribution = uniform -min = -1.0 -max = 0.0 -scale = auto - -[sweep.env.reward_illegal_move] -distribution = uniform -min = -1e-2 -max = -1e-4 -scale = auto - -[sweep.env.reward_move_block] -distribution = uniform -min = 0.0 -max = 1.0 -scale = auto diff --git a/pufferlib/config/ocean/trash_pickup.ini b/pufferlib/config/ocean/trash_pickup.ini deleted file mode 100644 index bb235ababa..0000000000 --- a/pufferlib/config/ocean/trash_pickup.ini +++ /dev/null @@ -1,28 +0,0 @@ -[base] -package = ocean -env_name = puffer_trash_pickup -policy_name = TrashPickup -rnn_name = Recurrent - -[vec] -num_envs = 8 - -[env] -num_envs = 128 -grid_size = 20 -num_agents = 8 -num_trash = 40 -num_bins = 2 -max_steps = 500 -report_interval = 32 -agent_sight_range = 5 - -[train] -total_timesteps = 100_000_000 - -[sweep.train.total_timesteps] -distribution = log_normal -min = 3e7 -max = 2e8 -mean = 1e8 -scale = 0.5 diff --git a/pufferlib/config/ocean/tripletriad.ini b/pufferlib/config/ocean/tripletriad.ini deleted file mode 100644 index aae55d0968..0000000000 --- a/pufferlib/config/ocean/tripletriad.ini +++ /dev/null @@ -1,21 +0,0 @@ -[base] -package = ocean -env_name = puffer_tripletriad -policy_name = Policy -rnn_name = Recurrent - -[env] -num_envs = 1024 - -[vec] -num_envs = 8 - -[train] -total_timesteps = 100_000_000 - -[sweep.train.total_timesteps] -distribution = log_normal -min = 5e7 -max = 2e8 -mean = 1e8 -scale = 0.25 diff --git a/pufferlib/config/open_spiel.ini b/pufferlib/config/open_spiel.ini deleted file mode 100644 index a3210cb79f..0000000000 --- a/pufferlib/config/open_spiel.ini +++ /dev/null @@ -1,7 +0,0 @@ -[base] -package = open_spiel -env_name = connect_four - -[train] -num_envs = 32 -batch_size = 4096 diff --git a/pufferlib/config/pokemon_red.ini b/pufferlib/config/pokemon_red.ini deleted file mode 100644 index a0c2485ce4..0000000000 --- a/pufferlib/config/pokemon_red.ini +++ /dev/null @@ -1,17 +0,0 @@ -[base] -package = pokemon_red -env_name = pokemon_red - -[train] -total_timesteps = 1_000_000 -num_envs = 96 -num_workers = 24 -env_batch_size = 32 -zero_copy = False -update_epochs = 3 -gamma = 0.998 -batch_size = 65536 -minibatch_size = 2048 -compile = True -learning_rate = 2.0e-4 -anneal_lr = False diff --git a/pufferlib/config/procgen.ini b/pufferlib/config/procgen.ini deleted file mode 100644 index cc7c6cba8b..0000000000 --- a/pufferlib/config/procgen.ini +++ /dev/null @@ -1,15 +0,0 @@ -[base] -package = procgen -env_name = bigfish bossfight caveflyer chaser climber coinrun dodgeball fruitbot heist jumper leaper maze miner ninja plunder starpilot - -[vec] -num_envs = 128 -num_workers = 16 -batch_size = 64 - -[train] -batch_size = 8192 -minibatch_size = 2048 -update_epochs = 1 -bptt_horizon = 64 -total_timesteps = 25_000_000 diff --git a/pufferlib/config/slimevolley.ini b/pufferlib/config/slimevolley.ini deleted file mode 100644 index 847672f6d4..0000000000 --- a/pufferlib/config/slimevolley.ini +++ /dev/null @@ -1,12 +0,0 @@ -[base] -package = slimevolley -env_name = slimevolley - -[train] -num_envs=1536 -num_workers=24 -env_batch_size=512 -zero_copy=False -batch_size=65536 -minibatch_size=8192 -update_epochs=1 diff --git a/pufferlib/config/stable_retro.ini b/pufferlib/config/stable_retro.ini deleted file mode 100644 index 8f22399864..0000000000 --- a/pufferlib/config/stable_retro.ini +++ /dev/null @@ -1,3 +0,0 @@ -[base] -package = stable_retro -env_name = Airstriker-Genesis diff --git a/pufferlib/config/starcraft.ini b/pufferlib/config/starcraft.ini deleted file mode 100644 index 9af2bfb114..0000000000 --- a/pufferlib/config/starcraft.ini +++ /dev/null @@ -1,2 +0,0 @@ -[base] -package = smac diff --git a/pufferlib/config/trade_sim.ini b/pufferlib/config/trade_sim.ini deleted file mode 100644 index 2a7f5b4054..0000000000 --- a/pufferlib/config/trade_sim.ini +++ /dev/null @@ -1,30 +0,0 @@ -[base] -package = trade_sim -env_name = trade_sim -policy_name = Policy -rnn_name = Recurrent - -[vec] -backend = Multiprocessing -num_envs = 1024 -num_workers = 16 -batch_size = 512 - -#[env] -#num_envs = 128 - -[train] -total_timesteps = 100_000_000 -gamma = 0.95 -learning_rate = 0.05 -minibatch_size = 32768 - -[sweep] -metric = final_capital - -[sweep.train.total_timesteps] -distribution = log_normal -min = 2e7 -max = 1e8 -mean = 5e7 -scale = auto diff --git a/pufferlib/config/tribal_village.ini b/pufferlib/config/tribal_village.ini deleted file mode 100644 index 6eb5bb96ae..0000000000 --- a/pufferlib/config/tribal_village.ini +++ /dev/null @@ -1,60 +0,0 @@ -[base] -package = tribal_village -env_name = tribal_village tribal-village -policy_name = Policy -rnn_name = Recurrent - -[vec] -num_envs = 192 -num_workers = 12 - -[env] -render_mode = rgb_array -max_steps = 512 -ore_per_battery = 3 -batteries_per_heart = 2 -enable_combat = True -clippy_spawn_rate = 0.1 -clippy_damage = 10 -heart_reward = 1.0 -battery_reward = 0.5 -ore_reward = 0.1 -survival_penalty = -0.01 -death_penalty = -1.0 - -[train] -total_timesteps = 50_000_000 -batch_size = auto -bptt_horizon = 32 -learning_rate = 0.001 -ent_coef = 0.01 -vf_coef = 0.5 -max_grad_norm = 0.5 -gamma = 0.99 -gae_lambda = 0.95 -clip_coef = 0.2 -minibatch_size = 32768 - -[sweep] -metric = agent/heart.gained - -[sweep.env.heart_reward] -distribution = uniform -min = 0.5 -mean = 1.0 -max = 2.0 -scale = auto - -[sweep.env.battery_reward] -distribution = uniform -min = 0.1 -mean = 0.5 -max = 1.0 -scale = auto - -[sweep.env.ore_reward] -distribution = uniform -min = 0.01 -mean = 0.1 -max = 0.5 -scale = auto diff --git a/pufferlib/emulation.py b/pufferlib/emulation.py deleted file mode 100644 index f576f530f0..0000000000 --- a/pufferlib/emulation.py +++ /dev/null @@ -1,518 +0,0 @@ -from pdb import set_trace as T - -import numpy as np -import warnings - -import gymnasium -import inspect - -import pufferlib -import pufferlib.spaces -from pufferlib.spaces import Discrete, Tuple, Dict - -def emulate(struct, sample): - if isinstance(sample, dict): - for k, v in sample.items(): - emulate(struct[k], v) - elif isinstance(sample, tuple): - for i, v in enumerate(sample): - emulate(struct[f'f{i}'], v) - else: - struct[()] = sample - -def make_buffer(arr_dtype, struct_dtype, struct, n=None): - '''None instead of 1 makes it work for 1 agent PZ envs''' - ''' - if n is None: - struct = np.zeros(1, dtype=struct_dtype) - else: - struct = np.zeros(n, dtype=struct_dtype) - ''' - - arr = struct.view(arr_dtype) - - if n is None: - arr = arr.ravel() - else: - arr = arr.reshape(n, -1) - - return arr - -def _nativize(struct, space): - if isinstance(space, Discrete): - return struct.item() - elif isinstance(space, Tuple): - return tuple(_nativize(struct[f'f{i}'], elem) - for i, elem in enumerate(space)) - elif isinstance(space, Dict): - return {k: _nativize(struct[k], value) - for k, value in space.items()} - else: - return struct - -def nativize(arr, space, struct_dtype): - struct = np.asarray(arr).view(struct_dtype)[0] - return _nativize(struct, space) - -# TODO: Uncomment? -''' -try: - from pufferlib.extensions import emulate, nativize -except ImportError: - warnings.warn('PufferLib Cython extensions not installed. Using slow Python versions') -''' - -def get_dtype_bounds(dtype): - if dtype == bool: - return 0, 1 - elif np.issubdtype(dtype, np.integer): - return np.iinfo(dtype).min, np.iinfo(dtype).max - elif np.issubdtype(dtype, np.unsignedinteger): - return np.iinfo(dtype).min, np.iinfo(dtype).max - elif np.issubdtype(dtype, np.floating): - # Gym fails on float64 - return np.finfo(np.float32).min, np.finfo(np.float32).max - else: - raise ValueError(f"Unsupported dtype: {dtype}") - - -def dtype_from_space(space): - if isinstance(space, pufferlib.spaces.Tuple): - dtype = [] - for i, elem in enumerate(space): - dtype.append((f'f{i}', dtype_from_space(elem))) - elif isinstance(space, pufferlib.spaces.Dict): - dtype = [] - for k, value in space.items(): - dtype.append((k, dtype_from_space(value))) - elif isinstance(space, (pufferlib.spaces.Discrete)): - dtype = (np.int32, ()) - elif isinstance(space, (pufferlib.spaces.MultiDiscrete)): - dtype = (np.int32, (len(space.nvec),)) - else: - dtype = (space.dtype, space.shape) - - return np.dtype(dtype, align=True) - -def flatten_space(space): - if isinstance(space, pufferlib.spaces.Tuple): - subspaces = [] - for e in space: - subspaces.extend(flatten_space(e)) - return subspaces - elif isinstance(space, pufferlib.spaces.Dict): - subspaces = [] - for e in space.values(): - subspaces.extend(flatten_space(e)) - return subspaces - else: - return [space] - -def emulate_observation_space(space): - emulated_dtype = dtype_from_space(space) - - if isinstance(space, pufferlib.spaces.Box): - return space, emulated_dtype - - leaves = flatten_space(space) - dtypes = [e.dtype for e in leaves] - if dtypes.count(dtypes[0]) == len(dtypes): - dtype = dtypes[0] - else: - dtype = np.dtype(np.uint8) - - mmin, mmax = get_dtype_bounds(dtype) - numel = emulated_dtype.itemsize // dtype.itemsize - emulated_space = gymnasium.spaces.Box(low=mmin, high=mmax, shape=(numel,), dtype=dtype) - return emulated_space, emulated_dtype - -def emulate_action_space(space): - if isinstance(space, pufferlib.spaces.Box): - return space, space.dtype - elif isinstance(space, (pufferlib.spaces.Discrete, pufferlib.spaces.MultiDiscrete)): - return space, np.int32 - - emulated_dtype = dtype_from_space(space) - leaves = flatten_space(space) - emulated_space = gymnasium.spaces.MultiDiscrete([e.n for e in leaves]) - return emulated_space, emulated_dtype - - -class GymnasiumPufferEnv(gymnasium.Env): - def __init__(self, env=None, env_creator=None, env_args=[], env_kwargs={}, buf=None, seed=0): - self.env = make_object(env, env_creator, env_args, env_kwargs) - - self.initialized = False - self.done = True - - self.is_observation_checked = False - self.is_action_checked = False - - self.observation_space, self.obs_dtype = emulate_observation_space( - self.env.observation_space) - self.action_space, self.atn_dtype = emulate_action_space( - self.env.action_space) - self.single_observation_space = self.observation_space - self.single_action_space = self.action_space - self.num_agents = 1 - - self.is_obs_emulated = self.single_observation_space is not self.env.observation_space - self.is_atn_emulated = self.single_action_space is not self.env.action_space - self.emulated = dict( - observation_dtype=self.observation_space.dtype, - emulated_observation_dtype=self.obs_dtype, - ) - - self.render_modes = 'human rgb_array'.split() - - pufferlib.set_buffers(self, buf) - if isinstance(self.env.observation_space, pufferlib.spaces.Box): - self.obs_struct = self.observations - else: - self.obs_struct = self.observations.view(self.obs_dtype) - - @property - def render_mode(self): - return self.env.render_mode - - def seed(self, seed): - self.env.seed(seed) - - def reset(self, seed=None): - self.initialized = True - self.done = False - - ob, info = _seed_and_reset(self.env, seed) - if not self.is_observation_checked: - self.is_observation_checked = check_space( - ob, self.env.observation_space) - - if self.is_obs_emulated: - emulate(self.obs_struct, ob) - else: - self.observations[:] = ob - - self.rewards[0] = 0 - self.terminals[0] = False - self.truncations[0] = False - self.masks[0] = True - - return self.observations, info - - def step(self, action): - '''Execute an action and return (observation, reward, done, info)''' - if not self.initialized: - raise pufferlib.APIUsageError('step() called before reset()') - if self.done: - raise pufferlib.APIUsageError('step() called after environment is done') - - # Unpack actions from multidiscrete into the original action space - if self.is_atn_emulated: - action = nativize(action, self.env.action_space, self.atn_dtype) - elif isinstance(action, np.ndarray): - action = action.ravel() - # TODO: profile or speed up - if isinstance(self.action_space, pufferlib.spaces.Discrete): - action = action[0] - - if not self.is_action_checked: - self.is_action_checked = check_space( - action, self.env.action_space) - - ob, reward, done, truncated, info = self.env.step(action) - - - if self.is_obs_emulated: - emulate(self.obs_struct, ob) - else: - self.observations[:] = ob - - self.rewards[0] = reward - self.terminals[0] = done - self.truncations[0] = truncated - self.masks[0] = True - - self.done = done or truncated - return self.observations, reward, done, truncated, info - - def render(self): - return self.env.render() - - def close(self): - return self.env.close() - -class PettingZooPufferEnv: - def __init__(self, env=None, env_creator=None, env_args=[], env_kwargs={}, buf=None, seed=0): - self.env = make_object(env, env_creator, env_args, env_kwargs) - self.initialized = False - self.all_done = True - - self.is_observation_checked = False - self.is_action_checked = False - - # Compute the observation and action spaces - single_agent = self.possible_agents[0] - self.env_single_observation_space = self.env.observation_space(single_agent) - self.env_single_action_space = self.env.action_space(single_agent) - self.single_observation_space, self.obs_dtype = ( - emulate_observation_space(self.env_single_observation_space)) - self.single_action_space, self.atn_dtype = ( - emulate_action_space(self.env_single_action_space)) - self.is_obs_emulated = self.single_observation_space is not self.env_single_observation_space - self.is_atn_emulated = self.single_action_space is not self.env_single_action_space - self.emulated = dict( - observation_dtype = self.single_observation_space.dtype, - emulated_observation_dtype = self.obs_dtype, - ) - - self.num_agents = len(self.possible_agents) - - pufferlib.set_buffers(self, buf) - if isinstance(self.env_single_observation_space, pufferlib.spaces.Box): - self.obs_struct = self.observations - else: - self.obs_struct = self.observations.view(self.obs_dtype) - - @property - def render_mode(self): - return self.env.render_mode - - @property - def agents(self): - return self.env.agents - - @property - def possible_agents(self): - return self.env.possible_agents - - @property - def done(self): - return len(self.agents) == 0 or self.all_done - - def observation_space(self, agent): - '''Returns the observation space for a single agent''' - if agent not in self.possible_agents: - raise pufferlib.InvalidAgentError(agent, self.possible_agents) - - return self.single_observation_space - - def action_space(self, agent): - '''Returns the action space for a single agent''' - if agent not in self.possible_agents: - raise pufferlib.InvalidAgentError(agent, self.possible_agents) - - return self.single_action_space - - def reset(self, seed=None): - if not self.initialized: - self.dict_obs = {agent: self.observations[i] for i, agent in enumerate(self.possible_agents)} - - self.initialized = True - self.all_done = False - self.mask = {k: False for k in self.possible_agents} - - obs, info = self.env.reset(seed=seed) - - if not self.is_observation_checked: - for k, ob in obs.items(): - self.is_observation_checked = check_space( - ob, self.env.observation_space(k)) - - # Call user featurizer and flatten the observations - self.observations[:] = 0 - for i, agent in enumerate(self.possible_agents): - if agent not in obs: - continue - - ob = obs[agent] - self.mask[agent] = True - if self.is_obs_emulated: - emulate(self.obs_struct[i], ob) - else: - self.observations[i] = ob - - self.rewards[:] = 0 - self.terminals[:] = False - self.truncations[:] = False - self.masks[:] = True - return self.dict_obs, info - - def step(self, actions): - '''Step the environment and return (observations, rewards, dones, infos)''' - if not self.initialized: - raise pufferlib.APIUsageError('step() called before reset()') - if self.done: - raise pufferlib.APIUsageError('step() called after environment is done') - - if isinstance(actions, np.ndarray): - if not self.is_action_checked and len(actions) != self.num_agents: - raise pufferlib.APIUsageError( - f'Actions specified as len {len(actions)} but environment has {self.num_agents} agents') - - actions = {agent: actions[i] for i, agent in enumerate(self.possible_agents)} - - # Postprocess actions and validate action spaces - if not self.is_action_checked: - for agent in actions: - if agent not in self.possible_agents: - raise pufferlib.InvalidAgentError(agent, self.possible_agents) - - self.is_action_checked = check_space( - next(iter(actions.values())), - self.single_action_space - ) - - # Unpack actions from multidiscrete into the original action space - unpacked_actions = {} - for agent, atn in actions.items(): - if agent not in self.possible_agents: - raise pufferlib.InvalidAgentError(agent, self.agents) - - if agent not in self.agents: - continue - - if self.is_atn_emulated: - atn = nativize(atn, self.env_single_action_space, self.atn_dtype) - - unpacked_actions[agent] = atn - - obs, rewards, dones, truncateds, infos = self.env.step(unpacked_actions) - # TODO: Can add this assert once NMMO Horizon is ported to puffer - # assert all(dones.values()) == (len(self.env.agents) == 0) - self.mask = {k: False for k in self.possible_agents} - self.rewards[:] = 0 - self.terminals[:] = True - self.truncations[:] = False - for i, agent in enumerate(self.possible_agents): - # TODO: negative padding buf - if agent not in obs: - self.observations[i] = 0 - self.rewards[i] = 0 - self.terminals[i] = True - self.truncations[i] = False - self.masks[i] = False - continue - - ob = obs[agent] - self.mask[agent] = True - if self.is_obs_emulated: - emulate(self.obs_struct[i], ob) - else: - self.observations[i] = ob - - self.rewards[i] = rewards[agent] - self.terminals[i] = dones[agent] - self.truncations[i] = truncateds[agent] - self.masks[i] = True - - self.all_done = all(dones.values()) or all(truncateds.values()) - rewards = pad_agent_data(rewards, self.possible_agents, 0) - dones = pad_agent_data(dones, self.possible_agents, True) # You changed this from false to match api test... is this correct? - truncateds = pad_agent_data(truncateds, self.possible_agents, False) - return self.dict_obs, rewards, dones, truncateds, infos - - def render(self): - return self.env.render() - - def close(self): - return self.env.close() - -def pad_agent_data(data, agents, pad_value): - return {agent: data[agent] if agent in data else pad_value - for agent in agents} - -def make_object(object_instance=None, object_creator=None, creator_args=[], creator_kwargs={}): - if (object_instance is None) == (object_creator is None): - raise ValueError('Exactly one of object_instance or object_creator must be provided') - - if object_instance is not None: - if callable(object_instance) or inspect.isclass(object_instance): - raise TypeError('object_instance must be an instance, not a function or class') - return object_instance - - if object_creator is not None: - if not callable(object_creator): - raise TypeError('object_creator must be a callable') - - if creator_args is None: - creator_args = [] - - if creator_kwargs is None: - creator_kwargs = {} - - return object_creator(*creator_args, **creator_kwargs) - -def check_space(data, space): - try: - contains = space.contains(data) - except: - raise pufferlib.APIUsageError( - f'Error checking space {space} with sample :\n{data}') - - if not contains: - raise pufferlib.APIUsageError( - f'Data:\n{data}\n not in space:\n{space}') - - return True - -def _seed_and_reset(env, seed): - if seed is None: - # Gym bug: does not reset env correctly - # when seed is passed as explicit None - return env.reset() - - try: - obs, info = env.reset(seed=seed) - except: - try: - env.seed(seed) - obs, info = env.reset() - except: - obs, info = env.reset() - warnings.warn('WARNING: Environment does not support seeding.', DeprecationWarning) - - return obs, info - -class GymnaxPufferEnv(pufferlib.PufferEnv): - def __init__(self, env, env_params, num_envs=1, buf=None): - from gymnax.spaces import gymnax_space_to_gym_space - - gymnax_obs_space = env.observation_space(env_params) - self.single_observation_space = gymnax_space_to_gym_space(gymnax_obs_space) - - gymnax_act_space = env.action_space(env_params) - self.single_action_space = gymnax_space_to_gym_space(gymnax_act_space) - - self.num_agents = num_envs - - super().__init__(buf) - self.env_params = env_params - self.env = env - - import jax - self.reset_fn = jax.jit(jax.vmap(env.reset, in_axes=(0, None))) - self.step_fn = jax.jit(jax.vmap(env.step, in_axes=(0, 0, 0, None))) - self.rng = jax.random.PRNGKey(0) - - def reset(self, rng, params=None): - import jax - self.rng, _rng = jax.random.split(self.rng) - self.rngs = jax.random.split(_rng, self.num_agents) - obs, self.state = self.reset_fn(self.rngs, params) - from torch.utils import dlpack as torch_dlpack - self.observations = torch_dlpack.from_dlpack(jax.dlpack.to_dlpack(obs)) - return self.observations, [] - - def step(self, action): - import jax - #self.rng, _rng = jax.random.split(self.rng) - #rngs = jax.random.split(_rng, self.num_agents) - obs, self.state, reward, done, info = self.step_fn(self.rngs, self.state, action, self.env_params) - - # Convert JAX array to DLPack, then to PyTorch tensor - from torch.utils import dlpack as torch_dlpack - self.observations = torch_dlpack.from_dlpack(jax.dlpack.to_dlpack(obs)) - self.rewards = np.asarray(reward) - self.terminals = np.asarray(done) - infos = [{k: v.mean().item() for k, v in info.items()}] - return self.observations, self.rewards, self.terminals, self.terminals, infos diff --git a/pufferlib/environments/__init__.py b/pufferlib/environments/__init__.py deleted file mode 100644 index d6c969523e..0000000000 --- a/pufferlib/environments/__init__.py +++ /dev/null @@ -1,21 +0,0 @@ -from pdb import set_trace as T -import pufferlib - -def try_import(module_path, package_name=None): - if package_name is None: - package_name = module_path - try: - package = __import__(module_path) - except ImportError as e: - raise ImportError( - f'{e.args[0]}\n\n' - 'This is probably an installation error. Try: ' - f'pip install pufferlib[{package_name}]. ' - - 'Note that some environments have non-python dependencies. ' - 'These are included in PufferTank. Or, you can install ' - 'manually by following the instructions provided by the ' - 'environment meaintainers. But some are finicky, so we ' - 'recommend using PufferTank.' - ) from e - return package diff --git a/pufferlib/environments/atari/__init__.py b/pufferlib/environments/atari/__init__.py deleted file mode 100644 index 59cda9e7c2..0000000000 --- a/pufferlib/environments/atari/__init__.py +++ /dev/null @@ -1,12 +0,0 @@ -from .environment import env_creator - -try: - import torch -except ImportError: - pass -else: - from .torch import Policy - try: - from .torch import Recurrent - except: - Recurrent = None diff --git a/pufferlib/environments/atari/environment.py b/pufferlib/environments/atari/environment.py deleted file mode 100644 index 92295ecaa9..0000000000 --- a/pufferlib/environments/atari/environment.py +++ /dev/null @@ -1,215 +0,0 @@ -from pdb import set_trace as T -import numpy as np -import functools - -import gymnasium as gym - -import pufferlib -import pufferlib.emulation -import pufferlib.environments - -def env_creator(name='breakout'): - return functools.partial(make, name) - -def make(name, obs_type='grayscale', frameskip=4, - full_action_space=False, framestack=1, - repeat_action_probability=0.0, render_mode='rgb_array', - buf=None, seed=0): - '''Atari creation function''' - pufferlib.environments.try_import('ale_py', 'AtariEnv') - - ale_render_mode = render_mode - if render_mode == 'human': - ale_render_mode = 'rgb_array' - obs_type = 'rgb' - frameskip = 1 - full_action_space = True - upscale = 4 - elif render_mode == 'raylib': - ale_render_mode = 'rgb_array' - upscale = 8 - - from ale_py import AtariEnv - env = AtariEnv(name, obs_type=obs_type, frameskip=frameskip, - repeat_action_probability=repeat_action_probability, - full_action_space=full_action_space, - render_mode=ale_render_mode) - - action_set = env._action_set - - if render_mode != 'human': - env = pufferlib.ResizeObservation(env, downscale=2) - - if framestack > 1: - env = gym.wrappers.FrameStack(env, framestack) - - if render_mode in ('human', 'raylib'): - env = RaylibClient(env, action_set, frameskip, upscale) - else: - env = AtariPostprocessor(env) # Don't use standard postprocessor - - env = pufferlib.EpisodeStats(env) - env = pufferlib.emulation.GymnasiumPufferEnv(env=env, buf=buf) - return env - -class AtariPostprocessor(gym.Wrapper): - '''Atari breaks the normal PufferLib postprocessor because - it sends terminal=True every live, not every episode''' - def __init__(self, env): - super().__init__(env) - shape = env.observation_space.shape - if len(shape) < 3: - shape = (1, *shape) - else: - shape = (shape[2], shape[0], shape[1]) - - self.observation_space = gym.spaces.Box(low=0, high=255, - shape=shape, dtype=env.observation_space.dtype) - - def unsqueeze_transpose(self, obs): - if len(obs.shape) == 3: - return np.transpose(obs, (2, 0, 1)) - else: - return np.expand_dims(obs, 0) - - def reset(self, seed=None, options=None): - obs, _ = self.env.reset(seed=seed) - return self.unsqueeze_transpose(obs), {} - - def step(self, action): - obs, reward, terminal, truncated, _ = self.env.step(action) - return self.unsqueeze_transpose(obs), reward, terminal, truncated, {} - -class RaylibClient(gym.Wrapper): - def __init__(self, env, action_set, frameskip=4, upscale=4): - self.env = env - - self.keymap = {} - for i, atn in enumerate(action_set): - self.keymap[atn.value] = i - - obs_shape = env.observation_space.shape - if len(obs_shape) == 2: - height, width = obs_shape - channels = 1 - else: - height, width, channels = obs_shape - - height *= upscale - width *= upscale - from raylib import rl, colors - rl.InitWindow(width, height, "Atari".encode()) - rl.SetTargetFPS(60//frameskip) - self.rl = rl - self.colors = colors - - - import numpy as np - rendered = np.zeros((width, height, 4), dtype=np.uint8) - - import pyray - from cffi import FFI - raylib_image = pyray.Image(FFI().from_buffer(rendered.data), - width, height, 1, pyray.PIXELFORMAT_UNCOMPRESSED_R8G8B8) - self.texture = rl.LoadTextureFromImage(raylib_image) - self.action = 0 - - self.upscale = upscale - self.rescaler = np.ones((upscale, upscale, 1), dtype=np.uint8) - - def any_key_pressed(self, keys): - for key in keys: - if self.rl.IsKeyPressed(key): - return True - return False - - def any_key_down(self, keys): - for key in keys: - if self.rl.IsKeyDown(key): - return True - return False - - def down(self): - return self.any_key_down([self.rl.KEY_S, self.rl.KEY_DOWN]) - - def up(self): - return self.any_key_down([self.rl.KEY_W, self.rl.KEY_UP]) - - def left(self): - return self.any_key_down([self.rl.KEY_A, self.rl.KEY_LEFT]) - - def right(self): - return self.any_key_down([self.rl.KEY_D, self.rl.KEY_RIGHT]) - - def render(self): - from ale_py import Action - - rl = self.rl - if rl.IsKeyPressed(rl.KEY_ESCAPE): - exit(0) - - elif rl.IsKeyDown(rl.KEY_SPACE): - if self.left() and self.down(): - action = Action.DOWNLEFTFIRE.value - elif self.right() and self.down(): - action = Action.DOWNRIGHTFIRE.value - elif self.left() and self.up(): - action = Action.UPLEFTFIRE.value - elif self.right() and self.up(): - action = Action.UPRIGHTFIRE.value - elif self.left(): - action = Action.LEFTFIRE.value - elif self.right(): - action = Action.RIGHTFIRE.value - elif self.up(): - action = Action.UPFIRE.value - elif self.down(): - action = Action.DOWNFIRE.value - else: - action = Action.FIRE.value - elif self.left() and self.down(): - action = Action.DOWNLEFT.value - elif self.right() and self.down(): - action = Action.DOWNRIGHT.value - elif self.left() and self.up(): - action = Action.UPLEFT.value - elif self.right() and self.up(): - action = Action.UPRIGHT.value - elif self.left(): - action = Action.LEFT.value - elif self.right(): - action = Action.RIGHT.value - elif self.up(): - action = Action.UP.value - else: - action = Action.NOOP.value - - if action in self.keymap: - self.action = self.keymap[action] - else: - self.action = Action.NOOP.value - - #frame = self.env.render() - frame = self.frame - if len(frame.shape) < 3: - frame = np.expand_dims(frame, 2) - frame = np.repeat(frame, 3, axis=2) - - if self.upscale > 1: - frame = np.kron(frame, self.rescaler) - - rl.BeginDrawing() - rl.ClearBackground(self.colors.BLACK) - rl.UpdateTexture(self.texture, frame.tobytes()) - rl.DrawTextureEx(self.texture, (0, 0), 0, 1, self.colors.WHITE) - rl.EndDrawing() - - def reset(self, seed=None, options=None): - obs, info = self.env.reset(seed=seed, options=options) - self.frame = obs - return obs, info - - def step(self, action): - obs, reward, terminal, truncated, info = self.env.step(self.action) - self.frame = obs - return obs, reward, terminal, truncated, info diff --git a/pufferlib/environments/atari/torch.py b/pufferlib/environments/atari/torch.py deleted file mode 100644 index cae86bbe46..0000000000 --- a/pufferlib/environments/atari/torch.py +++ /dev/null @@ -1,18 +0,0 @@ -import pufferlib.models - - -class Recurrent(pufferlib.models.LSTMWrapper): - def __init__(self, env, policy, input_size=512, hidden_size=512): - super().__init__(env, policy, input_size, hidden_size) - -class Policy(pufferlib.models.Convolutional): - def __init__(self, env, input_size=512, hidden_size=512, output_size=512, - framestack=1, flat_size=64*6*9, **kwargs): - super().__init__( - env=env, - input_size=input_size, - hidden_size=hidden_size, - output_size=output_size, - framestack=framestack, - flat_size=flat_size, - ) diff --git a/pufferlib/environments/box2d/__init__.py b/pufferlib/environments/box2d/__init__.py deleted file mode 100644 index eff86ef021..0000000000 --- a/pufferlib/environments/box2d/__init__.py +++ /dev/null @@ -1,12 +0,0 @@ -from .environment import env_creator, make - -try: - import torch -except ImportError: - pass -else: - from .torch import Policy - try: - from .torch import Recurrent - except: - Recurrent = None diff --git a/pufferlib/environments/box2d/environment.py b/pufferlib/environments/box2d/environment.py deleted file mode 100644 index f2fd12b7e8..0000000000 --- a/pufferlib/environments/box2d/environment.py +++ /dev/null @@ -1,21 +0,0 @@ -from pdb import set_trace as T - -import gymnasium -import functools - -import pufferlib.emulation -import pufferlib.environments -import pufferlib.postprocess - - -def env_creator(name='car-racing'): - return functools.partial(make, name=name) - -def make(name, domain_randomize=True, continuous=False, render_mode='rgb_array', buf=None): - if name == 'car-racing': - name = 'CarRacing-v2' - - env = gymnasium.make(name, render_mode=render_mode, - domain_randomize=domain_randomize, continuous=continuous) - env = pufferlib.postprocess.EpisodeStats(env) - return pufferlib.emulation.GymnasiumPufferEnv(env=env, buf=buf) diff --git a/pufferlib/environments/box2d/torch.py b/pufferlib/environments/box2d/torch.py deleted file mode 100644 index b7cdd6acbd..0000000000 --- a/pufferlib/environments/box2d/torch.py +++ /dev/null @@ -1,24 +0,0 @@ -from functools import partial -import torch - -import pufferlib.models - -class Recurrent(pufferlib.models.LSTMWrapper): - def __init__(self, env, policy, - input_size=128, hidden_size=128, num_layers=1): - super().__init__(env, policy, - input_size, hidden_size, num_layers) - -class Policy(pufferlib.models.Convolutional): - def __init__(self, env, - input_size=128, hidden_size=128, output_size=128, - framestack=3, flat_size=64*8*8): - super().__init__( - env=env, - input_size=input_size, - hidden_size=hidden_size, - output_size=output_size, - framestack=framestack, - flat_size=flat_size, - channels_last=True, - ) diff --git a/pufferlib/environments/bsuite/__init__.py b/pufferlib/environments/bsuite/__init__.py deleted file mode 100644 index eff86ef021..0000000000 --- a/pufferlib/environments/bsuite/__init__.py +++ /dev/null @@ -1,12 +0,0 @@ -from .environment import env_creator, make - -try: - import torch -except ImportError: - pass -else: - from .torch import Policy - try: - from .torch import Recurrent - except: - Recurrent = None diff --git a/pufferlib/environments/bsuite/environment.py b/pufferlib/environments/bsuite/environment.py deleted file mode 100644 index f39c661e50..0000000000 --- a/pufferlib/environments/bsuite/environment.py +++ /dev/null @@ -1,44 +0,0 @@ -from pdb import set_trace as T -import gym -import functools - -import pufferlib.emulation -import pufferlib.wrappers - -import bsuite -from bsuite.utils import gym_wrapper - -def env_creator(name='bandit/0'): - return functools.partial(make, name) - -def make(name='bandit/0', results_dir='experiments/bsuite', overwrite=True, buf=None): - '''BSuite environments''' - bsuite = pufferlib.environments.try_import('bsuite') - from bsuite.utils import gym_wrapper - env = bsuite.load_and_record_to_csv(name, results_dir, overwrite=overwrite) - env = gym_wrapper.GymFromDMEnv(env) - env = BSuiteStopper(env) - env = pufferlib.wrappers.GymToGymnasium(env) - env = pufferlib.emulation.GymnasiumPufferEnv(env, buf=buf) - return env - -class BSuiteStopper: - def __init__(self, env): - self.env = env - self.num_episodes = 0 - - self.step = self.env.step - self.render = self.env.render - self.close = self.env.close - self.observation_space = self.env.observation_space - self.action_space = self.env.action_space - - def reset(self): - '''Forces the environment to stop after the - number of episodes required by bsuite''' - self.num_episodes += 1 - - if self.num_episodes >= self.env.bsuite_num_episodes: - exit(0) - - return self.env.reset() diff --git a/pufferlib/environments/bsuite/torch.py b/pufferlib/environments/bsuite/torch.py deleted file mode 100644 index 8b13194e9e..0000000000 --- a/pufferlib/environments/bsuite/torch.py +++ /dev/null @@ -1 +0,0 @@ -from pufferlib.models import Default as Policy diff --git a/pufferlib/environments/butterfly/__init__.py b/pufferlib/environments/butterfly/__init__.py deleted file mode 100644 index eff86ef021..0000000000 --- a/pufferlib/environments/butterfly/__init__.py +++ /dev/null @@ -1,12 +0,0 @@ -from .environment import env_creator, make - -try: - import torch -except ImportError: - pass -else: - from .torch import Policy - try: - from .torch import Recurrent - except: - Recurrent = None diff --git a/pufferlib/environments/butterfly/environment.py b/pufferlib/environments/butterfly/environment.py deleted file mode 100644 index 994e53e9e7..0000000000 --- a/pufferlib/environments/butterfly/environment.py +++ /dev/null @@ -1,25 +0,0 @@ -from pdb import set_trace as T -from pettingzoo.utils.conversions import aec_to_parallel_wrapper -import functools - -import pufferlib.emulation -import pufferlib.environments - - -def env_creator(name='cooperative_pong_v5'): - return functools.partial(make, name) - -def make(name, buf=None): - pufferlib.environments.try_import('pettingzoo.butterfly', 'butterfly') - if name == 'cooperative_pong_v5': - from pettingzoo.butterfly import cooperative_pong_v5 as pong - env_cls = pong.raw_env - elif name == 'knights_archers_zombies_v10': - from pettingzoo.butterfly import knights_archers_zombies_v10 as kaz - env_cls = kaz.raw_env - else: - raise ValueError(f'Unknown environment: {name}') - - env = env_cls() - env = aec_to_parallel_wrapper(env) - return pufferlib.emulation.PettingZooPufferEnv(env=env, buf=buf) diff --git a/pufferlib/environments/butterfly/torch.py b/pufferlib/environments/butterfly/torch.py deleted file mode 100644 index 5965a39713..0000000000 --- a/pufferlib/environments/butterfly/torch.py +++ /dev/null @@ -1,26 +0,0 @@ -import pufferlib.models - - -class Policy(pufferlib.models.Convolutional): - def __init__( - self, - env, - flat_size=3520, - channels_last=True, - downsample=4, - input_size=512, - hidden_size=128, - output_size=128, - **kwargs - ): - super().__init__( - env, - framestack=3, - flat_size=flat_size, - channels_last=channels_last, - downsample=downsample, - input_size=input_size, - hidden_size=hidden_size, - output_size=output_size, - **kwargs - ) diff --git a/pufferlib/environments/classic_control/__init__.py b/pufferlib/environments/classic_control/__init__.py deleted file mode 100644 index eff86ef021..0000000000 --- a/pufferlib/environments/classic_control/__init__.py +++ /dev/null @@ -1,12 +0,0 @@ -from .environment import env_creator, make - -try: - import torch -except ImportError: - pass -else: - from .torch import Policy - try: - from .torch import Recurrent - except: - Recurrent = None diff --git a/pufferlib/environments/classic_control/environment.py b/pufferlib/environments/classic_control/environment.py deleted file mode 100644 index 9da76d3e94..0000000000 --- a/pufferlib/environments/classic_control/environment.py +++ /dev/null @@ -1,40 +0,0 @@ -import gymnasium -from gymnasium.envs import classic_control -import functools -import numpy as np - -import pufferlib -import pufferlib.emulation -import pufferlib.postprocess - -ALIASES = { - 'cartpole': 'CartPole-v0', - 'mountaincar': 'MountainCar-v0', -} - -def env_creator(name='cartpole'): - return functools.partial(make, name) - -def make(name, render_mode='rgb_array', buf=None): - '''Create an environment by name''' - - if name in ALIASES: - name = ALIASES[name] - - env = gymnasium.make(name, render_mode=render_mode) - if name == 'MountainCar-v0': - env = MountainCarWrapper(env) - - #env = gymnasium.wrappers.NormalizeObservation(env) - env = gymnasium.wrappers.TransformObservation(env, lambda obs: np.clip(obs, -1, 1)) - #env = gymnasium.wrappers.NormalizeReward(env, gamma=gamma) - env = gymnasium.wrappers.TransformReward(env, lambda reward: np.clip(reward, -1, 1)) - env = pufferlib.postprocess.EpisodeStats(env) - return pufferlib.emulation.GymnasiumPufferEnv(env=env, buf=buf) - -class MountainCarWrapper(gymnasium.Wrapper): - def step(self, action): - obs, reward, terminated, truncated, info = self.env.step(action) - reward = abs(obs[0]+0.5) - return obs, reward, terminated, truncated, info - diff --git a/pufferlib/environments/classic_control/torch.py b/pufferlib/environments/classic_control/torch.py deleted file mode 100644 index ed3afb8636..0000000000 --- a/pufferlib/environments/classic_control/torch.py +++ /dev/null @@ -1,6 +0,0 @@ -import pufferlib.models - - -class Policy(pufferlib.models.Default): - def __init__(self, env, hidden_size=64): - super().__init__(env, hidden_size) diff --git a/pufferlib/environments/classic_control_continuous/__init__.py b/pufferlib/environments/classic_control_continuous/__init__.py deleted file mode 100644 index eff86ef021..0000000000 --- a/pufferlib/environments/classic_control_continuous/__init__.py +++ /dev/null @@ -1,12 +0,0 @@ -from .environment import env_creator, make - -try: - import torch -except ImportError: - pass -else: - from .torch import Policy - try: - from .torch import Recurrent - except: - Recurrent = None diff --git a/pufferlib/environments/classic_control_continuous/environment.py b/pufferlib/environments/classic_control_continuous/environment.py deleted file mode 100644 index 47f2936572..0000000000 --- a/pufferlib/environments/classic_control_continuous/environment.py +++ /dev/null @@ -1,27 +0,0 @@ -import gymnasium -import functools - -import pufferlib -import pufferlib.emulation -import pufferlib.postprocess - - -def env_creator(name='MountainCarContinuous-v0'): - return functools.partial(make, name) - -def make(name, render_mode='rgb_array', buf=None): - '''Create an environment by name''' - env = gymnasium.make(name, render_mode=render_mode) - if name == 'MountainCarContinuous-v0': - env = MountainCarWrapper(env) - - env = pufferlib.postprocess.ClipAction(env) - env = pufferlib.postprocess.EpisodeStats(env) - return pufferlib.emulation.GymnasiumPufferEnv(env=env, buf=buf) - -class MountainCarWrapper(gymnasium.Wrapper): - def step(self, action): - obs, reward, terminated, truncated, info = self.env.step(action) - reward = abs(obs[0]+0.5) - return obs, reward, terminated, truncated, info - diff --git a/pufferlib/environments/classic_control_continuous/torch.py b/pufferlib/environments/classic_control_continuous/torch.py deleted file mode 100644 index ed3afb8636..0000000000 --- a/pufferlib/environments/classic_control_continuous/torch.py +++ /dev/null @@ -1,6 +0,0 @@ -import pufferlib.models - - -class Policy(pufferlib.models.Default): - def __init__(self, env, hidden_size=64): - super().__init__(env, hidden_size) diff --git a/pufferlib/environments/cogames/__init__.py b/pufferlib/environments/cogames/__init__.py deleted file mode 100644 index b23ed91d7b..0000000000 --- a/pufferlib/environments/cogames/__init__.py +++ /dev/null @@ -1,9 +0,0 @@ -"""CoGames integration package.""" - -from .environment import env_creator, make - -try: - import torch - from .torch import Policy, Recurrent -except ImportError: - pass diff --git a/pufferlib/environments/cogames/environment.py b/pufferlib/environments/cogames/environment.py deleted file mode 100644 index 0fbe475957..0000000000 --- a/pufferlib/environments/cogames/environment.py +++ /dev/null @@ -1,27 +0,0 @@ -"""CoGames wrapper for PufferLib.""" - -import functools -from cogames.cli.mission import get_mission -from mettagrid import PufferMettaGridEnv -from mettagrid.envs.stats_tracker import StatsTracker -from mettagrid.simulator import Simulator -from mettagrid.util.stats_writer import NoopStatsWriter - - -def env_creator(name="cogames.cogs_v_clips.machina_1.open_world"): - return functools.partial(make, name=name) - - -def make(name="cogames.cogs_v_clips.machina_1.open_world", variants=None, cogs=None, render_mode="auto", seed=None, buf=None): - mission_name = name.removeprefix("cogames.cogs_v_clips.") if name.startswith("cogames.cogs_v_clips.") else name - variants = variants.split() if isinstance(variants, str) else variants - _, env_cfg, _ = get_mission(mission_name, variants_arg=variants, cogs=cogs) - - render = "none" if render_mode == "auto" else "unicode" if render_mode in {"human", "ansi"} else render_mode - simulator = Simulator() - simulator.add_event_handler(StatsTracker(NoopStatsWriter())) - env = PufferMettaGridEnv(simulator=simulator, cfg=env_cfg, buf=buf, seed=seed or 0) - env.render_mode = render - if seed: - env.reset(seed) - return env diff --git a/pufferlib/environments/cogames/torch.py b/pufferlib/environments/cogames/torch.py deleted file mode 100644 index 3eb2e5319b..0000000000 --- a/pufferlib/environments/cogames/torch.py +++ /dev/null @@ -1,25 +0,0 @@ -"""Torch policies for CoGames environments.""" - -import torch -import pufferlib.models -import pufferlib.pytorch - - -class Policy(pufferlib.models.Default): - def __init__(self, env, hidden_size: int = 256, **kwargs): - super().__init__(env, hidden_size=hidden_size) - self.register_buffer("_inv_scale", torch.tensor(1.0 / 255.0), persistent=False) - - def encode_observations(self, observations, state=None): - batch_size = observations.shape[0] - if self.is_dict_obs: - obs_map = pufferlib.pytorch.nativize_tensor(observations, self.dtype) - flattened = torch.cat([v.view(batch_size, -1) for v in obs_map.values()], dim=1) - else: - flattened = observations.view(batch_size, -1).float() * self._inv_scale - return self.encoder(flattened) - - -class Recurrent(pufferlib.models.LSTMWrapper): - def __init__(self, env, policy, input_size: int = 256, hidden_size: int = 256): - super().__init__(env, policy, input_size=input_size, hidden_size=hidden_size) diff --git a/pufferlib/environments/craftax/__init__.py b/pufferlib/environments/craftax/__init__.py deleted file mode 100644 index eff86ef021..0000000000 --- a/pufferlib/environments/craftax/__init__.py +++ /dev/null @@ -1,12 +0,0 @@ -from .environment import env_creator, make - -try: - import torch -except ImportError: - pass -else: - from .torch import Policy - try: - from .torch import Recurrent - except: - Recurrent = None diff --git a/pufferlib/environments/craftax/environment.py b/pufferlib/environments/craftax/environment.py deleted file mode 100644 index deb85ccd97..0000000000 --- a/pufferlib/environments/craftax/environment.py +++ /dev/null @@ -1,13 +0,0 @@ -import functools - -import pufferlib -import pufferlib.emulation - -def env_creator(name='Craftax-Symbolic-v1'): - return functools.partial(make, name) - -def make(name, num_envs=2048, buf=None): - from craftax.craftax_env import make_craftax_env_from_name - env = make_craftax_env_from_name(name, auto_reset=True) - env_params = env.default_params - return pufferlib.emulation.GymnaxPufferEnv(env, env_params, num_envs=num_envs, buf=buf) diff --git a/pufferlib/environments/craftax/torch.py b/pufferlib/environments/craftax/torch.py deleted file mode 100644 index dded197799..0000000000 --- a/pufferlib/environments/craftax/torch.py +++ /dev/null @@ -1,72 +0,0 @@ -import torch -from torch import nn - -import pufferlib.models - -Recurrent = pufferlib.models.LSTMWrapper - -''' -CRAFTAX_CHANNELS = 83 - -# Are these transposed? -CRAFTAX_ROWS = 11 -CRAFTAX_COLS = 9 - -N_MAP = CRAFTAX_ROWS * CRAFTAX_COLS * CRAFTAX_CHANNELS -N_FLAT = 51 -''' - -CRAFTAX_ROWS = 7 -CRAFTAX_COLS = 9 -CRAFTAX_CHANNELS = 21 -N_MAP = CRAFTAX_ROWS * CRAFTAX_COLS * CRAFTAX_CHANNELS -N_FLAT = 22 - - -class Policy(nn.Module): - def __init__(self, env, cnn_channels=32, hidden_size=128, **kwargs): - super().__init__() - self.map_encoder = nn.Sequential( - pufferlib.pytorch.layer_init( - nn.Conv2d(21, cnn_channels, 3, stride=2)), - nn.ReLU(), - pufferlib.pytorch.layer_init( - nn.Conv2d(cnn_channels, cnn_channels, 3, stride=1)), - nn.ReLU(), - nn.Flatten(), - ) - self.flat_encoder = nn.Sequential( - pufferlib.pytorch.layer_init(nn.Linear(N_FLAT, hidden_size)), - nn.ReLU(), - ) - self.proj = nn.Sequential( - pufferlib.pytorch.layer_init(nn.Linear(2*cnn_channels + hidden_size, hidden_size)), - nn.ReLU(), - ) - self.actor = pufferlib.pytorch.layer_init( - nn.Linear(hidden_size, env.single_action_space.n), std=0.01) - self.value_fn = pufferlib.pytorch.layer_init( - nn.Linear(hidden_size, 1), std=1) - - self.is_continuous = False - - def forward(self, observations): - hidden, lookup = self.encode_observations(observations) - actions, value = self.decode_actions(hidden, lookup) - return actions, value - - def encode_observations(self, observations): - map_obs = observations[:, :N_MAP].view( - -1, CRAFTAX_ROWS, CRAFTAX_COLS, CRAFTAX_CHANNELS - ).permute(0, 3, 1, 2) - map_obs = self.map_encoder(map_obs) - flat_obs = observations[:, N_MAP:] - flat_obs = self.flat_encoder(flat_obs) - features = torch.cat([map_obs, flat_obs], dim=1) - features = self.proj(features) - return features, None - - def decode_actions(self, flat_hidden, lookup, concat=None): - action = self.actor(flat_hidden) - value = self.value_fn(flat_hidden) - return action, value diff --git a/pufferlib/environments/crafter/__init__.py b/pufferlib/environments/crafter/__init__.py deleted file mode 100644 index eff86ef021..0000000000 --- a/pufferlib/environments/crafter/__init__.py +++ /dev/null @@ -1,12 +0,0 @@ -from .environment import env_creator, make - -try: - import torch -except ImportError: - pass -else: - from .torch import Policy - try: - from .torch import Recurrent - except: - Recurrent = None diff --git a/pufferlib/environments/crafter/environment.py b/pufferlib/environments/crafter/environment.py deleted file mode 100644 index e320e347d3..0000000000 --- a/pufferlib/environments/crafter/environment.py +++ /dev/null @@ -1,46 +0,0 @@ -from pdb import set_trace as T - -import gym -import gymnasium -import shimmy -import functools - -import pufferlib -import pufferlib.emulation -import pufferlib.environments -import pufferlib.postprocess -import pufferlib.utils - - -class TransposeObs(gym.Wrapper): - def observation(self, observation): - return observation.transpose(2, 0, 1) - -def env_creator(name='crafter'): - return functools.partial(make, name) - -def make(name, buf=None): - '''Crafter creation function''' - if name == 'crafter': - name = 'CrafterReward-v1' - - pufferlib.environments.try_import('crafter') - env = gym.make(name) - env.reset = pufferlib.utils.silence_warnings(env.reset) - env = shimmy.GymV21CompatibilityV0(env=env) - env = RenderWrapper(env) - env = TransposeObs(env) - env = pufferlib.postprocess.EpisodeStats(env) - return pufferlib.emulation.GymnasiumPufferEnv(env=env, buf=buf) - -class RenderWrapper(gym.Wrapper): - def __init__(self, env): - super().__init__(env) - self.env = env - - @property - def render_mode(self): - return 'rgb_array' - - def render(self, *args, **kwargs): - return self.env.unwrapped.env.unwrapped.render((256,256)) diff --git a/pufferlib/environments/crafter/torch.py b/pufferlib/environments/crafter/torch.py deleted file mode 100644 index f6f4e52371..0000000000 --- a/pufferlib/environments/crafter/torch.py +++ /dev/null @@ -1,26 +0,0 @@ -import pufferlib.models - - -class Policy(pufferlib.models.Convolutional): - def __init__( - self, - env, - flat_size=1024, - channels_last=True, - downsample=1, - input_size=512, - hidden_size=128, - output_size=128, - **kwargs - ): - super().__init__( - env, - framestack=3, - flat_size=flat_size, - channels_last=channels_last, - downsample=downsample, - input_size=input_size, - hidden_size=hidden_size, - output_size=output_size, - **kwargs - ) diff --git a/pufferlib/environments/dm_control/__init__.py b/pufferlib/environments/dm_control/__init__.py deleted file mode 100644 index eff86ef021..0000000000 --- a/pufferlib/environments/dm_control/__init__.py +++ /dev/null @@ -1,12 +0,0 @@ -from .environment import env_creator, make - -try: - import torch -except ImportError: - pass -else: - from .torch import Policy - try: - from .torch import Recurrent - except: - Recurrent = None diff --git a/pufferlib/environments/dm_control/environment.py b/pufferlib/environments/dm_control/environment.py deleted file mode 100644 index f492fa659d..0000000000 --- a/pufferlib/environments/dm_control/environment.py +++ /dev/null @@ -1,24 +0,0 @@ -from pdb import set_trace as T - -import gym -import shimmy -import functools - -import pufferlib -import pufferlib.emulation -import pufferlib.environments - - -def env_creator(name='walker'): - '''Deepmind Control environment creation function - - No support for bindings yet because PufferLib does - not support continuous action spaces.''' - return functools.partial(make, name) - -def make(name, task_name='walk', buf=None): - '''Untested. Let us know in Discord if you want to use dmc in PufferLib.''' - dm_control = pufferlib.environments.try_import('dm_control.suite', 'dmc') - env = dm_control.suite.load(name, task_name) - env = shimmy.DmControlCompatibilityV0(env=env) - return pufferlib.emulation.GymnasiumPufferEnv(env, buf=buf) diff --git a/pufferlib/environments/dm_control/torch.py b/pufferlib/environments/dm_control/torch.py deleted file mode 100644 index 8b13194e9e..0000000000 --- a/pufferlib/environments/dm_control/torch.py +++ /dev/null @@ -1 +0,0 @@ -from pufferlib.models import Default as Policy diff --git a/pufferlib/environments/dm_lab/__init__.py b/pufferlib/environments/dm_lab/__init__.py deleted file mode 100644 index eff86ef021..0000000000 --- a/pufferlib/environments/dm_lab/__init__.py +++ /dev/null @@ -1,12 +0,0 @@ -from .environment import env_creator, make - -try: - import torch -except ImportError: - pass -else: - from .torch import Policy - try: - from .torch import Recurrent - except: - Recurrent = None diff --git a/pufferlib/environments/dm_lab/environment.py b/pufferlib/environments/dm_lab/environment.py deleted file mode 100644 index 17bbde770f..0000000000 --- a/pufferlib/environments/dm_lab/environment.py +++ /dev/null @@ -1,24 +0,0 @@ -from pdb import set_trace as T - -import gym -import shimmy -import functools - -import pufferlib -import pufferlib.emulation -import pufferlib.environments - - -def env_creator(name='seekavoid_arena_01'): - '''Deepmind Lab binding creation function - dm-lab requires extensive setup. Use PufferTank.''' - return functools.partial(make, name=name) - -def make(name, buf=None): - '''Deepmind Lab binding creation function - dm-lab requires extensive setup. Currently dropped frop PufferTank. - Let us know if you need this for your work.''' - dm_lab = pufferlib.environments.try_import('deepmind_lab', 'dm-lab') - env = dm_lab.Lab(name, ['RGB_INTERLEAVED']) - env = shimmy.DmLabCompatibilityV0(env=env) - return pufferlib.emulation.GymnasiumPufferEnv(env=env, buf=buf) diff --git a/pufferlib/environments/dm_lab/torch.py b/pufferlib/environments/dm_lab/torch.py deleted file mode 100644 index c8e4114982..0000000000 --- a/pufferlib/environments/dm_lab/torch.py +++ /dev/null @@ -1,26 +0,0 @@ -import pufferlib.models - - -class Policy(pufferlib.models.Convolutional): - def __init__( - self, - env, - flat_size=3136, - channels_last=True, - downsample=1, - input_size=512, - hidden_size=128, - output_size=128, - **kwargs - ): - super().__init__( - env, - framestack=3, - flat_size=flat_size, - channels_last=channels_last, - downsample=downsample, - input_size=input_size, - hidden_size=hidden_size, - output_size=output_size, - **kwargs - ) diff --git a/pufferlib/environments/gpudrive/__init__.py b/pufferlib/environments/gpudrive/__init__.py deleted file mode 100644 index 59cda9e7c2..0000000000 --- a/pufferlib/environments/gpudrive/__init__.py +++ /dev/null @@ -1,12 +0,0 @@ -from .environment import env_creator - -try: - import torch -except ImportError: - pass -else: - from .torch import Policy - try: - from .torch import Recurrent - except: - Recurrent = None diff --git a/pufferlib/environments/gpudrive/environment.py b/pufferlib/environments/gpudrive/environment.py deleted file mode 100644 index 31302e65db..0000000000 --- a/pufferlib/environments/gpudrive/environment.py +++ /dev/null @@ -1,146 +0,0 @@ -import os -import numpy as np -from pathlib import Path -import torch -import gymnasium - -from pygpudrive.env.config import EnvConfig, RenderConfig, SceneConfig, SelectionDiscipline -from pygpudrive.env.env_torch import GPUDriveTorchEnv - -def env_creator(name='gpudrive'): - return PufferGPUDrive - -class PufferGPUDrive: - def __init__(self, device='cuda', max_cont_agents=64, num_worlds=64, k_unique_scenes=1): - self.device = device - self.max_cont_agents = max_cont_agents - self.num_worlds = num_worlds - self.k_unique_scenes = k_unique_scenes - self.total_agents = max_cont_agents * num_worlds - - # Set working directory to the base directory 'gpudrive' - working_dir = os.path.join(Path.cwd(), '../gpudrive') - os.chdir(working_dir) - - scene_config = SceneConfig( - path='biggest_file/', - num_scenes=num_worlds, - discipline=SelectionDiscipline.K_UNIQUE_N, - k_unique_scenes=k_unique_scenes, - ) - - env_config = EnvConfig( - steer_actions = torch.round( - torch.linspace(-1.0, 1.0, 3), decimals=3), - accel_actions = torch.round( - torch.linspace(-3, 3, 3), decimals=3 - ) - ) - - render_config = RenderConfig( - resolution=(512, 512), # Quality of the rendered images - ) - - self.env = GPUDriveTorchEnv( - config=env_config, - scene_config=scene_config, - render_config=render_config, - max_cont_agents=max_cont_agents, - device=device, - ) - - self.obs_size = self.env.observation_space.shape[-1] - self.action_space = self.env.action_space - self.observation_space = self.env.observation_space - self.observation_space = gymnasium.spaces.Box( - low=0, high=255, shape=(self.obs_size,), dtype=np.float32) - self.single_observation_space = self.observation_space - self.single_action_space = self.action_space - self.done = False - self.emulated = None - self.render_mode = 'rgb_array' - self.num_live = [] - - self.controlled_agent_mask = self.env.cont_agent_mask.clone() - self.obs = self.env.reset()[self.controlled_agent_mask] - self.num_controlled = self.controlled_agent_mask.sum().item() - self.num_agents = self.obs.shape[0] - self.env_id = np.array([i for i in range(self.num_agents)]) - self.mask = np.ones(self.num_agents, dtype=bool) - self.actions = torch.zeros((num_worlds, max_cont_agents), - dtype=torch.int64).to(self.device) - - def _obs_and_mask(self, obs): - #self.buf.masks[:] = self.env.cont_agent_mask.numpy().ravel() * self.live_agent_mask - #return np.asarray(obs).reshape(NUM_WORLDS*MAX_NUM_OBJECTS, self.obs_size) - #return obs.numpy().reshape(NUM_WORLDS*MAX_NUM_OBJECTS, self.obs_size)[:, :6] - return obs.view(self.total_agents, self.obs_size) - - def close(self): - '''There is no point in closing the env because - Madrona doesn't close correctly anyways. You will want - to cache this copy for later use. Cuda errors if you don't''' - pass - #self.env.close() - #del self.env.sim - - def reset(self, seed=None, options=None): - self.reward = torch.zeros(self.num_agents, dtype=torch.float32).to(self.device) - self.terminal = torch.zeros(self.num_agents, dtype=torch.bool).to(self.device) - self.truncated = torch.zeros(self.num_agents, dtype=torch.bool).to(self.device) - - self.episode_returns = torch.zeros(self.num_agents, dtype=torch.float32).to(self.device) - self.episode_lengths = torch.zeros(self.num_agents, dtype=torch.float32).to(self.device) - self.live_agent_mask = torch.ones((self.num_worlds, self.max_cont_agents), dtype=bool).to(self.device) - return self.obs, self.reward, self.terminal, self.truncated, [], self.env_id, self.mask - - def step(self, action): - action = torch.from_numpy(action).to(self.device) - self.actions[self.controlled_agent_mask] = action - self.env.step_dynamics(self.actions) - - obs = self.env.get_obs()[self.controlled_agent_mask] - reward = self.env.get_rewards()[self.controlled_agent_mask] - terminal = self.env.get_dones().bool() - - done_worlds = torch.where( - (terminal.nan_to_num(0) * self.controlled_agent_mask).sum(dim=1) - == self.controlled_agent_mask.sum(dim=1) - )[0].cpu() - - self.episode_returns += reward - self.episode_lengths += 1 - self.mask = self.live_agent_mask[self.controlled_agent_mask].cpu().numpy() - self.live_agent_mask[terminal] = 0 - terminal = terminal[self.controlled_agent_mask] - - info = [] - self.num_live.append(self.mask.sum()) - - if len(done_worlds) > 0: - controlled_mask = self.controlled_agent_mask[done_worlds] - info_tensor = self.env.get_infos()[done_worlds][controlled_mask] - num_finished_agents = controlled_mask.sum().item() - info.append({ - 'off_road': info_tensor[:, 0].sum().item() / num_finished_agents, - 'veh_collisions': info_tensor[:, 1].sum().item() / num_finished_agents, - 'non_veh_collisions': info_tensor[:, 2].sum().item() / num_finished_agents, - 'goal_achieved': info_tensor[:, 3].sum().item() / num_finished_agents, - 'num_finished_agents': num_finished_agents, - 'episode_length': self.episode_lengths[done_worlds].mean().item(), - 'mean_reward_per_episode': self.episode_returns[done_worlds].mean().item(), - 'control_density': self.num_controlled / self.num_agents, - 'data_density': np.mean(self.num_live) / self.num_agents, - }) - - self.num_live = [] - for idx in done_worlds: - self.env.sim.reset(idx) - self.episode_returns[idx] = 0 - self.episode_lengths[idx] = 0 - self.live_agent_mask[idx] = self.controlled_agent_mask[idx] - - return obs, reward, terminal, self.truncated, info, self.env_id, self.mask - - def render(self, world_render_idx=0): - return self.env.render(world_render_idx=world_render_idx) diff --git a/pufferlib/environments/gpudrive/torch.py b/pufferlib/environments/gpudrive/torch.py deleted file mode 100644 index 5e684e507e..0000000000 --- a/pufferlib/environments/gpudrive/torch.py +++ /dev/null @@ -1,90 +0,0 @@ -from torch import nn -import torch -import torch.nn.functional as F - -from functools import partial -import pufferlib.models - -from pufferlib.models import Default as Policy -Recurrent = pufferlib.models.LSTMWrapper - -EGO_STATE_DIM = 6 -PARTNER_DIM = 10 -ROAD_MAP_DIM = 13 - -MAX_CONTROLLED_VEHICLES = 32 -ROADMAP_AGENT_FEAT_DIM = MAX_CONTROLLED_VEHICLES - 1 -TOP_K_ROADPOINTS = 64 # Number of visible roadpoints from the road graph - -def unpack_obs(obs_flat): - """ - Unpack the flattened observation into the ego state and visible state. - Args: - obs_flat (torch.Tensor): flattened observation tensor of shape (batch_size, obs_dim) - Return: - ego_state, road_objects, stop_signs, road_graph (torch.Tensor). - """ - # Unpack ego and visible state - ego_state = obs_flat[:, :EGO_STATE_DIM] - vis_state = obs_flat[:, EGO_STATE_DIM :] - # Visible state object order: road_objects, road_points - # Find the ends of each section - ro_end_idx = PARTNER_DIM * ROADMAP_AGENT_FEAT_DIM - rg_end_idx = ro_end_idx + (ROAD_MAP_DIM * TOP_K_ROADPOINTS) - - # Unflatten and reshape to (batch_size, num_objects, object_dim) - road_objects = (vis_state[:, :ro_end_idx]).reshape( - -1, ROADMAP_AGENT_FEAT_DIM, PARTNER_DIM - ) - road_graph = (vis_state[:, ro_end_idx:rg_end_idx]).reshape( - -1, - TOP_K_ROADPOINTS, - ROAD_MAP_DIM, - ) - return ego_state, road_objects, road_graph - -class Policy(nn.Module): - def __init__(self, env, input_size=64, hidden_size=128, **kwargs): - super().__init__() - self.ego_embed = nn.Sequential( - pufferlib.pytorch.layer_init(nn.Linear(EGO_STATE_DIM, input_size)), - torch.nn.ReLU(), - pufferlib.pytorch.layer_init(nn.Linear(input_size, input_size)), - ) - - self.partner_embed = nn.Sequential( - pufferlib.pytorch.layer_init(nn.Linear(PARTNER_DIM, input_size)), - torch.nn.ReLU(), - pufferlib.pytorch.layer_init(nn.Linear(input_size, input_size)), - ) - - self.road_map_embed = nn.Sequential( - pufferlib.pytorch.layer_init(nn.Linear(ROAD_MAP_DIM, input_size)), - torch.nn.ReLU(), - pufferlib.pytorch.layer_init(nn.Linear(input_size, input_size)), - ) - - self.proj = pufferlib.pytorch.layer_init(nn.Linear(3*input_size, hidden_size)) - - self.actor = pufferlib.pytorch.layer_init( - nn.Linear(hidden_size, env.single_action_space.n), std=0.01) - self.value_fn = pufferlib.pytorch.layer_init( - nn.Linear(hidden_size, 1), std=1) - - def forward(self, observations): - hidden, lookup = self.encode_observations(observations) - actions, value = self.decode_actions(hidden, lookup) - return actions, value - - def encode_observations(self, observations): - ego_state, road_objects, road_graph = unpack_obs(observations) - ego_embed = self.ego_embed(ego_state) - partner_embed, _ = self.partner_embed(road_objects).max(dim=1) - road_map_embed, _ = self.road_map_embed(road_graph).max(dim=1) - embed = torch.cat([ego_embed, partner_embed, road_map_embed], dim=1) - return self.proj(embed), None - - def decode_actions(self, flat_hidden, lookup, concat=None): - action = self.actor(flat_hidden) - value = self.value_fn(flat_hidden) - return action, value diff --git a/pufferlib/environments/griddly/__init__.py b/pufferlib/environments/griddly/__init__.py deleted file mode 100644 index eff86ef021..0000000000 --- a/pufferlib/environments/griddly/__init__.py +++ /dev/null @@ -1,12 +0,0 @@ -from .environment import env_creator, make - -try: - import torch -except ImportError: - pass -else: - from .torch import Policy - try: - from .torch import Recurrent - except: - Recurrent = None diff --git a/pufferlib/environments/griddly/environment.py b/pufferlib/environments/griddly/environment.py deleted file mode 100644 index fdf8c2430e..0000000000 --- a/pufferlib/environments/griddly/environment.py +++ /dev/null @@ -1,37 +0,0 @@ -from pdb import set_trace as T - -import gym -import shimmy -import functools - -import pufferlib -import pufferlib.emulation -import pufferlib.environments -import pufferlib.postprocess - -ALIASES = { - 'spiders': 'GDY-Spiders-v0', -} - -def env_creator(name='spiders'): - return functools.partial(make, name) - -# TODO: fix griddly -def make(name, buf=None): - '''Griddly creation function - - Note that Griddly environments do not have observation spaces until - they are created and reset''' - if name in ALIASES: - name = ALIASES[name] - - import warnings - warnings.warn('Griddly has been segfaulting in the latest build and we do not know why. Submit a PR if you find a fix!') - pufferlib.environments.try_import('griddly') - with pufferlib.utils.Suppress(): - env = gym.make(name) - env.reset() # Populate observation space - - env = shimmy.GymV21CompatibilityV0(env=env) - env = pufferlib.postprocess.EpisodeStats(env) - return pufferlib.emulation.GymnasiumPufferEnv(env, buf=buf) diff --git a/pufferlib/environments/griddly/torch.py b/pufferlib/environments/griddly/torch.py deleted file mode 100644 index 8b13194e9e..0000000000 --- a/pufferlib/environments/griddly/torch.py +++ /dev/null @@ -1 +0,0 @@ -from pufferlib.models import Default as Policy diff --git a/pufferlib/environments/gvgai/environment.py b/pufferlib/environments/gvgai/environment.py deleted file mode 100644 index fa4da86fdd..0000000000 --- a/pufferlib/environments/gvgai/environment.py +++ /dev/null @@ -1,28 +0,0 @@ -from pdb import set_trace as T -import numpy as np -import functools - -import gym - -import pufferlib -import pufferlib.emulation -import pufferlib.environments -import pufferlib.utils -import pufferlib.postprocess -import pufferlib.wrappers - -def env_creator(name='zelda'): - if name == 'zelda': - name = 'gvgai-zelda-lvl0-v0' - return functools.partial(make, name) - -def make(name, obs_type='grayscale', frameskip=4, full_action_space=False, - repeat_action_probability=0.0, render_mode='rgb_array', buf=None): - '''Atari creation function''' - pufferlib.environments.try_import('gym_gvgai') - env = gym.make(name) - env = pufferlib.wrappers.GymToGymnasium(env) - env = pufferlib.postprocess.EpisodeStats(env) - env = pufferlib.emulation.GymnasiumPufferEnv(env=env, buf=buf) - return env - diff --git a/pufferlib/environments/kinetix/__init__.py b/pufferlib/environments/kinetix/__init__.py deleted file mode 100644 index eff86ef021..0000000000 --- a/pufferlib/environments/kinetix/__init__.py +++ /dev/null @@ -1,12 +0,0 @@ -from .environment import env_creator, make - -try: - import torch -except ImportError: - pass -else: - from .torch import Policy - try: - from .torch import Recurrent - except: - Recurrent = None diff --git a/pufferlib/environments/kinetix/environment.py b/pufferlib/environments/kinetix/environment.py deleted file mode 100644 index 116a5e12ea..0000000000 --- a/pufferlib/environments/kinetix/environment.py +++ /dev/null @@ -1,180 +0,0 @@ -import functools -import numpy as np - -import pufferlib - -train_levels = [ - "s/h0_weak_thrust", - "s/h7_unicycle_left", - "s/h3_point_the_thruster", - "s/h4_thrust_aim", - "s/h1_thrust_over_ball", - "s/h5_rotate_fall", - "s/h9_explode_then_thrust_over", - "s/h6_unicycle_right", - "s/h8_unicycle_balance", - "s/h2_one_wheel_car", - "m/h0_unicycle", - "m/h1_car_left", - "m/h2_car_right", - "m/h3_car_thrust", - "m/h4_thrust_the_needle", - "m/h5_angry_birds", - "m/h6_thrust_over", - "m/h7_car_flip", - "m/h8_weird_vehicle", - "m/h9_spin_the_right_way", - "m/h10_thrust_right_easy", - "m/h11_thrust_left_easy", - "m/h12_thrustfall_left", - "m/h13_thrustfall_right", - "m/h14_thrustblock", - "m/h15_thrustshoot", - "m/h16_thrustcontrol_right", - "m/h17_thrustcontrol_left", - "m/h18_thrust_right_very_easy", - "m/h19_thrust_left_very_easy", - "m/arm_left", - "m/arm_right", - "m/arm_up", - "m/arm_hard", - "l/h0_angrybirds", - "l/h1_car_left", - "l/h2_car_ramp", - "l/h3_car_right", - "l/h4_cartpole", - "l/h5_flappy_bird", - "l/h6_lorry", - "l/h7_maze_1", - "l/h8_maze_2", - "l/h9_morph_direction", - "l/h10_morph_direction_2", - "l/h11_obstacle_avoidance", - "l/h12_platformer_1", - "l/h13_platformer_2", - "l/h14_simple_thruster", - "l/h15_swing_up", - "l/h16_thruster_goal", - "l/h17_unicycle", - "l/hard_beam_balance", - "l/hard_cartpole_thrust", - "l/hard_cartpole_wheels", - "l/hard_lunar_lander", - "l/hard_pinball", - "l/grasp_hard", - "l/grasp_easy", - "l/mjc_half_cheetah", - "l/mjc_half_cheetah_easy", - "l/mjc_hopper", - "l/mjc_hopper_easy", - "l/mjc_swimmer", - "l/mjc_walker", - "l/mjc_walker_easy", - "l/car_launch", - "l/car_swing_around", - "l/chain_lander", - "l/chain_thrust", - "l/gears", - "l/lever_puzzle", - "l/pr", - "l/rail", -] - - -def env_creator(name="kinetix"): - from kinetix.environment.env import ObservationType, ActionType - - _, obs, act = name.split("-") - if obs == "symbolic": obs = "symbolic_flat" - - try: - obs = ObservationType.from_string(obs) - except ValueError: - raise ValueError(f"Unknown observation type: {obs}.") - try: - act = ActionType.from_string(act) - except ValueError: - raise ValueError(f"Unknown action type: {act}.") - - return functools.partial(KinetixPufferEnv, observation_type=obs, action_type=act) - - -def make(name, *args, **kwargs): - return KinetixPufferEnv(*args, **kwargs) - - -class KinetixPufferEnv(pufferlib.environment.PufferEnv): - def __init__(self, observation_type, action_type, num_envs=1, buf=None): - - from kinetix.environment.env import make_kinetix_env, ObservationType, ActionType - from kinetix.environment.env_state import EnvParams, StaticEnvParams - from kinetix.environment.ued.ued_state import UEDParams - from kinetix.environment.ued.ued import make_reset_fn_list_of_levels - - import jax - from gymnax.environments.spaces import gymnax_space_to_gym_space - - self.observation_type = observation_type - self.action_type = action_type - - # Use default parameters - env_params = EnvParams() - static_env_params = StaticEnvParams().replace() - - # Create the environment - env = make_kinetix_env( - observation_type=observation_type, # ObservationType.PIXELS, - action_type=action_type, # ActionType.DISCRETE, - reset_fn=make_reset_fn_list_of_levels(train_levels, static_env_params), - env_params=env_params, - static_env_params=static_env_params, - ) - - self.single_observation_space = gymnax_space_to_gym_space(env.observation_space(env_params)) - self.single_action_space = gymnax_space_to_gym_space(env.action_space(env_params)) - self.num_agents = num_envs - - self.env = env - - super().__init__(buf) - self.env_params = env_params - self.env = env - - self.reset_fn = jax.jit(jax.vmap(env.reset, in_axes=(0, None))) - self.step_fn = jax.jit(jax.vmap(env.step, in_axes=(0, 0, 0, None))) - self.rng = jax.random.PRNGKey(0) - - def reset(self, rng, params=None): - import jax - from torch.utils import dlpack as torch_dlpack - - self.rng, _rng = jax.random.split(self.rng) - self.rngs = jax.random.split(_rng, self.num_agents) - obs, self.state = self.reset_fn(self.rngs, params) - obs = self._obs_to_tensor(obs) - - self.observations = torch_dlpack.from_dlpack(jax.dlpack.to_dlpack(obs)) - return self.observations, [] - - def step(self, action): - import jax - from torch.utils import dlpack as torch_dlpack - - obs, self.state, reward, done, info = self.step_fn(self.rngs, self.state, action, self.env_params) - obs = self._obs_to_tensor(obs) - - # Convert JAX array to DLPack, then to PyTorch tensor - self.observations = torch_dlpack.from_dlpack(jax.dlpack.to_dlpack(obs)) - self.rewards = np.asarray(reward) - self.terminals = np.asarray(done) - infos = [{k: v.mean().item() for k, v in info.items()} | {"reward": self.rewards.mean()} ] - return self.observations, self.rewards, self.terminals, self.terminals, infos - - def _obs_to_tensor(self, obs): - from kinetix.environment.env import ObservationType - if self.observation_type == ObservationType.PIXELS: - return obs.image - elif self.observation_type == ObservationType.SYMBOLIC_FLAT: - return obs - else: - raise ValueError(f"Unknown observation type: {self.observation_type}.") diff --git a/pufferlib/environments/kinetix/torch.py b/pufferlib/environments/kinetix/torch.py deleted file mode 100644 index d713d3d27f..0000000000 --- a/pufferlib/environments/kinetix/torch.py +++ /dev/null @@ -1,44 +0,0 @@ -import torch -from torch import nn - -import pufferlib.models - -Recurrent = pufferlib.models.LSTMWrapper - -from pufferlib.models import Default as Policy -SymbolicPolicy = Policy - -class PixelsPolicy(nn.Module): - def __init__(self, env, cnn_channels=32, hidden_size=128, **kwargs): - super().__init__() - self.hidden_size = 128 - self.map_encoder = nn.Sequential( - pufferlib.pytorch.layer_init(nn.Conv2d(3, cnn_channels, 8, stride=4)), - nn.ReLU(), - pufferlib.pytorch.layer_init(nn.Conv2d(cnn_channels, cnn_channels, 4, stride=2)), - nn.ReLU(), - nn.Flatten(), - ) - self.proj = nn.Sequential( - pufferlib.pytorch.layer_init(nn.Linear(14 * 14 * cnn_channels, hidden_size)), - nn.ReLU(), - ) - self.actor = pufferlib.pytorch.layer_init(nn.Linear(hidden_size, env.single_action_space.n), std=0.01) - self.value_fn = pufferlib.pytorch.layer_init(nn.Linear(hidden_size, 1), std=1) - - self.is_continuous = False - - def forward(self, observations): - hidden = self.encode_observations(observations) - actions, value = self.decode_actions(hidden) - return actions, value - - def encode_observations(self, observations): - encoded = self.map_encoder(observations.permute(0, 3, 1, 2)) - features = self.proj(encoded) - return features - - def decode_actions(self, flat_hidden, concat=None): - action = self.actor(flat_hidden) - value = self.value_fn(flat_hidden) - return action, value diff --git a/pufferlib/environments/links_awaken/__init__.py b/pufferlib/environments/links_awaken/__init__.py deleted file mode 100644 index 1a95905956..0000000000 --- a/pufferlib/environments/links_awaken/__init__.py +++ /dev/null @@ -1,12 +0,0 @@ -from .environment import env_creator, make_env - -try: - import torch -except ImportError: - pass -else: - from .torch import Policy - try: - from .torch import Recurrent - except: - Recurrent = None diff --git a/pufferlib/environments/links_awaken/environment.py b/pufferlib/environments/links_awaken/environment.py deleted file mode 100644 index 8016c3cf58..0000000000 --- a/pufferlib/environments/links_awaken/environment.py +++ /dev/null @@ -1,15 +0,0 @@ -from pdb import set_trace as T - -import gymnasium - -from links_awaken import LinksAwakenV1 as env_creator - -import pufferlib.emulation - - -def make_env(headless: bool = True, state_path=None, buf=None): - '''Links Awakening''' - env = env_creator(headless=headless, state_path=state_path) - env = gymnasium.wrappers.ResizeObservation(env, shape=(72, 80)) - return pufferlib.emulation.GymnasiumPufferEnv(env=env, - postprocessor_cls=pufferlib.emulation.BasicPostprocessor, buf=buf) diff --git a/pufferlib/environments/links_awaken/torch.py b/pufferlib/environments/links_awaken/torch.py deleted file mode 100644 index 4c92d2fded..0000000000 --- a/pufferlib/environments/links_awaken/torch.py +++ /dev/null @@ -1,21 +0,0 @@ -import pufferlib.models -from pufferlib.pytorch import LSTM - - -class Recurrent: - input_size = 512 - hidden_size = 512 - num_layers = 1 - -class Policy(pufferlib.models.Convolutional): - def __init__(self, env, input_size=512, hidden_size=512, output_size=512, - framestack=3, flat_size=64*5*6): - super().__init__( - env=env, - input_size=input_size, - hidden_size=hidden_size, - output_size=output_size, - framestack=framestack, - flat_size=flat_size, - channels_last=True, - ) diff --git a/pufferlib/environments/magent/__init__.py b/pufferlib/environments/magent/__init__.py deleted file mode 100644 index eff86ef021..0000000000 --- a/pufferlib/environments/magent/__init__.py +++ /dev/null @@ -1,12 +0,0 @@ -from .environment import env_creator, make - -try: - import torch -except ImportError: - pass -else: - from .torch import Policy - try: - from .torch import Recurrent - except: - Recurrent = None diff --git a/pufferlib/environments/magent/environment.py b/pufferlib/environments/magent/environment.py deleted file mode 100644 index 10fbfc2adb..0000000000 --- a/pufferlib/environments/magent/environment.py +++ /dev/null @@ -1,25 +0,0 @@ -from pdb import set_trace as T -from pettingzoo.utils.conversions import aec_to_parallel_wrapper -import functools - -import pufferlib.emulation -import pufferlib.environments -import pufferlib.wrappers - - -def env_creator(name='battle_v4'): - return functools.partial(make, name) - pufferlib.environments.try_import('pettingzoo.magent', 'magent') - -def make(name, buf=None): - '''MAgent Battle V4 creation function''' - if name == 'battle_v4': - from pettingzoo.magent import battle_v4 - env_cls = battle_v4.env - else: - raise ValueError(f'Unknown environment name {name}') - - env = env_cls() - env = aec_to_parallel_wrapper(env) - env = pufferlib.wrappers.PettingZooTruncatedWrapper(env) - return pufferlib.emulation.PettingZooPufferEnv(env=env, buf=buf) diff --git a/pufferlib/environments/magent/torch.py b/pufferlib/environments/magent/torch.py deleted file mode 100644 index eb43bcd72b..0000000000 --- a/pufferlib/environments/magent/torch.py +++ /dev/null @@ -1,41 +0,0 @@ -from torch import nn - -import pufferlib.models - - -class Policy(pufferlib.models.Policy): - '''Based off of the DQN policy in MAgent''' - def __init__(self, env, hidden_size=256, output_size=256, kernel_num=32): - '''The CleanRL default Atari policy: a stack of three convolutions followed by a linear layer - - Takes framestack as a mandatory keyword arguments. Suggested default is 1 frame - with LSTM or 4 frames without.''' - super().__init__(env) - self.num_actions = self.action_space.n - - self.network = nn.Sequential( - pufferlib.pytorch.layer_init(nn.Conv2d(5, kernel_num, 3)), - nn.ReLU(), - pufferlib.pytorch.layer_init(nn.Conv2d(kernel_num, kernel_num, 3)), - nn.ReLU(), - nn.Flatten(), - pufferlib.pytorch.layer_init(nn.Linear(kernel_num*9*9, hidden_size)), - nn.ReLU(), - pufferlib.pytorch.layer_init(nn.Linear(hidden_size, hidden_size)), - nn.ReLU(), - ) - - self.actor = pufferlib.pytorch.layer_init(nn.Linear(output_size, self.num_actions), std=0.01) - self.value_function = pufferlib.pytorch.layer_init(nn.Linear(output_size, 1), std=1) - - def critic(self, hidden): - return self.value_function(hidden) - - def encode_observations(self, observations): - observations = observations.permute(0, 3, 1, 2) - return self.network(observations), None - - def decode_actions(self, hidden, lookup): - action = self.actor(hidden) - value = self.value_function(hidden) - return action, value diff --git a/pufferlib/environments/mani_skill/__init__.py b/pufferlib/environments/mani_skill/__init__.py deleted file mode 100644 index eff86ef021..0000000000 --- a/pufferlib/environments/mani_skill/__init__.py +++ /dev/null @@ -1,12 +0,0 @@ -from .environment import env_creator, make - -try: - import torch -except ImportError: - pass -else: - from .torch import Policy - try: - from .torch import Recurrent - except: - Recurrent = None diff --git a/pufferlib/environments/mani_skill/environment.py b/pufferlib/environments/mani_skill/environment.py deleted file mode 100644 index 1d42c5ebf3..0000000000 --- a/pufferlib/environments/mani_skill/environment.py +++ /dev/null @@ -1,118 +0,0 @@ -import functools -import numpy as np -from collections import defaultdict - -import mani_skill.envs -from mani_skill.vector.wrappers.gymnasium import ManiSkillVectorEnv - -import gymnasium as gym -import torch - -import pufferlib - -ALIASES = { - 'mani_pickcube': 'PickCube-v1', - 'mani_pushcube': 'PushCube-v1', - 'mani_stackcube': 'StackCube-v1', - 'mani_peginsertion': 'PegInsertionSide-v1', -} - -def env_creator(name='PickCube-v1', **kwargs): - return functools.partial(make, name) - -def make(name, num_envs=1, render_mode='rgb_array', buf=None, seed=0, **kwargs): - '''Create an environment by name''' - - if name in ALIASES: - name = ALIASES[name] - - return ManiPufferEnv(name, num_envs=num_envs, render_mode=render_mode, buf=buf, seed=seed, **kwargs) - -class ManiPufferEnv(pufferlib.PufferEnv): - def __init__(self, name, num_envs=1, solver_position_iterations=15, - sim_steps_per_control=5, control_freq=20, render_mode='rgb_array', - log_interval=16, buf=None, seed=0): - sim_freq = int(sim_steps_per_control * control_freq) - sim_config = { - 'scene_config': { - 'solver_position_iterations': solver_position_iterations - }, - 'sim_freq': sim_freq, - 'control_freq': control_freq - } - self.env = gym.make(name, reward_mode='delta', num_envs=num_envs, - render_mode=render_mode, sim_config=sim_config) - self.env = ManiSkillVectorEnv(self.env, auto_reset=True, ignore_terminations=False, record_metrics=True) - self.agents_per_batch = num_envs - - obs_space = self.env.observation_space - self.single_observation_space = gym.spaces.Box( - low=obs_space.low[0], - high=obs_space.high[0], - shape=obs_space.shape[1:], - dtype=obs_space.dtype, - ) - - atn_space = self.env.action_space - self.single_action_space = gym.spaces.Box( - low=atn_space.low[0], - high=atn_space.high[0], - shape=atn_space.shape[1:], - dtype=atn_space.dtype, - ) - - self.render_mode = render_mode - self.num_agents = num_envs - self.log_interval = log_interval - self.tick = 0 - - self.env_id = np.arange(num_envs) - - self.logs = defaultdict(list) - - super().__init__(buf) - - def _flatten_info(self, info): - if "final_info" in info: - mask = info["_final_info"] - for k, v in info["final_info"]["episode"].items(): - self.logs[k].append(v[mask].float().mean().item()) - - def reset(self, seed=0): - obs, info = self.env.reset() - #self.observations = torch.nan_to_num(obs) - self.observations = torch.clamp(torch.nan_to_num(obs), -5, 5) - self.observations = obs / 20.0 - self._flatten_info(info) - return obs, [] - - def step(self, actions): - obs, reward, terminated, truncated, info = self.env.step(actions) - collapsed = torch.where(torch.isnan(obs).sum(1) > 0)[0] - if len(collapsed) > 0: - obs, _ = self.env.reset(options={'env_idx': collapsed}) - - self.observations = torch.clamp(torch.nan_to_num(obs), -5, 5) - #self.observations = obs / 20.0 #torch.nan_to_num(obs) - self.rewards = reward - self.terminated = terminated - self.truncated = truncated - self._flatten_info(info) - - self.infos = [] - self.tick += 1 - if self.tick % self.log_interval == 0: - info = {} - for k, v in self.logs.items(): - info[k] = np.mean(v) - - self.logs = defaultdict(list) - self.infos.append(info) - - return obs, reward, terminated, truncated, self.infos - - def render(self): - return self.env.render()[0].cpu().numpy() - - def close(self): - self.env.close() diff --git a/pufferlib/environments/mani_skill/torch.py b/pufferlib/environments/mani_skill/torch.py deleted file mode 100644 index abb8eaa188..0000000000 --- a/pufferlib/environments/mani_skill/torch.py +++ /dev/null @@ -1,71 +0,0 @@ -import numpy as np - -import torch -import torch.nn as nn - -import pufferlib -from pufferlib.models import Default as Policy -from pufferlib.models import LSTMWrapper as Recurrent - -class FakePolicy(nn.Module): - '''Default PyTorch policy. Flattens obs and applies a linear layer. - - PufferLib is not a framework. It does not enforce a base class. - You can use any PyTorch policy that returns actions and values. - We structure our forward methods as encode_observations and decode_actions - to make it easier to wrap policies with LSTMs. You can do that and use - our LSTM wrapper or implement your own. To port an existing policy - for use with our LSTM wrapper, simply put everything from forward() before - the recurrent cell into encode_observations and put everything after - into decode_actions. - ''' - def __init__(self, env, hidden_size=256): - super().__init__() - self.hidden_size = hidden_size - - n_obs = np.prod(env.single_observation_space.shape) - n_atn = env.single_action_space.shape[0] - self.decoder_mean = nn.Sequential( - pufferlib.pytorch.layer_init(nn.Linear(n_obs, 256)), - nn.Tanh(), - pufferlib.pytorch.layer_init(nn.Linear(256, 256)), - nn.Tanh(), - pufferlib.pytorch.layer_init(nn.Linear(256, 256)), - nn.Tanh(), - pufferlib.pytorch.layer_init(nn.Linear(256, n_atn), std=0.01), - ) - self.decoder_logstd = nn.Parameter(torch.zeros( - 1, env.single_action_space.shape[0])) - - self.value = nn.Sequential( - pufferlib.pytorch.layer_init(nn.Linear(n_obs, 256)), - nn.Tanh(), - pufferlib.pytorch.layer_init(nn.Linear(256, 256)), - nn.Tanh(), - pufferlib.pytorch.layer_init(nn.Linear(256, 256)), - nn.Tanh(), - pufferlib.pytorch.layer_init(nn.Linear(256, 1), std=1), - ) - - def forward_eval(self, observations, state=None): - hidden = self.encode_observations(observations, state=state) - logits, values = self.decode_actions(hidden) - return logits, values - - def forward(self, observations, state=None): - return self.forward_eval(observations, state) - - def encode_observations(self, observations, state=None): - '''Encodes a batch of observations into hidden states. Assumes - no time dimension (handled by LSTM wrappers).''' - return observations - - def decode_actions(self, hidden): - '''Decodes a batch of hidden states into (multi)discrete actions. - Assumes no time dimension (handled by LSTM wrappers).''' - mean = self.decoder_mean(hidden) - logstd = self.decoder_logstd.expand_as(mean) - std = torch.exp(logstd) - logits = torch.distributions.Normal(mean, std) - values = self.value(hidden) - return logits, values diff --git a/pufferlib/environments/metta/__init__.py b/pufferlib/environments/metta/__init__.py deleted file mode 100644 index eff86ef021..0000000000 --- a/pufferlib/environments/metta/__init__.py +++ /dev/null @@ -1,12 +0,0 @@ -from .environment import env_creator, make - -try: - import torch -except ImportError: - pass -else: - from .torch import Policy - try: - from .torch import Recurrent - except: - Recurrent = None diff --git a/pufferlib/environments/metta/environment.py b/pufferlib/environments/metta/environment.py deleted file mode 100644 index 21acc46102..0000000000 --- a/pufferlib/environments/metta/environment.py +++ /dev/null @@ -1,74 +0,0 @@ -import functools -import numpy as np -import gymnasium - -import pufferlib - -from omegaconf import OmegaConf -from metta.mettagrid.mettagrid_env import MettaGridEnv -from metta.mettagrid.curriculum.core import SingleTaskCurriculum -from metta.mettagrid.replay_writer import ReplayWriter - -def env_creator(name='metta'): - return functools.partial(make, name) - -def make(name, config='pufferlib/environments/metta/metta.yaml', render_mode='auto', buf=None, seed=0, - ore_reward=0.17088483842567775, battery_reward=0.9882859711234822, heart_reward=1.0): - '''Metta creation function''' - - OmegaConf.register_new_resolver("div", oc_divide, replace=True) - cfg = OmegaConf.load(config) - - # Update rewards under the new structure: agent.rewards.inventory - inventory_rewards = cfg['game']['agent']['rewards']['inventory'] - inventory_rewards['ore_red'] = float(ore_reward) - inventory_rewards['heart'] = float(heart_reward) - inventory_rewards['battery_red'] = float(battery_reward) - - curriculum = SingleTaskCurriculum('puffer', cfg) - return MettaPuff(curriculum, render_mode=render_mode, buf=buf, seed=seed) - -def oc_divide(a, b): - """ - Divide a by b, returning an int if both inputs are ints and result is a whole number, - otherwise return a float. - """ - result = a / b - # If both inputs are integers and the result is a whole number, return as int - if isinstance(a, int) and isinstance(b, int) and result.is_integer(): - return int(result) - return result - -class MettaPuff(MettaGridEnv): - def __init__(self, curriculum, render_mode='human', buf=None, seed=0): - self.replay_writer = None - #if render_mode == 'auto': - # self.replay_writer = ReplayWriter("metta/") - - super().__init__( - curriculum=curriculum, - render_mode=render_mode, - buf=buf, - replay_writer=self.replay_writer - ) - self.action_space = pufferlib.spaces.joint_space(self.single_action_space, self.num_agents) - self.actions = self.actions.astype(np.int32) - - @property - def single_action_space(self): - return gymnasium.spaces.MultiDiscrete(super().single_action_space.nvec, dtype=np.int32) - - def step(self, actions): - obs, rew, term, trunc, info = super().step(actions) - - if all(term) or all(trunc): - self.reset() - if 'agent_raw' in info: - del info['agent_raw'] - if 'episode_rewards' in info: - info['score'] = info['episode_rewards'] - - else: - info = [] - - return obs, rew, term, trunc, [info] diff --git a/pufferlib/environments/metta/metta.yaml b/pufferlib/environments/metta/metta.yaml deleted file mode 100644 index 6d66806fc0..0000000000 --- a/pufferlib/environments/metta/metta.yaml +++ /dev/null @@ -1,251 +0,0 @@ -name: "GDY-MettaGrid" - -report_stats_interval: 100 -normalize_rewards: false - -sampling: 0 -desync_episodes: true - -game: - # Required list of inventory items - inventory_item_names: - - ore_red - - ore_blue - - ore_green - - battery_red - - battery_blue - - battery_green - - heart - - armor - - laser - - blueprint - - num_agents: 64 - obs_width: 11 - obs_height: 11 - num_observation_tokens: 200 - max_steps: 1000 - - # Global observation tokens configuration - global_obs: - episode_completion_pct: true - last_action: true - last_reward: true - resource_rewards: false - - # Show recipe inputs in observations for all converters - recipe_details_obs: false - - agent: - default_resource_limit: 10 - resource_limits: - heart: 255 - freeze_duration: 10 - action_failure_penalty: 0.0 - - rewards: - inventory: - heart: 1 - stats: {} - - groups: - agent: - id: 0 - sprite: 0 - props: {} - - objects: - altar: - type_id: 8 - input_resources: - battery_red: 3 - output_resources: - heart: 1 - max_output: 5 - conversion_ticks: 1 - cooldown: 10 - initial_resource_count: 0 - - wall: - type_id: 1 - swappable: false - - block: - type_id: 14 - swappable: true - - mine_red: - type_id: 2 - output_resources: - ore_red: 1 - color: 0 - max_output: 5 - conversion_ticks: 1 - cooldown: 50 - initial_resource_count: 0 - - mine_blue: - type_id: 3 - color: 1 - output_resources: - ore_blue: 1 - max_output: 5 - conversion_ticks: 1 - cooldown: 50 - initial_resource_count: 0 - - mine_green: - type_id: 4 - output_resources: - ore_green: 1 - color: 2 - max_output: 5 - conversion_ticks: 1 - cooldown: 50 - initial_resource_count: 0 - - generator_red: - type_id: 5 - input_resources: - ore_red: 1 - output_resources: - battery_red: 1 - color: 0 - max_output: 5 - conversion_ticks: 1 - cooldown: 25 - initial_resource_count: 0 - - generator_blue: - type_id: 6 - input_resources: - ore_blue: 1 - output_resources: - battery_blue: 1 - color: 1 - max_output: 5 - conversion_ticks: 1 - cooldown: 25 - initial_resource_count: 0 - - generator_green: - type_id: 7 - input_resources: - ore_green: 1 - output_resources: - battery_green: 1 - color: 2 - max_output: 5 - conversion_ticks: 1 - cooldown: 25 - initial_resource_count: 0 - - armory: - type_id: 9 - input_resources: - ore_red: 3 - output_resources: - armor: 1 - max_output: 5 - conversion_ticks: 1 - cooldown: 10 - initial_resource_count: 0 - - lasery: - type_id: 10 - input_resources: - ore_red: 1 - battery_red: 2 - output_resources: - laser: 1 - max_output: 5 - conversion_ticks: 1 - cooldown: 10 - initial_resource_count: 0 - - lab: - type_id: 11 - input_resources: - ore_red: 3 - battery_red: 3 - output_resources: - blueprint: 1 - max_output: 5 - conversion_ticks: 1 - cooldown: 5 - initial_resource_count: 0 - - factory: - type_id: 12 - input_resources: - blueprint: 1 - ore_red: 5 - battery_red: 5 - output_resources: - armor: 5 - laser: 5 - max_output: 5 - conversion_ticks: 1 - cooldown: 5 - initial_resource_count: 0 - - temple: - type_id: 13 - input_resources: - heart: 1 - blueprint: 1 - output_resources: - heart: 5 - max_output: 5 - conversion_ticks: 1 - cooldown: 5 - initial_resource_count: 0 - - actions: - noop: - enabled: true - move: - enabled: true - rotate: - enabled: true - put_items: - enabled: true - get_items: - enabled: true - attack: - enabled: true - consumed_resources: - laser: 1 - defense_resources: - armor: 1 - swap: - enabled: true - change_color: - enabled: false - change_glyph: - enabled: false - number_of_glyphs: 4 - - map_builder: - _target_: metta.mettagrid.room.multi_room.MultiRoom - num_rooms: 1 - border_width: 6 - - room: - _target_: metta.mettagrid.room.random.Random - width: 64 - height: 64 - border_width: 0 - - agents: 64 - - objects: - mine_red: 128 - generator_red: 64 - altar: 32 - armory: 0 - lasery: 0 - lab: 0 - factory: 0 - temple: 0 - wall: 0 diff --git a/pufferlib/environments/metta/torch.py b/pufferlib/environments/metta/torch.py deleted file mode 100644 index 62aa4be3af..0000000000 --- a/pufferlib/environments/metta/torch.py +++ /dev/null @@ -1,119 +0,0 @@ -import numpy as np -import einops -import torch -from torch import nn -from torch.nn import functional as F - -import pufferlib.models - -class Recurrent(pufferlib.models.LSTMWrapper): - def __init__(self, env, policy, input_size=512, hidden_size=512): - super().__init__(env, policy, input_size, hidden_size) - -class Policy(nn.Module): - def __init__(self, env, cnn_channels=128, hidden_size=512, **kwargs): - super().__init__() - self.hidden_size = hidden_size - self.is_continuous = False - - self.out_width = 11 - self.out_height = 11 - self.num_layers = 22 - - self.network= nn.Sequential( - pufferlib.pytorch.layer_init( - nn.Conv2d(self.num_layers, cnn_channels, 5, stride=3)), - nn.ReLU(), - pufferlib.pytorch.layer_init( - nn.Conv2d(cnn_channels, cnn_channels, 3, stride=1)), - nn.ReLU(), - nn.Flatten(), - pufferlib.pytorch.layer_init(nn.Linear(cnn_channels, hidden_size//2)), - nn.ReLU(), - ) - - self.self_encoder = nn.Sequential( - pufferlib.pytorch.layer_init(nn.Linear(self.num_layers, hidden_size//2)), - nn.ReLU(), - ) - - #max_vec = torch.tensor([ 1., 9., 1., 30., 1., 3., 255., 26., 1., 1., 1., 1., - # 1., 47., 3., 3., 2., 1., 1., 1., 1., 1.])[None, :, None, None] - max_vec = torch.tensor([9., 1., 1., 10., 3., 254., 1., 1., 235., 8., 9., 250., 29., 1., 1., 8., 1., 1., 6., 3., 1., 2.])[None, :, None, None] - #max_vec = torch.ones(22)[None, :, None, None] - self.register_buffer('max_vec', max_vec) - - action_nvec = env.single_action_space.nvec - self.actor = nn.ModuleList([pufferlib.pytorch.layer_init( - nn.Linear(hidden_size, n), std=0.01) for n in action_nvec]) - - self.value = pufferlib.pytorch.layer_init( - nn.Linear(hidden_size, 1), std=1) - - def forward(self, observations, state=None): - hidden, lookup = self.encode_observations(observations) - actions, value = self.decode_actions(hidden, lookup) - return (actions, value), hidden - - def encode_observations(self, observations, state=None): - - token_observations = observations - B = token_observations.shape[0] - TT = 1 - if token_observations.dim() != 3: # hardcoding for shape [B, M, 3] - TT = token_observations.shape[1] - token_observations = einops.rearrange(token_observations, "b t m c -> (b t) m c") - - assert token_observations.shape[-1] == 3, f"Expected 3 channels per token. Got shape {token_observations.shape}" - token_observations[token_observations == 255] = 0 - - # coords_byte contains x and y coordinates in a single byte (first 4 bits are x, last 4 bits are y) - coords_byte = token_observations[..., 0].to(torch.uint8) - - # Extract x and y coordinate indices (0-15 range, but we need to make them long for indexing) - x_coord_indices = ((coords_byte >> 4) & 0x0F).long() # Shape: [B_TT, M] - y_coord_indices = (coords_byte & 0x0F).long() # Shape: [B_TT, M] - atr_indices = token_observations[..., 1].long() # Shape: [B_TT, M], ready for embedding - atr_values = token_observations[..., 2].float() # Shape: [B_TT, M] - - # In ObservationShaper we permute. Here, we create the observations pre-permuted. - # We'd like to pre-create this as part of initialization, but we don't know the batch size or time steps at - # that point. - box_obs = torch.zeros( - (B * TT, 22, self.out_width, self.out_height), - dtype=atr_values.dtype, - device=token_observations.device, - ) - batch_indices = torch.arange(B * TT, device=token_observations.device).unsqueeze(-1).expand_as(atr_values) - - # Add bounds checking to prevent out-of-bounds access - valid_tokens = coords_byte != 0xFF - valid_tokens = valid_tokens & (x_coord_indices < self.out_width) & (y_coord_indices < self.out_height) - valid_tokens = valid_tokens & (atr_indices < 22) # Also check attribute indices - - box_obs[ - batch_indices[valid_tokens], - atr_indices[valid_tokens], - x_coord_indices[valid_tokens], - y_coord_indices[valid_tokens], - ] = atr_values[valid_tokens] - - observations = box_obs - - #max_vec = box_obs.max(0)[0].max(1)[0].max(1)[0] - #self.max_vec = torch.maximum(self.max_vec, max_vec[None, :, None, None]) - #if (np.random.rand() < 0.001): - # breakpoint() - - features = observations / self.max_vec - #mmax = features.max(0)[0].max(1)[0].max(1)[0] - #self.max_vec = torch.maximum(self.max_vec, mmax[None, :, None, None]) - self_features = self.self_encoder(features[:, :, 5, 5]) - cnn_features = self.network(features) - return torch.cat([self_features, cnn_features], dim=1) - - def decode_actions(self, hidden): - #hidden = self.layer_norm(hidden) - logits = [dec(hidden) for dec in self.actor] - value = self.value(hidden) - return logits, value diff --git a/pufferlib/environments/microrts/__init__.py b/pufferlib/environments/microrts/__init__.py deleted file mode 100644 index eff86ef021..0000000000 --- a/pufferlib/environments/microrts/__init__.py +++ /dev/null @@ -1,12 +0,0 @@ -from .environment import env_creator, make - -try: - import torch -except ImportError: - pass -else: - from .torch import Policy - try: - from .torch import Recurrent - except: - Recurrent = None diff --git a/pufferlib/environments/microrts/environment.py b/pufferlib/environments/microrts/environment.py deleted file mode 100644 index 6c00f4d52b..0000000000 --- a/pufferlib/environments/microrts/environment.py +++ /dev/null @@ -1,50 +0,0 @@ -from pdb import set_trace as T -import numpy as np - -import warnings -import shimmy -import functools - -import pufferlib.emulation -import pufferlib.environments - - -def env_creator(name='GlobalAgentCombinedRewardEnv'): - return functools.partial(make, name) - -def make(name, buf=None): - '''Gym MicroRTS creation function - - This library appears broken. Step crashes in Java. - ''' - pufferlib.environments.try_import('gym_microrts') - if name == 'GlobalAgentCombinedRewardEnv': - from gym_microrts.envs import GlobalAgentCombinedRewardEnv - else: - raise ValueError(f'Unknown environment: {name}') - - with pufferlib.utils.Suppress(): - return GlobalAgentCombinedRewardEnv() - - env.reset = pufferlib.utils.silence_warnings(env.reset) - env.step = pufferlib.utils.silence_warnings(env.step) - - env = MicroRTS(env) - env = shimmy.GymV21CompatibilityV0(env=env) - return pufferlib.emulation.GymnasiumPufferEnv(env=env, buf=buf) - -class MicroRTS: - def __init__(self, env): - self.env = env - self.observation_space = self.env.observation_space - self.action_space = self.env.action_space - self.render = self.env.render - self.close = self.env.close - self.seed = self.env.seed - - def reset(self): - return self.env.reset().astype(np.int32) - - def step(self, action): - o, r, d, i = self.env.step(action) - return o.astype(np.int32), r, d, i diff --git a/pufferlib/environments/microrts/torch.py b/pufferlib/environments/microrts/torch.py deleted file mode 100644 index 8b13194e9e..0000000000 --- a/pufferlib/environments/microrts/torch.py +++ /dev/null @@ -1 +0,0 @@ -from pufferlib.models import Default as Policy diff --git a/pufferlib/environments/minerl/__init__.py b/pufferlib/environments/minerl/__init__.py deleted file mode 100644 index eff86ef021..0000000000 --- a/pufferlib/environments/minerl/__init__.py +++ /dev/null @@ -1,12 +0,0 @@ -from .environment import env_creator, make - -try: - import torch -except ImportError: - pass -else: - from .torch import Policy - try: - from .torch import Recurrent - except: - Recurrent = None diff --git a/pufferlib/environments/minerl/environment.py b/pufferlib/environments/minerl/environment.py deleted file mode 100644 index 771c3c600c..0000000000 --- a/pufferlib/environments/minerl/environment.py +++ /dev/null @@ -1,28 +0,0 @@ -from pdb import set_trace as T - -import gym -import shimmy -import functools - -import pufferlib -import pufferlib.emulation -import pufferlib.environments -import pufferlib.utils - - -def env_creator(name='MineRLBasaltFindCave-v0'): - return functools.partial(make, name=name) - -def make(name, buf=None): - '''Minecraft environment creation function''' - - pufferlib.environments.try_import('minerl') - - # Monkey patch to add .itmes to old gym.spaces.Dict - #gym.spaces.Dict.items = lambda self: self.spaces.items() - - #with pufferlib.utils.Suppress(): - env = gym.make(name) - - env = shimmy.GymV21CompatibilityV0(env=env) - return pufferlib.emulation.GymnasiumPufferEnv(env, buf=buf) diff --git a/pufferlib/environments/minerl/torch.py b/pufferlib/environments/minerl/torch.py deleted file mode 100644 index 8b13194e9e..0000000000 --- a/pufferlib/environments/minerl/torch.py +++ /dev/null @@ -1 +0,0 @@ -from pufferlib.models import Default as Policy diff --git a/pufferlib/environments/minigrid/__init__.py b/pufferlib/environments/minigrid/__init__.py deleted file mode 100644 index eff86ef021..0000000000 --- a/pufferlib/environments/minigrid/__init__.py +++ /dev/null @@ -1,12 +0,0 @@ -from .environment import env_creator, make - -try: - import torch -except ImportError: - pass -else: - from .torch import Policy - try: - from .torch import Recurrent - except: - Recurrent = None diff --git a/pufferlib/environments/minigrid/environment.py b/pufferlib/environments/minigrid/environment.py deleted file mode 100644 index 2bf373b7ea..0000000000 --- a/pufferlib/environments/minigrid/environment.py +++ /dev/null @@ -1,54 +0,0 @@ -from pdb import set_trace as T - -import gymnasium -import functools - -import pufferlib.emulation -import pufferlib.environments - -ALIASES = { - 'minigrid': 'MiniGrid-LavaGapS7-v0', -} - - -def env_creator(name='minigrid'): - return functools.partial(make, name=name) - -def make(name, render_mode='rgb_array', buf=None, seed=0): - if name in ALIASES: - name = ALIASES[name] - - minigrid = pufferlib.environments.try_import('minigrid') - env = gymnasium.make(name, render_mode=render_mode) - env = MiniGridWrapper(env) - env = pufferlib.EpisodeStats(env) - return pufferlib.emulation.GymnasiumPufferEnv(env=env, buf=buf) - -class MiniGridWrapper: - def __init__(self, env): - self.env = env - self.observation_space = gymnasium.spaces.Dict({ - k: v for k, v in self.env.observation_space.items() if - k != 'mission' - }) - self.action_space = self.env.action_space - self.close = self.env.close - self.render = self.env.render - self.close = self.env.close - self.render_mode = 'rgb_array' - - def reset(self, seed=None, options=None): - self.tick = 0 - obs, info = self.env.reset(seed=seed) - del obs['mission'] - return obs, info - - def step(self, action): - obs, reward, done, truncated, info = self.env.step(action) - del obs['mission'] - - self.tick += 1 - if self.tick == 100: - done = True - - return obs, reward, done, truncated, info diff --git a/pufferlib/environments/minigrid/torch.py b/pufferlib/environments/minigrid/torch.py deleted file mode 100644 index 8b13194e9e..0000000000 --- a/pufferlib/environments/minigrid/torch.py +++ /dev/null @@ -1 +0,0 @@ -from pufferlib.models import Default as Policy diff --git a/pufferlib/environments/minihack/__init__.py b/pufferlib/environments/minihack/__init__.py deleted file mode 100644 index eff86ef021..0000000000 --- a/pufferlib/environments/minihack/__init__.py +++ /dev/null @@ -1,12 +0,0 @@ -from .environment import env_creator, make - -try: - import torch -except ImportError: - pass -else: - from .torch import Policy - try: - from .torch import Recurrent - except: - Recurrent = None diff --git a/pufferlib/environments/minihack/environment.py b/pufferlib/environments/minihack/environment.py deleted file mode 100644 index d70ea03d58..0000000000 --- a/pufferlib/environments/minihack/environment.py +++ /dev/null @@ -1,62 +0,0 @@ -from pdb import set_trace as T - -import gym -import shimmy -import functools - -import pufferlib -import pufferlib.emulation -import pufferlib.environments - - -EXTRA_OBS_KEYS = [ - 'tty_chars', - 'tty_colors', - 'tty_cursor', -] - -ALIASES = { - 'minihack': 'MiniHack-River-v0', -} - -def env_creator(name='minihack'): - return functools.partial(make, name) - -def make(name, buf=None, seed=0): - '''NetHack binding creation function''' - if name in ALIASES: - name = ALIASES[name] - - import minihack - pufferlib.environments.try_import('minihack') - obs_key = minihack.base.MH_DEFAULT_OBS_KEYS + EXTRA_OBS_KEYS - env = gym.make(name, observation_keys=obs_key) - env = shimmy.GymV21CompatibilityV0(env=env) - env = MinihackWrapper(env) - return pufferlib.emulation.GymnasiumPufferEnv(env=env, buf=buf) - -class MinihackWrapper: - def __init__(self, env): - self.env = env - self.observation_space = self.env.observation_space - self.action_space = self.env.action_space - self.close = self.env.close - self.close = self.env.close - self.render_mode = 'ansi' - - def reset(self, seed=None): - obs, info = self.env.reset(seed=seed) - self.obs = obs - return obs, info - - def step(self, action): - obs, reward, done, truncated, info = self.env.step(action) - self.obs = obs - return obs, reward, done, truncated, info - - def render(self): - import nle - chars = nle.nethack.tty_render( - self.obs['tty_chars'], self.obs['tty_colors'], self.obs['tty_cursor']) - return chars - diff --git a/pufferlib/environments/minihack/torch.py b/pufferlib/environments/minihack/torch.py deleted file mode 100644 index 7781cb677e..0000000000 --- a/pufferlib/environments/minihack/torch.py +++ /dev/null @@ -1,8 +0,0 @@ -from pdb import set_trace as T - -import pufferlib.pytorch -from pufferlib.environments.nethack import Policy - -class Recurrent(pufferlib.models.LSTMWrapper): - def __init__(self, env, policy, input_size=512, hidden_size=512, num_layers=1): - super().__init__(env, policy, input_size, hidden_size, num_layers) diff --git a/pufferlib/environments/mujoco/__init__.py b/pufferlib/environments/mujoco/__init__.py deleted file mode 100644 index 1c91a2b0ff..0000000000 --- a/pufferlib/environments/mujoco/__init__.py +++ /dev/null @@ -1,12 +0,0 @@ -from .environment import * - -try: - import torch -except ImportError: - pass -else: - from .torch import Policy - try: - from .torch import Recurrent - except: - Recurrent = None diff --git a/pufferlib/environments/mujoco/environment.py b/pufferlib/environments/mujoco/environment.py deleted file mode 100644 index f9adad9f8d..0000000000 --- a/pufferlib/environments/mujoco/environment.py +++ /dev/null @@ -1,59 +0,0 @@ - -from pdb import set_trace as T - -import functools - -import numpy as np -import gymnasium - -import pufferlib -import pufferlib.emulation -import pufferlib.environments - - -def single_env_creator(env_name, capture_video, gamma, - run_name=None, idx=None, obs_norm=True, pufferl=False, render_mode='rgb_array', buf=None, seed=0): - if capture_video and idx == 0: - assert run_name is not None, "run_name must be specified when capturing videos" - env = gymnasium.make(env_name, render_mode="rgb_array") - env = gymnasium.wrappers.RecordVideo(env, f"videos/{run_name}") - else: - env = gymnasium.make(env_name, render_mode=render_mode) - - env = pufferlib.ClipAction(env) # NOTE: this changed actions space - env = pufferlib.EpisodeStats(env) - - if obs_norm: - env = gymnasium.wrappers.NormalizeObservation(env) - env = gymnasium.wrappers.TransformObservation(env, lambda obs: np.clip(obs, -10, 10), env.observation_space) - - env = gymnasium.wrappers.NormalizeReward(env, gamma=gamma) - env = gymnasium.wrappers.TransformReward(env, lambda reward: np.clip(reward, -10, 10)) - - if pufferl is True: - env = pufferlib.emulation.GymnasiumPufferEnv(env=env, buf=buf) - - return env - - -def cleanrl_env_creator(env_name, run_name, capture_video, gamma, idx): - kwargs = { - "env_name": env_name, - "run_name": run_name, - "capture_video": capture_video, - "gamma": gamma, - "idx": idx, - "pufferl": False, - } - return functools.partial(single_env_creator, **kwargs) - - -# Keep it simple for pufferl demo, for now -def env_creator(env_name="HalfCheetah-v4", gamma=0.99): - default_kwargs = { - "env_name": env_name, - "capture_video": False, - "gamma": gamma, - "pufferl": True, - } - return functools.partial(single_env_creator, **default_kwargs) diff --git a/pufferlib/environments/mujoco/torch.py b/pufferlib/environments/mujoco/torch.py deleted file mode 100644 index aca09b55d9..0000000000 --- a/pufferlib/environments/mujoco/torch.py +++ /dev/null @@ -1,3 +0,0 @@ - -from pufferlib.models import LSTMWrapper as Recurrent -from pufferlib.models import Default as Policy diff --git a/pufferlib/environments/nethack/Hack-Regular.ttf b/pufferlib/environments/nethack/Hack-Regular.ttf deleted file mode 100644 index 097db18146..0000000000 Binary files a/pufferlib/environments/nethack/Hack-Regular.ttf and /dev/null differ diff --git a/pufferlib/environments/nethack/__init__.py b/pufferlib/environments/nethack/__init__.py deleted file mode 100644 index eff86ef021..0000000000 --- a/pufferlib/environments/nethack/__init__.py +++ /dev/null @@ -1,12 +0,0 @@ -from .environment import env_creator, make - -try: - import torch -except ImportError: - pass -else: - from .torch import Policy - try: - from .torch import Recurrent - except: - Recurrent = None diff --git a/pufferlib/environments/nethack/environment.py b/pufferlib/environments/nethack/environment.py deleted file mode 100644 index 033b1d4e08..0000000000 --- a/pufferlib/environments/nethack/environment.py +++ /dev/null @@ -1,690 +0,0 @@ -from pdb import set_trace as T - -import shimmy -import gym -import functools - -import pufferlib -import pufferlib.emulation -import pufferlib.environments -#from .wrapper import RenderCharImagesWithNumpyWrapper - -# Copyright (c) Facebook, Inc. and its affiliates. -import enum -import logging -import os -import random -import sys -import tempfile -import time -import warnings -import weakref - -import gymnasium as gym -import numpy as np - -from nle import nethack - -logger = logging.getLogger(__name__) - -DUNGEON_SHAPE = nethack.DUNGEON_SHAPE - - -DEFAULT_MSG_PAD = 256 -DEFAULT_INV_PAD = 55 -DEFAULT_INVSTR_PAD = 80 - -ASCII_SPACE = ord(" ") -ASCII_y = ord("y") -ASCII_n = ord("n") -ASCII_ESC = nethack.C("[") - -FULL_ACTIONS = nethack.USEFUL_ACTIONS - -SKIP_EXCEPTIONS = (b"eat", b"attack", b"direction?", b"pray") - -NLE_SPACE_ITEMS = ( - ( - "glyphs", - gym.spaces.Box( - low=0, high=nethack.MAX_GLYPH, **nethack.OBSERVATION_DESC["glyphs"] - ), - ), - ("chars", gym.spaces.Box(low=0, high=255, **nethack.OBSERVATION_DESC["chars"])), - ("colors", gym.spaces.Box(low=0, high=15, **nethack.OBSERVATION_DESC["colors"])), - ( - "specials", - gym.spaces.Box(low=0, high=255, **nethack.OBSERVATION_DESC["specials"]), - ), - ( - "blstats", - gym.spaces.Box( - low=np.iinfo(np.int32).min, - high=np.iinfo(np.int32).max, - **nethack.OBSERVATION_DESC["blstats"], - ), - ), - ( - "message", - gym.spaces.Box( - low=np.iinfo(np.uint8).min, - high=np.iinfo(np.uint8).max, - **nethack.OBSERVATION_DESC["message"], - ), - ), - ( - "program_state", - gym.spaces.Box( - low=np.iinfo(np.int32).min, - high=np.iinfo(np.int32).max, - **nethack.OBSERVATION_DESC["program_state"], - ), - ), - ( - "internal", - gym.spaces.Box( - low=np.iinfo(np.int32).min, - high=np.iinfo(np.int32).max, - **nethack.OBSERVATION_DESC["internal"], - ), - ), - ( - "inv_glyphs", - gym.spaces.Box( - low=0, - high=nethack.MAX_GLYPH, - **nethack.OBSERVATION_DESC["inv_glyphs"], - ), - ), - ( - "inv_strs", - gym.spaces.Box(low=0, high=255, **nethack.OBSERVATION_DESC["inv_strs"]), - ), - ( - "inv_letters", - gym.spaces.Box(low=0, high=127, **nethack.OBSERVATION_DESC["inv_letters"]), - ), - ( - "inv_oclasses", - gym.spaces.Box( - low=0, - high=nethack.MAXOCLASSES, - **nethack.OBSERVATION_DESC["inv_oclasses"], - ), - ), - ( - "screen_descriptions", - gym.spaces.Box( - low=0, high=127, **nethack.OBSERVATION_DESC["screen_descriptions"] - ), - ), - ( - "tty_chars", - gym.spaces.Box(low=0, high=255, **nethack.OBSERVATION_DESC["tty_chars"]), - ), - ( - "tty_colors", - gym.spaces.Box( - low=0, - high=31, - **nethack.OBSERVATION_DESC["tty_colors"], - ), - ), - ( - "tty_cursor", - gym.spaces.Box(low=0, high=255, **nethack.OBSERVATION_DESC["tty_cursor"]), - ), - ( - "misc", - gym.spaces.Box( - low=np.iinfo(np.int32).min, - high=np.iinfo(np.int32).max, - **nethack.OBSERVATION_DESC["misc"], - ), - ), -) - - -class NLE(gym.Env): - """Standard NetHack Learning Environment. - - Implements a gym interface around `nethack.Nethack`. - - - Examples: - >>> env = NLE() - >>> obs, reset_info = env.reset() - >>> obs, reward, done, truncation, info = env.step(0) - >>> env.render() - """ - - # Gymnasium expects an fps rate > 0 for render checks - # but NetHack doesn't have any. Set it to 42, because - # that is always the answer to life, the universe and - # everything. - metadata = {"render_modes": ["human", "ansi", "full"], "render_fps": 42} - - class StepStatus(enum.IntEnum): - """Specifies the status of the terminal state. - - Note: - User may redefine this class in subtasks to handle / categorize - more terminal states. - - It is highly advised that, in such cases, the enums already defined - in this object are replicated in some way. See `nle.env.tasks` for - examples on how to do this right. - """ - - ABORTED = -1 - RUNNING = 0 - DEATH = 1 - - def __init__( - self, - save_ttyrec_every=0, - savedir=None, - character="mon-hum-neu-mal", - max_episode_steps=5000, - observation_keys=( - "glyphs", - "chars", - "colors", - "specials", - "blstats", - "message", - "inv_glyphs", - "inv_strs", - "inv_letters", - "inv_oclasses", - "screen_descriptions", - "tty_chars", - "tty_colors", - "tty_cursor", - ), - actions=None, - options=None, - wizard=False, - allow_all_yn_questions=False, - allow_all_modes=False, - spawn_monsters=True, - render_mode="human", - ): - """Constructs a new NLE environment. - - Args: - save_ttyrec_every: Integer, if 0, no ttyrecs (game recordings) will - be saved. Otherwise, save a ttyrec every Nth episode. - savedir (str or None): Path to save ttyrecs (game recordings) into, - if save_ttyrec_every is nonzero. If nonempty string, interpreted - as a path to a new or existing directory. - If "" (empty string) or None, NLE choses a unique directory name. - character (str): name of character. Defaults to "mon-hum-neu-mal". - max_episode_steps (int): maximum amount of steps allowed before the - game is forcefully quit. In such cases, ``info["end_status"]`` - will be equal to ``StepStatus.ABORTED``. Defaults to 5000. - observation_keys (list): keys to use when creating the observation. - Defaults to all. - actions (list): list of actions. If None, the full action space will - be used, i.e. ``nle.nethack.ACTIONS``. Defaults to None. - options (list): list of game options to initialize Nethack. If None, - Nethack will be initialized with the options found in - ``nle.nethack.NETHACKOPTIONS`. Defaults to None. - wizard (bool): activate wizard mode. Defaults to False. - allow_all_yn_questions (bool): - If set to True, no y/n questions in step() are declined. - If set to False, only elements of SKIP_EXCEPTIONS are not declined. - Defaults to False. - allow_all_modes (bool): - If set to True, do not decline menus, text input or auto 'MORE'. - If set to False, only skip click through 'MORE' on death. - spawn_monsters: If False, disables normal NetHack behavior to randomly - create monsters. - render_mode (str): mode used to render the screen. One of - "human" | "ansi" | "full". - Defaults to "human", i.e. what a human would see playing the game. - """ - self.character = character - self._max_episode_steps = max_episode_steps - self._allow_all_yn_questions = allow_all_yn_questions - self._allow_all_modes = allow_all_modes - self._save_ttyrec_every = save_ttyrec_every - self.render_mode = render_mode - - if actions is None: - actions = FULL_ACTIONS - self.actions = actions - - self.last_observation = () - - try: - if not save_ttyrec_every: - self.savedir = None - elif savedir: - self.savedir = os.path.abspath(savedir) - os.makedirs(self.savedir) - else: # Empty savedir: We create our unique savedir inside nle_data/. - parent_dir = os.path.join(os.getcwd(), "nle_data") - os.makedirs(parent_dir, exist_ok=True) - self.savedir = tempfile.mkdtemp( - prefix=time.strftime("%Y%m%d-%H%M%S_"), dir=parent_dir - ) - except FileExistsError: - logger.info("Using existing savedir: %s", self.savedir) - else: - if self.savedir: - logger.info("Created savedir: %s", self.savedir) - else: - logger.info("Not saving any NLE data.") - - self._observation_keys = list(observation_keys) - - if "internal" in self._observation_keys: - logger.warn( - "The 'internal' NLE observation was requested. " - "This might contain data that shouldn't be available to agents." - ) - - # Observations we always need. - for key in ( - "glyphs", - "blstats", - "tty_chars", - "message", - "program_state", - "internal", - ): - if key not in self._observation_keys: - self._observation_keys.append(key) - - self._glyph_index = self._observation_keys.index("glyphs") - self._blstats_index = self._observation_keys.index("blstats") - self._message_index = self._observation_keys.index("message") - self._program_state_index = self._observation_keys.index("program_state") - self._internal_index = self._observation_keys.index("internal") - - self._original_observation_keys = observation_keys - self._original_indices = tuple( - self._observation_keys.index(key) for key in observation_keys - ) - self._info = {} - - if self.savedir: - ttyrec_version = ".ttyrec%i.bz2" % nethack.TTYREC_VERSION - ttyrec_prefix = "nle.%i.%%i" % os.getpid() - self._ttyrec_pattern = os.path.join( - self.savedir, ttyrec_prefix + ttyrec_version - ) - ttyrec = self._ttyrec_pattern % 0 - # Create an xlogfile with the same format of name. - scoreprefix = ttyrec.replace("0" + ttyrec_version, "") - else: - ttyrec = None - scoreprefix = None - - self.nethack = nethack.Nethack( - observation_keys=self._observation_keys, - options=options, - playername="Agent-" + self.character, - ttyrec=ttyrec, - wizard=wizard, - spawn_monsters=spawn_monsters, - scoreprefix=scoreprefix, - ) - self._close_nethack = weakref.finalize(self, self.nethack.close) - - self._random = random.SystemRandom() - - # -1 so that it's 0-based on first reset - self._episode = -1 - - space_dict = dict(NLE_SPACE_ITEMS) - self.observation_space = gym.spaces.Dict( - {key: space_dict[key] for key in observation_keys} - ) - - self.action_space = gym.spaces.Discrete(len(self.actions)) - - def _get_observation(self, observation): - return { - key: observation[i] - for key, i in zip(self._original_observation_keys, self._original_indices) - } - - def _get_end_status(self, observation, done): - return done or self._check_abort(observation) - - def _get_information(self, end_status): - info = {} - info["end_status"] = end_status - info["is_ascended"] = self.nethack.how_done() == nethack.ASCENDED - return info - - def print_action_meanings(self): - for a_idx, a in enumerate(self.actions): - print(a_idx, a) - - def _check_abort(self, observation): - return self._steps >= self._max_episode_steps - - def step(self, action: int): - """Steps the environment. - - Args: - action (int): action integer as defined by ``self.action_space``. - - Returns: - (dict, float, bool, dict): a tuple containing - - (*dict*): an observation of the state; this will contain the keys - specified by ``self.observation_space``. - - (*float*): a reward; see ``self._reward_fn`` to see how it is - specified. - - (*bool*): True if the state is terminal, False otherwise. - - (*bool*): True if the episode is truncated, False otherwise. - - (*dict*): a dictionary of extra information (such as - `end_status`, i.e. a status info -- death, task win, etc. -- - for the terminal state). - """ - # Careful: By default we re-use Numpy arrays, so copy before! - old_score = self.last_observation[self._blstats_index][nethack.NLE_BL_SCORE] - - observation, done = self.nethack.step(self.actions[action]) - truncated = self._check_abort(observation) - - # is_game_over = observation[self._program_state_index][0] == 1 - # if is_game_over or not self._allow_all_modes: - # observation, done = self._perform_known_steps( - # observation, done, exceptions=True - # ) - - self._steps += 1 - - self.last_observation = observation - - end_status = self._get_end_status(observation, done) - - reward = float( - self._reward_fn(old_score, action, observation, end_status) - ) - - if end_status and not done: - # Try to end the game nicely. - self._quit_game(observation, done) - done = True - - return ( - self._get_observation(observation), - reward, - done, - truncated, - self._info, - ) - - def _in_moveloop(self, observation): - program_state = observation[self._program_state_index] - return program_state[3] # in_moveloop - - def reset(self, seed=None, options=None): - """Resets the environment. - - Note: - We attempt to manually navigate the first few menus so that the - first seen state is ready to be acted upon by the user. This might - fail in case Nethack is initialized with some uncommon options. - - Returns: - (tuple) (Observation of the state as - defined by `self.observation_space`, - Extra game state information) - """ - super().reset(seed=seed, options=options) - self._episode += 1 - if self.savedir and self._episode % self._save_ttyrec_every == 0: - new_ttyrec = self._ttyrec_pattern % self._episode - else: - new_ttyrec = None - self.last_observation = self.nethack.reset(new_ttyrec, options=options) - - self._steps = 0 - done = False - - for _ in range(1000): - # Get past initial phase of game. This should make sure - # all the observations are present. - if self._in_moveloop(self.last_observation): - break - # This fails if the agent picks up a scroll of scare - # monster at the 0th turn and gets asked to name it. - # Hence the defensive iteration above. - # TODO: Detect this 'in_getlin' situation and handle it. - self.last_observation, done = self.nethack.step(ASCII_SPACE) - assert not done, "Game ended unexpectedly" - else: - warnings.warn( - "Not in moveloop after 1000 tries, aborting (ttyrec: %s)." % new_ttyrec, - stacklevel=2, - ) - return self.reset(seed=seed, options=options) - - return self._get_observation(self.last_observation), {} - - def close(self): - self._close_nethack() - super().close() - - def seed(self, core=None, disp=None, reseed=False, lgen=None): - """Sets the state of the NetHack RNGs after the next reset. - - NetHack 3.6 uses two RNGs, core and disp. This is to prevent - RNG-manipulation by e.g. running into walls or other no-ops on the - actual game state. This is a measure against "tool-assisted - speedruns" (TAS). NLE can run in both NetHack's default mode and in - TAS-friendly "no reseeding" if `reseed` is set to False, see below. - - lgen allows the user to use a different RNG to generate the levels in - NetHack so that the levels become fixed and independent from the in-game - choices. - - Arguments: - core [int or None]: Seed for the core RNG. If None, chose a random - value. - disp [int or None]: Seed for the disp (anti-TAS) RNG. If None, chose - a random value. - reseed [boolean]: As an Anti-TAS (automation) measure, - NetHack 3.6 reseeds with true randomness every now and then. This - flag enables or disables this behavior. If set to True, trajectories - won't be reproducible. - lgen [int or None]: Seed for the level generator, used for RNG when - NetHack generates new levels. - - Returns: - [tuple] The seeds supplied, in the form (core, disp, reseed, lgen). - """ - if core is None: - core = self._random.randrange(sys.maxsize) - if disp is None: - disp = self._random.randrange(sys.maxsize) - self.nethack.set_initial_seeds(core, disp, reseed, lgen) - return (core, disp, reseed, lgen) - - def get_seeds(self): - """Returns current seeds. - - Returns: - (tuple): Current NetHack (core, disp, reseed, lgen) state. - """ - return self.nethack.get_current_seeds() - - def render(self): - """Renders the state of the environment.""" - mode = self.render_mode - - if mode == "human": - obs = self.last_observation - tty_chars = obs[self._observation_keys.index("tty_chars")] - tty_colors = obs[self._observation_keys.index("tty_colors")] - tty_cursor = obs[self._observation_keys.index("tty_cursor")] - print(nethack.tty_render(tty_chars, tty_colors, tty_cursor)) - return None - - if mode == "full": - message_index = self._observation_keys.index("message") - message = bytes(self.last_observation[message_index]) - print(message[: message.index(b"\0")]) - try: - inv_strs_index = self._observation_keys.index("inv_strs") - inv_letters_index = self._observation_keys.index("inv_letters") - - inv_strs = self.last_observation[inv_strs_index] - inv_letters = self.last_observation[inv_letters_index] - for letter, line in zip(inv_letters, inv_strs): - if np.all(line == 0): - break - print( - letter.tobytes().decode("utf-8"), line.tobytes().decode("utf-8") - ) - except ValueError: # inv_strs/letters not used. - pass - - chars = self.last_observation[self._observation_keys.index("chars")] - colors = self.last_observation[self._observation_keys.index("colors")] - print(nethack.tty_render(chars, colors)) - return None - - if mode in ("ansi", "string"): # Misnomer: This is the least ANSI of them all. - chars = self.last_observation[self._observation_keys.index("chars")] - # TODO: Why return a string here but print in the other branches? - return "\n".join([line.tobytes().decode("utf-8") for line in chars]) - - return "\nInvalid render mode: " + mode - - def __repr__(self): - return "<%s>" % self.__class__.__name__ - - def _is_episode_end(self, observation): - """Returns whether the episode has ended. - - Tasks may override this method to specify different conditions, so long - as the return value has a well defined __int__ method (e.g. booleans, - numerical types, enum.IntEnum) and that value is part of StepStatus. - - The return value will be stored into info["end_status"]. - """ - return self.StepStatus.RUNNING - - def _reward_fn(self, old_score, action, observation, end_status): - """Reward function. Difference between previous score and new score.""" - - if observation[self._blstats_index][0] == 0: - # Before game started and after it ended blstats are zero. - return 0.0 - - score = observation[self._blstats_index][nethack.NLE_BL_SCORE] - return score - old_score - - def _perform_known_steps(self, observation, done, exceptions=True): - steps = 0 - while not done: - steps += 1 - if observation[self._internal_index][3]: # xwaitforspace - observation, done = self.nethack.step(ASCII_SPACE) - continue - - internal = observation[self._internal_index] - in_yn_function = internal[1] - in_getlin = internal[2] - - if in_getlin: # Game asking for a line of text. We don't do that. - observation, done = self.nethack.step(ASCII_ESC) - continue - - if in_yn_function: # Game asking for a single character. - # Note: No auto-yes to final questions thanks to the disclose option. - if exceptions: - # This causes an annoying unnecessary copy... - msg = bytes(observation[self._message_index]) - # Do not skip some questions to allow agent to select - # stuff to eat, attack, and to select directions. - - # do not skip if all allowed or the allowed message appears - if self._allow_all_yn_questions or any( - el in msg for el in SKIP_EXCEPTIONS - ): - break - - # Otherwise, auto-decline. - observation, done = self.nethack.step(ASCII_ESC) - - break - if steps > 10: - print(steps, "steps to get out of menus and windows.") - return observation, done - - def _quit_game(self, observation, done): - """Smoothly quit a game.""" - # Get out of menus and windows. - # observation, done = self._perform_known_steps( - # observation, done, exceptions=False - # ) - - if done: - return - - # Quit the game. - actions = [0x80 | ord("q"), ord("y")] # M-q y - for a in actions: - observation, done = self.nethack.step(a) - - # Answer final questions. - # observation, done = self._perform_known_steps( - # observation, done, exceptions=False - # ) - - if not done: - # Somehow, the above logic failed us. - warnings.warn( - "Warning: smooth quitting of game failed, aborting.", stacklevel=2 - ) - -def env_creator(name='nethack'): - return functools.partial(make, name) - -def make(name, buf=None, seed=0): - '''NetHack binding creation function''' - if name == 'nethack': - name = 'NetHackScore-v0' - - nle = pufferlib.environments.try_import('nle') - from nle.env.tasks import NetHackScore - #env = NetHackScore(observation_keys=['blstats', 'chars']) - env = NLE(observation_keys=['blstats', 'chars']) - #env = RenderCharImagesWithNumpyWrapper(env) - #env = shimmy.GymV21CompatibilityV0(env=env) - env = NethackWrapper(env) - env = pufferlib.EpisodeStats(env) - return pufferlib.emulation.GymnasiumPufferEnv(env=env, buf=buf) - -class NethackWrapper: - def __init__(self, env): - self.env = env - self.observation_space = self.env.observation_space - self.action_space = self.env.action_space - self.close = self.env.close - self.close = self.env.close - self.render_mode = 'ansi' - - def reset(self, seed=None): - obs, info = self.env.reset(seed=seed) - self.obs = obs - return obs, info - - def step(self, action): - obs, reward, done, truncated, info = self.env.step(action) - self.obs = obs - return obs, reward, done, truncated, info - - def render(self): - import nle - chars = nle.nethack.tty_render( - self.obs['tty_chars'], self.obs['tty_colors'], self.obs['tty_cursor']) - return chars diff --git a/pufferlib/environments/nethack/torch.py b/pufferlib/environments/nethack/torch.py deleted file mode 100644 index 64af81e541..0000000000 --- a/pufferlib/environments/nethack/torch.py +++ /dev/null @@ -1,73 +0,0 @@ -from pdb import set_trace as T - -import torch -import torch.nn as nn -import torch.nn.functional as F - -import pufferlib.models -import pufferlib.pytorch -from pufferlib.pytorch import layer_init - -from pufferlib.models import LSTMWrapper as Recurrent -from pufferlib.models import Default as Policy - - -''' -class Recurrent(pufferlib.models.LSTMWrapper): - def __init__(self, env, policy, input_size=256, hidden_size=256, num_layers=1): - super().__init__(env, policy, input_size, hidden_size, num_layers) - -class Policy(nn.Module): - def __init__(self, env): - super().__init__() - self.dtype = pufferlib.pytorch.nativize_dtype(env.emulated) - - self.blstats_net = nn.Sequential( - nn.Embedding(256, 32), - nn.Flatten(), - ) - - self.char_embed = nn.Embedding(256, 32) - self.chars_net = nn.Sequential( - layer_init(nn.Conv2d(32, 32, 5, stride=(2, 3))), - nn.ReLU(), - layer_init(nn.Conv2d(32, 64, 5, stride=(1, 3))), - nn.ReLU(), - layer_init(nn.Conv2d(64, 64, 3, stride=1)), - nn.ReLU(), - nn.Flatten(), - ) - - self.proj = nn.Linear(864+960, 256) - self.actor = layer_init(nn.Linear(256, 8), std=0.01) - self.critic = layer_init(nn.Linear(256, 1), std=1) - - def forward_eval(self, x, state=None): - hidden = self.encode_observations(x) - actions, value = self.decode_actions(hidden) - return actions, value - - def forward(self, x, state=None): - hidden = self.encode_observations(x) - actions, value = self.decode_actions(hidden) - return actions, value - - def encode_observations(self, x): - x = x.type(torch.uint8) # Undo bad cleanrl cast - x = pufferlib.pytorch.nativize_tensor(x, self.dtype) - - blstats = torch.clip(x['blstats'] + 1, 0, 255).int() - blstats = self.blstats_net(blstats) - - chars = self.char_embed(x['chars'].int()) - chars = torch.permute(chars, (0, 3, 1, 2)) - chars = self.chars_net(chars) - - concat = torch.cat([blstats, chars], dim=1) - return self.proj(concat) - - def decode_actions(self, hidden): - value = self.critic(hidden) - action = self.actor(hidden) - return action, value -''' diff --git a/pufferlib/environments/nethack/wrapper.py b/pufferlib/environments/nethack/wrapper.py deleted file mode 100644 index 17781a6acf..0000000000 --- a/pufferlib/environments/nethack/wrapper.py +++ /dev/null @@ -1,306 +0,0 @@ -"""Taken & adapted from Chaos Dwarf in Nethack Challenge Starter Kit: -https://github.com/Miffyli/nle-sample-factory-baseline - - -MIT License - -Copyright (c) 2021 Anssi - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -""" - -import os - -import cv2 -import gym -import numpy as np -from numba import njit -from nle import nethack -from PIL import Image -from PIL import ImageDraw -from PIL import ImageFont - -#import render_utils - -SMALL_FONT_PATH = os.path.join(__package__.replace(".", "/"), "Hack-Regular.ttf") - -# Mapping of 0-15 colors used. -# Taken from bottom image here. It seems about right -# https://i.stack.imgur.com/UQVe5.png -COLORS = [ - "#000000", - "#800000", - "#008000", - "#808000", - "#000080", - "#800080", - "#008080", - "#808080", # - flipped these ones around - "#C0C0C0", # | the gray-out dull stuff - "#FF0000", - "#00FF00", - "#FFFF00", - "#0000FF", - "#FF00FF", - "#00FFFF", - "#FFFFFF", -] - - -@njit -def _tile_characters_to_image( - out_image, - chars, - colors, - output_height_chars, - output_width_chars, - char_array, - offset_h, - offset_w, -): - """ - Build an image using cached images of characters in char_array to out_image - """ - char_height = char_array.shape[3] - char_width = char_array.shape[4] - for h in range(output_height_chars): - h_char = h + offset_h - # Stuff outside boundaries is not visible, so - # just leave it black - if h_char < 0 or h_char >= chars.shape[0]: - continue - for w in range(output_width_chars): - w_char = w + offset_w - if w_char < 0 or w_char >= chars.shape[1]: - continue - char = chars[h_char, w_char] - color = colors[h_char, w_char] - h_pixel = h * char_height - w_pixel = w * char_width - out_image[ - :, h_pixel : h_pixel + char_height, w_pixel : w_pixel + char_width - ] = char_array[char, color] - - -def _initialize_char_array(font_size, rescale_font_size): - """Draw all characters in PIL and cache them in numpy arrays - - if rescale_font_size is given, assume it is (width, height) - - Returns a np array of (num_chars, num_colors, char_height, char_width, 3) - """ - font = ImageFont.truetype(SMALL_FONT_PATH, font_size) - dummy_text = "".join( - [(chr(i) if chr(i).isprintable() else " ") for i in range(256)] - ) - _, _, image_width, image_height = font.getbbox(dummy_text) - # Above can not be trusted (or its siblings).... - image_width = int(np.ceil(image_width / 256) * 256) - - char_width = rescale_font_size[0] - char_height = rescale_font_size[1] - - char_array = np.zeros((256, 16, char_height, char_width, 3), dtype=np.uint8) - image = Image.new("RGB", (image_width, image_height)) - image_draw = ImageDraw.Draw(image) - for color_index in range(16): - image_draw.rectangle((0, 0, image_width, image_height), fill=(0, 0, 0)) - image_draw.text((0, 0), dummy_text, fill=COLORS[color_index], spacing=0) - - arr = np.array(image).copy() - arrs = np.array_split(arr, 256, axis=1) - for char_index in range(256): - char = arrs[char_index] - if rescale_font_size: - char = cv2.resize(char, rescale_font_size, interpolation=cv2.INTER_AREA) - char_array[char_index, color_index] = char - return char_array - - -class RenderCharImagesWithNumpyWrapper(gym.Wrapper): - """ - Render characters as images, using PIL to render characters like we humans see on screen - but then some caching and numpy stuff to speed up things. - - To speed things up, crop image around the player. - """ - - def __init__( - self, - env, - font_size=9, - crop_size=12, - rescale_font_size=(6, 6), - blstats_cursor=False, - ): - super().__init__(env) - self.char_array = _initialize_char_array(font_size, rescale_font_size) - self.char_height = self.char_array.shape[2] - self.char_width = self.char_array.shape[3] - # Transpose for CHW - self.char_array = self.char_array.transpose(0, 1, 4, 2, 3) - - self.crop_size = crop_size - self.blstats_cursor = blstats_cursor - - self.half_crop_size = crop_size // 2 - self.output_height_chars = crop_size - self.output_width_chars = crop_size - self.chw_image_shape = ( - 3, - self.output_height_chars * self.char_height, - self.output_width_chars * self.char_width, - ) - - self.observation_space = gym.spaces.Box( - low=0, high=255, shape=self.chw_image_shape, dtype=np.uint8 - ) - - ''' - obs_spaces = { - "screen_image": gym.spaces.Box( - low=0, high=255, shape=self.chw_image_shape, dtype=np.uint8 - ) - } - obs_spaces.update( - [ - (k, self.env.observation_space[k]) - for k in self.env.observation_space - if k not in ["tty_chars", "tty_colors"] - ] - ) - self.observation_space = gym.spaces.Dict(obs_spaces) - ''' - - self.render_mode = 'rgb_array' - - def _render_text_to_image(self, obs): - chars = obs["tty_chars"] - colors = obs["tty_colors"] - offset_w = 0 - offset_h = 0 - if self.crop_size: - # Center around player - if self.blstats_cursor: - center_x, center_y = obs["blstats"][:2] - else: - center_y, center_x = obs["tty_cursor"] - offset_h = center_y - self.half_crop_size - offset_w = center_x - self.half_crop_size - - out_image = np.zeros(self.chw_image_shape, dtype=np.uint8) - - _tile_characters_to_image( - out_image=out_image, - chars=chars, - colors=colors, - output_height_chars=self.output_height_chars, - output_width_chars=self.output_width_chars, - char_array=self.char_array, - offset_h=offset_h, - offset_w=offset_w, - ) - - return out_image - obs["screen_image"] = out_image - del obs["tty_chars"] - del obs["tty_colors"] - return obs - - def step(self, action): - obs, reward, done, info = self.env.step(action) - self.obs = obs - obs = self._render_text_to_image(obs) - return obs, reward, done, info - - def reset(self): - obs = self.env.reset() - self.obs = obs - obs = self._render_text_to_image(obs) - return obs - - def render(self, mode='rgb_array'): - return self.obs - - -class RenderCharImagesWithNumpyWrapperV2(gym.Wrapper): - """ - Same as V1, but simpler and faster. - """ - - def __init__( - self, - env, - font_size=9, - crop_size=12, - rescale_font_size=(6, 6), - ): - super().__init__(env) - self.char_array = _initialize_char_array(font_size, rescale_font_size) - self.char_height = self.char_array.shape[2] - self.char_width = self.char_array.shape[3] - # Transpose for CHW - self.char_array = self.char_array.transpose(0, 1, 4, 2, 3) - self.char_array = np.ascontiguousarray(self.char_array) - self.crop_size = crop_size - - crop_rows = crop_size or nethack.nethack.TERMINAL_SHAPE[0] - crop_cols = crop_size or nethack.nethack.TERMINAL_SHAPE[1] - - self.chw_image_shape = ( - 3, - crop_rows * self.char_height, - crop_cols * self.char_width, - ) - - obs_spaces = { - "screen_image": gym.spaces.Box( - low=0, high=255, shape=self.chw_image_shape, dtype=np.uint8 - ) - } - obs_spaces.update( - [ - (k, self.env.observation_space[k]) - for k in self.env.observation_space - if k not in ["tty_chars", "tty_colors"] - ] - ) - self.observation_space = gym.spaces.Dict(obs_spaces) - - def _populate_obs(self, obs): - screen = np.zeros(self.chw_image_shape, order="C", dtype=np.uint8) - render_utils.render_crop( - obs["tty_chars"], - obs["tty_colors"], - obs["tty_cursor"], - self.char_array, - screen, - crop_size=self.crop_size, - ) - obs["screen_image"] = screen - - def step(self, action): - obs, reward, done, info = self.env.step(action) - self._populate_obs(obs) - return obs, reward, done, info - - def reset(self): - obs = self.env.reset() - self._populate_obs(obs) - return obs diff --git a/pufferlib/environments/nmmo/__init__.py b/pufferlib/environments/nmmo/__init__.py deleted file mode 100644 index eff86ef021..0000000000 --- a/pufferlib/environments/nmmo/__init__.py +++ /dev/null @@ -1,12 +0,0 @@ -from .environment import env_creator, make - -try: - import torch -except ImportError: - pass -else: - from .torch import Policy - try: - from .torch import Recurrent - except: - Recurrent = None diff --git a/pufferlib/environments/nmmo/environment.py b/pufferlib/environments/nmmo/environment.py deleted file mode 100644 index f4ef1c9988..0000000000 --- a/pufferlib/environments/nmmo/environment.py +++ /dev/null @@ -1,77 +0,0 @@ -from pdb import set_trace as T -import numpy as np -import functools - -import pufferlib -import pufferlib.emulation -import pufferlib.environments -import pufferlib.wrappers -import pufferlib.postprocess - - -def env_creator(name='nmmo'): - return functools.partial(make, name) - -def make(name, *args, buf=None, **kwargs): - '''Neural MMO creation function''' - nmmo = pufferlib.environments.try_import('nmmo') - env = nmmo.Env(*args, **kwargs) - env = NMMOWrapper(env) - env = pufferlib.postprocess.MultiagentEpisodeStats(env) - env = pufferlib.postprocess.MeanOverAgents(env) - return pufferlib.emulation.PettingZooPufferEnv(env=env, buf=buf) - -class NMMOWrapper(pufferlib.postprocess.PettingZooWrapper): - '''Remove task spam''' - @property - def render_mode(self): - return 'rgb_array' - - def render(self): - '''Quick little renderer for NMMO''' - tiles = self.env.tile_map[:, :, 2].astype(np.uint8) - render = np.zeros((tiles.shape[0], tiles.shape[1], 3), dtype=np.uint8) - BROWN = (136, 69, 19) - render[tiles == 1] = (0, 0, 255) - render[tiles == 2] = (0, 255, 0) - render[tiles == 3] = BROWN - render[tiles == 4] = (64, 255, 64) - render[tiles == 5] = (128, 128, 128) - render[tiles == 6] = BROWN - render[tiles == 7] = (255, 128, 128) - render[tiles == 8] = BROWN - render[tiles == 9] = (128, 255, 128) - render[tiles == 10] = BROWN - render[tiles == 11] = (128, 128, 255) - render[tiles == 12] = BROWN - render[tiles == 13] = (192, 255, 192) - render[tiles == 14] = (0, 0, 255) - render[tiles == 15] = (64, 64, 255) - - for agent in self.env.realm.players.values(): - agent_r = agent.row.val - agent_c = agent.col.val - render[agent_r, agent_c, :] = (255, 255, 0) - - for npc in self.env.realm.npcs.values(): - agent_r = npc.row.val - agent_c = npc.col.val - render[agent_r, agent_c, :] = (255, 0, 0) - - return render - - def reset(self, seed=None): - obs, infos = self.env.reset(seed=seed) - self.obs = obs - return obs, infos - - def step(self, actions): - obs, rewards, dones, truncateds, infos = self.env.step(actions) - infos = {k: list(v['task'].values())[0] for k, v in infos.items()} - self.obs = obs - return obs, rewards, dones, truncateds, infos - - def close(self): - return self.env.close() - - diff --git a/pufferlib/environments/nmmo/torch.py b/pufferlib/environments/nmmo/torch.py deleted file mode 100644 index e98134f3af..0000000000 --- a/pufferlib/environments/nmmo/torch.py +++ /dev/null @@ -1,96 +0,0 @@ -from pdb import set_trace as T - -import torch -import torch.nn.functional as F - -import pufferlib -import pufferlib.emulation -import pufferlib.models -import pufferlib.pytorch -from pufferlib.environments import try_import - -try_import("nmmo") -from nmmo.entity.entity import EntityState - - -class Recurrent(pufferlib.models.LSTMWrapper): - def __init__(self, env, policy, input_size=256, hidden_size=256, num_layers=1): - super().__init__(env, policy, input_size, hidden_size, num_layers) - -class Policy(torch.nn.Module): - NUM_ATTRS = 34 - EntityId = EntityState.State.attr_name_to_col["id"] - tile_offset = torch.tensor([i*256 for i in range(3)]) - entity_offset = torch.tensor([i*256 for i in range(3, 34)]) - - def __init__(self, env, input_size=256, hidden_size=256, output_size=256): - super().__init__() - self.dtype = pufferlib.pytorch.nativize_dtype(env.emulated) - - # A dumb example encoder that applies a linear layer to agent self features - self.embedding = torch.nn.Embedding(self.NUM_ATTRS*256, 32) - self.tile_conv_1 = torch.nn.Conv2d(96, 32, 3) - self.tile_conv_2 = torch.nn.Conv2d(32, 8, 3) - self.tile_fc = torch.nn.Linear(8*11*11, input_size) - - self.entity_fc = torch.nn.Linear(31*32, input_size) - - self.proj_fc = torch.nn.Linear(2*input_size, input_size) - - self.decoders = torch.nn.ModuleList([torch.nn.Linear(hidden_size, n) - for n in env.single_action_space.nvec]) - self.value_head = torch.nn.Linear(hidden_size, 1) - - def forward(self, x): - hidden, lookup = self.encode_observations(x) - actions, value = self.decode_actions(hidden, lookup) - return actions, value - - def encode_observations(self, env_outputs): - env_outputs = pufferlib.pytorch.nativize_tensor(env_outputs, self.dtype) - - tile = env_outputs['Tile'] - # Center on player - # This is cursed without clone?? - tile[:, :, :2] -= tile[:, 112:113, :2].clone() - tile[:, :, :2] += 7 - tile = self.embedding( - tile.long().clip(0, 255) + self.tile_offset.to(tile.device) - ) - - agents, tiles, features, embed = tile.shape - tile = tile.view(agents, tiles, features*embed).transpose(1, 2).view(agents, features*embed, 15, 15) - - tile = self.tile_conv_1(tile) - tile = F.relu(tile) - tile = self.tile_conv_2(tile) - tile = F.relu(tile) - tile = tile.contiguous().view(agents, -1) - tile = self.tile_fc(tile) - tile = F.relu(tile) - - # Pull out rows corresponding to the agent - agentEmb = env_outputs["Entity"] - my_id = env_outputs["AgentId"][:,0] - entity_ids = agentEmb[:,:,self.EntityId] - mask = (entity_ids == my_id.unsqueeze(1)) & (entity_ids != 0) - mask = mask.int() - row_indices = torch.where(mask.any(dim=1), mask.argmax(dim=1), torch.zeros_like(mask.sum(dim=1))) - entity = agentEmb[torch.arange(agentEmb.shape[0]), row_indices] - - entity = self.embedding( - entity.long().clip(0, 255) + self.entity_offset.to(entity.device) - ) - agents, attrs, embed = entity.shape - entity = entity.view(agents, attrs*embed) - - entity = self.entity_fc(entity) - entity = F.relu(entity) - - obs = torch.cat([tile, entity], dim=-1) - return self.proj_fc(obs), None - - def decode_actions(self, hidden, lookup, concat=True): - value = self.value_head(hidden) - actions = [dec(hidden) for dec in self.decoders] - return actions, value diff --git a/pufferlib/environments/open_spiel/__init__.py b/pufferlib/environments/open_spiel/__init__.py deleted file mode 100644 index eff86ef021..0000000000 --- a/pufferlib/environments/open_spiel/__init__.py +++ /dev/null @@ -1,12 +0,0 @@ -from .environment import env_creator, make - -try: - import torch -except ImportError: - pass -else: - from .torch import Policy - try: - from .torch import Recurrent - except: - Recurrent = None diff --git a/pufferlib/environments/open_spiel/environment.py b/pufferlib/environments/open_spiel/environment.py deleted file mode 100644 index a5679b759c..0000000000 --- a/pufferlib/environments/open_spiel/environment.py +++ /dev/null @@ -1,56 +0,0 @@ -from pdb import set_trace as T -import numpy as np -import functools - -import pufferlib -from pufferlib import namespace -import pufferlib.emulation -import pufferlib.environments - - -def env_creator(name='connect_four'): - '''OpenSpiel creation function''' - return functools.partial(make, name) - -def make( - name, - multiplayer=False, - n_rollouts=5, - max_simulations=10, - min_simulations=None, - buf=None - ): - '''OpenSpiel creation function''' - pyspiel = pufferlib.environments.try_import('pyspiel', 'open_spiel') - env = pyspiel.load_game(name) - - if min_simulations is None: - min_simulations = max_simulations - - from pufferlib.environments.open_spiel.gymnasium_environment import ( - OpenSpielGymnasiumEnvironment - ) - from pufferlib.environments.open_spiel.pettingzoo_environment import ( - OpenSpielPettingZooEnvironment - ) - - kwargs = dict( - env=env, - n_rollouts=int(n_rollouts), - min_simulations=int(min_simulations), - max_simulations=int(max_simulations), - ) - - if multiplayer: - env = OpenSpielPettingZooEnvironment(**kwargs) - wrapper_cls = pufferlib.emulation.PettingZooPufferEnv - else: - env = OpenSpielGymnasiumEnvironment(**kwargs) - wrapper_cls = pufferlib.emulation.GymnasiumPufferEnv - - return wrapper_cls( - env=env, - postprocessor_cls=pufferlib.emulation.BasicPostprocessor, - buf=buf, - ) - diff --git a/pufferlib/environments/open_spiel/gymnasium_environment.py b/pufferlib/environments/open_spiel/gymnasium_environment.py deleted file mode 100644 index ae5bfba599..0000000000 --- a/pufferlib/environments/open_spiel/gymnasium_environment.py +++ /dev/null @@ -1,88 +0,0 @@ -from pdb import set_trace as T -import numpy as np - -from open_spiel.python.algorithms import mcts - -import pufferlib -from pufferlib import namespace -from pufferlib.environments.open_spiel.utils import ( - solve_chance_nodes, - get_obs_and_infos, - observation_space, - action_space, - init, - render, - close, -) - - -def create_bots(state, seed): - assert seed is not None, 'seed must be set' - rnd_state = np.random.RandomState(seed) - - evaluator = mcts.RandomRolloutEvaluator( - n_rollouts=state.n_rollouts, - random_state=rnd_state - ) - - return [mcts.MCTSBot( - game=state.env, - uct_c=2, - max_simulations=a, - evaluator=evaluator, - random_state=rnd_state, - child_selection_fn=mcts.SearchNode.puct_value, - solve=True, - ) for a in range(state.min_simulations, state.max_simulations + 1)] - -def reset(state, seed = None, options = None): - state.state = state.env.new_initial_state() - - if not state.has_reset: - state.has_reset = True - state.seed_value = seed - np.random.seed(seed) - state.all_bots = create_bots(state, seed) - - state.bot = np.random.choice(state.all_bots) - - if np.random.rand() < 0.5: - bot_atn = state.bot.step(state.state) - state.state.apply_action(bot_atn) - - obs, infos = get_obs_and_infos(state) - player = state.state.current_player() - return obs[player], infos[player] - -def step(state, action): - player = state.state.current_player() - solve_chance_nodes(state) - state.state.apply_action(action) - - # Take other move with a bot - if not state.state.is_terminal(): - bot_atn = state.bot.step(state.state) - solve_chance_nodes(state) - state.state.apply_action(bot_atn) - - # Now that we have applied all actions, get the next obs. - obs, all_infos = get_obs_and_infos(state) - reward = state.state.returns()[player] - info = all_infos[player] - - # Are we done? - terminated = state.state.is_terminal() - if terminated: - key = f'win_mcts_{state.bot.max_simulations}' - info[key] = int(reward==1) - - return obs[player], reward, terminated, False, info - -class OpenSpielGymnasiumEnvironment: - __init__ = init - step = step - reset = reset - observation_space = property(observation_space) - action_space = property(action_space) - render = render - close = close diff --git a/pufferlib/environments/open_spiel/pettingzoo_environment.py b/pufferlib/environments/open_spiel/pettingzoo_environment.py deleted file mode 100644 index cbfca0af42..0000000000 --- a/pufferlib/environments/open_spiel/pettingzoo_environment.py +++ /dev/null @@ -1,68 +0,0 @@ -from pdb import set_trace as T -import numpy as np - -import pufferlib -from pufferlib import namespace - -from pufferlib.environments.open_spiel.utils import ( - solve_chance_nodes, - get_obs_and_infos, - observation_space, - action_space, - init, - render, - close, -) - -def agents(state): - return state.agents - -def possible_agents(state): - return list(range(state.env.num_players())) - -def pz_observation_space(state, agent): - return observation_space(state) - -def pz_action_space(state, agent): - return action_space(state) - -def reset(state, seed = None, options = None): - state.state = state.env.new_initial_state() - obs, infos = get_obs_and_infos(state) - state.agents = state.possible_agents - - if not state.has_reset: - state.has_reset = True - state.seed_value = seed - np.random.seed(seed) - - return obs, infos - -def step(state, actions): - curr_player = state.state.current_player() - solve_chance_nodes(state) - state.state.apply_action(actions[curr_player]) - obs, infos = get_obs_and_infos(state) - rewards = {ag: r for ag, r in enumerate(state.state.returns())} - - # Are we done? - is_terminated = state.state.is_terminal() - terminateds = {a: False for a in obs} - truncateds = {a: False for a in obs} - - if is_terminated: - terminateds = {a: True for a in state.possible_agents} - state.agents = [] - - return obs, rewards, terminateds, truncateds, infos - -class OpenSpielPettingZooEnvironment: - __init__ = init - step = step - reset = reset - agents = lambda state: state.agents - possible_agents = property(possible_agents) - observation_space = pz_observation_space - action_space = pz_action_space - render = render - close = close diff --git a/pufferlib/environments/open_spiel/torch.py b/pufferlib/environments/open_spiel/torch.py deleted file mode 100644 index 4d1845b6ba..0000000000 --- a/pufferlib/environments/open_spiel/torch.py +++ /dev/null @@ -1,44 +0,0 @@ -from pdb import set_trace as T -import numpy as np - -import torch -from torch import nn - -import pufferlib.emulation -from pufferlib.models import Policy as Base - -class Policy(Base): - def __init__(self, env, input_size=128, hidden_size=128): - '''Default PyTorch policy, meant for debugging. - This should run with any environment but is unlikely to learn anything. - - Uses a single linear layer + relu to encode observations and a list of - linear layers to decode actions. The value function is a single linear layer. - ''' - super().__init__(env) - - self.flat_observation_space = env.flat_observation_space - self.flat_observation_structure = env.flat_observation_structure - - self.encoder = nn.Linear(np.prod( - env.structured_observation_space['obs'].shape), hidden_size) - self.decoder = nn.Linear(hidden_size, self.action_space.n) - - self.value_head = nn.Linear(hidden_size, 1) - - def encode_observations(self, observations): - '''Linear encoder function''' - observations = pufferlib.emulation.unpack_batched_obs(observations, - self.flat_observation_space, self.flat_observation_structure) - obs = observations['obs'].view(observations['obs'].shape[0], -1) - self.action_mask = observations['action_mask'] - - hidden = torch.relu(self.encoder(obs)) - return hidden, None - - def decode_actions(self, hidden, lookup, concat=True): - '''Concatenated linear decoder function''' - value = self.value_head(hidden) - action = self.decoder(hidden) - action = action.masked_fill(self.action_mask == 0, -1e9) - return action, value \ No newline at end of file diff --git a/pufferlib/environments/open_spiel/utils.py b/pufferlib/environments/open_spiel/utils.py deleted file mode 100644 index 8eab105c28..0000000000 --- a/pufferlib/environments/open_spiel/utils.py +++ /dev/null @@ -1,99 +0,0 @@ -from pdb import set_trace as T -import numpy as np - -import gymnasium - -from pufferlib import namespace - - -def init(self, - env, - n_rollouts, - min_simulations, - max_simulations - ): - #state.num_agents = state.env.num_players() - return namespace(self, - env=env, - type=env.get_type(), - n_rollouts=n_rollouts, - min_simulations=min_simulations, - max_simulations=max_simulations, - state=None, - agents=[], - has_reset=False, - ) - -def observation_space(state): - return gymnasium.spaces.Dict({ - 'obs': gymnasium.spaces.Box( - low=0.0, - high=1.0, - shape=(state.env.observation_tensor_size(),), - dtype=np.float32, - ), - 'action_mask': gymnasium.spaces.Box( - low=0, - high=1, - shape=(action_space(state).n,), - dtype=np.int8 - ) - }) - -def action_space(state): - return gymnasium.spaces.Discrete( - state.env.num_distinct_actions()) - -def render(state, mode=None) -> None: - if mode == "human": - print(state.state) - -def close(state): - pass - -def act(state, action): - solve_chance_nodes(state) - state.state.apply_action(action) - -def get_obs_and_infos(state): - # Before calculating an observation, there could be chance nodes - # (that may have an effect on the actual observations). - # E.g. After reset, figure out initial (random) positions of the - # agents. - solve_chance_nodes(state) - - if state.state.is_terminal(): - return ( - state.last_obs, - {player: {} for player in range(state.env.num_players())}, - ) - - # Sequential game: - curr_player = state.state.current_player() - mask = state.state.legal_actions(curr_player) - np_mask = np.zeros(action_space(state).n) - np_mask[mask] = 1 - - state.last_obs = {player: { - 'obs': np.reshape(state.state.observation_tensor(), - [-1]).astype(np.float32), - 'action_mask': np_mask.astype(np.int8), - } for player in range(state.env.num_players())} - - state.last_info = {curr_player: {}} - - return ( - {curr_player: state.last_obs[curr_player]}, - state.last_info, - ) - -def solve_chance_nodes(state): - # Before applying action(s), there could be chance nodes. - # E.g. if env has to figure out, which agent's action should get - # resolved first in a simultaneous node. - # Chance node(s): Sample a (non-player) action and apply. - while state.state.is_chance_node(): - assert state.state.current_player() == -1 - actions, probs = zip(*state.state.chance_outcomes()) - action = np.random.choice(actions, p=probs) - state.state.apply_action(action) diff --git a/pufferlib/environments/pokemon_red/__init__.py b/pufferlib/environments/pokemon_red/__init__.py deleted file mode 100644 index eff86ef021..0000000000 --- a/pufferlib/environments/pokemon_red/__init__.py +++ /dev/null @@ -1,12 +0,0 @@ -from .environment import env_creator, make - -try: - import torch -except ImportError: - pass -else: - from .torch import Policy - try: - from .torch import Recurrent - except: - Recurrent = None diff --git a/pufferlib/environments/pokemon_red/environment.py b/pufferlib/environments/pokemon_red/environment.py deleted file mode 100644 index fe0bd85e78..0000000000 --- a/pufferlib/environments/pokemon_red/environment.py +++ /dev/null @@ -1,31 +0,0 @@ -from pdb import set_trace as T - -import gymnasium -import functools - -from pokegym import Environment - -import pufferlib.emulation -import pufferlib.postprocess - - -def env_creator(name='pokemon_red'): - return functools.partial(make, name) - -def make(name, headless: bool = True, state_path=None, buf=None, seed=0): - '''Pokemon Red''' - env = Environment(headless=headless, state_path=state_path) - env = RenderWrapper(env) - env = pufferlib.postprocess.EpisodeStats(env) - return pufferlib.emulation.GymnasiumPufferEnv(env=env, buf=buf, seed=seed) - -class RenderWrapper(gymnasium.Wrapper): - def __init__(self, env): - self.env = env - - @property - def render_mode(self): - return 'rgb_array' - - def render(self): - return self.env.screen.screen_ndarray() diff --git a/pufferlib/environments/pokemon_red/torch.py b/pufferlib/environments/pokemon_red/torch.py deleted file mode 100644 index 370b023bf6..0000000000 --- a/pufferlib/environments/pokemon_red/torch.py +++ /dev/null @@ -1,36 +0,0 @@ -from functools import partial -import torch - -import pufferlib.models - - -class Recurrent(pufferlib.models.LSTMWrapper): - def __init__(self, env, policy, - input_size=512, hidden_size=512, num_layers=1): - super().__init__(env, policy, - input_size, hidden_size, num_layers) - -class Policy(pufferlib.models.Convolutional): - def __init__(self, env, - input_size=512, hidden_size=512, output_size=512, - framestack=4, flat_size=64*5*6): - super().__init__( - env=env, - input_size=input_size, - hidden_size=hidden_size, - output_size=output_size, - framestack=framestack, - flat_size=flat_size, - channels_last=True, - ) - - -''' -class Policy(pufferlib.models.ProcgenResnet): - def __init__(self, env, cnn_width=16, mlp_width=512): - super().__init__( - env=env, - cnn_width=cnn_width, - mlp_width=mlp_width, - ) -''' diff --git a/pufferlib/environments/procgen/__init__.py b/pufferlib/environments/procgen/__init__.py deleted file mode 100644 index eff86ef021..0000000000 --- a/pufferlib/environments/procgen/__init__.py +++ /dev/null @@ -1,12 +0,0 @@ -from .environment import env_creator, make - -try: - import torch -except ImportError: - pass -else: - from .torch import Policy - try: - from .torch import Recurrent - except: - Recurrent = None diff --git a/pufferlib/environments/procgen/environment.py b/pufferlib/environments/procgen/environment.py deleted file mode 100644 index 3d889b73fd..0000000000 --- a/pufferlib/environments/procgen/environment.py +++ /dev/null @@ -1,74 +0,0 @@ -from pdb import set_trace as T -import numpy as np - -import gym -import gymnasium -import shimmy -import functools - -import pufferlib -import pufferlib.emulation -import pufferlib.environments - -from stable_baselines3.common.atari_wrappers import ( - MaxAndSkipEnv, -) - -def env_creator(name='bigfish'): - return functools.partial(make, name) - -def make(name, num_envs=1, num_levels=0, start_level=0, - distribution_mode='easy', render_mode=None, buf=None, seed=0): - '''Atari creation function with default CleanRL preprocessing based on Stable Baselines3 wrappers''' - assert int(num_envs) == float(num_envs), "num_envs must be an integer" - num_envs = int(num_envs) - - procgen = pufferlib.environments.try_import('procgen') - envs = procgen.ProcgenEnv( - env_name=name, - num_envs=num_envs, - num_levels=num_levels, - start_level=start_level, - distribution_mode=distribution_mode, - render_mode=render_mode, - ) - envs = gym.wrappers.TransformObservation(envs, lambda obs: obs["rgb"]) - envs.single_action_space = envs.action_space - envs.single_observation_space = envs.observation_space["rgb"] - envs.is_vector_env = True - envs = gym.wrappers.RecordEpisodeStatistics(envs) - envs = gym.wrappers.NormalizeReward(envs) - envs = gym.wrappers.TransformReward(envs, lambda reward: np.clip(reward, -10, 10)) - assert isinstance(envs.single_action_space, gym.spaces.Discrete), "only discrete action space is supported" - envs = ProcgenWrapper(envs) - envs = shimmy.GymV21CompatibilityV0(env=envs, render_mode=render_mode) - #envs = gymnasium.wrappers.GrayScaleObservation(envs) - #envs = gymnasium.wrappers.FrameStack(envs, 4)#, framestack) - #envs = MaxAndSkipEnv(envs, skip=2) - envs = pufferlib.EpisodeStats(envs) - return pufferlib.emulation.GymnasiumPufferEnv(env=envs, buf=buf) - -class ProcgenWrapper: - def __init__(self, env): - self.env = env - self.observation_space = self.env.observation_space['rgb'] - self.action_space = self.env.action_space - - @property - def render_mode(self): - return 'rgb_array' - - def reset(self, seed=None): - obs = self.env.reset()[0] - return obs - - def render(self, mode=None): - return self.env.env.env.env.env.env.get_info()[0]['rgb'] - - def close(self): - return self.env.close() - - def step(self, actions): - actions = np.asarray(actions).reshape(1) - obs, rewards, dones, infos = self.env.step(actions) - return obs[0], rewards[0], dones[0], infos[0] diff --git a/pufferlib/environments/procgen/torch.py b/pufferlib/environments/procgen/torch.py deleted file mode 100644 index 924926c34f..0000000000 --- a/pufferlib/environments/procgen/torch.py +++ /dev/null @@ -1,50 +0,0 @@ -from pdb import set_trace as T -from torch import nn -import pufferlib.models - -# This policy ended up being useful broadly -# so I included it in the defaults - -class Recurrent(pufferlib.models.LSTMWrapper): - def __init__(self, env, policy, input_size=256, hidden_size=256, num_layers=1): - super().__init__(env, policy, input_size, hidden_size, num_layers) - -class Policy (nn.Module): - def __init__(self, env, *args, input_size=256, hidden_size=256, - output_size=256, **kwargs): - '''The CleanRL default NatureCNN policy used for Atari. - It's just a stack of three convolutions followed by a linear layer - - Takes framestack as a mandatory keyword argument. Suggested default is 1 frame - with LSTM or 4 frames without.''' - super().__init__() - - self.network= nn.Sequential( - pufferlib.pytorch.layer_init(nn.Conv2d(3, 16, 8, stride=4)), - nn.ReLU(), - pufferlib.pytorch.layer_init(nn.Conv2d(16, 32, 4, stride=2)), - nn.ReLU(), - nn.Flatten(), - pufferlib.pytorch.layer_init(nn.Linear(1152, hidden_size)), - nn.ReLU(), - ) - self.actor = pufferlib.pytorch.layer_init( - nn.Linear(hidden_size, env.single_action_space.n), std=0.01) - self.value_fn = pufferlib.pytorch.layer_init( - nn.Linear(output_size, 1), std=1) - - def forward(self, observations): - hidden, lookup = self.encode_observations(observations) - actions, value = self.decode_actions(hidden, lookup) - return actions, value - - def encode_observations(self, observations): - observations = observations.permute(0, 3, 1, 2) - return self.network(observations.float() / 255.0), None - - def decode_actions(self, flat_hidden, lookup, concat=None): - action = self.actor(flat_hidden) - value = self.value_fn(flat_hidden) - return action, value - -Policy = pufferlib.models.ProcgenResnet diff --git a/pufferlib/environments/slimevolley/__init__.py b/pufferlib/environments/slimevolley/__init__.py deleted file mode 100644 index 59cda9e7c2..0000000000 --- a/pufferlib/environments/slimevolley/__init__.py +++ /dev/null @@ -1,12 +0,0 @@ -from .environment import env_creator - -try: - import torch -except ImportError: - pass -else: - from .torch import Policy - try: - from .torch import Recurrent - except: - Recurrent = None diff --git a/pufferlib/environments/slimevolley/environment.py b/pufferlib/environments/slimevolley/environment.py deleted file mode 100644 index a46d79562e..0000000000 --- a/pufferlib/environments/slimevolley/environment.py +++ /dev/null @@ -1,70 +0,0 @@ -from pdb import set_trace as T -import numpy as np -import functools - -import gym -import shimmy - -import pufferlib -import pufferlib.emulation -import pufferlib.environments -import pufferlib.utils -import pufferlib.postprocess - - -def env_creator(name='SlimeVolley-v0'): - return functools.partial(make, name) - -def make(name, render_mode='rgb_array', buf=None): - if name == 'slimevolley': - name = 'SlimeVolley-v0' - - from slimevolleygym import SlimeVolleyEnv - SlimeVolleyEnv.atari_mode = True - env = SlimeVolleyEnv() - env.policy.predict = lambda obs: np.random.randint(0, 2, 3) - env = SlimeVolleyMultiDiscrete(env) - env = SkipWrapper(env, repeat_count=4) - env = shimmy.GymV21CompatibilityV0(env=env) - env = pufferlib.postprocess.EpisodeStats(env) - return pufferlib.emulation.GymnasiumPufferEnv(env=env, buf=buf) - -class SlimeVolleyMultiDiscrete(gym.Wrapper): - def __init__(self, env): - super().__init__(env) - #self.action_space = gym.spaces.MultiDiscrete( - # [2 for _ in range(env.action_space.n)]) - - def reset(self, seed=None): - return self.env.reset().astype(np.float32) - - def step(self, action): - obs, reward, done, info = self.env.step(action) - return obs.astype(np.float32), reward, done, info - -class SkipWrapper(gym.Wrapper): - """ - Generic common frame skipping wrapper - Will perform action for `x` additional steps - """ - def __init__(self, env, repeat_count): - super(SkipWrapper, self).__init__(env) - self.repeat_count = repeat_count - self.stepcount = 0 - - def step(self, action): - done = False - total_reward = 0 - current_step = 0 - while current_step < (self.repeat_count + 1) and not done: - self.stepcount += 1 - obs, reward, done, info = self.env.step(action) - total_reward += reward - current_step += 1 - - return obs, total_reward, done, info - - def reset(self): - self.stepcount = 0 - return self.env.reset() - diff --git a/pufferlib/environments/slimevolley/torch.py b/pufferlib/environments/slimevolley/torch.py deleted file mode 100644 index e5188f3b7e..0000000000 --- a/pufferlib/environments/slimevolley/torch.py +++ /dev/null @@ -1,4 +0,0 @@ -import pufferlib.models - -Recurrent = pufferlib.models.LSTMWrapper -Policy = pufferlib.models.Default diff --git a/pufferlib/environments/smac/__init__.py b/pufferlib/environments/smac/__init__.py deleted file mode 100644 index eff86ef021..0000000000 --- a/pufferlib/environments/smac/__init__.py +++ /dev/null @@ -1,12 +0,0 @@ -from .environment import env_creator, make - -try: - import torch -except ImportError: - pass -else: - from .torch import Policy - try: - from .torch import Recurrent - except: - Recurrent = None diff --git a/pufferlib/environments/smac/environment.py b/pufferlib/environments/smac/environment.py deleted file mode 100644 index e104e860b3..0000000000 --- a/pufferlib/environments/smac/environment.py +++ /dev/null @@ -1,23 +0,0 @@ -import functools - -import pufferlib -import pufferlib.emulation -import pufferlib.environments -import pufferlib.wrappers - - -def env_creator(name='smac'): - return functools.partial(make, name) - -def make(name, buf=None): - '''Starcraft Multiagent Challenge creation function - - Support for SMAC is WIP because environments do not function without - an action-masked baseline policy.''' - pufferlib.environments.try_import('smac') - from smac.env.pettingzoo.StarCraft2PZEnv import _parallel_env as smac_env - - env = smac_env(1000) - env = pufferlib.wrappers.PettingZooTruncatedWrapper(env) - env = pufferlib.emulation.PettingZooPufferEnv(env, buf=buf) - return env diff --git a/pufferlib/environments/smac/torch.py b/pufferlib/environments/smac/torch.py deleted file mode 100644 index 8b13194e9e..0000000000 --- a/pufferlib/environments/smac/torch.py +++ /dev/null @@ -1 +0,0 @@ -from pufferlib.models import Default as Policy diff --git a/pufferlib/environments/stable_retro/__init__.py b/pufferlib/environments/stable_retro/__init__.py deleted file mode 100644 index eff86ef021..0000000000 --- a/pufferlib/environments/stable_retro/__init__.py +++ /dev/null @@ -1,12 +0,0 @@ -from .environment import env_creator, make - -try: - import torch -except ImportError: - pass -else: - from .torch import Policy - try: - from .torch import Recurrent - except: - Recurrent = None diff --git a/pufferlib/environments/stable_retro/environment.py b/pufferlib/environments/stable_retro/environment.py deleted file mode 100644 index 092708613b..0000000000 --- a/pufferlib/environments/stable_retro/environment.py +++ /dev/null @@ -1,72 +0,0 @@ -from pdb import set_trace as T -import numpy as np - -import gymnasium as gym -import functools - -import pufferlib -import pufferlib.emulation -import pufferlib.environments - - -def env_creator(name='Airstriker-Genesis'): - return functools.partial(make, name) - -def make(name='Airstriker-Genesis', framestack=4, buf=None): - '''Atari creation function with default CleanRL preprocessing based on Stable Baselines3 wrappers''' - retro = pufferlib.environments.try_import('retro', 'stable-retro') - - from stable_baselines3.common.atari_wrappers import ( - ClipRewardEnv, - EpisodicLifeEnv, - FireResetEnv, - MaxAndSkipEnv, - ) - with pufferlib.utils.Suppress(): - env = retro.make(name) - - env = gym.wrappers.RecordEpisodeStatistics(env) - env = MaxAndSkipEnv(env, skip=4) - env = ClipRewardEnv(env) - env = gym.wrappers.ResizeObservation(env, (84, 84)) - env = gym.wrappers.GrayScaleObservation(env) - env = gym.wrappers.FrameStack(env, framestack) - return pufferlib.emulation.GymnasiumPufferEnv( - env=env, postprocessor_cls=AtariFeaturizer, buf=buf) - -class AtariFeaturizer(pufferlib.emulation.Postprocessor): - def reset(self, obs): - self.epoch_return = 0 - self.epoch_length = 0 - self.done = False - - #@property - #def observation_space(self): - # return gym.spaces.Box(0, 255, (1, 84, 84), dtype=np.uint8) - - def observation(self, obs): - return np.array(obs) - return np.array(obs[1], dtype=np.float32) - - def reward_done_truncated_info(self, reward, done, truncated, info): - return reward, done, truncated, info - if 'lives' in info: - if info['lives'] == 0 and done: - info['return'] = info['episode']['r'] - info['length'] = info['episode']['l'] - info['time'] = info['episode']['t'] - return reward, True, info - return reward, False, info - - if self.done: - return reward, done, info - - if done: - info['return'] = self.epoch_return - info['length'] = self.epoch_length - self.done = True - else: - self.epoch_length += 1 - self.epoch_return += reward - - return reward, done, info diff --git a/pufferlib/environments/stable_retro/torch.py b/pufferlib/environments/stable_retro/torch.py deleted file mode 100644 index 0ab6021838..0000000000 --- a/pufferlib/environments/stable_retro/torch.py +++ /dev/null @@ -1,19 +0,0 @@ -import pufferlib.models - - -class Recurrent: - input_size = 512 - hidden_size = 512 - num_layers = 1 - -class Policy(pufferlib.models.Convolutional): - def __init__(self, env, input_size=512, hidden_size=512, output_size=512, - framestack=4, flat_size=64*7*7): - super().__init__( - env=env, - input_size=input_size, - hidden_size=hidden_size, - output_size=output_size, - framestack=framestack, - flat_size=flat_size, - ) diff --git a/pufferlib/environments/test/__init__.py b/pufferlib/environments/test/__init__.py deleted file mode 100644 index 9d3bfe4212..0000000000 --- a/pufferlib/environments/test/__init__.py +++ /dev/null @@ -1,23 +0,0 @@ -from .environment import ( - GymnasiumPerformanceEnv, - PettingZooPerformanceEnv, - GymnasiumTestEnv, - PettingZooTestEnv, - make_all_mock_environments, - MOCK_OBSERVATION_SPACES, - MOCK_ACTION_SPACES, -) - -from .mock_environments import MOCK_SINGLE_AGENT_ENVIRONMENTS -from .mock_environments import MOCK_MULTI_AGENT_ENVIRONMENTS - -try: - import torch -except ImportError: - pass -else: - from .torch import Policy - try: - from .torch import Recurrent - except: - Recurrent = None diff --git a/pufferlib/environments/test/environment.py b/pufferlib/environments/test/environment.py deleted file mode 100644 index ff82c6e47b..0000000000 --- a/pufferlib/environments/test/environment.py +++ /dev/null @@ -1,439 +0,0 @@ -from pdb import set_trace as T -import numpy as np - -import time -import hashlib - -import gym -import gymnasium -from gymnasium.spaces import Box, Discrete, Dict, Tuple -from pufferlib import spaces -from pettingzoo.utils.env import ParallelEnv - -import pufferlib -import pufferlib.emulation -import pufferlib.utils - - -HIGH = 100 -LOW = 0 - -MOCK_OBSERVATION_SPACES = [ - # Atari space - Box(low=0, high=255, shape=(4, 84, 84), dtype=np.uint8), - - # NetHack space - Dict({ - 'blstats': Box(-2147483648, 2147483647, (27,), 'int64'), - 'chars': Box(0, 255, (21, 79), 'uint8'), - 'colors': Box(0, 15, (21, 79), 'uint8'), - 'glyphs': Box(0, 5976, (21, 79), 'int16'), - 'inv_glyphs': Box(0, 5976, (55,), 'int16'), - 'inv_letters': Box(0, 127, (55,), 'uint8'), - 'inv_oclasses': Box(0, 18, (55,), 'uint8'), - 'inv_strs': Box(0, 255, (55, 80), 'uint8'), - 'message': Box(0, 255, (256,), 'uint8'), - 'screen_descriptions': Box(0, 127, (21, 79, 80), 'uint8'), - 'specials': Box(0, 255, (21, 79), 'uint8'), - 'tty_chars': Box(0, 255, (24, 80), 'uint8'), - 'tty_colors': Box(0, 31, (24, 80), 'int8'), - 'tty_cursor': Box(0, 255, (2,), 'uint8'), - }), - - # Neural MMO space - Dict({ - 'ActionTargets': Dict({ - 'Attack': Dict({ - 'Style': Box(0, 1, (3,), 'int8'), - 'Target': Box(0, 1, (100,), 'int8'), - }), - 'Buy': Dict({ - 'MarketItem': Box(0, 1, (1024,), 'int8'), - }), - 'Comm': Dict({ - 'Token': Box(0, 1, (50,), 'int8'), - }), - 'Destroy': Dict({ - 'InventoryItem': Box(0, 1, (12,), 'int8'), - }), - 'Give': Dict({ - 'InventoryItem': Box(0, 1, (12,), 'int8'), - 'Target': Box(0, 1, (100,), 'int8'), - }), - 'GiveGold': Dict({ - 'Price': Box(0, 1, (99,), 'int8'), - 'Target': Box(0, 1, (100,), 'int8'), - }), - 'Move': Dict({ - 'Direction': Box(0, 1, (5,), 'int8'), - }), - 'Sell': Dict({ - 'InventoryItem': Box(0, 1, (12,), 'int8'), - 'Price': Box(0, 1, (99,), 'int8'), - }), - 'Use': Dict({ - 'InventoryItem': Box(0, 1, (12,), 'int8'), - }) - }), - 'AgentId': Discrete(129), - 'CurrentTick': Discrete(1025), - 'Entity': Box(-32768, 32767, (100, 23), 'int16'), - 'Inventory': Box(-32768, 32767, (12, 16), 'int16'), - 'Market': Box(-32768, 32767, (1024, 16), 'int16'), - 'Task': Box(-32770.0, 32770.0, (1024,), 'float16'), - 'Tile': Box(-32768, 32767, (225, 3), 'int16'), - }), - - # Simple spaces - Discrete(5), - Box(low=LOW, high=HIGH, shape=(4,), dtype=np.float32), - - # Nested spaces - Dict({ - "foo": Box(low=LOW, high=HIGH, shape=(2,), dtype=np.float32), - "bar": Box(low=LOW, high=HIGH, shape=(2,), dtype=np.float32), - }), - Tuple((Discrete(3), Discrete(4))), - Tuple(( - Box(low=LOW, high=HIGH, shape=(2,), dtype=np.float32), - Discrete(3), - Dict({ - "baz": Box(low=LOW, high=HIGH, shape=(1,), dtype=np.float32), - "qux": Box(low=LOW, high=HIGH, shape=(1,), dtype=np.float32), - }), - )), - Dict({ - "foo": Tuple(( - Box(low=LOW, high=HIGH, shape=(2,), dtype=np.float32), - Discrete(3), - )), - "bar": Dict({ - "baz": Discrete(2), - "qux": Discrete(4), - }), - }), -] - -MOCK_ACTION_SPACES = [ - # NetHack action space - Discrete(5), - - # Neural MMO action space - Dict({ - 'Attack': Dict({ - 'Style': Discrete(3), - 'Target': Discrete(100), - }), - 'Buy': Dict({ - 'MarketItem': Discrete(1024), - }), - 'Comm': Dict({ - 'Token': Discrete(50), - }), - 'Destroy': Dict({ - 'InventoryItem': Discrete(12), - }), - 'Give': Dict({ - 'InventoryItem': Discrete(12), - 'Target': Discrete(100), - }), - 'GiveGold': Dict({ - 'Price': Discrete(99), - 'Target': Discrete(100), - }), - 'Move': Dict({ - 'Direction': Discrete(5), - }), - 'Sell': Dict({ - 'InventoryItem': Discrete(12), - 'Price': Discrete(99), - }), - 'Use': Dict({ - 'InventoryItem': Discrete(12), - }) - }), - - # Nested spaces - Tuple((Discrete(2), Discrete(3))), - Dict({ - "foo": Discrete(4), - "bar": Discrete(2), - }), - Tuple(( - Discrete(4), - Dict({ - "baz": Discrete(2), - "qux": Discrete(2), - }), - )), - Dict({ - "foo": Tuple(( - Discrete(2), - Discrete(3), - )), - "bar": Dict({ - "baz": Discrete(2), - "qux": Discrete(4), - }), - }), -] - -MOCK_TEAMS = { - 'None': None, - 'single': { - 'team_1': ['agent_1'], - 'team_2': ['agent_2'], - 'team_3': ['agent_3'], - 'team_4': ['agent_4'], - 'team_5': ['agent_5'], - 'team_6': ['agent_6'], - 'team_7': ['agent_7'], - 'team_8': ['agent_8'], - 'team_9': ['agent_9'], - 'team_10': ['agent_10'], - 'team_11': ['agent_11'], - 'team_12': ['agent_12'], - 'team_13': ['agent_13'], - 'team_14': ['agent_14'], - 'team_15': ['agent_15'], - 'team_16': ['agent_16'], - }, - 'pairs': { - 'team_1': ['agent_1', 'agent_2'], - 'team_2': ['agent_3', 'agent_4'], - 'team_3': ['agent_5', 'agent_6'], - 'team_4': ['agent_7', 'agent_8'], - 'team_5': ['agent_9', 'agent_10'], - 'team_6': ['agent_11', 'agent_12'], - 'team_7': ['agent_13', 'agent_14'], - 'team_8': ['agent_15', 'agent_16'], - }, - 'mixed': { - 'team_1': ['agent_1', 'agent_2'], - 'team_2': ['agent_3', 'agent_4', 'agent_5', 'agent_6'], - 'team_3': ['agent_7', 'agent_8', 'agent_9'], - 'team_4': ['agent_10', 'agent_11', 'agent_12', 'agent_13', 'agent_14'], - 'team_5': ['agent_15', 'agent_16'], - }, -} - -DEFAULT_OBSERVATION_SPACE = gymnasium.spaces.Box( - low=-2**20, high=2**20, - shape=(1,), dtype=np.float32 -) -DEFAULT_ACTION_SPACE = gymnasium.spaces.Discrete(2) - - -def make_all_mock_environments(): - mock_single_agent_environments = [] - mock_multi_agent_environments = [] - for obs_space in MOCK_OBSERVATION_SPACES: - for act_space in MOCK_ACTION_SPACES: - mock_single_agent_environments.append( - GymnasiumTestEnv( - observation_space=obs_space, - action_space=act_space, - ) - ) - - mock_multi_agent_environments.append( - PettingZooTestEnv( - observation_space=obs_space, - action_space=act_space, - initial_agents=16, - max_agents=16, - spawn_per_tick=0, - death_per_tick=1, - ) - ) - return mock_single_agent_environments, mock_multi_agent_environments - -def do_work(delay_mean, delay_std): - start, idx = time.process_time(), 0 - target_time = delay_mean + delay_std*np.random.randn() - while time.process_time() - start < target_time: - idx += 1 - return - -class GymnasiumPerformanceEnv: - def __init__(self, delay_mean=0, delay_std=0): - self.observation_space = DEFAULT_OBSERVATION_SPACE - self.action_space = DEFAULT_ACTION_SPACE - self.observation = self.observation_space.sample() - - self.delay_mean = delay_mean - self.delay_std = delay_std - - # Test performance independent of PufferLib seeding - np.random.seed(time.time_ns() % 2**32) - - def reset(self, seed=None): - return self.observation, {} - - def step(self, action): - do_work(self.delay_mean, self.delay_std) - return self.observation, 0, False, False, {} - - def close(self): - pass - -class PettingZooPerformanceEnv: - def __init__(self, delay_mean, delay_std): - self.possible_agents = [1] - self.agents = [1] - self.done = False - - self.delay_mean = delay_mean - self.delay_std = delay_std - - def observation_space(self, agent): - return DEFAULT_OBSERVATION_SPACE - - def action_space(self, agent): - return DEFAULT_ACTION_SPACE - - def reset(self, seed=None): - return {1: self.observation_space(1).sample()}, {1: {}} - - def step(self, actions): - obs = {1: np.array([0], dtype=np.float32)} - rewards = {1: 1} - dones = {1: False} - truncateds = {1: False} - infos = {1: {}} - - do_work(self.delay_mean, self.delay_std) - - return obs, rewards, dones, truncateds, infos - - def close(self): - pass - -class GymnasiumTestEnv(gym.Env): - def __init__(self, - observation_space=DEFAULT_OBSERVATION_SPACE, - action_space=DEFAULT_ACTION_SPACE): - self.observation_space = observation_space - self.action_space = action_space - - def reset(self, seed=None): - self.tick = 0 - self.rng = pufferlib.utils.RandomState(seed) - - ob = _sample_space('agent_1', self.tick, self.observation_space) - return ob, {} - - def step(self, actions): - reward = self.tick - done = self.tick < 10 - self.tick += 1 - - ob = _sample_space('agent_1', self.tick, self.observation_space) - return ob, reward, done, False, {'dead': done} - - def close(self): - pass - -class PettingZooTestEnv(ParallelEnv): - def __init__(self, - observation_space=DEFAULT_OBSERVATION_SPACE, - action_space=DEFAULT_ACTION_SPACE, - initial_agents=16, max_agents=16, - spawn_per_tick=0, death_per_tick=1, - homogeneous_spaces=True): - self._observation_space = observation_space - self._action_space = action_space - self.initial_agents = initial_agents - self.max_agents = max_agents - self.spawn_per_tick = spawn_per_tick - self.death_per_tick = death_per_tick - self.homogeneous_spaces = homogeneous_spaces - - self.possible_agents = [f'agent_{i+1}' for i in range(max_agents)] - self.agents = [] - - def reset(self, seed=None): - self.tick = 0 - self.agents = self.possible_agents[:self.initial_agents] - - obs = {a: _sample_space(a, self.tick, self._observation_space) - for a in self.agents} - infos = {a: {} for a in self.agents} - return obs, infos - - def step(self, actions): - obs, rewards, dones, truncateds, infos = {}, {}, {}, {}, {} - self.tick += 1 - - dead = self.agents[:self.death_per_tick] - for kill in dead: - self.agents.remove(kill) - # TODO: Make pufferlib work without pad obs - # but still require rewards, dones, and optionally infos - obs[kill] = _sample_space(kill, self.tick, - self._observation_space, zero=True) - rewards[kill] = -1 - dones[kill] = True - truncateds[kill] = False - infos[kill] = {'dead': True} - - # TODO: Fix this - assert self.spawn_per_tick == 0 - for spawn in range(self.spawn_per_tick): - # TODO: Make pufferlib check if an agent respawns on the - # Same tick as it dies (is this good or bad?) - spawn = self.rng.choice(self.possible_agents) - if spawn not in self.agents + dead: - self.agents.append(spawn) - - for agent in self.agents: - obs[agent] = _sample_space(agent, self.tick, self._observation_space) - rewards[agent] = 0.1 * _agent_str_to_int(agent) - dones[agent] = False - truncateds[agent] = False - infos[agent] = {'dead': False} - - return obs, rewards, dones, truncateds, infos - - def observation_space(self, agent) -> gym.Space: - return self._observation_space - - def action_space(self, agent) -> gym.Space: - return self._action_space - - def render(self, mode='human'): - pass - - def close(self): - pass - -### Other Mock environments and utilities -def _agent_str_to_int(agent): - return int(agent.split('_')[-1]) - -def _sample_space(agent, tick, space, zero=False): - if isinstance(agent, str): - agent = float(agent.split('_')[-1]) - - if isinstance(space, spaces.Discrete): - if zero: - return 0 - return int((10*agent + tick) % space.n) - elif isinstance(space, spaces.Box): - if zero: - return np.zeros(space.shape, dtype=space.dtype) - - # Try to make a relatively unique data pattern - # without using RNG - nonce = 10*agent + tick - low = space.low - high = space.high - sample = low + np.arange(low.size).reshape(space.shape) + nonce - sample = (sample % high).astype(space.dtype) - return sample - elif isinstance(space, spaces.Tuple): - return tuple(_sample_space(agent, tick, s, zero) for s in space.spaces) - elif isinstance(space, spaces.Dict): - return {k: _sample_space(agent, tick, v, zero) for k, v in space.spaces.items()} - else: - raise ValueError(f"Invalid space type: {type(space)}") diff --git a/pufferlib/environments/test/mock_environments.py b/pufferlib/environments/test/mock_environments.py deleted file mode 100644 index 8e8db330ed..0000000000 --- a/pufferlib/environments/test/mock_environments.py +++ /dev/null @@ -1,429 +0,0 @@ -from pdb import set_trace as T -import numpy as np - -import time -import hashlib -from functools import partial - -import gymnasium as gym -from gymnasium.spaces import Box, Discrete, Dict, Tuple -from pettingzoo.utils.env import ParallelEnv - -import pufferlib -import pufferlib.emulation -import pufferlib.utils - - -HIGH = 100 -LOW = 0 - -def make_performance_env(delay=0, bandwidth=1): - return pufferlib.emulation.PettingZooPufferEnv( - env_creator=PerformanceEnv, - env_args=[delay, bandwidth], - ) - -class PerformanceEnv: - def __init__(self, delay=0, bandwith=1): - self.agents = [1] - self.possible_agents = [1] - self.done = False - - self.delay = delay - assert bandwith > 0 - self.bandwidth = bandwith - - def reset(self, seed=None): - return {1: self.observation_space(1).sample()}, {1: {}} - - def step(self, actions): - obs = {1: np.array([0], dtype=np.float32)} - rewards = {1: 1} - dones = {1: False} - truncateds = {1: False} - infos = {1: {}} - - # Busy wait so process does not swap on sleep - end = time.perf_counter() + self.delay - while time.perf_counter() < end: - pass - - return obs, rewards, dones, truncateds, infos - - def observation_space(self, agent): - return Box( - low=-2**20, high=2**20, - shape=(self.bandwidth,), dtype=np.float32 - ) - - def action_space(self, agent): - return Discrete(2) - - -### Other Mock environments and utilities -def _agent_str_to_int(agent): - return int(agent.split('_')[-1]) - - -def _sample_space(agent, tick, space, zero=False): - if isinstance(agent, str): - agent = float(agent.split('_')[-1]) - - if isinstance(space, Discrete): - if zero: - return 0 - return int((10*agent + tick) % space.n) - elif isinstance(space, Box): - if zero: - return np.zeros(space.shape, dtype=space.dtype) - - # Try to make a relatively unique data pattern - # without using RNG - nonce = 10*agent + tick - low = space.low - high = space.high - sample = low + np.arange(low.size).reshape(space.shape) + nonce - sample = (sample % high).astype(space.dtype) - return sample - elif isinstance(space, Tuple): - return tuple(_sample_space(agent, tick, s, zero) for s in space.spaces) - elif isinstance(space, Dict): - return {k: _sample_space(agent, tick, v, zero) for k, v in space.spaces.items()} - else: - raise ValueError(f"Invalid space type: {type(space)}") - -class GymnasiumTestEnv(gym.Env): - def __init__(self, observation_space, action_space): - self.observation_space = observation_space - self.action_space = action_space - - def reset(self, seed=None): - self.tick = 0 - self.rng = pufferlib.utils.RandomState(seed) - - ob = _sample_space('agent_1', self.tick, self.observation_space) - return ob, {} - - def step(self, actions): - reward = self.tick - done = self.tick < 10 - self.tick += 1 - - ob = _sample_space('agent_1', self.tick, self.observation_space) - return ob, reward, done, False, {'dead': done} - - -def make_mock_singleagent_env(observation_space, action_space): - return partial( - GymnasiumTestEnv, - observation_space=observation_space, - action_space=action_space, - ) - -class TestEnv(ParallelEnv): - def __init__(self, observation_space, action_space, initial_agents, - max_agents, spawn_per_tick, death_per_tick): - self.single_observation_space = observation_space - self.single_action_space = action_space - self.initial_agents = initial_agents - self.max_agents = max_agents - self.spawn_per_tick = spawn_per_tick - self.death_per_tick = death_per_tick - - self.possible_agents = [f'agent_{i+1}' for i in range(max_agents)] - self.agents = [] - - def reset(self, seed=None): - self.tick = 0 - self.agents = self.possible_agents[:self.initial_agents] - - obs = {a: _sample_space(a, self.tick, self.single_observation_space) - for a in self.agents} - infos = {a: {} for a in self.agents} - return obs, infos - - def step(self, actions): - obs, rewards, dones, truncateds, infos = {}, {}, {}, {}, {} - self.tick += 1 - - dead = self.agents[:self.death_per_tick] - for kill in dead: - self.agents.remove(kill) - # TODO: Make pufferlib work without pad obs - # but still require rewards, dones, and optionally infos - obs[kill] = _sample_space(kill, self.tick, self.single_observation_space, zero=True) - rewards[kill] = -1 - dones[kill] = True - truncateds[kill] = False - infos[kill] = {'dead': True} - - # TODO: Fix this - assert self.spawn_per_tick == 0 - for spawn in range(self.spawn_per_tick): - # TODO: Make pufferlib check if an agent respawns on the - # Same tick as it dies (is this good or bad?) - spawn = self.rng.choice(self.possible_agents) - if spawn not in self.agents + dead: - self.agents.append(spawn) - - for agent in self.agents: - obs[agent] = _sample_space(agent, self.tick, self.single_observation_space) - rewards[agent] = 0.1 * _agent_str_to_int(agent) - dones[agent] = False - truncateds[agent] = False - infos[agent] = {'dead': False} - - return obs, rewards, dones, truncateds, infos - - def observation_space(self, agent) -> gym.Space: - return self.single_observation_space - - def action_space(self, agent) -> gym.Space: - return self.single_action_space - - def render(self, mode='human'): - pass - - def close(self): - pass - -def make_mock_multiagent_env( - observation_space, - action_space, - initial_agents, - max_agents, - spawn_per_tick, - death_per_tick, - homogeneous_spaces=True): - return partial( - TestEnv, - observation_space=observation_space, - action_space=action_space, - initial_agents=initial_agents, - max_agents=max_agents, - spawn_per_tick=spawn_per_tick, - death_per_tick=death_per_tick, - ) - - -MOCK_OBSERVATION_SPACES = [ - # Atari space - Box(low=0, high=255, shape=(4, 84, 84), dtype=np.uint8), - - # NetHack space - Dict({ - 'blstats': Box(-2147483648, 2147483647, (27,), 'int64'), - 'chars': Box(0, 255, (21, 79), 'uint8'), - 'colors': Box(0, 15, (21, 79), 'uint8'), - 'glyphs': Box(0, 5976, (21, 79), 'int16'), - 'inv_glyphs': Box(0, 5976, (55,), 'int16'), - 'inv_letters': Box(0, 127, (55,), 'uint8'), - 'inv_oclasses': Box(0, 18, (55,), 'uint8'), - 'inv_strs': Box(0, 255, (55, 80), 'uint8'), - 'message': Box(0, 255, (256,), 'uint8'), - 'screen_descriptions': Box(0, 127, (21, 79, 80), 'uint8'), - 'specials': Box(0, 255, (21, 79), 'uint8'), - 'tty_chars': Box(0, 255, (24, 80), 'uint8'), - 'tty_colors': Box(0, 31, (24, 80), 'int8'), - 'tty_cursor': Box(0, 255, (2,), 'uint8'), - }), - - # Neural MMO space - Dict({ - 'ActionTargets': Dict({ - 'Attack': Dict({ - 'Style': Box(0, 1, (3,), 'int8'), - 'Target': Box(0, 1, (100,), 'int8'), - }), - 'Buy': Dict({ - 'MarketItem': Box(0, 1, (1024,), 'int8'), - }), - 'Comm': Dict({ - 'Token': Box(0, 1, (50,), 'int8'), - }), - 'Destroy': Dict({ - 'InventoryItem': Box(0, 1, (12,), 'int8'), - }), - 'Give': Dict({ - 'InventoryItem': Box(0, 1, (12,), 'int8'), - 'Target': Box(0, 1, (100,), 'int8'), - }), - 'GiveGold': Dict({ - 'Price': Box(0, 1, (99,), 'int8'), - 'Target': Box(0, 1, (100,), 'int8'), - }), - 'Move': Dict({ - 'Direction': Box(0, 1, (5,), 'int8'), - }), - 'Sell': Dict({ - 'InventoryItem': Box(0, 1, (12,), 'int8'), - 'Price': Box(0, 1, (99,), 'int8'), - }), - 'Use': Dict({ - 'InventoryItem': Box(0, 1, (12,), 'int8'), - }) - }), - 'AgentId': Discrete(129), - 'CurrentTick': Discrete(1025), - 'Entity': Box(-32768, 32767, (100, 23), 'int16'), - 'Inventory': Box(-32768, 32767, (12, 16), 'int16'), - 'Market': Box(-32768, 32767, (1024, 16), 'int16'), - 'Task': Box(-32770.0, 32770.0, (1024,), 'float16'), - 'Tile': Box(-32768, 32767, (225, 3), 'int16'), - }), - - # Simple spaces - Discrete(5), - Box(low=LOW, high=HIGH, shape=(4,), dtype=np.float32), - - # Nested spaces - Dict({ - "foo": Box(low=LOW, high=HIGH, shape=(2,), dtype=np.float32), - "bar": Box(low=LOW, high=HIGH, shape=(2,), dtype=np.float32), - }), - Tuple((Discrete(3), Discrete(4))), - Tuple(( - Box(low=LOW, high=HIGH, shape=(2,), dtype=np.float32), - Discrete(3), - Dict({ - "baz": Box(low=LOW, high=HIGH, shape=(1,), dtype=np.float32), - "qux": Box(low=LOW, high=HIGH, shape=(1,), dtype=np.float32), - }), - )), - Dict({ - "foo": Tuple(( - Box(low=LOW, high=HIGH, shape=(2,), dtype=np.float32), - Discrete(3), - )), - "bar": Dict({ - "baz": Discrete(2), - "qux": Discrete(4), - }), - }), -] - - -MOCK_ACTION_SPACES = [ - # NetHack action space - Discrete(5), - - # Neural MMO action space - Dict({ - 'Attack': Dict({ - 'Style': Discrete(3), - 'Target': Discrete(100), - }), - 'Buy': Dict({ - 'MarketItem': Discrete(1024), - }), - 'Comm': Dict({ - 'Token': Discrete(50), - }), - 'Destroy': Dict({ - 'InventoryItem': Discrete(12), - }), - 'Give': Dict({ - 'InventoryItem': Discrete(12), - 'Target': Discrete(100), - }), - 'GiveGold': Dict({ - 'Price': Discrete(99), - 'Target': Discrete(100), - }), - 'Move': Dict({ - 'Direction': Discrete(5), - }), - 'Sell': Dict({ - 'InventoryItem': Discrete(12), - 'Price': Discrete(99), - }), - 'Use': Dict({ - 'InventoryItem': Discrete(12), - }) - }), - - # Nested spaces - Tuple((gym.spaces.Discrete(2), gym.spaces.Discrete(3))), - Dict({ - "foo": Discrete(4), - "bar": Discrete(2), - }), - Tuple(( - Discrete(4), - Dict({ - "baz": Discrete(2), - "qux": Discrete(2), - }), - )), - Dict({ - "foo": Tuple(( - Discrete(2), - Discrete(3), - )), - "bar": Dict({ - "baz": Discrete(2), - "qux": Discrete(4), - }), - }), -] - -MOCK_TEAMS = { - 'None': None, - 'single': { - 'team_1': ['agent_1'], - 'team_2': ['agent_2'], - 'team_3': ['agent_3'], - 'team_4': ['agent_4'], - 'team_5': ['agent_5'], - 'team_6': ['agent_6'], - 'team_7': ['agent_7'], - 'team_8': ['agent_8'], - 'team_9': ['agent_9'], - 'team_10': ['agent_10'], - 'team_11': ['agent_11'], - 'team_12': ['agent_12'], - 'team_13': ['agent_13'], - 'team_14': ['agent_14'], - 'team_15': ['agent_15'], - 'team_16': ['agent_16'], - }, - 'pairs': { - 'team_1': ['agent_1', 'agent_2'], - 'team_2': ['agent_3', 'agent_4'], - 'team_3': ['agent_5', 'agent_6'], - 'team_4': ['agent_7', 'agent_8'], - 'team_5': ['agent_9', 'agent_10'], - 'team_6': ['agent_11', 'agent_12'], - 'team_7': ['agent_13', 'agent_14'], - 'team_8': ['agent_15', 'agent_16'], - }, - 'mixed': { - 'team_1': ['agent_1', 'agent_2'], - 'team_2': ['agent_3', 'agent_4', 'agent_5', 'agent_6'], - 'team_3': ['agent_7', 'agent_8', 'agent_9'], - 'team_4': ['agent_10', 'agent_11', 'agent_12', 'agent_13', 'agent_14'], - 'team_5': ['agent_15', 'agent_16'], - }, -} - -MOCK_SINGLE_AGENT_ENVIRONMENTS = [] -MOCK_MULTI_AGENT_ENVIRONMENTS = [] -for obs_space in MOCK_OBSERVATION_SPACES: - for act_space in MOCK_ACTION_SPACES: - MOCK_SINGLE_AGENT_ENVIRONMENTS.append( - make_mock_singleagent_env( - observation_space=obs_space, - action_space=act_space, - ) - ) - - MOCK_MULTI_AGENT_ENVIRONMENTS.append( - make_mock_multiagent_env( - observation_space=obs_space, - action_space=act_space, - initial_agents=16, - max_agents=16, - spawn_per_tick=0, - death_per_tick=1, - ) - ) diff --git a/pufferlib/environments/test/torch.py b/pufferlib/environments/test/torch.py deleted file mode 100644 index 8b13194e9e..0000000000 --- a/pufferlib/environments/test/torch.py +++ /dev/null @@ -1 +0,0 @@ -from pufferlib.models import Default as Policy diff --git a/pufferlib/environments/trade_sim/__init__.py b/pufferlib/environments/trade_sim/__init__.py deleted file mode 100644 index eff86ef021..0000000000 --- a/pufferlib/environments/trade_sim/__init__.py +++ /dev/null @@ -1,12 +0,0 @@ -from .environment import env_creator, make - -try: - import torch -except ImportError: - pass -else: - from .torch import Policy - try: - from .torch import Recurrent - except: - Recurrent = None diff --git a/pufferlib/environments/trade_sim/environment.py b/pufferlib/environments/trade_sim/environment.py deleted file mode 100644 index 0c245c0b25..0000000000 --- a/pufferlib/environments/trade_sim/environment.py +++ /dev/null @@ -1,37 +0,0 @@ -import functools -import numpy as np - -import pufferlib - -from nof1.simulation.env import TradingEnvironment - -def env_creator(name='metta'): - return functools.partial(make, name) - -def make(name, config_path='../nof1-trading-sim/config/experiment_cv.yaml', render_mode='human', buf=None, seed=1): - '''Crafter creation function''' - from nof1.utils.config_manager import ConfigManager - from nof1.data_ingestion.historical_data_reader import HistoricalDataReader - - config_manager = ConfigManager(config_path) - config = config_manager.config - data_reader = HistoricalDataReader(config_manager) - states, prices, atrs, timestamps = data_reader.preprocess_data() - - # Create environment - env = TradingEnvironmentPuff(config_manager.config, states=states, prices=prices, atrs=atrs, timestamps=timestamps) - return pufferlib.emulation.GymnasiumPufferEnv(env, buf=buf) - -class TradingEnvironmentPuff(TradingEnvironment): - def reset(self): - obs, info = super().reset() - return obs.astype(np.float32), info - - def step(self, action): - obs, reward, terminated, truncated, info = super().step(action) - - if not terminated and not truncated: - info = {} - - return obs.astype(np.float32), reward, terminated, truncated, info - diff --git a/pufferlib/environments/trade_sim/torch.py b/pufferlib/environments/trade_sim/torch.py deleted file mode 100644 index be832843f7..0000000000 --- a/pufferlib/environments/trade_sim/torch.py +++ /dev/null @@ -1,4 +0,0 @@ -import pufferlib.models - -Policy = pufferlib.models.Default -Recurrent = pufferlib.models.LSTMWrapper diff --git a/pufferlib/environments/tribal_village/__init__.py b/pufferlib/environments/tribal_village/__init__.py deleted file mode 100644 index 36de06c454..0000000000 --- a/pufferlib/environments/tribal_village/__init__.py +++ /dev/null @@ -1,12 +0,0 @@ -from .environment import env_creator, make - -try: - import torch -except ImportError: - pass -else: - from .torch import Policy - try: - from .torch import Recurrent - except: - Recurrent = None \ No newline at end of file diff --git a/pufferlib/environments/tribal_village/environment.py b/pufferlib/environments/tribal_village/environment.py deleted file mode 100644 index 898b9876e1..0000000000 --- a/pufferlib/environments/tribal_village/environment.py +++ /dev/null @@ -1,53 +0,0 @@ -""" -Tribal Village Environment PufferLib Integration. - -Prefers a local tribal-village checkout for rapid iteration; falls back to the -installed package if not present. -""" - -import functools -import sys -from pathlib import Path -from typing import Any, Dict, Optional - -import pufferlib - - -def _import_tribal_village_env(): - """Prefer local tribal-village checkout if present; else import package.""" - repo_root = Path(__file__).resolve().parents[2] - fallback_dir = repo_root.parent / 'tribal-village' - if fallback_dir.exists(): - if str(fallback_dir) not in sys.path: - sys.path.insert(0, str(fallback_dir)) - try: - from tribal_village_env.environment import TribalVillageEnv # type: ignore - return TribalVillageEnv - except ImportError: - pass - - try: - from tribal_village_env.environment import TribalVillageEnv # type: ignore - return TribalVillageEnv - except ImportError as exc: - raise ImportError("""Failed to import tribal-village environment. Install the package with - pip install pufferlib[tribal-village] --no-build-isolation -or keep a checkout at ../tribal-village containing tribal_village_env/.""") from exc - - -def env_creator(name='tribal_village'): - return functools.partial(make, name=name) - - -def make(name='tribal_village', config=None, buf=None, **kwargs): - """Create a tribal village PufferLib environment instance.""" - TribalVillageEnv = _import_tribal_village_env() - - # Merge config with kwargs - if config is None: - config = {} - config = {**config, **kwargs} - - # Create the environment - env = TribalVillageEnv(config=config, buf=buf) - return env diff --git a/pufferlib/environments/tribal_village/torch.py b/pufferlib/environments/tribal_village/torch.py deleted file mode 100644 index 96c48d422d..0000000000 --- a/pufferlib/environments/tribal_village/torch.py +++ /dev/null @@ -1,63 +0,0 @@ -""" -Ultra-minimal PyTorch policy for Tribal Village - optimized for maximum SPS. -""" - -import torch -import torch.nn as nn -import pufferlib.pytorch -import pufferlib.models - - -class Policy(nn.Module): - """Ultra-minimal policy optimized for speed over sophistication.""" - - def __init__(self, env, hidden_size=64, **kwargs): - super().__init__() - self.hidden_size = hidden_size - self.is_continuous = False - - # Dense observation processing - 21 layers -> hidden_size - self.layer_proj = pufferlib.pytorch.layer_init(nn.Linear(21, hidden_size)) - - # Action heads - action_space = env.single_action_space - self.actor = nn.ModuleList([ - pufferlib.pytorch.layer_init(nn.Linear(hidden_size, n), std=0.01) - for n in action_space.nvec - ]) - - # Value head - self.value = pufferlib.pytorch.layer_init(nn.Linear(hidden_size, 1), std=1.0) - - def forward(self, observations: torch.Tensor, state=None): - hidden = self.encode_observations(observations, state) - actions, value = self.decode_actions(hidden) - return (actions, value), hidden - - def forward_eval(self, observations: torch.Tensor, state=None): - hidden = self.encode_observations(observations, state) - return self.decode_actions(hidden) - - def encode_observations(self, observations: torch.Tensor, state=None) -> torch.Tensor: - """Ultra-fast dense observation processing.""" - # observations shape: (batch, 21, 11, 11) - direct dense format from Nim - - # Global average pooling across spatial dimensions - features = observations.float().mean(dim=(2, 3)) # (batch, 21) - one value per layer - - # Use the pre-initialized layer projection - hidden = torch.relu(self.layer_proj(features)) # (batch, hidden_size) - return hidden - - def decode_actions(self, hidden: torch.Tensor): - """Simple action decoding.""" - logits = [head(hidden) for head in self.actor] - values = self.value(hidden) - return logits, values - - -class Recurrent(pufferlib.models.LSTMWrapper): - """Minimal LSTM wrapper.""" - - def __init__(self, env, policy, input_size=64, hidden_size=64): - super().__init__(env, policy, input_size, hidden_size) \ No newline at end of file diff --git a/pufferlib/environments/vizdoom/__init__.py b/pufferlib/environments/vizdoom/__init__.py deleted file mode 100644 index 59cda9e7c2..0000000000 --- a/pufferlib/environments/vizdoom/__init__.py +++ /dev/null @@ -1,12 +0,0 @@ -from .environment import env_creator - -try: - import torch -except ImportError: - pass -else: - from .torch import Policy - try: - from .torch import Recurrent - except: - Recurrent = None diff --git a/pufferlib/environments/vizdoom/environment.py b/pufferlib/environments/vizdoom/environment.py deleted file mode 100644 index d98a263f90..0000000000 --- a/pufferlib/environments/vizdoom/environment.py +++ /dev/null @@ -1,69 +0,0 @@ -from pdb import set_trace as T -import numpy as np -import functools - -import gymnasium as gym - -import pufferlib -import pufferlib.emulation -import pufferlib.environments -import pufferlib.utils -import pufferlib.postprocess - - -def env_creator(name='doom'): - return functools.partial(make, name) - -def make(name, framestack=1, render_mode='rgb_array', buf=None): - '''Atari creation function with default CleanRL preprocessing based on Stable Baselines3 wrappers''' - if name == 'doom': - name = 'VizdoomHealthGatheringSupreme-v0' - - #pufferlib.environments.try_import('vizdoom', 'gymnasium_wrapper') - from stable_baselines3.common.atari_wrappers import ( - ClipRewardEnv, - EpisodicLifeEnv, - FireResetEnv, - MaxAndSkipEnv, - NoopResetEnv, - ) - # Make does not work without this imported - # TODO: Fix try_import - from vizdoom import gymnasium_wrapper - with pufferlib.utils.Suppress(): - env = gym.make(name, render_mode=render_mode) - - env = DoomWrapper(env) # Don't use standard postprocessor - - #env = gym.wrappers.RecordEpisodeStatistics(env) - #env = NoopResetEnv(env, noop_max=30) - #env = MaxAndSkipEnv(env, skip=4) - #env = EpisodicLifeEnv(env) - #if "FIRE" in env.unwrapped.get_action_meanings(): - # env = FireResetEnv(env) - #env = ClipRewardEnv(env) - #env = gym.wrappers.GrayScaleObservation(env) - #env = gym.wrappers.FrameStack(env, framestack) - return pufferlib.emulation.GymnasiumPufferEnv(env=env, buf=buf) - -class DoomWrapper(gym.Wrapper): - '''Gymnasium env does not expose proper options for screen scale and - render format. This is slow. So we do it ourselves. Not it is fast. Yay!''' - def __init__(self, env): - super().__init__(env.unwrapped) - if env.observation_space['screen'].shape[0] != 120: - raise ValueError('Wrong screen resolution. Doom does not provide ' - 'a way to change this. You must edit scenarios/.cfg' - 'This is inside your local ViZDoom installation. Likely in python system packages' - 'Set screen resolution to RES_160X120 and screen format to GRAY8') - - self.observation_space = gym.spaces.Box( - low=0, high=255, shape=(60, 80, 1), dtype=np.uint8) - - def reset(self, seed=None, options=None): - obs, info = self.env.reset(seed=seed, options=options) - return obs['screen'][::2, ::2], {} - - def step(self, action): - obs, reward, terminal, truncated, info = self.env.step(action) - return obs['screen'][::2, ::2], reward, terminal, truncated, info diff --git a/pufferlib/environments/vizdoom/torch.py b/pufferlib/environments/vizdoom/torch.py deleted file mode 100644 index 4fd6964a5f..0000000000 --- a/pufferlib/environments/vizdoom/torch.py +++ /dev/null @@ -1,19 +0,0 @@ -import pufferlib.models - - -class Recurrent(pufferlib.models.LSTMWrapper): - def __init__(self, env, policy, input_size=512, hidden_size=512, num_layers=1): - super().__init__(env, policy, input_size, hidden_size, num_layers) - -class Policy(pufferlib.models.Convolutional): - def __init__(self, env, input_size=512, hidden_size=512, output_size=512, - framestack=1, flat_size=64*4*6): - super().__init__( - env=env, - input_size=input_size, - hidden_size=hidden_size, - output_size=output_size, - framestack=framestack, - flat_size=flat_size, - channels_last=True - ) diff --git a/pufferlib/extensions/cuda/pufferlib.cu b/pufferlib/extensions/cuda/pufferlib.cu deleted file mode 100644 index 9426a7e5e1..0000000000 --- a/pufferlib/extensions/cuda/pufferlib.cu +++ /dev/null @@ -1,88 +0,0 @@ -#include -#include -#include - -namespace pufferlib { - -__host__ __device__ void puff_advantage_row_cuda(float* values, float* rewards, float* dones, - float* importance, float* advantages, float gamma, float lambda, - float rho_clip, float c_clip, int horizon) { - float lastpufferlam = 0; - for (int t = horizon-2; t >= 0; t--) { - int t_next = t + 1; - float nextnonterminal = 1.0 - dones[t_next]; - float rho_t = fminf(importance[t], rho_clip); - float c_t = fminf(importance[t], c_clip); - float delta = rho_t*(rewards[t_next] + gamma*values[t_next]*nextnonterminal - values[t]); - lastpufferlam = delta + gamma*lambda*c_t*lastpufferlam*nextnonterminal; - advantages[t] = lastpufferlam; - } -} - -void vtrace_check_cuda(torch::Tensor values, torch::Tensor rewards, - torch::Tensor dones, torch::Tensor importance, torch::Tensor advantages, - int num_steps, int horizon) { - - // Validate input tensors - torch::Device device = values.device(); - for (const torch::Tensor& t : {values, rewards, dones, importance, advantages}) { - TORCH_CHECK(t.dim() == 2, "Tensor must be 2D"); - TORCH_CHECK(t.device() == device, "All tensors must be on same device"); - TORCH_CHECK(t.size(0) == num_steps, "First dimension must match num_steps"); - TORCH_CHECK(t.size(1) == horizon, "Second dimension must match horizon"); - TORCH_CHECK(t.dtype() == torch::kFloat32, "All tensors must be float32"); - if (!t.is_contiguous()) { - t.contiguous(); - } - } -} - - // [num_steps, horizon] -__global__ void puff_advantage_kernel(float* values, float* rewards, - float* dones, float* importance, float* advantages, float gamma, - float lambda, float rho_clip, float c_clip, int num_steps, int horizon) { - int row = blockIdx.x*blockDim.x + threadIdx.x; - if (row >= num_steps) { - return; - } - int offset = row*horizon; - puff_advantage_row_cuda(values + offset, rewards + offset, dones + offset, - importance + offset, advantages + offset, gamma, lambda, rho_clip, c_clip, horizon); -} - -void compute_puff_advantage_cuda(torch::Tensor values, torch::Tensor rewards, - torch::Tensor dones, torch::Tensor importance, torch::Tensor advantages, - double gamma, double lambda, double rho_clip, double c_clip) { - int num_steps = values.size(0); - int horizon = values.size(1); - vtrace_check_cuda(values, rewards, dones, importance, advantages, num_steps, horizon); - TORCH_CHECK(values.is_cuda(), "All tensors must be on GPU"); - - int threads_per_block = 256; - int blocks = (num_steps + threads_per_block - 1) / threads_per_block; - - puff_advantage_kernel<<>>( - values.data_ptr(), - rewards.data_ptr(), - dones.data_ptr(), - importance.data_ptr(), - advantages.data_ptr(), - gamma, - lambda, - rho_clip, - c_clip, - num_steps, - horizon - ); - - cudaError_t err = cudaGetLastError(); - if (err != cudaSuccess) { - throw std::runtime_error(cudaGetErrorString(err)); - } -} - -TORCH_LIBRARY_IMPL(pufferlib, CUDA, m) { - m.impl("compute_puff_advantage", &compute_puff_advantage_cuda); -} - -} diff --git a/pufferlib/extensions/extensions.pyx b/pufferlib/extensions/extensions.pyx deleted file mode 100644 index 7181eff23d..0000000000 --- a/pufferlib/extensions/extensions.pyx +++ /dev/null @@ -1,49 +0,0 @@ -# distutils: define_macros=NPY_NO_DEPRECATED_API=NPY_1_7_API_VERSION -# cython: language_level=3 -# cython: boundscheck=False -# cython: initializedcheck=False -# cython: wraparound=False -# cython: nonecheck=False - -'''Cythonized implementations of PufferLib's emulation functions - -emulate is about 2x faster than Python. Nativize is only slightly faster. -''' - -import numpy as np -cimport numpy as cnp - -from pufferlib.spaces import Tuple, Dict, Discrete - - -def emulate(cnp.ndarray np_struct, object sample): - cdef str k - cdef int i - - if isinstance(sample, dict): - for k, v in sample.items(): - emulate(np_struct[k], v) - elif isinstance(sample, tuple): - for i, v in enumerate(sample): - emulate(np_struct[f'f{i}'], v) - else: - np_struct[()] = sample - -cdef object _nativize(np_struct, object space): - cdef str k - cdef int i - - if isinstance(space, Discrete): - return np_struct.item() - elif isinstance(space, Tuple): - return tuple(_nativize(np_struct[f'f{i}'], elem) - for i, elem in enumerate(space)) - elif isinstance(space, Dict): - return {k: _nativize(np_struct[k], value) - for k, value in space.items()} - else: - return np_struct - -def nativize(arr, object space, cnp.dtype struct_dtype): - np_struct = np.asarray(arr).view(struct_dtype)[0] - return _nativize(np_struct, space) diff --git a/pufferlib/extensions/pufferlib.cpp b/pufferlib/extensions/pufferlib.cpp deleted file mode 100644 index a20d58bc27..0000000000 --- a/pufferlib/extensions/pufferlib.cpp +++ /dev/null @@ -1,95 +0,0 @@ -#include -#include -#include -#include -#include - -extern "C" { - /* Creates a dummy empty _C module that can be imported from Python. - The import from Python will load the .so consisting of this file - in this extension, so that the TORCH_LIBRARY static initializers - below are run. */ - PyObject* PyInit__C(void) - { - static struct PyModuleDef module_def = { - PyModuleDef_HEAD_INIT, - "_C", /* name of module */ - NULL, /* module documentation, may be NULL */ - -1, /* size of per-interpreter state of the module, - or -1 if the module keeps state in global variables. */ - NULL, /* methods */ - }; - return PyModule_Create(&module_def); - } -} - -namespace pufferlib { - -void puff_advantage_row(float* values, float* rewards, float* dones, - float* importance, float* advantages, float gamma, float lambda, - float rho_clip, float c_clip, int horizon) { - float lastpufferlam = 0; - for (int t = horizon-2; t >= 0; t--) { - int t_next = t + 1; - float nextnonterminal = 1.0 - dones[t_next]; - float rho_t = fminf(importance[t], rho_clip); - float c_t = fminf(importance[t], c_clip); - float delta = rho_t*(rewards[t_next] + gamma*values[t_next]*nextnonterminal - values[t]); - lastpufferlam = delta + gamma*lambda*c_t*lastpufferlam*nextnonterminal; - advantages[t] = lastpufferlam; - } -} - -void vtrace_check(torch::Tensor values, torch::Tensor rewards, - torch::Tensor dones, torch::Tensor importance, torch::Tensor advantages, - int num_steps, int horizon) { - - // Validate input tensors - torch::Device device = values.device(); - for (const torch::Tensor& t : {values, rewards, dones, importance, advantages}) { - TORCH_CHECK(t.dim() == 2, "Tensor must be 2D"); - TORCH_CHECK(t.device() == device, "All tensors must be on same device"); - TORCH_CHECK(t.size(0) == num_steps, "First dimension must match num_steps"); - TORCH_CHECK(t.size(1) == horizon, "Second dimension must match horizon"); - TORCH_CHECK(t.dtype() == torch::kFloat32, "All tensors must be float32"); - if (!t.is_contiguous()) { - t.contiguous(); - } - } -} - - -// [num_steps, horizon] -void puff_advantage(float* values, float* rewards, float* dones, float* importance, - float* advantages, float gamma, float lambda, float rho_clip, float c_clip, - int num_steps, const int horizon){ - for (int offset = 0; offset < num_steps*horizon; offset+=horizon) { - puff_advantage_row(values + offset, rewards + offset, - dones + offset, importance + offset, advantages + offset, - gamma, lambda, rho_clip, c_clip, horizon - ); - } -} - - -void compute_puff_advantage_cpu(torch::Tensor values, torch::Tensor rewards, - torch::Tensor dones, torch::Tensor importance, torch::Tensor advantages, - double gamma, double lambda, double rho_clip, double c_clip) { - int num_steps = values.size(0); - int horizon = values.size(1); - vtrace_check(values, rewards, dones, importance, advantages, num_steps, horizon); - puff_advantage(values.data_ptr(), rewards.data_ptr(), - dones.data_ptr(), importance.data_ptr(), advantages.data_ptr(), - gamma, lambda, rho_clip, c_clip, num_steps, horizon - ); -} - -TORCH_LIBRARY(pufferlib, m) { - m.def("compute_puff_advantage(Tensor(a!) values, Tensor(b!) rewards, Tensor(c!) dones, Tensor(d!) importance, Tensor(e!) advantages, float gamma, float lambda, float rho_clip, float c_clip) -> ()"); - } - -TORCH_LIBRARY_IMPL(pufferlib, CPU, m) { - m.impl("compute_puff_advantage", &compute_puff_advantage_cpu); -} - -} diff --git a/pufferlib/extensions/puffernet.pyx b/pufferlib/extensions/puffernet.pyx deleted file mode 100644 index feb03a8689..0000000000 --- a/pufferlib/extensions/puffernet.pyx +++ /dev/null @@ -1,98 +0,0 @@ -# distutils: define_macros=NPY_NO_DEPRECATED_API=NPY_1_7_API_VERSION -# cython: language_level=3 -# cython: boundscheck=False -# cython: initializedcheck=False -# cython: wraparound=False -# cython: cdivision=True -# cython: nonecheck=False -# cython: profile=False - -from libc.stdlib cimport rand, RAND_MAX -from libc.math cimport sqrtf -from cpython.list cimport PyList_GET_ITEM -cimport cython -cimport numpy as cnp -import numpy as np - -cdef extern from "puffernet.h": - void _linear(float* input, float* weights, float* bias, float* output, - int batch_size, int input_dim, int output_dim) - void _relu(float* input, float* output,int size) - void _gelu(float* input, float* output, int size) - float _sigmoid(float x) - void _conv2d(float* input, float* weights, float* bias, - float* output, int batch_size, int in_width, int in_height, - int in_channels, int out_channels, int kernel_size, int stride) - void _conv3d(float* input, float* weights, float* bias, - float* output, int batch_size, int in_width, int in_height, int in_depth, - int in_channels, int out_channels, int kernel_size, int stride) - void _embedding(int* input, float* weights, float* output, - int batch_size, int num_embeddings, int embedding_dim) - void _lstm(float* input, float* state_h, float* state_c, float* weights_input, - float* weights_state, float* bias_input, float*bias_state, - float *buffer, int batch_size, int input_size, int hidden_size) - void _layernorm(float* input, float* weights, float* bias, float* output, - int batch_size, int input_size) - void _one_hot(int* input, int* output, int batch_size, - int input_size, int num_classes) - void _cat_dim1(float* x, float* y, float* output, - int batch_size, int x_size, int y_size) - void _argmax_multidiscrete(float* input, int* output, - int batch_size, int logit_sizes[], int num_actions) - -def puf_linear_layer(cnp.ndarray input, cnp.ndarray weights, cnp.ndarray bias, cnp.ndarray output, - int batch_size, int input_dim, int output_dim): - _linear( input.data, weights.data, bias.data, - output.data, batch_size, input_dim, output_dim) - -def puf_relu(cnp.ndarray input, cnp.ndarray output, int size): - _relu( input.data, output.data, size) - -def puf_gelu(cnp.ndarray input, cnp.ndarray output, int size): - _gelu( input.data, output.data, size) - -def puf_sigmoid(float x): - return _sigmoid(x) - -def puf_convolution_layer(cnp.ndarray input, cnp.ndarray weights, cnp.ndarray bias, - cnp.ndarray output, int batch_size, int in_width, int in_height, - int in_channels, int out_channels, int kernel_size, int stride): - _conv2d( input.data, weights.data, bias.data, - output.data, batch_size, in_width, in_height, in_channels, out_channels, - kernel_size, stride) - -def puf_convolution_3d_layer(cnp.ndarray input, cnp.ndarray weights, cnp.ndarray bias, - cnp.ndarray output, int batch_size, int in_width, int in_height, int in_depth, - int in_channels, int out_channels, int kernel_size, int stride): - _conv3d( input.data, weights.data, bias.data, - output.data, batch_size, in_width, in_height, in_depth, in_channels, out_channels, - kernel_size, stride) - -def puf_lstm(cnp.ndarray input, cnp.ndarray state_h, cnp.ndarray state_c, cnp.ndarray weights_input, - cnp.ndarray weights_state, cnp.ndarray bias_input, cnp.ndarray bias_state, - cnp.ndarray buffer, int batch_size, int input_size, int hidden_size): - _lstm( input.data, state_h.data, state_c.data, - weights_input.data, weights_state.data, bias_input.data, - bias_state.data, buffer.data, batch_size, input_size, hidden_size) - -def puf_embedding(cnp.ndarray input, cnp.ndarray weights, cnp.ndarray output, - int batch_size, int num_embeddings, int embedding_dim): - _embedding( input.data, weights.data, output.data, - batch_size, num_embeddings, embedding_dim) - -def puf_layernorm(cnp.ndarray input, cnp.ndarray weights, cnp.ndarray bias, - cnp.ndarray output, int batch_size, int input_size): - _layernorm( input.data, weights.data, bias.data, - output.data, batch_size, input_size) - -def puf_one_hot(cnp.ndarray input, cnp.ndarray output, int batch_size, int input_size, int num_classes): - _one_hot( input.data, output.data, batch_size, input_size, num_classes) - -def puf_cat_dim1(cnp.ndarray x, cnp.ndarray y, cnp.ndarray output, int batch_size, int x_size, int y_size): - _cat_dim1( x.data, y.data, output.data, batch_size, x_size, y_size) - -def puf_argmax_multidiscrete(cnp.ndarray input, cnp.ndarray output, - int batch_size, cnp.ndarray logit_sizes, int num_actions): - _argmax_multidiscrete( input.data, output.data, - batch_size, logit_sizes.data, num_actions) - diff --git a/pufferlib/models.py b/pufferlib/models.py index fa43d7071c..dc06eb5fbf 100644 --- a/pufferlib/models.py +++ b/pufferlib/models.py @@ -1,310 +1,264 @@ -from pdb import set_trace as T import numpy as np import torch import torch.nn as nn +import torch.nn.functional as F -import pufferlib.emulation -import pufferlib.pytorch -import pufferlib.spaces +class Policy(nn.Module): + def __init__(self, encoder, decoder, network): + super().__init__() + self.encoder = encoder + self.decoder = decoder + self.network = network + def initial_state(self, batch_size, device): + return self.network.initial_state(batch_size, device) -class Default(nn.Module): - '''Default PyTorch policy. Flattens obs and applies a linear layer. + def forward_eval(self, x, state): + h = self.encoder(x) + h, state = self.network.forward_eval(h, state) + logits, values = self.decoder(h) + return logits, values, state - PufferLib is not a framework. It does not enforce a base class. - You can use any PyTorch policy that returns actions and values. - We structure our forward methods as encode_observations and decode_actions - to make it easier to wrap policies with LSTMs. You can do that and use - our LSTM wrapper or implement your own. To port an existing policy - for use with our LSTM wrapper, simply put everything from forward() before - the recurrent cell into encode_observations and put everything after - into decode_actions. - ''' - def __init__(self, env, hidden_size=128): + def forward(self, x): + B, TT = x.shape[:2] + h = self.encoder(x.reshape(B*TT, *x.shape[2:])) + h = self.network.forward_train(h.reshape(B, TT, -1)) + logits, values = self.decoder(h.reshape(B*TT, -1)) + return logits, values.reshape(B, TT) + +class DefaultEncoder(nn.Module): + def __init__(self, obs_size, hidden_size=128): super().__init__() - self.hidden_size = hidden_size - self.is_multidiscrete = isinstance(env.single_action_space, - pufferlib.spaces.MultiDiscrete) - self.is_continuous = isinstance(env.single_action_space, - pufferlib.spaces.Box) - try: - self.is_dict_obs = isinstance(env.env.observation_space, pufferlib.spaces.Dict) - except: - self.is_dict_obs = isinstance(env.observation_space, pufferlib.spaces.Dict) - - if self.is_dict_obs: - self.dtype = pufferlib.pytorch.nativize_dtype(env.emulated) - input_size = int(sum(np.prod(v.shape) for v in env.env.observation_space.values())) - self.encoder = nn.Linear(input_size, self.hidden_size) - else: - num_obs = np.prod(env.single_observation_space.shape) - self.encoder = torch.nn.Sequential( - pufferlib.pytorch.layer_init(nn.Linear(num_obs, hidden_size)), - nn.GELU(), - ) - - if self.is_multidiscrete: - self.action_nvec = tuple(env.single_action_space.nvec) - num_atns = sum(self.action_nvec) - self.decoder = pufferlib.pytorch.layer_init( - nn.Linear(hidden_size, num_atns), std=0.01) - elif not self.is_continuous: - num_atns = env.single_action_space.n - self.decoder = pufferlib.pytorch.layer_init( - nn.Linear(hidden_size, num_atns), std=0.01) - else: - self.decoder_mean = pufferlib.pytorch.layer_init( - nn.Linear(hidden_size, env.single_action_space.shape[0]), std=0.01) - self.decoder_logstd = nn.Parameter(torch.zeros( - 1, env.single_action_space.shape[0])) + self.encoder = nn.Linear(obs_size, hidden_size) - self.value = pufferlib.pytorch.layer_init( - nn.Linear(hidden_size, 1), std=1) + def forward(self, observations): + return self.encoder(observations.view(observations.shape[0], -1).float()) - def forward_eval(self, observations, state=None): - hidden = self.encode_observations(observations, state=state) - logits, values = self.decode_actions(hidden) - return logits, values +class DefaultDecoder(nn.Module): + def __init__(self, nvec, hidden_size=128): + super().__init__() + self.nvec = tuple(nvec) + self.is_continuous = sum(nvec) == len(nvec) - def forward(self, observations, state=None): - return self.forward_eval(observations, state) - - def encode_observations(self, observations, state=None): - '''Encodes a batch of observations into hidden states. Assumes - no time dimension (handled by LSTM wrappers).''' - batch_size = observations.shape[0] - if self.is_dict_obs: - observations = pufferlib.pytorch.nativize_tensor(observations, self.dtype) - observations = torch.cat([v.view(batch_size, -1) for v in observations.values()], dim=1) - else: - observations = observations.view(batch_size, -1) - return self.encoder(observations.float()) - - def decode_actions(self, hidden): - '''Decodes a batch of hidden states into (multi)discrete actions. - Assumes no time dimension (handled by LSTM wrappers).''' - if self.is_multidiscrete: - logits = self.decoder(hidden).split(self.action_nvec, dim=1) - elif self.is_continuous: + if self.is_continuous: + num_atns = len(nvec) + self.decoder_mean = nn.Linear(hidden_size, num_atns) + self.decoder_logstd = nn.Parameter(torch.zeros(1, num_atns)) + else: + self.decoder = nn.Linear(hidden_size, int(np.sum(nvec))) + + self.value_function = nn.Linear(hidden_size, 1) + + def forward(self, hidden): + if self.is_continuous: mean = self.decoder_mean(hidden) logstd = self.decoder_logstd.expand_as(mean) - std = torch.exp(logstd) - logits = torch.distributions.Normal(mean, std) + logits = torch.distributions.Normal(mean, torch.exp(logstd)) else: logits = self.decoder(hidden) + if len(self.nvec) > 1: + logits = logits.split(self.nvec, dim=1) - values = self.value(hidden) + values = self.value_function(hidden) return logits, values -class LSTMWrapper(nn.Module): - def __init__(self, env, policy, input_size=128, hidden_size=128): - '''Wraps your policy with an LSTM without letting you shoot yourself in the - foot with bad transpose and shape operations. This saves much pain. - Requires that your policy define encode_observations and decode_actions. - See the Default policy for an example.''' +class MLP(nn.Module): + def __init__(self, hidden_size, num_layers=1, **kwargs): super().__init__() - self.obs_shape = env.single_observation_space.shape + layers = [] + for _ in range(num_layers): + layers += [nn.Linear(hidden_size, hidden_size), nn.GELU()] + self.net = nn.Sequential(*layers) - self.policy = policy - self.input_size = input_size - self.hidden_size = hidden_size - self.is_continuous = self.policy.is_continuous - - for name, param in self.named_parameters(): - if 'layer_norm' in name: - continue - if "bias" in name: - nn.init.constant_(param, 0) - elif "weight" in name and param.ndim >= 2: - nn.init.orthogonal_(param, 1.0) - - self.lstm = nn.LSTM(input_size, hidden_size) - - self.cell = torch.nn.LSTMCell(input_size, hidden_size) - self.cell.weight_ih = self.lstm.weight_ih_l0 - self.cell.weight_hh = self.lstm.weight_hh_l0 - self.cell.bias_ih = self.lstm.bias_ih_l0 - self.cell.bias_hh = self.lstm.bias_hh_l0 - - #self.pre_layernorm = nn.LayerNorm(hidden_size) - #self.post_layernorm = nn.LayerNorm(hidden_size) - - def forward_eval(self, observations, state): - '''Forward function for inference. 3x faster than using LSTM directly''' - hidden = self.policy.encode_observations(observations, state=state) - h = state['lstm_h'] - c = state['lstm_c'] - - # TODO: Don't break compile - if h is not None: - assert h.shape[0] == c.shape[0] == observations.shape[0], 'LSTM state must be (h, c)' - lstm_state = (h, c) - else: - lstm_state = None - - #hidden = self.pre_layernorm(hidden) - hidden, c = self.cell(hidden, lstm_state) - #hidden = self.post_layernorm(hidden) - state['hidden'] = hidden - state['lstm_h'] = hidden - state['lstm_c'] = c - logits, values = self.policy.decode_actions(hidden) - return logits, values + def initial_state(self, batch_size, device): + return () - def forward(self, observations, state): - '''Forward function for training. Uses LSTM for fast time-batching''' - x = observations - lstm_h = state['lstm_h'] - lstm_c = state['lstm_c'] - - x_shape, space_shape = x.shape, self.obs_shape - x_n, space_n = len(x_shape), len(space_shape) - if x_shape[-space_n:] != space_shape: - raise ValueError('Invalid input tensor shape', x.shape) - - if x_n == space_n + 1: - B, TT = x_shape[0], 1 - elif x_n == space_n + 2: - B, TT = x_shape[:2] - else: - raise ValueError('Invalid input tensor shape', x.shape) + def forward_eval(self, h, state): + return self.net(h), state - if lstm_h is not None: - assert lstm_h.shape[1] == lstm_c.shape[1] == B, 'LSTM state must be (h, c)' - lstm_state = (lstm_h, lstm_c) - else: - lstm_state = None - - x = x.reshape(B*TT, *space_shape) - hidden = self.policy.encode_observations(x, state) - assert hidden.shape == (B*TT, self.input_size) - - hidden = hidden.reshape(B, TT, self.input_size) - - hidden = hidden.transpose(0, 1) - #hidden = self.pre_layernorm(hidden) - hidden, (lstm_h, lstm_c) = self.lstm.forward(hidden, lstm_state) - hidden = hidden.float() - - #hidden = self.post_layernorm(hidden) - hidden = hidden.transpose(0, 1) - - flat_hidden = hidden.reshape(B*TT, self.hidden_size) - logits, values = self.policy.decode_actions(flat_hidden) - values = values.reshape(B, TT) - #state.batch_logits = logits.reshape(B, TT, -1) - state['hidden'] = hidden - state['lstm_h'] = lstm_h.detach() - state['lstm_c'] = lstm_c.detach() - return logits, values + def forward_train(self, h): + return self.net(h) -class Convolutional(nn.Module): - def __init__(self, env, *args, framestack, flat_size, - input_size=512, hidden_size=512, output_size=512, +class MinGRU(nn.Module): + # https://arxiv.org/abs/2410.01201v1 + def __init__(self, hidden_size, num_layers=1, **kwargs): + super().__init__() + self.hidden_size = hidden_size + self.num_layers = num_layers + self.layers = nn.ModuleList([ + nn.Linear(hidden_size, 3 * hidden_size, bias=False) for _ in range(num_layers) + ]) + + def _g(self, x): + return torch.where(x >= 0, x + 0.5, x.sigmoid()) + + def _log_g(self, x): + return torch.where(x >= 0, (F.relu(x) + 0.5).log(), -F.softplus(-x)) + + def _highway(self, x, out, proj): + g = proj.sigmoid() + return g * out + (1.0 - g) * x + + def _heinsen_scan(self, log_coeffs, log_values): + a_star = log_coeffs.cumsum(dim=1) + return (a_star + (log_values - a_star).logcumsumexp(dim=1)).exp() + + def initial_state(self, batch_size, device): + return (torch.zeros(self.num_layers, batch_size, self.hidden_size, device=device),) + + def forward_eval(self, h, state): + state = state[0] + assert state.shape[1] == h.shape[0] + h = h.unsqueeze(1) + state_out = [] + for i in range(self.num_layers): + hidden, gate, proj = self.layers[i](h).chunk(3, dim=-1) + out = torch.lerp(state[i:i+1].transpose(0, 1), self._g(hidden), gate.sigmoid()) + h = self._highway(h, out, proj) + state_out.append(out[:, -1:]) + return h.squeeze(1), (torch.stack(state_out, 0).squeeze(2),) + + def forward_train(self, h): + T = h.shape[1] + for i in range(self.num_layers): + hidden, gate, proj = self.layers[i](h).chunk(3, dim=-1) + log_coeffs = -F.softplus(gate) + log_values = -F.softplus(-gate) + self._log_g(hidden) + out = self._heinsen_scan(log_coeffs, log_values)[:, -T:] + h = self._highway(h, out, proj) + return h + +class LSTM(nn.Module): + def __init__(self, hidden_size, num_layers=1, **kwargs): + super().__init__() + self.hidden_size = hidden_size + self.num_layers = num_layers + + self.lstm = nn.LSTM(hidden_size, hidden_size, num_layers=num_layers) + self.cell = nn.ModuleList([torch.nn.LSTMCell(hidden_size, hidden_size) for _ in range(num_layers)]) + + for i in range(num_layers): + cell = self.cell[i] + w_ih = getattr(self.lstm, f'weight_ih_l{i}') + w_hh = getattr(self.lstm, f'weight_hh_l{i}') + b_ih = getattr(self.lstm, f'bias_ih_l{i}') + b_hh = getattr(self.lstm, f'bias_hh_l{i}') + nn.init.orthogonal_(w_ih, 1.0) + nn.init.orthogonal_(w_hh, 1.0) + b_ih.data.zero_() + b_hh.data.zero_() + cell.weight_ih = w_ih + cell.weight_hh = w_hh + cell.bias_ih = b_ih + cell.bias_hh = b_hh + + def initial_state(self, batch_size, device): + h = torch.zeros(self.num_layers, batch_size, self.hidden_size, device=device) + c = torch.zeros(self.num_layers, batch_size, self.hidden_size, device=device) + return h, c + + def forward_eval(self, h, state): + assert state[0].shape[1] == state[1].shape[1] == h.shape[0] + lstm_h, lstm_c = state + for i in range(self.num_layers): + h, c = self.cell[i](h, (lstm_h[i], lstm_c[i])) + lstm_h[i] = h + lstm_c[i] = c + return h, (lstm_h, lstm_c) + + def forward_train(self, h): + # h: [B, T, H] + h = h.transpose(0, 1) + h, _ = self.lstm(h) + return h.transpose(0, 1) + +class GRU(nn.Module): + def __init__(self, hidden_size, num_layers=1, **kwargs): + super().__init__() + self.hidden_size = hidden_size + self.num_layers = num_layers + + self.gru = nn.GRU(hidden_size, hidden_size, num_layers=num_layers) + self.cell = nn.ModuleList([torch.nn.GRUCell(hidden_size, hidden_size) for _ in range(num_layers)]) + self.norm = torch.nn.RMSNorm(hidden_size) + + for i in range(num_layers): + cell = self.cell[i] + w_ih = getattr(self.gru, f'weight_ih_l{i}') + w_hh = getattr(self.gru, f'weight_hh_l{i}') + b_ih = getattr(self.gru, f'bias_ih_l{i}') + b_hh = getattr(self.gru, f'bias_hh_l{i}') + nn.init.orthogonal_(w_ih, 1.0) + nn.init.orthogonal_(w_hh, 1.0) + b_ih.data.zero_() + b_hh.data.zero_() + cell.weight_ih = w_ih + cell.weight_hh = w_hh + cell.bias_ih = b_ih + cell.bias_hh = b_hh + + def initial_state(self, batch_size, device): + h = torch.zeros(self.num_layers, batch_size, self.hidden_size, device=device) + return (h,) + + def forward_eval(self, h, state): + assert state[0].shape[1] == h.shape[0] + state = state[0] + for i in range(self.num_layers): + h_in = h + h = self.cell[i](h, state[i]) + state[i] = h + h = h + h_in + h = self.norm(h) + return h, (state,) + + def forward_train(self, h): + # h: [B, T, H] + h = h.transpose(0, 1) + h_in = h + h, _ = self.gru(h) + h = h + h_in + h = self.norm(h) + return h.transpose(0, 1) + +class NatureEncoder(nn.Module): + '''NatureCNN encoder (Mnih et al. 2015). Returns [batch, hidden_size].''' + def __init__(self, env, hidden_size=512, framestack=1, flat_size=64*7*7, channels_last=False, downsample=1, **kwargs): - '''The CleanRL default NatureCNN policy used for Atari. - It's just a stack of three convolutions followed by a linear layer - - Takes framestack as a mandatory keyword argument. Suggested default is 1 frame - with LSTM or 4 frames without.''' super().__init__() self.channels_last = channels_last self.downsample = downsample - - #TODO: Remove these from required params - self.hidden_size = hidden_size - self.is_continuous = False - - self.network= nn.Sequential( - pufferlib.pytorch.layer_init(nn.Conv2d(framestack, 32, 8, stride=4)), + self.network = nn.Sequential( + nn.Conv2d(framestack, 32, 8, stride=4), nn.ReLU(), - pufferlib.pytorch.layer_init(nn.Conv2d(32, 64, 4, stride=2)), + nn.Conv2d(32, 64, 4, stride=2), nn.ReLU(), - pufferlib.pytorch.layer_init(nn.Conv2d(64, 64, 3, stride=1)), + nn.Conv2d(64, 64, 3, stride=1), nn.ReLU(), nn.Flatten(), - pufferlib.pytorch.layer_init(nn.Linear(flat_size, hidden_size)), + nn.Linear(flat_size, hidden_size), nn.ReLU(), ) - self.actor = pufferlib.pytorch.layer_init( - nn.Linear(hidden_size, env.single_action_space.n), std=0.01) - self.value_fn = pufferlib.pytorch.layer_init( - nn.Linear(output_size, 1), std=1) - - def forward(self, observations, state=None): - hidden = self.encode_observations(observations) - actions, value = self.decode_actions(hidden) - return actions, value - - def forward_train(self, observations, state=None): - return self.forward(observations, state) - def encode_observations(self, observations, state=None): + def forward(self, observations): if self.channels_last: observations = observations.permute(0, 3, 1, 2) if self.downsample > 1: observations = observations[:, :, ::self.downsample, ::self.downsample] return self.network(observations.float() / 255.0) - def decode_actions(self, flat_hidden): - action = self.actor(flat_hidden) - value = self.value_fn(flat_hidden) - return action, value - -class ProcgenResnet(nn.Module): - '''Procgen baseline from the AICrowd NeurIPS 2020 competition - Based on the ResNet architecture that was used in the Impala paper.''' - def __init__(self, env, cnn_width=16, mlp_width=256): - super().__init__() - h, w, c = env.single_observation_space.shape - shape = (c, h, w) - conv_seqs = [] - for out_channels in [cnn_width, 2*cnn_width, 2*cnn_width]: - conv_seq = ConvSequence(shape, out_channels) - shape = conv_seq.get_output_shape() - conv_seqs.append(conv_seq) - conv_seqs += [ - nn.Flatten(), - nn.ReLU(), - nn.Linear(in_features=shape[0] * shape[1] * shape[2], out_features=mlp_width), - nn.ReLU(), - ] - self.network = nn.Sequential(*conv_seqs) - self.actor = pufferlib.pytorch.layer_init( - nn.Linear(mlp_width, env.single_action_space.n), std=0.01) - self.value = pufferlib.pytorch.layer_init( - nn.Linear(mlp_width, 1), std=1) - - def forward(self, observations, state=None): - hidden = self.encode_observations(observations) - actions, value = self.decode_actions(hidden) - return actions, value - - def forward_train(self, observations, state=None): - return self.forward(observations, state) - - def encode_observations(self, x): - hidden = self.network(x.permute((0, 3, 1, 2)) / 255.0) - return hidden - - def decode_actions(self, hidden): - '''linear decoder function''' - action = self.actor(hidden) - value = self.value(hidden) - return action, value - class ResidualBlock(nn.Module): def __init__(self, channels): super().__init__() - self.conv0 = nn.Conv2d(in_channels=channels, out_channels=channels, kernel_size=3, padding=1) - self.conv1 = nn.Conv2d(in_channels=channels, out_channels=channels, kernel_size=3, padding=1) + self.conv0 = nn.Conv2d(channels, channels, 3, padding=1) + self.conv1 = nn.Conv2d(channels, channels, 3, padding=1) def forward(self, x): inputs = x - x = nn.functional.relu(x) + x = F.relu(x) x = self.conv0(x) - x = nn.functional.relu(x) + x = F.relu(x) x = self.conv1(x) return x + inputs @@ -313,18 +267,39 @@ def __init__(self, input_shape, out_channels): super().__init__() self._input_shape = input_shape self._out_channels = out_channels - self.conv = nn.Conv2d(in_channels=self._input_shape[0], out_channels=self._out_channels, kernel_size=3, padding=1) - self.res_block0 = ResidualBlock(self._out_channels) - self.res_block1 = ResidualBlock(self._out_channels) + self.conv = nn.Conv2d(input_shape[0], out_channels, 3, padding=1) + self.res_block0 = ResidualBlock(out_channels) + self.res_block1 = ResidualBlock(out_channels) def forward(self, x): x = self.conv(x) - x = nn.functional.max_pool2d(x, kernel_size=3, stride=2, padding=1) + x = F.max_pool2d(x, kernel_size=3, stride=2, padding=1) x = self.res_block0(x) x = self.res_block1(x) - assert x.shape[1:] == self.get_output_shape() return x def get_output_shape(self): _c, h, w = self._input_shape return (self._out_channels, (h + 1) // 2, (w + 1) // 2) + +class ImpalaEncoder(nn.Module): + '''IMPALA ResNet encoder (Espeholt et al. 2018). Returns [batch, hidden_size].''' + def __init__(self, env, hidden_size=256, cnn_width=16, **kwargs): + super().__init__() + h, w, c = env.single_observation_space.shape + shape = (c, h, w) + conv_seqs = [] + for out_channels in [cnn_width, 2*cnn_width, 2*cnn_width]: + conv_seq = ConvSequence(shape, out_channels) + shape = conv_seq.get_output_shape() + conv_seqs.append(conv_seq) + conv_seqs += [ + nn.Flatten(), + nn.ReLU(), + nn.Linear(shape[0] * shape[1] * shape[2], hidden_size), + nn.ReLU(), + ] + self.network = nn.Sequential(*conv_seqs) + + def forward(self, observations): + return self.network(observations.permute(0, 3, 1, 2).float() / 255.0) diff --git a/pufferlib/muon.py b/pufferlib/muon.py new file mode 100644 index 0000000000..bd56f2d1fb --- /dev/null +++ b/pufferlib/muon.py @@ -0,0 +1,135 @@ +"""Simple Muon optimizer numerically matched to Lukas's HeavyBall implementation.""" + +import torch +from torch import Tensor + +from torch.optim.optimizer import ( + _to_scalar, + Optimizer, + ParamsT, +) + +__all__ = ["Muon"] + +NS_COEFS = [ + (4.0848, -6.8946, 2.9270), + (3.9505, -6.3029, 2.6377), + (3.7418, -5.5913, 2.3037), + (2.8769, -3.1427, 1.2046), + (2.8366, -3.0525, 1.2012) +] + +def zeropower_via_newtonschulz5(G, eps=1e-7): + G = G.clone() + x = G + if G.size(-2) > G.size(-1): + x = x.mT + + x = x / torch.clamp(G.norm(dim=(-2, -1)), min=eps) + + for a, b, c in NS_COEFS: + s = x @ x.mT + y = c * s + y.diagonal(dim1=-2, dim2=-1).add_(b) + y = y @ s + y.diagonal(dim1=-2, dim2=-1).add_(a) + x = y @ x + + if G.size(-2) > G.size(-1): + x = x.mT + + return x.to(G.dtype) + +class Muon(Optimizer): + def __init__( + self, + params: ParamsT, + lr: float = 0.0025, + weight_decay: float = 0.0, + momentum: float = 0.9, + eps: float = 1e-8) -> None: + if isinstance(lr, Tensor) and lr.numel() != 1: + raise ValueError("Tensor lr must be 1-element") + if lr < 0.0: + raise ValueError(f"Learning rate should be >= 0 but is: {lr}") + if momentum < 0.0: + raise ValueError(f"momentum should be >= 0 but is: {momentum}") + if weight_decay < 0.0: + raise ValueError(f"weight decay should be >= 0 but is: {weight_decay}") + + defaults = { + "lr": lr, + "weight_decay": weight_decay, + "momentum": momentum, + "eps": eps, + } + super().__init__(params, defaults) + + def _init_group(self, group, params_with_grad, grads, muon_momentum_bufs): + for p in group["params"]: + if p.grad is None: + continue + + params_with_grad.append(p) + grads.append(p.grad) + + state = self.state[p] + + if "momentum_buffer" not in state: + state["momentum_buffer"] = torch.zeros_like( + p.grad, memory_format=torch.preserve_format + ) + muon_momentum_bufs.append(state["momentum_buffer"]) + + @torch.no_grad() + def step(self, closure=None): + """Performs a single optimization step.""" + loss = None + if closure is not None: + with torch.enable_grad(): + loss = closure() + + for group in self.param_groups: + lr = group["lr"] + weight_decay = group["weight_decay"] + momentum = group["momentum"] + eps = group["eps"] + + params_with_grad: list[Tensor] = [] + grads: list[Tensor] = [] + muon_momentum_bufs: list[Tensor] = [] + lr = _to_scalar(lr) + + for p in group["params"]: + if p.grad is None: + continue + + params_with_grad.append(p) + grads.append(p.grad) + + state = self.state[p] + + if "momentum_buffer" not in state: + state["momentum_buffer"] = torch.zeros_like( + p.grad, memory_format=torch.preserve_format + ) + muon_momentum_bufs.append(state["momentum_buffer"]) + + for i, param in enumerate(params_with_grad): + + grad = grads[i] + + buf = muon_momentum_bufs[i] + buf.mul_(momentum) + buf.add_(grad) + grad.add_(buf*momentum) + + if grad.ndim >= 2: + grad = grad.view(grad.shape[0], -1) + grad = zeropower_via_newtonschulz5(grad) # original has hardcoded steps and eps + grad *= max(1, grad.size(-2) / grad.size(-1)) ** 0.5 # Matches heavyball and Keller + + param.mul_(1 - lr * weight_decay) + param.sub_(lr*grad.view(param.shape)) + + return loss diff --git a/pufferlib/ocean/__init__.py b/pufferlib/ocean/__init__.py deleted file mode 100644 index 1c91a2b0ff..0000000000 --- a/pufferlib/ocean/__init__.py +++ /dev/null @@ -1,12 +0,0 @@ -from .environment import * - -try: - import torch -except ImportError: - pass -else: - from .torch import Policy - try: - from .torch import Recurrent - except: - Recurrent = None diff --git a/pufferlib/ocean/asteroids/asteroids.py b/pufferlib/ocean/asteroids/asteroids.py deleted file mode 100644 index cc3f6f9ebd..0000000000 --- a/pufferlib/ocean/asteroids/asteroids.py +++ /dev/null @@ -1,53 +0,0 @@ -import gymnasium -import numpy as np - -import pufferlib -from pufferlib.ocean.asteroids import binding - -class Asteroids(pufferlib.PufferEnv): - def __init__(self, num_envs=1, render_mode=None, log_interval=128, buf=None, seed=0, size=500, frameskip=4): - obs_shape = 4 + 5 * 20 # player pos, player vel, [asteroid pos, asteroid vel, asteroid size] x num asteroids - self.single_observation_space = gymnasium.spaces.Box(low=-5, high=5, - shape=(obs_shape,), dtype=np.float32) - self.single_action_space = gymnasium.spaces.Discrete(4) # forward, left, right, shoot - self.render_mode = render_mode - self.num_agents = num_envs - - super().__init__(buf) - self.c_envs = binding.vec_init(self.observations, self.actions, self.rewards, - self.terminals, self.truncations, num_envs, seed, size=size, frameskip=frameskip) - - def reset(self, seed=0): - binding.vec_reset(self.c_envs, seed) - return self.observations, [] - - def step(self, actions): - self.actions[:] = actions - binding.vec_step(self.c_envs) - info = [binding.vec_log(self.c_envs)] - return (self.observations, self.rewards, - self.terminals, self.truncations, info) - - def render(self): - binding.vec_render(self.c_envs, 0) - - def close(self): - binding.vec_close(self.c_envs) - -if __name__ == '__main__': - N = 4096 - env = Asteroids(num_envs=N) - env.reset() - steps = 0 - - CACHE = 1024 - actions = np.random.randint(0, 5, (CACHE, N)) - - import time - start = time.time() - while time.time() - start < 10: - env.step(actions[steps % CACHE]) - steps += 1 - - sps = int(env.num_agents*steps / (time.time() - start)) - print(f'Asteroids SPS: {sps:,}') diff --git a/pufferlib/ocean/battle/battle.py b/pufferlib/ocean/battle/battle.py deleted file mode 100644 index 2beb888e5b..0000000000 --- a/pufferlib/ocean/battle/battle.py +++ /dev/null @@ -1,85 +0,0 @@ -'''A simple sample environment. Use this as a template for your own envs.''' - -import gymnasium -import numpy as np - -import pufferlib -from pufferlib.ocean.battle import binding - -class Battle(pufferlib.PufferEnv): - def __init__(self, num_envs=1, width=1920, height=1080, size_x=1.0, - size_y=1.0, size_z=1.0, num_agents=1024, num_factories=32, - num_armies=4, render_mode=None, log_interval=128, buf=None, seed=0): - self.single_observation_space = gymnasium.spaces.Box(low=0, high=1, - shape=(num_armies*3 + 4*16 + 22 + 8,), dtype=np.float32) - self.single_action_space = gymnasium.spaces.Box( - low=-1, high=1, shape=(3,), dtype=np.float32) - self.render_mode = render_mode - self.num_agents = num_envs*num_agents - self.log_interval = log_interval - - if num_armies < 1 or num_armies > 8: - raise pufferlib.APIUsageError('num_armies must be in [1, 8]') - if num_agents % num_armies != 0: - raise pufferlib.APIUsageError('num_agents must be a multiple of num_armies') - - super().__init__(buf) - c_envs = [] - for i in range(num_envs): - c_env = binding.env_init( - self.observations[i*num_agents:(i+1)*num_agents], - self.actions[i*num_agents:(i+1)*num_agents], - self.rewards[i*num_agents:(i+1)*num_agents], - self.terminals[i*num_agents:(i+1)*num_agents], - self.truncations[i*num_agents:(i+1)*num_agents], - seed, width=width, height=height, size_x=size_x, size_y=size_y, size_z=size_z, - num_agents=num_agents*2, num_factories=num_factories, - num_armies=num_armies) - c_envs.append(c_env) - - self.c_envs = binding.vectorize(*c_envs) - - def reset(self, seed=0): - binding.vec_reset(self.c_envs, seed) - self.tick = 0 - return self.observations, [] - - def step(self, actions): - self.tick += 1 - self.actions[:] = actions - binding.vec_step(self.c_envs) - - info = [] - if self.tick % self.log_interval == 0: - log = binding.vec_log(self.c_envs) - if log: - info.append(log) - - return (self.observations, self.rewards, - self.terminals, self.truncations, info) - - def render(self): - binding.vec_render(self.c_envs, 0) - - def close(self): - binding.vec_close(self.c_envs) - -if __name__ == '__main__': - N = 512 - - env = Battle(num_envs=N) - env.reset() - steps = 0 - - CACHE = 1024 - actions = np.random.randint(env.single_action_space.nvec, size=(CACHE, 2)) - - i = 0 - import time - start = time.time() - while time.time() - start < 10: - env.step(actions[i % CACHE]) - steps += env.num_agents - i += 1 - - print('Battle SPS:', int(steps / (time.time() - start))) diff --git a/pufferlib/ocean/blastar/binding.c b/pufferlib/ocean/blastar/binding.c deleted file mode 100644 index 03e318a12d..0000000000 --- a/pufferlib/ocean/blastar/binding.c +++ /dev/null @@ -1,23 +0,0 @@ -#include "blastar.h" -#define Env Blastar -#include "../env_binding.h" - -static int my_init(Env* env, PyObject* args, PyObject* kwargs) { - env->num_obs = unpack(kwargs, "num_obs"); - init(env, env->num_obs); - return 0; -} - -static int my_log(PyObject* dict, Log* log) { - assign_to_dict(dict, "perf", log->perf); - assign_to_dict(dict, "score", log->score); - assign_to_dict(dict, "episode_return", log->episode_return); - assign_to_dict(dict, "episode_length", log->episode_length); - assign_to_dict(dict, "lives", log->lives); - assign_to_dict(dict, "vertical_closeness_rew", log->vertical_closeness_rew); - assign_to_dict(dict, "fired_bullet_rew", log->fired_bullet_rew); - assign_to_dict(dict, "kill_streak", log->kill_streak); - assign_to_dict(dict, "hit_enemy_with_bullet_rew", log->hit_enemy_with_bullet_rew); - assign_to_dict(dict, "avg_score_difference", log->avg_score_difference); - return 0; -} diff --git a/pufferlib/ocean/blastar/blastar.py b/pufferlib/ocean/blastar/blastar.py deleted file mode 100644 index e93b3067ec..0000000000 --- a/pufferlib/ocean/blastar/blastar.py +++ /dev/null @@ -1,71 +0,0 @@ -import numpy as np -import gymnasium -import pufferlib -from pufferlib.ocean.blastar import binding - -class Blastar(pufferlib.PufferEnv): - def __init__(self, num_envs=1, render_mode=None, buf=None, seed=0): - self.single_observation_space = gymnasium.spaces.Box( - low=0, high=1, shape=(10,), dtype=np.float32 - ) - self.single_action_space = gymnasium.spaces.Discrete(6) - self.render_mode = render_mode - self.num_agents = num_envs - self.num_obs = self.single_observation_space.shape[0] - self.tick = 0 - self.log_interval = 1 - - super().__init__(buf) - self.c_envs = binding.vec_init( - self.observations, - self.actions, - self.rewards, - self.terminals, - self.truncations, - num_envs, - seed, - num_obs=self.num_obs - ) - - def reset(self, seed=None): - self.tick = 0 - binding.vec_reset(self.c_envs, seed) - return self.observations, [] - - def step(self, actions): - self.actions[:] = actions - self.tick += 1 - binding.vec_step(self.c_envs) - - info = [] - if self.tick % self.log_interval == 0: - info.append(binding.vec_log(self.c_envs)) - - return (self.observations, self.rewards, - self.terminals, self.truncations, info) - - def render(self): - binding.vec_render(self.c_envs, 0) - - def close(self): - binding.vec_close(self.c_envs) - -def test_performance(timeout=10, atn_cache=1024): - env = Blastar(num_envs=1000) - env.reset(0) - tick = 0 - - rng = np.random.default_rng() - actions = rng.integers(0, 6, (atn_cache, env.num_agents)) - - import time - start = time.time() - while time.time() - start < timeout: - atn = actions[tick % atn_cache] - env.step(atn) - tick += 1 - - print('SPS:', env.num_agents * tick / (time.time() - start)) - -if __name__ == '__main__': - test_performance() diff --git a/pufferlib/ocean/boids/boids.py b/pufferlib/ocean/boids/boids.py deleted file mode 100644 index 329b36dea3..0000000000 --- a/pufferlib/ocean/boids/boids.py +++ /dev/null @@ -1,126 +0,0 @@ -''' -High-perf Boids -Inspired by https://people.ece.cornell.edu/land/courses/ece4760/labs/s2021/Boids/Boids.html -''' - -import numpy as np -import gymnasium - -import pufferlib -from pufferlib.ocean.boids import binding - -class Boids(pufferlib.PufferEnv): - def __init__( - self, - num_envs=1, - buf=None, - render_mode=None, - seed=0, - report_interval=1, - num_boids=1, - margin_turn_factor=1.0, - centering_factor=0.0, - avoid_factor=0.0, - matching_factor=0.0 - ): - ACTION_SPACE_SIZE = 2 - self.num_agents = num_envs * num_boids - self.num_boids = num_boids - - self.single_observation_space = gymnasium.spaces.Box( - -1000.0, 1000.0, shape=(num_boids*4,), dtype=np.float32 - ) - - #self.single_action_space = gymnasium.spaces.Box( - # -np.inf, np.inf, shape=(ACTION_SPACE_SIZE,), dtype=np.float32 - #) - self.single_action_space = gymnasium.spaces.MultiDiscrete([5, 5]) - - self.render_mode = render_mode - self.report_interval = report_interval - - super().__init__(buf) - self.actions = self.actions.astype(np.float32) - - # Create C binding with flattened action buffer - # We need to manually create a flattened action buffer to pass to C - #self.flat_actions = np.zeros((self.num_agents * ACTION_SPACE_SIZE), dtype=np.float32) - - c_envs = [] - for env_num in range(num_envs): - c_envs.append(binding.env_init( - self.observations[env_num*num_boids:(env_num+1)*num_boids], - #self.flat_actions[env_num*num_boids*ACTION_SPACE_SIZE:(env_num+1)*num_boids*ACTION_SPACE_SIZE], - self.actions[env_num*num_boids:(env_num+1)*num_boids], - self.rewards[env_num*num_boids:(env_num+1)*num_boids], - self.terminals[env_num*num_boids:(env_num+1)*num_boids], - self.truncations[env_num*num_boids:(env_num+1)*num_boids], - seed, - num_boids=num_boids, - report_interval=self.report_interval, - margin_turn_factor=margin_turn_factor, - centering_factor=centering_factor, - avoid_factor=avoid_factor, - matching_factor=matching_factor, - )) - - self.c_envs = binding.vectorize(*c_envs) - - def reset(self, seed=0): - self.tick = 0 - binding.vec_reset(self.c_envs, seed) - return self.observations, [] - - def step(self, actions): - # Clip actions to valid range - clipped_actions = (actions.astype(np.float32) - 2.0) / 4.0 - #clipped_actions = np.clip(actions, -1.0, 1.0) - - # Copy the clipped actions to our flat actions buffer for C binding - # Flatten from [num_agents, num_boids, 2] to a 1D array for C - # TODO: Check if I even need this? its not like I'm using the actions anywhere else - #self.flat_actions[:] = clipped_actions.reshape(-1) - - # Save the original actions for the experience buffer - # TODO: Same thing with this - self.actions[:] = clipped_actions - - self.tick += 1 - binding.vec_step(self.c_envs) - - info = [] - if self.tick % self.report_interval == 0: - log_data = binding.vec_log(self.c_envs) - if log_data: - info.append(log_data) - - # print(f"OBSERVATIONS: {self.observations}") - return (self.observations, self.rewards, - self.terminals, self.truncations, info) - - def render(self): - binding.vec_render(self.c_envs, 0) - - def close(self): - binding.vec_close(self.c_envs) - -def test_performance(timeout=10, atn_cache=1024): - env = Boids(num_envs=1000) - env.reset() - tick = 0 - - # Generate random actions with proper shape: [cache_size, num_agents, action_dim] - actions = np.random.uniform(-3.0, 3.0, (atn_cache, env.num_agents, 2)) - - import time - start = time.time() - while time.time() - start < timeout: - atn = actions[tick % atn_cache] - env.step(atn) - tick += 1 - - print(f'SPS: {env.num_agents * tick / (time.time() - start)}') - - -if __name__ == '__main__': - test_performance() diff --git a/pufferlib/ocean/breakout/binding.c b/pufferlib/ocean/breakout/binding.c deleted file mode 100644 index adf7667783..0000000000 --- a/pufferlib/ocean/breakout/binding.c +++ /dev/null @@ -1,32 +0,0 @@ -#include "breakout.h" - -#define Env Breakout -#include "../env_binding.h" - -static int my_init(Env* env, PyObject* args, PyObject* kwargs) { - env->frameskip = unpack(kwargs, "frameskip"); - env->width = unpack(kwargs, "width"); - env->height = unpack(kwargs, "height"); - env->initial_paddle_width = unpack(kwargs, "paddle_width"); - env->paddle_height = unpack(kwargs, "paddle_height"); - env->ball_width = unpack(kwargs, "ball_width"); - env->ball_height = unpack(kwargs, "ball_height"); - env->brick_width = unpack(kwargs, "brick_width"); - env->brick_height = unpack(kwargs, "brick_height"); - env->brick_rows = unpack(kwargs, "brick_rows"); - env->brick_cols = unpack(kwargs, "brick_cols"); - env->initial_ball_speed = unpack(kwargs, "initial_ball_speed"); - env->max_ball_speed = unpack(kwargs, "max_ball_speed"); - env->paddle_speed = unpack(kwargs, "paddle_speed"); - env->continuous = unpack(kwargs, "continuous"); - init(env); - return 0; -} - -static int my_log(PyObject* dict, Log* log) { - assign_to_dict(dict, "perf", log->perf); - assign_to_dict(dict, "score", log->score); - assign_to_dict(dict, "episode_return", log->episode_return); - assign_to_dict(dict, "episode_length", log->episode_length); - return 0; -} diff --git a/pufferlib/ocean/breakout/breakout.py b/pufferlib/ocean/breakout/breakout.py deleted file mode 100644 index b5a3021457..0000000000 --- a/pufferlib/ocean/breakout/breakout.py +++ /dev/null @@ -1,93 +0,0 @@ -import numpy as np -import gymnasium - -import pufferlib -from pufferlib.ocean.breakout import binding - -class Breakout(pufferlib.PufferEnv): - def __init__(self, num_envs=1, render_mode=None, - frameskip=4, width=576, height=330, - paddle_width=62, paddle_height=8, - ball_width=32, ball_height=32, - brick_width=32, brick_height=12, - brick_rows=6, brick_cols=18, - initial_ball_speed=256, max_ball_speed=448, - paddle_speed=620, - continuous=False, log_interval=128, - buf=None, seed=0): - self.single_observation_space = gymnasium.spaces.Box(low=0, high=1, - shape=(10 + brick_rows*brick_cols,), dtype=np.float32) - self.render_mode = render_mode - self.num_agents = num_envs - self.continuous = continuous - self.log_interval = log_interval - self.tick = 0 - - if continuous: - self.single_action_space = gymnasium.spaces.Box(low=-1, high=1, - shape=(1,), dtype=np.float32) - else: - self.single_action_space = gymnasium.spaces.Discrete(3) - - super().__init__(buf) - if continuous: - self.actions = self.actions.flatten() - else: - self.actions = self.actions.astype(np.float32) - - self.c_envs = binding.vec_init(self.observations, self.actions, self.rewards, - self.terminals, self.truncations, num_envs, seed, frameskip=frameskip, - width=width, height=height, paddle_width=paddle_width, - paddle_height=paddle_height, ball_width=ball_width, - ball_height=ball_height, brick_width=brick_width, - brick_height=brick_height, brick_rows=brick_rows, - brick_cols=brick_cols, initial_ball_speed=initial_ball_speed, - max_ball_speed=max_ball_speed, paddle_speed=paddle_speed, - continuous=continuous - ) - - def reset(self, seed=0): - binding.vec_reset(self.c_envs, seed) - self.tick = 0 - return self.observations, [] - - def step(self, actions): - if self.continuous: - self.actions[:] = np.clip(actions.flatten(), -1.0, 1.0) - else: - self.actions[:] = actions - - self.tick += 1 - binding.vec_step(self.c_envs) - - info = [] - if self.tick % self.log_interval == 0: - info.append(binding.vec_log(self.c_envs)) - - return (self.observations, self.rewards, - self.terminals, self.truncations, info) - - def render(self): - binding.vec_render(self.c_envs, 0) - - def close(self): - binding.vec_close(self.c_envs) - -def test_performance(timeout=10, atn_cache=1024): - env = Breakout(num_envs=1000) - env.reset() - tick = 0 - - actions = np.random.randint(0, 2, (atn_cache, env.num_agents)) - - import time - start = time.time() - while time.time() - start < timeout: - atn = actions[tick % atn_cache] - env.step(atn) - tick += 1 - - print(f'SPS: %f', env.num_agents * tick / (time.time() - start)) - -if __name__ == '__main__': - test_performance() diff --git a/pufferlib/ocean/cartpole/binding.c b/pufferlib/ocean/cartpole/binding.c deleted file mode 100644 index 52cdbf1c66..0000000000 --- a/pufferlib/ocean/cartpole/binding.c +++ /dev/null @@ -1,26 +0,0 @@ -#include "cartpole.h" -#define Env Cartpole -#include "../env_binding.h" - -static int my_init(Env* env, PyObject* args, PyObject* kwargs) { - env->cart_mass = unpack(kwargs, "cart_mass"); - env->pole_mass = unpack(kwargs, "pole_mass"); - env->pole_length = unpack(kwargs, "pole_length"); - env->gravity = unpack(kwargs, "gravity"); - env->force_mag = unpack(kwargs, "force_mag"); - env->tau = unpack(kwargs, "dt"); - env->continuous = unpack(kwargs, "continuous"); - init(env); - return 0; -} - -static int my_log(PyObject* dict, Log* log) { - assign_to_dict(dict, "score", log->score); - assign_to_dict(dict, "perf", log->perf); - assign_to_dict(dict, "episode_length", log->episode_length); - assign_to_dict(dict, "x_threshold_termination", log->x_threshold_termination); - assign_to_dict(dict, "pole_angle_termination", log->pole_angle_termination); - assign_to_dict(dict, "max_steps_termination", log->max_steps_termination); - assign_to_dict(dict, "n", log->n); - return 0; -} diff --git a/pufferlib/ocean/cartpole/cartpole.py b/pufferlib/ocean/cartpole/cartpole.py deleted file mode 100644 index 7f0c3caf26..0000000000 --- a/pufferlib/ocean/cartpole/cartpole.py +++ /dev/null @@ -1,108 +0,0 @@ -import numpy as np -import gymnasium -import pufferlib -from pufferlib.ocean.cartpole import binding - -class Cartpole(pufferlib.PufferEnv): - def __init__(self, num_envs=1, cart_mass=1.0, pole_mass=0.1, - pole_length=0.5, gravity=9.8, force_mag=10.0, dt=0.02, - render_mode='human', report_interval=1, continuous=False, - buf=None, seed=0): - self.render_mode = render_mode - self.num_agents = num_envs - self.report_interval = report_interval - self.tick = 0 - self.continuous = continuous - self.human_action = None - - self.num_obs = 4 - self.single_observation_space = gymnasium.spaces.Box( - low=-np.inf, high=np.inf, shape=(self.num_obs,), dtype=np.float32 - ) - if self.continuous: - self.single_action_space = gymnasium.spaces.Box( - low=-1.0, high=1.0, shape=(1,) - ) - - else: - self.single_action_space = gymnasium.spaces.Discrete(2) - - super().__init__(buf) - self.actions = np.zeros(num_envs, dtype=np.float32) - - self.c_envs = binding.vec_init( - self.observations, - self.actions, - self.rewards, - self.terminals, - self.truncations, - num_envs, - seed, - cart_mass=cart_mass, - pole_mass=pole_mass, - pole_length=pole_length, - gravity=gravity, - force_mag=force_mag, - dt=dt, - continuous=int(self.continuous), - ) - - def reset(self, seed=None): - self.tick = 0 - if seed is None: - binding.vec_reset(self.c_envs, 0) - else: - binding.vec_reset(self.c_envs, seed) - return self.observations, [] - - def step(self, actions): - if self.continuous: - self.actions[:] = np.clip(actions.flatten(), -1.0, 1.0) - else: - self.actions[:] = actions - - self.tick += 1 - binding.vec_step(self.c_envs) - - info = [] - if self.tick % self.report_interval == 0: - info.append(binding.vec_log(self.c_envs)) - - return ( - self.observations, - self.rewards, - self.terminals, - self.truncations, - info - ) - - def render(self): - binding.vec_render(self.c_envs, 0) - - def close(self): - binding.vec_close(self.c_envs) - -def test_performance(timeout=10, atn_cache=8192, continuous=True): - """Benchmark environment performance.""" - num_envs = 4096 - env = Cartpole(num_envs=num_envs, continuous=continuous) - env.reset() - tick = 0 - - if env.continuous: - actions = np.random.uniform(-1, 1, (atn_cache, num_envs, 1)).astype(np.float32) - else: - actions = np.random.randint(0, env.single_action_space.n, (atn_cache, num_envs)).astype(np.int8) - - import time - start = time.time() - while time.time() - start < timeout: - atn = actions[tick % atn_cache] - env.step(atn) - tick += 1 - sps = num_envs * tick / (time.time() - start) - print(f'SPS: {sps:,}') - -if __name__ == '__main__': - test_performance() - diff --git a/pufferlib/ocean/chain_mdp/README.md b/pufferlib/ocean/chain_mdp/README.md deleted file mode 100644 index 3cc26b8952..0000000000 --- a/pufferlib/ocean/chain_mdp/README.md +++ /dev/null @@ -1,7 +0,0 @@ -The Chain MDP [Osband et al., 2016] is a classic benchmark environment designed to test whether reinforcement learning algorithms are capable of systematic exploration rather than falling into short-sighted local optima. - -The environment is composed of $N$ states arranged in a linear chain. At each state $s_i (1 \leq i \leq N)$ the agent can take one of two actions: left or right. The transitions are deterministic: moving left shifts the agent to $s_{i-1}$, while moving right shifts it to $s_{i+1}$. The two boundary states, $s_1$ and $s_N$, are absorbing, meaning moving left while in state $s_1$ keeps you in that state. - -Rewards are sparse and asymmetric: reaching $s_1$ yields a small reward of 1/1000, while reaching $s_N$ yields a much larger reward of 1; all other states give zero reward. Each episode lasts exactly $N+9$ steps, and the agent always starts at $s_2$. - -This setup creates a strong exploration challenge: the nearby absorbing state $s_1$ provides an easy but suboptimal payoff, while the optimal long-term strategy requires consistently moving right until $s_N$ is reached. Uniformly random exploration is highly inefficient here—on average it takes $2^{N-2}$ steps before the agent reaches $s_N$ — so for large $N$, it is virtually impossible to discover the optimal strategy by chance within a single episode. \ No newline at end of file diff --git a/pufferlib/ocean/chain_mdp/chain_mdp.py b/pufferlib/ocean/chain_mdp/chain_mdp.py deleted file mode 100644 index 6b86aa7d5e..0000000000 --- a/pufferlib/ocean/chain_mdp/chain_mdp.py +++ /dev/null @@ -1,64 +0,0 @@ -'''A simple sample environment. Use this as a template for your own envs.''' - -import gymnasium -import numpy as np - -import pufferlib -from pufferlib.ocean.chain_mdp import binding - -class Chain(pufferlib.PufferEnv): - def __init__(self, num_envs=1, render_mode=None, log_interval=128, size=11, buf=None, seed=0): - self.single_observation_space = gymnasium.spaces.Box(low=0, high=1, - shape=(1,), dtype=np.uint8) - self.single_action_space = gymnasium.spaces.Discrete(2) - self.render_mode = render_mode - self.num_agents = num_envs - self.log_interval = log_interval - - super().__init__(buf) - self.c_envs = binding.vec_init(self.observations, self.actions, self.rewards, - self.terminals, self.truncations, num_envs, seed, size=size) - - def reset(self, seed=0): - binding.vec_reset(self.c_envs, seed) - self.tick = 0 - return self.observations, [] - - def step(self, actions): - self.tick += 1 - - self.actions[:] = actions - binding.vec_step(self.c_envs) - - info = [] - if self.tick % self.log_interval == 0: - info.append(binding.vec_log(self.c_envs)) - - return (self.observations, self.rewards, - self.terminals, self.truncations, info) - - def render(self): - binding.vec_render(self.c_envs, 0) - - def close(self): - binding.vec_close(self.c_envs) - -if __name__ == '__main__': - size = 10 - - env = Chain(size=size) - env.reset() - steps = 0 - - CACHE = 1024 - actions = np.random.randint(0, 2, (CACHE,)) - - i = 0 - import time - start = time.time() - while time.time() - start < 10: - env.step(actions[i % CACHE]) - steps += 1 - i += 1 - - print('Chain MDP SPS:', int(steps / (time.time() - start))) diff --git a/pufferlib/ocean/checkers/checkers.py b/pufferlib/ocean/checkers/checkers.py deleted file mode 100644 index 8c2195cfac..0000000000 --- a/pufferlib/ocean/checkers/checkers.py +++ /dev/null @@ -1,65 +0,0 @@ -import gymnasium -import numpy as np - -import pufferlib -from pufferlib.ocean.checkers import binding - -class Checkers(pufferlib.PufferEnv): - def __init__(self, num_envs=1, render_mode=None, log_interval=128, size=8, buf=None, seed=0): - self.single_observation_space = gymnasium.spaces.Box(low=0, high=1, - shape=(size*size,), dtype=np.uint8) - num_move_types = 8 # Move types are: NW, NE, SW, SE, 2*NW, 2*NE, 2*SW, 2*SE, - action_space_size = size * size * num_move_types - self.single_action_space = gymnasium.spaces.Discrete(action_space_size) - self.render_mode = render_mode - self.num_agents = num_envs - self.log_interval = log_interval - - super().__init__(buf) - self.c_envs = binding.vec_init(self.observations, self.actions, self.rewards, - self.terminals, self.truncations, num_envs, seed, size=size) - - def reset(self, seed=0): - binding.vec_reset(self.c_envs, seed) - self.tick = 0 - return self.observations, [] - - def step(self, actions): - self.tick += 1 - - self.actions[:] = actions - binding.vec_step(self.c_envs) - - info = [] - if self.tick % self.log_interval == 0: - info.append(binding.vec_log(self.c_envs)) - - return (self.observations, self.rewards, - self.terminals, self.truncations, info) - - def render(self): - binding.vec_render(self.c_envs, 0) - - def close(self): - binding.vec_close(self.c_envs) - -if __name__ == '__main__': - N = 4096 - size = 3 - - env = Checkers(num_envs=N, size=size) - env.reset() - steps = 0 - - CACHE = 1024 - actions = np.random.randint(0, size * size * 6, (CACHE, N)) - - i = 0 - import time - start = time.time() - while time.time() - start < 10: - env.step(actions[i % CACHE]) - steps += N - i += 1 - - print('Checkers SPS:', int(steps / (time.time() - start))) diff --git a/pufferlib/ocean/connect4/binding.c b/pufferlib/ocean/connect4/binding.c deleted file mode 100644 index de8d7877ac..0000000000 --- a/pufferlib/ocean/connect4/binding.c +++ /dev/null @@ -1,17 +0,0 @@ -#include "connect4.h" -#define Env CConnect4 -#include "../env_binding.h" - -static int my_init(Env* env, PyObject* args, PyObject* kwargs) { - init(env); - return 0; -} - -static int my_log(PyObject* dict, Log* log) { - assign_to_dict(dict, "perf", log->perf); - assign_to_dict(dict, "score", log->score); - assign_to_dict(dict, "episode_return", log->episode_return); - assign_to_dict(dict, "episode_length", log->episode_length); - assign_to_dict(dict, "n", log->n); - return 0; -} diff --git a/pufferlib/ocean/connect4/connect4.py b/pufferlib/ocean/connect4/connect4.py deleted file mode 100644 index 27cdffb25f..0000000000 --- a/pufferlib/ocean/connect4/connect4.py +++ /dev/null @@ -1,82 +0,0 @@ -'''High-perf Pong - -Inspired from https://gist.github.com/Yttrmin/18ecc3d2d68b407b4be1 -& https://jair.org/index.php/jair/article/view/10819/25823 -& https://www.youtube.com/watch?v=PSQt5KGv7Vk -''' - -import numpy as np -import gymnasium - -import pufferlib -from pufferlib.ocean.connect4 import binding - - -class Connect4(pufferlib.PufferEnv): - def __init__(self, num_envs=1, render_mode=None, report_interval=128, - buf=None, seed=0): - - self.single_observation_space = gymnasium.spaces.Box(low=0, high=1, - shape=(42,), dtype=np.float32) - self.single_action_space = gymnasium.spaces.Discrete(7) - self.report_interval = report_interval - self.render_mode = render_mode - self.num_agents = num_envs - - super().__init__(buf=buf) - self.c_envs = binding.vec_init(self.observations, self.actions, self.rewards, - self.terminals, self.truncations, num_envs, seed) - - def reset(self, seed=None): - self.tick = 0 - if seed is None: - binding.vec_reset(self.c_envs, 0) - else: - binding.vec_reset(self.c_envs, seed) - return self.observations, [] - - def step(self, actions): - self.actions[:] = actions - binding.vec_step(self.c_envs) - self.tick += 1 - - info = [] - if self.tick % self.report_interval == 0: - log = binding.vec_log(self.c_envs) - if log['episode_length'] > 0: - info.append(log) - - return (self.observations, self.rewards, - self.terminals, self.truncations, info) - - def render(self): - binding.vec_render(self.c_envs, 0) - - def close(self): - binding.vec_close(self.c_envs) - - -def test_performance(timeout=10, atn_cache=1024, num_envs=1024): - import time - - env = Connect4(num_envs=num_envs) - env.reset() - tick = 0 - - actions = np.random.randint( - 0, - env.single_action_space.n + 1, - (atn_cache, num_envs), - ) - - start = time.time() - while time.time() - start < timeout: - atn = actions[tick % atn_cache] - env.step(atn) - tick += 1 - - print(f'SPS: {num_envs * tick / (time.time() - start)}') - - -if __name__ == '__main__': - test_performance() diff --git a/pufferlib/ocean/connect4/connect4game b/pufferlib/ocean/connect4/connect4game deleted file mode 100755 index d2677ee4fa..0000000000 Binary files a/pufferlib/ocean/connect4/connect4game and /dev/null differ diff --git a/pufferlib/ocean/convert/binding.c b/pufferlib/ocean/convert/binding.c deleted file mode 100644 index e53f6e943d..0000000000 --- a/pufferlib/ocean/convert/binding.c +++ /dev/null @@ -1,22 +0,0 @@ -#include "convert.h" - -#define Env Convert -#include "../env_binding.h" - -static int my_init(Env* env, PyObject* args, PyObject* kwargs) { - env->width = unpack(kwargs, "width"); - env->height = unpack(kwargs, "height"); - env->num_agents = unpack(kwargs, "num_agents"); - env->num_factories = unpack(kwargs, "num_factories"); - env->num_resources = unpack(kwargs, "num_resources"); - init(env); - return 0; -} - -static int my_log(PyObject* dict, Log* log) { - assign_to_dict(dict, "perf", log->perf); - assign_to_dict(dict, "score", log->score); - assign_to_dict(dict, "episode_return", log->episode_return); - assign_to_dict(dict, "episode_length", log->episode_length); - return 0; -} diff --git a/pufferlib/ocean/convert/convert.py b/pufferlib/ocean/convert/convert.py deleted file mode 100644 index 1f57cead89..0000000000 --- a/pufferlib/ocean/convert/convert.py +++ /dev/null @@ -1,82 +0,0 @@ -'''A simple sample environment. Use this as a template for your own envs.''' - -import gymnasium -import numpy as np - -import pufferlib -from pufferlib.ocean.convert import binding - -class Convert(pufferlib.PufferEnv): - def __init__(self, num_envs=1, width=1920, height=1080, num_agents=1024, num_factories=32, - num_resources=8, render_mode=None, log_interval=128, buf=None, seed=0): - self.single_observation_space = gymnasium.spaces.Box(low=0, high=1, - shape=(2*num_resources + 4 + num_resources,), dtype=np.float32) - self.single_action_space = gymnasium.spaces.MultiDiscrete([9, 5]) - - self.render_mode = render_mode - self.num_agents = num_envs*num_agents - self.log_interval = log_interval - - if num_resources < 1 or num_resources > 8: - raise pufferlib.APIUsageError('num_resources must be in [1, 8]') - - super().__init__(buf) - c_envs = [] - for i in range(num_envs): - c_env = binding.env_init( - self.observations[i*num_agents:(i+1)*num_agents], - self.actions[i*num_agents:(i+1)*num_agents], - self.rewards[i*num_agents:(i+1)*num_agents], - self.terminals[i*num_agents:(i+1)*num_agents], - self.truncations[i*num_agents:(i+1)*num_agents], - seed, width=width, height=height, - num_agents=num_agents, num_factories=num_factories, - num_resources=num_resources) - c_envs.append(c_env) - - self.c_envs = binding.vectorize(*c_envs) - - def reset(self, seed=0): - binding.vec_reset(self.c_envs, seed) - self.tick = 0 - return self.observations, [] - - def step(self, actions): - self.tick += 1 - self.actions[:] = actions - binding.vec_step(self.c_envs) - - info = [] - if self.tick % self.log_interval == 0: - log = binding.vec_log(self.c_envs) - if log: - info.append(log) - - return (self.observations, self.rewards, - self.terminals, self.truncations, info) - - def render(self): - binding.vec_render(self.c_envs, 0) - - def close(self): - binding.vec_close(self.c_envs) - -if __name__ == '__main__': - N = 512 - - env = Convert(num_envs=N) - env.reset() - steps = 0 - - CACHE = 1024 - actions = np.random.randint(env.single_action_space.nvec, size=(CACHE, 2)) - - i = 0 - import time - start = time.time() - while time.time() - start < 10: - env.step(actions[i % CACHE]) - steps += env.num_agents - i += 1 - - print('Convert SPS:', int(steps / (time.time() - start))) diff --git a/pufferlib/ocean/convert_circle/convert_circle.py b/pufferlib/ocean/convert_circle/convert_circle.py deleted file mode 100644 index f8682535b2..0000000000 --- a/pufferlib/ocean/convert_circle/convert_circle.py +++ /dev/null @@ -1,83 +0,0 @@ -'''A simple sample environment. Use this as a template for your own envs.''' - -import gymnasium -import numpy as np - -import pufferlib -from pufferlib.ocean.convert_circle import binding - -class ConvertCircle(pufferlib.PufferEnv): - def __init__(self, num_envs=1, width=1920, height=1080, num_agents=1024, num_factories=32, - num_resources=8, equidistant=0, radius=30, render_mode=None, log_interval=128, buf=None, seed=0): - self.single_observation_space = gymnasium.spaces.Box(low=0, high=1, - shape=(2*num_resources + 4 + num_resources,), dtype=np.float32) - self.single_action_space = gymnasium.spaces.MultiDiscrete([9, 5]) - - self.render_mode = render_mode - self.num_agents = num_envs*num_agents - self.log_interval = log_interval - - if num_resources < 1 or num_resources > 8: - raise pufferlib.APIUsageError('num_resources must be in [1, 8]') - - super().__init__(buf) - c_envs = [] - for i in range(num_envs): - c_env = binding.env_init( - self.observations[i*num_agents:(i+1)*num_agents], - self.actions[i*num_agents:(i+1)*num_agents], - self.rewards[i*num_agents:(i+1)*num_agents], - self.terminals[i*num_agents:(i+1)*num_agents], - self.truncations[i*num_agents:(i+1)*num_agents], - seed, width=width, height=height, - num_agents=num_agents, num_factories=num_factories, - num_resources=num_resources, equidistant=equidistant, - radius=radius) - c_envs.append(c_env) - - self.c_envs = binding.vectorize(*c_envs) - - def reset(self, seed=0): - binding.vec_reset(self.c_envs, seed) - self.tick = 0 - return self.observations, [] - - def step(self, actions): - self.tick += 1 - self.actions[:] = actions - binding.vec_step(self.c_envs) - - info = [] - if self.tick % self.log_interval == 0: - log = binding.vec_log(self.c_envs) - if log: - info.append(log) - - return (self.observations, self.rewards, - self.terminals, self.truncations, info) - - def render(self): - binding.vec_render(self.c_envs, 0) - - def close(self): - binding.vec_close(self.c_envs) - -if __name__ == '__main__': - N = 512 - - env = ConvertCircle(num_envs=N) - env.reset() - steps = 0 - - CACHE = 1024 - actions = np.random.randint(env.single_action_space.nvec, size=(CACHE, 2)) - - i = 0 - import time - start = time.time() - while time.time() - start < 10: - env.step(actions[i % CACHE]) - steps += env.num_agents - i += 1 - - print('ConvertCircle SPS:', int(steps / (time.time() - start))) diff --git a/pufferlib/ocean/drive/binding.c b/pufferlib/ocean/drive/binding.c deleted file mode 100644 index fac309eeba..0000000000 --- a/pufferlib/ocean/drive/binding.c +++ /dev/null @@ -1,169 +0,0 @@ -#include "drive.h" -#define Env Drive -#define MY_SHARED -#define MY_PUT -#include "../env_binding.h" - -static int my_put(Env* env, PyObject* args, PyObject* kwargs) { - PyObject* obs = PyDict_GetItemString(kwargs, "observations"); - if (!PyObject_TypeCheck(obs, &PyArray_Type)) { - PyErr_SetString(PyExc_TypeError, "Observations must be a NumPy array"); - return 1; - } - PyArrayObject* observations = (PyArrayObject*)obs; - if (!PyArray_ISCONTIGUOUS(observations)) { - PyErr_SetString(PyExc_ValueError, "Observations must be contiguous"); - return 1; - } - env->observations = PyArray_DATA(observations); - - PyObject* act = PyDict_GetItemString(kwargs, "actions"); - if (!PyObject_TypeCheck(act, &PyArray_Type)) { - PyErr_SetString(PyExc_TypeError, "Actions must be a NumPy array"); - return 1; - } - PyArrayObject* actions = (PyArrayObject*)act; - if (!PyArray_ISCONTIGUOUS(actions)) { - PyErr_SetString(PyExc_ValueError, "Actions must be contiguous"); - return 1; - } - env->actions = PyArray_DATA(actions); - if (PyArray_ITEMSIZE(actions) == sizeof(double)) { - PyErr_SetString(PyExc_ValueError, "Action tensor passed as float64 (pass np.float32 buffer)"); - return 1; - } - - PyObject* rew = PyDict_GetItemString(kwargs, "rewards"); - if (!PyObject_TypeCheck(rew, &PyArray_Type)) { - PyErr_SetString(PyExc_TypeError, "Rewards must be a NumPy array"); - return 1; - } - PyArrayObject* rewards = (PyArrayObject*)rew; - if (!PyArray_ISCONTIGUOUS(rewards)) { - PyErr_SetString(PyExc_ValueError, "Rewards must be contiguous"); - return 1; - } - if (PyArray_NDIM(rewards) != 1) { - PyErr_SetString(PyExc_ValueError, "Rewards must be 1D"); - return 1; - } - env->rewards = PyArray_DATA(rewards); - - PyObject* term = PyDict_GetItemString(kwargs, "terminals"); - if (!PyObject_TypeCheck(term, &PyArray_Type)) { - PyErr_SetString(PyExc_TypeError, "Terminals must be a NumPy array"); - return 1; - } - PyArrayObject* terminals = (PyArrayObject*)term; - if (!PyArray_ISCONTIGUOUS(terminals)) { - PyErr_SetString(PyExc_ValueError, "Terminals must be contiguous"); - return 1; - } - if (PyArray_NDIM(terminals) != 1) { - PyErr_SetString(PyExc_ValueError, "Terminals must be 1D"); - return 1; - } - env->terminals = PyArray_DATA(terminals); - return 0; -} - -static PyObject* my_shared(PyObject* self, PyObject* args, PyObject* kwargs) { - int num_agents = unpack(kwargs, "num_agents"); - int num_maps = unpack(kwargs, "num_maps"); - clock_gettime(CLOCK_REALTIME, &ts); - srand(ts.tv_nsec); - int total_agent_count = 0; - int env_count = 0; - int max_envs = num_agents; - PyObject* agent_offsets = PyList_New(max_envs+1); - PyObject* map_ids = PyList_New(max_envs); - // getting env count - while(total_agent_count < num_agents && env_count < max_envs){ - char map_file[100]; - int map_id = rand() % num_maps; - Drive* env = calloc(1, sizeof(Drive)); - sprintf(map_file, "resources/drive/binaries/map_%03d.bin", map_id); - env->entities = load_map_binary(map_file, env); - set_active_agents(env); - // Store map_id - PyObject* map_id_obj = PyLong_FromLong(map_id); - PyList_SetItem(map_ids, env_count, map_id_obj); - // Store agent offset - PyObject* offset = PyLong_FromLong(total_agent_count); - PyList_SetItem(agent_offsets, env_count, offset); - total_agent_count += env->active_agent_count; - env_count++; - for(int j=0;jnum_entities;j++) { - free_entity(&env->entities[j]); - } - free(env->entities); - free(env->active_agent_indices); - free(env->static_car_indices); - free(env->expert_static_car_indices); - free(env); - } - if(total_agent_count >= num_agents){ - total_agent_count = num_agents; - } - PyObject* final_total_agent_count = PyLong_FromLong(total_agent_count); - PyList_SetItem(agent_offsets, env_count, final_total_agent_count); - PyObject* final_env_count = PyLong_FromLong(env_count); - // resize lists - PyObject* resized_agent_offsets = PyList_GetSlice(agent_offsets, 0, env_count + 1); - PyObject* resized_map_ids = PyList_GetSlice(map_ids, 0, env_count); - // - //Py_DECREF(agent_offsets); - //Py_DECREF(map_ids); - // create a tuple - PyObject* tuple = PyTuple_New(3); - PyTuple_SetItem(tuple, 0, resized_agent_offsets); - PyTuple_SetItem(tuple, 1, resized_map_ids); - PyTuple_SetItem(tuple, 2, final_env_count); - return tuple; - - //Py_DECREF(num); - /* - for(int i = 0;ihuman_agent_idx = unpack(kwargs, "human_agent_idx"); - env->reward_vehicle_collision = unpack(kwargs, "reward_vehicle_collision"); - env->reward_offroad_collision = unpack(kwargs, "reward_offroad_collision"); - env->reward_goal_post_respawn = unpack(kwargs, "reward_goal_post_respawn"); - env->reward_vehicle_collision_post_respawn = unpack(kwargs, "reward_vehicle_collision_post_respawn"); - env->spawn_immunity_timer = unpack(kwargs, "spawn_immunity_timer"); - int map_id = unpack(kwargs, "map_id"); - int max_agents = unpack(kwargs, "max_agents"); - - char map_file[100]; - sprintf(map_file, "resources/drive/binaries/map_%03d.bin", map_id); - env->num_agents = max_agents; - env->map_name = strdup(map_file); - init(env); - return 0; -} - -static int my_log(PyObject* dict, Log* log) { - assign_to_dict(dict, "perf", log->perf); - assign_to_dict(dict, "score", log->score); - assign_to_dict(dict, "episode_return", log->episode_return); - assign_to_dict(dict, "episode_length", log->episode_length); - assign_to_dict(dict, "offroad_rate", log->offroad_rate); - assign_to_dict(dict, "collision_rate", log->collision_rate); - assign_to_dict(dict, "dnf_rate", log->dnf_rate); - assign_to_dict(dict, "n", log->n); - assign_to_dict(dict, "completion_rate", log->completion_rate); - assign_to_dict(dict, "clean_collision_rate", log->clean_collision_rate); - return 0; -} diff --git a/pufferlib/ocean/drive/drive.c b/pufferlib/ocean/drive/drive.c deleted file mode 100644 index f2537d2654..0000000000 --- a/pufferlib/ocean/drive/drive.c +++ /dev/null @@ -1,335 +0,0 @@ -#include -#include -#include "drive.h" -#include "puffernet.h" - -typedef struct DriveNet DriveNet; -struct DriveNet { - int num_agents; - float* obs_self; - float* obs_partner; - float* obs_road; - float* partner_linear_output; - float* road_linear_output; - float* partner_layernorm_output; - float* road_layernorm_output; - float* partner_linear_output_two; - float* road_linear_output_two; - Linear* ego_encoder; - Linear* road_encoder; - Linear* partner_encoder; - LayerNorm* ego_layernorm; - LayerNorm* road_layernorm; - LayerNorm* partner_layernorm; - Linear* ego_encoder_two; - Linear* road_encoder_two; - Linear* partner_encoder_two; - MaxDim1* partner_max; - MaxDim1* road_max; - CatDim1* cat1; - CatDim1* cat2; - GELU* gelu; - Linear* shared_embedding; - ReLU* relu; - LSTM* lstm; - Linear* actor; - Linear* value_fn; - Multidiscrete* multidiscrete; -}; - -DriveNet* init_drivenet(Weights* weights, int num_agents) { - DriveNet* net = calloc(1, sizeof(DriveNet)); - int hidden_size = 256; - int input_size = 64; - - net->num_agents = num_agents; - net->obs_self = calloc(num_agents*7, sizeof(float)); // 7 features - net->obs_partner = calloc(num_agents*63*7, sizeof(float)); // 63 objects, 7 features - net->obs_road = calloc(num_agents*200*13, sizeof(float)); // 200 objects, 13 features - net->partner_linear_output = calloc(num_agents*63*input_size, sizeof(float)); - net->road_linear_output = calloc(num_agents*200*input_size, sizeof(float)); - net->partner_linear_output_two = calloc(num_agents*63*input_size, sizeof(float)); - net->road_linear_output_two = calloc(num_agents*200*input_size, sizeof(float)); - net->partner_layernorm_output = calloc(num_agents*63*input_size, sizeof(float)); - net->road_layernorm_output = calloc(num_agents*200*input_size, sizeof(float)); - net->ego_encoder = make_linear(weights, num_agents, 7, input_size); - net->ego_layernorm = make_layernorm(weights, num_agents, input_size); - net->ego_encoder_two = make_linear(weights, num_agents, input_size, input_size); - net->road_encoder = make_linear(weights, num_agents, 13, input_size); - net->road_layernorm = make_layernorm(weights, num_agents, input_size); - net->road_encoder_two = make_linear(weights, num_agents, input_size, input_size); - net->partner_encoder = make_linear(weights, num_agents, 7, input_size); - net->partner_layernorm = make_layernorm(weights, num_agents, input_size); - net->partner_encoder_two = make_linear(weights, num_agents, input_size, input_size); - net->partner_max = make_max_dim1(num_agents, 63, input_size); - net->road_max = make_max_dim1(num_agents, 200, input_size); - net->cat1 = make_cat_dim1(num_agents, input_size, input_size); - net->cat2 = make_cat_dim1(num_agents, input_size + input_size, input_size); - net->gelu = make_gelu(num_agents, 3*input_size); - net->shared_embedding = make_linear(weights, num_agents, input_size*3, hidden_size); - net->relu = make_relu(num_agents, hidden_size); - net->actor = make_linear(weights, num_agents, hidden_size, 20); - net->value_fn = make_linear(weights, num_agents, hidden_size, 1); - net->lstm = make_lstm(weights, num_agents, hidden_size, 256); - memset(net->lstm->state_h, 0, num_agents*256*sizeof(float)); - memset(net->lstm->state_c, 0, num_agents*256*sizeof(float)); - int logit_sizes[2] = {7, 13}; - net->multidiscrete = make_multidiscrete(num_agents, logit_sizes, 2); - return net; -} - -void free_drivenet(DriveNet* net) { - free(net->obs_self); - free(net->obs_partner); - free(net->obs_road); - free(net->partner_linear_output); - free(net->road_linear_output); - free(net->partner_linear_output_two); - free(net->road_linear_output_two); - free(net->ego_encoder); - free(net->road_encoder); - free(net->partner_encoder); - free(net->ego_layernorm); - free(net->road_layernorm); - free(net->partner_layernorm); - free(net->ego_encoder_two); - free(net->road_encoder_two); - free(net->partner_encoder_two); - free(net->partner_max); - free(net->road_max); - free(net->cat1); - free(net->cat2); - free(net->gelu); - free(net->shared_embedding); - free(net->relu); - free(net->multidiscrete); - free(net->actor); - free(net->value_fn); - free(net->lstm); - free(net); -} - -void forward(DriveNet* net, float* observations, int* actions) { - // Clear previous observations - memset(net->obs_self, 0, net->num_agents * 7 * sizeof(float)); - memset(net->obs_partner, 0, net->num_agents * 63 * 7 * sizeof(float)); - memset(net->obs_road, 0, net->num_agents * 200 * 13 * sizeof(float)); - - // Reshape observations into 2D boards and additional features - float (*obs_self)[7] = (float (*)[7])net->obs_self; - float (*obs_partner)[63][7] = (float (*)[63][7])net->obs_partner; - float (*obs_road)[200][13] = (float (*)[200][13])net->obs_road; - - for (int b = 0; b < net->num_agents; b++) { - int b_offset = b * (7 + 63*7 + 200*7); // offset for each batch - int partner_offset = b_offset + 7; - int road_offset = b_offset + 7 + 63*7; - // Process self observation - for(int i = 0; i < 7; i++) { - obs_self[b][i] = observations[b_offset + i]; - } - - // Process partner observation - for(int i = 0; i < 63; i++) { - for(int j = 0; j < 7; j++) { - obs_partner[b][i][j] = observations[partner_offset + i*7 + j]; - } - } - - // Process road observation - for(int i = 0; i < 200; i++) { - for(int j = 0; j < 7; j++) { - obs_road[b][i][j] = observations[road_offset + i*7 + j]; - } - for(int j = 0; j < 7; j++) { - if(j == observations[road_offset+i*7 + 6]) { - obs_road[b][i][6 + j] = 1.0f; - } else { - obs_road[b][i][6 + j] = 0.0f; - } - } - } - } - - // Forward pass through the network - linear(net->ego_encoder, net->obs_self); - layernorm(net->ego_layernorm, net->ego_encoder->output); - linear(net->ego_encoder_two, net->ego_layernorm->output); - for (int b = 0; b < net->num_agents; b++) { - for (int obj = 0; obj < 63; obj++) { - // Get the 7 features for this object - float* obj_features = &net->obs_partner[b*63*7 + obj*7]; - // Apply linear layer to this object - _linear(obj_features, net->partner_encoder->weights, net->partner_encoder->bias, - &net->partner_linear_output[b*63*64 + obj*64], 1, 7, 64); - } - } - - for (int b = 0; b < net->num_agents; b++) { - for (int obj = 0; obj < 63; obj++) { - float* after_first = &net->partner_linear_output[b*63*64 + obj*64]; - _layernorm(after_first, net->partner_layernorm->weights, net->partner_layernorm->bias, - &net->partner_layernorm_output[b*63*64 + obj*64], 1, 64); - } - } - for (int b = 0; b < net->num_agents; b++) { - for (int obj = 0; obj < 63; obj++) { - // Get the 7 features for this object - float* obj_features = &net->partner_layernorm_output[b*63*64 + obj*64]; - // Apply linear layer to this object - _linear(obj_features, net->partner_encoder_two->weights, net->partner_encoder_two->bias, - &net->partner_linear_output_two[b*63*64 + obj*64], 1, 64, 64); - - } - } - - // Process road objects: apply linear to each object individually - for (int b = 0; b < net->num_agents; b++) { - for (int obj = 0; obj < 200; obj++) { - // Get the 13 features for this object - float* obj_features = &net->obs_road[b*200*13 + obj*13]; - // Apply linear layer to this object - _linear(obj_features, net->road_encoder->weights, net->road_encoder->bias, - &net->road_linear_output[b*200*64 + obj*64], 1, 13, 64); - } - } - - // Apply layer norm and second linear to each road object - for (int b = 0; b < net->num_agents; b++) { - for (int obj = 0; obj < 200; obj++) { - float* after_first = &net->road_linear_output[b*200*64 + obj*64]; - _layernorm(after_first, net->road_layernorm->weights, net->road_layernorm->bias, - &net->road_layernorm_output[b*200*64 + obj*64], 1, 64); - } - } - for (int b = 0; b < net->num_agents; b++) { - for (int obj = 0; obj < 200; obj++) { - float* after_first = &net->road_layernorm_output[b*200*64 + obj*64]; - _linear(after_first, net->road_encoder_two->weights, net->road_encoder_two->bias, - &net->road_linear_output_two[b*200*64 + obj*64], 1, 64, 64); - } - } - - max_dim1(net->partner_max, net->partner_linear_output_two); - max_dim1(net->road_max, net->road_linear_output_two); - cat_dim1(net->cat1, net->ego_encoder_two->output, net->road_max->output); - cat_dim1(net->cat2, net->cat1->output, net->partner_max->output); - gelu(net->gelu, net->cat2->output); - linear(net->shared_embedding, net->gelu->output); - relu(net->relu, net->shared_embedding->output); - lstm(net->lstm, net->relu->output); - linear(net->actor, net->lstm->state_h); - linear(net->value_fn, net->lstm->state_h); - - // Get action by taking argmax of actor output - softmax_multidiscrete(net->multidiscrete, net->actor->output, actions); -} -void demo() { - - Drive env = { - .dynamics_model = CLASSIC, - .human_agent_idx = 0, - .reward_vehicle_collision = -0.1f, - .reward_offroad_collision = -0.1f, - .map_name = "resources/drive/binaries/map_942.bin", - .spawn_immunity_timer = 50 - }; - allocate(&env); - c_reset(&env); - c_render(&env); - Weights* weights = load_weights("resources/drive/puffer_drive_weights.bin", 595925); - DriveNet* net = init_drivenet(weights, env.active_agent_count); - //Client* client = make_client(&env); - int accel_delta = 2; - int steer_delta = 4; - while (!WindowShouldClose()) { - // Handle camera controls - int (*actions)[2] = (int(*)[2])env.actions; - forward(net, env.observations, env.actions); - if (IsKeyDown(KEY_LEFT_SHIFT)) { - actions[env.human_agent_idx][0] = 3; - actions[env.human_agent_idx][1] = 6; - if(IsKeyDown(KEY_UP) || IsKeyDown(KEY_W)){ - actions[env.human_agent_idx][0] += accel_delta; - // Cap acceleration to maximum of 6 - if(actions[env.human_agent_idx][0] > 6) { - actions[env.human_agent_idx][0] = 6; - } - } - if(IsKeyDown(KEY_DOWN) || IsKeyDown(KEY_S)){ - actions[env.human_agent_idx][0] -= accel_delta; - // Cap acceleration to minimum of 0 - if(actions[env.human_agent_idx][0] < 0) { - actions[env.human_agent_idx][0] = 0; - } - } - if(IsKeyDown(KEY_LEFT) || IsKeyDown(KEY_A)){ - actions[env.human_agent_idx][1] += steer_delta; - // Cap steering to minimum of 0 - if(actions[env.human_agent_idx][1] < 0) { - actions[env.human_agent_idx][1] = 0; - } - } - if(IsKeyDown(KEY_RIGHT) || IsKeyDown(KEY_D)){ - actions[env.human_agent_idx][1] -= steer_delta; - // Cap steering to maximum of 12 - if(actions[env.human_agent_idx][1] > 12) { - actions[env.human_agent_idx][1] = 12; - } - } - if(IsKeyPressed(KEY_TAB)){ - env.human_agent_idx = (env.human_agent_idx + 1) % env.active_agent_count; - } - } - c_step(&env); - c_render(&env); - } - - close_client(env.client); - free_allocated(&env); - free_drivenet(net); - free(weights); -} - -void performance_test() { - long test_time = 10; - Drive env = { - .dynamics_model = CLASSIC, - .human_agent_idx = 0, - .map_name = "resources/drive/binaries/map_942.bin" - }; - clock_t start_time, end_time; - double cpu_time_used; - start_time = clock(); - allocate(&env); - c_reset(&env); - end_time = clock(); - cpu_time_used = ((double) (end_time - start_time)) / CLOCKS_PER_SEC; - printf("Init time: %f\n", cpu_time_used); - - long start = time(NULL); - int i = 0; - int (*actions)[2] = (int(*)[2])env.actions; - - while (time(NULL) - start < test_time) { - // Set random actions for all agents - for(int j = 0; j < env.active_agent_count; j++) { - int accel = rand() % 7; - int steer = rand() % 13; - actions[j][0] = accel; // -1, 0, or 1 - actions[j][1] = steer; // Random steering - } - - c_step(&env); - i++; - } - long end = time(NULL); - printf("SPS: %ld\n", (i*env.active_agent_count) / (end - start)); - free_allocated(&env); -} - -int main() { - demo(); - // performance_test(); - return 0; -} diff --git a/pufferlib/ocean/drive/drive.h b/pufferlib/ocean/drive/drive.h deleted file mode 100644 index e83831f8b2..0000000000 --- a/pufferlib/ocean/drive/drive.h +++ /dev/null @@ -1,1832 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include "raylib.h" -#include "raymath.h" -#include "rlgl.h" -#include -// Entity Types -#define NONE 0 -#define VEHICLE 1 -#define PEDESTRIAN 2 -#define CYCLIST 3 -#define ROAD_LANE 4 -#define ROAD_LINE 5 -#define ROAD_EDGE 6 -#define STOP_SIGN 7 -#define CROSSWALK 8 -#define SPEED_BUMP 9 -#define DRIVEWAY 10 - -// Trajectory Length -#define TRAJECTORY_LENGTH 91 - -// Actions -#define NOOP 0 - -// Dynamics Models -#define CLASSIC 0 -#define INVERTIBLE_BICYLE 1 -#define DELTA_LOCAL 2 -#define STATE_DYNAMICS 3 - -// collision state -#define NO_COLLISION 0 -#define VEHICLE_COLLISION 1 -#define OFFROAD 2 - -// grid cell size -#define GRID_CELL_SIZE 5.0f -#define MAX_ENTITIES_PER_CELL 10 -#define SLOTS_PER_CELL (MAX_ENTITIES_PER_CELL*2 + 1) - -// Max road segment observation entities -#define MAX_ROAD_SEGMENT_OBSERVATIONS 200 -#define MAX_CARS 64 -// Observation Space Constants -#define MAX_SPEED 100.0f -#define MAX_VEH_LEN 30.0f -#define MAX_VEH_WIDTH 15.0f -#define MAX_VEH_HEIGHT 10.0f -#define MIN_REL_GOAL_COORD -1000.0f -#define MAX_REL_GOAL_COORD 1000.0f -#define MIN_REL_AGENT_POS -1000.0f -#define MAX_REL_AGENT_POS 1000.0f -#define MAX_ORIENTATION_RAD 2 * PI -#define MIN_RG_COORD -1000.0f -#define MAX_RG_COORD 1000.0f -#define MAX_ROAD_SCALE 100.0f -#define MAX_ROAD_SEGMENT_LENGTH 100.0f - -// Acceleration Values -static const float ACCELERATION_VALUES[7] = {-4.0000f, -2.6670f, -1.3330f, -0.0000f, 1.3330f, 2.6670f, 4.0000f}; -// static const float STEERING_VALUES[13] = {-3.1420f, -2.6180f, -2.0940f, -1.5710f, -1.0470f, -0.5240f, 0.0000f, 0.5240f, -// 1.0470f, 1.5710f, 2.0940f, 2.6180f, 3.1420f}; -static const float STEERING_VALUES[13] = {-1.000f, -0.833f, -0.667f, -0.500f, -0.333f, -0.167f, 0.000f, 0.167f, 0.333f, 0.500f, 0.667f, 0.833f, 1.000f}; -static const float offsets[4][2] = { - {-1, 1}, // top-left - {1, 1}, // top-right - {1, -1}, // bottom-right - {-1, -1} // bottom-left - }; - -static const int collision_offsets[25][2] = { - {-2, -2}, {-1, -2}, {0, -2}, {1, -2}, {2, -2}, // Top row - {-2, -1}, {-1, -1}, {0, -1}, {1, -1}, {2, -1}, // Second row - {-2, 0}, {-1, 0}, {0, 0}, {1, 0}, {2, 0}, // Middle row (including center) - {-2, 1}, {-1, 1}, {0, 1}, {1, 1}, {2, 1}, // Fourth row - {-2, 2}, {-1, 2}, {0, 2}, {1, 2}, {2, 2} // Bottom row -}; - -struct timespec ts; - -typedef struct Drive Drive; -typedef struct Client Client; -typedef struct Log Log; - -struct Log { - float episode_return; - float episode_length; - float perf; - float score; - float offroad_rate; - float collision_rate; - float clean_collision_rate; - float completion_rate; - float dnf_rate; - float n; -}; - -typedef struct Entity Entity; -struct Entity { - int type; - int array_size; - float* traj_x; - float* traj_y; - float* traj_z; - float* traj_vx; - float* traj_vy; - float* traj_vz; - float* traj_heading; - int* traj_valid; - float width; - float length; - float height; - float goal_position_x; - float goal_position_y; - float goal_position_z; - int mark_as_expert; - int collision_state; - float x; - float y; - float z; - float vx; - float vy; - float vz; - float heading; - float heading_x; - float heading_y; - int valid; - int reached_goal; - int respawn_timestep; - int collided_before_goal; - int reached_goal_this_episode; - int active_agent; -}; - -void free_entity(Entity* entity){ - // free trajectory arrays - free(entity->traj_x); - free(entity->traj_y); - free(entity->traj_z); - free(entity->traj_vx); - free(entity->traj_vy); - free(entity->traj_vz); - free(entity->traj_heading); - free(entity->traj_valid); -} - -float relative_distance(float a, float b){ - float distance = sqrtf(powf(a - b, 2)); - return distance; -} - -float relative_distance_2d(float x1, float y1, float x2, float y2){ - float dx = x2 - x1; - float dy = y2 - y1; - float distance = sqrtf(dx*dx + dy*dy); - return distance; -} - -struct Drive { - Client* client; - float* observations; - int* actions; - float* rewards; - unsigned char* terminals; - Log log; - Log* logs; - int num_agents; - int active_agent_count; - int* active_agent_indices; - int human_agent_idx; - Entity* entities; - int num_entities; - int num_cars; - int num_objects; - int num_roads; - int static_car_count; - int* static_car_indices; - int expert_static_car_count; - int* expert_static_car_indices; - int timestep; - int dynamics_model; - float* map_corners; - int* grid_cells; // holds entity ids and geometry index per cell - int grid_cols; - int grid_rows; - int vision_range; - int* neighbor_offsets; - int* neighbor_cache_entities; - int* neighbor_cache_indices; - float reward_vehicle_collision; - float reward_offroad_collision; - char* map_name; - float world_mean_x; - float world_mean_y; - int spawn_immunity_timer; - float reward_goal_post_respawn; - float reward_vehicle_collision_post_respawn; -}; - -void add_log(Drive* env) { - for(int i = 0; i < env->active_agent_count; i++){ - Entity* e = &env->entities[env->active_agent_indices[i]]; - if(e->reached_goal_this_episode){ - env->log.completion_rate += 1.0f; - } - int offroad = env->logs[i].offroad_rate; - env->log.offroad_rate += offroad; - int collided = env->logs[i].collision_rate; - env->log.collision_rate += collided; - int clean_collided = env->logs[i].clean_collision_rate; - env->log.clean_collision_rate += clean_collided; - if(e->reached_goal_this_episode && !e->collided_before_goal){ - env->log.score += 1.0f; - env->log.perf += 1.0f; - } - if(!offroad && !collided && !e->reached_goal_this_episode){ - env->log.dnf_rate += 1.0f; - } - env->log.episode_length += env->logs[i].episode_length; - env->log.episode_return += env->logs[i].episode_return; - env->log.n += 1; - } -} - -Entity* load_map_binary(const char* filename, Drive* env) { - FILE* file = fopen(filename, "rb"); - if (!file) return NULL; - fread(&env->num_objects, sizeof(int), 1, file); - fread(&env->num_roads, sizeof(int), 1, file); - env->num_entities = env->num_objects + env->num_roads; - Entity* entities = (Entity*)malloc(env->num_entities * sizeof(Entity)); - for (int i = 0; i < env->num_entities; i++) { - // Read base entity data - fread(&entities[i].type, sizeof(int), 1, file); - fread(&entities[i].array_size, sizeof(int), 1, file); - // Allocate arrays based on type - int size = entities[i].array_size; - entities[i].traj_x = (float*)malloc(size * sizeof(float)); - entities[i].traj_y = (float*)malloc(size * sizeof(float)); - entities[i].traj_z = (float*)malloc(size * sizeof(float)); - if (entities[i].type == 1 || entities[i].type == 2 || entities[i].type == 3) { // Object type - // Allocate arrays for object-specific data - entities[i].traj_vx = (float*)malloc(size * sizeof(float)); - entities[i].traj_vy = (float*)malloc(size * sizeof(float)); - entities[i].traj_vz = (float*)malloc(size * sizeof(float)); - entities[i].traj_heading = (float*)malloc(size * sizeof(float)); - entities[i].traj_valid = (int*)malloc(size * sizeof(int)); - } else { - // Roads don't use these arrays - entities[i].traj_vx = NULL; - entities[i].traj_vy = NULL; - entities[i].traj_vz = NULL; - entities[i].traj_heading = NULL; - entities[i].traj_valid = NULL; - } - // Read array data - fread(entities[i].traj_x, sizeof(float), size, file); - fread(entities[i].traj_y, sizeof(float), size, file); - fread(entities[i].traj_z, sizeof(float), size, file); - if (entities[i].type == 1 || entities[i].type == 2 || entities[i].type == 3) { // Object type - fread(entities[i].traj_vx, sizeof(float), size, file); - fread(entities[i].traj_vy, sizeof(float), size, file); - fread(entities[i].traj_vz, sizeof(float), size, file); - fread(entities[i].traj_heading, sizeof(float), size, file); - fread(entities[i].traj_valid, sizeof(int), size, file); - } - // Read remaining scalar fields - fread(&entities[i].width, sizeof(float), 1, file); - fread(&entities[i].length, sizeof(float), 1, file); - fread(&entities[i].height, sizeof(float), 1, file); - fread(&entities[i].goal_position_x, sizeof(float), 1, file); - fread(&entities[i].goal_position_y, sizeof(float), 1, file); - fread(&entities[i].goal_position_z, sizeof(float), 1, file); - fread(&entities[i].mark_as_expert, sizeof(int), 1, file); - } - fclose(file); - return entities; -} - -void set_start_position(Drive* env){ - //InitWindow(800, 600, "GPU Drive"); - //BeginDrawing(); - for(int i = 0; i < env->num_entities; i++){ - int is_active = 0; - for(int j = 0; j < env->active_agent_count; j++){ - if(env->active_agent_indices[j] == i){ - is_active = 1; - break; - } - } - Entity* e = &env->entities[i]; - e->x = e->traj_x[0]; - e->y = e->traj_y[0]; - e->z = e->traj_z[0]; - //printf("Entity %d is at (%f, %f, %f)\n", i, e->x, e->y, e->z); - //if (e->type < 4) { - // DrawRectangle(200+2*e->x, 200+2*e->y, 2.0, 2.0, RED); - //} - if(e->type >3 || e->type == 0){ - continue; - } - if(is_active == 0){ - e->vx = 0; - e->vy = 0; - e->vz = 0; - e->reached_goal = 0; - e->collided_before_goal = 0; - } else{ - e->vx = e->traj_vx[0]; - e->vy = e->traj_vy[0]; - e->vz = e->traj_vz[0]; - } - e->heading = e->traj_heading[0]; - e->heading_x = cosf(e->heading); - e->heading_y = sinf(e->heading); - e->valid = e->traj_valid[0]; - e->collision_state = 0; - e->respawn_timestep = -1; - } - //EndDrawing(); - int x = 0; - - -} - -int getGridIndex(Drive* env, float x1, float y1) { - if (env->map_corners[0] >= env->map_corners[2] || env->map_corners[1] >= env->map_corners[3]) { - printf("Invalid grid coordinates\n"); - return -1; // Invalid grid coordinates - } - float worldWidth = env->map_corners[2] - env->map_corners[0]; // Positive value - float worldHeight = env->map_corners[3] - env->map_corners[1]; // Positive value - int cellsX = (int)ceil(worldWidth / GRID_CELL_SIZE); // Number of columns - int cellsY = (int)ceil(worldHeight / GRID_CELL_SIZE); // Number of rows - float relativeX = x1 - env->map_corners[0]; // Distance from left - float relativeY = y1 - env->map_corners[1]; // Distance from top - int gridX = (int)(relativeX / GRID_CELL_SIZE); // Column index - int gridY = (int)(relativeY / GRID_CELL_SIZE); // Row index - if (gridX < 0 || gridX >= cellsX || gridY < 0 || gridY >= cellsY) { - return -1; // Return -1 for out of bounds - } - int index = (gridY*cellsX) + gridX; - return index; -} - -void add_entity_to_grid(Drive* env, int grid_index, int entity_idx, int geometry_idx){ - if(grid_index == -1){ - return; - } - int base_index = grid_index * SLOTS_PER_CELL; - int count = env->grid_cells[base_index]; - if(count>= MAX_ENTITIES_PER_CELL) return; - env->grid_cells[base_index + count*2 + 1] = entity_idx; - env->grid_cells[base_index + count*2 + 2] = geometry_idx; - env->grid_cells[base_index] = count + 1; - -} - -void init_grid_map(Drive* env){ - // Find top left and bottom right points of the map - float top_left_x; - float top_left_y; - float bottom_right_x; - float bottom_right_y; - int first_valid_point = 0; - for(int i = 0; i < env->num_entities; i++){ - if(env->entities[i].type > 3 && env->entities[i].type < 7){ - // Check all points in the trajectory for road elements - Entity* e = &env->entities[i]; - for(int j = 0; j < e->array_size; j++){ - if(e->traj_x[j] == -10000) continue; - if(e->traj_y[j] == -10000) continue; - if(!first_valid_point) { - top_left_x = bottom_right_x = e->traj_x[j]; - top_left_y = bottom_right_y = e->traj_y[j]; - first_valid_point = true; - continue; - } - if(e->traj_x[j] < top_left_x) top_left_x = e->traj_x[j]; - if(e->traj_x[j] > bottom_right_x) bottom_right_x = e->traj_x[j]; - if(e->traj_y[j] < top_left_y) top_left_y = e->traj_y[j]; - if(e->traj_y[j] > bottom_right_y) bottom_right_y = e->traj_y[j]; - } - } - } - - env->map_corners = (float*)calloc(4, sizeof(float)); - env->map_corners[0] = top_left_x; - env->map_corners[1] = top_left_y; - env->map_corners[2] = bottom_right_x; - env->map_corners[3] = bottom_right_y; - - // Calculate grid dimensions - float grid_width = bottom_right_x - top_left_x; - float grid_height = bottom_right_y - top_left_y; - env->grid_cols = ceil(grid_width / GRID_CELL_SIZE); - env->grid_rows = ceil(grid_height / GRID_CELL_SIZE); - int grid_cell_count = env->grid_cols*env->grid_rows; - env->grid_cells = (int*)calloc(grid_cell_count*SLOTS_PER_CELL, sizeof(int)); - // Populate grid cells - for(int i = 0; i < env->num_entities; i++){ - if(env->entities[i].type > 3 && env->entities[i].type < 7){ - for(int j = 0; j < env->entities[i].array_size - 1; j++){ - float x_center = (env->entities[i].traj_x[j] + env->entities[i].traj_x[j+1]) / 2; - float y_center = (env->entities[i].traj_y[j] + env->entities[i].traj_y[j+1]) / 2; - int grid_index = getGridIndex(env, x_center, y_center); - add_entity_to_grid(env, grid_index, i, j); - } - } - } -} - -void init_neighbor_offsets(Drive* env) { - // Allocate memory for the offsets - env->neighbor_offsets = (int*)calloc(env->vision_range*env->vision_range*2, sizeof(int)); - // neighbor offsets in a spiral pattern - int dx[] = {1, 0, -1, 0}; - int dy[] = {0, 1, 0, -1}; - int x = 0; // Current x offset - int y = 0; // Current y offset - int dir = 0; // Current direction (0: right, 1: up, 2: left, 3: down) - int steps_to_take = 1; // Number of steps in current direction - int steps_taken = 0; // Steps taken in current direction - int segments_completed = 0; // Count of direction segments completed - int total = 0; // Total offsets added - int max_offsets = env->vision_range*env->vision_range; - // Start at center (0,0) - int curr_idx = 0; - env->neighbor_offsets[curr_idx++] = 0; // x offset - env->neighbor_offsets[curr_idx++] = 0; // y offset - total++; - // Generate spiral pattern - while (total < max_offsets) { - // Move in current direction - x += dx[dir]; - y += dy[dir]; - // Only add if within vision range bounds - if (abs(x) <= env->vision_range/2 && abs(y) <= env->vision_range/2) { - env->neighbor_offsets[curr_idx++] = x; - env->neighbor_offsets[curr_idx++] = y; - total++; - } - steps_taken++; - // Check if we need to change direction - if(steps_taken != steps_to_take) continue; - steps_taken = 0; // Reset steps taken - dir = (dir + 1) % 4; // Change direction (clockwise: right->up->left->down) - segments_completed++; - // Increase step length every two direction changes - if (segments_completed % 2 == 0) { - steps_to_take++; - } - } -} - -void cache_neighbor_offsets(Drive* env){ - int count = 0; - int cell_count = env->grid_cols*env->grid_rows; - for(int i = 0; i < cell_count; i++){ - int cell_x = i % env->grid_cols; // Convert to 2D coordinates - int cell_y = i / env->grid_cols; - env->neighbor_cache_indices[i] = count; - for(int j = 0; j< env->vision_range*env->vision_range; j++){ - int x = cell_x + env->neighbor_offsets[j*2]; - int y = cell_y + env->neighbor_offsets[j*2+1]; - int grid_index = env->grid_cols*y + x; - if(x < 0 || x >= env->grid_cols || y < 0 || y >= env->grid_rows) continue; - int grid_count = env->grid_cells[grid_index*SLOTS_PER_CELL]; - count += grid_count * 2; - } - } - env->neighbor_cache_indices[cell_count] = count; - env->neighbor_cache_entities = (int*)calloc(count, sizeof(int)); - for(int i = 0; i < cell_count; i ++){ - int neighbor_cache_base_index = 0; - int cell_x = i % env->grid_cols; // Convert to 2D coordinates - int cell_y = i / env->grid_cols; - for(int j = 0; jvision_range*env->vision_range; j++){ - int x = cell_x + env->neighbor_offsets[j*2]; - int y = cell_y + env->neighbor_offsets[j*2+1]; - int grid_index = env->grid_cols*y + x; - if(x < 0 || x >= env->grid_cols || y < 0 || y >= env->grid_rows) continue; - int grid_count = env->grid_cells[grid_index*SLOTS_PER_CELL]; - int base_index = env->neighbor_cache_indices[i]; - int src_idx = grid_index*SLOTS_PER_CELL + 1; - int dst_idx = base_index + neighbor_cache_base_index; - // Copy grid_count pairs (entity_idx, geometry_idx) at once - memcpy(&env->neighbor_cache_entities[dst_idx], - &env->grid_cells[src_idx], - grid_count * 2 * sizeof(int)); - - // Update index outside the loop - neighbor_cache_base_index += grid_count * 2; - } - } -} - -int get_neighbor_cache_entities(Drive* env, int cell_idx, int* entities, int max_entities) { - if (cell_idx < 0 || cell_idx >= (env->grid_cols * env->grid_rows)) { - return 0; // Invalid cell index - } - int base_index = env->neighbor_cache_indices[cell_idx]; - int end_index = env->neighbor_cache_indices[cell_idx + 1]; - int count = end_index - base_index; - int pairs = count / 2; // Entity ID and geometry ID pairs - // Limit to available space - if (pairs > max_entities) { - pairs = max_entities; - count = pairs * 2; - } - memcpy(entities, env->neighbor_cache_entities + base_index, count * sizeof(int)); - return pairs; -} - -void set_means(Drive* env) { - float mean_x = 0.0f; - float mean_y = 0.0f; - int64_t point_count = 0; - - // Compute single mean for all entities (vehicles and roads) - for (int i = 0; i < env->num_entities; i++) { - if (env->entities[i].type == VEHICLE) { - for (int j = 0; j < env->entities[i].array_size; j++) { - // Assume a validity flag exists (e.g., valid[j]); adjust if not available - if (env->entities[i].traj_valid[j]) { // Add validity check if applicable - point_count++; - mean_x += (env->entities[i].traj_x[j] - mean_x) / point_count; - mean_y += (env->entities[i].traj_y[j] - mean_y) / point_count; - } - } - } else if (env->entities[i].type >= 4) { - for (int j = 0; j < env->entities[i].array_size; j++) { - point_count++; - mean_x += (env->entities[i].traj_x[j] - mean_x) / point_count; - mean_y += (env->entities[i].traj_y[j] - mean_y) / point_count; - } - } - } - env->world_mean_x = mean_x; - env->world_mean_y = mean_y; - for (int i = 0; i < env->num_entities; i++) { - if (env->entities[i].type == VEHICLE || env->entities[i].type >= 4) { - for (int j = 0; j < env->entities[i].array_size; j++) { - if(env->entities[i].traj_x[j] == -10000) continue; - env->entities[i].traj_x[j] -= mean_x; - env->entities[i].traj_y[j] -= mean_y; - } - env->entities[i].goal_position_x -= mean_x; - env->entities[i].goal_position_y -= mean_y; - } - } - -} - -void move_expert(Drive* env, int* actions, int agent_idx){ - Entity* agent = &env->entities[agent_idx]; - agent->x = agent->traj_x[env->timestep]; - agent->y = agent->traj_y[env->timestep]; - agent->z = agent->traj_z[env->timestep]; - agent->heading = agent->traj_heading[env->timestep]; - agent->heading_x = cosf(agent->heading); - agent->heading_y = sinf(agent->heading); -} - -bool check_line_intersection(float p1[2], float p2[2], float q1[2], float q2[2]) { - if (fmax(p1[0], p2[0]) < fmin(q1[0], q2[0]) || fmin(p1[0], p2[0]) > fmax(q1[0], q2[0]) || - fmax(p1[1], p2[1]) < fmin(q1[1], q2[1]) || fmin(p1[1], p2[1]) > fmax(q1[1], q2[1])) - return false; - - // Calculate vectors - float dx1 = p2[0] - p1[0]; - float dy1 = p2[1] - p1[1]; - float dx2 = q2[0] - q1[0]; - float dy2 = q2[1] - q1[1]; - - // Calculate cross products - float cross = dx1 * dy2 - dy1 * dx2; - - // If lines are parallel - if (cross == 0) return false; - - // Calculate relative vectors between start points - float dx3 = p1[0] - q1[0]; - float dy3 = p1[1] - q1[1]; - - // Calculate parameters for intersection point - float s = (dx1 * dy3 - dy1 * dx3) / cross; - float t = (dx2 * dy3 - dy2 * dx3) / cross; - - // Check if intersection point lies within both line segments - return (s >= 0 && s <= 1 && t >= 0 && t <= 1); -} - -int checkNeighbors(Drive* env, float x, float y, int* entity_list, int max_size, const int (*local_offsets)[2], int offset_size) { - // Get the grid index for the given position (x, y) - int index = getGridIndex(env, x, y); - if (index == -1) return 0; // Return 0 size if position invalid - // Calculate 2D grid coordinates - int cellsX = env->grid_cols; - int gridX = index % cellsX; - int gridY = index / cellsX; - int entity_list_count = 0; - // Fill the provided array - for (int i = 0; i < offset_size; i++) { - int nx = gridX + local_offsets[i][0]; - int ny = gridY + local_offsets[i][1]; - // Ensure the neighbor is within grid bounds - if(nx < 0 || nx >= env->grid_cols || ny < 0 || ny >= env->grid_rows) continue; - int neighborIndex = (ny * env->grid_cols + nx) * SLOTS_PER_CELL; - int count = env->grid_cells[neighborIndex]; - // Add entities from this cell to the list - for (int j = 0; j < count && entity_list_count < max_size; j++) { - int entityId = env->grid_cells[neighborIndex + 1 + j*2]; - int geometry_idx = env->grid_cells[neighborIndex + 2 + j*2]; - entity_list[entity_list_count] = entityId; - entity_list[entity_list_count + 1] = geometry_idx; - entity_list_count += 2; - } - } - return entity_list_count; -} - -int check_aabb_collision(Entity* car1, Entity* car2) { - // Get car corners in world space - float cos1 = car1->heading_x; - float sin1 = car1->heading_y; - float cos2 = car2->heading_x; - float sin2 = car2->heading_y; - - // Calculate half dimensions - float half_len1 = car1->length * 0.5f; - float half_width1 = car1->width * 0.5f; - float half_len2 = car2->length * 0.5f; - float half_width2 = car2->width * 0.5f; - - // Calculate car1's corners in world space - float car1_corners[4][2] = { - {car1->x + (half_len1 * cos1 - half_width1 * sin1), car1->y + (half_len1 * sin1 + half_width1 * cos1)}, - {car1->x + (half_len1 * cos1 + half_width1 * sin1), car1->y + (half_len1 * sin1 - half_width1 * cos1)}, - {car1->x + (-half_len1 * cos1 - half_width1 * sin1), car1->y + (-half_len1 * sin1 + half_width1 * cos1)}, - {car1->x + (-half_len1 * cos1 + half_width1 * sin1), car1->y + (-half_len1 * sin1 - half_width1 * cos1)} - }; - - // Calculate car2's corners in world space - float car2_corners[4][2] = { - {car2->x + (half_len2 * cos2 - half_width2 * sin2), car2->y + (half_len2 * sin2 + half_width2 * cos2)}, - {car2->x + (half_len2 * cos2 + half_width2 * sin2), car2->y + (half_len2 * sin2 - half_width2 * cos2)}, - {car2->x + (-half_len2 * cos2 - half_width2 * sin2), car2->y + (-half_len2 * sin2 + half_width2 * cos2)}, - {car2->x + (-half_len2 * cos2 + half_width2 * sin2), car2->y + (-half_len2 * sin2 - half_width2 * cos2)} - }; - - // Get the axes to check (normalized vectors perpendicular to each edge) - float axes[4][2] = { - {cos1, sin1}, // Car1's length axis - {-sin1, cos1}, // Car1's width axis - {cos2, sin2}, // Car2's length axis - {-sin2, cos2} // Car2's width axis - }; - - // Check each axis - for(int i = 0; i < 4; i++) { - float min1 = INFINITY, max1 = -INFINITY; - float min2 = INFINITY, max2 = -INFINITY; - - // Project car1's corners onto the axis - for(int j = 0; j < 4; j++) { - float proj = car1_corners[j][0] * axes[i][0] + car1_corners[j][1] * axes[i][1]; - min1 = fminf(min1, proj); - max1 = fmaxf(max1, proj); - } - - // Project car2's corners onto the axis - for(int j = 0; j < 4; j++) { - float proj = car2_corners[j][0] * axes[i][0] + car2_corners[j][1] * axes[i][1]; - min2 = fminf(min2, proj); - max2 = fmaxf(max2, proj); - } - - // If there's a gap on this axis, the boxes don't intersect - if(max1 < min2 || min1 > max2) { - return 0; // No collision - } - } - - // If we get here, there's no separating axis, so the boxes intersect - return 1; // Collision -} - -int collision_check(Drive* env, int agent_idx) { - Entity* agent = &env->entities[agent_idx]; - if(agent->x == -10000.0f ) return -1; - float half_length = agent->length/2.0f; - float half_width = agent->width/2.0f; - float cos_heading = cosf(agent->heading); - float sin_heading = sinf(agent->heading); - float corners[4][2]; - for (int i = 0; i < 4; i++) { - corners[i][0] = agent->x + (offsets[i][0]*half_length*cos_heading - offsets[i][1]*half_width*sin_heading); - corners[i][1] = agent->y + (offsets[i][0]*half_length*sin_heading + offsets[i][1]*half_width*cos_heading); - } - int collided = 0; - int car_collided_with_index = -1; - int entity_list[MAX_ENTITIES_PER_CELL*2*25]; // Array big enough for all neighboring cells - int list_size = checkNeighbors(env, agent->x, agent->y, entity_list, MAX_ENTITIES_PER_CELL*2*25, collision_offsets, 25); - for (int i = 0; i < list_size ; i+=2) { - if(entity_list[i] == -1) continue; - if(entity_list[i] == agent_idx) continue; - Entity* entity; - entity = &env->entities[entity_list[i]]; - if(entity->type != ROAD_EDGE) continue; - int geometry_idx = entity_list[i + 1]; - float start[2] = {entity->traj_x[geometry_idx], entity->traj_y[geometry_idx]}; - float end[2] = {entity->traj_x[geometry_idx + 1], entity->traj_y[geometry_idx + 1]}; - for (int k = 0; k < 4; k++) { // Check each edge of the bounding box - int next = (k + 1) % 4; - if (check_line_intersection(corners[k], corners[next], start, end)) { - collided = OFFROAD; - break; - } - } - if (collided == OFFROAD) break; - } - for(int i = 0; i < MAX_CARS; i++){ - int index = -1; - if(i < env->active_agent_count){ - index = env->active_agent_indices[i]; - } else if (i < env->num_cars){ - index = env->static_car_indices[i - env->active_agent_count]; - } - if(index == -1) continue; - if(index == agent_idx) continue; - Entity* entity = &env->entities[index]; - float x1 = entity->x; - float y1 = entity->y; - float dist = ((x1 - agent->x)*(x1 - agent->x) + (y1 - agent->y)*(y1 - agent->y)); - if(dist > 225.0f) continue; - if(check_aabb_collision(agent, entity)) { - collided = VEHICLE_COLLISION; - car_collided_with_index = index; - break; - } - } - agent->collision_state = collided; - // spawn immunity for collisions with other agent cars as agent_idx respawns - int is_active_agent = env->entities[agent_idx].active_agent; - int respawned = env->entities[agent_idx].respawn_timestep != -1; - int exceeded_spawn_immunity_agent = (env->timestep - env->entities[agent_idx].respawn_timestep) >= env->spawn_immunity_timer; - if(collided == VEHICLE_COLLISION && is_active_agent == 1 && respawned){ - agent->collision_state = 0; - } - - // spawn immunity for collisions with other cars who just respawned - if(collided == OFFROAD) return -1; - if(car_collided_with_index ==-1) return -1; - - int respawned_collided_with_car = env->entities[car_collided_with_index].respawn_timestep != -1; - int exceeded_spawn_immunity_collided_with_car = (env->timestep - env->entities[car_collided_with_index].respawn_timestep) >= env->spawn_immunity_timer; - int within_spawn_immunity_collided_with_car = (env->timestep - env->entities[car_collided_with_index].respawn_timestep) < env->spawn_immunity_timer; - if (respawned_collided_with_car) { - agent->collision_state = 0; - } - - return car_collided_with_index; -} - -int valid_active_agent(Drive* env, int agent_idx){ - float cos_heading = cosf(env->entities[agent_idx].traj_heading[0]); - float sin_heading = sinf(env->entities[agent_idx].traj_heading[0]); - float goal_x = env->entities[agent_idx].goal_position_x - env->entities[agent_idx].traj_x[0]; - float goal_y = env->entities[agent_idx].goal_position_y - env->entities[agent_idx].traj_y[0]; - // Rotate to ego vehicle's frame - float rel_goal_x = goal_x*cos_heading + goal_y*sin_heading; - float rel_goal_y = -goal_x*sin_heading + goal_y*cos_heading; - float distance_to_goal = relative_distance_2d(0, 0, rel_goal_x, rel_goal_y); - env->entities[agent_idx].width *= 0.7f; - env->entities[agent_idx].length *= 0.7f; - if(distance_to_goal >= 2.0f && env->entities[agent_idx].mark_as_expert == 0 && env->active_agent_count < env->num_agents){ - return distance_to_goal; - } - return 0; -} - -void set_active_agents(Drive* env){ - env->active_agent_count = 0; - env->static_car_count = 0; - env->num_cars = 1; - env->expert_static_car_count = 0; - int active_agent_indices[MAX_CARS]; - int static_car_indices[MAX_CARS]; - int expert_static_car_indices[MAX_CARS]; - - if(env->num_agents ==0){ - env->num_agents = MAX_CARS; - } - int first_agent_id = env->num_objects-1; - float distance_to_goal = valid_active_agent(env, first_agent_id); - if(distance_to_goal){ - env->active_agent_count = 1; - active_agent_indices[0] = first_agent_id; - env->entities[first_agent_id].active_agent = 1; - env->num_cars = 1; - } else { - env->active_agent_count = 0; - env->num_cars = 0; - } - for(int i = 0; i < env->num_objects-1 && env->num_cars < MAX_CARS; i++){ - if(env->entities[i].type != 1) continue; - if(env->entities[i].traj_valid[0] != 1) continue; - env->num_cars++; - float distance_to_goal = valid_active_agent(env, i); - if(distance_to_goal > 0){ - active_agent_indices[env->active_agent_count] = i; - env->active_agent_count++; - env->entities[i].active_agent = 1; - } else { - static_car_indices[env->static_car_count] = i; - env->static_car_count++; - env->entities[i].active_agent = 0; - if(env->entities[i].mark_as_expert == 1 || (distance_to_goal >=2.0f && env->active_agent_count == env->num_agents)){ - expert_static_car_indices[env->expert_static_car_count] = i; - env->expert_static_car_count++; - env->entities[i].mark_as_expert = 1; - } - } - } - // set up initial active agents - env->active_agent_indices = (int*)malloc(env->active_agent_count * sizeof(int)); - env->static_car_indices = (int*)malloc(env->static_car_count * sizeof(int)); - env->expert_static_car_indices = (int*)malloc(env->expert_static_car_count * sizeof(int)); - for(int i=0;iactive_agent_count;i++){ - env->active_agent_indices[i] = active_agent_indices[i]; - }; - for(int i=0;istatic_car_count;i++){ - env->static_car_indices[i] = static_car_indices[i]; - - } - for(int i=0;iexpert_static_car_count;i++){ - env->expert_static_car_indices[i] = expert_static_car_indices[i]; - } - return; -} - -void remove_bad_trajectories(Drive* env){ - set_start_position(env); - int legal_agent_count = 0; - int legal_trajectories[env->active_agent_count]; - int collided_agents[env->active_agent_count]; - int collided_with_indices[env->active_agent_count]; - memset(collided_agents, 0, env->active_agent_count * sizeof(int)); - // move experts through trajectories to check for collisions and remove as illegal agents - for(int t = 0; t < TRAJECTORY_LENGTH; t++){ - for(int i = 0; i < env->active_agent_count; i++){ - int agent_idx = env->active_agent_indices[i]; - move_expert(env, env->actions, agent_idx); - } - for(int i = 0; i < env->expert_static_car_count; i++){ - int expert_idx = env->expert_static_car_indices[i]; - if(env->entities[expert_idx].x == -10000) continue; - move_expert(env, env->actions, expert_idx); - } - // check collisions - for(int i = 0; i < env->active_agent_count; i++){ - int agent_idx = env->active_agent_indices[i]; - env->entities[agent_idx].collision_state = 0; - int collided_with_index = collision_check(env, agent_idx); - if(env->entities[agent_idx].collision_state > 0 && collided_agents[i] == 0){ - collided_agents[i] = 1; - collided_with_indices[i] = collided_with_index; - } - } - env->timestep++; - } - - for(int i = 0; i< env->active_agent_count; i++){ - if(collided_with_indices[i] == -1) continue; - for(int j = 0; j < env->static_car_count; j++){ - int static_car_idx = env->static_car_indices[j]; - if(static_car_idx != collided_with_indices[i]) continue; - env->entities[static_car_idx].traj_x[0] = -10000; - env->entities[static_car_idx].traj_y[0] = -10000; - } - } - env->timestep = 0; -} -void init(Drive* env){ - env->human_agent_idx = 0; - env->timestep = 0; - env->entities = load_map_binary(env->map_name, env); - env->dynamics_model = CLASSIC; - set_means(env); - init_grid_map(env); - env->vision_range = 21; - init_neighbor_offsets(env); - env->neighbor_cache_indices = (int*)calloc((env->grid_cols*env->grid_rows) + 1, sizeof(int)); - cache_neighbor_offsets(env); - set_active_agents(env); - remove_bad_trajectories(env); - set_start_position(env); - env->logs = (Log*)calloc(env->active_agent_count, sizeof(Log)); -} - -void c_close(Drive* env){ - for(int i = 0; i < env->num_entities; i++){ - free_entity(&env->entities[i]); - } - free(env->entities); - free(env->active_agent_indices); - free(env->logs); - free(env->map_corners); - free(env->grid_cells); - free(env->neighbor_offsets); - free(env->neighbor_cache_entities); - free(env->neighbor_cache_indices); - free(env->static_car_indices); - free(env->expert_static_car_indices); - // free(env->map_name); -} - -void allocate(Drive* env){ - init(env); - int max_obs = 7 + 7*(MAX_CARS - 1) + 7*MAX_ROAD_SEGMENT_OBSERVATIONS; - // printf("max obs: %d\n", max_obs*env->active_agent_count); - // printf("num cars: %d\n", env->num_cars); - // printf("num static cars: %d\n", env->static_car_count); - // printf("active agent count: %d\n", env->active_agent_count); - // printf("num objects: %d\n", env->num_objects); - env->observations = (float*)calloc(env->active_agent_count*max_obs, sizeof(float)); - env->actions = (int*)calloc(env->active_agent_count*2, sizeof(int)); - env->rewards = (float*)calloc(env->active_agent_count, sizeof(float)); - env->terminals= (unsigned char*)calloc(env->active_agent_count, sizeof(unsigned char)); - // printf("allocated\n"); -} - -void free_allocated(Drive* env){ - free(env->observations); - free(env->actions); - free(env->rewards); - free(env->terminals); - c_close(env); -} - -float clipSpeed(float speed) { - const float maxSpeed = MAX_SPEED; - if (speed > maxSpeed) return maxSpeed; - if (speed < -maxSpeed) return -maxSpeed; - return speed; -} - -float normalize_heading(float heading){ - if(heading > M_PI) heading -= 2*M_PI; - if(heading < -M_PI) heading += 2*M_PI; - return heading; -} - -void move_dynamics(Drive* env, int action_idx, int agent_idx){ - if(env->dynamics_model == CLASSIC){ - // clip acceleration & steering - Entity* agent = &env->entities[agent_idx]; - // Extract action components directly from the multi-discrete action array - int (*action_array)[2] = (int(*)[2])env->actions; - int acceleration_index = action_array[action_idx][0]; - int steering_index = action_array[action_idx][1]; - float acceleration = ACCELERATION_VALUES[acceleration_index]; - float steering = STEERING_VALUES[steering_index]; - - // Current state - float x = agent->x; - float y = agent->y; - float heading = agent->heading; - float vx = agent->vx; - float vy = agent->vy; - - // Calculate current speed - float speed = sqrtf(vx*vx + vy*vy); - - // Time step (adjust as needed) - const float dt = 0.1f; - // Update speed with acceleration - speed = speed + 0.5f*acceleration*dt; - // if (speed < 0) speed = 0; // Prevent going backward - speed = clipSpeed(speed); - // compute yaw rate - float beta = tanh(.5*tanf(steering)); - // new heading - float yaw_rate = (speed*cosf(beta)*tanf(steering)) / agent->length; - // new velocity - float new_vx = speed*cosf(heading + beta); - float new_vy = speed*sinf(heading + beta); - // Update position - x = x + (new_vx*dt); - y = y + (new_vy*dt); - heading = heading + yaw_rate*dt; - // heading = normalize_heading(heading); - // Apply updates to the agent's state - agent->x = x; - agent->y = y; - agent->heading = heading; - agent->heading_x = cosf(heading); - agent->heading_y = sinf(heading); - agent->vx = new_vx; - agent->vy = new_vy; - } - return; -} - -float normalize_value(float value, float min, float max){ - return (value - min) / (max - min); -} - -float reverse_normalize_value(float value, float min, float max){ - return value*50.0f; -} - -void compute_observations(Drive* env) { - int max_obs = 7 + 7*(MAX_CARS - 1) + 7*MAX_ROAD_SEGMENT_OBSERVATIONS; - memset(env->observations, 0, max_obs*env->active_agent_count*sizeof(float)); - float (*observations)[max_obs] = (float(*)[max_obs])env->observations; - for(int i = 0; i < env->active_agent_count; i++) { - float* obs = &observations[i][0]; - Entity* ego_entity = &env->entities[env->active_agent_indices[i]]; - if(ego_entity->type > 3) break; - if(ego_entity->respawn_timestep != -1) { - obs[6] = 1; - //continue; - } - float ego_heading = ego_entity->heading; - float cos_heading = ego_entity->heading_x; - float sin_heading = ego_entity->heading_y; - float ego_speed = sqrtf(ego_entity->vx*ego_entity->vx + ego_entity->vy*ego_entity->vy); - // Set goal distances - float goal_x = ego_entity->goal_position_x - ego_entity->x; - float goal_y = ego_entity->goal_position_y - ego_entity->y; - // Rotate to ego vehicle's frame - float rel_goal_x = goal_x*cos_heading + goal_y*sin_heading; - float rel_goal_y = -goal_x*sin_heading + goal_y*cos_heading; - //obs[0] = normalize_value(rel_goal_x, MIN_REL_GOAL_COORD, MAX_REL_GOAL_COORD); - //obs[1] = normalize_value(rel_goal_y, MIN_REL_GOAL_COORD, MAX_REL_GOAL_COORD); - obs[0] = rel_goal_x* 0.005f; - obs[1] = rel_goal_y* 0.005f; - //obs[2] = ego_speed / MAX_SPEED; - obs[2] = ego_speed * 0.01f; - obs[3] = ego_entity->width / MAX_VEH_WIDTH; - obs[4] = ego_entity->length / MAX_VEH_LEN; - obs[5] = (ego_entity->collision_state > 0) ? 1 : 0; - - // Relative Pos of other cars - int obs_idx = 7; // Start after goal distances - int cars_seen = 0; - for(int j = 0; j < MAX_CARS; j++) { - int index = -1; - if(j < env->active_agent_count){ - index = env->active_agent_indices[j]; - } else if (j < env->num_cars){ - index = env->static_car_indices[j - env->active_agent_count]; - } - if(index == -1) continue; - if(env->entities[index].type > 3) break; - if(index == env->active_agent_indices[i]) continue; // Skip self, but don't increment obs_idx - Entity* other_entity = &env->entities[index]; - if(ego_entity->respawn_timestep != -1) continue; - if(other_entity->respawn_timestep != -1) continue; - // Store original relative positions - float dx = other_entity->x - ego_entity->x; - float dy = other_entity->y - ego_entity->y; - float dist = (dx*dx + dy*dy); - if(dist > 2500.0f) continue; - // Rotate to ego vehicle's frame - float rel_x = dx*cos_heading + dy*sin_heading; - float rel_y = -dx*sin_heading + dy*cos_heading; - // Store observations with correct indexing - obs[obs_idx] = rel_x * 0.02f; - obs[obs_idx + 1] = rel_y * 0.02f; - obs[obs_idx + 2] = other_entity->width / MAX_VEH_WIDTH; - obs[obs_idx + 3] = other_entity->length / MAX_VEH_LEN; - // relative heading - float rel_heading_x = other_entity->heading_x * ego_entity->heading_x + - other_entity->heading_y * ego_entity->heading_y; // cos(a-b) = cos(a)cos(b) + sin(a)sin(b) - float rel_heading_y = other_entity->heading_y * ego_entity->heading_x - - other_entity->heading_x * ego_entity->heading_y; // sin(a-b) = sin(a)cos(b) - cos(a)sin(b) - - obs[obs_idx + 4] = rel_heading_x; - obs[obs_idx + 5] = rel_heading_y; - // obs[obs_idx + 4] = cosf(rel_heading) / MAX_ORIENTATION_RAD; - // obs[obs_idx + 5] = sinf(rel_heading) / MAX_ORIENTATION_RAD; - // // relative speed - float other_speed = sqrtf(other_entity->vx*other_entity->vx + other_entity->vy*other_entity->vy); - obs[obs_idx + 6] = other_speed / MAX_SPEED; - cars_seen++; - obs_idx += 7; // Move to next observation slot - } - int remaining_partner_obs = (MAX_CARS - 1 - cars_seen) * 7; - memset(&obs[obs_idx], 0, remaining_partner_obs * sizeof(float)); - obs_idx += remaining_partner_obs; - // map observations - int entity_list[MAX_ROAD_SEGMENT_OBSERVATIONS*2]; // Array big enough for all neighboring cells - int grid_idx = getGridIndex(env, ego_entity->x, ego_entity->y); - int list_size = get_neighbor_cache_entities(env, grid_idx, entity_list, MAX_ROAD_SEGMENT_OBSERVATIONS); - for(int k = 0; k < list_size; k++){ - int entity_idx = entity_list[k*2]; - int geometry_idx = entity_list[k*2+1]; - Entity* entity = &env->entities[entity_idx]; - float start_x = entity->traj_x[geometry_idx]; - float start_y = entity->traj_y[geometry_idx]; - float end_x = entity->traj_x[geometry_idx+1]; - float end_y = entity->traj_y[geometry_idx+1]; - float mid_x = (start_x + end_x) / 2.0f; - float mid_y = (start_y + end_y) / 2.0f; - float rel_x = mid_x - ego_entity->x; - float rel_y = mid_y - ego_entity->y; - float x_obs = rel_x*cos_heading + rel_y*sin_heading; - float y_obs = -rel_x*sin_heading + rel_y*cos_heading; - float length = relative_distance_2d(mid_x, mid_y, end_x, end_y); - float width = 0.1; - // Calculate angle from ego to midpoint (vector from ego to midpoint) - float dx = end_x - mid_x; - float dy = end_y - mid_y; - float dx_norm = dx; - float dy_norm = dy; - float hypot = sqrtf(dx*dx + dy*dy); - if(hypot > 0) { - dx_norm /= hypot; - dy_norm /= hypot; - } - // Compute sin and cos of relative angle directly without atan2f - float cos_angle = dx_norm*cos_heading + dy_norm*sin_heading; - float sin_angle = -dx_norm*sin_heading + dy_norm*cos_heading; - obs[obs_idx] = x_obs * 0.02f; - obs[obs_idx + 1] = y_obs * 0.02f; - obs[obs_idx + 2] = length / MAX_ROAD_SEGMENT_LENGTH; - obs[obs_idx + 3] = width / MAX_ROAD_SCALE; - obs[obs_idx + 4] = cos_angle; - obs[obs_idx + 5] = sin_angle; - obs[obs_idx + 6] = entity->type - 4.0f; - obs_idx += 7; - } - int remaining_obs = (MAX_ROAD_SEGMENT_OBSERVATIONS - list_size) * 7; - // Set the entire block to 0 at once - memset(&obs[obs_idx], 0, remaining_obs * sizeof(float)); - } -} - -void c_reset(Drive* env){ - env->timestep = 0; - set_start_position(env); - for(int x = 0;xactive_agent_count; x++){ - env->logs[x] = (Log){0}; - int agent_idx = env->active_agent_indices[x]; - env->entities[agent_idx].respawn_timestep = -1; - env->entities[agent_idx].reached_goal = 0; - env->entities[agent_idx].collided_before_goal = 0; - env->entities[agent_idx].reached_goal_this_episode = 0; - collision_check(env, agent_idx); - } - compute_observations(env); -} - -void respawn_agent(Drive* env, int agent_idx){ - env->entities[agent_idx].x = env->entities[agent_idx].traj_x[0]; - env->entities[agent_idx].y = env->entities[agent_idx].traj_y[0]; - env->entities[agent_idx].heading = env->entities[agent_idx].traj_heading[0]; - env->entities[agent_idx].heading_x = cosf(env->entities[agent_idx].heading); - env->entities[agent_idx].heading_y = sinf(env->entities[agent_idx].heading); - env->entities[agent_idx].vx = env->entities[agent_idx].traj_vx[0]; - env->entities[agent_idx].vy = env->entities[agent_idx].traj_vy[0]; - env->entities[agent_idx].reached_goal = 0; - env->entities[agent_idx].respawn_timestep = env->timestep; -} - -void c_step(Drive* env){ - memset(env->rewards, 0, env->active_agent_count * sizeof(float)); - memset(env->terminals, 0, env->active_agent_count * sizeof(unsigned char)); - env->timestep++; - if(env->timestep == TRAJECTORY_LENGTH){ - add_log(env); - c_reset(env); - return; - } - - // Move statix experts - for (int i = 0; i < env->expert_static_car_count; i++) { - int expert_idx = env->expert_static_car_indices[i]; - if(env->entities[expert_idx].x == -10000.0f) continue; - move_expert(env, env->actions, expert_idx); - } - // Process actions for all active agents - for(int i = 0; i < env->active_agent_count; i++){ - env->logs[i].score = 0.0f; - env->logs[i].episode_length += 1; - int agent_idx = env->active_agent_indices[i]; - env->entities[agent_idx].collision_state = 0; - move_dynamics(env, i, agent_idx); - // move_expert(env, env->actions, agent_idx); - } - for(int i = 0; i < env->active_agent_count; i++){ - int agent_idx = env->active_agent_indices[i]; - env->entities[agent_idx].collision_state = 0; - //if(env->entities[agent_idx].respawn_timestep != -1) continue; - collision_check(env, agent_idx); - int collision_state = env->entities[agent_idx].collision_state; - - if(collision_state > 0){ - if(collision_state == VEHICLE_COLLISION && env->entities[agent_idx].respawn_timestep == -1){ - if(env->entities[agent_idx].respawn_timestep != -1) { - env->rewards[i] = env->reward_vehicle_collision_post_respawn; - env->logs[i].episode_return += env->reward_vehicle_collision_post_respawn; - } else { - env->rewards[i] = env->reward_vehicle_collision; - env->logs[i].episode_return += env->reward_vehicle_collision; - env->logs[i].clean_collision_rate = 1.0f; - } - env->logs[i].collision_rate = 1.0f; - } - else if(collision_state == OFFROAD){ - env->rewards[i] = env->reward_offroad_collision; - env->logs[i].offroad_rate = 1.0f; - env->logs[i].episode_return += env->reward_offroad_collision; - } - if(!env->entities[agent_idx].reached_goal_this_episode){ - env->entities[agent_idx].collided_before_goal = 1; - } - //printf("agent %d collided\n", agent_idx); - } - - float distance_to_goal = relative_distance_2d( - env->entities[agent_idx].x, - env->entities[agent_idx].y, - env->entities[agent_idx].goal_position_x, - env->entities[agent_idx].goal_position_y); - if(distance_to_goal < 2.0f){ - if(env->entities[agent_idx].respawn_timestep != -1){ - env->rewards[i] += env->reward_goal_post_respawn; - env->logs[i].episode_return += env->reward_goal_post_respawn; - } else { - env->rewards[i] += 1.0f; - env->logs[i].episode_return += 1.0f; - //env->terminals[i] = 1; - } - env->entities[agent_idx].reached_goal = 1; - env->entities[agent_idx].reached_goal_this_episode = 1; - } - } - - for(int i = 0; i < env->active_agent_count; i++){ - int agent_idx = env->active_agent_indices[i]; - int reached_goal = env->entities[agent_idx].reached_goal; - int collision_state = env->entities[agent_idx].collision_state; - if(reached_goal){ - respawn_agent(env, agent_idx); - //env->entities[agent_idx].x = -10000; - //env->entities[agent_idx].y = -10000; - //env->entities[agent_idx].respawn_timestep = env->timestep; - } - } - compute_observations(env); -} - -const Color STONE_GRAY = (Color){80, 80, 80, 255}; -const Color PUFF_RED = (Color){187, 0, 0, 255}; -const Color PUFF_CYAN = (Color){0, 187, 187, 255}; -const Color PUFF_WHITE = (Color){241, 241, 241, 241}; -const Color PUFF_BACKGROUND = (Color){6, 24, 24, 255}; -const Color PUFF_BACKGROUND2 = (Color){18, 72, 72, 255}; - -typedef struct Client Client; -struct Client { - float width; - float height; - Texture2D puffers; - Vector3 camera_target; - float camera_zoom; - Camera3D camera; - Model cars[6]; - int car_assignments[MAX_CARS]; // To keep car model assignments consistent per vehicle - Vector3 default_camera_position; - Vector3 default_camera_target; -}; - -Client* make_client(Drive* env){ - Client* client = (Client*)calloc(1, sizeof(Client)); - client->width = 1280; - client->height = 704; - SetConfigFlags(FLAG_MSAA_4X_HINT); - InitWindow(client->width, client->height, "PufferLib Ray GPU Drive"); - SetTargetFPS(30); - client->puffers = LoadTexture("resources/puffers_128.png"); - client->cars[0] = LoadModel("resources/drive/RedCar.glb"); - client->cars[1] = LoadModel("resources/drive/WhiteCar.glb"); - client->cars[2] = LoadModel("resources/drive/BlueCar.glb"); - client->cars[3] = LoadModel("resources/drive/YellowCar.glb"); - client->cars[4] = LoadModel("resources/drive/GreenCar.glb"); - client->cars[5] = LoadModel("resources/drive/GreyCar.glb"); - for (int i = 0; i < MAX_CARS; i++) { - client->car_assignments[i] = (rand() % 4) + 1; - } - // Get initial target position from first active agent - float map_center_x = (env->map_corners[0] + env->map_corners[2]) / 2.0f; - float map_center_y = (env->map_corners[1] + env->map_corners[3]) / 2.0f; - Vector3 target_pos = { - 0, - 0, // Y is up - 1 // Z is depth - }; - - // Set up camera to look at target from above and behind - client->default_camera_position = (Vector3){ - 0, // Same X as target - 120.0f, // 20 units above target - 175.0f // 20 units behind target - }; - client->default_camera_target = target_pos; - client->camera.position = client->default_camera_position; - client->camera.target = client->default_camera_target; - client->camera.up = (Vector3){ 0.0f, -1.0f, 0.0f }; // Y is up - client->camera.fovy = 45.0f; - client->camera.projection = CAMERA_PERSPECTIVE; - client->camera_zoom = 1.0f; - return client; -} - -// Camera control functions -void handle_camera_controls(Client* client) { - static Vector2 prev_mouse_pos = {0}; - static bool is_dragging = false; - float camera_move_speed = 0.5f; - - // Handle mouse drag for camera movement - if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) { - prev_mouse_pos = GetMousePosition(); - is_dragging = true; - } - - if (IsMouseButtonReleased(MOUSE_BUTTON_LEFT)) { - is_dragging = false; - } - - if (is_dragging) { - Vector2 current_mouse_pos = GetMousePosition(); - Vector2 delta = { - (current_mouse_pos.x - prev_mouse_pos.x) * camera_move_speed, - -(current_mouse_pos.y - prev_mouse_pos.y) * camera_move_speed - }; - - // Update camera position (only X and Y) - client->camera.position.x += delta.x; - client->camera.position.y += delta.y; - - // Update camera target (only X and Y) - client->camera.target.x += delta.x; - client->camera.target.y += delta.y; - - prev_mouse_pos = current_mouse_pos; - } - - // Handle mouse wheel for zoom - float wheel = GetMouseWheelMove(); - if (wheel != 0) { - float zoom_factor = 1.0f - (wheel * 0.1f); - // Calculate the current direction vector from target to position - Vector3 direction = { - client->camera.position.x - client->camera.target.x, - client->camera.position.y - client->camera.target.y, - client->camera.position.z - client->camera.target.z - }; - - // Scale the direction vector by the zoom factor - direction.x *= zoom_factor; - direction.y *= zoom_factor; - direction.z *= zoom_factor; - - // Update the camera position based on the scaled direction - client->camera.position.x = client->camera.target.x + direction.x; - client->camera.position.y = client->camera.target.y + direction.y; - client->camera.position.z = client->camera.target.z + direction.z; - } -} - -void draw_agent_obs(Drive* env, int agent_index){ - // Diamond dimensions - float diamond_height = 3.0f; // Total height of diamond - float diamond_width = 1.5f; // Width of diamond - float diamond_z = 8.0f; // Base Z position - - // Define diamond points - Vector3 top_point = (Vector3){0.0f, 0.0f, diamond_z + diamond_height/2}; // Top point - Vector3 bottom_point = (Vector3){0.0f, 0.0f, diamond_z - diamond_height/2}; // Bottom point - Vector3 front_point = (Vector3){0.0f, diamond_width/2, diamond_z}; // Front point - Vector3 back_point = (Vector3){0.0f, -diamond_width/2, diamond_z}; // Back point - Vector3 left_point = (Vector3){-diamond_width/2, 0.0f, diamond_z}; // Left point - Vector3 right_point = (Vector3){diamond_width/2, 0.0f, diamond_z}; // Right point - - // Draw the diamond faces - // Top pyramid - DrawTriangle3D(top_point, front_point, right_point, PUFF_CYAN); // Front-right face - DrawTriangle3D(top_point, right_point, back_point, PUFF_CYAN); // Back-right face - DrawTriangle3D(top_point, back_point, left_point, PUFF_CYAN); // Back-left face - DrawTriangle3D(top_point, left_point, front_point, PUFF_CYAN); // Front-left face - - // Bottom pyramid - DrawTriangle3D(bottom_point, right_point, front_point, PUFF_CYAN); // Front-right face - DrawTriangle3D(bottom_point, back_point, right_point, PUFF_CYAN); // Back-right face - DrawTriangle3D(bottom_point, left_point, back_point, PUFF_CYAN); // Back-left face - DrawTriangle3D(bottom_point, front_point, left_point, PUFF_CYAN); // Front-left face - if(!IsKeyDown(KEY_LEFT_CONTROL)){ - return; - } - int max_obs = 7 + 7*(MAX_CARS - 1) + 7*MAX_ROAD_SEGMENT_OBSERVATIONS; - float (*observations)[max_obs] = (float(*)[max_obs])env->observations; - float* agent_obs = &observations[agent_index][0]; - // draw goal - float goal_x = agent_obs[0] * 200; - float goal_y = agent_obs[1] * 200; - DrawSphere((Vector3){goal_x, goal_y, 1}, 0.5f, GREEN); - // First draw other agent observations - int obs_idx = 7; // Start after goal distances - for(int j = 0; j < MAX_CARS - 1; j++) { - if(agent_obs[obs_idx] == 0 || agent_obs[obs_idx + 1] == 0) { - obs_idx += 7; // Move to next agent observation - continue; - } - // Draw position of other agents - float x = agent_obs[obs_idx] * 50; - float y = agent_obs[obs_idx + 1] * 50; - DrawLine3D( - (Vector3){0, 0, 0}, - (Vector3){x, y, 1}, - ORANGE - ); - float theta_x = agent_obs[obs_idx + 4]; - float theta_y = agent_obs[obs_idx + 5]; - float partner_angle = atan2f(theta_y, theta_x); - // draw an arrow above the car pointing in the direction that the partner is going - float arrow_length = 7.5f; - float arrow_x = x + arrow_length*cosf(partner_angle); - float arrow_y = y + arrow_length*sinf(partner_angle); - DrawLine3D((Vector3){x, y, 1}, (Vector3){arrow_x, arrow_y, 1}, PUFF_WHITE); - // Calculate perpendicular offsets for arrow head - float arrow_size = 2.0f; // Size of the arrow head - float dx = arrow_x - x; - float dy = arrow_y - y; - float length = sqrtf(dx*dx + dy*dy); - if (length > 0) { - // Normalize direction vector - dx /= length; - dy /= length; - - // Calculate perpendicular vector - float px = -dy * arrow_size; - float py = dx * arrow_size; - - // Draw the two lines forming the arrow head - DrawLine3D( - (Vector3){arrow_x, arrow_y, 1}, - (Vector3){arrow_x - dx*arrow_size + px, arrow_y - dy*arrow_size + py, 1}, - PUFF_WHITE - ); - DrawLine3D( - (Vector3){arrow_x, arrow_y, 1}, - (Vector3){arrow_x - dx*arrow_size - px, arrow_y - dy*arrow_size - py, 1}, - PUFF_WHITE - ); - } - obs_idx += 7; // Move to next agent observation (7 values per agent) - } - // Then draw map observations - int map_start_idx = 7 + 7*(MAX_CARS - 1); // Start after agent observations - for(int k = 0; k < MAX_ROAD_SEGMENT_OBSERVATIONS; k++) { // Loop through potential map entities - int entity_idx = map_start_idx + k*7; - if(agent_obs[entity_idx] == 0 && agent_obs[entity_idx + 1] == 0){ - continue; - } - Color lineColor = BLUE; // Default color - int entity_type = (int)agent_obs[entity_idx + 6]; - // Choose color based on entity type - if(entity_type+4 != ROAD_EDGE){ - continue; - } - lineColor = PUFF_CYAN; - // For road segments, draw line between start and end points - float x_middle = agent_obs[entity_idx] * 50; - float y_middle = agent_obs[entity_idx + 1] * 50; - float rel_angle_x = (agent_obs[entity_idx + 4]); - float rel_angle_y = (agent_obs[entity_idx + 5]); - float rel_angle = atan2f(rel_angle_y, rel_angle_x); - float segment_length = agent_obs[entity_idx + 2] * MAX_ROAD_SEGMENT_LENGTH; - // Calculate endpoint using the relative angle directly - // Calculate endpoint directly - float x_start = x_middle - segment_length*cosf(rel_angle); - float y_start = y_middle - segment_length*sinf(rel_angle); - float x_end = x_middle + segment_length*cosf(rel_angle); - float y_end = y_middle + segment_length*sinf(rel_angle); - DrawLine3D((Vector3){0,0,0}, (Vector3){x_middle, y_middle, 1}, lineColor); - DrawCube((Vector3){x_middle, y_middle, 1}, 0.5f, 0.5f, 0.5f, lineColor); - DrawLine3D((Vector3){x_start, y_start, 1}, (Vector3){x_end, y_end, 1}, BLUE); - } -} - -void draw_road_edge(Drive* env, float start_x, float start_y, float end_x, float end_y){ - Color CURB_TOP = (Color){220, 220, 220, 255}; // Top surface - lightest - Color CURB_SIDE = (Color){180, 180, 180, 255}; // Side faces - medium - Color CURB_BOTTOM = (Color){160, 160, 160, 255}; - // Calculate curb dimensions - float curb_height = 0.5f; // Height of the curb - float curb_width = 0.3f; // Width/thickness of the curb - - // Calculate direction vector between start and end - Vector3 direction = { - end_x - start_x, - end_y - start_y, - 0.0f - }; - - // Calculate length of the segment - float length = sqrtf(direction.x * direction.x + direction.y * direction.y); - - // Normalize direction vector - Vector3 normalized_dir = { - direction.x / length, - direction.y / length, - 0.0f - }; - - // Calculate perpendicular vector for width - Vector3 perpendicular = { - -normalized_dir.y, - normalized_dir.x, - 0.0f - }; - - // Calculate the four bottom corners of the curb - Vector3 b1 = { - start_x - perpendicular.x * curb_width/2, - start_y - perpendicular.y * curb_width/2, - 1.0f - }; - Vector3 b2 = { - start_x + perpendicular.x * curb_width/2, - start_y + perpendicular.y * curb_width/2, - 1.0f - }; - Vector3 b3 = { - end_x + perpendicular.x * curb_width/2, - end_y + perpendicular.y * curb_width/2, - 1.0f - }; - Vector3 b4 = { - end_x - perpendicular.x * curb_width/2, - end_y - perpendicular.y * curb_width/2, - 1.0f - }; - - // Draw the curb faces - // Bottom face - DrawTriangle3D(b1, b2, b3, CURB_BOTTOM); - DrawTriangle3D(b1, b3, b4, CURB_BOTTOM); - - // Top face (raised by curb_height) - Vector3 t1 = {b1.x, b1.y, b1.z + curb_height}; - Vector3 t2 = {b2.x, b2.y, b2.z + curb_height}; - Vector3 t3 = {b3.x, b3.y, b3.z + curb_height}; - Vector3 t4 = {b4.x, b4.y, b4.z + curb_height}; - DrawTriangle3D(t1, t3, t2, CURB_TOP); - DrawTriangle3D(t1, t4, t3, CURB_TOP); - - // Side faces - DrawTriangle3D(b1, t1, b2, CURB_SIDE); - DrawTriangle3D(t1, t2, b2, CURB_SIDE); - DrawTriangle3D(b2, t2, b3, CURB_SIDE); - DrawTriangle3D(t2, t3, b3, CURB_SIDE); - DrawTriangle3D(b3, t3, b4, CURB_SIDE); - DrawTriangle3D(t3, t4, b4, CURB_SIDE); - DrawTriangle3D(b4, t4, b1, CURB_SIDE); - DrawTriangle3D(t4, t1, b1, CURB_SIDE); -} - -void c_render(Drive* env) { - if (env->client == NULL) { - env->client = make_client(env); - } - Client* client = env->client; - BeginDrawing(); - Color road = (Color){35, 35, 37, 255}; - ClearBackground(road); - BeginMode3D(client->camera); - handle_camera_controls(env->client); - - // Draw a grid to help with orientation - // DrawGrid(20, 1.0f); - DrawLine3D((Vector3){env->map_corners[0], env->map_corners[1], 0}, (Vector3){env->map_corners[2], env->map_corners[1], 0}, PUFF_CYAN); - DrawLine3D((Vector3){env->map_corners[0], env->map_corners[1], 0}, (Vector3){env->map_corners[0], env->map_corners[3], 0}, PUFF_CYAN); - DrawLine3D((Vector3){env->map_corners[2], env->map_corners[1], 0}, (Vector3){env->map_corners[2], env->map_corners[3], 0}, PUFF_CYAN); - DrawLine3D((Vector3){env->map_corners[0], env->map_corners[3], 0}, (Vector3){env->map_corners[2], env->map_corners[3], 0}, PUFF_CYAN); - for(int i = 0; i < env->num_entities; i++) { - // Draw cars - if(env->entities[i].type == 1 || env->entities[i].type == 2) { - // Check if this vehicle is an active agent - bool is_active_agent = false; - bool is_static_car = false; - int agent_index = -1; - for(int j = 0; j < env->active_agent_count; j++) { - if(env->active_agent_indices[j] == i) { - is_active_agent = true; - agent_index = j; - break; - } - } - for(int j = 0; j < env->static_car_count; j++) { - if(env->static_car_indices[j] == i) { - is_static_car = true; - break; - } - } - // HIDE CARS ON RESPAWN - IMPORTANT TO KNOW VISUAL SETTING - if(!is_active_agent && !is_static_car || env->entities[i].respawn_timestep != -1){ - continue; - } - Vector3 position; - float heading; - position = (Vector3){ - env->entities[i].x, - env->entities[i].y, - 1 - }; - heading = env->entities[i].heading; - // Create size vector - Vector3 size = { - env->entities[i].length, - env->entities[i].width, - env->entities[i].height - }; - // Save current transform - rlPushMatrix(); - // Translate to position, rotate around Y axis, then draw - rlTranslatef(position.x, position.y, position.z); - rlRotatef(heading*RAD2DEG, 0.0f, 0.0f, 1.0f); // Convert radians to degrees - // Determine color based on active status and other conditions - Color object_color = PUFF_BACKGROUND2; // Default color for non-active vehicles - Color outline_color = PUFF_CYAN; - Model car_model = client->cars[5]; - if(is_active_agent){ - car_model = client->cars[client->car_assignments[i %64]]; - } - if(agent_index == env->human_agent_idx){ - object_color = PUFF_CYAN; - outline_color = PUFF_WHITE; - } - if(is_active_agent && env->entities[i].collision_state > 0) { - car_model = client->cars[0]; // Collided agent - } - // Draw obs for human selected agent - if(agent_index == env->human_agent_idx && !env->entities[agent_index].reached_goal) { - draw_agent_obs(env, agent_index); - } - // Draw cube for cars static and active - // Calculate scale factors based on desired size and model dimensions - - BoundingBox bounds = GetModelBoundingBox(car_model); - Vector3 model_size = { - bounds.max.x - bounds.min.x, - bounds.max.y - bounds.min.y, - bounds.max.z - bounds.min.z - }; - Vector3 scale = { - size.x / model_size.x, - size.y / model_size.y, - size.z / model_size.z - }; - DrawModelEx(car_model, (Vector3){0, 0, 0}, (Vector3){1, 0, 0}, 90.0f, scale, WHITE); - rlPopMatrix(); - - float cos_heading = env->entities[i].heading_x; - float sin_heading = env->entities[i].heading_y; - - // Calculate half dimensions - float half_len = env->entities[i].length * 0.5f; - float half_width = env->entities[i].width * 0.5f; - - // Calculate the four corners of the collision box - Vector3 corners[4] = { - (Vector3){ - position.x + (half_len * cos_heading - half_width * sin_heading), - position.y + (half_len * sin_heading + half_width * cos_heading), - position.z - }, - (Vector3){ - position.x + (half_len * cos_heading + half_width * sin_heading), - position.y + (half_len * sin_heading - half_width * cos_heading), - position.z - }, - (Vector3){ - position.x + (-half_len * cos_heading - half_width * sin_heading), - position.y + (-half_len * sin_heading + half_width * cos_heading), - position.z - }, - (Vector3){ - position.x + (-half_len * cos_heading + half_width * sin_heading), - position.y + (-half_len * sin_heading - half_width * cos_heading), - position.z - } - }; - - // Draw the corners as spheres - /* - for(int j = 0; j < 4; j++) { - DrawSphere(corners[j], 0.3f, RED); // Draw red spheres at each corner - } - */ - for(int j = 0; j < 4; j++) { - DrawLine3D(corners[j], corners[(j+1)%4], PURPLE); // Draw red lines between corners - } - // FPV Camera Control - if(IsKeyDown(KEY_SPACE) && env->human_agent_idx== agent_index){ - if(env->entities[agent_index].reached_goal){ - env->human_agent_idx = rand() % env->active_agent_count; - } - Vector3 camera_position = (Vector3){ - position.x - (25.0f * cosf(heading)), - position.y - (25.0f * sinf(heading)), - position.z + 15 - }; - - Vector3 camera_target = (Vector3){ - position.x + 40.0f * cosf(heading), - position.y + 40.0f * sinf(heading), - position.z - 5.0f - }; - client->camera.position = camera_position; - client->camera.target = camera_target; - client->camera.up = (Vector3){0, 0, 1}; - } - if(IsKeyReleased(KEY_SPACE)){ - client->camera.position = client->default_camera_position; - client->camera.target = client->default_camera_target; - client->camera.up = (Vector3){0, 0, 1}; - } - // Draw goal position for active agents - - if(!is_active_agent || env->entities[i].valid == 0) { - continue; - } - if(!IsKeyDown(KEY_LEFT_CONTROL)){ - DrawSphere((Vector3){ - env->entities[i].goal_position_x, - env->entities[i].goal_position_y, - 1 - }, 0.5f, DARKGREEN); - } - } - // Draw road elements - if(env->entities[i].type <=3 && env->entities[i].type >= 7){ - continue; - } - for(int j = 0; j < env->entities[i].array_size - 1; j++) { - Vector3 start = { - env->entities[i].traj_x[j], - env->entities[i].traj_y[j], - 1 - }; - Vector3 end = { - env->entities[i].traj_x[j + 1], - env->entities[i].traj_y[j + 1], - 1 - }; - Color lineColor = GRAY; - if (env->entities[i].type == ROAD_LANE) lineColor = GRAY; - else if (env->entities[i].type == ROAD_LINE) lineColor = BLUE; - else if (env->entities[i].type == ROAD_EDGE) lineColor = WHITE; - else if (env->entities[i].type == DRIVEWAY) lineColor = RED; - if(env->entities[i].type != ROAD_EDGE){ - continue; - } - if(!IsKeyDown(KEY_LEFT_CONTROL)){ - draw_road_edge(env, start.x, start.y, end.x, end.y); - // DrawLine3D(start, end, lineColor); - // DrawCube(start, 0.5f, 0.5f, 0.5f, lineColor); - // DrawCube(end, 0.5f, 0.5f, 0.5f, lineColor); - } - } - } - // Draw grid cells using the stored bounds - float grid_start_x = env->map_corners[0]; - float grid_start_y = env->map_corners[1]; - for(int i = 0; i < env->grid_cols; i++) { - for(int j = 0; j < env->grid_rows; j++) { - float x = grid_start_x + i*GRID_CELL_SIZE; - float y = grid_start_y + j*GRID_CELL_SIZE; - // int index = i * env->grid_rows + j; - DrawCubeWires( - (Vector3){x + GRID_CELL_SIZE/2, y + GRID_CELL_SIZE/2, 1}, - GRID_CELL_SIZE, GRID_CELL_SIZE, 0.1f, PUFF_BACKGROUND2); - } - } - EndMode3D(); - // Draw debug info - DrawText(TextFormat("Camera Position: (%.2f, %.2f, %.2f)", - client->camera.position.x, - client->camera.position.y, - client->camera.position.z), 10, 10, 20, PUFF_WHITE); - DrawText(TextFormat("Camera Target: (%.2f, %.2f, %.2f)", - client->camera.target.x, - client->camera.target.y, - client->camera.target.z), 10, 30, 20, PUFF_WHITE); - DrawText(TextFormat("Timestep: %d", env->timestep), 10, 50, 20, PUFF_WHITE); - // acceleration & steering - int human_idx = env->active_agent_indices[env->human_agent_idx]; - DrawText(TextFormat("Controlling Agent: %d", env->human_agent_idx), 10, 70, 20, PUFF_WHITE); - DrawText(TextFormat("Agent Index: %d", human_idx), 10, 90, 20, PUFF_WHITE); - // Controls help - DrawText("Controls: W/S - Accelerate/Brake, A/D - Steer, 1-4 - Switch Agent", - 10, client->height - 30, 20, PUFF_WHITE); - // acceleration & steering - DrawText(TextFormat("Acceleration: %d", env->actions[env->human_agent_idx * 2]), 10, 110, 20, PUFF_WHITE); - DrawText(TextFormat("Steering: %d", env->actions[env->human_agent_idx * 2 + 1]), 10, 130, 20, PUFF_WHITE); - DrawText(TextFormat("Grid Rows: %d", env->grid_rows), 10, 150, 20, PUFF_WHITE); - DrawText(TextFormat("Grid Cols: %d", env->grid_cols), 10, 170, 20, PUFF_WHITE); - EndDrawing(); -} - -void close_client(Client* client){ - for (int i = 0; i < 6; i++) { - UnloadModel(client->cars[i]); - } - UnloadTexture(client->puffers); - CloseWindow(); - free(client); -} diff --git a/pufferlib/ocean/drive/drive.py b/pufferlib/ocean/drive/drive.py deleted file mode 100644 index d6557e3f69..0000000000 --- a/pufferlib/ocean/drive/drive.py +++ /dev/null @@ -1,344 +0,0 @@ -import numpy as np -import gymnasium -import json -import struct -import os -import random -import pufferlib -from pufferlib.ocean.drive import binding - -class Drive(pufferlib.PufferEnv): - def __init__(self, render_mode=None, report_interval=1, - width=1280, height=1024, - human_agent_idx=0, - reward_vehicle_collision=-0.1, - reward_offroad_collision=-0.1, - reward_goal_post_respawn=0.5, - reward_vehicle_collision_post_respawn=-0.25, - spawn_immunity_timer=30, - resample_frequency = 91, - num_maps=100, - num_agents=512, - buf = None, - seed=1): - - # env - self.render_mode = render_mode - self.num_maps = num_maps - self.report_interval = report_interval - self.reward_vehicle_collision = reward_vehicle_collision - self.reward_offroad_collision = reward_offroad_collision - self.reward_goal_post_respawn = reward_goal_post_respawn - self.reward_vehicle_collision_post_respawn = reward_vehicle_collision_post_respawn - self.spawn_immunity_timer = spawn_immunity_timer - self.human_agent_idx = human_agent_idx - self.resample_frequency = resample_frequency - self.num_obs = 7 + 63*7 + 200*7 - self.single_observation_space = gymnasium.spaces.Box(low=-1, high=1, - shape=(self.num_obs,), dtype=np.float32) - self.single_action_space = gymnasium.spaces.MultiDiscrete([7, 13]) - # self.single_action_space = gymnasium.spaces.Box( - # low=-1, high=1, shape=(2,), dtype=np.float32 - # ) - # Check if resources directory exists - binary_path = "resources/drive/binaries/map_000.bin" - if not os.path.exists(binary_path): - raise FileNotFoundError(f"Required directory {binary_path} not found. Please ensure the Drive maps are downloaded and installed correctly per docs.") - agent_offsets, map_ids, num_envs = binding.shared(num_agents=num_agents, num_maps=num_maps) - self.num_agents = num_agents - self.agent_offsets = agent_offsets - self.map_ids = map_ids - self.num_envs = num_envs - super().__init__(buf=buf) - env_ids = [] - for i in range(num_envs): - cur = agent_offsets[i] - nxt = agent_offsets[i+1] - env_id = binding.env_init( - self.observations[cur:nxt], - self.actions[cur:nxt], - self.rewards[cur:nxt], - self.terminals[cur:nxt], - self.truncations[cur:nxt], - seed, - human_agent_idx=human_agent_idx, - reward_vehicle_collision=reward_vehicle_collision, - reward_offroad_collision=reward_offroad_collision, - reward_goal_post_respawn=reward_goal_post_respawn, - reward_vehicle_collision_post_respawn=reward_vehicle_collision_post_respawn, - spawn_immunity_timer=spawn_immunity_timer, - map_id=map_ids[i], - max_agents = nxt-cur - ) - env_ids.append(env_id) - - self.c_envs = binding.vectorize(*env_ids) - - def reset(self, seed=0): - binding.vec_reset(self.c_envs, seed) - self.tick = 0 - return self.observations, [] - - def step(self, actions): - self.terminals[:] = 0 - self.actions[:] = actions - binding.vec_step(self.c_envs) - self.tick+=1 - info = [] - if self.tick % self.report_interval == 0: - log = binding.vec_log(self.c_envs) - if log: - info.append(log) - #print(log) - if(self.tick > 0 and self.resample_frequency > 0 and self.tick % self.resample_frequency == 0): - self.tick = 0 - will_resample = 1 - if will_resample: - binding.vec_close(self.c_envs) - agent_offsets, map_ids, num_envs = binding.shared(num_agents=self.num_agents, num_maps=self.num_maps) - env_ids = [] - seed = np.random.randint(0, 2**32-1) - for i in range(num_envs): - cur = agent_offsets[i] - nxt = agent_offsets[i+1] - env_id = binding.env_init( - self.observations[cur:nxt], - self.actions[cur:nxt], - self.rewards[cur:nxt], - self.terminals[cur:nxt], - self.truncations[cur:nxt], - seed, - human_agent_idx=self.human_agent_idx, - reward_vehicle_collision=self.reward_vehicle_collision, - reward_offroad_collision=self.reward_offroad_collision, - reward_goal_post_respawn=self.reward_goal_post_respawn, - reward_vehicle_collision_post_respawn=self.reward_vehicle_collision_post_respawn, - spawn_immunity_timer=self.spawn_immunity_timer, - map_id=map_ids[i], - max_agents = nxt-cur - ) - env_ids.append(env_id) - self.c_envs = binding.vectorize(*env_ids) - - binding.vec_reset(self.c_envs, seed) - self.terminals[:] = 1 - return (self.observations, self.rewards, - self.terminals, self.truncations, info) - - def render(self): - binding.vec_render(self.c_envs, 0) - - def close(self): - binding.vec_close(self.c_envs) - -def calculate_area(p1, p2, p3): - # Calculate the area of the triangle using the determinant method - return 0.5 * abs((p1['x'] - p3['x']) * (p2['y'] - p1['y']) - (p1['x'] - p2['x']) * (p3['y'] - p1['y'])) - -def simplify_polyline(geometry, polyline_reduction_threshold): - """Simplify the given polyline using a method inspired by Visvalingham-Whyatt, optimized for Python.""" - num_points = len(geometry) - if num_points < 3: - return geometry # Not enough points to simplify - - skip = [False] * num_points - skip_changed = True - - while skip_changed: - skip_changed = False - k = 0 - while k < num_points - 1: - k_1 = k + 1 - while k_1 < num_points - 1 and skip[k_1]: - k_1 += 1 - if k_1 >= num_points - 1: - break - - k_2 = k_1 + 1 - while k_2 < num_points and skip[k_2]: - k_2 += 1 - if k_2 >= num_points: - break - - point1 = geometry[k] - point2 = geometry[k_1] - point3 = geometry[k_2] - area = calculate_area(point1, point2, point3) - - if area < polyline_reduction_threshold: - skip[k_1] = True - skip_changed = True - k = k_2 - else: - k = k_1 - - return [geometry[i] for i in range(num_points) if not skip[i]] - -def save_map_binary(map_data, output_file): - trajectory_length = 91 - """Saves map data in a binary format readable by C""" - with open(output_file, 'wb') as f: - # Count total entities - print(len(map_data.get('objects', []))) - print(len(map_data.get('roads', []))) - num_objects = len(map_data.get('objects', [])) - num_roads = len(map_data.get('roads', [])) - # num_entities = num_objects + num_roads - f.write(struct.pack('i', num_objects)) - f.write(struct.pack('i', num_roads)) - # f.write(struct.pack('i', num_entities)) - # Write objects - for obj in map_data.get('objects', []): - # Write base entity data - obj_type = obj.get('type', 1) - if(obj_type =='vehicle'): - obj_type = 1 - elif(obj_type == 'pedestrian'): - obj_type = 2; - elif(obj_type == 'cyclist'): - obj_type = 3; - f.write(struct.pack('i', obj_type)) # type - # f.write(struct.pack('i', obj.get('id', 0))) # id - f.write(struct.pack('i', trajectory_length)) # array_size - # Write position arrays - positions = obj.get('position', []) - for i in range(trajectory_length): - pos = positions[i] if i < len(positions) else {'x': 0.0, 'y': 0.0, 'z': 0.0} - f.write(struct.pack('f', float(pos.get('x', 0.0)))) - for i in range(trajectory_length): - pos = positions[i] if i < len(positions) else {'x': 0.0, 'y': 0.0, 'z': 0.0} - f.write(struct.pack('f', float(pos.get('y', 0.0)))) - for i in range(trajectory_length): - pos = positions[i] if i < len(positions) else {'x': 0.0, 'y': 0.0, 'z': 0.0} - f.write(struct.pack('f', float(pos.get('z', 0.0)))) - - # Write velocity arrays - velocities = obj.get('velocity', []) - for arr, key in [(velocities, 'x'), (velocities, 'y'), (velocities, 'z')]: - for i in range(trajectory_length): - vel = arr[i] if i < len(arr) else {'x': 0.0, 'y': 0.0, 'z': 0.0} - f.write(struct.pack('f', float(vel.get(key, 0.0)))) - - # Write heading and valid arrays - headings = obj.get('heading', []) - f.write(struct.pack(f'{trajectory_length}f', *[float(headings[i]) if i < len(headings) else 0.0 for i in range(trajectory_length)])) - - valids = obj.get('valid', []) - f.write(struct.pack(f'{trajectory_length}i', *[int(valids[i]) if i < len(valids) else 0 for i in range(trajectory_length)])) - - # Write scalar fields - f.write(struct.pack('f', float(obj.get('width', 0.0)))) - f.write(struct.pack('f', float(obj.get('length', 0.0)))) - f.write(struct.pack('f', float(obj.get('height', 0.0)))) - goal_pos = obj.get('goalPosition', {'x': 0, 'y': 0, 'z': 0}) # Get goalPosition object with default - f.write(struct.pack('f', float(goal_pos.get('x', 0.0)))) # Get x value - f.write(struct.pack('f', float(goal_pos.get('y', 0.0)))) # Get y value - f.write(struct.pack('f', float(goal_pos.get('z', 0.0)))) # Get z value - f.write(struct.pack('i', obj.get('mark_as_expert', 0))) - - # Write roads - for idx, road in enumerate(map_data.get('roads', [])): - geometry = road.get('geometry', []) - road_type = road.get('map_element_id', 0) - road_type_word = road.get('type', 0) - if(road_type_word == "lane"): - road_type = 2 - elif(road_type_word == "road_edge"): - road_type = 15 - # breakpoint() - if(len(geometry) > 10 and road_type <=16): - geometry = simplify_polyline(geometry, .1) - size = len(geometry) - # breakpoint() - if(road_type >=0 and road_type <=3): - road_type = 4 - elif(road_type >=5 and road_type <=13): - road_type = 5 - elif(road_type >=14 and road_type <=16): - road_type = 6 - elif(road_type == 17): - road_type = 7 - elif(road_type == 18): - road_type = 8 - elif(road_type == 19): - road_type = 9 - elif(road_type == 20): - road_type = 10 - # Write base entity data - f.write(struct.pack('i', road_type)) # type - # f.write(struct.pack('i', road.get('id', 0))) # id - f.write(struct.pack('i', size)) # array_size - - # Write position arrays - for coord in ['x', 'y', 'z']: - for point in geometry: - f.write(struct.pack('f', float(point.get(coord, 0.0)))) - # Write scalar fields - f.write(struct.pack('f', float(road.get('width', 0.0)))) - f.write(struct.pack('f', float(road.get('length', 0.0)))) - f.write(struct.pack('f', float(road.get('height', 0.0)))) - goal_pos = road.get('goalPosition', {'x': 0, 'y': 0, 'z': 0}) # Get goalPosition object with default - f.write(struct.pack('f', float(goal_pos.get('x', 0.0)))) # Get x value - f.write(struct.pack('f', float(goal_pos.get('y', 0.0)))) # Get y value - f.write(struct.pack('f', float(goal_pos.get('z', 0.0)))) # Get z value - f.write(struct.pack('i', road.get('mark_as_expert', 0))) - -def load_map(map_name, binary_output=None): - """Loads a JSON map and optionally saves it as binary""" - with open(map_name, 'r') as f: - map_data = json.load(f) - - if binary_output: - save_map_binary(map_data, binary_output) - -def process_all_maps(): - """Process all maps and save them as binaries""" - import os - from pathlib import Path - - # Create the binaries directory if it doesn't exist - binary_dir = Path("resources/drive/binaries") - binary_dir.mkdir(parents=True, exist_ok=True) - - # Path to the training data - data_dir = Path("data/processed_big/training") - - # Get all JSON files in the training directory - json_files = sorted(data_dir.glob("*.json")) - - print(f"Found {len(json_files)} JSON files") - - # Process each JSON file - for i, map_path in enumerate(json_files[:10000]): - binary_file = f"map_{i:03d}.bin" # Use zero-padded numbers for consistent sorting - binary_path = binary_dir / binary_file - - print(f"Processing {map_path.name} -> {binary_file}") - # try: - load_map(str(map_path), str(binary_path)) - # except Exception as e: - # print(f"Error processing {map_path.name}: {e}") - -def test_performance(timeout=10, atn_cache=1024, num_agents=1024): - import time - - env = Drive(num_agents=num_agents) - env.reset() - tick = 0 - num_agents = 1024 - actions = np.stack([ - np.random.randint(0, space.n + 1, (atn_cache, num_agents)) - for space in env.single_action_space - ], axis=-1) - - start = time.time() - while time.time() - start < timeout: - atn = actions[tick % atn_cache] - env.step(atn) - tick += 1 - - print(f'SPS: {num_agents * tick / (time.time() - start)}') - env.close() -if __name__ == '__main__': - # test_performance() - process_all_maps() diff --git a/pufferlib/ocean/drone/binding.c b/pufferlib/ocean/drone/binding.c deleted file mode 100644 index ed5475ea96..0000000000 --- a/pufferlib/ocean/drone/binding.c +++ /dev/null @@ -1,26 +0,0 @@ -#include "drone.h" -#include "render.h" - -#define Env DroneEnv -#include "../env_binding.h" - -static int my_init(Env *env, PyObject *args, PyObject *kwargs) { - env->num_agents = unpack(kwargs, "num_agents"); - env->max_rings = unpack(kwargs, "max_rings"); - init(env); - return 0; -} - -static int my_log(PyObject *dict, Log *log) { - assign_to_dict(dict, "perf", log->perf); - assign_to_dict(dict, "score", log->score); - assign_to_dict(dict, "rings_passed", log->rings_passed); - assign_to_dict(dict, "ring_collisions", log->ring_collision); - assign_to_dict(dict, "collision_rate", log->collision_rate); - assign_to_dict(dict, "oob", log->oob); - assign_to_dict(dict, "timeout", log->timeout); - assign_to_dict(dict, "episode_return", log->episode_return); - assign_to_dict(dict, "episode_length", log->episode_length); - assign_to_dict(dict, "n", log->n); - return 0; -} diff --git a/pufferlib/ocean/drone/drone.c b/pufferlib/ocean/drone/drone.c deleted file mode 100644 index 7a3791594d..0000000000 --- a/pufferlib/ocean/drone/drone.c +++ /dev/null @@ -1,180 +0,0 @@ -// Standalone C demo for drone environment -// Compile using: ./scripts/build_ocean.sh drone [local|fast] -// Run with: ./drone - -#include "drone.h" -#include "puffernet.h" -#include - -#ifdef __EMSCRIPTEN__ -#include -#endif - -double randn(double mean, double std) { - static int has_spare = 0; - static double spare; - - if (has_spare) { - has_spare = 0; - return mean + std * spare; - } - - has_spare = 1; - double u, v, s; - do { - u = 2.0 * rand() / RAND_MAX - 1.0; - v = 2.0 * rand() / RAND_MAX - 1.0; - s = u * u + v * v; - } while (s >= 1.0 || s == 0.0); - - s = sqrt(-2.0 * log(s) / s); - spare = v * s; - return mean + std * (u * s); -} - -typedef struct LinearContLSTM LinearContLSTM; -struct LinearContLSTM { - int num_agents; - float *obs; - float *log_std; - Linear *encoder; - GELU *gelu1; - LSTM *lstm; - Linear *actor; - Linear *value_fn; - int num_actions; -}; - -LinearContLSTM *make_linearcontlstm(Weights *weights, int num_agents, int input_dim, - int logit_sizes[], int num_actions) { - LinearContLSTM *net = calloc(1, sizeof(LinearContLSTM)); - net->num_agents = num_agents; - net->obs = calloc(num_agents * input_dim, sizeof(float)); - net->num_actions = logit_sizes[0]; - net->log_std = weights->data; - weights->idx += net->num_actions; - net->encoder = make_linear(weights, num_agents, input_dim, 128); - net->gelu1 = make_gelu(num_agents, 128); - int atn_sum = 0; - for (int i = 0; i < num_actions; i++) { - atn_sum += logit_sizes[i]; - } - net->actor = make_linear(weights, num_agents, 128, atn_sum); - net->value_fn = make_linear(weights, num_agents, 128, 1); - net->lstm = make_lstm(weights, num_agents, 128, 128); - return net; -} - -void free_linearcontlstm(LinearContLSTM *net) { - free(net->obs); - free(net->encoder); - free(net->gelu1); - free(net->actor); - free(net->value_fn); - free(net->lstm); - free(net); -} - -void forward_linearcontlstm(LinearContLSTM *net, float *observations, float *actions) { - linear(net->encoder, observations); - gelu(net->gelu1, net->encoder->output); - lstm(net->lstm, net->gelu1->output); - linear(net->actor, net->lstm->state_h); - linear(net->value_fn, net->lstm->state_h); - for (int i = 0; i < net->num_actions; i++) { - float std = expf(net->log_std[i]); - float mean = net->actor->output[i]; - actions[i] = randn(mean, std); - } -} - -void generate_dummy_actions(DroneEnv *env) { - // Generate random floats in [-1, 1] range - env->actions[0] = ((float)rand() / (float)RAND_MAX) * 2.0f - 1.0f; - env->actions[1] = ((float)rand() / (float)RAND_MAX) * 2.0f - 1.0f; - env->actions[2] = ((float)rand() / (float)RAND_MAX) * 2.0f - 1.0f; - env->actions[3] = ((float)rand() / (float)RAND_MAX) * 2.0f - 1.0f; -} - -#ifdef __EMSCRIPTEN__ -typedef struct { - DroneEnv *env; - LinearContLSTM *net; - Weights *weights; -} WebRenderArgs; - -void emscriptenStep(void *e) { - WebRenderArgs *args = (WebRenderArgs *)e; - DroneEnv *env = args->env; - LinearContLSTM *net = args->net; - - forward_linearcontlstm(net, env->observations, env->actions); - c_step(env); - c_render(env); - return; -} - -WebRenderArgs *web_args = NULL; -#endif - -int main() { - srand(time(NULL)); // Seed random number generator - - DroneEnv *env = calloc(1, sizeof(DroneEnv)); - env->num_agents = 64; - env->max_rings = 10; - env->task = ORBIT; - init(env); - - size_t obs_size = 26; - size_t act_size = 4; - env->observations = (float *)calloc(env->num_agents * obs_size, sizeof(float)); - env->actions = (float *)calloc(env->num_agents * act_size, sizeof(float)); - env->rewards = (float *)calloc(env->num_agents, sizeof(float)); - env->terminals = (unsigned char *)calloc(env->num_agents, sizeof(float)); - - //Weights *weights = load_weights("resources/drone/drone_weights.bin", 136073); - //int logit_sizes[1] = {4}; - //LinearContLSTM *net = make_linearcontlstm(weights, env->num_agents, obs_size, logit_sizes, 1); - - if (!env->observations || !env->actions || !env->rewards) { - fprintf(stderr, "ERROR: Failed to allocate memory for demo buffers.\n"); - free(env->observations); - free(env->actions); - free(env->rewards); - free(env->terminals); - free(env); - return 0; - } - - init(env); - c_reset(env); - -#ifdef __EMSCRIPTEN__ - WebRenderArgs *args = calloc(1, sizeof(WebRenderArgs)); - args->env = env; - args->net = net; - args->weights = weights; - web_args = args; - - emscripten_set_main_loop_arg(emscriptenStep, args, 0, true); -#else - c_render(env); - - while (!WindowShouldClose()) { - //forward_linearcontlstm(net, env->observations, env->actions); - c_step(env); - c_render(env); - } - - c_close(env); - //free_linearcontlstm(net); - free(env->observations); - free(env->actions); - free(env->rewards); - free(env->terminals); - free(env); -#endif - - return 0; -} diff --git a/pufferlib/ocean/drone/drone.h b/pufferlib/ocean/drone/drone.h deleted file mode 100644 index 535fdc5ffa..0000000000 --- a/pufferlib/ocean/drone/drone.h +++ /dev/null @@ -1,278 +0,0 @@ -// Originally made by Sam Turner and Finlay Sanders, 2025. -// Included in pufferlib under the original project's MIT license. -// https://github.com/tensaur/drone - -#pragma once - -#include -#include -#include -#include - -#include "dronelib.h" -#include "tasks.h" - -typedef struct Client Client; -typedef struct DroneEnv DroneEnv; - -struct DroneEnv { - float *observations; - float *actions; - float *rewards; - unsigned char *terminals; - - Log log; - int tick; - int report_interval; - - DroneTask task; - int num_agents; - Drone *agents; - - int max_rings; - Target* ring_buffer; - - Client *client; -}; - -void init(DroneEnv *env) { - env->agents = (Drone*) calloc(env->num_agents, sizeof(Drone)); - env->ring_buffer = (Target*) calloc(env->max_rings, sizeof(Target)); - - for (int i = 0; i < env->num_agents; i++) { - env->agents[i].target = (Target*) calloc(1, sizeof(Target)); - } - - env->log = (Log){0}; - env->tick = 0; -} - -void add_log(DroneEnv *env, int idx, bool oob, bool ring_collision, - bool timeout) { - Drone *agent = &env->agents[idx]; - env->log.score += agent->score; - env->log.episode_return += agent->episode_return; - env->log.episode_length += agent->episode_length; - env->log.collision_rate += agent->collisions / (float)agent->episode_length; - env->log.perf += agent->score / (float)agent->episode_length; - if (oob) { - env->log.oob += 1.0f; - } - if (ring_collision) { - env->log.ring_collision += 1.0f; - } - if (timeout) { - env->log.timeout += 1.0f; - } - env->log.n += 1.0f; - - agent->episode_length = 0; - agent->episode_return = 0.0f; -} - -void compute_observations(DroneEnv *env) { - int idx = 0; - - for (int i = 0; i < env->num_agents; i++) { - Drone *agent = &env->agents[i]; - - Quat q_inv = quat_inverse(agent->state.quat); - Vec3 linear_vel_body = quat_rotate(q_inv, agent->state.vel); - Vec3 to_target = sub3(agent->target->pos, agent->state.pos); - - env->observations[idx++] = linear_vel_body.x / agent->params.max_vel; - env->observations[idx++] = linear_vel_body.y / agent->params.max_vel; - env->observations[idx++] = linear_vel_body.z / agent->params.max_vel; - - env->observations[idx++] = agent->state.omega.x / agent->params.max_omega; - env->observations[idx++] = agent->state.omega.y / agent->params.max_omega; - env->observations[idx++] = agent->state.omega.z / agent->params.max_omega; - - env->observations[idx++] = agent->state.quat.w; - env->observations[idx++] = agent->state.quat.x; - env->observations[idx++] = agent->state.quat.y; - env->observations[idx++] = agent->state.quat.z; - - env->observations[idx++] = agent->state.rpms[0] / agent->params.max_rpm; - env->observations[idx++] = agent->state.rpms[1] / agent->params.max_rpm; - env->observations[idx++] = agent->state.rpms[2] / agent->params.max_rpm; - env->observations[idx++] = agent->state.rpms[3] / agent->params.max_rpm; - - env->observations[idx++] = to_target.x / GRID_X; - env->observations[idx++] = to_target.y / GRID_Y; - env->observations[idx++] = to_target.z / GRID_Z; - - env->observations[idx++] = clampf(to_target.x, -1.0f, 1.0f); - env->observations[idx++] = clampf(to_target.y, -1.0f, 1.0f); - env->observations[idx++] = clampf(to_target.z, -1.0f, 1.0f); - - env->observations[idx++] = agent->target->normal.x; - env->observations[idx++] = agent->target->normal.y; - env->observations[idx++] = agent->target->normal.z; - - // Multiagent obs - Drone *nearest = nearest_drone(agent, env->agents, env->num_agents); - if (env->num_agents > 1) { - env->observations[idx++] = - clampf(nearest->state.pos.x - agent->state.pos.x, -1.0f, 1.0f); - env->observations[idx++] = - clampf(nearest->state.pos.y - agent->state.pos.y, -1.0f, 1.0f); - env->observations[idx++] = - clampf(nearest->state.pos.z - agent->state.pos.z, -1.0f, 1.0f); - } else { - env->observations[idx++] = MAX_DIST; - env->observations[idx++] = MAX_DIST; - env->observations[idx++] = MAX_DIST; - } - } -} - -void reset_agent(DroneEnv *env, Drone *agent, int idx) { - agent->last_dist_reward = 0.0f; - agent->episode_return = 0.0f; - agent->episode_length = 0; - agent->collisions = 0.0f; - agent->score = 0.0f; - - agent->buffer = env->ring_buffer; - agent->buffer_size = env->max_rings; - agent->buffer_idx = -1; - - float size = rndf(0.1f, 0.4f); - init_drone(agent, size, 0.1f); - - agent->state.pos = - (Vec3){rndf(-MARGIN_X, MARGIN_X), rndf(-MARGIN_Y, MARGIN_Y), - rndf(-MARGIN_Z, MARGIN_Z)}; - - if (env->task == RACE) { - while (norm3(sub3(agent->state.pos, env->ring_buffer[0].pos)) < - 2.0f * RING_RADIUS) { - agent->state.pos = - (Vec3){rndf(-MARGIN_X, MARGIN_X), rndf(-MARGIN_Y, MARGIN_Y), - rndf(-MARGIN_Z, MARGIN_Z)}; - } - } - - agent->prev_pos = agent->state.pos; -} - -void c_reset(DroneEnv *env) { - env->tick = 0; - int rng = rand(); - - if (rng > INT_MAX / 2) { - env->task = RACE; - } else { - env->task = (DroneTask)(rng % (TASK_N - 1)); - } - - if (env->task == RACE) { - reset_rings(env->ring_buffer, env->max_rings); - } - - for (int i = 0; i < env->num_agents; i++) { - Drone *agent = &env->agents[i]; - reset_agent(env, agent, i); - set_target(env->task, env->agents, i, env->num_agents); - } - - compute_observations(env); -} - -void c_step(DroneEnv *env) { - env->tick = (env->tick + 1) % HORIZON; - - for (int i = 0; i < env->num_agents; i++) { - Drone *agent = &env->agents[i]; - env->rewards[i] = 0; - env->terminals[i] = 0; - - float *atn = &env->actions[4 * i]; - move_drone(agent, atn); - - bool out_of_bounds = - agent->state.pos.x < -GRID_X || agent->state.pos.x > GRID_X || - agent->state.pos.y < -GRID_Y || agent->state.pos.y > GRID_Y || - agent->state.pos.z < -GRID_Z || agent->state.pos.z > GRID_Z; - - move_target(agent); - - bool collision = check_collision(agent, env->agents, env->num_agents); - float reward = 0.0f; - - if (env->task == RACE) { - // Check ring passage - Target *ring = &env->ring_buffer[agent->buffer_idx]; - int ring_passage = check_ring(agent, ring); - - // Ring collision - if (ring_passage < 0) { - env->rewards[i] = (float)ring_passage; - agent->episode_return += (float)ring_passage; - env->terminals[i] = 1; - add_log(env, i, false, true, false); - reset_agent(env, agent, i); - set_target(env->task, env->agents, i, env->num_agents); - continue; - } - - // Successfully passed through ring - advance to next - if (ring_passage > 0) { - set_target(env->task, env->agents, i, env->num_agents); - env->log.rings_passed += 1.0f; - } - - reward = dynamic_task_reward(agent, collision, ring_passage); - } else { - reward = static_task_reward(agent, collision); - } - - // Update agent state - agent->episode_length++; - agent->score += reward; - if (collision) { - agent->collisions += 1.0f; - } - - env->rewards[i] = reward; - agent->episode_return += reward; - - // Check termination conditions - if (out_of_bounds) { - env->rewards[i] -= 1.0f; - agent->episode_return -= 1.0f; - env->terminals[i] = 1; - add_log(env, i, true, false, false); - - reset_agent(env, agent, i); - set_target(env->task, env->agents, i, env->num_agents); - static_task_reward(agent, false); - } else if (env->tick >= HORIZON - 1) { - env->terminals[i] = 1; - add_log(env, i, false, false, true); - } - } - - if (env->tick >= HORIZON - 1) { - c_reset(env); - } - - compute_observations(env); -} - -void c_close_client(Client* client); - -void c_close(DroneEnv *env) { - for (int i = 0; i < env->num_agents; i++) { - free(env->agents[i].target); - } - - free(env->agents); - free(env->ring_buffer); - - if (env->client != NULL) { - c_close_client(env->client); - } -} - diff --git a/pufferlib/ocean/drone/drone.py b/pufferlib/ocean/drone/drone.py deleted file mode 100644 index 4e76d231d6..0000000000 --- a/pufferlib/ocean/drone/drone.py +++ /dev/null @@ -1,94 +0,0 @@ -import numpy as np -import gymnasium - -import pufferlib -from pufferlib.ocean.drone import binding - -class Drone(pufferlib.PufferEnv): - def __init__( - self, - num_envs=16, - num_drones=64, - max_rings=5, - render_mode=None, - report_interval=1024, - buf=None, - seed=0, - ): - self.single_observation_space = gymnasium.spaces.Box( - low=-1, - high=1, - shape=(26,), - dtype=np.float32, - ) - - self.single_action_space = gymnasium.spaces.Box( - low=-1, high=1, shape=(4,), dtype=np.float32 - ) - - self.num_agents = num_envs*num_drones - self.render_mode = render_mode - self.report_interval = report_interval - self.tick = 0 - - super().__init__(buf) - self.actions = self.actions.astype(np.float32) - - c_envs = [] - for i in range(num_envs): - c_envs.append(binding.env_init( - self.observations[i*num_drones:(i+1)*num_drones], - self.actions[i*num_drones:(i+1)*num_drones], - self.rewards[i*num_drones:(i+1)*num_drones], - self.terminals[i*num_drones:(i+1)*num_drones], - self.truncations[i*num_drones:(i+1)*num_drones], - i, - num_agents=num_drones, - max_rings=max_rings, - )) - - self.c_envs = binding.vectorize(*c_envs) - - def reset(self, seed=None): - self.tick = 0 - binding.vec_reset(self.c_envs, seed) - return self.observations, [] - - def step(self, actions): - self.actions[:] = actions - - self.tick += 1 - binding.vec_step(self.c_envs) - - info = [] - if self.tick % self.report_interval == 0: - log_data = binding.vec_log(self.c_envs) - if log_data: - info.append(log_data) - - return (self.observations, self.rewards, self.terminals, self.truncations, info) - - def render(self): - binding.vec_render(self.c_envs, 0) - - def close(self): - binding.vec_close(self.c_envs) - -def test_performance(timeout=10, atn_cache=1024): - env = Drone(num_envs=1000) - env.reset() - tick = 0 - - actions = [env.action_space.sample() for _ in range(atn_cache)] - - import time - start = time.time() - while time.time() - start < timeout: - atn = actions[tick % atn_cache] - env.step(atn) - tick += 1 - - print(f"SPS: {env.num_agents * tick / (time.time() - start)}") - -if __name__ == "__main__": - test_performance() diff --git a/pufferlib/ocean/drone/dronelib.h b/pufferlib/ocean/drone/dronelib.h deleted file mode 100644 index fd1f0d0c75..0000000000 --- a/pufferlib/ocean/drone/dronelib.h +++ /dev/null @@ -1,545 +0,0 @@ -// Originally made by Sam Turner and Finlay Sanders, 2025. -// Included in pufferlib under the original project's MIT license. -// https://github.com/tensaur/drone - -#pragma once - -#include -#include -#include -#include - -// Visualisation properties -#define WIDTH 1080 -#define HEIGHT 720 -#define TRAIL_LENGTH 50 -#define HORIZON 1024 - -// Physical constants for the drone -#define BASE_MASS 1.0f // kg -#define BASE_IXX 0.01f // kgm^2 -#define BASE_IYY 0.01f // kgm^2 -#define BASE_IZZ 0.02f // kgm^2 -#define BASE_ARM_LEN 0.1f // m -#define BASE_K_THRUST 3e-5f // thrust coefficient -#define BASE_K_ANG_DAMP 0.2f // angular damping coefficient -#define BASE_K_DRAG 1e-6f // drag (torque) coefficient -#define BASE_B_DRAG 0.1f // linear drag coefficient -#define BASE_GRAVITY 9.81f // m/s^2 -#define BASE_MAX_RPM 750.0f // rad/s -#define BASE_MAX_VEL 50.0f // m/s -#define BASE_MAX_OMEGA 50.0f // rad/s -#define BASE_K_MOT 0.1f // s (Motor lag constant) -#define BASE_J_MOT 1e-5f // kgm^2 (Motor rotational inertia) - -// Simulation properties -#define GRID_X 30.0f -#define GRID_Y 30.0f -#define GRID_Z 10.0f -#define MARGIN_X (GRID_X - 1) -#define MARGIN_Y (GRID_Y - 1) -#define MARGIN_Z (GRID_Z - 1) -#define RING_RADIUS 2.0f -#define V_TARGET 0.05f -#define DT 0.05f -#define DT_RNG 0.0f - -// Corner to corner distance -#define MAX_DIST sqrtf((2*GRID_X)*(2*GRID_X) + (2*GRID_Y)*(2*GRID_Y) + (2*GRID_Z)*(2*GRID_Z)) - -typedef struct Log Log; -struct Log { - float episode_return; - float episode_length; - float rings_passed; - float collision_rate; - float oob; - float ring_collision; - float timeout; - float score; - float perf; - float n; -}; - -typedef struct { - float w, x, y, z; -} Quat; - -typedef struct { - float x, y, z; -} Vec3; - -typedef struct { - Vec3 pos; - Vec3 vel; - Quat orientation; - Vec3 normal; - float radius; -} Target; - -typedef struct { - Vec3 pos[TRAIL_LENGTH]; - int index; - int count; -} Trail; - -typedef struct { - Vec3 pos; // global position (x, y, z) - Vec3 vel; // linear velocity (u, v, w) - Quat quat; // roll/pitch/yaw (phi/theta/psi) as a quaternion - Vec3 omega; // angular velocity (p, q, r) - float rpms[4]; // motor RPMs -} State; - -typedef struct { - Vec3 vel; // Derivative of position - Vec3 v_dot; // Derivative of velocity - Quat q_dot; // Derivative of quaternion - Vec3 w_dot; // Derivative of angular velocity - float rpm_dot[4]; // Derivative of motor RPMs -} StateDerivative; - -typedef struct { - // Physical properties. Modeled as part of the drone - // to make domain randomization easier. - float mass; // kg - float ixx; // kgm^2 - float iyy; // kgm^2 - float izz; // kgm^2 - float arm_len; // m - float k_thrust; // thrust coefficient - float k_ang_damp; // angular damping coefficient - float k_drag; // drag (torque) coefficient - float b_drag; // linear drag coefficient - float gravity; // m/s^2 - float max_rpm; // rad/s - float max_vel; // m/s - float max_omega; // rad/s - float k_mot; // s - float j_mot; // kgm^2 -} Params; - -typedef struct { - // core state and parameters - State state; - Params params; - Vec3 prev_pos; - - // current target - Target* target; - - // buffer agent can draw more targets from, - // allows agents to continue on their own separate paths - Target* buffer; - int buffer_idx; - int buffer_size; - - // logging utils - float last_dist_reward; - float episode_return; - int episode_length; - float score; - float collisions; -} Drone; - -static inline float clampf(float v, float min, float max) { - if (v < min) - return min; - if (v > max) - return max; - return v; -} - -static inline float rndf(float a, float b) { - return a + ((float)rand() / (float)RAND_MAX) * (b - a); -} - -static inline Vec3 add3(Vec3 a, Vec3 b) { - return (Vec3){a.x + b.x, a.y + b.y, a.z + b.z}; -} - -static inline Quat add_quat(Quat a, Quat b) { - return (Quat){a.w + b.w, a.x + b.x, a.y + b.y, a.z + b.z}; -} - -static inline Vec3 sub3(Vec3 a, Vec3 b) { - return (Vec3){a.x - b.x, a.y - b.y, a.z - b.z}; -} - -static inline Vec3 scalmul3(Vec3 a, float b) { - return (Vec3){a.x * b, a.y * b, a.z * b}; -} - -static inline Quat scalmul_quat(Quat a, float b) { - return (Quat){a.w * b, a.x * b, a.y * b, a.z * b}; -} - -static inline float dot3(Vec3 a, Vec3 b) { - return a.x * b.x + a.y * b.y + a.z * b.z; -} - -static inline float norm3(Vec3 a) { - return sqrtf(dot3(a, a)); -} - -static inline void clamp3(Vec3 *vec, float min, float max) { - vec->x = clampf(vec->x, min, max); - vec->y = clampf(vec->y, min, max); - vec->z = clampf(vec->z, min, max); -} - -static inline void clamp4(float a[4], float min, float max) { - a[0] = clampf(a[0], min, max); - a[1] = clampf(a[1], min, max); - a[2] = clampf(a[2], min, max); - a[3] = clampf(a[3], min, max); -} - -static inline Quat quat_mul(Quat q1, Quat q2) { - Quat out; - out.w = q1.w * q2.w - q1.x * q2.x - q1.y * q2.y - q1.z * q2.z; - out.x = q1.w * q2.x + q1.x * q2.w + q1.y * q2.z - q1.z * q2.y; - out.y = q1.w * q2.y - q1.x * q2.z + q1.y * q2.w + q1.z * q2.x; - out.z = q1.w * q2.z + q1.x * q2.y - q1.y * q2.x + q1.z * q2.w; - return out; -} - -static inline void quat_normalize(Quat *q) { - float n = sqrtf(q->w * q->w + q->x * q->x + q->y * q->y + q->z * q->z); - if (n > 0.0f) { - q->w /= n; - q->x /= n; - q->y /= n; - q->z /= n; - } -} - -static inline Vec3 quat_rotate(Quat q, Vec3 v) { - Quat qv = {0.0f, v.x, v.y, v.z}; - Quat tmp = quat_mul(q, qv); - Quat q_conj = {q.w, -q.x, -q.y, -q.z}; - Quat res = quat_mul(tmp, q_conj); - return (Vec3){res.x, res.y, res.z}; -} - -static inline Quat quat_inverse(Quat q) { - return (Quat){q.w, -q.x, -q.y, -q.z}; -} - -Quat rndquat() { - float u1 = rndf(0.0f, 1.0f); - float u2 = rndf(0.0f, 1.0f); - float u3 = rndf(0.0f, 1.0f); - - float sqrt_1_minus_u1 = sqrtf(1.0f - u1); - float sqrt_u1 = sqrtf(u1); - - float pi_2_u2 = 2.0f * M_PI * u2; - float pi_2_u3 = 2.0f * M_PI * u3; - - Quat q; - q.w = sqrt_1_minus_u1 * sinf(pi_2_u2); - q.x = sqrt_1_minus_u1 * cosf(pi_2_u2); - q.y = sqrt_u1 * sinf(pi_2_u3); - q.z = sqrt_u1 * cosf(pi_2_u3); - - return q; -} - -Target rndring(float radius) { - Target ring = {0}; - - ring.pos.x = rndf(-GRID_X + 2*radius, GRID_X - 2*radius); - ring.pos.y = rndf(-GRID_Y + 2*radius, GRID_Y - 2*radius); - ring.pos.z = rndf(-GRID_Z + 2*radius, GRID_Z - 2*radius); - - ring.orientation = rndquat(); - - Vec3 base_normal = {0.0f, 0.0f, 1.0f}; - ring.normal = quat_rotate(ring.orientation, base_normal); - - ring.radius = radius; - - return ring; -} - -void init_drone(Drone* drone, float size, float dr) { - drone->params.arm_len = size / 2.0f; - - // m ~ x^3 - float mass_scale = powf(drone->params.arm_len, 3.0f) / powf(BASE_ARM_LEN, 3.0f); - drone->params.mass = BASE_MASS * mass_scale * rndf(1.0f - dr, 1.0f + dr); - - // I ~ mx^2 - float base_Iscale = BASE_MASS * BASE_ARM_LEN * BASE_ARM_LEN; - float I_scale = drone->params.mass * powf(drone->params.arm_len, 2.0f) / base_Iscale; - drone->params.ixx = BASE_IXX * I_scale * rndf(1.0f - dr, 1.0f + dr); - drone->params.iyy = BASE_IYY * I_scale * rndf(1.0f - dr, 1.0f + dr); - drone->params.izz = BASE_IZZ * I_scale * rndf(1.0f - dr, 1.0f + dr); - - // k_thrust ~ m/l - float k_thrust_scale = (drone->params.mass * drone->params.arm_len) / (BASE_MASS * BASE_ARM_LEN); - drone->params.k_thrust = BASE_K_THRUST * k_thrust_scale * rndf(1.0f - dr, 1.0f + dr); - - // k_ang_damp ~ I - float base_avg_inertia = (BASE_IXX + BASE_IYY + BASE_IZZ) / 3.0f; - float avg_inertia = (drone->params.ixx + drone->params.iyy + drone->params.izz) / 3.0f; - float avg_inertia_scale = avg_inertia / base_avg_inertia; - drone->params.k_ang_damp = BASE_K_ANG_DAMP * avg_inertia_scale * rndf(1.0f - dr, 1.0f + dr); - - // drag ~ x^2 - float drag_scale = powf(drone->params.arm_len, 2.0f) / powf(BASE_ARM_LEN, 2.0f); - drone->params.k_drag = BASE_K_DRAG * drag_scale * rndf(1.0f - dr, 1.0f + dr); - drone->params.b_drag = BASE_B_DRAG * drag_scale * rndf(1.0f - dr, 1.0f + dr); - - // Small gravity randomization - drone->params.gravity = BASE_GRAVITY * rndf(0.99f, 1.01f); - - // RPM ~ 1/x - float rpm_scale = (BASE_ARM_LEN) / (drone->params.arm_len); - drone->params.max_rpm = BASE_MAX_RPM * rpm_scale * rndf(1.0f - dr, 1.0f + dr); - - drone->params.max_vel = BASE_MAX_VEL; - drone->params.max_omega = BASE_MAX_OMEGA; - - drone->params.k_mot = BASE_K_MOT * rndf(1.0f - dr, 1.0f + dr); - drone->params.j_mot = BASE_J_MOT * I_scale * rndf(1.0f - dr, 1.0f + dr); - - for (int i = 0; i < 4; i++) { - drone->state.rpms[i] = 0.0f; - } - drone->state.pos = (Vec3){0.0f, 0.0f, 0.0f}; - drone->prev_pos = drone->state.pos; - drone->state.vel = (Vec3){0.0f, 0.0f, 0.0f}; - drone->state.omega = (Vec3){0.0f, 0.0f, 0.0f}; - drone->state.quat = (Quat){1.0f, 0.0f, 0.0f, 0.0f}; -} - -void compute_derivatives(State* state, Params* params, float* actions, StateDerivative* derivatives) { - // first order rpm lag - float target_rpms[4]; - for (int i = 0; i < 4; i++) { - target_rpms[i] = (actions[i] + 1.0f) * 0.5f * params->max_rpm; - } - - // rpm rates - float rpm_dot[4]; - for (int i = 0; i < 4; i++) { - rpm_dot[i] = (1.0f / params->k_mot) * (target_rpms[i] - state->rpms[i]); - } - - // motor thrusts - float T[4]; - for (int i = 0; i < 4; i++) { - T[i] = params->k_thrust * powf(state->rpms[i], 2.0f); - } - - // body frame net force - Vec3 F_prop_body = {0.0f, 0.0f, T[0] + T[1] + T[2] + T[3]}; - - // body frame force -> world frame force - Vec3 F_prop = quat_rotate(state->quat, F_prop_body); - - // world frame linear drag - Vec3 F_aero; - F_aero.x = -params->b_drag * state->vel.x; - F_aero.y = -params->b_drag * state->vel.y; - F_aero.z = -params->b_drag * state->vel.z; - - // velocity rates, a = F/m - Vec3 v_dot; - v_dot.x = (F_prop.x + F_aero.x) / params->mass; - v_dot.y = (F_prop.y + F_aero.y) / params->mass; - v_dot.z = ((F_prop.z + F_aero.z) / params->mass) - params->gravity; - - // quaternion rates - Quat omega_q = {0.0f, state->omega.x, state->omega.y, state->omega.z}; - Quat q_dot = quat_mul(state->quat, omega_q); - q_dot.w *= 0.5f; - q_dot.x *= 0.5f; - q_dot.y *= 0.5f; - q_dot.z *= 0.5f; - - // body frame torques (plus copter) - //Vec3 Tau_prop; - //Tau_prop.x = params->arm_len*(T[1] - T[3]); - //Tau_prop.y = params->arm_len*(T[2] - T[0]); - //Tau_prop.z = params->k_drag*(T[0] - T[1] + T[2] - T[3]); - - // body frame torques (cross copter) - // M1=FR, M2=BR, M3=BL, M4=FL - // https://www.bitcraze.io/documentation/hardware/crazyflie_2_1_brushless/crazyflie_2_1_brushless-datasheet.pdf - float arm_factor = params->arm_len / sqrtf(2.0f); - Vec3 Tau_prop; - Tau_prop.x = arm_factor * ((T[0] + T[1]) - (T[3] + T[2])); - Tau_prop.y = arm_factor * ((T[0] + T[3]) - (T[1] + T[2])); - Tau_prop.z = params->k_drag * (-T[0] + T[1] - T[2] + T[3]); - - // torque from chaging motor speeds - float Tau_mot_z = params->j_mot * (rpm_dot[0] - rpm_dot[1] + rpm_dot[2] - rpm_dot[3]); - - // torque from angular damping - Vec3 Tau_aero; - Tau_aero.x = -params->k_ang_damp * state->omega.x; - Tau_aero.y = -params->k_ang_damp * state->omega.y; - Tau_aero.z = -params->k_ang_damp * state->omega.z; - - // gyroscopic torque - Vec3 Tau_iner; - Tau_iner.x = (params->iyy - params->izz) * state->omega.y * state->omega.z; - Tau_iner.y = (params->izz - params->ixx) * state->omega.z * state->omega.x; - Tau_iner.z = (params->ixx - params->iyy) * state->omega.x * state->omega.y; - - // angular velocity rates - Vec3 w_dot; - w_dot.x = (Tau_prop.x + Tau_aero.x + Tau_iner.x) / params->ixx; - w_dot.y = (Tau_prop.y + Tau_aero.y + Tau_iner.y) / params->iyy; - w_dot.z = (Tau_prop.z + Tau_aero.z + Tau_iner.z + Tau_mot_z) / params->izz; - - derivatives->vel = state->vel; - derivatives->v_dot = v_dot; - derivatives->q_dot = q_dot; - derivatives->w_dot = w_dot; - for (int i = 0; i < 4; i++) { - derivatives->rpm_dot[i] = rpm_dot[i]; - } -} - -void step(State* initial, StateDerivative* deriv, float dt, State* output) { - output->pos = add3(initial->pos, scalmul3(deriv->vel, dt)); - output->vel = add3(initial->vel, scalmul3(deriv->v_dot, dt)); - output->quat = add_quat(initial->quat, scalmul_quat(deriv->q_dot, dt)); - output->omega = add3(initial->omega, scalmul3(deriv->w_dot, dt)); - for (int i = 0; i < 4; i++) { - output->rpms[i] = initial->rpms[i] + deriv->rpm_dot[i] * dt; - } - quat_normalize(&output->quat); -} - -void rk4_step(State* state, Params* params, float* actions, float dt) { - StateDerivative k1, k2, k3, k4; - State temp_state; - - compute_derivatives(state, params, actions, &k1); - - step(state, &k1, dt * 0.5f, &temp_state); - compute_derivatives(&temp_state, params, actions, &k2); - - step(state, &k2, dt * 0.5f, &temp_state); - compute_derivatives(&temp_state, params, actions, &k3); - - step(state, &k3, dt, &temp_state); - compute_derivatives(&temp_state, params, actions, &k4); - - float dt_6 = dt / 6.0f; - - state->pos.x += (k1.vel.x + 2.0f * k2.vel.x + 2.0f * k3.vel.x + k4.vel.x) * dt_6; - state->pos.y += (k1.vel.y + 2.0f * k2.vel.y + 2.0f * k3.vel.y + k4.vel.y) * dt_6; - state->pos.z += (k1.vel.z + 2.0f * k2.vel.z + 2.0f * k3.vel.z + k4.vel.z) * dt_6; - - state->vel.x += (k1.v_dot.x + 2.0f * k2.v_dot.x + 2.0f * k3.v_dot.x + k4.v_dot.x) * dt_6; - state->vel.y += (k1.v_dot.y + 2.0f * k2.v_dot.y + 2.0f * k3.v_dot.y + k4.v_dot.y) * dt_6; - state->vel.z += (k1.v_dot.z + 2.0f * k2.v_dot.z + 2.0f * k3.v_dot.z + k4.v_dot.z) * dt_6; - - state->quat.w += (k1.q_dot.w + 2.0f * k2.q_dot.w + 2.0f * k3.q_dot.w + k4.q_dot.w) * dt_6; - state->quat.x += (k1.q_dot.x + 2.0f * k2.q_dot.x + 2.0f * k3.q_dot.x + k4.q_dot.x) * dt_6; - state->quat.y += (k1.q_dot.y + 2.0f * k2.q_dot.y + 2.0f * k3.q_dot.y + k4.q_dot.y) * dt_6; - state->quat.z += (k1.q_dot.z + 2.0f * k2.q_dot.z + 2.0f * k3.q_dot.z + k4.q_dot.z) * dt_6; - - state->omega.x += (k1.w_dot.x + 2.0f * k2.w_dot.x + 2.0f * k3.w_dot.x + k4.w_dot.x) * dt_6; - state->omega.y += (k1.w_dot.y + 2.0f * k2.w_dot.y + 2.0f * k3.w_dot.y + k4.w_dot.y) * dt_6; - state->omega.z += (k1.w_dot.z + 2.0f * k2.w_dot.z + 2.0f * k3.w_dot.z + k4.w_dot.z) * dt_6; - - for (int i = 0; i < 4; i++) { - state->rpms[i] += (k1.rpm_dot[i] + 2.0f * k2.rpm_dot[i] + 2.0f * k3.rpm_dot[i] + k4.rpm_dot[i]) * dt_6; - } - - quat_normalize(&state->quat); -} - -void move_drone(Drone* drone, float* actions) { - // clamp actions - clamp4(actions, -1.0f, 1.0f); - - // Domain randomized dt - float dt = DT * rndf(1.0f - DT_RNG, 1.0 + DT_RNG); - - // update drone state - drone->prev_pos = drone->state.pos; - rk4_step(&drone->state, &drone->params, actions, dt); - - // clamp and normalise for observations - clamp3(&drone->state.vel, -drone->params.max_vel, drone->params.max_vel); - clamp3(&drone->state.omega, -drone->params.max_omega, drone->params.max_omega); -} - -void reset_rings(Target* ring_buffer, int num_rings) { - ring_buffer[0] = rndring(RING_RADIUS); - - // ensure rings are spaced at least 2*ring_radius apart - for (int i = 1; i < num_rings; i++) { - do { - ring_buffer[i] = rndring(RING_RADIUS); - } while (norm3(sub3(ring_buffer[i].pos, ring_buffer[i - 1].pos)) < 2.0f * RING_RADIUS); - } -} - -int check_ring(Drone* drone, Target* ring) { - // previous dot product negative if on the 'entry' side of the ring's plane - float prev_dot = dot3(sub3(drone->prev_pos, ring->pos), ring->normal); - - // new dot product positive if on the 'exit' side of the ring's plane - float new_dot = dot3(sub3(drone->state.pos, ring->pos), ring->normal); - - bool valid_dir = (prev_dot < 0.0f && new_dot > 0.0f); - bool invalid_dir = (prev_dot > 0.0f && new_dot < 0.0f); - - // if we have crossed the plane of the ring - if (valid_dir || invalid_dir) { - // find intesection with ring's plane - Vec3 dir = sub3(drone->state.pos, drone->prev_pos); - float t = -prev_dot / dot3(ring->normal, dir); // possible nan - - Vec3 intersection = add3(drone->prev_pos, scalmul3(dir, t)); - float dist = norm3(sub3(intersection, ring->pos)); - - // reward or terminate based on distance to ring center - if (dist < (ring->radius - 0.5) && valid_dir) { - return 1; - } else if (dist < ring->radius + 0.5) { - return -1; - } - } - - return 0; -} - -Drone *nearest_drone(Drone *agent, Drone *others, int num_agents) { - float min_dist = FLT_MAX; - Drone *nearest = NULL; - - for (int i = 0; i < num_agents; i++) { - Drone *other = &others[i]; - if (other == agent) continue; - - float dist = norm3(sub3(agent->state.pos, other->state.pos)); - - if (dist < min_dist) { - min_dist = dist; - nearest = other; - } - } - - return nearest; -} - -bool check_collision(Drone *agent, Drone *others, int num_agents) { - if (num_agents <= 1) return false; - - Drone *nearest = nearest_drone(agent, others, num_agents); - Vec3 to_nearest = sub3(agent->state.pos, nearest->state.pos); - float nearest_dist = norm3(to_nearest); - - return nearest_dist < 0.1f; -} - diff --git a/pufferlib/ocean/drone/render.h b/pufferlib/ocean/drone/render.h deleted file mode 100644 index 7e3ff39720..0000000000 --- a/pufferlib/ocean/drone/render.h +++ /dev/null @@ -1,336 +0,0 @@ -// Originally made by Sam Turner and Finlay Sanders, 2025. -// Included in pufferlib under the original project's MIT license. -// https://github.com/tensaur/drone - -#pragma once - -#include - -#include "drone.h" -#include "dronelib.h" -#include "raylib.h" - -#define R (Color){255, 0, 0, 255} -#define W (Color){255, 255, 255, 255} -#define B (Color){0, 0, 255, 255} -Color COLORS[64] = { - W, B, B, R, R, B, B, W, - B, W, B, R, R, B, W, B, - B, B, W, R, R, W, B, B, - R, R, R, R, R, R, R, R, - R, R, R, R, R, R, R, R, - B, B, W, R, R, W, B, B, - B, W, B, R, R, B, W, B, - W, B, B, R, R, B, B, W -}; -#undef R -#undef W -#undef B - -typedef struct Client Client; - -struct Client { - Camera3D camera; - float width; - float height; - - float camera_distance; - float camera_azimuth; - float camera_elevation; - bool is_dragging; - Vector2 last_mouse_pos; - - // Trailing path buffer (for rendering only) - Trail *trails; -}; - -void c_close_client(Client *client) { - CloseWindow(); - free(client->trails); - free(client); -} - -static void update_camera_position(Client *c) { - float r = c->camera_distance; - float az = c->camera_azimuth; - float el = c->camera_elevation; - - float x = r * cosf(el) * cosf(az); - float y = r * cosf(el) * sinf(az); - float z = r * sinf(el); - - c->camera.position = (Vector3){x, y, z}; - c->camera.target = (Vector3){0, 0, 0}; -} - -void handle_camera_controls(Client *client) { - Vector2 mouse_pos = GetMousePosition(); - - if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) { - client->is_dragging = true; - client->last_mouse_pos = mouse_pos; - } - - if (IsMouseButtonReleased(MOUSE_BUTTON_LEFT)) { - client->is_dragging = false; - } - - if (client->is_dragging && IsMouseButtonDown(MOUSE_BUTTON_LEFT)) { - Vector2 mouse_delta = {mouse_pos.x - client->last_mouse_pos.x, - mouse_pos.y - client->last_mouse_pos.y}; - - float sensitivity = 0.005f; - - client->camera_azimuth -= mouse_delta.x * sensitivity; - - client->camera_elevation += mouse_delta.y * sensitivity; - client->camera_elevation = - clampf(client->camera_elevation, -PI / 2.0f + 0.1f, PI / 2.0f - 0.1f); - - client->last_mouse_pos = mouse_pos; - - update_camera_position(client); - } - - float wheel = GetMouseWheelMove(); - if (wheel != 0) { - client->camera_distance -= wheel * 2.0f; - client->camera_distance = clampf(client->camera_distance, 5.0f, 100.0f); - update_camera_position(client); - } -} - -Client *make_client(DroneEnv *env) { - Client *client = (Client *)calloc(1, sizeof(Client)); - - client->width = WIDTH; - client->height = HEIGHT; - - SetConfigFlags(FLAG_MSAA_4X_HINT); // antialiasing - InitWindow(WIDTH, HEIGHT, "PufferLib Drone"); - -#ifndef __EMSCRIPTEN__ - SetTargetFPS(60); -#endif - - if (!IsWindowReady()) { - TraceLog(LOG_ERROR, "Window failed to initialize\n"); - free(client); - return NULL; - } - - client->camera_distance = 40.0f; - client->camera_azimuth = 0.0f; - client->camera_elevation = PI / 10.0f; - client->is_dragging = false; - client->last_mouse_pos = (Vector2){0.0f, 0.0f}; - - client->camera.up = (Vector3){0.0f, 0.0f, 1.0f}; - client->camera.fovy = 45.0f; - client->camera.projection = CAMERA_PERSPECTIVE; - - update_camera_position(client); - - // Initialize trail buffer - client->trails = (Trail *)calloc(env->num_agents, sizeof(Trail)); - for (int i = 0; i < env->num_agents; i++) { - Trail *trail = &client->trails[i]; - trail->index = 0; - trail->count = 0; - for (int j = 0; j < TRAIL_LENGTH; j++) { - trail->pos[j] = env->agents[i].state.pos; - } - } - - return client; -} - -const Color PUFF_RED = (Color){187, 0, 0, 255}; -const Color PUFF_CYAN = (Color){0, 187, 187, 255}; -const Color PUFF_WHITE = (Color){241, 241, 241, 241}; -const Color PUFF_BACKGROUND = (Color){6, 24, 24, 255}; - -void DrawRing3D(Target ring, float thickness, Color entryColor, Color exitColor) { - float half_thick = thickness / 2.0f; - - Vector3 center_pos = {ring.pos.x, ring.pos.y, ring.pos.z}; - - Vector3 entry_start_pos = {center_pos.x - half_thick * ring.normal.x, - center_pos.y - half_thick * ring.normal.y, - center_pos.z - half_thick * ring.normal.z}; - - DrawCylinderWiresEx(entry_start_pos, center_pos, ring.radius, ring.radius, 32, - entryColor); - - Vector3 exit_end_pos = {center_pos.x + half_thick * ring.normal.x, - center_pos.y + half_thick * ring.normal.y, - center_pos.z + half_thick * ring.normal.z}; - - DrawCylinderWiresEx(center_pos, exit_end_pos, ring.radius, ring.radius, 32, - exitColor); -} - -void c_render(DroneEnv *env) { - if (env->client == NULL) { - env->client = make_client(env); - if (env->client == NULL) { - TraceLog(LOG_ERROR, "Failed to initialize client for rendering\n"); - return; - } - } - - if (WindowShouldClose()) { - c_close(env); - exit(0); - } - - if (IsKeyDown(KEY_ESCAPE)) { - c_close(env); - exit(0); - } - - if (IsKeyPressed(KEY_SPACE)) { - env->task = (DroneTask)((env->task + 1) % TASK_N); - - if (env->task == RACE) { - reset_rings(env->ring_buffer, env->max_rings); - } - - for (int i = 0; i < env->num_agents; i++) { - set_target(env->task, env->agents, i, env->num_agents); - } - } - - handle_camera_controls(env->client); - - Client *client = env->client; - - for (int i = 0; i < env->num_agents; i++) { - Drone *agent = &env->agents[i]; - Trail *trail = &client->trails[i]; - trail->pos[trail->index] = agent->state.pos; - trail->index = (trail->index + 1) % TRAIL_LENGTH; - if (trail->count < TRAIL_LENGTH) { - trail->count++; - } - if (env->terminals[i]) { - trail->index = 0; - trail->count = 0; - } - } - - BeginDrawing(); - ClearBackground(PUFF_BACKGROUND); - - BeginMode3D(client->camera); - - // draws bounding cube - DrawCubeWires((Vector3){0.0f, 0.0f, 0.0f}, GRID_X * 2.0f, GRID_Y * 2.0f, - GRID_Z * 2.0f, WHITE); - - for (int i = 0; i < env->num_agents; i++) { - Drone *agent = &env->agents[i]; - - // draws drone body - Color body_color = COLORS[i]; - DrawSphere( - (Vector3){agent->state.pos.x, agent->state.pos.y, agent->state.pos.z}, - 0.3f, body_color); - - // draws rotors according to thrust - float T[4]; - for (int j = 0; j < 4; j++) { - float rpm = - (env->actions[4 * i + j] + 1.0f) * 0.5f * agent->params.max_rpm; - T[j] = agent->params.k_thrust * rpm * rpm; - } - - const float rotor_radius = 0.15f; - const float visual_arm_len = agent->params.arm_len * 4.0f; - - Vec3 rotor_offsets_body[4] = {{+visual_arm_len, 0.0f, 0.0f}, - {-visual_arm_len, 0.0f, 0.0f}, - {0.0f, +visual_arm_len, 0.0f}, - {0.0f, -visual_arm_len, 0.0f}}; - - // Color base_colors[4] = {ORANGE, PURPLE, LIME, SKYBLUE}; - Color base_colors[4] = {body_color, body_color, body_color, body_color}; - - for (int j = 0; j < 4; j++) { - Vec3 world_off = quat_rotate(agent->state.quat, rotor_offsets_body[j]); - - Vector3 rotor_pos = {agent->state.pos.x + world_off.x, - agent->state.pos.y + world_off.y, - agent->state.pos.z + world_off.z}; - - float rpm = - (env->actions[4 * i + j] + 1.0f) * 0.5f * agent->params.max_rpm; - float intensity = 0.75f + 0.25f * (rpm / agent->params.max_rpm); - - Color rotor_color = - (Color){(unsigned char)(base_colors[j].r * intensity), - (unsigned char)(base_colors[j].g * intensity), - (unsigned char)(base_colors[j].b * intensity), 255}; - - DrawSphere(rotor_pos, rotor_radius, rotor_color); - - DrawCylinderEx( - (Vector3){agent->state.pos.x, agent->state.pos.y, agent->state.pos.z}, - rotor_pos, 0.02f, 0.02f, 8, BLACK); - } - - // draws line with direction and magnitude of velocity / 10 - if (norm3(agent->state.vel) > 0.1f) { - DrawLine3D( - (Vector3){agent->state.pos.x, agent->state.pos.y, agent->state.pos.z}, - (Vector3){agent->state.pos.x + agent->state.vel.x * 0.1f, - agent->state.pos.y + agent->state.vel.y * 0.1f, - agent->state.pos.z + agent->state.vel.z * 0.1f}, - MAGENTA); - } - - // Draw trailing path - Trail *trail = &client->trails[i]; - if (trail->count <= 2) { - continue; - } - for (int j = 0; j < trail->count - 1; j++) { - int idx0 = (trail->index - j - 1 + TRAIL_LENGTH) % TRAIL_LENGTH; - int idx1 = (trail->index - j - 2 + TRAIL_LENGTH) % TRAIL_LENGTH; - float alpha = - (float)(TRAIL_LENGTH - j) / (float)trail->count * 0.8f; // fade out - Color trail_color = ColorAlpha((Color){0, 187, 187, 255}, alpha); - DrawLine3D( - (Vector3){trail->pos[idx0].x, trail->pos[idx0].y, trail->pos[idx0].z}, - (Vector3){trail->pos[idx1].x, trail->pos[idx1].y, trail->pos[idx1].z}, - trail_color); - } - } - - // Rings - if (env->task == RACE) { - float ring_thickness = 0.2f; - for (int i = 0; i < env->max_rings; i++) { - Target ring = env->ring_buffer[i]; - DrawRing3D(ring, ring_thickness, GREEN, BLUE); - } - } - - if (IsKeyDown(KEY_TAB)) { - for (int i = 0; i < env->num_agents; i++) { - Drone *agent = &env->agents[i]; - Vec3 target_pos = agent->target->pos; - DrawSphere((Vector3){target_pos.x, target_pos.y, target_pos.z}, 0.45f, - (Color){0, 255, 255, 100}); - } - } - - EndMode3D(); - - DrawText("Left click + drag: Rotate camera", 10, 10, 16, PUFF_WHITE); - DrawText("Mouse wheel: Zoom in/out", 10, 30, 16, PUFF_WHITE); - DrawText(TextFormat("Task: %s", TASK_NAMES[env->task]), 10, 50, 16, - PUFF_WHITE); - - EndDrawing(); -} diff --git a/pufferlib/ocean/drone/tasks.h b/pufferlib/ocean/drone/tasks.h deleted file mode 100644 index 65dbe151e9..0000000000 --- a/pufferlib/ocean/drone/tasks.h +++ /dev/null @@ -1,158 +0,0 @@ -// Originally made by Sam Turner and Finlay Sanders, 2025. -// Included in pufferlib under the original project's MIT license. -// https://github.com/tensaur/drone - -#pragma once - -#include -#include - -#include "dronelib.h" - -typedef enum { - IDLE, - HOVER, - ORBIT, - FOLLOW, - CUBE, - CONGO, - FLAG, - RACE, - TASK_N // Should always be last -} DroneTask; - -static char const *TASK_NAMES[TASK_N] = {"idle", "hover", "orbit", "follow", - "cube", "congo", "flag", "race"}; - -void move_target(Drone *agent) { - agent->target->pos.x += agent->target->vel.x; - agent->target->pos.y += agent->target->vel.y; - agent->target->pos.z += agent->target->vel.z; - - if (agent->target->pos.x < -MARGIN_X || agent->target->pos.x > MARGIN_X) { - agent->target->vel.x = -agent->target->vel.x; - } - if (agent->target->pos.y < -MARGIN_Y || agent->target->pos.y > MARGIN_Y) { - agent->target->vel.y = -agent->target->vel.y; - } - if (agent->target->pos.z < -MARGIN_Z || agent->target->pos.z > MARGIN_Z) { - agent->target->vel.z = -agent->target->vel.z; - } -} - -void set_target_idle(Drone* agent) { - agent->target->pos = - (Vec3){rndf(-MARGIN_X, MARGIN_X), rndf(-MARGIN_Y, MARGIN_Y), - rndf(-MARGIN_Z, MARGIN_Z)}; - agent->target->vel = - (Vec3){rndf(-V_TARGET, V_TARGET), rndf(-V_TARGET, V_TARGET), - rndf(-V_TARGET, V_TARGET)}; -} - -void set_target_hover(Drone* agent) { - agent->target->pos = agent->state.pos; - agent->target->vel = (Vec3){0.0f, 0.0f, 0.0f}; -} - -void set_target_orbit(Drone* agent, int idx, int num_agents) { - // Fibbonacci sphere algorithm - float R = 8.0f; - float phi = M_PI * (sqrt(5.0f) - 1.0f); - float y = 1.0f - 2 * ((float)idx / (float)num_agents); - float radius = sqrtf(1.0f - y * y); - - float theta = phi * idx; - float x = cos(theta) * radius; - float z = sin(theta) * radius; - - agent->target->pos = (Vec3){R * x, R * z, R * y}; // convert to z up - agent->target->vel = (Vec3){0.0f, 0.0f, 0.0f}; -} - -void set_target_follow(Drone* agents, int idx) { - Drone *agent = &agents[idx]; - - if (idx == 0) { - set_target_idle(agent); - } else { - agent->target->pos = agents[0].target->pos; - agent->target->vel = agents[0].target->vel; - } -} - -void set_target_cube(Drone* agent, int idx) { - float z = idx / 16; - idx = idx % 16; - float x = (float)(idx % 4); - float y = (float)(idx / 4); - agent->target->pos = (Vec3){4 * x - 6, 4 * y - 6, 4 * z - 6}; - agent->target->vel = (Vec3){0.0f, 0.0f, 0.0f}; -} - -void set_target_congo(Drone* agents, int idx) { - if (idx == 0) { - set_target_idle(&agents[0]); - return; - } - - Drone* follow = &agents[idx - 1]; - Drone* lead = &agents[idx]; - lead->target->pos = follow->target->pos; - lead->target->vel = follow->target->vel; - - // TODO: Slow hack - for (int i = 0; i < 40; i++) { - move_target(lead); - } -} - -void set_target_flag(Drone* agent, int idx) { - float x = (float)(idx % 8); - float y = (float)(idx / 8); - x = 2.0f * x - 7; - y = 5 - 1.5f * y; - agent->target->pos = (Vec3){0.0f, x, y}; - agent->target->vel = (Vec3){0.0f, 0.0f, 0.0f}; -} - -void set_target_race(Drone* agent) { - agent->buffer_idx = (agent->buffer_idx + 1) % agent->buffer_size; - *agent->target = agent->buffer[agent->buffer_idx]; -} - -void set_target(DroneTask task, Drone* agents, int idx, int num_agents) { - Drone *agent = &agents[idx]; - - if (task == IDLE) set_target_idle(agent); - else if (task == HOVER) set_target_hover(agent); - else if (task == ORBIT) set_target_orbit(agent, idx, num_agents); - else if (task == FOLLOW) set_target_follow(agents, idx); - else if (task == CUBE) set_target_cube(agent, idx); - else if (task == CONGO) set_target_congo(agents, idx); - else if (task == FLAG) set_target_flag(agent, idx); - else if (task == RACE) set_target_race(agent); -} - -float static_task_reward(Drone *agent, bool collision) { - Vec3 to_target = sub3(agent->state.pos, agent->target->pos); - float dist = norm3(to_target); - float dist_reward = expf(-2.0f * dist); - - float density_reward = collision ? -1.0f : 0.0f; - float reward = dist_reward + density_reward; - - if (dist_reward < 0.0f && density_reward < 0.0f) { - reward *= -1.0f; - } - - float dr = reward - agent->last_dist_reward; - agent->last_dist_reward = reward; - - return dr; -} - -float dynamic_task_reward(Drone *agent, bool collision, int ring_passage) { - float density_reward = collision ? -1.0f : 0.0f; - return density_reward + (float)ring_passage; -} - diff --git a/pufferlib/ocean/enduro/binding.c b/pufferlib/ocean/enduro/binding.c deleted file mode 100644 index 04919d12d4..0000000000 --- a/pufferlib/ocean/enduro/binding.c +++ /dev/null @@ -1,40 +0,0 @@ -#include "enduro.h" -#include -#define Env Enduro -#include "../env_binding.h" - -static int my_init(Env* env, PyObject* args, PyObject* kwargs) { - env->width = unpack(kwargs, "width"); - env->height = unpack(kwargs, "height"); - env->car_width = unpack(kwargs, "car_width"); - env->car_height = unpack(kwargs, "car_height"); - env->max_enemies = unpack(kwargs, "max_enemies"); - env->continuous = unpack(kwargs, "continuous"); - - PyObject* seed_val = PyDict_GetItemString(kwargs, "seed"); - if (seed_val) { - env->seed = unpack(kwargs, "seed"); - // Initialize the RNG state with the seed - env->rng_state = env->seed; - } - - return 0; -} - -static int my_log(PyObject* dict, Log* log) { - assign_to_dict(dict, "perf", log->perf); - assign_to_dict(dict, "score", log->score); - assign_to_dict(dict, "episode_return", log->episode_return); - assign_to_dict(dict, "episode_length", log->episode_length); - assign_to_dict(dict, "reward", log->reward); - assign_to_dict(dict, "step_rew_car_passed_no_crash", log->step_rew_car_passed_no_crash); - assign_to_dict(dict, "crashed_penalty", log->crashed_penalty); - assign_to_dict(dict, "passed_cars", log->passed_cars); - assign_to_dict(dict, "passed_by_enemy", log->passed_by_enemy); - assign_to_dict(dict, "cars_to_pass", log->cars_to_pass); - assign_to_dict(dict, "days_completed", log->days_completed); - assign_to_dict(dict, "days_failed", log->days_failed); - assign_to_dict(dict, "collisions_player_vs_car", log->collisions_player_vs_car); - assign_to_dict(dict, "collisions_player_vs_road", log->collisions_player_vs_road); - return 0; -} diff --git a/pufferlib/ocean/enduro/enduro.py b/pufferlib/ocean/enduro/enduro.py deleted file mode 100644 index 286e8219e9..0000000000 --- a/pufferlib/ocean/enduro/enduro.py +++ /dev/null @@ -1,81 +0,0 @@ -import random -import numpy as np -import gymnasium - -import pufferlib -from pufferlib.ocean.enduro import binding - -class Enduro(pufferlib.PufferEnv): - def __init__(self, num_envs=1, render_mode=None, - width=152, height=210, car_width=16, car_height=11, - max_enemies=10, frameskip=1, continuous=False, - log_interval=128, buf=None, seed=None): - - self.single_observation_space = gymnasium.spaces.Box( - low=0, high=1, shape=(8 + (5 * max_enemies) + 9 + 1,), dtype=np.float32 - ) - # Example: 9 discrete actions - self.single_action_space = gymnasium.spaces.Discrete(9) - - self.render_mode = render_mode - self.num_agents = num_envs - self.continuous = continuous - self.log_interval = log_interval - self.human_action = None - self.tick = 0 - if seed is None: - self.seed = random.randint(1, 1000000) - else: - self.seed = 0 - super().__init__(buf) - - self.c_envs = binding.vec_init( - self.observations, self.actions, self.rewards, - self.terminals, self.truncations, num_envs, self.seed, - width=width, height=height, car_width=car_width, - car_height=car_height, max_enemies=max_enemies, - frameskip=frameskip, continuous=continuous - ) - - def reset(self, seed=None): - binding.vec_reset(self.c_envs, seed) - self.tick = 0 - return self.observations, [] - - def step(self, actions): - self.actions[:] = actions - - self.tick += 1 - binding.vec_step(self.c_envs) - - info = [] - if self.tick % self.log_interval == 0: - info.append(binding.vec_log(self.c_envs)) - - return (self.observations, self.rewards, - self.terminals, self.truncations, info) - - def render(self): - binding.vec_render(self.c_envs, 0) - - def close(self): - binding.vec_close(self.c_envs) - -def test_performance(timeout=10, atn_cache=1024): - env = Enduro(num_envs=2) - env.reset(env.seed) - tick = 0 - - actions = np.random.randint(0, env.single_action_space.n, (atn_cache, env.num_agents)) - - import time - start = time.time() - while time.time() - start < timeout: - atn = actions[tick % atn_cache] - env.step(atn) - tick += 1 - - print(f'SPS: {env.num_agents * tick / (time.time() - start)}') - -if __name__ == '__main__': - test_performance() \ No newline at end of file diff --git a/pufferlib/ocean/env_binding.h b/pufferlib/ocean/env_binding.h deleted file mode 100644 index f64b6148bc..0000000000 --- a/pufferlib/ocean/env_binding.h +++ /dev/null @@ -1,676 +0,0 @@ -#include -#include - -// Forward declarations for env-specific functions supplied by user -static int my_log(PyObject* dict, Log* log); -static int my_init(Env* env, PyObject* args, PyObject* kwargs); - -static PyObject* my_shared(PyObject* self, PyObject* args, PyObject* kwargs); -#ifndef MY_SHARED -static PyObject* my_shared(PyObject* self, PyObject* args, PyObject* kwargs) { - return NULL; -} -#endif - -static PyObject* my_get(PyObject* dict, Env* env); -#ifndef MY_GET -static PyObject* my_get(PyObject* dict, Env* env) { - return NULL; -} -#endif - -static int my_put(Env* env, PyObject* args, PyObject* kwargs); -#ifndef MY_PUT -static int my_put(Env* env, PyObject* args, PyObject* kwargs) { - return 0; -} -#endif - -#ifndef MY_METHODS -#define MY_METHODS {NULL, NULL, 0, NULL} -#endif - -static Env* unpack_env(PyObject* args) { - PyObject* handle_obj = PyTuple_GetItem(args, 0); - if (!PyObject_TypeCheck(handle_obj, &PyLong_Type)) { - PyErr_SetString(PyExc_TypeError, "env_handle must be an integer"); - return NULL; - } - - Env* env = (Env*)PyLong_AsVoidPtr(handle_obj); - if (!env) { - PyErr_SetString(PyExc_ValueError, "Invalid env handle"); - return NULL; - } - - return env; -} - -// Python function to initialize the environment -static PyObject* env_init(PyObject* self, PyObject* args, PyObject* kwargs) { - if (PyTuple_Size(args) != 6) { - PyErr_SetString(PyExc_TypeError, "Environment requires 5 arguments"); - return NULL; - } - - Env* env = (Env*)calloc(1, sizeof(Env)); - if (!env) { - PyErr_SetString(PyExc_MemoryError, "Failed to allocate environment"); - return NULL; - } - - PyObject* obs = PyTuple_GetItem(args, 0); - if (!PyObject_TypeCheck(obs, &PyArray_Type)) { - PyErr_SetString(PyExc_TypeError, "Observations must be a NumPy array"); - return NULL; - } - PyArrayObject* observations = (PyArrayObject*)obs; - if (!PyArray_ISCONTIGUOUS(observations)) { - PyErr_SetString(PyExc_ValueError, "Observations must be contiguous"); - return NULL; - } - env->observations = PyArray_DATA(observations); - - PyObject* act = PyTuple_GetItem(args, 1); - if (!PyObject_TypeCheck(act, &PyArray_Type)) { - PyErr_SetString(PyExc_TypeError, "Actions must be a NumPy array"); - return NULL; - } - PyArrayObject* actions = (PyArrayObject*)act; - if (!PyArray_ISCONTIGUOUS(actions)) { - PyErr_SetString(PyExc_ValueError, "Actions must be contiguous"); - return NULL; - } - env->actions = PyArray_DATA(actions); - if (PyArray_ITEMSIZE(actions) == sizeof(double)) { - PyErr_SetString(PyExc_ValueError, "Action tensor passed as float64 (pass np.float32 buffer)"); - return NULL; - } - - PyObject* rew = PyTuple_GetItem(args, 2); - if (!PyObject_TypeCheck(rew, &PyArray_Type)) { - PyErr_SetString(PyExc_TypeError, "Rewards must be a NumPy array"); - return NULL; - } - PyArrayObject* rewards = (PyArrayObject*)rew; - if (!PyArray_ISCONTIGUOUS(rewards)) { - PyErr_SetString(PyExc_ValueError, "Rewards must be contiguous"); - return NULL; - } - if (PyArray_NDIM(rewards) != 1) { - PyErr_SetString(PyExc_ValueError, "Rewards must be 1D"); - return NULL; - } - env->rewards = PyArray_DATA(rewards); - - PyObject* term = PyTuple_GetItem(args, 3); - if (!PyObject_TypeCheck(term, &PyArray_Type)) { - PyErr_SetString(PyExc_TypeError, "Terminals must be a NumPy array"); - return NULL; - } - PyArrayObject* terminals = (PyArrayObject*)term; - if (!PyArray_ISCONTIGUOUS(terminals)) { - PyErr_SetString(PyExc_ValueError, "Terminals must be contiguous"); - return NULL; - } - if (PyArray_NDIM(terminals) != 1) { - PyErr_SetString(PyExc_ValueError, "Terminals must be 1D"); - return NULL; - } - env->terminals = PyArray_DATA(terminals); - - PyObject* trunc = PyTuple_GetItem(args, 4); - if (!PyObject_TypeCheck(trunc, &PyArray_Type)) { - PyErr_SetString(PyExc_TypeError, "Truncations must be a NumPy array"); - return NULL; - } - PyArrayObject* truncations = (PyArrayObject*)trunc; - if (!PyArray_ISCONTIGUOUS(truncations)) { - PyErr_SetString(PyExc_ValueError, "Truncations must be contiguous"); - return NULL; - } - if (PyArray_NDIM(truncations) != 1) { - PyErr_SetString(PyExc_ValueError, "Truncations must be 1D"); - return NULL; - } - // env->truncations = PyArray_DATA(truncations); - - - PyObject* seed_arg = PyTuple_GetItem(args, 5); - if (!PyObject_TypeCheck(seed_arg, &PyLong_Type)) { - PyErr_SetString(PyExc_TypeError, "seed must be an integer"); - return NULL; - } - int seed = PyLong_AsLong(seed_arg); - - // Assumes each process has the same number of environments - srand(seed); - - // If kwargs is NULL, create a new dictionary - if (kwargs == NULL) { - kwargs = PyDict_New(); - } else { - Py_INCREF(kwargs); // We need to increment the reference since we'll be modifying it - } - - // Add the seed to kwargs - PyObject* py_seed = PyLong_FromLong(seed); - if (PyDict_SetItemString(kwargs, "seed", py_seed) < 0) { - PyErr_SetString(PyExc_RuntimeError, "Failed to set seed in kwargs"); - Py_DECREF(py_seed); - Py_DECREF(kwargs); - return NULL; - } - Py_DECREF(py_seed); - - PyObject* empty_args = PyTuple_New(0); - my_init(env, empty_args, kwargs); - Py_DECREF(kwargs); - if (PyErr_Occurred()) { - return NULL; - } - - return PyLong_FromVoidPtr(env); -} - -// Python function to reset the environment -static PyObject* env_reset(PyObject* self, PyObject* args) { - if (PyTuple_Size(args) != 2) { - PyErr_SetString(PyExc_TypeError, "env_reset requires 2 arguments"); - return NULL; - } - - Env* env = unpack_env(args); - if (!env){ - return NULL; - } - c_reset(env); - Py_RETURN_NONE; -} - -// Python function to step the environment -static PyObject* env_step(PyObject* self, PyObject* args) { - int num_args = PyTuple_Size(args); - if (num_args != 1) { - PyErr_SetString(PyExc_TypeError, "vec_render requires 1 argument"); - return NULL; - } - - Env* env = unpack_env(args); - if (!env){ - return NULL; - } - c_step(env); - Py_RETURN_NONE; -} - -// Python function to step the environment -static PyObject* env_render(PyObject* self, PyObject* args) { - Env* env = unpack_env(args); - if (!env){ - return NULL; - } - c_render(env); - Py_RETURN_NONE; -} - -// Python function to close the environment -static PyObject* env_close(PyObject* self, PyObject* args) { - Env* env = unpack_env(args); - if (!env){ - return NULL; - } - c_close(env); - free(env); - Py_RETURN_NONE; -} - -static PyObject* env_get(PyObject* self, PyObject* args) { - Env* env = unpack_env(args); - if (!env){ - return NULL; - } - PyObject* dict = PyDict_New(); - my_get(dict, env); - if (PyErr_Occurred()) { - return NULL; - } - return dict; -} - -static PyObject* env_put(PyObject* self, PyObject* args, PyObject* kwargs) { - int num_args = PyTuple_Size(args); - if (num_args != 1) { - PyErr_SetString(PyExc_TypeError, "env_put requires 1 positional argument"); - return NULL; - } - - Env* env = unpack_env(args); - if (!env){ - return NULL; - } - - PyObject* empty_args = PyTuple_New(0); - my_put(env, empty_args, kwargs); - if (PyErr_Occurred()) { - return NULL; - } - - Py_RETURN_NONE; -} - -typedef struct { - Env** envs; - int num_envs; -} VecEnv; - -static VecEnv* unpack_vecenv(PyObject* args) { - PyObject* handle_obj = PyTuple_GetItem(args, 0); - if (!PyObject_TypeCheck(handle_obj, &PyLong_Type)) { - PyErr_SetString(PyExc_TypeError, "env_handle must be an integer"); - return NULL; - } - - VecEnv* vec = (VecEnv*)PyLong_AsVoidPtr(handle_obj); - if (!vec) { - PyErr_SetString(PyExc_ValueError, "Missing or invalid vec env handle"); - return NULL; - } - - if (vec->num_envs <= 0) { - PyErr_SetString(PyExc_ValueError, "Missing or invalid vec env handle"); - return NULL; - } - - return vec; -} - -static PyObject* vec_init(PyObject* self, PyObject* args, PyObject* kwargs) { - if (PyTuple_Size(args) != 7) { - PyErr_SetString(PyExc_TypeError, "vec_init requires 6 arguments"); - return NULL; - } - - VecEnv* vec = (VecEnv*)calloc(1, sizeof(VecEnv)); - if (!vec) { - PyErr_SetString(PyExc_MemoryError, "Failed to allocate vec env"); - return NULL; - } - PyObject* num_envs_arg = PyTuple_GetItem(args, 5); - if (!PyObject_TypeCheck(num_envs_arg, &PyLong_Type)) { - PyErr_SetString(PyExc_TypeError, "num_envs must be an integer"); - return NULL; - } - int num_envs = PyLong_AsLong(num_envs_arg); - if (num_envs <= 0) { - PyErr_SetString(PyExc_TypeError, "num_envs must be greater than 0"); - return NULL; - } - vec->num_envs = num_envs; - vec->envs = (Env**)calloc(num_envs, sizeof(Env*)); - if (!vec->envs) { - PyErr_SetString(PyExc_MemoryError, "Failed to allocate vec env"); - return NULL; - } - - PyObject* seed_obj = PyTuple_GetItem(args, 6); - if (!PyObject_TypeCheck(seed_obj, &PyLong_Type)) { - PyErr_SetString(PyExc_TypeError, "seed must be an integer"); - return NULL; - } - int seed = PyLong_AsLong(seed_obj); - - PyObject* obs = PyTuple_GetItem(args, 0); - if (!PyObject_TypeCheck(obs, &PyArray_Type)) { - PyErr_SetString(PyExc_TypeError, "Observations must be a NumPy array"); - return NULL; - } - PyArrayObject* observations = (PyArrayObject*)obs; - if (!PyArray_ISCONTIGUOUS(observations)) { - PyErr_SetString(PyExc_ValueError, "Observations must be contiguous"); - return NULL; - } - if (PyArray_NDIM(observations) < 2) { - PyErr_SetString(PyExc_ValueError, "Batched Observations must be at least 2D"); - return NULL; - } - - PyObject* act = PyTuple_GetItem(args, 1); - if (!PyObject_TypeCheck(act, &PyArray_Type)) { - PyErr_SetString(PyExc_TypeError, "Actions must be a NumPy array"); - return NULL; - } - PyArrayObject* actions = (PyArrayObject*)act; - if (!PyArray_ISCONTIGUOUS(actions)) { - PyErr_SetString(PyExc_ValueError, "Actions must be contiguous"); - return NULL; - } - if (PyArray_ITEMSIZE(actions) == sizeof(double)) { - PyErr_SetString(PyExc_ValueError, "Action tensor passed as float64 (pass np.float32 buffer)"); - return NULL; - } - - PyObject* rew = PyTuple_GetItem(args, 2); - if (!PyObject_TypeCheck(rew, &PyArray_Type)) { - PyErr_SetString(PyExc_TypeError, "Rewards must be a NumPy array"); - return NULL; - } - PyArrayObject* rewards = (PyArrayObject*)rew; - if (!PyArray_ISCONTIGUOUS(rewards)) { - PyErr_SetString(PyExc_ValueError, "Rewards must be contiguous"); - return NULL; - } - if (PyArray_NDIM(rewards) != 1) { - PyErr_SetString(PyExc_ValueError, "Rewards must be 1D"); - return NULL; - } - - PyObject* term = PyTuple_GetItem(args, 3); - if (!PyObject_TypeCheck(term, &PyArray_Type)) { - PyErr_SetString(PyExc_TypeError, "Terminals must be a NumPy array"); - return NULL; - } - PyArrayObject* terminals = (PyArrayObject*)term; - if (!PyArray_ISCONTIGUOUS(terminals)) { - PyErr_SetString(PyExc_ValueError, "Terminals must be contiguous"); - return NULL; - } - if (PyArray_NDIM(terminals) != 1) { - PyErr_SetString(PyExc_ValueError, "Terminals must be 1D"); - return NULL; - } - - PyObject* trunc = PyTuple_GetItem(args, 4); - if (!PyObject_TypeCheck(trunc, &PyArray_Type)) { - PyErr_SetString(PyExc_TypeError, "Truncations must be a NumPy array"); - return NULL; - } - PyArrayObject* truncations = (PyArrayObject*)trunc; - if (!PyArray_ISCONTIGUOUS(truncations)) { - PyErr_SetString(PyExc_ValueError, "Truncations must be contiguous"); - return NULL; - } - if (PyArray_NDIM(truncations) != 1) { - PyErr_SetString(PyExc_ValueError, "Truncations must be 1D"); - return NULL; - } - - // If kwargs is NULL, create a new dictionary - if (kwargs == NULL) { - kwargs = PyDict_New(); - } else { - Py_INCREF(kwargs); // We need to increment the reference since we'll be modifying it - } - - for (int i = 0; i < num_envs; i++) { - Env* env = (Env*)calloc(1, sizeof(Env)); - if (!env) { - PyErr_SetString(PyExc_MemoryError, "Failed to allocate environment"); - Py_DECREF(kwargs); - return NULL; - } - vec->envs[i] = env; - - // // Make sure the log is initialized to 0 - memset(&env->log, 0, sizeof(Log)); - - env->observations = (void*)((char*)PyArray_DATA(observations) + i*PyArray_STRIDE(observations, 0)); - env->actions = (void*)((char*)PyArray_DATA(actions) + i*PyArray_STRIDE(actions, 0)); - env->rewards = (void*)((char*)PyArray_DATA(rewards) + i*PyArray_STRIDE(rewards, 0)); - env->terminals = (void*)((char*)PyArray_DATA(terminals) + i*PyArray_STRIDE(terminals, 0)); - // env->truncations = (void*)((char*)PyArray_DATA(truncations) + i*PyArray_STRIDE(truncations, 0)); - - // Assumes each process has the same number of environments - int env_seed = i + seed*vec->num_envs; - srand(env_seed); - - // Add the seed to kwargs for this environment - PyObject* py_seed = PyLong_FromLong(env_seed); - if (PyDict_SetItemString(kwargs, "seed", py_seed) < 0) { - PyErr_SetString(PyExc_RuntimeError, "Failed to set seed in kwargs"); - Py_DECREF(py_seed); - Py_DECREF(kwargs); - return NULL; - } - Py_DECREF(py_seed); - - PyObject* empty_args = PyTuple_New(0); - my_init(env, empty_args, kwargs); - if (PyErr_Occurred()) { - return NULL; - } - } - - Py_DECREF(kwargs); - return PyLong_FromVoidPtr(vec); -} - - -// Python function to close the environment -static PyObject* vectorize(PyObject* self, PyObject* args) { - int num_envs = PyTuple_Size(args); - if (num_envs == 0) { - PyErr_SetString(PyExc_TypeError, "make_vec requires at least 1 env id"); - return NULL; - } - - VecEnv* vec = (VecEnv*)calloc(1, sizeof(VecEnv)); - if (!vec) { - PyErr_SetString(PyExc_MemoryError, "Failed to allocate vec env"); - return NULL; - } - - vec->envs = (Env**)calloc(num_envs, sizeof(Env*)); - if (!vec->envs) { - PyErr_SetString(PyExc_MemoryError, "Failed to allocate vec env"); - return NULL; - } - - vec->num_envs = num_envs; - for (int i = 0; i < num_envs; i++) { - PyObject* handle_obj = PyTuple_GetItem(args, i); - if (!PyObject_TypeCheck(handle_obj, &PyLong_Type)) { - PyErr_SetString(PyExc_TypeError, "Env ids must be integers. Pass them as separate args with *env_ids, not as a list."); - return NULL; - } - vec->envs[i] = (Env*)PyLong_AsVoidPtr(handle_obj); - } - - return PyLong_FromVoidPtr(vec); -} - -static PyObject* vec_reset(PyObject* self, PyObject* args) { - if (PyTuple_Size(args) != 2) { - PyErr_SetString(PyExc_TypeError, "vec_reset requires 2 arguments"); - return NULL; - } - - VecEnv* vec = unpack_vecenv(args); - if (!vec) { - return NULL; - } - - PyObject* seed_arg = PyTuple_GetItem(args, 1); - if (!PyObject_TypeCheck(seed_arg, &PyLong_Type)) { - PyErr_SetString(PyExc_TypeError, "seed must be an integer"); - return NULL; - } - int seed = PyLong_AsLong(seed_arg); - - for (int i = 0; i < vec->num_envs; i++) { - // Assumes each process has the same number of environments - srand(i + seed*vec->num_envs); - c_reset(vec->envs[i]); - } - Py_RETURN_NONE; -} - -static PyObject* vec_step(PyObject* self, PyObject* arg) { - int num_args = PyTuple_Size(arg); - if (num_args != 1) { - PyErr_SetString(PyExc_TypeError, "vec_step requires 1 argument"); - return NULL; - } - - VecEnv* vec = unpack_vecenv(arg); - if (!vec) { - return NULL; - } - - for (int i = 0; i < vec->num_envs; i++) { - c_step(vec->envs[i]); - } - Py_RETURN_NONE; -} - -static PyObject* vec_render(PyObject* self, PyObject* args) { - int num_args = PyTuple_Size(args); - if (num_args != 2) { - PyErr_SetString(PyExc_TypeError, "vec_render requires 2 arguments"); - return NULL; - } - - VecEnv* vec = (VecEnv*)PyLong_AsVoidPtr(PyTuple_GetItem(args, 0)); - if (!vec) { - PyErr_SetString(PyExc_ValueError, "Invalid vec_env handle"); - return NULL; - } - - PyObject* env_id_arg = PyTuple_GetItem(args, 1); - if (!PyObject_TypeCheck(env_id_arg, &PyLong_Type)) { - PyErr_SetString(PyExc_TypeError, "env_id must be an integer"); - return NULL; - } - int env_id = PyLong_AsLong(env_id_arg); - - c_render(vec->envs[env_id]); - Py_RETURN_NONE; -} - -static int assign_to_dict(PyObject* dict, char* key, float value) { - PyObject* v = PyFloat_FromDouble(value); - if (v == NULL) { - PyErr_SetString(PyExc_TypeError, "Failed to convert log value"); - return 1; - } - if(PyDict_SetItemString(dict, key, v) < 0) { - PyErr_SetString(PyExc_TypeError, "Failed to set log value"); - return 1; - } - Py_DECREF(v); - return 0; -} - -static PyObject* vec_log(PyObject* self, PyObject* args) { - VecEnv* vec = unpack_vecenv(args); - if (!vec) { - return NULL; - } - - // Iterates over logs one float at a time. Will break - // horribly if Log has non-float data. - Log aggregate = {0}; - int num_keys = sizeof(Log) / sizeof(float); - for (int i = 0; i < vec->num_envs; i++) { - Env* env = vec->envs[i]; - for (int j = 0; j < num_keys; j++) { - ((float*)&aggregate)[j] += ((float*)&env->log)[j]; - ((float*)&env->log)[j] = 0.0f; - } - } - - PyObject* dict = PyDict_New(); - if (aggregate.n == 0.0f) { - return dict; - } - - // Average - float n = aggregate.n; - for (int i = 0; i < num_keys; i++) { - ((float*)&aggregate)[i] /= n; - } - - // User populates dict - my_log(dict, &aggregate); - assign_to_dict(dict, "n", n); - - return dict; -} - -static PyObject* vec_close(PyObject* self, PyObject* args) { - VecEnv* vec = unpack_vecenv(args); - if (!vec) { - return NULL; - } - - for (int i = 0; i < vec->num_envs; i++) { - c_close(vec->envs[i]); - free(vec->envs[i]); - } - free(vec->envs); - free(vec); - Py_RETURN_NONE; -} - -static double unpack(PyObject* kwargs, char* key) { - PyObject* val = PyDict_GetItemString(kwargs, key); - if (val == NULL) { - char error_msg[100]; - snprintf(error_msg, sizeof(error_msg), "Missing required keyword argument '%s'", key); - PyErr_SetString(PyExc_TypeError, error_msg); - return 1; - } - if (PyLong_Check(val)) { - long out = PyLong_AsLong(val); - if (out > INT_MAX || out < INT_MIN) { - char error_msg[100]; - snprintf(error_msg, sizeof(error_msg), "Value %ld of integer argument %s is out of range", out, key); - PyErr_SetString(PyExc_TypeError, error_msg); - return 1; - } - // Cast on return. Safe because double can represent all 32-bit ints exactly - return out; - } - if (PyFloat_Check(val)) { - return PyFloat_AsDouble(val); - } - char error_msg[100]; - snprintf(error_msg, sizeof(error_msg), "Failed to unpack keyword %s as int", key); - PyErr_SetString(PyExc_TypeError, error_msg); - return 1; -} - -// Method table -static PyMethodDef methods[] = { - {"env_init", (PyCFunction)env_init, METH_VARARGS | METH_KEYWORDS, "Init environment with observation, action, reward, terminal, truncation arrays"}, - {"env_reset", env_reset, METH_VARARGS, "Reset the environment"}, - {"env_step", env_step, METH_VARARGS, "Step the environment"}, - {"env_render", env_render, METH_VARARGS, "Render the environment"}, - {"env_close", env_close, METH_VARARGS, "Close the environment"}, - {"env_get", env_get, METH_VARARGS, "Get the environment state"}, - {"env_put", (PyCFunction)env_put, METH_VARARGS | METH_KEYWORDS, "Put stuff into env"}, - {"vectorize", vectorize, METH_VARARGS, "Make a vector of environment handles"}, - {"vec_init", (PyCFunction)vec_init, METH_VARARGS | METH_KEYWORDS, "Initialize a vector of environments"}, - {"vec_reset", vec_reset, METH_VARARGS, "Reset the vector of environments"}, - {"vec_step", vec_step, METH_VARARGS, "Step the vector of environments"}, - {"vec_log", vec_log, METH_VARARGS, "Log the vector of environments"}, - {"vec_render", vec_render, METH_VARARGS, "Render the vector of environments"}, - {"vec_close", vec_close, METH_VARARGS, "Close the vector of environments"}, - {"shared", (PyCFunction)my_shared, METH_VARARGS | METH_KEYWORDS, "Shared state"}, - MY_METHODS, - {NULL, NULL, 0, NULL} -}; - -// Module definition -static PyModuleDef module = { - PyModuleDef_HEAD_INIT, - "binding", - NULL, - -1, - methods -}; - -PyMODINIT_FUNC PyInit_binding(void) { - import_array(); - return PyModule_Create(&module); -} diff --git a/pufferlib/ocean/environment.py b/pufferlib/ocean/environment.py deleted file mode 100644 index 6c56a4ea20..0000000000 --- a/pufferlib/ocean/environment.py +++ /dev/null @@ -1,177 +0,0 @@ -import importlib -import pufferlib.emulation - -def lazy_import(module_path, attr): - """ - Returns a callable that, when called with any arguments, will - import the module, retrieve the attribute (usually a class or factory) - and then call it with the given arguments. - """ - return lambda *args, **kwargs: getattr(__import__(module_path, fromlist=[attr]), attr)(*args, **kwargs) - -def make_foraging(width=1080, height=720, num_agents=4096, horizon=512, - discretize=True, food_reward=0.1, render_mode='rgb_array'): - from .grid import grid - init_fn = grid.init_foraging - reward_fn = grid.reward_foraging - return grid.PufferGrid(width, height, num_agents, - horizon, discretize=discretize, food_reward=food_reward, init_fn=init_fn, reward_fn=reward_fn, render_mode=render_mode) - -def make_predator_prey(width=1080, height=720, num_agents=4096, horizon=512, - discretize=True, food_reward=0.1, render_mode='rgb_array'): - from .grid import grid - init_fn = grid.init_predator_prey - reward_fn = grid.reward_predator_prey - return grid.PufferGrid(width, height, num_agents, - horizon, discretize=discretize, food_reward=food_reward, - init_fn=init_fn, reward_fn=reward_fn, - render_mode=render_mode) - -def make_group(width=1080, height=720, num_agents=4096, horizon=512, - discretize=True, food_reward=0.1, render_mode='rgb_array'): - from .grid import grid - init_fn = grid.init_group - reward_fn = grid.reward_group - return grid.PufferGrid(width, height, num_agents, - horizon, discretize=discretize, food_reward=food_reward, - init_fn=init_fn, reward_fn=reward_fn, - render_mode=render_mode) - -def make_puffer(width=1080, height=720, num_agents=4096, horizon=512, - discretize=True, food_reward=0.1, render_mode='rgb_array'): - from .grid import grid - init_fn = grid.init_puffer - reward_fn = grid.reward_puffer - return grid.PufferGrid(width, height, num_agents, - horizon, discretize=discretize, food_reward=food_reward, - init_fn=init_fn, reward_fn=reward_fn, - render_mode=render_mode) - -def make_puffergrid(render_mode='raylib', vision_range=5, - num_envs=4096, num_maps=1000, max_map_size=9, - report_interval=128, buf=None): - return PufferGrid(render_mode, vision_range, num_envs, - num_maps, max_map_size, report_interval, buf) - -def make_continuous(discretize=False, buf=None, **kwargs): - from . import sanity - env = sanity.Continuous(discretize=discretize) - if not discretize: - env = pufferlib.ClipAction(env) - env = pufferlib.EpisodeStats(env) - return pufferlib.emulation.GymnasiumPufferEnv(env=env, buf=buf) - -def make_squared(distance_to_target=3, num_targets=1, buf=None, **kwargs): - from . import sanity - env = sanity.Squared(distance_to_target=distance_to_target, num_targets=num_targets, **kwargs) - env = pufferlib.EpisodeStats(env) - return pufferlib.emulation.GymnasiumPufferEnv(env=env, buf=buf, **kwargs) - -def make_bandit(num_actions=10, reward_scale=1, reward_noise=1, buf=None): - from . import sanity - env = sanity.Bandit(num_actions=num_actions, reward_scale=reward_scale, - reward_noise=reward_noise) - env = pufferlib.EpisodeStats(env) - return pufferlib.emulation.GymnasiumPufferEnv(env=env, buf=buf) - -def make_memory(mem_length=2, mem_delay=2, buf=None, **kwargs): - from . import sanity - env = sanity.Memory(mem_length=mem_length, mem_delay=mem_delay) - env = pufferlib.EpisodeStats(env) - return pufferlib.emulation.GymnasiumPufferEnv(env=env, buf=buf) - -def make_password(password_length=5, buf=None, **kwargs): - from . import sanity - env = sanity.Password(password_length=password_length) - env = pufferlib.EpisodeStats(env) - return pufferlib.emulation.GymnasiumPufferEnv(env=env, buf=buf) - -def make_performance(delay_mean=0, delay_std=0, bandwidth=1, buf=None, **kwargs): - from . import sanity - env = sanity.Performance(delay_mean=delay_mean, delay_std=delay_std, bandwidth=bandwidth) - env = pufferlib.EpisodeStats(env) - return pufferlib.emulation.GymnasiumPufferEnv(env=env, buf=buf) - -def make_performance_empiric(count_n=0, count_std=0, bandwidth=1, buf=None, **kwargs): - from . import sanity - env = sanity.PerformanceEmpiric(count_n=count_n, count_std=count_std, bandwidth=bandwidth) - env = pufferlib.EpisodeStats(env) - return pufferlib.emulation.GymnasiumPufferEnv(env=env, buf=buf) - -def make_stochastic(p=0.7, horizon=100, buf=None, **kwargs): - from . import sanity - env = sanity.Stochastic(p=p, horizon=100) - env = pufferlib.EpisodeStats(env) - return pufferlib.emulation.GymnasiumPufferEnv(env=env, buf=buf) - -def make_spaces(buf=None, **kwargs): - from . import sanity - env = sanity.Spaces() - env = pufferlib.EpisodeStats(env) - return pufferlib.emulation.GymnasiumPufferEnv(env=env, buf=buf, **kwargs) - -def make_multiagent(buf=None, **kwargs): - from . import sanity - env = sanity.Multiagent() - env = pufferlib.MultiagentEpisodeStats(env) - return pufferlib.emulation.PettingZooPufferEnv(env=env, buf=buf) - -MAKE_FUNCTIONS = { - 'battle': 'Battle', - 'breakout': 'Breakout', - 'blastar': 'Blastar', - 'convert': 'Convert', - 'convert_circle': 'ConvertCircle', - 'pong': 'Pong', - 'freeway': 'Freeway', - 'enduro': 'Enduro', - 'tetris': 'Tetris', - 'cartpole': 'Cartpole', - 'moba': 'Moba', - 'matsci': 'Matsci', - 'memory': 'Memory', - 'boids': 'Boids', - 'drone': 'Drone', - 'nmmo3': 'NMMO3', - 'snake': 'Snake', - 'squared': 'Squared', - 'pysquared': 'PySquared', - 'connect4': 'Connect4', - 'g2048': 'G2048', - 'terraform': 'Terraform', - 'template': 'Template', - 'tripletriad': 'TripleTriad', - 'tactical': 'Tactical', - 'target': 'Target', - 'go': 'Go', - 'rware': 'Rware', - 'trash_pickup': 'TrashPickupEnv', - 'tower_climb': 'TowerClimb', - 'grid': 'Grid', - 'shared_pool': 'PyCPR', - 'impulse_wars': 'ImpulseWars', - 'drive': 'Drive', - 'pacman': 'Pacman', - 'tmaze': 'TMaze', - 'checkers': 'Checkers', - 'asteroids': 'Asteroids', - 'whisker_racer': 'WhiskerRacer', - 'onestateworld': 'World', - 'onlyfish': 'OnlyFish', - 'chain_mdp': 'Chain', - 'spaces': make_spaces, - 'multiagent': make_multiagent, - 'slimevolley': 'SlimeVolley', -} - -def env_creator(name='squared', *args, **kwargs): - if 'puffer_' not in name: - raise pufferlib.APIUsageError(f'Invalid environment name: {name}') - - # TODO: Robust sanity / ocean imports - name = name.replace('puffer_', '') - try: - module = importlib.import_module(f'pufferlib.ocean.{name}.{name}') - return getattr(module, MAKE_FUNCTIONS[name]) - except ModuleNotFoundError: - return MAKE_FUNCTIONS[name] diff --git a/pufferlib/ocean/freeway/binding.c b/pufferlib/ocean/freeway/binding.c deleted file mode 100644 index 42eea05bb4..0000000000 --- a/pufferlib/ocean/freeway/binding.c +++ /dev/null @@ -1,31 +0,0 @@ -#include "freeway.h" - -#define Env Freeway -#include "../env_binding.h" - -static int my_init(Env* env, PyObject* args, PyObject* kwargs) { - env->frameskip = unpack(kwargs, "frameskip"); - env->width = unpack(kwargs, "width"); - env->height = unpack(kwargs, "height"); - env->player_width = unpack(kwargs, "player_width"); - env->player_height = unpack(kwargs, "player_height"); - env->car_width = unpack(kwargs, "car_width"); - env->car_height = unpack(kwargs, "car_height"); - env->lane_size = unpack(kwargs, "lane_size"); - env->level = unpack(kwargs, "level"); - env->difficulty = unpack(kwargs, "difficulty"); - env->use_dense_rewards = unpack(kwargs, "use_dense_rewards"); - env->env_randomization = unpack(kwargs, "env_randomization"); - env->enable_human_player = unpack(kwargs, "enable_human_player"); - init(env); - return 0; -} - -static int my_log(PyObject* dict, Log* log) { - assign_to_dict(dict, "perf", log->perf); - assign_to_dict(dict, "score", log->score); - assign_to_dict(dict, "episode_return", log->episode_return); - assign_to_dict(dict, "up_action_frac", log->up_action_frac); - assign_to_dict(dict, "hits", log->hits); - return 0; -} diff --git a/pufferlib/ocean/freeway/freeway.py b/pufferlib/ocean/freeway/freeway.py deleted file mode 100644 index 6e33cea87e..0000000000 --- a/pufferlib/ocean/freeway/freeway.py +++ /dev/null @@ -1,129 +0,0 @@ -import numpy as np -import gymnasium - -import pufferlib -from pufferlib.ocean.freeway import binding - - -class Freeway(pufferlib.PufferEnv): - def __init__( - self, - num_envs=1, - render_mode=None, - frameskip=4, - width=1216, - height=720, - player_width=64, - player_height=64, - car_width=64, - car_height=40, - lane_size=64, - difficulty=0, - level=0, - use_dense_rewards=True, - env_randomization=True, - enable_human_player=False, - log_interval=128, - buf=None, - seed=0, - ): - assert level < 8, "Level should be in {0, 1, 2, 3, 4, 5, 6, 7} or -1. Level -1 is a random mix of all 8 supported levels." - self.single_observation_space = gymnasium.spaces.Box( - low=0, high=1, shape=(34,), dtype=np.float32 - ) - self.render_mode = render_mode - self.num_agents = num_envs - self.log_interval = log_interval - self.tick = 0 - - self.single_action_space = gymnasium.spaces.Discrete(3) - - super().__init__(buf) - - self.c_envs = binding.vec_init( - self.observations, - self.actions, - self.rewards, - self.terminals, - self.truncations, - num_envs, - seed, - frameskip=frameskip, - width=width, - height=height, - player_width=player_width, - player_height=player_height, - car_width=car_width, - car_height=car_height, - lane_size=lane_size, - difficulty=difficulty, - level = level, - enable_human_player=enable_human_player, - env_randomization=env_randomization, - use_dense_rewards=use_dense_rewards, - ) - - def reset(self, seed=0): - binding.vec_reset(self.c_envs, seed) - self.tick = 0 - return self.observations, [] - - def step(self, actions): - self.actions[:] = actions - - self.tick += 1 - binding.vec_step(self.c_envs) - - info = [] - if self.tick % self.log_interval == 0: - info.append(binding.vec_log(self.c_envs)) - - return (self.observations, self.rewards, - self.terminals, self.truncations, info) - - def render(self): - binding.vec_render(self.c_envs, 0) - - def close(self): - binding.vec_close(self.c_envs) - -def test_performance(timeout=60, level = 0,atn_cache=1024): - env = Freeway(num_envs=1024, level=level) - env.reset() - tick = 0 - - actions = np.random.randint(0, 3, (atn_cache, env.num_agents)) - - import time - start = time.time() - while time.time() - start < timeout: - atn = actions[tick % atn_cache] - env.step(atn) - tick += 1 - env.close() - print(f'SPS: %f', env.num_agents * tick / (time.time() - start)) - -def test_render(timeout=60, level = 0,atn_cache=1024): - env = Freeway(num_envs=1, level=level) - env.reset(seed=0) - tick = 0 - - actions = np.random.randint(0, 3, (atn_cache, env.num_agents)) - - import time - start = time.time() - while time.time() - start < timeout: - atn = actions[tick % atn_cache] - obs, rew, term, trunc, i = env.step(atn) - env.render() - tick += 1 - if tick == 100: - env.reset() - env.close() - - -if __name__ == '__main__': - # test_performance() - for level in range(0,8): - test_performance(level = level, timeout=5, atn_cache=1024) - diff --git a/pufferlib/ocean/g2048/binding.c b/pufferlib/ocean/g2048/binding.c deleted file mode 100644 index 679703e220..0000000000 --- a/pufferlib/ocean/g2048/binding.c +++ /dev/null @@ -1,31 +0,0 @@ -#include "g2048.h" - -#define Env Game -#include "../env_binding.h" - -static int my_init(Env* env, PyObject* args, PyObject* kwargs) { - env->can_go_over_65536 = unpack(kwargs, "can_go_over_65536"); - env->reward_scaler = unpack(kwargs, "reward_scaler"); - env->endgame_env_prob = unpack(kwargs, "endgame_env_prob"); - env->scaffolding_ratio = unpack(kwargs, "scaffolding_ratio"); - env->use_heuristic_rewards = unpack(kwargs, "use_heuristic_rewards"); - env->snake_reward_weight = unpack(kwargs, "snake_reward_weight"); - env->use_sparse_reward = unpack(kwargs, "use_sparse_reward"); - init(env); - return 0; -} - -static int my_log(PyObject* dict, Log* log) { - assign_to_dict(dict, "perf", log->perf); - assign_to_dict(dict, "score", log->score); - assign_to_dict(dict, "merge_score", log->merge_score); - assign_to_dict(dict, "episode_return", log->episode_return); - assign_to_dict(dict, "episode_length", log->episode_length); - assign_to_dict(dict, "lifetime_max_tile", log->lifetime_max_tile); - assign_to_dict(dict, "reached_32768", log->reached_32768); - assign_to_dict(dict, "reached_65536", log->reached_65536); - assign_to_dict(dict, "monotonicity_reward", log->monotonicity_reward); - assign_to_dict(dict, "snake_state", log->snake_state); - assign_to_dict(dict, "snake_reward", log->snake_reward); - return 0; -} \ No newline at end of file diff --git a/pufferlib/ocean/g2048/eval.py b/pufferlib/ocean/g2048/eval.py deleted file mode 100644 index 138c272c75..0000000000 --- a/pufferlib/ocean/g2048/eval.py +++ /dev/null @@ -1,105 +0,0 @@ -from pufferlib import pufferl - -def evaluate(env_name, load_model_path): - args = pufferl.load_config(env_name) - args['vec']['num_envs'] = 1 - args['env']['num_envs'] = 4096 - args['load_model_path'] = load_model_path - # Turn off endgame_envs and scaffolding episodes, which do not report results - args['env']['endgame_env_prob'] = 0 - args['env']['scaffolding_ratio'] = 0 - args['env']['can_go_over_65536'] = True - - vecenv = pufferl.load_env(env_name, args) - policy = pufferl.load_policy(args, vecenv, env_name) - trainer = pufferl.PuffeRL(args['train'], vecenv, policy) - - # Each evaluate runs for 64 ticks. NOTE: bppt horizon might be short for g2048? - # Avg episode length from the current model is ~18000, so it takes ~300 epochs for an avg episode. - # It's hard to get the single best score because stats are already averaged across done envs. - for i in range(10000): - stats = trainer.evaluate() - - trainer.epoch += 1 - if i % 20 == 0: - trainer.print_dashboard() - - trainer.close() - - # Get the estimates - num_episodes = sum(stats['n']) - episode_lengths = sum(n * l for n, l in zip(stats['n'], stats['episode_length'])) / num_episodes - max_tiles = sum(n * m for n, m in zip(stats['n'], stats['score'])) / num_episodes - merge_scores = sum(n * s for n, s in zip(stats['n'], stats['merge_score'])) / num_episodes - reached_32768 = sum(n * s for n, s in zip(stats['n'], stats['reached_32768'])) / num_episodes - reached_65536 = sum(n * s for n, s in zip(stats['n'], stats['reached_65536'])) / num_episodes - - print(f"Num episodes: {int(num_episodes)}") - print(f"Max tile avg: {max_tiles:.1f}") - # The stats from vecenv are averaged across envs that were done in the same tick. Cannot get the single max. - print(f"Episode length -- Avg: {episode_lengths:.1f}, Max: {max(stats['episode_length']):.1f}") - print(f"Merge score -- Avg: {merge_scores:.1f}, Max: {max(stats['merge_score']):.1f}") - print(f"Reached 32768 prob: {reached_32768*100:.2f} %") - print(f"Reached 65536 prob: {reached_65536*100:.2f} %") - - """ - # hidden 256: https://wandb.ai/kywch/pufferlib/runs/nvd0pfuj?nw=nwuserkywch - Num episodes: 154406 - Max tile avg: 22532.9 - Episode length -- Avg: 16667.2, Max: 26659.1 - Merge score -- Avg: 462797.9, Max: 744224.9 - Reached 32768 prob: 46.08 % - Reached 65536 prob: 3.53 % - - # hidden 512: https://wandb.ai/kywch/pufferlib/runs/2ch3my60?nw=nwuserkywch - Num episodes: 119243 - Max tile avg: 30662.2 - Episode length -- Avg: 21539.7, Max: 29680.3 - Merge score -- Avg: 618011.8, Max: 918755.8 - Reached 32768 prob: 68.25 % - Reached 65536 prob: 13.09 % - - # hidden 512 (replication): https://wandb.ai/kywch/pufferlib/runs/5thsjr61?nw=nwuserkywch - Num episodes: 115652 - Max tile avg: 31773.2 - Episode length -- Avg: 22196.4, Max: 30316.5 - Merge score -- Avg: 639395.6, Max: 909969.8 - Reached 32768 prob: 71.22 % - Reached 65536 prob: 14.75 % - """ - -def finetune(env_name, load_model_path): - args = pufferl.load_config(env_name) - args['load_model_path'] = load_model_path - # args['env']['use_sparse_reward'] = True - args['env']['scaffolding_ratio'] = 0.85 - - # args['policy']['hidden_size'] = 512 - # args['rnn']['input_size'] = 512 - # args['rnn']['hidden_size'] = 512 - - args['train']['total_timesteps'] = 1_000_000_000 - args['train']['learning_rate'] = 0.00005 - args['train']['anneal_lr'] = False - - args['wandb'] = True - args['tag'] = 'pg2048' - - pufferl.train(env_name, args) - -if __name__ == '__main__': - import os - import wandb - - # https://wandb.ai/kywch/pufferlib/runs/5thsjr61?nw=nwuserkywch - wandb_run_id = '5thsjr61' - wandb.init(id=wandb_run_id, project='pufferlib', entity='kywch') - - artifact = wandb.use_artifact(f'{wandb_run_id}:latest') - data_dir = artifact.download() - model_file = max(os.listdir(data_dir)) - model_path = f'{data_dir}/{model_file}' - wandb.finish() - - evaluate('puffer_g2048', load_model_path=model_path) - # finetune('puffer_g2048', load_model_path='puffer_g2048_256_base.pt') diff --git a/pufferlib/ocean/g2048/g2048.c b/pufferlib/ocean/g2048/g2048.c deleted file mode 100644 index 1cd1cf89e0..0000000000 --- a/pufferlib/ocean/g2048/g2048.c +++ /dev/null @@ -1,98 +0,0 @@ -#include "g2048.h" -#include "g2048_net.h" - -#define OBS_DIM 289 -#define HIDDEN_DIM 512 - -// Set NO_RENDER to true to run evals without the render -#define NO_RENDER false -#define NUM_EVAL_RUNS 200 - -int main() { - srand(time(NULL)); - Game env = { - .can_go_over_65536 = true, - .reward_scaler = 0.0, - .endgame_env_prob = 0.0, - .scaffolding_ratio = 0.0, - .use_heuristic_rewards = false, - .snake_reward_weight = 0.0, - }; - init(&env); - - unsigned char observations[OBS_DIM] = {0}; - unsigned char terminals[1] = {0}; - int actions[1] = {0}; - float rewards[1] = {0}; - - env.observations = observations; - env.terminals = terminals; - env.actions = actions; - env.rewards = rewards; - - Weights* weights = load_weights("resources/g2048/g2048_weights.bin", 3713541); - G2048Net* net = make_g2048net(weights, OBS_DIM, HIDDEN_DIM); - c_reset(&env); - if (!NO_RENDER) c_render(&env); - printf("Starting...\n"); - - clock_t start_time = clock(); - - // Main game loop - int trial = 1; - int frame = 0; - int action = -1; - while (NO_RENDER || !WindowShouldClose()) { - if (!NO_RENDER) c_render(&env); // Render at the start of the loop - frame++; - - if (IsKeyDown(KEY_LEFT_SHIFT)) { - action = -1; - if (IsKeyDown(KEY_W) || IsKeyDown(KEY_UP)) action = UP; - else if (IsKeyDown(KEY_S) || IsKeyDown(KEY_DOWN)) action = DOWN; - else if (IsKeyDown(KEY_A) || IsKeyDown(KEY_LEFT)) action = LEFT; - else if (IsKeyDown(KEY_D) || IsKeyDown(KEY_RIGHT)) action = RIGHT; - env.actions[0] = action - 1; - } else if (frame % 1 != 0) { - continue; - } else { - action = 1; - forward_g2048net(net, env.observations, env.actions); - } - - if (action > 0) { - step_without_reset(&env); - } - - if (env.terminals[0] == 1) { - clock_t end_time = clock(); - double time_taken = (double)(end_time - start_time) / CLOCKS_PER_SEC; - printf("Trial: %d, Ticks: %d, Max Tile: %d, Merge Score: %d, Time: %.2fs\n", - trial++, env.tick, 1 << env.max_tile, env.score, time_taken); - - if (!NO_RENDER) { - // Reached the 65536 tile, so full stop. Savor the moment! - if (env.max_tile >= 16) WaitTime(100000); - WaitTime(10); - } - - c_reset(&env); - if (!NO_RENDER) c_render(&env); - start_time = clock(); - frame = 0; - } - - if (!NO_RENDER && IsKeyDown(KEY_LEFT_SHIFT) && action > 0) { - // Don't need to be super reactive - WaitTime(0.1); - } - - if (NO_RENDER && trial > NUM_EVAL_RUNS) break; - } - - free_g2048net(net); - free(weights); - c_close(&env); - printf("Finished %d trials.\n", NUM_EVAL_RUNS); - return 0; -} diff --git a/pufferlib/ocean/g2048/g2048.h b/pufferlib/ocean/g2048/g2048.h deleted file mode 100644 index 801fc74062..0000000000 --- a/pufferlib/ocean/g2048/g2048.h +++ /dev/null @@ -1,696 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include "raylib.h" - -static inline int min(int a, int b) { return a < b ? a : b; } -static inline int max(int a, int b) { return a > b ? a : b; } - -#define SIZE 4 -#define EMPTY 0 -#define UP 1 -#define DOWN 2 -#define LEFT 3 -#define RIGHT 4 -#define BASE_MAX_TICKS 1000 - -// These work well -#define MERGE_REWARD_WEIGHT 0.0625f -#define INVALID_MOVE_PENALTY -0.05f -#define GAME_OVER_PENALTY -1.0f - -// These may need experimenting, but work for now -#define STATE_REWARD_WEIGHT 0.01f // Fixed, small reward for maintaining "desirable" states -#define MONOTONICITY_REWARD_WEIGHT 0.00003f - -// Features: 18 per cell -// 1. Normalized tile value (current_val / max_val) -// 2. One-hot for empty (1 if empty, 0 if occupied) -// 3-18. One-hot for tile values 2^1 to 2^16 (16 features) -#define NUM_FEATURES 18 - -static inline float calculate_perf(unsigned char max_tile) { - // Reaching 65k -> 1.0, 32k -> 0.8, 16k -> 0.4, 8k -> 0.2, 4k -> 0.1, 2k -> 0.05 - float perf = 0.8f * (float)(1 << max_tile) / 32768.0f; - if (perf > 1.0f) perf = 1.0f; - return perf; -} - -typedef struct { - float perf; - float score; - float merge_score; - float episode_return; - float episode_length; - float lifetime_max_tile; - float reached_32768; - float reached_65536; - float snake_state; - float monotonicity_reward; - float snake_reward; - float n; -} Log; - -typedef struct { - Log log; // Required - unsigned char* observations; // Cheaper in memory if encoded in uint_8 - int* actions; // Required - float* rewards; // Required - unsigned char* terminals; // Required - - bool can_go_over_65536; // Set false for training, true for eval - float reward_scaler; // Pufferlib clips rew from -1 to 1, adjust the resulting rew accordingly - - float endgame_env_prob; // The prob of env being initialized as an endgame-only env - bool is_endgame_env; - float scaffolding_ratio; // The ratio for "scaffolding" runs, in which higher blocks are spawned - bool is_scaffolding_episode; - bool use_heuristic_rewards; - float snake_reward_weight; - bool use_sparse_reward; // Ignore all rewards and provide 1 for reaching 16k, 32k, 65k - - int score; - int tick; - unsigned char grid[SIZE][SIZE]; - unsigned char lifetime_max_tile; - unsigned char max_tile; // Episode max tile - float episode_reward; // Accumulate episode reward - float monotonicity_reward; - float snake_reward; - int moves_made; - int max_episode_ticks; // Dynamic max_ticks based on score - bool is_snake_state; - int snake_state_tick; - bool stop_at_65536; - - // Cached values to avoid recomputation - int empty_count; - bool game_over_cached; - bool grid_changed; -} Game; - -// Precomputed color table for rendering optimization -const Color PUFF_BACKGROUND = (Color){6, 24, 24, 255}; -const Color PUFF_WHITE = (Color){241, 241, 241, 241}; -const Color PUFF_RED = (Color){187, 0, 0, 255}; -const Color PUFF_CYAN = (Color){0, 187, 187, 255}; - -static Color tile_colors[17] = { - {6, 24, 24, 255}, // Empty/background - {187, 187, 187, 255}, // 2 - {170, 187, 187, 255}, // 4 - {150, 187, 187, 255}, // 8 - {130, 187, 187, 255}, // 16 - {110, 187, 187, 255}, // 32 - {90, 187, 187, 255}, // 64 (Getting more cyan) - {70, 187, 187, 255}, // 128 - {50, 187, 187, 255}, // 256 - {30, 187, 187, 255}, // 512 - {0, 187, 187, 255}, // 1024 (PUFF_CYAN) - {0, 150, 187, 255}, // 2048 - {0, 110, 187, 255}, // 4096 - {0, 70, 187, 255}, // 8192 - {187, 0, 0, 255}, // 16384 (PUFF_RED) - {204, 173, 17, 255}, // 32768 (Gold) - {6, 24, 24, 255}, // 65536+ (Invisible) -}; - -// Precomputed pow(x, 1.5) lookup table for x in [0, 19] to avoid expensive pow() calls. -static const unsigned char pow_1_5_lookup[20] = { - 0, 1, 2, 5, 8, 11, 14, 18, 22, 27, 31, 36, 41, 46, 52, 57, 64, 69, 75, 81 -}; - -// --- Logging --- -void add_log(Game* game); - -// --- Required functions for env_binding.h --- -void c_reset(Game* game); -void c_step(Game* game); -void c_render(Game* game); -void c_close(Game* game); - -void init(Game* game) { - game->lifetime_max_tile = 0; - game->is_endgame_env = (rand() / (float)RAND_MAX) < game->endgame_env_prob; -} - -void update_observations(Game* game) { - // Observation: 4x4 grid, 18 features per cell - // 1. Normalized tile value (current_val / max_val) - // 2. One-hot for empty (1 if empty, 0 if occupied) - // 3. One-hot for tile values 2^1 to 2^16 (16 features) - // 4. Additional obs: is_snake_state (1) - - int num_cell = SIZE * SIZE; - int num_additional_obs = 1; - memset(game->observations, 0, (num_cell * NUM_FEATURES + num_additional_obs) * sizeof(unsigned char)); - for (int i = 0; i < SIZE; i++) { - for (int j = 0; j < SIZE; j++) { - int feat1_idx = (i * SIZE + j); - int feat2_idx = num_cell + feat1_idx; - int feat3_idx = 2 * num_cell + 16 * feat1_idx; - unsigned char grid_val = game->grid[i][j]; - - // Feature 1: The original tile values ** 1.5, to make a bit superlinear within uint8 - game->observations[feat1_idx] = pow_1_5_lookup[grid_val]; - - // Feature 2: One-hot for empty - game->observations[feat2_idx] = (grid_val == EMPTY) ? 1 : 0; - - // Features 3-18: One-hot for tile values - // NOTE: If this ever gets close to 131072, revisit this - if (grid_val > 0) { - grid_val = min(grid_val, 16); - game->observations[feat3_idx + grid_val - 1] = 1; - } - } - } - // Additional obs - int offset = num_cell * NUM_FEATURES; - game->observations[offset] = game->is_snake_state; -} - -void add_log(Game* game) { - // Scaffolding runs will distort stats, so skip logging - if (game->is_endgame_env || game->is_scaffolding_episode) return; - - // Update the lifetime best - if (game->max_tile > game->lifetime_max_tile) { - game->lifetime_max_tile = game->max_tile; - } - - game->log.score += (float)(1 << game->max_tile); - game->log.perf += calculate_perf(game->max_tile); - game->log.merge_score += (float)game->score; - game->log.episode_length += game->tick; - game->log.episode_return += game->episode_reward; - game->log.lifetime_max_tile += (float)(1 << game->lifetime_max_tile); - game->log.reached_32768 += (game->max_tile >= 15); - game->log.reached_65536 += (game->max_tile >= 16); - game->log.snake_state += (float)game->snake_state_tick / (float)game->tick; - game->log.monotonicity_reward += game->monotonicity_reward * MONOTONICITY_REWARD_WEIGHT * game->reward_scaler; - game->log.snake_reward += game->snake_reward * game->snake_reward_weight * game->reward_scaler; - game->log.n += 1; -} - -static inline unsigned char get_new_tile(void) { - // 10% chance of 2, 90% chance of 1 - return (rand() % 10 == 0) ? 2 : 1; -} - -static inline void place_tile_at_random_cell(Game* game, unsigned char tile) { - if (game->empty_count == 0) return; - - int target = rand() % game->empty_count; - int pos = 0; - for (int i = 0; i < SIZE; i++) { - for (int j = 0; j < SIZE; j++) { - if (game->grid[i][j] == EMPTY) { - if (pos == target) { - game->grid[i][j] = tile; - game->empty_count--; - return; - } - pos++; - } - } - } -} - -void set_scaffolding_curriculum(Game* game) { - game->stop_at_65536 = true; - - if (game->lifetime_max_tile < 14) { - int curriculum = rand() % 5; - - // Spawn one high tiles from 8192, 16384, 32768, 65536 - unsigned char high_tile = max(12 + curriculum, game->lifetime_max_tile); - place_tile_at_random_cell(game, high_tile); - if (high_tile >= 16) game->stop_at_65536 = false; - - } else { - int curriculum = rand() % 8; - - if (curriculum < 2) { // curriculum 0, 1 - place_tile_at_random_cell(game, 14 + curriculum); // Spawn one of 16384 or 32768 - - } else if (curriculum == 2) { - // Place the tiles in the second row, so that they can be moved up in the first move - unsigned char tiles[] = {14, 13}; - memcpy(game->grid[1], tiles, 2); - game->empty_count -= 2; - } else if (curriculum == 3) { // harder - game->grid[1][0] = 14; game->empty_count--; - place_tile_at_random_cell(game, 13); - - } else if (curriculum == 4) { - unsigned char tiles[] = {15, 14}; - memcpy(game->grid[1], tiles, 2); - game->empty_count -= 2; - } else if (curriculum == 5) { // harder - game->grid[1][0] = 15; game->empty_count--; - place_tile_at_random_cell(game, 14); - - } else if (curriculum == 6) { - unsigned char tiles[] = {15, 14, 13}; - memcpy(game->grid[1], tiles, 3); - game->empty_count -= 3; - } else if (curriculum == 7) { // harder - game->grid[1][0] = 15; game->empty_count--; - place_tile_at_random_cell(game, 14); - place_tile_at_random_cell(game, 13); - } - } -} - -void set_endgame_curriculum(Game* game) { - game->stop_at_65536 = true; - int curriculum = rand() % 4; - - // Place the tiles in the second-third rows, so that they can be moved up in the first move - unsigned char tiles[] = {15, 14, 13, 12}; - memcpy(game->grid[1], tiles, 4); - game->empty_count -= 4; - - if (curriculum >= 1) { game->grid[2][3] = 11; game->empty_count--; } - if (curriculum >= 2) { - game->grid[2][2] = 10; - game->grid[2][1] = 9; - game->grid[2][0] = 8; - game->empty_count -= 3; - } -} - -void c_reset(Game* game) { - memset(game->grid, EMPTY, SIZE * SIZE); - game->score = 0; - game->tick = 0; - game->episode_reward = 0; - game->empty_count = SIZE * SIZE; - game->game_over_cached = false; - game->grid_changed = true; - game->moves_made = 0; - game->max_episode_ticks = BASE_MAX_TICKS; - game->max_tile = 0; - game->snake_state_tick = 0; - game->monotonicity_reward = 0; - game->snake_reward = 0; - game->is_snake_state = false; - game->stop_at_65536 = game->can_go_over_65536; - - if (game->terminals) game->terminals[0] = 0; - - // End game envs only do endgame curriculum - if (game->is_endgame_env) { - set_endgame_curriculum(game); - - } else { - // Higher tiles are spawned in scaffolding episodes - // Having high tiles saves moves to get there, allowing agents to experience it faster - game->is_scaffolding_episode = (rand() / (float)RAND_MAX) < game->scaffolding_ratio; - if (game->is_scaffolding_episode) { - set_scaffolding_curriculum(game); - - } else { - // Add two random tiles at the start - for (int i = 0; i < 2; i++) { - place_tile_at_random_cell(game, get_new_tile()); - } - } - } - - update_observations(game); -} - -// Optimized slide and merge with fewer memory operations -static inline bool slide_and_merge(Game* game, unsigned char* row, float* reward, float* score_increase) { - bool moved = false; - int write_pos = 0; - - // Single pass: slide and identify merge candidates - for (int read_pos = 0; read_pos < SIZE; read_pos++) { - if (row[read_pos] != EMPTY) { - if (write_pos != read_pos) { - row[write_pos] = row[read_pos]; - row[read_pos] = EMPTY; - moved = true; - } - write_pos++; - } - } - - // Merge pass - for (int i = 0; i < SIZE - 1; i++) { - if (row[i] != EMPTY && row[i] == row[i + 1]) { - row[i]++; - *reward += ((float)row[i]) * MERGE_REWARD_WEIGHT; - *score_increase += (float)(1 << (int)row[i]); - // Shift remaining elements left - for (int j = i + 1; j < SIZE - 1; j++) { - row[j] = row[j + 1]; - } - row[SIZE - 1] = EMPTY; - moved = true; - } - } - - return moved; -} - -bool move(Game* game, int direction, float* reward, float* score_increase) { - bool moved = false; - unsigned char temp[SIZE]; - - if (direction == UP || direction == DOWN) { - for (int col = 0; col < SIZE; col++) { - // Extract column - for (int i = 0; i < SIZE; i++) { - int idx = (direction == UP) ? i : SIZE - 1 - i; - temp[i] = game->grid[idx][col]; - } - - if (slide_and_merge(game, temp, reward, score_increase)) { - moved = true; - // Write back column - for (int i = 0; i < SIZE; i++) { - int idx = (direction == UP) ? i : SIZE - 1 - i; - game->grid[idx][col] = temp[i]; - } - } - } - } else { - for (int row = 0; row < SIZE; row++) { - // Extract row - for (int i = 0; i < SIZE; i++) { - int idx = (direction == LEFT) ? i : SIZE - 1 - i; - temp[i] = game->grid[row][idx]; - } - - if (slide_and_merge(game, temp, reward, score_increase)) { - moved = true; - // Write back row - for (int i = 0; i < SIZE; i++) { - int idx = (direction == LEFT) ? i : SIZE - 1 - i; - game->grid[row][idx] = temp[i]; - } - } - } - } - - if (moved) { - game->grid_changed = true; - game->game_over_cached = false; // Invalidate cache - } - - return moved; -} - -bool is_game_over(Game* game) { - // Use cached result if grid hasn't changed - if (!game->grid_changed && game->game_over_cached) { - return game->game_over_cached; - } - - // Quick check: if there are empty cells, game is not over - if (game->empty_count > 0) { - game->game_over_cached = false; - game->grid_changed = false; - return false; - } - - // Check for possible merges - for (int i = 0; i < SIZE; i++) { - for (int j = 0; j < SIZE; j++) { - unsigned char current = game->grid[i][j]; - if (i < SIZE - 1 && current == game->grid[i + 1][j]) { - game->game_over_cached = false; - game->grid_changed = false; - return false; - } - if (j < SIZE - 1 && current == game->grid[i][j + 1]) { - game->game_over_cached = false; - game->grid_changed = false; - return false; - } - } - } - - game->game_over_cached = true; - game->grid_changed = false; - return true; -} - -// Combined grid stats and heuristic calculation for performance -float update_stats_and_get_heuristic_rewards(Game* game) { - int empty_count = 0; - int top_row_count = 0; - unsigned char max_tile = 0; - unsigned char second_max_tile = 0; - unsigned char max_tile_in_row234 = 0; - float heuristic_state_reward = 0.0f; - float monotonicity_reward = 0.0f; - float snake_reward = 0.0f; - game->is_snake_state = false; - - for (int i = 0; i < SIZE; i++) { - for (int j = 0; j < SIZE; j++) { - unsigned char val = game->grid[i][j]; - - // Update empty count and max tile - if (val == EMPTY) empty_count++; - - // Count filled cells in the top row - if (i == 0 && val != EMPTY) top_row_count++; - - // Allow max and the second max tile to be the same - if (val >= max_tile) { - second_max_tile = max_tile; - max_tile = val; - } else if (val > second_max_tile && val < max_tile) { - second_max_tile = val; - } - - // Get the max tile in the 2nd, 3rd, 4th row - if (i > 0 && val > max_tile_in_row234) max_tile_in_row234 = val; - } - } - - game->empty_count = empty_count; - game->max_tile = max_tile; - - /* Heuristic rewards */ - - // Filled top row reward: A simple nudge to keep the top row filled - if (top_row_count == SIZE) heuristic_state_reward += STATE_REWARD_WEIGHT; - - bool max_in_top_left = (game->grid[0][0] == max_tile); - - // Corner reward: A simple nudge to keep the max tiles horizontally in the top row, left corner. - // When agents learn to put the max tile on the other corners, or put max tiles vertically - // they miss out snake rew, and this does happen sometimes. - if (max_in_top_left && game->grid[0][1] == second_max_tile && max_tile > 4) { - heuristic_state_reward += STATE_REWARD_WEIGHT; - } - - // Snake reward: look for the snake pattern, only when the max tile is at top left - if (max_in_top_left) { - monotonicity_reward += pow_1_5_lookup[max_tile]; - int evidence_for_snake = 0; - - for (int i = 0; i < 2; i++) { - unsigned char row_min = 32; - unsigned char next_row_max = 0; - for (int j = 0; j < SIZE; j++) { - unsigned char val = game->grid[i][j]; - - // Check horizontal monotonicity (snake pattern) for top two rows only - if (j < SIZE - 1) { - unsigned char next_col = game->grid[i][j+1]; - if (val != EMPTY && next_col != EMPTY) { - // Row 0: Reward decreasing left to right, e.g., 12-11-10-9 - if (i == 0 && val > next_col) { - monotonicity_reward += pow_1_5_lookup[next_col]; - evidence_for_snake++; - } - // Row 1: Reward increasing left to right, e.g., 5-6-7-8 - else if (i == 1 && val < next_col) { - monotonicity_reward += pow_1_5_lookup[val]; - } - } - } - - // Vertical monotonicity: give score after row scanning for min/max is done - if (val != EMPTY && val < row_min) row_min = val; - unsigned char next_row = game->grid[i+1][j]; - if (next_row != EMPTY && next_row > next_row_max) next_row_max = next_row; - // // Small column-level vertical reward - if (val != EMPTY && next_row != EMPTY && val > next_row) monotonicity_reward += next_row; - } - // Large row-level vertical reward - if (i < 2 && row_min < 20 && next_row_max > 0 && row_min > next_row_max) { - monotonicity_reward += 4 * pow_1_5_lookup[row_min]; - if (i == 0) evidence_for_snake++; - } - } - - // Snake bonus: sorted top row + the max_tile_in_row234 in the second row right - // For example, top row: 14-13-12-11, second row: ()-()-()-10 - unsigned char snake_tail = game->grid[1][3]; - if (evidence_for_snake >= 4 && snake_tail == max_tile_in_row234) { - game->is_snake_state = true; - game->snake_state_tick++; - snake_reward = snake_tail * snake_tail; - } - } - - // Trained models need game->is_snake_state as obs - if (!game->use_heuristic_rewards) return 0.0f; - - game->monotonicity_reward += monotonicity_reward; - game->snake_reward += snake_reward; - - return heuristic_state_reward + monotonicity_reward * MONOTONICITY_REWARD_WEIGHT + snake_reward * game->snake_reward_weight; -} - -void c_step(Game* game) { - float reward = 0.0f; - float score_add = 0.0f; - unsigned char prev_max_tile = game->max_tile; - bool did_move = move(game, game->actions[0] + 1, &reward, &score_add); - game->tick++; - - if (did_move) { - game->moves_made++; - place_tile_at_random_cell(game, get_new_tile()); - game->score += score_add; - - // Add heuristic rewards/penalties and update grid stats - reward += update_stats_and_get_heuristic_rewards(game); - reward *= game->reward_scaler; - - update_observations(game); // Observations only change if the grid changes - - // This is to limit infinite invalid moves during eval (happens for noob agents) - // Don't need to be tight. Don't need to show to human player. - int tick_multiplier = max(1, game->lifetime_max_tile - 8); // practically no limit for competent agent - game->max_episode_ticks = max(BASE_MAX_TICKS * tick_multiplier, game->score / 4); - - } else { - reward = INVALID_MOVE_PENALTY; - // No need to update observations if the grid hasn't changed - } - - bool game_over = is_game_over(game); - bool max_ticks_reached = game->tick >= game->max_episode_ticks; - bool max_level_reached = game->stop_at_65536 && game->max_tile >= 16; - game->terminals[0] = (game_over || max_ticks_reached || max_level_reached) ? 1 : 0; - - // Game over penalty overrides other rewards - if (game_over) { - reward = GAME_OVER_PENALTY; - } - - if (game->use_sparse_reward) { - reward = 0; // Ignore all previous reward - if (game->max_tile >= 14 && game->max_tile > prev_max_tile) reward = 1; - } - - game->rewards[0] = reward; - game->episode_reward += reward; - - if (game->terminals[0]) { - add_log(game); - c_reset(game); - } -} - -// Stepping for client/eval: no reward, no reset -void step_without_reset(Game* game) { - float score_add = 0.0f; - float reward = 0.0f; - bool did_move = move(game, game->actions[0] + 1, &reward, &score_add); - game->tick++; - - if (did_move) { - game->moves_made++; - place_tile_at_random_cell(game, get_new_tile()); - game->score += score_add; - update_stats_and_get_heuristic_rewards(game); // The reward is ignored. - update_observations(game); // Observations only change if the grid changes - } - - bool game_over = is_game_over(game); - game->terminals[0] = (game_over) ? 1 : 0; -} - -// Rendering optimizations -void c_render(Game* game) { - static bool window_initialized = false; - static char score_text[32]; - static const int px = 100; - - if (!window_initialized) { - InitWindow(px * SIZE, px * SIZE + 50, "2048"); - SetTargetFPS(30); // Increased for smoother rendering - window_initialized = true; - } - - if (IsKeyDown(KEY_ESCAPE)) { - CloseWindow(); - exit(0); - } - - BeginDrawing(); - ClearBackground(PUFF_BACKGROUND); - - // Draw grid - for (int i = 0; i < SIZE; i++) { - for (int j = 0; j < SIZE; j++) { - int val = game->grid[i][j]; - - // Use precomputed colors - int color_idx = min(val, 16); // Cap at the max index of our color array - Color color = tile_colors[color_idx]; - - DrawRectangle(j * px, i * px, px - 5, px - 5, color); - - if (val > 0) { - int display_val = 1 << val; // Power of 2 - // Pre-format text to avoid repeated formatting - snprintf(score_text, sizeof(score_text), "%d", display_val); - - int font_size = 32; - int x_offset = 20; // Default for 4-digit numbers - if (display_val < 10) x_offset = 40; // 1-digit - else if (display_val < 100) x_offset = 35; // 2-digit - else if (display_val < 1000) x_offset = 25; // 3-digit - else if (display_val < 10000) x_offset = 15; // 4-digit - else if (display_val < 100000) x_offset = 2; // 5-digit - else { - font_size = 24; - x_offset = 5; - } - - DrawText(score_text, j * px + x_offset, i * px + 34, font_size, PUFF_WHITE); - } - } - } - - // Draw score (format once per frame) - snprintf(score_text, sizeof(score_text), "Score: %d", game->score); - DrawText(score_text, 10, px * SIZE + 10, 24, PUFF_WHITE); - - snprintf(score_text, sizeof(score_text), "Moves: %d", game->moves_made); - DrawText(score_text, 210, px * SIZE + 10, 24, PUFF_WHITE); - - EndDrawing(); -} - -void c_close(Game* game) { - if (IsWindowReady()) { - CloseWindow(); - } -} diff --git a/pufferlib/ocean/g2048/g2048.py b/pufferlib/ocean/g2048/g2048.py deleted file mode 100644 index e65b225eeb..0000000000 --- a/pufferlib/ocean/g2048/g2048.py +++ /dev/null @@ -1,89 +0,0 @@ -'''2048 Gymnasium-compatible environment using the C backend.''' - -import gymnasium -import numpy as np - -import pufferlib -from pufferlib.ocean.g2048 import binding - -class G2048(pufferlib.PufferEnv): - def __init__(self, num_envs=1, reward_scaler=1.0, - can_go_over_65536=False, endgame_env_prob=0.0, scaffolding_ratio=0.0, - use_heuristic_rewards=False, snake_reward_weight=0.0, use_sparse_reward=False, - render_mode=None, log_interval=128, buf=None, seed=0): - self.single_observation_space = gymnasium.spaces.Box( - low=0, high=100, shape=(16*18 + 1,), dtype=np.uint8 - ) - self.single_action_space = gymnasium.spaces.Discrete(4) - self.render_mode = render_mode - self.num_agents = num_envs - self.log_interval = log_interval - - self.can_go_over_65536 = can_go_over_65536 - self.reward_scaler = reward_scaler - self.endgame_env_prob = endgame_env_prob - self.scaffolding_ratio = scaffolding_ratio - self.use_heuristic_rewards = use_heuristic_rewards - self.snake_reward_weight = snake_reward_weight - self.use_sparse_reward = use_sparse_reward - - super().__init__(buf) - self.c_envs = binding.vec_init( - self.observations, self.actions, self.rewards, - self.terminals, self.truncations, num_envs, seed, - can_go_over_65536 = self.can_go_over_65536, - reward_scaler = self.reward_scaler, - endgame_env_prob = self.endgame_env_prob, - scaffolding_ratio = self.scaffolding_ratio, - use_heuristic_rewards = self.use_heuristic_rewards, - snake_reward_weight = self.snake_reward_weight, - use_sparse_reward = self.use_sparse_reward - ) - - def reset(self, seed=0): - binding.vec_reset(self.c_envs, seed) - self.tick = 0 - return self.observations, [] - - def step(self, actions): - self.tick += 1 - - self.actions[:] = actions - binding.vec_step(self.c_envs) - - info = [] - if self.tick % self.log_interval == 0: - info.append(binding.vec_log(self.c_envs)) - - return ( - self.observations, self.rewards, - self.terminals, self.truncations, info - ) - - def render(self): - binding.vec_render(self.c_envs, 0) - - def close(self): - binding.vec_close(self.c_envs) - -if __name__ == '__main__': - N = 128 - - env = G2048(num_envs=N) - env.reset() - steps = 0 - - CACHE = 1024 - actions = np.random.randint(0, 4, (CACHE, N)) - - i = 0 - import time - start = time.time() - while time.time() - start < 10: - env.step(actions[i % CACHE]) - steps += N - i += 1 - - print('2048 SPS:', int(steps / (time.time() - start))) - - env.close() diff --git a/pufferlib/ocean/g2048/g2048_net.h b/pufferlib/ocean/g2048/g2048_net.h deleted file mode 100644 index e3dcf9a9bd..0000000000 --- a/pufferlib/ocean/g2048/g2048_net.h +++ /dev/null @@ -1,104 +0,0 @@ -#include "puffernet.h" - -typedef struct G2048Net G2048Net; - -struct G2048Net { - int hidden_dim; - float* obs; - Linear* layer1; - GELU* gelu1; - Linear* layer2; - GELU* gelu2; - Linear* layer3; - GELU* gelu3; - Linear* actor_hidden; - GELU* gelu_actor; - Linear* actor_head; - Linear* value_hidden; - GELU* gelu_value; - Linear* value_head; - LSTM* lstm; - Multidiscrete* multidiscrete; -}; - -G2048Net* make_g2048net(Weights* weights, int input_dim, int hidden_dim) { - G2048Net* net = calloc(1, sizeof(G2048Net)); - const int num_agents = 1; - const int num_actions = 1; - const int atn_sum = 4; - - int logit_sizes[1] = {4}; - net->obs = calloc(num_agents*input_dim, sizeof(float)); - net->hidden_dim = hidden_dim; - - if (hidden_dim <= 256) { - net->layer1 = make_linear(weights, num_agents, input_dim, 512); - net->gelu1 = make_gelu(num_agents, 512); - net->layer2 = make_linear(weights, num_agents, 512, 256); - net->gelu2 = make_gelu(num_agents, 256); - net->layer3 = make_linear(weights, num_agents, 256, hidden_dim); - net->gelu3 = make_gelu(num_agents, hidden_dim); - } else { - net->layer1 = make_linear(weights, num_agents, input_dim, 2*hidden_dim); - net->gelu1 = make_gelu(num_agents, 2*hidden_dim); - net->layer2 = make_linear(weights, num_agents, 2*hidden_dim, hidden_dim); - net->gelu2 = make_gelu(num_agents, hidden_dim); - net->layer3 = make_linear(weights, num_agents, hidden_dim, hidden_dim); - net->gelu3 = make_gelu(num_agents, hidden_dim); - } - - net->actor_hidden = make_linear(weights, num_agents, hidden_dim, hidden_dim); - net->gelu_actor = make_gelu(num_agents, hidden_dim); - net->actor_head = make_linear(weights, num_agents, hidden_dim, atn_sum); - - net->value_hidden = make_linear(weights, num_agents, hidden_dim, hidden_dim); - net->gelu_value = make_gelu(num_agents, hidden_dim); - net->value_head = make_linear(weights, num_agents, hidden_dim, 1); - - net->lstm = make_lstm(weights, num_agents, hidden_dim, hidden_dim); - net->multidiscrete = make_multidiscrete(num_agents, logit_sizes, num_actions); - return net; -} - -void free_g2048net(G2048Net* net) { - free(net->obs); - free(net->layer1); - free(net->gelu1); - free(net->layer2); - free(net->gelu2); - free(net->layer3); - free(net->gelu3); - - free(net->actor_hidden); - free(net->gelu_actor); - free(net->actor_head); - free(net->value_hidden); - free(net->gelu_value); - free(net->value_head); - - free(net->lstm); - free(net->multidiscrete); - free(net); -} - -void forward_g2048net(G2048Net* net, unsigned char* observations, int* actions) { - for (int i = 0; i < net->layer1->input_dim; i++) { - net->obs[i] = (float)observations[i]; - if (i < 16) net->obs[i] /= 100.0f; - } - - linear(net->layer1, net->obs); - gelu(net->gelu1, net->layer1->output); - linear(net->layer2, net->gelu1->output); - gelu(net->gelu2, net->layer2->output); - linear(net->layer3, net->gelu2->output); - gelu(net->gelu3, net->layer3->output); - - lstm(net->lstm, net->gelu3->output); - - // Actor only. Don't need critic in inference - linear(net->actor_hidden, net->lstm->state_h); - gelu(net->gelu_actor, net->actor_hidden->output); - linear(net->actor_head, net->gelu_actor->output); - softmax_multidiscrete(net->multidiscrete, net->actor_head->output, actions); -} diff --git a/pufferlib/ocean/go/binding.c b/pufferlib/ocean/go/binding.c deleted file mode 100644 index 272c0ba415..0000000000 --- a/pufferlib/ocean/go/binding.c +++ /dev/null @@ -1,33 +0,0 @@ -#include "go.h" -#define Env CGo -#include "../env_binding.h" - -static int my_init(Env* env, PyObject* args, PyObject* kwargs) { - env->width = unpack(kwargs, "width"); - env->height = unpack(kwargs, "height"); - env->grid_size = unpack(kwargs, "grid_size"); - env->board_width = unpack(kwargs, "board_width"); - env->board_height = unpack(kwargs, "board_height"); - env->grid_square_size = unpack(kwargs, "grid_square_size"); - env->moves_made = unpack(kwargs, "moves_made"); - env->komi = unpack(kwargs, "komi"); - env->score = unpack(kwargs, "score"); - env->last_capture_position = unpack(kwargs, "last_capture_position"); - env->reward_move_pass = unpack(kwargs, "reward_move_pass"); - env->reward_move_invalid = unpack(kwargs, "reward_move_invalid"); - env->reward_move_valid = unpack(kwargs, "reward_move_valid"); - env->reward_player_capture = unpack(kwargs, "reward_player_capture"); - env->reward_opponent_capture = unpack(kwargs, "reward_opponent_capture"); - - init(env); - return 0; -} - -static int my_log(PyObject* dict, Log* log) { - assign_to_dict(dict, "perf", log->perf); - assign_to_dict(dict, "score", log->score); - assign_to_dict(dict, "episode_length", log->episode_length); - assign_to_dict(dict, "episode_return", log->episode_return); - assign_to_dict(dict, "n", log->n); - return 0; -} diff --git a/pufferlib/ocean/go/go.c b/pufferlib/ocean/go/go.c deleted file mode 100644 index fcd6614ea3..0000000000 --- a/pufferlib/ocean/go/go.c +++ /dev/null @@ -1,229 +0,0 @@ -#include -#include "go.h" -#include "puffernet.h" - -typedef struct GoNet GoNet; -struct GoNet { - int num_agents; - float* obs_2d; - float* obs_1d; - Conv2D* conv1; - ReLU* relu1; - Conv2D* conv2; - Linear* flat; - CatDim1* cat; - Linear* proj; - ReLU* relu3; - LSTM* lstm; - Linear* actor; - Linear* value_fn; - Multidiscrete* multidiscrete; -}; -GoNet* init_gonet(Weights* weights, int num_agents, int grid_size) { - GoNet* net = calloc(1, sizeof(GoNet)); - int hidden_size = 128; - int cnn_channels = 64; - int conv1_output_size = grid_size - 2; - int output_size = grid_size - 4; - int cnn_flat_size = cnn_channels * output_size * output_size; - - net->num_agents = num_agents; - net->obs_2d = calloc(num_agents * grid_size * grid_size * 2, sizeof(float)); // 2 channels for player and opponent - net->obs_1d = calloc(num_agents * 2, sizeof(float)); // 2 additional features - - net->conv1 = make_conv2d(weights, num_agents, grid_size, grid_size, 2, cnn_channels, 3, 1); - net->relu1 = make_relu(num_agents, cnn_channels * conv1_output_size * conv1_output_size); - net->conv2 = make_conv2d(weights, num_agents, conv1_output_size, conv1_output_size, cnn_channels, cnn_channels, 3, 1); - net->flat = make_linear(weights, num_agents, 2, 32); - net->cat = make_cat_dim1(num_agents, cnn_flat_size, 32); - net->proj = make_linear(weights, num_agents, cnn_flat_size + 32, hidden_size); - net->relu3 = make_relu(num_agents, hidden_size); - net->actor = make_linear(weights, num_agents, hidden_size, grid_size*grid_size + 1); // +1 for pass move - net->value_fn = make_linear(weights, num_agents, hidden_size, 1); - net->lstm = make_lstm(weights, num_agents, hidden_size, 128); - int logit_sizes[6] = {grid_size*grid_size+1}; - net->multidiscrete = make_multidiscrete(num_agents, logit_sizes, 1); - return net; -} - -void free_gonet(GoNet* net) { - free(net->obs_2d); - free(net->obs_1d); - free(net->conv1); - free(net->relu1); - free(net->conv2); - free(net->flat); - free(net->cat); - free(net->relu3); - free(net->proj); - free(net->lstm); - free(net->actor); - free(net->value_fn); - free(net); -} - -void forward(GoNet* net, float* observations, int* actions, int grid_size) { - int full_board = grid_size * grid_size; - // Clear previous observations - memset(net->obs_2d, 0, net->num_agents * grid_size * grid_size * 2 * sizeof(float)); - memset(net->obs_1d, 0, net->num_agents * 2 * sizeof(float)); - - // Reshape observations into 2D boards and additional features - float (*obs_2d)[2][grid_size][grid_size] = (float (*)[2][grid_size][grid_size])net->obs_2d; - float (*obs_1d)[2] = (float (*)[2])net->obs_1d; - - for (int b = 0; b < net->num_agents; b++) { - int b_offset = b * (full_board * 2 + 2); // offset for each batch - - // Process black stones board - for (int i = 0; i < grid_size; i++) { - for (int j = 0; j < grid_size; j++) { - obs_2d[b][0][i][j] = observations[b_offset + i*grid_size + j]; - } - } - - // Process white stones board - for (int i = 0; i < grid_size; i++) { - for (int j = 0; j < grid_size; j++) { - obs_2d[b][1][i][j] = observations[b_offset + full_board + i*grid_size + j]; - } - } - - // Process additional features - obs_1d[b][0] = observations[b_offset + full_board * 2]; - obs_1d[b][1] = observations[b_offset + full_board * 2 + 1]; - } - - // Forward pass through the network - conv2d(net->conv1, net->obs_2d); - relu(net->relu1, net->conv1->output); - conv2d(net->conv2, net->relu1->output); - - linear(net->flat, net->obs_1d); - - cat_dim1(net->cat, net->conv2->output, net->flat->output); - linear(net->proj, net->cat->output); - relu(net->relu3, net->proj->output); - - lstm(net->lstm, net->relu3->output); - linear(net->actor, net->lstm->state_h); - linear(net->value_fn, net->lstm->state_h); - - // Get action by taking argmax of actor output - softmax_multidiscrete(net->multidiscrete, net->actor->output, actions); - -} - -void demo(int grid_size) { - - CGo env = { - .width = 950, - .height = 64*(grid_size+1), - .grid_size = grid_size, - .board_width = 64*(grid_size+1) + 400, - .board_height = 64*(grid_size+1), - .grid_square_size = 64, - .moves_made = 0, - .komi = 7.5, - .reward_move_pass = -0.25, - .reward_move_invalid = -0.1, - .reward_move_valid = 0.1 - }; - - Weights* weights = load_weights("resources/go/go_weights.bin", 254867); - GoNet* net = init_gonet(weights, 1, grid_size); - allocate(&env); - c_reset(&env); - c_render(&env); - - int tick = 0; - while (!WindowShouldClose()) { - // User can take control of the paddle - if(tick % 12 == 0) { - tick = 0; - int human_action = env.actions[0]; - forward(net, env.observations, env.actions, grid_size); - if (IsKeyDown(KEY_LEFT_SHIFT)) { - env.actions[0] = human_action; - } - c_step(&env); - if (IsKeyDown(KEY_LEFT_SHIFT)) { - env.actions[0] = -1; - } - } - tick++; - if (IsKeyDown(KEY_LEFT_SHIFT)) { - if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) { - Vector2 mousePos = GetMousePosition(); - - // Calculate the offset for the board - int boardOffsetX = env.grid_square_size; - int boardOffsetY = env.grid_square_size; - - // Adjust mouse position relative to the board - int relativeX = mousePos.x - boardOffsetX; - int relativeY = mousePos.y - boardOffsetY; - - // Calculate cell indices for the corners - int cellX = (relativeX + env.grid_square_size / 2) / env.grid_square_size; - int cellY = (relativeY + env.grid_square_size / 2) / env.grid_square_size; - - // Ensure the click is within the game board - if (cellX >= 0 && cellX <= env.grid_size && cellY >= 0 && cellY <= env.grid_size) { - // Calculate the point index (1-19) based on the click position - int pointIndex = cellY * (env.grid_size) + cellX + 1; - env.actions[0] = (unsigned short)pointIndex; - } - // Check if pass button is clicked - int passButtonX = env.width - 300; - int passButtonY = 200; - int passButtonWidth = 100; - int passButtonHeight = 50; - - if (mousePos.x >= passButtonX && mousePos.x <= passButtonX + passButtonWidth && - mousePos.y >= passButtonY && mousePos.y <= passButtonY + passButtonHeight) { - env.actions[0] = 0; // Send action 0 for pass - } - } - } - c_render(&env); - } - //close_client(client); - free_allocated(&env); -} - -void performance_test() { - long test_time = 10; - CGo env = { - .width = 1000, - .height = 800, - .grid_size = 9, - .board_width = 600, - .board_height = 600, - .grid_square_size = 600/9, - .moves_made = 0, - .komi = 7.5, - .reward_move_pass = -0.25, - .reward_move_invalid = -0.1, - .reward_move_valid = 0.1 - }; - allocate(&env); - c_reset(&env); - - long start = time(NULL); - int i = 0; - while (time(NULL) - start < test_time) { - env.actions[0] = rand() % (env.grid_size)*(env.grid_size); - c_step(&env); - i++; - } - long end = time(NULL); - printf("SPS: %ld\n", i / (end - start)); - free_allocated(&env); -} - -int main() { - demo(7); - // performance_test(); - return 0; -} diff --git a/pufferlib/ocean/go/go.py b/pufferlib/ocean/go/go.py deleted file mode 100644 index 06b87155d3..0000000000 --- a/pufferlib/ocean/go/go.py +++ /dev/null @@ -1,92 +0,0 @@ -'''High-perf Pong - -Inspired from https://gist.github.com/Yttrmin/18ecc3d2d68b407b4be1 -& https://jair.org/index.php/jair/article/view/10819/25823 -& https://www.youtube.com/watch?v=PSQt5KGv7Vk -''' - -import numpy as np -import gymnasium - -import pufferlib -from pufferlib.ocean.go import binding - -class Go(pufferlib.PufferEnv): - def __init__(self, num_envs=1, render_mode=None, log_interval=1, - width=950, height=800, - grid_size=7, - board_width=600, board_height=600, - grid_square_size=600/9, - moves_made=0, - komi=7.5, - score = 0.0, - last_capture_position=-1, - reward_move_pass = -0.25, - reward_move_invalid = -0.1, - reward_move_valid = 0.1, - reward_player_capture = 0.25, - reward_opponent_capture = -0.25, - buf = None, seed=0): - - # env - self.num_agents = num_envs - self.render_mode = render_mode - self.log_interval = log_interval - self.tick = 0 - self.num_obs = (grid_size) * (grid_size)*2 + 2 - self.num_act = (grid_size) * (grid_size) + 1 - self.single_observation_space = gymnasium.spaces.Box(low=0, high=1, - shape=(self.num_obs,), dtype=np.float32) - self.single_action_space = gymnasium.spaces.Discrete(self.num_act) - - super().__init__(buf=buf) - height = 64*(grid_size+1) - self.c_envs = binding.vec_init(self.observations, self.actions, self.rewards, - self.terminals, self.truncations, num_envs, seed, width=width, height=height, grid_size=grid_size, - board_width=board_width, board_height=board_height, grid_square_size=grid_square_size, - moves_made=moves_made, komi=komi, score=score, last_capture_position=last_capture_position, - reward_move_pass=reward_move_pass, reward_move_invalid=reward_move_invalid, - reward_move_valid=reward_move_valid, reward_player_capture=reward_player_capture, - reward_opponent_capture=reward_opponent_capture) - - def reset(self, seed=None): - binding.vec_reset(self.c_envs, seed) - self.tick = 0 - return self.observations, [] - - def step(self, actions): - self.actions[:] = actions - binding.vec_step(self.c_envs) - self.tick += 1 - info = [] - if self.tick % self.log_interval == 0: - info.append(binding.vec_log(self.c_envs)) - - return (self.observations, self.rewards, - self.terminals, self.truncations, info) - - def render(self): - binding.vec_render(self.c_envs, 0) - - def close(self): - binding.vec_close(self.c_envs) - -def test_performance(timeout=10, atn_cache=1024): - num_envs=1000 - env = Go(num_envs=num_envs) - env.reset() - tick = 0 - - actions = np.random.randint(0, env.single_action_space.n, (atn_cache, num_envs)) - - import time - start = time.time() - while time.time() - start < timeout: - atn = actions[tick % atn_cache] - env.step(atn) - tick += 1 - - sps = num_envs * tick / (time.time() - start) - print(f'SPS: {sps:,}') -if __name__ == '__main__': - test_performance() diff --git a/pufferlib/ocean/grid/__init__.py b/pufferlib/ocean/grid/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/pufferlib/ocean/grid/binding.c b/pufferlib/ocean/grid/binding.c deleted file mode 100644 index 449a8a587d..0000000000 --- a/pufferlib/ocean/grid/binding.c +++ /dev/null @@ -1,71 +0,0 @@ -#include "grid.h" - -#define Env Grid -#define MY_SHARED -#include "../env_binding.h" - -static PyObject* my_shared(PyObject* self, PyObject* args, PyObject* kwargs) { - int num_maps = unpack(kwargs, "num_maps"); - int max_size = unpack(kwargs, "max_size"); - int size = unpack(kwargs, "size"); - State* levels = calloc(num_maps, sizeof(State)); - - if (max_size <= 5) { - PyErr_SetString(PyExc_ValueError, "max_size must be >5"); - return NULL; - } - - // Temporary env used to gen maps - Grid env; - env.max_size = max_size; - init_grid(&env); - - srand(time(NULL)); - int start_seed = rand(); - for (int i = 0; i < num_maps; i++) { - int sz = size; - if (size == -1) { - sz = 5 + (rand() % (max_size-5)); - } - - if (sz % 2 == 0) { - sz -= 1; - } - - float difficulty = (float)rand()/(float)(RAND_MAX); - create_maze_level(&env, sz, sz, difficulty, start_seed + i); - init_state(&levels[i], max_size, 1); - get_state(&env, &levels[i]); - } - - return PyLong_FromVoidPtr(levels); -} - -static int my_init(Env* env, PyObject* args, PyObject* kwargs) { - env->max_size = unpack(kwargs, "max_size"); - env->num_maps = unpack(kwargs, "num_maps"); - init_grid(env); - - PyObject* handle_obj = PyDict_GetItemString(kwargs, "state"); - if (!PyObject_TypeCheck(handle_obj, &PyLong_Type)) { - PyErr_SetString(PyExc_TypeError, "state handle must be an integer"); - return 1; - } - - State* levels = (State*)PyLong_AsVoidPtr(handle_obj); - if (!levels) { - PyErr_SetString(PyExc_ValueError, "Invalid state handle"); - return 1; - } - - env->levels = levels; - return 0; -} - -static int my_log(PyObject* dict, Log* log) { - assign_to_dict(dict, "perf", log->perf); - assign_to_dict(dict, "score", log->score); - assign_to_dict(dict, "episode_return", log->episode_return); - assign_to_dict(dict, "episode_length", log->episode_length); - return 0; -} diff --git a/pufferlib/ocean/grid/c_grid.pyx b/pufferlib/ocean/grid/c_grid.pyx deleted file mode 100644 index 64c720a890..0000000000 --- a/pufferlib/ocean/grid/c_grid.pyx +++ /dev/null @@ -1,206 +0,0 @@ -# distutils: define_macros=NPY_NO_DEPRECATED_API=NPY_1_7_API_VERSION -# cython: language_level=3 -# cython: boundscheck=False -# cython: initializedcheck=False -# cython: wraparound=False -# cython: cdivision=True -# cython: nonecheck=False -# cython: profile=False - -from libc.stdlib cimport rand - -cdef: - int EMPTY = 0 - int FOOD = 1 - int WALL = 2 - int AGENT_1 = 3 - int AGENT_2 = 4 - int AGENT_3 = 5 - int AGENT_4 = 6 - - int PASS = 0 - int NORTH = 1 - int SOUTH = 2 - int EAST = 3 - int WEST = 4 - -cdef class Environment: - cdef: - int width - int height - int num_agents - int horizon - int vision_range - float agent_speed - bint discretize - float food_reward - int expected_lifespan - int obs_size - - unsigned char[:, :] grid - unsigned char[:, :, :] observations - float[:] rewards - float[:, :] agent_positions - float[:, :] spawn_position_cands - int[:] agent_colors - - def __init__(self, grid, agent_positions, spawn_position_cands, agent_colors, - observations, rewards, int width, int height, int num_agents, int horizon, - int vision_range, float agent_speed, bint discretize, float food_reward, - int expected_lifespan): - self.width = width - self.height = height - self.num_agents = num_agents - self.horizon = horizon - self.vision_range = vision_range - self.agent_speed = agent_speed - self.discretize = discretize - self.food_reward = food_reward - self.expected_lifespan = expected_lifespan - self.obs_size = 2*self.vision_range + 1 - - self.grid = grid - self.observations = observations - self.rewards = rewards - self.agent_positions = agent_positions - self.spawn_position_cands = spawn_position_cands - self.agent_colors = agent_colors - - cdef void compute_observations(self): - cdef: - float y - float x - int r - int c - int agent_idx - - for agent_idx in range(self.num_agents): - y = self.agent_positions[agent_idx, 0] - x = self.agent_positions[agent_idx, 1] - r = int(y) - c = int(x) - self.observations[agent_idx, :] = self.grid[ - r-self.vision_range:r+self.vision_range+1, - c-self.vision_range:c+self.vision_range+1 - ] - - cdef void spawn_food(self): - cdef int r, c, tile - while True: - r = rand() % (self.height - 1) - c = rand() % (self.width - 1) - tile = self.grid[r, c] - if tile == EMPTY: - self.grid[r, c] = FOOD - return - - cdef void spawn_agent(self, int agent_idx): - cdef int old_r, old_c, r, c, tile - - # Delete agent from old position - old_r = int(self.agent_positions[agent_idx, 0]) - old_c = int(self.agent_positions[agent_idx, 1]) - self.grid[old_r, old_c] = EMPTY - - r = rand() % (self.height - 1) - c = rand() % (self.width - 1) - tile = self.grid[r, c] - if tile == EMPTY: - # Spawn agent in new position - self.grid[r, c] = self.agent_colors[agent_idx] - self.agent_positions[agent_idx, 0] = r - self.agent_positions[agent_idx, 1] = c - return - - def reset(self, seed=0): - # Add borders - cdef int left = int(self.agent_speed * self.vision_range) - cdef int right = self.width - int(self.agent_speed*self.vision_range) - 1 - cdef int bottom = self.height - int(self.agent_speed*self.vision_range) - 1 - self.grid[:left, :] = WALL - self.grid[:, :left] = WALL - self.grid[bottom:, :] = WALL - self.grid[:, right:] = WALL - - # Agent spawning - cdef: - int spawn_idx - float y - float x - int disc_y - int disc_x - int agent_idx = 0 - - for spawn_idx in range(self.width*self.height): - y = self.spawn_position_cands[spawn_idx, 0] - x = self.spawn_position_cands[spawn_idx, 1] - disc_y = int(y) - disc_x = int(x) - - if self.grid[disc_y, disc_x] == EMPTY: - self.grid[disc_y, disc_x] = self.agent_colors[agent_idx] - self.agent_positions[agent_idx, 0] = y - self.agent_positions[agent_idx, 1] = x - agent_idx += 1 - if agent_idx == self.num_agents: - break - - self.compute_observations() - - def step(self, np_actions): - cdef: - float[:, :] actions_continuous - unsigned int[:, :] actions_discrete - int agent_idx - float y - float x - float vel_y - float vel_x - int disc_y - int disc_x - int disc_dest_y - int disc_dest_x - - if self.discretize: - actions_discrete = np_actions - else: - actions_continuous = np_actions - - for agent_idx in range(self.num_agents): - if self.discretize: - # Convert [0, 1, 2] to [-1, 0, 1] - vel_y = float(actions_discrete[agent_idx, 0]) - 1.0 - vel_x = float(actions_discrete[agent_idx, 1]) - 1.0 - else: - vel_y = actions_continuous[agent_idx, 0] - vel_x = actions_continuous[agent_idx, 1] - - y = self.agent_positions[agent_idx, 0] - x = self.agent_positions[agent_idx, 1] - dest_y = y + self.agent_speed * vel_y - dest_x = x + self.agent_speed * vel_x - - # Discretize - disc_y = int(y) - disc_x = int(x) - disc_dest_y = int(dest_y) - disc_dest_x = int(dest_x) - - if self.grid[disc_dest_y, disc_dest_x] == FOOD: - self.grid[disc_dest_y, disc_dest_x] = EMPTY - self.rewards[agent_idx] = self.food_reward - self.spawn_food() - - if self.grid[disc_dest_y, disc_dest_x] == 0: - self.grid[disc_y, disc_x] = EMPTY - self.grid[disc_dest_y, disc_dest_x] = self.agent_colors[agent_idx] - - # Continuous position update - self.agent_positions[agent_idx, 0] = dest_y - self.agent_positions[agent_idx, 1] = dest_x - - # Randomly respawn agents - if rand() % self.expected_lifespan == 0: - self.spawn_agent(agent_idx) - - self.compute_observations() diff --git a/pufferlib/ocean/grid/cy_grid.pyx b/pufferlib/ocean/grid/cy_grid.pyx deleted file mode 100644 index bfafe25c2a..0000000000 --- a/pufferlib/ocean/grid/cy_grid.pyx +++ /dev/null @@ -1,186 +0,0 @@ -# distutils: define_macros=NPY_NO_DEPRECATED_API=NPY_1_7_API_VERSION -# cython: language_level=3 -# cython: boundscheck=False -# cython: initializedcheck=False -# cython: wraparound=False -# cython: cdivision=True -# cython: nonecheck=False -# cython: profile=True - -from libc.stdlib cimport calloc, free, rand - -cdef extern from "grid.h": - int LOG_BUFFER_SIZE - - ctypedef struct Log: - float episode_return; - float episode_length; - float score; - - ctypedef struct LogBuffer - LogBuffer* allocate_logbuffer(int) - void free_logbuffer(LogBuffer*) - Log aggregate_and_clear(LogBuffer*) - - ctypedef struct Agent: - float y; - float x; - float prev_y; - float prev_x; - float spawn_y; - float spawn_x; - int color; - float direction; - int held; - - ctypedef struct Grid: - int width; - int height; - int num_agents; - int horizon; - int vision; - float speed; - int obs_size; - int max_size; - bint discretize; - Log log; - LogBuffer* log_buffer; - Agent* agents; - unsigned char* grid; - int* counts; - unsigned char* observations; - float* actions; - float* rewards; - unsigned char* dones; - - ctypedef struct State: - int width; - int height; - int num_agents; - Agent* agents; - unsigned char* grid; - - cdef: - void create_maze_level(Grid* env, int width, int height, float difficulty, int seed) - void load_locked_room_env(unsigned char* observations, - unsigned int* actions, float* rewards, float* dones) - void init_grid(Grid* env) - void reset(Grid* env, int seed) - void compute_observations(Grid* env) - bint step(Grid* env) - ctypedef struct Renderer - Renderer* init_renderer(int cell_size, int width, int height) - void render_global(Renderer*erenderer, Grid* env, float frac, float overlay) - void clear_overlay(Renderer* renderer) - void close_renderer(Renderer* renderer) - void init_state(State* state, int max_size, int num_agents) - void free_state(State* state) - void get_state(Grid* env, State* state) - void set_state(Grid* env, State* state) - -import numpy as np -cimport numpy as cnp - -cdef class CGrid: - cdef: - Grid* envs - State* levels - Renderer* client - LogBuffer* logs - int num_envs - int num_maps - int max_size - - def __init__(self, unsigned char[:, :] observations, float[:] actions, - float[:] rewards, unsigned char[:] terminals, int num_envs, int num_maps, - int size, int max_size): - - self.num_envs = num_envs - self.num_maps = num_maps - if size > max_size: - max_size = size - - self.max_size = max_size - - self.client = NULL - self.levels = calloc(num_maps, sizeof(State)) - self.envs = calloc(num_envs, sizeof(Grid)) - self.logs = allocate_logbuffer(LOG_BUFFER_SIZE) - - cdef int i - for i in range(num_envs): - self.envs[i] = Grid( - observations = &observations[i, 0], - actions = &actions[i], - rewards = &rewards[i], - dones = &terminals[i], - log_buffer = self.logs, - max_size = max_size, - num_agents = 1, - vision = 5, - speed = 1, - discretize = True, - ) - init_grid(&self.envs[i]) - - cdef float difficulty - cdef int sz - for i in range(num_maps): - - # RNG or fixed size - if size == -1: - sz = np.random.randint(5, max_size) - else: - sz = size - - if sz % 2 == 0: - sz -= 1 - - difficulty = np.random.rand() - create_maze_level(&self.envs[0], sz, sz, difficulty, i) - init_state(&self.levels[i], max_size, 1) - get_state(&self.envs[0], &self.levels[i]) - - def reset(self): - cdef int i, idx - for i in range(self.num_envs): - idx = rand() % self.num_maps - reset(&self.envs[i], i) - set_state(&self.envs[i], &self.levels[idx]) - compute_observations(&self.envs[i]) - - def step(self): - cdef: - int i, idx - bint done - - for i in range(self.num_envs): - done = step(&self.envs[i]) - if done: - idx = rand() % self.num_maps - reset(&self.envs[i], i) - set_state(&self.envs[i], &self.levels[idx]) - - if i == 0 and self.client != NULL: - clear_overlay(self.client) - - def render(self, int cell_size=16, float overlay=0.0): - if self.client == NULL: - import os - cwd = os.getcwd() - os.chdir(os.path.abspath(os.path.join(os.path.dirname(__file__), "..", ".."))) - self.client = init_renderer(cell_size, self.max_size, self.max_size) - os.chdir(cwd) - - render_global(self.client, &self.envs[0], 0, overlay) - - def log(self): - cdef Log log = aggregate_and_clear(self.logs) - return log - - def close(self): - if self.client != NULL: - close_renderer(self.client) - self.client = NULL - - #free_envs(self.envs, self.num_envs) diff --git a/pufferlib/ocean/grid/grid.c b/pufferlib/ocean/grid/grid.c deleted file mode 100644 index 3a267a3138..0000000000 --- a/pufferlib/ocean/grid/grid.c +++ /dev/null @@ -1,93 +0,0 @@ -#include "grid.h" - -int main() { - int max_size = 32; - int width = 32; - int height = 32; - int num_agents = 1; - int horizon = 128; - float speed = 1; - int vision = 5; - bool discretize = true; - - int render_cell_size = 32; - int seed = 0; - - Grid* env = allocate_grid(max_size, num_agents, horizon, - vision, speed, discretize); - - //env->width = 32; - //env->height = 32; env->agents[0].spawn_x = 16; - //env->agents[0].spawn_y = 16; - //env->agents[0].color = 6; - //reset(env, seed); - //load_locked_room_preset(env); - - - State* levels = calloc(1, sizeof(State)); - - create_maze_level(env, 31, 31, 0.85, seed); - init_state(levels, max_size, num_agents); - get_state(env, levels); - env->num_maps = 1; - env->levels = levels; - //generate_locked_room(env); - //State state; - //init_state(&state, env->max_size, env->num_agents); - //get_state(env, &state); - - /* - width = height = 31; - env->width=31; - env->height=31; - env->agents[0].spawn_x = 1; - env->agents[0].spawn_y = 1; - reset(env, seed); - generate_growing_tree_maze(env->grid, env->width, env->height, max_size, 0.85, 0); - env->grid[(env->height-2)*env->max_size + (env->width - 2)] = GOAL; - */ - - int tick = 0; - c_render(env); - while (!WindowShouldClose()) { - // User can take control of the first agent - env->actions[0] = ATN_FORWARD; - Agent* agent = &env->agents[0]; - - // TODO: Why are up and down flipped? - if (IsKeyDown(KEY_LEFT_SHIFT)) { - if (IsKeyDown(KEY_UP) || IsKeyDown(KEY_W)){ - //env->actions[0] = ATN_FORWARD; - agent->direction = 3.0*PI/2.0; - } else if (IsKeyDown(KEY_DOWN) || IsKeyDown(KEY_S)) { - //env->actions[0] = ATN_BACK; - agent->direction = PI/2.0; - } else if (IsKeyDown(KEY_LEFT) || IsKeyDown(KEY_A)) { - //env->actions[0] = ATN_LEFT; - agent->direction = PI; - } else if (IsKeyDown(KEY_RIGHT) || IsKeyDown(KEY_D)) { - //env->actions[0] = ATN_RIGHT; - agent->direction = 0; - } else { - env->actions[0] = ATN_PASS; - } - } else { - for (int i = 0; i < num_agents; i++) { - env->actions[i] = rand() % 5; - } - } - - //env->actions[0] = actions[t]; - tick = (tick + 1)%12; - bool done = false; - if (tick % 1 == 0) { - c_step(env); - //printf("direction: %f\n", env->agents[0].direction); - - } - c_render(env); - } - free_allocated_grid(env); - return 0; -} - diff --git a/pufferlib/ocean/grid/grid.py b/pufferlib/ocean/grid/grid.py deleted file mode 100644 index 0229d6fe71..0000000000 --- a/pufferlib/ocean/grid/grid.py +++ /dev/null @@ -1,67 +0,0 @@ -import numpy as np -import os - -import gymnasium - -import pufferlib -from pufferlib.ocean.grid import binding - -class Grid(pufferlib.PufferEnv): - def __init__(self, render_mode='raylib', vision_range=5, - num_envs=4096, num_maps=1000, map_size=-1, max_size=9, - report_interval=128, buf=None, seed=0): - assert map_size <= max_size - self.obs_size = 2*vision_range + 1 - self.single_observation_space = gymnasium.spaces.Box(low=0, high=255, - shape=(self.obs_size*self.obs_size,), dtype=np.uint8) - self.single_action_space = gymnasium.spaces.Discrete(5) - self.render_mode = render_mode - self.num_agents = num_envs - self.report_interval = report_interval - super().__init__(buf=buf) - self.float_actions = np.zeros_like(self.actions).astype(np.float32) - self.c_state = binding.shared(num_maps=num_maps, max_size=max_size, size=map_size) - self.c_envs = binding.vec_init(self.observations, self.float_actions, - self.rewards, self.terminals, self.truncations, num_envs, seed, - state=self.c_state, max_size=max_size, num_maps=num_maps) - pass - - def reset(self, seed=None): - self.tick = 0 - binding.vec_reset(self.c_envs, seed) - return self.observations, [] - - def step(self, actions): - self.float_actions[:] = actions - binding.vec_step(self.c_envs) - - info = [] - if self.tick % self.report_interval == 0: - info.append(binding.vec_log(self.c_envs)) - - self.tick += 1 - return (self.observations, self.rewards, - self.terminals, self.truncations, info) - - def render(self, overlay=0): - binding.vec_render(self.c_envs, overlay) - - def close(self): - pass - #binding.vec_close(self.c_envs) - -def test_performance(timeout=10, atn_cache=1024): - env = CGrid(num_envs=1000) - env.reset() - tick = 0 - - actions = np.random.randint(0, 2, (atn_cache, env.num_envs)) - - import time - start = time.time() - while time.time() - start < timeout: - atn = actions[tick % atn_cache] - env.step(atn) - tick += 1 - - print(f'SPS: %f', env.num_envs * tick / (time.time() - start)) diff --git a/pufferlib/ocean/impulse_wars/.clang-format b/pufferlib/ocean/impulse_wars/.clang-format deleted file mode 100644 index d9ba19d3de..0000000000 --- a/pufferlib/ocean/impulse_wars/.clang-format +++ /dev/null @@ -1,229 +0,0 @@ ---- -Language: Cpp -AccessModifierOffset: -2 -AlignAfterOpenBracket: BlockIndent -AlignArrayOfStructures: None -AlignConsecutiveAssignments: - Enabled: false - AcrossEmptyLines: false - AcrossComments: false - AlignCompound: false - AlignFunctionPointers: false - PadOperators: true -AlignConsecutiveBitFields: - Enabled: false - AcrossEmptyLines: false - AcrossComments: false - AlignCompound: false - AlignFunctionPointers: false - PadOperators: false -AlignConsecutiveDeclarations: - Enabled: false - AcrossEmptyLines: false - AcrossComments: false - AlignCompound: false - AlignFunctionPointers: false - PadOperators: false -AlignConsecutiveMacros: - Enabled: false - AcrossEmptyLines: false - AcrossComments: false - AlignCompound: false - AlignFunctionPointers: false - PadOperators: false -AlignConsecutiveShortCaseStatements: - Enabled: false - AcrossEmptyLines: false - AcrossComments: false - AlignCaseColons: false -AlignEscapedNewlines: Right -AlignOperands: Align -AlignTrailingComments: - Kind: Always - OverEmptyLines: 0 -AllowAllArgumentsOnNextLine: true -AllowAllParametersOfDeclarationOnNextLine: true -AllowBreakBeforeNoexceptSpecifier: Never -AllowShortBlocksOnASingleLine: Never -AllowShortCaseLabelsOnASingleLine: false -AllowShortCompoundRequirementOnASingleLine: true -AllowShortEnumsOnASingleLine: true -AllowShortFunctionsOnASingleLine: All -AllowShortIfStatementsOnASingleLine: Never -AllowShortLambdasOnASingleLine: All -AllowShortLoopsOnASingleLine: false -AlwaysBreakAfterDefinitionReturnType: None -AlwaysBreakAfterReturnType: None -AlwaysBreakBeforeMultilineStrings: false -AlwaysBreakTemplateDeclarations: MultiLine -AttributeMacros: - - __capability -BinPackArguments: false -BinPackParameters: false -BitFieldColonSpacing: Both -BraceWrapping: - AfterCaseLabel: false - AfterClass: false - AfterControlStatement: Never - AfterEnum: false - AfterExternBlock: false - AfterFunction: false - AfterNamespace: false - AfterObjCDeclaration: false - AfterStruct: false - AfterUnion: false - BeforeCatch: false - BeforeElse: false - BeforeLambdaBody: false - BeforeWhile: false - IndentBraces: false - SplitEmptyFunction: true - SplitEmptyRecord: true - SplitEmptyNamespace: true -BreakAdjacentStringLiterals: true -BreakAfterAttributes: Leave -BreakAfterJavaFieldAnnotations: false -BreakArrays: true -BreakBeforeBinaryOperators: None -BreakBeforeClosingBracket: Always -BreakBeforeConceptDeclarations: Always -BreakBeforeBraces: Custom -BreakBeforeInlineASMColon: OnlyMultiline -BreakBeforeTernaryOperators: true -BreakConstructorInitializers: BeforeColon -BreakInheritanceList: BeforeColon -BreakStringLiterals: true -ColumnLimit: 0 -CommentPragmas: '^ IWYU pragma:' -CompactNamespaces: false -ConstructorInitializerIndentWidth: 4 -ContinuationIndentWidth: 4 -Cpp11BracedListStyle: true -DerivePointerAlignment: false -DisableFormat: false -EmptyLineAfterAccessModifier: Never -EmptyLineBeforeAccessModifier: LogicalBlock -ExperimentalAutoDetectBinPacking: false -FixNamespaceComments: false -IfMacros: - - KJ_IF_MAYBE -IncludeBlocks: Preserve -IncludeIsMainRegex: '(Test)?$' -IncludeIsMainSourceRegex: '' -IndentAccessModifiers: false -IndentCaseBlocks: false -IndentCaseLabels: false -IndentExternBlock: AfterExternBlock -IndentGotoLabels: true -IndentPPDirectives: None -IndentRequiresClause: true -IndentWidth: 4 -IndentWrappedFunctionNames: false -InsertBraces: true -InsertNewlineAtEOF: false -InsertTrailingCommas: Wrapped -IntegerLiteralSeparator: - Binary: 0 - BinaryMinDigits: 0 - Decimal: 0 - DecimalMinDigits: 0 - Hex: 0 - HexMinDigits: 0 -JavaScriptQuotes: Leave -JavaScriptWrapImports: true -KeepEmptyLinesAtTheStartOfBlocks: true -KeepEmptyLinesAtEOF: false -LambdaBodyIndentation: Signature -LineEnding: DeriveLF -MacroBlockBegin: '' -MacroBlockEnd: '' -MaxEmptyLinesToKeep: 1 -NamespaceIndentation: None -ObjCBinPackProtocolList: Auto -ObjCBlockIndentWidth: 2 -ObjCBreakBeforeNestedBlockParam: true -ObjCSpaceAfterProperty: false -ObjCSpaceBeforeProtocolList: true -PackConstructorInitializers: Never -PenaltyBreakAssignment: 2 -PenaltyBreakBeforeFirstCallParameter: 19 -PenaltyBreakComment: 300 -PenaltyBreakFirstLessLess: 120 -PenaltyBreakOpenParenthesis: 0 -PenaltyBreakScopeResolution: 500 -PenaltyBreakString: 1000 -PenaltyBreakTemplateDeclaration: 10 -PenaltyExcessCharacter: 1000000 -PenaltyIndentedWhitespace: 0 -PenaltyReturnTypeOnItsOwnLine: 60 -PointerAlignment: Right -PPIndentWidth: -1 -QualifierAlignment: Leave -ReferenceAlignment: Pointer -ReflowComments: true -RemoveBracesLLVM: false -RemoveParentheses: Leave -RemoveSemicolon: false -RequiresClausePosition: OwnLine -RequiresExpressionIndentation: OuterScope -SeparateDefinitionBlocks: Leave -ShortNamespaceLines: 1 -SkipMacroDefinitionBody: false -SortIncludes: CaseSensitive -SortJavaStaticImport: Before -SortUsingDeclarations: LexicographicNumeric -SpaceAfterCStyleCast: false -SpaceAfterLogicalNot: false -SpaceAfterTemplateKeyword: true -SpaceAroundPointerQualifiers: Default -SpaceBeforeAssignmentOperators: true -SpaceBeforeCaseColon: false -SpaceBeforeCpp11BracedList: false -SpaceBeforeCtorInitializerColon: true -SpaceBeforeInheritanceColon: true -SpaceBeforeJsonColon: false -SpaceBeforeParens: ControlStatements -SpaceBeforeParensOptions: - AfterControlStatements: true - AfterForeachMacros: true - AfterFunctionDefinitionName: false - AfterFunctionDeclarationName: false - AfterIfMacros: true - AfterOverloadedOperator: false - AfterPlacementOperator: true - AfterRequiresInClause: false - AfterRequiresInExpression: false - BeforeNonEmptyParentheses: false -SpaceBeforeRangeBasedForLoopColon: true -SpaceBeforeSquareBrackets: false -SpaceInEmptyBlock: false -SpacesBeforeTrailingComments: 1 -SpacesInAngles: Never -SpacesInContainerLiterals: true -SpacesInLineCommentPrefix: - Minimum: 1 - Maximum: -1 -SpacesInParens: Never -SpacesInParensOptions: - InCStyleCasts: false - InConditionalStatements: false - InEmptyParentheses: false - Other: false -SpacesInSquareBrackets: false -Standard: Latest -StatementAttributeLikeMacros: - - Q_EMIT -StatementMacros: - - Q_UNUSED - - QT_REQUIRE_VERSION -TabWidth: 4 -UseTab: Never -VerilogBreakBetweenInstancePorts: true -WhitespaceSensitiveMacros: - - BOOST_PP_STRINGIZE - - CF_SWIFT_NAME - - NS_SWIFT_NAME - - PP_STRINGIZE - - STRINGIZE -... - diff --git a/pufferlib/ocean/impulse_wars/CMakeLists.txt b/pufferlib/ocean/impulse_wars/CMakeLists.txt deleted file mode 100644 index fec78fa53f..0000000000 --- a/pufferlib/ocean/impulse_wars/CMakeLists.txt +++ /dev/null @@ -1,138 +0,0 @@ -# 3.22 was released on Nov 2021, should be widely available -cmake_minimum_required(VERSION 3.22) -include(FetchContent) - -project( - impulse-wars - DESCRIPTION "Impulse Wars" - LANGUAGES C -) - -message(INFO " C Compiler: ${CMAKE_C_COMPILER} ${CMAKE_C_COMPILER_VERSION} ${CMAKE_C_COMPILER_ID}") - -# use ccache if available to speed up subsequent builds -find_program(CCACHE_FOUND "ccache") -if(CCACHE_FOUND) - set(CMAKE_C_COMPILER_LAUNCHER "ccache") -endif() - -# enable some C23 features, the c2x standard is a WIP standard supported -# by gcc since 9 (May 2019) and clang since 9 (Sep 2019) -set(CMAKE_C_FLAGS_INIT " -std=c2x") - -# force position independent code everywhere to prevent some rare -# linker errors depending on what compiler is used -add_compile_options("-fPIC") - -if(CMAKE_BUILD_TYPE MATCHES Debug) - # leak detection doesn't work correctly when the code is called by - # Python, so disable it - if(DEFINED BUILD_PYTHON_MODULE) - add_compile_options("-fno-omit-frame-pointer" "-fsanitize=address,undefined,bounds,pointer-overflow") - add_link_options("-shared-libasan" "-fno-omit-frame-pointer" "-fsanitize=address,undefined,bounds,pointer-overflow") - else() - add_compile_options("-fno-omit-frame-pointer" "-fsanitize=address,undefined,bounds,pointer-overflow,leak") - add_link_options("-fno-omit-frame-pointer" "-fsanitize=address,undefined,bounds,pointer-overflow,leak") - endif() - - # mold is an extremely fast linker, use it if available - # only use mold in debug mode, link time optimization currently doesn't - # work with mold and provides large speedups - find_program(MOLD_FOUND "mold") - if(MOLD_FOUND) - add_link_options("-fuse-ld=mold") - endif() -else() - add_compile_options("-flto" "-fno-math-errno") - if (NOT DEFINED EMSCRIPTEN) - # emscripten doesn't support -march=native, it doesn't make sense - # for WASM anyway - add_compile_options("-march=native") - else() - # tell emscripten to generate an HTML file that can be used to - # test the WASM, and ensure necessary code is transformed to be - # async friendly; it allows the game to be run much more smoothly - set(CMAKE_EXECUTABLE_SUFFIX ".html") - add_link_options("-sASYNCIFY") - endif() - # ensure the linker used is from the same compiler toolchain, or else - # link time optimization will probably fail; if we're using - # emscripten it will use it's own linker - if(CMAKE_C_COMPILER_ID MATCHES "Clang" AND NOT DEFINED EMSCRIPTEN) - add_link_options("-fuse-ld=lld") - endif() - - # add_compile_options("-pg") - # add_link_options("-pg") -endif() - -set_property(GLOBAL PROPERTY USE_FOLDERS ON) -set(FETCHCONTENT_QUIET FALSE) - -# fetch and configure dependencies -FetchContent_Declare( - raylib - URL https://github.com/raysan5/raylib/archive/c1ab645ca298a2801097931d1079b10ff7eb9df8.zip # 5.5 -) -set(BUILD_SHARED_LIBS OFF CACHE BOOL "Statically link raylib" FORCE) -set(WITH_PIC "Compile static library as position-independent code" ON) -set(CUSTOMIZE_BUILD ON CACHE BOOL "Customize raylib build settings" FORCE) -set(USE_AUDIO OFF CACHE BOOL "Don't build unused audio module" FORCE) -FetchContent_MakeAvailable(raylib) - -# if box2d is fetched first installing built python module will fail -# for reasons unbeknownst to mere mortals -# maybe due to install prefix schenanigans? -FetchContent_Declare( - box2d - URL https://github.com/capnspacehook/box2d/archive/df25d747be0ab2fd9425eece022d2ec897c2028d.zip -) -set(BOX2D_ENABLE_SIMD ON CACHE BOOL "Enable SIMD math (faster)" FORCE) -set(BOX2D_AVX2 ON CACHE BOOL "Enable AVX2 (faster)" FORCE) -add_compile_definitions(B2_MAX_WORLDS=65534) -FetchContent_MakeAvailable(box2d) -# this is set to off by box2d to enable cross platform determinism, but -# I don't care about that and want the small speedup instead -target_compile_options(box2d PRIVATE "-ffp-contract=fast") - -function(configure_target target_name) - target_include_directories( - ${target_name} PRIVATE - "${CMAKE_CURRENT_SOURCE_DIR}" - "${CMAKE_CURRENT_SOURCE_DIR}/include" - ) - - # Mark box2d as a system include directory to suppress warnings from it - target_include_directories(${target_name} SYSTEM PRIVATE "${box2d_SOURCE_DIR}/src") - - target_link_libraries(${target_name} PRIVATE raylib box2d) - - target_compile_options(${target_name} PRIVATE - "-Werror" "-Wall" "-Wextra" "-Wpedantic" - "-Wno-implicit-fallthrough" "-Wno-variadic-macros" "-Wno-strict-prototypes" "-Wno-gnu-statement-expression" - ) -endfunction() - -if(DEFINED BUILD_PYTHON_MODULE) - find_package( - Python - COMPONENTS Interpreter Development.Module NumPy - REQUIRED - ) - - python_add_library(binding MODULE binding.c WITH_SOABI) - - target_include_directories(binding PRIVATE - ${Python_NumPy_INCLUDE_DIRS} - ) - - configure_target(binding) - - install(TARGETS binding DESTINATION .) -elseif(DEFINED BUILD_DEMO) - add_executable(demo "${CMAKE_CURRENT_SOURCE_DIR}/impulse_wars.c") - configure_target(demo) -elseif(DEFINED BUILD_BENCHMARK) - add_executable(benchmark "${CMAKE_CURRENT_SOURCE_DIR}/benchmark.c") - configure_target(benchmark) -endif() diff --git a/pufferlib/ocean/impulse_wars/Makefile b/pufferlib/ocean/impulse_wars/Makefile deleted file mode 100644 index ce593669da..0000000000 --- a/pufferlib/ocean/impulse_wars/Makefile +++ /dev/null @@ -1,61 +0,0 @@ -RELEASE_PYTHON_MODULE_DIR := python-module-release -DEBUG_PYTHON_MODULE_DIR := python-module-debug -DEBUG_DIR := debug-demo -RELEASE_DIR := release-demo -RELEASE_WEB_DIR := release-demo-web -BENCHMARK_DIR := benchmark - -DEBUG_BUILD_TYPE := Debug -RELEASE_BUILD_TYPE := Release - -# install build dependencies if this is a fresh build, Python won't -# install build dependencies when --no-build-isolation is passed -# build with no isolation so that builds can be cached and/or incremental - -# build Python module in release mode -.PHONY: python-module-release -python-module-release: - @test -d $(RELEASE_PYTHON_MODULE_DIR) || pip install scikit-build-core autopxd2 cython - @pip install --no-build-isolation --config-settings=editable.rebuild=true -Cbuild-dir=$(RELEASE_PYTHON_MODULE_DIR) -v . - -# build Python module in debug mode -.PHONY: python-module-debug -python-module-debug: - @test -d $(DEBUG_PYTHON_MODULE_DIR) || pip install scikit-build-core autopxd2 cython - @pip install --no-build-isolation --config-settings=editable.rebuild=true --config-settings=cmake.build-type="Debug" -Cbuild-dir=$(DEBUG_PYTHON_MODULE_DIR) -v . - -# build C demo in debug mode -.PHONY: debug-demo -debug-demo: - @mkdir -p $(DEBUG_DIR) - @cd $(DEBUG_DIR) && \ - cmake -GNinja -DCMAKE_BUILD_TYPE=$(DEBUG_BUILD_TYPE) -DBUILD_DEMO=true -DCMAKE_C_COMPILER=clang-20 .. && \ - cmake --build . - -# build C demo in release mode -.PHONY: release-demo -release-demo: - @mkdir -p $(RELEASE_DIR) - @cd $(RELEASE_DIR) && \ - cmake -GNinja -DCMAKE_BUILD_TYPE=$(RELEASE_BUILD_TYPE) -DBUILD_DEMO=true -DCMAKE_C_COMPILER=clang-20 .. && \ - cmake --build . - -# build C demo in release mode for web -.PHONY: release-demo-web -release-demo-web: - @mkdir -p $(RELEASE_WEB_DIR) - @cd $(RELEASE_WEB_DIR) && \ - emcmake cmake -GNinja -DCMAKE_BUILD_TYPE=$(RELEASE_BUILD_TYPE) -DPLATFORM=Web -DBUILD_DEMO=true .. && \ - cmake --build . - -# build C benchmark -.PHONY: benchmark -benchmark: - @mkdir -p $(BENCHMARK_DIR) - @cd $(BENCHMARK_DIR) && \ - cmake -GNinja -DCMAKE_BUILD_TYPE=$(RELEASE_BUILD_TYPE) -DBUILD_BENCHMARK=true -DCMAKE_C_COMPILER=clang-20 .. && \ - cmake --build . - -.PHONY: clean -clean: - @rm -rf build $(RELEASE_PYTHON_MODULE_DIR) $(DEBUG_PYTHON_MODULE_DIR) $(DEBUG_DIR) $(RELEASE_DIR) $(RELEASE_WEB_DIR) $(BENCHMARK_DIR) diff --git a/pufferlib/ocean/impulse_wars/README.md b/pufferlib/ocean/impulse_wars/README.md deleted file mode 100644 index accca74381..0000000000 --- a/pufferlib/ocean/impulse_wars/README.md +++ /dev/null @@ -1,12 +0,0 @@ -# Impulse Wars - -To build, you need to have the following: -- cmake -- make -- ninja -- raylib required deps installed: https://github.com/raysan5/raylib/wiki/Working-on-GNU-Linux - -Run `make && cp python-module-release/binding.*.so .` to build the python module in release mode. -`puffer_impulse_wars` env should now be trainable. - -When watching evaluations, you need to set all instances of `is_training = False` and `render = True` in the config file. diff --git a/pufferlib/ocean/impulse_wars/impulse_wars.py b/pufferlib/ocean/impulse_wars/impulse_wars.py deleted file mode 100644 index 6fc2f5d27e..0000000000 --- a/pufferlib/ocean/impulse_wars/impulse_wars.py +++ /dev/null @@ -1,181 +0,0 @@ -from types import SimpleNamespace - -import gymnasium -import numpy as np - -import pufferlib -from pufferlib.ocean.impulse_wars import binding - - -discMoveToContMove = np.array([ - [1.0, 0.707107, 0.0, -0.707107, -1.0, -0.707107, 0.0, 0.707107, 0.0], - [0.0, 0.707107, 1.0, 0.707107, 0.0, -0.707107, -1.0, -0.707107, 0.0], -], dtype=np.float32) -discAimToContAim = np.array([ - [1.0, 0.92388, 0.707107, 0.382683, 0.0, -0.382683, -0.707107, -0.92388, -1.0, -0.92388, -0.707107, -0.382683, 0.0, 0.382683, 0.707107, 0.92388, 0.0], - [0.0, 0.382683, 0.707107, 0.92388, 1.0, 0.92388, 0.707107, 0.382683, 0.0, -0.382683, -0.707107, -0.92388, -1.0, -0.92388, -0.707107, -0.382683, 0.0], -], dtype=np.float32) - - -class ImpulseWars(pufferlib.PufferEnv): - def __init__( - self, - num_envs: int = 1, - num_drones: int = 2, - num_agents: int = 1, - enable_teams: bool = False, - sitting_duck: bool = False, - continuous: bool = False, - is_training: bool = True, - human_control: bool = False, - reward_win: float = 2.0, - reward_self_kill: float = -1.0, - reward_enemy_death: float = 1.0, - reward_enemy_kill: float = 1.0, - reward_death: float = -0.25, - reward_energy_emptied: float = -0.75, - reward_weapon_pickup: float = 0.5, - reward_shield_break: float = 0.5, - reward_shot_hit_coef: float = 0.005, - reward_explosion_hit_coef: float = 0.005, - seed: int = 0, - render: bool = False, - report_interval: int = 64, - buf = None, - ): - self.obsInfo = SimpleNamespace(**binding.get_consts(num_drones)) - - if num_envs <= 0: - raise ValueError("num_envs must be greater than 0") - if num_drones > self.obsInfo.maxDrones or num_drones <= 0: - raise ValueError(f"num_drones must greater than 0 and less than or equal to {self.obsInfo.maxDrones}") - if num_agents > num_drones or num_agents <= 0: - raise ValueError("num_agents must greater than 0 and less than or equal to num_drones") - if enable_teams and (num_drones % 2 != 0 or num_drones <= 2): - raise ValueError("enable_teams is only supported for even numbers of drones greater than 2") - - self.numDrones = num_drones - self.continuous = continuous - - self.num_agents = num_agents * num_envs - self.tick = 0 - - # map observations are bit packed to save space, and scalar - # observations need to be floats - self.single_observation_space = gymnasium.spaces.Box( - low=0, high=255, shape=(self.obsInfo.obsBytes,), dtype=np.uint8 - ) - - if self.continuous: - # action space is actually bounded by (-1, 1) but pufferlib - # will check that actions are within the bounds of the action - # space before actions get to the env, and we ensure the actions - # are bounded there; so set bounds to (-inf, inf) here so - # action bounds checks pass - self.single_action_space = gymnasium.spaces.Box( - low=float("-inf"), high=float("inf"), shape=(self.obsInfo.contActionsSize,), dtype=np.float32 - ) - else: - self.single_action_space = gymnasium.spaces.MultiDiscrete( - [ - 9, # move, noop + 8 directions - 17, # aim, noop + 16 directions - 2, # shoot or not - 2, # brake or not - 2, # burst - ] - ) - - self.report_interval = report_interval - self.render_mode = "human" if render else None - - super().__init__(buf) - if not self.continuous: - self.actions = np.zeros((self.num_agents, self.obsInfo.contActionsSize), dtype=np.float32) - - self.c_envs = binding.vec_init( - self.observations, - self.actions, - self.rewards, - self.terminals, - self.truncations, - num_envs, - seed, - num_drones=num_drones, - num_agents=num_agents, - map_idx=-1, - enable_teams=enable_teams, - sitting_duck=sitting_duck, - is_training=is_training, - continuous=continuous, - reward_win=reward_win, - reward_self_kill=reward_self_kill, - reward_enemy_death=reward_enemy_death, - reward_enemy_kill=reward_enemy_kill, - reward_death=reward_death, - reward_energy_emptied=reward_energy_emptied, - reward_weapon_pickup=reward_weapon_pickup, - reward_shield_break=reward_shield_break, - reward_shot_hit_coef=reward_shot_hit_coef, - reward_explosion_hit_coef=reward_explosion_hit_coef, - ) - - binding.shared(self.c_envs) - - def reset(self, seed=None): - self.tick = 0 - if seed is None: - binding.vec_reset(self.c_envs, 0) - else: - binding.vec_reset(self.c_envs, seed) - return self.observations, [] - - def step(self, actions): - if self.continuous: - self.actions[:] = actions - else: - contMove = discMoveToContMove[:, actions[:, 0]].T - contAim = discAimToContAim[:, actions[:, 1]].T - contRest = actions[:, 2:].astype(np.float32) - self.actions[:] = np.concatenate([contMove, contAim, contRest], axis=1) - - self.tick += 1 - binding.vec_step(self.c_envs) - - infos = [] - if self.tick % self.report_interval == 0: - infos.append(binding.vec_log(self.c_envs)) - - return self.observations, self.rewards, self.terminals, self.truncations, infos - - def render(self): - binding.vec_render(self.c_envs, 0) - - def close(self): - binding.vec_close(self.c_envs) - - -def testPerf(timeout, actionCache, numEnvs): - env = ImpulseWars(numEnvs) - - import time - - np.random.seed(int(time.time())) - actions = np.random.uniform(-1, 1, (actionCache, env.num_agents, 7)) - - tick = 0 - start = time.time() - while time.time() - start < timeout: - action = actions[tick % actionCache] - env.step(action) - tick += 1 - - sps = numEnvs * (tick / (time.time() - start)) - print(f"SPS: {sps:,}") - print(f"Steps: {numEnvs * tick}") - - env.close() - - -if __name__ == "__main__": - testPerf(timeout=5, actionCache=1024, numEnvs=1) diff --git a/pufferlib/ocean/impulse_wars/include/cc_array.h b/pufferlib/ocean/impulse_wars/include/cc_array.h deleted file mode 100644 index 311f99122b..0000000000 --- a/pufferlib/ocean/impulse_wars/include/cc_array.h +++ /dev/null @@ -1,1410 +0,0 @@ -/* - * Collections-C - * Copyright (C) 2013-2015 Srđan Panić - * - * This file is part of Collections-C. - * - * Collections-C is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Collections-C is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Collections-C. If not, see . - */ - -#ifndef CC_ARRAY_H -#define CC_ARRAY_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include "cc_common.h" - -/** - * A dynamic array that expands automatically as elements are - * added. The array supports amortized constant time insertion - * and removal of elements at the end of the array, as well as - * constant time access. - */ -typedef struct cc_array_s CC_Array; - -/** - * Array configuration structure. Used to initialize a new Array - * with specific values. - */ -typedef struct cc_array_conf_s { - /** - * The initial capacity of the array */ - size_t capacity; - - /** - * The rate at which the buffer expands (capacity * exp_factor). */ - float exp_factor; - - /** - * Memory allocators used to allocate the Array structure and the - * underlying data buffers. */ - void *(*mem_alloc)(size_t size); - void *(*mem_calloc)(size_t blocks, size_t size); - void (*mem_free)(void *block); -} CC_ArrayConf; - -/** - * Array iterator structure. Used to iterate over the elements of - * the array in an ascending order. The iterator also supports - * operations for safely adding and removing elements during - * iteration. - */ -typedef struct cc_array_iter_s { - /** - * The array associated with this iterator */ - CC_Array *ar; - - /** - * The current position of the iterator.*/ - size_t index; - - /** - * Set to true if the last returned element was removed. */ - bool last_removed; -} CC_ArrayIter; - -/** - * Array zip iterator structure. Used to iterate over the elements of two - * arrays in lockstep in an ascending order until one of the Arrays is - * exhausted. The iterator also supports operations for safely adding - * and removing elements during iteration. - */ -typedef struct array_zip_iter_s { - CC_Array *ar1; - CC_Array *ar2; - size_t index; - bool last_removed; -} CC_ArrayZipIter; - -enum cc_stat cc_array_new(CC_Array **out); -enum cc_stat cc_array_new_conf(CC_ArrayConf const *const conf, CC_Array **out); -void cc_array_conf_init(CC_ArrayConf *conf); -size_t cc_array_struct_size(); - -void cc_array_destroy(CC_Array *ar); -void cc_array_destroy_cb(CC_Array *ar, void (*cb)(void *)); - -enum cc_stat cc_array_add(CC_Array *ar, void *element); -enum cc_stat cc_array_add_at(CC_Array *ar, void *element, size_t index); -enum cc_stat cc_array_replace_at(CC_Array *ar, void *element, size_t index, void **out); -enum cc_stat cc_array_swap_at(CC_Array *ar, size_t index1, size_t index2); - -enum cc_stat cc_array_remove(CC_Array *ar, void *element, void **out); -enum cc_stat cc_array_remove_fast(CC_Array *ar, void *element, void **out); -enum cc_stat cc_array_remove_at(CC_Array *ar, size_t index, void **out); -enum cc_stat cc_array_remove_fast_at(CC_Array *ar, size_t index, void **out); -enum cc_stat cc_array_remove_last(CC_Array *ar, void **out); -void cc_array_remove_all(CC_Array *ar); -void cc_array_remove_all_free(CC_Array *ar); - -enum cc_stat cc_array_get_at(const CC_Array *ar, size_t index, void **out); -enum cc_stat cc_array_get_last(const CC_Array *ar, void **out); - -enum cc_stat cc_array_subarray(CC_Array *ar, size_t from, size_t to, CC_Array **out); -enum cc_stat cc_array_copy_shallow(CC_Array *ar, CC_Array **out); -enum cc_stat cc_array_copy_deep(CC_Array *ar, void *(*cp)(void *), CC_Array **out); - -void cc_array_reverse(CC_Array *ar); -enum cc_stat cc_array_trim_capacity(CC_Array *ar); - -size_t cc_array_contains(const CC_Array *ar, void *element); -size_t cc_array_contains_value(const CC_Array *ar, void *element, int (*cmp)(const void *, const void *)); -size_t cc_array_size(const CC_Array *ar); -size_t cc_array_capacity(const CC_Array *ar); - -enum cc_stat cc_array_index_of(const CC_Array *ar, void *element, size_t *index); -void cc_array_sort(CC_Array *ar, int (*cmp)(const void *, const void *)); - -void cc_array_map(CC_Array *ar, void (*fn)(void *)); -void cc_array_reduce(CC_Array *ar, void (*fn)(void *, void *, void *), void *result); - -enum cc_stat cc_array_filter_mut(CC_Array *ar, bool (*predicate)(const void *)); -enum cc_stat cc_array_filter(CC_Array *ar, bool (*predicate)(const void *), CC_Array **out); - -void cc_array_iter_init(CC_ArrayIter *iter, CC_Array *ar); -enum cc_stat cc_array_iter_next(CC_ArrayIter *iter, void **out); -enum cc_stat cc_array_iter_remove(CC_ArrayIter *iter, void **out); -enum cc_stat cc_array_iter_remove_fast(CC_ArrayIter *iter, void **out); -enum cc_stat cc_array_iter_add(CC_ArrayIter *iter, void *element); -enum cc_stat cc_array_iter_replace(CC_ArrayIter *iter, void *element, void **out); -size_t cc_array_iter_index(CC_ArrayIter *iter); - -void cc_array_zip_iter_init(CC_ArrayZipIter *iter, CC_Array *a1, CC_Array *a2); -enum cc_stat cc_array_zip_iter_next(CC_ArrayZipIter *iter, void **out1, void **out2); -enum cc_stat cc_array_zip_iter_add(CC_ArrayZipIter *iter, void *e1, void *e2); -enum cc_stat cc_array_zip_iter_remove(CC_ArrayZipIter *iter, void **out1, void **out2); -enum cc_stat cc_array_zip_iter_replace(CC_ArrayZipIter *iter, void *e1, void *e2, void **out1, void **out2); -size_t cc_array_zip_iter_index(CC_ArrayZipIter *iter); - -const void *const *cc_array_get_buffer(CC_Array *ar); - -#define CC_ARRAY_FOREACH(val, array, body) \ - { \ - CC_ArrayIter cc_array_iter_53d46d2a04458e7b; \ - cc_array_iter_init(&cc_array_iter_53d46d2a04458e7b, array); \ - void *val; \ - while (cc_array_iter_next(&cc_array_iter_53d46d2a04458e7b, &val) != CC_ITER_END) \ - body \ - } - -#define CC_ARRAY_FOREACH_ZIP(val1, val2, array1, array2, body) \ - { \ - CC_ArrayZipIter cc_array_zip_iter_ea08d3e52f25883b3; \ - cc_array_zip_iter_init(&cc_array_zip_iter_ea08d3e52f25883b3, array1, array2); \ - void *val1; \ - void *val2; \ - while (cc_array_zip_iter_next(&cc_array_zip_iter_ea08d3e52f25883b3, &val1, &val2) != CC_ITER_END) \ - body \ - } - -#define DEFAULT_CAPACITY 8 -#define DEFAULT_EXPANSION_FACTOR 2 - -struct cc_array_s { - size_t size; - size_t capacity; - float exp_factor; - void **buffer; - - void *(*mem_alloc)(size_t size); - void *(*mem_calloc)(size_t blocks, size_t size); - void (*mem_free)(void *block); -}; - -static enum cc_stat expand_array_capacity(CC_Array *ar); - -/** - * Creates a new empty array and returns a status code. - * - * @param[out] out pointer to where the newly created CC_Array is to be stored - * - * @return CC_OK if the creation was successful, or CC_ERR_ALLOC if the - * memory allocation for the new CC_Array structure failed. - */ -enum cc_stat cc_array_new(CC_Array **out) { - CC_ArrayConf c; - cc_array_conf_init(&c); - return cc_array_new_conf(&c, out); -} - -/** - * Creates a new empty CC_Array based on the specified CC_ArrayConf struct and - * returns a status code. - * - * The CC_Array is allocated using the allocators specified in the CC_ArrayConf - * struct. The allocation may fail if underlying allocator fails. It may also - * fail if the values of exp_factor and capacity in the CC_ArrayConf do not meet - * the following condition: exp_factor < (CC_MAX_ELEMENTS / capacity). - * - * @param[in] conf array configuration structure - * @param[out] out pointer to where the newly created CC_Array is to be stored - * - * @return CC_OK if the creation was successful, CC_ERR_INVALID_CAPACITY if - * the above mentioned condition is not met, or CC_ERR_ALLOC if the memory - * allocation for the new CC_Array structure failed. - */ -enum cc_stat cc_array_new_conf(CC_ArrayConf const *const conf, CC_Array **out) { - float ex; - - /* The expansion factor must be greater than one for the - * array to grow */ - if (conf->exp_factor <= 1) { - ex = DEFAULT_EXPANSION_FACTOR; - } else { - ex = conf->exp_factor; - } - - /* Needed to avoid an integer overflow on the first resize and - * to easily check for any future overflows. */ - if (!conf->capacity || ex >= CC_MAX_ELEMENTS / conf->capacity) { - return CC_ERR_INVALID_CAPACITY; - } - - CC_Array *ar = (CC_Array *)conf->mem_calloc(1, sizeof(CC_Array)); - - if (!ar) { - return CC_ERR_ALLOC; - } - - void **buff = (void **)conf->mem_alloc(conf->capacity * sizeof(void *)); - - if (!buff) { - conf->mem_free(ar); - return CC_ERR_ALLOC; - } - - ar->buffer = buff; - ar->exp_factor = ex; - ar->capacity = conf->capacity; - ar->mem_alloc = conf->mem_alloc; - ar->mem_calloc = conf->mem_calloc; - ar->mem_free = conf->mem_free; - - *out = ar; - return CC_OK; -} - -/** - * Initializes the fields of the CC_ArrayConf struct to default values. - * - * @param[in, out] conf CC_ArrayConf structure that is being initialized - */ -void cc_array_conf_init(CC_ArrayConf *conf) { - conf->exp_factor = DEFAULT_EXPANSION_FACTOR; - conf->capacity = DEFAULT_CAPACITY; - conf->mem_alloc = malloc; - conf->mem_calloc = calloc; - conf->mem_free = free; -} - -/** - * Destroys the CC_Array structure, but leaves the data it used to hold intact. - * - * @param[in] ar the array that is to be destroyed - */ -void cc_array_destroy(CC_Array *ar) { - ar->mem_free(ar->buffer); - ar->mem_free(ar); -} - -/** - * Destroys the CC_Array structure along with all the data it holds. - * - * @note - * This function should not be called on a array that has some of its elements - * allocated on the stack. - * - * @param[in] ar the array that is being destroyed - */ -void cc_array_destroy_cb(CC_Array *ar, void (*cb)(void *)) { - size_t i; - for (i = 0; i < ar->size; i++) { - cb(ar->buffer[i]); - } - - cc_array_destroy(ar); -} - -/** - * Adds a new element to the CC_Array. The element is appended to the array making - * it the last element (the one with the highest index) of the CC_Array. - * - * @param[in] ar the array to which the element is being added - * @param[in] element the element that is being added - * - * @return CC_OK if the element was successfully added, CC_ERR_ALLOC if the - * memory allocation for the new element failed, or CC_ERR_MAX_CAPACITY if the - * array is already at maximum capacity. - */ -enum cc_stat cc_array_add(CC_Array *ar, void *element) { - if (ar->size >= ar->capacity) { - enum cc_stat status = expand_array_capacity(ar); - if (status != CC_OK) { - return status; - } - } - - ar->buffer[ar->size] = element; - ar->size++; - - return CC_OK; -} - -/** - * Adds a new element to the array at a specified position by shifting all - * subsequent elements by one. The specified index must be within the bounds - * of the array. This function may also fail if the memory allocation for - * the new element was unsuccessful. - * - * @param[in] ar the array to which the element is being added - * @param[in] element the element that is being added - * @param[in] index the position in the array at which the element is being - * added - * - * @return CC_OK if the element was successfully added, CC_ERR_OUT_OF_RANGE if - * the specified index was not in range, CC_ERR_ALLOC if the memory - * allocation for the new element failed, or CC_ERR_MAX_CAPACITY if the - * array is already at maximum capacity. - */ -enum cc_stat cc_array_add_at(CC_Array *ar, void *element, size_t index) { - if (index == ar->size) { - return cc_array_add(ar, element); - } - - if ((ar->size == 0 && index != 0) || index > (ar->size - 1)) { - return CC_ERR_OUT_OF_RANGE; - } - - if (ar->size >= ar->capacity) { - enum cc_stat status = expand_array_capacity(ar); - if (status != CC_OK) { - return status; - } - } - - size_t shift = (ar->size - index) * sizeof(void *); - - memmove(&(ar->buffer[index + 1]), - &(ar->buffer[index]), - shift); - - ar->buffer[index] = element; - ar->size++; - - return CC_OK; -} - -/** - * Replaces an array element at the specified index and optionally sets the out - * parameter to the value of the replaced element. The specified index must be - * within the bounds of the CC_Array. - * - * @param[in] ar array whose element is being replaced - * @param[in] element replacement element - * @param[in] index index at which the replacement element should be inserted - * @param[out] out pointer to where the replaced element is stored, or NULL if - * it is to be ignored - * - * @return CC_OK if the element was successfully replaced, or CC_ERR_OUT_OF_RANGE - * if the index was out of range. - */ -enum cc_stat cc_array_replace_at(CC_Array *ar, void *element, size_t index, void **out) { - if (index >= ar->size) { - return CC_ERR_OUT_OF_RANGE; - } - - if (out) { - *out = ar->buffer[index]; - } - - ar->buffer[index] = element; - - return CC_OK; -} - -enum cc_stat cc_array_swap_at(CC_Array *ar, size_t index1, size_t index2) { - void *tmp; - - if (index1 >= ar->size || index2 >= ar->size) { - return CC_ERR_OUT_OF_RANGE; - } - - tmp = ar->buffer[index1]; - - ar->buffer[index1] = ar->buffer[index2]; - ar->buffer[index2] = tmp; - return CC_OK; -} - -/** - * Removes the specified element from the CC_Array if such element exists and - * optionally sets the out parameter to the value of the removed element. - * - * @param[in] ar array from which the element is being removed - * @param[in] element element being removed - * @param[out] out pointer to where the removed value is stored, or NULL - * if it is to be ignored - * - * @return CC_OK if the element was successfully removed, or - * CC_ERR_VALUE_NOT_FOUND if the element was not found. - */ -enum cc_stat cc_array_remove(CC_Array *ar, void *element, void **out) { - size_t index; - enum cc_stat status = cc_array_index_of(ar, element, &index); - - if (status == CC_ERR_OUT_OF_RANGE) { - return CC_ERR_VALUE_NOT_FOUND; - } - - if (index != ar->size - 1) { - size_t block_size = (ar->size - 1 - index) * sizeof(void *); - - memmove(&(ar->buffer[index]), - &(ar->buffer[index + 1]), - block_size); - } - ar->size--; - - if (out) { - *out = element; - } - - return CC_OK; -} - -/** - * Removes a CC_Array element without preserving order and optionally sets the - * out parameter to the value of the removed element. The last element of the - * array is moved to the index of the element being removed, and the last - * element is removed. - * - * @param[in] ar the array whose last element is being removed - * @param[out] out pointer to where the removed value is stored, or NULL if it is - * to be ignored - * - * @return CC_OK if the element was successfully removed, or CC_ERR_OUT_OF_RANGE - * if the CC_Array is already empty. - */ -enum cc_stat cc_array_remove_fast(CC_Array *ar, void *element, void **out) { - size_t index = 0; - const enum cc_stat status = cc_array_index_of(ar, element, &index); - if (status != CC_OK) { - return status; - } - - if (out) { - *out = ar->buffer[index]; - } - - ar->buffer[index] = ar->buffer[ar->size - 1]; - ar->size--; - - return CC_OK; -} - -/** - * Removes an CC_Array element from the specified index and optionally sets the - * out parameter to the value of the removed element. The index must be within - * the bounds of the array. - * - * @param[in] ar the array from which the element is being removed - * @param[in] index the index of the element being removed. - * @param[out] out pointer to where the removed value is stored, - * or NULL if it is to be ignored - * - * @return CC_OK if the element was successfully removed, or CC_ERR_OUT_OF_RANGE - * if the index was out of range. - */ -enum cc_stat cc_array_remove_at(CC_Array *ar, size_t index, void **out) { - if (index >= ar->size) { - return CC_ERR_OUT_OF_RANGE; - } - - if (out) { - *out = ar->buffer[index]; - } - - if (index != ar->size - 1) { - size_t block_size = (ar->size - 1 - index) * sizeof(void *); - - memmove(&(ar->buffer[index]), - &(ar->buffer[index + 1]), - block_size); - } - ar->size--; - - return CC_OK; -} - -/** - * Removes a CC_Array element from the specified index and optionally sets the - * out parameter to the value of the removed element without preserving ordering. - * The last element of the array is moved to the index of the element being removed, - * and the last element is removed. The index must be within the bounds of the array. - * - * @param[in] ar the array from which the element is being removed - * @param[in] index the index of the element being removed. - * @param[out] out pointer to where the removed value is stored, - * or NULL if it is to be ignored - * - * @return CC_OK if the element was successfully removed, or CC_ERR_OUT_OF_RANGE - * if the index was out of range. - */ -enum cc_stat cc_array_remove_fast_at(CC_Array *ar, size_t index, void **out) { - if (index >= ar->size) { - return CC_ERR_OUT_OF_RANGE; - } - - if (out) { - *out = ar->buffer[index]; - } - - ar->buffer[index] = ar->buffer[ar->size - 1]; - ar->size--; - - return CC_OK; -} - -/** - * Removes an CC_Array element from the end of the array and optionally sets the - * out parameter to the value of the removed element. - * - * @param[in] ar the array whose last element is being removed - * @param[out] out pointer to where the removed value is stored, or NULL if it is - * to be ignored - * - * @return CC_OK if the element was successfully removed, or CC_ERR_OUT_OF_RANGE - * if the CC_Array is already empty. - */ -enum cc_stat cc_array_remove_last(CC_Array *ar, void **out) { - return cc_array_remove_at(ar, ar->size - 1, out); -} - -/** - * Removes all elements from the specified array. This function does not shrink - * the array capacity. - * - * @param[in] ar array from which all elements are to be removed - */ -void cc_array_remove_all(CC_Array *ar) { - ar->size = 0; -} - -/** - * Removes and frees all elements from the specified array. This function does - * not shrink the array capacity. - * - * @param[in] ar array from which all elements are to be removed - */ -void cc_array_remove_all_free(CC_Array *ar) { - size_t i; - for (i = 0; i < ar->size; i++) { - free(ar->buffer[i]); - } - - cc_array_remove_all(ar); -} - -/** - * Gets an CC_Array element from the specified index and sets the out parameter to - * its value. The specified index must be within the bounds of the array. - * - * @param[in] ar the array from which the element is being retrieved - * @param[in] index the index of the array element - * @param[out] out pointer to where the element is stored - * - * @return CC_OK if the element was found, or CC_ERR_OUT_OF_RANGE if the index - * was out of range. - */ -enum cc_stat cc_array_get_at(const CC_Array *ar, size_t index, void **out) { - if (index >= ar->size) { - return CC_ERR_OUT_OF_RANGE; - } - - *out = ar->buffer[index]; - return CC_OK; -} - -/** - * Gets the last element of the array or the element at the highest index - * and sets the out parameter to its value. - * - * @param[in] ar the array whose last element is being returned - * @param[out] out pointer to where the element is stored - * - * @return CC_OK if the element was found, or CC_ERR_VALUE_NOT_FOUND if the - * CC_Array is empty. - */ -enum cc_stat cc_array_get_last(const CC_Array *ar, void **out) { - if (ar->size == 0) { - return CC_ERR_VALUE_NOT_FOUND; - } - - return cc_array_get_at(ar, ar->size - 1, out); -} - -/** - * Returns the underlying array buffer. - * - * @note Any direct modification of the buffer may invalidate the CC_Array. - * - * @param[in] ar array whose underlying buffer is being returned - * - * @return array's internal buffer. - */ -const void *const *cc_array_get_buffer(CC_Array *ar) { - return (const void *const *)ar->buffer; -} - -/** - * Gets the index of the specified element. The returned index is the index - * of the first occurrence of the element starting from the beginning of the - * CC_Array. - * - * @param[in] ar array being searched - * @param[in] element the element whose index is being looked up - * @param[out] index pointer to where the index is stored - * - * @return CC_OK if the index was found, or CC_OUT_OF_RANGE if not. - */ -enum cc_stat cc_array_index_of(const CC_Array *ar, void *element, size_t *index) { - size_t i; - for (i = 0; i < ar->size; i++) { - if (ar->buffer[i] == element) { - *index = i; - return CC_OK; - } - } - return CC_ERR_OUT_OF_RANGE; -} - -/** - * Creates a subarray of the specified CC_Array, ranging from b - * index (inclusive) to e index (inclusive). The range indices - * must be within the bounds of the CC_Array, while the e index - * must be greater or equal to the b index. - * - * @note The new CC_Array is allocated using the original CC_Array's allocators - * and it also inherits the configuration of the original CC_Array. - * - * @param[in] ar array from which the subarray is being created - * @param[in] b the beginning index (inclusive) of the subarray that must be - * within the bounds of the array and must not exceed the - * the end index - * @param[in] e the end index (inclusive) of the subarray that must be within - * the bounds of the array and must be greater or equal to the - * beginning index - * @param[out] out pointer to where the new sublist is stored - * - * @return CC_OK if the subarray was successfully created, CC_ERR_INVALID_RANGE - * if the specified index range is invalid, or CC_ERR_ALLOC if the memory allocation - * for the new subarray failed. - */ -enum cc_stat cc_array_subarray(CC_Array *ar, size_t b, size_t e, CC_Array **out) { - if (b > e || e >= ar->size) { - return CC_ERR_INVALID_RANGE; - } - - CC_Array *sub_ar = (CC_Array *)ar->mem_calloc(1, sizeof(CC_Array)); - - if (!sub_ar) { - return CC_ERR_ALLOC; - } - - /* Try to allocate the buffer */ - if (!(sub_ar->buffer = (void **)ar->mem_alloc(ar->capacity * sizeof(void *)))) { - ar->mem_free(sub_ar); - return CC_ERR_ALLOC; - } - - sub_ar->mem_alloc = ar->mem_alloc; - sub_ar->mem_calloc = ar->mem_calloc; - sub_ar->mem_free = ar->mem_free; - sub_ar->size = e - b + 1; - sub_ar->capacity = sub_ar->size; - - memcpy(sub_ar->buffer, - &(ar->buffer[b]), - sub_ar->size * sizeof(void *)); - - *out = sub_ar; - return CC_OK; -} - -/** - * Creates a shallow copy of the specified CC_Array. A shallow copy is a copy of - * the CC_Array structure, but not the elements it holds. - * - * @note The new CC_Array is allocated using the original CC_Array's allocators - * and it also inherits the configuration of the original array. - * - * @param[in] ar the array to be copied - * @param[out] out pointer to where the newly created copy is stored - * - * @return CC_OK if the copy was successfully created, or CC_ERR_ALLOC if the - * memory allocation for the copy failed. - */ -enum cc_stat cc_array_copy_shallow(CC_Array *ar, CC_Array **out) { - CC_Array *copy = (CC_Array *)ar->mem_alloc(sizeof(CC_Array)); - - if (!copy) { - return CC_ERR_ALLOC; - } - - if (!(copy->buffer = (void **)ar->mem_calloc(ar->capacity, sizeof(void *)))) { - ar->mem_free(copy); - return CC_ERR_ALLOC; - } - copy->exp_factor = ar->exp_factor; - copy->size = ar->size; - copy->capacity = ar->capacity; - copy->mem_alloc = ar->mem_alloc; - copy->mem_calloc = ar->mem_calloc; - copy->mem_free = ar->mem_free; - - memcpy(copy->buffer, - ar->buffer, - copy->size * sizeof(void *)); - - *out = copy; - return CC_OK; -} - -/** - * Creates a deep copy of the specified CC_Array. A deep copy is a copy of - * both the CC_Array structure and the data it holds. - * - * @note The new CC_Array is allocated using the original CC_Array's allocators - * and it also inherits the configuration of the original CC_Array. - * - * @param[in] ar array to be copied - * @param[in] cp the copy function that should return a pointer to the copy of - * the data - * @param[out] out pointer to where the newly created copy is stored - * - * @return CC_OK if the copy was successfully created, or CC_ERR_ALLOC if the - * memory allocation for the copy failed. - */ -enum cc_stat cc_array_copy_deep(CC_Array *ar, void *(*cp)(void *), CC_Array **out) { - CC_Array *copy = (CC_Array *)ar->mem_alloc(sizeof(CC_Array)); - - if (!copy) { - return CC_ERR_ALLOC; - } - - if (!(copy->buffer = (void **)ar->mem_calloc(ar->capacity, sizeof(void *)))) { - ar->mem_free(copy); - return CC_ERR_ALLOC; - } - - copy->exp_factor = ar->exp_factor; - copy->size = ar->size; - copy->capacity = ar->capacity; - copy->mem_alloc = ar->mem_alloc; - copy->mem_calloc = ar->mem_calloc; - copy->mem_free = ar->mem_free; - - size_t i; - for (i = 0; i < copy->size; i++) { - copy->buffer[i] = cp(ar->buffer[i]); - } - - *out = copy; - - return CC_OK; -} - -/** - * Filters the CC_Array by modifying it. It removes all elements that don't - * return true on pred(element). - * - * @param[in] ar array that is to be filtered - * @param[in] pred predicate function which returns true if the element should - * be kept in the CC_Array - * - * @return CC_OK if the CC_Array was filtered successfully, or CC_ERR_OUT_OF_RANGE - * if the CC_Array is empty. - */ -enum cc_stat cc_array_filter_mut(CC_Array *ar, bool (*pred)(const void *)) { - if (ar->size == 0) { - return CC_ERR_OUT_OF_RANGE; - } - - size_t rm = 0; - size_t keep = 0; - - /* Look for clusters of non matching elements before moving - * in order to minimize the number of memmoves */ - for (size_t i = ar->size - 1; i != ((size_t)-1); i--) { - if (!pred(ar->buffer[i])) { - rm++; - continue; - } - if (rm > 0) { - if (keep > 0) { - size_t block_size = keep * sizeof(void *); - memmove(&(ar->buffer[i + 1]), - &(ar->buffer[i + 1 + rm]), - block_size); - } - ar->size -= rm; - rm = 0; - } - keep++; - } - /* Remove any remaining elements*/ - if (rm > 0) { - size_t block_size = keep * sizeof(void *); - memmove(&(ar->buffer[0]), - &(ar->buffer[rm]), - block_size); - - ar->size -= rm; - } - return CC_OK; -} - -/** - * Filters the CC_Array by creating a new CC_Array that contains all elements from the - * original CC_Array that return true on pred(element) without modifying the original - * CC_Array. - * - * @param[in] ar array that is to be filtered - * @param[in] pred predicate function which returns true if the element should - * be kept in the filtered array - * @param[out] out pointer to where the new filtered CC_Array is to be stored - * - * @return CC_OK if the CC_Array was filtered successfully, CC_ERR_OUT_OF_RANGE - * if the CC_Array is empty, or CC_ERR_ALLOC if the memory allocation for the - * new CC_Array failed. - */ -enum cc_stat cc_array_filter(CC_Array *ar, bool (*pred)(const void *), CC_Array **out) { - if (ar->size == 0) { - return CC_ERR_OUT_OF_RANGE; - } - - CC_Array *filtered = (CC_Array *)ar->mem_alloc(sizeof(CC_Array)); - - if (!filtered) { - return CC_ERR_ALLOC; - } - - if (!(filtered->buffer = (void **)ar->mem_calloc(ar->capacity, sizeof(void *)))) { - ar->mem_free(filtered); - return CC_ERR_ALLOC; - } - - filtered->exp_factor = ar->exp_factor; - filtered->size = 0; - filtered->capacity = ar->capacity; - filtered->mem_alloc = ar->mem_alloc; - filtered->mem_calloc = ar->mem_calloc; - filtered->mem_free = ar->mem_free; - - size_t f = 0; - for (size_t i = 0; i < ar->size; i++) { - if (pred(ar->buffer[i])) { - filtered->buffer[f++] = ar->buffer[i]; - filtered->size++; - } - } - *out = filtered; - - return CC_OK; -} - -/** - * Reverses the order of elements in the specified array. - * - * @param[in] ar array that is being reversed - */ -void cc_array_reverse(CC_Array *ar) { - if (ar->size == 0) { - return; - } - - size_t i; - size_t j; - for (i = 0, j = ar->size - 1; i < ar->size / 2; i++, j--) { - void *tmp = ar->buffer[i]; - ar->buffer[i] = ar->buffer[j]; - ar->buffer[j] = tmp; - } -} - -/** - * Trims the array's capacity, in other words, it shrinks the capacity to match - * the number of elements in the CC_Array, however the capacity will never shrink - * below 1. - * - * @param[in] ar array whose capacity is being trimmed - * - * @return CC_OK if the capacity was trimmed successfully, or CC_ERR_ALLOC if - * the reallocation failed. - */ -enum cc_stat cc_array_trim_capacity(CC_Array *ar) { - if (ar->size == ar->capacity) { - return CC_OK; - } - - void **new_buff = (void **)ar->mem_calloc(ar->size, sizeof(void *)); - - if (!new_buff) { - return CC_ERR_ALLOC; - } - - size_t size = ar->size < 1 ? 1 : ar->size; - - memcpy(new_buff, ar->buffer, size * sizeof(void *)); - ar->mem_free(ar->buffer); - - ar->buffer = new_buff; - ar->capacity = ar->size; - - return CC_OK; -} - -/** - * Returns the number of occurrences of the element within the specified CC_Array. - * - * @param[in] ar array that is being searched - * @param[in] element the element that is being searched for - * - * @return the number of occurrences of the element. - */ -size_t cc_array_contains(const CC_Array *ar, void *element) { - size_t o = 0; - size_t i; - for (i = 0; i < ar->size; i++) { - if (ar->buffer[i] == element) { - o++; - } - } - return o; -} - -/** - * Returns the number of occurrences of the value pointed to by e - * within the specified CC_Array. - * - * @param[in] ar array that is being searched - * @param[in] element the element that is being searched for - * @param[in] cmp comparator function which returns 0 if the values passed to it are equal - * - * @return the number of occurrences of the value. - */ -size_t cc_array_contains_value(const CC_Array *ar, void *element, int (*cmp)(const void *, const void *)) { - size_t o = 0; - size_t i; - for (i = 0; i < ar->size; i++) { - if (cmp(element, ar->buffer[i]) == 0) { - o++; - } - } - return o; -} - -/** - * Returns the size of the specified CC_Array. The size of the array is the - * number of elements contained within the CC_Array. - * - * @param[in] ar array whose size is being returned - * - * @return the the number of element within the CC_Array. - */ -size_t cc_array_size(const CC_Array *ar) { - return ar->size; -} - -/** - * Returns the capacity of the specified CC_Array. The capacity of the CC_Array is - * the maximum number of elements an CC_Array can hold before it has to be resized. - * - * @param[in] ar array whose capacity is being returned - * - * @return the capacity of the CC_Array. - */ -size_t cc_array_capacity(const CC_Array *ar) { - return ar->capacity; -} - -/** - * Sorts the specified array. - * - * @note - * Pointers passed to the comparator function will be pointers to the array - * elements that are of type (void*) ie. void**. So an extra step of - * dereferencing will be required before the data can be used for comparison: - * eg. my_type e = *(*((my_type**) ptr));. - * - * @code - * enum cc_stat mycmp(const void *e1, const void *e2) { - * MyType el1 = *(*((enum cc_stat**) e1)); - * MyType el2 = *(*((enum cc_stat**) e2)); - * - * if (el1 < el2) return -1; - * if (el1 > el2) return 1; - * return 0; - * } - * - * ... - * - * cc_array_sort(array, mycmp); - * @endcode - * - * @param[in] ar array to be sorted - * @param[in] cmp the comparator function that must be of type - * enum cc_stat cmp(const void e1*, const void e2*) that - * returns < 0 if the first element goes before the second, - * 0 if the elements are equal and > 0 if the second goes - * before the first - */ -void cc_array_sort(CC_Array *ar, int (*cmp)(const void *, const void *)) { - qsort(ar->buffer, ar->size, sizeof(void *), cmp); -} - -/** - * Expands the CC_Array capacity. This might fail if the the new buffer - * cannot be allocated. In case the expansion would overflow the index - * range, a maximum capacity buffer is allocated instead. If the capacity - * is already at the maximum capacity, no new buffer is allocated. - * - * @param[in] ar array whose capacity is being expanded - * - * @return CC_OK if the buffer was expanded successfully, CC_ERR_ALLOC if - * the memory allocation for the new buffer failed, or CC_ERR_MAX_CAPACITY - * if the array is already at maximum capacity. - */ -static enum cc_stat expand_array_capacity(CC_Array *ar) { - if (ar->capacity == CC_MAX_ELEMENTS) { - return CC_ERR_MAX_CAPACITY; - } - - size_t new_capacity = (size_t)(ar->capacity * ar->exp_factor); - - /* As long as the capacity is greater that the expansion factor - * at the point of overflow, this is check is valid. */ - if (new_capacity <= ar->capacity) { - ar->capacity = CC_MAX_ELEMENTS; - } else { - ar->capacity = new_capacity; - } - - void **new_buff = (void **)ar->mem_alloc(ar->capacity * sizeof(void *)); - - if (!new_buff) { - return CC_ERR_ALLOC; - } - - memcpy(new_buff, ar->buffer, ar->size * sizeof(void *)); - - ar->mem_free(ar->buffer); - ar->buffer = new_buff; - - return CC_OK; -} - -/** - * Applies the function fn to each element of the CC_Array. - * - * @param[in] ar array on which this operation is performed - * @param[in] fn operation function that is to be invoked on each CC_Array - * element - */ -void cc_array_map(CC_Array *ar, void (*fn)(void *e)) { - size_t i; - for (i = 0; i < ar->size; i++) { - fn(ar->buffer[i]); - } -} - -/** - * A fold/reduce function that collects all of the elements in the array - * together. For example, if we have an array of [a,b,c...] the end result - * will be (...((a+b)+c)+...). - * - * @param[in] ar the array on which this operation is performed - * @param[in] fn the operation function that is to be invoked on each array - * element - * @param[in] result the pointer which will collect the end result - */ -void cc_array_reduce(CC_Array *ar, void (*fn)(void *, void *, void *), void *result) { - if (ar->size == 1) { - fn(ar->buffer[0], NULL, result); - return; - } - if (ar->size > 1) { - fn(ar->buffer[0], ar->buffer[1], result); - } - - for (size_t i = 2; i < ar->size; i++) { - fn(result, ar->buffer[i], result); - } -} - -/** - * Initializes the iterator. - * - * @param[in] iter the iterator that is being initialized - * @param[in] ar the array to iterate over - */ -void cc_array_iter_init(CC_ArrayIter *iter, CC_Array *ar) { - iter->ar = ar; - iter->index = 0; - iter->last_removed = false; -} - -/** - * Advances the iterator and sets the out parameter to the value of the - * next element in the sequence. - * - * @param[in] iter the iterator that is being advanced - * @param[out] out pointer to where the next element is set - * - * @return CC_OK if the iterator was advanced, or CC_ITER_END if the - * end of the CC_Array has been reached. - */ -enum cc_stat cc_array_iter_next(CC_ArrayIter *iter, void **out) { - if (iter->index >= iter->ar->size) { - return CC_ITER_END; - } - - *out = iter->ar->buffer[iter->index]; - - iter->index++; - iter->last_removed = false; - - return CC_OK; -} - -/** - * Removes the last returned element by cc_array_iter_next() - * function without invalidating the iterator and optionally sets the out - * parameter to the value of the removed element. - * - * @note This function should only ever be called after a call to - * cc_array_iter_next(). - - * @param[in] iter the iterator on which this operation is being performed - * @param[out] out pointer to where the removed element is stored, or NULL - * if it is to be ignored - * - * @return CC_OK if the element was successfully removed, or - * CC_ERR_VALUE_NOT_FOUND. - */ -enum cc_stat cc_array_iter_remove(CC_ArrayIter *iter, void **out) { - enum cc_stat status = CC_ERR_VALUE_NOT_FOUND; - - if (!iter->last_removed) { - status = cc_array_remove_at(iter->ar, iter->index - 1, out); - if (status != CC_OK) { - return status; - } - - iter->last_removed = true; - if (iter->index > 0) { - iter->index--; - } - } - return status; -} - -/** - * Removes the last returned element by cc_array_iter_next() - * function without invalidating the iterator and optionally sets the out - * parameter to the value of the removed element. The order of the array - * is not preserved, the last element of the array is moved to the index - * of the last returned element and the last element is removed. - * - * @note This function should only ever be called after a call to - * cc_array_iter_next(). - - * @param[in] iter the iterator on which this operation is being performed - * @param[out] out pointer to where the removed element is stored, or NULL - * if it is to be ignored - * - * @return CC_OK if the element was successfully removed, or - * CC_ERR_VALUE_NOT_FOUND. - */ -enum cc_stat cc_array_iter_remove_fast(CC_ArrayIter *iter, void **out) { - enum cc_stat status = CC_ERR_VALUE_NOT_FOUND; - - if (!iter->last_removed) { - status = cc_array_remove_fast_at(iter->ar, iter->index - 1, out); - if (status != CC_OK) { - return status; - } - - iter->last_removed = true; - if (iter->index > 0) { - iter->index--; - } - } - return status; -} - -/** - * Adds a new element to the CC_Array after the last returned element by - * cc_array_iter_next() function without invalidating the - * iterator. - * - * @note This function should only ever be called after a call to - * cc_array_iter_next(). - * - * @param[in] iter the iterator on which this operation is being performed - * @param[in] element the element being added - * - * @return CC_OK if the element was successfully added, CC_ERR_ALLOC if the - * memory allocation for the new element failed, or CC_ERR_MAX_CAPACITY if - * the array is already at maximum capacity. - */ -enum cc_stat cc_array_iter_add(CC_ArrayIter *iter, void *element) { - return cc_array_add_at(iter->ar, element, iter->index++); -} - -/** - * Replaces the last returned element by cc_array_iter_next() - * with the specified element and optionally sets the out parameter to - * the value of the replaced element. - * - * @note This function should only ever be called after a call to - * cc_array_iter_next(). - * - * @param[in] iter the iterator on which this operation is being performed - * @param[in] element the replacement element - * @param[out] out pointer to where the replaced element is stored, or NULL - * if it is to be ignored - * - * @return CC_OK if the element was replaced successfully, or - * CC_ERR_OUT_OF_RANGE. - */ -enum cc_stat cc_array_iter_replace(CC_ArrayIter *iter, void *element, void **out) { - return cc_array_replace_at(iter->ar, element, iter->index - 1, out); -} - -/** - * Returns the index of the last returned element by cc_array_iter_next() - * . - * - * @note - * This function should not be called before a call to cc_array_iter_next() - * . - * - * @param[in] iter the iterator on which this operation is being performed - * - * @return the index. - */ -size_t cc_array_iter_index(CC_ArrayIter *iter) { - return iter->index - 1; -} - -/** - * Initializes the zip iterator. - * - * @param[in] iter iterator that is being initialized - * @param[in] ar1 first array - * @param[in] ar2 second array - */ -void cc_array_zip_iter_init(CC_ArrayZipIter *iter, CC_Array *ar1, CC_Array *ar2) { - iter->ar1 = ar1; - iter->ar2 = ar2; - iter->index = 0; - iter->last_removed = false; -} - -/** - * Outputs the next element pair in the sequence and advances the iterator. - * - * @param[in] iter iterator that is being advanced - * @param[out] out1 output of the first array element - * @param[out] out2 output of the second array element - * - * @return CC_OK if a next element pair is returned, or CC_ITER_END if the end of one - * of the arrays has been reached. - */ -enum cc_stat cc_array_zip_iter_next(CC_ArrayZipIter *iter, void **out1, void **out2) { - if (iter->index >= iter->ar1->size || iter->index >= iter->ar2->size) { - return CC_ITER_END; - } - - *out1 = iter->ar1->buffer[iter->index]; - *out2 = iter->ar2->buffer[iter->index]; - - iter->index++; - iter->last_removed = false; - - return CC_OK; -} - -/** - * Removes and outputs the last returned element pair by cc_array_zip_iter_next() - * without invalidating the iterator. - * - * @param[in] iter iterator on which this operation is being performed - * @param[out] out1 output of the removed element from the first array - * @param[out] out2 output of the removed element from the second array - * - * @return CC_OK if the element was successfully removed, CC_ERR_OUT_OF_RANGE if the - * state of the iterator is invalid, or CC_ERR_VALUE_NOT_FOUND if the element was - * already removed. - */ -enum cc_stat cc_array_zip_iter_remove(CC_ArrayZipIter *iter, void **out1, void **out2) { - if ((iter->index - 1) >= iter->ar1->size || (iter->index - 1) >= iter->ar2->size) { - return CC_ERR_OUT_OF_RANGE; - } - - if (!iter->last_removed) { - cc_array_remove_at(iter->ar1, iter->index - 1, out1); - cc_array_remove_at(iter->ar2, iter->index - 1, out2); - iter->last_removed = true; - return CC_OK; - } - return CC_ERR_VALUE_NOT_FOUND; -} - -/** - * Adds a new element pair to the arrays after the last returned element pair by - * cc_array_zip_iter_next() and immediately before an element pair - * that would be returned by a subsequent call to cc_array_zip_iter_next() - * without invalidating the iterator. - * - * @param[in] iter iterator on which this operation is being performed - * @param[in] e1 element added to the first array - * @param[in] e2 element added to the second array - * - * @return CC_OK if the element pair was successfully added to the arrays, or - * CC_ERR_ALLOC if the memory allocation for the new elements failed. - */ -enum cc_stat cc_array_zip_iter_add(CC_ArrayZipIter *iter, void *e1, void *e2) { - size_t index = iter->index++; - CC_Array *ar1 = iter->ar1; - CC_Array *ar2 = iter->ar2; - - /* Make sure both array buffers have room */ - if ((ar1->size == ar1->capacity && (expand_array_capacity(ar1) != CC_OK)) || - (ar2->size == ar2->capacity && (expand_array_capacity(ar2) != CC_OK))) { - return CC_ERR_ALLOC; - } - - cc_array_add_at(ar1, e1, index); - cc_array_add_at(ar2, e2, index); - - return CC_OK; -} - -/** - * Replaces the last returned element pair by cc_array_zip_iter_next() - * with the specified replacement element pair. - * - * @param[in] iter iterator on which this operation is being performed - * @param[in] e1 first array's replacement element - * @param[in] e2 second array's replacement element - * @param[out] out1 output of the replaced element from the first array - * @param[out] out2 output of the replaced element from the second array - * - * @return CC_OK if the element was successfully replaced, or CC_ERR_OUT_OF_RANGE. - */ -enum cc_stat cc_array_zip_iter_replace(CC_ArrayZipIter *iter, void *e1, void *e2, void **out1, void **out2) { - if ((iter->index - 1) >= iter->ar1->size || (iter->index - 1) >= iter->ar2->size) { - return CC_ERR_OUT_OF_RANGE; - } - - cc_array_replace_at(iter->ar1, e1, iter->index - 1, out1); - cc_array_replace_at(iter->ar2, e2, iter->index - 1, out2); - - return CC_OK; -} - -/** - * Returns the index of the last returned element pair by cc_array_zip_iter_next(). - * - * @param[in] iter iterator on which this operation is being performed - * - * @return current iterator index. - */ -size_t cc_array_zip_iter_index(CC_ArrayZipIter *iter) { - return iter->index - 1; -} - -size_t cc_array_struct_size() { - return sizeof(CC_Array); -} - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/pufferlib/ocean/impulse_wars/include/cc_common.h b/pufferlib/ocean/impulse_wars/include/cc_common.h deleted file mode 100644 index 1740460646..0000000000 --- a/pufferlib/ocean/impulse_wars/include/cc_common.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Collections-C - * Copyright (C) 2013-2014 Srđan Panić - * - * This file is part of Collections-C. - * - * Collections-C is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Collections-C is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Collections-C. If not, see . - */ - -#ifndef CC_COMMON_H -#define CC_COMMON_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include -#include - -#ifdef ARCH_64 -#define MAX_POW_TWO (((size_t)1) << 63) -#else -#define MAX_POW_TWO (((size_t)1) << 31) -#endif /* ARCH_64 */ - -enum cc_stat { - CC_OK = 0, - - CC_ERR_ALLOC = 1, - CC_ERR_INVALID_CAPACITY = 2, - CC_ERR_INVALID_RANGE = 3, - CC_ERR_MAX_CAPACITY = 4, - CC_ERR_KEY_NOT_FOUND = 6, - CC_ERR_VALUE_NOT_FOUND = 7, - CC_ERR_OUT_OF_RANGE = 8, - - CC_ITER_END = 9, -}; - -#define CC_MAX_ELEMENTS ((size_t) - 2) - -#if defined(_MSC_VER) - -#define INLINE __inline -#define FORCE_INLINE __forceinline - -#else - -#define INLINE inline -#define FORCE_INLINE inline __attribute__((always_inline)) - -#endif /* _MSC_VER */ - -int cc_common_cmp_str(const void *key1, const void *key2); - -#define CC_CMP_STRING cc_common_cmp_str - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/pufferlib/ocean/impulse_wars/include/dlmalloc.h b/pufferlib/ocean/impulse_wars/include/dlmalloc.h deleted file mode 100644 index 4ef7c9cfd5..0000000000 --- a/pufferlib/ocean/impulse_wars/include/dlmalloc.h +++ /dev/null @@ -1,6264 +0,0 @@ -/* - Default header file for malloc-2.7.2, written by Doug Lea - and released to the public domain. Use, modify, and redistribute - this code without permission or acknowledgement in any way you wish. - Send questions, comments, complaints, performance data, etc to - dl@cs.oswego.edu. - - last update: Sun Feb 25 18:38:11 2001 Doug Lea (dl at gee) - - This header is for ANSI C/C++ only. You can set either of - the following #defines before including: - - * If USE_DL_PREFIX is defined, it is assumed that malloc.c - was also compiled with this option, so all routines - have names starting with "dl". - - * If HAVE_USR_INCLUDE_MALLOC_H is defined, it is assumed that this - file will be #included AFTER . This is needed only if - your system defines a struct mallinfo that is incompatible with the - standard one declared here. Otherwise, you can include this file - INSTEAD of your system system . At least on ANSI, all - declarations should be compatible with system versions -*/ - -#ifndef MALLOC_270_H -#define MALLOC_270_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include /* for size_t */ - -#define USE_DL_PREFIX - -/* - malloc(size_t n) - Returns a pointer to a newly allocated chunk of at least n bytes, or - null if no space is available. Additionally, on failure, errno is - set to ENOMEM on ANSI C systems. - - If n is zero, malloc returns a minimum-sized chunk. The minimum size - is 16 bytes on most 32bit systems, and either 24 or 32 bytes on - 64bit systems, depending on internal size and alignment restrictions. - - On most systems, size_t is an unsigned type. Calls with values of n - that appear "negative" when signed are interpreted as requests for - huge amounts of space, which will most often fail. - - The maximum allowed value of n differs across systems, but is in all - cases less (typically by 8K) than the maximum representable value of - a size_t. Requests greater than this value result in failure. -*/ - -#ifndef USE_DL_PREFIX -void *malloc(size_t); -#else -void *dlmalloc(size_t); -#endif - -/* - free(void* p) - Releases the chunk of memory pointed to by p, that had been previously - allocated using malloc or a related routine such as realloc. - It has no effect if p is null. It can have arbitrary (and bad!) - effects if p has already been freed or was not obtained via malloc. - - Unless disabled using mallopt, freeing very large spaces will, - when possible, automatically trigger operations that give - back unused memory to the system, thus reducing program footprint. -*/ -#ifndef USE_DL_PREFIX -void free(void *); -#else -void dlfree(void *); -#endif - -/* - calloc(size_t n_elements, size_t element_size); - Returns a pointer to n_elements * element_size bytes, with all locations - set to zero. -*/ -#ifndef USE_DL_PREFIX -void *calloc(size_t, size_t); -#else -void *dlcalloc(size_t, size_t); -#endif - -/* - realloc(void* p, size_t n) - Returns a pointer to a chunk of size n that contains the same data - as does chunk p up to the minimum of (n, p's size) bytes. - - The returned pointer may or may not be the same as p. The algorithm - prefers extending p when possible, otherwise it employs the - equivalent of a malloc-copy-free sequence. - - If p is null, realloc is equivalent to malloc. - - If space is not available, realloc returns null, errno is set (if on - ANSI) and p is NOT freed. - - if n is for fewer bytes than already held by p, the newly unused - space is lopped off and freed if possible. Unless the #define - REALLOC_ZERO_BYTES_FREES is set, realloc with a size argument of - zero (re)allocates a minimum-sized chunk. - - Large chunks that were internally obtained via mmap will always - be reallocated using malloc-copy-free sequences unless - the system supports MREMAP (currently only linux). - - The old unix realloc convention of allowing the last-free'd chunk - to be used as an argument to realloc is not supported. -*/ - -#ifndef USE_DL_PREFIX -void *realloc(void *, size_t); -#else -void *dlrealloc(void *, size_t); -#endif - -/* - memalign(size_t alignment, size_t n); - Returns a pointer to a newly allocated chunk of n bytes, aligned - in accord with the alignment argument. - - The alignment argument should be a power of two. If the argument is - not a power of two, the nearest greater power is used. - 8-byte alignment is guaranteed by normal malloc calls, so don't - bother calling memalign with an argument of 8 or less. - - Overreliance on memalign is a sure way to fragment space. -*/ - -#ifndef USE_DL_PREFIX -void *memalign(size_t, size_t); -#else -void *dlmemalign(size_t, size_t); -#endif - -/* - valloc(size_t n); - Allocates a page-aligned chunk of at least n bytes. - Equivalent to memalign(pagesize, n), where pagesize is the page - size of the system. If the pagesize is unknown, 4096 is used. -*/ - -#ifndef USE_DL_PREFIX -void *valloc(size_t); -#else -void *dlvalloc(size_t); -#endif - -/* - independent_calloc(size_t n_elements, size_t element_size, void* chunks[]); - - independent_calloc is similar to calloc, but instead of returning a - single cleared space, it returns an array of pointers to n_elements - independent elements, each of which can hold contents of size - elem_size. Each element starts out cleared, and can be - independently freed, realloc'ed etc. The elements are guaranteed to - be adjacently allocated (this is not guaranteed to occur with - multiple callocs or mallocs), which may also improve cache locality - in some applications. - - The "chunks" argument is optional (i.e., may be null, which is - probably the most typical usage). If it is null, the returned array - is itself dynamically allocated and should also be freed when it is - no longer needed. Otherwise, the chunks array must be of at least - n_elements in length. It is filled in with the pointers to the - chunks. - - In either case, independent_calloc returns this pointer array, or - null if the allocation failed. If n_elements is zero and "chunks" - is null, it returns a chunk representing an array with zero elements - (which should be freed if not wanted). - - Each element must be individually freed when it is no longer - needed. If you'd like to instead be able to free all at once, you - should instead use regular calloc and assign pointers into this - space to represent elements. (In this case though, you cannot - independently free elements.) - - independent_calloc simplifies and speeds up implementations of many - kinds of pools. It may also be useful when constructing large data - structures that initially have a fixed number of fixed-sized nodes, - but the number is not known at compile time, and some of the nodes - may later need to be freed. For example: - - struct Node { int item; struct Node* next; }; - - struct Node* build_list() { - struct Node** pool; - int n = read_number_of_nodes_needed(); - if (n <= 0) return 0; - pool = (struct Node**)(independent_calloc(n, sizeof(struct Node), 0); - if (pool == 0) return 0; // failure - // organize into a linked list... - struct Node* first = pool[0]; - for (i = 0; i < n-1; ++i) - pool[i]->next = pool[i+1]; - free(pool); // Can now free the array (or not, if it is needed later) - return first; - } -*/ - -#ifndef USE_DL_PREFIX -void **independent_calloc(size_t, size_t, void **); -#else -void **dlindependent_calloc(size_t, size_t, void **); -#endif - -/* - independent_comalloc(size_t n_elements, size_t sizes[], void* chunks[]); - - independent_comalloc allocates, all at once, a set of n_elements - chunks with sizes indicated in the "sizes" array. It returns - an array of pointers to these elements, each of which can be - independently freed, realloc'ed etc. The elements are guaranteed to - be adjacently allocated (this is not guaranteed to occur with - multiple callocs or mallocs), which may also improve cache locality - in some applications. - - The "chunks" argument is optional (i.e., may be null). If it is null - the returned array is itself dynamically allocated and should also - be freed when it is no longer needed. Otherwise, the chunks array - must be of at least n_elements in length. It is filled in with the - pointers to the chunks. - - In either case, independent_comalloc returns this pointer array, or - null if the allocation failed. If n_elements is zero and chunks is - null, it returns a chunk representing an array with zero elements - (which should be freed if not wanted). - - Each element must be individually freed when it is no longer - needed. If you'd like to instead be able to free all at once, you - should instead use a single regular malloc, and assign pointers at - particular offsets in the aggregate space. (In this case though, you - cannot independently free elements.) - - independent_comallac differs from independent_calloc in that each - element may have a different size, and also that it does not - automatically clear elements. - - independent_comalloc can be used to speed up allocation in cases - where several structs or objects must always be allocated at the - same time. For example: - - struct Head { ... } - struct Foot { ... } - - void send_message(char* msg) { - int msglen = strlen(msg); - size_t sizes[3] = { sizeof(struct Head), msglen, sizeof(struct Foot) }; - void* chunks[3]; - if (independent_comalloc(3, sizes, chunks) == 0) - die(); - struct Head* head = (struct Head*)(chunks[0]); - char* body = (char*)(chunks[1]); - struct Foot* foot = (struct Foot*)(chunks[2]); - // ... - } - - In general though, independent_comalloc is worth using only for - larger values of n_elements. For small values, you probably won't - detect enough difference from series of malloc calls to bother. - - Overuse of independent_comalloc can increase overall memory usage, - since it cannot reuse existing noncontiguous small chunks that - might be available for some of the elements. -*/ - -#ifndef USE_DL_PREFIX -void **independent_comalloc(size_t, size_t *, void **); -#else -void **dlindependent_comalloc(size_t, size_t *, void **); -#endif - -/* - pvalloc(size_t n); - Equivalent to valloc(minimum-page-that-holds(n)), that is, - round up n to nearest pagesize. - */ - -#ifndef USE_DL_PREFIX -void *pvalloc(size_t); -#else -void *dlpvalloc(size_t); -#endif - -/* - cfree(void* p); - Equivalent to free(p). - - cfree is needed/defined on some systems that pair it with calloc, - for odd historical reasons (such as: cfree is used in example - code in the first edition of K&R). -*/ - -#ifndef USE_DL_PREFIX -void cfree(void *); -#else -void dlcfree(void *); -#endif - -/* - malloc_trim(size_t pad); - - If possible, gives memory back to the system (via negative - arguments to sbrk) if there is unused memory at the `high' end of - the malloc pool. You can call this after freeing large blocks of - memory to potentially reduce the system-level memory requirements - of a program. However, it cannot guarantee to reduce memory. Under - some allocation patterns, some large free blocks of memory will be - locked between two used chunks, so they cannot be given back to - the system. - - The `pad' argument to malloc_trim represents the amount of free - trailing space to leave untrimmed. If this argument is zero, - only the minimum amount of memory to maintain internal data - structures will be left (one page or less). Non-zero arguments - can be supplied to maintain enough trailing space to service - future expected allocations without having to re-obtain memory - from the system. - - Malloc_trim returns 1 if it actually released any memory, else 0. - On systems that do not support "negative sbrks", it will always - return 0. -*/ - -#ifndef USE_DL_PREFIX -int malloc_trim(size_t); -#else -int dlmalloc_trim(size_t); -#endif - -/* - malloc_usable_size(void* p); - - Returns the number of bytes you can actually use in an allocated - chunk, which may be more than you requested (although often not) due - to alignment and minimum size constraints. You can use this many - bytes without worrying about overwriting other allocated - objects. This is not a particularly great programming practice. But - malloc_usable_size can be more useful in debugging and assertions, - for example: - - p = malloc(n); - assert(malloc_usable_size(p) >= 256); -*/ - -#ifndef USE_DL_PREFIX -size_t malloc_usable_size(void *); -#else -size_t dlmalloc_usable_size(void *); -#endif - -/* - malloc_stats(); - Prints on stderr the amount of space obtained from the system (both - via sbrk and mmap), the maximum amount (which may be more than - current if malloc_trim and/or munmap got called), and the current - number of bytes allocated via malloc (or realloc, etc) but not yet - freed. Note that this is the number of bytes allocated, not the - number requested. It will be larger than the number requested - because of alignment and bookkeeping overhead. Because it includes - alignment wastage as being in use, this figure may be greater than - zero even when no user-level chunks are allocated. - - The reported current and maximum system memory can be inaccurate if - a program makes other calls to system memory allocation functions - (normally sbrk) outside of malloc. - - malloc_stats prints only the most commonly interesting statistics. - More information can be obtained by calling mallinfo. -*/ - -#ifndef USE_DL_PREFIX -void malloc_stats(void); -#else -void dlmalloc_stats(void); -#endif - -/* - mallinfo() - Returns (by copy) a struct containing various summary statistics: - - arena: current total non-mmapped bytes allocated from system - ordblks: the number of free chunks - smblks: the number of fastbin blocks (i.e., small chunks that - have been freed but not use resused or consolidated) - hblks: current number of mmapped regions - hblkhd: total bytes held in mmapped regions - usmblks: the maximum total allocated space. This will be greater - than current total if trimming has occurred. - fsmblks: total bytes held in fastbin blocks - uordblks: current total allocated space (normal or mmapped) - fordblks: total free space - keepcost: the maximum number of bytes that could ideally be released - back to system via malloc_trim. ("ideally" means that - it ignores page restrictions etc.) - - The names of some of these fields don't bear much relation with - their contents because this struct was defined as standard in - SVID/XPG so reflects the malloc implementation that was then used - in SystemV Unix. - - The original SVID version of this struct, defined on most systems - with mallinfo, declares all fields as ints. But some others define - as unsigned long. If your system defines the fields using a type of - different width than listed here, you should #include your system - version before including this file. The struct declaration is - suppressed if _MALLOC_H is defined (which is done in most system - malloc.h files). You can also suppress it by defining - HAVE_USR_INCLUDE_MALLOC_H. - - Because these fields are ints, but internal bookkeeping is done with - unsigned longs, the reported values may appear as negative, and may - wrap around zero and thus be inaccurate. -*/ - -#ifndef HAVE_USR_INCLUDE_MALLOC_H -#ifndef _MALLOC_H -struct mallinfo { - int arena; - int ordblks; - int smblks; - int hblks; - int hblkhd; - int usmblks; - int fsmblks; - int uordblks; - int fordblks; - int keepcost; -}; -#endif -#endif - -#ifndef USE_DL_PREFIX -struct mallinfo mallinfo(void); -#else -struct mallinfo mallinfo(void); -#endif - -/* - mallopt(int parameter_number, int parameter_value) - Sets tunable parameters The format is to provide a - (parameter-number, parameter-value) pair. mallopt then sets the - corresponding parameter to the argument value if it can (i.e., so - long as the value is meaningful), and returns 1 if successful else - 0. SVID/XPG defines four standard param numbers for mallopt, - normally defined in malloc.h. Only one of these (M_MXFAST) is used - in this malloc. The others (M_NLBLKS, M_GRAIN, M_KEEP) don't apply, - so setting them has no effect. But this malloc also supports four - other options in mallopt. See below for details. Briefly, supported - parameters are as follows (listed defaults are for "typical" - configurations). - - Symbol param # default allowed param values - M_MXFAST 1 64 0-80 (0 disables fastbins) - M_TRIM_THRESHOLD -1 128*1024 any (-1U disables trimming) - M_TOP_PAD -2 0 any - M_MMAP_THRESHOLD -3 128*1024 any (or 0 if no MMAP support) - M_MMAP_MAX -4 65536 any (0 disables use of mmap) -*/ - -#ifndef USE_DL_PREFIX -int mallopt(int, int); -#else -int dlmallopt(int, int); -#endif - -/* Descriptions of tuning options */ - -/* - M_MXFAST is the maximum request size used for "fastbins", special bins - that hold returned chunks without consolidating their spaces. This - enables future requests for chunks of the same size to be handled - very quickly, but can increase fragmentation, and thus increase the - overall memory footprint of a program. - - This malloc manages fastbins very conservatively yet still - efficiently, so fragmentation is rarely a problem for values less - than or equal to the default. The maximum supported value of MXFAST - is 80. You wouldn't want it any higher than this anyway. Fastbins - are designed especially for use with many small structs, objects or - strings -- the default handles structs/objects/arrays with sizes up - to 8 4byte fields, or small strings representing words, tokens, - etc. Using fastbins for larger objects normally worsens - fragmentation without improving speed. - - You can reduce M_MXFAST to 0 to disable all use of fastbins. This - causes the malloc algorithm to be a closer approximation of - fifo-best-fit in all cases, not just for larger requests, but will - generally cause it to be slower. -*/ - -#ifndef M_MXFAST -#define M_MXFAST 1 -#endif - -/* - M_TRIM_THRESHOLD is the maximum amount of unused top-most memory - to keep before releasing via malloc_trim in free(). - - Automatic trimming is mainly useful in long-lived programs. - Because trimming via sbrk can be slow on some systems, and can - sometimes be wasteful (in cases where programs immediately - afterward allocate more large chunks) the value should be high - enough so that your overall system performance would improve by - releasing this much memory. - - The trim threshold and the mmap control parameters (see below) - can be traded off with one another. Trimming and mmapping are - two different ways of releasing unused memory back to the - system. Between these two, it is often possible to keep - system-level demands of a long-lived program down to a bare - minimum. For example, in one test suite of sessions measuring - the XF86 X server on Linux, using a trim threshold of 128K and a - mmap threshold of 192K led to near-minimal long term resource - consumption. - - If you are using this malloc in a long-lived program, it should - pay to experiment with these values. As a rough guide, you - might set to a value close to the average size of a process - (program) running on your system. Releasing this much memory - would allow such a process to run in memory. Generally, it's - worth it to tune for trimming rather tham memory mapping when a - program undergoes phases where several large chunks are - allocated and released in ways that can reuse each other's - storage, perhaps mixed with phases where there are no such - chunks at all. And in well-behaved long-lived programs, - controlling release of large blocks via trimming versus mapping - is usually faster. - - However, in most programs, these parameters serve mainly as - protection against the system-level effects of carrying around - massive amounts of unneeded memory. Since frequent calls to - sbrk, mmap, and munmap otherwise degrade performance, the default - parameters are set to relatively high values that serve only as - safeguards. - - The trim value It must be greater than page size to have any useful - effect. To disable trimming completely, you can set to - (unsigned long)(-1) - - Trim settings interact with fastbin (MXFAST) settings: Unless - compiled with TRIM_FASTBINS defined, automatic trimming never takes - place upon freeing a chunk with size less than or equal to - MXFAST. Trimming is instead delayed until subsequent freeing of - larger chunks. However, you can still force an attempted trim by - calling malloc_trim. - - Also, trimming is not generally possible in cases where - the main arena is obtained via mmap. - - Note that the trick some people use of mallocing a huge space and - then freeing it at program startup, in an attempt to reserve system - memory, doesn't have the intended effect under automatic trimming, - since that memory will immediately be returned to the system. -*/ - -#define M_TRIM_THRESHOLD -1 - -/* - M_TOP_PAD is the amount of extra `padding' space to allocate or - retain whenever sbrk is called. It is used in two ways internally: - - * When sbrk is called to extend the top of the arena to satisfy - a new malloc request, this much padding is added to the sbrk - request. - - * When malloc_trim is called automatically from free(), - it is used as the `pad' argument. - - In both cases, the actual amount of padding is rounded - so that the end of the arena is always a system page boundary. - - The main reason for using padding is to avoid calling sbrk so - often. Having even a small pad greatly reduces the likelihood - that nearly every malloc request during program start-up (or - after trimming) will invoke sbrk, which needlessly wastes - time. - - Automatic rounding-up to page-size units is normally sufficient - to avoid measurable overhead, so the default is 0. However, in - systems where sbrk is relatively slow, it can pay to increase - this value, at the expense of carrying around more memory than - the program needs. -*/ - -#define M_TOP_PAD -2 - -/* - M_MMAP_THRESHOLD is the request size threshold for using mmap() - to service a request. Requests of at least this size that cannot - be allocated using already-existing space will be serviced via mmap. - (If enough normal freed space already exists it is used instead.) - - Using mmap segregates relatively large chunks of memory so that - they can be individually obtained and released from the host - system. A request serviced through mmap is never reused by any - other request (at least not directly; the system may just so - happen to remap successive requests to the same locations). - - Segregating space in this way has the benefits that: - - 1. Mmapped space can ALWAYS be individually released back - to the system, which helps keep the system level memory - demands of a long-lived program low. - 2. Mapped memory can never become `locked' between - other chunks, as can happen with normally allocated chunks, which - means that even trimming via malloc_trim would not release them. - 3. On some systems with "holes" in address spaces, mmap can obtain - memory that sbrk cannot. - - However, it has the disadvantages that: - - 1. The space cannot be reclaimed, consolidated, and then - used to service later requests, as happens with normal chunks. - 2. It can lead to more wastage because of mmap page alignment - requirements - 3. It causes malloc performance to be more dependent on host - system memory management support routines. - - The advantages of mmap nearly always outweigh disadvantages for - "large" chunks, but the value of "large" varies across systems. The - default is an empirically derived value that works well in most - systems. -*/ - -#define M_MMAP_THRESHOLD -3 - -/* - M_MMAP_MAX is the maximum number of requests to simultaneously - service using mmap. This parameter exists because - some systems have a limited number of internal tables for - use by mmap, and using more than a few of them may degrade - performance. - - The default is set to a value that serves only as a safeguard. - Setting to 0 disables use of mmap for servicing large requests. If - mmap is not supported on a system, the default value is 0, and - attempts to set it to non-zero values in mallopt will fail. -*/ - -#define M_MMAP_MAX -4 - -/* Unused SVID2/XPG mallopt options, listed for completeness */ - -#ifndef M_NBLKS -#define M_NLBLKS 2 /* UNUSED in this malloc */ -#endif -#ifndef M_GRAIN -#define M_GRAIN 3 /* UNUSED in this malloc */ -#endif -#ifndef M_KEEP -#define M_KEEP 4 /* UNUSED in this malloc */ -#endif - -/* - Some malloc.h's declare alloca, even though it is not part of malloc. -*/ - -#ifndef _ALLOCA_H -extern void *alloca(size_t); -#endif - -/* - This is a version (aka dlmalloc) of malloc/free/realloc written by - Doug Lea and released to the public domain. Use, modify, and - redistribute this code without permission or acknowledgement in any - way you wish. Send questions, comments, complaints, performance - data, etc to dl@cs.oswego.edu - -* VERSION 2.7.2 Sat Aug 17 09:07:30 2002 Doug Lea (dl at gee) - - Note: There may be an updated version of this malloc obtainable at - ftp://gee.cs.oswego.edu/pub/misc/malloc.c - Check before installing! - -* Quickstart - - This library is all in one file to simplify the most common usage: - ftp it, compile it (-O), and link it into another program. All - of the compile-time options default to reasonable values for use on - most unix platforms. Compile -DWIN32 for reasonable defaults on windows. - You might later want to step through various compile-time and dynamic - tuning options. - - For convenience, an include file for code using this malloc is at: - ftp://gee.cs.oswego.edu/pub/misc/malloc-2.7.1.h - You don't really need this .h file unless you call functions not - defined in your system include files. The .h file contains only the - excerpts from this file needed for using this malloc on ANSI C/C++ - systems, so long as you haven't changed compile-time options about - naming and tuning parameters. If you do, then you can create your - own malloc.h that does include all settings by cutting at the point - indicated below. - -* Why use this malloc? - - This is not the fastest, most space-conserving, most portable, or - most tunable malloc ever written. However it is among the fastest - while also being among the most space-conserving, portable and tunable. - Consistent balance across these factors results in a good general-purpose - allocator for malloc-intensive programs. - - The main properties of the algorithms are: - * For large (>= 512 bytes) requests, it is a pure best-fit allocator, - with ties normally decided via FIFO (i.e. least recently used). - * For small (<= 64 bytes by default) requests, it is a caching - allocator, that maintains pools of quickly recycled chunks. - * In between, and for combinations of large and small requests, it does - the best it can trying to meet both goals at once. - * For very large requests (>= 128KB by default), it relies on system - memory mapping facilities, if supported. - - For a longer but slightly out of date high-level description, see - http://gee.cs.oswego.edu/dl/html/malloc.html - - You may already by default be using a C library containing a malloc - that is based on some version of this malloc (for example in - linux). You might still want to use the one in this file in order to - customize settings or to avoid overheads associated with library - versions. - -* Contents, described in more detail in "description of public routines" below. - - Standard (ANSI/SVID/...) functions: - malloc(size_t n); - calloc(size_t n_elements, size_t element_size); - free(Void_t* p); - realloc(Void_t* p, size_t n); - memalign(size_t alignment, size_t n); - valloc(size_t n); - mallinfo() - mallopt(int parameter_number, int parameter_value) - - Additional functions: - independent_calloc(size_t n_elements, size_t size, Void_t* chunks[]); - independent_comalloc(size_t n_elements, size_t sizes[], Void_t* chunks[]); - pvalloc(size_t n); - cfree(Void_t* p); - malloc_trim(size_t pad); - malloc_usable_size(Void_t* p); - malloc_stats(); - -* Vital statistics: - - Supported pointer representation: 4 or 8 bytes - Supported size_t representation: 4 or 8 bytes - Note that size_t is allowed to be 4 bytes even if pointers are 8. - You can adjust this by defining INTERNAL_SIZE_T - - Alignment: 2 * sizeof(size_t) (default) - (i.e., 8 byte alignment with 4byte size_t). This suffices for - nearly all current machines and C compilers. However, you can - define MALLOC_ALIGNMENT to be wider than this if necessary. - - Minimum overhead per allocated chunk: 4 or 8 bytes - Each malloced chunk has a hidden word of overhead holding size - and status information. - - Minimum allocated size: 4-byte ptrs: 16 bytes (including 4 overhead) - 8-byte ptrs: 24/32 bytes (including, 4/8 overhead) - - When a chunk is freed, 12 (for 4byte ptrs) or 20 (for 8 byte - ptrs but 4 byte size) or 24 (for 8/8) additional bytes are - needed; 4 (8) for a trailing size field and 8 (16) bytes for - free list pointers. Thus, the minimum allocatable size is - 16/24/32 bytes. - - Even a request for zero bytes (i.e., malloc(0)) returns a - pointer to something of the minimum allocatable size. - - The maximum overhead wastage (i.e., number of extra bytes - allocated than were requested in malloc) is less than or equal - to the minimum size, except for requests >= mmap_threshold that - are serviced via mmap(), where the worst case wastage is 2 * - sizeof(size_t) bytes plus the remainder from a system page (the - minimal mmap unit); typically 4096 or 8192 bytes. - - Maximum allocated size: 4-byte size_t: 2^32 minus about two pages - 8-byte size_t: 2^64 minus about two pages - - It is assumed that (possibly signed) size_t values suffice to - represent chunk sizes. `Possibly signed' is due to the fact - that `size_t' may be defined on a system as either a signed or - an unsigned type. The ISO C standard says that it must be - unsigned, but a few systems are known not to adhere to this. - Additionally, even when size_t is unsigned, sbrk (which is by - default used to obtain memory from system) accepts signed - arguments, and may not be able to handle size_t-wide arguments - with negative sign bit. Generally, values that would - appear as negative after accounting for overhead and alignment - are supported only via mmap(), which does not have this - limitation. - - Requests for sizes outside the allowed range will perform an optional - failure action and then return null. (Requests may also - also fail because a system is out of memory.) - - Thread-safety: NOT thread-safe unless USE_MALLOC_LOCK defined - - When USE_MALLOC_LOCK is defined, wrappers are created to - surround every public call with either a pthread mutex or - a win32 spinlock (depending on WIN32). This is not - especially fast, and can be a major bottleneck. - It is designed only to provide minimal protection - in concurrent environments, and to provide a basis for - extensions. If you are using malloc in a concurrent program, - you would be far better off obtaining ptmalloc, which is - derived from a version of this malloc, and is well-tuned for - concurrent programs. (See http://www.malloc.de) Note that - even when USE_MALLOC_LOCK is defined, you can can guarantee - full thread-safety only if no threads acquire memory through - direct calls to MORECORE or other system-level allocators. - - Compliance: I believe it is compliant with the 1997 Single Unix Specification - (See http://www.opennc.org). Also SVID/XPG, ANSI C, and probably - others as well. - -* Synopsis of compile-time options: - - People have reported using previous versions of this malloc on all - versions of Unix, sometimes by tweaking some of the defines - below. It has been tested most extensively on Solaris and - Linux. It is also reported to work on WIN32 platforms. - People also report using it in stand-alone embedded systems. - - The implementation is in straight, hand-tuned ANSI C. It is not - at all modular. (Sorry!) It uses a lot of macros. To be at all - usable, this code should be compiled using an optimizing compiler - (for example gcc -O3) that can simplify expressions and control - paths. (FAQ: some macros import variables as arguments rather than - declare locals because people reported that some debuggers - otherwise get confused.) - - OPTION DEFAULT VALUE - - Compilation Environment options: - - __STD_C derived from C compiler defines - WIN32 NOT defined - HAVE_MEMCPY defined - USE_MEMCPY 1 if HAVE_MEMCPY is defined - HAVE_MMAP defined as 1 - MMAP_CLEARS 1 - HAVE_MREMAP 0 unless linux defined - malloc_getpagesize derived from system #includes, or 4096 if not - HAVE_USR_INCLUDE_MALLOC_H NOT defined - LACKS_UNISTD_H NOT defined unless WIN32 - LACKS_SYS_PARAM_H NOT defined unless WIN32 - LACKS_SYS_MMAN_H NOT defined unless WIN32 - LACKS_FCNTL_H NOT defined - - Changing default word sizes: - - INTERNAL_SIZE_T size_t - MALLOC_ALIGNMENT 2 * sizeof(INTERNAL_SIZE_T) - PTR_UINT unsigned long - CHUNK_SIZE_T unsigned long - - Configuration and functionality options: - - USE_DL_PREFIX NOT defined - USE_PUBLIC_MALLOC_WRAPPERS NOT defined - USE_MALLOC_LOCK NOT defined - DL_DEBUG NOT defined - REALLOC_ZERO_BYTES_FREES NOT defined - MALLOC_FAILURE_ACTION errno = ENOMEM, if __STD_C defined, else no-op - TRIM_FASTBINS 0 - FIRST_SORTED_BIN_SIZE 512 - - Options for customizing MORECORE: - - MORECORE sbrk - MORECORE_CONTIGUOUS 1 - MORECORE_CANNOT_TRIM NOT defined - MMAP_AS_MORECORE_SIZE (1024 * 1024) - - Tuning options that are also dynamically changeable via mallopt: - - DEFAULT_MXFAST 64 - DEFAULT_TRIM_THRESHOLD 256 * 1024 - DEFAULT_TOP_PAD 0 - DEFAULT_MMAP_THRESHOLD 256 * 1024 - DEFAULT_MMAP_MAX 65536 - - There are several other #defined constants and macros that you - probably don't want to touch unless you are extending or adapting malloc. -*/ - -/* - WIN32 sets up defaults for MS environment and compilers. - Otherwise defaults are for unix. -*/ - -/* #define WIN32 */ - -#ifdef WIN32 - -#define WIN32_LEAN_AND_MEAN -#include - -/* Win32 doesn't supply or need the following headers */ -#define LACKS_UNISTD_H -#define LACKS_SYS_PARAM_H -#define LACKS_SYS_MMAN_H - -/* Use the supplied emulation of sbrk */ -#define MORECORE sbrk -#define MORECORE_CONTIGUOUS 1 -#define MORECORE_FAILURE ((void *)(-1)) - -/* Use the supplied emulation of mmap and munmap */ -#define HAVE_MMAP 1 -#define MUNMAP_FAILURE (-1) -#define MMAP_CLEARS 1 - -/* These values don't really matter in windows mmap emulation */ -#define MAP_PRIVATE 1 -#define MAP_ANONYMOUS 2 -#define PROT_READ 1 -#define PROT_WRITE 2 - -/* Emulation functions defined at the end of this file */ - -/* If USE_MALLOC_LOCK, use supplied critical-section-based lock functions */ -#ifdef USE_MALLOC_LOCK -static int slwait(int *sl); -static int slrelease(int *sl); -#endif - -static long getpagesize(void); -static long getregionsize(void); -static void *sbrk(long size); -static void *mmap(void *ptr, long size, long prot, long type, long handle, long arg); -static long munmap(void *ptr, long size); - -static void vminfo(unsigned long *free, unsigned long *reserved, unsigned long *committed); -static int cpuinfo(int whole, unsigned long *kernel, unsigned long *user); - -#endif - -/* - __STD_C should be nonzero if using ANSI-standard C compiler, a C++ - compiler, or a C compiler sufficiently close to ANSI to get away - with it. -*/ - -#ifndef __STD_C -#if defined(__STDC__) || defined(_cplusplus) -#define __STD_C 1 -#else -#define __STD_C 0 -#endif -#endif /*__STD_C*/ - -/* - Void_t* is the pointer type that malloc should say it returns -*/ - -#ifndef Void_t -#if (__STD_C || defined(WIN32)) -#define Void_t void -#else -#define Void_t char -#endif -#endif /*Void_t*/ - -#if __STD_C -#include /* for size_t */ -#else -#include -#endif - -/* define LACKS_UNISTD_H if your system does not have a . */ - -/* #define LACKS_UNISTD_H */ - -#ifndef LACKS_UNISTD_H -#include -#endif - -/* define LACKS_SYS_PARAM_H if your system does not have a . */ - -/* #define LACKS_SYS_PARAM_H */ - -#include /* needed for optional MALLOC_FAILURE_ACTION */ -#include /* needed for malloc_stats */ - -/* - Debugging: - - Because freed chunks may be overwritten with bookkeeping fields, this - malloc will often die when freed memory is overwritten by user - programs. This can be very effective (albeit in an annoying way) - in helping track down dangling pointers. - - If you compile with -DDL_DEBUG, a number of assertion checks are - enabled that will catch more memory errors. You probably won't be - able to make much sense of the actual assertion errors, but they - should help you locate incorrectly overwritten memory. The - checking is fairly extensive, and will slow down execution - noticeably. Calling malloc_stats or mallinfo with DL_DEBUG set will - attempt to check every non-mmapped allocated and free chunk in the - course of computing the summmaries. (By nature, mmapped regions - cannot be checked very much automatically.) - - Setting DL_DEBUG may also be helpful if you are trying to modify - this code. The assertions in the check routines spell out in more - detail the assumptions and invariants underlying the algorithms. - - Setting DL_DEBUG does NOT provide an automated mechanism for checking - that all accesses to malloced memory stay within their - bounds. However, there are several add-ons and adaptations of this - or other mallocs available that do this. -*/ - -#include - -/* - The unsigned integer type used for comparing any two chunk sizes. - This should be at least as wide as size_t, but should not be signed. -*/ - -#ifndef CHUNK_SIZE_T -#define CHUNK_SIZE_T unsigned long -#endif - -/* - The unsigned integer type used to hold addresses when they are are - manipulated as integers. Except that it is not defined on all - systems, intptr_t would suffice. -*/ -#ifndef PTR_UINT -#define PTR_UINT unsigned long -#endif - -/* - INTERNAL_SIZE_T is the word-size used for internal bookkeeping - of chunk sizes. - - The default version is the same as size_t. - - While not strictly necessary, it is best to define this as an - unsigned type, even if size_t is a signed type. This may avoid some - artificial size limitations on some systems. - - On a 64-bit machine, you may be able to reduce malloc overhead by - defining INTERNAL_SIZE_T to be a 32 bit `unsigned int' at the - expense of not being able to handle more than 2^32 of malloced - space. If this limitation is acceptable, you are encouraged to set - this unless you are on a platform requiring 16byte alignments. In - this case the alignment requirements turn out to negate any - potential advantages of decreasing size_t word size. - - Implementors: Beware of the possible combinations of: - - INTERNAL_SIZE_T might be signed or unsigned, might be 32 or 64 bits, - and might be the same width as int or as long - - size_t might have different width and signedness as INTERNAL_SIZE_T - - int and long might be 32 or 64 bits, and might be the same width - To deal with this, most comparisons and difference computations - among INTERNAL_SIZE_Ts should cast them to CHUNK_SIZE_T, being - aware of the fact that casting an unsigned int to a wider long does - not sign-extend. (This also makes checking for negative numbers - awkward.) Some of these casts result in harmless compiler warnings - on some systems. -*/ - -#ifndef INTERNAL_SIZE_T -#define INTERNAL_SIZE_T size_t -#endif - -/* The corresponding word size */ -#define SIZE_SZ (sizeof(INTERNAL_SIZE_T)) - -/* - MALLOC_ALIGNMENT is the minimum alignment for malloc'ed chunks. - It must be a power of two at least 2 * SIZE_SZ, even on machines - for which smaller alignments would suffice. It may be defined as - larger than this though. Note however that code and data structures - are optimized for the case of 8-byte alignment. -*/ - -#ifndef MALLOC_ALIGNMENT -#define MALLOC_ALIGNMENT (2 * SIZE_SZ) -#endif - -/* The corresponding bit mask value */ -#define MALLOC_ALIGN_MASK (MALLOC_ALIGNMENT - 1) - -/* - REALLOC_ZERO_BYTES_FREES should be set if a call to - realloc with zero bytes should be the same as a call to free. - Some people think it should. Otherwise, since this malloc - returns a unique pointer for malloc(0), so does realloc(p, 0). -*/ - -/* #define REALLOC_ZERO_BYTES_FREES */ - -/* - TRIM_FASTBINS controls whether free() of a very small chunk can - immediately lead to trimming. Setting to true (1) can reduce memory - footprint, but will almost always slow down programs that use a lot - of small chunks. - - Define this only if you are willing to give up some speed to more - aggressively reduce system-level memory footprint when releasing - memory in programs that use many small chunks. You can get - essentially the same effect by setting MXFAST to 0, but this can - lead to even greater slowdowns in programs using many small chunks. - TRIM_FASTBINS is an in-between compile-time option, that disables - only those chunks bordering topmost memory from being placed in - fastbins. -*/ - -#ifndef TRIM_FASTBINS -#define TRIM_FASTBINS 0 -#endif - -/* - USE_DL_PREFIX will prefix all public routines with the string 'dl'. - This is necessary when you only want to use this malloc in one part - of a program, using your regular system malloc elsewhere. -*/ - -/* #define USE_DL_PREFIX */ - -/* - USE_MALLOC_LOCK causes wrapper functions to surround each - callable routine with pthread mutex lock/unlock. - - USE_MALLOC_LOCK forces USE_PUBLIC_MALLOC_WRAPPERS to be defined -*/ - -/* #define USE_MALLOC_LOCK */ - -/* - If USE_PUBLIC_MALLOC_WRAPPERS is defined, every public routine is - actually a wrapper function that first calls MALLOC_PREACTION, then - calls the internal routine, and follows it with - MALLOC_POSTACTION. This is needed for locking, but you can also use - this, without USE_MALLOC_LOCK, for purposes of interception, - instrumentation, etc. It is a sad fact that using wrappers often - noticeably degrades performance of malloc-intensive programs. -*/ - -#ifdef USE_MALLOC_LOCK -#define USE_PUBLIC_MALLOC_WRAPPERS -#else -/* #define USE_PUBLIC_MALLOC_WRAPPERS */ -#endif - -/* - Two-phase name translation. - All of the actual routines are given mangled names. - When wrappers are used, they become the public callable versions. - When DL_PREFIX is used, the callable names are prefixed. -*/ - -#ifndef USE_PUBLIC_MALLOC_WRAPPERS -#define cALLOc public_cALLOc -#define fREe public_fREe -#define cFREe public_cFREe -#define mALLOc public_mALLOc -#define mEMALIGn public_mEMALIGn -#define rEALLOc public_rEALLOc -#define vALLOc public_vALLOc -#define pVALLOc public_pVALLOc -#define mALLINFo public_mALLINFo -#define mALLOPt public_mALLOPt -#define mTRIm public_mTRIm -#define mSTATs public_mSTATs -#define mUSABLe public_mUSABLe -#define iCALLOc public_iCALLOc -#define iCOMALLOc public_iCOMALLOc -#endif - -#ifdef USE_DL_PREFIX -#define public_cALLOc dlcalloc -#define public_fREe dlfree -#define public_cFREe dlcfree -#define public_mALLOc dlmalloc -#define public_mEMALIGn dlmemalign -#define public_rEALLOc dlrealloc -#define public_vALLOc dlvalloc -#define public_pVALLOc dlpvalloc -#define public_mALLINFo dlmallinfo -#define public_mALLOPt dlmallopt -#define public_mTRIm dlmalloc_trim -#define public_mSTATs dlmalloc_stats -#define public_mUSABLe dlmalloc_usable_size -#define public_iCALLOc dlindependent_calloc -#define public_iCOMALLOc dlindependent_comalloc -#else /* USE_DL_PREFIX */ -#define public_cALLOc calloc -#define public_fREe free -#define public_cFREe cfree -#define public_mALLOc malloc -#define public_mEMALIGn memalign -#define public_rEALLOc realloc -#define public_vALLOc valloc -#define public_pVALLOc pvalloc -#define public_mALLINFo mallinfo -#define public_mALLOPt mallopt -#define public_mTRIm malloc_trim -#define public_mSTATs malloc_stats -#define public_mUSABLe malloc_usable_size -#define public_iCALLOc independent_calloc -#define public_iCOMALLOc independent_comalloc -#endif /* USE_DL_PREFIX */ - -/* - HAVE_MEMCPY should be defined if you are not otherwise using - ANSI STD C, but still have memcpy and memset in your C library - and want to use them in calloc and realloc. Otherwise simple - macro versions are defined below. - - USE_MEMCPY should be defined as 1 if you actually want to - have memset and memcpy called. People report that the macro - versions are faster than libc versions on some systems. - - Even if USE_MEMCPY is set to 1, loops to copy/clear small chunks - (of <= 36 bytes) are manually unrolled in realloc and calloc. -*/ - -#define HAVE_MEMCPY - -#ifndef USE_MEMCPY -#ifdef HAVE_MEMCPY -#define USE_MEMCPY 1 -#else -#define USE_MEMCPY 0 -#endif -#endif - -#if (__STD_C || defined(HAVE_MEMCPY)) - -#ifdef WIN32 -/* On Win32 memset and memcpy are already declared in windows.h */ -#else -#if __STD_C -void *memset(void *, int, size_t); -void *memcpy(void *, const void *, size_t); -#else -Void_t *memset(); -Void_t *memcpy(); -#endif -#endif -#endif - -/* - MALLOC_FAILURE_ACTION is the action to take before "return 0" when - malloc fails to be able to return memory, either because memory is - exhausted or because of illegal arguments. - - By default, sets errno if running on STD_C platform, else does nothing. -*/ - -#ifndef MALLOC_FAILURE_ACTION -#if __STD_C -#define MALLOC_FAILURE_ACTION \ - errno = ENOMEM; - -#else -#define MALLOC_FAILURE_ACTION -#endif -#endif - -/* - MORECORE-related declarations. By default, rely on sbrk -*/ - -#ifdef LACKS_UNISTD_H -#if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__) -#if __STD_C -extern Void_t *sbrk(ptrdiff_t); -#else -extern Void_t *sbrk(); -#endif -#endif -#endif - -/* - MORECORE is the name of the routine to call to obtain more memory - from the system. See below for general guidance on writing - alternative MORECORE functions, as well as a version for WIN32 and a - sample version for pre-OSX macos. -*/ - -// #define _GNU_SOURCE -// #include -extern void *sbrk(intptr_t __delta) __THROW; -#define MORECORE sbrk - -/* - MORECORE_FAILURE is the value returned upon failure of MORECORE - as well as mmap. Since it cannot be an otherwise valid memory address, - and must reflect values of standard sys calls, you probably ought not - try to redefine it. -*/ - -#ifndef MORECORE_FAILURE -#define MORECORE_FAILURE (-1) -#endif - -/* - If MORECORE_CONTIGUOUS is true, take advantage of fact that - consecutive calls to MORECORE with positive arguments always return - contiguous increasing addresses. This is true of unix sbrk. Even - if not defined, when regions happen to be contiguous, malloc will - permit allocations spanning regions obtained from different - calls. But defining this when applicable enables some stronger - consistency checks and space efficiencies. -*/ - -#ifndef MORECORE_CONTIGUOUS -#define MORECORE_CONTIGUOUS 1 -#endif - -/* - Define MORECORE_CANNOT_TRIM if your version of MORECORE - cannot release space back to the system when given negative - arguments. This is generally necessary only if you are using - a hand-crafted MORECORE function that cannot handle negative arguments. -*/ - -/* #define MORECORE_CANNOT_TRIM */ - -/* - Define HAVE_MMAP as true to optionally make malloc() use mmap() to - allocate very large blocks. These will be returned to the - operating system immediately after a free(). Also, if mmap - is available, it is used as a backup strategy in cases where - MORECORE fails to provide space from system. - - This malloc is best tuned to work with mmap for large requests. - If you do not have mmap, operations involving very large chunks (1MB - or so) may be slower than you'd like. -*/ - -#ifndef HAVE_MMAP -#define HAVE_MMAP 1 -#endif - -#if HAVE_MMAP -/* - Standard unix mmap using /dev/zero clears memory so calloc doesn't - need to. -*/ - -#ifndef MMAP_CLEARS -#define MMAP_CLEARS 1 -#endif - -#else /* no mmap */ -#ifndef MMAP_CLEARS -#define MMAP_CLEARS 0 -#endif -#endif - -/* - MMAP_AS_MORECORE_SIZE is the minimum mmap size argument to use if - sbrk fails, and mmap is used as a backup (which is done only if - HAVE_MMAP). The value must be a multiple of page size. This - backup strategy generally applies only when systems have "holes" in - address space, so sbrk cannot perform contiguous expansion, but - there is still space available on system. On systems for which - this is known to be useful (i.e. most linux kernels), this occurs - only when programs allocate huge amounts of memory. Between this, - and the fact that mmap regions tend to be limited, the size should - be large, to avoid too many mmap calls and thus avoid running out - of kernel resources. -*/ - -#ifndef MMAP_AS_MORECORE_SIZE -#define MMAP_AS_MORECORE_SIZE (1024 * 1024) -#endif - -/* - Define HAVE_MREMAP to make realloc() use mremap() to re-allocate - large blocks. This is currently only possible on Linux with - kernel versions newer than 1.3.77. -*/ - -#ifndef HAVE_MREMAP -#if defined(linux) && defined(__USE_GNU) -#define HAVE_MREMAP 1 -#else -#define HAVE_MREMAP 0 -#endif - -#endif /* HAVE_MMAP */ - -/* - The system page size. To the extent possible, this malloc manages - memory from the system in page-size units. Note that this value is - cached during initialization into a field of malloc_state. So even - if malloc_getpagesize is a function, it is only called once. - - The following mechanics for getpagesize were adapted from bsd/gnu - getpagesize.h. If none of the system-probes here apply, a value of - 4096 is used, which should be OK: If they don't apply, then using - the actual value probably doesn't impact performance. -*/ - -#ifndef malloc_getpagesize - -#ifndef LACKS_UNISTD_H -#include -#endif - -#ifdef _SC_PAGESIZE /* some SVR4 systems omit an underscore */ -#ifndef _SC_PAGE_SIZE -#define _SC_PAGE_SIZE _SC_PAGESIZE -#endif -#endif - -#ifdef _SC_PAGE_SIZE -#define malloc_getpagesize sysconf(_SC_PAGE_SIZE) -#else -#if defined(BSD) || defined(DGUX) || defined(HAVE_GETPAGESIZE) -extern size_t getpagesize(); -#define malloc_getpagesize getpagesize() -#else -#ifdef WIN32 /* use supplied emulation of getpagesize */ -#define malloc_getpagesize getpagesize() -#else -#ifndef LACKS_SYS_PARAM_H -#include -#endif -#ifdef EXEC_PAGESIZE -#define malloc_getpagesize EXEC_PAGESIZE -#else -#ifdef NBPG -#ifndef CLSIZE -#define malloc_getpagesize NBPG -#else -#define malloc_getpagesize (NBPG * CLSIZE) -#endif -#else -#ifdef NBPC -#define malloc_getpagesize NBPC -#else -#ifdef PAGESIZE -#define malloc_getpagesize PAGESIZE -#else /* just guess */ -#define malloc_getpagesize (4096) -#endif -#endif -#endif -#endif -#endif -#endif -#endif -#endif - -/* - This version of malloc supports the standard SVID/XPG mallinfo - routine that returns a struct containing usage properties and - statistics. It should work on any SVID/XPG compliant system that has - a /usr/include/malloc.h defining struct mallinfo. (If you'd like to - install such a thing yourself, cut out the preliminary declarations - as described above and below and save them in a malloc.h file. But - there's no compelling reason to bother to do this.) - - The main declaration needed is the mallinfo struct that is returned - (by-copy) by mallinfo(). The SVID/XPG malloinfo struct contains a - bunch of fields that are not even meaningful in this version of - malloc. These fields are are instead filled by mallinfo() with - other numbers that might be of interest. - - HAVE_USR_INCLUDE_MALLOC_H should be set if you have a - /usr/include/malloc.h file that includes a declaration of struct - mallinfo. If so, it is included; else an SVID2/XPG2 compliant - version is declared below. These must be precisely the same for - mallinfo() to work. The original SVID version of this struct, - defined on most systems with mallinfo, declares all fields as - ints. But some others define as unsigned long. If your system - defines the fields using a type of different width than listed here, - you must #include your system version and #define - HAVE_USR_INCLUDE_MALLOC_H. -*/ - -/* #define HAVE_USR_INCLUDE_MALLOC_H */ - -#ifdef HAVE_USR_INCLUDE_MALLOC_H -#include "/usr/include/malloc.h" -#else - -/* SVID2/XPG mallinfo structure */ - -/* - SVID/XPG defines four standard parameter numbers for mallopt, - normally defined in malloc.h. Only one of these (M_MXFAST) is used - in this malloc. The others (M_NLBLKS, M_GRAIN, M_KEEP) don't apply, - so setting them has no effect. But this malloc also supports other - options in mallopt described below. -*/ -#endif - -/* ---------- description of public routines ------------ */ - -/* - malloc(size_t n) - Returns a pointer to a newly allocated chunk of at least n bytes, or null - if no space is available. Additionally, on failure, errno is - set to ENOMEM on ANSI C systems. - - If n is zero, malloc returns a minumum-sized chunk. (The minimum - size is 16 bytes on most 32bit systems, and 24 or 32 bytes on 64bit - systems.) On most systems, size_t is an unsigned type, so calls - with negative arguments are interpreted as requests for huge amounts - of space, which will often fail. The maximum supported value of n - differs across systems, but is in all cases less than the maximum - representable value of a size_t. -*/ -#if __STD_C -Void_t *public_mALLOc(size_t); -#else -Void_t *public_mALLOc(); -#endif - -/* - free(Void_t* p) - Releases the chunk of memory pointed to by p, that had been previously - allocated using malloc or a related routine such as realloc. - It has no effect if p is null. It can have arbitrary (i.e., bad!) - effects if p has already been freed. - - Unless disabled (using mallopt), freeing very large spaces will - when possible, automatically trigger operations that give - back unused memory to the system, thus reducing program footprint. -*/ -#if __STD_C -void public_fREe(Void_t *); -#else -void public_fREe(); -#endif - -/* - calloc(size_t n_elements, size_t element_size); - Returns a pointer to n_elements * element_size bytes, with all locations - set to zero. -*/ -#if __STD_C -Void_t *public_cALLOc(size_t, size_t); -#else -Void_t *public_cALLOc(); -#endif - -/* - realloc(Void_t* p, size_t n) - Returns a pointer to a chunk of size n that contains the same data - as does chunk p up to the minimum of (n, p's size) bytes, or null - if no space is available. - - The returned pointer may or may not be the same as p. The algorithm - prefers extending p when possible, otherwise it employs the - equivalent of a malloc-copy-free sequence. - - If p is null, realloc is equivalent to malloc. - - If space is not available, realloc returns null, errno is set (if on - ANSI) and p is NOT freed. - - if n is for fewer bytes than already held by p, the newly unused - space is lopped off and freed if possible. Unless the #define - REALLOC_ZERO_BYTES_FREES is set, realloc with a size argument of - zero (re)allocates a minimum-sized chunk. - - Large chunks that were internally obtained via mmap will always - be reallocated using malloc-copy-free sequences unless - the system supports MREMAP (currently only linux). - - The old unix realloc convention of allowing the last-free'd chunk - to be used as an argument to realloc is not supported. -*/ -#if __STD_C -Void_t *public_rEALLOc(Void_t *, size_t); -#else -Void_t *public_rEALLOc(); -#endif - -/* - memalign(size_t alignment, size_t n); - Returns a pointer to a newly allocated chunk of n bytes, aligned - in accord with the alignment argument. - - The alignment argument should be a power of two. If the argument is - not a power of two, the nearest greater power is used. - 8-byte alignment is guaranteed by normal malloc calls, so don't - bother calling memalign with an argument of 8 or less. - - Overreliance on memalign is a sure way to fragment space. -*/ -#if __STD_C -Void_t *public_mEMALIGn(size_t, size_t); -#else -Void_t *public_mEMALIGn(); -#endif - -/* - valloc(size_t n); - Equivalent to memalign(pagesize, n), where pagesize is the page - size of the system. If the pagesize is unknown, 4096 is used. -*/ -#if __STD_C -Void_t *public_vALLOc(size_t); -#else -Void_t *public_vALLOc(); -#endif - -/* - mallopt(int parameter_number, int parameter_value) - Sets tunable parameters The format is to provide a - (parameter-number, parameter-value) pair. mallopt then sets the - corresponding parameter to the argument value if it can (i.e., so - long as the value is meaningful), and returns 1 if successful else - 0. SVID/XPG/ANSI defines four standard param numbers for mallopt, - normally defined in malloc.h. Only one of these (M_MXFAST) is used - in this malloc. The others (M_NLBLKS, M_GRAIN, M_KEEP) don't apply, - so setting them has no effect. But this malloc also supports four - other options in mallopt. See below for details. Briefly, supported - parameters are as follows (listed defaults are for "typical" - configurations). - - Symbol param # default allowed param values - M_MXFAST 1 64 0-80 (0 disables fastbins) - M_TRIM_THRESHOLD -1 256*1024 any (-1U disables trimming) - M_TOP_PAD -2 0 any - M_MMAP_THRESHOLD -3 256*1024 any (or 0 if no MMAP support) - M_MMAP_MAX -4 65536 any (0 disables use of mmap) -*/ -#if __STD_C -int public_mALLOPt(int, int); -#else -int public_mALLOPt(); -#endif - -/* - mallinfo() - Returns (by copy) a struct containing various summary statistics: - - arena: current total non-mmapped bytes allocated from system - ordblks: the number of free chunks - smblks: the number of fastbin blocks (i.e., small chunks that - have been freed but not use resused or consolidated) - hblks: current number of mmapped regions - hblkhd: total bytes held in mmapped regions - usmblks: the maximum total allocated space. This will be greater - than current total if trimming has occurred. - fsmblks: total bytes held in fastbin blocks - uordblks: current total allocated space (normal or mmapped) - fordblks: total free space - keepcost: the maximum number of bytes that could ideally be released - back to system via malloc_trim. ("ideally" means that - it ignores page restrictions etc.) - - Because these fields are ints, but internal bookkeeping may - be kept as longs, the reported values may wrap around zero and - thus be inaccurate. -*/ -#if __STD_C -struct mallinfo public_mALLINFo(void); -#else -struct mallinfo public_mALLINFo(); -#endif - -/* - independent_calloc(size_t n_elements, size_t element_size, Void_t* chunks[]); - - independent_calloc is similar to calloc, but instead of returning a - single cleared space, it returns an array of pointers to n_elements - independent elements that can hold contents of size elem_size, each - of which starts out cleared, and can be independently freed, - realloc'ed etc. The elements are guaranteed to be adjacently - allocated (this is not guaranteed to occur with multiple callocs or - mallocs), which may also improve cache locality in some - applications. - - The "chunks" argument is optional (i.e., may be null, which is - probably the most typical usage). If it is null, the returned array - is itself dynamically allocated and should also be freed when it is - no longer needed. Otherwise, the chunks array must be of at least - n_elements in length. It is filled in with the pointers to the - chunks. - - In either case, independent_calloc returns this pointer array, or - null if the allocation failed. If n_elements is zero and "chunks" - is null, it returns a chunk representing an array with zero elements - (which should be freed if not wanted). - - Each element must be individually freed when it is no longer - needed. If you'd like to instead be able to free all at once, you - should instead use regular calloc and assign pointers into this - space to represent elements. (In this case though, you cannot - independently free elements.) - - independent_calloc simplifies and speeds up implementations of many - kinds of pools. It may also be useful when constructing large data - structures that initially have a fixed number of fixed-sized nodes, - but the number is not known at compile time, and some of the nodes - may later need to be freed. For example: - - struct Node { int item; struct Node* next; }; - - struct Node* build_list() { - struct Node** pool; - int n = read_number_of_nodes_needed(); - if (n <= 0) return 0; - pool = (struct Node**)(independent_calloc(n, sizeof(struct Node), 0); - if (pool == 0) die(); - // organize into a linked list... - struct Node* first = pool[0]; - for (i = 0; i < n-1; ++i) - pool[i]->next = pool[i+1]; - free(pool); // Can now free the array (or not, if it is needed later) - return first; - } -*/ -#if __STD_C -Void_t **public_iCALLOc(size_t, size_t, Void_t **); -#else -Void_t **public_iCALLOc(); -#endif - -/* - independent_comalloc(size_t n_elements, size_t sizes[], Void_t* chunks[]); - - independent_comalloc allocates, all at once, a set of n_elements - chunks with sizes indicated in the "sizes" array. It returns - an array of pointers to these elements, each of which can be - independently freed, realloc'ed etc. The elements are guaranteed to - be adjacently allocated (this is not guaranteed to occur with - multiple callocs or mallocs), which may also improve cache locality - in some applications. - - The "chunks" argument is optional (i.e., may be null). If it is null - the returned array is itself dynamically allocated and should also - be freed when it is no longer needed. Otherwise, the chunks array - must be of at least n_elements in length. It is filled in with the - pointers to the chunks. - - In either case, independent_comalloc returns this pointer array, or - null if the allocation failed. If n_elements is zero and chunks is - null, it returns a chunk representing an array with zero elements - (which should be freed if not wanted). - - Each element must be individually freed when it is no longer - needed. If you'd like to instead be able to free all at once, you - should instead use a single regular malloc, and assign pointers at - particular offsets in the aggregate space. (In this case though, you - cannot independently free elements.) - - independent_comallac differs from independent_calloc in that each - element may have a different size, and also that it does not - automatically clear elements. - - independent_comalloc can be used to speed up allocation in cases - where several structs or objects must always be allocated at the - same time. For example: - - struct Head { ... } - struct Foot { ... } - - void send_message(char* msg) { - int msglen = strlen(msg); - size_t sizes[3] = { sizeof(struct Head), msglen, sizeof(struct Foot) }; - void* chunks[3]; - if (independent_comalloc(3, sizes, chunks) == 0) - die(); - struct Head* head = (struct Head*)(chunks[0]); - char* body = (char*)(chunks[1]); - struct Foot* foot = (struct Foot*)(chunks[2]); - // ... - } - - In general though, independent_comalloc is worth using only for - larger values of n_elements. For small values, you probably won't - detect enough difference from series of malloc calls to bother. - - Overuse of independent_comalloc can increase overall memory usage, - since it cannot reuse existing noncontiguous small chunks that - might be available for some of the elements. -*/ -#if __STD_C -Void_t **public_iCOMALLOc(size_t, size_t *, Void_t **); -#else -Void_t **public_iCOMALLOc(); -#endif - -/* - pvalloc(size_t n); - Equivalent to valloc(minimum-page-that-holds(n)), that is, - round up n to nearest pagesize. - */ -#if __STD_C -Void_t *public_pVALLOc(size_t); -#else -Void_t *public_pVALLOc(); -#endif - -/* - cfree(Void_t* p); - Equivalent to free(p). - - cfree is needed/defined on some systems that pair it with calloc, - for odd historical reasons (such as: cfree is used in example - code in the first edition of K&R). -*/ -#if __STD_C -void public_cFREe(Void_t *); -#else -void public_cFREe(); -#endif - -/* - malloc_trim(size_t pad); - - If possible, gives memory back to the system (via negative - arguments to sbrk) if there is unused memory at the `high' end of - the malloc pool. You can call this after freeing large blocks of - memory to potentially reduce the system-level memory requirements - of a program. However, it cannot guarantee to reduce memory. Under - some allocation patterns, some large free blocks of memory will be - locked between two used chunks, so they cannot be given back to - the system. - - The `pad' argument to malloc_trim represents the amount of free - trailing space to leave untrimmed. If this argument is zero, - only the minimum amount of memory to maintain internal data - structures will be left (one page or less). Non-zero arguments - can be supplied to maintain enough trailing space to service - future expected allocations without having to re-obtain memory - from the system. - - Malloc_trim returns 1 if it actually released any memory, else 0. - On systems that do not support "negative sbrks", it will always - rreturn 0. -*/ -#if __STD_C -int public_mTRIm(size_t); -#else -int public_mTRIm(); -#endif - -/* - malloc_usable_size(Void_t* p); - - Returns the number of bytes you can actually use in - an allocated chunk, which may be more than you requested (although - often not) due to alignment and minimum size constraints. - You can use this many bytes without worrying about - overwriting other allocated objects. This is not a particularly great - programming practice. malloc_usable_size can be more useful in - debugging and assertions, for example: - - p = malloc(n); - assert(malloc_usable_size(p) >= 256); - -*/ -#if __STD_C -size_t public_mUSABLe(Void_t *); -#else -size_t public_mUSABLe(); -#endif - -/* - malloc_stats(); - Prints on stderr the amount of space obtained from the system (both - via sbrk and mmap), the maximum amount (which may be more than - current if malloc_trim and/or munmap got called), and the current - number of bytes allocated via malloc (or realloc, etc) but not yet - freed. Note that this is the number of bytes allocated, not the - number requested. It will be larger than the number requested - because of alignment and bookkeeping overhead. Because it includes - alignment wastage as being in use, this figure may be greater than - zero even when no user-level chunks are allocated. - - The reported current and maximum system memory can be inaccurate if - a program makes other calls to system memory allocation functions - (normally sbrk) outside of malloc. - - malloc_stats prints only the most commonly interesting statistics. - More information can be obtained by calling mallinfo. - -*/ -#if __STD_C -void public_mSTATs(void); -#else -void public_mSTATs(void); -#endif - -/* mallopt tuning options */ - -/* - M_MXFAST is the maximum request size used for "fastbins", special bins - that hold returned chunks without consolidating their spaces. This - enables future requests for chunks of the same size to be handled - very quickly, but can increase fragmentation, and thus increase the - overall memory footprint of a program. - - This malloc manages fastbins very conservatively yet still - efficiently, so fragmentation is rarely a problem for values less - than or equal to the default. The maximum supported value of MXFAST - is 80. You wouldn't want it any higher than this anyway. Fastbins - are designed especially for use with many small structs, objects or - strings -- the default handles structs/objects/arrays with sizes up - to 16 4byte fields, or small strings representing words, tokens, - etc. Using fastbins for larger objects normally worsens - fragmentation without improving speed. - - M_MXFAST is set in REQUEST size units. It is internally used in - chunksize units, which adds padding and alignment. You can reduce - M_MXFAST to 0 to disable all use of fastbins. This causes the malloc - algorithm to be a closer approximation of fifo-best-fit in all cases, - not just for larger requests, but will generally cause it to be - slower. -*/ - -/* M_MXFAST is a standard SVID/XPG tuning option, usually listed in malloc.h */ -#ifndef M_MXFAST -#define M_MXFAST 1 -#endif - -#ifndef DEFAULT_MXFAST -#define DEFAULT_MXFAST 64 -#endif - -/* - M_TRIM_THRESHOLD is the maximum amount of unused top-most memory - to keep before releasing via malloc_trim in free(). - - Automatic trimming is mainly useful in long-lived programs. - Because trimming via sbrk can be slow on some systems, and can - sometimes be wasteful (in cases where programs immediately - afterward allocate more large chunks) the value should be high - enough so that your overall system performance would improve by - releasing this much memory. - - The trim threshold and the mmap control parameters (see below) - can be traded off with one another. Trimming and mmapping are - two different ways of releasing unused memory back to the - system. Between these two, it is often possible to keep - system-level demands of a long-lived program down to a bare - minimum. For example, in one test suite of sessions measuring - the XF86 X server on Linux, using a trim threshold of 128K and a - mmap threshold of 192K led to near-minimal long term resource - consumption. - - If you are using this malloc in a long-lived program, it should - pay to experiment with these values. As a rough guide, you - might set to a value close to the average size of a process - (program) running on your system. Releasing this much memory - would allow such a process to run in memory. Generally, it's - worth it to tune for trimming rather tham memory mapping when a - program undergoes phases where several large chunks are - allocated and released in ways that can reuse each other's - storage, perhaps mixed with phases where there are no such - chunks at all. And in well-behaved long-lived programs, - controlling release of large blocks via trimming versus mapping - is usually faster. - - However, in most programs, these parameters serve mainly as - protection against the system-level effects of carrying around - massive amounts of unneeded memory. Since frequent calls to - sbrk, mmap, and munmap otherwise degrade performance, the default - parameters are set to relatively high values that serve only as - safeguards. - - The trim value must be greater than page size to have any useful - effect. To disable trimming completely, you can set to - (unsigned long)(-1) - - Trim settings interact with fastbin (MXFAST) settings: Unless - TRIM_FASTBINS is defined, automatic trimming never takes place upon - freeing a chunk with size less than or equal to MXFAST. Trimming is - instead delayed until subsequent freeing of larger chunks. However, - you can still force an attempted trim by calling malloc_trim. - - Also, trimming is not generally possible in cases where - the main arena is obtained via mmap. - - Note that the trick some people use of mallocing a huge space and - then freeing it at program startup, in an attempt to reserve system - memory, doesn't have the intended effect under automatic trimming, - since that memory will immediately be returned to the system. -*/ - -#define M_TRIM_THRESHOLD -1 - -#ifndef DEFAULT_TRIM_THRESHOLD -#define DEFAULT_TRIM_THRESHOLD (256 * 1024) -#endif - -/* - M_TOP_PAD is the amount of extra `padding' space to allocate or - retain whenever sbrk is called. It is used in two ways internally: - - * When sbrk is called to extend the top of the arena to satisfy - a new malloc request, this much padding is added to the sbrk - request. - - * When malloc_trim is called automatically from free(), - it is used as the `pad' argument. - - In both cases, the actual amount of padding is rounded - so that the end of the arena is always a system page boundary. - - The main reason for using padding is to avoid calling sbrk so - often. Having even a small pad greatly reduces the likelihood - that nearly every malloc request during program start-up (or - after trimming) will invoke sbrk, which needlessly wastes - time. - - Automatic rounding-up to page-size units is normally sufficient - to avoid measurable overhead, so the default is 0. However, in - systems where sbrk is relatively slow, it can pay to increase - this value, at the expense of carrying around more memory than - the program needs. -*/ - -#define M_TOP_PAD -2 - -#ifndef DEFAULT_TOP_PAD -#define DEFAULT_TOP_PAD (0) -#endif - -/* - M_MMAP_THRESHOLD is the request size threshold for using mmap() - to service a request. Requests of at least this size that cannot - be allocated using already-existing space will be serviced via mmap. - (If enough normal freed space already exists it is used instead.) - - Using mmap segregates relatively large chunks of memory so that - they can be individually obtained and released from the host - system. A request serviced through mmap is never reused by any - other request (at least not directly; the system may just so - happen to remap successive requests to the same locations). - - Segregating space in this way has the benefits that: - - 1. Mmapped space can ALWAYS be individually released back - to the system, which helps keep the system level memory - demands of a long-lived program low. - 2. Mapped memory can never become `locked' between - other chunks, as can happen with normally allocated chunks, which - means that even trimming via malloc_trim would not release them. - 3. On some systems with "holes" in address spaces, mmap can obtain - memory that sbrk cannot. - - However, it has the disadvantages that: - - 1. The space cannot be reclaimed, consolidated, and then - used to service later requests, as happens with normal chunks. - 2. It can lead to more wastage because of mmap page alignment - requirements - 3. It causes malloc performance to be more dependent on host - system memory management support routines which may vary in - implementation quality and may impose arbitrary - limitations. Generally, servicing a request via normal - malloc steps is faster than going through a system's mmap. - - The advantages of mmap nearly always outweigh disadvantages for - "large" chunks, but the value of "large" varies across systems. The - default is an empirically derived value that works well in most - systems. -*/ - -#define M_MMAP_THRESHOLD -3 - -#ifndef DEFAULT_MMAP_THRESHOLD -#define DEFAULT_MMAP_THRESHOLD (256 * 1024) -#endif - -/* - M_MMAP_MAX is the maximum number of requests to simultaneously - service using mmap. This parameter exists because -. Some systems have a limited number of internal tables for - use by mmap, and using more than a few of them may degrade - performance. - - The default is set to a value that serves only as a safeguard. - Setting to 0 disables use of mmap for servicing large requests. If - HAVE_MMAP is not set, the default value is 0, and attempts to set it - to non-zero values in mallopt will fail. -*/ - -#define M_MMAP_MAX -4 - -#ifndef DEFAULT_MMAP_MAX -#if HAVE_MMAP -#define DEFAULT_MMAP_MAX (65536) -#else -#define DEFAULT_MMAP_MAX (0) -#endif -#endif - -/* - ======================================================================== - To make a fully customizable malloc.h header file, cut everything - above this line, put into file malloc.h, edit to suit, and #include it - on the next line, as well as in programs that use this malloc. - ======================================================================== -*/ - -/* #include "malloc.h" */ - -/* --------------------- public wrappers ---------------------- */ - -#ifdef USE_PUBLIC_MALLOC_WRAPPERS - -/* Declare all routines as internal */ -#if __STD_C -static Void_t *mALLOc(size_t); -static void fREe(Void_t *); -static Void_t *rEALLOc(Void_t *, size_t); -static Void_t *mEMALIGn(size_t, size_t); -static Void_t *vALLOc(size_t); -static Void_t *pVALLOc(size_t); -static Void_t *cALLOc(size_t, size_t); -static Void_t **iCALLOc(size_t, size_t, Void_t **); -static Void_t **iCOMALLOc(size_t, size_t *, Void_t **); -static void cFREe(Void_t *); -static int mTRIm(size_t); -static size_t mUSABLe(Void_t *); -static void mSTATs(); -static int mALLOPt(int, int); -static struct mallinfo mALLINFo(void); -#else -static Void_t *mALLOc(); -static void fREe(); -static Void_t *rEALLOc(); -static Void_t *mEMALIGn(); -static Void_t *vALLOc(); -static Void_t *pVALLOc(); -static Void_t *cALLOc(); -static Void_t **iCALLOc(); -static Void_t **iCOMALLOc(); -static void cFREe(); -static int mTRIm(); -static size_t mUSABLe(); -static void mSTATs(); -static int mALLOPt(); -static struct mallinfo mALLINFo(); -#endif - -/* - MALLOC_PREACTION and MALLOC_POSTACTION should be - defined to return 0 on success, and nonzero on failure. - The return value of MALLOC_POSTACTION is currently ignored - in wrapper functions since there is no reasonable default - action to take on failure. -*/ - -#ifdef USE_MALLOC_LOCK - -#ifdef WIN32 - -static int mALLOC_MUTEx; -#define MALLOC_PREACTION slwait(&mALLOC_MUTEx) -#define MALLOC_POSTACTION slrelease(&mALLOC_MUTEx) - -#else - -#include - -static pthread_mutex_t mALLOC_MUTEx = PTHREAD_MUTEX_INITIALIZER; - -#define MALLOC_PREACTION pthread_mutex_lock(&mALLOC_MUTEx) -#define MALLOC_POSTACTION pthread_mutex_unlock(&mALLOC_MUTEx) - -#endif /* USE_MALLOC_LOCK */ - -#else - -/* Substitute anything you like for these */ - -#define MALLOC_PREACTION (0) -#define MALLOC_POSTACTION (0) - -#endif - -Void_t *public_mALLOc(size_t bytes) { - Void_t *m; - if (MALLOC_PREACTION != 0) { - return 0; - } - m = mALLOc(bytes); - if (MALLOC_POSTACTION != 0) { - } - return m; -} - -void public_fREe(Void_t *m) { - if (MALLOC_PREACTION != 0) { - return; - } - fREe(m); - if (MALLOC_POSTACTION != 0) { - } -} - -Void_t *public_rEALLOc(Void_t *m, size_t bytes) { - if (MALLOC_PREACTION != 0) { - return 0; - } - m = rEALLOc(m, bytes); - if (MALLOC_POSTACTION != 0) { - } - return m; -} - -Void_t *public_mEMALIGn(size_t alignment, size_t bytes) { - Void_t *m; - if (MALLOC_PREACTION != 0) { - return 0; - } - m = mEMALIGn(alignment, bytes); - if (MALLOC_POSTACTION != 0) { - } - return m; -} - -Void_t *public_vALLOc(size_t bytes) { - Void_t *m; - if (MALLOC_PREACTION != 0) { - return 0; - } - m = vALLOc(bytes); - if (MALLOC_POSTACTION != 0) { - } - return m; -} - -Void_t *public_pVALLOc(size_t bytes) { - Void_t *m; - if (MALLOC_PREACTION != 0) { - return 0; - } - m = pVALLOc(bytes); - if (MALLOC_POSTACTION != 0) { - } - return m; -} - -Void_t *public_cALLOc(size_t n, size_t elem_size) { - Void_t *m; - if (MALLOC_PREACTION != 0) { - return 0; - } - m = cALLOc(n, elem_size); - if (MALLOC_POSTACTION != 0) { - } - return m; -} - -Void_t **public_iCALLOc(size_t n, size_t elem_size, Void_t **chunks) { - Void_t **m; - if (MALLOC_PREACTION != 0) { - return 0; - } - m = iCALLOc(n, elem_size, chunks); - if (MALLOC_POSTACTION != 0) { - } - return m; -} - -Void_t **public_iCOMALLOc(size_t n, size_t sizes[], Void_t **chunks) { - Void_t **m; - if (MALLOC_PREACTION != 0) { - return 0; - } - m = iCOMALLOc(n, sizes, chunks); - if (MALLOC_POSTACTION != 0) { - } - return m; -} - -void public_cFREe(Void_t *m) { - if (MALLOC_PREACTION != 0) { - return; - } - cFREe(m); - if (MALLOC_POSTACTION != 0) { - } -} - -int public_mTRIm(size_t s) { - int result; - if (MALLOC_PREACTION != 0) { - return 0; - } - result = mTRIm(s); - if (MALLOC_POSTACTION != 0) { - } - return result; -} - -size_t public_mUSABLe(Void_t *m) { - size_t result; - if (MALLOC_PREACTION != 0) { - return 0; - } - result = mUSABLe(m); - if (MALLOC_POSTACTION != 0) { - } - return result; -} - -void public_mSTATs() { - if (MALLOC_PREACTION != 0) { - return; - } - mSTATs(); - if (MALLOC_POSTACTION != 0) { - } -} - -struct mallinfo public_mALLINFo() { - struct mallinfo m; - if (MALLOC_PREACTION != 0) { - struct mallinfo nm = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - return nm; - } - m = mALLINFo(); - if (MALLOC_POSTACTION != 0) { - } - return m; -} - -int public_mALLOPt(int p, int v) { - int result; - if (MALLOC_PREACTION != 0) { - return 0; - } - result = mALLOPt(p, v); - if (MALLOC_POSTACTION != 0) { - } - return result; -} - -#endif - -/* ------------- Optional versions of memcopy ---------------- */ - -#if USE_MEMCPY - -/* - Note: memcpy is ONLY invoked with non-overlapping regions, - so the (usually slower) memmove is not needed. -*/ - -#define MALLOC_COPY(dest, src, nbytes) memcpy(dest, src, nbytes) -#define MALLOC_ZERO(dest, nbytes) memset(dest, 0, nbytes) - -#else /* !USE_MEMCPY */ - -/* Use Duff's device for good zeroing/copying performance. */ - -#define MALLOC_ZERO(charp, nbytes) \ - do { \ - INTERNAL_SIZE_T *mzp = (INTERNAL_SIZE_T *)(charp); \ - CHUNK_SIZE_T mctmp = (nbytes) / sizeof(INTERNAL_SIZE_T); \ - long mcn; \ - if (mctmp < 8) \ - mcn = 0; \ - else { \ - mcn = (mctmp - 1) / 8; \ - mctmp %= 8; \ - } \ - switch (mctmp) { \ - case 0: \ - for (;;) { \ - *mzp++ = 0; \ - case 7: \ - *mzp++ = 0; \ - case 6: \ - *mzp++ = 0; \ - case 5: \ - *mzp++ = 0; \ - case 4: \ - *mzp++ = 0; \ - case 3: \ - *mzp++ = 0; \ - case 2: \ - *mzp++ = 0; \ - case 1: \ - *mzp++ = 0; \ - if (mcn <= 0) \ - break; \ - mcn--; \ - } \ - } \ - } while (0) - -#define MALLOC_COPY(dest, src, nbytes) \ - do { \ - INTERNAL_SIZE_T *mcsrc = (INTERNAL_SIZE_T *)src; \ - INTERNAL_SIZE_T *mcdst = (INTERNAL_SIZE_T *)dest; \ - CHUNK_SIZE_T mctmp = (nbytes) / sizeof(INTERNAL_SIZE_T); \ - long mcn; \ - if (mctmp < 8) \ - mcn = 0; \ - else { \ - mcn = (mctmp - 1) / 8; \ - mctmp %= 8; \ - } \ - switch (mctmp) { \ - case 0: \ - for (;;) { \ - *mcdst++ = *mcsrc++; \ - case 7: \ - *mcdst++ = *mcsrc++; \ - case 6: \ - *mcdst++ = *mcsrc++; \ - case 5: \ - *mcdst++ = *mcsrc++; \ - case 4: \ - *mcdst++ = *mcsrc++; \ - case 3: \ - *mcdst++ = *mcsrc++; \ - case 2: \ - *mcdst++ = *mcsrc++; \ - case 1: \ - *mcdst++ = *mcsrc++; \ - if (mcn <= 0) \ - break; \ - mcn--; \ - } \ - } \ - } while (0) - -#endif - -/* ------------------ MMAP support ------------------ */ - -#if HAVE_MMAP - -#ifndef LACKS_FCNTL_H -#include -#endif - -#ifndef LACKS_SYS_MMAN_H -#include -#endif - -#if !defined(MAP_ANONYMOUS) && defined(MAP_ANON) -#define MAP_ANONYMOUS MAP_ANON -#endif - -/* - Nearly all versions of mmap support MAP_ANONYMOUS, - so the following is unlikely to be needed, but is - supplied just in case. -*/ - -#ifndef MAP_ANONYMOUS - -static int dev_zero_fd = -1; /* Cached file descriptor for /dev/zero. */ - -#define MMAP(addr, size, prot, flags) ((dev_zero_fd < 0) ? (dev_zero_fd = open("/dev/zero", O_RDWR), \ - mmap((addr), (size), (prot), (flags), dev_zero_fd, 0)) \ - : mmap((addr), (size), (prot), (flags), dev_zero_fd, 0)) - -#else - -#define MMAP(addr, size, prot, flags) \ - (mmap((addr), (size), (prot), (flags) | MAP_ANONYMOUS, -1, 0)) - -#endif - -#endif /* HAVE_MMAP */ - -/* - ----------------------- Chunk representations ----------------------- -*/ - -/* - This struct declaration is misleading (but accurate and necessary). - It declares a "view" into memory allowing access to necessary - fields at known offsets from a given base. See explanation below. -*/ - -struct malloc_chunk { - - INTERNAL_SIZE_T prev_size; /* Size of previous chunk (if free). */ - INTERNAL_SIZE_T size; /* Size in bytes, including overhead. */ - - struct malloc_chunk *fd; /* double links -- used only if free. */ - struct malloc_chunk *bk; -}; - -typedef struct malloc_chunk *mchunkptr; - -/* - malloc_chunk details: - - (The following includes lightly edited explanations by Colin Plumb.) - - Chunks of memory are maintained using a `boundary tag' method as - described in e.g., Knuth or Standish. (See the paper by Paul - Wilson ftp://ftp.cs.utexas.edu/pub/garbage/allocsrv.ps for a - survey of such techniques.) Sizes of free chunks are stored both - in the front of each chunk and at the end. This makes - consolidating fragmented chunks into bigger chunks very fast. The - size fields also hold bits representing whether chunks are free or - in use. - - An allocated chunk looks like this: - - - chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Size of previous chunk, if allocated | | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Size of chunk, in bytes |P| - mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | User data starts here... . - . . - . (malloc_usable_space() bytes) . - . | -nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Size of chunk | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - - - Where "chunk" is the front of the chunk for the purpose of most of - the malloc code, but "mem" is the pointer that is returned to the - user. "Nextchunk" is the beginning of the next contiguous chunk. - - Chunks always begin on even word boundries, so the mem portion - (which is returned to the user) is also on an even word boundary, and - thus at least double-word aligned. - - Free chunks are stored in circular doubly-linked lists, and look like this: - - chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Size of previous chunk | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - `head:' | Size of chunk, in bytes |P| - mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Forward pointer to next chunk in list | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Back pointer to previous chunk in list | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Unused space (may be 0 bytes long) . - . . - . | -nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - `foot:' | Size of chunk, in bytes | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - - The P (PREV_INUSE) bit, stored in the unused low-order bit of the - chunk size (which is always a multiple of two words), is an in-use - bit for the *previous* chunk. If that bit is *clear*, then the - word before the current chunk size contains the previous chunk - size, and can be used to find the front of the previous chunk. - The very first chunk allocated always has this bit set, - preventing access to non-existent (or non-owned) memory. If - prev_inuse is set for any given chunk, then you CANNOT determine - the size of the previous chunk, and might even get a memory - addressing fault when trying to do so. - - Note that the `foot' of the current chunk is actually represented - as the prev_size of the NEXT chunk. This makes it easier to - deal with alignments etc but can be very confusing when trying - to extend or adapt this code. - - The two exceptions to all this are - - 1. The special chunk `top' doesn't bother using the - trailing size field since there is no next contiguous chunk - that would have to index off it. After initialization, `top' - is forced to always exist. If it would become less than - MINSIZE bytes long, it is replenished. - - 2. Chunks allocated via mmap, which have the second-lowest-order - bit (IS_MMAPPED) set in their size fields. Because they are - allocated one-by-one, each must contain its own trailing size field. - -*/ - -/* - ---------- Size and alignment checks and conversions ---------- -*/ - -/* conversion from malloc headers to user pointers, and back */ - -#define chunk2mem(p) ((Void_t *)((char *)(p) + 2 * SIZE_SZ)) -#define mem2chunk(mem) ((mchunkptr)((char *)(mem) - 2 * SIZE_SZ)) - -/* The smallest possible chunk */ -#define MIN_CHUNK_SIZE (sizeof(struct malloc_chunk)) - -/* The smallest size we can malloc is an aligned minimal chunk */ - -#define MINSIZE \ - (CHUNK_SIZE_T)(((MIN_CHUNK_SIZE + MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK)) - -/* Check if m has acceptable alignment */ - -#define aligned_OK(m) (((PTR_UINT)((m)) & (MALLOC_ALIGN_MASK)) == 0) - -/* - Check if a request is so large that it would wrap around zero when - padded and aligned. To simplify some other code, the bound is made - low enough so that adding MINSIZE will also not wrap around sero. -*/ - -#define REQUEST_OUT_OF_RANGE(req) \ - ((CHUNK_SIZE_T)(req) >= \ - (CHUNK_SIZE_T)(INTERNAL_SIZE_T)(-2 * MINSIZE)) - -/* pad request bytes into a usable size -- internal version */ - -#define request2size(req) \ - (((req) + SIZE_SZ + MALLOC_ALIGN_MASK < MINSIZE) ? MINSIZE : ((req) + SIZE_SZ + MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK) - -/* Same, except also perform argument check */ - -#define checked_request2size(req, sz) \ - if (REQUEST_OUT_OF_RANGE(req)) { \ - MALLOC_FAILURE_ACTION; \ - return 0; \ - } \ - (sz) = request2size(req); - -/* - --------------- Physical chunk operations --------------- -*/ - -/* size field is or'ed with PREV_INUSE when previous adjacent chunk in use */ -#define PREV_INUSE 0x1 - -/* extract inuse bit of previous chunk */ -#define prev_inuse(p) ((p)->size & PREV_INUSE) - -/* size field is or'ed with IS_MMAPPED if the chunk was obtained with mmap() */ -#define IS_MMAPPED 0x2 - -/* check for mmap()'ed chunk */ -#define chunk_is_mmapped(p) ((p)->size & IS_MMAPPED) - -/* - Bits to mask off when extracting size - - Note: IS_MMAPPED is intentionally not masked off from size field in - macros for which mmapped chunks should never be seen. This should - cause helpful core dumps to occur if it is tried by accident by - people extending or adapting this malloc. -*/ -#define SIZE_BITS (PREV_INUSE | IS_MMAPPED) - -/* Get size, ignoring use bits */ -#define chunksize(p) ((p)->size & ~(SIZE_BITS)) - -/* Ptr to next physical malloc_chunk. */ -#define next_chunk(p) ((mchunkptr)(((char *)(p)) + ((p)->size & ~PREV_INUSE))) - -/* Ptr to previous physical malloc_chunk */ -#define prev_chunk(p) ((mchunkptr)(((char *)(p)) - ((p)->prev_size))) - -/* Treat space at ptr + offset as a chunk */ -#define chunk_at_offset(p, s) ((mchunkptr)(((char *)(p)) + (s))) - -/* extract p's inuse bit */ -#define inuse(p) \ - ((((mchunkptr)(((char *)(p)) + ((p)->size & ~PREV_INUSE)))->size) & PREV_INUSE) - -/* set/clear chunk as being inuse without otherwise disturbing */ -#define set_inuse(p) \ - ((mchunkptr)(((char *)(p)) + ((p)->size & ~PREV_INUSE)))->size |= PREV_INUSE - -#define clear_inuse(p) \ - ((mchunkptr)(((char *)(p)) + ((p)->size & ~PREV_INUSE)))->size &= ~(PREV_INUSE) - -/* check/set/clear inuse bits in known places */ -#define inuse_bit_at_offset(p, s) \ - (((mchunkptr)(((char *)(p)) + (s)))->size & PREV_INUSE) - -#define set_inuse_bit_at_offset(p, s) \ - (((mchunkptr)(((char *)(p)) + (s)))->size |= PREV_INUSE) - -#define clear_inuse_bit_at_offset(p, s) \ - (((mchunkptr)(((char *)(p)) + (s)))->size &= ~(PREV_INUSE)) - -/* Set size at head, without disturbing its use bit */ -#define set_head_size(p, s) ((p)->size = (((p)->size & PREV_INUSE) | (s))) - -/* Set size/use field */ -#define set_head(p, s) ((p)->size = (s)) - -/* Set size at footer (only when chunk is not in use) */ -#define set_foot(p, s) (((mchunkptr)((char *)(p) + (s)))->prev_size = (s)) - -/* - -------------------- Internal data structures -------------------- - - All internal state is held in an instance of malloc_state defined - below. There are no other static variables, except in two optional - cases: - * If USE_MALLOC_LOCK is defined, the mALLOC_MUTEx declared above. - * If HAVE_MMAP is true, but mmap doesn't support - MAP_ANONYMOUS, a dummy file descriptor for mmap. - - Beware of lots of tricks that minimize the total bookkeeping space - requirements. The result is a little over 1K bytes (for 4byte - pointers and size_t.) -*/ - -/* - Bins - - An array of bin headers for free chunks. Each bin is doubly - linked. The bins are approximately proportionally (log) spaced. - There are a lot of these bins (128). This may look excessive, but - works very well in practice. Most bins hold sizes that are - unusual as malloc request sizes, but are more usual for fragments - and consolidated sets of chunks, which is what these bins hold, so - they can be found quickly. All procedures maintain the invariant - that no consolidated chunk physically borders another one, so each - chunk in a list is known to be preceeded and followed by either - inuse chunks or the ends of memory. - - Chunks in bins are kept in size order, with ties going to the - approximately least recently used chunk. Ordering isn't needed - for the small bins, which all contain the same-sized chunks, but - facilitates best-fit allocation for larger chunks. These lists - are just sequential. Keeping them in order almost never requires - enough traversal to warrant using fancier ordered data - structures. - - Chunks of the same size are linked with the most - recently freed at the front, and allocations are taken from the - back. This results in LRU (FIFO) allocation order, which tends - to give each chunk an equal opportunity to be consolidated with - adjacent freed chunks, resulting in larger free chunks and less - fragmentation. - - To simplify use in double-linked lists, each bin header acts - as a malloc_chunk. This avoids special-casing for headers. - But to conserve space and improve locality, we allocate - only the fd/bk pointers of bins, and then use repositioning tricks - to treat these as the fields of a malloc_chunk*. -*/ - -typedef struct malloc_chunk *mbinptr; - -/* addressing -- note that bin_at(0) does not exist */ -#define bin_at(m, i) ((mbinptr)((char *)&((m)->bins[(i) << 1]) - (SIZE_SZ << 1))) - -/* analog of ++bin */ -#define next_bin(b) ((mbinptr)((char *)(b) + (sizeof(mchunkptr) << 1))) - -/* Reminders about list directionality within bins */ -#define first(b) ((b)->fd) -#define last(b) ((b)->bk) - -/* Take a chunk off a bin list */ -#define unlink(P, BK, FD) \ - { \ - FD = P->fd; \ - BK = P->bk; \ - FD->bk = BK; \ - BK->fd = FD; \ - } - -/* - Indexing - - Bins for sizes < 512 bytes contain chunks of all the same size, spaced - 8 bytes apart. Larger bins are approximately logarithmically spaced: - - 64 bins of size 8 - 32 bins of size 64 - 16 bins of size 512 - 8 bins of size 4096 - 4 bins of size 32768 - 2 bins of size 262144 - 1 bin of size what's left - - The bins top out around 1MB because we expect to service large - requests via mmap. -*/ - -#define NBINS 96 -#define NSMALLBINS 32 -#define SMALLBIN_WIDTH 8 -#define MIN_LARGE_SIZE 256 - -#define in_smallbin_range(sz) \ - ((CHUNK_SIZE_T)(sz) < (CHUNK_SIZE_T)MIN_LARGE_SIZE) - -#define smallbin_index(sz) (((unsigned)(sz)) >> 3) - -/* - Compute index for size. We expect this to be inlined when - compiled with optimization, else not, which works out well. -*/ -static int largebin_index(unsigned int sz) { - unsigned int x = sz >> SMALLBIN_WIDTH; - unsigned int m; /* bit position of highest set bit of m */ - - if (x >= 0x10000) { - return NBINS - 1; - } - - /* On intel, use BSRL instruction to find highest bit */ -#if defined(__GNUC__) && defined(i386) - - __asm__("bsrl %1,%0\n\t" - : "=r"(m) - : "g"(x)); - -#else - { - /* - Based on branch-free nlz algorithm in chapter 5 of Henry - S. Warren Jr's book "Hacker's Delight". - */ - - unsigned int n = ((x - 0x100) >> 16) & 8; - x <<= n; - m = ((x - 0x1000) >> 16) & 4; - n += m; - x <<= m; - m = ((x - 0x4000) >> 16) & 2; - n += m; - x = (x << m) >> 14; - m = 13 - n + (x & ~(x >> 1)); - } -#endif - - /* Use next 2 bits to create finer-granularity bins */ - return NSMALLBINS + (m << 2) + ((sz >> (m + 6)) & 3); -} - -#define bin_index(sz) \ - ((in_smallbin_range(sz)) ? smallbin_index(sz) : largebin_index(sz)) - -/* - FIRST_SORTED_BIN_SIZE is the chunk size corresponding to the - first bin that is maintained in sorted order. This must - be the smallest size corresponding to a given bin. - - Normally, this should be MIN_LARGE_SIZE. But you can weaken - best fit guarantees to sometimes speed up malloc by increasing value. - Doing this means that malloc may choose a chunk that is - non-best-fitting by up to the width of the bin. - - Some useful cutoff values: - 512 - all bins sorted - 2560 - leaves bins <= 64 bytes wide unsorted - 12288 - leaves bins <= 512 bytes wide unsorted - 65536 - leaves bins <= 4096 bytes wide unsorted - 262144 - leaves bins <= 32768 bytes wide unsorted - -1 - no bins sorted (not recommended!) -*/ - -#define FIRST_SORTED_BIN_SIZE MIN_LARGE_SIZE -/* #define FIRST_SORTED_BIN_SIZE 65536 */ - -/* - Unsorted chunks - - All remainders from chunk splits, as well as all returned chunks, - are first placed in the "unsorted" bin. They are then placed - in regular bins after malloc gives them ONE chance to be used before - binning. So, basically, the unsorted_chunks list acts as a queue, - with chunks being placed on it in free (and malloc_consolidate), - and taken off (to be either used or placed in bins) in malloc. -*/ - -/* The otherwise unindexable 1-bin is used to hold unsorted chunks. */ -#define unsorted_chunks(M) (bin_at(M, 1)) - -/* - Top - - The top-most available chunk (i.e., the one bordering the end of - available memory) is treated specially. It is never included in - any bin, is used only if no other chunk is available, and is - released back to the system if it is very large (see - M_TRIM_THRESHOLD). Because top initially - points to its own bin with initial zero size, thus forcing - extension on the first malloc request, we avoid having any special - code in malloc to check whether it even exists yet. But we still - need to do so when getting memory from system, so we make - initial_top treat the bin as a legal but unusable chunk during the - interval between initialization and the first call to - sYSMALLOc. (This is somewhat delicate, since it relies on - the 2 preceding words to be zero during this interval as well.) -*/ - -/* Conveniently, the unsorted bin can be used as dummy top on first call */ -#define initial_top(M) (unsorted_chunks(M)) - -/* - Binmap - - To help compensate for the large number of bins, a one-level index - structure is used for bin-by-bin searching. `binmap' is a - bitvector recording whether bins are definitely empty so they can - be skipped over during during traversals. The bits are NOT always - cleared as soon as bins are empty, but instead only - when they are noticed to be empty during traversal in malloc. -*/ - -/* Conservatively use 32 bits per map word, even if on 64bit system */ -#define BINMAPSHIFT 5 -#define BITSPERMAP (1U << BINMAPSHIFT) -#define BINMAPSIZE (NBINS / BITSPERMAP) - -#define idx2block(i) ((i) >> BINMAPSHIFT) -#define idx2bit(i) ((1U << ((i) & ((1U << BINMAPSHIFT) - 1)))) - -#define mark_bin(m, i) ((m)->binmap[idx2block(i)] |= idx2bit(i)) -#define unmark_bin(m, i) ((m)->binmap[idx2block(i)] &= ~(idx2bit(i))) -#define get_binmap(m, i) ((m)->binmap[idx2block(i)] & idx2bit(i)) - -/* - Fastbins - - An array of lists holding recently freed small chunks. Fastbins - are not doubly linked. It is faster to single-link them, and - since chunks are never removed from the middles of these lists, - double linking is not necessary. Also, unlike regular bins, they - are not even processed in FIFO order (they use faster LIFO) since - ordering doesn't much matter in the transient contexts in which - fastbins are normally used. - - Chunks in fastbins keep their inuse bit set, so they cannot - be consolidated with other free chunks. malloc_consolidate - releases all chunks in fastbins and consolidates them with - other free chunks. -*/ - -typedef struct malloc_chunk *mfastbinptr; - -/* offset 2 to use otherwise unindexable first 2 bins */ -#define fastbin_index(sz) ((((unsigned int)(sz)) >> 3) - 2) - -/* The maximum fastbin request size we support */ -#define MAX_FAST_SIZE 80 - -#define NFASTBINS (fastbin_index(request2size(MAX_FAST_SIZE)) + 1) - -/* - FASTBIN_CONSOLIDATION_THRESHOLD is the size of a chunk in free() - that triggers automatic consolidation of possibly-surrounding - fastbin chunks. This is a heuristic, so the exact value should not - matter too much. It is defined at half the default trim threshold as a - compromise heuristic to only attempt consolidation if it is likely - to lead to trimming. However, it is not dynamically tunable, since - consolidation reduces fragmentation surrounding loarge chunks even - if trimming is not used. -*/ - -#define FASTBIN_CONSOLIDATION_THRESHOLD \ - ((unsigned long)(DEFAULT_TRIM_THRESHOLD) >> 1) - -/* - Since the lowest 2 bits in max_fast don't matter in size comparisons, - they are used as flags. -*/ - -/* - ANYCHUNKS_BIT held in max_fast indicates that there may be any - freed chunks at all. It is set true when entering a chunk into any - bin. -*/ - -#define ANYCHUNKS_BIT (1U) - -#define have_anychunks(M) (((M)->max_fast & ANYCHUNKS_BIT)) -#define set_anychunks(M) ((M)->max_fast |= ANYCHUNKS_BIT) -#define clear_anychunks(M) ((M)->max_fast &= ~ANYCHUNKS_BIT) - -/* - FASTCHUNKS_BIT held in max_fast indicates that there are probably - some fastbin chunks. It is set true on entering a chunk into any - fastbin, and cleared only in malloc_consolidate. -*/ - -#define FASTCHUNKS_BIT (2U) - -#define have_fastchunks(M) (((M)->max_fast & FASTCHUNKS_BIT)) -#define set_fastchunks(M) ((M)->max_fast |= (FASTCHUNKS_BIT | ANYCHUNKS_BIT)) -#define clear_fastchunks(M) ((M)->max_fast &= ~(FASTCHUNKS_BIT)) - -/* - Set value of max_fast. - Use impossibly small value if 0. -*/ - -#define set_max_fast(M, s) \ - (M)->max_fast = (((s) == 0) ? SMALLBIN_WIDTH : request2size(s)) | \ - ((M)->max_fast & (FASTCHUNKS_BIT | ANYCHUNKS_BIT)) - -#define get_max_fast(M) \ - ((M)->max_fast & ~(FASTCHUNKS_BIT | ANYCHUNKS_BIT)) - -/* - morecore_properties is a status word holding dynamically discovered - or controlled properties of the morecore function -*/ - -#define MORECORE_CONTIGUOUS_BIT (1U) - -#define contiguous(M) \ - (((M)->morecore_properties & MORECORE_CONTIGUOUS_BIT)) -#define noncontiguous(M) \ - (((M)->morecore_properties & MORECORE_CONTIGUOUS_BIT) == 0) -#define set_contiguous(M) \ - ((M)->morecore_properties |= MORECORE_CONTIGUOUS_BIT) -#define set_noncontiguous(M) \ - ((M)->morecore_properties &= ~MORECORE_CONTIGUOUS_BIT) - -/* - ----------- Internal state representation and initialization ----------- -*/ - -struct malloc_state { - - /* The maximum chunk size to be eligible for fastbin */ - INTERNAL_SIZE_T max_fast; /* low 2 bits used as flags */ - - /* Fastbins */ - mfastbinptr fastbins[NFASTBINS]; - - /* Base of the topmost chunk -- not otherwise kept in a bin */ - mchunkptr top; - - /* The remainder from the most recent split of a small request */ - mchunkptr last_remainder; - - /* Normal bins packed as described above */ - mchunkptr bins[NBINS * 2]; - - /* Bitmap of bins. Trailing zero map handles cases of largest binned size */ - unsigned int binmap[BINMAPSIZE + 1]; - - /* Tunable parameters */ - CHUNK_SIZE_T trim_threshold; - INTERNAL_SIZE_T top_pad; - INTERNAL_SIZE_T mmap_threshold; - - /* Memory map support */ - int n_mmaps; - int n_mmaps_max; - int max_n_mmaps; - - /* Cache malloc_getpagesize */ - unsigned int pagesize; - - /* Track properties of MORECORE */ - unsigned int morecore_properties; - - /* Statistics */ - INTERNAL_SIZE_T mmapped_mem; - INTERNAL_SIZE_T sbrked_mem; - INTERNAL_SIZE_T max_sbrked_mem; - INTERNAL_SIZE_T max_mmapped_mem; - INTERNAL_SIZE_T max_total_mem; -}; - -typedef struct malloc_state *mstate; - -/* - There is exactly one instance of this struct in this malloc. - If you are adapting this malloc in a way that does NOT use a static - malloc_state, you MUST explicitly zero-fill it before using. This - malloc relies on the property that malloc_state is initialized to - all zeroes (as is true of C statics). -*/ - -static struct malloc_state av_; /* never directly referenced */ - -/* - All uses of av_ are via get_malloc_state(). - At most one "call" to get_malloc_state is made per invocation of - the public versions of malloc and free, but other routines - that in turn invoke malloc and/or free may call more then once. - Also, it is called in check* routines if DL_DEBUG is set. -*/ - -#define get_malloc_state() (&(av_)) - -/* - Initialize a malloc_state struct. - - This is called only from within malloc_consolidate, which needs - be called in the same contexts anyway. It is never called directly - outside of malloc_consolidate because some optimizing compilers try - to inline it at all call points, which turns out not to be an - optimization at all. (Inlining it in malloc_consolidate is fine though.) -*/ - -#if __STD_C -static void malloc_init_state(mstate av) -#else -static void malloc_init_state(av) mstate av; -#endif -{ - int i; - mbinptr bin; - - /* Establish circular links for normal bins */ - for (i = 1; i < NBINS; ++i) { - bin = bin_at(av, i); - bin->fd = bin->bk = bin; - } - - av->top_pad = DEFAULT_TOP_PAD; - av->n_mmaps_max = DEFAULT_MMAP_MAX; - av->mmap_threshold = DEFAULT_MMAP_THRESHOLD; - av->trim_threshold = DEFAULT_TRIM_THRESHOLD; - -#if MORECORE_CONTIGUOUS - set_contiguous(av); -#else - set_noncontiguous(av); -#endif - - set_max_fast(av, DEFAULT_MXFAST); - - av->top = initial_top(av); - av->pagesize = malloc_getpagesize; -} - -/* - Other internal utilities operating on mstates -*/ - -#if __STD_C -static Void_t *sYSMALLOc(INTERNAL_SIZE_T, mstate); -static int sYSTRIm(size_t, mstate); -static void malloc_consolidate(mstate); -static Void_t **iALLOc(size_t, size_t *, int, Void_t **); -#else -static Void_t *sYSMALLOc(); -static int sYSTRIm(); -static void malloc_consolidate(); -static Void_t **iALLOc(); -#endif - -/* - Debugging support - - These routines make a number of assertions about the states - of data structures that should be true at all times. If any - are not true, it's very likely that a user program has somehow - trashed memory. (It's also possible that there is a coding error - in malloc. In which case, please report it!) -*/ - -#if !DL_DEBUG - -#define check_chunk(P) -#define check_free_chunk(P) -#define check_inuse_chunk(P) -#define check_remalloced_chunk(P, N) -#define check_malloced_chunk(P, N) -#define check_malloc_state() - -#else -#define check_chunk(P) do_check_chunk(P) -#define check_free_chunk(P) do_check_free_chunk(P) -#define check_inuse_chunk(P) do_check_inuse_chunk(P) -#define check_remalloced_chunk(P, N) do_check_remalloced_chunk(P, N) -#define check_malloced_chunk(P, N) do_check_malloced_chunk(P, N) -#define check_malloc_state() do_check_malloc_state() - -/* - Properties of all chunks -*/ - -#if __STD_C -static void do_check_chunk(mchunkptr p) -#else -static void do_check_chunk(p) mchunkptr p; -#endif -{ - mstate av = get_malloc_state(); - CHUNK_SIZE_T sz = chunksize(p); - /* min and max possible addresses assuming contiguous allocation */ - char *max_address = (char *)(av->top) + chunksize(av->top); - char *min_address = max_address - av->sbrked_mem; - - if (!chunk_is_mmapped(p)) { - - /* Has legal address ... */ - if (p != av->top) { - if (contiguous(av)) { - assert(((char *)p) >= min_address); - assert(((char *)p + sz) <= ((char *)(av->top))); - } - } else { - /* top size is always at least MINSIZE */ - assert((CHUNK_SIZE_T)(sz) >= MINSIZE); - /* top predecessor always marked inuse */ - assert(prev_inuse(p)); - } - } else { -#if HAVE_MMAP - /* address is outside main heap */ - if (contiguous(av) && av->top != initial_top(av)) { - assert(((char *)p) < min_address || ((char *)p) > max_address); - } - /* chunk is page-aligned */ - assert(((p->prev_size + sz) & (av->pagesize - 1)) == 0); - /* mem is aligned */ - assert(aligned_OK(chunk2mem(p))); -#else - /* force an appropriate assert violation if debug set */ - assert(!chunk_is_mmapped(p)); -#endif - } -} - -/* - Properties of free chunks -*/ - -#if __STD_C -static void do_check_free_chunk(mchunkptr p) -#else -static void do_check_free_chunk(p) mchunkptr p; -#endif -{ - mstate av = get_malloc_state(); - - INTERNAL_SIZE_T sz = p->size & ~PREV_INUSE; - mchunkptr next = chunk_at_offset(p, sz); - - do_check_chunk(p); - - /* Chunk must claim to be free ... */ - assert(!inuse(p)); - assert(!chunk_is_mmapped(p)); - - /* Unless a special marker, must have OK fields */ - if ((CHUNK_SIZE_T)(sz) >= MINSIZE) { - assert((sz & MALLOC_ALIGN_MASK) == 0); - assert(aligned_OK(chunk2mem(p))); - /* ... matching footer field */ - assert(next->prev_size == sz); - /* ... and is fully consolidated */ - assert(prev_inuse(p)); - assert(next == av->top || inuse(next)); - - /* ... and has minimally sane links */ - assert(p->fd->bk == p); - assert(p->bk->fd == p); - } else { /* markers are always of size SIZE_SZ */ - assert(sz == SIZE_SZ); - } -} - -/* - Properties of inuse chunks -*/ - -#if __STD_C -static void do_check_inuse_chunk(mchunkptr p) -#else -static void do_check_inuse_chunk(p) mchunkptr p; -#endif -{ - mstate av = get_malloc_state(); - mchunkptr next; - do_check_chunk(p); - - if (chunk_is_mmapped(p)) { - return; /* mmapped chunks have no next/prev */ - } - - /* Check whether it claims to be in use ... */ - assert(inuse(p)); - - next = next_chunk(p); - - /* ... and is surrounded by OK chunks. - Since more things can be checked with free chunks than inuse ones, - if an inuse chunk borders them and debug is on, it's worth doing them. - */ - if (!prev_inuse(p)) { - /* Note that we cannot even look at prev unless it is not inuse */ - mchunkptr prv = prev_chunk(p); - assert(next_chunk(prv) == p); - do_check_free_chunk(prv); - } - - if (next == av->top) { - assert(prev_inuse(next)); - assert(chunksize(next) >= MINSIZE); - } else if (!inuse(next)) { - do_check_free_chunk(next); - } -} - -/* - Properties of chunks recycled from fastbins -*/ - -#if __STD_C -static void do_check_remalloced_chunk(mchunkptr p, INTERNAL_SIZE_T s) -#else -static void do_check_remalloced_chunk(p, s) mchunkptr p; -INTERNAL_SIZE_T s; -#endif -{ - INTERNAL_SIZE_T sz = p->size & ~PREV_INUSE; - - do_check_inuse_chunk(p); - - /* Legal size ... */ - assert((sz & MALLOC_ALIGN_MASK) == 0); - assert((CHUNK_SIZE_T)(sz) >= MINSIZE); - /* ... and alignment */ - assert(aligned_OK(chunk2mem(p))); - /* chunk is less than MINSIZE more than request */ - assert((long)(sz) - (long)(s) >= 0); - assert((long)(sz) - (long)(s + MINSIZE) < 0); -} - -/* - Properties of nonrecycled chunks at the point they are malloced -*/ - -#if __STD_C -static void do_check_malloced_chunk(mchunkptr p, INTERNAL_SIZE_T s) -#else -static void do_check_malloced_chunk(p, s) mchunkptr p; -INTERNAL_SIZE_T s; -#endif -{ - /* same as recycled case ... */ - do_check_remalloced_chunk(p, s); - - /* - ... plus, must obey implementation invariant that prev_inuse is - always true of any allocated chunk; i.e., that each allocated - chunk borders either a previously allocated and still in-use - chunk, or the base of its memory arena. This is ensured - by making all allocations from the the `lowest' part of any found - chunk. This does not necessarily hold however for chunks - recycled via fastbins. - */ - - assert(prev_inuse(p)); -} - -/* - Properties of malloc_state. - - This may be useful for debugging malloc, as well as detecting user - programmer errors that somehow write into malloc_state. - - If you are extending or experimenting with this malloc, you can - probably figure out how to hack this routine to print out or - display chunk addresses, sizes, bins, and other instrumentation. -*/ - -static void do_check_malloc_state(void) { - mstate av = get_malloc_state(); - int i; - mchunkptr p; - mchunkptr q; - mbinptr b; - unsigned int binbit; - int empty; - unsigned int idx; - INTERNAL_SIZE_T size; - CHUNK_SIZE_T total = 0; - int max_fast_bin; - - /* internal size_t must be no wider than pointer type */ - assert(sizeof(INTERNAL_SIZE_T) <= sizeof(char *)); - - /* alignment is a power of 2 */ - assert((MALLOC_ALIGNMENT & (MALLOC_ALIGNMENT - 1)) == 0); - - /* cannot run remaining checks until fully initialized */ - if (av->top == 0 || av->top == initial_top(av)) { - return; - } - - /* pagesize is a power of 2 */ - assert((av->pagesize & (av->pagesize - 1)) == 0); - - /* properties of fastbins */ - - /* max_fast is in allowed range */ - assert(get_max_fast(av) <= request2size(MAX_FAST_SIZE)); - - max_fast_bin = fastbin_index(av->max_fast); - - for (i = 0; NFASTBINS - i > 0; ++i) { - p = av->fastbins[i]; - - /* all bins past max_fast are empty */ - if (i > max_fast_bin) { - assert(p == 0); - } - - while (p != 0) { - /* each chunk claims to be inuse */ - do_check_inuse_chunk(p); - total += chunksize(p); - /* chunk belongs in this bin */ - assert(fastbin_index(chunksize(p)) == i); - p = p->fd; - } - } - - if (total != 0) { - assert(have_fastchunks(av)); - } else if (!have_fastchunks(av)) { - assert(total == 0); - } - - /* check normal bins */ - for (i = 1; i < NBINS; ++i) { - b = bin_at(av, i); - - /* binmap is accurate (except for bin 1 == unsorted_chunks) */ - if (i >= 2) { - binbit = get_binmap(av, i); - empty = last(b) == b; - if (!binbit) { - assert(empty); - } else if (!empty) { - assert(binbit); - } - } - - for (p = last(b); p != b; p = p->bk) { - /* each chunk claims to be free */ - do_check_free_chunk(p); - size = chunksize(p); - total += size; - if (i >= 2) { - /* chunk belongs in bin */ - idx = bin_index(size); - assert(idx == i); - /* lists are sorted */ - if ((CHUNK_SIZE_T)size >= (CHUNK_SIZE_T)(FIRST_SORTED_BIN_SIZE)) { - assert(p->bk == b || - (CHUNK_SIZE_T)chunksize(p->bk) >= - (CHUNK_SIZE_T)chunksize(p)); - } - } - /* chunk is followed by a legal chain of inuse chunks */ - for (q = next_chunk(p); - (q != av->top && inuse(q) && - (CHUNK_SIZE_T)(chunksize(q)) >= MINSIZE); - q = next_chunk(q)) { - do_check_inuse_chunk(q); - } - } - } - - /* top chunk is OK */ - check_chunk(av->top); - - /* sanity checks for statistics */ - - assert(total <= (CHUNK_SIZE_T)(av->max_total_mem)); - assert(av->n_mmaps >= 0); - assert(av->n_mmaps <= av->max_n_mmaps); - - assert((CHUNK_SIZE_T)(av->sbrked_mem) <= - (CHUNK_SIZE_T)(av->max_sbrked_mem)); - - assert((CHUNK_SIZE_T)(av->mmapped_mem) <= - (CHUNK_SIZE_T)(av->max_mmapped_mem)); - - assert((CHUNK_SIZE_T)(av->max_total_mem) >= - (CHUNK_SIZE_T)(av->mmapped_mem) + (CHUNK_SIZE_T)(av->sbrked_mem)); -} -#endif - -/* ----------- Routines dealing with system allocation -------------- */ - -/* - sysmalloc handles malloc cases requiring more memory from the system. - On entry, it is assumed that av->top does not have enough - space to service request for nb bytes, thus requiring that av->top - be extended or replaced. -*/ - -#if __STD_C -static Void_t *sYSMALLOc(INTERNAL_SIZE_T nb, mstate av) -#else -static Void_t *sYSMALLOc(nb, av) -INTERNAL_SIZE_T nb; -mstate av; -#endif -{ - mchunkptr old_top; /* incoming value of av->top */ - INTERNAL_SIZE_T old_size; /* its size */ - char *old_end; /* its end address */ - - long size; /* arg to first MORECORE or mmap call */ - char *brk; /* return value from MORECORE */ - - long correction; /* arg to 2nd MORECORE call */ - char *snd_brk; /* 2nd return val */ - - INTERNAL_SIZE_T front_misalign; /* unusable bytes at front of new space */ - INTERNAL_SIZE_T end_misalign; /* partial page left at end of new space */ - char *aligned_brk; /* aligned offset into brk */ - - mchunkptr p; /* the allocated/returned chunk */ - mchunkptr remainder; /* remainder from allocation */ - CHUNK_SIZE_T remainder_size; /* its size */ - - CHUNK_SIZE_T sum; /* for updating stats */ - - size_t pagemask = av->pagesize - 1; - - /* - If there is space available in fastbins, consolidate and retry - malloc from scratch rather than getting memory from system. This - can occur only if nb is in smallbin range so we didn't consolidate - upon entry to malloc. It is much easier to handle this case here - than in malloc proper. - */ - - if (have_fastchunks(av)) { - assert(in_smallbin_range(nb)); - malloc_consolidate(av); - return mALLOc(nb - MALLOC_ALIGN_MASK); - } - -#if HAVE_MMAP - - /* - If have mmap, and the request size meets the mmap threshold, and - the system supports mmap, and there are few enough currently - allocated mmapped regions, try to directly map this request - rather than expanding top. - */ - - if ((CHUNK_SIZE_T)(nb) >= (CHUNK_SIZE_T)(av->mmap_threshold) && - (av->n_mmaps < av->n_mmaps_max)) { - - char *mm; /* return value from mmap call*/ - - /* - Round up size to nearest page. For mmapped chunks, the overhead - is one SIZE_SZ unit larger than for normal chunks, because there - is no following chunk whose prev_size field could be used. - */ - size = (nb + SIZE_SZ + MALLOC_ALIGN_MASK + pagemask) & ~pagemask; - - /* Don't try if size wraps around 0 */ - if ((CHUNK_SIZE_T)(size) > (CHUNK_SIZE_T)(nb)) { - - mm = (char *)(MMAP(0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE)); - - if (mm != (char *)(MORECORE_FAILURE)) { - - /* - The offset to the start of the mmapped region is stored - in the prev_size field of the chunk. This allows us to adjust - returned start address to meet alignment requirements here - and in memalign(), and still be able to compute proper - address argument for later munmap in free() and realloc(). - */ - - front_misalign = (INTERNAL_SIZE_T)chunk2mem(mm) & MALLOC_ALIGN_MASK; - if (front_misalign > 0) { - correction = MALLOC_ALIGNMENT - front_misalign; - p = (mchunkptr)(mm + correction); - p->prev_size = correction; - set_head(p, (size - correction) | IS_MMAPPED); - } else { - p = (mchunkptr)mm; - p->prev_size = 0; - set_head(p, size | IS_MMAPPED); - } - - /* update statistics */ - - if (++av->n_mmaps > av->max_n_mmaps) { - av->max_n_mmaps = av->n_mmaps; - } - - sum = av->mmapped_mem += size; - if (sum > (CHUNK_SIZE_T)(av->max_mmapped_mem)) { - av->max_mmapped_mem = sum; - } - sum += av->sbrked_mem; - if (sum > (CHUNK_SIZE_T)(av->max_total_mem)) { - av->max_total_mem = sum; - } - - check_chunk(p); - - return chunk2mem(p); - } - } - } -#endif - - /* Record incoming configuration of top */ - - old_top = av->top; - old_size = chunksize(old_top); - old_end = (char *)(chunk_at_offset(old_top, old_size)); - - brk = snd_brk = (char *)(MORECORE_FAILURE); - - /* - If not the first time through, we require old_size to be - at least MINSIZE and to have prev_inuse set. - */ - - assert((old_top == initial_top(av) && old_size == 0) || - ((CHUNK_SIZE_T)(old_size) >= MINSIZE && - prev_inuse(old_top))); - - /* Precondition: not enough current space to satisfy nb request */ - assert((CHUNK_SIZE_T)(old_size) < (CHUNK_SIZE_T)(nb + MINSIZE)); - - /* Precondition: all fastbins are consolidated */ - assert(!have_fastchunks(av)); - - /* Request enough space for nb + pad + overhead */ - - size = nb + av->top_pad + MINSIZE; - - /* - If contiguous, we can subtract out existing space that we hope to - combine with new space. We add it back later only if - we don't actually get contiguous space. - */ - - if (contiguous(av)) { - size -= old_size; - } - - /* - Round to a multiple of page size. - If MORECORE is not contiguous, this ensures that we only call it - with whole-page arguments. And if MORECORE is contiguous and - this is not first time through, this preserves page-alignment of - previous calls. Otherwise, we correct to page-align below. - */ - - size = (size + pagemask) & ~pagemask; - - /* - Don't try to call MORECORE if argument is so big as to appear - negative. Note that since mmap takes size_t arg, it may succeed - below even if we cannot call MORECORE. - */ - - if (size > 0) { - brk = (char *)(MORECORE(size)); - } - - /* - If have mmap, try using it as a backup when MORECORE fails or - cannot be used. This is worth doing on systems that have "holes" in - address space, so sbrk cannot extend to give contiguous space, but - space is available elsewhere. Note that we ignore mmap max count - and threshold limits, since the space will not be used as a - segregated mmap region. - */ - -#if HAVE_MMAP - if (brk == (char *)(MORECORE_FAILURE)) { - - /* Cannot merge with old top, so add its size back in */ - if (contiguous(av)) { - size = (size + old_size + pagemask) & ~pagemask; - } - - /* If we are relying on mmap as backup, then use larger units */ - if ((CHUNK_SIZE_T)(size) < (CHUNK_SIZE_T)(MMAP_AS_MORECORE_SIZE)) { - size = MMAP_AS_MORECORE_SIZE; - } - - /* Don't try if size wraps around 0 */ - if ((CHUNK_SIZE_T)(size) > (CHUNK_SIZE_T)(nb)) { - - brk = (char *)(MMAP(0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE)); - - if (brk != (char *)(MORECORE_FAILURE)) { - - /* We do not need, and cannot use, another sbrk call to find end */ - snd_brk = brk + size; - - /* - Record that we no longer have a contiguous sbrk region. - After the first time mmap is used as backup, we do not - ever rely on contiguous space since this could incorrectly - bridge regions. - */ - set_noncontiguous(av); - } - } - } -#endif - - if (brk != (char *)(MORECORE_FAILURE)) { - av->sbrked_mem += size; - - /* - If MORECORE extends previous space, we can likewise extend top size. - */ - - if (brk == old_end && snd_brk == (char *)(MORECORE_FAILURE)) { - set_head(old_top, (size + old_size) | PREV_INUSE); - } - - /* - Otherwise, make adjustments: - - * If the first time through or noncontiguous, we need to call sbrk - just to find out where the end of memory lies. - - * We need to ensure that all returned chunks from malloc will meet - MALLOC_ALIGNMENT - - * If there was an intervening foreign sbrk, we need to adjust sbrk - request size to account for fact that we will not be able to - combine new space with existing space in old_top. - - * Almost all systems internally allocate whole pages at a time, in - which case we might as well use the whole last page of request. - So we allocate enough more memory to hit a page boundary now, - which in turn causes future contiguous calls to page-align. - */ - - else { - front_misalign = 0; - end_misalign = 0; - correction = 0; - aligned_brk = brk; - - /* - If MORECORE returns an address lower than we have seen before, - we know it isn't really contiguous. This and some subsequent - checks help cope with non-conforming MORECORE functions and - the presence of "foreign" calls to MORECORE from outside of - malloc or by other threads. We cannot guarantee to detect - these in all cases, but cope with the ones we do detect. - */ - if (contiguous(av) && old_size != 0 && brk < old_end) { - set_noncontiguous(av); - } - - /* handle contiguous cases */ - if (contiguous(av)) { - - /* - We can tolerate forward non-contiguities here (usually due - to foreign calls) but treat them as part of our space for - stats reporting. - */ - if (old_size != 0) { - av->sbrked_mem += brk - old_end; - } - - /* Guarantee alignment of first new chunk made from this space */ - - front_misalign = (INTERNAL_SIZE_T)chunk2mem(brk) & MALLOC_ALIGN_MASK; - if (front_misalign > 0) { - - /* - Skip over some bytes to arrive at an aligned position. - We don't need to specially mark these wasted front bytes. - They will never be accessed anyway because - prev_inuse of av->top (and any chunk created from its start) - is always true after initialization. - */ - - correction = MALLOC_ALIGNMENT - front_misalign; - aligned_brk += correction; - } - - /* - If this isn't adjacent to existing space, then we will not - be able to merge with old_top space, so must add to 2nd request. - */ - - correction += old_size; - - /* Extend the end address to hit a page boundary */ - end_misalign = (INTERNAL_SIZE_T)(brk + size + correction); - correction += ((end_misalign + pagemask) & ~pagemask) - end_misalign; - - assert(correction >= 0); - snd_brk = (char *)(MORECORE(correction)); - - if (snd_brk == (char *)(MORECORE_FAILURE)) { - /* - If can't allocate correction, try to at least find out current - brk. It might be enough to proceed without failing. - */ - correction = 0; - snd_brk = (char *)(MORECORE(0)); - } else if (snd_brk < brk) { - /* - If the second call gives noncontiguous space even though - it says it won't, the only course of action is to ignore - results of second call, and conservatively estimate where - the first call left us. Also set noncontiguous, so this - won't happen again, leaving at most one hole. - - Note that this check is intrinsically incomplete. Because - MORECORE is allowed to give more space than we ask for, - there is no reliable way to detect a noncontiguity - producing a forward gap for the second call. - */ - snd_brk = brk + size; - correction = 0; - set_noncontiguous(av); - } - } - - /* handle non-contiguous cases */ - else { - /* MORECORE/mmap must correctly align */ - assert(aligned_OK(chunk2mem(brk))); - - /* Find out current end of memory */ - if (snd_brk == (char *)(MORECORE_FAILURE)) { - snd_brk = (char *)(MORECORE(0)); - av->sbrked_mem += snd_brk - brk - size; - } - } - - /* Adjust top based on results of second sbrk */ - if (snd_brk != (char *)(MORECORE_FAILURE)) { - av->top = (mchunkptr)aligned_brk; - set_head(av->top, (snd_brk - aligned_brk + correction) | PREV_INUSE); - av->sbrked_mem += correction; - - /* - If not the first time through, we either have a - gap due to foreign sbrk or a non-contiguous region. Insert a - double fencepost at old_top to prevent consolidation with space - we don't own. These fenceposts are artificial chunks that are - marked as inuse and are in any case too small to use. We need - two to make sizes and alignments work out. - */ - - if (old_size != 0) { - /* - Shrink old_top to insert fenceposts, keeping size a - multiple of MALLOC_ALIGNMENT. We know there is at least - enough space in old_top to do this. - */ - old_size = (old_size - 3 * SIZE_SZ) & ~MALLOC_ALIGN_MASK; - set_head(old_top, old_size | PREV_INUSE); - - /* - Note that the following assignments completely overwrite - old_top when old_size was previously MINSIZE. This is - intentional. We need the fencepost, even if old_top otherwise gets - lost. - */ - chunk_at_offset(old_top, old_size)->size = - SIZE_SZ | PREV_INUSE; - - chunk_at_offset(old_top, old_size + SIZE_SZ)->size = - SIZE_SZ | PREV_INUSE; - - /* - If possible, release the rest, suppressing trimming. - */ - if (old_size >= MINSIZE) { - INTERNAL_SIZE_T tt = av->trim_threshold; - av->trim_threshold = (INTERNAL_SIZE_T)(-1); - fREe(chunk2mem(old_top)); - av->trim_threshold = tt; - } - } - } - } - - /* Update statistics */ - sum = av->sbrked_mem; - if (sum > (CHUNK_SIZE_T)(av->max_sbrked_mem)) { - av->max_sbrked_mem = sum; - } - - sum += av->mmapped_mem; - if (sum > (CHUNK_SIZE_T)(av->max_total_mem)) { - av->max_total_mem = sum; - } - - check_malloc_state(); - - /* finally, do the allocation */ - - p = av->top; - size = chunksize(p); - - /* check that one of the above allocation paths succeeded */ - if ((CHUNK_SIZE_T)(size) >= (CHUNK_SIZE_T)(nb + MINSIZE)) { - remainder_size = size - nb; - remainder = chunk_at_offset(p, nb); - av->top = remainder; - set_head(p, nb | PREV_INUSE); - set_head(remainder, remainder_size | PREV_INUSE); - check_malloced_chunk(p, nb); - return chunk2mem(p); - } - } - - /* catch all failure paths */ - MALLOC_FAILURE_ACTION; - return 0; -} - -/* - sYSTRIm is an inverse of sorts to sYSMALLOc. It gives memory back - to the system (via negative arguments to sbrk) if there is unused - memory at the `high' end of the malloc pool. It is called - automatically by free() when top space exceeds the trim - threshold. It is also called by the public malloc_trim routine. It - returns 1 if it actually released any memory, else 0. -*/ - -#if __STD_C -static int sYSTRIm(size_t pad, mstate av) -#else -static int sYSTRIm(pad, av) -size_t pad; -mstate av; -#endif -{ - long top_size; /* Amount of top-most memory */ - long extra; /* Amount to release */ - long released; /* Amount actually released */ - char *current_brk; /* address returned by pre-check sbrk call */ - char *new_brk; /* address returned by post-check sbrk call */ - size_t pagesz; - - pagesz = av->pagesize; - top_size = chunksize(av->top); - - /* Release in pagesize units, keeping at least one page */ - extra = ((top_size - pad - MINSIZE + (pagesz - 1)) / pagesz - 1) * pagesz; - - if (extra > 0) { - - /* - Only proceed if end of memory is where we last set it. - This avoids problems if there were foreign sbrk calls. - */ - current_brk = (char *)(MORECORE(0)); - if (current_brk == (char *)(av->top) + top_size) { - - /* - Attempt to release memory. We ignore MORECORE return value, - and instead call again to find out where new end of memory is. - This avoids problems if first call releases less than we asked, - of if failure somehow altered brk value. (We could still - encounter problems if it altered brk in some very bad way, - but the only thing we can do is adjust anyway, which will cause - some downstream failure.) - */ - - MORECORE(-extra); - new_brk = (char *)(MORECORE(0)); - - if (new_brk != (char *)MORECORE_FAILURE) { - released = (long)(current_brk - new_brk); - - if (released != 0) { - /* Success. Adjust top. */ - av->sbrked_mem -= released; - set_head(av->top, (top_size - released) | PREV_INUSE); - check_malloc_state(); - return 1; - } - } - } - } - return 0; -} - -/* - ------------------------------ malloc ------------------------------ -*/ - -#if __STD_C -Void_t *mALLOc(size_t bytes) -#else -Void_t *mALLOc(bytes) -size_t bytes; -#endif -{ - mstate av = get_malloc_state(); - - INTERNAL_SIZE_T nb; /* normalized request size */ - unsigned int idx; /* associated bin index */ - mbinptr bin; /* associated bin */ - mfastbinptr *fb; /* associated fastbin */ - - mchunkptr victim; /* inspected/selected chunk */ - INTERNAL_SIZE_T size; /* its size */ - int victim_index; /* its bin index */ - - mchunkptr remainder; /* remainder from a split */ - CHUNK_SIZE_T remainder_size; /* its size */ - - unsigned int block; /* bit map traverser */ - unsigned int bit; /* bit map traverser */ - unsigned int map; /* current word of binmap */ - - mchunkptr fwd; /* misc temp for linking */ - mchunkptr bck; /* misc temp for linking */ - - /* - Convert request size to internal form by adding SIZE_SZ bytes - overhead plus possibly more to obtain necessary alignment and/or - to obtain a size of at least MINSIZE, the smallest allocatable - size. Also, checked_request2size traps (returning 0) request sizes - that are so large that they wrap around zero when padded and - aligned. - */ - - checked_request2size(bytes, nb); - - /* - Bypass search if no frees yet - */ - if (!have_anychunks(av)) { - if (av->max_fast == 0) { /* initialization check */ - malloc_consolidate(av); - } - goto use_top; - } - - /* - If the size qualifies as a fastbin, first check corresponding bin. - */ - - if ((CHUNK_SIZE_T)(nb) <= (CHUNK_SIZE_T)(av->max_fast)) { - fb = &(av->fastbins[(fastbin_index(nb))]); - if ((victim = *fb) != 0) { - *fb = victim->fd; - check_remalloced_chunk(victim, nb); - return chunk2mem(victim); - } - } - - /* - If a small request, check regular bin. Since these "smallbins" - hold one size each, no searching within bins is necessary. - (For a large request, we need to wait until unsorted chunks are - processed to find best fit. But for small ones, fits are exact - anyway, so we can check now, which is faster.) - */ - - if (in_smallbin_range(nb)) { - idx = smallbin_index(nb); - bin = bin_at(av, idx); - - if ((victim = last(bin)) != bin) { - bck = victim->bk; - set_inuse_bit_at_offset(victim, nb); - bin->bk = bck; - bck->fd = bin; - - check_malloced_chunk(victim, nb); - return chunk2mem(victim); - } - } - - /* - If this is a large request, consolidate fastbins before continuing. - While it might look excessive to kill all fastbins before - even seeing if there is space available, this avoids - fragmentation problems normally associated with fastbins. - Also, in practice, programs tend to have runs of either small or - large requests, but less often mixtures, so consolidation is not - invoked all that often in most programs. And the programs that - it is called frequently in otherwise tend to fragment. - */ - - else { - idx = largebin_index(nb); - if (have_fastchunks(av)) { - malloc_consolidate(av); - } - } - - /* - Process recently freed or remaindered chunks, taking one only if - it is exact fit, or, if this a small request, the chunk is remainder from - the most recent non-exact fit. Place other traversed chunks in - bins. Note that this step is the only place in any routine where - chunks are placed in bins. - */ - - while ((victim = unsorted_chunks(av)->bk) != unsorted_chunks(av)) { - bck = victim->bk; - size = chunksize(victim); - - /* - If a small request, try to use last remainder if it is the - only chunk in unsorted bin. This helps promote locality for - runs of consecutive small requests. This is the only - exception to best-fit, and applies only when there is - no exact fit for a small chunk. - */ - - if (in_smallbin_range(nb) && - bck == unsorted_chunks(av) && - victim == av->last_remainder && - (CHUNK_SIZE_T)(size) > (CHUNK_SIZE_T)(nb + MINSIZE)) { - - /* split and reattach remainder */ - remainder_size = size - nb; - remainder = chunk_at_offset(victim, nb); - unsorted_chunks(av)->bk = unsorted_chunks(av)->fd = remainder; - av->last_remainder = remainder; - remainder->bk = remainder->fd = unsorted_chunks(av); - - set_head(victim, nb | PREV_INUSE); - set_head(remainder, remainder_size | PREV_INUSE); - set_foot(remainder, remainder_size); - - check_malloced_chunk(victim, nb); - return chunk2mem(victim); - } - - /* remove from unsorted list */ - unsorted_chunks(av)->bk = bck; - bck->fd = unsorted_chunks(av); - - /* Take now instead of binning if exact fit */ - - if (size == nb) { - set_inuse_bit_at_offset(victim, size); - check_malloced_chunk(victim, nb); - return chunk2mem(victim); - } - - /* place chunk in bin */ - - if (in_smallbin_range(size)) { - victim_index = smallbin_index(size); - bck = bin_at(av, victim_index); - fwd = bck->fd; - } else { - victim_index = largebin_index(size); - bck = bin_at(av, victim_index); - fwd = bck->fd; - - if (fwd != bck) { - /* if smaller than smallest, place first */ - if ((CHUNK_SIZE_T)(size) < (CHUNK_SIZE_T)(bck->bk->size)) { - fwd = bck; - bck = bck->bk; - } else if ((CHUNK_SIZE_T)(size) >= - (CHUNK_SIZE_T)(FIRST_SORTED_BIN_SIZE)) { - - /* maintain large bins in sorted order */ - size |= PREV_INUSE; /* Or with inuse bit to speed comparisons */ - while ((CHUNK_SIZE_T)(size) < (CHUNK_SIZE_T)(fwd->size)) { - fwd = fwd->fd; - } - bck = fwd->bk; - } - } - } - - mark_bin(av, victim_index); - victim->bk = bck; - victim->fd = fwd; - fwd->bk = victim; - bck->fd = victim; - } - - /* - If a large request, scan through the chunks of current bin to - find one that fits. (This will be the smallest that fits unless - FIRST_SORTED_BIN_SIZE has been changed from default.) This is - the only step where an unbounded number of chunks might be - scanned without doing anything useful with them. However the - lists tend to be short. - */ - - if (!in_smallbin_range(nb)) { - bin = bin_at(av, idx); - - for (victim = last(bin); victim != bin; victim = victim->bk) { - size = chunksize(victim); - - if ((CHUNK_SIZE_T)(size) >= (CHUNK_SIZE_T)(nb)) { - remainder_size = size - nb; - unlink(victim, bck, fwd); - - /* Exhaust */ - if (remainder_size < MINSIZE) { - set_inuse_bit_at_offset(victim, size); - check_malloced_chunk(victim, nb); - return chunk2mem(victim); - } - /* Split */ - else { - remainder = chunk_at_offset(victim, nb); - unsorted_chunks(av)->bk = unsorted_chunks(av)->fd = remainder; - remainder->bk = remainder->fd = unsorted_chunks(av); - set_head(victim, nb | PREV_INUSE); - set_head(remainder, remainder_size | PREV_INUSE); - set_foot(remainder, remainder_size); - check_malloced_chunk(victim, nb); - return chunk2mem(victim); - } - } - } - } - - /* - Search for a chunk by scanning bins, starting with next largest - bin. This search is strictly by best-fit; i.e., the smallest - (with ties going to approximately the least recently used) chunk - that fits is selected. - - The bitmap avoids needing to check that most blocks are nonempty. - */ - - ++idx; - bin = bin_at(av, idx); - block = idx2block(idx); - map = av->binmap[block]; - bit = idx2bit(idx); - - for (;;) { - - /* Skip rest of block if there are no more set bits in this block. */ - if (bit > map || bit == 0) { - do { - if (++block >= BINMAPSIZE) { /* out of bins */ - goto use_top; - } - } while ((map = av->binmap[block]) == 0); - - bin = bin_at(av, (block << BINMAPSHIFT)); - bit = 1; - } - - /* Advance to bin with set bit. There must be one. */ - while ((bit & map) == 0) { - bin = next_bin(bin); - bit <<= 1; - assert(bit != 0); - } - - /* Inspect the bin. It is likely to be non-empty */ - victim = last(bin); - - /* If a false alarm (empty bin), clear the bit. */ - if (victim == bin) { - av->binmap[block] = map &= ~bit; /* Write through */ - bin = next_bin(bin); - bit <<= 1; - } - - else { - size = chunksize(victim); - - /* We know the first chunk in this bin is big enough to use. */ - assert((CHUNK_SIZE_T)(size) >= (CHUNK_SIZE_T)(nb)); - - remainder_size = size - nb; - - /* unlink */ - bck = victim->bk; - bin->bk = bck; - bck->fd = bin; - - /* Exhaust */ - if (remainder_size < MINSIZE) { - set_inuse_bit_at_offset(victim, size); - check_malloced_chunk(victim, nb); - return chunk2mem(victim); - } - - /* Split */ - else { - remainder = chunk_at_offset(victim, nb); - - unsorted_chunks(av)->bk = unsorted_chunks(av)->fd = remainder; - remainder->bk = remainder->fd = unsorted_chunks(av); - /* advertise as last remainder */ - if (in_smallbin_range(nb)) { - av->last_remainder = remainder; - } - - set_head(victim, nb | PREV_INUSE); - set_head(remainder, remainder_size | PREV_INUSE); - set_foot(remainder, remainder_size); - check_malloced_chunk(victim, nb); - return chunk2mem(victim); - } - } - } - -use_top: - /* - If large enough, split off the chunk bordering the end of memory - (held in av->top). Note that this is in accord with the best-fit - search rule. In effect, av->top is treated as larger (and thus - less well fitting) than any other available chunk since it can - be extended to be as large as necessary (up to system - limitations). - - We require that av->top always exists (i.e., has size >= - MINSIZE) after initialization, so if it would otherwise be - exhuasted by current request, it is replenished. (The main - reason for ensuring it exists is that we may need MINSIZE space - to put in fenceposts in sysmalloc.) - */ - - victim = av->top; - size = chunksize(victim); - - if ((CHUNK_SIZE_T)(size) >= (CHUNK_SIZE_T)(nb + MINSIZE)) { - remainder_size = size - nb; - remainder = chunk_at_offset(victim, nb); - av->top = remainder; - set_head(victim, nb | PREV_INUSE); - set_head(remainder, remainder_size | PREV_INUSE); - - check_malloced_chunk(victim, nb); - return chunk2mem(victim); - } - - /* - If no space in top, relay to handle system-dependent cases - */ - return sYSMALLOc(nb, av); -} - -/* - ------------------------------ free ------------------------------ -*/ - -#if __STD_C -void fREe(Void_t *mem) -#else -void fREe(mem) Void_t *mem; -#endif -{ - mstate av = get_malloc_state(); - - mchunkptr p; /* chunk corresponding to mem */ - INTERNAL_SIZE_T size; /* its size */ - mfastbinptr *fb; /* associated fastbin */ - mchunkptr nextchunk; /* next contiguous chunk */ - INTERNAL_SIZE_T nextsize; /* its size */ - int nextinuse; /* true if nextchunk is used */ - INTERNAL_SIZE_T prevsize; /* size of previous contiguous chunk */ - mchunkptr bck; /* misc temp for linking */ - mchunkptr fwd; /* misc temp for linking */ - - /* free(0) has no effect */ - if (mem != 0) { - p = mem2chunk(mem); - size = chunksize(p); - - check_inuse_chunk(p); - - /* - If eligible, place chunk on a fastbin so it can be found - and used quickly in malloc. - */ - - if ((CHUNK_SIZE_T)(size) <= (CHUNK_SIZE_T)(av->max_fast) - -#if TRIM_FASTBINS - /* - If TRIM_FASTBINS set, don't place chunks - bordering top into fastbins - */ - && (chunk_at_offset(p, size) != av->top) -#endif - ) { - - set_fastchunks(av); - fb = &(av->fastbins[fastbin_index(size)]); - p->fd = *fb; - *fb = p; - } - - /* - Consolidate other non-mmapped chunks as they arrive. - */ - - else if (!chunk_is_mmapped(p)) { - set_anychunks(av); - - nextchunk = chunk_at_offset(p, size); - nextsize = chunksize(nextchunk); - - /* consolidate backward */ - if (!prev_inuse(p)) { - prevsize = p->prev_size; - size += prevsize; - p = chunk_at_offset(p, -((long)prevsize)); - unlink(p, bck, fwd); - } - - if (nextchunk != av->top) { - /* get and clear inuse bit */ - nextinuse = inuse_bit_at_offset(nextchunk, nextsize); - set_head(nextchunk, nextsize); - - /* consolidate forward */ - if (!nextinuse) { - unlink(nextchunk, bck, fwd); - size += nextsize; - } - - /* - Place the chunk in unsorted chunk list. Chunks are - not placed into regular bins until after they have - been given one chance to be used in malloc. - */ - - bck = unsorted_chunks(av); - fwd = bck->fd; - p->bk = bck; - p->fd = fwd; - bck->fd = p; - fwd->bk = p; - - set_head(p, size | PREV_INUSE); - set_foot(p, size); - - check_free_chunk(p); - } - - /* - If the chunk borders the current high end of memory, - consolidate into top - */ - - else { - size += nextsize; - set_head(p, size | PREV_INUSE); - av->top = p; - check_chunk(p); - } - - /* - If freeing a large space, consolidate possibly-surrounding - chunks. Then, if the total unused topmost memory exceeds trim - threshold, ask malloc_trim to reduce top. - - Unless max_fast is 0, we don't know if there are fastbins - bordering top, so we cannot tell for sure whether threshold - has been reached unless fastbins are consolidated. But we - don't want to consolidate on each free. As a compromise, - consolidation is performed if FASTBIN_CONSOLIDATION_THRESHOLD - is reached. - */ - - if ((CHUNK_SIZE_T)(size) >= FASTBIN_CONSOLIDATION_THRESHOLD) { - if (have_fastchunks(av)) { - malloc_consolidate(av); - } - -#ifndef MORECORE_CANNOT_TRIM - if ((CHUNK_SIZE_T)(chunksize(av->top)) >= - (CHUNK_SIZE_T)(av->trim_threshold)) { - sYSTRIm(av->top_pad, av); - } -#endif - } - } - /* - If the chunk was allocated via mmap, release via munmap() - Note that if HAVE_MMAP is false but chunk_is_mmapped is - true, then user must have overwritten memory. There's nothing - we can do to catch this error unless DL_DEBUG is set, in which case - check_inuse_chunk (above) will have triggered error. - */ - - else { -#if HAVE_MMAP - INTERNAL_SIZE_T offset = p->prev_size; - av->n_mmaps--; - av->mmapped_mem -= (size + offset); - munmap((char *)p - offset, size + offset); -#endif - } - } -} - -/* - ------------------------- malloc_consolidate ------------------------- - - malloc_consolidate is a specialized version of free() that tears - down chunks held in fastbins. Free itself cannot be used for this - purpose since, among other things, it might place chunks back onto - fastbins. So, instead, we need to use a minor variant of the same - code. - - Also, because this routine needs to be called the first time through - malloc anyway, it turns out to be the perfect place to trigger - initialization code. -*/ - -#if __STD_C -static void malloc_consolidate(mstate av) -#else -static void malloc_consolidate(av) mstate av; -#endif -{ - mfastbinptr *fb; /* current fastbin being consolidated */ - mfastbinptr *maxfb; /* last fastbin (for loop control) */ - mchunkptr p; /* current chunk being consolidated */ - mchunkptr nextp; /* next chunk to consolidate */ - mchunkptr unsorted_bin; /* bin header */ - mchunkptr first_unsorted; /* chunk to link to */ - - /* These have same use as in free() */ - mchunkptr nextchunk; - INTERNAL_SIZE_T size; - INTERNAL_SIZE_T nextsize; - INTERNAL_SIZE_T prevsize; - int nextinuse; - mchunkptr bck; - mchunkptr fwd; - - /* - If max_fast is 0, we know that av hasn't - yet been initialized, in which case do so below - */ - - if (av->max_fast != 0) { - clear_fastchunks(av); - - unsorted_bin = unsorted_chunks(av); - - /* - Remove each chunk from fast bin and consolidate it, placing it - then in unsorted bin. Among other reasons for doing this, - placing in unsorted bin avoids needing to calculate actual bins - until malloc is sure that chunks aren't immediately going to be - reused anyway. - */ - - maxfb = &(av->fastbins[fastbin_index(av->max_fast)]); - fb = &(av->fastbins[0]); - do { - if ((p = *fb) != 0) { - *fb = 0; - - do { - check_inuse_chunk(p); - nextp = p->fd; - - /* Slightly streamlined version of consolidation code in free() */ - size = p->size & ~PREV_INUSE; - nextchunk = chunk_at_offset(p, size); - nextsize = chunksize(nextchunk); - - if (!prev_inuse(p)) { - prevsize = p->prev_size; - size += prevsize; - p = chunk_at_offset(p, -((long)prevsize)); - unlink(p, bck, fwd); - } - - if (nextchunk != av->top) { - nextinuse = inuse_bit_at_offset(nextchunk, nextsize); - set_head(nextchunk, nextsize); - - if (!nextinuse) { - size += nextsize; - unlink(nextchunk, bck, fwd); - } - - first_unsorted = unsorted_bin->fd; - unsorted_bin->fd = p; - first_unsorted->bk = p; - - set_head(p, size | PREV_INUSE); - p->bk = unsorted_bin; - p->fd = first_unsorted; - set_foot(p, size); - } - - else { - size += nextsize; - set_head(p, size | PREV_INUSE); - av->top = p; - } - - } while ((p = nextp) != 0); - } - } while (fb++ != maxfb); - } else { - malloc_init_state(av); - check_malloc_state(); - } -} - -/* - ------------------------------ realloc ------------------------------ -*/ - -#if __STD_C -Void_t *rEALLOc(Void_t *oldmem, size_t bytes) -#else -Void_t *rEALLOc(oldmem, bytes) -Void_t *oldmem; -size_t bytes; -#endif -{ - mstate av = get_malloc_state(); - - INTERNAL_SIZE_T nb; /* padded request size */ - - mchunkptr oldp; /* chunk corresponding to oldmem */ - INTERNAL_SIZE_T oldsize; /* its size */ - - mchunkptr newp; /* chunk to return */ - INTERNAL_SIZE_T newsize; /* its size */ - Void_t *newmem; /* corresponding user mem */ - - mchunkptr next; /* next contiguous chunk after oldp */ - - mchunkptr remainder; /* extra space at end of newp */ - CHUNK_SIZE_T remainder_size; /* its size */ - - mchunkptr bck; /* misc temp for linking */ - mchunkptr fwd; /* misc temp for linking */ - - CHUNK_SIZE_T copysize; /* bytes to copy */ - unsigned int ncopies; /* INTERNAL_SIZE_T words to copy */ - INTERNAL_SIZE_T *s; /* copy source */ - INTERNAL_SIZE_T *d; /* copy destination */ - -#ifdef REALLOC_ZERO_BYTES_FREES - if (bytes == 0) { - fREe(oldmem); - return 0; - } -#endif - - /* realloc of null is supposed to be same as malloc */ - if (oldmem == 0) { - return mALLOc(bytes); - } - - checked_request2size(bytes, nb); - - oldp = mem2chunk(oldmem); - oldsize = chunksize(oldp); - - check_inuse_chunk(oldp); - - if (!chunk_is_mmapped(oldp)) { - - if ((CHUNK_SIZE_T)(oldsize) >= (CHUNK_SIZE_T)(nb)) { - /* already big enough; split below */ - newp = oldp; - newsize = oldsize; - } - - else { - next = chunk_at_offset(oldp, oldsize); - - /* Try to expand forward into top */ - if (next == av->top && - (CHUNK_SIZE_T)(newsize = oldsize + chunksize(next)) >= - (CHUNK_SIZE_T)(nb + MINSIZE)) { - set_head_size(oldp, nb); - av->top = chunk_at_offset(oldp, nb); - set_head(av->top, (newsize - nb) | PREV_INUSE); - return chunk2mem(oldp); - } - - /* Try to expand forward into next chunk; split off remainder below */ - else if (next != av->top && - !inuse(next) && - (CHUNK_SIZE_T)(newsize = oldsize + chunksize(next)) >= - (CHUNK_SIZE_T)(nb)) { - newp = oldp; - unlink(next, bck, fwd); - } - - /* allocate, copy, free */ - else { - newmem = mALLOc(nb - MALLOC_ALIGN_MASK); - if (newmem == 0) { - return 0; /* propagate failure */ - } - - newp = mem2chunk(newmem); - newsize = chunksize(newp); - - /* - Avoid copy if newp is next chunk after oldp. - */ - if (newp == next) { - newsize += oldsize; - newp = oldp; - } else { - /* - Unroll copy of <= 36 bytes (72 if 8byte sizes) - We know that contents have an odd number of - INTERNAL_SIZE_T-sized words; minimally 3. - */ - - copysize = oldsize - SIZE_SZ; - s = (INTERNAL_SIZE_T *)(oldmem); - d = (INTERNAL_SIZE_T *)(newmem); - ncopies = copysize / sizeof(INTERNAL_SIZE_T); - assert(ncopies >= 3); - - if (ncopies > 9) { - MALLOC_COPY(d, s, copysize); - } - - else { - *(d + 0) = *(s + 0); - *(d + 1) = *(s + 1); - *(d + 2) = *(s + 2); - if (ncopies > 4) { - *(d + 3) = *(s + 3); - *(d + 4) = *(s + 4); - if (ncopies > 6) { - *(d + 5) = *(s + 5); - *(d + 6) = *(s + 6); - if (ncopies > 8) { - *(d + 7) = *(s + 7); - *(d + 8) = *(s + 8); - } - } - } - } - - fREe(oldmem); - check_inuse_chunk(newp); - return chunk2mem(newp); - } - } - } - - /* If possible, free extra space in old or extended chunk */ - - assert((CHUNK_SIZE_T)(newsize) >= (CHUNK_SIZE_T)(nb)); - - remainder_size = newsize - nb; - - if (remainder_size < MINSIZE) { /* not enough extra to split off */ - set_head_size(newp, newsize); - set_inuse_bit_at_offset(newp, newsize); - } else { /* split remainder */ - remainder = chunk_at_offset(newp, nb); - set_head_size(newp, nb); - set_head(remainder, remainder_size | PREV_INUSE); - /* Mark remainder as inuse so free() won't complain */ - set_inuse_bit_at_offset(remainder, remainder_size); - fREe(chunk2mem(remainder)); - } - - check_inuse_chunk(newp); - return chunk2mem(newp); - } - - /* - Handle mmap cases - */ - - else { -#if HAVE_MMAP - -#if HAVE_MREMAP - INTERNAL_SIZE_T offset = oldp->prev_size; - size_t pagemask = av->pagesize - 1; - char *cp; - CHUNK_SIZE_T sum; - - /* Note the extra SIZE_SZ overhead */ - newsize = (nb + offset + SIZE_SZ + pagemask) & ~pagemask; - - /* don't need to remap if still within same page */ - if (oldsize == newsize - offset) { - return oldmem; - } - - cp = (char *)mremap((char *)oldp - offset, oldsize + offset, newsize, 1); - - if (cp != (char *)MORECORE_FAILURE) { - - newp = (mchunkptr)(cp + offset); - set_head(newp, (newsize - offset) | IS_MMAPPED); - - assert(aligned_OK(chunk2mem(newp))); - assert((newp->prev_size == offset)); - - /* update statistics */ - sum = av->mmapped_mem += newsize - oldsize; - if (sum > (CHUNK_SIZE_T)(av->max_mmapped_mem)) { - av->max_mmapped_mem = sum; - } - sum += av->sbrked_mem; - if (sum > (CHUNK_SIZE_T)(av->max_total_mem)) { - av->max_total_mem = sum; - } - - return chunk2mem(newp); - } -#endif - - /* Note the extra SIZE_SZ overhead. */ - if ((CHUNK_SIZE_T)(oldsize) >= (CHUNK_SIZE_T)(nb + SIZE_SZ)) { - newmem = oldmem; /* do nothing */ - } else { - /* Must alloc, copy, free. */ - newmem = mALLOc(nb - MALLOC_ALIGN_MASK); - if (newmem != 0) { - MALLOC_COPY(newmem, oldmem, oldsize - 2 * SIZE_SZ); - fREe(oldmem); - } - } - return newmem; - -#else - /* If !HAVE_MMAP, but chunk_is_mmapped, user must have overwritten mem */ - check_malloc_state(); - MALLOC_FAILURE_ACTION; - return 0; -#endif - } -} - -/* - ------------------------------ memalign ------------------------------ -*/ - -#if __STD_C -Void_t *mEMALIGn(size_t alignment, size_t bytes) -#else -Void_t *mEMALIGn(alignment, bytes) -size_t alignment; -size_t bytes; -#endif -{ - INTERNAL_SIZE_T nb; /* padded request size */ - char *m; /* memory returned by malloc call */ - mchunkptr p; /* corresponding chunk */ - char *brk; /* alignment point within p */ - mchunkptr newp; /* chunk to return */ - INTERNAL_SIZE_T newsize; /* its size */ - INTERNAL_SIZE_T leadsize; /* leading space before alignment point */ - mchunkptr remainder; /* spare room at end to split off */ - CHUNK_SIZE_T remainder_size; /* its size */ - INTERNAL_SIZE_T size; - - /* If need less alignment than we give anyway, just relay to malloc */ - - if (alignment <= MALLOC_ALIGNMENT) { - return mALLOc(bytes); - } - - /* Otherwise, ensure that it is at least a minimum chunk size */ - - if (alignment < MINSIZE) { - alignment = MINSIZE; - } - - /* Make sure alignment is power of 2 (in case MINSIZE is not). */ - if ((alignment & (alignment - 1)) != 0) { - size_t a = MALLOC_ALIGNMENT * 2; - while ((CHUNK_SIZE_T)a < (CHUNK_SIZE_T)alignment) { - a <<= 1; - } - alignment = a; - } - - checked_request2size(bytes, nb); - - /* - Strategy: find a spot within that chunk that meets the alignment - request, and then possibly free the leading and trailing space. - */ - - /* Call malloc with worst case padding to hit alignment. */ - - m = (char *)(mALLOc(nb + alignment + MINSIZE)); - - if (m == 0) { - return 0; /* propagate failure */ - } - - p = mem2chunk(m); - - if ((((PTR_UINT)(m)) % alignment) != 0) { /* misaligned */ - - /* - Find an aligned spot inside chunk. Since we need to give back - leading space in a chunk of at least MINSIZE, if the first - calculation places us at a spot with less than MINSIZE leader, - we can move to the next aligned spot -- we've allocated enough - total room so that this is always possible. - */ - - brk = (char *)mem2chunk((PTR_UINT)(((PTR_UINT)(m + alignment - 1)) & - -((signed long)alignment))); - if ((CHUNK_SIZE_T)(brk - (char *)(p)) < MINSIZE) { - brk += alignment; - } - - newp = (mchunkptr)brk; - leadsize = brk - (char *)(p); - newsize = chunksize(p) - leadsize; - - /* For mmapped chunks, just adjust offset */ - if (chunk_is_mmapped(p)) { - newp->prev_size = p->prev_size + leadsize; - set_head(newp, newsize | IS_MMAPPED); - return chunk2mem(newp); - } - - /* Otherwise, give back leader, use the rest */ - set_head(newp, newsize | PREV_INUSE); - set_inuse_bit_at_offset(newp, newsize); - set_head_size(p, leadsize); - fREe(chunk2mem(p)); - p = newp; - - assert(newsize >= nb && - (((PTR_UINT)(chunk2mem(p))) % alignment) == 0); - } - - /* Also give back spare room at the end */ - if (!chunk_is_mmapped(p)) { - size = chunksize(p); - if ((CHUNK_SIZE_T)(size) > (CHUNK_SIZE_T)(nb + MINSIZE)) { - remainder_size = size - nb; - remainder = chunk_at_offset(p, nb); - set_head(remainder, remainder_size | PREV_INUSE); - set_head_size(p, nb); - fREe(chunk2mem(remainder)); - } - } - - check_inuse_chunk(p); - return chunk2mem(p); -} - -/* - ------------------------------ calloc ------------------------------ -*/ - -#if __STD_C -Void_t *cALLOc(size_t n_elements, size_t elem_size) -#else -Void_t *cALLOc(n_elements, elem_size) -size_t n_elements; -size_t elem_size; -#endif -{ - mchunkptr p; - CHUNK_SIZE_T clearsize; - CHUNK_SIZE_T nclears; - INTERNAL_SIZE_T *d; - - Void_t *mem = mALLOc(n_elements * elem_size); - - if (mem != 0) { - p = mem2chunk(mem); - - if (!chunk_is_mmapped(p)) { - /* - Unroll clear of <= 36 bytes (72 if 8byte sizes) - We know that contents have an odd number of - INTERNAL_SIZE_T-sized words; minimally 3. - */ - - d = (INTERNAL_SIZE_T *)mem; - clearsize = chunksize(p) - SIZE_SZ; - nclears = clearsize / sizeof(INTERNAL_SIZE_T); - assert(nclears >= 3); - - if (nclears > 9) { - MALLOC_ZERO(d, clearsize); - } - - else { - *(d + 0) = 0; - *(d + 1) = 0; - *(d + 2) = 0; - if (nclears > 4) { - *(d + 3) = 0; - *(d + 4) = 0; - if (nclears > 6) { - *(d + 5) = 0; - *(d + 6) = 0; - if (nclears > 8) { - *(d + 7) = 0; - *(d + 8) = 0; - } - } - } - } - } -#if !MMAP_CLEARS - else { - d = (INTERNAL_SIZE_T *)mem; - /* - Note the additional SIZE_SZ - */ - clearsize = chunksize(p) - 2 * SIZE_SZ; - MALLOC_ZERO(d, clearsize); - } -#endif - } - return mem; -} - -/* - ------------------------------ cfree ------------------------------ -*/ - -#if __STD_C -void cFREe(Void_t *mem) -#else -void cFREe(mem) Void_t *mem; -#endif -{ - fREe(mem); -} - -/* - ------------------------- independent_calloc ------------------------- -*/ - -#if __STD_C -Void_t **iCALLOc(size_t n_elements, size_t elem_size, Void_t *chunks[]) -#else -Void_t **iCALLOc(n_elements, elem_size, chunks) -size_t n_elements; -size_t elem_size; -Void_t *chunks[]; -#endif -{ - size_t sz = elem_size; /* serves as 1-element array */ - /* opts arg of 3 means all elements are same size, and should be cleared */ - return iALLOc(n_elements, &sz, 3, chunks); -} - -/* - ------------------------- independent_comalloc ------------------------- -*/ - -#if __STD_C -Void_t **iCOMALLOc(size_t n_elements, size_t sizes[], Void_t *chunks[]) -#else -Void_t **iCOMALLOc(n_elements, sizes, chunks) -size_t n_elements; -size_t sizes[]; -Void_t *chunks[]; -#endif -{ - return iALLOc(n_elements, sizes, 0, chunks); -} - -/* - ------------------------------ ialloc ------------------------------ - ialloc provides common support for independent_X routines, handling all of - the combinations that can result. - - The opts arg has: - bit 0 set if all elements are same size (using sizes[0]) - bit 1 set if elements should be zeroed -*/ - -#if __STD_C -static Void_t **iALLOc(size_t n_elements, - size_t *sizes, - int opts, - Void_t *chunks[]) -#else -static Void_t **iALLOc(n_elements, sizes, opts, chunks) -size_t n_elements; -size_t *sizes; -int opts; -Void_t *chunks[]; -#endif -{ - mstate av = get_malloc_state(); - INTERNAL_SIZE_T element_size; /* chunksize of each element, if all same */ - INTERNAL_SIZE_T contents_size; /* total size of elements */ - INTERNAL_SIZE_T array_size; /* request size of pointer array */ - Void_t *mem; /* malloced aggregate space */ - mchunkptr p; /* corresponding chunk */ - INTERNAL_SIZE_T remainder_size; /* remaining bytes while splitting */ - Void_t **marray; /* either "chunks" or malloced ptr array */ - mchunkptr array_chunk; /* chunk for malloced ptr array */ - int mmx; /* to disable mmap */ - INTERNAL_SIZE_T size; - size_t i; - - /* Ensure initialization */ - if (av->max_fast == 0) { - malloc_consolidate(av); - } - - /* compute array length, if needed */ - if (chunks != 0) { - if (n_elements == 0) { - return chunks; /* nothing to do */ - } - marray = chunks; - array_size = 0; - } else { - /* if empty req, must still return chunk representing empty array */ - if (n_elements == 0) { - return (Void_t **)mALLOc(0); - } - marray = 0; - array_size = request2size(n_elements * (sizeof(Void_t *))); - } - - /* compute total element size */ - if (opts & 0x1) { /* all-same-size */ - element_size = request2size(*sizes); - contents_size = n_elements * element_size; - } else { /* add up all the sizes */ - element_size = 0; - contents_size = 0; - for (i = 0; i != n_elements; ++i) { - contents_size += request2size(sizes[i]); - } - } - - /* subtract out alignment bytes from total to minimize overallocation */ - size = contents_size + array_size - MALLOC_ALIGN_MASK; - - /* - Allocate the aggregate chunk. - But first disable mmap so malloc won't use it, since - we would not be able to later free/realloc space internal - to a segregated mmap region. - */ - mmx = av->n_mmaps_max; /* disable mmap */ - av->n_mmaps_max = 0; - mem = mALLOc(size); - av->n_mmaps_max = mmx; /* reset mmap */ - if (mem == 0) { - return 0; - } - - p = mem2chunk(mem); - assert(!chunk_is_mmapped(p)); - remainder_size = chunksize(p); - - if (opts & 0x2) { /* optionally clear the elements */ - MALLOC_ZERO(mem, remainder_size - SIZE_SZ - array_size); - } - - /* If not provided, allocate the pointer array as final part of chunk */ - if (marray == 0) { - array_chunk = chunk_at_offset(p, contents_size); - marray = (Void_t **)(chunk2mem(array_chunk)); - set_head(array_chunk, (remainder_size - contents_size) | PREV_INUSE); - remainder_size = contents_size; - } - - /* split out elements */ - for (i = 0;; ++i) { - marray[i] = chunk2mem(p); - if (i != n_elements - 1) { - if (element_size != 0) { - size = element_size; - } else { - size = request2size(sizes[i]); - } - remainder_size -= size; - set_head(p, size | PREV_INUSE); - p = chunk_at_offset(p, size); - } else { /* the final element absorbs any overallocation slop */ - set_head(p, remainder_size | PREV_INUSE); - break; - } - } - -#if DL_DEBUG - if (marray != chunks) { - /* final element must have exactly exhausted chunk */ - if (element_size != 0) { - assert(remainder_size == element_size); - } else { - assert(remainder_size == request2size(sizes[i])); - } - check_inuse_chunk(mem2chunk(marray)); - } - - for (i = 0; i != n_elements; ++i) { - check_inuse_chunk(mem2chunk(marray[i])); - } -#endif - - return marray; -} - -/* - ------------------------------ valloc ------------------------------ -*/ - -#if __STD_C -Void_t *vALLOc(size_t bytes) -#else -Void_t *vALLOc(bytes) -size_t bytes; -#endif -{ - /* Ensure initialization */ - mstate av = get_malloc_state(); - if (av->max_fast == 0) { - malloc_consolidate(av); - } - return mEMALIGn(av->pagesize, bytes); -} - -/* - ------------------------------ pvalloc ------------------------------ -*/ - -#if __STD_C -Void_t *pVALLOc(size_t bytes) -#else -Void_t *pVALLOc(bytes) -size_t bytes; -#endif -{ - mstate av = get_malloc_state(); - size_t pagesz; - - /* Ensure initialization */ - if (av->max_fast == 0) { - malloc_consolidate(av); - } - pagesz = av->pagesize; - return mEMALIGn(pagesz, (bytes + pagesz - 1) & ~(pagesz - 1)); -} - -/* - ------------------------------ malloc_trim ------------------------------ -*/ - -#if __STD_C -int mTRIm(size_t pad) -#else -int mTRIm(pad) -size_t pad; -#endif -{ - mstate av = get_malloc_state(); - /* Ensure initialization/consolidation */ - malloc_consolidate(av); - -#ifndef MORECORE_CANNOT_TRIM - return sYSTRIm(pad, av); -#else - return 0; -#endif -} - -/* - ------------------------- malloc_usable_size ------------------------- -*/ - -#if __STD_C -size_t mUSABLe(Void_t *mem) -#else -size_t mUSABLe(mem) -Void_t *mem; -#endif -{ - mchunkptr p; - if (mem != 0) { - p = mem2chunk(mem); - if (chunk_is_mmapped(p)) { - return chunksize(p) - 2 * SIZE_SZ; - } else if (inuse(p)) { - return chunksize(p) - SIZE_SZ; - } - } - return 0; -} - -/* - ------------------------------ mallinfo ------------------------------ -*/ - -struct mallinfo mALLINFo() { - mstate av = get_malloc_state(); - struct mallinfo mi; - int i; - mbinptr b; - mchunkptr p; - INTERNAL_SIZE_T avail; - INTERNAL_SIZE_T fastavail; - int nblocks; - int nfastblocks; - - /* Ensure initialization */ - if (av->top == 0) { - malloc_consolidate(av); - } - - check_malloc_state(); - - /* Account for top */ - avail = chunksize(av->top); - nblocks = 1; /* top always exists */ - - /* traverse fastbins */ - nfastblocks = 0; - fastavail = 0; - - for (i = 0; NFASTBINS - i > 0; ++i) { - for (p = av->fastbins[i]; p != 0; p = p->fd) { - ++nfastblocks; - fastavail += chunksize(p); - } - } - - avail += fastavail; - - /* traverse regular bins */ - for (i = 1; i < NBINS; ++i) { - b = bin_at(av, i); - for (p = last(b); p != b; p = p->bk) { - ++nblocks; - avail += chunksize(p); - } - } - - mi.smblks = nfastblocks; - mi.ordblks = nblocks; - mi.fordblks = avail; - mi.uordblks = av->sbrked_mem - avail; - mi.arena = av->sbrked_mem; - mi.hblks = av->n_mmaps; - mi.hblkhd = av->mmapped_mem; - mi.fsmblks = fastavail; - mi.keepcost = chunksize(av->top); - mi.usmblks = av->max_total_mem; - return mi; -} - -/* - ------------------------------ malloc_stats ------------------------------ -*/ - -void mSTATs(void) { - struct mallinfo mi = mALLINFo(); - -#ifdef WIN32 - { - CHUNK_SIZE_T free, reserved, committed; - vminfo(&free, &reserved, &committed); - fprintf(stderr, "free bytes = %10lu\n", - free); - fprintf(stderr, "reserved bytes = %10lu\n", - reserved); - fprintf(stderr, "committed bytes = %10lu\n", - committed); - } -#endif - - fprintf(stderr, "max system bytes = %10lu\n", - (CHUNK_SIZE_T)(mi.usmblks)); - fprintf(stderr, "system bytes = %10lu\n", - (CHUNK_SIZE_T)(mi.arena + mi.hblkhd)); - fprintf(stderr, "in use bytes = %10lu\n", - (CHUNK_SIZE_T)(mi.uordblks + mi.hblkhd)); - -#ifdef WIN32 - { - CHUNK_SIZE_T kernel, user; - if (cpuinfo(TRUE, &kernel, &user)) { - fprintf(stderr, "kernel ms = %10lu\n", - kernel); - fprintf(stderr, "user ms = %10lu\n", - user); - } - } -#endif -} - -/* - ------------------------------ mallopt ------------------------------ -*/ - -#if __STD_C -int mALLOPt(int param_number, int value) -#else -int mALLOPt(param_number, value) -int param_number; -int value; -#endif -{ - mstate av = get_malloc_state(); - /* Ensure initialization/consolidation */ - malloc_consolidate(av); - - switch (param_number) { - case M_MXFAST: - if (value >= 0 && value <= MAX_FAST_SIZE) { - set_max_fast(av, value); - return 1; - } else { - return 0; - } - - case M_TRIM_THRESHOLD: - av->trim_threshold = value; - return 1; - - case M_TOP_PAD: - av->top_pad = value; - return 1; - - case M_MMAP_THRESHOLD: - av->mmap_threshold = value; - return 1; - - case M_MMAP_MAX: -#if !HAVE_MMAP - if (value != 0) { - return 0; - } -#endif - av->n_mmaps_max = value; - return 1; - - default: - return 0; - } -} - -/* - -------------------- Alternative MORECORE functions -------------------- -*/ - -/* - General Requirements for MORECORE. - - The MORECORE function must have the following properties: - - If MORECORE_CONTIGUOUS is false: - - * MORECORE must allocate in multiples of pagesize. It will - only be called with arguments that are multiples of pagesize. - - * MORECORE(0) must return an address that is at least - MALLOC_ALIGNMENT aligned. (Page-aligning always suffices.) - - else (i.e. If MORECORE_CONTIGUOUS is true): - - * Consecutive calls to MORECORE with positive arguments - return increasing addresses, indicating that space has been - contiguously extended. - - * MORECORE need not allocate in multiples of pagesize. - Calls to MORECORE need not have args of multiples of pagesize. - - * MORECORE need not page-align. - - In either case: - - * MORECORE may allocate more memory than requested. (Or even less, - but this will generally result in a malloc failure.) - - * MORECORE must not allocate memory when given argument zero, but - instead return one past the end address of memory from previous - nonzero call. This malloc does NOT call MORECORE(0) - until at least one call with positive arguments is made, so - the initial value returned is not important. - - * Even though consecutive calls to MORECORE need not return contiguous - addresses, it must be OK for malloc'ed chunks to span multiple - regions in those cases where they do happen to be contiguous. - - * MORECORE need not handle negative arguments -- it may instead - just return MORECORE_FAILURE when given negative arguments. - Negative arguments are always multiples of pagesize. MORECORE - must not misinterpret negative args as large positive unsigned - args. You can suppress all such calls from even occurring by defining - MORECORE_CANNOT_TRIM, - - There is some variation across systems about the type of the - argument to sbrk/MORECORE. If size_t is unsigned, then it cannot - actually be size_t, because sbrk supports negative args, so it is - normally the signed type of the same width as size_t (sometimes - declared as "intptr_t", and sometimes "ptrdiff_t"). It doesn't much - matter though. Internally, we use "long" as arguments, which should - work across all reasonable possibilities. - - Additionally, if MORECORE ever returns failure for a positive - request, and HAVE_MMAP is true, then mmap is used as a noncontiguous - system allocator. This is a useful backup strategy for systems with - holes in address spaces -- in this case sbrk cannot contiguously - expand the heap, but mmap may be able to map noncontiguous space. - - If you'd like mmap to ALWAYS be used, you can define MORECORE to be - a function that always returns MORECORE_FAILURE. - - Malloc only has limited ability to detect failures of MORECORE - to supply contiguous space when it says it can. In particular, - multithreaded programs that do not use locks may result in - rece conditions across calls to MORECORE that result in gaps - that cannot be detected as such, and subsequent corruption. - - If you are using this malloc with something other than sbrk (or its - emulation) to supply memory regions, you probably want to set - MORECORE_CONTIGUOUS as false. As an example, here is a custom - allocator kindly contributed for pre-OSX macOS. It uses virtually - but not necessarily physically contiguous non-paged memory (locked - in, present and won't get swapped out). You can use it by - uncommenting this section, adding some #includes, and setting up the - appropriate defines above: - - #define MORECORE osMoreCore - #define MORECORE_CONTIGUOUS 0 - - There is also a shutdown routine that should somehow be called for - cleanup upon program exit. - - #define MAX_POOL_ENTRIES 100 - #define MINIMUM_MORECORE_SIZE (64 * 1024) - static int next_os_pool; - void *our_os_pools[MAX_POOL_ENTRIES]; - - void *osMoreCore(int size) - { - void *ptr = 0; - static void *sbrk_top = 0; - - if (size > 0) - { - if (size < MINIMUM_MORECORE_SIZE) - size = MINIMUM_MORECORE_SIZE; - if (CurrentExecutionLevel() == kTaskLevel) - ptr = PoolAllocateResident(size + RM_PAGE_SIZE, 0); - if (ptr == 0) - { - return (void *) MORECORE_FAILURE; - } - // save ptrs so they can be freed during cleanup - our_os_pools[next_os_pool] = ptr; - next_os_pool++; - ptr = (void *) ((((CHUNK_SIZE_T) ptr) + RM_PAGE_MASK) & ~RM_PAGE_MASK); - sbrk_top = (char *) ptr + size; - return ptr; - } - else if (size < 0) - { - // we don't currently support shrink behavior - return (void *) MORECORE_FAILURE; - } - else - { - return sbrk_top; - } - } - - // cleanup any allocated memory pools - // called as last thing before shutting down driver - - void osCleanupMem(void) - { - void **ptr; - - for (ptr = our_os_pools; ptr < &our_os_pools[MAX_POOL_ENTRIES]; ptr++) - if (*ptr) - { - PoolDeallocate(*ptr); - *ptr = 0; - } - } - -*/ - -/* - -------------------------------------------------------------- - - Emulation of sbrk for win32. - Donated by J. Walter . - For additional information about this code, and malloc on Win32, see - http://www.genesys-e.de/jwalter/ -*/ - -#ifdef WIN32 - -#ifdef _DEBUG -/* #define TRACE */ -#endif - -/* Support for USE_MALLOC_LOCK */ -#ifdef USE_MALLOC_LOCK - -/* Wait for spin lock */ -static int slwait(int *sl) { - while (InterlockedCompareExchange((void **)sl, (void *)1, (void *)0) != 0) { - Sleep(0); - } - return 0; -} - -/* Release spin lock */ -static int slrelease(int *sl) { - InterlockedExchange(sl, 0); - return 0; -} - -#ifdef NEEDED -/* Spin lock for emulation code */ -static int g_sl; -#endif - -#endif /* USE_MALLOC_LOCK */ - -/* getpagesize for windows */ -static long getpagesize(void) { - static long g_pagesize = 0; - if (!g_pagesize) { - SYSTEM_INFO system_info; - GetSystemInfo(&system_info); - g_pagesize = system_info.dwPageSize; - } - return g_pagesize; -} -static long getregionsize(void) { - static long g_regionsize = 0; - if (!g_regionsize) { - SYSTEM_INFO system_info; - GetSystemInfo(&system_info); - g_regionsize = system_info.dwAllocationGranularity; - } - return g_regionsize; -} - -/* A region list entry */ -typedef struct _region_list_entry { - void *top_allocated; - void *top_committed; - void *top_reserved; - long reserve_size; - struct _region_list_entry *previous; -} region_list_entry; - -/* Allocate and link a region entry in the region list */ -static int region_list_append(region_list_entry **last, void *base_reserved, long reserve_size) { - region_list_entry *next = HeapAlloc(GetProcessHeap(), 0, sizeof(region_list_entry)); - if (!next) { - return FALSE; - } - next->top_allocated = (char *)base_reserved; - next->top_committed = (char *)base_reserved; - next->top_reserved = (char *)base_reserved + reserve_size; - next->reserve_size = reserve_size; - next->previous = *last; - *last = next; - return TRUE; -} -/* Free and unlink the last region entry from the region list */ -static int region_list_remove(region_list_entry **last) { - region_list_entry *previous = (*last)->previous; - if (!HeapFree(GetProcessHeap(), sizeof(region_list_entry), *last)) { - return FALSE; - } - *last = previous; - return TRUE; -} - -#define CEIL(size, to) (((size) + (to) - 1) & ~((to) - 1)) -#define FLOOR(size, to) ((size) & ~((to) - 1)) - -#define SBRK_SCALE 0 -/* #define SBRK_SCALE 1 */ -/* #define SBRK_SCALE 2 */ -/* #define SBRK_SCALE 4 */ - -/* sbrk for windows */ -static void *sbrk(long size) { - static long g_pagesize, g_my_pagesize; - static long g_regionsize, g_my_regionsize; - static region_list_entry *g_last; - void *result = (void *)MORECORE_FAILURE; -#ifdef TRACE - printf("sbrk %d\n", size); -#endif -#if defined(USE_MALLOC_LOCK) && defined(NEEDED) - /* Wait for spin lock */ - slwait(&g_sl); -#endif - /* First time initialization */ - if (!g_pagesize) { - g_pagesize = getpagesize(); - g_my_pagesize = g_pagesize << SBRK_SCALE; - } - if (!g_regionsize) { - g_regionsize = getregionsize(); - g_my_regionsize = g_regionsize << SBRK_SCALE; - } - if (!g_last) { - if (!region_list_append(&g_last, 0, 0)) { - goto sbrk_exit; - } - } - /* Assert invariants */ - assert(g_last); - assert((char *)g_last->top_reserved - g_last->reserve_size <= (char *)g_last->top_allocated && - g_last->top_allocated <= g_last->top_committed); - assert((char *)g_last->top_reserved - g_last->reserve_size <= (char *)g_last->top_committed && - g_last->top_committed <= g_last->top_reserved && - (unsigned)g_last->top_committed % g_pagesize == 0); - assert((unsigned)g_last->top_reserved % g_regionsize == 0); - assert((unsigned)g_last->reserve_size % g_regionsize == 0); - /* Allocation requested? */ - if (size >= 0) { - /* Allocation size is the requested size */ - long allocate_size = size; - /* Compute the size to commit */ - long to_commit = (char *)g_last->top_allocated + allocate_size - (char *)g_last->top_committed; - /* Do we reach the commit limit? */ - if (to_commit > 0) { - /* Round size to commit */ - long commit_size = CEIL(to_commit, g_my_pagesize); - /* Compute the size to reserve */ - long to_reserve = (char *)g_last->top_committed + commit_size - (char *)g_last->top_reserved; - /* Do we reach the reserve limit? */ - if (to_reserve > 0) { - /* Compute the remaining size to commit in the current region */ - long remaining_commit_size = (char *)g_last->top_reserved - (char *)g_last->top_committed; - if (remaining_commit_size > 0) { - /* Assert preconditions */ - assert((unsigned)g_last->top_committed % g_pagesize == 0); - assert(0 < remaining_commit_size && remaining_commit_size % g_pagesize == 0); - { - /* Commit this */ - void *base_committed = VirtualAlloc(g_last->top_committed, remaining_commit_size, - MEM_COMMIT, PAGE_READWRITE); - /* Check returned pointer for consistency */ - if (base_committed != g_last->top_committed) { - goto sbrk_exit; - } - /* Assert postconditions */ - assert((unsigned)base_committed % g_pagesize == 0); -#ifdef TRACE - printf("Commit %p %d\n", base_committed, remaining_commit_size); -#endif - /* Adjust the regions commit top */ - g_last->top_committed = (char *)base_committed + remaining_commit_size; - } - } - { - /* Now we are going to search and reserve. */ - int contiguous = -1; - int found = FALSE; - MEMORY_BASIC_INFORMATION memory_info; - void *base_reserved; - long reserve_size; - do { - /* Assume contiguous memory */ - contiguous = TRUE; - /* Round size to reserve */ - reserve_size = CEIL(to_reserve, g_my_regionsize); - /* Start with the current region's top */ - memory_info.BaseAddress = g_last->top_reserved; - /* Assert preconditions */ - assert((unsigned)memory_info.BaseAddress % g_pagesize == 0); - assert(0 < reserve_size && reserve_size % g_regionsize == 0); - while (VirtualQuery(memory_info.BaseAddress, &memory_info, sizeof(memory_info))) { - /* Assert postconditions */ - assert((unsigned)memory_info.BaseAddress % g_pagesize == 0); -#ifdef TRACE - printf("Query %p %d %s\n", memory_info.BaseAddress, memory_info.RegionSize, - memory_info.State == MEM_FREE ? "FREE" : (memory_info.State == MEM_RESERVE ? "RESERVED" : (memory_info.State == MEM_COMMIT ? "COMMITTED" : "?"))); -#endif - /* Region is free, well aligned and big enough: we are done */ - if (memory_info.State == MEM_FREE && - (unsigned)memory_info.BaseAddress % g_regionsize == 0 && - memory_info.RegionSize >= (unsigned)reserve_size) { - found = TRUE; - break; - } - /* From now on we can't get contiguous memory! */ - contiguous = FALSE; - /* Recompute size to reserve */ - reserve_size = CEIL(allocate_size, g_my_regionsize); - memory_info.BaseAddress = (char *)memory_info.BaseAddress + memory_info.RegionSize; - /* Assert preconditions */ - assert((unsigned)memory_info.BaseAddress % g_pagesize == 0); - assert(0 < reserve_size && reserve_size % g_regionsize == 0); - } - /* Search failed? */ - if (!found) { - goto sbrk_exit; - } - /* Assert preconditions */ - assert((unsigned)memory_info.BaseAddress % g_regionsize == 0); - assert(0 < reserve_size && reserve_size % g_regionsize == 0); - /* Try to reserve this */ - base_reserved = VirtualAlloc(memory_info.BaseAddress, reserve_size, - MEM_RESERVE, PAGE_NOACCESS); - if (!base_reserved) { - int rc = GetLastError(); - if (rc != ERROR_INVALID_ADDRESS) { - goto sbrk_exit; - } - } - /* A null pointer signals (hopefully) a race condition with another thread. */ - /* In this case, we try again. */ - } while (!base_reserved); - /* Check returned pointer for consistency */ - if (memory_info.BaseAddress && base_reserved != memory_info.BaseAddress) { - goto sbrk_exit; - } - /* Assert postconditions */ - assert((unsigned)base_reserved % g_regionsize == 0); -#ifdef TRACE - printf("Reserve %p %d\n", base_reserved, reserve_size); -#endif - /* Did we get contiguous memory? */ - if (contiguous) { - long start_size = (char *)g_last->top_committed - (char *)g_last->top_allocated; - /* Adjust allocation size */ - allocate_size -= start_size; - /* Adjust the regions allocation top */ - g_last->top_allocated = g_last->top_committed; - /* Recompute the size to commit */ - to_commit = (char *)g_last->top_allocated + allocate_size - (char *)g_last->top_committed; - /* Round size to commit */ - commit_size = CEIL(to_commit, g_my_pagesize); - } - /* Append the new region to the list */ - if (!region_list_append(&g_last, base_reserved, reserve_size)) { - goto sbrk_exit; - } - /* Didn't we get contiguous memory? */ - if (!contiguous) { - /* Recompute the size to commit */ - to_commit = (char *)g_last->top_allocated + allocate_size - (char *)g_last->top_committed; - /* Round size to commit */ - commit_size = CEIL(to_commit, g_my_pagesize); - } - } - } - /* Assert preconditions */ - assert((unsigned)g_last->top_committed % g_pagesize == 0); - assert(0 < commit_size && commit_size % g_pagesize == 0); - { - /* Commit this */ - void *base_committed = VirtualAlloc(g_last->top_committed, commit_size, - MEM_COMMIT, PAGE_READWRITE); - /* Check returned pointer for consistency */ - if (base_committed != g_last->top_committed) { - goto sbrk_exit; - } - /* Assert postconditions */ - assert((unsigned)base_committed % g_pagesize == 0); -#ifdef TRACE - printf("Commit %p %d\n", base_committed, commit_size); -#endif - /* Adjust the regions commit top */ - g_last->top_committed = (char *)base_committed + commit_size; - } - } - /* Adjust the regions allocation top */ - g_last->top_allocated = (char *)g_last->top_allocated + allocate_size; - result = (char *)g_last->top_allocated - size; - /* Deallocation requested? */ - } else if (size < 0) { - long deallocate_size = -size; - /* As long as we have a region to release */ - while ((char *)g_last->top_allocated - deallocate_size < (char *)g_last->top_reserved - g_last->reserve_size) { - /* Get the size to release */ - long release_size = g_last->reserve_size; - /* Get the base address */ - void *base_reserved = (char *)g_last->top_reserved - release_size; - /* Assert preconditions */ - assert((unsigned)base_reserved % g_regionsize == 0); - assert(0 < release_size && release_size % g_regionsize == 0); - { - /* Release this */ - int rc = VirtualFree(base_reserved, 0, - MEM_RELEASE); - /* Check returned code for consistency */ - if (!rc) { - goto sbrk_exit; - } -#ifdef TRACE - printf("Release %p %d\n", base_reserved, release_size); -#endif - } - /* Adjust deallocation size */ - deallocate_size -= (char *)g_last->top_allocated - (char *)base_reserved; - /* Remove the old region from the list */ - if (!region_list_remove(&g_last)) { - goto sbrk_exit; - } - } - { - /* Compute the size to decommit */ - long to_decommit = (char *)g_last->top_committed - ((char *)g_last->top_allocated - deallocate_size); - if (to_decommit >= g_my_pagesize) { - /* Compute the size to decommit */ - long decommit_size = FLOOR(to_decommit, g_my_pagesize); - /* Compute the base address */ - void *base_committed = (char *)g_last->top_committed - decommit_size; - /* Assert preconditions */ - assert((unsigned)base_committed % g_pagesize == 0); - assert(0 < decommit_size && decommit_size % g_pagesize == 0); - { - /* Decommit this */ - int rc = VirtualFree((char *)base_committed, decommit_size, - MEM_DECOMMIT); - /* Check returned code for consistency */ - if (!rc) { - goto sbrk_exit; - } -#ifdef TRACE - printf("Decommit %p %d\n", base_committed, decommit_size); -#endif - } - /* Adjust deallocation size and regions commit and allocate top */ - deallocate_size -= (char *)g_last->top_allocated - (char *)base_committed; - g_last->top_committed = base_committed; - g_last->top_allocated = base_committed; - } - } - /* Adjust regions allocate top */ - g_last->top_allocated = (char *)g_last->top_allocated - deallocate_size; - /* Check for underflow */ - if ((char *)g_last->top_reserved - g_last->reserve_size > (char *)g_last->top_allocated || - g_last->top_allocated > g_last->top_committed) { - /* Adjust regions allocate top */ - g_last->top_allocated = (char *)g_last->top_reserved - g_last->reserve_size; - goto sbrk_exit; - } - result = g_last->top_allocated; - } - /* Assert invariants */ - assert(g_last); - assert((char *)g_last->top_reserved - g_last->reserve_size <= (char *)g_last->top_allocated && - g_last->top_allocated <= g_last->top_committed); - assert((char *)g_last->top_reserved - g_last->reserve_size <= (char *)g_last->top_committed && - g_last->top_committed <= g_last->top_reserved && - (unsigned)g_last->top_committed % g_pagesize == 0); - assert((unsigned)g_last->top_reserved % g_regionsize == 0); - assert((unsigned)g_last->reserve_size % g_regionsize == 0); - -sbrk_exit: -#if defined(USE_MALLOC_LOCK) && defined(NEEDED) - /* Release spin lock */ - slrelease(&g_sl); -#endif - return result; -} - -/* mmap for windows */ -static void *mmap(void *ptr, long size, long prot, long type, long handle, long arg) { - static long g_pagesize; - static long g_regionsize; -#ifdef TRACE - printf("mmap %d\n", size); -#endif -#if defined(USE_MALLOC_LOCK) && defined(NEEDED) - /* Wait for spin lock */ - slwait(&g_sl); -#endif - /* First time initialization */ - if (!g_pagesize) { - g_pagesize = getpagesize(); - } - if (!g_regionsize) { - g_regionsize = getregionsize(); - } - /* Assert preconditions */ - assert((unsigned)ptr % g_regionsize == 0); - assert(size % g_pagesize == 0); - /* Allocate this */ - ptr = VirtualAlloc(ptr, size, - MEM_RESERVE | MEM_COMMIT | MEM_TOP_DOWN, PAGE_READWRITE); - if (!ptr) { - ptr = (void *)MORECORE_FAILURE; - goto mmap_exit; - } - /* Assert postconditions */ - assert((unsigned)ptr % g_regionsize == 0); -#ifdef TRACE - printf("Commit %p %d\n", ptr, size); -#endif -mmap_exit: -#if defined(USE_MALLOC_LOCK) && defined(NEEDED) - /* Release spin lock */ - slrelease(&g_sl); -#endif - return ptr; -} - -/* munmap for windows */ -static long munmap(void *ptr, long size) { - static long g_pagesize; - static long g_regionsize; - int rc = MUNMAP_FAILURE; -#ifdef TRACE - printf("munmap %p %d\n", ptr, size); -#endif -#if defined(USE_MALLOC_LOCK) && defined(NEEDED) - /* Wait for spin lock */ - slwait(&g_sl); -#endif - /* First time initialization */ - if (!g_pagesize) { - g_pagesize = getpagesize(); - } - if (!g_regionsize) { - g_regionsize = getregionsize(); - } - /* Assert preconditions */ - assert((unsigned)ptr % g_regionsize == 0); - assert(size % g_pagesize == 0); - /* Free this */ - if (!VirtualFree(ptr, 0, - MEM_RELEASE)) { - goto munmap_exit; - } - rc = 0; -#ifdef TRACE - printf("Release %p %d\n", ptr, size); -#endif -munmap_exit: -#if defined(USE_MALLOC_LOCK) && defined(NEEDED) - /* Release spin lock */ - slrelease(&g_sl); -#endif - return rc; -} - -static void vminfo(CHUNK_SIZE_T *free, CHUNK_SIZE_T *reserved, CHUNK_SIZE_T *committed) { - MEMORY_BASIC_INFORMATION memory_info; - memory_info.BaseAddress = 0; - *free = *reserved = *committed = 0; - while (VirtualQuery(memory_info.BaseAddress, &memory_info, sizeof(memory_info))) { - switch (memory_info.State) { - case MEM_FREE: - *free += memory_info.RegionSize; - break; - case MEM_RESERVE: - *reserved += memory_info.RegionSize; - break; - case MEM_COMMIT: - *committed += memory_info.RegionSize; - break; - } - memory_info.BaseAddress = (char *)memory_info.BaseAddress + memory_info.RegionSize; - } -} - -static int cpuinfo(int whole, CHUNK_SIZE_T *kernel, CHUNK_SIZE_T *user) { - if (whole) { - __int64 creation64, exit64, kernel64, user64; - int rc = GetProcessTimes(GetCurrentProcess(), - (FILETIME *)&creation64, - (FILETIME *)&exit64, - (FILETIME *)&kernel64, - (FILETIME *)&user64); - if (!rc) { - *kernel = 0; - *user = 0; - return FALSE; - } - *kernel = (CHUNK_SIZE_T)(kernel64 / 10000); - *user = (CHUNK_SIZE_T)(user64 / 10000); - return TRUE; - } else { - __int64 creation64, exit64, kernel64, user64; - int rc = GetThreadTimes(GetCurrentThread(), - (FILETIME *)&creation64, - (FILETIME *)&exit64, - (FILETIME *)&kernel64, - (FILETIME *)&user64); - if (!rc) { - *kernel = 0; - *user = 0; - return FALSE; - } - *kernel = (CHUNK_SIZE_T)(kernel64 / 10000); - *user = (CHUNK_SIZE_T)(user64 / 10000); - return TRUE; - } -} - -#endif /* WIN32 */ - -/* ------------------------------------------------------------ -History: - V2.7.2 Sat Aug 17 09:07:30 2002 Doug Lea (dl at gee) - * Fix malloc_state bitmap array misdeclaration - - V2.7.1 Thu Jul 25 10:58:03 2002 Doug Lea (dl at gee) - * Allow tuning of FIRST_SORTED_BIN_SIZE - * Use PTR_UINT as type for all ptr->int casts. Thanks to John Belmonte. - * Better detection and support for non-contiguousness of MORECORE. - Thanks to Andreas Mueller, Conal Walsh, and Wolfram Gloger - * Bypass most of malloc if no frees. Thanks To Emery Berger. - * Fix freeing of old top non-contiguous chunk im sysmalloc. - * Raised default trim and map thresholds to 256K. - * Fix mmap-related #defines. Thanks to Lubos Lunak. - * Fix copy macros; added LACKS_FCNTL_H. Thanks to Neal Walfield. - * Branch-free bin calculation - * Default trim and mmap thresholds now 256K. - - V2.7.0 Sun Mar 11 14:14:06 2001 Doug Lea (dl at gee) - * Introduce independent_comalloc and independent_calloc. - Thanks to Michael Pachos for motivation and help. - * Make optional .h file available - * Allow > 2GB requests on 32bit systems. - * new WIN32 sbrk, mmap, munmap, lock code from . - Thanks also to Andreas Mueller , - and Anonymous. - * Allow override of MALLOC_ALIGNMENT (Thanks to Ruud Waij for - helping test this.) - * memalign: check alignment arg - * realloc: don't try to shift chunks backwards, since this - leads to more fragmentation in some programs and doesn't - seem to help in any others. - * Collect all cases in malloc requiring system memory into sYSMALLOc - * Use mmap as backup to sbrk - * Place all internal state in malloc_state - * Introduce fastbins (although similar to 2.5.1) - * Many minor tunings and cosmetic improvements - * Introduce USE_PUBLIC_MALLOC_WRAPPERS, USE_MALLOC_LOCK - * Introduce MALLOC_FAILURE_ACTION, MORECORE_CONTIGUOUS - Thanks to Tony E. Bennett and others. - * Include errno.h to support default failure action. - - V2.6.6 Sun Dec 5 07:42:19 1999 Doug Lea (dl at gee) - * return null for negative arguments - * Added Several WIN32 cleanups from Martin C. Fong - * Add 'LACKS_SYS_PARAM_H' for those systems without 'sys/param.h' - (e.g. WIN32 platforms) - * Cleanup header file inclusion for WIN32 platforms - * Cleanup code to avoid Microsoft Visual C++ compiler complaints - * Add 'USE_DL_PREFIX' to quickly allow co-existence with existing - memory allocation routines - * Set 'malloc_getpagesize' for WIN32 platforms (needs more work) - * Use 'assert' rather than 'ASSERT' in WIN32 code to conform to - usage of 'assert' in non-WIN32 code - * Improve WIN32 'sbrk()' emulation's 'findRegion()' routine to - avoid infinite loop - * Always call 'fREe()' rather than 'free()' - - V2.6.5 Wed Jun 17 15:57:31 1998 Doug Lea (dl at gee) - * Fixed ordering problem with boundary-stamping - - V2.6.3 Sun May 19 08:17:58 1996 Doug Lea (dl at gee) - * Added pvalloc, as recommended by H.J. Liu - * Added 64bit pointer support mainly from Wolfram Gloger - * Added anonymously donated WIN32 sbrk emulation - * Malloc, calloc, getpagesize: add optimizations from Raymond Nijssen - * malloc_extend_top: fix mask error that caused wastage after - foreign sbrks - * Add linux mremap support code from HJ Liu - - V2.6.2 Tue Dec 5 06:52:55 1995 Doug Lea (dl at gee) - * Integrated most documentation with the code. - * Add support for mmap, with help from - Wolfram Gloger (Gloger@lrz.uni-muenchen.de). - * Use last_remainder in more cases. - * Pack bins using idea from colin@nyx10.cs.du.edu - * Use ordered bins instead of best-fit threshhold - * Eliminate block-local decls to simplify tracing and debugging. - * Support another case of realloc via move into top - * Fix error occuring when initial sbrk_base not word-aligned. - * Rely on page size for units instead of SBRK_UNIT to - avoid surprises about sbrk alignment conventions. - * Add mallinfo, mallopt. Thanks to Raymond Nijssen - (raymond@es.ele.tue.nl) for the suggestion. - * Add `pad' argument to malloc_trim and top_pad mallopt parameter. - * More precautions for cases where other routines call sbrk, - courtesy of Wolfram Gloger (Gloger@lrz.uni-muenchen.de). - * Added macros etc., allowing use in linux libc from - H.J. Lu (hjl@gnu.ai.mit.edu) - * Inverted this history list - - V2.6.1 Sat Dec 2 14:10:57 1995 Doug Lea (dl at gee) - * Re-tuned and fixed to behave more nicely with V2.6.0 changes. - * Removed all preallocation code since under current scheme - the work required to undo bad preallocations exceeds - the work saved in good cases for most test programs. - * No longer use return list or unconsolidated bins since - no scheme using them consistently outperforms those that don't - given above changes. - * Use best fit for very large chunks to prevent some worst-cases. - * Added some support for debugging - - V2.6.0 Sat Nov 4 07:05:23 1995 Doug Lea (dl at gee) - * Removed footers when chunks are in use. Thanks to - Paul Wilson (wilson@cs.texas.edu) for the suggestion. - - V2.5.4 Wed Nov 1 07:54:51 1995 Doug Lea (dl at gee) - * Added malloc_trim, with help from Wolfram Gloger - (wmglo@Dent.MED.Uni-Muenchen.DE). - - V2.5.3 Tue Apr 26 10:16:01 1994 Doug Lea (dl at g) - - V2.5.2 Tue Apr 5 16:20:40 1994 Doug Lea (dl at g) - * realloc: try to expand in both directions - * malloc: swap order of clean-bin strategy; - * realloc: only conditionally expand backwards - * Try not to scavenge used bins - * Use bin counts as a guide to preallocation - * Occasionally bin return list chunks in first scan - * Add a few optimizations from colin@nyx10.cs.du.edu - - V2.5.1 Sat Aug 14 15:40:43 1993 Doug Lea (dl at g) - * faster bin computation & slightly different binning - * merged all consolidations to one part of malloc proper - (eliminating old malloc_find_space & malloc_clean_bin) - * Scan 2 returns chunks (not just 1) - * Propagate failure in realloc if malloc returns 0 - * Add stuff to allow compilation on non-ANSI compilers - from kpv@research.att.com - - V2.5 Sat Aug 7 07:41:59 1993 Doug Lea (dl at g.oswego.edu) - * removed potential for odd address access in prev_chunk - * removed dependency on getpagesize.h - * misc cosmetics and a bit more internal documentation - * anticosmetics: mangled names in macros to evade debugger strangeness - * tested on sparc, hp-700, dec-mips, rs6000 - with gcc & native cc (hp, dec only) allowing - Detlefs & Zorn comparison study (in SIGPLAN Notices.) - - Trial version Fri Aug 28 13:14:29 1992 Doug Lea (dl at g.oswego.edu) - * Based loosely on libg++-1.2X malloc. (It retains some of the overall - structure of old version, but most details differ.) - -*/ - -#ifdef __cplusplus -}; /* end of extern "C" */ -#endif - -#endif /* MALLOC_270_H */ diff --git a/pufferlib/ocean/impulse_wars/pyproject.toml b/pufferlib/ocean/impulse_wars/pyproject.toml deleted file mode 100644 index df67b2bd17..0000000000 --- a/pufferlib/ocean/impulse_wars/pyproject.toml +++ /dev/null @@ -1,25 +0,0 @@ -[build-system] -requires = ["scikit-build-core>=0.10", "autopxd2>=2.5.0", "cython>=3.0.11"] -build-backend = "scikit_build_core.build" - -[project] -name = "binding" -version = "1.0.0" -requires-python = ">=3.11" - -[tool.scikit-build] -minimum-version = "build-system.requires" -cmake.build-type = "Release" -build.verbose = true -logging.level = "INFO" - -[tool.scikit-build.cmake.define] -BUILD_PYTHON_MODULE = true -CMAKE_C_COMPILER = "clang-20" - -[tool.ruff] -line-length = 110 - -[tool.ruff.lint] -# skip "Module level import not at top of file" -ignore = ["E402"] diff --git a/pufferlib/ocean/matsci/matsci.py b/pufferlib/ocean/matsci/matsci.py deleted file mode 100644 index eda5df1a41..0000000000 --- a/pufferlib/ocean/matsci/matsci.py +++ /dev/null @@ -1,66 +0,0 @@ -'''A minimal matsci for your own envs.''' - -import gymnasium -import numpy as np - -import pufferlib -from pufferlib.ocean.matsci import binding - -class Matsci(pufferlib.PufferEnv): - def __init__(self, num_envs=1, num_atoms=2, render_mode=None, log_interval=128, buf=None, seed=0): - self.single_observation_space = gymnasium.spaces.Box(low=0, high=1, - shape=(3,), dtype=np.float32) - self.single_action_space = gymnasium.spaces.Box( - low=-1, high=1, shape=(3,), dtype=np.float32 - ) - self.render_mode = render_mode - self.num_agents = num_envs*num_atoms - - super().__init__(buf) - c_envs = [] - for i in range(num_envs): - c_envs.append(binding.env_init( - self.observations[i*num_atoms:(i+1)*num_atoms], - self.actions[i*num_atoms:(i+1)*num_atoms], - self.rewards[i*num_atoms:(i+1)*num_atoms], - self.terminals[i*num_atoms:(i+1)*num_atoms], - self.truncations[i*num_atoms:(i+1)*num_atoms], - i, - num_agents=num_atoms, - )) - - self.c_envs = binding.vectorize(*c_envs) - - def reset(self, seed=0): - binding.vec_reset(self.c_envs, seed) - return self.observations, [] - - def step(self, actions): - self.actions[:] = actions - binding.vec_step(self.c_envs) - info = [binding.vec_log(self.c_envs)] - return (self.observations, self.rewards, - self.terminals, self.truncations, info) - - def render(self): - binding.vec_render(self.c_envs, 0) - - def close(self): - binding.vec_close(self.c_envs) - -if __name__ == '__main__': - N = 4096 - env = Matsci(num_envs=N) - env.reset() - steps = 0 - - CACHE = 1024 - actions = np.random.randint(0, 5, (CACHE, N)) - - import time - start = time.time() - while time.time() - start < 10: - env.step(actions[steps % CACHE]) - steps += 1 - - print('Squared SPS:', int(env.num_agents*steps / (time.time() - start))) diff --git a/pufferlib/ocean/memory/memory.py b/pufferlib/ocean/memory/memory.py deleted file mode 100644 index ca7786786d..0000000000 --- a/pufferlib/ocean/memory/memory.py +++ /dev/null @@ -1,53 +0,0 @@ -'''A minimal test env for memory (note: requires credit assignment too because RL)''' - -import gymnasium -import numpy as np - -import pufferlib -from pufferlib.ocean.memory import binding - -class Memory(pufferlib.PufferEnv): - def __init__(self, num_envs=1, render_mode=None, log_interval=128, length=4, buf=None, seed=0): - self.single_observation_space = gymnasium.spaces.Box(low=0, high=1, - shape=(1,), dtype=np.float32) - self.single_action_space = gymnasium.spaces.Discrete(2) - self.render_mode = render_mode - self.num_agents = num_envs - - super().__init__(buf) - self.c_envs = binding.vec_init(self.observations, self.actions, self.rewards, - self.terminals, self.truncations, num_envs, seed, length=length) - - def reset(self, seed=0): - binding.vec_reset(self.c_envs, seed) - return self.observations, [] - - def step(self, actions): - self.actions[:] = actions - binding.vec_step(self.c_envs) - info = [binding.vec_log(self.c_envs)] - return (self.observations, self.rewards, - self.terminals, self.truncations, info) - - def render(self): - binding.vec_render(self.c_envs, 0) - - def close(self): - binding.vec_close(self.c_envs) - -if __name__ == '__main__': - N = 4096 - env = Memory(num_envs=N) - env.reset() - steps = 0 - - CACHE = 1024 - actions = np.random.randint(0, 5, (CACHE, N)) - - import time - start = time.time() - while time.time() - start < 10: - env.step(actions[steps % CACHE]) - steps += 1 - - print('Squared SPS:', int(env.num_agents*steps / (time.time() - start))) diff --git a/pufferlib/ocean/moba/__init__.py b/pufferlib/ocean/moba/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/pufferlib/ocean/moba/binding.c b/pufferlib/ocean/moba/binding.c deleted file mode 100644 index c48c5fc9e9..0000000000 --- a/pufferlib/ocean/moba/binding.c +++ /dev/null @@ -1,150 +0,0 @@ -#include "moba.h" - -#define Env MOBA -#define MY_SHARED -#include "../env_binding.h" - -static PyObject* my_shared(PyObject* self, PyObject* args, PyObject* kwargs) { - unsigned char* game_map_npy = read_file("resources/moba/game_map.npy"); - int* ai_path_buffer = calloc(3*8*128*128, sizeof(int)); - unsigned char* ai_paths = calloc(128*128*128*128, sizeof(unsigned char)); - for (int i = 0; i < 128*128*128*128; i++) { - ai_paths[i] = 255; - } - - PyObject* ai_path_buffer_handle = PyLong_FromVoidPtr(ai_path_buffer); - PyObject* ai_paths_handle = PyLong_FromVoidPtr(ai_paths); - PyObject* game_map_handle = PyLong_FromVoidPtr(game_map_npy); - PyObject* state = PyDict_New(); - PyDict_SetItemString(state, "ai_path_buffer", ai_path_buffer_handle); - PyDict_SetItemString(state, "ai_paths", ai_paths_handle); - PyDict_SetItemString(state, "game_map", game_map_handle); - return PyLong_FromVoidPtr(state); -} - -static int my_init(Env* env, PyObject* args, PyObject* kwargs) { - env->vision_range = unpack(kwargs, "vision_range"); - env->agent_speed = unpack(kwargs, "agent_speed"); - env->discretize = unpack(kwargs, "discretize"); - env->reward_death = unpack(kwargs, "reward_death"); - env->reward_xp = unpack(kwargs, "reward_xp"); - env->reward_distance = unpack(kwargs, "reward_distance"); - env->reward_tower = unpack(kwargs, "reward_tower"); - env->script_opponents = unpack(kwargs, "script_opponents"); - - PyObject* handle_obj = PyDict_GetItemString(kwargs, "state"); - if (handle_obj == NULL) { - PyErr_SetString(PyExc_KeyError, "Key 'state' not found in kwargs"); - return 1; - } - - // Check if handle_obj is a PyLong - if (!PyLong_Check(handle_obj)) { - PyErr_SetString(PyExc_TypeError, "state handle must be an integer"); - return 1; - } - - // Convert PyLong to PyObject* (state dictionary) - PyObject* state_dict = (PyObject*)PyLong_AsVoidPtr(handle_obj); - if (state_dict == NULL) { - PyErr_SetString(PyExc_ValueError, "Invalid state dictionary pointer"); - return 1; - } - - // Verify it’s a dictionary - if (!PyDict_Check(state_dict)) { - PyErr_SetString(PyExc_TypeError, "State pointer does not point to a dictionary"); - return 1; - } - - // Basic validation: check reference count - if (state_dict->ob_refcnt <= 0) { - PyErr_SetString(PyExc_RuntimeError, "State dictionary has invalid reference count"); - return 1; - } - - // Extract ai_path_buffer - PyObject* ai_path_buffer_obj = PyDict_GetItemString(state_dict, "ai_path_buffer"); - if (ai_path_buffer_obj == NULL) { - PyErr_SetString(PyExc_KeyError, "Key 'ai_path_buffer' not found in state"); - return 1; - } - if (!PyLong_Check(ai_path_buffer_obj)) { - PyErr_SetString(PyExc_TypeError, "ai_path_buffer must be an integer"); - return 1; - } - env->ai_path_buffer = (int*)PyLong_AsVoidPtr(ai_path_buffer_obj); - if (env->ai_path_buffer == NULL) { - PyErr_SetString(PyExc_ValueError, "Invalid ai_path_buffer pointer"); - return 1; - } - - // Extract ai_paths - PyObject* ai_paths_obj = PyDict_GetItemString(state_dict, "ai_paths"); - if (ai_paths_obj == NULL) { - PyErr_SetString(PyExc_KeyError, "Key 'ai_paths' not found in state"); - return 1; - } - if (!PyLong_Check(ai_paths_obj)) { - PyErr_SetString(PyExc_TypeError, "ai_paths must be an integer"); - return 1; - } - env->ai_paths = (unsigned char*)PyLong_AsVoidPtr(ai_paths_obj); - if (env->ai_paths == NULL) { - PyErr_SetString(PyExc_ValueError, "Invalid ai_paths pointer"); - return 1; - } - - // Extract game_map - PyObject* game_map_obj = PyDict_GetItemString(state_dict, "game_map"); - if (game_map_obj == NULL) { - PyErr_SetString(PyExc_KeyError, "Key 'game_map' not found in state"); - return 1; - } - if (!PyLong_Check(game_map_obj)) { - PyErr_SetString(PyExc_TypeError, "game_map must be an integer"); - return 1; - } - unsigned char* game_map = (unsigned char*)PyLong_AsVoidPtr(game_map_obj); - if (game_map == NULL) { - PyErr_SetString(PyExc_ValueError, "Invalid game_map pointer"); - return 1; - } - - init_moba(env, game_map); - return 0; -} - -static int my_log(PyObject* dict, Log* log) { - assign_to_dict(dict, "perf", log->perf); - assign_to_dict(dict, "score", log->score); - assign_to_dict(dict, "episode_return", log->episode_return); - assign_to_dict(dict, "episode_length", log->episode_length); - assign_to_dict(dict, "radiant_victory", log->radiant_victory); - assign_to_dict(dict, "dire_victory", log->dire_victory); - assign_to_dict(dict, "radiant_level", log->radiant_level); - assign_to_dict(dict, "dire_level", log->dire_level); - assign_to_dict(dict, "radiant_towers_alive", log->radiant_towers_alive); - assign_to_dict(dict, "dire_towers_alive", log->dire_towers_alive); - - assign_to_dict(dict, "radiant_support_episode_return", log->radiant_support_episode_return); - assign_to_dict(dict, "radiant_support_reward_death", log->radiant_support_reward_death); - assign_to_dict(dict, "radiant_support_reward_xp", log->radiant_support_reward_xp); - assign_to_dict(dict, "radiant_support_reward_distance", log->radiant_support_reward_distance); - assign_to_dict(dict, "radiant_support_reward_tower", log->radiant_support_reward_tower); - assign_to_dict(dict, "radiant_support_level", log->radiant_support_level); - assign_to_dict(dict, "radiant_support_kills", log->radiant_support_kills); - assign_to_dict(dict, "radiant_support_deaths", log->radiant_support_deaths); - assign_to_dict(dict, "radiant_support_damage_dealt", log->radiant_support_damage_dealt); - assign_to_dict(dict, "radiant_support_damage_received", log->radiant_support_damage_received); - assign_to_dict(dict, "radiant_support_healing_dealt", log->radiant_support_healing_dealt); - assign_to_dict(dict, "radiant_support_healing_received", log->radiant_support_healing_received); - assign_to_dict(dict, "radiant_support_creeps_killed", log->radiant_support_creeps_killed); - assign_to_dict(dict, "radiant_support_neutrals_killed", log->radiant_support_neutrals_killed); - assign_to_dict(dict, "radiant_support_towers_killed", log->radiant_support_towers_killed); - assign_to_dict(dict, "radiant_support_usage_auto", log->radiant_support_usage_auto); - assign_to_dict(dict, "radiant_support_usage_q", log->radiant_support_usage_q); - assign_to_dict(dict, "radiant_support_usage_w", log->radiant_support_usage_w); - assign_to_dict(dict, "radiant_support_usage_e", log->radiant_support_usage_e); - return 0; -} diff --git a/pufferlib/ocean/moba/cy_moba.pyx b/pufferlib/ocean/moba/cy_moba.pyx deleted file mode 100644 index 51725d108e..0000000000 --- a/pufferlib/ocean/moba/cy_moba.pyx +++ /dev/null @@ -1,299 +0,0 @@ -from libc.stdlib cimport calloc, free -import numpy as np - -cdef extern from "moba.h": - int EMPTY - int WALL - int TOWER - int RADIANT_CREEP - int DIRE_CREEP - int NEUTRAL - int RADIANT_SUPPORT - int RADIANT_ASSASSIN - int RADIANT_BURST - int RADIANT_TANK - int RADIANT_CARRY - int DIRE_SUPPORT - int DIRE_ASSASSIN - int DIRE_BURST - int DIRE_TANK - int DIRE_CARRY - - int TOWER_VISION - int CREEP_VISION - int NEUTRAL_VISION - - int ENTITY_PLAYER - int ENTITY_CREEP - int ENTITY_NEUTRAL - int ENTITY_TOWER - - int XP_RANGE - int MAX_USES - - int LOG_BUFFER_SIZE - - ctypedef struct PlayerLog: - float episode_return - float reward_death - float reward_xp - float reward_distance - float reward_tower - float level - float kills - float deaths - float damage_dealt - float damage_received - float healing_dealt - float healing_received - float creeps_killed - float neutrals_killed - float towers_killed - float usage_auto - float usage_q - float usage_w - float usage_e - - ctypedef struct Log: - float perf - float score - float episode_return - float episode_length - float reward_death - float reward_xp - float reward_distance - float reward_tower - - float radiant_victory - float radiant_level - float radiant_towers_alive - - float dire_victory - float dire_level - float dire_towers_alive - - PlayerLog radiant_support - PlayerLog radiant_assassin - PlayerLog radiant_burst - PlayerLog radiant_tank - PlayerLog radiant_carry - - PlayerLog dire_support - PlayerLog dire_assassin - PlayerLog dire_burst - PlayerLog dire_tank - PlayerLog dire_carry - - ctypedef struct LogBuffer - LogBuffer* allocate_logbuffer(int) - void free_logbuffer(LogBuffer*) - Log aggregate_and_clear(LogBuffer*) - - ctypedef int (*skill)(MOBA*, Entity*, Entity*) noexcept - - ctypedef struct Map: - unsigned char* grid; - int* pids - int width - int height - - ctypedef struct CachedRNG: - float* rng - int rng_n - int rng_idx - - ctypedef struct Reward: - float death; - float xp; - float distance; - float tower; - - ctypedef struct Entity: - int pid; - int entity_type; - int hero_type; - int grid_id; - int team; - float health; - float max_health; - float mana; - float max_mana; - float y; - float x; - float spawn_y; - float spawn_x; - float damage; - int lane; - int waypoint; - float move_speed; - float move_modifier; - int stun_timer; - int move_timer; - int q_timer; - int w_timer; - int e_timer; - int basic_attack_timer; - int basic_attack_cd; - int is_hit; - int level; - int xp; - int xp_on_kill; - float reward; - int tier; - float base_health; - float base_mana; - float base_damage; - int hp_gain_per_level; - int mana_gain_per_level; - int damage_gain_per_level; - float last_x; - float last_y; - int target_pid; - int attack_aoe; - - ctypedef struct MOBA: - int vision_range; - float agent_speed; - unsigned char discretize; - unsigned char script_opponents; - int obs_size; - int creep_idx; - int tick; - - Map* map; - unsigned char* ai_paths; - int* ai_path_buffer; - unsigned char* observations; - int* actions; - float* rewards; - unsigned char* terminals; - unsigned char* truncations; - Entity* entities; - Reward* reward_components; - LogBuffer* log_buffer; - PlayerLog log[10]; - - float reward_death; - float reward_xp; - float reward_distance; - float reward_tower; - - int total_towers_taken; - int total_levels_gained; - int radiant_victories; - int dire_victories; - - # MAX_ENTITIES x MAX_SCANNED_TARGETS - Entity* scanned_targets[256][121]; - skill skills[10][3]; - - CachedRNG *rng; - - ctypedef struct GameRenderer - GameRenderer* init_game_renderer(int cell_size, int width, int height) - int render_game(GameRenderer* renderer, MOBA* env, int frame) - void close_game_renderer(GameRenderer* renderer) - - ctypedef struct Reward - void init_moba(MOBA* env, unsigned char* game_map_npy) - void free_moba(MOBA* env) - - unsigned char* read_file(char* filename) - - void c_reset(MOBA* env) - void c_step(MOBA* env) - void randomize_tower_hp(MOBA* env) - -cpdef entity_dtype(): - '''Make a dummy entity to get the dtype''' - cdef Entity entity - return np.asarray(&entity).dtype - -cpdef reward_dtype(): - '''Make a dummy reward to get the dtype''' - cdef Reward reward - return np.asarray(&reward).dtype - -cdef class CyMOBA: - cdef MOBA* envs - cdef GameRenderer* client - cdef int num_envs - cdef LogBuffer* logs - - cdef int* ai_path_buffer - cdef unsigned char* ai_paths - - def __init__(self, unsigned char[:, :] observations, int[:, :] actions, - float[:] rewards, unsigned char[:] terminals, int num_envs, int vision_range, - float agent_speed, bint discretize, float reward_death, float reward_xp, - float reward_distance, float reward_tower, bint script_opponents): - - self.num_envs = num_envs - self.client = NULL - self.envs = calloc(num_envs, sizeof(MOBA)) - self.logs = allocate_logbuffer(LOG_BUFFER_SIZE) - - import os - cwd = os.getcwd() - os.chdir(os.path.abspath(os.path.join(os.path.dirname(__file__), "..", ".."))) - cdef unsigned char* game_map_npy = read_file("resources/moba/game_map.npy"); - os.chdir(cwd) - - self.ai_path_buffer = calloc(3*8*128*128, sizeof(int)) - self.ai_paths = calloc(128*128*128*128, sizeof(unsigned char)) - cdef int i - for i in range(128*128*128*128): - self.ai_paths[i] = 255 - - cdef int inc = 5 if script_opponents else 10 - for i in range(num_envs): - self.envs[i] = MOBA( - observations=&observations[inc*i, 0], - actions=&actions[inc*i, 0], - rewards=&rewards[inc*i], - terminals=&terminals[inc*i], - ai_paths = self.ai_paths, - ai_path_buffer = self.ai_path_buffer, - log_buffer=self.logs, - vision_range=vision_range, - agent_speed=agent_speed, - discretize=discretize, - reward_death=reward_death, - reward_xp=reward_xp, - reward_distance=reward_distance, - reward_tower=reward_tower, - script_opponents=script_opponents, - ) - init_moba(&self.envs[i], game_map_npy) - - def reset(self): - cdef int i - for i in range(self.num_envs): - c_reset(&self.envs[i]) - - def step(self): - cdef int i - for i in range(self.num_envs): - c_step(&self.envs[i]) - - def render(self, int tick): - if self.client == NULL: - import os - cwd = os.getcwd() - os.chdir(os.path.abspath(os.path.join(os.path.dirname(__file__), "..", ".."))) - self.client = init_game_renderer(32, 41, 23) - os.chdir(cwd) - - render_game(self.client, &self.envs[0], tick) - - def close(self): - if self.client != NULL: - close_game_renderer(self.client) - self.client = NULL - - # TODO: free - #free_moba(self.envs) - - def log(self): - cdef Log log = aggregate_and_clear(self.logs) - return log diff --git a/pufferlib/ocean/moba/moba.c b/pufferlib/ocean/moba/moba.c deleted file mode 100644 index 29b50cca7e..0000000000 --- a/pufferlib/ocean/moba/moba.c +++ /dev/null @@ -1,215 +0,0 @@ -#include "moba.h" -#include "puffernet.h" - -typedef struct MOBANet MOBANet; -struct MOBANet { - int num_agents; - float* obs_2d; - float* obs_1d; - Conv2D* conv1; - ReLU* relu1; - Conv2D* conv2; - Linear* flat; - CatDim1* cat; - ReLU* relu2; - Linear* proj; - ReLU* relu3; - LSTM* lstm; - Linear* actor; - Linear* value_fn; - Multidiscrete* multidiscrete; -}; - -MOBANet* init_mobanet(Weights* weights, int num_agents) { - MOBANet* net = calloc(1, sizeof(MOBANet)); - int hidden = 128; - net->num_agents = num_agents; - net->obs_2d = calloc(num_agents*11*11*19, sizeof(float)); - net->obs_1d = calloc(num_agents*26, sizeof(float)); - net->conv1 = make_conv2d(weights, num_agents, 11, 11, 19, hidden, 5, 3); - net->relu1 = make_relu(num_agents, hidden*3*3); - net->conv2 = make_conv2d(weights, num_agents, 3, 3, hidden, hidden, 3, 1); - net->flat = make_linear(weights, num_agents, 26, hidden); - net->cat = make_cat_dim1(num_agents, hidden, hidden); - net->relu2 = make_relu(num_agents, 2*hidden); - net->proj = make_linear(weights, num_agents, 2*hidden, 128); - net->relu3 = make_relu(num_agents, 128); - net->actor = make_linear(weights, num_agents, 128, 23); - net->value_fn = make_linear(weights, num_agents, 128, 1); - net->lstm = make_lstm(weights, num_agents, 128, 128); - int logit_sizes[6] = {7, 7, 3, 2, 2, 2}; - net->multidiscrete = make_multidiscrete(num_agents, logit_sizes, 6); - return net; -} - -void free_mobanet(MOBANet* net) { - free(net->obs_2d); - free(net->obs_1d); - free(net->conv1); - free(net->relu1); - free(net->conv2); - free(net->flat); - free(net->cat); - free(net->relu2); - free(net->proj); - free(net->relu3); - free(net->actor); - free(net->value_fn); - free(net->lstm); - free(net->multidiscrete); - free(net); -} - -void forward(MOBANet* net, unsigned char* observations, int* actions) { - memset(net->obs_2d, 0, net->num_agents*11*11*19*sizeof(float)); - float (*obs_2d)[19][11][11] = (float (*)[19][11][11])net->obs_2d; - float (*obs_1d)[26] = (float (*)[26])net->obs_1d; - for (int b = 0; b < net->num_agents; b++) { - int b_offset = b*(11*11*4 + 26); - for (int i = 0; i < 11; i++) { - for (int j = 0; j < 11; j++) { - int elem_offset = 4*(i*11 + j); - int one_hot_idx = observations[b_offset + elem_offset]; - obs_2d[b][one_hot_idx][i][j] = 1; - obs_2d[b][16][i][j] = observations[b_offset + elem_offset+1] / 255.0f; - obs_2d[b][17][i][j] = observations[b_offset + elem_offset+2] / 255.0f; - obs_2d[b][18][i][j] = observations[b_offset + elem_offset+3] / 255.0f; - } - } - for (int i = 0; i < 26; i++) { - obs_1d[b][i] = observations[b_offset + 11*11*4 + i] / 255.0f; - } - } - - conv2d(net->conv1, net->obs_2d); - relu(net->relu1, net->conv1->output); - conv2d(net->conv2, net->relu1->output); - - linear(net->flat, net->obs_1d); - - cat_dim1(net->cat, net->conv2->output, net->flat->output); - relu(net->relu2, net->cat->output); - linear(net->proj, net->relu2->output); - relu(net->relu3, net->proj->output); - - lstm(net->lstm, net->relu3->output); - - linear(net->actor, net->lstm->state_h); - linear(net->value_fn, net->lstm->state_h); - - softmax_multidiscrete(net->multidiscrete, net->actor->output, actions); - for (int i = 0; i < net->num_agents; i++) { - actions[i*6] = 100*(actions[i*6] - 3); - actions[i*6 + 1] = 100*(actions[i*6 + 1] - 3); - } -} - -void demo() { - Weights* weights = load_weights("resources/moba/moba_weights.bin", 380056); - bool script_opponents = true; - - int num_agents = script_opponents ? 5 : 10; - MOBANet* net = init_mobanet(weights, num_agents); - - MOBA env = { - .vision_range = 5, - .agent_speed = 1.0, - .discretize = true, - .reward_death = -1.0, - .reward_xp = 0.006, - .reward_distance = 0.05, - .reward_tower = 3.0, - .script_opponents = script_opponents, - }; - allocate_moba(&env); - c_reset(&env); - c_render(&env); - int frame = 1; - while (!WindowShouldClose()) { - if (frame % 12 == 0) { - c_step(&env); - forward(net, env.observations, env.actions); - } - c_render(&env); - frame = (frame + 1) % 12; - } - free_mobanet(net); - free(weights); - free_allocated_moba(&env); - //close_game_renderer(renderer); -} - -void test_performance(float test_time) { - bool script_opponents = true; - int num_agents = script_opponents ? 5 : 10; - - MOBA env = { - .vision_range = 5, - .agent_speed = 1.0, - .discretize = true, - .reward_death = -1.0, - .reward_xp = 0.006, - .reward_distance = 0.05, - .reward_tower = 3.0, - .script_opponents = script_opponents, - }; - allocate_moba(&env); - - c_reset(&env); - int start = time(NULL); - int i = 0; - while (time(NULL) - start < test_time) { - for (int j = 0; j < num_agents; j++) { - env.actions[6*j] = rand()%600 - 300; - env.actions[6*j + 1] = rand()%600 - 300; - env.actions[6*j + 2] = rand()%3; - env.actions[6*j + 3] = rand()%2; - env.actions[6*j + 4] = rand()%2; - env.actions[6*j + 5] = rand()%2; - } - c_step(&env); - i++; - } - int end = time(NULL); - printf("SPS: %f\n", (float)num_agents*i / (end - start)); -} - -void test_bugs(float test_time) { - Weights* weights = load_weights("resources/moba/moba_weights.bin", 380056); - MOBANet* net = init_mobanet(weights, 10); - - MOBA env = { - .vision_range = 5, - .agent_speed = 1.0, - .discretize = true, - .reward_death = -1.0, - .reward_xp = 0.006, - .reward_distance = 0.05, - .reward_tower = 3.0, - .script_opponents = true, - }; - allocate_moba(&env); - - c_reset(&env); - int start = time(NULL); - int i = 0; - while (time(NULL) - start < test_time) { - c_step(&env); - forward(net, env.observations, env.actions); - i++; - } - int end = time(NULL); - printf("SPS: %f\n", 10.0f*i / (end - start)); - printf("Frames: %i\n", i); - free_mobanet(net); - free(weights); - free_allocated_moba(&env); -} - - -int main() { - //test_bugs(2.0f); - demo(); - //test_performance(30.0f); - return 0; -} diff --git a/pufferlib/ocean/moba/moba.py b/pufferlib/ocean/moba/moba.py deleted file mode 100644 index 4b4dd0be8b..0000000000 --- a/pufferlib/ocean/moba/moba.py +++ /dev/null @@ -1,113 +0,0 @@ -from pdb import set_trace as T -import numpy as np -import os - -import pettingzoo -import gymnasium - -import pufferlib -from pufferlib.ocean.moba import binding - -MAP_OBS_N = 11*11*4 -PLAYER_OBS_N = 26 - -class Moba(pufferlib.PufferEnv): - def __init__(self, num_envs=4, vision_range=5, agent_speed=1.0, - discretize=True, reward_death=-1.0, reward_xp=0.006, - reward_distance=0.05, reward_tower=3.0, report_interval=32, - script_opponents=True, render_mode='human', buf=None, seed=0): - - self.report_interval = report_interval - self.render_mode = render_mode - self.num_agents = 5*num_envs if script_opponents else 10*num_envs - - self.single_observation_space = gymnasium.spaces.Box(low=0, high=255, - shape=(MAP_OBS_N + PLAYER_OBS_N,), dtype=np.uint8) - self.single_action_space = gymnasium.spaces.MultiDiscrete([7, 7, 3, 2, 2, 2]) - - super().__init__(buf=buf) - - c_envs = [] - players = 5 if script_opponents else 10 - self.c_state = binding.shared() - for i in range(num_envs): - env_id = binding.env_init( - self.observations[i*players:(i+1)*players], - self.actions[i*players:(i+1)*players], - self.rewards[i*players:(i+1)*players], - self.terminals[i*players:(i+1)*players], - self.truncations[i*players:(i+1)*players], - i + seed*num_envs, - vision_range=vision_range, - agent_speed=agent_speed, - discretize=discretize, - reward_death=reward_death, - reward_xp=reward_xp, - reward_distance=reward_distance, - reward_tower=reward_tower, - script_opponents=script_opponents, - state=self.c_state, - ) - c_envs.append(env_id) - - self.c_envs = binding.vectorize(*c_envs) - - def reset(self, seed=0): - binding.vec_reset(self.c_envs, seed) - self.tick = 0 - return self.observations, [] - - def step(self, actions): - self.actions[:] = actions - self.actions[:, 0] = 100*(self.actions[:, 0] - 3) - self.actions[:, 1] = 100*(self.actions[:, 1] - 3) - binding.vec_step(self.c_envs) - - infos = [] - self.tick += 1 - if self.tick % self.report_interval == 0: - log = binding.vec_log(self.c_envs) - if log: - infos.append(log) - - return (self.observations, self.rewards, - self.terminals, self.truncations, infos) - - def render(self): - for frame in range(12): - binding.vec_render(self.c_envs, 0) - - def close(self): - binding.vec_close(self.c_envs) - - -def test_performance(timeout=20, atn_cache=1024, num_envs=400): - tick = 0 - - import time - start = time.time() - while time.time() - start < timeout: - atns = actions[tick % atn_cache] - env.step(atns) - tick += 1 - - print(f'SPS: %f', 10*num_envs*tick / (time.time() - start)) - -if __name__ == '__main__': - # Run with c profile - from cProfile import run - num_envs = 400 - env = Moba(num_envs=num_envs, report_interval=10000000) - env.reset() - actions = np.random.randint(0, env.single_action_space.nvec, (1024, 10*num_envs, 6)) - test_performance(20, 1024, num_envs) - exit(0) - - run('test_performance(20)', 'stats.profile') - import pstats - from pstats import SortKey - p = pstats.Stats('stats.profile') - p.sort_stats(SortKey.TIME).print_stats(25) - exit(0) - - #test_performance(10) diff --git a/pufferlib/ocean/nmmo3/binding.c b/pufferlib/ocean/nmmo3/binding.c deleted file mode 100644 index d5c97cf1ce..0000000000 --- a/pufferlib/ocean/nmmo3/binding.c +++ /dev/null @@ -1,50 +0,0 @@ -#include "nmmo3.h" - -#define Env MMO -#include "../env_binding.h" - -static int my_init(Env* env, PyObject* args, PyObject* kwargs) { - env->width = unpack(kwargs, "width"); - env->height = unpack(kwargs, "height"); - env->num_players = unpack(kwargs, "num_players"); - env->num_enemies = unpack(kwargs, "num_enemies"); - env->num_resources = unpack(kwargs, "num_resources"); - env->num_weapons = unpack(kwargs, "num_weapons"); - env->num_gems = unpack(kwargs, "num_gems"); - env->tiers = unpack(kwargs, "tiers"); - env->levels = unpack(kwargs, "levels"); - env->teleportitis_prob = unpack(kwargs, "teleportitis_prob"); - env->enemy_respawn_ticks = unpack(kwargs, "enemy_respawn_ticks"); - env->item_respawn_ticks = unpack(kwargs, "item_respawn_ticks"); - env->x_window = unpack(kwargs, "x_window"); - env->y_window = unpack(kwargs, "y_window"); - env->reward_combat_level = unpack(kwargs, "reward_combat_level"); - env->reward_prof_level = unpack(kwargs, "reward_prof_level"); - env->reward_item_level = unpack(kwargs, "reward_item_level"); - env->reward_market = unpack(kwargs, "reward_market"); - env->reward_death = unpack(kwargs, "reward_death"); - init(env); - return 0; -} - -static int my_log(PyObject* dict, Log* log) { - assign_to_dict(dict, "perf", log->perf); - assign_to_dict(dict, "score", log->score); - assign_to_dict(dict, "episode_return", log->episode_return); - assign_to_dict(dict, "episode_length", log->episode_length); - assign_to_dict(dict, "return_comb_lvl", log->return_comb_lvl); - assign_to_dict(dict, "return_prof_lvl", log->return_prof_lvl); - assign_to_dict(dict, "return_item_atk_lvl", log->return_item_atk_lvl); - assign_to_dict(dict, "return_item_def_lvl", log->return_item_def_lvl); - assign_to_dict(dict, "return_market_buy", log->return_market_buy); - assign_to_dict(dict, "return_market_sell", log->return_market_sell); - assign_to_dict(dict, "return_death", log->return_death); - assign_to_dict(dict, "min_comb_prof", log->min_comb_prof); - assign_to_dict(dict, "purchases", log->purchases); - assign_to_dict(dict, "sales", log->sales); - assign_to_dict(dict, "equip_attack", log->equip_attack); - assign_to_dict(dict, "equip_defense", log->equip_defense); - assign_to_dict(dict, "r", log->r); - assign_to_dict(dict, "c", log->c); - return 0; -} diff --git a/pufferlib/ocean/nmmo3/cy_nmmo3.pyx b/pufferlib/ocean/nmmo3/cy_nmmo3.pyx deleted file mode 100644 index 65d037097b..0000000000 --- a/pufferlib/ocean/nmmo3/cy_nmmo3.pyx +++ /dev/null @@ -1,270 +0,0 @@ -# distutils: define_macros=NPY_NO_DEPRECATED_API=NPY_1_7_API_VERSION -# cython: language_level=3 -# cython: boundscheck=True -# cython: initializedcheck=True -# cython: wraparound=True -# cython: cdivision=False -# cython: nonecheck=True -# cython: profile=True - -from libc.stdlib cimport calloc, free -cimport numpy as cnp -import numpy as np - -cdef extern from "nmmo3.h": - int LOG_BUFFER_SIZE - - ctypedef struct Log: - float episode_return; - float episode_length; - float return_comb_lvl; - float return_prof_lvl; - float return_item_atk_lvl; - float return_item_def_lvl; - float return_market_buy; - float return_market_sell; - float return_death; - float min_comb_prof; - float purchases; - float sales; - float equip_attack; - float equip_defense; - float r; - float c; - - ctypedef struct LogBuffer - LogBuffer* allocate_logbuffer(int) - void free_logbuffer(LogBuffer*) - Log aggregate_and_clear(LogBuffer*) - - int ATN_NOOP - - ctypedef struct Entity: - int type - int comb_lvl - int element - int dir - int anim - int hp - int hp_max - int prof_lvl - int ui_mode - int market_tier - int sell_idx - int gold - int in_combat - int equipment[5] - int inventory[12] - int is_equipped[12] - int wander_range - int ranged - int goal - int equipment_attack - int equipment_defense - int r - int c - int spawn_r - int spawn_c - int min_comb_prof[500] - int min_comb_prof_idx - int time_alive; - int purchases; - int sales; - - ctypedef struct Reward: - float total - float death; - float pioneer; - float comb_lvl; - float prof_lvl; - float item_atk_lvl; - float item_def_lvl; - float item_tool_lvl; - float market_buy; - float market_sell; - - ctypedef struct ItemMarket: - int offer_idx - int max_offers - - ctypedef struct RespawnBuffer: - int* buffer - int ticks - int size - - ctypedef struct MMO: - int width - int height - int num_players - int num_enemies - int num_resources - int num_weapons - int num_gems - char* terrain - unsigned char* rendered - Entity* players - Entity* enemies - short* pids - unsigned char* items - Reward* rewards - unsigned char* counts - unsigned char* obs - int* actions - int tick - int tiers - int levels - float teleportitis_prob - int x_window - int y_window - int obs_size - int enemy_respawn_ticks - int item_respawn_ticks - ItemMarket* market - int market_buys - int market_sells - RespawnBuffer* resource_respawn_buffer - RespawnBuffer* enemy_respawn_buffer - Log* logs - LogBuffer* log_buffer - float reward_combat_level - float reward_prof_level - float reward_item_level - float reward_market - float reward_death - - ctypedef struct Client - Client* make_client(MMO* env) - #void close_client(Client* client) - int tick(Client* client, MMO* env, float delta) - - void init_mmo(MMO* env) - void c_reset(MMO* env, int seed) - void c_step(MMO* env) - -cpdef entity_dtype(): - '''Make a dummy entity to get the dtype''' - cdef Entity entity - return np.asarray(&entity).dtype - -cpdef reward_dtype(): - '''Make a dummy reward to get the dtype''' - cdef Reward reward - return np.asarray(&reward).dtype - -cdef class Environment: - cdef: - MMO* envs - Client* client - LogBuffer* logs - int num_envs - - def __init__(self, unsigned char[:, :] observations, int[:, :] players, - int[:, :] enemies, float[:, :] rewards, int[:] actions, - list width, list height, int num_envs, list num_players, - list num_enemies, list num_resources, list num_weapons, list num_gems, - list tiers, list levels, list teleportitis_prob, list enemy_respawn_ticks, - list item_respawn_ticks, float reward_combat_level, float reward_prof_level, - float reward_item_level, float reward_market, float reward_death, - int x_window=7, int y_window=5): - - cdef: - int total_players = 0 - int total_enemies = 0 - int n_players = 0 - int n_enemies = 0 - - self.num_envs = num_envs - self.envs = calloc(num_envs, sizeof(MMO)) - self.logs = allocate_logbuffer(LOG_BUFFER_SIZE) - for i in range(num_envs): - obs_i = observations[total_players:total_players+n_players] - rewards_i = rewards[total_players:total_players+n_players] - players_i = players[total_players:total_players+n_players] - enemies_i = enemies[total_enemies:total_enemies+n_enemies] - #counts_i = counts[total_players:total_players+n_players] - #terrain_i = terrain[total_players:total_players+n_players] - #rendered_i = rendered[total_players:total_players+n_players] - actions_i = actions[total_players:total_players+n_players] - - self.envs[i] = MMO( - obs=&observations[total_players, 0], - rewards= &rewards[total_players, 0], - players= &players[total_players, 0], - enemies= &enemies[total_enemies, 0], - actions=&actions[total_players], - width=width[i], - height=height[i], - num_players=num_players[i], - num_enemies=num_enemies[i], - num_resources=num_resources[i], - num_weapons=num_weapons[i], - num_gems=num_gems[i], - tiers=tiers[i], - levels=levels[i], - teleportitis_prob=teleportitis_prob[i], - enemy_respawn_ticks=enemy_respawn_ticks[i], - item_respawn_ticks=item_respawn_ticks[i], - x_window=x_window, - y_window=y_window, - log_buffer=self.logs, - reward_combat_level=reward_combat_level, - reward_prof_level=reward_prof_level, - reward_item_level=reward_item_level, - reward_market=reward_market, - reward_death=reward_death, - ) - n_players = num_players[i] - n_enemies = num_enemies[i] - - init_mmo(&self.envs[i]) - total_players += n_players - total_enemies += n_enemies - - self.client = NULL - - def reset(self): - cdef int i - for i in range(self.num_envs): - # TODO: Seed - c_reset(&self.envs[i], i+1) - # Do I need to reset terrain here? - - def step(self): - cdef int i - for i in range(self.num_envs): - c_step(&self.envs[i]) - - def pids(self): - ary = np.zeros((512, 512), dtype=np.intc) - cdef int i, j - for i in range(512): - for j in range(512): - ary[i, j] = self.envs[0].pids[512*i + j] - return ary - - def render(self): - if self.client == NULL: - import os - cwd = os.getcwd() - os.chdir(os.path.abspath(os.path.join(os.path.dirname(__file__), "..", ".."))) - self.client = make_client(&self.envs[0]) - os.chdir(cwd) - - cdef int i, atn - cdef int action = ATN_NOOP; - for i in range(36): - atn = tick(self.client, &self.envs[0], i/36.0) - if atn != ATN_NOOP: - action = atn - - self.envs[0].actions[0] = action - - # TODO - def close(self): - if self.client != NULL: - #close_game_renderer(self.renderer) - self.client = NULL - - def log(self): - cdef Log log = aggregate_and_clear(self.logs) - return log diff --git a/pufferlib/ocean/nmmo3/make_sprite_sheets.py b/pufferlib/ocean/nmmo3/make_sprite_sheets.py deleted file mode 100644 index be4d52c334..0000000000 --- a/pufferlib/ocean/nmmo3/make_sprite_sheets.py +++ /dev/null @@ -1,498 +0,0 @@ -''' -This script is used to generate scaled and combined sprite sheets for nmmo3 -You will need the to put the following folders into the same directory. They -can be purchased from ManaSeed on itch.io - -20.04c - Summer Forest 4.2 -20.05c - Spring Forest 4.1 -20.06a - Autumn Forest 4.1 -20.07a - Winter Forest 4.0a -20.01a - Character Base 2.5c -20.01c - Peasant Farmer Pants & Hat 2.1 (comp. v01) -20.01c - Peasant Farmer Pants & Hat 2.2 (optional combat animations) -20.08b - Bow Combat 3.2 -21.07b - Sword & Shield Combat 2.3 -21.10a - Forester Pointed Hat & Tunic 2.1a (comp. v01) -21.10a - Forester Pointed Hat & Tunic 2.2 (optional, combat animations) -''' - -from itertools import product -from PIL import Image -import pyray as ray -import numpy as np -import random -import sys -import os -import cv2 - - -SHEET_SIZE = 2048 -N_GENERATE = 10 - -ELEMENTS = ( - ('neutral', 1, ray.Color(255, 255, 255, 255)), - ('fire', 5, ray.Color(255, 128, 128, 255)), - ('water', 9, ray.Color(128, 128, 255, 255)), - ('earth', 11, ray.Color(128, 255, 128, 255)), - ('air', 3, ray.Color(255, 255, 128, 255)), -) - -BASE = list(range(8)) -HAIR = list(range(14)) -CLOTHES = list(range(1, 6)) -SWORD = list(range(1, 6)) -BOW = list(range(1, 6)) -QUIVER = list(range(1, 9)) - -# Hair colors, indices into files -''' -HAIR = { - ELEM_NEUTRAL: 1, - ELEM_FIRE: 5, - ELEM_WATER: 9, - ELEM_EARTH: 11, - ELEM_AIR: 3 -} -''' - - -# Character base -character = 'char_a_p1_0bas_humn_v{i:02}.png' -demon = 'char_a_p1_0bas_demn_v{i:02}.png' -goblin = 'char_a_p1_0bas_gbln_v{i:02}.png' -hair_dap = 'char_a_p1_4har_dap1_v{i:02}.png' -hair_bob = 'char_a_p1_4har_bob1_v{i:02}.png' - -# Combat animations -sword_character = 'char_a_pONE3_0bas_humn_v{i:02}.png' -sword_weapon = 'char_a_pONE3_6tla_sw01_v{i:02}.png' -sword_hair_bob = 'char_a_pONE3_4har_bob1_v{i:02}.png' -sword_hair_dap = 'char_a_pONE3_4har_dap1_v{i:02}.png' -bow_character = 'char_a_pBOW3_0bas_humn_v{i:02}.png' -bow_hair_dap = 'char_a_pBOW3_4har_dap1_v{i:02}.png' -bow_hair_bob = 'char_a_pBOW3_4har_bob1_v{i:02}.png' -bow_weapon = 'char_a_pBOW3_6tla_bo01_v{i:02}.png' -bow_quiver = 'char_a_pBOW3_7tlb_qv01_v{i:02}.png' -arrow = 'aro_comn_v{i:02}.png' - -# Peasant character alternative -peasant_clothes = 'char_a_p1_1out_pfpn_v{i:02}.png' -sword_peasant_clothes = 'char_a_pONE3_1out_pfpn_v{i:02}.png' -bow_peasant_clothes = 'char_a_pBOW3_1out_pfpn_v{i:02}.png' - -# Forester character alternative -forester_hat = 'char_a_p1_5hat_pnty_v{i:02}.png' -forester_clothes = 'char_a_p1_1out_fstr_v{i:02}.png' -sword_forester_hat = 'char_a_pONE3_5hat_pnty_v{i:02}.png' -sword_forester_clothes = 'char_a_pONE3_1out_fstr_v{i:02}.png' -bow_forester_hat = 'char_a_pBOW3_5hat_pnty_v{i:02}.png' -bow_forester_clothes = 'char_a_pBOW3_1out_fstr_v{i:02}.png' - -sword_mask = np.array(( - (1, 1, 1, 1, 1, 1, 1, 1), - (1, 1, 1, 1, 1, 1, 1, 1), - (1, 0, 1, 1, 1, 1, 1, 1), - (1, 0, 1, 1, 1, 1, 1, 1), - (0, 0, 1, 1, 1, 1, 1, 1), - (1, 1, 1, 1, 1, 1, 1, 1), - (0, 0, 1, 1, 0, 0, 0, 0), - (0, 0, 1, 1, 0, 0, 0, 0), -)) - -bow_mask = np.array(( - (0, 0, 0, 0, 0, 0, 0, 0), - (1, 1, 1, 1, 1, 1, 1, 1), - (1, 0, 0, 0, 0, 0, 0, 0), - (1, 0, 0, 0, 0, 0, 0, 0), - (0, 0, 0, 0, 0, 0, 0, 0), - (1, 1, 1, 1, 1, 1, 1, 1), - (1, 0, 0, 0, 0, 0, 0, 0), - (1, 0, 0, 0, 0, 0, 0, 0), -)) - -quiver_mask = np.array(( - (1, 1, 1, 1, 1, 1, 1, 1), - (0, 0, 0, 0, 0, 0, 0, 0), - (1, 1, 1, 1, 1, 1, 1, 1), - (1, 1, 1, 1, 1, 1, 1, 1), - (1, 1, 1, 1, 1, 1, 1, 1), - (0, 0, 0, 0, 0, 0, 0, 0), - (1, 1, 1, 1, 1, 1, 1, 1), - (1, 1, 1, 1, 1, 1, 1, 1), -)) - -def draw_tex(path, f_name, i, x, y, tint=None): - if tint is None: - tint = ray.WHITE - - path = os.path.join(path, f_name).format(i=i) - texture = ray.load_texture(path) - source_rect = ray.Rectangle(0, 0, texture.width, -texture.height) - dest_rect = ray.Rectangle(x, y, texture.width, texture.height) - ray.draw_texture_pro(texture, source_rect, dest_rect, (0, 0), 0, tint) - -def draw_masked_tex(path, f_name, i, x, y, mask, tint=None): - if tint is None: - tint = ray.WHITE - - path = os.path.join(path, f_name).format(i=i) - texture = ray.load_texture(path) - Y, X = mask.shape - for r, row in enumerate(mask): - for c, m in enumerate(row): - if m == 0: - continue - - src_x = c * 128 - src_y = r * 128 - source_rect = ray.Rectangle(src_x, src_y, 128, -128) - - dst_x = x + src_x - dst_y = y + (Y-r-1)*128 - dest_rect = ray.Rectangle(dst_x, dst_y, 128, 128) - - ray.draw_texture_pro(texture, source_rect, dest_rect, (0, 0), 0, tint) - -def draw_arrow(tex, src_x, src_y, dst_x, dst_y, offset_x, offset_y, rot): - source_rect = ray.Rectangle(src_x*32, src_y*32, 32, -32) - dest_rect = ray.Rectangle(dst_x*128 + offset_x, SHEET_SIZE-(dst_y+1)*128+ offset_y, 32, 32) - ray.draw_texture_pro(tex, source_rect, dest_rect, (0, 0), rot, ray.WHITE) - -def draw_sheet(src, hair_i, tint, seed=None): - if seed is not None: - random.seed(seed) - - base_i = random.choice(BASE) - if hair_i is None: - hair_i = random.choice(HAIR) - clothes_i = random.choice(CLOTHES) - sword_i = random.choice(SWORD) - bow_i = random.choice(BOW) - quiver_i = random.choice(QUIVER) - - hair_variant = random.randint(0, 1) - hair = [hair_dap, hair_bob][hair_variant] - sword_hair = [sword_hair_dap, sword_hair_bob][hair_variant] - bow_hair = [bow_hair_dap, bow_hair_bob][hair_variant] - - clothes_variant = random.randint(0, 1) - clothes = [peasant_clothes, forester_clothes][clothes_variant] - sword_clothes = [sword_peasant_clothes, sword_forester_clothes][clothes_variant] - bow_clothes = [bow_peasant_clothes, bow_forester_clothes][clothes_variant] - - x = 0 - y = 1024 - draw_tex(src, character, base_i, x, y) - draw_tex(src, hair, hair_i, x, y) - draw_tex(src, clothes, clothes_i, x, y) - - x = 0 - y = 0 - draw_masked_tex(src, sword_weapon, sword_i, x, y, sword_mask, tint=tint) - draw_tex(src, sword_character, base_i, x, y) - draw_tex(src, sword_hair, hair_i, x, y) - draw_tex(src, sword_clothes, clothes_i, x, y) - draw_masked_tex(src, sword_weapon, sword_i, x, y, 1-sword_mask, tint=tint) - - x = 1024 - y = 1024 - draw_masked_tex(src, bow_weapon, bow_i, x, y, bow_mask, tint=tint) - draw_masked_tex(src, bow_quiver, quiver_i, x, y, quiver_mask, tint=tint) - draw_tex(src, bow_character, base_i, x, y) - draw_tex(src, bow_hair, hair_i, x, y) - draw_tex(src, bow_clothes, clothes_i, x, y) - draw_masked_tex(src, bow_weapon, bow_i, x, y, 1-bow_mask, tint=tint) - draw_masked_tex(src, bow_quiver, quiver_i, x, y, 1-quiver_mask, tint=tint) - - arrow_path = os.path.join(src, arrow).format(i=quiver_i) - arrow_tex = ray.load_texture(arrow_path) - - ### Arrows are manually aligned - # Left facing arrows - draw_arrow(arrow_tex, 4, 1, 9, 3, 24, 40, 0) - draw_arrow(arrow_tex, 4, 1, 10, 3, 24, 40, 0) - draw_arrow(arrow_tex, 3, 1, 11, 3, 24, 52, 0) - draw_arrow(arrow_tex, 1, 1, 12, 3, 38, 64, 0) - - # Right facing arrows - draw_arrow(arrow_tex, 4, 1, 9, 2, 64+42, 48, 120) - draw_arrow(arrow_tex, 4, 1, 10, 2, 64+42, 48, 120) - draw_arrow(arrow_tex, 3, 1, 11, 2, 64+32, 82, 180) - draw_arrow(arrow_tex, 1, 1, 12, 2, 56, 98, 180+80) - - -def scale_image(image_array, scale_factor): - if scale_factor < 1: - # Scale down with exact interpolation - scaled_image_array = image_array[::int(1/scale_factor), ::int(1/scale_factor)] - elif scale_factor > 1: - # Scale up (duplicate pixels) - scaled_image_array = np.repeat( - np.repeat( - image_array, scale_factor, axis=0 - ), scale_factor, axis=1 - ) - else: - # No scaling - scaled_image_array = image_array - - return scaled_image_array - -def copy_and_scale_files(source_directory, target_directory, scale_factor): - for root, dirs, files in os.walk(source_directory): - relative_path = os.path.relpath(root, source_directory) - target_path = os.path.join(target_directory) - os.makedirs(target_path, exist_ok=True) - - for file in files: - src_file_path = os.path.join(root, file) - target_file_path = os.path.join(target_directory, file) - - path = src_file_path.lower() - if path.endswith('.ttf'): - os.copy(src_file_path, target_file_path) - continue - - if not src_file_path.lower().endswith(('.png', '.jpg', '.jpeg')): - continue - - image = Image.open(src_file_path) - image_array = np.array(image) - scaled_image_array = scale_image(image_array, scale_factor) - scaled_image = Image.fromarray(scaled_image_array) - scaled_image.save(target_file_path) - -if len(sys.argv) != 4: - print("Usage: script.py source_directory target_directory scale_factor") - sys.exit(1) - -source_directory = sys.argv[1] -target_directory = sys.argv[2] -scale_factor = float(sys.argv[3]) - -if not os.path.exists(source_directory): - print("Source directory does not exist.") - sys.exit(1) - -valid_scales = [0.125, 0.25, 0.5, 1, 2, 4] -if scale_factor not in valid_scales: - print(f'Scale factor must be one of {valid_scales}') - -intermediate_directory = os.path.join(target_directory, 'temp') -if not os.path.exists(intermediate_directory): - os.makedirs(intermediate_directory) - copy_and_scale_files(source_directory, intermediate_directory, scale_factor) - -ray.init_window(SHEET_SIZE, SHEET_SIZE, "NMMO3") -ray.set_target_fps(60) - -output_image = ray.load_render_texture(SHEET_SIZE, SHEET_SIZE) - -i = 0 -while not ray.window_should_close() and i < N_GENERATE: - ray.set_window_title(f'Generating sheet {i+1}/{N_GENERATE}') - - for elem in ELEMENTS: - elem_name, hair_i, tint = elem - ray.begin_drawing() - ray.begin_texture_mode(output_image) - ray.clear_background(ray.BLANK) - draw_sheet(intermediate_directory, hair_i, tint, seed=i) - ray.end_texture_mode() - - image = ray.load_image_from_texture(output_image.texture) - f_path = os.path.join(target_directory, f'{elem_name}_{i}.png') - ray.export_image(image, f_path) - - ray.clear_background(ray.GRAY) - ray.draw_texture(output_image.texture, 0, 0, ray.WHITE) - ray.end_drawing() - - i += 1 - -coords = (0, 1) -spring = cv2.imread(intermediate_directory + '/spring forest.png') -summer = cv2.imread(intermediate_directory + '/summer forest.png') -autumn = cv2.imread(intermediate_directory + '/autumn forest (bare).png') -winter = cv2.imread(intermediate_directory + '/winter forest (clean).png') - -spring = scale_image(spring, 2) -summer = scale_image(summer, 2) -autumn = scale_image(autumn, 2) -winter = scale_image(winter, 2) - -SEASONS = [spring, summer, autumn, winter] - -spring_sparkle = cv2.imread(intermediate_directory + '/spring water sparkles B.png') -summer_sparkle = cv2.imread(intermediate_directory + '/summer water sparkles B 16x16.png') -autumn_sparkle = cv2.imread(intermediate_directory + '/autumn water sparkles B 16x16.png') -winter_sparkle = cv2.imread(intermediate_directory + '/winter water sparkles B 16x16.png') - -spring_sparkle = scale_image(spring_sparkle, 2) -summer_sparkle = scale_image(summer_sparkle, 2) -autumn_sparkle = scale_image(autumn_sparkle, 2) -winter_sparkle = scale_image(winter_sparkle, 2) - -SPARKLES = [spring_sparkle, summer_sparkle, autumn_sparkle, winter_sparkle] - -GRASS_OFFSET = (0, 0) -DIRT_OFFSET = (5, 0) -STONE_OFFSET = (9, 0) -WATER_OFFSET = (29, 16) - -# Not compatible with water -GRASS_1 = (0, 1) -GRASS_2 = (0, 2) -GRASS_3 = (0, 3) -GRASS_4 = (0, 4) -GRASS_5 = (0, 5) - -DIRT_1 = (8, 0) -DIRT_2 = (8, 1) -DIRT_3 = (8, 2) -DIRT_4 = (8, 3) -DIRT_5 = (8, 4) - -STONE_1 = (12, 0) -STONE_2 = (12, 1) -STONE_3 = (12, 2) -STONE_4 = (12, 3) -STONE_5 = (12, 4) - -WATER_1 = (27, 14) -WATER_2 = (28, 13) -WATER_3 = (28, 14) -WATER_4 = (29, 13) -WATER_5 = (29, 14) - -GRASS_N = [GRASS_1, GRASS_2, GRASS_3, GRASS_4, GRASS_5] -DIRT_N = [DIRT_1, DIRT_2, DIRT_3, DIRT_4, DIRT_5] -STONE_N = [STONE_1, STONE_2, STONE_3, STONE_4, STONE_5] -WATER_N = [WATER_1, WATER_2, WATER_3, WATER_4, WATER_5] - -ALL_MATERIALS = [DIRT_N, STONE_N, WATER_N] -ALL_OFFSETS = [DIRT_OFFSET, STONE_OFFSET, WATER_OFFSET] - -# These values are just sentinels -# They will be mapped to GRASS/DIRT/STONE/WATER -FULL = (-1, 0) -EMPTY = (0, -1) - -TL_CORNER = (0, 0) -T_FLAT = (1, 0) -TR_CORNER = (2, 0) -L_FLAT = (0, 1) -CENTER = (1, 1) -R_FLAT = (2, 1) -BL_CORNER = (0, 2) -B_FLAT = (1, 2) -BR_CORNER = (2, 2) -TL_DIAG = (0, 3) -TR_DIAG = (1, 3) -BL_DIAG = (0, 4) -BR_DIAG = (1, 4) -TRR_DIAG = (2, 3) -BRR_DIAG = (2, 4) - -OFFSETS = [TL_CORNER, T_FLAT, TR_CORNER, L_FLAT, CENTER, R_FLAT, BL_CORNER, - B_FLAT, BR_CORNER, TL_DIAG, TR_DIAG, BL_DIAG, BR_DIAG, TRR_DIAG, BRR_DIAG] - -TILE_SIZE = int(32 * scale_factor) -SHEET_SIZE = 64 -SHEET_PX = TILE_SIZE * SHEET_SIZE -merged_sheet = np.zeros((SHEET_PX, SHEET_PX, 3), dtype=np.uint8) - -def gen_lerps(): - valid_combinations = [] - for combo in product(range(10), repeat=4): - if sum(combo) == 9 and any(weight > 0 for weight in combo): - valid_combinations.append(combo) - - return valid_combinations - -def gen_lerps(): - valid_combinations = [] - for total_sum in range(1, 10): # Loop through all possible sums from 1 to 9 - for combo in product(range(10), repeat=4): - if sum(combo) == total_sum: - valid_combinations.append(combo) - return valid_combinations - -def slice(r, c): - return np.s_[ - r*TILE_SIZE:(r+1)*TILE_SIZE, - c*TILE_SIZE:(c+1)*TILE_SIZE - ] - -idx = 0 -for sheet in SEASONS: - for offset, material in zip(ALL_OFFSETS, ALL_MATERIALS): - src_dx, src_dy = offset - - # Write full tile textures. These are irregularly - # arranged in the source sheet and require manual offsets. - for src_x, src_y in material: - dst_r, dst_c = divmod(idx, SHEET_SIZE) - idx += 1 - - src_pos = slice(src_y, src_x) - tile_tex = sheet[src_pos] - - dst_pos = slice(dst_r, dst_c) - merged_sheet[dst_pos] = tile_tex - - # Write partial tile textures. These have fixed offsets - for dx, dy in OFFSETS: - dst_r, dst_c = divmod(idx, SHEET_SIZE) - idx += 1 - - src_pos = slice(dy+src_dy, dx+src_dx) - tile_tex = sheet[src_pos] - - dst_pos = slice(dst_r, dst_c) - merged_sheet[dst_pos] = tile_tex - -for x, y in WATER_N: - # 3 animations - for anim_y in range(3): - for season, sparkle in zip(SEASONS, SPARKLES): - src_pos = slice(y, x) - tile_tex = season[src_pos] - - # 4 frame animation - for anim_x in range(4): - dst_r, dst_c = divmod(idx, SHEET_SIZE) - idx += 1 - - src_pos = slice(anim_y, anim_x) - sparkle_tex = sparkle[src_pos] - - dst_pos = slice(dst_r, dst_c) - merged_sheet[dst_pos] = tile_tex - mask = np.where(sparkle_tex != 0) - merged_sheet[dst_pos][mask] = sparkle_tex[mask] - - -for src in range(1, 5): - tex_src = slice(src, 0) - tiles = [spring[tex_src], summer[tex_src], autumn[tex_src], winter[tex_src]] - for combo in gen_lerps(): - tex = np.zeros((TILE_SIZE, TILE_SIZE, 3)) - total_weight = sum(combo) - for i, weight in enumerate(combo): - tex += weight/total_weight * tiles[i] - - tex = tex.astype(np.uint8) - - dst_r, dst_c = divmod(idx, SHEET_SIZE) - idx += 1 - - dst_pos = slice(dst_r, dst_c) - merged_sheet[dst_pos] = tex - - print(idx) - -# save image -cv2.imwrite('merged_sheet.png', merged_sheet) -cv2.imshow('merged_sheet', merged_sheet) -cv2.waitKey(0) diff --git a/pufferlib/ocean/nmmo3/nmmo3.py b/pufferlib/ocean/nmmo3/nmmo3.py deleted file mode 100644 index 32623501ba..0000000000 --- a/pufferlib/ocean/nmmo3/nmmo3.py +++ /dev/null @@ -1,232 +0,0 @@ -from pdb import set_trace as T -import numpy as np -from types import SimpleNamespace -import gymnasium -import pettingzoo -import time - -from pufferlib.ocean.nmmo3 import binding -#import binding - -import pufferlib - -class NMMO3(pufferlib.PufferEnv): - def __init__(self, width=8*[512], height=8*[512], num_envs=4, - num_players=1024, num_enemies=2048, num_resources=2048, - num_weapons=1024, num_gems=512, tiers=5, levels=40, - teleportitis_prob=0.001, enemy_respawn_ticks=2, - item_respawn_ticks=100, x_window=7, y_window=5, - reward_combat_level=1.0, reward_prof_level=1.0, - reward_item_level=0.5, reward_market=0.01, - reward_death=-1.0, log_interval=128, buf=None, seed=0): - - self.log_interval = log_interval - - if len(width) > num_envs: - width = width[:num_envs] - if len(height) > num_envs: - height = height[:num_envs] - - if not isinstance(width, list): - width = num_envs * [width] - if not isinstance(height, list): - height = num_envs * [height] - if not isinstance(num_players, list): - num_players = num_envs * [num_players] - if not isinstance(num_enemies, list): - num_enemies = num_envs * [num_enemies] - if not isinstance(num_resources, list): - num_resources = num_envs * [num_resources] - if not isinstance(num_weapons, list): - num_weapons = num_envs * [num_weapons] - if not isinstance(num_gems, list): - num_gems = num_envs * [num_gems] - if not isinstance(tiers, list): - tiers = num_envs * [tiers] - if not isinstance(levels, list): - levels = num_envs * [levels] - if not isinstance(teleportitis_prob, list): - teleportitis_prob = num_envs * [teleportitis_prob] - if not isinstance(enemy_respawn_ticks, list): - enemy_respawn_ticks = num_envs * [enemy_respawn_ticks] - if not isinstance(item_respawn_ticks, list): - item_respawn_ticks = num_envs * [item_respawn_ticks] - - assert isinstance(width, list) - assert isinstance(height, list) - assert isinstance(num_players, list) - assert isinstance(num_enemies, list) - assert isinstance(num_resources, list) - assert isinstance(num_weapons, list) - assert isinstance(num_gems, list) - assert isinstance(tiers, list) - assert isinstance(levels, list) - assert isinstance(teleportitis_prob, list) - assert isinstance(enemy_respawn_ticks, list) - assert isinstance(item_respawn_ticks, list) - assert isinstance(x_window, int) - assert isinstance(y_window, int) - - assert len(width) == num_envs - assert len(height) == num_envs - assert len(num_players) == num_envs - assert len(num_enemies) == num_envs - assert len(num_resources) == num_envs - assert len(num_weapons) == num_envs - assert len(num_gems) == num_envs - assert len(tiers) == num_envs - assert len(levels) == num_envs - assert len(teleportitis_prob) == num_envs - assert len(enemy_respawn_ticks) == num_envs - assert len(item_respawn_ticks) == num_envs - - total_players = 0 - total_enemies = 0 - for idx in range(num_envs): - assert isinstance(width[idx], int) - assert isinstance(height[idx], int) - - if num_players[idx] is None: - num_players[idx] = width[idx] * height[idx] // 2048 - if num_enemies[idx] is None: - num_enemies[idx] = width[idx] * height[idx] // 512 - if num_resources[idx] is None: - num_resources[idx] = width[idx] * height[idx] // 1024 - if num_weapons[idx] is None: - num_weapons[idx] = width[idx] * height[idx] // 2048 - if num_gems[idx] is None: - num_gems[idx] = width[idx] * height[idx] // 4096 - if tiers[idx] is None: - if height[idx] <= 128: - tiers[idx] = 1 - elif height[idx] <= 256: - tiers[idx] = 2 - elif height[idx] <= 512: - tiers[idx] = 3 - elif height[idx] <= 1024: - tiers[idx] = 4 - else: - tiers[idx] = 5 - if levels[idx] is None: - if height[idx] <= 128: - levels[idx] = 7 - elif height[idx] <= 256: - levels[idx] = 15 - elif height[idx] <= 512: - levels[idx] = 31 - elif height[idx] <= 1024: - levels[idx] = 63 - else: - levels[idx] = 99 - - total_players += num_players[idx] - total_enemies += num_enemies[idx] - - self.players_flat = np.zeros((total_players, 51+501+3), dtype=np.intc) - self.enemies_flat = np.zeros((total_enemies, 51+501+3), dtype=np.intc) - self.rewards_flat = np.zeros((total_players, 10), dtype=np.float32) - #map_obs = np.zeros((total_players, 11*15 + 47 + 10), dtype=np.intc) - #counts = np.zeros((num_envs, height, width), dtype=np.uint8) - #terrain = np.zeros((num_envs, height, width), dtype=np.uint8) - #rendered = np.zeros((num_envs, height, width, 3), dtype=np.uint8) - actions = np.zeros((total_players), dtype=np.intc) - self.actions = actions - - self.num_agents = total_players - self.num_players = total_players - self.num_enemies = total_enemies - - self.comb_goal_mask = np.array([1, 0, 1, 0, 1, 1, 0, 1, 1, 1]) - self.prof_goal_mask = np.array([0, 0, 0, 1, 0, 0, 1, 1, 1, 1]) - self.tick = 0 - - self.single_observation_space = gymnasium.spaces.Box(low=0, - high=255, shape=(11*15*10+47+10,), dtype=np.uint8) - self.single_action_space = gymnasium.spaces.Discrete(26) - self.render_mode = 'human' - - super().__init__(buf) - player_count = 0 - enemy_count = 0 - c_envs = [] - for i in range(num_envs): - players = num_players[i] - enemies = num_enemies[i] - env_id = binding.env_init( - self.observations[player_count:player_count+players], - self.actions[player_count:player_count+players], - self.rewards[player_count:player_count+players], - self.terminals[player_count:player_count+players], - self.truncations[player_count:player_count+players], - i + seed*num_envs, - width=width[i], - height=height[i], - num_players=num_players[i], - num_enemies=num_enemies[i], - num_resources=num_resources[i], - num_weapons=num_weapons[i], - num_gems=num_gems[i], - tiers=tiers[i], - levels=levels[i], - teleportitis_prob=teleportitis_prob[i], - enemy_respawn_ticks=enemy_respawn_ticks[i], - item_respawn_ticks=item_respawn_ticks[i], - x_window=x_window, - y_window=y_window, - reward_combat_level=reward_combat_level, - reward_prof_level=reward_prof_level, - reward_item_level=reward_item_level, - reward_market=reward_market, - reward_death=reward_death, - ) - c_envs.append(env_id) - player_count += players - enemy_count += enemies - - self.c_envs = binding.vectorize(*c_envs) - - def reset(self, seed=0): - self.rewards.fill(0) - self.is_reset = True - binding.vec_reset(self.c_envs, seed) - return self.observations, [] - - def step(self, actions): - if not hasattr(self, 'is_reset'): - raise Exception('Must call reset before step') - self.rewards.fill(0) - self.actions[:] = actions[:] - binding.vec_step(self.c_envs) - - info = [] - if self.tick % self.log_interval == 0: - info.append(binding.vec_log(self.c_envs)) - - self.tick += 1 - return self.observations, self.rewards, self.terminals, self.truncations, info - - def render(self): - for i in range(36): - binding.vec_render(self.c_envs, 0) - - def close(self): - binding.vec_close(self.c_envs) - -def test_performance(cls, timeout=10, atn_cache=1024): - env = cls(num_envs=1) - env.reset() - tick = 0 - - actions = np.random.randint(0, 2, (atn_cache, env.num_agents)) - - import time - start = time.time() - while time.time() - start < timeout: - atn = actions[tick % atn_cache] - env.step(atn) - tick += 1 - - print(f'{env.__class__.__name__}: SPS: {env.num_agents * tick / (time.time() - start)}') - -if __name__ == '__main__': - test_performance(NMMO3) diff --git a/pufferlib/ocean/onestateworld/README.md b/pufferlib/ocean/onestateworld/README.md deleted file mode 100644 index f2da04b5df..0000000000 --- a/pufferlib/ocean/onestateworld/README.md +++ /dev/null @@ -1,14 +0,0 @@ -The One-State World is a simple research testbed designed for studying exploration strategies. - -- Structure: - - - The environment has only one state. - - At each step, the agent can choose between two actions: - - Action 0: Produces a reward with low expectation and low variance. Concretely, rewards are sampled from a Gaussian distribution with mean 0.1 and variance 0 (i.e., always 0.1). - - Action 1: Produces a reward with higher expectation but also higher variance. Rewards are sampled from a Gaussian distribution with a larger mean, but with substantial variance. -- Objective: - - The environment is meant to challenge exploration algorithms by forcing them to balance between: - - Exploiting the “safe” but low-payoff option (Action 0). - - Exploring the “risky” but potentially more rewarding option (Action 1). - -The core goal is to evaluate how well different exploration methods can identify and manage stochastic, high-variance rewards in a minimal setting. \ No newline at end of file diff --git a/pufferlib/ocean/onestateworld/onestateworld.py b/pufferlib/ocean/onestateworld/onestateworld.py deleted file mode 100644 index c52a7a7b11..0000000000 --- a/pufferlib/ocean/onestateworld/onestateworld.py +++ /dev/null @@ -1,67 +0,0 @@ -'''A simple sample environment. Use this as a template for your own envs.''' - -import gymnasium -import numpy as np - -import pufferlib -from pufferlib.ocean.onestateworld import binding - -class World(pufferlib.PufferEnv): - def __init__(self, num_envs=1, render_mode=None, log_interval=128, - mean_left=0.1, mean_right=1, var_right=5, buf=None, seed=0): - self.single_observation_space = gymnasium.spaces.Box(low=0, high=0, - shape=(1,), dtype=np.uint8) - self.single_action_space = gymnasium.spaces.Discrete(2) - self.render_mode = render_mode - self.num_agents = num_envs - self.log_interval = log_interval - - super().__init__(buf) - self.c_envs = binding.vec_init(self.observations, self.actions, self.rewards, - self.terminals, self.truncations, num_envs, seed, - mean_left=mean_left, mean_right=mean_right, var_right=var_right - ) - - def reset(self, seed=0): - binding.vec_reset(self.c_envs, seed) - self.tick = 0 - return self.observations, [] - - def step(self, actions): - self.tick += 1 - - self.actions[:] = actions - binding.vec_step(self.c_envs) - - info = [] - if self.tick % self.log_interval == 0: - info.append(binding.vec_log(self.c_envs)) - - return (self.observations, self.rewards, - self.terminals, self.truncations, info) - - def render(self): - binding.vec_render(self.c_envs, 0) - - def close(self): - binding.vec_close(self.c_envs) - -if __name__ == '__main__': - size = 10 - - env = World(size=size) - env.reset() - steps = 0 - - CACHE = 1024 - actions = np.random.randint(0, 2, (CACHE,)) - - i = 0 - import time - start = time.time() - while time.time() - start < 10: - env.step(actions[i % CACHE]) - steps += 1 - i += 1 - - print('SPS:', int(steps / (time.time() - start))) diff --git a/pufferlib/ocean/onlyfish/onlyfish.py b/pufferlib/ocean/onlyfish/onlyfish.py deleted file mode 100644 index 2414efe38a..0000000000 --- a/pufferlib/ocean/onlyfish/onlyfish.py +++ /dev/null @@ -1,64 +0,0 @@ -'''No hate. Onlyfins..''' - -import gymnasium -import numpy as np - -import pufferlib -from pufferlib.ocean.onlyfish import binding - -class OnlyFish(pufferlib.PufferEnv): - def __init__(self, num_envs=1, num_agents=8, render_mode=None, log_interval=128, buf=None, seed=0): - self.single_observation_space = gymnasium.spaces.Box(low=0, high=1, - shape=(21,), dtype=np.float32) - self.single_action_space = gymnasium.spaces.MultiDiscrete([9, 5]) - self.render_mode = render_mode - self.num_agents = num_envs*num_agents - self.log_interval = log_interval - - super().__init__(buf) - c_envs = [] - for i in range(num_envs): - c_env = binding.env_init( - self.observations[i*num_agents:(i+1)*num_agents], - self.actions[i*num_agents:(i+1)*num_agents], - self.rewards[i*num_agents:(i+1)*num_agents], - self.terminals[i*num_agents:(i+1)*num_agents], - self.truncations[i*num_agents:(i+1)*num_agents], - seed, num_agents=num_agents) - c_envs.append(c_env) - - self.c_envs = binding.vectorize(*c_envs) - - def reset(self, seed=0): - binding.vec_reset(self.c_envs, seed) - return self.observations, [] - - def step(self, actions): - self.actions[:] = actions - binding.vec_step(self.c_envs) - info = [binding.vec_log(self.c_envs)] - return (self.observations, self.rewards, - self.terminals, self.truncations, info) - - def render(self): - binding.vec_render(self.c_envs, 0) - - def close(self): - binding.vec_close(self.c_envs) - -if __name__ == '__main__': - N = 4096 - env = OnlyFish(num_envs=N) - env.reset() - steps = 0 - - CACHE = 1024 - actions = np.random.randint(0, 5, (CACHE, N)) - - import time - start = time.time() - while time.time() - start < 10: - env.step(actions[steps % CACHE]) - steps += 1 - - print('OnlyFish SPS:', int(env.num_agents*steps / (time.time() - start))) diff --git a/pufferlib/ocean/pacman/binding.c b/pufferlib/ocean/pacman/binding.c deleted file mode 100644 index f9f8c1c818..0000000000 --- a/pufferlib/ocean/pacman/binding.c +++ /dev/null @@ -1,23 +0,0 @@ -#include "pacman.h" - -#define Env PacmanEnv -#include "../env_binding.h" - -static int my_init(Env* env, PyObject* args, PyObject* kwargs) { - env->randomize_starting_position = unpack(kwargs, "randomize_starting_position"); - env->min_start_timeout = unpack(kwargs, "min_start_timeout"); - env->max_start_timeout = unpack(kwargs, "max_start_timeout"); - env->frightened_time = unpack(kwargs, "frightened_time"); - env->max_mode_changes = unpack(kwargs, "max_mode_changes"); - env->scatter_mode_length = unpack(kwargs, "scatter_mode_length"); - env->chase_mode_length = unpack(kwargs, "chase_mode_length"); - init(env); - return 0; -} - -static int my_log(PyObject* dict, Log* log) { - assign_to_dict(dict, "score", log->score); - assign_to_dict(dict, "episode_return", log->episode_return); - assign_to_dict(dict, "episode_length", log->episode_length); - return 0; -} diff --git a/pufferlib/ocean/pacman/pacman.py b/pufferlib/ocean/pacman/pacman.py deleted file mode 100644 index 1521b6ffb9..0000000000 --- a/pufferlib/ocean/pacman/pacman.py +++ /dev/null @@ -1,79 +0,0 @@ -import pufferlib - -import numpy as np -import gymnasium - -import pufferlib -from pufferlib.ocean.pacman import binding - - -class Pacman(pufferlib.PufferEnv): - def __init__(self, num_envs=1, render_mode=None, - randomize_starting_position = 0, - min_start_timeout = 0, - max_start_timeout = 49, - frightened_time = 35, - max_mode_changes = 6, - scatter_mode_length = 70, - chase_mode_length = 140, - log_interval=128, - buf=None, seed=0): - - ghost_observations_count = 9 - player_observations_count = 11 - num_ghosts = 4 - - num_dots = 244 - observations_count = (player_observations_count + ghost_observations_count * num_ghosts + num_dots) - - self.single_observation_space = gymnasium.spaces.Box( - low=0, - high=1, - shape=(observations_count,), - dtype=np.float32 - ) - self.single_action_space = gymnasium.spaces.Discrete(4) - - self.render_mode = render_mode - self.num_agents = num_envs - self.log_interval = log_interval - self.human_action = None - self.tick = 0 - - super().__init__(buf) - - self.c_envs = binding.vec_init(self.observations, self.actions, self.rewards, - self.terminals, self.truncations, num_envs, seed, - randomize_starting_position = randomize_starting_position, - min_start_timeout = min_start_timeout, - max_start_timeout = max_start_timeout, - frightened_time = frightened_time, - max_mode_changes = max_mode_changes, - scatter_mode_length = scatter_mode_length, - chase_mode_length = chase_mode_length, - ) - - def reset(self, seed=None): - binding.vec_reset(self.c_envs, seed) - self.tick = 0 - return self.observations, [] - - def step(self, actions): - self.actions[:] = actions - - self.tick += 1 - binding.vec_step(self.c_envs) - - info = [] - if self.tick % self.log_interval == 0: - info.append(binding.vec_log(self.c_envs)) - - return (self.observations, self.rewards, - self.terminals, self.truncations, info) - - def render(self): - for _ in range(7): - binding.vec_render(self.c_envs, 0) - - def close(self): - binding.vec_close(self.c_envs) diff --git a/pufferlib/ocean/pong/binding.c b/pufferlib/ocean/pong/binding.c deleted file mode 100644 index 4a84ae1d7b..0000000000 --- a/pufferlib/ocean/pong/binding.c +++ /dev/null @@ -1,31 +0,0 @@ -#include "pong.h" - -#define Env Pong -#include "../env_binding.h" - -static int my_init(Env* env, PyObject* args, PyObject* kwargs) { - env->width = unpack(kwargs, "width"); - env->height = unpack(kwargs, "height"); - env->paddle_width = unpack(kwargs, "paddle_width"); - env->paddle_height = unpack(kwargs, "paddle_height"); - env->ball_width = unpack(kwargs, "ball_width"); - env->ball_height = unpack(kwargs, "ball_height"); - env->paddle_speed = unpack(kwargs, "paddle_speed"); - env->ball_initial_speed_x = unpack(kwargs, "ball_initial_speed_x"); - env->ball_initial_speed_y = unpack(kwargs, "ball_initial_speed_y"); - env->ball_max_speed_y = unpack(kwargs, "ball_max_speed_y"); - env->ball_speed_y_increment = unpack(kwargs, "ball_speed_y_increment"); - env->max_score = unpack(kwargs, "max_score"); - env->frameskip = unpack(kwargs, "frameskip"); - env->continuous = unpack(kwargs, "continuous"); - init(env); - return 0; -} - -static int my_log(PyObject* dict, Log* log) { - assign_to_dict(dict, "perf", log->perf); - assign_to_dict(dict, "score", log->score); - assign_to_dict(dict, "episode_return", log->episode_return); - assign_to_dict(dict, "episode_length", log->episode_length); - return 0; -} diff --git a/pufferlib/ocean/pong/cy_pong.pyx b/pufferlib/ocean/pong/cy_pong.pyx deleted file mode 100644 index 88ba2b66f1..0000000000 --- a/pufferlib/ocean/pong/cy_pong.pyx +++ /dev/null @@ -1,114 +0,0 @@ -cimport numpy as cnp -from libc.stdlib cimport calloc, free -import os - -cdef extern from "pong.h": - ctypedef char* LOG_KEYS[]; - ctypedef struct Client: - pass - - ctypedef struct Pong: - Client* client; - float log[4]; - float* observations; - float* actions; - float* rewards; - unsigned char* terminals; - float paddle_yl; - float paddle_yr; - float ball_x; - float ball_y; - float ball_vx; - float ball_vy; - unsigned int score_l; - unsigned int score_r; - float width; - float height; - float paddle_width; - float paddle_height; - float ball_width; - float ball_height; - float paddle_speed; - float ball_initial_speed_x; - float ball_initial_speed_y; - float ball_max_speed_y; - float ball_speed_y_increment; - unsigned int max_score; - float min_paddle_y; - float max_paddle_y; - float paddle_dir; - int tick; - int n_bounces; - int win; - int frameskip; - int continuous; - - void init(Pong* env) - void c_reset(Pong* env) - void c_step(Pong* env) - - void c_render(Pong* env) - -cdef class CyPong: - cdef: - Pong* envs - int num_envs - float width - float height - float paddle_width - float paddle_height - float ball_width - float ball_height - - def __init__(self, float[:, :] observations, float[:] actions, - float[:] rewards, unsigned char[:] terminals, int num_envs, - float width, float height, float paddle_width, float paddle_height, - float ball_width, float ball_height, float paddle_speed, - float ball_initial_speed_x, float ball_initial_speed_y, - float ball_max_speed_y, float ball_speed_y_increment, - unsigned int max_score, int frameskip, int continuous): - - self.num_envs = num_envs - self.envs = calloc(num_envs, sizeof(Pong)) - - cdef int i - for i in range(num_envs): - self.envs[i] = Pong( - observations = &observations[i, 0], - actions = &actions[i], - rewards = &rewards[i], - terminals = &terminals[i], - width=width, - height=height, - paddle_width=paddle_width, - paddle_height=paddle_height, - ball_width=ball_width, - ball_height=ball_height, - paddle_speed=paddle_speed, - ball_initial_speed_x=ball_initial_speed_x, - ball_initial_speed_y=ball_initial_speed_y, - ball_max_speed_y=ball_max_speed_y, - ball_speed_y_increment=ball_speed_y_increment, - max_score=max_score, - frameskip=frameskip, - continuous=continuous, - ) - init(&self.envs[i]) - - def reset(self): - cdef int i - for i in range(self.num_envs): - c_reset(&self.envs[i]) - - def step(self): - cdef int i - - for i in range(self.num_envs): - c_step(&self.envs[i]) - - def render(self): - cdef Pong* env = &self.envs[0] - c_render(env) - - def close(self): - free(self.envs) diff --git a/pufferlib/ocean/pong/pong.c b/pufferlib/ocean/pong/pong.c deleted file mode 100644 index 3a91aa877e..0000000000 --- a/pufferlib/ocean/pong/pong.c +++ /dev/null @@ -1,99 +0,0 @@ -#include -#include "pong.h" -#include "puffernet.h" - -void demo() { - Weights* weights = load_weights("resources/pong/pong_weights.bin", 133764); - - int logit_sizes[1] = {3}; - LinearLSTM* net = make_linearlstm(weights, 1, 8, logit_sizes, 1); - - Pong env = { - .width = 500, - .height = 640, - .paddle_width = 20, - .paddle_height = 70, - .ball_width = 32, - .ball_height = 32, - .paddle_speed = 8, - .ball_initial_speed_x = 10, - .ball_initial_speed_y = 1, - .ball_speed_y_increment = 3, - .ball_max_speed_y = 13, - .max_score = 21, - .frameskip = 1, - .continuous = 0, - }; - allocate(&env); - c_reset(&env); - c_render(&env); - SetTargetFPS(60); - int frame = 0; - while (!WindowShouldClose()) { - // User can take control of the paddle - if (IsKeyDown(KEY_LEFT_SHIFT)) { - if(env.continuous) { - float move = GetMouseWheelMove(); - float clamped_wheel = fmaxf(-1.0f, fminf(1.0f, move)); - env.actions[0] = clamped_wheel; - printf("Mouse wheel move: %f\n", env.actions[0]); - } else { - env.actions[0] = 0.0; - if (IsKeyDown(KEY_UP) || IsKeyDown(KEY_W)) env.actions[0] = 1.0; - if (IsKeyDown(KEY_DOWN) || IsKeyDown(KEY_S)) env.actions[0] = 2.0; - } - } else if (frame % 8 == 0) { - // Apply frameskip outside the env for smoother rendering - int* actions = (int*)env.actions; - forward_linearlstm(net, env.observations, actions); - env.actions[0] = actions[0]; - } - - frame = (frame + 1) % 8; - c_step(&env); - c_render(&env); - } - free_linearlstm(net); - free(weights); - free_allocated(&env); - close_client(env.client); -} - -void test_performance(int timeout) { - Pong env = { - .width = 500, - .height = 640, - .paddle_width = 20, - .paddle_height = 70, - .ball_width = 32, - .ball_height = 32, - .paddle_speed = 8, - .ball_initial_speed_x = 10, - .ball_initial_speed_y = 1, - .ball_speed_y_increment = 3, - .ball_max_speed_y = 13, - .max_score = 21, - .frameskip = 1, - .continuous = 0, - }; - allocate(&env); - c_reset(&env); - - int start = time(NULL); - int num_steps = 0; - while (time(NULL) - start < timeout) { - env.actions[0] = rand() % 3; - c_step(&env); - num_steps++; - } - - int end = time(NULL); - float sps = num_steps / (end - start); - printf("Test Environment SPS: %f\n", sps); - free_allocated(&env); -} - -int main() { - demo(); - //test_performance(10); -} diff --git a/pufferlib/ocean/pong/pong.py b/pufferlib/ocean/pong/pong.py deleted file mode 100644 index 1a37a693be..0000000000 --- a/pufferlib/ocean/pong/pong.py +++ /dev/null @@ -1,159 +0,0 @@ -'''High-perf Pong - -Inspired from https://gist.github.com/Yttrmin/18ecc3d2d68b407b4be1 -& https://jair.org/index.php/jair/article/view/10819/25823 -& https://www.youtube.com/watch?v=PSQt5KGv7Vk -''' - -import numpy as np -import gymnasium - -import pufferlib -from pufferlib.ocean.pong import binding -#import binding - -class Pong(pufferlib.PufferEnv): - def __init__(self, num_envs=1, render_mode=None, - width=500, height=640, paddle_width=20, paddle_height=70, - ball_width=32, ball_height=32, paddle_speed=8, - ball_initial_speed_x=10, ball_initial_speed_y=1, - ball_speed_y_increment=3, ball_max_speed_y=13, - max_score=21, frameskip=1, continuous=False, log_interval=128, - buf=None, seed=0): - self.single_observation_space = gymnasium.spaces.Box( - low=0, high=1, shape=(8,), dtype=np.float32, - ) - if continuous: - self.single_action_space = gymnasium.spaces.Box( - low=-1, high=1, dtype=np.float32, - ) - else: - self.single_action_space = gymnasium.spaces.Discrete(3) - - self.render_mode = render_mode - self.num_agents = num_envs - self.continuous = continuous - self.log_interval = log_interval - self.human_action = None - self.tick = 0 - - super().__init__(buf) - if continuous: - self.actions = self.actions.flatten() - else: - self.actions = self.actions.astype(np.float32) - - self.c_envs = binding.vec_init(self.observations, self.actions, self.rewards, - self.terminals, self.truncations, num_envs, seed, width=width, height=height, - paddle_width=paddle_width, paddle_height=paddle_height, - ball_width=ball_width, ball_height=ball_height, - paddle_speed=paddle_speed, ball_initial_speed_x=ball_initial_speed_x, - ball_initial_speed_y=ball_initial_speed_y, - ball_max_speed_y=ball_max_speed_y, ball_speed_y_increment=ball_speed_y_increment, - max_score=max_score, frameskip=frameskip, continuous=continuous - ) - - def reset(self, seed=0): - binding.vec_reset(self.c_envs, seed) - self.tick = 0 - return self.observations, [] - - def step(self, actions): - if self.continuous: - self.actions[:] = np.clip(actions.flatten(), -1.0, 1.0) - else: - self.actions[:] = actions - - self.tick += 1 - binding.vec_step(self.c_envs) - - info = [] - if self.tick % self.log_interval == 0: - info.append(binding.vec_log(self.c_envs)) - - return (self.observations, self.rewards, - self.terminals, self.truncations, info) - - def render(self): - binding.vec_render(self.c_envs, 0) - - def close(self): - binding.vec_close(self.c_envs) - -#from cy_pong import CyPong -class CythonPong(pufferlib.PufferEnv): - def __init__(self, num_envs=1, render_mode=None, - width=500, height=640, paddle_width=20, paddle_height=70, - ball_width=32, ball_height=32, paddle_speed=8, - ball_initial_speed_x=10, ball_initial_speed_y=1, - ball_speed_y_increment=3, ball_max_speed_y=13, - max_score=21, frameskip=1, continuous=False, report_interval=128, buf=None): - self.single_observation_space = gymnasium.spaces.Box( - low=0, high=1, shape=(8,), dtype=np.float32, - ) - if continuous: - self.single_action_space = gymnasium.spaces.Box( - low=-1, high=1, dtype=np.float32, - ) - else: - self.single_action_space = gymnasium.spaces.Discrete(3) - - self.render_mode = render_mode - self.num_agents = num_envs - self.continuous = continuous - self.report_interval = report_interval - self.human_action = None - self.tick = 0 - - super().__init__(buf) - if continuous: - self.actions = self.actions.flatten() - else: - self.actions = self.actions.astype(np.float32) - self.c_envs = CyPong(self.observations, self.actions, self.rewards, - self.terminals, num_envs, width, height, - paddle_width, paddle_height, ball_width, ball_height, - paddle_speed, ball_initial_speed_x, ball_initial_speed_y, - ball_max_speed_y, ball_speed_y_increment, max_score, frameskip, continuous) - - def reset(self, seed=None): - self.tick = 0 - self.c_envs.reset() - return self.observations, [] - - def step(self, actions): - if self.continuous: - self.actions[:] = np.clip(actions.flatten(), -1.0, 1.0) - else: - self.actions[:] = actions - - self.c_envs.step() - info = [] - self.tick += 1 - return (self.observations, self.rewards, - self.terminals, self.truncations, info) - - def render(self): - self.c_envs.render() - - def close(self): - self.c_envs.close() - -def test_performance(cls, timeout=10, atn_cache=1024): - env = cls(num_envs=1000) - env.reset() - tick = 0 - - actions = np.random.randint(0, 2, (atn_cache, env.num_agents)) - - import time - start = time.time() - while time.time() - start < timeout: - atn = actions[tick % atn_cache] - env.step(atn) - tick += 1 - - print(f'{env.__class__.__name__}: SPS: {env.num_agents * tick / (time.time() - start)}') - -if __name__ == '__main__': - test_performance(Pong) diff --git a/pufferlib/ocean/pysquared/pysquared.py b/pufferlib/ocean/pysquared/pysquared.py deleted file mode 100644 index eee180bc7d..0000000000 --- a/pufferlib/ocean/pysquared/pysquared.py +++ /dev/null @@ -1,131 +0,0 @@ -'''Pure python version of Squared, a simple single-agent sample environment. - Use this as a template for your own envs. -''' - -# We only use Gymnasium for their spaces API for compatibility with other libraries. -import gymnasium -import numpy as np - -import pufferlib - -NOOP = 0 -DOWN = 1 -UP = 2 -LEFT = 3 -RIGHT = 4 - -EMPTY = 0 -AGENT = 1 -TARGET = 2 - -# Inherit from PufferEnv -class PySquared(pufferlib.PufferEnv): - # Required keyword arguments: render_mode, buf, seed - def __init__(self, render_mode='ansi', size=11, buf=None, seed=0): - # Required attributes below - self.single_observation_space = gymnasium.spaces.Box(low=0, high=1, - shape=(size*size,), dtype=np.uint8) - self.single_action_space = gymnasium.spaces.Discrete(5) - self.render_mode = render_mode - self.num_agents = 1 - - # Call super after initializing attributes - super().__init__(buf) - - # Add anything else you want - self.size = size - - # All methods below are required with the signatures shown - def reset(self, seed=0): - self.observations[0, :] = EMPTY - self.observations[0, self.size*self.size//2] = AGENT - self.r = self.size//2 - self.c = self.size//2 - self.tick = 0 - while True: - target_r, target_c = np.random.randint(0, self.size, 2) - if target_r != self.r or target_c != self.c: - self.observations[0, target_r*self.size + target_c] = TARGET - break - - # Observations are read from self. Don't create extra copies - return self.observations, [] - - def step(self, actions): - atn = actions[0] - - # Note that terminals, rewards, etc. are updated in-place - self.terminals[0] = False - self.rewards[0] = 0 - - self.observations[0, self.r*self.size + self.c] = EMPTY - - if atn == DOWN: - self.r += 1 - elif atn == RIGHT: - self.c += 1 - elif atn == UP: - self.r -= 1 - elif atn == LEFT: - self.c -= 1 - - # Info is a list of dictionaries - info = [] - pos = self.r*self.size + self.c - if (self.tick > 3*self.size - or self.r < 0 - or self.c < 0 - or self.r >= self.size - or self.c >= self.size): - self.terminals[0] = True - self.rewards[0] = -1.0 - info = [{'reward': -1.0}] - self.reset() - elif self.observations[0, pos] == TARGET: - self.terminals[0] = True - self.rewards[0] = 1.0 - info = [{'reward': 1.0}] - self.reset() - else: - self.observations[0, pos] = AGENT - self.tick += 1 - - # Return the in-place versions. Don't copy! - return self.observations, self.rewards, self.terminals, self.truncations, info - - def render(self): - # Quick ascii rendering. If you want a Python-based renderer, - # we highly recommend Raylib over PyGame etc. If you use the - # C-style Python API, it will be very easy to port to C native later. - chars = [] - grid = self.observations.reshape(self.size, self.size) - for row in grid: - for val in row: - if val == AGENT: - color = 94 - elif val == TARGET: - color = 91 - else: - color = 90 - chars.append(f'\033[{color}m██\033[0m') - chars.append('\n') - return ''.join(chars) - - def close(self): - pass - -if __name__ == '__main__': - env = PySquared() - env.reset() - steps = 0 - - CACHE = 1024 - actions = np.random.randint(0, 5, (CACHE, 1)) - - import time - start = time.time() - while time.time() - start < 10: - env.step(actions[steps % CACHE]) - steps += 1 - - print('PySquared SPS:', int(steps / (time.time() - start))) diff --git a/pufferlib/ocean/render.py b/pufferlib/ocean/render.py deleted file mode 100644 index 1a6b024043..0000000000 --- a/pufferlib/ocean/render.py +++ /dev/null @@ -1,247 +0,0 @@ -import numpy as np -import os - -from cffi import FFI -from raylib import rl, colors -import pyray - -PUFF_BACKGROUND = [6, 24, 24, 255] -PUFF_TEXT = [0, 187, 187, 255] - -ANSI_COLORS = [30, 34, 36, 90, 31, 97, 91, 37] - -COLORS = np.array([ - [6, 24, 24 ], # Background - [0, 0, 255], # Food - [0, 128, 255], # Corpse - [128, 128, 128], # Wall - [255, 0, 0], # Snake - [255, 255, 255], # Snake - [255, 85, 85], # Snake - [170, 170, 170], # Snake -], dtype=np.uint8) - - -def any_key_down(keys): - for key in keys: - if rl.IsKeyDown(key): - return True - return False - -def any_key_pressed(keys): - for key in keys: - if rl.IsKeyPressed(key): - return True - return False - -def cdata_to_numpy(): - image = rl.LoadImageFromScreen() - data_pointer = image.data - width = image.width - height = image.height - channels = 4 - data_size = width * height * channels - cdata = FFI().buffer(data_pointer, data_size) - return np.frombuffer(cdata, dtype=np.uint8 - ).reshape((height, width, channels)) - -def make_texture(width, height): - rendered = np.zeros((height, width, 4), dtype=np.uint8) - raylib_image = pyray.Image(FFI().from_buffer(rendered.data), - width, height, 1, pyray.PIXELFORMAT_UNCOMPRESSED_R8G8B8) - return rl.LoadTextureFromImage(raylib_image) - -class AnsiRender: - def __init__(self, colors=None): - self.colors = colors - if colors is None: - self.colors = ANSI_COLORS - - def render(self, grid): - frame = '' - for v in range(grid.shape[0]): - lines = [] - for line in grid[v-1:-v, v-1:-v]: - lines.append(''.join([ - f'\033[{ANSI_COLORS[val]}m██\033[0m' for val in line])) - - frame = '\n'.join(lines) - - return frame - -class RGBArrayRender: - def __init__(self, colors=None, upscale=1): - self.colors = colors - if colors is None: - self.colors = COLORS - - self.rescaler = np.ones((upscale, upscale, 1), dtype=np.uint8) - self.upscale = upscale - - def render(self, grid): - frame = self.colors[grid] - - if self.upscale > 1: - frame = np.kron(frame, self.rescaler) - - return frame - -class GridRender: - def __init__(self, width, height, screen_width=1080, screen_height=720, - colors=None, fps=60, name='PufferLib Raylib Renderer'): - self.width = width - self.height = height - self.fps = fps - - self.colors = colors - if colors is None: - self.colors = COLORS - - rl.InitWindow(screen_width, screen_height, name.encode()) - rl.SetTargetFPS(fps) - self.width = width - self.height = height - - camera = pyray.Camera2D() - camera.target= (width/2, height/2) - camera.rotation = 0.0 - camera.zoom = min(screen_width/width, screen_height/height) - self.camera = camera - - self.speed = min(screen_width, screen_height) / 100 - self.texture = make_texture(width, height) - - self.show_help = False - self.screen_width = screen_width - self.screen_height = screen_height - - def render(self, grid, *args, end_drawing=True): - assert grid.shape[0] == self.height - assert grid.shape[1] == self.width - rendered = self.colors[grid] - - if rl.IsKeyDown(rl.KEY_ESCAPE): - exit(0) - - screen_width = rl.GetScreenWidth() - screen_height = rl.GetScreenHeight() - - camera = self.camera - camera.offset.x = screen_width/2 - camera.offset.y = screen_height/2 - - fps = rl.GetFPS() or self.fps - fps_mul = self.fps / fps - speed = self.speed * fps_mul - zoom_speed = 0.01 * fps_mul - - if any_key_down([rl.KEY_SPACE]): - camera.zoom = min(screen_width/self.width, screen_height/self.height) - camera.target.x = self.width/2 - camera.target.y = self.height/2 - - if any_key_down([rl.KEY_LEFT_SHIFT]): - speed *= 3 - zoom_speed *= 3 - - speed = speed / camera.zoom - - if any_key_down([rl.KEY_UP, rl.KEY_W]): - camera.target.y -= speed - if any_key_down([rl.KEY_DOWN, rl.KEY_S]): - camera.target.y += speed - if any_key_down([rl.KEY_LEFT, rl.KEY_A]): - camera.target.x -= speed - if any_key_down([rl.KEY_RIGHT, rl.KEY_D]): - camera.target.x += speed - if any_key_down([rl.KEY_Q, rl.KEY_MINUS]): - camera.zoom /= 1 + zoom_speed - if any_key_down([rl.KEY_E, rl.KEY_EQUAL]): - camera.zoom *= 1 + zoom_speed - - if any_key_pressed([rl.KEY_TAB, rl.KEY_GRAVE]): - self.show_help = not self.show_help - - rl.BeginDrawing() - rl.BeginMode2D(self.camera) - rl.ClearBackground(PUFF_BACKGROUND) - rl.UpdateTexture(self.texture, rendered.tobytes()) - rl.DrawTextureEx(self.texture, (0, 0), 0, 1, colors.WHITE) - rl.EndMode2D() - if self.show_help: - # Stats - rl.DrawText(f'FPS: {fps}'.encode(), 10, 10, 20, PUFF_TEXT) - rl.DrawText(f'Zoom: {camera.zoom:.2f}'.encode(), 10, 30, 20, PUFF_TEXT) - rl.DrawText(f'X: {camera.offset.x:.2f}'.encode(), 10, 50, 20, PUFF_TEXT) - rl.DrawText(f'Y: {camera.offset.y:.2f}'.encode(), 10, 70, 20, PUFF_TEXT) - rl.DrawText(f'Speed: {speed:.2f}'.encode(), 10, 90, 20, PUFF_TEXT) - - # Controls - rl.DrawText('Move: WASD/HJKL'.encode(), 10, 120, 20, PUFF_TEXT) - rl.DrawText('Zoom: QE/-+'.encode(), 10, 140, 20, PUFF_TEXT) - rl.DrawText('Turbo: Shift'.encode(), 10, 160, 20, PUFF_TEXT) - rl.DrawText('Help: Tab/~'.encode(), 10, 180, 20, PUFF_TEXT) - rl.DrawText('Reset: Space'.encode(), 10, 200, 20, PUFF_TEXT) - - if end_drawing: - rl.EndDrawing() - - return cdata_to_numpy() - -class GameRender: - def __init__(self, width, height, screen_width=1080, screen_height=720, - colors=None, name='PufferLib Raylib Game'): - self.client = GridRender(width, height, - screen_width, screen_height, colors, name) - - def render(self, grid, x, y): - self.client.camera.target.x = x - self.client.camera.target.y = y - return self.client.render(grid) - -class TestGameRender: - def __init__(self, width, height, colors=None, - tile_size=16, name='PufferLib Raylib Game'): - assert width % tile_size == 0 - assert height % tile_size == 0 - assert (width // tile_size) % 2 == 1 - assert (height // tile_size) % 2 == 1 - - self.width = width - self.height = height - - self.colors = colors - if colors is None: - self.colors = COLORS - - self.x_tiles = width // tile_size - self.y_tiles = height // tile_size - - rl.InitWindow(width, height, name.encode()) - rl.SetTargetFPS(60) - - def render(self, grid, agent_positions): - action = None - if rl.IsKeyDown(rl.KEY_UP) or rl.IsKeyDown(rl.KEY_W): - action = 0 - elif rl.IsKeyDown(rl.KEY_DOWN) or rl.IsKeyDown(rl.KEY_S): - action = 1 - elif rl.IsKeyDown(rl.KEY_LEFT) or rl.IsKeyDown(rl.KEY_A): - action = 2 - elif rl.IsKeyDown(rl.KEY_RIGHT) or rl.IsKeyDown(rl.KEY_D): - action = 3 - - rl.BeginDrawing() - rl.ClearBackground(PUFF_BACKGROUND) - - main_y, main_x = agent_positions[0] - dx = self.x_tiles // 2 - dy = self.y_tiles // 2 - - -if __name__ == '__main__': - renderer = GridRender(256, 256) - grid = np.random.randint(0, 3, (256, 256), dtype=np.uint8) - while True: - frame = renderer.render(grid) - diff --git a/pufferlib/ocean/robocode/build_local.sh b/pufferlib/ocean/robocode/build_local.sh deleted file mode 100644 index 4dd2865c06..0000000000 --- a/pufferlib/ocean/robocode/build_local.sh +++ /dev/null @@ -1,3 +0,0 @@ -clang -Wall -Wuninitialized -Wmisleading-indentation -fsanitize=address,undefined,bounds,pointer-overflow,leak -ferror-limit=3 -g -o robocode robocode.c -I./raylib-5.0_linux_amd64/include/ -L./raylib-5.0_linux_amd64/lib/ -lraylib -lGL -lm -lpthread -ldl -lrt -lX11 -DPLATFORM_DESKTOP - - diff --git a/pufferlib/ocean/robocode/robocode b/pufferlib/ocean/robocode/robocode deleted file mode 100755 index 59131fc78f..0000000000 Binary files a/pufferlib/ocean/robocode/robocode and /dev/null differ diff --git a/pufferlib/ocean/robocode/robocode.c b/pufferlib/ocean/robocode/robocode.c deleted file mode 100644 index c7b3105f20..0000000000 --- a/pufferlib/ocean/robocode/robocode.c +++ /dev/null @@ -1,57 +0,0 @@ -#include "robocode.h" - -int main() { - Env env = {0}; - env.num_agents = 2; - env.width = 768; - env.height = 576; - allocate_env(&env); - reset(&env); - - Client* client = make_client(&env); - - while (!WindowShouldClose()) { - for (int i = 0; i < NUM_ACTIONS; i++) { - env.actions[i] = 0; - } - - env.actions[0] = 16.0f; - float x = env.robots[0].x; - float y = env.robots[0].y; - float op_x = env.robots[1].x; - float op_y = env.robots[1].y; - float gun_heading = env.robots[0].gun_heading; - float angle_to_op = 180*atan2(op_y - y, op_x - x)/M_PI; - float gun_delta = angle_to_op - gun_heading; - if (gun_delta < -180) gun_delta += 360; - env.actions[2] = (gun_delta > 0) ? 1.0f : -1.0f; - if (gun_delta < 5 && gun_delta > -5) env.actions[4] = 1.0; - - env.actions[5] = 16.0f; - x = env.robots[1].x; - y = env.robots[1].y; - op_x = env.robots[0].x; - op_y = env.robots[0].y; - gun_heading = env.robots[1].gun_heading; - angle_to_op = 180*atan2(op_y - y, op_x - x)/M_PI; - gun_delta = angle_to_op - gun_heading; - if (gun_delta < -180) gun_delta += 360; - env.actions[7] = (gun_delta > 0) ? 1.0f : -1.0f; - if (gun_delta < 5 && gun_delta > -5) env.actions[9] = 1.0; - - - //if (IsKeyPressed(KEY_ESCAPE)) break; - if (IsKeyDown(KEY_W)) env.actions[0] = 16.0f; - if (IsKeyDown(KEY_S)) env.actions[0] = -16.0f; - if (IsKeyDown(KEY_A)) env.actions[1] = -2.0f; - if (IsKeyDown(KEY_D)) env.actions[1] = 2.0f; - if (IsKeyDown(KEY_Q)) env.actions[2] = -1.0f; - if (IsKeyDown(KEY_E)) env.actions[2] = 1.0f; - if (IsKeyDown(KEY_SPACE)) env.actions[4] = 1.0f; - - step(&env); - render(client, &env); - } - CloseWindow(); - return 0; -} diff --git a/pufferlib/ocean/robocode/robocode.h b/pufferlib/ocean/robocode/robocode.h deleted file mode 100644 index d57636d8a7..0000000000 --- a/pufferlib/ocean/robocode/robocode.h +++ /dev/null @@ -1,369 +0,0 @@ -#include -#include -#include -#include -#include -#include "raylib.h" - -#define NUM_ACTIONS 5 -#define NUM_BULLETS 16 - -float cos_deg(float deg) { - return cos(deg * 3.14159265358979323846 / 180.0); -} - -float sin_deg(float deg) { - return sin(deg * 3.14159265358979323846 / 180.0); -} - -typedef struct Bullet Bullet; -struct Bullet { - float x; - float y; - float heading; - float firepower; - bool live; -}; - -typedef struct Robot Robot; -struct Robot { - float x; - float y; - float v; - float heading; - float gun_heading; - float radar_heading_prev; - float radar_heading; - float gun_heat; - int energy; - int bullet_idx; -}; - -typedef struct Env Env; -struct Env { - int num_agents; - int width; - int height; - Robot* robots; - Bullet* bullets; - float* actions; -}; - -void allocate_env(Env* env) { - env->robots = (Robot*)calloc(env->num_agents, sizeof(Robot)); - env->bullets = (Bullet*)calloc(NUM_BULLETS*env->num_agents, sizeof(Bullet)); - env->actions = (float*)calloc(NUM_ACTIONS*env->num_agents, sizeof(float)); -} - -void free_env(Env* env) { - free(env->robots); - free(env->actions); -} - -void move(Env* env, Robot* robot, float distance) { - float dx = cos_deg(robot->heading); - float dy = sin_deg(robot->heading); - //float accel = 1.0;//2.0*distance / (robot->v * robot->v); - float accel = distance; - - if (accel > 1.0) { - accel = 1.0; - } else if (accel < -2.0) { - accel = -2.0; - } - - robot->v += accel; - if (robot->v > 8.0) { - robot->v = 8.0; - } else if (robot->v < -8.0) { - robot->v = -8.0; - } - - float new_x = robot->x + dx * robot->v; - float new_y = robot->y + dy * robot->v; - - // Collision check - for (int j = 0; j < env->num_agents; j++) { - Robot* target = &env->robots[j]; - if (target == robot) { - continue; - } - float dx = target->x - new_x; - float dy = target->y - new_y; - float dist = sqrt(dx*dx + dy*dy); - if (dist > 32.0f) { - continue; - } - - target->energy -= 0.6; - robot->energy -= 0.6; - return; - } - - robot->x = new_x; - robot->y = new_y; - -} - -float turn(Env* env, Robot* robot, float degrees) { - float abs_v = fabs(robot->v); - float d_angle = 10 - 0.75*abs_v; - if (degrees > d_angle) { - degrees = d_angle; - } else if (degrees < -d_angle) { - degrees = -d_angle; - } - - robot->heading += degrees; - if (robot->heading > 360) { - robot->heading -= 360; - } else if (robot->heading < 0) { - robot->heading += 360; - } - return degrees; -} - -void fire(Env* env, Robot* robot, float firepower) { - if (robot->gun_heat > 0) { - return; - } - if (robot->energy < firepower) { - return; - } - robot->energy -= firepower; - - Bullet* bullet = &env->bullets[robot->bullet_idx]; - robot->bullet_idx = (robot->bullet_idx + 1) % NUM_BULLETS; - robot->gun_heat += 1.0f + firepower/5.0f; - - bullet->x = robot->x + 64*cos_deg(robot->gun_heading); - bullet->y = robot->y + 64*sin_deg(robot->gun_heading); - bullet->heading = robot->gun_heading; - bullet->firepower = firepower; - bullet->live = true; -} - -void reset(Env* env) { - int idx = 0; - float x, y; - while (idx < env->num_agents) { - Robot* robot = &env->robots[idx]; - x = 16 + rand() % (env->width-32); - y = 16 + rand() % (env->height-32); - bool collided = false; - for (int j = 0; j < idx; j++) { - Robot* other = &env->robots[j]; - float dx = x - other->x; - float dy = y - other->y; - float dist = sqrt(dx*dx + dy*dy); - if (dist < 32.0f) { - collided = true; - break; - } - } - if (!collided) { - robot->x = x; - robot->y = y; - robot->v = 0; - robot->heading = 0; - robot->energy = 100; - robot->gun_heat = 3; - idx += 1; - } - } -} - -void step(Env* env) { - // Update bullets - for (int agent = 0; agent < env->num_agents; agent++) { - Robot* robot = &env->robots[agent]; - if (robot->energy <= 0) { - reset(env); - return; - } - - for (int blt = 0; blt < NUM_BULLETS; blt++) { - Bullet* bullet = &env->bullets[agent*NUM_BULLETS + blt]; - if (!bullet->live) { - continue; - } - - float v = 20.0f - 3.0f*bullet->firepower; - bullet->x += v*cos_deg(bullet->heading); - bullet->y += v*sin_deg(bullet->heading); - - // Bounds check - if (bullet->x < 0 || bullet->x > env->width - || bullet->y < 0 || bullet->y > env->height) { - bullet->live = false; - continue; - } - - // Collision check - for (int j = 0; j < env->num_agents; j++) { - Robot* target = &env->robots[j]; - float dx = target->x - bullet->x; - float dy = target->y - bullet->y; - float dist = sqrt(dx*dx + dy*dy); - if (dist > 32.0f) { - continue; - } - - float damage = 4*bullet->firepower; - if (bullet->firepower > 1.0f) { - damage += 2*(bullet->firepower - 1.0f); - } - - target->energy -= damage; - robot->energy += 3*bullet->firepower; - bullet->live = false; - } - } - } - - for (int i = 0; i < env->num_agents; i++) { - Robot* robot = &env->robots[i]; - int atn_offset = i*NUM_ACTIONS; - - // Cool down gun - if (robot->gun_heat > 0) { - robot->gun_heat -= 0.1f; - } - - // Move - int move_atn = env->actions[atn_offset]; - move(env, robot, move_atn); - - // Turn - int turn_atn = env->actions[atn_offset + 1]; - float turn_degrees = turn(env, robot, turn_atn); - - // Gun - float gun_degrees = env->actions[atn_offset + 2] + turn_degrees; - robot->gun_heading += gun_degrees; - if (robot->gun_heading > 360) { - robot->gun_heading -= 360; - } else if (robot->gun_heading < 0) { - robot->gun_heading += 360; - } - - // Radar - float radar_degrees = env->actions[atn_offset + 3] + gun_degrees; - robot->radar_heading_prev = robot->radar_heading; - robot->radar_heading += radar_degrees; - if (robot->radar_heading > 360) { - robot->radar_heading -= 360; - } else if (robot->radar_heading < 0) { - robot->radar_heading += 360; - } - - // Fire - float firepower = env->actions[atn_offset + 4]; - if (firepower > 0) { - fire(env, robot, firepower); - } - - // Clip position - if (robot->x < 16) { - robot->x = 16; - } else if (robot->x > env->width - 16) { - robot->x = env->width - 16; - } - if (robot->y < 16) { - robot->y = 16; - } else if (robot->y > env->height - 16) { - robot->y = env->height - 16; - } - } -} - -typedef struct Client Client; -struct Client { - Texture2D atlas; -}; - -Client* make_client(Env* env) { - InitWindow(768, 576, "PufferLib Ray Robocode"); - SetTargetFPS(60); - Client* client = (Client*)calloc(1, sizeof(Client)); - client->atlas = LoadTexture("resources/robocode/robocode.png"); - return client; -} - -void close_client(Client* client) { - UnloadTexture(client->atlas); - CloseWindow(); -} - -void render(Client* client, Env* env) { - BeginDrawing(); - ClearBackground((Color){6, 24, 24, 255}); - - for (int x = 0; x < env->width; x+=64) { - for (int y = 0; y < env->height; y+=64) { - int src_x = 64 * ((x*33409+ y*30971) % 5); - Rectangle src_rect = (Rectangle){src_x, 0, 64, 64}; - Vector2 dest_pos = (Vector2){x, y}; - DrawTextureRec(client->atlas, src_rect, dest_pos, WHITE); - } - } - - for (int i = 0; i < env->num_agents; i++) { - int atn_offset = i*NUM_ACTIONS; - int turn_atn = env->actions[atn_offset + 1]; - int gun_atn = env->actions[atn_offset + 2] + turn_atn; - int radar_atn = env->actions[atn_offset + 3] + gun_atn; - - Robot robot = env->robots[i]; - Vector2 robot_pos = (Vector2){robot.x, robot.y}; - - // Radar - float radar_left = (radar_atn > 0) ? robot.radar_heading: robot.radar_heading_prev; - float radar_right = (radar_atn > 0) ? robot.radar_heading_prev : robot.radar_heading; - Vector2 radar_left_pos = (Vector2){ - robot.x + 1200*cos_deg(radar_left), - robot.y + 1200*sin_deg(radar_left) - }; - Vector2 radar_right_pos = (Vector2){ - robot.x + 1200*cos_deg(radar_right), - robot.y + 1200*sin_deg(radar_right) - }; - DrawTriangle(robot_pos, radar_left_pos, radar_right_pos, (Color){0, 255, 0, 128}); - - // Gun - Vector2 gun_pos = (Vector2){ - robot.x + 64*cos_deg(robot.gun_heading), - robot.y + 64*sin_deg(robot.gun_heading) - }; - //DrawLineEx(robot_pos, gun_pos, 4, WHITE); - - // Robot - //DrawCircle(robot.x, robot.y, 32, RED); - //DrawCircle(robot.x, robot.y, 16, WHITE); - float theta = robot.heading; - float dx = cos_deg(theta); - float dy = sin_deg(theta); - int src_y = 64 + 64*(i%2); - Rectangle body_rect = (Rectangle){0, src_y, 64, 64}; - Rectangle radar_rect = (Rectangle){64, src_y, 64, 64}; - Rectangle gun_rect = (Rectangle){128, src_y, 64, 64}; - Rectangle dest_rect = (Rectangle){robot.x, robot.y, 64, 64}; - Vector2 origin = (Vector2){32, 32}; - DrawTexturePro(client->atlas, body_rect, dest_rect, origin, robot.heading+90, WHITE); - DrawTexturePro(client->atlas, radar_rect, dest_rect, origin, robot.radar_heading+90, WHITE); - DrawTexturePro(client->atlas, gun_rect, dest_rect, origin, robot.gun_heading+90, WHITE); - - DrawText(TextFormat("%i", robot.energy), robot.x-16, robot.y-48, 12, WHITE); - } - - for (int i = 0; i < env->num_agents*NUM_BULLETS; i++) { - Bullet bullet = env->bullets[i]; - if (!bullet.live) { - continue; - } - Vector2 bullet_pos = (Vector2){bullet.x, bullet.y}; - DrawCircleV(bullet_pos, 4, WHITE); - } - - EndDrawing(); -} diff --git a/pufferlib/ocean/rocket_lander/cy_rocket_lander.pyx b/pufferlib/ocean/rocket_lander/cy_rocket_lander.pyx deleted file mode 100644 index 31a7fcb4fa..0000000000 --- a/pufferlib/ocean/rocket_lander/cy_rocket_lander.pyx +++ /dev/null @@ -1,129 +0,0 @@ -cimport numpy as cnp -from libc.stdlib cimport calloc, free -import os - -cdef extern from "rocket_lander.h": - int LOG_BUFFER_SIZE - - ctypedef struct b2WorldId: - unsigned short index1 - unsigned short revision - ctypedef struct b2BodyId: - int index1 - unsigned short revision - unsigned char world0 - ctypedef struct b2Vec2: - float x - float y - - ctypedef struct Log: - float episode_return; - float episode_length; - float score; - - ctypedef struct LogBuffer - LogBuffer* allocate_logbuffer(int) - void free_logbuffer(LogBuffer*) - Log aggregate_and_clear(LogBuffer*) - - ctypedef struct Entity: - b2BodyId bodyId; - b2Vec2 extent; - - ctypedef struct Lander: - float* observations; - float* actions; - float* reward; - unsigned char* terminal; - unsigned char* truncation; - LogBuffer* log_buffer; - Log log; - int tick; - b2WorldId world_id; - b2BodyId barge_id; - b2BodyId lander_id; - Entity barge; - Entity lander; - - ctypedef struct Client - - void init_lander(Lander* env) - void reset(Lander* env) - void step(Lander* env) - void free_lander(Lander* env) - - Client* make_client(Lander* env) - void render(Client* client, Lander* env) - void close_client(Client* client) - -cdef class CyRocketLander: - cdef: - Lander* envs - Client* client - LogBuffer* logs - int num_envs - - def __init__(self, cnp.ndarray observations, cnp.ndarray actions, - cnp.ndarray rewards, cnp.ndarray terminals, - cnp.ndarray truncations, int num_envs): - - self.num_envs = num_envs - self.client = NULL - self.envs = calloc(num_envs, sizeof(Lander)) - self.logs = allocate_logbuffer(LOG_BUFFER_SIZE) - - cdef: - cnp.ndarray observations_i - cnp.ndarray actions_i - cnp.ndarray rewards_i - cnp.ndarray terminals_i - cnp.ndarray truncations_i - - cdef int i - for i in range(num_envs): - observations_i = observations[i:i+1] - actions_i = actions[i:i+1] - rewards_i = rewards[i:i+1] - terminals_i = terminals[i:i+1] - truncations_i = truncations[i:i+1] - self.envs[i] = Lander( - observations = observations_i.data, - actions = actions_i.data, - reward = rewards_i.data, - terminal = terminals_i.data, - truncation = truncations_i.data, - log_buffer=self.logs, - ) - init_lander(&self.envs[i]) - - def reset(self): - cdef int i - for i in range(self.num_envs): - reset(&self.envs[i]) - - def step(self): - cdef int i - for i in range(self.num_envs): - step(&self.envs[i]) - - def render(self): - cdef Lander* env = &self.envs[0] - if self.client == NULL: - self.client = make_client(env) - - render(self.client, env) - - def close(self): - if self.client != NULL: - close_client(self.client) - self.client = NULL - - cdef int i - for i in range(self.num_envs): - free_lander(&self.envs[i]) - free(self.envs) - free(self.logs) - - def log(self): - cdef Log log = aggregate_and_clear(self.logs) - return log diff --git a/pufferlib/ocean/rocket_lander/rocket_lander.c b/pufferlib/ocean/rocket_lander/rocket_lander.c deleted file mode 100644 index d216166478..0000000000 --- a/pufferlib/ocean/rocket_lander/rocket_lander.c +++ /dev/null @@ -1,59 +0,0 @@ -#include "rocket_lander.h" - -int main(void) { - demo(); - return 0; -} - - - - /* - Entity legs[2] = {0}; - for (int i = 0; i < 2; i++) { - float leg_i = (i == 0) ? -1 : 1; - b2Vec2 leg_extent = (b2Vec2){LEG_W / SCALE, LEG_H / SCALE}; - - b2BodyDef leg = b2DefaultBodyDef(); - leg.type = b2_dynamicBody; - leg.position = (b2Vec2){-leg_i * LEG_AWAY, INITIAL_Y - LANDER_HEIGHT/2 - leg_extent.y/2}; - //leg.position = (b2Vec2){0, 0}; - leg.rotation = b2MakeRot(leg_i * 1.05); - b2BodyId leg_id = b2CreateBody(world_id, &leg); - - b2Polygon leg_box = b2MakeBox(leg_extent.x, leg_extent.y); - b2ShapeDef leg_shape = b2DefaultShapeDef(); - b2CreatePolygonShape(leg_id, &leg_shape, &leg_box); - - float joint_x = leg_i*LANDER_WIDTH/2; - float joint_y = INITIAL_Y - LANDER_HEIGHT/2 - leg_extent.y/2; - b2Vec2 joint_p = (b2Vec2){joint_x, joint_y}; - - b2RevoluteJointDef joint = b2DefaultRevoluteJointDef(); - joint.bodyIdA = lander_id; - joint.bodyIdB = leg_id; - joint.localAnchorA = b2Body_GetLocalPoint(lander_id, joint_p); - joint.localAnchorB = b2Body_GetLocalPoint(leg_id, joint_p); - joint.localAnchorB = (b2Vec2){i * 0.5, LEG_DOWN}; - joint.enableMotor = true; - joint.enableLimit = true; - joint.maxMotorTorque = LEG_SPRING_TORQUE; - joint.motorSpeed = 0.3*i; - - if (i == 0) { - joint.lowerAngle = 40 * DEGTORAD; - joint.upperAngle = 45 * DEGTORAD; - } else { - joint.lowerAngle = -45 * DEGTORAD; - joint.upperAngle = -40 * DEGTORAD; - } - - b2JointId joint_id = b2CreateRevoluteJoint(world_id, &joint); - - legs[i] = (Entity){ - .extent = leg_extent, - .bodyId = leg_id, - }; - } - */ - - diff --git a/pufferlib/ocean/rocket_lander/rocket_lander.h b/pufferlib/ocean/rocket_lander/rocket_lander.h deleted file mode 100644 index 26cedc1cfa..0000000000 --- a/pufferlib/ocean/rocket_lander/rocket_lander.h +++ /dev/null @@ -1,479 +0,0 @@ -#include -#include -#include -#include - -#include "raylib.h" -#include "box2d/box2d.h" - -// This shows how to use Box2D v3 with raylib. -// It also show how to use Box2D with pixel units. -// -#define LOG_BUFFER_SIZE 1024 - -typedef struct Log Log; -struct Log { - float episode_return; - float episode_length; - float score; -}; - -typedef struct LogBuffer LogBuffer; -struct LogBuffer { - Log* logs; - int length; - int idx; -}; - -LogBuffer* allocate_logbuffer(int size) { - LogBuffer* logs = (LogBuffer*)calloc(1, sizeof(LogBuffer)); - logs->logs = (Log*)calloc(size, sizeof(Log)); - logs->length = size; - logs->idx = 0; - return logs; -} - -void free_logbuffer(LogBuffer* buffer) { - free(buffer->logs); - free(buffer); -} - -void add_log(LogBuffer* logs, Log* log) { - if (logs->idx == logs->length) { - return; - } - logs->logs[logs->idx] = *log; - logs->idx += 1; - //printf("Log: %f, %f, %f\n", log->episode_return, log->episode_length, log->score); -} - -Log aggregate_and_clear(LogBuffer* logs) { - Log log = {0}; - if (logs->idx == 0) { - return log; - } - for (int i = 0; i < logs->idx; i++) { - log.episode_return += logs->logs[i].episode_return; - log.episode_length += logs->logs[i].episode_length; - log.score += logs->logs[i].score; - } - log.episode_return /= logs->idx; - log.episode_length /= logs->idx; - log.score /= logs->idx; - logs->idx = 0; - return log; -} - -typedef struct Entity -{ - b2BodyId bodyId; - b2Vec2 extent; -} Entity; - -#define GROUND_COUNT 14 -#define BOX_COUNT 10 - -const float SCALE = 30; -const float VIEWPORT_W = 1000; -const float VIEWPORT_H = 800; -const float GRAVITY = 9.8f; -const float W = VIEWPORT_W / SCALE; -const float H = VIEWPORT_H / SCALE; - -const float BARGE_FRICTION = 2; -const float BARGE_HEIGHT = 10; -const float BARGE_WIDTH = 100; - -const float LANDER_WIDTH = 20; -const float LANDER_HEIGHT = 227; - -const float LEG_AWAY = 20; -const float LEG_DOWN = 0.3; -const float LEG_W = 30; -const float LEG_H = 10*LANDER_HEIGHT / 8; -const float LEG_SPRING_TORQUE = LANDER_HEIGHT / 2; - -const float INITIAL_Y = 500; - - -const float PX_PER_METER = 1.0f; -const float DEGTORAD = PI / 180.0f; - -const float THRUST_SCALE = 1000000; -const float SIDE_THRUST_SCALE = 1000000; - -void DrawEntity(const Entity* entity, Color color) -{ - // The boxes were created centered on the bodies, but raylib draws textures starting at the top left corner. - // b2Body_GetWorldPoint gets the top left corner of the box accounting for rotation. - b2Vec2 p = b2Body_GetWorldPoint(entity->bodyId, (b2Vec2){0, 0}); - float width = 2*entity->extent.x; - float height = 2*entity->extent.y; - - b2Rot rotation = b2Body_GetRotation(entity->bodyId); - float radians = b2Rot_GetAngle(rotation); - float degrees = radians / DEGTORAD; - - //b2Rot rotation = b2Body_GetRotation(entity->bodyId); - //float radians = b2Rot_GetAngle(rotation); - //printf("\t: x: %f, y: %f, w: %f, h: %f, deg: %f\n", p.x, p.y, width, height, degrees); - - Rectangle rec = (Rectangle){ - PX_PER_METER*p.x, - -PX_PER_METER*p.y, - PX_PER_METER*width, - PX_PER_METER*height, - }; - DrawRectanglePro(rec, (Vector2){rec.width/2, rec.height/2}, -degrees, color); - //DrawTextureEx(entity->texture, ps, RAD2DEG * radians, 1.0f, WHITE); - - // I used these circles to ensure the coordinates are correct - //DrawCircleV(ps, 5.0f, BLACK); - //p = b2Body_GetWorldPoint(entity->bodyId, (b2Vec2){0.0f, 0.0f}); - //ps = (Vector2){ p.x, p.y }; - //DrawCircleV(ps, 5.0f, BLUE); - //p = b2Body_GetWorldPoint(entity->bodyId, (b2Vec2){ entity->extent.x, entity->extent.y }); - //ps = (Vector2){ p.x, p.y }; - //DrawCircleV(ps, 5.0f, RED); -} - - -typedef struct Lander Lander; -struct Lander { - float* observations; - float* actions; - float* reward; - unsigned char* terminal; - unsigned char* truncation; - LogBuffer* log_buffer; - Log log; - int tick; - b2WorldId world_id; - b2BodyId barge_id; - b2BodyId lander_id; - Entity barge; - Entity lander; -}; - -void init_lander(Lander* env) { - b2SetLengthUnitsPerMeter(PX_PER_METER); - - // 128 pixels per meter is a appropriate for this scene. The boxes are 128 pixels wide. - b2WorldDef worldDef = b2DefaultWorldDef(); - - // Realistic gravity is achieved by multiplying gravity by the length unit. - worldDef.gravity.y = -9.8f * PX_PER_METER; - b2WorldId world_id = b2CreateWorld(&worldDef); - env->world_id = world_id; - - b2BodyDef barge_body = b2DefaultBodyDef(); - barge_body.position = (b2Vec2){0, 0}; - barge_body.type = b2_staticBody; - b2BodyId barge_id = b2CreateBody(world_id, &barge_body); - env->barge_id = barge_id; - - b2Vec2 barge_extent = (b2Vec2){BARGE_WIDTH/2, BARGE_HEIGHT/2}; - b2Polygon barge_box = b2MakeBox(barge_extent.x, barge_extent.y); - b2ShapeDef barge_shape = b2DefaultShapeDef(); - b2CreatePolygonShape(barge_id, &barge_shape, &barge_box); - Entity barge = { - .extent = barge_extent, - .bodyId = barge_id, - }; - env->barge = barge; - - b2BodyDef lander_body = b2DefaultBodyDef(); - lander_body.position = (b2Vec2){0, INITIAL_Y}; - lander_body.type = b2_dynamicBody; - b2BodyId lander_id = b2CreateBody(world_id, &lander_body); - env->lander_id = lander_id; - - b2Vec2 lander_extent = (b2Vec2){LANDER_WIDTH / 2, LANDER_HEIGHT / 2}; - b2Polygon lander_box = b2MakeBox(lander_extent.x, lander_extent.y); - b2ShapeDef lander_shape = b2DefaultShapeDef(); - b2CreatePolygonShape(lander_id, &lander_shape, &lander_box); - Entity lander = { - .extent = lander_extent, - .bodyId = lander_id, - }; - env->lander = lander; -} - -void allocate_lander(Lander* env) { - env->observations = (float*)calloc(6, sizeof(float)); - env->actions = (float*)calloc(3, sizeof(float)); - env->reward = (float*)calloc(1, sizeof(float)); - env->terminal = (unsigned char*)calloc(1, sizeof(unsigned char)); - env->truncation = (unsigned char*)calloc(1, sizeof(unsigned char)); - env->log_buffer = allocate_logbuffer(LOG_BUFFER_SIZE); - init_lander(env); -} - -void compute_observations_and_reward(Lander* env, float prev_x, float prev_y) { - b2Transform transform = b2Body_GetTransform(env->lander_id); - b2Vec2 pos = transform.p; - float rot = b2Rot_GetAngle(transform.q); - b2Vec2 vel = b2Body_GetLinearVelocity(env->lander_id); - float ang_vel = b2Body_GetAngularVelocity(env->lander_id); - - float reward_x = (fabsf(prev_x) - fabsf(pos.x))/ 1000; - float reward_y = (fabsf(prev_y) - fabsf(pos.y))/ 1000; - //float reward_rot = -fabsf(rot)/ PI / 10; - //printf("Reward: %f, %f, %f\n", reward_x, reward_y, reward_rot); - float reward = reward_x + reward_y;// + reward_rot; - - reward = 0; - if (env->actions[0] == 0) { - reward = 1; - } - - env->reward[0] = reward; - env->log.episode_return += reward; - - env->observations[0] = pos.x / 500; - env->observations[1] = pos.y / 1200; - env->observations[2] = vel.x / 200; - env->observations[3] = vel.y / 200; - env->observations[4] = rot / PI / 10; - env->observations[5] = ang_vel / PI; -} - -void reset(Lander* env) { - env->log = (Log){0}; - env->tick = 0; - - b2Body_SetTransform( - env->lander_id, - (b2Vec2){0, INITIAL_Y}, - b2MakeRot(0) - ); - b2Body_SetLinearVelocity(env->lander_id, (b2Vec2){0, 0}); - b2Body_SetAngularVelocity(env->lander_id, 0.0f); - - b2Transform transform = b2Body_GetTransform(env->lander_id); - b2Vec2 pos = transform.p; - env->reward[0] = 0; - compute_observations_and_reward(env, pos.x, pos.y); - env->reward[0] = 0; -} - -void step(Lander* env) { - env->reward[0] = 0; - b2Transform transform = b2Body_GetTransform(env->lander_id); - b2Vec2 pos = transform.p; - printf("Pos x: %f, y: %f\n", pos.x, pos.y); - - b2Vec2 p_thrust = b2Body_GetWorldPoint(env->lander_id, - (b2Vec2){0, -LANDER_HEIGHT/2}); - b2Vec2 p_left = b2Body_GetWorldPoint(env->lander_id, - (b2Vec2){-LANDER_WIDTH/2, LANDER_HEIGHT/2}); - b2Vec2 p_right= b2Body_GetWorldPoint(env->lander_id, - (b2Vec2){LANDER_WIDTH/2, LANDER_HEIGHT/2}); - - b2Vec2 force = (b2Vec2){0, 0}; - b2Rot rotation = b2Body_GetRotation(env->lander_id); - float radians = b2Rot_GetAngle(rotation); - - - // Main thruster - float atn_thrust = THRUST_SCALE * env->actions[0]; - float rad_thrust = radians + 0.02*(float)rand()/RAND_MAX; - force = (b2Vec2){ - atn_thrust*sin(rad_thrust), - atn_thrust*cos(rad_thrust) - }; - b2Body_ApplyForce(env->lander_id, force, p_thrust, true); - - // Top left thruster - float atn_left = SIDE_THRUST_SCALE * env->actions[1]; - float rad_left = -radians + PI/2 + 0.02*(float)rand()/RAND_MAX; - force = (b2Vec2){ - atn_left*sin(rad_left), - atn_left*cos(rad_left) - }; - b2Body_ApplyForce(env->lander_id, force, p_left, true); - - // Top right thruster - float atn_right = SIDE_THRUST_SCALE * env->actions[2]; - float rad_right = -radians - PI/2 + 0.02*(float)rand()/RAND_MAX; - force = (b2Vec2){ - atn_right*sin(rad_right), - atn_right*cos(rad_right) - }; - b2Body_ApplyForce(env->lander_id, force, p_right, true); - - b2World_Step(env->world_id, 60.0f, 4); - - - transform = b2Body_GetTransform(env->lander_id); - bool do_reset = false; - if (transform.p.x < -500 || transform.p.x > 500 || transform.p.y > 1200) { - do_reset = true; - //env->reward[0] -= 1.0; - //env->log.episode_return -= 1.0; - } - if (transform.p.y < 120) { - do_reset = true; - printf("Transform y: %f\n", transform.p.y); - } - if (env->tick > 1000) { - do_reset = true; - printf("Tick: %i\n", env->tick); - } - if (do_reset) { - printf("Reset\n"); - env->log.episode_length = env->tick; - add_log(env->log_buffer, &env->log); - reset(env); - } - env->tick += 1; - - compute_observations_and_reward(env, pos.x, pos.y); - //printf("Reward: %f\n", env->reward[0]); - //env->reward[0] = -(atn_thrust + atn_left + atn_right) / 10000000; -} - -void free_lander(Lander* env) { - free_logbuffer(env->log_buffer); - b2DestroyWorld(env->world_id); -} - -typedef struct Client Client; -struct Client { - Camera2D camera; -}; - -Client* make_client(Lander* env) { - Client* client = (Client*)calloc(1, sizeof(Client)); - - int width = 1920, height = 1080; - InitWindow(width, height, "box2d-raylib"); - SetTargetFPS(60); - - client->camera = (Camera2D){ - .target = (Vector2){0, 0}, - .offset = (Vector2){width/2, 9*height/10}, - .rotation = 0.0f, - .zoom = 1.0f, - }; - return client; -} - -void close_client(Client* client) { - CloseWindow(); - free(client); -} - -void render(Client* client, Lander* env) { - if (IsKeyPressed(KEY_ESCAPE)) { - exit(0); - } - BeginDrawing(); - ClearBackground(DARKGRAY); - BeginMode2D(client->camera); - - env->actions[0] = 0; - env->actions[1] = 0; - env->actions[2] = 0; - if (IsKeyDown(KEY_W)) { - env->actions[0] = 1; - } - if (IsKeyDown(KEY_Q)) { - env->actions[1] = 1; - } - if (IsKeyDown(KEY_E)) { - env->actions[2] = 1; - } - - - /* - b2Rot rotation = b2Body_GetRotation(lander_id); - float radians = b2Rot_GetAngle(rotation); - float mag = 1000000; - - if (IsKeyDown(KEY_W)) { - float rad_thrust = radians + 0.02*(float)rand()/RAND_MAX; - b2Vec2 force = (b2Vec2){mag*sin(rad_thrust), mag*cos(rad_thrust)}; - b2Body_ApplyForce(lander_id, force, p_thrust, true); - DrawCircle(p_thrust.x, -p_thrust.y, 20, RED); - } - if (IsKeyDown(KEY_Q)) { - float rad_left = -radians + PI/2 + 0.02*(float)rand()/RAND_MAX; - if (rad_left > PI) { - rad_left -= 2*PI; - } - b2Vec2 force = (b2Vec2){mag*sin(rad_left), mag*cos(rad_left)}; - b2Body_ApplyForce(lander_id, force, p_left, true); - DrawCircle(p_left.x, -p_left.y, 20, RED); - } - if (IsKeyDown(KEY_E)) { - float rad_right = -radians - PI/2 + 0.02*(float)rand()/RAND_MAX; - b2Vec2 force = (b2Vec2){mag*sin(rad_right), mag*cos(rad_right)}; - b2Body_ApplyForce(lander_id, force, p_right, true); - DrawCircle(p_right.x, -p_right.y, 20, RED); - } - - - if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) { - Vector2 mousePos = GetScreenToWorld2D(GetMousePosition(), camera); - float x = mousePos.x; - float y = -mousePos.y; - b2Vec2 origin = (b2Vec2){x, y}; - b2Vec2 p = b2Body_GetWorldPoint(lander_id, - (b2Vec2){0, -LANDER_HEIGHT/2}); - float mag = 1000; - b2Vec2 force = (b2Vec2){ - mag * (p.x - origin.x), - mag * (p.y - origin.y), - }; - b2Body_ApplyForce(lander_id, force, p, true); - DrawLine(mousePos.x, mousePos.y, p.x, -p.y, RED); - } - - b2Transform transform = b2Body_GetTransform(lander_id); - printf("y: %f\n", transform.p.y); - if (transform.p.y < 120) { - reset(&env); - } - */ - - //DrawRectangle(0, 0, 100, 100, RED); - DrawEntity(&env->barge, RED); - DrawEntity(&env->lander, BLUE); - //DrawEntity(&legs[0], GREEN); - //DrawEntity(&legs[1], GREEN); - EndMode2D(); - EndDrawing(); -} - -void demo() { - Lander env = {0}; - allocate_lander(&env); - Client* client = make_client(&env); - - while (!WindowShouldClose()) { - step(&env); - render(client, &env); - } -} - -void test_render() { - InitWindow(1920, 1080, "box2d-raylib"); - SetTargetFPS(60); - - while (!WindowShouldClose()) { - BeginDrawing(); - ClearBackground(DARKGRAY); - - Rectangle rec = (Rectangle){500, 500, 200, 200}; - Vector2 origin = (Vector2){rec.width/2, rec.height/2}; - DrawRectanglePro(rec, origin, 45, RED); - - DrawCircle(500, 500, 30, BLUE); - - EndDrawing(); - } - -} - - diff --git a/pufferlib/ocean/rocket_lander/rocket_lander.py b/pufferlib/ocean/rocket_lander/rocket_lander.py deleted file mode 100644 index aee2f67a88..0000000000 --- a/pufferlib/ocean/rocket_lander/rocket_lander.py +++ /dev/null @@ -1,73 +0,0 @@ -'''High-perf Pong - -Inspired from https://gist.github.com/Yttrmin/18ecc3d2d68b407b4be1 -& https://jair.org/index.php/jair/article/view/10819/25823 -& https://www.youtube.com/watch?v=PSQt5KGv7Vk -''' - -import numpy as np -import gymnasium - -import pufferlib -from pufferlib.ocean.rocket_lander.cy_rocket_lander import CyRocketLander - -class RocketLander(pufferlib.PufferEnv): - def __init__(self, num_envs=1, render_mode=None, report_interval=32, buf=None): - self.single_observation_space = gymnasium.spaces.Box(low=0, high=1, - shape=(6,), dtype=np.float32) - self.single_action_space = gymnasium.spaces.Discrete(4) - self.render_mode = render_mode - self.num_agents = num_envs - self.report_interval = report_interval - - super().__init__(buf) - self.float_actions = np.zeros((num_envs, 3), dtype=np.float32) - self.c_envs = CyRocketLander(self.observations, self.float_actions, self.rewards, - self.terminals, self.truncations, num_envs) - - def reset(self, seed=None): - self.tick = 0 - self.c_envs.reset() - return self.observations, [] - - def step(self, actions): - self.float_actions[:, :] = 0 - self.float_actions[:, 0] = actions == 1 - self.float_actions[:, 1] = actions == 2 - self.float_actions[:, 2] = actions == 3 - self.c_envs.step() - - info = [] - if self.tick % self.report_interval == 0: - log = self.c_envs.log() - if log['episode_length'] > 0: - info.append(log) - - self.tick += 1 - return (self.observations, self.rewards, - self.terminals, self.truncations, info) - - def render(self): - self.c_envs.render() - - def close(self): - self.c_envs.close() - -def test_performance(timeout=10, atn_cache=1024): - env = RocketLander(num_envs=1000) - env.reset() - tick = 0 - - actions = np.random.randint(0, 2, (atn_cache, env.num_envs)) - - import time - start = time.time() - while time.time() - start < timeout: - atn = actions[tick % atn_cache] - env.step(atn) - tick += 1 - - print(f'SPS: %f', env.num_envs * tick / (time.time() - start)) - -if __name__ == '__main__': - test_performance() diff --git a/pufferlib/ocean/rware/binding.c b/pufferlib/ocean/rware/binding.c deleted file mode 100644 index 3cf1d5d147..0000000000 --- a/pufferlib/ocean/rware/binding.c +++ /dev/null @@ -1,24 +0,0 @@ -#include "rware.h" - -#define Env CRware -#include "../env_binding.h" - -static int my_init(Env* env, PyObject* args, PyObject* kwargs) { - env->width = unpack(kwargs, "width"); - env->height = unpack(kwargs, "height"); - env->map_choice = unpack(kwargs, "map_choice"); - env->num_agents = unpack(kwargs, "num_agents"); - env->num_requested_shelves = unpack(kwargs, "num_requested_shelves"); - env->grid_square_size = unpack(kwargs, "grid_square_size"); - env->human_agent_idx = unpack(kwargs, "human_agent_idx"); - init(env); - return 0; -} - -static int my_log(PyObject* dict, Log* log) { - assign_to_dict(dict, "perf", log->perf); - assign_to_dict(dict, "score", log->score); - assign_to_dict(dict, "episode_return", log->episode_return); - assign_to_dict(dict, "episode_length", log->episode_length); - return 0; -} diff --git a/pufferlib/ocean/rware/rware.py b/pufferlib/ocean/rware/rware.py deleted file mode 100644 index 25fb181169..0000000000 --- a/pufferlib/ocean/rware/rware.py +++ /dev/null @@ -1,102 +0,0 @@ -'''High-perf Pong - -Inspired from https://gist.github.com/Yttrmin/18ecc3d2d68b407b4be1 -& https://jair.org/index.php/jair/article/view/10819/25823 -& https://www.youtube.com/watch?v=PSQt5KGv7Vk -''' - -import numpy as np -import gymnasium - -import pufferlib -from pufferlib.ocean.rware import binding - -PLAYER_OBS_N = 27 - -class Rware(pufferlib.PufferEnv): - def __init__(self, num_envs=1, render_mode=None, report_interval=1, - width=1280, height=640, - num_agents=4, - map_choice=1, - num_requested_shelves=4, - grid_square_size=64, - human_agent_idx=0, - reward_type=1, - buf = None, seed=0): - - # env - self.num_agents = num_envs*num_agents - self.render_mode = render_mode - self.report_interval = report_interval - - self.num_obs = 27 - self.single_observation_space = gymnasium.spaces.Box(low=0, high=1, - shape=(self.num_obs,), dtype=np.float32) - self.single_action_space = gymnasium.spaces.Discrete(5) - - super().__init__(buf=buf) - c_envs = [] - for i in range(num_envs): - env_id = binding.env_init( - self.observations[i*num_agents:(i+1)*num_agents], - self.actions[i*num_agents:(i+1)*num_agents], - self.rewards[i*num_agents:(i+1)*num_agents], - self.terminals[i*num_agents:(i+1)*num_agents], - self.truncations[i*num_agents:(i+1)*num_agents], - i + seed * num_envs, - width=width, - height=height, - map_choice=map_choice, - num_agents=num_agents, - num_requested_shelves=num_requested_shelves, - grid_square_size=grid_square_size, - human_agent_idx=human_agent_idx - ) - c_envs.append(env_id) - - self.c_envs = binding.vectorize(*c_envs) - - def reset(self, seed=0): - binding.vec_reset(self.c_envs, seed) - self.tick = 0 - return self.observations, [] - - def step(self, actions): - self.actions[:] = actions - binding.vec_step(self.c_envs) - self.tick += 1 - - info = [] - if self.tick % self.report_interval == 0: - log = binding.vec_log(self.c_envs) - if log: - info.append(log) - - return (self.observations, self.rewards, - self.terminals, self.truncations, info) - - def render(self): - binding.vec_render(self.c_envs, 0) - - def close(self): - binding.vec_close(self.c_envs) - -def test_performance(timeout=10, atn_cache=1024): - num_envs=1000; - env = MyRware(num_envs=num_envs) - env.reset() - tick = 0 - - actions = np.random.randint(0, env.single_action_space.n, (atn_cache, 5*num_envs)) - - import time - start = time.time() - while time.time() - start < timeout: - atn = actions[tick % atn_cache] - env.step(atn) - tick += 1 - - sps = num_envs * tick / (time.time() - start) - print(f'SPS: {sps:,}') -if __name__ == '__main__': - test_performance() diff --git a/pufferlib/ocean/sanity.py b/pufferlib/ocean/sanity.py deleted file mode 100644 index a90d1f0942..0000000000 --- a/pufferlib/ocean/sanity.py +++ /dev/null @@ -1,725 +0,0 @@ -import gymnasium -import pettingzoo -import numpy as np -import random -import time - - -class Bandit(gymnasium.Env): - '''Pufferlib Bandit environment - - Simulates a classic multiarmed bandit problem. - - Observation space: Box(0, 1, (1,)). The observation is always 1. - Action space: Discrete(num_actions). Which arm to pull. - Args: - num_actions: The number of bandit arms - reward_scale: The scale of the reward - reward_noise: The standard deviation of the reward signal - hard_fixed_seed: All instances of the environment should share the same seed. - ''' - def __init__(self, num_actions=4, reward_scale=1, - reward_noise=0, hard_fixed_seed=42): - self.num_actions = num_actions - self.reward_scale = reward_scale - self.reward_noise = reward_noise - self.hard_fixed_seed = hard_fixed_seed - self.observation=np.ones(1, dtype=np.float32) - self.observation_space=gymnasium.spaces.Box( - low=-1, high=1, shape=(1,)) - self.action_space=gymnasium.spaces.Discrete(num_actions) - self.render_mode = 'ansi' - - def reset(self, seed=None): - # Bandit problem requires a single fixed seed - # for all environments - seed = self.hard_fixed_seed - - if seed is not None: - random.seed(seed) - np.random.seed(seed) - - self.solution_idx = np.random.randint(0, self.num_actions) - - return self.observation, {} - - def step(self, action): - assert action == int(action) and action >= 0 and action < self.num_actions - - correct = False - reward = 0 - if action == self.solution_idx: - correct = True - reward = 1 - - reward_noise = 0 - if self.reward_noise != 0: - reward_noise = np.random.randn() * self.reward_scale - - # Couples reward noise to scale - reward = (reward + reward_noise) * self.reward_scale - - return self.observation, reward, True, False, {'score': correct} - -class Memory(gymnasium.Env): - '''Pufferlib Memory environment - - Repeat the observed sequence after a delay. It is randomly generated upon every reset. This is a test of memory length and capacity. It starts requiring credit assignment if you make the sequence too long. - - The sequence is presented one digit at a time, followed by a string of 0. The agent should output 0s for the first mem_length + mem_delay steps, then output the sequence. - - Observation space: Box(0, 1, (1,)). The current digit. - Action space: Discrete(2). Your guess for the next digit. - - Args: - mem_length: The length of the sequence - mem_delay: The number of 0s between the sequence and the agent's response - ''' - def __init__(self, mem_length=1, mem_delay=0): - self.mem_length = mem_length - self.mem_delay = mem_delay - self.horizon = 2 * mem_length + mem_delay - self.observation_space=gymnasium.spaces.Box( - low=-1, high=1, shape=(1,)) - self.action_space=gymnasium.spaces.Discrete(2) - self.render_mode = 'ansi' - - def reset(self, seed=None): - if seed is not None: - random.seed(seed) - np.random.seed(seed) - - self.solution = np.random.randint(0, 2, size=self.horizon).astype(np.float32) - self.solution[-(self.mem_length + self.mem_delay):] = -1 - self.submission = np.zeros(self.horizon) - 1 - self.tick = 1 - - return self.solution[0], {} - - def step(self, action): - assert self.tick < self.horizon - assert action in (0, 1) - - ob = reward = 0.0 - - if self.tick < self.mem_length: - ob = self.solution[self.tick] - reward = float(action == 0) - - if self.tick >= self.mem_length + self.mem_delay: - idx = self.tick - self.mem_length - self.mem_delay - sol = self.solution[idx] - reward = float(action == sol) - self.submission[self.tick] = action - - self.tick += 1 - terminal = self.tick == self.horizon - - info = {} - if terminal: - info['score'] = np.all( - self.solution[:self.mem_length] == self.submission[-self.mem_length:]) - - return ob, reward, terminal, False, info - - def render(self): - def _render(val): - if val == 1: - c = 94 - elif val == 0: - c = 91 - else: - c = 90 - return f'\033[{c}m██\033[0m' - - chars = [] - for val in self.solution: - c = _render(val) - chars.append(c) - chars.append(' Solution\n') - - for val in self.submission: - c = _render(val) - chars.append(c) - chars.append(' Prediction\n') - - return ''.join(chars) - - -class Multiagent(pettingzoo.ParallelEnv): - '''Pufferlib Multiagent environment - - Agent 1 must pick action 0 and Agent 2 must pick action 1 - - Observation space: Box(0, 1, (1,)). 0 for Agent 1 and 1 for Agent 2 - Action space: Discrete(2). Which action to take. - ''' - def __init__(self): - self.observation = { - 1: np.zeros(1, dtype=np.float32), - 2: np.ones(1, dtype=np.float32), - } - self.terminal = { - 1: True, - 2: True, - } - self.truncated = { - 1: False, - 2: False, - } - self.possible_agents=[1, 2] - self.agents=[1, 2] - self.render_mode = 'ansi' - - def observation_space(self, agent): - return gymnasium.spaces.Box( - low=0, high=1, shape=(1,)) - - def action_space(self, agent): - return gymnasium.spaces.Discrete(2) - - def reset(self, seed=None): - # Reallocating is faster than zeroing - self.view=np.zeros((2, 5), dtype=np.float32) - return self.observation, {} - - def step(self, action): - reward = {} - assert 1 in action and action[1] in (0, 1) - if action[1] == 0: - self.view[0, 2] = 1 - reward[1] = 1 - else: - self.view[0, 0] = 1 - reward[1] = 0 - - assert 2 in action and action[2] in (0, 1) - if action[2] == 1: - self.view[1, 2] = 1 - reward[2] = 1 - else: - self.view[1, 4] = 1 - reward[2] = 0 - - info = { - 1: {'score': reward[1]}, - 2: {'score': reward[2]}, - } - return self.observation, reward, self.terminal, self.truncated, info - - def render(self): - def _render(val): - if val == 1: - c = 94 - elif val == 0: - c = 90 - else: - c = 90 - return f'\033[{c}m██\033[0m' - - chars = [] - for row in self.view: - for val in row: - c = _render(val) - chars.append(c) - chars.append('\n') - return ''.join(chars) - -class Password(gymnasium.Env): - '''Pufferlib Password environment - - Guess the password, which is a static binary string. Your policy has to - not determinize before it happens to get the reward, and it also has to - latch onto the reward within a few instances of getting it. - - Observation space: Box(0, 1, (password_length,)). A binary vector containing your guesses so far, so that the environment will be solvable without memory. - Action space: Discrete(2). Your guess for the next digit. - - Args: - password_length: The number of binary digits in the password. - hard_fixed_seed: A fixed seed for the environment. It should be the same for all instances. This environment does not make sense when randomly generated. - ''' - - def __init__(self, password_length=5, hard_fixed_seed=42): - self.password_length = password_length - self.hard_fixed_seed = hard_fixed_seed - self.observation_space=gymnasium.spaces.Box( - low=-1, high=1, shape=(password_length,)) - self.action_space=gymnasium.spaces.Discrete(2) - self.render_mode = 'ansi' - - def reset(self, seed=None): - # Bandit problem requires a single fixed seed - # for all environments - seed = self.hard_fixed_seed - if seed is not None: - random.seed(seed) - np.random.seed(seed) - - self.observation = np.zeros(self.password_length, dtype=np.float32) - 1 - self.solution = np.random.randint( - 0, 2, size=self.password_length).astype(np.float32) - self.tick = 0 - - return self.observation, {} - - def step(self, action): - assert self.tick < self.password_length - assert action in (0, 1) - - self.observation[self.tick] = action - self.tick += 1 - - reward = 0 - terminal = self.tick == self.password_length - info = {} - - if terminal: - reward = float(np.all(self.observation == self.solution)) - info['score'] = reward - - return self.observation, reward, terminal, False, info - - def render(self): - def _render(val): - if val == 1: - c = 94 - elif val == 0: - c = 91 - else: - c = 90 - return f'\033[{c}m██\033[0m' - - chars = [] - for val in self.solution: - c = _render(val) - chars.append(c) - chars.append(' Solution\n') - - for val in self.observation: - c = _render(val) - chars.append(c) - chars.append(' Prediction\n') - - return ''.join(chars) - -class Performance(gymnasium.Env): - def __init__(self, delay_mean=0, delay_std=0, bandwidth=1): - np.random.seed(time.time_ns() % 2**32) - - self.observation_space = gymnasium.spaces.Box( - low=-2**20, high=2**20, - shape=(bandwidth,), dtype=np.float32 - ) - self.action_space = gymnasium.spaces.Discrete(2) - self.observation = self.observation_space.sample() - self.render_mode = 'ansi' - - def reset(self, seed=None): - return self.observation, {} - - def step(self, action): - start = time.process_time() - idx = 0 - target_time = self.delay_mean + self.delay_std*np.random.randn() - while time.process_time() - start < target_time: - idx += 1 - - return self.observation, 0, False, False, {} - -class PerformanceEmpiric(gymnasium.Env): - def __init__(self, count_n=0, count_std=0, bandwidth=1): - np.random.seed(time.time_ns() % 2**32) - - self.observation_space = gymnasium.spaces.Box( - low=-2**20, high=2**20, - shape=(bandwidth,), dtype=np.float32 - ) - self.action_space = gymnasium.spaces.Discrete(2) - self.observation = self.observation_space.sample() - self.count_n = count_n - self.count_std = count_std - self.bandwidth = bandwidth - self.render_mode = 'ansi' - - def reset(self, seed=None): - return self.observation, {} - - def step(self, action): - idx = 0 - target = self.count_n + self.count_std * np.random.randn() - while idx < target: - idx += 1 - - return self.observation, 0, False, False, {} - -class Spaces(gymnasium.Env): - '''Pufferlib Spaces environment - - A simple environment with hierarchical observation and action spaces - - The image action should be 1 if the sum of the image is positive, 0 otherwise - The flat action should be 1 if the sum of the flat obs is positive, 0 otherwise - - 0.5 reward is given for each correct action - - Does not provide rendering - ''' - def __init__(self): - self.observation_space = gymnasium.spaces.Dict({ - 'image': gymnasium.spaces.Box( - low=0, high=1, shape=(5, 5), dtype=np.float32), - 'flat': gymnasium.spaces.Box( - low=-1, high=1, shape=(5,), dtype=np.int8), - }) - self.action_space = gymnasium.spaces.Dict({ - 'image': gymnasium.spaces.Discrete(2), - 'flat': gymnasium.spaces.Discrete(2), - }) - self.render_mode = 'ansi' - - def reset(self, seed=None): - self.observation = { - 'image': np.random.rand(5, 5).astype(np.float32), - 'flat': np.random.randint(-1, 2, (5,), dtype=np.int8), - } - self.image_sign = np.sum(self.observation['image']) > 0 - self.flat_sign = np.sum(self.observation['flat']) > 0 - - return self.observation, {} - - def step(self, action): - assert isinstance(action, dict) - assert 'image' in action and action['image'] in (0, 1) - assert 'flat' in action and action['flat'] in (0, 1) - - reward = 0 - if self.image_sign == action['image']: - reward += 0.5 - - if self.flat_sign == action['flat']: - reward += 0.5 - - info = dict(score=reward) - return self.observation, reward, True, False, info - -class Squared(gymnasium.Env): - '''Pufferlib Squared environment - - Agent starts at the center of a square grid. - Targets are placed on the perimeter of the grid. - Reward is 1 minus the L-inf distance to the closest target. - This means that reward varies from -1 to 1. - Reward is not given for targets that have already been hit. - - Observation space: Box(-1, 1, (grid_size, grid_size)). The map. - Action space: Discrete(8). Which direction to move. - - Args: - distance_to_target: The distance from the center to the closest target. - num_targets: The number of targets to randomly generate. - - ''' - - MOVES = [(0, -1), (0, 1), (-1, 0), (1, 0), (1, -1), (-1, -1), (1, 1), (-1, 1)] - - def __init__(self, - distance_to_target=1, - num_targets=-1, - ): - grid_size = 2 * distance_to_target + 1 - if num_targets == -1: - num_targets = 4 * distance_to_target - - self.distance_to_target = distance_to_target - self.possible_targets = self._all_possible_targets(grid_size) - self.num_targets = num_targets - self.grid_size = grid_size - self.max_ticks = num_targets * distance_to_target - self.observation_space = gymnasium.spaces.Box( - low=-1, high=1, shape=(grid_size, grid_size)) - self.action_space = gymnasium.spaces.Discrete(8) - self.render_mode = 'ansi' - - def _all_possible_targets(self, grid_size): - return [(x, y) for x in range(grid_size) for y in range(grid_size) - if x == 0 or y == 0 or x == grid_size - 1 or y == grid_size - 1] - - def reset(self, seed=None): - if seed is not None: - random.seed(seed) - np.random.seed(seed) - - # Allocating a new grid is faster than resetting an old one - self.grid = np.zeros((self.grid_size, self.grid_size), dtype=np.float32) - self.grid[self.distance_to_target, self.distance_to_target] = -1 - self.agent_pos = (self.distance_to_target, self.distance_to_target) - self.tick = 0 - - self.targets = random.sample(self.possible_targets, self.num_targets) - for x, y in self.targets: - self.grid[x, y] = 1 - - return self.grid, {} - - def step(self, action): - x, y = self.agent_pos - self.grid[x, y] = 0 - - dx, dy = Squared.MOVES[action] - x += dx - y += dy - - min_dist = min([max(abs(x-tx), abs(y-ty)) for tx, ty in self.targets]) - # This reward function will return 0.46 average reward for an unsuccessful - # episode with distance_to_target=4 and num_targets=1 (0.5 for solve) - # It looks reasonable but is not very discriminative - reward = 1 - min_dist / self.distance_to_target - - # This reward function will return 1 when the agent moves in the right direction - # (plus an adjustment for the 0 reset reward) to average 1 for success - # It is not much better than the previous one. - #reward = state.distance_to_target - min_dist - state.tick + 1/state.max_ticks - - # This function will return 0, 0.2, 0.4, ... 1 for successful episodes (n=5) - # And will drop rewards to 0 or less as soon as an error is made - # Somewhat smoother but actually worse than the previous ones - # reward = (state.distance_to_target - min_dist - state.tick) / (state.max_ticks - state.tick) - - - # This one nicely tracks the task completed metric but does not optimize well - #if state.distance_to_target - min_dist - state.tick == 1: - # reward = 1 - #else: - # reward = -state.tick - - if (x, y) in self.targets: - self.targets.remove((x, y)) - #state.grid[x, y] = 0 - - dist_from_origin = max(abs(x-self.distance_to_target), abs(y-self.distance_to_target)) - if dist_from_origin >= self.distance_to_target: - self.agent_pos = self.distance_to_target, self.distance_to_target - else: - self.agent_pos = x, y - - self.grid[self.agent_pos] = -1 - self.tick += 1 - - done = self.tick >= self.max_ticks - score = (self.num_targets - len(self.targets)) / self.num_targets - info = {'score': score} if done else {} - - return self.grid, reward, done, False, info - - def render(self): - chars = [] - for row in self.grid: - for val in row: - if val == 1: - color = 94 - elif val == -1: - color = 91 - else: - color = 90 - chars.append(f'\033[{color}m██\033[0m') - chars.append('\n') - return ''.join(chars) - -class Stochastic(gymnasium.Env): - '''Pufferlib Stochastic environment - - The optimal policy is to play action 0 < p % of the time and action 1 < (1 - p) % - This is a test of whether your algorithm can learn a nontrivial stochastic policy. - Do not use a policy with memory, as that will trivialize the problem. - - Observation space: Box(0, 1, (1,)). The observation is always 0. - Action space: Discrete(2). Select action 0 or action 1. - - Args: - p: The optimal probability for action 0 - horizon: How often the environment should reset - ''' - def __init__(self, p=0.75, horizon=1000): - self.p = p - self.horizon = horizon - self.observation_space = gymnasium.spaces.Box( - low=0, high=1, shape=(1,)) - self.action_space = gymnasium.spaces.Discrete(2) - self.render_mode = 'ansi' - - def reset(self, seed=None): - if seed is not None: - random.seed(seed) - np.random.seed(seed) - - self.tick = 0 - self.count = 0 - self.action = 0 - - return np.zeros(1, dtype=np.float32), {} - - def step(self, action): - assert self.tick < self.horizon - assert action in (0, 1) - - self.tick += 1 - self.count += action == 0 - self.action = action - - terminal = self.tick == self.horizon - atn0_frac = self.count / self.tick - proximity_to_p = 1 - (self.p - atn0_frac)**2 - - reward = proximity_to_p if ( - (action == 0 and atn0_frac < self.p) or - (action == 1 and atn0_frac >= self.p)) else 0 - - info = {} - if terminal: - info['score'] = proximity_to_p - - return np.zeros(1, dtype=np.float32), reward, terminal, False, info - - def render(self): - def _render(val): - if val == 1: - c = 94 - elif val == 0: - c = 91 - else: - c = 90 - return f'\033[{c}m██\033[0m' - chars = [] - if self.tick == 0: - solution = 0 - else: - solution = 0 if self.count / self.tick < self.p else 1 - chars.append(_render(solution)) - chars.append(' Solution\n') - - chars.append(_render(self.action)) - chars.append(' Prediction\n') - - return ''.join(chars) - -class Continuous(gymnasium.Env): - def __init__(self, discretize=False): - self.observation_space=gymnasium.spaces.Box( - low=-1, high=1, shape=(6,)) - self.discretize = discretize - if discretize: - self.action_space=gymnasium.spaces.Discrete(4) - else: - self.action_space=gymnasium.spaces.Box( - low=-1, high=1, shape=(2,)) - - self.render_mode = 'human' - self.client = None - - def reset(self, seed=None, options=None): - # pos_x, pos_y, vel_x, vel_y, target_x, target_y - self.state = 2*np.random.rand(6)-1 - self.state[2:4] = 0 - self.tick = 0 - - return self.state, {} - - def step(self, action): - if self.discretize: - accel_x, accel_y = 0, 0 - if action == 0: - accel_x = -0.1 - elif action == 1: - accel_x = 0.1 - elif action == 2: - accel_y = -0.1 - elif action == 3: - accel_y = 0.1 - else: - accel_x, accel_y = 0.1*action - - self.state[2] += accel_x - self.state[3] += accel_y - self.state[0] += self.state[2] - self.state[1] += self.state[3] - - pos_x, pos_y, vel_x, vel_y, target_x, target_y = self.state - - if pos_x < -1 or pos_x > 1 or pos_y < -1 or pos_y > 1: - return self.state, -1, True, False, {'score': 0} - - dist = np.sqrt((pos_x - target_x)**2 + (pos_y - target_y)**2) - reward = 0.02 * (1 - dist) - - self.tick += 1 - done = dist < 0.1 - truncated = self.tick >= 100 - - # TODO: GAE implementation making agent not hit target - # without a big reward here - info = {} - if done: - reward = 5.0 - info = {'score': 1} - elif truncated: - reward = 0.0 - info = {'score': 0} - - return self.state, reward, done, truncated, info - - def render(self): - if self.client is None: - self.client = RaylibClient() - - pos_x, pos_y, vel_x, vel_y, target_x, target_y = self.state - frame, atn = self.client.render(pos_x, pos_y, target_x, target_y) - return frame - -class RaylibClient: - def __init__(self, width=1080, height=720, size=20): - self.width = width - self.height = height - self.size = size - - from raylib import rl - rl.InitWindow(width, height, - "PufferLib Simple Continuous".encode()) - rl.SetTargetFPS(10) - self.rl = rl - - from cffi import FFI - self.ffi = FFI() - - def _cdata_to_numpy(self): - image = self.rl.LoadImageFromScreen() - width, height, channels = image.width, image.height, 4 - cdata = self.ffi.buffer(image.data, width*height*channels) - return np.frombuffer(cdata, dtype=np.uint8 - ).reshape((height, width, channels))[:, :, :3] - - def render(self, pos_x, pos_y, target_x, target_y): - rl = self.rl - action = None - if rl.IsKeyDown(rl.KEY_UP) or rl.IsKeyDown(rl.KEY_W): - action = 0 - elif rl.IsKeyDown(rl.KEY_DOWN) or rl.IsKeyDown(rl.KEY_S): - action = 1 - elif rl.IsKeyDown(rl.KEY_LEFT) or rl.IsKeyDown(rl.KEY_A): - action = 2 - elif rl.IsKeyDown(rl.KEY_RIGHT) or rl.IsKeyDown(rl.KEY_D): - action = 3 - - rl.BeginDrawing() - rl.ClearBackground([6, 24, 24, 255]) - - pos_x = int((0.5+pos_x/2) * self.width) - pos_y = int((0.5+pos_y/2) * self.height) - target_x = int((0.5+target_x/2) * self.width) - target_y = int((0.5+target_y/2) * self.height) - - rl.DrawCircle(pos_x, pos_y, self.size, [255, 0, 0, 255]) - rl.DrawCircle(target_x, target_y, self.size, [0, 0, 255, 255]) - - rl.EndDrawing() - return self._cdata_to_numpy(), action diff --git a/pufferlib/ocean/shared_pool/shared_pool.py b/pufferlib/ocean/shared_pool/shared_pool.py deleted file mode 100644 index 885b44366e..0000000000 --- a/pufferlib/ocean/shared_pool/shared_pool.py +++ /dev/null @@ -1,109 +0,0 @@ -import gymnasium -import numpy as np - -import pufferlib -from pufferlib.ocean.shared_pool import binding - -class PyCPR(pufferlib.PufferEnv): - def __init__(self, - num_envs=1, - widths=[32], - heights=[32], - num_agents=[8], - vision=3, - reward_food=1.0, - interactive_food_reward=5.0, - reward_move=-0.01, - food_base_spawn_rate=2e-3, - report_interval=1, - render_mode=None, - buf=None, - seed=0, - ): - widths = num_envs*widths - heights = num_envs*heights - num_agents = num_envs*num_agents - - self.single_observation_space = gymnasium.spaces.Box(low=0, high=255, shape=((2*vision+1)*(2*vision+1),), dtype=np.uint8) - self.single_action_space = gymnasium.spaces.Discrete(5) - self.render_mode = render_mode - self.num_agents = sum(num_agents) - - self.tick = 0 - self.report_interval = report_interval - - super().__init__(buf) - c_envs = [] - for i in range(num_envs): - n = num_agents[i] - env_id = binding.env_init( - self.observations[i*n:(i+1)*n], - self.actions[i*n:(i+1)*n], - self.rewards[i*n:(i+1)*n], - self.terminals[i*n:(i+1)*n], - self.truncations[i*n:(i+1)*n], - i + seed * num_envs, - width=widths[i], - height=heights[i], - num_agents=num_agents[i], - vision=vision, - reward_food=reward_food, - interactive_food_reward=interactive_food_reward, - reward_move=reward_move, - food_base_spawn_rate=food_base_spawn_rate, - ) - c_envs.append(env_id) - - self.c_envs = binding.vectorize(*c_envs) - - def reset(self, seed=None): - self.tick = 0 - binding.vec_reset(self.c_envs, seed) - return self.observations, [] - - def step(self, actions): - self.actions[:] = actions - binding.vec_step(self.c_envs) - self.tick += 1 - - info = [] - if self.tick % self.report_interval == 0: - log = binding.vec_log(self.c_envs) - if log: - info.append(log) - - return (self.observations, self.rewards, self.terminals, self.truncations, info) - - def render(self): - binding.vec_render(self.c_envs, 0) - - def close(self): - binding.vec_close(self.c_envs) - -if __name__ == "__main__": - env = PyCPR() - env.reset() - tick = 0 - timeout=30 - - tot_agents = env.num_agents - actions = np.random.randint(0,5,(1024,tot_agents)) - - import time - start = time.time() - # while time.time() - start < timeout: - while tick < 500: - atns = actions[tick % 1024] - env.step(atns) - if -1 in env.rewards: - breakpoint() - # env.render() - tick += 1 - - print(f'SPS: {int(tot_agents * tick / (time.time() - start)):_}') - - env.close() - - - - diff --git a/pufferlib/ocean/slimevolley/binding.c b/pufferlib/ocean/slimevolley/binding.c deleted file mode 100644 index 3d294935e8..0000000000 --- a/pufferlib/ocean/slimevolley/binding.c +++ /dev/null @@ -1,18 +0,0 @@ -#include "slimevolley.h" - -#define Env SlimeVolley -#include "../env_binding.h" - -static int my_init(Env* env, PyObject* args, PyObject* kwargs) { - env->num_agents = unpack(kwargs, "num_agents"); - init(env); - return 0; -} - -static int my_log(PyObject* dict, Log* log) { - assign_to_dict(dict, "perf", log->perf); - assign_to_dict(dict, "score", log->score); - assign_to_dict(dict, "episode_return", log->episode_return); - assign_to_dict(dict, "episode_length", log->episode_length); - return 0; -} diff --git a/pufferlib/ocean/slimevolley/eval.py b/pufferlib/ocean/slimevolley/eval.py deleted file mode 100644 index 081b2c346b..0000000000 --- a/pufferlib/ocean/slimevolley/eval.py +++ /dev/null @@ -1,77 +0,0 @@ -import gymnasium -import numpy as np - -from pufferlib.ocean.slimevolley import binding -import pufferlib -from pufferlib.ocean.torch import Policy -import torch - -class SlimeVolley(pufferlib.PufferEnv): - def __init__(self, num_envs=1, render_mode=None, log_interval=128, buf=None, seed=0, - num_agents=1): - assert num_agents in {1, 2}, "num_agents must be 1 or 2" - num_obs = 12 - self.single_observation_space = gymnasium.spaces.Box(low=0, high=1, - shape=(num_obs,), dtype=np.float32) - self.single_action_space = gymnasium.spaces.MultiDiscrete([2, 2, 2]) - - self.render_mode = render_mode - self.num_agents = num_envs * num_agents - self.log_interval = log_interval - - super().__init__(buf) - c_envs = [] - for i in range(num_envs): - c_env = binding.env_init( - self.observations[i*num_agents:(i+1)*num_agents], - self.actions[i*num_agents:(i+1)*num_agents], - self.rewards[i*num_agents:(i+1)*num_agents], - self.terminals[i*num_agents:(i+1)*num_agents], - self.truncations[i*num_agents:(i+1)*num_agents], - seed, - num_agents=num_agents - ) - c_envs.append(c_env) - - self.c_envs = binding.vectorize(*c_envs) - - def reset(self, seed=0): - binding.vec_reset(self.c_envs, seed) - self.tick = 0 - return self.observations, [] - - def step(self, actions): - self.tick += 1 - self.actions[:] = actions - binding.vec_step(self.c_envs) - - info = [] - if self.tick % self.log_interval == 0: - log = binding.vec_log(self.c_envs) - if log: - info.append(log) - - return (self.observations, self.rewards, - self.terminals, self.truncations, info) - - def render(self): - binding.vec_render(self.c_envs, 0) - - def close(self): - binding.vec_close(self.c_envs) - - -if __name__ == "__main__": - env = SlimeVolley(num_envs=1, num_agents=1) - observations, _ = env.reset() - env.render() - policy = Policy(env) - policy.load_state_dict(torch.load("checkpoint.pt", map_location="cpu")) - with torch.no_grad(): - while True: - actions = policy(torch.from_numpy(observations)) - actions = [float(torch.argmax(a)) for a in actions[0]] - o, r, t, _, i = env.step([actions]) - env.render() - if t[0]: - break \ No newline at end of file diff --git a/pufferlib/ocean/slimevolley/slimevolley.py b/pufferlib/ocean/slimevolley/slimevolley.py deleted file mode 100644 index a060cc8d70..0000000000 --- a/pufferlib/ocean/slimevolley/slimevolley.py +++ /dev/null @@ -1,81 +0,0 @@ -'''A simple sample environment. Use this as a template for your own envs.''' - -import gymnasium -import numpy as np - -from pufferlib.ocean.slimevolley import binding -import pufferlib - -class SlimeVolley(pufferlib.PufferEnv): - def __init__(self, num_envs=1, render_mode=None, log_interval=128, buf=None, seed=0, - num_agents=1): - assert num_agents in {1, 2}, "num_agents must be 1 or 2" - num_obs = 12 - self.single_observation_space = gymnasium.spaces.Box(low=0, high=1, - shape=(num_obs,), dtype=np.float32) - self.single_action_space = gymnasium.spaces.MultiDiscrete([2, 2, 2]) - - self.render_mode = render_mode - self.num_agents = num_envs * num_agents - self.log_interval = log_interval - - super().__init__(buf) - c_envs = [] - for i in range(num_envs): - c_env = binding.env_init( - self.observations[i*num_agents:(i+1)*num_agents], - self.actions[i*num_agents:(i+1)*num_agents], - self.rewards[i*num_agents:(i+1)*num_agents], - self.terminals[i*num_agents:(i+1)*num_agents], - self.truncations[i*num_agents:(i+1)*num_agents], - seed, - num_agents=num_agents - ) - c_envs.append(c_env) - - self.c_envs = binding.vectorize(*c_envs) - - def reset(self, seed=0): - binding.vec_reset(self.c_envs, seed) - self.tick = 0 - return self.observations, [] - - def step(self, actions): - self.tick += 1 - self.actions[:] = actions - binding.vec_step(self.c_envs) - - info = [] - if self.tick % self.log_interval == 0: - log = binding.vec_log(self.c_envs) - if log: - info.append(log) - - return (self.observations, self.rewards, - self.terminals, self.truncations, info) - - def render(self): - binding.vec_render(self.c_envs, 0) - - def close(self): - binding.vec_close(self.c_envs) - -if __name__ == '__main__': - N = 8 - - env = SlimeVolley(num_envs=N, num_agents=2) - env.reset() - steps = 0 - - CACHE = 1024 - actions = np.random.randint(env.single_action_space.nvec, size=(CACHE, N*2, 3)) - - i = 0 - import time - start = time.time() - while time.time() - start < 10: - env.step(actions[i % CACHE]) - steps += env.num_agents - i += 1 - - print('SlimeVolley SPS:', int(steps / (time.time() - start))) \ No newline at end of file diff --git a/pufferlib/ocean/snake/README.md b/pufferlib/ocean/snake/README.md deleted file mode 100644 index 4ea7c0d15e..0000000000 --- a/pufferlib/ocean/snake/README.md +++ /dev/null @@ -1,17 +0,0 @@ -# PufferLib Multi-Snake - -This is a simple multi-agent snake environment runnable with any number of snakes, board size, food, etc. I originally implemented this to demonstrate how simple it is to implement ultra high performance environments that run at millions of steps per second. The exact same approaches you see here are used in all of my more complex simulators. - -# Cython version - -The Cython version is the original. It runs over 10M steps/second/core on a high-end CPU. This is the version that we currently have bound to training. You can use it with the PufferLib demo script (--env snake) or import it from pufferlib/environments/ocean. There are a number of default board sizes and settings. If you would like to contribute games to PufferLib, you can use this project as a template. There is a bit of bloat in the .py file because we have to trick PufferLib's vectorization into thinking this is a vecenv. In the future, there will be a more standard advanced API. - -Key concepts: -- Memory views: Cython provides a way to access numpy arrays as C arrays or structs. This gives you C-speed numpy indexing and prevents you from having to copy data around. When running with multiprocessing, the observation buffers are stored in shared memory, so you are literally simulating into the experience buffer. -- No memory management: All data is allocated by Numpy and passed to C. This is fast and also prevents any chance of leaks -- No python callbacks: Compile and optimize with annotations enabled (see setup.py) to ensure that the Cython code never calls back to Python. You should be able to get >>1M agent steps/second for almost any sim - -# C version - -The C version is a direct port of the Cython version, plus a few minor tweaks. It includes a pure C raylib client and a pure C MLP forward pass for running local inference. I made this so that we could run a cool demo in the browser 100% client side. I may port additional simulators in the future, and you are welcome to contribute C code to PufferLib, but this is not required. You can make things plenty fast in Cython. To build this locally, all you need is the raylib source. If you want to build for web, follow RayLib's emscripten setup. - diff --git a/pufferlib/ocean/snake/__init__.py b/pufferlib/ocean/snake/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/pufferlib/ocean/snake/binding.c b/pufferlib/ocean/snake/binding.c deleted file mode 100644 index 360c021f6d..0000000000 --- a/pufferlib/ocean/snake/binding.c +++ /dev/null @@ -1,29 +0,0 @@ -#include "snake.h" - -#define Env CSnake -#include "../env_binding.h" - -static int my_init(Env* env, PyObject* args, PyObject* kwargs) { - env->width = unpack(kwargs, "width"); - env->height = unpack(kwargs, "height"); - env->num_snakes = unpack(kwargs, "num_snakes"); - env->vision = unpack(kwargs, "vision"); - env->leave_corpse_on_death = unpack(kwargs, "leave_corpse_on_death"); - env->food = unpack(kwargs, "num_food"); - env->reward_food = unpack(kwargs, "reward_food"); - env->reward_corpse = unpack(kwargs, "reward_corpse"); - env->reward_death = unpack(kwargs, "reward_death"); - env->max_snake_length = unpack(kwargs, "max_snake_length"); - env->cell_size = unpack(kwargs, "cell_size"); - init_csnake(env); - return 0; -} - -static int my_log(PyObject* dict, Log* log) { - assign_to_dict(dict, "perf", log->perf); - assign_to_dict(dict, "score", log->score); - assign_to_dict(dict, "episode_return", log->episode_return); - assign_to_dict(dict, "episode_length", log->episode_length); - assign_to_dict(dict, "n", log->n); - return 0; -} diff --git a/pufferlib/ocean/snake/snake.py b/pufferlib/ocean/snake/snake.py deleted file mode 100644 index 1883b4c228..0000000000 --- a/pufferlib/ocean/snake/snake.py +++ /dev/null @@ -1,124 +0,0 @@ -'''High-perf many-agent snake. Inspired by snake env from https://github.com/dnbt777''' - -import numpy as np -import gymnasium - -import pufferlib -from pufferlib import APIUsageError -from pufferlib.ocean.snake import binding - -class Snake(pufferlib.PufferEnv): - def __init__(self, num_envs=16, width=640, height=360, - num_snakes=256, num_food=4096, - vision=5, leave_corpse_on_death=True, - reward_food=0.1, reward_corpse=0.1, reward_death=-1.0, - report_interval=128, max_snake_length=1024, - render_mode='human', buf=None, seed=0): - - if num_envs is not None: - num_snakes = num_envs * [num_snakes] - width = num_envs * [width] - height = num_envs * [height] - num_food = num_envs * [num_food] - leave_corpse_on_death = num_envs * [leave_corpse_on_death] - - if not (len(num_snakes) == len(width) == len(height) == len(num_food)): - raise APIUsageError('num_snakes, width, height, num_food must be lists of equal length') - - for w, h in zip(width, height): - if w < 2*vision+2 or h < 2*vision+2: - raise APIUsageError('width and height must be at least 2*vision+2') - - max_area = max([w*h for h, w in zip(height, width)]) - self.max_snake_length = min(max_snake_length, max_area) - self.report_interval = report_interval - - self.single_observation_space = gymnasium.spaces.Box( - low=0, high=2, shape=(2*vision+1, 2*vision+1), dtype=np.int8) - self.single_action_space = gymnasium.spaces.Discrete(4) - self.num_agents = sum(num_snakes) - self.render_mode = render_mode - self.tick = 0 - - self.cell_size = int(np.ceil(1280 / max(max(width), max(height)))) - - super().__init__(buf) - c_envs = [] - offset = 0 - for i in range(num_envs): - ns = num_snakes[i] - obs_slice = self.observations[offset:offset+ns] - act_slice = self.actions[offset:offset+ns] - rew_slice = self.rewards[offset:offset+ns] - term_slice = self.terminals[offset:offset+ns] - trunc_slice = self.truncations[offset:offset+ns] - # Seed each env uniquely: i + seed * num_envs - env_seed = i + seed * num_envs - env_id = binding.env_init( - obs_slice, - act_slice, - rew_slice, - term_slice, - trunc_slice, - env_seed, - width=width[i], - height=height[i], - num_snakes=ns, - num_food=num_food[i], - vision=vision, - leave_corpse_on_death=leave_corpse_on_death[i], - reward_food=reward_food, - reward_corpse=reward_corpse, - reward_death=reward_death, - max_snake_length=self.max_snake_length, - cell_size=self.cell_size - ) - c_envs.append(env_id) - offset += ns - self.c_envs = binding.vectorize(*c_envs) - - def reset(self, seed=None): - self.tick = 0 - if seed is None: - binding.vec_reset(self.c_envs, 0) - else: - binding.vec_reset(self.c_envs, seed) - return self.observations, [] - - def step(self, actions): - self.actions[:] = actions - self.tick += 1 - binding.vec_step(self.c_envs) - - info = [] - if self.tick % self.report_interval == 0: - info.append(binding.vec_log(self.c_envs)) - - return (self.observations, self.rewards, - self.terminals, self.truncations, info) - - def render(self): - binding.vec_render(self.c_envs, self.cell_size) - - def close(self): - binding.vec_close(self.c_envs) - -def test_performance(timeout=10, atn_cache=1024): - env = Snake() - env.reset() - tick = 0 - - total_snakes = env.num_agents - actions = np.random.randint(0, 4, (atn_cache, total_snakes)) - - import time - start = time.time() - while time.time() - start < timeout: - atns = actions[tick % atn_cache] - env.step(atns) - tick += 1 - - print(f'SPS: %f', total_snakes * tick / (time.time() - start)) - -if __name__ == '__main__': - test_performance() diff --git a/pufferlib/ocean/squared/binding.c b/pufferlib/ocean/squared/binding.c deleted file mode 100644 index be9dfade28..0000000000 --- a/pufferlib/ocean/squared/binding.c +++ /dev/null @@ -1,17 +0,0 @@ -#include "squared.h" - -#define Env Squared -#include "../env_binding.h" - -static int my_init(Env* env, PyObject* args, PyObject* kwargs) { - env->size = unpack(kwargs, "size"); - return 0; -} - -static int my_log(PyObject* dict, Log* log) { - assign_to_dict(dict, "perf", log->perf); - assign_to_dict(dict, "score", log->score); - assign_to_dict(dict, "episode_return", log->episode_return); - assign_to_dict(dict, "episode_length", log->episode_length); - return 0; -} diff --git a/pufferlib/ocean/squared/squared.py b/pufferlib/ocean/squared/squared.py deleted file mode 100644 index 533778810b..0000000000 --- a/pufferlib/ocean/squared/squared.py +++ /dev/null @@ -1,64 +0,0 @@ -'''A simple sample environment. Use this as a template for your own envs.''' - -import gymnasium -import numpy as np - -import pufferlib -from pufferlib.ocean.squared import binding - -class Squared(pufferlib.PufferEnv): - def __init__(self, num_envs=1, render_mode=None, log_interval=128, size=11, buf=None, seed=0): - self.single_observation_space = gymnasium.spaces.Box(low=0, high=1, - shape=(size*size,), dtype=np.uint8) - self.single_action_space = gymnasium.spaces.Discrete(5) - self.render_mode = render_mode - self.num_agents = num_envs - self.log_interval = log_interval - - super().__init__(buf) - self.c_envs = binding.vec_init(self.observations, self.actions, self.rewards, - self.terminals, self.truncations, num_envs, seed, size=size) - - def reset(self, seed=0): - binding.vec_reset(self.c_envs, seed) - self.tick = 0 - return self.observations, [] - - def step(self, actions): - self.tick += 1 - - self.actions[:] = actions - binding.vec_step(self.c_envs) - - info = [] - if self.tick % self.log_interval == 0: - info.append(binding.vec_log(self.c_envs)) - - return (self.observations, self.rewards, - self.terminals, self.truncations, info) - - def render(self): - binding.vec_render(self.c_envs, 0) - - def close(self): - binding.vec_close(self.c_envs) - -if __name__ == '__main__': - N = 4096 - - env = Squared(num_envs=N) - env.reset() - steps = 0 - - CACHE = 1024 - actions = np.random.randint(0, 5, (CACHE, N)) - - i = 0 - import time - start = time.time() - while time.time() - start < 10: - env.step(actions[i % CACHE]) - steps += N - i += 1 - - print('Squared SPS:', int(steps / (time.time() - start))) diff --git a/pufferlib/ocean/tactical/__init__.py b/pufferlib/ocean/tactical/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/pufferlib/ocean/tactical/tactical.py b/pufferlib/ocean/tactical/tactical.py deleted file mode 100644 index 0ded63cca9..0000000000 --- a/pufferlib/ocean/tactical/tactical.py +++ /dev/null @@ -1,508 +0,0 @@ -import numpy as np -import gymnasium -import os -#from raylib import rl -#import heapq - -import pufferlib -from pufferlib.ocean.tactical import binding -# from pufferlib.environments.ocean import render - -EMPTY = 0 -GROUND = 1 -HOLE = 2 -WALL = 3 - -MAP_DICT = { - '_': EMPTY, - '.': GROUND, - '|': HOLE, - '#': WALL, -} - - -class Tactical: - def __init__(self, num_envs=200, render_mode='human', seed=0): - self.num_envs = num_envs - self.render_mode = render_mode - - # env spec (TODO) - self.observation_space = gymnasium.spaces.Box( - low=0, high=2, shape=(10,), dtype=np.uint8) - self.action_space = gymnasium.spaces.Discrete(4) - self.single_observation_space = self.observation_space - self.single_action_space = self.action_space - self.num_agents = self.num_envs - self.render_mode = render_mode - self.emulated = None - self.done = False - self.buf = pufferlib.namespace( - observations = np.zeros( - (num_envs, 10), dtype=np.uint8), - rewards = np.zeros(num_envs, dtype=np.float32), - terminals = np.zeros(num_envs, dtype=bool), - truncations = np.zeros(num_envs, dtype=bool), - masks = np.ones(num_envs, dtype=bool), - ) - self.actions = np.zeros(num_envs, dtype=np.uint32) - - self.c_envs = binding.vec_init( - self.buf.observations, - self.actions, - self.buf.rewards, - self.buf.terminals, - self.buf.truncations, - num_envs, - seed, - num_obs=self.buf.observations.shape[1] - ) - - # render - # if render_mode == 'human': - # self.client = RaylibClient() - - # map_path = 'pufferlib/environments/ocean/tactical/map.txt' - # map_path = 'pufferlib/environments/ocean/tactical/map_test.txt' - # print(map_path) - # self.load_map(map_path) - - def load_map(self, filename): - with open(filename, 'r') as f: - self.map_str = [line.strip() for line in f.read().strip().split('\n') if line[0] != ';'] - self.map_width = len(self.map_str[0]) - self.map_height = len(self.map_str) - self.map = np.zeros((self.map_height, self.map_width), dtype=np.uint8) - for i, row in enumerate(self.map_str): - for j, cell in enumerate(row): - self.map[i, j] = MAP_DICT[cell] - - def reset(self, seed=None): - self.c_envs = [] - for i in range(self.num_envs): - self.c_envs.append(binding.vec_init( - self.buf.observations[i], - self.actions[i:i+1], - self.buf.rewards[i:i+1])) - binding.vec_reset(self.c_envs[i]) - - return self.buf.observations, {} - - def step(self, actions): - self.actions[:] = actions - for c_env in self.c_envs: - binding.vec_step(c_env) - - info = {} - - return (self.buf.observations, self.buf.rewards, - self.buf.terminals, self.buf.truncations, info) - - def render(self): - return binding.vec_render(self.c_envs, 0) - # if self.render_mode == 'human': - # return self.client.render(self.map) - - def close(self): - for c_env in self.c_envs: - binding.vec_close(c_env) - -''' -def a_star_search(map, start, goal): - frontier = [] - heapq.heappush(frontier, (0, start)) - - came_from = {} - cost_so_far = {} - came_from[start] = None - cost_so_far[start] = 0 - - while len(frontier) > 0: - current = heapq.heappop(frontier)[1] - - if current == goal: - break - - for dx, dy in [(0, 1), (0, -1), (1, 0), (-1, 0)]: - next = (current[0] + dx, current[1] + dy) - if next[0] < 0 or next[1] < 0 or next[0] >= map.shape[0] or next[1] >= map.shape[1] or map[next] != GROUND: - continue - new_cost = cost_so_far[current] + 1 - if next not in cost_so_far or new_cost < cost_so_far[next]: - cost_so_far[next] = new_cost - priority = new_cost + abs(next[0] - goal[0]) + abs(next[1] - goal[1]) - heapq.heappush(frontier, (priority, next)) - came_from[next] = current - - # return came_from, cost_so_far - # reconstruct path - path = [] - if goal not in came_from: # no path was found - return [] - assert current == goal - while current != start: - path.append(current) - current = came_from[current] - # path.append(start) - path.reverse() - return path - - -class RaylibClient: - def __init__(self): - self.screenw = 1200 - self.screenh = 900 - rl.InitWindow(self.screenw, self.screenh, "Puffer Tactical".encode()) - rl.SetTargetFPS(60) - - self.row = 12 - self.col = 12 - - self.anim = False - self.anim_type = None - self.anim_path = None - self.anim_path_progress = None - - self.spell_mode = False - - self.cra_bottom = rl.LoadTexture('pufferlib/environments/ocean/tactical/sacri_bottom.png'.encode()) - self.cra_top = rl.LoadTexture('pufferlib/environments/ocean/tactical/sacri_top.png'.encode()) - self.cra_left = rl.LoadTexture('pufferlib/environments/ocean/tactical/sacri_left.png'.encode()) - self.cra_right = rl.LoadTexture('pufferlib/environments/ocean/tactical/sacri_right.png'.encode()) - self.cra_tex = self.cra_bottom - - def render(self, map): - # TODO : rather than compute isometric coordinates - # could be easier to do all cartesian and use a coordinate conversion (linear algebra, some cos/sin) - # to go back and forth between the two coordinate systems? - # see https://en.wikipedia.org/wiki/Isometric_projection - if rl.IsKeyDown(rl.KEY_ESCAPE): - exit(0) - - if rl.IsKeyDown(rl.KEY_E) and not self.anim: - self.spell_mode = True - if rl.IsKeyDown(rl.KEY_R) and not self.anim: - self.spell_mode = False - - nrows, ncols = map.shape - - # figure out dimensions so the map scales to fit on the screen - - # map width = 14, map height = 16 - # find map width (longest bottomleft-topright diagonal) - - mapw = -1 - for i in range(nrows): - horizontal_line = [map[i-k,k] for k in range(min(i + 1, ncols))] - if set(horizontal_line) == {EMPTY}: continue - i0, i1 = 0, len(horizontal_line) - 1 - while horizontal_line[i0] == EMPTY: i0 += 1 - while horizontal_line[i1] == EMPTY: i1 -= 1 - mapw = max(mapw, i1 - i0 + 1) - maph = -1 - for i in range(ncols): - vertical_line = [map[k,i+k] for k in range(min(ncols - i, nrows))] - if set(vertical_line) == {EMPTY}: continue - i0, i1 = 0, len(vertical_line) - 1 - while vertical_line[i0] == EMPTY: i0 += 1 - while vertical_line[i1] == EMPTY: i1 -= 1 - maph = max(maph, i1 - i0 + 1) - - - padding_top = 100 - padding_bottom = 100 - cw_max = (self.screenw) / mapw - ch_max = (self.screenh - padding_top - padding_bottom) / maph - # we want ch = cw / 2 -> pick the best ratio - if ch_max > cw_max / 2: - cw = cw_max - ch = cw / 2 - else: - ch = ch_max - cw = ch * 2 - - # figure out correct offset to center the game - xmin = 1e9 - ymin = 1e9 - for i, row in enumerate(map): - for j, cell in enumerate(row): - # todo not the most efficient + avoid code repetition - if cell != EMPTY: - xa = 0.5 * (j + 1) * cw - 0.5 * (i + 1) * cw - ya = 0.5 * (j + 1) * ch + 0.5 * (i + 1) * ch - xmin = min(xmin, xa - cw / 2) - ymin = min(ymin, ya) - - # import sys; sys.exit(0) - - offset_x = -xmin + (self.screenw-cw*mapw)/2 # center - offset_y = -ymin + padding_top - # cw = 80 - # ch = cw / 2 - - rl.BeginDrawing() - rl.ClearBackground(render.PUFF_BACKGROUND) - - # get mouse pos - mx, my = rl.GetMouseX(), rl.GetMouseY() - rl.DrawText(f"Mouse: {mx}, {my}".encode(), 15, 10, 20, render.PUFF_TEXT) - # get corresponding cell (if any) - # to get the formula: we know that cell (row, col) = (i, j) starts at coordinates - # x = offset_x + 0.5 * (j + 1) * cw - 0.5 * (i + 1) * cw - # y = offset_y + 0.5 * (j + 1) * ch + 0.5 * (i + 1) * ch - # Solve this to write i and j as a function of x and y and we get the formulas below - ci = int((offset_x - mx) / cw + (my - offset_y) / ch - 1) - cj = int((mx - offset_x) / cw + (my - offset_y) / ch - 1) - cell = None if ci < 0 or cj < 0 or ci >= nrows or cj >= ncols else (ci, cj) - rl.DrawText(f"Cell: {cell}".encode(), 15, 35, 20, render.PUFF_TEXT) - - - # movement - movement = np.zeros_like(map) - - if not self.anim and not self.spell_mode: - if cell is not None: - # draw movement path - path = a_star_search(map, start=(self.row, self.col), goal=(ci, cj)) - if path: - path_rows, path_cols = zip(*path) - movement[path_rows, path_cols] = 1 - - if rl.IsMouseButtonPressed(rl.MOUSE_BUTTON_LEFT): - if cell is not None and map[cell] == GROUND: - # self.row = ci - # self.col = cj - self.anim = True - self.anim_type = 'move' - self.anim_path = [(self.row, self.col)] + path - self.anim_path_progress = 0 - - # line of sight - los = np.ones_like(map) - - for i in range(nrows): - for j in range(ncols): - cell = map[i, j] - if cell != GROUND: - los[i, j] = 0 - elif (i, j) == (self.row, self.col): - los[i, j] = 0 - else: - # use bresenham-based supercover line algorithm - # http://eugen.dedu.free.fr/projects/bresenham/ - # note: bresenham alone doesnt find all cells covered by the lines - # implementation from https://www.redblobgames.com/grids/line-drawing/#supercover (covers all quadrants) <- here it is explained very well, the algo is pretty simple - # now we could precompute this on the map for every pair of points - # the question is: if we add one obstacle, how does it change lines of sight? mb its fast enough to just simulate in real time? - # ONE OTHER APPROACH: for every pair of points, assume one point is the observer and the other is a wall (so, ignoring the geometry of the map). then, what lines of sight do we have? then we just need to do a logical and for all lines of sight. not sure its even faster though, it doesnt seem to be. - # an optimization: instead of doing lines of sight for all pair of points, we could check between observer and all border cells of the map? then, we set all cells to line of sight true and as soon as we hit an obstacle, we'll set all subsequent cells to line of sight false. this should hit all the cells? - # bressenham: check all points between character and (i, j), if any is an obstacle then cancel the line of sight - x0 = self.col - y0 = self.row - x1 = j - y1 = i - ### - dx = x1 - x0 - dy = y1 - y0 - nx = abs(dx) - ny = abs(dy) - sign_x = 1 if dx > 0 else -1 - sign_y = 1 if dy > 0 else -1 - px = x0 - py = y0 - ix = 0 - iy = 0 - while ix < nx or iy < ny: - if map[py, px] == WALL: - los[i, j] = 0 - break - decision = (1 + 2 * ix) * ny - (1 + 2 * iy) * nx - if decision == 0: - # next step is diagonal - px += sign_x - py += sign_y - ix += 1 - iy += 1 - elif decision < 0: - # next step is horizontal - px += sign_x - ix += 1 - else: - # next step is vertical - py += sign_y - iy += 1 - - - - # bool IsMouseButtonPressed(int button); - - - # naive (O(n^3)) for each pair of cell A, B - # we draw the line from the center of cell A to the center of cell B - # then we use bressenham's algo https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm - # to find all the cells that the line goes through - # if any of these is an obstacle, then there is no line of sight between A and B. Otherwise there is. - - # maybe better: for each obstacle, directly find all the cells this obstacle hides and mask them - - - - - # draw cells from top-left to bottom-right - # isometric cell link to bottom link to top - # (ground) 4 - # a a 5 a 6 - # b e c (b<->c = cw) b 0 c b 7 c - # d 1 d 2 d - # (a<->d = ch) 3 - # cell dimensions (as per drawing above) - for i, row in enumerate(map): - for j, cell in enumerate(row): - # compute isometrics coordinates (points a,b,c,d) -- TODO of course all this should be precomputed - xa = offset_x + 0.5 * (j + 1) * cw - 0.5 * (i + 1) * cw - xb, xc, xd = xa - cw / 2, xa + cw / 2, xa - ya = offset_y + 0.5 * (j + 1) * ch + 0.5 * (i + 1) * ch - yb, yc, yd = ya + ch / 2, ya + ch / 2, ya + ch - xe, ye = xa, yb - # draw cell - if cell == WALL: - dy = ch * 0.4 - x4, x5, x6, x7 = xa, xb, xc, xd - y4, y5, y6, y7 = ya - dy, yb - dy, yc - dy, yd - dy - rl.DrawTriangleStrip([(x4, y4), (x5, y5), (x6, y6), (x7, y7)], 4, [163, 197, 69, 255]) # top square - rl.DrawTriangleStrip([(xc, yc), (x6, y6), (xd, yd), (x7, y7), (xb, yb), (x5, y5)], 6, [40, 20, 5, 255]) # connection with ground - elif cell == HOLE: - pass # leave empty, as a hole should be - elif cell == GROUND: - if movement[(i, j)]: - col = [0, 180, 0, 255] - elif self.spell_mode: - #elif abs(i - self.row) + abs(j - self.col) <= 10 and abs(i - self.row) + abs(j - self.col) > 0: - if los[(i, j)]: - if (i, j) == (ci, cj): - col = [255, 165, 0, 255] - else: - col = [68, 109, 153, 255] - else: - col = [112, 123, 111, 255] - else: - col = [189, 205, 125, 255] if (i + j) % 2 == 0 else [180, 195, 118, 255] - rl.DrawTriangleStrip([(xa, ya), (xb, yb), (xc, yc), (xd, yd)], 4, col) - - # draw white border around cell - rl.DrawLineStrip([(xa, ya), (xb, yb), (xd, yd), (xc, yc), (xa, ya)], 5, (255, 255, 255, 255)) - # Draw dirt below the cell - if cell == GROUND or cell == WALL: - # here we only draw what will be seen ; maybe it's faster to draw everything and not do any checks - dy = ch * 0.7 - x0, x1, x2, x3 = xa, xb, xc, xd - y0, y1, y2, y3 = ya + dy, yb + dy, yc + dy, yd + dy - if i == len(map) - 1 or map[i+1,j] in [HOLE, EMPTY]: - rl.DrawTriangleStrip([(xb, yb), (x1, y1), (xd, yd), (x3, y3)], 4, [68, 48, 10, 255]) # left side (b-1-3-d boundary) - if j == len(row) - 1 or map[i,j+1] in [HOLE, EMPTY]: - rl.DrawTriangleStrip([(xd, yd), (x3, y3), (xc, yc), (x2, y2)], 4, [95, 77, 21, 255]) # right side (d-3-2-c boundary) - - - - # draw character - - xe = offset_x + 0.5 * (self.col + 1) * cw - 0.5 * (self.row + 1) * cw - ye = offset_y + 0.5 * (self.col + 1) * ch + 0.5 * (self.row + 1) * ch + ch / 2 - - xe_m = offset_x + 0.5 * (cj + 1) * cw - 0.5 * (ci + 1) * cw - ye_m = offset_y + 0.5 * (cj + 1) * ch + 0.5 * (ci + 1) * ch + ch / 2 - - # 465*1129 - cra_tex_w = 465 - cra_tex_h = 1129 - cra_tex_desired_h = 1.6 * ch - scale = cra_tex_desired_h / cra_tex_h - cra_tex_desired_w = cra_tex_w * scale - cra_x = xe - cra_tex_desired_w / 2 - cra_y = ye - cra_tex_desired_h + 0.1 * ch - - if self.anim and self.anim_type == "move": - # cur is updated when we arrive at the center of a new cell - cur = self.anim_path[int(self.anim_path_progress)] - self.row, self.col = cur - transition_progress = self.anim_path_progress - int(self.anim_path_progress) - if cur == self.anim_path[-1]: - self.anim = False - else: - next = self.anim_path[int(self.anim_path_progress)+1] - # use correct facing of the texture - if next[0] == cur[0] + 1: - self.cra_tex = self.cra_bottom - self.movx, self.movy = -1, 1 - elif next[0] == cur[0] - 1: - self.cra_tex = self.cra_top - self.movx, self.movy = 1, -1 - elif next[1] == cur[1] + 1: - self.cra_tex = self.cra_right - self.movx, self.movy = 1, 1 - elif next[1] == cur[1] - 1: - self.cra_tex = self.cra_left - self.movx, self.movy = -1, -1 - # add a delta to the x,y texture position for continuous movement - delta_x = (transition_progress) * cw * 0.5 * self.movx - delta_y = (transition_progress) * ch * 0.5 * self.movy - self.anim_path_progress += 0.1 - cur = self.anim_path[int(self.anim_path_progress)] - self.row, self.col = cur - else: - delta_x = delta_y = 0 - - coef = 0.35 - thickness = 2 - if self.anim and self.anim_type == 'move': - col = [189, 205, 125, 255] if (self.anim_path[0][0] + self.anim_path[0][1]) % 2 == 0 else [180, 195, 118, 255] - else: - col = [189, 205, 125, 255] if (self.row + self.col) % 2 == 0 else [180, 195, 118, 255] - rl.DrawEllipse(int(xe + delta_x), int(ye + delta_y), cw * coef, ch * coef, [255, 0, 0, 255]) - rl.DrawEllipse(int(xe + delta_x), int(ye + delta_y), cw * coef - thickness, ch * coef - thickness, col) - - rl.DrawTextureEx(self.cra_tex, (cra_x + delta_x, cra_y + delta_y), 0, scale, [255, 255, 255, 255]) - - # void DrawSplineLinear(Vector2 *points, int pointCount, float thick, Color color); // Draw spline: Linear, minimum 2 points - # rl.DrawSplineLinear([(xe, ye), (mx, my)], 10, 5, [255, 0, 0, 255]) - # rl.DrawSplineBezierQuadratic([(xe, ye-cra_tex_desired_h/2), ((xe+mx)/2,(ye+my)/2-200), (mx, my)], 3, 5, [255, 0, 0, 255]) - - if rl.IsMouseButtonPressed(rl.MOUSE_BUTTON_LEFT) and self.spell_mode and los[ci,cj]: - self.anim = True - self.anim_type = "spell" - self.spell_mode = False - - self.anim_path = [(xe, ye-cra_tex_desired_h/2), ((xe+mx)/2,(ye+my)/2-200), (xe_m, ye_m)] - self.anim_path_progress = 0.01 - - if self.anim and self.anim_type == "spell": - self.anim_path_progress += 0.025 - pt = rl.GetSplinePointBezierQuad(*self.anim_path, min(self.anim_path_progress, 1.0)) - - if self.anim_path_progress <= 1.0: - rl.DrawCircle(int(pt.x), int(pt.y), 10, [255, 0, 0, 255]) - else: - rl.DrawCircle(int(pt.x), int(pt.y), 10 + (self.anim_path_progress - 1.0) * 100, [255, 0, 0, int(255 - (self.anim_path_progress - 1.0) * 1200)]) - - if self.anim_path_progress >= 1.2: - self.anim = False - - rl.EndDrawing() - return render.cdata_to_numpy() -''' - - -if __name__ == '__main__': - PROFILE = False - env = Tactical(num_envs=1, render_mode='human') - env.reset() - import time - t0 = time.time() - steps = 0 - while not PROFILE or time.time() - t0 < 10: - env.step([0] * env.num_envs) - if not PROFILE: - if env.render() == 1: # exit code - break - steps += 1 - print('SPS:', 1 * steps / (time.time() - t0)) - diff --git a/pufferlib/ocean/target/binding.c b/pufferlib/ocean/target/binding.c deleted file mode 100644 index f8e7bde78e..0000000000 --- a/pufferlib/ocean/target/binding.c +++ /dev/null @@ -1,21 +0,0 @@ -#include "target.h" - -#define Env Target -#include "../env_binding.h" - -static int my_init(Env* env, PyObject* args, PyObject* kwargs) { - env->width = unpack(kwargs, "width"); - env->height = unpack(kwargs, "height"); - env->num_agents = unpack(kwargs, "num_agents"); - env->num_goals = unpack(kwargs, "num_goals"); - init(env); - return 0; -} - -static int my_log(PyObject* dict, Log* log) { - assign_to_dict(dict, "perf", log->perf); - assign_to_dict(dict, "score", log->score); - assign_to_dict(dict, "episode_return", log->episode_return); - assign_to_dict(dict, "episode_length", log->episode_length); - return 0; -} diff --git a/pufferlib/ocean/target/target.c b/pufferlib/ocean/target/target.c deleted file mode 100644 index 61a91a9fce..0000000000 --- a/pufferlib/ocean/target/target.c +++ /dev/null @@ -1,64 +0,0 @@ -/* Pure C demo file for Target. Build it with: - * bash scripts/build_ocean.sh target local (debug) - * bash scripts/build_ocean.sh target fast - * We suggest building and debugging your env in pure C first. You - * get faster builds and better error messages - */ -#include "target.h" - -/* Puffernet is our lightweight cpu inference library that - * lets you load basic PyTorch model architectures so that - * you can run them in pure C or on the web via WASM - */ -#include "puffernet.h" - -int main() { - int num_agents = 8; - int num_goals = 4; - int num_obs = 2*(num_agents + num_goals) + 4; - - // Weights are exported by running puffer export - Weights* weights = load_weights("resources/target/target_weights.bin", 137743); - - int logit_sizes[2] = {9, 5}; - LinearLSTM* net = make_linearlstm(weights, num_agents, num_obs, logit_sizes, 2); - - Target env = { - .width = 1080, - .height = 720, - .num_agents = num_agents, - .num_goals = num_goals - }; - init(&env); - - // Allocate these manually since they aren't being passed from Python - env.observations = calloc(env.num_agents*num_obs, sizeof(float)); - env.actions = calloc(2*env.num_agents, sizeof(int)); - env.rewards = calloc(env.num_agents, sizeof(float)); - env.terminals = calloc(env.num_agents, sizeof(unsigned char)); - - // Always call reset and render first - c_reset(&env); - c_render(&env); - - // while(True) will break web builds - while (!WindowShouldClose()) { - for (int i=0; i -#include -#include -#include -#include "raylib.h" - -#define HAND_SIZE 10 -#define BOARD_SIZE 10 -#define DECK_SIZE 60 -#define STACK_SIZE 100 - -#define ACTION_ENTER 10 -#define ACTION_NOOP 11 - -#define TO_USER true; -#define TO_STACK false; - -typedef struct TCG TCG; -typedef bool (*call)(TCG*, unsigned char); -bool phase_untap(TCG* env, unsigned char atn); -bool phase_draw(TCG* env, unsigned char atn); -bool phase_play(TCG* env, unsigned char atn); -bool phase_attack(TCG* env, unsigned char atn); -bool phase_block(TCG* env, unsigned char atn); -void reset(TCG* env); - -typedef struct Stack Stack; -struct Stack { - call data[STACK_SIZE]; - int idx; -}; - -void push(Stack* stack, call fn) { - assert(stack->idx < STACK_SIZE); - stack->data[stack->idx] = fn; - stack->idx += 1; -} - -call pop(Stack* stack) { - assert(stack->idx > 0); - stack->idx -= 1; - return stack->data[stack->idx]; -} - -call peek(Stack* stack) { - assert(stack->idx > 0); - return stack->data[stack->idx - 1]; -} - -typedef struct Card Card; -struct Card { - int cost; - int attack; - int health; - bool is_land; - bool remove; - bool tapped; - bool attacking; - int defending; -}; - -typedef struct CardArray CardArray; -struct CardArray { - Card* cards; - int length; - int max; -}; - -CardArray* allocate_card_array(int max) { - CardArray* hand = (CardArray*)calloc(1, sizeof(CardArray)); - hand->cards = (Card*)calloc(max, sizeof(Card)); - hand->max = max; - return hand; -} - -void free_card_array(CardArray* ary) { - free(ary->cards); - free(ary); -} - -void condense_card_array(CardArray* ary) { - int idx = 0; - for (int i = 0; i < ary->length; i++) { - if (!ary->cards[i].remove) { - ary->cards[idx] = ary->cards[i]; - idx += 1; - } - } - ary->length = idx; -} - -struct TCG { - CardArray* my_hand; - CardArray* my_board; - CardArray* my_deck; - int my_health; - int my_mana; - bool my_land_played; - - CardArray* op_hand; - CardArray* op_board; - CardArray* op_deck; - int op_health; - int op_mana; - bool op_land_played; - - Stack* stack; - //bool attackers[BOARD_SIZE]; - //bool defenders[BOARD_SIZE][BOARD_SIZE]; - int block_idx; - int turn; -}; - -void allocate_tcg(TCG* env) { - env->stack = calloc(1, sizeof(Stack)); - env->my_hand = allocate_card_array(HAND_SIZE); - env->op_hand = allocate_card_array(HAND_SIZE); - env->my_board = allocate_card_array(BOARD_SIZE); - env->op_board = allocate_card_array(BOARD_SIZE); - env->my_deck = allocate_card_array(DECK_SIZE); - env->op_deck = allocate_card_array(DECK_SIZE); -} - -void free_tcg(TCG* env) { - free_card_array(env->my_hand); - free_card_array(env->op_hand); - free_card_array(env->my_board); - free_card_array(env->op_board); - free_card_array(env->my_deck); - free_card_array(env->op_deck); -} - -void randomize_deck(CardArray* deck) { - for (int i = 0; i < deck->length; i++) { - deck->cards[i].defending = -1; - if (rand() % 3 == 0) { - deck->cards[i].is_land = true; - } else { - int cost = rand() % 6; - deck->cards[i].cost = cost; - deck->cards[i].attack = cost + 1; - deck->cards[i].health = cost + 1; - } - } -} - -void draw_card(TCG* env, CardArray* deck, CardArray* hand) { - if (deck->length == 0) { - reset(env); - return; - } - if (hand->length == hand->max) { - return; - } - Card card = deck->cards[deck->length - 1]; - hand->cards[hand->length] = card; - deck->length -= 1; - hand->length += 1; -} - -bool can_attack(CardArray* board) { - for (int i = 0; i < board->length; i++) { - if (!board->cards[i].is_land) { - return true; - } - } - return false; -} - -int tappable_mana(TCG* env) { - CardArray* board = (env->turn == 0) ? env->my_board : env->op_board; - int tappable = 0; - for (int i = 0; i < board->length; i++) { - Card card = board->cards[i]; - if (card.is_land && !card.tapped) { - tappable += 1; - } - } - return tappable; -} - -bool can_play(TCG* env) { - CardArray* hand = (env->turn == 0) ? env->my_hand : env->op_hand; - int* mana = (env->turn == 0) ? &env->my_mana : &env->op_mana; - bool* land_played = (env->turn == 0) ? &env->my_land_played : &env->op_land_played; - - int min_cost = 99; - for (int i = 0; i < hand->length; i++) { - if (hand->cards[i].is_land && !*land_played) { - return true; - } else if (hand->cards[i].cost < min_cost) { - min_cost = hand->cards[i].cost; - } - } - - int tappable = tappable_mana(env); - return *mana + tappable >= min_cost; -} - -bool phase_untap(TCG* env, unsigned char atn) { - printf("PHASE_UNTAP\n"); - bool* land_played = (env->turn == 0) ? &env->my_land_played : &env->op_land_played; - *land_played = false; - - env->turn = 1 - env->turn; - CardArray* board = (env->turn == 0) ? env->my_board : env->op_board; - - int* mana = (env->turn == 0) ? &env->my_mana : &env->op_mana; - *mana = 0; - - for (int i = 0; i < board->length; i++) { - Card card = board->cards[i]; - if (card.is_land && card.tapped) { - board->cards[i].tapped = false; - } - } - - push(env->stack, phase_draw); - return TO_STACK; -} - -bool phase_draw(TCG* env, unsigned char atn) { - printf("PHASE_DRAW\n"); - CardArray* deck = (env->turn == 0) ? env->my_deck : env->op_deck; - CardArray* hand = (env->turn == 0) ? env->my_hand : env->op_hand; - draw_card(env, deck, hand); - push(env->stack, phase_play); - return TO_STACK; -} - -bool phase_play(TCG* env, unsigned char atn) { - printf("PHASE_PLAY\n"); - CardArray* hand = (env->turn == 0) ? env->my_hand : env->op_hand; - CardArray* board = (env->turn == 0) ? env->my_board : env->op_board; - int* mana = (env->turn == 0) ? &env->my_mana : &env->op_mana; - bool* land_played = (env->turn == 0) ? &env->my_land_played : &env->op_land_played; - - if (board->length == BOARD_SIZE) { - printf("\t Board full\n"); - push(env->stack, phase_attack); - return TO_STACK; - } - - if (!can_play(env)) { - printf("\t No valid moves\n"); - push(env->stack, phase_attack); - return TO_STACK; - } - - if (atn == ACTION_NOOP) { - push(env->stack, phase_play); - return TO_USER; - } else if (atn == ACTION_ENTER) { - push(env->stack, phase_attack); - return TO_STACK; - } else if (atn >= hand->length) { - printf("\t Invalid action: %i\n. Hand length: %i\n", atn, hand->length); - push(env->stack, phase_play); - return TO_USER; - } - - Card card = hand->cards[atn]; - if (card.is_land) { - if (*land_played) { - printf("\t Already played land this turn\n"); - push(env->stack, phase_play); - return TO_USER; - } - board->cards[board->length] = card; - board->length += 1; - *land_played = true; - hand->cards[atn].remove = true; - condense_card_array(hand); - printf("\t Land played\n"); - push(env->stack, phase_play); - return TO_USER; - } - - if (card.cost > *mana + tappable_mana(env)) { - printf("\t Not enough mana\n"); - push(env->stack, phase_play); - return TO_USER; - } - - // Auto tap lands? - for (int i = 0; i < board->length; i++) { - if (card.cost <= *mana) { - break; - } - Card card = board->cards[i]; - if (card.is_land && !card.tapped) { - *mana += 1; - board->cards[i].tapped = true; - } - } - - assert(*mana >= card.cost); - *mana -= card.cost; - board->cards[board->length] = card; - board->length += 1; - hand->cards[atn].remove = true; - condense_card_array(hand); - printf("\t Card played\n"); - push(env->stack, phase_play); - return TO_USER; -} - -bool phase_attack(TCG* env, unsigned char atn) { - printf("PHASE_ATTACK\n"); - CardArray* board = (env->turn == 0) ? env->my_board : env->op_board; - - if (!can_attack(board)) { - printf("\t No valid attacks. Phase end\n"); - push(env->stack, phase_untap); - return TO_STACK; - } - - if (atn == ACTION_NOOP) { - push(env->stack, phase_attack); - return TO_USER; - } else if (atn == ACTION_ENTER) { - printf("\t Attacks confirmed. Phase end\n"); - env->turn = 1 - env->turn; - push(env->stack, phase_block); - return TO_STACK; - } else if (atn >= board->length) { - printf("\t Invalid action %i\n", atn); - push(env->stack, phase_attack); - return TO_USER; - } else if (board->cards[atn].is_land) { - printf("\t Cannot attack with land\n"); - push(env->stack, phase_attack); - return TO_USER; - } else { - printf("\t Setting attacker %i\n", atn); - board->cards[atn].attacking = !board->cards[atn].attacking; - push(env->stack, phase_attack); - return TO_USER; - } -} - -bool phase_block(TCG* env, unsigned char atn) { - printf("PHASE_BLOCK\n"); - CardArray* defender_board = (env->turn == 0) ? env->my_board : env->op_board; - CardArray* board = (env->turn == 0) ? env->op_board : env->my_board; - int* health = (env->turn == 0) ? &env->op_health : &env->my_health; - - while (env->block_idx < board->length && !board->cards[env->block_idx].attacking) { - printf("\t Skipping block for %i (not attacking)\n", env->block_idx); - env->block_idx++; - } - - bool can_block = false; - for (int i = 0; i < defender_board->length; i++) { - Card* card = &defender_board->cards[i]; - if (card->is_land) { - continue; - } - if (card->defending == -1 || card->defending == env->block_idx) { - can_block = true; - printf("\t Can block with %i\n", i); - break; - } - } - if (!can_block) { - env->block_idx = board->length; - } - - if (env->block_idx == board->length) { - printf("\t Attacker board length: %i\n", board->length); - for (int atk = 0; atk < board->length; atk++) { - printf("\t Resolving %i\n", atk); - Card* attacker = &board->cards[atk]; - if (!attacker->attacking) { - printf("\t Not attacking\n"); - continue; - } - int attacker_attack = attacker->attack; - int attacker_health = attacker->health; - for (int def = 0; def < defender_board->length; def++) { - Card* defender = &defender_board->cards[def]; - if (defender->defending != atk) { - continue; - } - if (attacker_attack >= defender->health) { - attacker_attack -= defender->health; - attacker_health -= defender->attack; - defender->health = 0; - defender->remove = true; - } else { - attacker_health -= defender->attack; - attacker_attack = 0; - } - if (attacker_health <= 0) { - attacker->remove = true; - break; - } - } - printf("\t Reducing health by %i\n", attacker_attack); - *health -= attacker_attack; - } - - if (*health <= 0) { - printf("\t Game over\n"); - reset(env); - } - - condense_card_array(env->my_board); - condense_card_array(env->op_board); - - CardArray* defender_deck = (env->turn == 0) ? env->my_deck : env->op_deck; - CardArray* defender_hand = (env->turn == 0) ? env->my_hand : env->op_hand; - draw_card(env, defender_deck, defender_hand); - - for (int i = 0; i < board->length; i++) { - board->cards[i].attacking = false; - } - for (int i = 0; i < defender_board->length; i++) { - defender_board->cards[i].defending = -1; - } - printf("\t Set block idx to 0\n"); - env->block_idx = 0; - env->turn = 1 - env->turn; - push(env->stack, phase_untap); - return TO_STACK; - } - - if (atn == ACTION_NOOP) { - push(env->stack, phase_block); - return TO_USER; - } else if (atn == ACTION_ENTER) { - printf("\t Manual block confirm %i\n", env->block_idx); - env->block_idx++; - push(env->stack, phase_block); - return TO_STACK; - } else if (atn >= defender_board->length) { - printf("\t Invalid block action %i\n", atn); - push(env->stack, phase_block); - return TO_USER; - } else if (defender_board->cards[atn].is_land) { - printf("\t Cannot block with land\n"); - push(env->stack, phase_block); - return TO_USER; - } - - for (int i = 0; i < env->block_idx; i++) { - if (defender_board->cards[atn].defending == i) { - printf("\t Already blocked\n"); - push(env->stack, phase_block); - return TO_USER; - } - } - printf("\t Blocking index %i with %i\n", env->block_idx, atn); - Card* card = &defender_board->cards[atn]; - if (card->defending == env->block_idx) { - card->defending = -1; - } else { - card->defending = env->block_idx; - } - push(env->stack, phase_block); - return TO_USER; -} - -void step(TCG* env, unsigned char atn) { - printf("Turn: %i, Action: %i\n", env->turn, atn); - while (true) { - call fn = pop(env->stack); - bool return_to_user = fn(env, atn); - if (return_to_user) { - return; - } - atn = ACTION_NOOP; - } -} - -void reset(TCG* env) { - env->my_deck->length = DECK_SIZE; - env->op_deck->length = DECK_SIZE; - env->my_hand->length = 0; - env->op_hand->length = 0; - env->my_board->length = 0; - env->op_board->length = 0; - env->my_health = 20; - env->op_health = 20; - randomize_deck(env->my_deck); - randomize_deck(env->op_deck); - env->turn = rand() % 2; - for (int i = 0; i < 5; i++) { - draw_card(env, env->my_deck, env->my_hand); - draw_card(env, env->op_deck, env->op_hand); - } - push(env->stack, phase_draw); - step(env, ACTION_NOOP); -} - -void init_client(TCG* env) { - InitWindow(1080, 720, "Puffer the Schooling TCG"); - SetTargetFPS(60); -} - -void close_client(TCG* env) { - CloseWindow(); -} - -int card_x(int col, int n) { - int cards_width = 72*n; - int offset = 72*col; - return GetScreenWidth()/2 - cards_width/2 + offset; -} - -int card_y(int row) { - return 64 + (128 + 20)*row; -} - -void render_card(Card* card, int x, int y, Color color) { - DrawRectangle(x, y, 64, 128, color); - if (card->is_land) { - DrawText("Land", x + 16, y + 40, 16, WHITE); - } else { - DrawText(TextFormat("%i", card->cost), x + 32, y+16, 20, WHITE); - DrawText(TextFormat("%i", card->attack), x + 32, y + 40, 20, WHITE); - DrawText(TextFormat("%i", card->health), x + 32, y + 64, 20, WHITE); - } -} - -void render_label(int x, int y, int idx) { - DrawText(TextFormat("%i", (idx+1)%10), x+32, y+96, 20, YELLOW); -} - -void render(TCG* env) { - BeginDrawing(); - ClearBackground((Color){6, 24, 24, 255}); - - for (int i = 0; i < env->my_hand->length; i++) { - Card card = env->my_hand->cards[i]; - int x = card_x(i, env->my_hand->length); - int y = card_y(3); - render_card(&card, x, y, RED); - if (env->turn == 0) { - render_label(x, y, i); - } - } - - for (int i = 0; i < env->my_board->length; i++) { - Card card = env->my_board->cards[i]; - int x = card_x(i, env->my_board->length); - int y = card_y(2); - if (card.attacking) { - y -= 16; - } - Color color = (card.tapped) ? (Color){128, 0, 0, 255}: RED; - render_card(&card, x, y, color); - if (env->turn == 0) { - render_label(x, y, i); - } - } - - for (int i = 0; i < env->op_board->length; i++) { - Card card = env->op_board->cards[i]; - int x = card_x(i, env->op_board->length); - int y = card_y(1); - if (card.attacking) { - y += 16; - } - Color color = (card.tapped) ? (Color){0, 0, 128, 255}: BLUE; - render_card(&card, x, y, color); - } - - for (int i = 0; i < env->my_board->length; i++) { - Card card = env->my_board->cards[i]; - if (card.defending == -1) { - continue; - } - DrawLineEx( - (Vector2){32+card_x(i, env->my_board->length), 64+card_y(2)}, - (Vector2){32+card_x(card.defending, env->op_board->length), 64+card_y(1)}, - 3.0f, WHITE - ); - } - - for (int i = 0; i < env->op_hand->length; i++) { - Card card = env->op_hand->cards[i]; - int x = card_x(i, env->op_hand->length); - int y = card_y(0); - render_card(&card, x, y, BLUE); - } - - int x = GetScreenWidth() - 128; - int y = 32; - - call fn = peek(env->stack); - if (fn == phase_draw) { - DrawText("Draw", x, y, 20, WHITE); - } else if (fn == phase_play) { - DrawText("Play", x, y, 20, WHITE); - } else if (fn == phase_attack) { - DrawText("Attack", x, y, 20, WHITE); - } else if (fn == phase_block) { - DrawText("Block", x, y, 20, WHITE); - } - - DrawText(TextFormat("Health: %i", env->my_health), 32, 32, 20, WHITE); - DrawText(TextFormat("Health: %i", env->op_health), 32, GetScreenHeight() - 64, 20, WHITE); - - EndDrawing(); -} diff --git a/pufferlib/ocean/template/template.py b/pufferlib/ocean/template/template.py deleted file mode 100644 index b73abd7653..0000000000 --- a/pufferlib/ocean/template/template.py +++ /dev/null @@ -1,54 +0,0 @@ -'''A minimal template for your own envs.''' - -import gymnasium -import numpy as np - -import pufferlib -from pufferlib.ocean.template import binding - -class Template(pufferlib.PufferEnv): - def __init__(self, num_envs=1, render_mode=None, log_interval=128, size=5, buf=None, seed=0): - self.single_observation_space = gymnasium.spaces.Box(low=0, high=1, - shape=(1,), dtype=np.uint8) - self.single_action_space = gymnasium.spaces.Discrete(2) - self.render_mode = render_mode - self.num_agents = num_envs - - super().__init__(buf) - self.c_envs = binding.vec_init(self.observations, self.actions, self.rewards, - self.terminals, self.truncations, num_envs, seed, size=size) - self.size = size - - def reset(self, seed=0): - binding.vec_reset(self.c_envs, seed) - return self.observations, [] - - def step(self, actions): - self.actions[:] = actions - binding.vec_step(self.c_envs) - info = [binding.vec_log(self.c_envs)] - return (self.observations, self.rewards, - self.terminals, self.truncations, info) - - def render(self): - binding.vec_render(self.c_envs, 0) - - def close(self): - binding.vec_close(self.c_envs) - -if __name__ == '__main__': - N = 4096 - env = Template(num_envs=N) - env.reset() - steps = 0 - - CACHE = 1024 - actions = np.random.randint(0, 5, (CACHE, N)) - - import time - start = time.time() - while time.time() - start < 10: - env.step(actions[steps % CACHE]) - steps += 1 - - print('Squared SPS:', int(env.num_agents*steps / (time.time() - start))) diff --git a/pufferlib/ocean/terraform/binding.c b/pufferlib/ocean/terraform/binding.c deleted file mode 100644 index 1c88f2aab4..0000000000 --- a/pufferlib/ocean/terraform/binding.c +++ /dev/null @@ -1,22 +0,0 @@ -#include "terraform.h" - -#define Env Terraform -#include "../env_binding.h" - -static int my_init(Env* env, PyObject* args, PyObject* kwargs) { - env->size = unpack(kwargs, "size"); - env->num_agents = unpack(kwargs, "num_agents"); - env->reward_scale = unpack(kwargs, "reward_scale"); - env->reset_frequency = unpack(kwargs, "reset_frequency"); - init(env); - return 0; -} - -static int my_log(PyObject* dict, Log* log) { - assign_to_dict(dict, "perf", log->perf); - assign_to_dict(dict, "score", log->score); - assign_to_dict(dict, "episode_return", log->episode_return); - assign_to_dict(dict, "episode_length", log->episode_length); - assign_to_dict(dict, "quadrant_progress", log->quadrant_progress); - return 0; -} diff --git a/pufferlib/ocean/terraform/terraform.c b/pufferlib/ocean/terraform/terraform.c deleted file mode 100644 index 02bb4fcb64..0000000000 --- a/pufferlib/ocean/terraform/terraform.c +++ /dev/null @@ -1,247 +0,0 @@ -#include "terraform.h" -#include "puffernet.h" - -void allocate(Terraform* env) { - env->observations = (float*)calloc(env->num_agents*442, sizeof(float)); - env->actions = (int*)calloc(3*env->num_agents, sizeof(int)); - env->rewards = (float*)calloc(env->num_agents, sizeof(float)); - env->terminals = (unsigned char*)calloc(env->num_agents, sizeof(unsigned char)); - init(env); -} - -void free_allocated(Terraform* env) { - free(env->observations); - free(env->actions); - free(env->rewards); - free(env->terminals); - free_initialized(env); -} - -typedef struct TerraformNet TerraformNet; -struct TerraformNet { - int num_agents; - float* local_obs2d; - float* global_obs2d; - float* obs_1d; - Conv2D* local_conv1; - ReLU* relu1; - Conv2D* local_conv2; - ReLU* relu2; - Conv2D* global_conv1; - ReLU* relu3; - Conv2D* global_conv2; - ReLU* relu4; - Linear* flat; - CatDim1* cat1; - CatDim1* cat2; - Linear* proj; - ReLU* relu5; - LSTM* lstm; - Linear* actor; - Linear* value_fn; - Multidiscrete* multidiscrete; -}; -TerraformNet* init_terranet(Weights* weights, int num_agents, int vision_size, int quadrant_size) { - TerraformNet* net = calloc(1, sizeof(TerraformNet)); - int hidden_size = 512; - int cnn_channels = 32; - int local_conv1_output_size = 3; - int local_conv2_output_size = 1; - int global_conv1_output_size = 4; - int global_conv2_output_size = 2; - int local_cnn_flat_size = cnn_channels * (local_conv2_output_size * local_conv2_output_size); - int global_cnn_flat_size = cnn_channels * (global_conv2_output_size * global_conv2_output_size); - - net->num_agents = num_agents; - net->local_obs2d = calloc(num_agents * vision_size * vision_size * 2, sizeof(float)); // 2 channels - height map & deltas - net->global_obs2d = calloc(num_agents * quadrant_size * quadrant_size * 2, sizeof(float)); // 2 channels - global volume map and agent location - net->obs_1d = calloc(num_agents * 5, sizeof(float)); // 2 additional features - - net->local_conv1 = make_conv2d(weights, num_agents, vision_size, vision_size, 2, cnn_channels, 5, 3); - net->relu1 = make_relu(num_agents, cnn_channels * local_conv1_output_size * local_conv1_output_size); - net->local_conv2 = make_conv2d(weights, num_agents, local_conv1_output_size, local_conv1_output_size, cnn_channels, cnn_channels, 3, 1); - net->relu2 = make_relu(num_agents, cnn_channels * local_conv2_output_size * local_conv2_output_size); - net->global_conv1 = make_conv2d(weights, num_agents, quadrant_size, quadrant_size, 2, cnn_channels, 3, 1); - net->relu3 = make_relu(num_agents, cnn_channels * global_conv1_output_size * global_conv1_output_size); - net->global_conv2 = make_conv2d(weights, num_agents, global_conv1_output_size, global_conv1_output_size, cnn_channels, cnn_channels, 3, 1); - net->relu4 = make_relu(num_agents, cnn_channels * global_conv2_output_size * global_conv2_output_size); - net->flat = make_linear(weights, num_agents, 5, hidden_size); - net->cat1 = make_cat_dim1(num_agents, local_cnn_flat_size, global_cnn_flat_size); - net->cat2 = make_cat_dim1(num_agents, local_cnn_flat_size + global_cnn_flat_size, hidden_size); - net->proj = make_linear(weights, num_agents, local_cnn_flat_size + global_cnn_flat_size + hidden_size, hidden_size); - net->relu5 = make_relu(num_agents, hidden_size); - net->actor = make_linear(weights, num_agents, hidden_size, 13); // +1 for pass move - net->value_fn = make_linear(weights, num_agents, hidden_size, 1); - net->lstm = make_lstm(weights, num_agents, hidden_size, 512); - int logit_sizes[3] = {5, 5, 3}; - net->multidiscrete = make_multidiscrete(num_agents, logit_sizes, 3); - return net; -} - -void free_terranet(TerraformNet* net) { - free(net->local_obs2d); - free(net->global_obs2d); - free(net->obs_1d); - free(net->local_conv1); - free(net->relu1); - free(net->local_conv2); - free(net->relu2); - free(net->global_conv1); - free(net->relu3); - free(net->global_conv2); - free(net->relu4); - free(net->flat); - free(net->cat1); - free(net->cat2); - free(net->proj); - free(net->relu5); - free(net->lstm); - free(net->actor); - free(net->value_fn); - free(net); -} - -void forward(TerraformNet* net, float* observations, int* actions, int vision_size, int quadrant_size) { - int local_vision_size = vision_size * vision_size; - int global_quadrant_size = quadrant_size * quadrant_size; - // Clear previous observations - memset(net->local_obs2d, 0, net->num_agents * vision_size * vision_size * 2 * sizeof(float)); - memset(net->global_obs2d, 0, net->num_agents * quadrant_size * quadrant_size * 2 * sizeof(float)); - memset(net->obs_1d, 0, net->num_agents * 5 * sizeof(float)); - - // Reshape observations into 2D boards and additional features - float (*local_obs2d)[2][vision_size][vision_size] = (float (*)[2][vision_size][vision_size])net->local_obs2d; - float (*global_obs2d)[2][quadrant_size][quadrant_size] = (float (*)[2][quadrant_size][quadrant_size])net->global_obs2d; - float (*obs_1d)[5] = (float (*)[5])net->obs_1d; - - for (int b = 0; b < net->num_agents; b++) { - int b_offset = b * (local_vision_size * 2 + global_quadrant_size * 2 + 5); // offset for each batch - - // Process local vision board - int obs_2d_idx = 0; - for(int z = 0; z < 2; z++) { - for (int i = 0; i < vision_size; i++) { - for (int j = 0; j < vision_size; j++) { - local_obs2d[b][z][i][j] = observations[b_offset + obs_2d_idx]; - obs_2d_idx++; - } - } - } - - // Process additional features - obs_1d[b][0] = observations[b_offset + obs_2d_idx]; - obs_1d[b][1] = observations[b_offset + obs_2d_idx + 1]; - obs_1d[b][2] = observations[b_offset + obs_2d_idx + 2]; - obs_1d[b][3] = observations[b_offset + obs_2d_idx + 3]; - obs_1d[b][4] = observations[b_offset + obs_2d_idx + 4]; - obs_2d_idx += 5; - - // Process global quadrant board - for(int z = 0; z < 2; z++) { - for (int i = 0; i < quadrant_size; i++) { - for (int j = 0; j < quadrant_size; j++) { - global_obs2d[b][z][i][j] = observations[b_offset + obs_2d_idx]; - obs_2d_idx++; - } - } - } - } - - // Forward pass through the network - // local convs - conv2d(net->local_conv1, net->local_obs2d); - relu(net->relu1, net->local_conv1->output); - conv2d(net->local_conv2, net->relu1->output); - relu(net->relu2, net->local_conv2->output); - // global convs - conv2d(net->global_conv1, net->global_obs2d); - relu(net->relu3, net->global_conv1->output); - conv2d(net->global_conv2, net->relu3->output); - relu(net->relu4, net->global_conv2->output); - - linear(net->flat, net->obs_1d); - - cat_dim1(net->cat1, net->relu2->output, net->relu4->output); - cat_dim1(net->cat2, net->cat1->output, net->flat->output); - linear(net->proj, net->cat2->output); - relu(net->relu5, net->proj->output); - - lstm(net->lstm, net->relu5->output); - linear(net->actor, net->lstm->state_h); - linear(net->value_fn, net->lstm->state_h); - - // Get action by taking argmax of actor output - softmax_multidiscrete(net->multidiscrete, net->actor->output, actions); - -} - -void demo() { - Weights* weights = load_weights("resources/terraform/puffer_terraform_weights.bin", 2476814); - TerraformNet* net = init_terranet(weights, 1, 11, 6); - srand(time(NULL)); - Terraform env = {.size = 64, .num_agents = 1, .reset_frequency = 8192, .reward_scale = 0.04f}; - allocate(&env); - - c_reset(&env); - c_render(&env); - while (!WindowShouldClose()) { - forward(net, env.observations, env.actions, 11, 6); - int policy_actions[3] = {env.actions[0], env.actions[1], env.actions[2]}; - - if(IsKeyDown(KEY_LEFT_SHIFT)) { - // When shift is held, stop the dozer - env.actions[0] = 2; // Stop vertical movement - env.actions[1] = 2; // Stop horizontal movement - env.actions[2] = 0; // no scoop or drop - // Override with keyboard controls if keys are pressed - if (IsKeyPressed(KEY_UP) || IsKeyPressed(KEY_W)) env.actions[0] = 4; - if (IsKeyPressed(KEY_DOWN) || IsKeyPressed(KEY_S)) env.actions[0] = 0; - if (IsKeyDown(KEY_LEFT) || IsKeyDown(KEY_A)) env.actions[1] = 0; - if (IsKeyDown(KEY_RIGHT) || IsKeyDown(KEY_D)) env.actions[1] = 4; - if (IsKeyPressed(KEY_SPACE)) env.actions[2] = 1; - if (IsKeyPressed(KEY_ENTER)) env.actions[2] = 2; - } - c_step(&env); - c_render(&env); - } - free_allocated(&env); - close_client(env.client); - free_terranet(net); - free(weights); -} - -void test_performance(int timeout) { - srand(time(NULL)); - Terraform env = { - .size = 64, - .num_agents = 8, - .reset_frequency = 512, - .reward_scale = 0.01f, - }; - allocate(&env); - c_reset(&env); - - int start = time(NULL); - int num_steps = 0; - while (time(NULL) - start < timeout) { - for (int i = 0; i < env.num_agents; i++) { - env.actions[3*i] = rand() % 5; - env.actions[3*i + 1] = rand() % 5; - env.actions[3*i + 2] = rand() % 3; - } - - c_step(&env); - num_steps++; - } - - int end = time(NULL); - float sps = num_steps * env.num_agents / (end - start); - printf("Test Environment SPS: %f\n", sps); - free_allocated(&env); -} - -int main() { - // test_performance(10); - demo(); -} - diff --git a/pufferlib/ocean/terraform/terraform.py b/pufferlib/ocean/terraform/terraform.py deleted file mode 100644 index 9bb886d179..0000000000 --- a/pufferlib/ocean/terraform/terraform.py +++ /dev/null @@ -1,85 +0,0 @@ -'''A simple sample environment. Use this as a template for your own envs.''' - -import gymnasium -import numpy as np -import random -import pufferlib -from pufferlib.ocean.terraform import binding -import time -OBS_SIZE = 11 - -class Terraform(pufferlib.PufferEnv): - def __init__(self, num_envs=1, num_agents=8, map_size=64, - render_mode=None, log_interval=32, buf=None, seed=0, reset_frequency=8192, - reward_scale=0.01): - self.single_observation_space = gymnasium.spaces.Box(low=0, high=1, - shape=(2*OBS_SIZE*OBS_SIZE + 5 + 36*2,), dtype=np.float32) - self.single_action_space = gymnasium.spaces.MultiDiscrete([5, 5, 3], dtype=np.int32) - self.render_mode = render_mode - self.num_agents = num_envs*num_agents - self.log_interval = log_interval - self.reset_frequency = reset_frequency - self.reward_scale = reward_scale - super().__init__(buf) - c_envs = [] - for i in range(num_envs): - c_env = binding.env_init( - self.observations[i*num_agents:(i+1)*num_agents], - self.actions[i*num_agents:(i+1)*num_agents], - self.rewards[i*num_agents:(i+1)*num_agents], - self.terminals[i*num_agents:(i+1)*num_agents], - self.truncations[i*num_agents:(i+1)*num_agents], - seed, - size=map_size, - num_agents=num_agents, - reset_frequency=reset_frequency, - reward_scale=reward_scale, - ) - c_envs.append(c_env) - - self.c_envs = binding.vectorize(*c_envs) - - def reset(self, seed=None): - binding.vec_reset(self.c_envs, seed) - self.tick = 0 - return self.observations, [] - - def step(self, actions): - self.tick += 1 - self.actions[:] = actions - binding.vec_step(self.c_envs) - - episode_returns = self.rewards[self.terminals] - - info = [] - if self.tick % self.log_interval == 0: - info.append(binding.vec_log(self.c_envs)) - - return (self.observations, self.rewards, - self.terminals, self.truncations, info) - - def render(self): - binding.vec_render(self.c_envs, 0) - - def close(self): - binding.vec_close(self.c_envs) - -if __name__ == '__main__': - TIME = 10 - env = Terraform(num_envs=512, num_agents=1, render_mode='human', map_size=64, seed=0) - actions = np.random.randint(0, 5, (512, 3)) # Changed from the stack approach - - - import time - steps = 0 - start = time.time() - while time.time() - start < TIME: - env.step(actions) - steps += 2048 - - print('SPS:', env.num_agents * steps / (time.time() - start)) - - - - - diff --git a/pufferlib/ocean/tetris/binding.c b/pufferlib/ocean/tetris/binding.c deleted file mode 100644 index 213b258420..0000000000 --- a/pufferlib/ocean/tetris/binding.c +++ /dev/null @@ -1,32 +0,0 @@ -#include "tetris.h" - -#define Env Tetris -#include "../env_binding.h" - -static int my_init(Env* env, PyObject* args, PyObject* kwargs) { - env->n_rows = unpack(kwargs, "n_rows"); - env->n_cols = unpack(kwargs, "n_cols"); - env->use_deck_obs = unpack(kwargs, "use_deck_obs"); - env->n_noise_obs = unpack(kwargs, "n_noise_obs"); - env->n_init_garbage = unpack(kwargs, "n_init_garbage"); - init(env); - return 0; -} - -static int my_log(PyObject* dict, Log* log) { - assign_to_dict(dict, "score", log->score); - assign_to_dict(dict, "perf", log->perf); - assign_to_dict(dict, "ep_length", log->ep_length); - assign_to_dict(dict, "ep_return", log->ep_return); - assign_to_dict(dict, "avg_combo", log->avg_combo); - assign_to_dict(dict, "lines_deleted", log->lines_deleted); - assign_to_dict(dict, "game_level", log->game_level); - assign_to_dict(dict, "ticks_per_line", log->ticks_per_line); - - // assign_to_dict(dict, "atn_frac_soft_drop", log->atn_frac_soft_drop); - assign_to_dict(dict, "atn_frac_hard_drop", log->atn_frac_hard_drop); - assign_to_dict(dict, "atn_frac_rotate", log->atn_frac_rotate); - assign_to_dict(dict, "atn_frac_hold", log->atn_frac_hold); - - return 0; -} \ No newline at end of file diff --git a/pufferlib/ocean/tetris/tetris.c b/pufferlib/ocean/tetris/tetris.c deleted file mode 100644 index ea014e05e5..0000000000 --- a/pufferlib/ocean/tetris/tetris.c +++ /dev/null @@ -1,103 +0,0 @@ -#include -#include "tetris.h" -#include "puffernet.h" -#define min(a, b) (((a) < (b)) ? (a) : (b)) -#define max(a, b) (((a) > (b)) ? (a) : (b)) - -// Network with hidden size 256. Should go to puffernet -LinearLSTM* make_linearlstm_256(Weights* weights, int num_agents, int input_dim, int logit_sizes[], int num_actions) { - LinearLSTM* net = calloc(1, sizeof(LinearLSTM)); - net->num_agents = num_agents; - net->obs = calloc(num_agents*input_dim, sizeof(float)); - int hidden_dim = 256; - net->encoder = make_linear(weights, num_agents, input_dim, hidden_dim); - net->gelu1 = make_gelu(num_agents, hidden_dim); - int atn_sum = 0; - for (int i = 0; i < num_actions; i++) { - atn_sum += logit_sizes[i]; - } - net->actor = make_linear(weights, num_agents, hidden_dim, atn_sum); - net->value_fn = make_linear(weights, num_agents, hidden_dim, 1); - net->lstm = make_lstm(weights, num_agents, hidden_dim, hidden_dim); - net->multidiscrete = make_multidiscrete(num_agents, logit_sizes, num_actions); - return net; -} - - -void demo() { - Tetris env = { - .n_rows = 20, - .n_cols = 10, - .use_deck_obs = true, - .n_noise_obs = 0, - .n_init_garbage = 0, - }; - allocate(&env); - env.client = make_client(&env); - c_reset(&env); - - Weights* weights = load_weights("resources/tetris/tetris_weights.bin", 588552); - int logit_sizes[1] = {7}; - LinearLSTM* net = make_linearlstm_256(weights, 1, 234, logit_sizes, 1); - - // State tracking for single-press actions to avoid using IsKeyPressed - // because IsKeyPressed doesn't work well in web browsers - static bool rotate_key_was_down = false; - static bool hard_drop_key_was_down = false; - static bool swap_key_was_down = false; - - int frame = 0; - env.actions[0] = 0; - while (!WindowShouldClose()) { - bool process_logic = true; - frame++; - - if (IsKeyDown(KEY_LEFT_SHIFT)) { - if (frame % 3 != 0) { - // This effectively slows down the client by 3x - process_logic = false; - } else { - // Use KeyDown for left, right, down to allow continuous input - // Though, IsKeyDown can overshoot ... - if (IsKeyDown(KEY_LEFT) || IsKeyDown(KEY_A)) { - env.actions[0] = 1; - } else if (IsKeyDown(KEY_RIGHT) || IsKeyDown(KEY_D)) { - env.actions[0] = 2; - } else if (IsKeyDown(KEY_DOWN) || IsKeyDown(KEY_S)) { - env.actions[0] = 4; // Soft drop - } - // Manual state tracking for single-press actions, mutually exclusive - else if ((IsKeyDown(KEY_UP) || IsKeyDown(KEY_W)) && !rotate_key_was_down) { - env.actions[0] = 3; // Rotate - } else if (IsKeyDown(KEY_SPACE) && !hard_drop_key_was_down) { - env.actions[0] = 5; // Hard drop - } else if (IsKeyDown(KEY_C) && !swap_key_was_down) { - env.actions[0] = 6; // Swap - } - } - } else { - forward_linearlstm(net, env.observations, env.actions); - } - - if (process_logic) { - // Update key state flags after processing actions for the frame - rotate_key_was_down = IsKeyDown(KEY_UP) || IsKeyDown(KEY_W); - hard_drop_key_was_down = IsKeyDown(KEY_SPACE); - swap_key_was_down = IsKeyDown(KEY_C); - - c_step(&env); - - env.actions[0] = 0; - } - - c_render(&env); - } - - free_linearlstm(net); - free_allocated(&env); - close_client(env.client); -} - -int main() { - demo(); -} diff --git a/pufferlib/ocean/tetris/tetris.py b/pufferlib/ocean/tetris/tetris.py deleted file mode 100644 index a566272e2d..0000000000 --- a/pufferlib/ocean/tetris/tetris.py +++ /dev/null @@ -1,90 +0,0 @@ -import gymnasium -import numpy as np -import pufferlib -from pufferlib.ocean.tetris import binding - -class Tetris(pufferlib.PufferEnv): - def __init__( - self, - num_envs=1, - n_cols=10, - n_rows=20, - use_deck_obs=True, - n_noise_obs=10, - n_init_garbage=4, - render_mode=None, - log_interval=32, - buf=None, - seed=0 - ): - self.single_observation_space = gymnasium.spaces.Box(low=0, high=1, - shape=(n_cols*n_rows + 6 + 7 * 4 + n_noise_obs,), dtype=np.float32) - self.single_action_space = gymnasium.spaces.Discrete(7) - self.render_mode = render_mode - self.log_interval = log_interval - self.num_agents = num_envs - - super().__init__(buf) - self.n_cols = n_cols - self.n_rows = n_rows - self.c_envs = binding.vec_init( - self.observations, - self.actions, - self.rewards, - self.terminals, - self.truncations, - num_envs, - seed, - n_cols=n_cols, - n_rows=n_rows, - use_deck_obs=use_deck_obs, - n_noise_obs=n_noise_obs, - n_init_garbage=n_init_garbage, - ) - - def reset(self, seed=0): - binding.vec_reset(self.c_envs, seed) - self.tick = 0 - return self.observations, [] - - def step(self, actions): - self.actions[:] = actions - - self.tick += 1 - binding.vec_step(self.c_envs) - - info = [] - if self.tick % self.log_interval == 0: - info.append(binding.vec_log(self.c_envs)) - - return (self.observations, self.rewards, - self.terminals, self.truncations, info) - - def render(self): - binding.vec_render(self.c_envs, 0) - - def close(self): - binding.vec_close(self.c_envs) - -if __name__ == '__main__': - TIME = 10 - num_envs = 4096 - env = Tetris(num_envs=num_envs) - actions = [ - [env.single_action_space.sample() for _ in range(num_envs) ]for _ in range(1000) - ] - obs, _ = env.reset(seed = np.random.randint(0,1000)) - - import time - start = time.time() - tick = 0 - - while time.time() - start < TIME: - action = actions[tick%1000] - env.render() - print(np.array(obs[0][0:200]).reshape(20,10), obs[0][200:206], obs[0][206:]) - obs, _, _, _, _ = env.step(action) - tick += 1 - print('SPS:', (tick*num_envs) / (time.time() - start)) - env.close() - diff --git a/pufferlib/ocean/tmaze/README.md b/pufferlib/ocean/tmaze/README.md deleted file mode 100644 index 15b722492f..0000000000 --- a/pufferlib/ocean/tmaze/README.md +++ /dev/null @@ -1,15 +0,0 @@ -The T-maze is designed to test the memory capacity of RL algorithms under partial observability. - -* The maze consists of a corridor of length N, ending in a T-junction with two final states (left and right). -* Start condition: At the first tile of the corridor, the observation contains a special marker (3 or 4). This marker determines which final state (left or right) will yield reward +1 and which yields -1. -* Termination: The episode terminates immediately when the agent reaches a final state. -* Observations: local observation: obs = [current, front, left, right] with values: 0=wall, 1=open, 2&3 being the two possible states of the starting tile. -* Actions: The agent can either go forward, left or right. It can not go back or turn inside the corridor -* Rewards: Rewards are 0 everywhere except on the final states. If the starting state was a 2, the reward of 1 is on the left and -1 on the right. If the starting state was a 3, the reward of 1 is on the right and -1 on the left. - -Examples of observations: - -* Middle of corridor: [1,1,0,0] -* At T-junction: [1,0,1,1] -* Starting state: [3,1,0,0] -* At a final/terminal state: [1,0,0,0] diff --git a/pufferlib/ocean/tmaze/tmaze.py b/pufferlib/ocean/tmaze/tmaze.py deleted file mode 100644 index 4948b7ae1c..0000000000 --- a/pufferlib/ocean/tmaze/tmaze.py +++ /dev/null @@ -1,64 +0,0 @@ -'''A simple sample environment. Use this as a template for your own envs.''' - -import gymnasium -import numpy as np - -import pufferlib -from pufferlib.ocean.tmaze import binding - -class TMaze(pufferlib.PufferEnv): - def __init__(self, num_envs=1, render_mode=None, log_interval=128, size=11, buf=None, seed=0): - self.single_observation_space = gymnasium.spaces.Box(low=0, high=1, - shape=(4,), dtype=np.uint8) - self.single_action_space = gymnasium.spaces.Discrete(3) - self.render_mode = render_mode - self.num_agents = num_envs - self.log_interval = log_interval - - super().__init__(buf) - self.c_envs = binding.vec_init(self.observations, self.actions, self.rewards, - self.terminals, self.truncations, num_envs, seed, size=size) - - def reset(self, seed=0): - binding.vec_reset(self.c_envs, seed) - self.tick = 0 - return self.observations, [] - - def step(self, actions): - self.tick += 1 - - self.actions[:] = actions - binding.vec_step(self.c_envs) - - info = [] - if self.tick % self.log_interval == 0: - info.append(binding.vec_log(self.c_envs)) - - return (self.observations, self.rewards, - self.terminals, self.truncations, info) - - def render(self): - binding.vec_render(self.c_envs, 0) - - def close(self): - binding.vec_close(self.c_envs) - -if __name__ == '__main__': - size = 10 - - env = TMaze(size=size) - env.reset() - steps = 0 - - CACHE = 1024 - actions = np.random.randint(0, 3, (CACHE,)) - - i = 0 - import time - start = time.time() - while time.time() - start < 10: - env.step(actions[i % CACHE]) - steps += 1 - i += 1 - - print('Chain MDP SPS:', int(steps / (time.time() - start))) diff --git a/pufferlib/ocean/torch.py b/pufferlib/ocean/torch.py deleted file mode 100644 index c7663c5f5b..0000000000 --- a/pufferlib/ocean/torch.py +++ /dev/null @@ -1,965 +0,0 @@ -from types import SimpleNamespace -from typing import Any, Tuple - -from gymnasium import spaces - -from torch import nn -import torch -from torch.distributions.normal import Normal -from torch import nn -import torch.nn.functional as F - -import pufferlib -import pufferlib.models - -from pufferlib.models import Default as Policy -from pufferlib.models import Convolutional as Conv -Recurrent = pufferlib.models.LSTMWrapper -from pufferlib.pytorch import layer_init, _nativize_dtype, nativize_tensor -import numpy as np - - -class Boids(nn.Module): - def __init__(self, env, cnn_channels=32, hidden_size=128, **kwargs): - super().__init__() - self.hidden_size = hidden_size - self.is_continuous = False - self.network = nn.Sequential( - pufferlib.pytorch.layer_init(nn.Linear(4, hidden_size)), - nn.GELU(), - pufferlib.pytorch.layer_init(nn.Linear(hidden_size, hidden_size)), - ) - self.action_vec = tuple(env.single_action_space.nvec) - self.actor = pufferlib.pytorch.layer_init( - nn.Linear(hidden_size, sum(self.action_vec)), std=0.01) - self.value_fn = pufferlib.pytorch.layer_init( - nn.Linear(hidden_size, 1), std=1) - - def forward(self, observations, state=None): - hidden = self.encode_observations(observations) - actions, value = self.decode_actions(hidden) - return actions, value - - def forward_train(self, x, state=None): - return self.forward(x, state) - - def encode_observations(self, observations, state=None): - batch, n, = observations.shape - return self.network(observations.reshape(batch, n//4, 4)).max(dim=1)[0] - - def decode_actions(self, flat_hidden, state=None): - value = self.value_fn(flat_hidden) - action = self.actor(flat_hidden).split(self.action_vec, dim=1) - return action, value - -class NMMO3LSTM(pufferlib.models.LSTMWrapper): - def __init__(self, env, policy, input_size=512, hidden_size=512): - super().__init__(env, policy, input_size, hidden_size) - -class NMMO3(nn.Module): - def __init__(self, env, hidden_size=512, output_size=512, **kwargs): - super().__init__() - self.hidden_size = hidden_size - #self.dtype = pufferlib.pytorch.nativize_dtype(env.emulated) - self.num_actions = env.single_action_space.n - self.factors = np.array([4, 4, 17, 5, 3, 5, 5, 5, 7, 4]) - offsets = torch.tensor([0] + list(np.cumsum(self.factors)[:-1])).view(1, -1, 1, 1) - self.register_buffer('offsets', offsets) - self.cum_facs = np.cumsum(self.factors) - - self.multihot_dim = self.factors.sum() - self.is_continuous = False - - self.map_2d = nn.Sequential( - pufferlib.pytorch.layer_init(nn.Conv2d(self.multihot_dim, 128, 5, stride=3)), - nn.ReLU(), - pufferlib.pytorch.layer_init(nn.Conv2d(128, 128, 3, stride=1)), - nn.Flatten(), - ) - - self.player_discrete_encoder = nn.Sequential( - nn.Embedding(128, 32), - nn.Flatten(), - ) - self.proj = nn.Sequential( - pufferlib.pytorch.layer_init(nn.Linear(1817, hidden_size)), - nn.ReLU(), - ) - - self.layer_norm = nn.LayerNorm(hidden_size) - self.actor = pufferlib.pytorch.layer_init( - nn.Linear(output_size, self.num_actions), std=0.01) - self.value_fn = pufferlib.pytorch.layer_init(nn.Linear(output_size, 1), std=1) - - def forward(self, x, state=None): - hidden = self.encode_observations(x) - actions, value = self.decode_actions(hidden) - return actions, value - - def forward_train(self, x, state=None): - return self.forward(x, state) - - def encode_observations(self, observations, state=None): - batch = observations.shape[0] - ob_map = observations[:, :11*15*10].view(batch, 11, 15, 10) - ob_player = observations[:, 11*15*10:-10] - ob_reward = observations[:, -10:] - - batch = ob_map.shape[0] - map_buf = torch.zeros(batch, 59, 11, 15, dtype=torch.float32, device=observations.device) - codes = ob_map.permute(0, 3, 1, 2) + self.offsets - map_buf.scatter_(1, codes, 1) - ob_map = self.map_2d(map_buf) - - player_discrete = self.player_discrete_encoder(ob_player.int()) - - obs = torch.cat([ob_map, player_discrete, ob_player.to(ob_map.dtype), ob_reward], dim=1) - obs = self.proj(obs) - return obs - - def decode_actions(self, flat_hidden): - flat_hidden = self.layer_norm(flat_hidden) - action = self.actor(flat_hidden) - value = self.value_fn(flat_hidden) - return action, value - -class Terraform(nn.Module): - def __init__(self, env, cnn_channels=32, hidden_size=128, **kwargs): - super().__init__() - self.hidden_size = hidden_size - self.is_continuous = False - - self.local_net_2d = nn.Sequential( - pufferlib.pytorch.layer_init( - nn.Conv2d(2, cnn_channels, 5, stride=3)), - nn.ReLU(), - pufferlib.pytorch.layer_init( - nn.Conv2d(cnn_channels, cnn_channels, 3, stride=1)), - nn.ReLU(), - nn.Flatten(), - ) - - self.global_net_2d = nn.Sequential( - pufferlib.pytorch.layer_init( - nn.Conv2d(2, cnn_channels, 3, stride=1)), - nn.ReLU(), - pufferlib.pytorch.layer_init( - nn.Conv2d(cnn_channels, cnn_channels, 3, stride=1)), - nn.ReLU(), - nn.Flatten(), - ) - - self.net_1d = nn.Sequential( - pufferlib.pytorch.layer_init( - nn.Linear(5, hidden_size)), - nn.Flatten(), - ) - self.proj = nn.Sequential( - pufferlib.pytorch.layer_init(nn.Linear(hidden_size + cnn_channels*5, hidden_size)), - nn.ReLU(), - ) - self.atn_dim = env.single_action_space.nvec.tolist() - self.actor = pufferlib.pytorch.layer_init(nn.Linear(hidden_size, sum(self.atn_dim)), std=0.01) - self.value = pufferlib.pytorch.layer_init( - nn.Linear(hidden_size, 1), std=1) - - def forward(self, observations, state=None): - hidden = self.encode_observations(observations, state) - actions, value = self.decode_actions(hidden) - return actions, value - - def forward_train(self, x, state=None): - return self.forward(x, state) - - def encode_observations(self, observations, state=None): - # breakpoint() - obs_2d = observations[:, :242].reshape(-1, 2, 11, 11).float() - obs_1d = observations[:, 242:247].reshape(-1, 5).float() - location_2d = observations[:, 247:].reshape(-1,2, 6, 6).float() - hidden_local_2d = self.local_net_2d(obs_2d) - hidden_global_2d = self.global_net_2d(location_2d) - hidden_1d = self.net_1d(obs_1d) - hidden = torch.cat([hidden_local_2d, hidden_global_2d, hidden_1d], dim=1) - return self.proj(hidden) - - def decode_actions(self, hidden): - action = self.actor(hidden) - action = torch.split(action, self.atn_dim, dim=1) - #action = [head(hidden) for head in self.actor] - value = self.value(hidden) - return action, value - - -class Snake(nn.Module): - def __init__(self, env, cnn_channels=32, hidden_size=128): - super().__init__() - self.hidden_size = hidden_size - self.is_continuous = False - - encode_dim = cnn_channels - - ''' - self.network= nn.Sequential( - pufferlib.pytorch.layer_init( - nn.Conv2d(8, cnn_channels, 5, stride=3)), - nn.ReLU(), - pufferlib.pytorch.layer_init( - nn.Conv2d(cnn_channels, cnn_channels, 3, stride=1)), - nn.ReLU(), - nn.Flatten(), - ) - self.proj = nn.Sequential( - pufferlib.pytorch.layer_init(nn.Linear(encode_dim, hidden_size)), - nn.ReLU(), - ) - - ''' - self.encoder= torch.nn.Sequential( - nn.Linear(8*np.prod(env.single_observation_space.shape), hidden_size), - nn.GELU(), - ) - self.decoder = pufferlib.pytorch.layer_init( - nn.Linear(hidden_size, env.single_action_space.n), std=0.01) - self.value = pufferlib.pytorch.layer_init( - nn.Linear(hidden_size, 1), std=1) - - def forward(self, observations, state=None): - #observations = F.one_hot(observations.long(), 8).permute(0, 3, 1, 2).float() - hidden = self.encode_observations(observations) - actions, value = self.decode_actions(hidden) - return actions, value - - def forward_train(self, x, state=None): - return self.forward(x, state) - - def encode_observations(self, observations, state=None): - observations = F.one_hot(observations.long(), 8).view(-1, 11*11*8).float() - return self.encoder(observations) - - def decode_actions(self, hidden): - action = self.decoder(hidden) - value = self.value(hidden) - return action, value - -''' -class Snake(pufferlib.models.Default): - def __init__(self, env, hidden_size=128): - super().__init__() - - def encode_observations(self, observations, state=None): - observations = F.one_hot(observations.long(), 8).view(-1, 11*11*8).float() - super().encode_observations(observations, state) -''' - -class Grid(nn.Module): - def __init__(self, env, cnn_channels=32, hidden_size=128, **kwargs): - super().__init__() - self.hidden_size = hidden_size - self.network = nn.Sequential( - pufferlib.pytorch.layer_init( - nn.Conv2d(32, cnn_channels, 5, stride=3)), - nn.ReLU(), - pufferlib.pytorch.layer_init( - nn.Conv2d(cnn_channels, cnn_channels, 3, stride=1)), - nn.Flatten(), - nn.ReLU(), - pufferlib.pytorch.layer_init(nn.Linear(cnn_channels, hidden_size)), - nn.ReLU(), - ) - - self.is_continuous = isinstance(env.single_action_space, pufferlib.spaces.Box) - if self.is_continuous: - self.decoder_mean = pufferlib.pytorch.layer_init( - nn.Linear(hidden_size, env.single_action_space.shape[0]), std=0.01) - self.decoder_logstd = nn.Parameter(torch.zeros( - 1, env.single_action_space.shape[0])) - else: - num_actions = env.single_action_space.n - self.actor = pufferlib.pytorch.layer_init( - nn.Linear(hidden_size, num_actions), std=0.01) - - self.value_fn = pufferlib.pytorch.layer_init( - nn.Linear(hidden_size, 1), std=1) - - def forward(self, observations, state=None): - hidden = self.encode_observations(observations) - actions, value = self.decode_actions(hidden) - return actions, value - - def forward_train(self, x, state=None): - return self.forward(x, state) - - def encode_observations(self, observations, state=None): - hidden = observations.view(-1, 11, 11).long() - hidden = F.one_hot(hidden, 32).permute(0, 3, 1, 2).float() - hidden = self.network(hidden) - return hidden - - def decode_actions(self, flat_hidden, state=None): - value = self.value_fn(flat_hidden) - if self.is_continuous: - mean = self.decoder_mean(flat_hidden) - logstd = self.decoder_logstd.expand_as(mean) - std = torch.exp(logstd) - probs = torch.distributions.Normal(mean, std) - batch = flat_hidden.shape[0] - return probs, value - else: - action = self.actor(flat_hidden) - return action, value - -class Go(nn.Module): - def __init__(self, env, cnn_channels=64, hidden_size=128, **kwargs): - super().__init__() - self.hidden_size = hidden_size - self.is_continuous = False - # 3 categories 2 boards. - # categories = player, opponent, empty - # boards = current, previous - self.cnn = nn.Sequential( - pufferlib.pytorch.layer_init( - nn.Conv2d(2, cnn_channels, 3, stride=1)), - nn.ReLU(), - pufferlib.pytorch.layer_init( - nn.Conv2d(cnn_channels, cnn_channels, 3, stride = 1)), - nn.Flatten(), - ) - - obs_size = env.single_observation_space.shape[0] - self.grid_size = int(np.sqrt((obs_size-2)/2)) - output_size = self.grid_size - 4 - cnn_flat_size = cnn_channels * output_size * output_size - - self.flat = pufferlib.pytorch.layer_init(nn.Linear(2,32)) - - self.proj = pufferlib.pytorch.layer_init(nn.Linear(cnn_flat_size + 32, hidden_size)) - - self.actor = pufferlib.pytorch.layer_init( - nn.Linear(hidden_size, env.single_action_space.n), std=0.01) - - self.value_fn = pufferlib.pytorch.layer_init( - nn.Linear(hidden_size, 1), std=1) - - def forward(self, observations, state=None): - hidden = self.encode_observations(observations) - actions, value = self.decode_actions(hidden) - return actions, value - - def forward_train(self, x, state=None): - return self.forward(x, state) - - def encode_observations(self, observations, state=None): - grid_size = int(np.sqrt((observations.shape[1] - 2) / 2)) - full_board = grid_size * grid_size - black_board = observations[:, :full_board].view(-1,1, grid_size,grid_size).float() - white_board = observations[:, full_board:-2].view(-1,1, grid_size, grid_size).float() - board_features = torch.cat([black_board, white_board],dim=1) - flat_feature1 = observations[:, -2].unsqueeze(1).float() - flat_feature2 = observations[:, -1].unsqueeze(1).float() - # Pass board through cnn - cnn_features = self.cnn(board_features) - # Pass extra feature - flat_features = torch.cat([flat_feature1, flat_feature2],dim=1) - flat_features = self.flat(flat_features) - # pass all features - features = torch.cat([cnn_features, flat_features], dim=1) - features = F.relu(self.proj(features)) - - return features - - def decode_actions(self, flat_hidden, state=None): - value = self.value_fn(flat_hidden) - action = self.actor(flat_hidden) - return action, value - -class MOBA(nn.Module): - def __init__(self, env, cnn_channels=128, hidden_size=128, **kwargs): - super().__init__() - self.hidden_size = hidden_size - self.cnn = nn.Sequential( - pufferlib.pytorch.layer_init( - nn.Conv2d(16 + 3, cnn_channels, 5, stride=3)), - nn.ReLU(), - pufferlib.pytorch.layer_init( - nn.Conv2d(cnn_channels, cnn_channels, 3, stride=1)), - nn.Flatten(), - ) - self.flat = pufferlib.pytorch.layer_init(nn.Linear(26, 128)) - self.proj = pufferlib.pytorch.layer_init(nn.Linear(128+cnn_channels, hidden_size)) - - self.is_continuous = isinstance(env.single_action_space, pufferlib.spaces.Box) - if self.is_continuous: - self.decoder_mean = pufferlib.pytorch.layer_init( - nn.Linear(hidden_size, env.single_action_space.shape[0]), std=0.01) - self.decoder_logstd = nn.Parameter(torch.zeros( - 1, env.single_action_space.shape[0])) - else: - self.atn_dim = env.single_action_space.nvec.tolist() - self.actor = pufferlib.pytorch.layer_init( - nn.Linear(hidden_size, sum(self.atn_dim)), std=0.01) - - self.value_fn = pufferlib.pytorch.layer_init( - nn.Linear(hidden_size, 1), std=1) - - def forward(self, observations, state=None): - hidden = self.encode_observations(observations) - actions, value = self.decode_actions(hidden) - return actions, value - - def forward_train(self, x, state=None): - return self.forward(x, state) - - def encode_observations(self, observations, state=None): - cnn_features = observations[:, :-26].view(-1, 11, 11, 4).long() - map_features = F.one_hot(cnn_features[:, :, :, 0], 16).permute(0, 3, 1, 2).float() - extra_map_features = (cnn_features[:, :, :, -3:].float() / 255).permute(0, 3, 1, 2) - cnn_features = torch.cat([map_features, extra_map_features], dim=1) - #print('observations 2d: ', map_features[0].cpu().numpy().tolist()) - cnn_features = self.cnn(cnn_features) - #print('cnn features: ', cnn_features[0].detach().cpu().numpy().tolist()) - - flat_features = observations[:, -26:].float() / 255.0 - #print('observations 1d: ', flat_features[0, 0]) - flat_features = self.flat(flat_features) - #print('flat features: ', flat_features[0].detach().cpu().numpy().tolist()) - - features = torch.cat([cnn_features, flat_features], dim=1) - features = F.relu(self.proj(F.relu(features))) - #print('features: ', features[0].detach().cpu().numpy().tolist()) - return features - - def decode_actions(self, flat_hidden): - #print('lstm: ', flat_hidden[0].detach().cpu().numpy().tolist()) - value = self.value_fn(flat_hidden) - if self.is_continuous: - mean = self.decoder_mean(flat_hidden) - logstd = self.decoder_logstd.expand_as(mean) - std = torch.exp(logstd) - probs = torch.distributions.Normal(mean, std) - batch = flat_hidden.shape[0] - return probs, value - else: - action = self.actor(flat_hidden) - action = torch.split(action, self.atn_dim, dim=1) - - #argmax_samples = [torch.argmax(a, dim=1).detach().cpu().numpy().tolist() for a in action] - #print('argmax samples: ', argmax_samples) - - return action, value - -class TrashPickup(nn.Module): - def __init__(self, env, cnn_channels=32, hidden_size=128, **kwargs): - super().__init__() - self.hidden_size = hidden_size - self.is_continuous = False - self.network= nn.Sequential( - pufferlib.pytorch.layer_init( - nn.Conv2d(5, cnn_channels, 5, stride=3)), - nn.ReLU(), - pufferlib.pytorch.layer_init( - nn.Conv2d(cnn_channels, cnn_channels, 3, stride=1)), - nn.ReLU(), - nn.Flatten(), - pufferlib.pytorch.layer_init(nn.Linear(cnn_channels, hidden_size)), - ) - self.actor = pufferlib.pytorch.layer_init( - nn.Linear(hidden_size, env.single_action_space.n), std=0.01) - self.value_fn = pufferlib.pytorch.layer_init( - nn.Linear(hidden_size, 1), std=1) - - def forward(self, observations, state=None): - hidden = self.encode_observations(observations) - actions, value = self.decode_actions(hidden) - return actions, value - - def forward_train(self, x, state=None): - return self.forward(x, state) - - def encode_observations(self, observations, state=None): - observations = observations.view(-1, 5, 11, 11).float() - return self.network(observations) - - def decode_actions(self, flat_hidden): - action = self.actor(flat_hidden) - value = self.value_fn(flat_hidden) - return action, value - -class TowerClimbLSTM(pufferlib.models.LSTMWrapper): - def __init__(self, env, policy, input_size = 256, hidden_size = 256): - super().__init__(env, policy, input_size, hidden_size) - -class TowerClimb(nn.Module): - def __init__(self, env, cnn_channels=16, hidden_size = 256, **kwargs): - self.hidden_size = hidden_size - self.is_continuous = False - super().__init__() - self.network = nn.Sequential( - pufferlib.pytorch.layer_init( - nn.Conv3d(1, cnn_channels, 3, stride = 1)), - nn.ReLU(), - pufferlib.pytorch.layer_init( - nn.Conv3d(cnn_channels, cnn_channels, 3, stride=1)), - nn.Flatten() - ) - cnn_flat_size = cnn_channels * 1 * 1 * 5 - - # Process player obs - self.flat = pufferlib.pytorch.layer_init(nn.Linear(3,16)) - - # combine - self.proj = pufferlib.pytorch.layer_init( - nn.Linear(cnn_flat_size + 16, hidden_size)) - self.actor = pufferlib.pytorch.layer_init( - nn.Linear(hidden_size, env.single_action_space.n), std = 0.01) - self.value_fn = pufferlib.pytorch.layer_init( - nn.Linear(hidden_size, 1 ), std=1) - - def forward(self, observations, state=None): - hidden = self.encode_observations(observations) - actions, value = self.decode_actions(hidden) - return actions, value - - def forward_train(self, x, state=None): - return self.forward(x, state) - - def encode_observations(self, observations, state=None): - board_state = observations[:,:225] - player_info = observations[:, -3:] - board_features = board_state.view(-1, 1, 5,5,9).float() - cnn_features = self.network(board_features) - flat_features = self.flat(player_info.float()) - - features = torch.cat([cnn_features,flat_features],dim = 1) - features = self.proj(features) - return features - - def decode_actions(self, flat_hidden): - action = self.actor(flat_hidden) - value = self.value_fn(flat_hidden) - - return action, value - - -class ImpulseWarsLSTM(Recurrent): - def __init__(self, env: pufferlib.PufferEnv, policy: nn.Module, input_size: int = 512, hidden_size: int = 512): - super().__init__(env, policy, input_size, hidden_size) - - -class ImpulseWarsPolicy(nn.Module): - def __init__( - self, - env: pufferlib.PufferEnv, - cnn_channels: int = 64, - weapon_type_embedding_dims: int = 2, - input_size: int = 512, - hidden_size: int = 512, - batch_size: int = 131_072, - num_drones: int = 2, - continuous: bool = False, - is_training: bool = True, - **kwargs, - ): - super().__init__() - self.hidden_size = hidden_size - - self.is_continuous = continuous - - self.numDrones = num_drones - self.isTraining = is_training - from pufferlib.ocean.impulse_wars import binding - self.obsInfo = SimpleNamespace(**binding.get_consts(self.numDrones)) - - self.discreteFactors = np.array( - [self.obsInfo.wallTypes] * self.obsInfo.numNearWallObs - + [self.obsInfo.wallTypes + 1] * self.obsInfo.numFloatingWallObs - + [self.numDrones + 1] * self.obsInfo.numProjectileObs, - ) - discreteOffsets = torch.tensor([0] + list(np.cumsum(self.discreteFactors)[:-1])).view( - 1, -1 - ) - self.register_buffer("discreteOffsets", discreteOffsets, persistent=False) - self.discreteMultihotDim = self.discreteFactors.sum() - - multihotBuffer = torch.zeros(batch_size, self.discreteMultihotDim) - self.register_buffer("multihotOutput", multihotBuffer, persistent=False) - - # most of the observation is a 2D array of bytes, but the end - # contains around 200 floats; this allows us to treat the end - # of the observation as a float array - _, *self.dtype = _nativize_dtype( - np.dtype((np.uint8, (self.obsInfo.continuousObsBytes,))), - np.dtype((np.float32, (self.obsInfo.continuousObsSize,))), - ) - self.dtype = tuple(self.dtype) - - self.weaponTypeEmbedding = nn.Embedding(self.obsInfo.weaponTypes, weapon_type_embedding_dims) - - # each byte in the map observation contains 4 values: - # - 2 bits for wall type - # - 1 bit for is floating wall - # - 1 bit for is weapon pickup - # - 3 bits for drone index - self.register_buffer( - "unpackMask", - torch.tensor([0x60, 0x10, 0x08, 0x07], dtype=torch.uint8), - persistent=False, - ) - self.register_buffer("unpackShift", torch.tensor([5, 4, 3, 0], dtype=torch.uint8), persistent=False) - - self.mapObsInputChannels = (self.obsInfo.wallTypes + 1) + 1 + 1 + self.numDrones - self.mapCNN = nn.Sequential( - layer_init( - nn.Conv2d( - self.mapObsInputChannels, - cnn_channels, - kernel_size=5, - stride=3, - ) - ), - nn.ReLU(), - layer_init(nn.Conv2d(cnn_channels, cnn_channels, kernel_size=3, stride=1)), - nn.ReLU(), - nn.Flatten(), - ) - cnnOutputSize = self._computeCNNShape() - - featuresSize = ( - cnnOutputSize - + (self.obsInfo.numNearWallObs * (self.obsInfo.wallTypes + self.obsInfo.nearWallPosObsSize)) - + ( - self.obsInfo.numFloatingWallObs - * (self.obsInfo.wallTypes + 1 + self.obsInfo.floatingWallInfoObsSize) - ) - + ( - self.obsInfo.numWeaponPickupObs - * (weapon_type_embedding_dims + self.obsInfo.weaponPickupPosObsSize) - ) - + ( - self.obsInfo.numProjectileObs - * (weapon_type_embedding_dims + self.obsInfo.projectileInfoObsSize + self.numDrones + 1) - ) - + ((self.numDrones - 1) * (weapon_type_embedding_dims + self.obsInfo.enemyDroneObsSize)) - + (self.obsInfo.droneObsSize + weapon_type_embedding_dims) - + self.obsInfo.miscObsSize - ) - - self.encoder = nn.Sequential( - layer_init(nn.Linear(featuresSize, input_size)), - nn.ReLU(), - ) - - if self.is_continuous: - self.actorMean = layer_init(nn.Linear(hidden_size, env.single_action_space.shape[0]), std=0.01) - self.actorLogStd = nn.Parameter(torch.zeros(1, env.single_action_space.shape[0])) - else: - self.actionDim = env.single_action_space.nvec.tolist() - self.actor = layer_init(nn.Linear(hidden_size, sum(self.actionDim)), std=0.01) - - self.critic = layer_init(nn.Linear(hidden_size, 1), std=1.0) - - def forward(self, obs: torch.Tensor, state = None) -> Tuple[torch.Tensor, torch.Tensor]: - hidden = self.encode_observations(obs) - actions, value = self.decode_actions(hidden) - return actions, value - - def unpack(self, batchSize: int, obs: torch.Tensor) -> torch.Tensor: - # prepare map obs to be unpacked - mapObs = obs[:, : self.obsInfo.mapObsSize].reshape((batchSize, -1, 1)) - # unpack wall types, weapon pickup types, and drone indexes - mapObs = (mapObs & self.unpackMask) >> self.unpackShift - # reshape so channels are first, required for torch conv2d - return mapObs.permute(0, 2, 1).reshape( - (batchSize, 4, self.obsInfo.mapObsRows, self.obsInfo.mapObsColumns) - ) - - def encode_observations(self, obs: torch.Tensor, state: Any = None) -> torch.Tensor: - batchSize = obs.shape[0] - - mapObs = self.unpack(batchSize, obs) - - # one hot encode wall types - wallTypeObs = mapObs[:, 0, :, :].long() - wallTypes = F.one_hot(wallTypeObs, self.obsInfo.wallTypes + 1).permute(0, 3, 1, 2).float() - - # unsqueeze floating wall booleans (is wall a floating wall) - floatingWallObs = mapObs[:, 1, :, :].unsqueeze(1) - - # unsqueeze map pickup booleans (does map tile contain a weapon pickup) - mapPickupObs = mapObs[:, 2, :, :].unsqueeze(1) - - # one hot drone indexes - droneIndexObs = mapObs[:, 3, :, :].long() - droneIndexes = F.one_hot(droneIndexObs, self.numDrones).permute(0, 3, 1, 2).float() - - # combine all map observations and feed through CNN - mapObs = torch.cat((wallTypes, floatingWallObs, mapPickupObs, droneIndexes), dim=1) - map = self.mapCNN(mapObs) - - # process discrete observations - multihotInput = ( - obs[:, self.obsInfo.nearWallTypesObsOffset : self.obsInfo.projectileTypesObsOffset] - + self.discreteOffsets - ) - multihotOutput = self.multihotOutput[:batchSize].zero_() - multihotOutput.scatter_(1, multihotInput.long(), 1) - - weaponTypeObs = obs[:, self.obsInfo.projectileTypesObsOffset : self.obsInfo.discreteObsSize].int() - weaponTypes = self.weaponTypeEmbedding(weaponTypeObs).float() - weaponTypes = torch.flatten(weaponTypes, start_dim=1, end_dim=-1) - - # process continuous observations - continuousObs = nativize_tensor(obs[:, self.obsInfo.continuousObsOffset :], self.dtype) - # combine all observations and feed through final linear encoder - features = torch.cat((map, multihotOutput, weaponTypes, continuousObs), dim=-1) - - return self.encoder(features) - - def decode_actions(self, hidden: torch.Tensor): - if self.is_continuous: - actionMean = self.actorMean(hidden) - if self.isTraining: - actionLogStd = self.actorLogStd.expand_as(actionMean) - actionStd = torch.exp(actionLogStd) - action = Normal(actionMean, actionStd) - else: - action = actionMean - else: - action = self.actor(hidden) - action = torch.split(action, self.actionDim, dim=1) - - value = self.critic(hidden) - - return action, value - - def _computeCNNShape(self) -> int: - mapSpace = spaces.Box( - low=0, - high=1, - shape=(self.mapObsInputChannels, self.obsInfo.mapObsRows, self.obsInfo.mapObsColumns), - dtype=np.float32, - ) - - with torch.no_grad(): - t = torch.as_tensor(mapSpace.sample()[None]) - return self.mapCNN(t).shape[1] - -class Drive(nn.Module): - def __init__(self, env, input_size=128, hidden_size=128, **kwargs): - super().__init__() - self.hidden_size = hidden_size - self.ego_encoder = nn.Sequential( - pufferlib.pytorch.layer_init( - nn.Linear(7, input_size)), - nn.LayerNorm(input_size), - # nn.ReLU(), - pufferlib.pytorch.layer_init( - nn.Linear(input_size, input_size)) - ) - max_road_objects = 13 - self.road_encoder = nn.Sequential( - pufferlib.pytorch.layer_init( - nn.Linear(max_road_objects, input_size)), - nn.LayerNorm(input_size), - # nn.ReLU(), - pufferlib.pytorch.layer_init( - nn.Linear(input_size, input_size)) - ) - max_partner_objects = 7 - self.partner_encoder = nn.Sequential( - pufferlib.pytorch.layer_init( - nn.Linear(max_partner_objects, input_size)), - nn.LayerNorm(input_size), - # nn.ReLU(), - pufferlib.pytorch.layer_init( - nn.Linear(input_size, input_size)) - ) - - - self.shared_embedding = nn.Sequential( - nn.GELU(), - pufferlib.pytorch.layer_init(nn.Linear(3*input_size, hidden_size)), - ) - self.is_continuous = isinstance(env.single_action_space, pufferlib.spaces.Box) - - self.atn_dim = env.single_action_space.nvec.tolist() - self.actor = pufferlib.pytorch.layer_init( - nn.Linear(hidden_size, sum(self.atn_dim)), std = 0.01) - self.value_fn = pufferlib.pytorch.layer_init( - nn.Linear(hidden_size, 1 ), std=1) - - def forward(self, observations, state=None): - hidden = self.encode_observations(observations) - actions, value = self.decode_actions(hidden) - return actions, value - - def forward_train(self, x, state=None): - return self.forward(x, state) - - def encode_observations(self, observations, state=None): - ego_dim = 7 - partner_dim = 63 * 7 - road_dim = 200*7 - ego_obs = observations[:, :ego_dim] - partner_obs = observations[:, ego_dim:ego_dim+partner_dim] - road_obs = observations[:, ego_dim+partner_dim:ego_dim+partner_dim+road_dim] - - partner_objects = partner_obs.view(-1, 63, 7) - road_objects = road_obs.view(-1, 200, 7) - road_continuous = road_objects[:, :, :6] # First 6 features - road_categorical = road_objects[:, :, 6] - road_onehot = F.one_hot(road_categorical.long(), num_classes=7) # Shape: [batch, 200, 7] - road_objects = torch.cat([road_continuous, road_onehot], dim=2) - ego_features = self.ego_encoder(ego_obs) - partner_features, _ = self.partner_encoder(partner_objects).max(dim=1) - road_features, _ = self.road_encoder(road_objects).max(dim=1) - - concat_features = torch.cat([ego_features, road_features, partner_features], dim=1) - - # Pass through shared embedding - embedding = F.relu(self.shared_embedding(concat_features)) - # embedding = self.shared_embedding(concat_features) - return embedding - - def decode_actions(self, flat_hidden): - action = self.actor(flat_hidden) - action = torch.split(action, self.atn_dim, dim=1) - value = self.value_fn(flat_hidden) - return action, value - -class Drone(nn.Module): - ''' Drone policy. Flattens obs and applies a linear layer. - ''' - def __init__(self, env, hidden_size=128): - super().__init__() - self.hidden_size = hidden_size - self.is_multidiscrete = isinstance(env.single_action_space, - pufferlib.spaces.MultiDiscrete) - self.is_continuous = isinstance(env.single_action_space, - pufferlib.spaces.Box) - try: - self.is_dict_obs = isinstance(env.env.observation_space, pufferlib.spaces.Dict) - except: - self.is_dict_obs = isinstance(env.observation_space, pufferlib.spaces.Dict) - - if self.is_dict_obs: - self.dtype = pufferlib.pytorch.nativize_dtype(env.emulated) - input_size = int(sum(np.prod(v.shape) for v in env.env.observation_space.values())) - self.encoder = nn.Linear(input_size, self.hidden_size) - else: - self.encoder = torch.nn.Sequential( - nn.Linear(np.prod(env.single_observation_space.shape), hidden_size), - nn.GELU(), - ) - - if self.is_multidiscrete: - self.action_nvec = tuple(env.single_action_space.nvec) - self.decoder = pufferlib.pytorch.layer_init( - nn.Linear(hidden_size, sum(self.action_nvec)), std=0.01) - elif not self.is_continuous: - self.decoder = pufferlib.pytorch.layer_init( - nn.Linear(hidden_size, env.single_action_space.n), std=0.01) - else: - self.decoder_mean = pufferlib.pytorch.layer_init( - nn.Linear(hidden_size, env.single_action_space.shape[0]), std=0.01) - self.decoder_logstd = nn.Parameter(torch.zeros( - 1, env.single_action_space.shape[0])) - - self.value = pufferlib.pytorch.layer_init( - nn.Linear(hidden_size, 1), std=1) - - def forward_eval(self, observations, state=None): - hidden = self.encode_observations(observations, state=state) - logits, values = self.decode_actions(hidden) - return logits, values - - def forward(self, observations, state=None): - return self.forward_eval(observations, state) - - def encode_observations(self, observations, state=None): - '''Encodes a batch of observations into hidden states. Assumes - no time dimension (handled by LSTM wrappers).''' - batch_size = observations.shape[0] - if self.is_dict_obs: - observations = pufferlib.pytorch.nativize_tensor(observations, self.dtype) - observations = torch.cat([v.view(batch_size, -1) for v in observations.values()], dim=1) - else: - observations = observations.view(batch_size, -1) - return self.encoder(observations.float()) - - def decode_actions(self, hidden): - '''Decodes a batch of hidden states into (multi)discrete actions. - Assumes no time dimension (handled by LSTM wrappers).''' - if self.is_multidiscrete: - logits = self.decoder(hidden).split(self.action_nvec, dim=1) - elif self.is_continuous: - mean = self.decoder_mean(hidden) - logstd = self.decoder_logstd.expand_as(mean) - std = torch.exp(logstd) - logits = torch.distributions.Normal(mean, std) - else: - logits = self.decoder(hidden) - - values = self.value(hidden) - return logits, values - - -class G2048(nn.Module): - def __init__(self, env, hidden_size=128): - super().__init__() - self.hidden_size = hidden_size - self.is_continuous = False - - num_obs = np.prod(env.single_observation_space.shape) - - if hidden_size <= 256: - self.encoder = torch.nn.Sequential( - pufferlib.pytorch.layer_init(nn.Linear(num_obs, 512)), - nn.GELU(), - pufferlib.pytorch.layer_init(nn.Linear(512, 256)), - nn.GELU(), - pufferlib.pytorch.layer_init(nn.Linear(256, hidden_size)), - nn.GELU(), - ) - else: - self.encoder = torch.nn.Sequential( - pufferlib.pytorch.layer_init(nn.Linear(num_obs, 2*hidden_size)), - nn.GELU(), - pufferlib.pytorch.layer_init(nn.Linear(2*hidden_size, hidden_size)), - nn.GELU(), - pufferlib.pytorch.layer_init(nn.Linear(hidden_size, hidden_size)), - nn.GELU(), - ) - - num_atns = env.single_action_space.n - self.decoder = torch.nn.Sequential( - pufferlib.pytorch.layer_init(nn.Linear(hidden_size, hidden_size)), - nn.GELU(), - pufferlib.pytorch.layer_init(nn.Linear(hidden_size, num_atns), std=0.01), - ) - self.value = torch.nn.Sequential( - pufferlib.pytorch.layer_init(nn.Linear(hidden_size, hidden_size)), - nn.GELU(), - pufferlib.pytorch.layer_init(nn.Linear(hidden_size, 1), std=1.0), - ) - - def forward_eval(self, observations, state=None): - hidden = self.encode_observations(observations, state=state) - logits, values = self.decode_actions(hidden) - return logits, values - - def forward(self, observations, state=None): - return self.forward_eval(observations, state) - - def encode_observations(self, observations, state=None): - batch_size = observations.shape[0] - observations = observations.view(batch_size, -1).float() - - # Scale the feat 1 (tile**1.5) - observations[:, :16] = observations[:, :16] / 100.0 - - return self.encoder(observations) - - def decode_actions(self, hidden): - logits = self.decoder(hidden) - values = self.value(hidden) - return logits, values diff --git a/pufferlib/ocean/tower_climb/binding.c b/pufferlib/ocean/tower_climb/binding.c deleted file mode 100644 index c80d8153f7..0000000000 --- a/pufferlib/ocean/tower_climb/binding.c +++ /dev/null @@ -1,101 +0,0 @@ -#include "tower_climb.h" - -#define Env CTowerClimb -#define MY_SHARED -#include "../env_binding.h" - -static PyObject* my_shared(PyObject* self, PyObject* args, PyObject* kwargs) { - int num_maps = unpack(kwargs, "num_maps"); - Level* levels = calloc(num_maps, sizeof(Level)); - PuzzleState* puzzle_states = calloc(num_maps, sizeof(PuzzleState)); - - for (int i = 0; i < num_maps; i++) { - int goal_height = rand() % 4 + 5; - int min_moves = 10; - int max_moves = 15; - init_level(&levels[i]); - init_puzzle_state(&puzzle_states[i]); - cy_init_random_level(&levels[i], goal_height, max_moves, min_moves, i); - levelToPuzzleState(&levels[i], &puzzle_states[i]); - } - - PyObject* levels_handle = PyLong_FromVoidPtr(levels); - PyObject* puzzles_handle = PyLong_FromVoidPtr(puzzle_states); - PyObject* state = PyDict_New(); - PyDict_SetItemString(state, "levels", levels_handle); - PyDict_SetItemString(state, "puzzles", puzzles_handle); - return PyLong_FromVoidPtr(state); -} - -static int my_init(Env* env, PyObject* args, PyObject* kwargs) { - env->num_maps = unpack(kwargs, "num_maps"); - env->reward_climb_row = unpack(kwargs, "reward_climb_row"); - env->reward_fall_row = unpack(kwargs, "reward_fall_row"); - env->reward_illegal_move = unpack(kwargs, "reward_illegal_move"); - env->reward_move_block = unpack(kwargs, "reward_move_block"); - init(env); - - PyObject* handle_obj = PyDict_GetItemString(kwargs, "state"); - if (handle_obj == NULL) { - PyErr_SetString(PyExc_KeyError, "Key 'state' not found in kwargs"); - return 1; - } - - // Check if handle_obj is a PyLong - if (!PyLong_Check(handle_obj)) { - PyErr_SetString(PyExc_TypeError, "state handle must be an integer"); - return 1; - } - - // Convert PyLong to PyObject* (state dictionary) - PyObject* state_dict = (PyObject*)PyLong_AsVoidPtr(handle_obj); - if (state_dict == NULL) { - PyErr_SetString(PyExc_ValueError, "Invalid state dictionary pointer"); - return 1; - } - - // Verify it’s a dictionary - if (!PyDict_Check(state_dict)) { - PyErr_SetString(PyExc_TypeError, "State pointer does not point to a dictionary"); - return 1; - } - - // Basic validation: check reference count - if (state_dict->ob_refcnt <= 0) { - PyErr_SetString(PyExc_RuntimeError, "State dictionary has invalid reference count"); - return 1; - } - - PyObject* levels_obj = PyDict_GetItemString(state_dict, "levels"); - if (levels_obj == NULL) { - PyErr_SetString(PyExc_KeyError, "Key 'levels' not found in state"); - return 1; - } - if (!PyLong_Check(levels_obj)) { - PyErr_SetString(PyExc_TypeError, "levels must be an integer"); - return 1; - } - env->all_levels = (Level*)PyLong_AsVoidPtr(levels_obj); - - PyObject* puzzles_obj = PyDict_GetItemString(state_dict, "puzzles"); - if (!PyObject_TypeCheck(puzzles_obj, &PyLong_Type)) { - PyErr_SetString(PyExc_TypeError, "puzzles handle must be an integer"); - return 1; - } - PuzzleState* puzzles = (PuzzleState*)PyLong_AsVoidPtr(puzzles_obj); - if (!puzzles) { - PyErr_SetString(PyExc_ValueError, "Invalid puzzles handle"); - return 1; - } - env->all_puzzles = puzzles; - - return 0; -} - -static int my_log(PyObject* dict, Log* log) { - assign_to_dict(dict, "perf", log->perf); - assign_to_dict(dict, "score", log->score); - assign_to_dict(dict, "episode_return", log->episode_return); - assign_to_dict(dict, "episode_length", log->episode_length); - return 0; -} diff --git a/pufferlib/ocean/tower_climb/tower_climb.c b/pufferlib/ocean/tower_climb/tower_climb.c deleted file mode 100644 index d5489958e9..0000000000 --- a/pufferlib/ocean/tower_climb/tower_climb.c +++ /dev/null @@ -1,224 +0,0 @@ -#include -#include -#include "tower_climb.h" -#include "puffernet.h" - -typedef struct TowerClimbNet TowerClimbNet; -struct TowerClimbNet { - int num_agents; - float* obs_3d; - float* obs_1d; - Conv3D* conv1; - ReLU* relu1; - Conv3D* conv2; - Linear* flat; - CatDim1* cat; - Linear* proj; - LSTM* lstm; - Linear* actor; - Linear* value_fn; - Multidiscrete* multidiscrete; -}; - -TowerClimbNet* init_tower_climb_net(Weights* weights, int num_agents) { - TowerClimbNet* net = calloc(1, sizeof(TowerClimbNet)); - int hidden_size = 256; - int cnn_channels = 16; - // Calculate correct output sizes for Conv3D layers - // First conv: (5,5,9) -> (4,4,8) with kernel=2, stride=1 - // Second conv: (4,4,8) -> (3,3,7) with kernel=2, stride=1 - int cnn_flat_size = cnn_channels * 1 * 1 * 5; // Match PyTorch size - - net->num_agents = num_agents; - net->obs_3d = calloc(5 * 5 * 9, sizeof(float)); - net->obs_1d = calloc(3, sizeof(float)); - net->conv1 = make_conv3d(weights, num_agents, 9, 5, 5, 1, cnn_channels, 3, 1); - net->relu1 = make_relu(num_agents, cnn_channels * 3 * 3 * 7); - net->conv2 = make_conv3d(weights, num_agents, 7, 3, 3, cnn_channels, cnn_channels, 3, 1); - net->flat = make_linear(weights, num_agents, 3, 16); - net->cat = make_cat_dim1(num_agents, cnn_flat_size, 16); - net->proj = make_linear(weights, num_agents, cnn_flat_size + 16, hidden_size); - net->actor = make_linear(weights, num_agents, hidden_size, 6); - net->value_fn = make_linear(weights, num_agents, hidden_size, 1); - net->lstm = make_lstm(weights, num_agents, hidden_size, hidden_size); - int logit_sizes[1] = {6}; - net->multidiscrete = make_multidiscrete(num_agents, logit_sizes, 1); - return net; -} - -void forward(TowerClimbNet* net, unsigned char* observations, int* actions) { - int vision_size = 5 * 5 * 9; - int player_size = 3; - // clear previous observations - memset(net->obs_3d, 0, vision_size * sizeof(float)); - memset(net->obs_1d, 0, player_size * sizeof(float)); - // reshape board to 3d tensor - float (*obs_3d)[1][5][5][9] = (float (*)[1][5][5][9])net->obs_3d; - float (*obs_1d)[3] = (float (*)[3])net->obs_1d; - // process vision board - int obs_3d_idx = 0; - for (int b = 0; b < 1; b++) { - for (int d = 0; d < 5; d++) { - for (int h = 0; h < 5; h++) { - for (int w = 0; w < 9; w++) { - obs_3d[b][0][d][h][w] = observations[obs_3d_idx]; - obs_3d_idx++; - } - } - } - } - // process player board - for (int i = 0; i < player_size; i++) { - obs_1d[0][i] = observations[vision_size + i]; - } - - conv3d(net->conv1, net->obs_3d); - relu(net->relu1, net->conv1->output); - conv3d(net->conv2, net->relu1->output); - linear(net->flat, net->obs_1d); - cat_dim1(net->cat, net->conv2->output, net->flat->output); - linear(net->proj, net->cat->output); - lstm(net->lstm, net->proj->output); - linear(net->actor, net->lstm->state_h); - linear(net->value_fn, net->lstm->state_h); - softmax_multidiscrete(net->multidiscrete, net->actor->output, actions); -} - -void free_tower_climb_net(TowerClimbNet* net) { - free(net->obs_3d); - free(net->obs_1d); - free(net->conv1); - free(net->relu1); - free(net->conv2); - free(net->flat); - free(net->cat); - free(net->proj); - free(net->actor); - free(net->value_fn); - free(net->lstm); - free(net->multidiscrete); - free(net); -} - -void demo() { - Weights* weights = load_weights("resources/tower_climb/tower_climb_weights.bin", 560407); - TowerClimbNet* net = init_tower_climb_net(weights, 1); - - int num_maps = 1; // Generate 1 map only to start faster - Level* levels = calloc(num_maps, sizeof(Level)); - PuzzleState* puzzle_states = calloc(num_maps, sizeof(PuzzleState)); - - srand(time(NULL)); - - for (int i = 0; i < num_maps; i++) { - int goal_height = rand() % 4 + 5; - int min_moves = 10; - int max_moves = 15; - init_level(&levels[i]); - init_puzzle_state(&puzzle_states[i]); - cy_init_random_level(&levels[i], goal_height, max_moves, min_moves, i); - levelToPuzzleState(&levels[i], &puzzle_states[i]); - } - - CTowerClimb* env = allocate(); - env->num_maps = num_maps; - env->all_levels = levels; - env->all_puzzles = puzzle_states; - - int random_level = 5 + (rand() % 4); - init_random_level(env, random_level, 15, 10, rand()); - c_reset(env); - c_render(env); - Client* client = env->client; - client->enable_animations = 1; - int tick = 0; - while (!WindowShouldClose()) { - if (tick % 6 == 0 && !client->isMoving) { - tick = 0; - int human_action = env->actions[0]; - forward(net, env->observations, env->actions); - if (IsKeyDown(KEY_LEFT_SHIFT)) { - env->actions[0] = human_action; - } - c_step(env); - if (IsKeyDown(KEY_LEFT_SHIFT)) { - env->actions[0] = NOOP; - } - } - tick++; - if (IsKeyDown(KEY_LEFT_SHIFT)) { - // Camera controls - if (IsKeyPressed(KEY_UP)) { // || IsKeyPressed(KEY_W)) { - env->actions[0] = UP; - } - if (IsKeyPressed(KEY_LEFT)) { //|| IsKeyPressed(KEY_A)) { - env->actions[0] = LEFT; - } - if (IsKeyPressed(KEY_RIGHT)) { //|| IsKeyPressed(KEY_D)) { - env->actions[0] = RIGHT; - } - if (IsKeyPressed(KEY_DOWN)) { //|| IsKeyPressed(KEY_S)){ - env->actions[0] = DOWN; - } - if (IsKeyPressed(KEY_SPACE)){ - env->actions[0] = GRAB; - } - if (IsKeyPressed(KEY_RIGHT_SHIFT)){ - env->actions[0] = DROP; - } - } - c_render(env); - - // Handle delayed level reset after puffer animation finishes - if (env->pending_reset) { - bool shouldReset = false; - - if (env->celebrationStarted) { - // Wait for full celebration sequence: 0.8s climbing + 0.4s beam + 0.7s banner = 1.9s total - float celebrationDuration = GetTime() - env->celebrationStartTime; - shouldReset = (celebrationDuration >= 1.9f); - } else { - // No celebration; reset when banner finishes - shouldReset = (!client->showBanner || client->bannerType != 1); - } - - if (shouldReset) { - env->pending_reset = false; - c_reset(env); - } - } - } - close_client(client); - free_allocated(env); - free_tower_climb_net(net); - free(weights); - free(levels[0].map); - free(levels); - free(puzzle_states[0].blocks); - free(puzzle_states); -} - -void performance_test() { - long test_time = 10; - CTowerClimb* env = allocate(); - int seed = 0; - init_random_level(env, 8, 25, 15, seed); - long start = time(NULL); - int i = 0; - while (time(NULL) - start < test_time) { - env->actions[0] = rand() % 5; - c_step(env); - i++; - } - long end = time(NULL); - printf("SPS: %ld\n", i / (end - start)); - free_allocated(env); -} - -int main() { - demo(); - // performance_test(); - return 0; -} - - diff --git a/pufferlib/ocean/tower_climb/tower_climb.py b/pufferlib/ocean/tower_climb/tower_climb.py deleted file mode 100644 index 80b19dde84..0000000000 --- a/pufferlib/ocean/tower_climb/tower_climb.py +++ /dev/null @@ -1,73 +0,0 @@ -import numpy as np -import gymnasium - -import pufferlib -from pufferlib.ocean.tower_climb import binding - - -class TowerClimb(pufferlib.PufferEnv): - def __init__(self, num_envs=4096, render_mode=None, report_interval=1, - num_maps=50, reward_climb_row = .25, reward_fall_row = 0, reward_illegal_move = -0.01, - reward_move_block = 0.2, buf = None, seed=0): - - # env - self.num_agents = num_envs - self.render_mode = render_mode - self.report_interval = report_interval - - self.num_obs = 228 - self.single_observation_space = gymnasium.spaces.Box(low=0, high=255, - shape=(self.num_obs,), dtype=np.uint8) - self.single_action_space = gymnasium.spaces.Discrete(6) - - super().__init__(buf=buf) - c_envs = [] - self.c_state = binding.shared(num_maps=num_maps) - self.c_envs = binding.vec_init(self.observations, self.actions, - self.rewards, self.terminals, self.truncations, num_envs, seed, - num_maps=num_maps, reward_climb_row=reward_climb_row, - reward_fall_row=reward_fall_row, reward_illegal_move=reward_illegal_move, - reward_move_block=reward_move_block, state=self.c_state) - - def reset(self, seed=None): - binding.vec_reset(self.c_envs, seed) - self.tick = 0 - return self.observations, [] - - def step(self, actions): - self.actions[:] = actions - binding.vec_step(self.c_envs) - self.tick += 1 - info = [] - if self.tick % self.report_interval == 0: - log = binding.vec_log(self.c_envs) - if log: - info.append(log) - - return (self.observations, self.rewards, - self.terminals, self.truncations, info) - - def render(self): - binding.vec_render(self.c_envs, 0) - - def close(self): - #binding.vec_close(self.c_envs) - pass - -def test_performance(timeout=10, atn_cache=1024): - num_envs=1000; - env = TowerClimb(num_envs=num_envs) - env.reset() - tick = 0 - - actions = np.random.randint(0, env.single_action_space.n, (atn_cache, num_envs)) - - import time - start = time.time() - while time.time() - start < timeout: - atn = actions[tick % atn_cache] - env.step(atn) - tick += 1 - - sps = num_envs * tick / (time.time() - start) - print(f'SPS: {sps:,}') diff --git a/pufferlib/ocean/trash_pickup/README.md b/pufferlib/ocean/trash_pickup/README.md deleted file mode 100644 index 670c142997..0000000000 --- a/pufferlib/ocean/trash_pickup/README.md +++ /dev/null @@ -1,18 +0,0 @@ -# TrashPickup Environment - -A lightweight multi-agent reinforcement learning (RL) environment designed for coordination and cooperation research. Agents pick up trash and deposit it in bins for rewards. - -## Key Features -- **Multi-Agent Coordination:** Encourages teamwork, efficient planning, and resource allocation. -- **Configurable Setup:** Adjustable grid size, number of agents, trash, bins, and episode length. -- **Discrete Action Space:** Actions include `UP`, `DOWN`, `LEFT`, `RIGHT`. -- **Fast and Lightweight:** Optimized for rapid training and testing. - -## Example Research Goals -- Investigate emergent behaviors like task allocation and coordination. -- Study efficient resource collection and bin-pushing strategies. - -## Ideal For -- RL researchers exploring multi-agent cooperation. -- Students learning about multi-agent systems. -- Developers testing scalable RL algorithms. diff --git a/pufferlib/ocean/trash_pickup/binding.c b/pufferlib/ocean/trash_pickup/binding.c deleted file mode 100644 index 4e23da1b39..0000000000 --- a/pufferlib/ocean/trash_pickup/binding.c +++ /dev/null @@ -1,24 +0,0 @@ -#include "trash_pickup.h" - -#define Env CTrashPickupEnv -#include "../env_binding.h" - -static int my_init(Env* env, PyObject* args, PyObject* kwargs) { - env->num_agents = unpack(kwargs, "num_agents"); - env->grid_size = unpack(kwargs, "grid_size"); - env->num_trash = unpack(kwargs, "num_trash"); - env->num_bins = unpack(kwargs, "num_bins"); - env->max_steps = unpack(kwargs, "max_steps"); - env->agent_sight_range = unpack(kwargs, "agent_sight_range"); - initialize_env(env); - return 0; -} - -static int my_log(PyObject* dict, Log* log) { - assign_to_dict(dict, "perf", log->perf); - assign_to_dict(dict, "score", log->score); - assign_to_dict(dict, "episode_return", log->episode_return); - assign_to_dict(dict, "episode_length", log->episode_length); - assign_to_dict(dict, "trash_collected", log->trash_collected); - return 0; -} diff --git a/pufferlib/ocean/trash_pickup/cy_trash_pickup.pyx b/pufferlib/ocean/trash_pickup/cy_trash_pickup.pyx deleted file mode 100644 index 114a67aa2c..0000000000 --- a/pufferlib/ocean/trash_pickup/cy_trash_pickup.pyx +++ /dev/null @@ -1,110 +0,0 @@ -cimport numpy as cnp -from libc.stdlib cimport calloc, free # Use calloc for zero-initialized allocation -from libc.stdint cimport uint64_t - -cdef extern from "trash_pickup.h": - int LOG_BUFFER_SIZE - - ctypedef struct Log: - float perf; - float score; - float episode_return; - float episode_length; - float trash_collected; - - ctypedef struct LogBuffer - LogBuffer* allocate_logbuffer(int) - void free_logbuffer(LogBuffer*) - Log aggregate_and_clear(LogBuffer*) - - ctypedef struct CTrashPickupEnv: - char* observations - int* actions - float* rewards - unsigned char* dones - LogBuffer* log_buffer - - int grid_size - int num_agents - int num_trash - int num_bins - int max_steps - int agent_sight_range - - - ctypedef struct Client - - void initialize_env(CTrashPickupEnv* env) - void free_allocated(CTrashPickupEnv* env) - - Client* make_client(CTrashPickupEnv* env) - void close_client(Client* client) - void c_render(Client* client, CTrashPickupEnv* env) - void c_reset(CTrashPickupEnv* env) - void c_step(CTrashPickupEnv* env) - -cdef class CyTrashPickup: - cdef: - CTrashPickupEnv* envs - Client* client - LogBuffer* logs - int num_envs - - def __init__(self, char[:, :] observations, int[:] actions, - float[:] rewards, unsigned char[:] terminals, int num_envs, - int num_agents=3, int grid_size=10, int num_trash=15, - int num_bins=2, int max_steps=300, int agent_sight_range=5): - self.num_envs = num_envs - self.envs = calloc(num_envs, sizeof(CTrashPickupEnv)) - if self.envs == NULL: - raise MemoryError("Failed to allocate memory for CTrashPickupEnv") - self.client = NULL - - self.logs = allocate_logbuffer(LOG_BUFFER_SIZE) - - cdef int inc = num_agents - - cdef int i - for i in range(num_envs): - self.envs[i] = CTrashPickupEnv( - observations=&observations[inc*i, 0], - actions=&actions[inc*i], - rewards=&rewards[inc*i], - dones=&terminals[inc*i], - log_buffer=self.logs, - grid_size=grid_size, - num_agents=num_agents, - num_trash=num_trash, - num_bins=num_bins, - max_steps=max_steps, - agent_sight_range=agent_sight_range - ) - initialize_env(&self.envs[i]) - - def reset(self): - cdef int i - for i in range(self.num_envs): - c_reset(&self.envs[i]) - - def step(self): - cdef int i - for i in range(self.num_envs): - c_step(&self.envs[i]) - - def render(self): - cdef CTrashPickupEnv* env = &self.envs[0] - if self.client == NULL: - self.client = make_client(env) - - c_render(self.client, env) - - def close(self): - if self.client != NULL: - close_client(self.client) - self.client = NULL - - free(self.envs) - - def log(self): - cdef Log log = aggregate_and_clear(self.logs) - return log diff --git a/pufferlib/ocean/trash_pickup/trash_pickup.c b/pufferlib/ocean/trash_pickup/trash_pickup.c deleted file mode 100644 index 1a313ecd9a..0000000000 --- a/pufferlib/ocean/trash_pickup/trash_pickup.c +++ /dev/null @@ -1,116 +0,0 @@ -#include -#include "trash_pickup.h" -#include "puffernet.h" - -// Demo function for visualizing the TrashPickupEnv -void demo(int grid_size, int num_agents, int num_trash, int num_bins, int max_steps) { - CTrashPickupEnv env = { - .grid_size = grid_size, - .num_agents = num_agents, - .num_trash = num_trash, - .num_bins = num_bins, - .max_steps = max_steps, - .agent_sight_range = 5, - .do_human_control = true - }; - - bool use_pretrained_model = true; - - Weights* weights; - ConvLSTM* net; - - if (use_pretrained_model){ - weights = load_weights("resources/trash_pickup/trash_pickup_weights.bin", 150245); - int vision = 2*env.agent_sight_range + 1; - net = make_convlstm(weights, env.num_agents, vision, 5, 32, 128, 4); - } - - allocate(&env); - c_reset(&env); - c_render(&env); - - int tick = 0; - while (!WindowShouldClose()) { - if (tick % 2 == 0) { - // Random actions for all agents - for (int i = 0; i < env.num_agents; i++) { - if (use_pretrained_model) - { - for (int e = 0; e < env.total_num_obs; e++) { - net->obs[e] = env.observations[e]; - } - forward_convlstm(net, net->obs, env.actions); - } - else{ - env.actions[i] = rand() % 4; // 0 = UP, 1 = DOWN, 2 = LEFT, 3 = RIGHT - } - // printf("action: %d \n", env.actions[i]); - } - - // Override human control actions - if (IsKeyDown(KEY_LEFT_SHIFT)) { - // Handle keyboard input only for selected agent - if (IsKeyDown(KEY_UP) || IsKeyDown(KEY_W)) { - env.actions[0] = ACTION_UP; - } - if (IsKeyDown(KEY_LEFT) || IsKeyDown(KEY_A)) { - env.actions[0] = ACTION_LEFT; - } - if (IsKeyDown(KEY_RIGHT) || IsKeyDown(KEY_D)) { - env.actions[0] = ACTION_RIGHT; - } - if (IsKeyDown(KEY_DOWN) || IsKeyDown(KEY_S)) { env.actions[0] = ACTION_DOWN; } - } - - // Step the environment and render the grid - c_step(&env); - - } - tick++; - - c_render(&env); - } - - free_convlstm(net); - free(weights); - free_allocated(&env); - //close_client(client); -} - -// Performance test function for benchmarking -void performance_test() { - long test_time = 10; // Test duration in seconds - - CTrashPickupEnv env = { - .grid_size = 10, - .num_agents = 4, - .num_trash = 20, - .num_bins = 1, - .max_steps = 150, - .agent_sight_range = 5 - }; - allocate(&env); - c_reset(&env); - - long start = time(NULL); - int i = 0; - int inc = env.num_agents; - while (time(NULL) - start < test_time) { - for (int e = 0; e < env.num_agents; e++) { - env.actions[e] = rand() % 4; - } - c_step(&env); - i += inc; - } - long end = time(NULL); - printf("SPS: %ld\n", i / (end - start)); - free_allocated(&env); -} - - -// Main entry point -int main() { - demo(20, 8, 40, 2, 300); // Visual demo - //performance_test(); // Uncomment for benchmarking - return 0; -} diff --git a/pufferlib/ocean/trash_pickup/trash_pickup.py b/pufferlib/ocean/trash_pickup/trash_pickup.py deleted file mode 100644 index 57409d0eea..0000000000 --- a/pufferlib/ocean/trash_pickup/trash_pickup.py +++ /dev/null @@ -1,125 +0,0 @@ -import numpy as np -from gymnasium import spaces - -import pufferlib -from pufferlib.ocean.trash_pickup import binding - -class TrashPickupEnv(pufferlib.PufferEnv): - def __init__(self, num_envs=1, render_mode=None, report_interval=1, buf=None, - grid_size=10, num_agents=3, num_trash=15, num_bins=2, max_steps=300, agent_sight_range=5, seed=0): - # Env Setup - self.render_mode = render_mode - self.report_interval = report_interval - - # Validate num_agents - if not isinstance(num_agents, int) or num_agents <= 0: - raise ValueError("num_agents must be an integer greater than 0.") - self.num_agents = num_envs * num_agents - self.num_agents_per_env = num_agents - - # Handle num_trash input - if not isinstance(num_trash, int) or num_trash <= 0: - raise ValueError("num_trash must be an int > 0") - self.num_trash = num_trash - - # Handle num_bins input - if not isinstance(num_bins, int) or num_bins <= 0: - raise ValueError("num_bins must be an int > 0") - self.num_bins = num_bins - - if not isinstance(max_steps, int) or max_steps < 10: - raise ValueError("max_steps must be an int >= 10") - self.max_steps = max_steps - - if not isinstance(agent_sight_range, int) or agent_sight_range < 2: - raise ValueError("agent sight range must be an int >= 2") - self.agent_sight_range = agent_sight_range - - # Calculate minimum required grid size - min_grid_size = int((num_agents + self.num_trash + self.num_bins) ** 0.5) + 1 - if not isinstance(grid_size, int) or grid_size < min_grid_size: - raise ValueError( - f"grid_size must be an integer >= {min_grid_size}. " - f"Received grid_size={grid_size}, with num_agents={num_agents}, num_trash={self.num_trash}, and num_bins={self.num_bins}." - ) - self.grid_size = grid_size - - # Entity Attribute Based Obs-Space - # num_obs_trash = num_trash * 3 # [presence, x pos, y pos] for each trash - # num_obs_bin = num_bins * 2 # [x pos, y pos] for each bin - # num_obs_agent = num_agents * 3 # [carrying trash, x pos, y pos] for each agent - # self.num_obs = num_obs_trash + num_obs_bin + num_obs_agent; - - # 2D Local crop obs space - self.num_obs = ((((agent_sight_range * 2 + 1) * (agent_sight_range * 2 + 1)) * 5)); # one-hot encoding for all cell types in local crop around agent (minus the cell the agent is currently in) - - self.single_observation_space = spaces.Box(low=0, high=1, - shape=(self.num_obs,), dtype=np.int8) - self.single_action_space = spaces.Discrete(4) - - super().__init__(buf=buf) - c_envs = [] - for i in range(num_envs): - env_id = binding.env_init( - self.observations[i*num_agents:(i+1)*num_agents], - self.actions[i*num_agents:(i+1)*num_agents], - self.rewards[i*num_agents:(i+1)*num_agents], - self.terminals[i*num_agents:(i+1)*num_agents], - self.truncations[i*num_agents:(i+1)*num_agents], - i + seed * num_envs, - num_agents=num_agents, - grid_size=grid_size, - num_trash=num_trash, - num_bins=num_bins, - max_steps=max_steps, - agent_sight_range=agent_sight_range, - ) - c_envs.append(env_id) - - self.c_envs = binding.vectorize(*c_envs) - - def reset(self, seed=None): - binding.vec_reset(self.c_envs, seed) - self.tick = 0 - return self.observations, [] - - def step(self, actions): - self.actions[:] = actions - binding.vec_step(self.c_envs) - self.tick += 1 - - info = [] - if self.tick % self.report_interval == 0: - log = binding.vec_log(self.c_envs) - if log: - info.append(log) - - return (self.observations, self.rewards, - self.terminals, self.truncations, info) - - def render(self): - binding.vec_render(self.c_envs, 0) - - def close(self): - binding.vec_close(self.c_envs) - -def test_performance(timeout=10, atn_cache=1024): - env = TrashPickupEnv(num_envs=1024, grid_size=10, num_agents=4, - num_trash=20, num_bins=1, max_steps=150, agent_sight_range=5) - - env.reset() - tick = 0 - - actions = np.random.randint(0, 4, (atn_cache, env.num_agents)) - - import time - start = time.time() - while time.time() - start < timeout: - atn = actions[tick % atn_cache] - env.step(atn) - tick += 1 - - print(f'SPS: %f', env.num_agents * tick / (time.time() - start)) - -if __name__ == '__main__': - test_performance() diff --git a/pufferlib/ocean/tripletriad/binding.c b/pufferlib/ocean/tripletriad/binding.c deleted file mode 100644 index 4c725d3130..0000000000 --- a/pufferlib/ocean/tripletriad/binding.c +++ /dev/null @@ -1,22 +0,0 @@ -#include "tripletriad.h" - -#define Env CTripleTriad -#include "../env_binding.h" - -static int my_init(Env* env, PyObject* args, PyObject* kwargs) { - env->width = unpack(kwargs, "width"); - env->height = unpack(kwargs, "height"); - env->card_width = unpack(kwargs, "card_width"); - env->card_height = unpack(kwargs, "card_height"); - init_ctripletriad(env); - return 0; -} - -static int my_log(PyObject* dict, Log* log) { - assign_to_dict(dict, "perf", log->perf); - assign_to_dict(dict, "score", log->score); - assign_to_dict(dict, "episode_return", log->episode_return); - assign_to_dict(dict, "episode_length", log->episode_length); - assign_to_dict(dict, "n", log->n); - return 0; -} diff --git a/pufferlib/ocean/tripletriad/tripletriad.py b/pufferlib/ocean/tripletriad/tripletriad.py deleted file mode 100644 index fce49c4ca5..0000000000 --- a/pufferlib/ocean/tripletriad/tripletriad.py +++ /dev/null @@ -1,65 +0,0 @@ -import numpy as np -import gymnasium - -import pufferlib -from pufferlib.ocean.tripletriad import binding - -class TripleTriad(pufferlib.PufferEnv): - def __init__(self, num_envs=1, render_mode=None, report_interval=1, - width=990, height=690, card_width=192, card_height=224, buf=None, seed=0): - self.single_observation_space = gymnasium.spaces.Box(low=0, high=1, - shape=(114,), dtype=np.float32) - self.single_action_space = gymnasium.spaces.Discrete(14) - self.report_interval = report_interval - self.render_mode = render_mode - self.num_agents = num_envs - - super().__init__(buf=buf) - self.c_envs = binding.vec_init(self.observations, self.actions, - self.rewards, self.terminals, self.truncations, num_envs, seed, width=width, height=height, - card_width=card_width, card_height=card_height) - - def reset(self, seed=None): - self.tick = 0 - if seed is None: - binding.vec_reset(self.c_envs, 0) - else: - binding.vec_reset(self.c_envs, seed) - return self.observations, [] - - def step(self, actions): - self.actions[:] = actions - binding.vec_step(self.c_envs) - self.tick += 1 - - info = [] - if self.tick % self.report_interval == 0: - info.append(binding.vec_log(self.c_envs)) - - return (self.observations, self.rewards, - self.terminals, self.truncations, info) - - def render(self): - binding.vec_render(self.c_envs, 0) - - def close(self): - binding.vec_close(self.c_envs) - -def test_performance(timeout=10, atn_cache=1024): - env = TripleTriad(num_envs=1000) - env.reset() - tick = 0 - - actions = np.random.randint(0, 2, (atn_cache, env.num_agents)) - - import time - start = time.time() - while time.time() - start < timeout: - atn = actions[tick % atn_cache] - env.step(atn) - tick += 1 - - print(f'SPS: {env.num_agents * tick / (time.time() - start):,}') - -if __name__ == '__main__': - test_performance() diff --git a/pufferlib/ocean/whisker_racer/binding.c b/pufferlib/ocean/whisker_racer/binding.c deleted file mode 100644 index 88582daafd..0000000000 --- a/pufferlib/ocean/whisker_racer/binding.c +++ /dev/null @@ -1,49 +0,0 @@ -#include "whisker_racer.h" - -#define Env WhiskerRacer -#include "../env_binding.h" - -static int my_init(Env* env, PyObject* args, PyObject* kwargs) { - env->frameskip = unpack(kwargs, "frameskip"); - env->width = unpack(kwargs, "width"); - env->height = unpack(kwargs, "height"); - env->llw_ang = unpack(kwargs, "llw_ang"); - env->flw_ang = unpack(kwargs, "flw_ang"); - env->frw_ang = unpack(kwargs, "frw_ang"); - env->rrw_ang = unpack(kwargs, "rrw_ang"); - env->max_whisker_length = unpack(kwargs, "max_whisker_length"); - env->turn_pi_frac = unpack(kwargs, "turn_pi_frac"); - env->maxv = unpack(kwargs, "maxv"); - env->render = unpack(kwargs, "render"); - env->continuous = unpack(kwargs, "continuous"); - env->reward_yellow = unpack(kwargs, "reward_yellow"); - env->reward_green = unpack(kwargs, "reward_green"); - env->gamma = unpack(kwargs, "gamma"); - env->track_width = unpack(kwargs, "track_width"); - env->num_radial_sectors = unpack(kwargs, "num_radial_sectors"); - env->num_points = unpack(kwargs, "num_points"); - env->bezier_resolution = unpack(kwargs, "bezier_resolution"); - env->turn_pi_frac = unpack(kwargs, "turn_pi_frac"); - env->w_ang = unpack(kwargs, "w_ang"); - env->corner_thresh = unpack(kwargs, "corner_thresh"); - env->ftmp1 = unpack(kwargs, "ftmp1"); - env->ftmp2 = unpack(kwargs, "ftmp2"); - env->ftmp3 = unpack(kwargs, "ftmp3"); - env->ftmp4 = unpack(kwargs, "ftmp4"); - env->mode7 = unpack(kwargs, "mode7"); - env->render_many = unpack(kwargs, "render_many"); - env->rng = unpack(kwargs, "rng"); - env->method = unpack(kwargs, "method"); - env->i = unpack(kwargs, "i"); - - init(env); - return 0; -} - -static int my_log(PyObject* dict, Log* log) { - assign_to_dict(dict, "perf", log->perf); - assign_to_dict(dict, "score", log->score); - assign_to_dict(dict, "episode_return", log->episode_return); - assign_to_dict(dict, "episode_length", log->episode_length); - return 0; -} diff --git a/pufferlib/ocean/whisker_racer/whisker_racer.py b/pufferlib/ocean/whisker_racer/whisker_racer.py deleted file mode 100644 index 5430ff3fe5..0000000000 --- a/pufferlib/ocean/whisker_racer/whisker_racer.py +++ /dev/null @@ -1,111 +0,0 @@ -import numpy as np -import gymnasium -import time - -import pufferlib -from pufferlib.ocean.whisker_racer import binding - -class WhiskerRacer(pufferlib.PufferEnv): - def __init__(self, num_envs=1, render_mode=None, - frameskip=4, width=1080, height=720, - llw_ang=-3.14/4, flw_ang=-3.14/6, - frw_ang=3.14/6, rrw_ang=3.14/4, - max_whisker_length=100, - turn_pi_frac=20, - maxv=5, render=0, - continuous=False, log_interval=128, - reward_yellow=0.25, reward_green=0.0, gamma=0.9, track_width=50, - num_radial_sectors=16, num_points=4, bezier_resolution=16, w_ang=0.523, - corner_thresh=0.5, ftmp1=0.1, ftmp2=0.1, ftmp3=0.1, ftmp4=0.1, - mode7=0, render_many=0, seed=42, - buf=None, rng=42, i=1, method=0): - self.single_observation_space = gymnasium.spaces.Box(low=0, high=1, - shape=(3,), dtype=np.float32) - self.render_mode = render_mode - self.num_agents = num_envs - self.continuous = continuous - self.log_interval = log_interval - self.tick = 0 - - if continuous: - self.single_action_space = gymnasium.spaces.Box(low=-1, high=1, shape=(1,), dtype=np.float32) - else: - self.single_action_space = gymnasium.spaces.Discrete(3) - - super().__init__(buf) - - if continuous: - self.actions = self.actions.flatten() - else: - self.actions = self.actions.astype(np.float32) - - c_envs = [] - for i in range(num_envs): - env_id = binding.env_init( - self.observations[i:i+1], - self.actions[i:i+1], - self.rewards[i:i+1], - self.terminals[i:i+1], - self.truncations[i:i+1], - seed, num_envs=num_envs, seed=seed, frameskip=frameskip, width=width, height=height, - llw_ang=llw_ang, flw_ang=flw_ang, frw_ang=frw_ang, rrw_ang=rrw_ang, max_whisker_length=max_whisker_length, - turn_pi_frac=turn_pi_frac, maxv=maxv, render=render, continuous=continuous, - reward_yellow=reward_yellow, reward_green=reward_green, gamma=gamma, track_width=track_width, - num_radial_sectors=num_radial_sectors, num_points=num_points, bezier_resolution=bezier_resolution, w_ang=w_ang, - corner_thresh=corner_thresh, ftmp1=ftmp1,ftmp2=ftmp2,ftmp3=ftmp3,ftmp4=ftmp4, - mode7=mode7, render_many=render_many, rng=rng+i, i=i, method=method - ) - c_envs.append(env_id) - self.c_envs = binding.vectorize(*c_envs) - - def reset(self, seed=0): - binding.vec_reset(self.c_envs, seed) - self.tick = 0 - return self.observations, [] - - def step(self, actions): - #start = time.time() - if self.continuous: - self.actions[:] = np.clip(actions.flatten(), -1.0, 1.0) - else: - self.actions[:] = actions - - self.tick += 1 - binding.vec_step(self.c_envs) - - info = [] - if self.tick % self.log_interval == 0: - info.append(binding.vec_log(self.c_envs)) - #end = time.time() - #print(f"python step took {end - start:.3e} seconds") - return (self.observations, self.rewards, - self.terminals, self.truncations, info) - - def render(self): - binding.vec_render(self.c_envs, 0) - - def close(self): - binding.vec_close(self.c_envs) - -def test_performance(timeout=10, atn_cache=1024): - print("test_performance in whisker_racer.py") - env = WhiskerRacer(num_envs=1) - env.reset() - tick = 0 - - actions = np.random.randint(0, 2, (atn_cache, env.num_agents)) - - import time - start = time.time() - while time.time() - start < timeout: - print("atn = actions[tick % atn_cache] in whisker_racer.py") - atn = actions[tick % atn_cache] - print("env.step in whisker_racer.py") - env.step(atn) - tick += 1 - - print(f'SPS: %f', env.num_agents * tick / (time.time() - start)) - -if __name__ == '__main__': - print("whisker_racer.py") - test_performance() diff --git a/pufferlib/pufferl.py b/pufferlib/pufferl.py index 7132a19f90..8fc0c03a89 100644 --- a/pufferlib/pufferl.py +++ b/pufferlib/pufferl.py @@ -1,1306 +1,479 @@ -## puffer [train | eval | sweep] [env_name] [optional args] -- See https://puffer.ai for full detail0 +## puffer [train | eval | sweep] [env_name] [optional args] -- See https://puffer.ai for full details # This is the same as python -m pufferlib.pufferl [train | eval | sweep] [env_name] [optional args] -# Distributed example: torchrun --standalone --nnodes=1 --nproc-per-node=6 -m pufferlib.pufferl train puffer_nmmo3 -import contextlib import warnings warnings.filterwarnings('error', category=RuntimeWarning) import os import sys import glob +import json import ast import time -import random -import shutil import argparse -import importlib import configparser -from threading import Thread -from collections import defaultdict, deque +from collections import defaultdict +import multiprocessing as mp +from copy import deepcopy import numpy as np -import psutil import torch -import torch.distributed -from torch.distributed.elastic.multiprocessing.errors import record -import torch.utils.cpp_extension - import pufferlib -import pufferlib.sweep -import pufferlib.vector -import pufferlib.pytorch try: from pufferlib import _C except ImportError: - raise ImportError('Failed to import C/CUDA advantage kernel. If you have non-default PyTorch, try installing with --no-build-isolation') + raise ImportError('Failed to import PufferLib C++ backend. If you have non-default PyTorch, try installing with --no-build-isolation') import rich import rich.traceback from rich.table import Table -from rich.console import Console from rich_argparse import RichHelpFormatter rich.traceback.install(show_locals=False) import signal # Aggressively exit on ctrl+c signal.signal(signal.SIGINT, lambda sig, frame: os._exit(0)) -from torch.utils.cpp_extension import ( - CUDA_HOME, - ROCM_HOME -) -# Assume advantage kernel has been built if torch has been compiled with CUDA or HIP support -# and can find CUDA or HIP in the system -ADVANTAGE_CUDA = bool(CUDA_HOME or ROCM_HOME) - -class PuffeRL: - def __init__(self, config, vecenv, policy, logger=None): - # Backend perf optimization - torch.set_float32_matmul_precision('high') - torch.backends.cudnn.deterministic = config['torch_deterministic'] - torch.backends.cudnn.benchmark = True - - # Reproducibility - seed = config['seed'] - #random.seed(seed) - #np.random.seed(seed) - #torch.manual_seed(seed) - - # Vecenv info - vecenv.async_reset(seed) - obs_space = vecenv.single_observation_space - atn_space = vecenv.single_action_space - total_agents = vecenv.num_agents - self.total_agents = total_agents - - # Experience - if config['batch_size'] == 'auto' and config['bptt_horizon'] == 'auto': - raise pufferlib.APIUsageError('Must specify batch_size or bptt_horizon') - elif config['batch_size'] == 'auto': - config['batch_size'] = total_agents * config['bptt_horizon'] - elif config['bptt_horizon'] == 'auto': - config['bptt_horizon'] = config['batch_size'] // total_agents - - batch_size = config['batch_size'] - horizon = config['bptt_horizon'] - segments = batch_size // horizon - self.segments = segments - if total_agents > segments: - raise pufferlib.APIUsageError( - f'Total agents {total_agents} <= segments {segments}' - ) - - device = config['device'] - self.observations = torch.zeros(segments, horizon, *obs_space.shape, - dtype=pufferlib.pytorch.numpy_to_torch_dtype_dict[obs_space.dtype], - pin_memory=device == 'cuda' and config['cpu_offload'], - device='cpu' if config['cpu_offload'] else device) - self.actions = torch.zeros(segments, horizon, *atn_space.shape, device=device, - dtype=pufferlib.pytorch.numpy_to_torch_dtype_dict[atn_space.dtype]) - self.values = torch.zeros(segments, horizon, device=device) - self.logprobs = torch.zeros(segments, horizon, device=device) - self.rewards = torch.zeros(segments, horizon, device=device) - self.terminals = torch.zeros(segments, horizon, device=device) - self.truncations = torch.zeros(segments, horizon, device=device) - self.ratio = torch.ones(segments, horizon, device=device) - self.importance = torch.ones(segments, horizon, device=device) - self.ep_lengths = torch.zeros(total_agents, device=device, dtype=torch.int32) - self.ep_indices = torch.arange(total_agents, device=device, dtype=torch.int32) - self.free_idx = total_agents - - # LSTM - if config['use_rnn']: - n = vecenv.agents_per_batch - h = policy.hidden_size - self.lstm_h = {i*n: torch.zeros(n, h, device=device) for i in range(total_agents//n)} - self.lstm_c = {i*n: torch.zeros(n, h, device=device) for i in range(total_agents//n)} - - # Minibatching & gradient accumulation - minibatch_size = config['minibatch_size'] - max_minibatch_size = config['max_minibatch_size'] - self.minibatch_size = min(minibatch_size, max_minibatch_size) - if minibatch_size > max_minibatch_size and minibatch_size % max_minibatch_size != 0: - raise pufferlib.APIUsageError( - f'minibatch_size {minibatch_size} > max_minibatch_size {max_minibatch_size} must divide evenly') - - if batch_size < minibatch_size: - raise pufferlib.APIUsageError( - f'batch_size {batch_size} must be >= minibatch_size {minibatch_size}' - ) - - self.accumulate_minibatches = max(1, minibatch_size // max_minibatch_size) - self.total_minibatches = int(config['update_epochs'] * batch_size / self.minibatch_size) - self.minibatch_segments = self.minibatch_size // horizon - if self.minibatch_segments * horizon != self.minibatch_size: - raise pufferlib.APIUsageError( - f'minibatch_size {self.minibatch_size} must be divisible by bptt_horizon {horizon}' - ) +def unroll_nested_dict(d): + if not isinstance(d, dict): + return d - # Torch compile - self.uncompiled_policy = policy - self.policy = policy - if config['compile']: - self.policy = torch.compile(policy, mode=config['compile_mode']) - self.policy.forward_eval = torch.compile(policy, mode=config['compile_mode']) - pufferlib.pytorch.sample_logits = torch.compile(pufferlib.pytorch.sample_logits, mode=config['compile_mode']) - - # Optimizer - if config['optimizer'] == 'adam': - optimizer = torch.optim.Adam( - self.policy.parameters(), - lr=config['learning_rate'], - betas=(config['adam_beta1'], config['adam_beta2']), - eps=config['adam_eps'], - ) - elif config['optimizer'] == 'muon': - import heavyball - from heavyball import ForeachMuon - warnings.filterwarnings(action='ignore', category=UserWarning, module=r'heavyball.*') - heavyball.utils.compile_mode = "default" - - # # optionally a little bit better/faster alternative to newtonschulz iteration - # import heavyball.utils - # heavyball.utils.zeroth_power_mode = 'thinky_polar_express' - - # heavyball_momentum=True introduced in heavyball 2.1.1 - # recovers heavyball-1.7.2 behaviour - previously swept hyperparameters work well - optimizer = ForeachMuon( - self.policy.parameters(), - lr=config['learning_rate'], - betas=(config['adam_beta1'], config['adam_beta2']), - eps=config['adam_eps'], - heavyball_momentum=True, - ) + for k, v in d.items(): + if isinstance(v, dict): + for k2, v2 in unroll_nested_dict(v): + yield f"{k}/{k2}", v2 else: - raise ValueError(f'Unknown optimizer: {config["optimizer"]}') - - self.optimizer = optimizer - - # Logging - self.logger = logger - if logger is None: - self.logger = NoLogger(config) - - # Learning rate scheduler - epochs = config['total_timesteps'] // config['batch_size'] - eta_min = config['learning_rate'] * config['min_lr_ratio'] - self.scheduler = torch.optim.lr_scheduler.CosineAnnealingLR( - optimizer, T_max=epochs, eta_min=eta_min) - self.total_epochs = epochs - - # Automatic mixed precision - precision = config['precision'] - self.amp_context = contextlib.nullcontext() - if config.get('amp', True) and config['device'] == 'cuda': - self.amp_context = torch.amp.autocast(device_type='cuda', dtype=getattr(torch, precision)) - if precision not in ('float32', 'bfloat16'): - raise pufferlib.APIUsageError(f'Invalid precision: {precision}: use float32 or bfloat16') - - # Initializations - self.config = config - self.vecenv = vecenv - self.epoch = 0 - self.global_step = 0 - self.last_log_step = 0 - self.last_log_time = time.time() - self.start_time = time.time() - self.utilization = Utilization() - self.profile = Profile() - self.stats = defaultdict(list) - self.last_stats = defaultdict(list) - self.losses = {} - - # Dashboard - self.model_size = sum(p.numel() for p in policy.parameters() if p.requires_grad) - self.print_dashboard(clear=True) - - @property - def uptime(self): - return time.time() - self.start_time - - @property - def sps(self): - if self.global_step == self.last_log_step: - return 0 - - return (self.global_step - self.last_log_step) / (time.time() - self.last_log_time) - - def evaluate(self): - profile = self.profile - epoch = self.epoch - profile('eval', epoch) - profile('eval_misc', epoch, nest=True) - - config = self.config - device = config['device'] - - if config['use_rnn']: - for k in self.lstm_h: - self.lstm_h[k].zero_() - self.lstm_c[k].zero_() - - self.full_rows = 0 - while self.full_rows < self.segments: - profile('env', epoch) - o, r, d, t, info, env_id, mask = self.vecenv.recv() - - profile('eval_misc', epoch) - env_id = slice(env_id[0], env_id[-1] + 1) - - done_mask = d + t # TODO: Handle truncations separately - self.global_step += int(mask.sum()) - - profile('eval_copy', epoch) - o = torch.as_tensor(o) - o_device = o.to(device)#, non_blocking=True) - r = torch.as_tensor(r).to(device)#, non_blocking=True) - d = torch.as_tensor(d).to(device)#, non_blocking=True) - - profile('eval_forward', epoch) - with torch.no_grad(), self.amp_context: - state = dict( - reward=r, - done=d, - env_id=env_id, - mask=mask, - ) - - if config['use_rnn']: - state['lstm_h'] = self.lstm_h[env_id.start] - state['lstm_c'] = self.lstm_c[env_id.start] - - logits, value = self.policy.forward_eval(o_device, state) - action, logprob, _ = pufferlib.pytorch.sample_logits(logits) - r = torch.clamp(r, -1, 1) - - profile('eval_copy', epoch) - with torch.no_grad(): - if config['use_rnn']: - self.lstm_h[env_id.start] = state['lstm_h'] - self.lstm_c[env_id.start] = state['lstm_c'] - - # Fast path for fully vectorized envs - l = self.ep_lengths[env_id.start].item() - batch_rows = slice(self.ep_indices[env_id.start].item(), 1+self.ep_indices[env_id.stop - 1].item()) - - if config['cpu_offload']: - self.observations[batch_rows, l] = o - else: - self.observations[batch_rows, l] = o_device - - self.actions[batch_rows, l] = action - self.logprobs[batch_rows, l] = logprob - self.rewards[batch_rows, l] = r - self.terminals[batch_rows, l] = d.float() - self.values[batch_rows, l] = value.flatten() - - # Note: We are not yet handling masks in this version - self.ep_lengths[env_id] += 1 - if l+1 >= config['bptt_horizon']: - num_full = env_id.stop - env_id.start - self.ep_indices[env_id] = self.free_idx + torch.arange(num_full, device=config['device']).int() - self.ep_lengths[env_id] = 0 - self.free_idx += num_full - self.full_rows += num_full - - action = action.cpu().numpy() - if isinstance(logits, torch.distributions.Normal): - action = np.clip(action, self.vecenv.action_space.low, self.vecenv.action_space.high) - - profile('eval_misc', epoch) - for i in info: - for k, v in pufferlib.unroll_nested_dict(i): - if isinstance(v, np.ndarray): - v = v.tolist() - elif isinstance(v, (list, tuple)): - self.stats[k].extend(v) - else: - self.stats[k].append(v) - - profile('env', epoch) - self.vecenv.send(action) - - profile('eval_misc', epoch) - self.free_idx = self.total_agents - self.ep_indices = torch.arange(self.total_agents, device=device, dtype=torch.int32) - self.ep_lengths.zero_() - profile.end() - return self.stats - - @record - def train(self): - profile = self.profile - epoch = self.epoch - profile('train', epoch) - profile('train_misc', epoch, nest=True) - losses = defaultdict(float) - config = self.config - device = config['device'] - - b0 = config['prio_beta0'] - a = config['prio_alpha'] - clip_coef = config['clip_coef'] - vf_clip = config['vf_clip_coef'] - anneal_beta = b0 + (1 - b0)*a*self.epoch/self.total_epochs - self.ratio[:] = 1 - - for mb in range(self.total_minibatches): - profile('train_misc', epoch) - self.amp_context.__enter__() - - shape = self.values.shape - advantages = torch.zeros(shape, device=device) - advantages = compute_puff_advantage(self.values, self.rewards, - self.terminals, self.ratio, advantages, config['gamma'], - config['gae_lambda'], config['vtrace_rho_clip'], config['vtrace_c_clip']) - - # Prioritize experience by advantage magnitude - adv = advantages.abs().sum(axis=1) - prio_weights = torch.nan_to_num(adv**a, 0, 0, 0) - prio_probs = (prio_weights + 1e-6)/(prio_weights.sum() + 1e-6) - idx = torch.multinomial(prio_probs, self.minibatch_segments) - mb_prio = (self.segments*prio_probs[idx, None])**-anneal_beta - - profile('train_copy', epoch) - mb_obs = self.observations[idx] - mb_actions = self.actions[idx] - mb_logprobs = self.logprobs[idx] - mb_rewards = self.rewards[idx] - mb_terminals = self.terminals[idx] - mb_truncations = self.truncations[idx] - mb_ratio = self.ratio[idx] - mb_values = self.values[idx] - mb_returns = advantages[idx] + mb_values - mb_advantages = advantages[idx] - - profile('train_forward', epoch) - if not config['use_rnn']: - mb_obs = mb_obs.reshape(-1, *self.vecenv.single_observation_space.shape) - - state = dict( - action=mb_actions, - lstm_h=None, - lstm_c=None, - ) + yield k, v - logits, newvalue = self.policy(mb_obs, state) - actions, newlogprob, entropy = pufferlib.pytorch.sample_logits(logits, action=mb_actions) - - profile('train_misc', epoch) - newlogprob = newlogprob.reshape(mb_logprobs.shape) - logratio = newlogprob - mb_logprobs - ratio = logratio.exp() - self.ratio[idx] = ratio.detach() - - with torch.no_grad(): - old_approx_kl = (-logratio).mean() - approx_kl = ((ratio - 1) - logratio).mean() - clipfrac = ((ratio - 1.0).abs() > config['clip_coef']).float().mean() - - # NOTE: Commenting this out since adv is replaced below - # adv = advantages[idx] - # adv = compute_puff_advantage(mb_values, mb_rewards, mb_terminals, - # ratio, adv, config['gamma'], config['gae_lambda'], - # config['vtrace_rho_clip'], config['vtrace_c_clip']) - - # Weight advantages by priority and normalize - adv = mb_advantages - adv = mb_prio * (adv - adv.mean()) / (adv.std() + 1e-8) - - # Losses - pg_loss1 = -adv * ratio - pg_loss2 = -adv * torch.clamp(ratio, 1 - clip_coef, 1 + clip_coef) - pg_loss = torch.max(pg_loss1, pg_loss2).mean() - - newvalue = newvalue.view(mb_returns.shape) - v_clipped = mb_values + torch.clamp(newvalue - mb_values, -vf_clip, vf_clip) - v_loss_unclipped = (newvalue - mb_returns) ** 2 - v_loss_clipped = (v_clipped - mb_returns) ** 2 - v_loss = 0.5*torch.max(v_loss_unclipped, v_loss_clipped).mean() - - entropy_loss = entropy.mean() - - loss = pg_loss + config['vf_coef']*v_loss - config['ent_coef']*entropy_loss - self.amp_context.__enter__() # TODO: AMP needs some debugging - - # This breaks vloss clipping? - self.values[idx] = newvalue.detach().float() - - # Logging - profile('train_misc', epoch) - losses['policy_loss'] += pg_loss.item() / self.total_minibatches - losses['value_loss'] += v_loss.item() / self.total_minibatches - losses['entropy'] += entropy_loss.item() / self.total_minibatches - losses['old_approx_kl'] += old_approx_kl.item() / self.total_minibatches - losses['approx_kl'] += approx_kl.item() / self.total_minibatches - losses['clipfrac'] += clipfrac.item() / self.total_minibatches - losses['importance'] += ratio.mean().item() / self.total_minibatches - - # Learn on accumulated minibatches - profile('learn', epoch) - loss.backward() - if (mb + 1) % self.accumulate_minibatches == 0: - torch.nn.utils.clip_grad_norm_(self.policy.parameters(), config['max_grad_norm']) - self.optimizer.step() - self.optimizer.zero_grad() - - # Reprioritize experience - profile('train_misc', epoch) - if config['anneal_lr']: - self.scheduler.step() - - y_pred = self.values.flatten() - y_true = advantages.flatten() + self.values.flatten() - var_y = y_true.var() - explained_var = torch.nan if var_y == 0 else (1 - (y_true - y_pred).var() / var_y).item() - losses['explained_variance'] = explained_var - - profile.end() - logs = None - self.epoch += 1 - done_training = self.global_step >= config['total_timesteps'] - if done_training or self.global_step == 0 or time.time() > self.last_log_time + 0.25: - logs = self.mean_and_log() - self.losses = losses - self.print_dashboard() - self.stats = defaultdict(list) - self.last_log_time = time.time() - self.last_log_step = self.global_step - profile.clear() - - if self.epoch % config['checkpoint_interval'] == 0 or done_training: - self.save_checkpoint() - self.msg = f'Checkpoint saved at update {self.epoch}' - - return logs - - def mean_and_log(self): - config = self.config - for k in list(self.stats.keys()): - v = self.stats[k] - try: - v = np.mean(v) - except: - del self.stats[k] - - self.stats[k] = v - - device = config['device'] - agent_steps = int(dist_sum(self.global_step, device)) - logs = { - 'SPS': dist_sum(self.sps, device), - 'agent_steps': agent_steps, - 'uptime': time.time() - self.start_time, - 'epoch': int(dist_sum(self.epoch, device)), - 'learning_rate': self.optimizer.param_groups[0]["lr"], - **{f'environment/{k}': v for k, v in self.stats.items()}, - **{f'losses/{k}': v for k, v in self.losses.items()}, - **{f'performance/{k}': v['elapsed'] for k, v in self.profile}, - #**{f'environment/{k}': dist_mean(v, device) for k, v in self.stats.items()}, - #**{f'losses/{k}': dist_mean(v, device) for k, v in self.losses.items()}, - #**{f'performance/{k}': dist_sum(v['elapsed'], device) for k, v in self.profile}, - } - - if torch.distributed.is_initialized(): - if torch.distributed.get_rank() != 0: - self.logger.log(logs, agent_steps) - return logs - else: - return None - - self.logger.log(logs, agent_steps) - return logs - - def close(self): - self.vecenv.close() - self.utilization.stop() - model_path = self.save_checkpoint() - run_id = self.logger.run_id - path = os.path.join(self.config['data_dir'], f'{self.config["env"]}_{run_id}.pt') - shutil.copy(model_path, path) - return path - - def save_checkpoint(self): - if torch.distributed.is_initialized(): - if torch.distributed.get_rank() != 0: - return - - run_id = self.logger.run_id - path = os.path.join(self.config['data_dir'], f'{self.config["env"]}_{run_id}') - if not os.path.exists(path): - os.makedirs(path) - - model_name = f'model_{self.config["env"]}_{self.epoch:06d}.pt' - model_path = os.path.join(path, model_name) - if os.path.exists(model_path): - return model_path - - torch.save(self.uncompiled_policy.state_dict(), model_path) - - state = { - 'optimizer_state_dict': self.optimizer.state_dict(), - 'global_step': self.global_step, - 'agent_step': self.global_step, - 'update': self.epoch, - 'model_name': model_name, - 'run_id': run_id, - } - state_path = os.path.join(path, 'trainer_state.pt') - torch.save(state, state_path + '.tmp') - os.replace(state_path + '.tmp', state_path) - return model_path - - def print_dashboard(self, clear=False, idx=[0], - c1='[cyan]', c2='[dim default]', b1='[bright_cyan]', b2='[default]'): - config = self.config - sps = dist_sum(self.sps, config['device']) - agent_steps = dist_sum(self.global_step, config['device']) - if torch.distributed.is_initialized(): - if torch.distributed.get_rank() != 0: - return - - profile = self.profile - console = Console() - dashboard = Table(box=rich.box.ROUNDED, expand=True, - show_header=False, border_style='bright_cyan') - table = Table(box=None, expand=True, show_header=False) - dashboard.add_row(table) - - table.add_column(justify="left", width=30) - table.add_column(justify="center", width=12) - table.add_column(justify="center", width=12) - table.add_column(justify="center", width=13) - table.add_column(justify="right", width=13) - - table.add_row( - f'{b1}PufferLib {b2}3.0 {idx[0]*" "}:blowfish:', - f'{c1}CPU: {b2}{np.mean(self.utilization.cpu_util):.1f}{c2}%', - f'{c1}GPU: {b2}{np.mean(self.utilization.gpu_util):.1f}{c2}%', - f'{c1}DRAM: {b2}{np.mean(self.utilization.cpu_mem):.1f}{c2}%', - f'{c1}VRAM: {b2}{np.mean(self.utilization.gpu_mem):.1f}{c2}%', - ) - idx[0] = (idx[0] - 1) % 10 - - s = Table(box=None, expand=True) - remaining = f'{b2}A hair past a freckle{c2}' - if sps != 0: - remaining = duration((config['total_timesteps'] - agent_steps)/sps, b2, c2) - - s.add_column(f"{c1}Summary", justify='left', vertical='top', width=10) - s.add_column(f"{c1}Value", justify='right', vertical='top', width=14) - s.add_row(f'{b2}Env', f'{b2}{config["env"]}') - s.add_row(f'{b2}Params', abbreviate(self.model_size, b2, c2)) - s.add_row(f'{b2}Steps', abbreviate(agent_steps, b2, c2)) - s.add_row(f'{b2}SPS', abbreviate(sps, b2, c2)) - s.add_row(f'{b2}Epoch', f'{b2}{self.epoch}') - s.add_row(f'{b2}Uptime', duration(self.uptime, b2, c2)) - s.add_row(f'{b2}Remaining', remaining) - - delta = profile.eval['buffer'] + profile.train['buffer'] - p = Table(box=None, expand=True, show_header=False) - p.add_column(f"{c1}Performance", justify="left", width=10) - p.add_column(f"{c1}Time", justify="right", width=8) - p.add_column(f"{c1}%", justify="right", width=4) - p.add_row(*fmt_perf('Evaluate', b1, delta, profile.eval, b2, c2)) - p.add_row(*fmt_perf(' Forward', b2, delta, profile.eval_forward, b2, c2)) - p.add_row(*fmt_perf(' Env', b2, delta, profile.env, b2, c2)) - p.add_row(*fmt_perf(' Copy', b2, delta, profile.eval_copy, b2, c2)) - p.add_row(*fmt_perf(' Misc', b2, delta, profile.eval_misc, b2, c2)) - p.add_row(*fmt_perf('Train', b1, delta, profile.train, b2, c2)) - p.add_row(*fmt_perf(' Forward', b2, delta, profile.train_forward, b2, c2)) - p.add_row(*fmt_perf(' Learn', b2, delta, profile.learn, b2, c2)) - p.add_row(*fmt_perf(' Copy', b2, delta, profile.train_copy, b2, c2)) - p.add_row(*fmt_perf(' Misc', b2, delta, profile.train_misc, b2, c2)) - - l = Table(box=None, expand=True, ) - l.add_column(f'{c1}Losses', justify="left", width=16) - l.add_column(f'{c1}Value', justify="right", width=8) - for metric, value in self.losses.items(): - l.add_row(f'{b2}{metric}', f'{b2}{value:.3f}') - - monitor = Table(box=None, expand=True, pad_edge=False) - monitor.add_row(s, p, l) - dashboard.add_row(monitor) - - table = Table(box=None, expand=True, pad_edge=False) - dashboard.add_row(table) - left = Table(box=None, expand=True) - right = Table(box=None, expand=True) - table.add_row(left, right) - left.add_column(f"{c1}User Stats", justify="left", width=20) - left.add_column(f"{c1}Value", justify="right", width=10) - right.add_column(f"{c1}User Stats", justify="left", width=20) - right.add_column(f"{c1}Value", justify="right", width=10) - i = 0 - - if self.stats: - self.last_stats = self.stats - - for metric, value in (self.stats or self.last_stats).items(): - try: # Discard non-numeric values - int(value) - except: - continue +def abbreviate(num, b2, c2): + prefixes = ['', 'K', 'M', 'B', 'T'] + for i, prefix in enumerate(prefixes): + if num < 1e3: break + num /= 1e3 + + return f'{b2}{num:.1f}{c2}{prefix}' +def duration(seconds, b2, c2): + if seconds < 0: return f"{b2}0{c2}s" + if seconds < 1: return f"{b2}{seconds*1000:.0f}{c2}ms" + seconds = int(seconds) + d = f'{b2}{seconds // 86400}{c2}d ' + h = f'{b2}{(seconds // 3600) % 24}{c2}h ' + m = f'{b2}{(seconds // 60) % 60}{c2}m ' + s = f'{b2}{seconds % 60}{c2}s' + return d + h + m + s + +def fmt_perf(name, color, delta_ref, elapsed, b2, c2): + percent = 0 if delta_ref == 0 else int(100*elapsed/delta_ref - 1e-5) + return f'{color}{name}', duration(elapsed, b2, c2), f'{b2}{percent:2d}{c2}%' + +def print_dashboard(args, model_size, flat_logs, clear=False, idx=[0], + c1='[cyan]', c2='[white]', b1='[bright_cyan]', b2='[bright_white]'): + g = lambda k, d=0: flat_logs.get(k, d) + console = rich.console.Console() + dashboard = Table(box=rich.box.ROUNDED, expand=True, + show_header=False, border_style='bright_cyan') + table = Table(box=None, expand=True, show_header=False) + dashboard.add_row(table) + + table.add_column(justify="left", width=30) + table.add_column(justify="center", width=12) + table.add_column(justify="center", width=18) + table.add_column(justify="right", width=12) + + table.add_row( + f'{b1}PufferLib {b2}4.0 {idx[0]*" "}:blowfish:', + f'{c1}GPU: {b2}{g("util/gpu_percent"):.0f}{c2}%', + f'{c1}VRAM: {b2}{g("util/vram_used_gb"):.1f}{c2}/{b2}{g("util/vram_total_gb"):.0f}{c2}G', + f'{c1}RAM: {b2}{g("util/cpu_mem_gb"):.1f}{c2}G', + ) + idx[0] = (idx[0] - 1) % 10 + + s = Table(box=None, expand=True) + remaining = f'{b2}A hair past a freckle{c2}' + agent_steps = g('agent_steps') + if g('SPS') != 0: + remaining = duration((args['train']['total_timesteps']*args['train'].get('gpus', 1) - agent_steps)/g('SPS'), b2, c2) + + s.add_column(f"{c1}Summary", justify='left', vertical='top', width=10) + s.add_column(f"{c1}Value", justify='right', vertical='top', width=14) + s.add_row(f'{c2}Env', f'{b2}{args["env_name"]}') + s.add_row(f'{c2}Params', abbreviate(model_size, b2, c2)) + s.add_row(f'{c2}Steps', abbreviate(agent_steps, b2, c2)) + s.add_row(f'{c2}SPS', abbreviate(g('SPS'), b2, c2)) + s.add_row(f'{c2}Epoch', f'{b2}{g("epoch")}') + s.add_row(f'{c2}Uptime', duration(g('uptime'), b2, c2)) + s.add_row(f'{c2}Remaining', remaining) + + rollout = g('perf/rollout') + train = g('perf/train') + delta = rollout + train + p = Table(box=None, expand=True, show_header=False) + p.add_column(f"{c1}Performance", justify="left", width=10) + p.add_column(f"{c1}Time", justify="right", width=8) + p.add_column(f"{c1}%", justify="right", width=4) + p.add_row(*fmt_perf('Evaluate', b1, delta, rollout, b2, c2)) + p.add_row(*fmt_perf(' GPU', b2, delta, g('perf/eval_gpu'), b2, c2)) + p.add_row(*fmt_perf(' Env', b2, delta, g('perf/eval_env'), b2, c2)) + p.add_row(*fmt_perf('Train', b1, delta, train, b2, c2)) + p.add_row(*fmt_perf(' Misc', b2, delta, g('perf/train_misc'), b2, c2)) + p.add_row(*fmt_perf(' Forward', b2, delta, g('perf/train_forward'), b2, c2)) + + l = Table(box=None, expand=True) + l.add_column(f'{c1}Losses', justify="left", width=16) + l.add_column(f'{c1}Value', justify="right", width=8) + for k, v in flat_logs.items(): + if k.startswith('loss/'): + l.add_row(f'{b2}{k[5:]}', f'{b2}{v:.3f}') + + monitor = Table(box=None, expand=True, pad_edge=False) + monitor.add_row(s, p, l) + dashboard.add_row(monitor) + + table = Table(box=None, expand=True, pad_edge=False) + dashboard.add_row(table) + left = Table(box=None, expand=True) + right = Table(box=None, expand=True) + table.add_row(left, right) + left.add_column(f"{c1}User Stats", justify="left", width=20) + left.add_column(f"{c1}Value", justify="right", width=10) + right.add_column(f"{c1}User Stats", justify="left", width=20) + right.add_column(f"{c1}Value", justify="right", width=10) + + i = 0 + for k, v in flat_logs.items(): + if k.startswith('env/') and k != 'env/n': u = left if i % 2 == 0 else right - u.add_row(f'{b2}{metric}', f'{b2}{value:.3f}') + u.add_row(f'{b2}{k[4:]}', f'{b2}{v:.3f}') i += 1 if i == 30: break - if clear: - console.clear() + if clear: + console.clear() + + with console.capture() as capture: + console.print(dashboard) + + print('\033[0;0H' + capture.get()) + +def validate_config(args): + minibatch_size = args['train']['minibatch_size'] + horizon = args['train']['horizon'] + total_agents = args['vec']['total_agents'] + assert (minibatch_size % horizon) == 0, \ + f'minibatch_size {minibatch_size} must be divisible by horizon {horizon}' + assert minibatch_size <= horizon * total_agents, \ + f'minibatch_size {minibatch_size} > total_agents {total_agents} * horizon {horizon}' + +def _resolve_backend(args): + compiled_env = getattr(_C, 'env_name', None) + assert compiled_env is None or compiled_env == args['env_name'], \ + f'build.sh was run for {compiled_env}, not {args["env_name"]}' + if args.get('slowly'): + from pufferlib.torch_pufferl import PuffeRL + return PuffeRL + return _C + +def _train_worker(args): + backend = _resolve_backend(args) + pufferl = backend.create_pufferl(args) + args.pop('nccl_id', None) + while pufferl.global_step < args['train']['total_timesteps']: + backend.rollouts(pufferl) + backend.train(pufferl) + + backend.close(pufferl) + +def _train(env_name, args, sweep_obj=None, result_queue=None, verbose=False): + '''Single-GPU training worker. Process target for both DDP ranks and sweep trials.''' + backend = _resolve_backend(args) + rank = args['rank'] + run_id = str(int(1000*time.time())) + if args['wandb']: + import wandb + run_id = wandb.util.generate_id() + wandb.init(id=run_id, config=args, + project=args['wandb_project'], group=args['wandb_group'], + tags=[args['tag']] if args['tag'] is not None else [], + settings=wandb.Settings(console="off"), + ) - with console.capture() as capture: - console.print(dashboard) + target_key = f'env/{args["sweep"]["metric"]}' + total_timesteps = args['train']['total_timesteps'] + all_logs = [] - print('\033[0;0H' + capture.get()) + checkpoint_dir = os.path.join(args['checkpoint_dir'], args['env_name'], run_id) + os.makedirs(checkpoint_dir, exist_ok=True) -def compute_puff_advantage(values, rewards, terminals, - ratio, advantages, gamma, gae_lambda, vtrace_rho_clip, vtrace_c_clip): - '''CUDA kernel for puffer advantage with automatic CPU fallback. You need - nvcc (in cuda-dev-tools or in a cuda-dev docker base) for PufferLib to - compile the fast version.''' + log_dir = os.path.join(args['log_dir'], args['env_name']) + os.makedirs(log_dir, exist_ok=True) - device = values.device - if not ADVANTAGE_CUDA: - values = values.cpu() - rewards = rewards.cpu() - terminals = terminals.cpu() - ratio = ratio.cpu() - advantages = advantages.cpu() + try: + pufferl = backend.create_pufferl(args) + except RuntimeError as e: + print(f'WARNING: {e}, skipping') + if result_queue is not None: + result_queue.put((args['gpu_id'], [], [], [])) + return + + args.pop('nccl_id', None) + model_size = pufferl.num_params() + if verbose: + flat_logs = dict(unroll_nested_dict(backend.log(pufferl))) + print_dashboard(args, model_size, flat_logs, clear=True) + + model_path = '' + flat_logs = {} + train_epochs = int(total_timesteps // (args['vec']['total_agents'] * args['train']['horizon'])) + eval_epochs = train_epochs // 2 + for epoch in range(train_epochs + eval_epochs): + backend.rollouts(pufferl) + + if epoch < train_epochs: + backend.train(pufferl) + + if (epoch % args['checkpoint_interval'] == 0 or epoch == train_epochs - 1) and sweep_obj is None: + model_path = os.path.join(checkpoint_dir, f'{pufferl.global_step:016d}.bin') + backend.save_weights(pufferl, model_path) + + # Rate limit, but always log for eval to maintain determinism + if time.time() < pufferl.last_log_time + 0.6 and epoch < train_epochs - 1: + continue - torch.ops.pufferlib.compute_puff_advantage(values, rewards, terminals, - ratio, advantages, gamma, gae_lambda, vtrace_rho_clip, vtrace_c_clip) + logs = backend.eval_log(pufferl) if epoch >= train_epochs else backend.log(pufferl) + flat_logs = {**flat_logs, **dict(unroll_nested_dict(logs))} - if not ADVANTAGE_CUDA: - return advantages.to(device) + if verbose: + print_dashboard(args, model_size, flat_logs) - return advantages + if target_key not in flat_logs: + continue + if args['wandb']: + wandb.log(flat_logs, step=flat_logs['agent_steps']) -def abbreviate(num, b2, c2): - if num < 1e3: - return f'{b2}{num}{c2}' - elif num < 1e6: - return f'{b2}{num/1e3:.1f}{c2}K' - elif num < 1e9: - return f'{b2}{num/1e6:.1f}{c2}M' - elif num < 1e12: - return f'{b2}{num/1e9:.1f}{c2}B' - else: - return f'{b2}{num/1e12:.2f}{c2}T' + if epoch < train_epochs: + all_logs.append(flat_logs) -def duration(seconds, b2, c2): - if seconds < 0: - return f"{b2}0{c2}s" - seconds = int(seconds) - h = seconds // 3600 - m = (seconds % 3600) // 60 - s = seconds % 60 - return f"{b2}{h}{c2}h {b2}{m}{c2}m {b2}{s}{c2}s" if h else f"{b2}{m}{c2}m {b2}{s}{c2}s" if m else f"{b2}{s}{c2}s" - -def fmt_perf(name, color, delta_ref, prof, b2, c2): - percent = 0 if delta_ref == 0 else int(100*prof['buffer']/delta_ref - 1e-5) - return f'{color}{name}', duration(prof['elapsed'], b2, c2), f'{b2}{percent:2d}{c2}%' - -def dist_sum(value, device): - if not torch.distributed.is_initialized(): - return value - - tensor = torch.tensor(value, device=device) - torch.distributed.all_reduce(tensor, op=torch.distributed.ReduceOp.SUM) - return tensor.item() - -def dist_mean(value, device): - if not torch.distributed.is_initialized(): - return value - - return dist_sum(value, device) / torch.distributed.get_world_size() - -class Profile: - def __init__(self, frequency=5): - self.profiles = defaultdict(lambda: defaultdict(float)) - self.frequency = frequency - self.stack = [] - - def __iter__(self): - return iter(self.profiles.items()) - - def __getattr__(self, name): - return self.profiles[name] - - def __call__(self, name, epoch, nest=False): - # Skip profiling the first few epochs, which are noisy due to setup - if (epoch + 1) % self.frequency != 0: - return - - if torch.cuda.is_available(): - torch.cuda.synchronize() - - tick = time.time() - if len(self.stack) != 0 and not nest: - self.pop(tick) - - self.stack.append(name) - self.profiles[name]['start'] = tick - - def pop(self, end): - profile = self.profiles[self.stack.pop()] - delta = end - profile['start'] - profile['delta'] += delta - # Multiply delta by freq to account for skipped epochs - profile['elapsed'] += delta * self.frequency - - def end(self): - if torch.cuda.is_available(): - torch.cuda.synchronize() - - end = time.time() - for i in range(len(self.stack)): - self.pop(end) - - def clear(self): - for prof in self.profiles.values(): - if prof['delta'] > 0: - prof['buffer'] = prof['delta'] - prof['delta'] = 0 - -class Utilization(Thread): - def __init__(self, delay=1, maxlen=20): - super().__init__() - self.cpu_mem = deque([0], maxlen=maxlen) - self.cpu_util = deque([0], maxlen=maxlen) - self.gpu_util = deque([0], maxlen=maxlen) - self.gpu_mem = deque([0], maxlen=maxlen) - self.stopped = False - self.delay = delay - self.start() - - def run(self): - while not self.stopped: - self.cpu_util.append(100*psutil.cpu_percent()/psutil.cpu_count()) - mem = psutil.virtual_memory() - self.cpu_mem.append(100*mem.active/mem.total) - if torch.cuda.is_available(): - # Monitoring in distributed crashes nvml - if torch.distributed.is_initialized(): - time.sleep(self.delay) - continue - - self.gpu_util.append(torch.cuda.utilization()) - free, total = torch.cuda.mem_get_info() - self.gpu_mem.append(100*(total-free)/total) - else: - self.gpu_util.append(0) - self.gpu_mem.append(0) - - time.sleep(self.delay) - - def stop(self): - self.stopped = True - -def downsample(data_list, num_points): - if not data_list or num_points <= 0: - return [] - if num_points == 1: - return [data_list[-1]] - if len(data_list) <= num_points: - return data_list - - last = data_list[-1] - data_list = data_list[:-1] - - data_np = np.array(data_list) - num_points -= 1 # one down for the last one - - n = (len(data_np) // num_points) * num_points - data_np = data_np[-n:] if n > 0 else data_np - downsampled = data_np.reshape(num_points, -1).mean(axis=1) - - return downsampled.tolist() + [last] - -class NoLogger: - def __init__(self, args): - self.run_id = str(int(100*time.time())) - - def log(self, logs, step): - pass - - def close(self, model_path, early_stop): - pass - -class NeptuneLogger: - def __init__(self, args, load_id=None, mode='async'): - import neptune as nept - neptune_name = args['neptune_name'] - neptune_project = args['neptune_project'] - neptune = nept.init_run( - project=f"{neptune_name}/{neptune_project}", - capture_hardware_metrics=False, - capture_stdout=False, - capture_stderr=False, - capture_traceback=False, - with_id=load_id, - mode=mode, - tags = [args['tag']] if args['tag'] is not None else [], - ) - self.run_id = neptune._sys_id - self.neptune = neptune - for k, v in pufferlib.unroll_nested_dict(args): - neptune[k].append(v) - self.should_upload_model = not args['no_model_upload'] - - def log(self, logs, step): - for k, v in logs.items(): - self.neptune[k].append(v, step=step) - - def upload_model(self, model_path): - self.neptune['model'].track_files(model_path) - - def close(self, model_path, early_stop): - self.neptune['early_stop'] = early_stop - if self.should_upload_model: - self.upload_model(model_path) - self.neptune.stop() - - def download(self): - self.neptune["model"].download(destination='artifacts') - return f'artifacts/{self.run_id}.pt' - -class WandbLogger: - def __init__(self, args, load_id=None, resume='allow'): - import wandb - wandb.init( - id=load_id or wandb.util.generate_id(), - project=args['wandb_project'], - group=args['wandb_group'], - allow_val_change=True, - save_code=False, - resume=resume, - config=args, - tags = [args['tag']] if args['tag'] is not None else [], - settings=wandb.Settings(console="off"), # stop sending dashboard to wandb - ) - self.wandb = wandb - self.run_id = wandb.run.id - self.should_upload_model = not args['no_model_upload'] - - def log(self, logs, step): - self.wandb.log(logs, step=step) - - def upload_model(self, model_path): - artifact = self.wandb.Artifact(self.run_id, type='model') - artifact.add_file(model_path) - self.wandb.run.log_artifact(artifact) - - def close(self, model_path, early_stop): - self.wandb.run.summary['early_stop'] = early_stop - if self.should_upload_model: - self.upload_model(model_path) - self.wandb.finish() - - def download(self): - artifact = self.wandb.use_artifact(f'{self.run_id}:latest') - data_dir = artifact.download() - model_file = max(os.listdir(data_dir)) - return f'{data_dir}/{model_file}' - -def train(env_name, args=None, vecenv=None, policy=None, logger=None, early_stop_fn=None): - args = args or load_config(env_name) + if (sweep_obj is not None + and pufferl.global_step > min(0.20*total_timesteps, 100_000_000) and + sweep_obj.early_stop(logs, target_key)): + break + elif flat_logs['env/n'] > args['eval_episodes']: + break - # Assume TorchRun DDP is used if LOCAL_RANK is set - if 'LOCAL_RANK' in os.environ: - world_size = int(os.environ.get('WORLD_SIZE', 1)) - print("World size", world_size) - master_addr = os.environ.get('MASTER_ADDR', 'localhost') - master_port = os.environ.get('MASTER_PORT', '29500') - local_rank = int(os.environ["LOCAL_RANK"]) - print(f"rank: {local_rank}, MASTER_ADDR={master_addr}, MASTER_PORT={master_port}") - torch.cuda.set_device(local_rank) - os.environ["CUDA_VISIBLE_DEVICES"] = str(local_rank) - - vecenv = vecenv or load_env(env_name, args) - policy = policy or load_policy(args, vecenv, env_name) - - if 'LOCAL_RANK' in os.environ: - args['train']['device'] = torch.cuda.current_device() - torch.distributed.init_process_group(backend='nccl', world_size=world_size) - policy = policy.to(local_rank) - model = torch.nn.parallel.DistributedDataParallel( - policy, device_ids=[local_rank], output_device=local_rank - ) - if hasattr(policy, 'lstm'): - #model.lstm = policy.lstm - model.hidden_size = policy.hidden_size - model.forward_eval = policy.forward_eval - policy = model.to(local_rank) + print_dashboard(args, model_size, flat_logs) + backend.close(pufferl) - if args['neptune']: - logger = NeptuneLogger(args) - elif args['wandb']: - logger = WandbLogger(args) + if target_key not in flat_logs: + if result_queue is not None: + result_queue.put((args['gpu_id'], None, None, None)) + return - train_config = { **args['train'], 'env': env_name } - pufferl = PuffeRL(train_config, vecenv, policy, logger) + # This version has the training perf logs and eval env logs + all_logs.append(flat_logs) - # Sweep needs data for early stopped runs, so send data when steps > 100M - logging_threshold = min(0.20*train_config['total_timesteps'], 100_000_000) - all_logs = [] + # Downsample results + n = args['sweep']['downsample'] + metrics = {k: [[]] for k in all_logs[0]} + logged_timesteps = all_logs[-1]['agent_steps'] + next_bin = logged_timesteps / (n - 1) if n > 1 else np.inf + for log in all_logs: + for k, v in log.items(): + metrics[k][-1].append(v) - while pufferl.global_step < train_config['total_timesteps']: - if train_config['device'] == 'cuda': - torch.compiler.cudagraph_mark_step_begin() - pufferl.evaluate() - if train_config['device'] == 'cuda': - torch.compiler.cudagraph_mark_step_begin() - logs = pufferl.train() - - if logs is not None: - should_stop_early = False - if early_stop_fn is not None: - should_stop_early = early_stop_fn(logs) - # This is hacky, but need to see if threshold looks reasonable - if 'early_stop_threshold' in logs: - pufferl.logger.log({'environment/early_stop_threshold': logs['early_stop_threshold']}, logs['agent_steps']) - - if pufferl.global_step > logging_threshold: - all_logs.append(logs) - - if should_stop_early: - model_path = pufferl.close() - pufferl.logger.close(model_path, early_stop=True) - return all_logs - - # Final eval. You can reset the env here, but depending on - # your env, this can skew data (i.e. you only collect the shortest - # rollouts within a fixed number of epochs) - for i in range(128): # Run eval for at least 32, but put a hard stop at 128. - stats = pufferl.evaluate() - if i >= 32 and stats: - break + if log['agent_steps'] < next_bin: + continue - logs = pufferl.mean_and_log() - if logs is not None: - all_logs.append(logs) + next_bin += logged_timesteps / (n - 1) + for k in metrics: + metrics[k][-1] = np.mean(metrics[k][-1]) + metrics[k].append([]) - pufferl.print_dashboard() - model_path = pufferl.close() - pufferl.logger.close(model_path, early_stop=False) - return all_logs + for k in metrics: + metrics[k][-1] = all_logs[-1][k] -def eval(env_name, args=None, vecenv=None, policy=None): - args = args or load_config(env_name) - backend = args['vec']['backend'] - if backend != 'PufferEnv': - backend = 'Serial' - - args['vec'] = dict(backend=backend, num_envs=1) - vecenv = vecenv or load_env(env_name, args) - - policy = policy or load_policy(args, vecenv, env_name) - ob, info = vecenv.reset() - driver = vecenv.driver_env - num_agents = vecenv.observation_space.shape[0] - device = args['train']['device'] - - state = {} - if args['train']['use_rnn']: - state = dict( - lstm_h=torch.zeros(num_agents, policy.hidden_size, device=device), - lstm_c=torch.zeros(num_agents, policy.hidden_size, device=device), - ) + # Save own log: config + downsampled results + log_dir = os.path.join(args['log_dir'], args['env_name']) + os.makedirs(log_dir, exist_ok=True) + with open(os.path.join(log_dir, run_id + '.json'), 'w') as f: + json.dump({**args, 'metrics': metrics}, f) - frames = [] - while True: - render = driver.render() - if len(frames) < args['save_frames']: - frames.append(render) - - # Screenshot Ocean envs with F12, gifs with control + F12 - if driver.render_mode == 'ansi': - print('\033[0;0H' + render + '\n') - time.sleep(1/args['fps']) - elif driver.render_mode == 'rgb_array': - pass - #import cv2 - #render = cv2.cvtColor(render, cv2.COLOR_RGB2BGR) - #cv2.imshow('frame', render) - #cv2.waitKey(1) - #time.sleep(1/args['fps']) - - with torch.no_grad(): - ob = torch.as_tensor(ob).to(device) - logits, value = policy.forward_eval(ob, state) - action, logprob, _ = pufferlib.pytorch.sample_logits(logits) - action = action.cpu().numpy().reshape(vecenv.action_space.shape) - - if isinstance(logits, torch.distributions.Normal): - action = np.clip(action, vecenv.action_space.low, vecenv.action_space.high) - - ob = vecenv.step(action)[0] - - if len(frames) > 0 and len(frames) == args['save_frames']: - import imageio - imageio.mimsave(args['gif_path'], frames, fps=args['fps'], loop=0) - print(f'Saved {len(frames)} frames to {args["gif_path"]}') - -def stop_if_loss_nan(logs): - return any("losses/" in k and np.isnan(v) for k, v in logs.items()) - -def sweep(args=None, env_name=None): + if args['wandb']: + if sweep_obj is None and model_path: # Don't spam uploads during sweeps + artifact = wandb.Artifact(run_id, type='model') + artifact.add_file(model_path) + wandb.run.log_artifact(artifact) + + wandb.run.finish() + + if result_queue is not None: + result_queue.put((args['gpu_id'], metrics['env/score'], metrics['uptime'], metrics['agent_steps'])) + +def train(env_name, args=None, gpus=None, **kwargs): args = args or load_config(env_name) - if not args['wandb'] and not args['neptune']: - raise pufferlib.APIUsageError('Sweeps require either wandb or neptune') - args['no_model_upload'] = True # Uploading trained model during sweep crashed wandb + validate_config(args) + + subprocess = gpus is not None + gpus = list(gpus or range(args['train']['gpus'])) + args['train']['total_timesteps'] //= len(gpus) + args['world_size'] = len(gpus) + args['nccl_id'] = _C.get_nccl_id() if len(gpus) > 1 else b'' + + if not subprocess: + gpus = gpus[-1:] + gpus[:-1] # Main process gets rank 0 + + ctx = mp.get_context('spawn') + for rank, gpu_id in reversed(list(enumerate(gpus))): + worker_args = deepcopy(args) + worker_args['rank'] = rank + worker_args['gpu_id'] = gpu_id + if rank == 0 and not subprocess: + _train(env_name, worker_args, verbose=True) + else: + ctx.Process(target=_train, args=(env_name, worker_args), + kwargs=kwargs).start() - method = args['sweep'].pop('method') +def sweep(env_name, args=None, pareto=False): + '''Train entry point. Handles single-GPU, multi-GPU DDP, and sweeps.''' + args = args or load_config(env_name) + exp_gpus = args['train']['gpus'] + sweep_gpus = args['sweep']['gpus'] or len(os.listdir('/proc/driver/nvidia/gpus')) + args['vec']['num_threads'] //= (sweep_gpus // exp_gpus) + args['no_model_upload'] = True + + sweep_config = args['sweep'] + method = sweep_config.pop('method') + import pufferlib.sweep try: sweep_cls = getattr(pufferlib.sweep, method) except: - raise pufferlib.APIUsageError(f'Invalid sweep method {method}. See pufferlib.sweep') - - sweep = sweep_cls(args['sweep']) - points_per_run = args['sweep']['downsample'] - target_key = f'environment/{args["sweep"]["metric"]}' - running_target_buffer = deque(maxlen=30) - - def stop_if_perf_below(logs): - if stop_if_loss_nan(logs): - logs['is_loss_nan'] = True - return True - - if method != 'Protein': - return False - - if ('uptime' in logs and target_key in logs): - metric_val, cost = logs[target_key], logs['uptime'] - running_target_buffer.append(metric_val) - target_running_mean = np.mean(running_target_buffer) - - # If metric distribution is percentile, threshold is also logit transformed - threshold = sweep.get_early_stop_threshold(cost) - logs['early_stop_threshold'] = max(threshold, -5) # clipping for visualization - - if sweep.should_stop(max(target_running_mean, metric_val), cost): - logs['is_loss_nan'] = False - return True - return False - - for i in range(args['max_runs']): - seed = time.time_ns() & 0xFFFFFFFF - random.seed(seed) - np.random.seed(seed) - torch.manual_seed(seed) - - # In the first run, skip sweep and use the train args specified in the config - if i > 0: - sweep.suggest(args) - - all_logs = train(env_name, args=args, early_stop_fn=stop_if_perf_below) - all_logs = [e for e in all_logs if target_key in e] - - if not all_logs: - sweep.observe(args, 0, 0, is_failure=True) - continue - - total_timesteps = args['train']['total_timesteps'] - - scores = downsample([log[target_key] for log in all_logs], points_per_run) - costs = downsample([log['uptime'] for log in all_logs], points_per_run) - timesteps = downsample([log['agent_steps'] for log in all_logs], points_per_run) - - is_final_loss_nan = all_logs[-1].get('is_loss_nan', False) - if is_final_loss_nan: - s = scores.pop() - c = costs.pop() - args['train']['total_timesteps'] = timesteps.pop() - sweep.observe(args, s, c, is_failure=True) - - for score, cost, timestep in zip(scores, costs, timesteps): - args['train']['total_timesteps'] = timestep - sweep.observe(args, score, cost) + raise ValueError(f'Invalid sweep method {method}. See pufferlib.sweep') - # Prevent logging final eval steps as training steps - args['train']['total_timesteps'] = total_timesteps - -def profile(args=None, env_name=None, vecenv=None, policy=None): - args = load_config() - vecenv = vecenv or load_env(env_name, args) - policy = policy or load_policy(args, vecenv) - - train_config = dict(**args['train'], env=args['env_name'], tag=args['tag']) - pufferl = PuffeRL(train_config, vecenv, policy, neptune=args['neptune'], wandb=args['wandb']) - - import torchvision.models as models - from torch.profiler import profile, record_function, ProfilerActivity - with profile(activities=[ProfilerActivity.CPU, ProfilerActivity.CUDA], record_shapes=True) as prof: - with record_function("model_inference"): - for _ in range(10): - stats = pufferl.evaluate() - pufferl.train() + sweep_obj = sweep_cls(sweep_config) + num_experiments = args['sweep']['max_runs'] + ts_default = args['train']['total_timesteps'] + ts_config = sweep_config.get('train', {}).get('total_timesteps', {'min': ts_default, 'max': ts_default}) + + all_timesteps = np.geomspace(ts_config['min'], ts_config['max'], sweep_gpus) + result_queue = mp.get_context('spawn').Queue() + + active = {} + completed = 0 + while completed < num_experiments: + if len(active) >= sweep_gpus//exp_gpus: # Collect completed runs + gpu_id, scores, costs, timesteps = result_queue.get() + done_args = active.pop(gpu_id) + + if not scores: + sweep_obj.observe(done_args, 0, 0, is_failure=True) + else: + completed += 1 + + for s, c, t in zip(scores, costs, timesteps): + done_args['train']['total_timesteps'] = t + sweep_obj.observe(done_args, s, c, is_failure=False) + + idx = completed + len(active) + if idx >= num_experiments: + break # All experiments launched + + # TODO: only 1 per sweep etc + gpu_id = next(i for i in range(sweep_gpus) if i not in active) + timestep_total = all_timesteps[gpu_id] if pareto else None + if idx > 1: # First experiment uses defaults + sweep_obj.suggest(args, fixed_total_timesteps=timestep_total) + + try: + validate_config(args) + except (AssertionError, ValueError) as e: + print(f'WARNING: {e}, skipping') + sweep_obj.observe(args, 0, 0, is_failure=True) + continue - print(prof.key_averages().table(sort_by='cuda_time_total', row_limit=10)) - prof.export_chrome_trace("trace.json") + exp_args = deepcopy(args) + active[gpu_id] = exp_args + train(env_name, exp_args, range(gpu_id, gpu_id + exp_gpus), + sweep_obj=sweep_obj, result_queue=result_queue) -def export(args=None, env_name=None, vecenv=None, policy=None): +def eval(env_name, args=None, load_path=None): + '''Evaluate a trained policy. Supports both native and --slowly torch backends.''' args = args or load_config(env_name) - args['vec'] = dict(backend='Serial', num_envs=1) - vecenv = vecenv or load_env(env_name, args) - policy = policy or load_policy(args, vecenv) - - weights = [] - for name, param in policy.named_parameters(): - weights.append(param.data.cpu().numpy().flatten()) - print(name, param.shape, param.data.cpu().numpy().ravel()[0]) - - path = f'{args["env_name"]}_weights.bin' - weights = np.concatenate(weights) - weights.tofile(path) - print(f'Saved {len(weights)} weights to {path}') - -def autotune(args=None, env_name=None, vecenv=None, policy=None): - package = args['package'] - module_name = 'pufferlib.ocean' if package == 'ocean' else f'pufferlib.environments.{package}' - env_module = importlib.import_module(module_name) - env_name = args['env_name'] - make_env = env_module.env_creator(env_name) - pufferlib.vector.autotune(make_env, batch_size=args['train']['env_batch_size']) - -def load_env(env_name, args): - package = args['package'] - module_name = 'pufferlib.ocean' if package == 'ocean' else f'pufferlib.environments.{package}' - env_module = importlib.import_module(module_name) - make_env = env_module.env_creator(env_name) - return pufferlib.vector.make(make_env, env_kwargs=args['env'], **args['vec']) - -def load_policy(args, vecenv, env_name=''): - package = args['package'] - module_name = 'pufferlib.ocean' if package == 'ocean' else f'pufferlib.environments.{package}' - env_module = importlib.import_module(module_name) - - device = args['train']['device'] - policy_cls = getattr(env_module.torch, args['policy_name']) - policy = policy_cls(vecenv.driver_env, **args['policy']) - - rnn_name = args['rnn_name'] - if rnn_name is not None: - rnn_cls = getattr(env_module.torch, args['rnn_name']) - policy = rnn_cls(vecenv.driver_env, policy, **args['rnn']) - - policy = policy.to(device) - - load_id = args['load_id'] - if load_id is not None: - if args['neptune']: - path = NeptuneLogger(args, load_id, mode='read-only').download() - elif args['wandb']: - path = WandbLogger(args, load_id).download() - else: - raise pufferlib.APIUsageError('No run id provided for eval') + args['reset_state'] = False + args['train']['horizon'] = 1 - state_dict = torch.load(path, map_location=device) - state_dict = {k.replace('module.', ''): v for k, v in state_dict.items()} - policy.load_state_dict(state_dict) + backend = _resolve_backend(args) + pufferl = backend.create_pufferl(args) - load_path = args['load_model_path'] + # Resolve load path + load_path = load_path or args.get('load_model_path') if load_path == 'latest': - load_path = max(glob.glob(f"experiments/{env_name}*.pt"), key=os.path.getctime) + checkpoint_dir = args['checkpoint_dir'] + pattern = os.path.join(checkpoint_dir, args['env_name'], '**', '*.bin') + candidates = glob.glob(pattern, recursive=True) + if not candidates: + raise FileNotFoundError(f'No .bin checkpoints found in {checkpoint_dir}/{args["env_name"]}/') + load_path = max(candidates, key=os.path.getctime) if load_path is not None: - state_dict = torch.load(load_path, map_location=device) - state_dict = {k.replace('module.', ''): v for k, v in state_dict.items()} - policy.load_state_dict(state_dict) - #state_path = os.path.join(*load_path.split('/')[:-1], 'state.pt') - #optim_state = torch.load(state_path)['optimizer_state_dict'] - #pufferl.optimizer.load_state_dict(optim_state) - - return policy - -def load_config(env_name, parser=None): - puffer_dir = os.path.dirname(os.path.realpath(__file__)) - puffer_config_dir = os.path.join(puffer_dir, 'config/**/*.ini') - puffer_default_config = os.path.join(puffer_dir, 'config/default.ini') - if env_name == 'default': - p = configparser.ConfigParser() - p.read(puffer_default_config) - else: - for path in glob.glob(puffer_config_dir, recursive=True): - p = configparser.ConfigParser() - p.read([puffer_default_config, path]) - if env_name in p['base']['env_name'].split(): break - else: - raise pufferlib.APIUsageError('No config for env_name {}'.format(env_name)) + backend.load_weights(pufferl, load_path) + print(f'Loaded weights from {load_path}') - return process_config(p, parser=parser) - -def load_config_file(file_path, fill_in_default=True, parser=None): - if not os.path.exists(file_path): - raise pufferlib.APIUsageError('No config file found') - - config_paths = [file_path] - - if fill_in_default: - puffer_dir = os.path.dirname(os.path.realpath(__file__)) - # Process the puffer defaults first - config_paths.insert(0, os.path.join(puffer_dir, 'config/default.ini')) - - p = configparser.ConfigParser() - p.read(config_paths) + while True: + backend.render(pufferl, 0) + backend.rollouts(pufferl) - return process_config(p, parser=parser) + backend.close(pufferl) -def make_parser(): - '''Creates the argument parser with default PufferLib arguments.''' +def load_config(env_name): parser = argparse.ArgumentParser(formatter_class=RichHelpFormatter, add_help=False) parser.add_argument('--load-model-path', type=str, default=None, help='Path to a pretrained checkpoint') parser.add_argument('--load-id', type=str, - default=None, help='Kickstart/eval from from a finished Wandb/Neptune run') + default=None, help='Kickstart/eval from from a finished Wandbrun') parser.add_argument('--render-mode', type=str, default='auto', choices=['auto', 'human', 'ansi', 'rgb_array', 'raylib', 'None']) - parser.add_argument('--save-frames', type=int, default=0) - parser.add_argument('--gif-path', type=str, default='eval.gif') - parser.add_argument('--fps', type=float, default=15) - parser.add_argument('--max-runs', type=int, default=200, help='Max number of sweep runs') parser.add_argument('--wandb', action='store_true', help='Use wandb for logging') - parser.add_argument('--wandb-project', type=str, default='pufferlib') + parser.add_argument('--wandb-project', type=str, default='puffer4') parser.add_argument('--wandb-group', type=str, default='debug') - parser.add_argument('--neptune', action='store_true', help='Use neptune for logging') - parser.add_argument('--neptune-name', type=str, default='pufferai') - parser.add_argument('--neptune-project', type=str, default='ablations') - parser.add_argument('--no-model-upload', action='store_true', help='Do not upload models to wandb or neptune') - parser.add_argument('--local-rank', type=int, default=0, help='Used by torchrun for DDP') parser.add_argument('--tag', type=str, default=None, help='Tag for experiment') - return parser - -def process_config(config, parser=None): - if parser is None: - parser = make_parser() - + parser.add_argument('--slowly', action='store_true', help='Use PyTorch training backend') + parser.add_argument('--save-frames', type=int, default=0) + parser.add_argument('--gif-path', type=str, default='eval.gif') + parser.add_argument('--fps', type=float, default=15) parser.description = f':blowfish: PufferLib [bright_cyan]{pufferlib.__version__}[/]' \ ' demo options. Shows valid args for your env and policy' - def auto_type(value): - """Type inference for numeric args that use 'auto' as a default value""" - if value == 'auto': return value - if value.isnumeric(): return int(value) - return float(value) + repo_dir = os.path.dirname(os.path.dirname(os.path.realpath(__file__))) + puffer_config_dir = os.path.join(repo_dir, 'config/**/*.ini') + puffer_default_config = os.path.join(repo_dir, 'config/default.ini') + #CC: Remove the default. Just raise an error on "puffer train" etc with no env (think we already do) + if env_name == 'default': + p = configparser.ConfigParser() + p.read(puffer_default_config) + else: + for path in glob.glob(puffer_config_dir, recursive=True): + p = configparser.ConfigParser() + p.read([puffer_default_config, path]) + if env_name in p['base']['env_name'].split(): break + else: + raise ValueError('No config for env_name {}'.format(env_name)) - for section in config.sections(): - for key in config[section]: + for section in p.sections(): + for key in p[section]: try: - value = ast.literal_eval(config[section][key]) + value = ast.literal_eval(p[section][key]) except: - value = config[section][key] + value = p[section][key] + #TODO: Can clean up with default sections in 3.13+ fmt = f'--{key}' if section == 'base' else f'--{section}.{key}' + dtype = type(value) parser.add_argument( - fmt.replace('_', '-'), - default=value, - type=auto_type if value == 'auto' else type(value) + fmt.replace('_', '-'), default=value, + type=lambda v, t=dtype: v if v == 'auto' else t(v), ) parser.add_argument('-h', '--help', default=argparse.SUPPRESS, @@ -1310,38 +483,35 @@ def auto_type(value): parsed = vars(parser.parse_args()) args = defaultdict(dict) for key, value in parsed.items(): - next = args + nxt = args for subkey in key.split('.'): - prev = next - next = next.setdefault(subkey, {}) + prev = nxt + nxt = nxt.setdefault(subkey, {}) prev[subkey] = value - args['train']['env'] = args['env_name'] or '' # for trainer dashboard - args['train']['use_rnn'] = args['rnn_name'] is not None - return args + args['env_name'] = env_name + for section in p.sections(): + args.setdefault(section, {}) + return dict(args) def main(): - err = 'Usage: puffer [train, eval, sweep, autotune, profile, export] [env_name] [optional args]. --help for more info' + err = 'Usage: puffer [train, eval, sweep, paretosweep] [env_name] [optional args]. --help for more info' if len(sys.argv) < 3: - raise pufferlib.APIUsageError(err) + raise ValueError(err) mode = sys.argv.pop(1) env_name = sys.argv.pop(1) - if mode == 'train': - train(env_name=env_name) - elif mode == 'eval': - eval(env_name=env_name) - elif mode == 'sweep': - sweep(env_name=env_name) - elif mode == 'autotune': - autotune(env_name=env_name) - elif mode == 'profile': - profile(env_name=env_name) - elif mode == 'export': - export(env_name=env_name) + args = load_config(env_name) + + if 'train' in mode: + train(env_name=env_name, args=args) + elif 'eval' in mode: + eval(env_name=env_name, args=args) + elif 'sweep' in mode: + sweep(env_name=env_name, args=args, pareto='pareto' in mode) else: - raise pufferlib.APIUsageError(err) + raise ValueError(err) if __name__ == '__main__': main() diff --git a/pufferlib/pufferlib.py b/pufferlib/pufferlib.py deleted file mode 100644 index 5bef2b0a5e..0000000000 --- a/pufferlib/pufferlib.py +++ /dev/null @@ -1,458 +0,0 @@ -import os -import sys -import warnings - -from contextlib import redirect_stdout, redirect_stderr, contextmanager -from types import SimpleNamespace -from collections.abc import Mapping -from io import StringIO -from functools import wraps - -import numpy as np -import gymnasium - -import pufferlib.spaces - -ENV_ERROR = ''' -Environment missing required attribute {}. The most common cause is -calling super() before you have assigned the attribute. -''' - - -def set_buffers(env, buf=None): - if buf is None: - obs_space = env.single_observation_space - env.observations = np.zeros((env.num_agents, *obs_space.shape), dtype=obs_space.dtype) - env.rewards = np.zeros(env.num_agents, dtype=np.float32) - env.terminals = np.zeros(env.num_agents, dtype=bool) - env.truncations = np.zeros(env.num_agents, dtype=bool) - env.masks = np.ones(env.num_agents, dtype=bool) - - # TODO: Major kerfuffle on inferring action space dtype. This needs some asserts? - atn_space = pufferlib.spaces.joint_space(env.single_action_space, env.num_agents) - if isinstance(env.single_action_space, pufferlib.spaces.Box): - env.actions = np.zeros(atn_space.shape, dtype=atn_space.dtype) - else: - env.actions = np.zeros(atn_space.shape, dtype=np.int32) - else: - env.observations = buf['observations'] - env.rewards = buf['rewards'] - env.terminals = buf['terminals'] - env.truncations = buf['truncations'] - env.masks = buf['masks'] - env.actions = buf['actions'] - -class PufferEnv: - def __init__(self, buf=None): - if not hasattr(self, 'single_observation_space'): - raise APIUsageError(ENV_ERROR.format('single_observation_space')) - if not hasattr(self, 'single_action_space'): - raise APIUsageError(ENV_ERROR.format('single_action_space')) - if not hasattr(self, 'num_agents'): - raise APIUsageError(ENV_ERROR.format('num_agents')) - if self.num_agents < 1: - raise APIUsageError('num_agents must be >= 1') - - if hasattr(self, 'observation_space'): - raise APIUsageError('PufferEnvs must define single_observation_space, not observation_space') - if hasattr(self, 'action_space'): - raise APIUsageError('PufferEnvs must define single_action_space, not action_space') - if not isinstance(self.single_observation_space, pufferlib.spaces.Box): - raise APIUsageError('Native observation_space must be a Box') - if (not isinstance(self.single_action_space, pufferlib.spaces.Discrete) - and not isinstance(self.single_action_space, pufferlib.spaces.MultiDiscrete) - and not isinstance(self.single_action_space, pufferlib.spaces.Box)): - raise APIUsageError('Native action_space must be a Discrete, MultiDiscrete, or Box') - - set_buffers(self, buf) - - self.action_space = pufferlib.spaces.joint_space(self.single_action_space, self.num_agents) - self.observation_space = pufferlib.spaces.joint_space(self.single_observation_space, self.num_agents) - self.agent_ids = np.arange(self.num_agents) - - @property - def agent_per_batch(self): - return self.num_agents - - @property - def emulated(self): - '''Native envs do not use emulation''' - return False - - @property - def done(self): - '''Native envs handle resets internally''' - return False - - @property - def driver_env(self): - '''For compatibility with Multiprocessing''' - return self - - def reset(self, seed=None): - raise NotImplementedError - - def step(self, actions): - raise NotImplementedError - - def close(self): - raise NotImplementedError - - def async_reset(self, seed=None): - _, self.infos = self.reset(seed) - assert isinstance(self.infos, list), 'PufferEnvs must return info as a list of dicts' - - def send(self, actions): - _, _, _, _, self.infos = self.step(actions) - assert isinstance(self.infos, list), 'PufferEnvs must return info as a list of dicts' - - def recv(self): - return (self.observations, self.rewards, self.terminals, - self.truncations, self.infos, self.agent_ids, self.masks) - -### Postprocessing -class ResizeObservation(gymnasium.Wrapper): - '''Fixed downscaling wrapper. Do NOT use gym.wrappers.ResizeObservation - It uses a laughably slow OpenCV resize. -50% on Atari just from that.''' - def __init__(self, env, downscale=2): - super().__init__(env) - self.downscale = downscale - y_size, x_size = env.observation_space.shape - assert y_size % downscale == 0 and x_size % downscale == 0 - y_size = env.observation_space.shape[0] // downscale - x_size = env.observation_space.shape[1] // downscale - self.observation_space = gymnasium.spaces.Box( - low=0, high=255, shape=(y_size, x_size), dtype=np.uint8) - - def reset(self, seed=None, options=None): - obs, info = self.env.reset(seed=seed, options=options) - return obs[::self.downscale, ::self.downscale], info - - def step(self, action): - obs, reward, terminal, truncated, info = self.env.step(action) - return obs[::self.downscale, ::self.downscale], reward, terminal, truncated, info - -class ClipAction(gymnasium.Wrapper): - '''Wrapper for Gymnasium environments that clips actions''' - def __init__(self, env): - self.env = env - assert isinstance(env.action_space, gymnasium.spaces.Box) - self._observation_space = env.observation_space - self._action_space = env.action_space - dtype_info = np.finfo(env.action_space.dtype) - self.action_space = gymnasium.spaces.Box( - low=dtype_info.min, - high=dtype_info.max, - shape=env.action_space.shape, - dtype=env.action_space.dtype, - ) - - def step(self, action): - action = np.clip(action, self.env.action_space.low, self.env.action_space.high) - return self.env.step(action) - - -class EpisodeStats(gymnasium.Wrapper): - '''Wrapper for Gymnasium environments that stores - episodic returns and lengths in infos''' - def __init__(self, env): - self.env = env - self.observation_space = env.observation_space - self.action_space = env.action_space - self.reset() - - def reset(self, seed=None, options=None): - self.info = dict(episode_return=[], episode_length=0) - # TODO: options - return self.env.reset(seed=seed)#, options=options) - - def step(self, action): - observation, reward, terminated, truncated, info = super().step(action) - - for k, v in unroll_nested_dict(info): - if k not in self.info: - self.info[k] = [] - - self.info[k].append(v) - - self.info['episode_return'].append(reward) - self.info['episode_length'] += 1 - - info = {} - if terminated or truncated: - for k, v in self.info.items(): - try: - info[k] = sum(v) - continue - except TypeError: - pass - - if isinstance(v, str): - info[k] = v - continue - - try: - x = int(v) # probably a value - info[k] = v - continue - except TypeError: - pass - - return observation, reward, terminated, truncated, info - -class PettingZooWrapper: - '''PettingZoo does not provide a ParallelEnv wrapper. This code is adapted from - their AEC wrapper, to prevent unneeded conversions to/from AEC''' - def __init__(self, env): - self.env = env - - def __getattr__(self, name): - '''Returns an attribute with ``name``, unless ``name`` starts with an underscore.''' - if name.startswith('_') and name != '_cumulative_rewards': - raise AttributeError(f'accessing private attribute "{name}" is prohibited') - return getattr(self.env, name) - - @property - def unwrapped(self): - return self.env.unwrapped - - def close(self): - self.env.close() - - def render(self): - return self.env.render() - - def reset(self, seed=None, options=None): - try: - return self.env.reset(seed=seed, options=options) - except TypeError: - return self.env.reset(seed=seed) - - def observe(self, agent): - return self.env.observe(agent) - - def state(self): - return self.env.state() - - def step(self, action): - return self.env.step(action) - - def observation_space(self, agent): - return self.env.observation_space(agent) - - def action_space(self, agent): - return self.env.action_space(agent) - - def __str__(self) -> str: - '''Returns a name which looks like: "max_observation".''' - return f'{type(self).__name__}<{str(self.env)}>' - -class MeanOverAgents(PettingZooWrapper): - '''Averages over agent infos''' - def _mean(self, infos): - list_infos = {} - for agent, info in infos.items(): - for k, v in info.items(): - if k not in list_infos: - list_infos[k] = [] - - list_infos[k].append(v) - - mean_infos = {} - for k, v in list_infos.items(): - try: - mean_infos[k] = np.mean(v) - except: - pass - - return mean_infos - - def reset(self, seed=None, options=None): - observations, infos = super().reset(seed, options) - infos = self._mean(infos) - return observations, infos - - def step(self, actions): - observations, rewards, terminations, truncations, infos = super().step(actions) - infos = self._mean(infos) - return observations, rewards, terminations, truncations, infos - -class MultiagentEpisodeStats(PettingZooWrapper): - '''Wrapper for PettingZoo environments that stores - episodic returns and lengths in infos''' - def reset(self, seed=None, options=None): - observations, infos = super().reset(seed=seed, options=options) - self.infos = { - agent: dict(episode_return=[], episode_length=0) - for agent in self.possible_agents - } - return observations, infos - - def step(self, actions): - observations, rewards, terminations, truncations, infos = super().step(actions) - - all_infos = {} - for agent in infos: - agent_info = self.infos[agent] - for k, v in unroll_nested_dict(infos[agent]): - if k not in agent_info: - agent_info[k] = [] - - agent_info[k].append(v) - - # Saved to self. TODO: Clean up - agent_info['episode_return'].append(rewards[agent]) - agent_info['episode_length'] += 1 - - agent_info = {} - all_infos[agent] = agent_info - if terminations[agent] or truncations[agent]: - for k, v in self.infos[agent].items(): - try: - agent_info[k] = sum(v) - continue - except TypeError: - pass - - if isinstance(v, str): - agent_info[k] = v - continue - - try: - x = int(v) # probably a value - agent_info[k] = v - continue - except TypeError: - pass - - return observations, rewards, terminations, truncations, all_infos -### Exceptions -class EnvironmentSetupError(RuntimeError): - def __init__(self, e, package): - super().__init__(self.message) - -class APIUsageError(RuntimeError): - """Exception raised when the API is used incorrectly.""" - - def __init__(self, message="API usage error."): - self.message = message - super().__init__(self.message) - -class InvalidAgentError(ValueError): - """Exception raised when an invalid agent key is used.""" - - def __init__(self, agent_id, agents): - message = ( - f'Invalid agent/team ({agent_id}) specified. ' - f'Valid values:\n{agents}' - ) - super().__init__(message) - -class GymToGymnasium: - def __init__(self, env): - self.env = env - self.observation_space = env.observation_space - self.action_space = env.action_space - self.render = env.render - self.metadata = env.metadata - - def reset(self, seed=None, options=None): - if seed is not None: - ob = self.env.reset(seed=seed) - else: - ob = self.env.reset() - return ob, {} - - def step(self, action): - observation, reward, done, info = self.env.step(action) - return observation, reward, done, False, info - - def close(self): - self.env.close() - -### Wrappers -class PettingZooTruncatedWrapper: - def __init__(self, env): - self.env = env - self.observation_space = env.observation_space - self.action_space = env.action_space - self.render = env.render - - @property - def render_mode(self): - return self.env.render_mode - - @property - def possible_agents(self): - return self.env.possible_agents - - @property - def agents(self): - return self.env.agents - - def reset(self, seed=None): - if seed is not None: - ob, info = self.env.reset(seed=seed) - else: - ob, info = self.env.reset() - info = {k: {} for k in ob} - return ob, info - - def step(self, actions): - observations, rewards, terminals, truncations, infos = self.env.step(actions) - return observations, rewards, terminals, truncations, infos - - def close(self): - self.env.close() - -### Misc -def unroll_nested_dict(d): - if not isinstance(d, dict): - return d - - for k, v in d.items(): - if isinstance(v, dict): - for k2, v2 in unroll_nested_dict(v): - yield f"{k}/{k2}", v2 - else: - yield k, v - -def silence_warnings(original_func, category=DeprecationWarning): - @wraps(original_func) - def wrapper(*args, **kwargs): - with warnings.catch_warnings(): - warnings.simplefilter("ignore", category=category) - return original_func(*args, **kwargs) - return wrapper - -class Suppress(): - def __init__(self): - self.f = StringIO() - self.null_1 = os.open(os.devnull, os.O_WRONLY | os.O_TRUNC | os.O_CREAT) - self.null_2 = os.open(os.devnull, os.O_WRONLY | os.O_TRUNC | os.O_CREAT) - - def __enter__(self): - # Suppress C library outputs - self.orig_stdout = os.dup(1) - self.orig_stderr = os.dup(2) - os.dup2(self.null_1, 1) - os.dup2(self.null_2, 2) - - # Suppress Python outputs - self._stdout_redirector = redirect_stdout(self.f) - self._stderr_redirector = redirect_stderr(self.f) - self._stdout_redirector.__enter__() - self._stderr_redirector.__enter__() - - def __exit__(self, exc_type, exc_val, exc_tb): - # Enable C library outputs - os.dup2(self.orig_stdout, 1) - os.dup2(self.orig_stderr, 2) - os.close(self.orig_stdout) - os.close(self.orig_stderr) - os.close(self.null_1) - os.close(self.null_2) - - # Enable Python outputs - self._stdout_redirector.__exit__(exc_type, exc_val, exc_tb) - self._stderr_redirector.__exit__(exc_type, exc_val, exc_tb) diff --git a/pufferlib/pytorch.py b/pufferlib/pytorch.py deleted file mode 100644 index e18bea40c5..0000000000 --- a/pufferlib/pytorch.py +++ /dev/null @@ -1,231 +0,0 @@ -import sys -from pdb import set_trace as T -from typing import Dict, List, Tuple, Union - -import numpy as np -import torch -from torch import nn -from torch.distributions import Categorical -from torch.distributions.utils import logits_to_probs - -import pufferlib -import pufferlib.models - - -numpy_to_torch_dtype_dict = { - np.dtype("float64"): torch.float64, - np.dtype("float32"): torch.float32, - np.dtype("float16"): torch.float16, - np.dtype("uint64"): torch.uint64, - np.dtype("uint32"): torch.uint32, - np.dtype("uint16"): torch.uint16, - np.dtype("uint8"): torch.uint8, - np.dtype("int64"): torch.int64, - np.dtype("int32"): torch.int32, - np.dtype("int16"): torch.int16, - np.dtype("int8"): torch.int8, -} - - -LITTLE_BYTE_ORDER = sys.byteorder == "little" - -# USER NOTE: You should not get any errors in nativize. -# This is a complicated piece of code that attempts to convert -# flat bytes to structured tensors without breaking torch.compile. -# If you hit any errors, please post on discord.gg/puffer -# One exception: make sure you didn't change the dtype of your data -# ie by doing torch.Tensor(data) instead of torch.from_numpy(data) - -# dtype of the tensor -# shape of the tensor -# starting element of the observation -# number of elements of the observation to take -# could be a namedtuple or dataclass -NativeDTypeValue = Tuple[torch.dtype, List[int], int, int] -NativeDType = Union[NativeDTypeValue, Dict[str, Union[NativeDTypeValue, "NativeDType"]]] - -# TODO: handle discrete obs -# Spend some time trying to break this fn with differnt obs -def nativize_dtype(emulated) -> NativeDType: - # sample dtype - the dtype of what we obtain from the environment (usually bytes) - sample_dtype: np.dtype = emulated['observation_dtype'] - # structured dtype - the gym.Space converted numpy dtype - - # the observation represents (could be dict, tuple, box, etc.) - structured_dtype: np.dtype = emulated['emulated_observation_dtype'] - subviews, dtype, shape, offset, delta = _nativize_dtype(sample_dtype, structured_dtype) - if subviews is None: - return (dtype, shape, offset, delta) - else: - return subviews - -def round_to(x, base): - return int(base * np.ceil(x/base)) - -def _nativize_dtype(sample_dtype: np.dtype, - structured_dtype: np.dtype, - offset: int = 0) -> NativeDType: - if structured_dtype.fields is None: - if structured_dtype.subdtype is not None: - dtype, shape = structured_dtype.subdtype - else: - dtype = structured_dtype - shape = (1,) - - delta = int(np.prod(shape)) - if sample_dtype.base.itemsize == 1: - offset = round_to(offset, dtype.alignment) - delta *= dtype.itemsize - else: - assert dtype.itemsize == sample_dtype.base.itemsize - - return None, numpy_to_torch_dtype_dict[dtype], shape, offset, delta - else: - subviews = {} - start_offset = offset - all_delta = 0 - for name, (dtype, _) in structured_dtype.fields.items(): - views, dtype, shape, offset, delta = _nativize_dtype( - sample_dtype, dtype, offset) - - if views is not None: - subviews[name] = views - else: - subviews[name] = (dtype, shape, offset, delta) - - offset += delta - all_delta += delta - - return subviews, dtype, shape, start_offset, all_delta - - -def nativize_tensor(observation: torch.Tensor, native_dtype: NativeDType): - return _nativize_tensor(observation, native_dtype) - - -# torch.view(dtype) does not compile -# This is a workaround hack -# @thatguy - can you figure out a more robust way to handle cast? -# I think it may screw up for non-uint data... so I put a hard .view -# fallback that breaks compile -def compilable_cast(u8, dtype): - if dtype in (torch.uint8, torch.uint16, torch.uint32, torch.uint64): - n = dtype.itemsize - bytes = [u8[..., i::n].to(dtype) for i in range(n)] - if not LITTLE_BYTE_ORDER: - bytes = bytes[::-1] - - bytes = sum(bytes[i] << (i * 8) for i in range(n)) - return bytes.view(dtype) - return u8.view(dtype) # breaking cast - - -def _nativize_tensor(observation: torch.Tensor, native_dtype: NativeDType): - if isinstance(native_dtype, tuple): - dtype, shape, offset, delta = native_dtype - torch._check_is_size(offset) - torch._check_is_size(delta) - # Important, we are assuming that obervations of shape - # [N, D] where N is number of examples and D is number of - # bytes per example is being passed in - slice = observation.narrow(1, offset, delta) - # slice = slice.contiguous() - # slice = compilable_cast(slice, dtype) - slice = slice.view(dtype) - slice = slice.view(observation.shape[0], *shape) - return slice - else: - subviews = {} - for name, dtype in native_dtype.items(): - subviews[name] = _nativize_tensor(observation, dtype) - return subviews - - -def nativize_observation(observation, emulated): - # TODO: Any way to check that user has not accidentally cast data to float? - # float is natively supported, but only if that is the actual correct type - return nativize_tensor( - observation, - emulated['observation_dtype'], - emulated['emulated_observation_dtype'], - ) - -def flattened_tensor_size(native_dtype): - return _flattened_tensor_size(native_dtype) - -def _flattened_tensor_size(native_dtype): - if isinstance(native_dtype, tuple): - return np.prod(native_dtype[1]) # shape - else: - res = 0 - for _, dtype in native_dtype.items(): - res += _flattened_tensor_size(dtype) - return res - -def layer_init(layer, std=np.sqrt(2), bias_const=0.0): - """CleanRL's default layer initialization""" - torch.nn.init.orthogonal_(layer.weight, std) - torch.nn.init.constant_(layer.bias, bias_const) - return layer - -# taken from torch.distributions.Categorical -def log_prob(logits, value): - value = value.long().unsqueeze(-1) - value, log_pmf = torch.broadcast_tensors(value, logits) - value = value[..., :1] - return log_pmf.gather(-1, value).squeeze(-1) - -# taken from torch.distributions.Categorical -def entropy(logits): - min_real = torch.finfo(logits.dtype).min - logits = torch.clamp(logits, min=min_real) - p_log_p = logits * logits_to_probs(logits) - return -p_log_p.sum(-1) - -def entropy_probs(logits, probs): - p_log_p = logits * probs - return -p_log_p.sum(-1) - -def sample_logits(logits, action=None): - is_discrete = isinstance(logits, torch.Tensor) - if isinstance(logits, torch.distributions.Normal): - batch = logits.loc.shape[0] - if action is None: - mean = torch.nan_to_num(logits.loc, 0.0, 0.0, 0.0) - std = torch.nan_to_num(logits.scale, 1.0, 1.0, 1.0) - logits = torch.distributions.Normal(mean, std) - action = logits.sample().view(batch, -1) - - log_probs = logits.log_prob(action.view(batch, -1)).sum(1) - logits_entropy = logits.entropy().view(batch, -1).sum(1) - return action, log_probs, logits_entropy - elif is_discrete: - logits = logits.unsqueeze(0) - # TODO: Double check this - else: #multi-discrete - logits = torch.nn.utils.rnn.pad_sequence( - [l.transpose(0,1) for l in logits], - batch_first=False, - padding_value=-torch.inf - ).permute(1,2,0) - - # This can fail on nans etc - normalized_logits = logits - logits.logsumexp(dim=-1, keepdim=True) - probs = logits_to_probs(logits) - - if action is None: - probs = torch.nan_to_num(probs, 1e-8, 1e-8, 1e-8) - action = torch.multinomial(probs.reshape(-1, probs.shape[-1]), 1, replacement=True).int() - action = action.reshape(probs.shape[:-1]) - else: - batch = logits[0].shape[0] - action = action.view(batch, -1).T - - assert len(logits) == len(action) - logprob = log_prob(normalized_logits, action) - logits_entropy = entropy(normalized_logits).sum(0) - - if is_discrete: - return action.squeeze(0), logprob.squeeze(0), logits_entropy.squeeze(0) - - return action.T, logprob.sum(0), logits_entropy diff --git a/pufferlib/resources/breakout/breakout_weights.bin b/pufferlib/resources/breakout/breakout_weights.bin deleted file mode 100644 index 82c61a9b41..0000000000 Binary files a/pufferlib/resources/breakout/breakout_weights.bin and /dev/null differ diff --git a/pufferlib/resources/cartpole/cartpole_weights.bin b/pufferlib/resources/cartpole/cartpole_weights.bin deleted file mode 100644 index 35c0a75794..0000000000 Binary files a/pufferlib/resources/cartpole/cartpole_weights.bin and /dev/null differ diff --git a/pufferlib/resources/connect4/connect4_weights.bin b/pufferlib/resources/connect4/connect4_weights.bin deleted file mode 100644 index 11dbaf78f1..0000000000 Binary files a/pufferlib/resources/connect4/connect4_weights.bin and /dev/null differ diff --git a/pufferlib/resources/drive/puffer_drive_weights.bin b/pufferlib/resources/drive/puffer_drive_weights.bin deleted file mode 100644 index 29737db60a..0000000000 Binary files a/pufferlib/resources/drive/puffer_drive_weights.bin and /dev/null differ diff --git a/pufferlib/resources/drone/drone_weights.bin b/pufferlib/resources/drone/drone_weights.bin deleted file mode 100644 index 4961312afe..0000000000 Binary files a/pufferlib/resources/drone/drone_weights.bin and /dev/null differ diff --git a/pufferlib/resources/enduro/enduro_weights.bin b/pufferlib/resources/enduro/enduro_weights.bin deleted file mode 100644 index cff7b9904c..0000000000 Binary files a/pufferlib/resources/enduro/enduro_weights.bin and /dev/null differ diff --git a/pufferlib/resources/freeway/freeway_weights.bin b/pufferlib/resources/freeway/freeway_weights.bin deleted file mode 100644 index 97b4c53095..0000000000 Binary files a/pufferlib/resources/freeway/freeway_weights.bin and /dev/null differ diff --git a/pufferlib/resources/go/go_weights.bin b/pufferlib/resources/go/go_weights.bin deleted file mode 100644 index 8677889da3..0000000000 Binary files a/pufferlib/resources/go/go_weights.bin and /dev/null differ diff --git a/pufferlib/resources/moba/game_map.npy b/pufferlib/resources/moba/game_map.npy deleted file mode 100644 index 3fb1b41a35..0000000000 Binary files a/pufferlib/resources/moba/game_map.npy and /dev/null differ diff --git a/pufferlib/resources/moba/moba_weights.bin b/pufferlib/resources/moba/moba_weights.bin deleted file mode 100644 index cbd29a7af2..0000000000 Binary files a/pufferlib/resources/moba/moba_weights.bin and /dev/null differ diff --git a/pufferlib/resources/pacman/pacman_weights.bin b/pufferlib/resources/pacman/pacman_weights.bin deleted file mode 100644 index 55e1fa11c3..0000000000 Binary files a/pufferlib/resources/pacman/pacman_weights.bin and /dev/null differ diff --git a/pufferlib/resources/pong/pong_weights.bin b/pufferlib/resources/pong/pong_weights.bin deleted file mode 100644 index 7d9f0d6f15..0000000000 Binary files a/pufferlib/resources/pong/pong_weights.bin and /dev/null differ diff --git a/pufferlib/resources/target/star.png b/pufferlib/resources/target/star.png deleted file mode 100644 index 2738c18643..0000000000 Binary files a/pufferlib/resources/target/star.png and /dev/null differ diff --git a/pufferlib/resources/target/target_weights.bin b/pufferlib/resources/target/target_weights.bin deleted file mode 100644 index fea80dbb01..0000000000 Binary files a/pufferlib/resources/target/target_weights.bin and /dev/null differ diff --git a/pufferlib/resources/terraform/puffer_terraform_weights.bin b/pufferlib/resources/terraform/puffer_terraform_weights.bin deleted file mode 100644 index 2809577aab..0000000000 Binary files a/pufferlib/resources/terraform/puffer_terraform_weights.bin and /dev/null differ diff --git a/pufferlib/resources/tetris/tetris_weights.bin b/pufferlib/resources/tetris/tetris_weights.bin deleted file mode 100644 index 09d0a74ebe..0000000000 Binary files a/pufferlib/resources/tetris/tetris_weights.bin and /dev/null differ diff --git a/pufferlib/resources/tower_climb/tower_climb_weights.bin b/pufferlib/resources/tower_climb/tower_climb_weights.bin deleted file mode 100644 index e5136c78a3..0000000000 Binary files a/pufferlib/resources/tower_climb/tower_climb_weights.bin and /dev/null differ diff --git a/pufferlib/resources/trash_pickup/trash_pickup_weights.bin b/pufferlib/resources/trash_pickup/trash_pickup_weights.bin deleted file mode 100644 index b72a0a99bb..0000000000 Binary files a/pufferlib/resources/trash_pickup/trash_pickup_weights.bin and /dev/null differ diff --git a/pufferlib/resources/tripletriad/tripletriad_weights.bin b/pufferlib/resources/tripletriad/tripletriad_weights.bin deleted file mode 100644 index af04c23803..0000000000 Binary files a/pufferlib/resources/tripletriad/tripletriad_weights.bin and /dev/null differ diff --git a/pufferlib/spaces.py b/pufferlib/spaces.py deleted file mode 100644 index bf9582df41..0000000000 --- a/pufferlib/spaces.py +++ /dev/null @@ -1,25 +0,0 @@ -import numpy as np -import gym -import gymnasium - -Box = (gym.spaces.Box, gymnasium.spaces.Box) -Dict = (gym.spaces.Dict, gymnasium.spaces.Dict) -Discrete = (gym.spaces.Discrete, gymnasium.spaces.Discrete) -MultiBinary = (gym.spaces.MultiBinary, gymnasium.spaces.MultiBinary) -MultiDiscrete = (gym.spaces.MultiDiscrete, gymnasium.spaces.MultiDiscrete) -Tuple = (gym.spaces.Tuple, gymnasium.spaces.Tuple) - -def joint_space(space, n): - if isinstance(space, Discrete): - return gymnasium.spaces.MultiDiscrete([space.n] * n) - elif isinstance(space, MultiDiscrete): - return gymnasium.spaces.Box(low=0, - high=np.repeat(space.nvec[None] - 1, n, axis=0), - shape=(n, len(space)), dtype=space.dtype) - elif isinstance(space, Box): - low = np.repeat(space.low[None], n, axis=0) - high = np.repeat(space.high[None], n, axis=0) - return gymnasium.spaces.Box(low=low, high=high, - shape=(n, *space.shape), dtype=space.dtype) - else: - raise ValueError(f'Unsupported space: {space}') diff --git a/pufferlib/sweep.py b/pufferlib/sweep.py index 73c510a620..1212d8e1ec 100644 --- a/pufferlib/sweep.py +++ b/pufferlib/sweep.py @@ -1,6 +1,7 @@ import random import math import warnings +from collections import deque from copy import deepcopy from contextlib import contextmanager @@ -22,6 +23,17 @@ EPSILON = 1e-6 +def unroll_nested_dict(d): + if not isinstance(d, dict): + return d + + for k, v in d.items(): + if isinstance(v, dict): + for k2, v2 in unroll_nested_dict(v): + yield f"{k}/{k2}", v2 + else: + yield k, v + @contextmanager def default_tensor_dtype(dtype): old_dtype = torch.get_default_dtype() @@ -117,9 +129,7 @@ def __init__(self, min, max, scale, is_integer=False): super().__init__(min, max, scale, is_integer) def normalize(self, value): - #assert isinstance(value, (int, float)) - #assert value != 0.0 - #assert value != 1.0 + value = max(self.min, min(value, self.max)) zero_one = (math.log(1-value, self.base) - math.log(1-self.min, self.base))/(math.log(1-self.max, self.base) - math.log(1-self.min, self.base)) return 2*zero_one - 1 @@ -136,10 +146,10 @@ def _params_from_puffer_sweep(sweep_config, only_include=None): for name, param in sweep_config.items(): if name in ('method', 'metric', 'metric_distribution', 'goal', 'downsample', 'use_gpu', 'prune_pareto', - 'sweep_only', 'max_suggestion_cost', 'early_stop_quantile'): + 'sweep_only', 'max_suggestion_cost', 'early_stop_quantile', 'gpus', 'max_runs'): continue - assert isinstance(param, dict) + assert isinstance(param, dict), f'Param {name} is not a dict' if any(isinstance(param[k], dict) for k in param): param_spaces[name] = _params_from_puffer_sweep(param, only_include) continue @@ -174,7 +184,7 @@ def _params_from_puffer_sweep(sweep_config, only_include=None): class Hyperparameters: def __init__(self, config, verbose=True): self.spaces = _params_from_puffer_sweep(config) - self.flat_spaces = dict(pufferlib.unroll_nested_dict(self.spaces)) + self.flat_spaces = dict(unroll_nested_dict(self.spaces)) self.num = len(self.flat_spaces) self.metric = config['metric'] @@ -214,7 +224,7 @@ def sample(self, n, mu=None, scale=1): return np.clip(samples, self.min_bounds, self.max_bounds) def from_dict(self, params): - flat_params = dict(pufferlib.unroll_nested_dict(params)) + flat_params = dict(unroll_nested_dict(params)) values = [] for key, space in self.flat_spaces.items(): assert key in flat_params, f'Missing hyperparameter {key}' @@ -308,7 +318,7 @@ def __init__(self, self.random_suggestions = random_suggestions self.success_observations = [] - def suggest(self, fill=None): + def suggest(self, fill=None, fixed_total_timesteps=None): suggestions = self.hyperparameters.sample(self.random_suggestions) self.suggestion = random.choice(suggestions) return self.hyperparameters.to_dict(self.suggestion, fill), {} @@ -322,6 +332,12 @@ def observe(self, hypers, score, cost, is_failure=False): is_failure=is_failure, )) + def early_stop(self, logs, target_key): + if any("loss/" in k and np.isnan(v) for k, v in logs.items()): + logs['is_loss_nan'] = True + return True + return False + class ParetoGenetic: def __init__(self, @@ -339,7 +355,7 @@ def __init__(self, self.log_bias = log_bias self.success_observations = [] - def suggest(self, fill=None): + def suggest(self, fill=None, fixed_total_timesteps=None): if len(self.success_observations) == 0: suggestion = self.hyperparameters.search_centers return self.hyperparameters.to_dict(suggestion, fill), {} @@ -373,6 +389,12 @@ def observe(self, hypers, score, cost, is_failure=False): is_failure=is_failure, )) + def early_stop(self, logs, target_key): + if any("loss/" in k and np.isnan(v) for k, v in logs.items()): + logs['is_loss_nan'] = True + return True + return False + class ExactGPModel(ExactGP): def __init__(self, train_x, train_y, likelihood, x_dim): @@ -551,10 +573,13 @@ def __init__(self, # self.num_random_samples = 3 * points_per_run * self.hyperparameters.num self.cost_param_idx = self.hyperparameters.get_flat_idx(cost_param) + self.cost_space = None self.cost_random_suggestion = None if self.cost_param_idx is not None: + self.cost_space = list(self.hyperparameters.flat_spaces.values())[self.cost_param_idx] self.cost_random_suggestion = -0.8 # In norm cost space. Make arg if necessary self.target_cost_ratio = [] + self._running_target_buffer = deque(maxlen=30) self.gp_max_obs = gp_max_obs # train time bumps after 800? self.infer_batch_size = infer_batch_size @@ -711,10 +736,13 @@ def _sample_target_cost_ratio(self, expansion_rate, target_ratios=(0.16, 0.32, 0 target_ratio = np.clip(self.target_cost_ratio.pop() + 0.1 * np.random.randn(), 0, 1) return (1 + expansion_rate) * target_ratio - def suggest(self, fill): + def suggest(self, fill, fixed_total_timesteps=None): info = {} self.suggestion_idx += 1 - + fixed_cost_norm = None + if fixed_total_timesteps is not None and self.cost_space is not None: + fixed_cost_norm = self.cost_space.normalize(fixed_total_timesteps) + # NOTE: Changed pufferl to use the train args, NOT the sweep hyperparam search center # if len(self.success_observations) == 0 and self.seed_with_search_center: # suggestion = self.hyperparameters.search_centers @@ -724,7 +752,9 @@ def suggest(self, fill): # Suggest the next point in the Sobol sequence zero_one = self.sobol.random(1)[0] suggestion = 2*zero_one - 1 # Scale from [0, 1) to [-1, 1) - if self.cost_param_idx is not None: + if fixed_cost_norm is not None: + suggestion[self.cost_param_idx] = fixed_cost_norm + elif self.cost_param_idx is not None: cost_suggestion = self.cost_random_suggestion + 0.1 * np.random.randn() suggestion[self.cost_param_idx] = np.clip(cost_suggestion, -1, 1) # limit the cost return self.hyperparameters.to_dict(suggestion, fill), info @@ -764,6 +794,9 @@ def suggest(self, fill): suggestions = self.hyperparameters.sample( len(search_centers)*self.suggestions_per_pareto, mu=search_centers) + if fixed_cost_norm is not None: + suggestions[:, self.cost_param_idx] = fixed_cost_norm + dedup_indices = self._filter_near_duplicates(suggestions) suggestions = suggestions[dedup_indices] @@ -812,11 +845,12 @@ def suggest(self, fill): # Maximize score. (Tried upper confidence bounds, but it did more harm because gp was noisy) suggestion_scores = self.hyperparameters.optimize_direction * gp_y_norm - # Then, decide the budget for this session and favor closer suggestions - max_c_mask = gp_c < self.max_suggestion_cost - target_cost = self._sample_target_cost_ratio(self.expansion_rate) - weight = 1 - abs(target_cost - gp_log_c_norm) - suggestion_scores *= max_c_mask * weight + # When cost is fixed (pareto mode), skip cost-based weighting + if fixed_cost_norm is None: + max_c_mask = gp_c < self.max_suggestion_cost + target_cost = self._sample_target_cost_ratio(self.expansion_rate) + weight = 1 - abs(target_cost - gp_log_c_norm) + suggestion_scores *= max_c_mask * weight # Then, consider the prob of training success, only when downsample = 1 # NOTE: Useful only in limited scenarios, where each data point is expensive. So turn it off by default. @@ -910,3 +944,22 @@ def should_stop(self, score, cost): score = self.logit_transform(score) return score < threshold + + def early_stop(self, logs, target_key): + for k, v in logs['loss'].items(): + if np.isnan(v): + logs['is_loss_nan'] = True + return True + + if 'uptime' not in logs or target_key not in logs: + return False + + metric_val, cost = logs['env'][target_key], logs['uptime'] + self._running_target_buffer.append(metric_val) + target_running_mean = np.mean(self._running_target_buffer) + threshold = self.get_early_stop_threshold(cost) + logs['early_stop_threshold'] = max(threshold, -5) + if self.should_stop(max(target_running_mean, metric_val), cost): + logs['is_loss_nan'] = False + return True + return False diff --git a/pufferlib/torch_pufferl.py b/pufferlib/torch_pufferl.py new file mode 100644 index 0000000000..efe042b100 --- /dev/null +++ b/pufferlib/torch_pufferl.py @@ -0,0 +1,511 @@ +## puffer [train | eval | sweep] [env_name] [optional args] -- See https://puffer.ai for full detail0 +# This is the same as python -m pufferlib.pufferl [train | eval | sweep] [env_name] [optional args] +# Distributed example: torchrun --standalone --nnodes=1 --nproc-per-node=6 -m pufferlib.pufferl train puffer_nmmo3 + +import os +import glob +import time +import ctypes +from collections import defaultdict + +import numpy as np + +import torch +import torch.distributed +from torch.distributions.utils import logits_to_probs + +import pufferlib +import pufferlib.pufferl +from pufferlib.muon import Muon +from pufferlib import _C +if _C.precision_bytes != 4: + raise RuntimeError( + f'_C was compiled with bf16 precision (precision_bytes={_C.precision_bytes}). ' + 'The PyTorch backend requires float32. Rerun build.sh with --float' + ) + +_OBS_DTYPE_MAP = { + 'ByteTensor': torch.uint8, + 'FloatTensor': torch.float32, +} + +_TORCH_TO_TYPESTR = { + torch.uint8: '|u1', + torch.float32: ' 1 else action.unsqueeze(-1)).to(dtype=torch.float32).contiguous() + if self.gpu: + actions_flat = actions_flat.cuda() + self._vec.gpu_step(actions_flat.data_ptr()) + torch.cuda.synchronize() + else: + self._vec.cpu_step(actions_flat.data_ptr()) + + o, r, d = self.vec_obs, self.vec_rewards, self.vec_terminals + prof.mark(3) + prof.elapsed(P.EVAL_GPU, 1, 2) + prof.elapsed(P.EVAL_ENV, 2, 3) + + prof.mark(1) + prof.elapsed(P.ROLLOUT, 0, 1) + self.global_step += self.total_agents * horizon + self.env_logs = self._vec.log() + + def train(self): + prof = self.profile + losses = defaultdict(float) + config = self.config + device = self.device + + b0 = config['prio_beta0'] + a = config['prio_alpha'] + clip_coef = config['clip_coef'] + vf_clip = config['vf_clip_coef'] + anneal_beta = b0 + (1 - b0)*a*self.epoch/self.total_epochs + self.ratio[:] = 1 + + learning_rate = config['learning_rate'] + if config['anneal_lr'] and self.epoch > 0: + lr_ratio = self.epoch / self.total_epochs + lr_min = config['learning_rate'] * config['min_lr_ratio'] + learning_rate = lr_min + 0.5*(learning_rate - lr_min) * (1 + np.cos(np.pi * lr_ratio)) + self.optimizer.param_groups[0]['lr'] = learning_rate + + # Transpose from [horizon, agents] (contiguous writes) to [agents, horizon] (minibatch indexing) + obs = self.observations.transpose(0, 1).contiguous() + act = self.actions.transpose(0, 1).contiguous() + val = self.values.T.contiguous() + lp = self.logprobs.T.contiguous() + rew = self.rewards.T.contiguous().clamp(-1, 1) + ter = self.terminals.T.contiguous() + + P = Profile + prof.mark(0) + num_minibatches = int(config['replay_ratio'] * self.batch_size / config['minibatch_size']) + for mb in range(num_minibatches): + shape = val.shape + advantages = torch.zeros(shape, device=device) + advantages = compute_puff_advantage(val, rew, + ter, self.ratio, advantages, config['gamma'], + config['gae_lambda'], config['vtrace_rho_clip'], config['vtrace_c_clip']) + + adv = advantages.abs().sum(axis=1) + prio_weights = torch.nan_to_num(adv**a, 0, 0, 0) + prio_probs = (prio_weights + 1e-6)/(prio_weights.sum() + 1e-6) + idx = torch.multinomial(prio_probs, + self.minibatch_segments, replacement=True) + mb_prio = (self.total_agents*prio_probs[idx, None])**-anneal_beta + + mb_obs = obs[idx] + mb_actions = act[idx] + mb_logprobs = lp[idx] + mb_values = val[idx] + mb_returns = advantages[idx] + mb_values + mb_advantages = advantages[idx] + + prof.mark(1) + logits, newvalue = self.policy(mb_obs) + actions, newlogprob, entropy = sample_logits(logits, action=mb_actions) + prof.mark(2) + prof.elapsed(P.TRAIN_FORWARD, 1, 2) + + newlogprob = newlogprob.reshape(mb_logprobs.shape) + logratio = newlogprob - mb_logprobs + ratio = logratio.exp() + self.ratio[idx] = ratio.detach() + + with torch.no_grad(): + old_approx_kl = (-logratio).mean() + approx_kl = ((ratio - 1) - logratio).mean() + clipfrac = ((ratio - 1.0).abs() > config['clip_coef']).float().mean() + + adv = mb_advantages + adv = mb_prio * (adv - adv.mean()) / (adv.std() + 1e-8) + + pg_loss1 = -adv * ratio + pg_loss2 = -adv * torch.clamp(ratio, 1 - clip_coef, 1 + clip_coef) + pg_loss = torch.max(pg_loss1, pg_loss2).mean() + + newvalue = newvalue.view(mb_returns.shape) + v_clipped = mb_values + torch.clamp(newvalue - mb_values, -vf_clip, vf_clip) + v_loss_unclipped = (newvalue - mb_returns) ** 2 + v_loss_clipped = (v_clipped - mb_returns) ** 2 + v_loss = 0.5*torch.max(v_loss_unclipped, v_loss_clipped).mean() + + entropy_loss = entropy.mean() + loss = pg_loss + config['vf_coef']*v_loss - config['ent_coef']*entropy_loss + val[idx] = newvalue.detach().float() + + losses['policy_loss'] += pg_loss + losses['value_loss'] += v_loss + losses['entropy'] += entropy_loss + losses['old_approx_kl'] += old_approx_kl + losses['approx_kl'] += approx_kl + losses['clipfrac'] += clipfrac + losses['importance'] += ratio.mean() + + loss.backward() + torch.nn.utils.clip_grad_norm_(self.policy.parameters(), config['max_grad_norm']) + self.optimizer.step() + self.optimizer.zero_grad() + + prof.mark(1) + prof.elapsed(P.TRAIN, 0, 1) + + losses = {k: v.item() / num_minibatches for k, v in losses.items()} + y_pred = val.flatten() + y_true = advantages.flatten() + val.flatten() + var_y = y_true.var() + explained_var = torch.nan if var_y == 0 else (1 - (y_true - y_pred).var() / var_y).item() + losses['explained_variance'] = explained_var + + self.losses = losses + self.epoch += 1 + + def log(self): + P = Profile + perf = self.profile.read_and_reset() + logs = { + 'SPS': self.sps * self.world_size, + 'agent_steps': self.global_step * self.world_size, + 'uptime': time.time() - self.start_time, + 'epoch': self.epoch, + 'env': dict(getattr(self, 'env_logs', {})), + 'loss': dict(getattr(self, 'losses', {})), + 'perf': { + 'rollout': perf[P.ROLLOUT], + 'eval_gpu': perf[P.EVAL_GPU], + 'eval_env': perf[P.EVAL_ENV], + 'train': perf[P.TRAIN], + 'train_misc': perf[P.TRAIN_MISC], + 'train_forward': perf[P.TRAIN_FORWARD], + }, + 'util': dict(_C.get_utilization(self.args.get('gpu_id', 0))) if self.gpu else {}, + } + self.last_log_time = time.time() + self.last_log_step = self.global_step + return logs + + eval_log = log + + def save_weights(self, path): + torch.save(self.policy.state_dict(), path) + + def load_weights(self, path): + state_dict = torch.load(path, map_location=self.device) + state_dict = {k.replace('module.', ''): v for k, v in state_dict.items()} + self.policy.load_state_dict(state_dict) + + def render(self, env_id=0): + self._vec.render(env_id) + + def close(self): + self.vec_obs = None + self.vec_rewards = None + self.vec_terminals = None + self._vec.close() + + @classmethod + def create_pufferl(cls, args): + '''Matches _C.create_pufferl(args) interface.''' + # DDP setup + if 'LOCAL_RANK' in os.environ: + world_size = int(os.environ.get('WORLD_SIZE', 1)) + local_rank = int(os.environ['LOCAL_RANK']) + torch.cuda.set_device(local_rank) + os.environ['CUDA_VISIBLE_DEVICES'] = str(local_rank) + + args['vec']['num_buffers'] = 1 + vec = _C.create_vec(args, _C.gpu) + policy = load_policy(args, vec) + + if 'LOCAL_RANK' in os.environ: + torch.distributed.init_process_group(backend='nccl', world_size=world_size) + policy = policy.to(local_rank) + model = torch.nn.parallel.DistributedDataParallel( + policy, device_ids=[local_rank], output_device=local_rank) + if hasattr(policy, 'lstm'): + model.hidden_size = policy.hidden_size + model.forward_eval = policy.forward_eval + model.initial_state = policy.initial_state + policy = model.to(local_rank) + + return cls(args, vec, policy) + +def compute_puff_advantage(values, rewards, terminals, + ratio, advantages, gamma, gae_lambda, vtrace_rho_clip, vtrace_c_clip): + num_steps, horizon = values.shape + fn = _C.puff_advantage if values.is_cuda else _C.puff_advantage_cpu + fn( + values.data_ptr(), rewards.data_ptr(), terminals.data_ptr(), + ratio.data_ptr(), advantages.data_ptr(), + num_steps, horizon, + gamma, gae_lambda, vtrace_rho_clip, vtrace_c_clip) + return advantages + +class Profile: + '''Matches pufferlib.cu profiling: accumulate ms, report seconds.''' + ROLLOUT, EVAL_GPU, EVAL_ENV, TRAIN, TRAIN_MISC, TRAIN_FORWARD, NUM = range(7) + + def __init__(self, gpu=True): + self.accum = [0.0] * Profile.NUM + self.gpu = gpu + if gpu: + self._events = [torch.cuda.Event(enable_timing=True) for _ in range(4)] + else: + self._stamps = [0.0] * 4 + + def mark(self, idx): + if self.gpu: + self._events[idx].record() + else: + self._stamps[idx] = time.perf_counter() + + def elapsed(self, idx, start_ev, end_ev): + if self.gpu: + self._events[end_ev].synchronize() + self.accum[idx] += self._events[start_ev].elapsed_time(self._events[end_ev]) + else: + self.accum[idx] += (self._stamps[end_ev] - self._stamps[start_ev]) * 1000.0 + + def read_and_reset(self): + out = [v / 1000.0 for v in self.accum] + self.accum = [0.0] * Profile.NUM + return out + +def load_policy(args, vec): + import pufferlib.models + policy_kwargs = args['policy'] + network_cls = getattr(pufferlib.models, args['torch']['network']) + encoder_cls = getattr(pufferlib.models, args['torch']['encoder']) + decoder_cls = getattr(pufferlib.models, args['torch']['decoder']) + + network = network_cls(**policy_kwargs) + encoder = encoder_cls(vec.obs_size, policy_kwargs['hidden_size']) + decoder = decoder_cls(vec.act_sizes, policy_kwargs['hidden_size']) + policy = pufferlib.models.Policy(encoder, decoder, network) + + device = 'cuda' if _C.gpu else 'cpu' + policy = policy.to(device) + + load_id = args['load_id'] + if load_id is not None: + if args['wandb']: + import wandb + artifact = wandb.use_artifact(f'{load_id}:latest') + data_dir = artifact.download() + path = f'{data_dir}/{max(os.listdir(data_dir))}' + else: + raise ValueError('load_id requires --wandb') + + state_dict = torch.load(path, map_location=device) + state_dict = {k.replace('module.', ''): v for k, v in state_dict.items()} + policy.load_state_dict(state_dict) + + load_path = args['load_model_path'] + if load_path == 'latest': + pattern = os.path.join(args['checkpoint_dir'], args['env_name'], '**', '*.bin') + candidates = glob.glob(pattern, recursive=True) + load_path = max(candidates, key=os.path.getctime) + + if load_path is not None: + state_dict = torch.load(load_path, map_location=device) + state_dict = {k.replace('module.', ''): v for k, v in state_dict.items()} + policy.load_state_dict(state_dict) + + return policy + diff --git a/pufferlib/vector.py b/pufferlib/vector.py deleted file mode 100644 index 78614f4d65..0000000000 --- a/pufferlib/vector.py +++ /dev/null @@ -1,925 +0,0 @@ -# TODO: Check actions passed to envs are right shape? On first call at least - -from pdb import set_trace as T - -import numpy as np -import time -import psutil - -from pufferlib.emulation import GymnasiumPufferEnv, PettingZooPufferEnv -from pufferlib import PufferEnv, set_buffers -import pufferlib.spaces -import gymnasium - -RESET = 0 -STEP = 1 -SEND = 2 -RECV = 3 -CLOSE = 4 -MAIN = 5 -INFO = 6 - -def recv_precheck(vecenv): - if vecenv.flag != RECV: - raise pufferlib.APIUsageError('Call reset before stepping') - - vecenv.flag = SEND - -def send_precheck(vecenv, actions): - if vecenv.flag != SEND: - raise pufferlib.APIUsageError('Call (async) reset + recv before sending') - - actions = np.asarray(actions) - if not vecenv.initialized: - vecenv.initialized = True - if not vecenv.action_space.contains(actions): - raise pufferlib.APIUsageError('Actions do not match action space') - - vecenv.flag = RECV - return actions - -def reset(vecenv, seed=42): - vecenv.async_reset(seed) - obs, rewards, terminals, truncations, infos, env_ids, masks = vecenv.recv() - return obs, infos - -def step(vecenv, actions): - actions = np.asarray(actions) - vecenv.send(actions) - obs, rewards, terminals, truncations, infos, env_ids, masks = vecenv.recv() - return obs, rewards, terminals, truncations, infos # include env_ids or no? - -class Serial: - reset = reset - step = step - - @property - def num_envs(self): - return self.agents_per_batch - - def __init__(self, env_creators, env_args, env_kwargs, num_envs, buf=None, seed=0, **kwargs): - self.driver_env = env_creators[0](*env_args[0], **env_kwargs[0]) - self.agents_per_batch = self.driver_env.num_agents * num_envs - self.num_agents = self.agents_per_batch - - self.single_observation_space = self.driver_env.single_observation_space - self.single_action_space = self.driver_env.single_action_space - self.action_space = pufferlib.spaces.joint_space(self.single_action_space, self.agents_per_batch) - self.observation_space = pufferlib.spaces.joint_space(self.single_observation_space, self.agents_per_batch) - - - set_buffers(self, buf) - - self.envs = [] - ptr = 0 - for i in range(num_envs): - end = ptr + self.driver_env.num_agents - buf_i = dict( - observations=self.observations[ptr:end], - rewards=self.rewards[ptr:end], - terminals=self.terminals[ptr:end], - truncations=self.truncations[ptr:end], - masks=self.masks[ptr:end], - actions=self.actions[ptr:end] - ) - ptr = end - seed_i = seed + i if seed is not None else None - env = env_creators[i](*env_args[i], buf=buf_i, seed=seed_i, **env_kwargs[i]) - self.envs.append(env) - - self.driver_env = driver = self.envs[0] - self.emulated = self.driver_env.emulated - check_envs(self.envs, self.driver_env) - self.agents_per_env = [env.num_agents for env in self.envs] - assert sum(self.agents_per_env) == self.agents_per_batch - self.agent_ids = np.arange(self.num_agents) - self.initialized = False - self.flag = RESET - - def _avg_infos(self): - infos = {} - for e in self.infos: - for k, v in pufferlib.unroll_nested_dict(e): - if k not in infos: - infos[k] = [] - - if isinstance(v, list): - infos[k].append(np.mean(v)) - else: - infos[k].append(v) - - for k in list(infos.keys()): - try: - infos[k] = np.mean(infos[k]) - except: - del infos[k] - - def async_reset(self, seed=None): - self.flag = RECV - infos = [] - for i, env in enumerate(self.envs): - if seed is None: - ob, i = env.reset() - else: - ob, i = env.reset(seed=seed+i) - - if isinstance(i, list): - infos.extend(i) - else: - infos.append(i) - - self.infos = infos - self._avg_infos() - - def send(self, actions): - if not actions.flags.contiguous: - actions = np.ascontiguousarray(actions) - - actions = send_precheck(self, actions) - rewards, dones, truncateds, self.infos = [], [], [], [] - ptr = 0 - for idx, env in enumerate(self.envs): - end = ptr + self.agents_per_env[idx] - atns = actions[ptr:end] - if env.done: - o, i = env.reset() - else: - o, r, d, t, i = env.step(atns) - - if i: - if isinstance(i, list): - self.infos.extend(i) - else: - self.infos.append(i) - - ptr = end - - self._avg_infos() - - def notify(self): - for env in self.envs: - env.notify() - - def recv(self): - recv_precheck(self) - return (self.observations, self.rewards, self.terminals, self.truncations, - self.infos, self.agent_ids, self.masks) - - def close(self): - for env in self.envs: - env.close() - -def _worker_process(env_creators, env_args, env_kwargs, obs_shape, obs_dtype, atn_shape, atn_dtype, - num_envs, num_agents, num_workers, worker_idx, send_pipe, recv_pipe, shm, is_native, seed): - - # Environments read and write directly to shared memory - shape = (num_workers, num_envs*num_agents) - atn_arr = np.ndarray((*shape, *atn_shape), - dtype=atn_dtype, buffer=shm['actions'])[worker_idx] - buf = dict( - observations=np.ndarray((*shape, *obs_shape), - dtype=obs_dtype, buffer=shm['observations'])[worker_idx], - rewards=np.ndarray(shape, dtype=np.float32, buffer=shm['rewards'])[worker_idx], - terminals=np.ndarray(shape, dtype=bool, buffer=shm['terminals'])[worker_idx], - truncations=np.ndarray(shape, dtype=bool, buffer=shm['truncateds'])[worker_idx], - masks=np.ndarray(shape, dtype=bool, buffer=shm['masks'])[worker_idx], - actions=atn_arr, - ) - buf['masks'][:] = True - - if is_native and num_envs == 1: - envs = env_creators[0](*env_args[0], **env_kwargs[0], buf=buf, seed=seed) - else: - envs = Serial(env_creators, env_args, env_kwargs, num_envs, buf=buf, seed=seed*num_envs) - - semaphores=np.ndarray(num_workers, dtype=np.uint8, buffer=shm['semaphores']) - notify=np.ndarray(num_workers, dtype=bool, buffer=shm['notify']) - start = time.time() - while True: - if notify[worker_idx]: - envs.notify() - notify[worker_idx] = False - - sem = semaphores[worker_idx] - if sem >= MAIN: - if time.time() - start > 0.5: - time.sleep(0.01) - continue - - start = time.time() - if sem == RESET: - seed = recv_pipe.recv() - _, infos = envs.reset(seed=seed) - elif sem == STEP: - _, _, _, _, infos = envs.step(atn_arr) - elif sem == CLOSE: - envs.close() - send_pipe.send(None) - break - - if infos: - semaphores[worker_idx] = INFO - send_pipe.send(infos) - else: - semaphores[worker_idx] = MAIN - -class Multiprocessing: - '''Runs environments in parallel using multiprocessing - - Use this vectorization module for most applications - ''' - reset = reset - step = step - - @property - def num_envs(self): - return self.agents_per_batch - - def __init__(self, env_creators, env_args, env_kwargs, - num_envs, num_workers=None, batch_size=None, - zero_copy=True, sync_traj=True, overwork=False, seed=0, **kwargs): - if batch_size is None: - batch_size = num_envs - if num_workers is None: - num_workers = num_envs - - import psutil - cpu_cores = psutil.cpu_count(logical=False) - if num_workers > cpu_cores and not overwork: - raise pufferlib.APIUsageError(' '.join([ - f'num_workers ({num_workers}) > hardware cores ({cpu_cores}) is disallowed by default.', - 'PufferLib multiprocessing is heavily optimized for 1 process per hardware core.', - 'If you really want to do this, set overwork=True (--vec-overwork in our demo.py).', - ])) - - num_batches = num_envs / batch_size - if zero_copy and num_batches != int(num_batches): - # This is so you can have n equal buffers - raise pufferlib.APIUsageError( - 'zero_copy: num_envs must be divisible by batch_size') - - self.num_environments = num_envs - envs_per_worker = num_envs // num_workers - self.envs_per_worker = envs_per_worker - self.workers_per_batch = batch_size // envs_per_worker - self.num_workers = num_workers - - # I really didn't want to need a driver process... with mp.shared_memory - # we can fetch this data from the worker processes and ever perform - # additional space checks. Unfortunately, SharedMemory has a janky integration - # with the resource tracker that spams warnings and does not work with - # forked processes. So for now, RawArray is much more reliable. - # You can't send a RawArray through a pipe. - self.driver_env = driver_env = env_creators[0](*env_args[0], **env_kwargs[0]) - is_native = isinstance(driver_env, PufferEnv) - self.emulated = False if is_native else driver_env.emulated - self.num_agents = num_agents = driver_env.num_agents * num_envs - self.agents_per_batch = driver_env.num_agents * batch_size - agents_per_worker = driver_env.num_agents * envs_per_worker - obs_space = driver_env.single_observation_space - obs_shape = obs_space.shape - obs_dtype = obs_space.dtype - obs_ctype = np.ctypeslib.as_ctypes_type(obs_dtype) - atn_space = driver_env.single_action_space - atn_shape = atn_space.shape - atn_dtype = atn_space.dtype - if isinstance(atn_space, (pufferlib.spaces.Discrete, pufferlib.spaces.MultiDiscrete)): - atn_dtype = np.int32 - - atn_ctype = np.ctypeslib.as_ctypes_type(atn_dtype) - - self.single_observation_space = driver_env.single_observation_space - self.single_action_space = driver_env.single_action_space - self.action_space = pufferlib.spaces.joint_space(self.single_action_space, self.agents_per_batch) - self.observation_space = pufferlib.spaces.joint_space(self.single_observation_space, self.agents_per_batch) - self.agent_ids = np.arange(num_agents).reshape(num_workers, agents_per_worker) - - from multiprocessing import RawArray, set_start_method - # Mac breaks without setting fork... but setting it breaks sweeps on 2nd run - #set_start_method('fork') - self.shm = dict( - observations=RawArray(obs_ctype, num_agents * int(np.prod(obs_shape))), - actions=RawArray(atn_ctype, num_agents * int(np.prod(atn_shape))), - rewards=RawArray('f', num_agents), - terminals=RawArray('b', num_agents), - truncateds=RawArray('b', num_agents), - masks=RawArray('b', num_agents), - semaphores=RawArray('c', num_workers), - notify=RawArray('b', num_workers), - ) - shape = (num_workers, agents_per_worker) - self.obs_batch_shape = (self.agents_per_batch, *obs_shape) - self.atn_batch_shape = (self.workers_per_batch, agents_per_worker, *atn_shape) - self.actions = np.ndarray((*shape, *atn_shape), - dtype=atn_dtype, buffer=self.shm['actions']) - self.buf = dict( - observations=np.ndarray((*shape, *obs_shape), - dtype=obs_dtype, buffer=self.shm['observations']), - rewards=np.ndarray(shape, dtype=np.float32, buffer=self.shm['rewards']), - terminals=np.ndarray(shape, dtype=bool, buffer=self.shm['terminals']), - truncations=np.ndarray(shape, dtype=bool, buffer=self.shm['truncateds']), - masks=np.ndarray(shape, dtype=bool, buffer=self.shm['masks']), - semaphores=np.ndarray(num_workers, dtype=np.uint8, buffer=self.shm['semaphores']), - notify=np.ndarray(num_workers, dtype=bool, buffer=self.shm['notify']), - ) - self.buf['semaphores'][:] = MAIN - - from multiprocessing import Pipe, Process - self.send_pipes, w_recv_pipes = zip(*[Pipe() for _ in range(num_workers)]) - w_send_pipes, self.recv_pipes = zip(*[Pipe() for _ in range(num_workers)]) - self.recv_pipe_dict = {p: i for i, p in enumerate(self.recv_pipes)} - - self.processes = [] - for i in range(num_workers): - start = i * envs_per_worker - end = start + envs_per_worker - seed_i = seed + i if seed is not None else None - p = Process( - target=_worker_process, - args=(env_creators[start:end], env_args[start:end], - env_kwargs[start:end], obs_shape, obs_dtype, - atn_shape, atn_dtype, envs_per_worker, driver_env.num_agents, - num_workers, i, w_send_pipes[i], w_recv_pipes[i], - self.shm, is_native, seed_i) - ) - p.start() - self.processes.append(p) - - self.flag = RESET - self.initialized = False - self.zero_copy = zero_copy - self.sync_traj = sync_traj - - self.ready_workers = [] - self.waiting_workers = [] - - def recv(self): - recv_precheck(self) - while True: - # Bandaid patch for new experience buffer desync - if self.sync_traj: - worker = self.waiting_workers[0] - sem = self.buf['semaphores'][worker] - if sem >= MAIN: - self.waiting_workers.pop(0) - self.ready_workers.append(worker) - else: - worker = self.waiting_workers.pop(0) - sem = self.buf['semaphores'][worker] - if sem >= MAIN: - self.ready_workers.append(worker) - else: - self.waiting_workers.append(worker) - - if sem == INFO: - self.infos[worker] = self.recv_pipes[worker].recv() - - if not self.ready_workers: - continue - - if self.workers_per_batch == 1: - # Fastest path. Zero-copy optimized for batch size 1 - w_slice = self.ready_workers[0] - s_range = [w_slice] - self.waiting_workers.append(w_slice) - self.ready_workers.pop(0) - break - elif self.workers_per_batch == self.num_workers: - # Slowest path. Zero-copy synchornized for all workers - if len(self.ready_workers) < self.num_workers: - continue - - w_slice = slice(0, self.num_workers) - s_range = range(0, self.num_workers) - self.waiting_workers.extend(s_range) - self.ready_workers = [] - break - elif self.zero_copy: - # Zero-copy for batch size > 1. Has to wait for - # a contiguous block of workers and adds a few - # microseconds of extra index processing time - completed = np.zeros(self.num_workers, dtype=bool) - completed[self.ready_workers] = True - buffers = completed.reshape( - -1, self.workers_per_batch).all(axis=1) - start = buffers.argmax() - if not buffers[start]: - continue - - start *= self.workers_per_batch - end = start + self.workers_per_batch - w_slice = slice(start, end) - s_range = range(start, end) - self.waiting_workers.extend(s_range) - self.ready_workers = [e for e in self.ready_workers - if e not in s_range] - break - elif len(self.ready_workers) >= self.workers_per_batch: - # Full async path for batch size > 1. Alawys copies - # data because of non-contiguous worker indices - # Can be faster for envs with small observations - w_slice = self.ready_workers[:self.workers_per_batch] - s_range = w_slice - self.waiting_workers.extend(s_range) - self.ready_workers = self.ready_workers[self.workers_per_batch:] - break - - self.w_slice = w_slice - buf = self.buf - - o = buf['observations'][w_slice].reshape(self.obs_batch_shape) - r = buf['rewards'][w_slice].ravel() - d = buf['terminals'][w_slice].ravel() - t = buf['truncations'][w_slice].ravel() - - infos = [] - for i in s_range: - if self.infos[i]: - infos.extend(self.infos[i]) - self.infos[i] = [] - - agent_ids = self.agent_ids[w_slice].ravel() - m = buf['masks'][w_slice].ravel() - self.batch_mask = m - - return o, r, d, t, infos, agent_ids, m - - def send(self, actions): - actions = send_precheck(self, actions).reshape(self.atn_batch_shape) - # TODO: What shape? - - idxs = self.w_slice - self.actions[idxs] = actions - self.buf['semaphores'][idxs] = STEP - - def async_reset(self, seed=0): - # Flush any waiting workers - while self.waiting_workers: - worker = self.waiting_workers.pop(0) - sem = self.buf['semaphores'][worker] - if sem >= MAIN: - self.ready_workers.append(worker) - if sem == INFO: - self.recv_pipes[worker].recv() - else: - self.waiting_workers.append(worker) - - self.flag = RECV - self.prev_env_id = [] - self.flag = RECV - - self.ready_workers = [] - self.ready_next_workers = [] # Used to evenly sample workers - self.waiting_workers = list(range(self.num_workers)) - self.infos = [[] for _ in range(self.num_workers)] - - self.buf['semaphores'][:] = RESET - for i in range(self.num_workers): - start = i*self.envs_per_worker - end = (i+1)*self.envs_per_worker - self.send_pipes[i].send(seed+i) - - def notify(self): - self.buf['notify'][:] = True - - def close(self): - self.driver_env.close() - for p in self.processes: - p.terminate() - -class Ray(): - '''Runs environments in parallel on multiple processes using Ray - - Use this module for distributed simulation on a cluster. - ''' - reset = reset - step = step - - def __init__(self, env_creators, env_args, env_kwargs, num_envs, - num_workers=None, batch_size=None, **kwargs): - if batch_size is None: - batch_size = num_envs - if num_workers is None: - num_workers = num_envs - - self.env_pool = num_envs != batch_size - envs_per_worker = num_envs // num_workers - self.workers_per_batch = batch_size // envs_per_worker - self.num_workers = num_workers - - driver_env = env_creators[0](*env_args[0], **env_kwargs[0]) - self.driver_env = driver_env - self.emulated = driver_env.emulated - self.num_agents = num_agents = driver_env.num_agents * num_envs - self.agents_per_batch = driver_env.num_agents * batch_size - agents_per_worker = driver_env.num_agents * envs_per_worker - obs_space = driver_env.single_observation_space - obs_shape = obs_space.shape - atn_space = driver_env.single_action_space - atn_shape = atn_space.shape - - shape = (num_workers, agents_per_worker) - self.obs_batch_shape = (self.agents_per_batch, *obs_shape) - self.atn_batch_shape = (self.workers_per_batch, agents_per_worker, *atn_shape) - - self.single_observation_space = driver_env.single_observation_space - self.single_action_space = driver_env.single_action_space - self.action_space = pufferlib.spaces.joint_space(self.single_action_space, self.agents_per_batch) - self.observation_space = pufferlib.spaces.joint_space(self.single_observation_space, self.agents_per_batch) - - self.agent_ids = np.arange(num_agents).reshape(num_workers, agents_per_worker) - - import ray - if not ray.is_initialized(): - import logging - ray.init( - include_dashboard=False, # WSL Compatibility - logging_level=logging.ERROR, - ) - - self.envs = [] - for i in range(num_workers): - start = i * envs_per_worker - end = start + envs_per_worker - self.envs.append( - ray.remote(Serial).remote( - env_creators[start:end], - env_args[start:end], - env_kwargs[start:end], - envs_per_worker - ) - ) - - self.async_handles = None - self.initialized = False - self.flag = RESET - self.ray = ray - self.prev_env_id = [] - - def recv(self): - recv_precheck(self) - recvs = [] - next_env_id = [] - workers_per_batch = self.workers_per_batch - if self.env_pool: - recvs = self.ray.get(self.async_handles[:workers_per_batch]) - env_id = [_ for _ in range(workers_per_batch)] - else: - ready, busy = self.ray.wait( - self.async_handles, num_returns=workers_per_batch) - env_id = [self.async_handles.index(e) for e in ready] - recvs = self.ray.get(ready) - - o, r, d, t, infos, ids, m = zip(*recvs) - self.prev_env_id = env_id - - infos = [i for ii in infos for i in ii] - - o = np.stack(o, axis=0).reshape(self.obs_batch_shape) - r = np.stack(r, axis=0).ravel() - d = np.stack(d, axis=0).ravel() - t = np.stack(t, axis=0).ravel() - m = np.stack(m, axis=0).ravel() - agent_ids = self.agent_ids[env_id].ravel() - return o, r, d, t, infos, agent_ids, m - - def send(self, actions): - actions = send_precheck(self, actions).reshape(self.atn_batch_shape) - # TODO: What shape? - - handles = [] - for i, e in enumerate(self.prev_env_id): - atns = actions[i] - env = self.envs[e] - env.send.remote(atns) - handles.append(env.recv.remote()) - - self.async_handles = handles - - def async_reset(self, seed=42): - self.flag = RECV - if seed is None: - kwargs = {} - else: - kwargs = {"seed": seed} - - handles = [] - for idx, e in enumerate(self.envs): - e.async_reset.remote(**kwargs) - handles.append(e.recv.remote()) - - self.async_handles = handles - - def close(self): - self.ray.get([e.close.remote() for e in self.envs]) - self.ray.shutdown() - - -def make(env_creator_or_creators, env_args=None, env_kwargs=None, backend=PufferEnv, num_envs=1, seed=0, **kwargs): - if num_envs < 1: - raise pufferlib.APIUsageError('num_envs must be at least 1') - if num_envs != int(num_envs): - raise pufferlib.APIUsageError('num_envs must be an integer') - - if isinstance(backend, str): - try: - backend = getattr(pufferlib.vector, backend) - except: - raise pufferlib.APIUsageError(f'Invalid backend: {backend}') - - if backend == PufferEnv: - env_args = env_args or [] - env_kwargs = env_kwargs or {} - vecenv = env_creator_or_creators(*env_args, **env_kwargs) - if not isinstance(vecenv, PufferEnv): - raise pufferlib.APIUsageError('Native vectorization requires a native PufferEnv. Use Serial or Multiprocessing instead.') - if num_envs != 1: - raise pufferlib.APIUsageError('Native vectorization is for PufferEnvs that handle all per-process vectorization internally. If you want to run multiple separate Python instances on a single process, use Serial or Multiprocessing instead') - - return vecenv - - if 'num_workers' in kwargs: - if kwargs['num_workers'] == 'auto': - kwargs['num_workers'] = num_envs - - # TODO: None? - envs_per_worker = num_envs / kwargs['num_workers'] - if envs_per_worker != int(envs_per_worker): - raise pufferlib.APIUsageError('num_envs must be divisible by num_workers') - - if 'batch_size' in kwargs: - if kwargs['batch_size'] == 'auto': - if num_envs == 1: - kwargs['batch_size'] = 1 - else: - kwargs['batch_size'] = num_envs // 2 - - batch_size = kwargs['batch_size'] - if batch_size is None: - batch_size = num_envs - - if batch_size % envs_per_worker != 0: - raise pufferlib.APIUsageError( - 'batch_size must be divisible by (num_envs / num_workers)') - - - if env_args is None: - env_args = [] - - if env_kwargs is None: - env_kwargs = {} - - if not isinstance(env_creator_or_creators, (list, tuple)): - env_creators = [env_creator_or_creators] * num_envs - env_args = [env_args] * num_envs - env_kwargs = [env_kwargs] * num_envs - else: - env_creators = env_creator_or_creators - - if len(env_creators) != num_envs: - raise pufferlib.APIUsageError('env_creators must be a list of length num_envs') - if len(env_args) != num_envs: - raise pufferlib.APIUsageError('env_args must be a list of length num_envs') - if len(env_kwargs) != num_envs: - raise pufferlib.APIUsageError('env_kwargs must be a list of length num_envs') - - for i in range(num_envs): - if not callable(env_creators[i]): - raise pufferlib.APIUsageError('env_creators must be a list of callables') - if not isinstance(env_args[i], (list, tuple)): - raise pufferlib.APIUsageError('env_args must be a list of lists or tuples') - if not isinstance(env_kwargs[i], dict): - raise pufferlib.APIUsageError('env_kwargs must be a list of dictionaries') - - # Keeps batch size consistent when debugging with Serial backend - if backend is Serial and 'batch_size' in kwargs: - num_envs = kwargs['batch_size'] - - # TODO: Check num workers is not greater than num envs. This results in - # different Serial vs Multiprocessing behavior - - # Sanity check args - for k in kwargs: - if k not in ['num_workers', 'batch_size', 'zero_copy', 'overwork', 'backend']: - raise pufferlib.APIUsageError(f'Invalid argument: {k}') - - # TODO: First step action space check - - return backend(env_creators, env_args, env_kwargs, num_envs, **kwargs) - -def make_seeds(seed, num_envs): - if isinstance(seed, int): - return [seed + i for i in range(num_envs)] - - err = f'seed {seed} must be an integer or a list of integers' - if isinstance(seed, (list, tuple)): - if len(seed) != num_envs: - raise pufferlib.APIUsageError(err) - - return seed - - raise pufferlib.APIUsageError(err) - -def check_envs(envs, driver): - valid = (PufferEnv, GymnasiumPufferEnv, PettingZooPufferEnv) - if not isinstance(driver, valid): - raise pufferlib.APIUsageError(f'env_creator must be {valid}') - - driver_obs = driver.single_observation_space - driver_atn = driver.single_action_space - for env in envs: - if not isinstance(env, valid): - raise pufferlib.APIUsageError(f'env_creators must be {valid}') - obs_space = env.single_observation_space - if obs_space != driver_obs: - raise pufferlib.APIUsageError(f'\n{obs_space}\n{driver_obs} obs space mismatch') - atn_space = env.single_action_space - if atn_space != driver_atn: - raise pufferlib.APIUsageError(f'\n{atn_space}\n{driver_atn} atn space mismatch') - -def autotune(env_creator, batch_size, max_envs=194, model_forward_s=0.0, - max_env_ram_gb=32, max_batch_vram_gb=0.05, time_per_test=5): - '''Determine the optimal vectorization parameters for your system''' - # TODO: fix multiagent - - if batch_size is None: - raise ValueError('batch_size must not be None') - - if max_envs < batch_size: - raise ValueError('max_envs < min_batch_size') - - num_cores = psutil.cpu_count(logical=False) - idle_ram = psutil.Process().memory_info().rss - load_ram = idle_ram - - # Initial profile to estimate single-core performance - print('Profiling single-core performance for ~', time_per_test, 'seconds') - env = env_creator() - env.reset() - obs_space = env.single_observation_space - actions = [ - np.array([env.single_action_space.sample() - for _ in range(env.num_agents)]) - for _ in range(1000) - ] - - num_agents = env.num_agents - steps = 0 - step_times = [] - reset_times = [] - start = time.time() - while time.time() - start < time_per_test: - idle_ram = max(idle_ram, psutil.Process().memory_info().rss) - s = time.time() - if env.done: - env.reset() - reset_times.append(time.time() - s) - else: - env.step(actions[steps%1000]) - step_times.append(time.time() - s) - steps += 1 - - env.close() - sum_time = sum(step_times) + sum(reset_times) - reset_percent = 100 * sum(reset_times) / sum_time - sps = steps * num_agents / sum_time - step_variance = 100 * np.std(step_times) / np.mean(step_times) - reset_mean = np.mean(reset_times) - ram_usage = max(1, (idle_ram - load_ram)) / 1e9 - - obs_size_gb = ( - np.prod(obs_space.shape) - * np.dtype(obs_space.dtype).itemsize - * num_agents - / 1e9 - ) - - # Max bandwidth - bandwidth = obs_size_gb * sps - throughput = bandwidth * num_cores - - print('Profile complete') - print(f' SPS: {sps:.3f}') - print(f' STD: {step_variance:.3f}%') - print(f' Reset: {reset_percent:.3f}%') - print(f' RAM: {1000*ram_usage:.3f} MB/env') - print(f' Bandwidth: {bandwidth:.3f} GB/s') - print(f' Throughput: {throughput:.3f} GB/s ({num_cores} cores)') - print() - - # Cap envs based on max allowed RAM - max_allowed_by_ram = max_env_ram_gb // ram_usage - if max_allowed_by_ram < max_envs: - max_envs = int(max_allowed_by_ram) - print('Reducing max envs to', max_envs, 'based on RAM') - - # Cap envs based on estimated max speedup - #linear_speedup = (num_cores * steps / sum_time) // 500 - #if linear_speedup < max_envs and linear_speedup > num_cores: - # max_envs = int(linear_speedup) - # print('Reducing max envs to', max_envs, 'based on single-core speed') - - # Cap envs based on hardware - hardware_envs = max_envs - (max_envs % num_cores) - if hardware_envs > batch_size and hardware_envs != max_envs: - max_envs = int(hardware_envs) - print('Reducing max envs to', max_envs, 'based on core division') - - max_allowed_by_vram = max_batch_vram_gb // obs_size_gb - if max_allowed_by_vram < batch_size: - raise ValueError('max_allowed_by_vram < batch_size') - - print() - configs = [] - - # Strategy 1: one batch per core - strategy_cores = min(num_cores, max_envs // batch_size) - configs.append(dict( - num_envs=batch_size*strategy_cores, - num_workers=strategy_cores, - batch_size=batch_size, - backend=Multiprocessing, - )) - - strategy_min_envs_per_worker = int(np.ceil((batch_size+1) / num_cores)) - strategy_num_envs = [] - for envs_per_worker in range(strategy_min_envs_per_worker, batch_size): - num_envs = envs_per_worker * num_cores - if num_envs > max_envs: - break - elif batch_size % envs_per_worker != 0: - continue - - # Strategy 2: Full async. Only reasonable for low bandwidth - #if throughput < 1.5: - configs.append(dict( - num_envs=num_envs, - num_workers=num_cores, - batch_size=batch_size, - zero_copy=False, - backend=Multiprocessing, - )) - - # Strategy 3: Contiguous blocks. Only reasonable for high bandwidth - num_batchs = num_envs / batch_size - if num_batchs != int(num_batchs): - continue - if throughput > 0.5: - configs.append(dict( - num_envs=num_envs, - num_workers=num_cores, - batch_size=batch_size, - backend=Multiprocessing, - )) - - # Strategy 4: Full sync - perhaps nichely useful - for strategy_cores in range(num_cores, 1, -1): - if batch_size % strategy_cores != 0: - continue - - configs.append(dict( - num_envs=batch_size, - num_workers=strategy_cores, - batch_size=batch_size, - backend=Multiprocessing, - )) - - # Strategy 5: Serial - configs.append(dict( - num_envs=batch_size, - backend=Serial, - )) - - for config in configs: - with pufferlib.Suppress(): - envs = make(env_creator, **config) - envs.reset() - actions = [envs.action_space.sample() for _ in range(1000)] - step_time = 0 - steps = 0 - start = time.time() - while time.time() - start < time_per_test: - s = time.time() - envs.send(actions[steps%1000]) - step_time += time.time() - s - - if model_forward_s > 0: - time.sleep(model_forward_s) - - s = time.time() - envs.recv() - step_time += time.time() - s - - steps += 1 - - end = time.time() - envs.close() - sps = steps * envs.agents_per_batch / step_time - print(f'SPS: {sps:.3f}') - for k, v in config.items(): - if k == 'backend': - v = v.__name__ - - print(f' {k}: {v}') - - print() diff --git a/pyproject.toml b/pyproject.toml index 7977074490..d8c18a0158 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,247 +1,30 @@ [project] name = "pufferlib" -version = "3.0.0" +version = "4.0.0" description = "Fast and sane reinforcement learning" -requires-python = ">=3.9" +requires-python = ">=3.10" readme = {file = "README.md", content-type = "text/markdown"} -license = {text = "MIT"} +license = {file = "LICENSE"} authors = [{ name = "Joseph Suarez", email = "jsuarez@puffer.ai" }] classifiers=[ "Intended Audience :: Science/Research", "Intended Audience :: Developers", - "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", "Programming Language :: Python :: 3.14", ] -dynamic = ["dependencies"] - -# Default Gym/Gymnasium/PettingZoo versions -# Gym: -# - 0.26 still has deprecation warnings and is the last version of the package -# - 0.25 adds a breaking API change to reset, step, and render_modes -# - 0.24 is broken -# - 0.22-0.23 triggers deprecation warnings by calling its own functions -# - 0.21 is the most stable version -# - <= 0.20 is missing dict methods for gym.spaces.Dict -# - 0.18-0.21 require setuptools<=65.5.0 -#'gym==0.23', -#'gymnasium==0.29.1', -#'pettingzoo==1.24.1', -[project.optional-dependencies] -avalon = [ - 'gymnasium==0.29.1', - 'avalon-rl==1.0.0', -] - -atari = [ - 'gymnasium[accept-rom-license]==0.29.1', - 'opencv-python==3.4.17.63', - 'ale_py==0.9.0', -] - -box2d = [ - 'gymnasium[box2d]==0.29.1', - 'swig==4.1.1', -] - -bsuite = [ - 'gym==0.23', - 'gymnasium==0.29.1', - 'bsuite==0.3.5', -] - -butterfly = [ - 'gym==0.23', - 'gymnasium==0.29.1', - 'pettingzoo[butterfly]==1.24.1', -] - -classic_control = [ - 'gym==0.23', - 'gymnasium==0.29.1', -] - -crafter = [ - 'gym==0.23', - 'gymnasium==0.29.1', - 'crafter==1.8.3', -] - -craftax = [ - 'gymnasium==0.29.1', - 'craftax', -] - -dm_control = [ - 'gym==0.23', - 'gymnasium==0.29.1', - 'dm_control==1.0.11', -] - -dm_lab = [ - 'gym==0.23', - 'gymnasium==0.29.1', - 'gym_deepmindlab==0.1.2', - 'dm_env==1.6', -] - -griddly = [ - 'gym==0.23', - 'gymnasium==0.29.1', - 'griddly==1.6.7', - 'imageio', -] - -kinetix = [ - 'gym==0.23', - 'gymnasium==0.29.1', - 'kinetix-env', -] - -magent = [ - 'gym==0.23', - 'gymnasium==0.29.1', - 'pettingzoo==1.19.0', - 'magent==0.2.4', - # The Magent2 package is broken for now - #'magent2==0.3.2', -] - -metta = [ - 'gym==0.23', - 'gymnasium==0.29.1', - 'omegaconf', - 'hydra-core', - 'duckdb', - 'raylib>=5.5.0', - 'metta-common @ git+https://github.com/metta-ai/metta.git@main#subdirectory=common', - 'metta-mettagrid @ git+https://github.com/metta-ai/metta.git@main#subdirectory=mettagrid', -] - -cogames = [ - 'gym', - 'gymnasium', - 'omegaconf', - 'hydra-core', - 'duckdb', - 'raylib>=5.5.0', - 'mettagrid @ git+https://github.com/metta-ai/metta.git@main#subdirectory=packages/mettagrid', - 'cogames @ git+https://github.com/metta-ai/metta.git@main#subdirectory=packages/cogames', -] - -microrts = [ - 'gym==0.23', - 'gymnasium==0.29.1', - 'ffmpeg==1.4', - 'gym_microrts==0.3.2', -] - -minerl = [ - 'gym==0.17.0', - 'gymnasium==0.29.1', - #'git+https://github.com/minerllabs/minerl' - # Compatiblity warning with urllib3 and chardet - #'requests==2.31.0', -] - -minigrid = [ - 'gym==0.23', - 'gymnasium==0.29.1', - 'minigrid==2.3.1', -] - -minihack = [ - 'gym==0.23', - 'gymnasium==0.29.1', - 'minihack==0.1.5', -] - -mujoco = [ - 'gymnasium[mujoco]==1.0.0', - 'moviepy', -] - -nethack = [ - 'gym==0.23', - 'gymnasium==0.29.1', - 'nle==0.9.1', -] - -nmmo = [ - 'gym==0.23', - 'gymnasium==0.29.1', - 'pettingzoo==1.24.1', - 'nmmo>=2.1', -] - -open_spiel = [ - 'gym==0.23', - 'gymnasium==0.29.1', - 'pettingzoo==1.19.0', - 'open_spiel==1.3', -] - -pokemon_red = [ - 'gym==0.23', - 'gymnasium==0.29.1', - 'pokegym>=0.2.0', - 'einops==0.6.1', - 'matplotlib', - 'scikit-image', - 'pyboy<2.0.0', - 'hnswlib==0.7.0', - 'mediapy', - 'pandas==2.0.2', - 'pettingzoo', - 'websockets', -] - -procgen = [ - 'gym==0.23', - 'gymnasium==0.29.1', - 'stable_baselines3==2.1.0', - 'procgen-mirror==0.10.7', # Procgen mirror for 3.11 and 3.12 support - # Note: You need glfw==2.7 after installing for some torch versions -] - -#'smac': [ -# 'git+https://github.com/oxwhirl/smac.git', -#], -#'stable-retro': [ -# 'git+https://github.com/Farama-Foundation/stable-retro.git', -#] - -slimevolley = [ - 'gym==0.23', - 'gymnasium==0.29.1', - 'slimevolley==0.1.0', -] - -vizdoom = [ - 'gym==0.23', - 'gymnasium==0.29.1', - 'vizdoom==1.2.3', - 'stable_baselines3==2.1.0', -] - -ray = [ - 'ray==2.23.0', -] - -tribal-village = [ - 'gym==0.23', - 'gymnasium==0.29.1', - 'numpy<2.0', - 'tribal-village @ git+https://github.com/Metta-AI/tribal-village.git@main', -] - -cleanrl = [ - 'stable_baselines3==2.1.0', - 'tensorboard==2.11.2', - 'tyro==0.8.6', +dependencies = [ + "setuptools", + "numpy", + "torch>=2.9", + "rich", + "rich_argparse", + "gpytorch", + "scikit-learn", + "wandb", + "pybind11", ] [project.scripts] @@ -250,12 +33,10 @@ puffer = "pufferlib.pufferl:main" [project.urls] Homepage = "https://puffer.ai" +[tool.setuptools.packages.find] +where = ["."] +include = ["pufferlib*"] + [build-system] -requires = ["setuptools", "wheel", "Cython", "numpy<2.0", "torch"] +requires = ["setuptools"] build-backend = "setuptools.build_meta" - -[tool.uv] -no-build-isolation-package = ["torch"] - -[tool.setuptools] -license-files = ["LICENSE"] diff --git a/resources b/resources deleted file mode 120000 index e0160317a6..0000000000 --- a/resources +++ /dev/null @@ -1 +0,0 @@ -pufferlib/resources/ \ No newline at end of file diff --git a/pufferlib/resources/battle/artillery.glb b/resources/battle/artillery.glb similarity index 100% rename from pufferlib/resources/battle/artillery.glb rename to resources/battle/artillery.glb diff --git a/pufferlib/resources/battle/base.glb b/resources/battle/base.glb similarity index 100% rename from pufferlib/resources/battle/base.glb rename to resources/battle/base.glb diff --git a/pufferlib/resources/battle/bomber.glb b/resources/battle/bomber.glb similarity index 100% rename from pufferlib/resources/battle/bomber.glb rename to resources/battle/bomber.glb diff --git a/pufferlib/resources/battle/car.glb b/resources/battle/car.glb similarity index 100% rename from pufferlib/resources/battle/car.glb rename to resources/battle/car.glb diff --git a/pufferlib/resources/battle/drone.glb b/resources/battle/drone.glb similarity index 100% rename from pufferlib/resources/battle/drone.glb rename to resources/battle/drone.glb diff --git a/pufferlib/resources/battle/fighter.glb b/resources/battle/fighter.glb similarity index 100% rename from pufferlib/resources/battle/fighter.glb rename to resources/battle/fighter.glb diff --git a/pufferlib/resources/battle/mothership.glb b/resources/battle/mothership.glb similarity index 100% rename from pufferlib/resources/battle/mothership.glb rename to resources/battle/mothership.glb diff --git a/pufferlib/resources/battle/shader_330.fs b/resources/battle/shader_330.fs similarity index 100% rename from pufferlib/resources/battle/shader_330.fs rename to resources/battle/shader_330.fs diff --git a/pufferlib/resources/battle/shader_330.vs b/resources/battle/shader_330.vs similarity index 100% rename from pufferlib/resources/battle/shader_330.vs rename to resources/battle/shader_330.vs diff --git a/pufferlib/resources/battle/tank.glb b/resources/battle/tank.glb similarity index 100% rename from pufferlib/resources/battle/tank.glb rename to resources/battle/tank.glb diff --git a/pufferlib/resources/blastar/blastar_weights.bin b/resources/blastar/blastar_weights.bin similarity index 100% rename from pufferlib/resources/blastar/blastar_weights.bin rename to resources/blastar/blastar_weights.bin diff --git a/pufferlib/resources/blastar/enemy_bullet.png b/resources/blastar/enemy_bullet.png similarity index 100% rename from pufferlib/resources/blastar/enemy_bullet.png rename to resources/blastar/enemy_bullet.png diff --git a/pufferlib/resources/blastar/enemy_ship.png b/resources/blastar/enemy_ship.png similarity index 100% rename from pufferlib/resources/blastar/enemy_ship.png rename to resources/blastar/enemy_ship.png diff --git a/pufferlib/resources/blastar/player_bullet.png b/resources/blastar/player_bullet.png similarity index 100% rename from pufferlib/resources/blastar/player_bullet.png rename to resources/blastar/player_bullet.png diff --git a/pufferlib/resources/blastar/player_death_explosion.png b/resources/blastar/player_death_explosion.png similarity index 100% rename from pufferlib/resources/blastar/player_death_explosion.png rename to resources/blastar/player_death_explosion.png diff --git a/pufferlib/resources/blastar/player_ship.png b/resources/blastar/player_ship.png similarity index 100% rename from pufferlib/resources/blastar/player_ship.png rename to resources/blastar/player_ship.png diff --git a/resources/boxoban/Crate_Black.jpg b/resources/boxoban/Crate_Black.jpg new file mode 100644 index 0000000000..78ebb3c523 Binary files /dev/null and b/resources/boxoban/Crate_Black.jpg differ diff --git a/resources/boxoban/EndPoint_Black.jpg b/resources/boxoban/EndPoint_Black.jpg new file mode 100644 index 0000000000..ca22b7b5d5 Binary files /dev/null and b/resources/boxoban/EndPoint_Black.jpg differ diff --git a/resources/boxoban/EndPoint_Blue.jpg b/resources/boxoban/EndPoint_Blue.jpg new file mode 100644 index 0000000000..9ce180ff9b Binary files /dev/null and b/resources/boxoban/EndPoint_Blue.jpg differ diff --git a/resources/boxoban/GroundGravel_Concrete.jpg b/resources/boxoban/GroundGravel_Concrete.jpg new file mode 100644 index 0000000000..095c2a24e7 Binary files /dev/null and b/resources/boxoban/GroundGravel_Concrete.jpg differ diff --git a/resources/boxoban/Wall_Black.jpg b/resources/boxoban/Wall_Black.jpg new file mode 100644 index 0000000000..1fa3db8997 Binary files /dev/null and b/resources/boxoban/Wall_Black.jpg differ diff --git a/resources/breakout/breakout_weights.bin b/resources/breakout/breakout_weights.bin new file mode 100644 index 0000000000..ffef6190a9 Binary files /dev/null and b/resources/breakout/breakout_weights.bin differ diff --git a/resources/cartpole/cartpole_weights.bin b/resources/cartpole/cartpole_weights.bin new file mode 100644 index 0000000000..483ff34930 Binary files /dev/null and b/resources/cartpole/cartpole_weights.bin differ diff --git a/resources/connect4/connect4_weights.bin b/resources/connect4/connect4_weights.bin new file mode 100644 index 0000000000..125acfa08b Binary files /dev/null and b/resources/connect4/connect4_weights.bin differ diff --git a/resources/constellation/blur_100.fs b/resources/constellation/blur_100.fs new file mode 100644 index 0000000000..7ce63677a5 --- /dev/null +++ b/resources/constellation/blur_100.fs @@ -0,0 +1,22 @@ +#version 100 +precision mediump float; +varying vec2 fragTexCoord; +varying vec4 fragColor; +uniform sampler2D texture0; + +const float renderWidth = 960.0; +const float offset0 = 0.0; +const float offset1 = 1.3846153846; +const float offset2 = 3.2307692308; +const float weight0 = 0.2270270270; +const float weight1 = 0.3162162162; +const float weight2 = 0.0702702703; + +void main() { + vec3 texelColor = texture2D(texture0, fragTexCoord).rgb * weight0; + texelColor += texture2D(texture0, fragTexCoord + vec2(offset1) / renderWidth).rgb * weight1; + texelColor += texture2D(texture0, fragTexCoord - vec2(offset1) / renderWidth).rgb * weight1; + texelColor += texture2D(texture0, fragTexCoord + vec2(offset2) / renderWidth).rgb * weight2; + texelColor += texture2D(texture0, fragTexCoord - vec2(offset2) / renderWidth).rgb * weight2; + gl_FragColor = vec4(texelColor, 1.0); +} diff --git a/resources/constellation/blur_100.vs b/resources/constellation/blur_100.vs new file mode 100644 index 0000000000..d0e2bae535 --- /dev/null +++ b/resources/constellation/blur_100.vs @@ -0,0 +1,13 @@ +#version 100 +attribute vec3 vertexPosition; +attribute vec2 vertexTexCoord; +attribute vec4 vertexColor; +uniform mat4 mvp; +varying vec2 fragTexCoord; +varying vec4 fragColor; + +void main() { + fragTexCoord = vertexTexCoord; + fragColor = vertexColor; + gl_Position = mvp * vec4(vertexPosition, 1.0); +} diff --git a/resources/constellation/blur_330.fs b/resources/constellation/blur_330.fs new file mode 100644 index 0000000000..39eb593460 --- /dev/null +++ b/resources/constellation/blur_330.fs @@ -0,0 +1,35 @@ +#version 330 + +// Input vertex attributes (from vertex shader) +in vec2 fragTexCoord; +in vec4 fragColor; + +// Input uniform values +uniform sampler2D texture0; +uniform vec4 colDiffuse; + +// Output fragment color +out vec4 finalColor; + +// NOTE: Add your custom variables here + +// NOTE: Render size values must be passed from code +const float renderWidth = 960; +const float renderHeight = 520; + +float offset[3] = float[](0.0, 1.3846153846, 3.2307692308); +float weight[3] = float[](0.2270270270, 0.3162162162, 0.0702702703); + +void main() +{ + // Texel color fetching from texture sampler + vec3 texelColor = texture(texture0, fragTexCoord).rgb*weight[0]; + + for (int i = 1; i < 3; i++) + { + texelColor += texture(texture0, fragTexCoord + vec2(offset[i])/renderWidth, 0.0).rgb*weight[i]; + texelColor += texture(texture0, fragTexCoord - vec2(offset[i])/renderWidth, 0.0).rgb*weight[i]; + } + + finalColor = vec4(texelColor, 1.0); +} diff --git a/resources/constellation/blur_330.vs b/resources/constellation/blur_330.vs new file mode 100644 index 0000000000..19a71b87e1 --- /dev/null +++ b/resources/constellation/blur_330.vs @@ -0,0 +1,26 @@ +#version 330 + +// Input vertex attributes +in vec3 vertexPosition; +in vec2 vertexTexCoord; +in vec3 vertexNormal; +in vec4 vertexColor; + +// Input uniform values +uniform mat4 mvp; + +// Output vertex attributes (to fragment shader) +out vec2 fragTexCoord; +out vec4 fragColor; + +// NOTE: Add your custom variables here + +void main() +{ + // Send vertex attributes to fragment shader + fragTexCoord = vertexTexCoord; + fragColor = vertexColor; + + // Calculate final vertex position + gl_Position = mvp*vec4(vertexPosition, 1.0); +} diff --git a/resources/constellation/experiments.json b/resources/constellation/experiments.json new file mode 100644 index 0000000000..5df900d509 --- /dev/null +++ b/resources/constellation/experiments.json @@ -0,0 +1 @@ +{"breakout": {"SPS": "643437,2.64265e+06,7.40486e+06,1.99889e+06,1.41699e+06,1.43078e+06,1.43844e+06,1.44579e+06,2.74607e+06,2.73457e+06,2.71885e+06,2.7275e+06,2.7534e+06,1.27706e+06,365584,1.15468e+07,2.28501e+07,2.39674e+07,2.43488e+07,4.13183e+06,4.11514e+06,6.87593e+06,6.68795e+06,1.55171e+07,1.54929e+07,1.50656e+07,454786,474716,478320,485354,1.63195e+07,1.61858e+07,2.05644e+06,2.05564e+06,1.30793e+06,304628,308693,311228,308846,282640,3.96138e+06,2.63764e+06,2.63061e+06,895514,1.64527e+07,1.61652e+07,291712,293565,1.19616e+06,555574,555858,3.64984e+06,2.17772e+07,2.2236e+07,2.23567e+07,4.13003e+06,6.77782e+06,1.4679e+07,2.3084e+06,2.47202e+06,2.74982e+06,4.14008e+06,1.61315e+07,6.21091e+06,424598,1.05566e+06,1.54998e+07,2.14073e+07,2.42256e+07,4.18857e+06,4.80874e+06,4.9543e+06,1.88556e+06,689525,5.08921e+06,1.02071e+06,1.77204e+07,1.5192e+07,1.51101e+07,1.50934e+07,1.51722e+07,1.74529e+06,1.92023e+06,1.96585e+06,2.15531e+06,8.91862e+06,1.12051e+07,3.12358e+06,570614,4.00144e+06,1.60633e+06,4.4108e+06,5.116e+06,5.11158e+06,5.13717e+06,5.09874e+06,7.66821e+06,7.80767e+06,7.86795e+06,7.8893e+06,1.76405e+06,4.6842e+06,3.5377e+06,7.33663e+06,642153,3.14945e+06,3.11245e+06,3.10607e+06,418164,406367,725111,328017,708230,164944,2.15815e+06,1.17736e+06,1.17706e+06,2.133e+07,2.22878e+07,2.24398e+07,4.3398e+06,6.25887e+06,1.09135e+06,5.28452e+06,5.21735e+06,1.23548e+07,1.61287e+07,3.19515e+06,3.21838e+06,3.2142e+06,3.17873e+06,5.55519e+06,5.49793e+06,1.85555e+07,1.63611e+07,1.63032e+07,1.08308e+07,1.0869e+07,503158,536477,539849,496041,4.61949e+06,9.71726e+06,6.94758e+06,6.97606e+06,1.55339e+07,806102,2.03533e+06,3.33279e+06,3.24576e+06,322748,402959,408718,414110,417128,677455,5.09703e+06,5.08611e+06,5.85927e+06,6.16257e+06,652209,5.4843e+06,2.1677e+06,1.09874e+07,1.03867e+07,1.02552e+07,1.02681e+07,1.55662e+06,607772,1.53336e+06,1.08773e+06,2.29641e+07,3.22886e+06,1.30162e+07,5.34693e+06,5.82982e+06,1.13307e+06,674422,676125", "agent_steps": "10.0925,67.7642,7.60218,6.5536,4.1943,20.4472,28.5737,32.5059,5.04627,14.3524,23.8879,33.4234,38.142,10.9445,4.84966,6.02931,27.6999,63.1767,92.5368,17.9241,29.8516,7.60218,21.6269,66.5846,89.6532,8.45414,4.58752,22.1512,30.933,35.1273,69.7303,91.7504,52.4943,59.8999,51.3802,4.06323,11.9276,19.7919,27.5251,31.1951,62.3903,7.70048,22.741,8.32307,70.2546,92.0125,4.84966,14.1558,5.75625,35.9742,40.7634,65.0117,72.4828,93.1922,93.8476,21.758,66.5846,65.8855,7.20896,21.2992,56.492,7.3728,14.9422,63.701,6.81574,10.0925,89.6532,69.9924,21.889,6.16038,18.0879,30.0155,11.0428,20.054,5.89824,8.84736,9.43718,41.2877,64.2253,85.7211,88.8668,5.11181,14.9422,24.8381,64.553,8.38861,63.9631,5.6361,8.65075,33.8166,36.8968,4.52198,13.1727,21.889,30.6053,34.9307,7.73325,22.2167,36.8968,51.5768,8.25754,8.45414,73.8591,74.0557,18.8744,24.0845,56.066,64.0287,8.02816,4.78413,12.0586,7.34003,5.37395,9.69933,7.40557,23.593,54.7881,71.1721,92.4058,93.8476,7.56941,9.24058,20.2506,8.38861,24.576,12.3208,91.7504,14.549,24.1828,33.8166,38.6007,7.30726,21.1681,11.2722,69.4682,91.6193,72.4828,82.5754,7.4711,32.8991,46.0063,6.29146,72.1551,9.96147,63.8321,72.876,89.3911,7.07789,8.9129,6.25869,18.4156,8.58522,15.0733,25.0348,34.9962,39.8459,5.17734,5.96378,17.4981,6.61914,19.1037,4.1943,58.7203,9.33888,8.9129,24.9037,41.4188,57.9338,5.0135,8.12646,8.84736,51.7734,70.2546,30.933,12.5829,7.2745,21.0371,51.3802,7.66771,22.8721", "uptime": "16.7331,26.1605,1.12282,3.43381,3.05184,14.4165,20.0906,22.8194,1.89999,5.29288,8.78931,12.2937,14.024,9.20145,13.5807,0.735154,1.21717,2.72631,3.93215,4.58983,7.54687,1.17036,3.24308,4.25347,5.74484,0.667171,10.2763,48.0238,66.5242,75.2539,4.24922,5.60822,27.8952,31.4936,39.4591,13.5029,39.0966,64.4581,89.3874,101.31,16.979,2.94239,8.66656,9.2844,4.2431,5.56736,16.7397,48.4597,4.8802,64.9197,73.5394,20.5051,3.34,4.27677,4.30608,5.25908,9.89317,4.25339,4.04174,9.9784,22.981,1.85557,0.987785,9.96375,16.2265,9.57872,5.74151,3.36411,0.907049,1.65516,4.29965,6.73441,5.93746,29.2977,1.19521,9.03319,0.656689,2.73763,4.25489,5.6792,5.88654,3.15266,8.48205,13.6753,30.797,1.08702,6.32102,1.89285,14.9542,9.27185,23.6368,1.16782,3.01542,4.72614,6.42538,7.26757,1.10696,3.0471,4.97434,6.94965,4.75919,1.8235,21.7676,10.869,29.4685,7.94612,18.103,20.662,19.7577,12.0334,16.708,22.3943,7.7043,58.7584,3.57674,20.0633,46.5221,3.32513,4.29351,4.35777,1.76893,1.58616,19.3559,1.62348,4.70664,1.04253,5.61223,4.53438,7.54345,10.5394,12.0303,1.35007,3.90412,0.65618,4.24137,5.59592,7.68692,8.61626,15.0075,62.926,87.2809,12.7646,15.235,1.08112,9.62693,10.9642,5.76175,8.89013,4.46551,1.947,5.64558,27,37.229,61.8278,86.0324,97.7342,7.94047,1.23367,3.47801,1.28363,3.40296,6.44732,10.9042,4.50513,0.839378,2.34189,3.94765,5.55874,3.28357,13.7815,6.03041,49.6914,3.0765,10.8115,1.00861,1.54416,3.99876,47.0414,11.5443,34.0199", "epoch": "77,1034,29,50,16,78,109,124,77,219,364.5,510,582,167,37,11.5,105.667,241,353,273.5,455.5,29,82.5,254,342,64.5,17.5,84.5,118,134,266,350,400.5,457,98,15.5,45.5,75.5,105,119,476,117.5,347,63.5,268,351,18.5,54,175.667,274.462,311,248,276.5,355.5,358,83,254,251.333,55,162.5,431,225,28.5,243,52,38.5,342,133.5,83.5,47,138,229,168.5,153,22.5,67.5,36,157.5,245,327,339,39,114,189.5,492.5,32,244,86,16.5,258,281.5,69,201,334,467,533,59,169.5,281.5,393.5,126,64.5,563.5,565,144,367.5,855.5,977,122.5,36.5,92,14,41,18.5,113,180,418,271.5,352.5,358,115.5,141,154.5,64,187.5,23.5,350,222,369,516,589,111.5,323,21.5,265,349.5,276.5,315,28.5,125.5,175.5,24,1101,38,487,556,341,27,34,95.5,281,65.5,57.5,95.5,133.5,152,39.5,91,267,101,291.5,16,112,285,34,95,158,221,76.5,62,67.5,197.5,134,118,48,55.5,160.5,98,58.5,174.5", "env/perf": "0.469624,1,0.0112734,0.22676,0.0346727,0.799082,0.992284,0.997273,0.101522,0.537151,0.967607,0.998246,0.999718,0.479925,0.195564,0.00989548,0.215937,0.419107,0.681392,0.453173,0.862162,0.0316085,0.379794,0.541878,0.957062,0.0069166,0.1064,0.938141,0.998949,0.999985,0.598999,0.975089,0.999832,1,0.999949,0.135838,0.722224,0.982753,0.999014,0.999786,0.999919,0.302552,0.80268,0.337048,0.608457,0.976096,0.276047,0.796627,0.28991,0.99901,0.999993,0.999966,0.655644,0.994667,0.997995,0.555635,0.998923,0.532379,0.230687,0.830848,0.999994,0.261188,0.0203578,0.997049,0.328429,0.528378,0.957062,0.447682,0.0293053,0.069824,0.485056,0.88303,0.439826,0.81041,0.0279265,0.41236,0.00513474,0.325314,0.686921,0.944473,0.963464,0.223381,0.773666,0.970873,0.999997,0.0111403,0.971346,0.105924,0.382121,0.978661,0.999207,0.0203834,0.334623,0.648869,0.975487,0.995776,0.107408,0.432844,0.820524,0.994596,0.323631,0.193921,0.999988,0.999616,0.819863,0.701481,0.999936,0.999953,0.40008,0.194904,0.544108,0.34843,0.263979,0.417816,0.26165,0.868093,0.99998,0.628142,0.992822,0.997995,0.190878,0.194083,0.808691,0.182388,0.509132,0.025487,0.975046,0.348073,0.768592,0.997041,0.999795,0.147179,0.502616,0.00472398,0.594271,0.974425,0.996058,0.999181,0.313687,0.998643,0.999998,0.309117,0.999849,0.0303079,0.996526,0.999323,0.953424,0.296136,0.30402,0.216878,0.64982,0.417367,0.906839,0.998281,0.999952,1,0.263687,0.0439062,0.334916,0.0945765,0.411714,0.0063153,0.999307,0.312503,0.0184347,0.284444,0.510235,0.876339,0.129249,0.373536,0.351898,1,0.462118,0.985861,0.0261059,0.14547,0.413296,0.999849,0.315056,0.977695", "env/score": "405.755,864,9.74021,195.92,29.9572,690.407,857.333,861.643,87.7148,464.098,836.012,862.485,863.757,414.655,168.967,8.54968,186.57,362.108,588.721,391.541,744.908,27.3097,328.142,468.181,826.9,5.97594,91.9299,810.554,863.092,863.987,517.533,842.476,863.855,864,863.956,117.364,624.001,849.099,863.148,863.815,863.93,261.405,693.515,291.21,525.706,843.347,238.505,688.286,250.482,863.145,863.994,863.971,566.475,859.392,862.268,480.068,863.069,459.974,199.313,717.853,863.995,225.666,17.5891,861.451,283.763,456.518,826.9,386.795,25.3198,60.328,419.088,762.938,380.009,700.194,24.1285,356.279,4.43642,281.071,593.499,816.024,832.435,193.002,668.448,838.834,863.997,9.62519,839.244,91.5182,330.153,845.563,863.315,17.6112,289.114,560.623,842.82,860.35,92.8007,373.977,708.933,859.331,279.617,167.547,863.99,863.668,708.362,606.08,863.945,863.959,345.669,168.397,470.109,301.043,228.078,360.993,226.066,750.032,863.982,542.714,857.798,862.268,164.918,167.687,698.709,157.583,439.89,22.0207,842.439,300.735,664.063,861.444,863.823,127.163,434.26,4.08149,513.449,841.902,860.594,863.292,271.025,862.827,863.998,267.077,863.869,26.186,860.999,863.415,823.757,255.862,262.673,187.382,561.445,360.605,783.509,862.515,863.958,864,227.825,37.935,289.368,81.7141,355.721,5.45641,863.401,270.002,15.9276,245.759,440.843,757.157,111.671,322.735,304.039,864,399.268,851.784,22.5555,125.686,357.087,863.87,272.208,844.728", "env/episode_return": "405.755,864,9.74021,195.92,29.9572,690.407,857.333,861.643,87.7148,464.098,836.012,862.485,863.757,414.655,168.967,8.54968,186.57,362.108,588.721,391.541,744.908,27.3097,328.142,468.181,826.9,5.97594,91.9299,810.554,863.092,863.987,517.533,842.476,863.855,864,863.956,117.364,624.001,849.099,863.148,863.815,863.93,261.405,693.515,291.21,525.706,843.347,238.505,688.286,250.482,863.145,863.994,863.971,566.475,859.392,862.268,480.068,863.069,459.974,199.313,717.853,863.995,225.666,17.5891,861.451,283.763,456.518,826.9,386.795,25.3198,60.328,419.088,762.938,380.009,700.194,24.1285,356.279,4.43642,281.071,593.499,816.024,832.435,193.002,668.448,838.834,863.997,9.62519,839.244,91.5182,330.153,845.563,863.315,17.6112,289.114,560.623,842.82,860.35,92.8007,373.977,708.933,859.331,279.617,167.547,863.99,863.668,708.362,606.08,863.945,863.959,345.669,168.397,470.109,301.043,228.078,360.993,226.066,750.032,863.982,542.714,857.798,862.268,164.918,167.687,698.709,157.583,439.89,22.0207,842.439,300.735,664.063,861.444,863.823,127.163,434.26,4.08149,513.449,841.902,860.594,863.292,271.025,862.827,863.998,267.077,863.869,26.186,860.999,863.415,823.757,255.862,262.673,187.382,561.445,360.605,783.509,862.515,863.958,864,227.825,37.935,289.368,81.7141,355.721,5.45641,863.401,270.002,15.9276,245.759,440.843,757.157,111.671,322.735,304.039,864,399.268,851.784,22.5555,125.686,357.087,863.87,272.208,844.728", "env/episode_length": "8693.28,14211.2,1546.36,4495.88,1709.66,13838.2,16527.1,16296.4,2508.33,9523,15811.4,15974.3,14971.4,8891.83,4146.9,1569.63,4247.04,7129.22,12017.2,8083.07,14496.3,2101.55,6693.78,9186.64,16302.1,1322.72,2829.5,15771.2,15154.6,14681.8,10162.9,16513,14536.4,13991.8,14765.5,3340.53,12600.7,16237.4,15344.3,14845.5,14634.5,5668.93,13921.3,6624.5,10324.2,16525.3,5146.37,13625,5565.64,14415.6,14304.8,14692.5,10869.2,16477.9,16386.2,9636.48,14999.3,9050.27,4650.55,14746.2,14247.1,4991.62,1881.67,15371.1,6143.16,9456.84,16302.1,7379.49,1941.34,2070.7,8629.75,15746.1,7911.95,13957.1,1918.61,7370.57,1079.92,6089.75,12298.9,16704.1,16881.1,4555.84,13241.8,16380.5,14021.1,1420.43,16741.4,2637.93,7127.09,16535.4,15453.2,1366.65,6120.36,11235.3,16660.2,16579.8,3075.09,7352.79,13521.4,15801.4,6107.58,3980.05,14586.2,14588.7,14178.7,12357.2,15462.3,14834.6,7586.51,3963.09,9706.16,6653.43,5197.07,7772.74,5171.7,15229.8,15581.6,10398.5,16493.2,16386.2,4274.06,4086.04,14298.4,3850.8,8485.78,2081.23,16515.6,6228.43,12602.4,16119.7,15065.1,3484.87,8834.83,880.875,10082.4,16506.6,16505.6,15310.1,5936.3,15047.5,13800.1,5801.11,15188.4,2311.65,15644,15111.3,16247.2,5720.39,5767.78,4288.68,11381.9,7571.98,14786,14964.1,13930.4,13301.3,5115.9,2279.63,6041.93,2695.72,6815.82,1232.19,14626.2,5872.7,1307.26,5179.7,9022.25,13724,3444.8,7139.33,6683.29,13723.2,8112.12,16437,2070.1,3676.75,7155.95,14488,6266.94,16357.4", "env/n": "139.869,7172,697.891,236.825,682.742,64.3871,63.3871,4021,110.799,13.5448,19.9452,13.9172,5414,64.4713,182.425,1706.68,19117.7,7603,4371,23.4011,14.2857,394.396,93.5556,3598,2154.5,201.535,578.412,63.9706,68.9697,4802,3486,1700,27.2982,6399,6885,484.967,73.7667,64.8,68.4483,4171,6649,68.9868,16.8831,121,3431.33,1647.5,348.111,72.9143,918.733,80.3077,4273,8915,4183.5,1783,10039,76.2909,8747,3563,198.028,32.5463,7904,37.1954,1268.89,10017,140.33,200.803,2154.5,6807.5,43576.5,322.264,51.6813,29.7143,51.5269,34.3267,692.275,86.6439,186.372,3944,1786.67,1324,7901,235,42.12,39.9474,28.8,620.475,6106,145.396,489.844,33.2427,34.15,213.573,37.2707,18.1504,15.4135,4228,158.486,41.0982,21.7143,26.0893,61.7673,247.452,27.5188,7652,35.4,19.1762,17.4713,8645,122.787,217.444,110.033,606.444,159,677.5,80.5973,30.2773,34.1429,4261,1978.5,10039,81.7091,78.3883,31.4314,251.943,68.6452,1078.93,1677.5,9.78231,10.2993,15.2109,3828,95.4423,22.3349,1757.58,3515,1727.5,50.2308,8059,301.446,54.6,60.16,251.532,9497,464.261,25.4604,7076,2212,260.66,254.646,93.0435,19.4225,90.8828,51.0789,53.6579,55.8684,4454,164.551,155.171,39.0113,133.187,37.2165,1115.58,6017,50.8513,572.525,91.2063,34.6349,56.6667,107.387,133.593,70.2692,57.3571,6105,52.5455,696.473,175.933,64.1226,121.815,192.672,31.9138", "perf/rollout": "0.0359422,0.00574112,0.0166916,0.0153764,0.0265294,0.0222017,0.0216488,0.0215535,0.00407218,0.00420363,0.00421001,0.00423365,0.00414395,0.013459,0.0442807,0.0362757,0.356824,0.365072,0.369729,0.00425512,0.00430956,0.0138012,0.0148225,0.373595,0.352149,0.00602134,0.0892388,0.0610234,0.0537897,0.04902,0.373048,0.26501,0.0123586,0.0125196,0.041045,0.0896395,0.0751614,0.064975,0.0715757,0.0602205,0.00748706,0.00600305,0.00599426,0.0136904,0.369901,0.254442,0.0482269,0.0422697,0.142028,0.0704973,0.0473313,0.0242496,0.346643,0.191247,0.033524,0.0162737,0.012259,0.39338,0.0246974,0.0199264,0.0131497,0.00300765,0.0234674,0.0115743,0.0256734,0.0292872,0.353876,0.266302,0.370019,0.0169379,0.0120993,0.0112799,0.00816066,0.0137907,0.0132691,0.0181141,0.00839762,0.232065,0.235785,0.199944,0.160075,0.0226089,0.0147048,0.0140004,0.0113905,0.0206113,0.0137577,0.00844156,0.107848,0.008021,0.0179115,0.00793659,0.00563595,0.00557452,0.00559674,0.00571728,0.00758068,0.00706931,0.00698635,0.00685869,0.00812768,0.0082375,0.0108674,0.00773931,0.0219705,0.00638775,0.00649235,0.00650883,0.024094,0.039983,0.0295278,0.128392,0.0441755,0.176054,0.0071182,0.0122061,0.011444,0.344437,0.210684,0.0733151,0.00424628,0.00552331,0.0130834,0.0083667,0.00869843,0.0237701,0.264693,0.00395793,0.00389155,0.00390939,0.00418448,0.0042384,0.00446423,0.0220793,0.369484,0.265686,0.0139732,0.0140073,0.0808015,0.037907,0.0347551,0.0522944,0.00408125,0.0101563,0.00740737,0.00706267,0.360951,0.0440319,0.0238498,0.00576379,0.00595171,0.032078,0.0511703,0.0376367,0.0316017,0.0280273,0.0455709,0.00500151,0.00491334,0.00475495,0.00413631,0.0584749,0.0228839,0.00498797,0.0106198,0.0117025,0.0120546,0.0121076,0.00952642,0.0417301,0.0178441,0.0430186,0.294067,0.0322013,0.0135708,0.010253,0.0081879,0.0395968,0.021637,0.019768", "perf/eval_gpu": "0.0209057,0.00233021,0.00526857,0.00646257,0.0114809,0.00705462,0.00694557,0.00683161,0.00114782,0.00103918,0.00104301,0.00106689,0.00102524,0.00658677,0.0291494,0.0170974,0.191182,0.18719,0.184896,0.00115904,0.00117181,0.0034718,0.00340215,0.244541,0.227887,0.00218648,0.0601322,0.0380454,0.031622,0.02717,0.239616,0.170575,0.00484174,0.00481588,0.0211191,0.0584922,0.0480499,0.0386189,0.04142,0.0357385,0.00208614,0.00202266,0.00200099,0.00624973,0.237192,0.162587,0.0278669,0.0229231,0.120946,0.0602609,0.0404371,0.00822602,0.191368,0.100354,0.0179887,0.00369265,0.00229375,0.275975,0.0145096,0.0102372,0.00507326,0.00107859,0.00491306,0.00203286,0.0137438,0.0111938,0.226664,0.130902,0.20322,0.00720744,0.00359415,0.003079,0.00375627,0.00655139,0.00282428,0.0096767,0.00505161,0.136225,0.135362,0.113852,0.092245,0.011862,0.00528024,0.00507468,0.00477429,0.0103443,0.00447196,0.00334658,0.0637849,0.00211285,0.00782821,0.00305203,0.00182965,0.0017982,0.00179261,0.00180467,0.00248284,0.00193385,0.00196249,0.00190096,0.00403999,0.00187214,0.00377652,0.00208238,0.0116021,0.00269431,0.00264566,0.00264719,0.0145287,0.0238056,0.0133539,0.0869127,0.0298746,0.14031,0.0029042,0.00451849,0.00408203,0.190573,0.111783,0.0392836,0.000949775,0.0019693,0.00483075,0.00222912,0.00217066,0.00509512,0.17039,0.0012538,0.00126038,0.00126723,0.0013081,0.00122066,0.00123438,0.012312,0.242822,0.173528,0.00347297,0.00343021,0.051013,0.0216856,0.0180053,0.0334386,0.00101398,0.0028903,0.00213167,0.00201118,0.233044,0.0210947,0.00818327,0.00207769,0.00208221,0.0186308,0.035052,0.0221256,0.0166741,0.0149726,0.0311279,0.00200036,0.00195493,0.00162828,0.00109598,0.0192033,0.00756415,0.00156281,0.00280032,0.00273918,0.00269567,0.00285391,0.00432529,0.0267502,0.00959757,0.0210442,0.143005,0.0142707,0.00277446,0.00353716,0.00209171,0.0183988,0.0106377,0.00872639", "perf/eval_env": "0.00668782,0.00166852,0.00750415,0.00401086,0.00836972,0.00845246,0.00784733,0.00787087,0.00189991,0.00216269,0.0023239,0.00231839,0.00230507,0.00211062,0.00441555,0.0123425,0.118178,0.134456,0.140686,0.00198976,0.00191242,0.00765975,0.00818781,0.09077,0.0874549,0.00216092,0.00766828,0.00920107,0.0080099,0.0079226,0.095719,0.0688494,0.00373008,0.00389241,0.0138448,0.00785597,0.00885619,0.00834938,0.00832499,0.00740588,0.00338164,0.00268887,0.00258789,0.00345288,0.0947853,0.0659083,0.00872879,0.00823097,0.0120604,0.00629153,0.00424128,0.00867922,0.121191,0.0692371,0.012188,0.00916035,0.00771737,0.0842254,0.00361707,0.00389373,0.00464233,0.000987086,0.0155142,0.00691964,0.00389738,0.0111112,0.0901194,0.120628,0.117348,0.00519334,0.00574285,0.0058287,0.00216961,0.00396465,0.00782039,0.00385591,0.00232443,0.0700496,0.0731014,0.0623991,0.0504951,0.00476105,0.004928,0.00489116,0.00345315,0.00450049,0.00551651,0.00228473,0.0156098,0.00387733,0.00411847,0.00176954,0.00198572,0.00196102,0.00199805,0.00199726,0.00261487,0.00305918,0.00286974,0.00303934,0.0020608,0.00441921,0.00353867,0.0034977,0.00494833,0.00188905,0.0021529,0.00215459,0.00291485,0.00508964,0.00508289,0.0197483,0.00421521,0.0250643,0.00214074,0.00376439,0.00400002,0.116811,0.0753878,0.0265119,0.00235568,0.00174968,0.00399474,0.00436863,0.00490889,0.0136472,0.0682179,0.00174443,0.00162439,0.00165061,0.00176414,0.00202535,0.00206355,0.00706773,0.0940198,0.0685973,0.00726285,0.00726668,0.00819537,0.00709024,0.00697427,0.00731453,0.00214977,0.00579925,0.00296182,0.00313954,0.0906967,0.00827627,0.00842759,0.00224991,0.00216707,0.00358954,0.0067939,0.00640164,0.00674998,0.00617819,0.00466847,0.00158637,0.00181439,0.00178394,0.00190849,0.0369844,0.0110945,0.00196721,0.00621398,0.00685747,0.00730412,0.00727936,0.00187311,0.00451475,0.00314064,0.00704571,0.130161,0.00789592,0.00821201,0.00385789,0.00424611,0.0114664,0.00375701,0.0039564", "perf/train_misc": "0.00729723,0.000775968,0.00132456,0.00265948,0.0190968,0.0137576,0.0137579,0.0135229,0.002511,0.00251276,0.00251266,0.00250987,0.00251904,0.00195874,0.00772743,0.00219995,0.0517924,0.0471214,0.0471987,0.00111398,0.00111343,0.00319632,0.00319575,0.0280926,0.0262351,0.000139931,0.0147031,0.0109967,0.0109621,0.0110828,0.0278882,0.0204437,0.00215849,0.00214205,0.00763494,0.0294089,0.0211185,0.0212162,0.0212194,0.0209295,0.00278323,0.000953583,0.000953644,0.00492229,0.028606,0.0193388,0.0307745,0.0232584,0.0116449,0.0151238,0.0101973,0.00287008,0.0328776,0.0181248,0.00324141,0.00627438,0.00382771,0.0251135,0.00147077,0.00147156,0.00146867,0.000363267,0.00148142,0.00763699,0.00797708,0.0154668,0.0268409,0.0685537,0.0433081,0.00130644,0.00130588,0.00130522,0.00113892,0.00506128,0.00452292,0.00715968,0.000512238,0.0297452,0.0297628,0.0251027,0.0203759,0.00298369,0.00298914,0.00298246,0.00208361,0.00072595,0.0007288,0.000760522,0.0360086,0.00301415,0.00278759,0.000540641,0.000539778,0.000540641,0.000539418,0.000530368,0.00110868,0.00110874,0.00111003,0.00110899,0.00126126,0.00274642,0.00190146,0.00109779,0.0046823,0.000367423,0.000368732,0.000370688,0.00315795,0.0084623,0.00647289,0.0531034,0.00654955,0.0530984,0.000930245,0.00623414,0.00624425,0.0320142,0.0200459,0.00708966,0.00152705,0.00032573,0.0055676,0.00124002,0.00123789,0.00274341,0.0196127,0.00156517,0.00156593,0.00156531,0.00156259,0.000587363,0.000583828,0.00150702,0.0284318,0.0206664,0.00161683,0.00160982,0.0200523,0.0176087,0.0176445,0.0147546,0.00109146,0.00202809,0.00127911,0.00129414,0.0266854,0.0177051,0.010509,0.000950757,0.000955398,0.00776211,0.0180492,0.0181243,0.0181044,0.0183091,0.00691083,0.000430783,0.000429579,0.000744426,0.000742387,0.0161482,0.00759808,0.000765625,0.00194073,0.00194346,0.00194212,0.0019414,0.00106386,0.00617779,0.00681573,0.00812042,0.0619178,0.00238613,0.000875892,0.00158492,0.0015782,0.0336974,0.00769756,0.00697917", "perf/train_forward": "0.17485,0.0176947,0.0166582,0.0472007,0.194782,0.144929,0.145057,0.14482,0.0162916,0.016304,0.0163065,0.0163054,0.0162918,0.035776,0.353984,0.0223735,0.210909,0.188023,0.184719,0.00974943,0.00975011,0.0202436,0.020267,0.183476,0.173149,0.00165788,0.630702,0.479147,0.479292,0.479474,0.192739,0.13712,0.0483275,0.0483656,0.351609,1.02019,0.75174,0.752294,0.752152,0.751608,0.0220242,0.0171483,0.0171472,0.126853,0.192366,0.131638,1.06922,0.825364,0.462273,0.612803,0.413852,0.0437944,0.227635,0.121446,0.0216934,0.0397609,0.0217375,0.17293,0.0320088,0.0320023,0.0318996,0.00390296,0.00613884,0.0221,0.303727,0.234474,0.1734,0.275971,0.203318,0.0132064,0.0132103,0.0132077,0.0247313,0.169843,0.0329589,0.102664,0.00505265,0.341182,0.340642,0.286957,0.233562,0.0491914,0.0492098,0.0492253,0.0466157,0.0082537,0.00825856,0.0111327,1.04964,0.0210513,0.0600696,0.00586476,0.00583406,0.0058318,0.00583574,0.00585728,0.00780769,0.00781124,0.0078107,0.00781084,0.0278638,0.0161161,0.0232282,0.00814285,0.176362,0.013434,0.0134394,0.0134676,0.135258,0.317464,0.153645,2.00789,0.152841,3.85121,0.021639,0.0919789,0.0919934,0.224707,0.134628,0.0477491,0.00828757,0.00384244,0.100597,0.0144207,0.0144174,0.015405,0.134306,0.0142082,0.0142031,0.01421,0.0141701,0.00604752,0.00604702,0.00829877,0.193364,0.140027,0.00768858,0.00772915,0.505364,0.431805,0.431946,0.570973,0.00769536,0.0136013,0.00975907,0.00973107,0.177724,0.322421,0.0937245,0.0121986,0.0121981,0.365643,0.580512,0.580987,0.581422,0.58196,0.16217,0.00674419,0.00674387,0.00512717,0.00512691,0.444786,0.0639549,0.00858055,0.01037,0.0103673,0.0103681,0.0103728,0.0306032,0.183118,0.0600438,0.187877,0.259416,0.045582,0.00491047,0.0119299,0.0119438,0.38325,0.181025,0.165497", "perf/train": "0.182147,0.0184707,0.0179828,0.0498602,0.213879,0.158687,0.158814,0.158343,0.0188025,0.0188168,0.0188192,0.0188153,0.0188109,0.0377347,0.361712,0.0245734,0.262702,0.235145,0.231918,0.0108634,0.0108635,0.0234399,0.0234627,0.211569,0.199384,0.00179781,0.645405,0.490143,0.490254,0.490556,0.220627,0.157564,0.050486,0.0505076,0.359244,1.0496,0.772858,0.77351,0.773371,0.772537,0.0248074,0.0181019,0.0181008,0.131775,0.220972,0.150977,1.1,0.848623,0.473918,0.627927,0.424049,0.0466645,0.260513,0.139571,0.0249348,0.0460353,0.0255652,0.198044,0.0334796,0.0334739,0.0333683,0.00426623,0.00762026,0.029737,0.311704,0.249941,0.20024,0.344525,0.246626,0.0145129,0.0145162,0.0145129,0.0258703,0.174904,0.0374818,0.109824,0.00556489,0.370927,0.370405,0.312059,0.253938,0.0521751,0.052199,0.0522078,0.0486993,0.00897965,0.00898736,0.0118932,1.08565,0.0240655,0.0628572,0.0064054,0.00637384,0.00637244,0.00637516,0.00638765,0.00891638,0.00891998,0.00892074,0.00891983,0.0291251,0.0188625,0.0251296,0.00924064,0.181044,0.0138014,0.0138081,0.0138383,0.138416,0.325926,0.160118,2.06099,0.159391,3.90431,0.0225692,0.098213,0.0982376,0.256721,0.154674,0.0548388,0.00981461,0.00416817,0.106165,0.0156607,0.0156553,0.0181484,0.153918,0.0157734,0.015769,0.0157754,0.0157327,0.00663488,0.00663085,0.00980579,0.221795,0.160693,0.00930541,0.00933898,0.525416,0.449414,0.449591,0.585728,0.00878682,0.0156294,0.0110382,0.0110252,0.20441,0.340126,0.104234,0.0131493,0.0131535,0.373405,0.598561,0.599111,0.599526,0.600269,0.169081,0.00717497,0.00717345,0.0058716,0.0058693,0.460934,0.071553,0.00934618,0.0123108,0.0123108,0.0123103,0.0123142,0.0316671,0.189296,0.0668595,0.195998,0.321334,0.0479681,0.00578637,0.0135148,0.013522,0.416947,0.188723,0.172476", "util/gpu_percent": "88.4379,97,95.2909,87.1649,98.2903,98.5806,98.6452,97,89.3813,92.6621,93.3288,93.4345,94,92.5438,97.5068,44,95.3333,98,96.5,91.033,86.1099,85.8679,90.537,97.6667,98,32.2456,97.3235,98.7647,99.303,100,98.3333,97.5,97.1754,98,100,98.9667,97.8333,99.3667,97.5517,95,95,86.6579,94.303,97.5161,98,96.5,99.1667,99.8286,98.8,99.5769,100,96,98,96,96,94.3818,93,97,82.6542,91.0648,97,79.9448,69,91,98.6602,97.8947,97.5,98,98,66.8132,86.9341,89.7363,93.6557,98.4554,94.5,96.25,57.5581,98.5,98.6667,99,99,89.1067,95.68,95.9605,98.2,63.678,90,86.8994,93.3438,95,97.9875,51.8779,72.5564,88.8271,89.188,89,68.7798,84.9643,90.5357,90.9821,92.4122,81.1774,96,90,99.4632,92.5041,95.0656,94,97.877,99.3333,95.6284,100,90.8519,100,88.0317,95.916,96.1176,98,97.5,98,78.4136,76.4799,98.2549,94.878,93.0806,92.6591,99,95,94.6599,94.6735,95,74.4423,85.707,70.9474,98.6667,99,86.4231,88,96.25,99.28,98.92,96.5957,89,71.5362,78.6835,39,99,89.4717,88.9231,83.6576,92.5882,99.1172,98.4737,99.1579,99.5526,100,87.9487,77.2171,93.1073,69.861,86.4794,94.8387,98,75.4195,67.7288,89.6032,88.5238,90.5238,94.8067,93.561,91.0923,96.375,98,90.0303,61.5165,72.8365,90.0189,99.4444,99.0948,99.3621", "util/gpu_mem": "6.3604,6.39579,18.8037,6.47721,6.56677,6.56677,6.56677,6.56677,5.32919,5.32919,5.32919,5.32919,5.32919,6.02783,8.63484,8.61856,6.93927,6.93927,6.93927,5.70372,5.70372,5.72815,5.72815,14.9568,14.9553,7.5601,9.95624,10.19,10.19,10.19,19.2828,19.2828,21.0346,21.0346,11.6637,8.96649,9.00123,9.00123,9.00123,9.00123,20.31,5.777,5.777,6.62377,14.2255,14.2147,8.87096,8.87096,7.22755,7.92679,7.92679,7.33212,7.01939,7.01939,7.01939,5.92356,6.24109,14.3503,6.92791,6.94131,6.94131,5.18264,20.4402,6.20853,7.48682,6.33066,15.3853,7.70598,7.06194,5.75257,5.75257,5.75257,5.92356,7.00644,6.85174,5.84756,15.0612,8.36841,8.36841,8.36841,8.36841,6.16912,6.20038,6.20038,6.81103,8.27963,8.29288,5.47575,9.70959,5.71186,6.95759,18.6437,20.0168,20.0168,20.0168,20.0168,5.9317,5.9317,5.9317,5.9317,20.4717,5.46761,6.14339,5.92356,7.21813,22.549,22.549,22.549,7.50604,8.17075,6.79475,10.0362,7.00705,10.3609,6.39579,6.06197,6.06197,7.01939,7.01939,7.01939,5.38619,5.88285,6.38765,6.50164,6.50164,7.12043,14.1416,20.0168,20.0168,20.0168,20.0168,6.10268,6.10268,17.8208,14.4934,14.493,20.6031,20.6031,8.26264,7.52753,7.52753,8.305,5.54088,6.64819,5.79328,5.79328,14.9562,6.94945,6.29809,19.626,19.626,7.99366,7.96463,8.08119,8.08119,8.08119,6.97012,6.17596,6.17596,5.39433,5.39433,4.84067,21.7592,4.91395,6.35508,6.35508,6.35508,6.35508,6.64005,7.16895,20.0852,8.472,7.62662,7.69851,6.64819,5.777,5.777,21.2155,6.79475,6.79475", "util/vram_used_gb": "1.06463,1.07312,4.04956,1.09265,1.11414,1.11414,1.11414,1.11414,0.817261,0.817261,0.817261,0.817261,0.817261,0.984852,1.61023,1.60632,1.72284,1.72284,1.72284,0.907104,0.907104,0.912964,0.912964,3.11218,3.11182,1.35242,1.92721,1.98328,1.98328,1.98328,4.1499,4.1499,4.58472,4.58472,2.33679,1.68979,1.69812,1.69812,1.69812,1.69812,4.41089,0.924683,0.924683,1.12781,2.93675,2.93414,1.66687,1.66687,1.81464,2.03729,2.03729,1.29773,1.74835,1.74835,1.74835,0.959839,1.03601,2.96667,1.20077,1.20398,1.20398,0.782104,4.44214,1.0282,1.33484,1.0575,3.21497,1.96698,1.7619,0.918823,0.918823,0.918823,0.959839,1.2196,1.1825,0.94161,3.15179,2.17792,2.17792,2.17792,2.17792,1.01875,1.02625,1.02625,1.17273,1.52502,1.5282,0.852417,1.86804,0.909058,1.20789,4.01118,4.34058,4.34058,4.34058,4.34058,0.961792,0.961792,0.961792,0.961792,4.44968,0.850464,1.01257,0.959839,1.27039,4.948,4.948,4.948,1.33945,1.4989,1.16882,1.94638,1.21975,2.02429,1.07312,0.993042,0.993042,1.74835,1.74835,1.74835,0.830933,0.950073,1.07117,1.09851,1.09851,1.24695,2.91663,4.34058,4.34058,4.34058,4.34058,1.00281,1.00281,3.81378,3.00102,3.00092,4.4812,4.4812,1.52094,1.3446,1.3446,1.53111,0.868042,1.13367,0.928589,0.928589,3.11203,1.20593,1.04968,4.24683,4.24683,1.45642,1.44946,1.47742,1.47742,1.47742,1.21089,1.02039,1.02039,0.832886,0.832886,0.700073,4.75854,0.717651,1.06335,1.06335,1.06335,1.06335,1.13171,1.25859,4.35698,1.57117,1.94171,1.38562,1.13367,0.924683,0.924683,4.62811,1.16882,1.16882", "util/vram_total_gb": "23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,31.356,31.356,31.356,23.5272,23.5272,23.5272,23.5272,23.5126,23.5126,23.5272,23.5272,23.5272,23.5272,23.5272,23.5126,23.5126,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5126,23.5126,23.5272,23.5272,31.356,31.356,31.356,23.5272,31.356,31.356,31.356,23.5272,23.5272,23.5126,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5126,31.356,31.356,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,31.356,31.356,31.356,31.356,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,31.356,31.356,31.356,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5126,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5126,23.5126,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5126,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,31.356,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272", "util/cpu_mem_gb": "1.21146,1.15289,1.0948,1.17621,1.2154,1.2154,1.2154,1.2154,1.13575,1.13575,1.13575,1.13575,1.13575,1.17002,1.37356,1.23147,1.03447,1.03447,1.03447,1.13871,1.13918,1.15613,1.15622,0.902958,0.903006,1.13787,1.3788,1.37881,1.37881,1.37881,0.901627,0.901665,1.10269,1.10269,1.25027,1.37829,1.37829,1.37829,1.37829,1.37829,1.07029,1.13832,1.13849,1.17408,0.901747,0.901789,1.37851,1.37851,1.04762,1.21298,1.21299,1.22996,1.06892,1.06892,1.06892,1.1625,1.16356,0.901766,1.18391,1.18391,1.18439,1.13628,1.09838,1.1637,1.24713,1.20321,0.903183,1.0539,1.03618,1.15342,1.15342,1.15377,1.16032,1.18219,1.16271,1.17648,1.0708,1.08419,1.08419,1.08419,1.08419,1.19336,1.19336,1.19336,1.18524,1.18564,1.18613,1.1605,1.34753,1.1472,1.22639,1.06504,1.06516,1.06553,1.06553,1.06553,1.14455,1.14455,1.14455,1.14477,1.07004,1.14242,1.17626,1.15117,1.2325,1.07408,1.07475,1.07475,1.24601,1.34578,1.2467,1.41724,1.24587,1.37923,1.14886,1.17566,1.17566,1.04582,1.04582,1.04582,1.13303,1.1408,1.16526,1.15376,1.15376,1.1807,0.901628,1.05382,1.05413,1.05431,1.05431,1.13403,1.13403,1.11481,0.903433,0.903471,1.07853,1.07853,1.37833,1.23293,1.23293,1.26804,1.1365,1.15865,1.14817,1.14824,0.901686,1.26668,1.17675,1.0746,1.0746,1.2649,1.25052,1.25052,1.25052,1.25052,1.24719,1.14545,1.14545,1.13174,1.13175,1.15591,1.13663,1.13112,1.15498,1.15541,1.15541,1.15541,1.18321,1.26606,1.08473,1.34502,1.05409,1.24976,1.15823,1.14909,1.14909,1.1559,1.24784,1.24784", "wandb": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,1,1,1,1,0,0,1,1,1,1,1,0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,1,1,0,0,0,1,0,0,0,1,1,0,1,1,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,0,1,1,1,1,1,1,1,0,0,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1", "rank": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "world_size": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "gpu_id": "2,3,0,5,1,1,1,1,1,1,1,1,1,3,2,5,0,0,0,1,1,1,1,0,0,2,3,3,3,3,0,0,0,0,3,1,1,1,1,1,0,4,4,5,0,0,5,5,0,0,0,5,0,0,0,3,4,0,3,3,3,2,0,4,5,4,0,0,0,5,5,5,2,2,5,5,0,0,0,0,0,2,2,2,5,3,3,5,2,4,1,0,0,0,0,0,3,3,3,3,0,4,4,1,3,0,0,0,3,3,1,2,3,1,2,1,1,0,0,0,4,4,1,4,4,1,0,0,0,0,0,3,3,0,0,0,0,0,3,1,1,4,3,3,3,3,0,4,2,0,0,2,3,3,3,3,5,4,4,3,3,1,0,4,2,2,2,2,3,5,0,1,0,3,1,1,1,0,4,4", "profile": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "checkpoint_interval": "200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200", "eval_episodes": "10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000", "cudagraphs": "10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10", "seed": "73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73", "vec/total_agents": "1024,2048,4096,2048,2048,2048,2048,2048,4096,4096,4096,4096,4096,1024,512,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,1024,1024,1024,1024,4096,4096,2048,2048,4096,1024,1024,1024,1024,1024,4096,2048,2048,2048,4096,4096,1024,1024,512,512,512,2048,4096,4096,4096,4096,8192,4096,2048,2048,2048,2048,8192,16384,1024,2048,4096,8192,4096,2048,2048,2048,1024,2048,8192,2048,8192,4096,4096,4096,4096,2048,2048,2048,2048,4096,4096,1024,2048,4096,1024,2048,2048,2048,2048,2048,4096,4096,4096,4096,2048,4096,2048,4096,1024,2048,2048,2048,512,512,1024,2048,1024,2048,2048,2048,2048,4096,4096,4096,4096,2048,2048,4096,4096,8192,4096,4096,4096,4096,4096,4096,4096,8192,4096,4096,4096,4096,1024,2048,2048,2048,4096,8192,4096,4096,4096,2048,4096,2048,2048,1024,2048,2048,2048,2048,1024,2048,2048,4096,4096,1024,4096,1024,8192,8192,8192,8192,1024,1024,2048,1024,8192,2048,8192,4096,4096,4096,1024,1024", "vec/num_buffers": "6.9619,8,7.33793,8,8,8,8,8,8,8,8,8,8,8,7.70651,8,8,8,8,8,8,6.94,6.94,8,8,7.91997,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,6.37246,6.37246,8,8,8,8,8,4.62746,4.64117,4.64117,8,8,8,8,7.67276,8,8,8,8,8,7.05975,7.41365,8,8,6.40843,8,8,8,6.88454,6.88454,6.88454,6.38066,8,8,7.20425,7.83715,8,8,8,8,8,8,8,8,8,8,6.78484,8,8,8,8,8,8,8,8,8,8,8,8,8,7.98712,8,8,7.09408,8,8,8,8,7.19244,8,8,8,6.75812,8,8,8,8,8,8,8,7.56954,8,8,8,7.3001,8,8,8,8,8,7.68473,7.68473,8,8,8,8,8,8,8,8,8,8,7.39626,8,8,8,8,8,7.95309,7.95309,8,8,8,8,8,8,7.02817,7.02817,7.67015,7.67015,1.28448,8,6.5894,7.82119,7.82119,7.82119,7.82119,8,8,8,8,8,8,7.5206,8,8,8,8,8", "vec/num_threads": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5.77483,5.77483,5.77483,1,1,1,1,8,8,1,1,1,1,1,8,8,1,1,1,1,1,1,1,1,1,1,1,1,8,8,1,1,1.19342,1,1,1,8,8,8,1,1,8,1,1,1,1,1,1,1,1,8,6.63658,9.19386,1,1,1,1,1,1,1,1,6.08878,6.08878,6.08878,6.08878,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,8,8,8,1,1,1,1,1,1,8,1,1,1,1,1,1,1,8,8,1,1,1,1,1,1,1,1,1,1,8,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,9.37281,1,1,1,1,1,1,1", "env/num_agents": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "env/frameskip": "5,3,4,5,4,4,4,4,4,4,4,4,4,4,3,5,4,4,4,4,4,3,3,4,4,2,4,4,4,4,4,4,3,3,4,4,4,4,4,4,3,4,4,4,4,4,4,4,4,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,5,4,4,4,4,4,5,4,1,3,3,3,3,5,5,5,3,3,3,4,4,4,4,4,4,4,4,4,3,3,3,3,4,5,3,3,4,4,4,4,8,4,5,5,4,6,5,4,4,4,4,4,5,3,4,5,5,4,4,3,3,3,3,4,4,3,4,4,3,3,4,3,3,4,4,4,3,3,4,4,5,4,4,3,3,3,3,3,4,4,4,4,4,5,3,7,3,3,3,3,4,4,3,3,4,3,5,4,4,3,4,4", "env/width": "576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576,576", "env/height": "330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330,330", "env/initial_paddle_width": "62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62", "env/paddle_width": "62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62,62", "env/paddle_height": "8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8", "env/ball_width": "32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32", "env/ball_height": "32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32", "env/brick_width": "32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32", "env/brick_height": "12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12", "env/brick_rows": "6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6", "env/brick_cols": "18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18", "env/initial_ball_speed": "256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256", "env/max_ball_speed": "448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448,448", "env/paddle_speed": "620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620,620", "env/continuous": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "policy/hidden_size": "256,256,64,256,256,256,256,256,128,128,128,128,128,256,512,64,32,32,32,128,128,64,64,64,64,128,512,512,512,512,64,64,256,256,512,512,512,512,512,512,128,256,256,512,64,64,512,512,256,256,256,128,64,64,64,128,64,64,256,256,256,64,64,64,512,256,64,32,64,128,128,128,256,512,128,128,32,128,128,128,128,128,128,128,256,64,64,128,512,128,256,128,128,128,128,128,128,128,128,128,256,128,128,128,512,256,256,256,512,512,256,512,256,1024,256,256,256,64,64,64,128,128,512,128,128,32,64,256,256,256,256,128,128,32,64,64,128,128,256,512,512,512,128,64,128,128,64,128,128,64,64,512,512,512,512,512,256,128,128,128,128,32,128,128,64,64,64,64,256,256,128,256,32,128,64,64,64,256,256,256", "policy/num_layers": "4.80058,4.50696,4.92467,3.06293,2.81646,2.81646,2.81646,2.81646,3.2127,3.2127,3.2127,3.2127,3.2127,3.54584,5.65175,3.23181,1.69005,1.69005,1.69005,4.14909,4.14909,2.51426,2.51426,2,2,2.73295,4.7626,4.7626,4.7626,4.7626,2,2,4.74518,4.74518,4.42431,4.32906,4.32906,4.32906,4.32906,4.32906,3.8876,3.79149,3.79149,3.60679,2,2,4.27107,4.27107,8,8,8,3.36081,2,2,2,2.50891,4.58148,2,4.70568,4.70568,4.70568,4.12691,3.23824,4.35812,4.61727,3.77175,2,2.05811,1.85575,2.97881,2.97881,2.97881,3.93671,4.87151,4.60167,4.60223,3.62587,2.61463,2.61463,2.61463,2.61463,5.41349,5.41349,5.41349,4.04635,4.07281,4.07281,3.92034,3.76126,3.95849,3.50803,3.83802,3.83802,3.83802,3.83802,3.83802,2.92478,2.92478,2.92478,2.92478,4.02616,2.59838,3.71262,3.40855,4.44275,5.37536,5.37536,5.37536,4.39555,4.15525,4.06573,5.83444,4.29263,4.29099,4.06442,3.48627,3.48627,2,2,2,2.81616,3.39175,2.66835,4.04773,4.04773,3.33715,2,3.35947,3.35947,3.35947,3.35947,4.36108,4.36108,4.01155,2,2,1.81061,1.81061,4.43557,3.66415,3.66415,5.28692,3.01273,4.14819,3.178,3.178,2,5.04862,3.51724,4.17395,4.17395,5.69546,4.40118,4.40118,4.40118,4.40118,4.53843,4.12623,4.12623,3.994,3.994,6.84741,2.3905,2.36247,3.137,3.137,3.137,3.137,4.4575,5.5815,2.91398,3.22599,2.48882,4.45463,4.69841,3.08752,3.08752,3.32665,4.11284,4.11284", "policy/expansion_factor": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "legacy/torch_deterministic": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "legacy/cpu_offload": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "legacy/compile": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "legacy/compile_fullgraph": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "train/gpus": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "train/seed": "42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42", "train/total_timesteps": "79.8425,67.7749,58.1523,51.3094,32.6313,32.6313,32.6313,32.6313,38.1681,38.1681,38.1681,38.1681,38.1681,86.9901,38.159,45.6541,131.932,131.932,131.932,47.6607,47.6607,57.1615,57.1615,94,94,63.1645,35.2556,35.2556,35.2556,35.2556,94,94,60.0055,60.0055,51.7051,31.4254,31.4254,31.4254,31.4254,31.4254,62.4091,60.5358,60.5358,65.6453,94,94,37.0385,37.0385,43.2259,40.8194,40.8194,65.196,94,94,94,57.6508,66.5961,94,56.5781,56.5781,56.5781,57.9317,113.985,63.8769,53.7574,79.2917,94,150.205,117.691,47.9128,47.9128,47.9128,87.7041,53.2425,43.9613,69.7568,59.8319,88.8883,88.8883,88.8883,88.8883,39.5944,39.5944,39.5944,73.6715,64.0718,64.0718,44.562,65.6653,53.9788,42.1125,34.9532,34.9532,34.9532,34.9532,34.9532,58.8672,58.8672,58.8672,58.8672,65.0035,65.9747,84.2816,74.0926,50.0966,64.071,64.071,64.071,63.9466,37.3914,96.0277,56.9491,42.3774,75.2825,58.3331,62.5714,62.5714,94,94,94,58.9422,72.5741,53.6342,65.3917,65.3917,93.8506,94,38.6272,38.6272,38.6272,38.6272,56.4218,56.4218,83.2542,94,94,82.5927,82.5927,58.0027,52.5432,52.5432,48.8845,72.2136,74.7324,72.9656,72.9656,94,54.8938,69.4245,49.01,49.01,67.3002,40.052,40.052,40.052,40.052,40.7364,46.5332,46.5332,50.8025,50.8025,32.4353,59.0354,74.2832,66.0854,66.0854,66.0854,66.0854,39.4291,64.4113,68.9017,59.2421,142.564,35.3528,96.8633,55.7786,55.7786,58.3999,60.8737,60.8737", "train/learning_rate": "0.0105116,0.0252635,0.0482472,0.0267114,0.00748947,0.00748947,0.00748947,0.00748947,0.00939502,0.00939502,0.00939502,0.00939502,0.00939502,0.00986884,0.0240499,0.1,0.0580381,0.0580381,0.0580381,0.0120847,0.0120847,0.0303388,0.0303388,0.1,0.1,0.1,0.0149278,0.0149278,0.0149278,0.0149278,0.1,0.1,0.0151674,0.0151674,0.0281555,0.0134168,0.0134168,0.0134168,0.0134168,0.0134168,0.0206965,0.0206328,0.0206328,0.0240837,0.1,0.1,0.00870803,0.00870803,0.00846751,0.0100881,0.0100881,0.0465997,0.1,0.1,0.1,0.0216083,0.0320278,0.1,0.0149757,0.0149757,0.0149757,0.0159827,0.1,0.0242579,0.0296195,0.00656835,0.1,0.1,0.061713,0.0238972,0.0238972,0.0238972,0.0141285,0.0211239,0.0271535,0.0122089,0.1,0.0168292,0.0168292,0.0168292,0.0168292,0.0102546,0.0102546,0.0102546,0.0297699,0.1,0.1,0.0136386,0.0207517,0.00897806,0.0203087,0.0125341,0.0125341,0.0125341,0.0125341,0.0125341,0.0247848,0.0247848,0.0247848,0.0247848,0.0238356,0.01576,0.0156935,0.0167842,0.0143757,0.0131697,0.0131697,0.0131697,0.00447966,0.0112398,0.0148014,0.00905468,0.0302056,0.012753,0.0169202,0.00716372,0.00716372,0.1,0.1,0.1,0.053738,0.0235945,0.0101617,0.0175038,0.0175038,0.1,0.1,0.00877027,0.00877027,0.00877027,0.00877027,0.0275707,0.0275707,0.1,0.1,0.1,0.0583695,0.0583695,0.0178882,0.013007,0.013007,0.0308766,0.0262848,0.1,0.0143931,0.0143931,0.1,0.0196376,0.0312113,0.0117158,0.0117158,0.0181477,0.00865108,0.00865108,0.00865108,0.00865108,0.00919533,0.0309494,0.0309494,0.0237121,0.0237121,0.00125875,0.0467703,0.00694832,0.0245047,0.0245047,0.0245047,0.0245047,0.0258571,0.0115076,0.0247078,0.0225418,0.0637113,0.0181129,0.0826739,0.0489043,0.0489043,0.0190949,0.00641435,0.00641435", "train/anneal_lr": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "train/min_lr_ratio": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "train/gamma": "0.975913,0.99377,0.991502,0.992905,0.983403,0.983403,0.983403,0.983403,0.977384,0.977384,0.977384,0.977384,0.977384,0.974686,0.994316,0.978903,0.990316,0.990316,0.990316,0.973737,0.973737,0.981466,0.981466,0.972125,0.972125,0.988794,0.971664,0.971664,0.971664,0.971664,0.972125,0.972125,0.99208,0.99208,0.994947,0.990019,0.990019,0.990019,0.990019,0.990019,0.996919,0.989353,0.989353,0.992086,0.972125,0.972125,0.989255,0.989255,0.979789,0.97119,0.97119,0.981101,0.972125,0.972125,0.972125,0.9592,0.976437,0.972125,0.980149,0.980149,0.980149,0.986057,0.984855,0.989363,0.995374,0.995179,0.972125,0.98526,0.900056,0.979481,0.979481,0.979481,0.990617,0.987238,0.984545,0.988029,0.920817,0.991908,0.991908,0.991908,0.991908,0.987647,0.987647,0.987647,0.991031,0.968669,0.968669,0.99268,0.986708,0.976528,0.987328,0.972811,0.972811,0.972811,0.972811,0.972811,0.991199,0.991199,0.991199,0.991199,0.989525,0.983037,0.989297,0.962929,0.993597,0.992224,0.992224,0.992224,0.922709,0.991693,0.994571,0.994927,0.983085,0.993979,0.973797,0.979891,0.979891,0.972125,0.972125,0.972125,0.984792,0.982306,0.982603,0.987592,0.987592,0.950994,0.972125,0.980758,0.980758,0.980758,0.980758,0.992,0.992,0.974512,0.972125,0.972125,0.959455,0.959455,0.996047,0.994416,0.994416,0.995115,0.950367,0.991442,0.982973,0.982973,0.972125,0.987921,0.968664,0.970723,0.970723,0.98191,0.988933,0.988933,0.988933,0.988933,0.991473,0.972375,0.972375,0.994674,0.994674,0.971954,0.981502,0.98782,0.966542,0.966542,0.966542,0.966542,0.964926,0.985618,0.994586,0.977478,0.894484,0.986707,0.980416,0.977031,0.977031,0.987164,0.985528,0.985528", "train/gae_lambda": "0.299522,0.700454,0.966839,0.724739,0.776715,0.776715,0.776715,0.776715,0.654132,0.654132,0.654132,0.654132,0.654132,0.752888,0.631933,0.970319,0.964136,0.964136,0.964136,0.274851,0.274851,0.791462,0.791462,0.948722,0.948722,0.960627,0.818201,0.818201,0.818201,0.818201,0.948722,0.948722,0.886719,0.886719,0.745336,0.824489,0.824489,0.824489,0.824489,0.824489,0.817517,0.702322,0.702322,0.617058,0.948722,0.948722,0.867458,0.867458,0.950564,0.951092,0.951092,0.675803,0.948722,0.948722,0.948722,0.824018,0.73071,0.948722,0.795634,0.795634,0.795634,0.799056,0.895258,0.800914,0.513907,0.530815,0.948722,0.933756,0.984645,0.790664,0.790664,0.790664,0.74043,0.693455,0.834543,0.851624,0.979073,0.976703,0.976703,0.976703,0.976703,0.769404,0.769404,0.769404,0.672477,0.960169,0.960169,0.841773,0.788588,0.780438,0.832387,0.850721,0.850721,0.850721,0.850721,0.850721,0.904661,0.904661,0.904661,0.904661,0.753878,0.833485,0.832336,0.875389,0.73318,0.809073,0.809073,0.809073,0.699457,0.819764,0.740656,0.745035,0.601054,0.510686,0.887791,0.768117,0.768117,0.948722,0.948722,0.948722,0.919747,0.944527,0.838879,0.805337,0.805337,0.899522,0.948722,0.89531,0.89531,0.89531,0.89531,0.80164,0.80164,0.97897,0.948722,0.948722,0.882893,0.882893,0.770064,0.782558,0.782558,0.796238,0.865094,0.893536,0.877519,0.877519,0.948722,0.598328,0.798218,0.847281,0.847281,0.683458,0.707321,0.707321,0.707321,0.707321,0.880069,0.834152,0.834152,0.915208,0.915208,0.825679,0.721228,0.911316,0.827736,0.827736,0.827736,0.827736,0.782676,0.734197,0.72433,0.788551,0.949919,0.76705,0.831485,0.812818,0.812818,0.87479,0.626624,0.626624", "train/replay_ratio": "3.52176,1.97426,2.71366,2.76662,3.03793,3.03793,3.03793,3.03793,2.35194,2.35194,2.35194,2.35194,2.35194,2.78507,2.46025,1.18067,1.90278,1.90278,1.90278,1.92181,1.92181,2.2458,2.2458,1.42421,1.42421,0.579906,3.83893,3.83893,3.83893,3.83893,1.42421,1.42421,2.30344,2.30344,2.39517,3.72967,3.72967,3.72967,3.72967,3.72967,2.41883,2.33266,2.33266,2.67601,1.42421,1.42421,4,4,1.26645,1.55175,1.55175,2.26549,1.42421,1.42421,1.42421,2.41458,1.83171,1.42421,1.53079,1.53079,1.53079,1.90787,0.25,2.11495,3.70539,2.88884,1.42421,2.00288,1.4738,2.46076,2.46076,2.46076,2.93807,2.76573,2.13981,4,1.64941,1.905,1.905,1.905,1.905,1.65534,1.65534,1.65534,2.14182,1.38584,1.38584,1.9256,4,1.34169,2.83395,1.33388,1.33388,1.33388,1.33388,1.33388,1.76576,1.76576,1.76576,1.76576,2.92101,2.37404,2.03902,0.87609,2.44922,1.54017,1.54017,1.54017,3.62095,2.77699,3.21735,2.84003,3.02299,3.03143,2.27609,3.48021,3.48021,1.42421,1.42421,1.42421,2.69316,1.38564,3.07294,1.9874,1.9874,1.876,1.42421,1.39471,1.39471,1.39471,1.39471,1.8662,1.8662,0.793541,1.42421,1.42421,1.10948,1.10948,2.9665,3.85874,3.85874,2.55626,1.90192,1.82298,1.09114,1.09114,1.42421,3.17162,4,1.29517,1.29517,4,4,4,4,4,3.0754,1.97314,1.97314,1.37232,1.37232,2.16592,2.33325,2.78786,1.69534,1.69534,1.69534,1.69534,2.97039,2.93654,4,2.80937,1.66468,1.93707,0.671554,2.50555,2.50555,2.71906,3.60326,3.60326", "train/clip_coef": "0.437293,0.323424,0.952953,0.333223,0.673234,0.673234,0.673234,0.673234,0.297839,0.297839,0.297839,0.297839,0.297839,0.619752,0.421908,0.644491,0.630715,0.630715,0.630715,0.188592,0.188592,0.323486,0.323486,0.67465,0.67465,0.757799,0.358278,0.358278,0.358278,0.358278,0.67465,0.67465,0.599813,0.599813,0.267117,0.489387,0.489387,0.489387,0.489387,0.489387,0.540381,0.213168,0.213168,0.560335,0.67465,0.67465,0.214161,0.214161,0.630071,0.50936,0.50936,0.599214,0.67465,0.67465,0.67465,0.273841,0.390375,0.67465,0.434117,0.434117,0.434117,0.484634,1,0.223188,0.636457,0.203577,0.67465,0.509771,0.561299,0.24269,0.24269,0.24269,0.462618,0.439369,0.444198,0.31007,0.763867,0.50795,0.50795,0.50795,0.50795,0.315203,0.315203,0.315203,0.390186,0.708242,0.708242,0.76422,0.348353,0.200207,0.399296,0.337247,0.337247,0.337247,0.337247,0.337247,0.465886,0.465886,0.465886,0.465886,0.40664,0.532825,0.654384,0.476811,0.629859,0.495763,0.495763,0.495763,0.247589,0.144141,0.431143,0.6711,0.527356,0.373962,0.553791,0.814461,0.814461,0.67465,0.67465,0.67465,0.240581,0.492546,0.625371,0.559309,0.559309,0.778058,0.67465,0.451649,0.451649,0.451649,0.451649,0.267177,0.267177,0.954372,0.67465,0.67465,0.526015,0.526015,0.350036,0.478297,0.478297,0.296539,0.345002,0.928127,0.347051,0.347051,0.67465,0.476643,0.306638,0.141863,0.141863,0.413578,0.213093,0.213093,0.213093,0.213093,0.461104,0.468189,0.468189,0.405963,0.405963,0.554247,0.402333,0.554804,0.448011,0.448011,0.448011,0.448011,0.428473,0.541484,0.277928,0.397288,0.526497,0.655547,0.853493,0.69438,0.69438,0.438488,0.403626,0.403626", "train/vf_coef": "4.63007,5,2.07331,5,4.59448,4.59448,4.59448,4.59448,5,5,5,5,5,4.16197,5,1.62757,1.23702,1.23702,1.23702,5,5,3.57291,3.57291,1.21955,1.21955,1.7977,5,5,5,5,1.21955,1.21955,4.5936,4.5936,4.04835,4.74257,4.74257,4.74257,4.74257,4.74257,5,5,5,3.7863,1.21955,1.21955,5,5,4.10912,5,5,5,1.21955,1.21955,1.21955,4.40667,4.76589,1.21955,4.25864,4.25864,4.25864,4.87861,3.03228,3.81468,5,4.85905,1.21955,1.94509,2.36068,5,5,5,5,3.74043,3.08885,5,2.22919,2.35923,2.35923,2.35923,2.35923,5,5,5,5,3.23781,3.23781,5,4.94824,4.95029,3.482,5,5,5,5,5,3.79816,3.79816,3.79816,3.79816,5,4.53937,2.48936,3.58172,5,5,5,5,5,4.7794,4.42122,4.90812,4.0029,4.4982,4.68132,3.4299,3.4299,1.21955,1.21955,1.21955,4.59245,3.60183,2.95138,3.98942,3.98942,3.59256,1.21955,5,5,5,5,3.22599,3.22599,2.40986,1.21955,1.21955,4.73335,4.73335,4.75341,4.94771,4.94771,5,5,3.4769,4.39137,4.39137,1.21955,3.23361,5,4.81405,4.81405,3.67407,4.15107,4.15107,4.15107,4.15107,5,5,5,4.09813,4.09813,1.67673,4.22083,4.08441,4.54681,4.54681,4.54681,4.54681,4.25874,4.89385,5,4.47354,1.82294,2.74504,2.01665,2.76679,2.76679,5,5,5", "train/vf_clip_coef": "2.65326,2.82132,3.58128,1.81136,2.48481,2.48481,2.48481,2.48481,1.96609,1.96609,1.96609,1.96609,1.96609,2.45648,1.99751,0.895386,1.12108,1.12108,1.12108,2.06528,2.06528,0.696956,0.696956,1.22917,1.22917,0.470743,2.8635,2.8635,2.8635,2.8635,1.22917,1.22917,3.15947,3.15947,1.83727,2.58935,2.58935,2.58935,2.58935,2.58935,3.91452,2.37072,2.37072,1.46303,1.22917,1.22917,3.70247,3.70247,3.48128,3.56147,3.56147,3.68383,1.22917,1.22917,1.22917,2.81672,1.16608,1.22917,2.71346,2.71346,2.71346,1.40688,3.07716,1.16668,2.14732,3.47439,1.22917,0.857951,0.167656,3.63469,3.63469,3.63469,3.13064,3.38887,1.06562,2.6389,2.13867,0.01,0.01,0.01,0.01,2.21148,2.21148,2.21148,2.72346,3.61542,3.61542,2.21371,4.15696,1.76018,2.5641,3.5677,3.5677,3.5677,3.5677,3.5677,1.64649,1.64649,1.64649,1.64649,1.80682,2.60743,4.72381,1.91056,2.38254,2.0255,2.0255,2.0255,1.28405,1.64782,1.7318,1.0491,1.6127,0.980613,2.05467,2.3245,2.3245,1.22917,1.22917,1.22917,1.72854,1.3466,1.17436,3.625,3.625,4.44096,1.22917,2.77585,2.77585,2.77585,2.77585,1.5832,1.5832,2.94303,1.22917,1.22917,0.818,0.818,1.12067,4.03079,4.03079,1.78341,3.63918,3.34963,0.864596,0.864596,1.22917,2.95799,2.3163,3.25994,3.25994,3.28889,3.5491,3.5491,3.5491,3.5491,4.38919,2.06504,2.06504,2.76089,2.76089,1.34351,0.590069,1.47068,2.00594,2.00594,2.00594,2.00594,2.7275,1.62961,2.94134,3.19032,0.853989,0.793239,3.4148,1.46812,1.46812,2.42157,3.99634,3.99634", "train/max_grad_norm": "0.1,1.82789,2.05606,2.16045,0.1,0.1,0.1,0.1,0.868629,0.868629,0.868629,0.868629,0.868629,0.283153,0.636522,2.5908,1.73362,1.73362,1.73362,1.54538,1.54538,0.1,0.1,1.81092,1.81092,2.06601,0.829388,0.829388,0.829388,0.829388,1.81092,1.81092,0.707283,0.707283,2.45253,1.00337,1.00337,1.00337,1.00337,1.00337,0.802126,0.434394,0.434394,0.810802,1.81092,1.81092,0.250352,0.250352,2.7831,0.871875,0.871875,0.855934,1.81092,1.81092,1.81092,0.58955,0.981444,1.81092,0.636908,0.636908,0.636908,0.1,2.52235,0.696415,1.20258,0.247123,1.81092,1.61381,2.50687,1.55444,1.55444,1.55444,0.117655,0.771962,0.182469,0.181718,0.69403,1.33668,1.33668,1.33668,1.33668,1.55277,1.55277,1.55277,1.26473,3.19534,3.19534,0.1,1.89521,0.550384,0.1,1.20442,1.20442,1.20442,1.20442,1.20442,0.505415,0.505415,0.505415,0.505415,0.349531,0.215116,3.31007,1.4603,0.625204,0.1,0.1,0.1,0.1,0.1,1.03726,1.16994,0.292446,0.540649,0.1,0.1,0.1,1.81092,1.81092,1.81092,0.1,0.1,0.270509,2.24553,2.24553,3.53597,1.81092,0.180271,0.180271,0.180271,0.180271,0.30991,0.30991,2.4611,1.81092,1.81092,0.650503,0.650503,0.409293,0.219308,0.219308,1.19173,1.46034,2.17665,0.957136,0.957136,1.81092,0.1,0.484193,1.73415,1.73415,0.1,0.105856,0.105856,0.105856,0.105856,1.50951,0.129777,0.129777,0.129644,0.129644,0.951355,1.26128,0.129532,0.465633,0.465633,0.465633,0.465633,0.119836,0.288439,1.22078,0.269198,1.33785,1.0602,2.97725,0.1,0.1,1.51474,1.28722,1.28722", "train/ent_coef": "0.00339201,0.000401129,0.00196533,0.000805653,0.0201586,0.0201586,0.0201586,0.0201586,0.000196017,0.000196017,0.000196017,0.000196017,0.000196017,0.010044,0.0172702,0.000956205,0.034914,0.034914,0.034914,0.000678726,0.000678726,0.00128156,0.00128156,0.00332407,0.00332407,0.00189448,0.00720581,0.00720581,0.00720581,0.00720581,0.00332407,0.00332407,0.00793368,0.00793368,0.00699874,0.00101481,0.00101481,0.00101481,0.00101481,0.00101481,0.00734064,0.000907068,0.000907068,0.00211072,0.00332407,0.00332407,0.00394741,0.00394741,8.1384e-05,8.69313e-05,8.69313e-05,0.00700638,0.00332407,0.00332407,0.00332407,0.00124677,0.0594954,0.00332407,0.000513653,0.000513653,0.000513653,0.0538421,0.000970807,0.0314715,8.82963e-05,0.000158581,0.00332407,0.0110032,0.00759812,0.000212532,0.000212532,0.000212532,0.00509761,0.00930532,0.0200346,0.00157458,0.00459426,0.0198753,0.0198753,0.0198753,0.0198753,0.00974081,0.00974081,0.00974081,0.00100447,0.00407461,0.00407461,0.00199255,0.00360717,0.00384501,0.00664432,0.00073103,0.00073103,0.00073103,0.00073103,0.00073103,0.00653474,0.00653474,0.00653474,0.00653474,0.000282101,0.00112994,0.00446715,0.046831,0.00439807,0.0206447,0.0206447,0.0206447,0.00984559,0.119385,0.00105993,0.00183382,0.00569339,0.00295168,0.0104402,0.00110547,0.00110547,0.00332407,0.00332407,0.00332407,0.00296477,0.0317551,0.000424365,0.00912031,0.00912031,0.0221765,0.00332407,0.00145829,0.00145829,0.00145829,0.00145829,0.0114648,0.0114648,0.000398872,0.00332407,0.00332407,0.0208539,0.0208539,0.0188007,0.00350205,0.00350205,0.00334476,0.000551607,0.00423072,0.0316282,0.0316282,0.00332407,0.0264414,0.00063899,0.0040138,0.0040138,0.000171778,0.000193322,0.000193322,0.000193322,0.000193322,0.00576667,0.00154918,0.00154918,0.0104702,0.0104702,0.0281382,0.00433273,0.0564548,0.0181366,0.0181366,0.0181366,0.0181366,0.00257201,0.0306123,0.0071345,0.001333,0.0197434,0.00487838,0.00424739,0.00807011,0.00807011,0.00862914,8.46704e-05,8.46704e-05", "train/beta1": "0.5,0.5,0.5,0.575716,0.5,0.5,0.5,0.5,0.82625,0.82625,0.82625,0.82625,0.82625,0.5,0.5,0.5,0.896572,0.896572,0.896572,0.77269,0.77269,0.910183,0.910183,0.727971,0.727971,0.769415,0.5,0.5,0.5,0.5,0.727971,0.727971,0.5,0.5,0.669694,0.5,0.5,0.5,0.5,0.5,0.884042,0.82975,0.82975,0.5,0.727971,0.727971,0.84449,0.84449,0.829685,0.916637,0.916637,0.742744,0.727971,0.727971,0.727971,0.73458,0.818938,0.727971,0.81968,0.81968,0.81968,0.92896,0.5,0.889231,0.5,0.888601,0.727971,0.864801,0.930686,0.835084,0.835084,0.835084,0.805154,0.5,0.66255,0.638696,0.5,0.829806,0.829806,0.829806,0.829806,0.796424,0.796424,0.796424,0.5,0.5,0.5,0.699367,0.772534,0.80317,0.71975,0.793586,0.793586,0.793586,0.793586,0.793586,0.800107,0.800107,0.800107,0.800107,0.791779,0.854076,0.5,0.864764,0.5,0.855938,0.855938,0.855938,0.868907,0.588222,0.5,0.886266,0.5,0.82333,0.758248,0.5,0.5,0.727971,0.727971,0.727971,0.820936,0.812412,0.5,0.810454,0.810454,0.5,0.727971,0.851295,0.851295,0.851295,0.851295,0.888478,0.888478,0.5,0.727971,0.727971,0.879382,0.879382,0.5,0.505156,0.505156,0.695997,0.683217,0.5,0.642253,0.642253,0.727971,0.5,0.757704,0.869817,0.869817,0.5,0.876479,0.876479,0.876479,0.876479,0.503823,0.5,0.5,0.75177,0.75177,0.977885,0.698428,0.689097,0.929821,0.929821,0.929821,0.929821,0.5,0.5,0.735728,0.5,0.888128,0.775558,0.675955,0.815567,0.815567,0.5,0.5,0.5", "train/beta2": "0.987452,0.991808,0.99766,0.997155,0.997919,0.997919,0.997919,0.997919,0.997275,0.997275,0.997275,0.997275,0.997275,0.999751,0.99641,0.999172,0.995952,0.995952,0.995952,0.971786,0.971786,0.989122,0.989122,0.998627,0.998627,0.999691,0.919822,0.919822,0.919822,0.919822,0.998627,0.998627,0.999014,0.999014,0.987814,0.997039,0.997039,0.997039,0.997039,0.997039,0.997175,0.975497,0.975497,0.997929,0.998627,0.998627,0.939734,0.939734,0.998005,0.999976,0.999976,0.999824,0.998627,0.998627,0.998627,0.948777,0.984367,0.998627,0.99919,0.99919,0.99919,0.995726,0.963091,0.98271,0.992277,0.992066,0.998627,0.999621,0.998405,0.989766,0.989766,0.989766,0.952994,0.999888,0.991028,0.996285,0.999422,0.993894,0.993894,0.993894,0.993894,0.995716,0.995716,0.995716,0.994778,0.995095,0.995095,0.999876,0.972625,0.996464,0.999698,0.99558,0.99558,0.99558,0.99558,0.99558,0.983986,0.983986,0.983986,0.983986,0.998942,0.998207,0.9,0.994684,0.997854,0.9932,0.9932,0.9932,0.987132,0.922365,0.999932,0.993911,0.999206,0.911049,0.988481,0.964995,0.964995,0.998627,0.998627,0.998627,0.995396,0.998277,0.999827,0.996133,0.996133,0.99874,0.998627,0.975485,0.975485,0.975485,0.975485,0.952201,0.952201,0.995887,0.998627,0.998627,0.994879,0.994879,0.999321,0.995982,0.995982,0.991444,0.983983,0.983107,0.95718,0.95718,0.998627,0.999001,0.990803,0.995199,0.995199,0.992299,0.92759,0.92759,0.92759,0.92759,0.99645,0.999486,0.999486,0.999642,0.999642,0.999392,0.994994,0.999952,0.9,0.9,0.9,0.9,0.998307,0.998329,0.996926,0.976914,0.995918,0.991648,0.942649,0.9,0.9,0.992952,0.97635,0.97635", "train/eps": "0.0001,1.94553e-05,3.33135e-05,1.45981e-06,1.66882e-05,1.66882e-05,1.66882e-05,1.66882e-05,7.54511e-06,7.54511e-06,7.54511e-06,7.54511e-06,7.54511e-06,4.82706e-06,0.0001,0.0001,3.83136e-05,3.83136e-05,3.83136e-05,1.53768e-05,1.53768e-05,0.0001,0.0001,8.33946e-05,8.33946e-05,0.0001,4.69495e-05,4.69495e-05,4.69495e-05,4.69495e-05,8.33946e-05,8.33946e-05,0.0001,0.0001,0.0001,8.41802e-06,8.41802e-06,8.41802e-06,8.41802e-06,8.41802e-06,1.30557e-06,4.13057e-07,4.13057e-07,8.87985e-06,8.33946e-05,8.33946e-05,0.0001,0.0001,6.02751e-07,1.89842e-08,1.89842e-08,0.0001,8.33946e-05,8.33946e-05,8.33946e-05,0.0001,3.12482e-06,8.33946e-05,1.60528e-06,1.60528e-06,1.60528e-06,1.45937e-06,1.23826e-05,1.60037e-05,0.0001,0.0001,8.33946e-05,2.00209e-05,2.80171e-06,0.0001,0.0001,0.0001,7.77087e-07,1.02272e-05,2.0059e-05,0.0001,0.0001,0.0001,0.0001,0.0001,0.0001,4.38273e-05,4.38273e-05,4.38273e-05,0.0001,0.0001,0.0001,0.0001,6.26654e-05,0.0001,0.0001,0.0001,0.0001,0.0001,0.0001,0.0001,2.1114e-06,2.1114e-06,2.1114e-06,2.1114e-06,0.0001,8.47835e-09,8.76794e-07,0.0001,6.92769e-07,0.0001,0.0001,0.0001,0.0001,0.0001,4.30711e-07,0.0001,0.0001,4.25126e-06,9.35232e-05,7.03322e-05,7.03322e-05,8.33946e-05,8.33946e-05,8.33946e-05,8.87563e-07,1.1778e-06,0.0001,6.55546e-05,6.55546e-05,0.0001,8.33946e-05,0.0001,0.0001,0.0001,0.0001,4.49578e-07,4.49578e-07,0.0001,8.33946e-05,8.33946e-05,2.00766e-05,2.00766e-05,4.63275e-06,2.1033e-05,2.1033e-05,2.67649e-05,4.65026e-05,2.99244e-05,1.82456e-06,1.82456e-06,8.33946e-05,4.67772e-07,0.0001,0.0001,0.0001,1.51934e-06,0.0001,0.0001,0.0001,0.0001,0.0001,0.0001,0.0001,0.0001,0.0001,5.55688e-13,2.32416e-06,0.0001,7.81239e-05,7.81239e-05,7.81239e-05,7.81239e-05,2.81358e-06,7.51772e-05,9.03176e-05,0.0001,1.92401e-05,9.46771e-05,1.69218e-05,1.21909e-06,1.21909e-06,0.0001,3.62262e-06,3.62262e-06", "train/minibatch_size": "4096,8192,65536,8192,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,65536,65536,65536,65536,8192,8192,16384,16384,65536,65536,65536,8192,8192,8192,8192,65536,65536,8192,8192,16384,4096,4096,4096,4096,4096,8192,8192,8192,4096,65536,65536,4096,4096,4096,4096,4096,16384,65536,65536,65536,8192,16384,65536,8192,8192,8192,8192,16384,16384,4096,4096,65536,65536,65536,16384,16384,16384,8192,4096,16384,4096,65536,65536,65536,65536,65536,4096,4096,4096,8192,65536,65536,8192,8192,4096,8192,8192,8192,8192,8192,8192,16384,16384,16384,16384,8192,8192,8192,8192,4096,16384,16384,16384,4096,4096,4096,4096,4096,4096,8192,4096,4096,65536,65536,65536,8192,16384,4096,16384,16384,65536,65536,4096,4096,4096,4096,16384,16384,65536,65536,65536,16384,16384,4096,4096,4096,4096,8192,32768,8192,8192,65536,4096,8192,4096,4096,4096,4096,4096,4096,4096,4096,16384,16384,8192,8192,4096,16384,4096,32768,32768,32768,32768,8192,4096,4096,8192,65536,16384,32768,16384,16384,4096,4096,4096", "train/horizon": "128,32,64,64,128,128,128,128,16,16,16,16,16,64,256,128,64,64,64,16,16,64,64,64,64,32,256,256,256,256,64,64,64,64,128,256,256,256,256,256,32,32,32,64,64,64,256,256,64,256,256,128,64,64,64,64,32,64,64,64,64,16,64,16,128,128,64,64,64,64,64,64,64,64,32,64,32,64,64,64,64,64,64,64,64,64,64,64,256,32,128,32,32,32,32,32,32,32,32,32,32,32,64,32,128,32,32,32,128,256,128,256,128,256,32,64,64,64,64,64,16,32,64,32,32,64,64,16,16,16,16,16,16,64,64,64,64,64,256,128,128,128,16,32,32,32,64,128,64,32,32,128,128,128,128,128,128,32,32,16,16,256,128,32,32,32,32,32,64,128,64,256,64,128,32,32,32,128,128,128", "train/vtrace_rho_clip": "3.99681,3.01797,4.35127,3.55088,3.77601,3.77601,3.77601,3.77601,3.05246,3.05246,3.05246,3.05246,3.05246,4.21504,3.003,2.18105,1.12567,1.12567,1.12567,2.63073,2.63073,5,5,2.10173,2.10173,2.1737,1.54946,1.54946,1.54946,1.54946,2.10173,2.10173,3.65122,3.65122,3.94554,4.80212,4.80212,4.80212,4.80212,4.80212,4.00119,2.85502,2.85502,5,2.10173,2.10173,2.4519,2.4519,2.91462,2.35887,2.35887,4.16003,2.10173,2.10173,2.10173,2.92588,5,2.10173,4.48093,4.48093,4.48093,4.98876,4.16201,4.98401,1.67506,3.49405,2.10173,1.43329,2.79512,4.28436,4.28436,4.28436,3.65157,4.05339,5,1.859,1.19392,1.17011,1.17011,1.17011,1.17011,4.30059,4.30059,4.30059,3.70925,3.39895,3.39895,2.85104,1.95063,4.54274,3.36862,3.35394,3.35394,3.35394,3.35394,3.35394,4.48556,4.48556,4.48556,4.48556,3.64664,4.93014,3.54387,4.10194,3.82866,3.45346,3.45346,3.45346,4.78157,3.70671,4.78379,3.78702,3.1616,2.98819,4.82857,2.98368,2.98368,2.10173,2.10173,2.10173,5,4.36639,3.99339,3.92726,3.92726,3.04133,2.10173,2.32782,2.32782,2.32782,2.32782,3.97918,3.97918,4.61655,2.10173,2.10173,5,5,3.99172,2.19189,2.19189,5,2.49623,5,3.40122,3.40122,2.10173,3.60489,3.06771,4.53951,4.53951,4.03042,2.79465,2.79465,2.79465,2.79465,3.84394,2.69675,2.69675,4.7139,4.7139,1.73661,4.46514,4.06368,4.40926,4.40926,4.40926,4.40926,3.77848,4.41898,2.71638,4.49597,2.91165,5,2.44036,3.39841,3.39841,2.52919,1.89703,1.89703", "train/vtrace_c_clip": "5,3.80922,5,3.9465,4.01119,4.01119,4.01119,4.01119,5,5,5,5,5,5,4.77363,2.08321,1.71997,1.71997,1.71997,4.23259,4.23259,5,5,1.08304,1.08304,1.84312,5,5,5,5,1.08304,1.08304,5,5,4.0785,4.54923,4.54923,4.54923,4.54923,4.54923,5,5,5,5,1.08304,1.08304,5,5,1.95918,1.69557,1.69557,4.48575,1.08304,1.08304,1.08304,4.99203,4.53583,1.08304,5,5,5,5,2.8872,4.41887,4.0559,5,1.08304,1.70011,0.769463,3.84045,3.84045,3.84045,4.22002,5,4.49165,5,1.86627,1.48436,1.48436,1.48436,1.48436,4.95389,4.95389,4.95389,5,5,5,5,5,4.84355,4.44063,5,5,5,5,5,5,5,5,5,5,4.30825,4.21022,5,3.38629,5,5,5,5,5,5,4.00897,5,5,4.3704,4.45524,4.45524,1.08304,1.08304,1.08304,5,3.95779,4.67807,5,5,4.50282,1.08304,5,5,5,5,4.64224,4.64224,5,1.08304,1.08304,5,5,3.66184,5,5,3.63148,4.39394,4.50041,5,5,1.08304,5,5,4.52683,4.52683,4.14863,5,5,5,5,4.55383,4.61073,4.61073,5,5,3.87572,5,4.30712,3.8594,3.8594,3.8594,3.8594,4.08016,4.79452,5,4.73639,1.38593,3.94857,5,4.74409,4.74409,4.42342,5,5", "train/prio_alpha": "0.64675,0.395024,0.56498,0.183622,0.344332,0.344332,0.344332,0.344332,0.485021,0.485021,0.485021,0.485021,0.485021,0.533753,0.250281,0.0710904,0.0110151,0.0110151,0.0110151,0.383412,0.383412,0.38719,0.38719,0.1,0.1,0,0.42166,0.42166,0.42166,0.42166,0.1,0.1,0.320039,0.320039,0.527191,0.585804,0.585804,0.585804,0.585804,0.585804,0.364898,0.41543,0.41543,0.586007,0.1,0.1,0.191949,0.191949,0.107013,0.0673792,0.0673792,0.477,0.1,0.1,0.1,0.447708,0.0810675,0.1,0.24013,0.24013,0.24013,0.151266,0.35915,0.165708,0.190366,0.422653,0.1,0,0.32717,0.453399,0.453399,0.453399,0.560215,0.451881,0.3177,0.24192,0,0,0,0,0,0.587311,0.587311,0.587311,0.33941,0.50973,0.50973,0.528173,0.137663,0.337975,0.331689,0.329735,0.329735,0.329735,0.329735,0.329735,0.237942,0.237942,0.237942,0.237942,0.252805,0.281839,0.520621,0.14909,0.371385,0.491783,0.491783,0.491783,0.366801,0.0939313,0.285576,0.486158,0.608144,0.110828,0.36701,0.606798,0.606798,0.1,0.1,0.1,0.161392,0.31902,0.464985,0.155734,0.155734,0.573658,0.1,0.266009,0.266009,0.266009,0.266009,0.438026,0.438026,0.463515,0.1,0.1,0.248853,0.248853,0.282797,0.323337,0.323337,0.410263,0.277663,0.234476,0.292032,0.292032,0.1,0.379235,0.122824,0.138599,0.138599,0.305488,0.381989,0.381989,0.381989,0.381989,0.293671,0.478218,0.478218,0.137389,0.137389,0.702644,0.355929,0.40625,0.20549,0.20549,0.20549,0.20549,0.329048,0.504246,0.118472,0.310729,0.0309519,0.45796,0.52035,0.205876,0.205876,0.51834,0.283411,0.283411", "train/prio_beta0": "0,0,0,0.065563,0.0489542,0.0489542,0.0489542,0.0489542,0,0,0,0,0,0.0550648,0,0.766417,1,1,1,0.151786,0.151786,0.217111,0.217111,0.824716,0.824716,0.632747,0,0,0,0,0.824716,0.824716,0.00104494,0.00104494,0.131328,0,0,0,0,0,0.0409898,0,0,0,0.824716,0.824716,0,0,0.876439,1,1,0,0.824716,0.824716,0.824716,0,0.268185,0.824716,0,0,0,0.0530948,0.074618,0,0,0,0.824716,0.647665,0.840528,0.0567537,0.0567537,0.0567537,0.0767511,0.0169015,0,0,0.675104,1,1,1,1,0,0,0,0.0427257,0,0,0,0.230236,0.0436163,0.235636,0.0996752,0.0996752,0.0996752,0.0996752,0.0996752,0.0264842,0.0264842,0.0264842,0.0264842,0,0,0.0186211,0.106429,0.0522481,0.0304544,0.0304544,0.0304544,0,0.147146,0,0,0,0,0.20515,0.136106,0.136106,0.824716,0.824716,0.824716,0,0.074517,0.163504,0,0,0.152986,0.824716,0,0,0,0,0.111896,0.111896,0,0.824716,0.824716,0,0,0.197423,0.17741,0.17741,0.0947275,0,0.220307,0,0,0.824716,0.208187,0,0,0,0,0,0,0,0,0.0232605,0,0,0,0,0.838985,0,0.0478954,0.101339,0.101339,0.101339,0.101339,0,0,0.154544,0,0.869972,0,0,0.0321973,0.0321973,0.0283388,0,0", "train/use_rnn": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "no_model_upload": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "slowly": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "save_frames": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "fps": "15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15", "reset_state": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "tsne1": "48.6049,52.1539,49.7458,52.5954,49.9212,49.9213,49.9211,49.9213,60.989,60.9891,60.9888,60.9888,60.989,49.4684,50.9789,36.485,39.1033,39.1033,39.1033,62.8356,62.8358,55.7184,55.7184,37.5231,37.5231,36.3581,55.5713,55.5712,55.5712,55.5712,38.0788,38.0788,51.1376,51.1376,54.046,50.1472,50.1471,50.1472,50.1473,50.1483,57.95,59.3813,59.3813,48.9344,37.2056,38.0788,58.1528,58.1528,31.3196,31.3353,31.3353,56.9933,37.5231,38.0788,38.0788,59.1749,57.3963,37.5231,58.8747,58.8747,58.8747,58.0066,49.7175,57.3191,52.685,59.9262,38.0788,39.3175,39.476,57.9598,57.9598,57.9598,58.2475,50.7023,56.0369,57.6661,37.1511,38.2616,38.2616,38.2616,38.2616,61.0331,61.0331,61.0331,51.8031,50.0727,50.0727,55.2002,57.6992,60.7299,55.5499,59.6422,59.6422,59.6422,59.6422,59.6422,57.0557,57.0557,57.0557,57.0558,58.8145,58.2656,49.9867,58.3879,50.4907,55.7654,55.7654,55.7654,56.1139,56.6452,50.1612,55.5539,49.1441,58.1487,55.7165,47.8949,47.8949,37.5231,36.9986,36.9986,57.9742,56.508,48.3008,57.3029,57.3029,50.1804,38.0788,61.8558,61.8557,61.8558,61.8557,57.5152,57.5152,49.7672,37.5231,38.0788,56.6944,56.6944,50.4104,52.651,52.651,55.1155,59.9676,49.6725,59.6545,59.6545,38.0788,49.1252,58.0454,61.0877,61.0877,51.1985,58.8534,58.8534,58.8534,58.8534,51.8951,51.4248,51.4247,58.7247,58.7247,16.133,55.5854,55.0789,58.44,58.44,58.44,58.4399,51.203,49.6715,57.7725,51.6036,39.5835,55.2014,50.1244,57.5353,57.5374,50.3321,53.1205,53.1205", "tsne2": "-39.2066,-35.2338,-28.3774,-35.2234,-36.9308,-36.932,-36.9322,-36.9319,-33.4197,-33.4197,-33.4197,-33.4197,-33.4197,-37.4878,-38.0315,-54.6415,-56.8778,-56.8778,-56.8778,-34.1705,-34.1705,-25.7175,-25.7176,-56.3474,-56.3474,-56.3574,-39.8628,-39.8631,-39.8631,-39.8631,-55.4475,-55.4475,-36.0306,-36.0306,-33.3493,-39.3786,-39.3791,-39.3786,-39.3784,-39.3762,-30.073,-33.3998,-33.3998,-38.422,-55.2033,-55.4475,-38.2538,-38.2538,-14.6521,-14.6716,-14.6716,-30.7951,-56.3474,-55.4475,-55.4475,-32.9754,-26.0065,-56.3474,-29.7369,-29.7369,-29.7369,-26.7389,-29.4127,-25.7116,-39.6125,-34.531,-55.4475,-56.2194,-54.8252,-31.7154,-31.7154,-31.7154,-33.4372,-37.0285,-27.0452,-35.7939,-53.9621,-57.8529,-57.8529,-57.8529,-57.8529,-29.8688,-29.8688,-29.8688,-35.6009,-28.5658,-28.5658,-30.6699,-37.491,-29.3856,-32.3148,-31.0348,-31.0348,-31.0348,-31.0348,-31.0348,-27.2579,-27.2579,-27.2579,-27.2578,-34.1557,-28.9231,-30.5906,-27.0639,-37.611,-29.5423,-29.5419,-29.5418,-34.0905,-39.659,-38.567,-33.8811,-37.9263,-39.2505,-31.4148,-37.2031,-37.2031,-56.3474,-55.6174,-55.6174,-27.9824,-27.5376,-38.0642,-29.4885,-29.4885,-28.3717,-55.4475,-31.79,-31.7899,-31.79,-31.7899,-24.7382,-24.7382,-28.6918,-56.3474,-55.4475,-26.4632,-26.4632,-37.9451,-38.3705,-38.3705,-33.9043,-31.8153,-28.8701,-25.7859,-25.7859,-55.4475,-36.4111,-35.3887,-28.5889,-28.5889,-39.4445,-38.4757,-38.4757,-38.4757,-38.4757,-37.4733,-34.187,-34.1856,-27.832,-27.832,9.60499,-27.2449,-31.8916,-22.6324,-22.6324,-22.6324,-22.6323,-36.7661,-37.7904,-35.7602,-37.1657,-55.3788,-27.0756,-29.614,-22.8496,-22.85,-35.8594,-39.3588,-39.3588"}, "cartpole": {"SPS": "2.24406e+06,1.42569e+07,1.71302e+07,4.91068e+06,1.01755e+07,1.11163e+07,1.73207e+07,3.73568e+07,4.60207e+07,4.68044e+07,4.66306e+07,2.73195e+06,2.80647e+06,1.64397e+07,1.84654e+07,1.81889e+07,2.05886e+07,2.14508e+07,2.66245e+07,2.664e+07,1.06174e+07,2.13211e+07,2.31009e+07,2.38742e+07,2.67856e+07,2.68759e+07,3.22262e+07,2.14186e+07,1.58193e+07,2.30141e+06,8.66009e+06,1.70415e+07,1.70415e+07,1.70415e+07,6.69609e+06,8.30594e+06,3.05794e+06,2.72897e+06,4.79046e+06,4.78723e+06,4.6904e+06,1.29876e+06,2.30587e+07,2.69148e+07,5.90997e+06,2.64496e+06,1.95377e+07,2.58697e+07,2.92594e+07,5.68792e+06,5.91753e+06,8.99936e+06,2.36324e+07,2.71191e+07,2.45466e+07,2.46743e+07,7.94384e+06,3.61106e+06,3.6223e+06,8.74513e+06,9.36502e+06,9.5076e+06,1.87465e+06,1.05073e+07,1.15643e+07,4.01701e+07,2.21703e+06,1.15994e+07,3.18978e+07,3.187e+07,3.17686e+07,1.30084e+07,5.86711e+06,3.90178e+06,1.92546e+07,3.94759e+07,6.94814e+06,2.62758e+07,3.10316e+07,1.89832e+06,9.86469e+06,4.55403e+06,4.48709e+06,1.15827e+07,1.1597e+07,2.54288e+07,2.85521e+07,5.89559e+06,3.35765e+07,4.19316e+07,4.26481e+07,4.22553e+07,3.48155e+07,4.10848e+07,2.44148e+07,2.44e+07,7.55855e+06,1.75998e+06,8.20665e+06,2.08691e+07", "agent_steps": "0.262144,0.32768,1.11411,2.3593,0.720896,1.96608,2.81805,0.786432,2.09715,3.40787,4.58752,0.851968,2.3593,0.720896,1.96608,0.720896,3.21126,0.524288,5.50502,6.02931,0.720896,1.04858,0.720896,0.720896,1.96608,0.786432,2.09715,1.11411,3.67002,1.96608,0.524288,1.57286,1.57286,1.57286,2.75251,3.40787,0.720896,1.17965,4.58752,4.98074,1.96608,0.393216,3.53894,3.2768,1.96608,0.786432,0.851968,1.17965,3.14573,1.04858,3.01466,0.917504,0.720896,1.96608,17.5636,19.9229,6.29146,5.76717,6.29146,0.65536,1.90054,3.14573,0.786432,0.720896,1.96608,0.98304,0.262144,0.786432,3.67002,5.04627,5.6361,4.45645,0.98304,0.917504,3.67002,2.09715,1.24518,0.786432,2.09715,7.34003,0.688128,0.786432,0.917504,2.88358,4.71859,0.720896,2.03162,1.96608,0.786432,2.09715,3.40787,4.58752,0.786432,0.720896,17.5636,19.9229,1.96608,0.393216,3.40787,0.393216", "uptime": "0.406902,0.26584,0.0834309,0.498394,0.0845787,0.197708,0.186249,0.0352127,0.0638724,0.0920966,0.117404,0.323572,0.860895,0.0624197,0.130378,0.070911,0.193309,0.043394,0.2581,0.277777,0.0798306,0.073187,0.0465147,0.0450176,0.0919807,0.0419883,0.0829815,0.0669556,0.247624,0.879884,0.0605407,0.124919,0.124919,0.124919,0.436004,0.434819,0.246512,0.449146,0.990207,1.0723,0.432596,1.20626,0.177536,0.142507,0.353699,0.318356,0.0650861,0.0605397,0.128634,0.198939,0.531755,0.116243,0.0518731,0.098265,0.735682,0.831796,0.873246,1.61005,1.75494,0.0878733,0.222941,0.35426,0.430953,0.0813183,0.190747,0.0348518,0.118241,0.0787917,0.138565,0.181694,0.200198,0.35876,0.192619,0.246406,0.216133,0.0842933,0.19093,0.0397638,0.0823765,3.89358,0.0862992,0.191354,0.219806,0.271499,0.429811,0.0440806,0.0902404,0.354728,0.0396942,0.0713916,0.102382,0.1302,0.039131,0.0277821,0.742269,0.838889,0.283675,0.217612,0.433402,0.0308846", "epoch": "2,2.5,17,18,5.5,15,21.5,3,8,13,17.5,6.5,18,5.5,15,5.5,24.5,2,21,23,5.5,8,5.5,5.5,15,3,8,8.5,14,15,1,3,3,3,10.5,13,5.5,9,17.5,19,15,1.5,13.5,12.5,15,6,6.5,4.5,12,8,23,7,5.5,15,67,76,12,11,12,10,29,48,6,5.5,15,7.5,1,6,28,38.5,43,17,7.5,7,28,8,19,3,8,14,10.5,6,7,11,18,5.5,15.5,15,3,8,13,17.5,6,5.5,67,76,15,1.5,13,3", "env/score": "7.35834,9.94922,128.69,196.091,76.5059,190.116,195.765,37.0692,151.165,191.133,195.356,124.19,196.183,94.0001,194.364,46.2373,197.408,29.289,199.375,199.681,102.718,105.749,33.4642,44.903,171.184,31.8925,144.651,112.837,198.596,188.687,18.6652,144.956,183.86,183.86,196.718,198.975,114.997,149.49,199.77,199.882,189.404,10.3317,195.403,194.436,195.906,119.106,105.51,102.407,192.397,132.572,199.322,129.354,95.8654,192.378,199.975,199.977,199.946,199.9,199.999,105.396,187.356,197.427,117.348,48.0914,192.98,21.7253,8.18766,106.69,198.3,198.655,199.161,198.631,130.613,140.727,197.688,151.73,150.013,32.0312,120.186,200,114.54,117.67,132.16,196.055,199.862,63.7851,181.383,190.655,29.3439,144.459,193.121,197.057,30.9443,7.88112,199.975,199.977,192.46,10.2061,199.015,10.8511", "env/perf": "0.00197851,0.0149007,0.635905,0.97314,0.359272,0.944322,0.973747,0.160926,0.750328,0.950275,0.971602,0.593346,0.973638,0.447494,0.964697,0.166575,0.981521,0.0838431,0.990997,0.389685,0.493499,0.519385,0.138752,0.197475,0.849014,0.133748,0.715098,0.546492,0.987554,0.937471,0.0153637,0.71934,0.912508,0.912508,0.969834,0.989599,0.555526,0.730545,0.993844,0.194045,0.939073,0.018015,0.971539,0.964337,0.973152,0.567474,0.510932,0.481602,0.956049,0.638896,0.991223,0.6205,0.463754,0.955036,0.99487,0.392538,0.803932,0.994522,0.398295,0.504793,0.927248,0.980898,0.557646,0.196522,0.958745,0.0957971,0.0273094,0.521888,0.985906,0.988035,0.397472,0.987527,0.62827,0.682309,0.983119,0.74391,0.743527,0.132889,0.585235,0.326217,0.554894,0.556087,0.63534,0.975274,0.994317,0.301815,0.901913,0.94557,0.115253,0.715099,0.95813,0.979511,0.125862,0.0183224,0.99487,0.392538,0.952049,0.0078817,0.989136,0.0179541", "env/episode_length": "7.35834,9.94922,128.69,196.091,76.5059,190.116,195.765,37.0692,151.165,191.133,195.356,124.19,196.183,94.0001,194.364,46.2373,197.408,29.289,199.375,199.681,102.718,105.749,33.4642,44.903,171.184,31.8925,144.651,112.837,198.596,188.687,18.6652,144.956,183.86,183.86,196.718,198.975,114.997,149.49,199.77,199.882,189.404,10.3317,195.403,194.436,195.906,119.106,105.51,102.407,192.397,132.572,199.322,129.354,95.8654,192.378,199.975,199.977,199.946,199.9,199.999,105.396,187.356,197.427,117.348,48.0914,192.98,21.7253,8.18766,106.69,198.3,198.655,199.161,198.631,130.613,140.727,197.688,151.73,150.013,32.0312,120.186,200,114.54,117.67,132.16,196.055,199.862,63.7851,181.383,190.655,29.3439,144.459,193.121,197.057,30.9443,7.88112,199.975,199.977,192.46,10.2061,199.015,10.8511", "env/x_threshold_termination": "0,0,0.346386,0.0297181,0.0292766,0.210966,0.130028,0,0.213102,0.216817,0.131691,0.0841632,0.0932182,0.085375,0.0857086,0,0.000284495,0,0.0241237,0.0135019,0.153322,0.0956359,0,0,0.165216,0.000118624,0.458245,0.149296,0.0526018,0.186114,0,0.140063,0.0617978,0.0617978,0.014744,0.0651015,0.425904,0.078497,0.00955588,0.00390662,0.0654932,0,0.169611,0.122681,0.0884461,0.217153,0.17719,0.151881,0.273702,0.0186636,0.015987,0.0615794,0.0402672,0.150194,0,0,0,0.00498247,0.000195446,0.14291,0.103003,0.0315093,0.15546,0.00538389,0.157498,0,0,0.147267,0.0440302,0.0348651,0.0203602,0.0623904,0.0718905,0.102772,0.0637759,0.333758,0.101158,0,0.196273,0,0.134214,0.0015889,0.0551511,0.167567,0.014413,0.0539162,0.417366,0.175431,7.53296e-05,0.0926611,0.124644,0.0597549,0,0,0,0,0.10328,0,0.0270205,0", "env/pole_angle_termination": "1,1,0.422466,0.0448518,0.905188,0.080074,0.0564082,1,0.560071,0.0661351,0.0186002,0.451582,0.0321859,0.731808,0.0504746,0.998381,0.0651337,1,0.00755906,0.00794791,0.649087,0.804844,1,0.998982,0.383715,0.999881,0.315164,0.581732,0.0152991,0.0618669,1,0.679495,0.473093,0.473093,0.0332287,0.0229615,0.473569,0.41082,0.00687404,0.00533587,0.135096,1,0.0227041,0.0454065,0.0558256,0.617325,0.582743,0.65786,0.0389061,0.504115,0.00881468,0.685506,0.843619,0.125014,0.000351133,0.000288962,0.000591833,0.00102245,0,0.649862,0.14677,0.0313832,0.59524,0.979834,0.149343,1,1,0.699184,0.0320519,0.0208126,0.0134103,0.0117207,0.540289,0.418636,0.0255647,0.386363,0.366575,1,0.685171,0,0.573535,0.641801,0.505738,0.0421296,0.000748366,0.926783,0.104267,0.104985,0.999925,0.709859,0.107104,0.028331,1,1,0.000351133,0.000288962,0.0921401,1,0.0128507,1", "env/max_steps_termination": "0,0,0.238881,0.928381,0.0672343,0.717761,0.819328,0,0.231811,0.727059,0.852748,0.466564,0.877082,0.18415,0.867403,0.00161867,0.936191,0,0.970293,0.980274,0.200133,0.102713,0,0.00101789,0.45816,0,0.229978,0.273297,0.936144,0.761029,0,0.18612,0.47605,0.47605,0.952867,0.919446,0.112007,0.515893,0.984496,0.99171,0.801447,0,0.814718,0.835637,0.859222,0.170732,0.243011,0.193155,0.695044,0.480151,0.976468,0.260592,0.11868,0.73257,0.999649,0.999711,0.999408,0.994123,0.999902,0.21017,0.753984,0.939991,0.254445,0.0152311,0.705276,0,0,0.156517,0.926973,0.947748,0.967698,0.930498,0.394628,0.482192,0.915432,0.285685,0.535811,0,0.121544,1,0.299715,0.357897,0.444677,0.800013,0.985926,0.0199782,0.485095,0.727379,0,0.202988,0.779495,0.916756,0,0,0.999649,0.999711,0.811887,0,0.961655,0", "env/n": "18749,12736.8,933.788,664.545,2740.6,655.222,676.429,6201,1281.6,1190.4,1382,2600.83,696,2015.6,623.444,3041.4,661.3,8368,1356,10443,1668.6,1548.13,3844.2,3089.1,700.556,6972.4,1388.8,1797.38,1158,698.222,25144,1585,3382,3382,1343,1334,2621.6,1639.94,1322.25,10495,628,22420,1366.62,1343.75,664.222,1783.73,1968.58,3946.12,1399.71,2278.87,664.667,1864.92,1734,686.667,1312.37,10382,10138,2630.33,10233,1201.84,343.842,332.421,2568.36,5293.2,665.111,6267.07,20553,2096.27,666.818,686.6,10216,1320.57,2203.07,1628,666.182,1583.2,620.378,7238.6,1585,12494,1486.5,2010.36,2160.38,1433.14,1528.29,2479.2,717.3,681.778,7171.2,1193.2,1212.8,1580.25,4518.64,18719.5,1312.37,10382,683,24457,1297.2,11756.8", "perf/rollout": "0.12627,0.0663224,0.00190373,0.0032327,0.00395463,0.0022107,0.00437054,0.00586553,0.0024704,0.00237594,0.00239569,0.00589718,0.00432012,0.00448244,0.00237881,0.00778179,0.00431719,0.0145574,0.00469036,0.0046699,0.0035064,0.00426318,0.00398512,0.00380614,0.00214484,0.00564313,0.00231295,0.00327094,0.00262263,0.00507124,0.0416903,0.0117843,0.0117843,0.0117843,0.00646857,0.00756183,0.00546999,0.00608461,0.00744206,0.00744843,0.00254607,0.546824,0.0039376,0.00385153,0.00370746,0.00724227,0.00467805,0.0062038,0.003893,0.0050715,0.00367494,0.00507918,0.00479913,0.0024156,0.00441875,0.00435877,0.0162611,0.0104852,0.0104775,0.002686,0.00188371,0.0018844,0.00609359,0.00538301,0.00374842,0.00221942,0.0222609,0.00356817,0.00248733,0.00249302,0.0025053,0.0047369,0.00674129,0.00506249,0.00243937,0.0023406,0.00151521,0.00506845,0.00240259,0.00970721,0.00314656,0.00624132,0.00670261,0.00261767,0.00258483,0.00379167,0.00201352,0.00374614,0.00663075,0.00262628,0.00252781,0.0025869,0.00393098,0.00271661,0.00448001,0.00447845,0.00372844,0.0223372,0.00422735,0.00667324", "perf/eval_gpu": "0.115147,0.0249625,0.000861339,0.00180826,0.00186221,0.00103944,0.00257279,0.00274743,0.00112063,0.0010817,0.00108411,0.00333024,0.00252982,0.00234586,0.00109375,0.00467145,0.00226319,0.00800503,0.00219338,0.0021869,0.00151688,0.00215,0.00195151,0.00185452,0.00102391,0.00278457,0.00105843,0.00160007,0.00133128,0.00323474,0.0170547,0.0037432,0.0037432,0.0037432,0.00361515,0.00475441,0.00302407,0.00374376,0.0046649,0.00466784,0.00157079,0.0833488,0.00206336,0.00203248,0.00233111,0.00442402,0.00252247,0.00326368,0.00202518,0.00267277,0.00196772,0.00287041,0.00240144,0.00113284,0.0026097,0.00256625,0.00800547,0.00680846,0.00680701,0.00126118,0.000989962,0.000984978,0.00345693,0.00303199,0.00235604,0.000848475,0.00737864,0.00171506,0.00119,0.00118856,0.00123267,0.00288449,0.00418338,0.00283708,0.00118445,0.001082,0.000761156,0.00210271,0.00112917,0.00618884,0.00158188,0.00364687,0.00416343,0.00130004,0.001304,0.00154934,0.00102539,0.00233091,0.00358185,0.00120286,0.00118642,0.00117533,0.0018817,0.00087053,0.00259265,0.00259281,0.00197569,0.0113079,0.00241243,0.00214625", "perf/eval_env": "0.00473713,0.0406026,0.000538545,0.000716907,0.00133185,0.000564905,0.000725146,0.00228411,0.000743147,0.000726576,0.00073007,0.00140761,0.000729047,0.00125237,0.000536235,0.00163097,0.000668208,0.00551072,0.00104995,0.00103264,0.00134882,0.00102406,0.00124601,0.00125391,0.000569516,0.00203633,0.000707913,0.000979925,0.000713594,0.000710025,0.022031,0.00682763,0.00682763,0.00682763,0.00143846,0.00138825,0.00160115,0.00114293,0.00137569,0.00138145,0.00047119,0.461983,0.000923958,0.000878875,0.000670241,0.00128638,0.00116958,0.00184876,0.000921408,0.00129546,0.000710879,0.00137602,0.00146555,0.00053416,0.000878516,0.000863759,0.0069918,0.00197159,0.00196838,0.000820397,0.000364157,0.000363509,0.0014449,0.00150069,0.000674244,0.000950953,0.0134428,0.00130624,0.000536011,0.000535837,0.000541832,0.0010091,0.00112437,0.00141715,0.000530014,0.000716845,0.000489593,0.00211762,0.000708093,0.00180366,0.000947344,0.00137036,0.0012945,0.000662544,0.00066537,0.00160939,0.000477488,0.000700539,0.00204101,0.000695449,0.000663085,0.000692836,0.00122647,0.00143173,0.0009113,0.000926244,0.000706879,0.00964179,0.00096482,0.00381712", "perf/train_misc": "0.00520517,0.0010623,0.000563748,0.00323751,0.00420523,0.00193328,0.000273938,0.00298895,0.000928454,0.000928518,0.000925696,0.00616914,0.00321374,0.00208364,0.000952082,0.000582576,0.000269219,0.00180333,0.000886227,0.000894016,0.00417821,0.00110465,0.00118698,0.00118598,0.000550741,0.00566643,0.00170173,0.00119907,0.0032232,0.00327568,0.0377255,0.00309453,0.00309453,0.00309453,0.00392789,0.00179876,0.0060465,0.00533892,0.0038925,0.0038871,0.00262656,0.0183627,0.0011584,0.000994544,0.0016831,0.0127896,0.00135102,0.00209732,0.000856416,0.00294105,0.00166954,0.0017122,0.00103634,0.000484836,0.000701576,0.000704608,0.0070103,0.0102349,0.0103168,0.00122507,0.000753812,0.000738464,0.0127608,0.00150785,0.000690436,0.000367152,0.117139,0.00253484,0.000254467,0.000253856,0.000253792,0.00191939,0.00278282,0.00535926,0.000674164,0.00121995,0.00185569,0.00554811,0.00173118,0.0207749,0.000568352,0.00661651,0.00310018,0.00464325,0.0046164,0.00107822,0.000509021,0.00168799,0.00336974,0.00104999,0.00104822,0.00105082,0.000392303,0.000347341,0.000704677,0.000703488,0.00166569,0.0186234,0.00466942,0.00031385", "perf/train_forward": "0.084246,0.00759245,0.00247616,0.0199587,0.0158147,0.0073727,0.00274141,0.00676363,0.00200847,0.00201125,0.00200704,0.0735886,0.0388986,0.00768327,0.0035452,0.00360631,0.00159476,0.00788301,0.0040411,0.00403251,0.0157251,0.00413795,0.00443601,0.00443334,0.0019767,0.0125113,0.00383604,0.00452893,0.0104229,0.0482195,0.182456,0.0155187,0.0155187,0.0155187,0.028388,0.0219513,0.0716628,0.0632114,0.0430044,0.0428462,0.0225329,0.519533,0.00603904,0.00467558,0.0165806,0.0718688,0.00513084,0.00983028,0.00398043,0.0284747,0.0166078,0.016507,0.00384874,0.00172337,0.00533004,0.00530842,0.0482099,0.123781,0.123126,0.00674276,0.00417302,0.00407672,0.112338,0.0144985,0.00670374,0.00213953,0.99109,0.0136948,0.00116093,0.00116084,0.00116122,0.0132289,0.027,0.0471255,0.00348019,0.00278876,0.00835406,0.0126963,0.00401981,0.244095,0.00567889,0.0397554,0.0392274,0.0150388,0.0150546,0.00409236,0.00185119,0.0165622,0.00774799,0.00229704,0.00230031,0.00229581,0.00147731,0.0020579,0.00533129,0.00533299,0.0117273,0.655737,0.0227025,0.00370589", "perf/train": "0.0894512,0.00865475,0.00303991,0.0231962,0.0200199,0.00930598,0.00301535,0.00975259,0.00293693,0.00293977,0.00293274,0.0797577,0.0421123,0.00976691,0.00449728,0.00418889,0.00186398,0.00968634,0.00492733,0.00492653,0.0199033,0.0052426,0.00562298,0.00561932,0.00252744,0.0181777,0.00553777,0.00572799,0.0136461,0.0514952,0.220181,0.0186132,0.0186132,0.0186132,0.0323159,0.02375,0.0777093,0.0685503,0.0468969,0.0467333,0.0251594,0.537895,0.00719744,0.00567013,0.0182637,0.0846584,0.00648186,0.0119276,0.00483685,0.0314158,0.0182773,0.0182192,0.00488508,0.00220821,0.00603162,0.00601302,0.0552202,0.134016,0.133443,0.00796783,0.00492683,0.00481518,0.125099,0.0160064,0.00739418,0.00250668,1.10823,0.0162297,0.00141539,0.0014147,0.00141501,0.0151483,0.0297828,0.0524847,0.00415436,0.00400871,0.0102098,0.0182444,0.00575099,0.26487,0.00624724,0.0463719,0.0423276,0.019682,0.019671,0.00517059,0.00236021,0.0182502,0.0111177,0.00334703,0.00334853,0.00334662,0.00186961,0.00240524,0.00603597,0.00603648,0.013393,0.67436,0.0273719,0.00401974", "util/gpu_percent": "43,0,0,100,8,80,0,0,0,0,0,100,99.6364,0,0,0,0,1,18.2,91,1,16.8,3,0,0,3,3,0,0,99.7778,0,0,0,0,86,38,67.9,100,97,96,30,0,1,22.5,31.6667,100,0,0,0,40,40,0,0,0,93,93,97,100,100,11,11,11,100,7.5,75,0,100,44.7273,0,0,0,100,3,15,39,0,0,2,2,100,0,10,32,3,16.5714,0,0,84,1,1,1,1,25,5,92,92,77,96,93,0", "util/gpu_mem": "5.82585,4.51499,8.96587,6.6454,8.80302,8.80302,9.19384,8.82745,8.82745,8.82745,8.82745,8.72975,8.72975,6.83266,6.83266,9.14499,9.14499,4.23002,9.07985,9.07985,8.64018,7.14206,8.80302,8.80302,8.80302,8.82745,8.82745,8.80302,6.53141,7.74457,4.38472,4.38472,4.38472,4.38472,8.56691,8.79488,6.53955,8.95772,8.65647,8.65647,6.72682,7.70665,8.95772,8.78674,8.56691,8.99843,9.12056,8.78674,8.78674,8.76231,8.76231,8.71346,8.95772,8.95772,6.59654,6.59654,14.6106,6.75124,6.75124,8.6239,8.6239,8.6239,8.69718,8.71346,8.71346,8.55876,15.1357,8.69718,9.03914,9.03914,9.03914,8.73789,9.16127,6.36857,9.03914,8.91701,6.2383,8.16795,8.16795,7.77713,8.96587,8.84373,6.93851,6.94665,6.94665,8.7216,8.7216,8.56691,8.39592,8.39592,8.39592,8.39592,8.80302,8.55876,6.59654,6.59654,8.68089,7.39726,8.5262,4.57199", "util/vram_used_gb": "0.936401,0.621948,1.68964,1.133,1.65057,1.65057,1.74432,1.65643,1.65643,1.65643,1.65643,1.633,1.633,1.17792,1.17792,1.7326,1.7326,0.553589,1.71698,1.71698,1.61151,1.25214,1.65057,1.65057,1.65057,1.65643,1.65643,1.65057,1.10565,1.39667,0.590698,0.590698,0.590698,0.590698,1.59393,1.64862,1.1076,1.68768,1.61542,1.61542,1.15253,1.38757,1.68768,1.64667,1.59393,1.69745,1.72675,1.64667,1.64667,1.64081,1.64081,1.62909,1.68768,1.68768,1.12128,1.12128,3.0437,1.15839,1.15839,1.6076,1.6076,1.6076,1.62518,1.62909,1.62909,1.59198,3.16968,1.62518,1.70721,1.70721,1.70721,1.63495,1.73651,1.06659,1.70721,1.67792,1.03534,1.49823,1.49823,1.40448,1.68964,1.66034,1.20331,1.20526,1.20526,1.63104,1.63104,1.59393,1.55292,1.55292,1.55292,1.55292,1.65057,1.59198,1.12128,1.12128,1.62128,1.31335,1.58417,0.63562", "util/vram_total_gb": "23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272", "util/cpu_mem_gb": "1.19167,1.08496,1.01101,1.00738,1.0107,1.0107,1.01746,1.01298,1.01298,1.01298,1.01298,1.01798,1.01826,1.01228,1.01228,1.02706,1.02706,1.09217,1.02655,1.02655,1.00959,1.014,1.01146,1.01199,1.01199,1.013,1.01329,1.01168,1.00865,1.03801,1.10462,1.10462,1.10462,1.10462,1.01616,1.01732,1.01092,1.03315,1.01731,1.01731,1.01075,1.08673,1.01452,1.01551,1.0102,1.02885,1.01851,1.01523,1.01523,1.01688,1.01688,1.01197,1.01477,1.01477,1.01489,1.01489,1.01837,1.02057,1.02057,1.00776,1.00776,1.00776,1.01779,1.01089,1.01089,1.00476,1.00571,1.00805,1.01535,1.01535,1.01535,1.01147,1.03495,1.00787,1.01765,1.01247,1.00293,1.01043,1.01043,1.03474,1.01022,1.02263,1.03202,1.01672,1.01672,1.0102,1.0102,1.00968,1.01546,1.01546,1.01546,1.01546,1.01121,1.00698,1.01646,1.01646,1.0154,1.09416,1.01036,1.08459", "wandb": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "rank": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "world_size": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "gpu_id": "1,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,4", "profile": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "checkpoint_interval": "200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200", "eval_episodes": "10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000", "cudagraphs": "10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10", "seed": "73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73", "vec/total_agents": "1024,4096,4096,2048,4096,4096,2048,8192,8192,8192,8192,2048,2048,4096,4096,2048,2048,4096,4096,4096,4096,4096,4096,4096,4096,8192,8192,4096,8192,2048,4096,4096,4096,4096,2048,2048,2048,2048,2048,2048,4096,8192,4096,4096,2048,2048,4096,4096,4096,2048,2048,2048,4096,4096,4096,4096,8192,4096,4096,2048,2048,2048,2048,2048,2048,8192,16384,4096,4096,4096,4096,4096,2048,2048,4096,8192,4096,8192,8192,4096,2048,2048,2048,8192,8192,4096,4096,2048,8192,8192,8192,8192,4096,8192,4096,4096,2048,4096,4096,4096", "vec/num_buffers": "7.20343,1.65346,4.32287,1.73742,3.91073,3.91073,2.60507,3.87535,3.87535,3.87535,3.87535,2.87572,2.87572,4.62306,4.62306,4.91725,4.91725,2.31157,4.41269,4.41269,2.03319,4.41518,3.95783,3.8005,3.8005,3.82356,3.82356,3.97443,2.60637,3.4381,2.24918,2.24918,2.24918,2.24918,1.36412,1,1,3.80438,1.32924,1.32924,2.90293,2.83471,2.75276,2.07866,1.03473,4.40177,5.40991,2.00941,2.00941,2.08898,2.08898,1.04327,4.41784,4.41784,2,2,2.66344,1.22405,1.22405,2.58919,2.58919,2.58919,2.4167,1,1,1.31852,1.10172,1.2587,4.78896,4.78896,4.78896,1,4.36885,1,4.39422,3.38471,1,2.13277,2.13277,2.67359,2.01551,3.75589,3.52392,4.12717,4.12717,2.57515,2.57515,1,4.05954,4.05954,4.05954,4.05954,3.99096,1.74924,2,2,2.64941,1.60776,1,1.10584", "vec/num_threads": "2,2,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,2,16,16,16,16,16,16,16,16,16,16,16,16,2,2,2,2,16,16,16,16,16,16,16,2,16,16,16,16,16,16,16,16,16,16,16,16,16,16,2,16,16,16,16,16,16,16,16,16,2,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,2,16,2", "env/cart_mass": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "env/pole_mass": "0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1", "env/pole_length": "0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5", "env/gravity": "9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8,9.8", "env/force_mag": "10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10", "env/dt": "0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02,0.02", "env/continuous": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "policy/hidden_size": "128,64,32,32,32,32,64,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,512,64,32,32,32,32,32,32,32,32,32,32,32,64,64,32,32,32,32,32,32,64,32,32,32,256,32,32,32,32,32,32,32,32,32,32,32,32,64,32,32,32,32,32,32,32,32,32,32,32,32,32,32,64,64,32,256,32,64", "policy/num_layers": "3.97645,2.51787,2.50102,1.49213,1.60901,1.60901,2.08316,1,1,1,1,3.99466,3.99466,1.62433,1.62433,1,1,1,1,1,1.50614,1.14559,1,1,1,1,1,1,2.16304,4.32242,1,1,1,1,1.51731,2.4796,3.22052,3.24956,2.20908,2.20908,4.55551,5.55199,1.41004,1.38251,2.4382,1.87062,1.32264,1,1,2.38134,2.38134,2.4695,1,1,2,2,3.02869,3.10688,3.10688,1.48459,1.48459,1.48459,2.26831,2.51404,2.51404,1,4.83385,2.01056,2.11327,2.11327,2.11327,2.4293,2.08201,2.25267,2.33297,1.38826,2.12872,1,1,3.32006,3.61088,1.97689,3.22812,2.04004,2.04004,1,1,2.90046,1,1,1,1,1.23823,1.38941,2,2,1.50362,6.37267,1.5296,1.22664", "policy/expansion_factor": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "legacy/torch_deterministic": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "legacy/cpu_offload": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "legacy/compile": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "legacy/compile_fullgraph": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "train/gpus": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "train/seed": "42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42", "train/total_timesteps": "1.48039,1.83311,8.49385,6.10234,5,5,7.36117,5,5,5,5,6.05418,6.05418,5,5,5.08259,5.08259,2.9707,6.04849,6.04849,5.28063,7.88049,5.1616,5,5,5.41915,5.41915,8.12839,9.63289,5.03298,1.94269,1.94269,1.94269,1.94269,6.91137,5,5,8.57915,5,5,5,1.59586,8.83947,8.19645,5,5.59138,6.0613,7.92965,7.92965,7.91442,7.91442,6.48797,5,5,20,20,6.6898,6.51347,6.51347,5,5,5,5.54913,5,5,7.38419,1.2899,5.82432,5.64256,5.64256,5.64256,6.87592,7.12881,6.89476,5.64306,5.26869,9.55866,5,5,7.84149,5.17931,5.59435,6.7966,7.28292,7.28292,5.2336,5.2336,5,5.16176,5.16176,5.16176,5.16176,5.66333,5,20,20,5,1.48365,5,2.47229", "train/learning_rate": "0.0109988,0.1,0.1,0.0240347,0.072757,0.072757,0.071995,0.1,0.1,0.1,0.1,0.0650581,0.0650581,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.074322,0.0103346,0.0311129,0.0311129,0.1,0.1,0.1,0.1,0.0318155,0.1,0.1,0.1,0.1,0.0523351,0.1,0.0637687,0.024093,0.0297285,0.0297285,0.1,0.00660951,0.0778868,0.0848617,0.0561389,0.1,0.1,0.1,0.1,0.0263783,0.0263783,0.1,0.1,0.1,0.05,0.05,0.1,0.1,0.1,0.1,0.1,0.1,0.0277932,0.0240545,0.0240545,0.0736014,9.01988e-05,0.1,0.1,0.1,0.1,0.1,0.0444456,0.1,0.1,0.1,0.0886576,0.0588857,0.0588857,0.1,0.1,0.0173877,0.1,0.1,0.1,0.1,0.1,0.1,0.0575034,0.0575034,0.0575034,0.0575034,0.1,0.0878736,0.05,0.05,0.0294336,0.00199389,0.0154932,0.0649214", "train/anneal_lr": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "train/min_lr_ratio": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "train/gamma": "0.983792,0.824924,0.8,0.8,0.8,0.8,0.841804,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8279,0.8279,0.981681,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.979584,0.979584,0.979584,0.979584,0.921677,0.8,0.826291,0.8,0.8,0.8,0.8,0.998948,0.898458,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.95,0.95,0.988491,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.998029,0.8,0.8,0.8,0.8,0.8,0.828375,0.968431,0.8,0.8,0.89345,0.8,0.8,0.847041,0.8,0.8,0.899214,0.848784,0.848784,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.95,0.95,0.8,0.990737,0.8,0.893748", "train/gae_lambda": "0.478211,0.666728,0.864209,0.935393,0.970297,0.970297,0.962268,0.92712,0.92712,0.92712,0.92712,0.923317,0.923317,0.823391,0.823391,0.970903,0.970903,0.906038,0.976591,0.976591,0.722906,0.968913,0.955013,0.964979,0.964979,0.929206,0.929206,0.775859,0.725942,0.935446,0.898672,0.898672,0.898672,0.898672,0.936881,0.815078,0.880524,0.900234,0.769173,0.769173,0.716864,0.99478,0.972488,0.902066,0.921866,0.767179,0.842806,0.9496,0.9496,0.955622,0.955622,0.75876,0.922635,0.922635,0.9,0.9,0.952754,0.860155,0.860155,0.690003,0.690003,0.690003,0.931374,0.777019,0.777019,0.901067,0.937074,0.924981,0.922151,0.922151,0.922151,0.90048,0.913562,0.878297,0.882061,0.784764,0.851678,0.958437,0.958437,0.917938,0.672222,0.817411,0.808284,0.793324,0.793324,0.918617,0.918617,0.94259,0.971688,0.971688,0.971688,0.971688,0.934846,0.985259,0.9,0.9,0.948663,0.985196,0.856398,0.879189", "train/replay_ratio": "0.688146,0.824112,1.31742,4,3.40989,3.40989,1.23804,0.447514,0.447514,0.447514,0.447514,4,4,1.69943,1.69943,1.09122,1.09122,0.25,0.688571,0.688571,3.43002,1.08257,0.999122,0.982176,0.982176,0.892454,0.892454,1.22758,1.71142,4,1.11901,1.11901,1.11901,1.11901,4,3.51519,3.61119,4,4,4,2.41204,0.777355,1.76496,1.57112,4,4,1.22798,1.27941,1.27941,4,4,4,0.772443,0.772443,1,1,1.73681,3.77505,3.77505,3.79811,3.79811,3.79811,4,3.22485,3.22485,1.14735,2.80637,4,0.381289,0.381289,0.381289,3.03962,3.66696,3.50617,1.20236,1.17841,2.52512,1.69689,1.69689,3.84543,3.04161,4,3.90831,2.45709,2.45709,1.54813,1.54813,4,0.561469,0.561469,0.561469,0.561469,0.25,0.871428,1,1,4,2.28071,3.93648,0.661181", "train/clip_coef": "0.926688,0.300569,0.156601,0.129251,0.105927,0.105927,0.161581,0.318847,0.318847,0.318847,0.318847,0.130646,0.130646,0.188442,0.188442,0.19015,0.19015,0.298949,0.202215,0.202215,0.169808,0.165997,0.236756,0.223873,0.223873,0.174599,0.174599,0.201644,0.217944,0.112361,0.272733,0.272733,0.272733,0.272733,0.228969,0.415642,0.178398,0.30507,0.194322,0.194322,0.178368,0.582953,0.241587,0.177429,0.116858,0.138492,0.147075,0.268979,0.268979,0.169405,0.169405,0.194052,0.183778,0.183778,0.2,0.2,0.139199,0.267271,0.267271,0.074063,0.074063,0.074063,0.231176,0.169949,0.169949,0.0851597,0.258991,0.196902,0.143548,0.143548,0.143548,0.0971792,0.191053,0.196077,0.122657,0.244587,0.15502,0.19393,0.19393,0.205291,0.117285,0.224778,0.263918,0.210228,0.210228,0.185789,0.185789,0.0981961,0.266027,0.266027,0.266027,0.266027,0.0980712,0.195185,0.2,0.2,0.217041,0.981111,0.225902,0.23128", "train/vf_coef": "4.36442,1.12127,0.933673,1.01235,2.31415,2.31415,2.00123,0.879981,0.879981,0.879981,0.879981,1.52401,1.52401,0.1,0.1,0.707916,0.707916,2.14036,0.638561,0.638561,1.42565,0.1,1.4166,0.79459,0.79459,1.19658,1.19658,1.09717,1.23827,0.863226,2.83807,2.83807,2.83807,2.83807,1.95542,0.1,1.2824,0.870544,1.65391,1.65391,0.1,2.54575,1.67464,0.628517,0.1,1.68385,0.857596,2.00599,2.00599,1.79873,1.79873,0.1,0.1,0.1,2,2,1.69834,0.760295,0.760295,1.57997,1.57997,1.57997,2.78044,1.66652,1.66652,2.30151,1.18541,0.726054,1.77975,1.77975,1.77975,0.748922,2.72298,0.1,1.70614,1.45801,0.773511,0.568521,0.568521,1.87753,0.66548,1.3123,1.55282,0.786597,0.786597,1.66394,1.66394,0.584687,0.122439,0.122439,0.122439,0.122439,1.1057,0.978721,2,2,1.52307,3.29732,1.88321,1.21445", "train/vf_clip_coef": "4.97072,0.01,3.95825,2.5591,2.19215,2.19215,0.01,3.1358,3.1358,3.1358,3.1358,1.76772,1.76772,2.35552,2.35552,4.48411,4.48411,0.01,3.90764,3.90764,0.669834,4.5818,4.46023,5,5,2.67795,2.67795,4.07568,1.01781,1.88089,0.01,0.01,0.01,0.01,1.3333,1.0791,2.87988,1.8183,0.492755,0.492755,1.28551,1.41914,4.46778,2.96866,0.797937,0.706002,4.67613,5,5,1.92867,1.92867,2.50178,3.19767,3.19767,0.2,0.2,0.832437,1.34141,1.34141,1.23244,1.23244,1.23244,0.123435,2.47314,2.47314,3.26495,0.588185,2.40458,3.90833,3.90833,3.90833,0.609537,1.80833,2.80453,4.0608,2.72293,2.24648,5,5,1.33584,0.399627,1.68574,3.49951,1.49874,1.49874,4.14682,4.14682,2.36326,5,5,5,5,4.04969,3.67944,0.2,0.2,1.1778,4.15732,0.619109,0.01", "train/max_grad_norm": "0.451875,1.23339,0.740098,1.82722,1.33301,1.33301,0.48536,0.307511,0.307511,0.307511,0.307511,1.35164,1.35164,1.56726,1.56726,1.1062,1.1062,2.57164,0.1,0.1,1.32373,0.1,0.335321,0.491339,0.491339,0.1,0.1,3.08305,0.854859,2.16709,1.46079,1.46079,1.46079,1.46079,1.00396,1.23516,1.30437,0.93141,1.8835,1.8835,1.12104,1.1206,0.356313,0.137542,2.62612,0.33854,0.811492,0.310282,0.310282,0.396255,0.396255,1.28127,0.709053,0.709053,1.5,1.5,1.90034,2.07759,2.07759,2.18815,2.18815,2.18815,1.63288,2.13476,2.13476,1.61464,3.34224,1.10737,0.329667,0.329667,0.329667,2.79675,1.3051,1.46255,0.1,0.1,1.68671,1.20244,1.20244,1.48454,1.35011,1.40448,0.749521,0.93629,0.93629,0.1,0.1,3.12956,1.0407,1.0407,1.0407,1.0407,0.1,0.362246,1.5,1.5,1.15659,3.6766,2.74079,0.951474", "train/ent_coef": "0.00380838,0.00044948,0.0243558,0.0107361,0.012524,0.012524,0.00613188,0.0135899,0.0135899,0.0135899,0.0135899,0.0293751,0.0293751,0.0410703,0.0410703,0.0343323,0.0343323,0.00228927,0.00344241,0.00344241,0.0765836,0.00490747,0.015841,0.00684385,0.00684385,0.0427335,0.0427335,0.0746886,0.00899074,0.0104231,0.000164882,0.000164882,0.000164882,0.000164882,0.0848553,0.0204028,0.00404319,0.0512621,0.00950734,0.00950734,0.0649669,4.09472e-05,0.00168289,0.0211731,0.00971967,0.0508099,0.0172262,0.00333423,0.00333423,0.00887134,0.00887134,0.0228105,0.028756,0.028756,0.001,0.001,0.000807164,0.00722285,0.00722285,0.0456253,0.0456253,0.0456253,0.0961446,0.0174402,0.0174402,0.0465911,0.00102985,0.00604542,0.0367726,0.0367726,0.0367726,0.00643175,0.0576138,0.0182764,0.0194478,0.00506169,0.0107008,0.102811,0.102811,0.00925102,0.0163888,0.0617642,0.0605014,0.00395348,0.00395348,0.0173898,0.0173898,0.0141148,0.0200437,0.0200437,0.0200437,0.0200437,0.0253021,0.00646395,0.001,0.001,0.084159,0.000157174,0.0184784,0.000308389", "train/beta1": "0.971066,0.987795,0.78449,0.871915,0.889056,0.889056,0.937631,0.918489,0.918489,0.918489,0.918489,0.871163,0.871163,0.854689,0.854689,0.966739,0.966739,0.78774,0.850655,0.850655,0.811336,0.951468,0.811386,0.803713,0.803713,0.780831,0.780831,0.935027,0.881149,0.922279,0.986311,0.986311,0.986311,0.986311,0.893008,0.743283,0.907876,0.702489,0.905046,0.905046,0.882835,0.998976,0.889891,0.84652,0.904543,0.730307,0.952933,0.877926,0.877926,0.918433,0.918433,0.939059,0.942303,0.942303,0.95,0.95,0.916258,0.944475,0.944475,0.763653,0.763653,0.763653,0.834984,0.902684,0.902684,0.912897,0.987714,0.91211,0.942691,0.942691,0.942691,0.829183,0.967014,0.93392,0.863206,0.754697,0.759512,0.871181,0.871181,0.927165,0.811642,0.851519,0.970138,0.919096,0.919096,0.811577,0.811577,0.930756,0.91201,0.91201,0.91201,0.91201,0.954308,0.863726,0.95,0.95,0.936036,0.998185,0.889406,0.981442", "train/beta2": "0.999974,0.999845,0.989888,0.999618,0.99968,0.99968,0.999303,0.964285,0.964285,0.964285,0.964285,0.999951,0.999951,0.988956,0.988956,0.983835,0.983835,0.999798,0.9,0.9,0.999972,0.943046,0.943624,0.9,0.9,0.981351,0.981351,0.924638,0.998967,0.998987,0.993256,0.993256,0.993256,0.993256,0.999939,0.999132,0.999219,0.994689,0.999057,0.999057,0.999947,0.999536,0.986308,0.974326,0.999803,0.998748,0.9,0.9,0.9,0.999831,0.999831,0.999856,0.9,0.9,0.999,0.999,0.999805,0.999852,0.999852,0.999918,0.999918,0.999918,0.997815,0.999445,0.999445,0.994815,0.975852,0.999897,0.907572,0.907572,0.907572,0.999898,0.999828,0.999934,0.9,0.986935,0.996914,0.9,0.9,0.999296,0.999633,0.999827,0.999169,0.99588,0.99588,0.996866,0.996866,0.999646,0.9,0.9,0.9,0.9,0.9,0.971411,0.999,0.999,0.999971,0.997968,0.999979,0.998972", "train/eps": "1.44159e-06,1e-14,1.09691e-08,9.45846e-10,3.341e-10,3.341e-10,1.05633e-12,1.02245e-10,1.02245e-10,1.02245e-10,1.02245e-10,1.83044e-11,1.83044e-11,4.3897e-12,4.3897e-12,1.45937e-07,1.45937e-07,1.91644e-10,1.35214e-10,1.35214e-10,2.33043e-09,1.61168e-12,1.58832e-10,2.03796e-11,2.03796e-11,1.75342e-09,1.75342e-09,0.0001,2.29953e-10,4.81808e-12,4.22661e-12,4.22661e-12,4.22661e-12,4.22661e-12,1.08e-10,1.88945e-10,2.11154e-11,1.90584e-09,2.33174e-08,2.33174e-08,4.3211e-10,5.86864e-11,5.53883e-10,2.22754e-06,1.99904e-12,2.11041e-12,1.91458e-09,2.4183e-09,2.4183e-09,3.47213e-08,3.47213e-08,4.19456e-13,3.42078e-09,3.42078e-09,1e-12,1e-12,1.99555e-10,1.07526e-10,1.07526e-10,5.35604e-12,5.35604e-12,5.35604e-12,1.06394e-11,9.74837e-11,9.74837e-11,1.86031e-07,2.20619e-13,4.11425e-09,4.6046e-09,4.6046e-09,4.6046e-09,3.34605e-10,1.02222e-07,2.64077e-09,6.81695e-10,4.44132e-11,2.08932e-09,6.14189e-07,6.14189e-07,4.42253e-10,5.39452e-11,7.52743e-09,1.10141e-09,7.30017e-12,7.30017e-12,7.75689e-08,7.75689e-08,2.45806e-08,1.18131e-06,1.18131e-06,1.18131e-06,1.18131e-06,6.32337e-09,3.43006e-06,1e-12,1e-12,4.24548e-11,3.43818e-10,9.84197e-12,2.85419e-14", "train/minibatch_size": "4096,32768,16384,8192,16384,16384,32768,16384,16384,16384,16384,8192,8192,16384,16384,32768,32768,16384,16384,16384,16384,16384,16384,16384,16384,16384,16384,16384,16384,8192,16384,16384,16384,16384,16384,32768,8192,8192,16384,16384,8192,8192,32768,32768,16384,4096,16384,32768,32768,16384,16384,32768,16384,16384,32768,32768,16384,16384,16384,16384,16384,16384,4096,32768,32768,32768,16384,32768,16384,16384,16384,32768,16384,8192,16384,32768,8192,32768,32768,8192,32768,8192,16384,16384,16384,32768,32768,16384,16384,16384,16384,16384,16384,32768,32768,32768,16384,16384,16384,65536", "train/horizon": "128,32,16,64,32,32,64,32,32,32,32,64,64,32,32,64,64,64,64,64,32,32,32,32,32,32,32,32,32,64,128,128,128,128,128,128,64,64,128,128,32,32,64,64,64,64,32,64,64,64,64,64,32,32,64,64,64,128,128,32,32,32,64,64,64,16,16,32,32,32,32,64,64,64,32,32,16,32,32,128,32,64,64,32,32,32,32,64,32,32,32,32,32,16,64,64,64,64,64,32", "train/vtrace_rho_clip": "3.15806,1.14358,2.8338,2.00572,2.91716,2.91716,1.96253,2.18336,2.18336,2.18336,2.18336,1.54688,1.54688,2.10825,2.10825,2.88615,2.88615,1.20043,3.63435,3.63435,1.96835,2.37988,3.31289,3.2112,3.2112,3.1918,3.1918,2.82018,2.18681,2.91529,1.60786,1.60786,1.60786,1.60786,1.37465,1.87015,3.26278,2.86104,1.71098,1.71098,3.26829,4.00385,2.80655,1.71398,1.23176,2.11622,1.88953,3.94682,3.94682,2.61753,2.61753,2.27587,3.00596,3.00596,1,1,0.874458,1.69155,1.69155,1.23623,1.23623,1.23623,2.44465,1.8222,1.8222,1.5846,1.73234,2.71254,2.91145,2.91145,2.91145,2.90674,2.17408,1.69155,2.50634,2.72394,2.79553,2.9326,2.9326,2.23579,2.24987,1.88003,3.72081,2.25147,2.25147,2.66035,2.66035,2.86903,2.37178,2.37178,2.37178,2.37178,2.6675,2.21992,1,1,1.04578,4.49234,1.11551,0.467107", "train/vtrace_c_clip": "0.250951,0.1,4.55112,0.1,0.1,0.1,1.34198,2.94738,2.94738,2.94738,2.94738,1.08626,1.08626,2.88126,2.88126,1.98565,1.98565,1.89044,3.07229,3.07229,0.690149,1.10495,2.08836,1.79815,1.79815,4.66058,4.66058,3.42814,0.192887,0.1,1.31654,1.31654,1.31654,1.31654,0.789872,0.1,0.500738,1.06162,0.1,0.1,0.443698,2.39922,0.983223,2.63369,1.11221,0.1,0.857774,1.27965,1.27965,1.17714,1.17714,1.17919,2.44351,2.44351,1,1,1.72542,0.1,0.1,0.641781,0.641781,0.641781,0.1,0.649696,0.649696,4.16939,4.28787,1.24293,1.66148,1.66148,1.66148,0.1,1.2156,1.4167,1.89098,1.06922,1.31755,2.02897,2.02897,0.1,1.29823,0.759388,0.1,1.8556,1.8556,3.03957,3.03957,1.17952,1.9886,1.9886,1.9886,1.9886,2.40221,4.60158,1,1,0.1,1.81452,0.971188,0.949686", "train/prio_alpha": "0.150406,1,0.701765,1,1,1,0.948469,0.612053,0.612053,0.612053,0.612053,0.774035,0.774035,1,1,0.746844,0.746844,0.869603,0.893405,0.893405,1,1,0.732956,0.823525,0.823525,0.578232,0.578232,0.542816,0.945443,0.922429,0.677997,0.677997,0.677997,0.677997,0.805515,1,1,0.922435,1,1,1,0.371861,0.798386,0.526186,0.95867,1,0.823247,1,1,0.966711,0.966711,1,0.659826,0.659826,0.8,0.8,0.752771,0.978847,0.978847,1,1,1,0.79533,0.757321,0.757321,0.800119,0.562184,0.752663,0.786776,0.786776,0.786776,1,1,1,0.64377,0.711744,1,0.905628,0.905628,1,0.908279,1,1,1,1,0.656362,0.656362,0.998946,1,1,1,1,0.849094,0.992482,0.8,0.8,0.762563,0.932685,1,0.755861", "train/prio_beta0": "0.590118,0.0169713,0,0,0.306933,0.306933,0.219324,0.326373,0.326373,0.326373,0.326373,0,0,0.116024,0.116024,0.34268,0.34268,0.41404,0.0454327,0.0454327,0,0.0707473,0.30821,0.201379,0.201379,0,0,0.148089,0.243386,0,0.416183,0.416183,0.416183,0.416183,0.135407,0.0236262,0,0,0.144734,0.144734,0,0.768957,0.238362,0.326327,0.00967258,0,0.168266,0.47664,0.47664,0.0594527,0.0594527,0.220794,0.312652,0.312652,0.2,0.2,0.42691,0.0605175,0.0605175,0,0,0,0.0385879,0,0,0.123019,0.042759,0.253785,0.348617,0.348617,0.348617,0,0,0.0691299,0.522895,0.188456,0.274981,0.557078,0.557078,0.0685229,0.277613,0,0.310146,0.00533708,0.00533708,0.330884,0.330884,0,0.145909,0.145909,0.145909,0.145909,0.238743,0,0.2,0.2,0.081198,0.949475,0.14162,0.0100073", "train/use_rnn": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "no_model_upload": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "tsne1": "31.1238,-4.58634,-12.2497,-13.5702,-13.6304,-13.6304,-4.70187,-12.5838,-12.5838,-12.5838,-12.5838,-13.9958,-13.9958,-13.1023,-13.1023,-14.2291,-14.2291,-3.51299,-11.1764,-11.1764,-15.074,-11.2982,-12.1181,-11.4272,-11.4272,-11.9292,-11.9292,-14.0973,-13.8868,-13.426,-3.07572,-3.07473,-3.07462,-3.07572,-11.7091,-16.4709,-12.8083,-13.1732,-14.6054,-14.6054,-13.679,27.9968,-14.9065,-13.4789,-16.0103,-13.5144,-12.246,-11.3207,-11.3207,-13.5019,-13.5019,-15.7993,-12.9703,-12.9703,-4.52003,-4.52003,-3.68417,-15.2083,-15.2083,-15.483,-15.483,-15.483,-13.2523,-15.238,-15.238,-12.6417,-16.846,-14.7905,-12.2999,-12.2999,-12.2999,-16.097,-13.1366,-11.4227,-11.9894,-13.8884,-12.2574,-12.3262,-12.3262,-12.666,-16.3314,-13.7401,-11.0304,-13.1348,-13.1348,-13.4265,-13.4265,-14.4118,-13.1292,-13.1292,-13.1292,-13.1292,-12.4926,-12.3519,-4.52003,-4.52003,-14.5553,-4.51002,-15.6688,-4.60187", "tsne2": "-15.2984,0.923737,-31.1758,-23.0372,-24.9112,-24.9112,0.882996,-32.6403,-32.6403,-32.6403,-32.6403,-22.1706,-22.1706,-28.5718,-28.5718,-31.9934,-31.9934,4.38818,-35.0195,-35.0195,-22.8823,-34.1533,-33.9632,-35.4853,-35.4853,-31.4545,-31.4545,-35.184,-26.7202,-22.8907,3.53715,3.53723,3.53716,3.53715,-24.2464,-23.7346,-23.3309,-22.1484,-23.397,-23.397,-26.1546,8.36078,-31.5139,-31.8435,-22.9738,-21.1418,-35.9497,-36.4698,-36.4698,-24.0081,-24.0081,-25.1421,-34.9919,-34.9919,2.54384,2.54384,3.91796,-23.6251,-23.6251,-22.1708,-22.1708,-22.1708,-20.8563,-24.648,-24.648,-30.8101,3.54192,-25.2605,-35.0926,-35.0926,-35.0926,-24.0062,-24.048,-25.181,-35.6327,-30.5513,-26.2537,-36.9073,-36.9073,-23.1225,-24.5461,-22.7287,-24.609,-27.051,-27.051,-31.4307,-31.4307,-24.1845,-36.2372,-36.2372,-36.2372,-36.2372,-35.3954,-30.9453,2.54384,2.54384,-22.5078,20.2555,-22.7902,1.58323"}, "connect4": {"SPS": "187769,180372,670639,676622,697571,647237,761550,522425,515804,674084,186553,192906,192144,624699,181802,734199,660317,755086,696958,663795,654117,757541,893831,510883,507167,766733,708429,716189,711388,428001,674737,670852,679080,711927,624834,628401,417498,173388,178688,244529,249898,207254,751587,734231,676363,780698,723886,516307,193875,750559,343686,135508,137489,138316,139741,704876,694593,622865,456302,679119,728325,678104,675382,681103,669036,662765,692816,547198,546869,804992,657192,639909,652148,571445,807481,942358,151839,548696,549854,732179,578318,578899,612598,201982,351384,356187,780852,545487,648502,606291,700246,193296,186915,187283,187312", "agent_steps": "1.96608,4.82509,4.53837,7.55302,1.27795,3.76832,1.27795,1.26157,3.76013,1.27795,2.2487,3.76832,6.25869,2.44122,2.1463,31.7194,1.27795,1.27795,3.76832,5.11181,8.38861,1.27795,3.76832,1.26157,3.76013,1.27795,3.76832,6.25869,8.74906,2.31834,3.80109,6.29146,8.78182,9.96147,1.47456,1.27795,2.58867,6.16038,14.2213,0.393216,1.11411,2.02342,1.27795,3.76832,7.66771,1.27795,3.7847,1.27795,4.25984,3.80109,4.76774,1.67117,4.98074,11.5999,13.2383,1.27795,3.76832,2.32653,5.88186,1.7367,1.27795,3.76832,8.74906,9.96147,9.37165,2.50675,1.27795,8.38861,2.048,3.80109,1.26157,3.76013,6.25869,1.27795,1.27795,3.76832,1.76947,2.42483,1.25338,3.93216,9.04397,15.0405,1.27795,1.34349,2.21594,6.63962,2.78528,1.27795,1.27795,8.74906,1.57286,5.60333,14.4835,20.1851,22.9376", "uptime": "10.4916,26.8357,6.79076,11.2779,1.93756,5.58712,1.80216,2.64607,7.31102,2.00027,12.1247,19.1269,32.0776,3.95687,12.0998,43.7921,1.94579,1.8893,5.24729,7.67327,12.6339,1.8885,4.79549,2.56155,7.4606,1.86258,5.19802,8.75905,12.2861,5.45827,5.62351,9.34164,13.0557,14.7836,2.40452,2.0458,6.14144,35.5273,82.5087,1.67301,4.54544,9.76315,1.74646,5.07752,10.9543,1.78275,5.06621,2.50452,21.45,4.99511,14.4381,12.4889,36.6758,84.7166,96.5079,1.919,5.4266,3.80768,13.1412,2.56664,1.76536,5.35087,12.7285,14.517,13.5856,3.78566,1.92348,15.0422,4.08516,4.92122,2.00591,5.89436,9.90582,2.36248,1.90846,4.64535,11.564,4.2705,2.41737,5.50825,15.539,25.9623,2.17801,6.81621,6.44452,18.9743,3.67462,2.38635,2.04181,14.1672,2.2388,29.0793,74.9021,105.393,120.087", "epoch": "120,294.5,138.5,230.5,19.5,57.5,19.5,77,229.5,19.5,274.5,57.5,95.5,74.5,131,121,39,19.5,57.5,39,64,19.5,57.5,77,229.5,19.5,57.5,95.5,133.5,566,29,48,67,76,45,39,79,47,108.5,6,17,123.5,19.5,57.5,117,39,115.5,19.5,65,29,291,51,152,354,404,19.5,57.5,35.5,359,106,19.5,57.5,133.5,152,71.5,153,39,64,62.5,29,77,229.5,382,39,19.5,57.5,54,74,153,60,276,459,39,82,270.5,810.5,42.5,39,19.5,133.5,48,171,110.5,154,175", "env/perf": "0.811274,0.98927,0.984163,0.99293,0.532775,0.968026,0.286503,0.570624,0.935577,0.0732354,0.892487,0.987052,0.993813,0.835793,0.847529,0.999958,0.707586,0.475636,0.963397,0.989292,0.995875,0.15708,0.892969,0.688917,0.961709,0.476184,0.960614,0.990943,0.995494,0.807767,0.974405,0.991466,0.996208,0.99764,0.739116,0.681234,0.858003,0.995316,0.999891,0.000230543,0.000272703,0.805272,0.538627,0.970354,0.992352,0.569282,0.954191,0.681029,0.989147,0.929456,0.985475,0.790888,0.998911,0.9999,0.999916,0.58475,0.944389,0.788841,0.992599,0.772312,0.652198,0.942233,0.995997,0.996954,0.996425,0.856362,0.576667,0.99784,0.783504,0.934354,0.642698,0.982532,0.991872,0.679277,0.383106,0.871138,0.824258,0.840984,0.524788,0.974558,0.999811,0.999929,0.699125,0.780212,0.890785,0.995519,0.79999,0.655706,0.646204,0.996501,0.73324,0.989943,0.999918,0.999983,1", "env/score": "0.622549,0.97854,0.968327,0.98586,0.0655492,0.936052,-0.426993,0.141248,0.871154,-0.853529,0.784974,0.974104,0.987625,0.671586,0.695058,0.999915,0.415173,-0.0487274,0.926795,0.978584,0.99175,-0.68584,0.785937,0.377834,0.923418,-0.0476327,0.921229,0.981885,0.990988,0.615534,0.94881,0.982933,0.992415,0.99528,0.478232,0.362468,0.716006,0.990632,0.999783,-0.999539,-0.999455,0.610543,0.0772542,0.940708,0.984705,0.138563,0.908382,0.362059,0.978294,0.858912,0.970949,0.581776,0.997821,0.999801,0.999832,0.169499,0.888777,0.577681,0.985197,0.544623,0.304396,0.884466,0.991994,0.993908,0.99285,0.712724,0.153333,0.99568,0.567008,0.868707,0.285397,0.965063,0.983744,0.358555,-0.233787,0.742276,0.648516,0.681967,0.0495755,0.949116,0.999622,0.999857,0.39825,0.560423,0.781569,0.991039,0.599981,0.311411,0.292409,0.993003,0.466479,0.979886,0.999836,0.999966,1", "env/episode_return": "0.622549,0.97854,0.968327,0.98586,0.0655492,0.936052,-0.426993,0.141248,0.871154,-0.853529,0.784974,0.974104,0.987625,0.671586,0.695058,0.999915,0.415173,-0.0487274,0.926795,0.978584,0.99175,-0.68584,0.785937,0.377834,0.923418,-0.0476327,0.921229,0.981885,0.990988,0.615534,0.94881,0.982933,0.992415,0.99528,0.478232,0.362468,0.716006,0.990632,0.999783,-0.999539,-0.999455,0.610543,0.0772542,0.940708,0.984705,0.138563,0.908382,0.362059,0.978294,0.858912,0.970949,0.581776,0.997821,0.999801,0.999832,0.169499,0.888777,0.577681,0.985197,0.544623,0.304396,0.884466,0.991994,0.993908,0.99285,0.712724,0.153333,0.99568,0.567008,0.868707,0.285397,0.965063,0.983744,0.358555,-0.233787,0.742276,0.648516,0.681967,0.0495755,0.949116,0.999622,0.999857,0.39825,0.560423,0.781569,0.991039,0.599981,0.311411,0.292409,0.993003,0.466479,0.979886,0.999836,0.999966,1", "env/episode_length": "11.8877,10.1873,12.0478,11.9304,13.2028,12.1498,12.5892,13.7346,12.9105,10.5785,11.3939,10.4205,10.3339,12.5737,10.8411,10.1355,10.5783,13.4203,11.9124,11.033,10.8137,11.3284,16.6182,11.1593,9.77472,13.8511,12.5182,11.9733,11.9132,11.6468,11.5835,10.9773,10.893,10.9165,11.5889,10.5194,11.0094,10.6419,10.548,6.80364,6.76997,12.11,13.5411,14.0926,12.8688,13.3511,11.3897,10.7714,10.1965,11.7437,15.9946,10.3384,10.0005,10.0001,9.99992,13.6045,13.5498,12.5186,9.96595,11.7697,12.1924,10.9764,10.7682,10.7704,11.3447,9.93356,11.8606,9.99228,11.3041,12.9006,11.008,9.94273,9.81478,12.6538,15.0915,18.9229,12.213,12.1119,11.8143,11.9726,11.9938,11.9975,13.106,12.1919,9.82787,10.0006,12.7819,12.0192,11.9203,10.4516,12.5988,10.1825,9.50186,9.50056,9.49756", "env/n": "1283.35,1465.21,2511.52,2534.22,4831.24,4988.37,5108.24,1156.57,1181.43,5885.18,664.644,5739.05,5782.26,2440.31,1392.99,23553,2843.97,4762.87,5079.92,10900.3,11095.4,5690.71,3720.53,1378.82,1520.75,4660.71,4857,5052,5075.42,326.368,10427.8,10949.5,11019.7,11018,2646.85,2874.43,2754.83,11259,11350.1,8205.55,8412.36,1270.35,4716.97,4343.63,4727.62,2374.77,2647.63,5624.87,5853.51,10322.9,964.337,2930.76,2978.81,2979.05,11900,4668.39,4511.79,4934.1,1494.08,1291.09,5091.21,5473.95,5568.5,11163,10618.6,1510.64,2609.57,11925.5,2696.29,9445.21,1400.08,1497.41,1514.9,2467.22,4450.13,3289.34,2511.25,2529.49,656.603,5052.08,2521.71,2521.15,2389.48,1263.98,759.337,744.728,4832.7,2551.74,5199.21,5723.55,2452.23,2930.31,12480.5,12482.6,12501", "perf/rollout": "0.0841646,0.0824792,0.0449158,0.0444724,0.0833585,0.0890284,0.0786308,0.0284358,0.0280768,0.0882039,0.0423005,0.318446,0.320247,0.0437118,0.0849361,0.333078,0.042807,0.0839971,0.0879652,0.172164,0.175246,0.0850059,0.0692071,0.0295958,0.0293224,0.079605,0.0831609,0.0830439,0.0831289,0.0092092,0.169954,0.171072,0.169217,0.159493,0.0447479,0.0441712,0.0611258,0.706815,0.684819,0.159509,0.152176,0.075541,0.0814086,0.0827872,0.0863126,0.0407007,0.0426702,0.113676,0.316393,0.152552,0.0461124,0.173848,0.169568,0.168193,0.165896,0.0817341,0.0812763,0.0821631,0.0314526,0.0216764,0.0783738,0.0835615,0.0839591,0.0830681,0.174664,0.0222527,0.0450839,0.218852,0.0548474,0.14492,0.0233026,0.0237534,0.0234414,0.0533124,0.072098,0.0551018,0.164905,0.054578,0.0140826,0.0792982,0.0467334,0.0472548,0.0448777,0.0783087,0.0223664,0.0217577,0.0738534,0.0528309,0.0809229,0.0856885,0.0396631,0.158649,0.639263,0.637805,0.637695", "perf/eval_gpu": "0.00141956,0.00244912,0.00113228,0.00112282,0.00247504,0.00222676,0.00145053,0.000619495,0.000595616,0.000822394,0.000904856,0.00552044,0.00552725,0.00112265,0.00393065,0.00450199,0.00123396,0.00129364,0.00113647,0.00133616,0.00131885,0.00251863,0.00224127,0.00114543,0.0010963,0.0014008,0.00131776,0.00127338,0.00127464,0.000272717,0.00118218,0.00119239,0.00115595,0.00115293,0.00218243,0.00120461,0.00290314,0.0190796,0.0189716,0.00327734,0.00318567,0.00241085,0.00135552,0.00117026,0.00128299,0.00255994,0.00230559,0.00145606,0.00275764,0.00260649,0.00189511,0.00806667,0.00788172,0.00788873,0.0078846,0.00132299,0.00114472,0.000772498,0.0016618,0.000610165,0.00144856,0.00134349,0.00131296,0.00139978,0.00252352,0.0010693,0.000684855,0.00266402,0.00124325,0.0022296,0.00115717,0.00111999,0.00111604,0.00384018,0.00262141,0.00234589,0.00596628,0.00218147,0.000567803,0.00215522,0.0011072,0.00134606,0.0025968,0.00205025,0.00125073,0.00101681,0.00132173,0.00060622,0.00143392,0.00132518,0.00120919,0.00386338,0.0111563,0.0112322,0.0111789", "perf/eval_env": "0.0824365,0.0794431,0.0421811,0.0420785,0.0784085,0.0843222,0.0743265,0.0265284,0.0266691,0.0827779,0.0411024,0.311697,0.313494,0.0403058,0.0804196,0.324563,0.0398309,0.0787497,0.0844845,0.167003,0.167956,0.0779904,0.0644952,0.0266389,0.0269018,0.0734211,0.0759975,0.0776655,0.0785838,0.00834673,0.164369,0.165417,0.161438,0.153616,0.0398879,0.0411349,0.0552772,0.68291,0.661148,0.147494,0.143949,0.0725304,0.0767662,0.0788564,0.0830811,0.0353414,0.0384876,0.106546,0.312966,0.146742,0.0426203,0.16459,0.160531,0.159155,0.156872,0.0759985,0.0770542,0.0768713,0.0278175,0.0199756,0.0738967,0.0800656,0.0805476,0.0806399,0.168423,0.0199907,0.0415695,0.213844,0.049328,0.139408,0.0205761,0.0205769,0.0207621,0.0428635,0.0637912,0.0504762,0.157724,0.0406663,0.012557,0.0745228,0.0430792,0.0431143,0.0394247,0.0748019,0.0201767,0.0200236,0.0696896,0.0508128,0.0760131,0.0817377,0.0368774,0.152003,0.62568,0.624173,0.624113", "perf/train_misc": "0.00038431,0.000448442,0.000413461,0.000413721,0.00127869,0.00101975,0.00114543,0.000336194,0.000313327,0.00147601,0.000157103,0.00108596,0.00108316,0.00110102,0.000505611,0.00285786,0.000747934,0.000941152,0.000741103,0.0036528,0.00366162,0.000503782,0.000387917,0.000235289,0.000216925,0.000905029,0.000689955,0.000691827,0.000688596,7.51104e-05,0.00455667,0.00455352,0.00454162,0.00462234,0.000947676,0.000875766,0.00109863,0.00501257,0.00504109,0.0101083,0.00501193,0.000312227,0.00103746,0.000784848,0.000806521,0.000286108,0.000252786,0.00197601,0.00212247,0.00164701,0.000162421,0.000821255,0.000746622,0.00074545,0.000732992,0.00244368,0.00186949,0.00517322,0.000316756,0.000328041,0.00166819,0.00131101,0.00131249,0.00128723,0.00273258,0.000247076,0.00041664,0.00216884,0.000618742,0.00232486,0.000169685,0.000156397,0.000156362,0.000630418,0.000623308,0.000474163,0.0015678,0.000997404,0.000100428,0.00103756,0.0010965,0.00109532,0.000923907,0.000249228,0.000113573,0.000111892,0.00128792,0.00132577,0.00296347,0.00230625,0.000660256,0.00105789,0.00390986,0.00390273,0.00392893", "perf/train_forward": "0.00317894,0.00777699,0.00336279,0.00336171,0.0135949,0.0109578,0.00973716,0.00348869,0.00324248,0.0114797,0.00137772,0.0196,0.0196016,0.00858902,0.00552368,0.0207299,0.00697885,0.00657721,0.00520124,0.0214179,0.0214154,0.00462946,0.00364791,0.00280845,0.00260781,0.0105368,0.00825489,0.00825134,0.00825277,0.000243432,0.0195815,0.0195775,0.0195566,0.0197263,0.008272,0.0081594,0.0194535,0.04396,0.0439586,0.21043,0.104846,0.0039087,0.00710946,0.00553729,0.00952264,0.00242458,0.00215061,0.0170159,0.019576,0.0204263,0.00127859,0.0747944,0.0676071,0.0677154,0.0676272,0.0139982,0.0110411,0.0231394,0.00455799,0.0021833,0.0144129,0.0115984,0.0115846,0.0115845,0.0183197,0.00221475,0.00241508,0.0181969,0.0070125,0.0154851,0.00185321,0.00171292,0.00171235,0.00638002,0.0177541,0.0138127,0.0549368,0.008765,0.000862986,0.00898125,0.00865652,0.00865556,0.00996508,0.00301424,0.001016,0.000988047,0.0109817,0.00702756,0.0247811,0.0199149,0.00750623,0.00967002,0.0579437,0.0579371,0.0580731", "perf/train": "0.00356325,0.00822544,0.00377625,0.00377543,0.0148736,0.0119775,0.0108826,0.00382489,0.0035558,0.0129557,0.00153482,0.020686,0.0206847,0.00969004,0.00602929,0.0235877,0.00772679,0.00751836,0.00594235,0.0250707,0.025077,0.00513324,0.00403582,0.00304374,0.00282474,0.0114418,0.00894484,0.00894317,0.00894137,0.000318542,0.0241381,0.024131,0.0240982,0.0243487,0.00921968,0.00903516,0.0205521,0.0489725,0.0489997,0.220539,0.109858,0.00422092,0.00814691,0.00632214,0.0103292,0.00271069,0.0024034,0.0189919,0.0216984,0.0220733,0.00144101,0.0756157,0.0683537,0.0684608,0.0683602,0.0164419,0.0129106,0.0283127,0.00487474,0.00251134,0.0160811,0.0129094,0.0128971,0.0128717,0.0210523,0.00246182,0.00283172,0.0203657,0.00763124,0.01781,0.00202289,0.00186932,0.00186871,0.00701044,0.0183774,0.0142869,0.0565046,0.0097624,0.000963414,0.0100188,0.00975302,0.00975088,0.010889,0.00326347,0.00112957,0.00109994,0.0122696,0.00835333,0.0277446,0.0222212,0.00816648,0.0107279,0.0618536,0.0618398,0.062002", "util/gpu_percent": "6.69456,11.3367,20,20.7391,19.8158,23.8947,32.2632,16.8497,19.5263,12.8947,5.2573,7.71053,8.05263,27.3581,11.3985,17,22.6883,11.7632,12.5526,27.92,9.72,15.7105,22.1579,20.1895,22.8618,20.4211,16.8947,18.3421,17.1316,11.2812,12.1579,27.8421,10.2105,18,37.3483,24.0779,35.758,10.6452,9.33333,59,50.2727,8.31707,17.4474,13.7632,19.2553,28.0649,29.9868,32.3684,6.25581,26.7368,12.2176,35.7426,34.1683,30.0396,5,38.8947,20.2105,24.5857,25.8577,24.1848,21.2632,21,21.2632,21,12.25,32.2,11.039,14.96,23.2097,15.5263,26.4444,29.5658,30.7516,31.4416,39.7368,40.2105,25.6542,31.1088,19.4033,23.7179,26.776,25.847,34.3506,7.3681,15.9333,17.487,23.3452,16.5195,23.0526,27.9474,28.6947,9.89381,7.20455,8.65116,4", "util/gpu_mem": "20.4901,4.23816,5.19078,5.19078,5.40847,5.41875,5.40033,4.80725,4.8081,5.62745,19.7563,4.70226,4.70226,5.1076,20.6675,22.7933,5.19554,5.20963,5.22335,22.2315,22.2315,5.57131,5.58159,5.01894,5.0198,5.72129,5.72815,5.72815,5.72815,4.51465,5.28034,5.28034,5.28034,5.28034,5.30477,21.9496,20.7501,4.70226,4.70226,7.28327,7.28327,4.26259,5.36219,5.38619,5.72815,21.1615,21.1649,5.07936,4.14046,5.98055,4.38472,6.61563,6.61563,6.61563,6.61563,5.13164,5.14193,5.12355,20.5866,4.99352,5.35576,5.41061,5.41061,5.41061,5.47575,5.17449,5.25898,22.0523,17.283,5.47575,5.33733,5.33733,5.33733,21.1432,6.56806,6.57492,4.83253,5.30477,21.7022,5.41875,5.10936,5.10936,5.21489,4.44171,4.53918,4.53942,5.40441,4.72161,5.20878,5.23963,5.35902,21.0672,4.85696,4.85696,4.85696", "util/vram_used_gb": "4.45411,0.555542,0.784058,0.784058,0.836278,0.838745,0.834325,0.692056,0.692261,0.888807,4.27808,0.66687,0.66687,0.764104,4.49666,5.00659,0.785199,0.788581,0.79187,4.87183,4.87183,0.875341,0.877808,0.742838,0.743042,0.911319,0.912964,0.912964,0.912964,0.621865,0.805542,0.805542,0.805542,0.805542,0.811401,4.8042,4.51647,0.66687,0.66687,1.28601,1.28601,0.561401,0.825176,0.830933,0.912964,4.61516,4.61597,0.757331,0.532104,0.973511,0.590698,1.12585,1.12585,1.12585,1.12585,0.769872,0.772339,0.76793,4.47725,0.736738,0.823634,0.836792,0.836792,0.836792,0.852417,0.780151,0.800418,4.82886,3.68477,0.852417,0.819214,0.819214,0.819214,4.61078,1.11444,1.11609,0.69812,0.811401,4.74487,0.838745,0.764526,0.764526,0.789841,0.60437,0.62775,0.627808,0.835304,0.671512,0.788375,0.795776,0.824415,4.59253,0.703979,0.703979,0.703979", "util/vram_total_gb": "23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272", "util/cpu_mem_gb": "1.00149,1.08719,1.10194,1.10235,1.11717,1.11717,1.10312,1.08414,1.08427,1.0899,0.998818,1.08868,1.08868,1.10062,1.0044,1.09906,1.10188,1.09811,1.0982,1.01949,1.01949,1.12333,1.12333,1.09517,1.09517,1.1004,1.1004,1.1004,1.1004,1.08054,1.1007,1.1007,1.1007,1.1007,1.12267,1.02066,1.01102,1.12575,1.12575,1.08572,1.08572,1.0841,1.10226,1.10226,1.10024,1.04133,1.04133,1.09632,1.08413,1.12257,1.09306,1.09269,1.09269,1.09269,1.09269,1.09919,1.09919,1.0906,1.00482,1.09013,1.09948,1.09948,1.09948,1.09948,1.12404,1.09881,1.08925,1.03124,1.01651,1.12381,1.09996,1.10051,1.10051,1.04266,1.11843,1.11843,1.10892,1.12066,1.00636,1.1226,1.1001,1.10015,1.116,1.09168,1.08768,1.08878,1.09989,1.08637,1.10543,1.10543,1.10275,1.01985,1.09935,1.09935,1.09935", "wandb": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "rank": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "world_size": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "gpu_id": "0,1,3,3,3,3,3,1,1,5,0,2,2,3,0,0,3,1,1,0,0,4,4,5,5,2,2,2,2,4,2,2,2,2,3,0,0,3,3,4,4,2,4,4,3,0,0,1,5,3,4,1,1,1,1,2,2,4,0,5,3,3,3,3,3,5,4,0,0,1,1,1,1,0,4,4,3,4,0,2,3,3,3,4,4,4,1,4,3,3,3,0,1,1,1", "profile": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "checkpoint_interval": "200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200", "eval_episodes": "10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000", "cudagraphs": "10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10", "seed": "73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73", "vec/total_agents": "512,256,1024,1024,1024,1024,2048,1024,1024,4096,256,512,512,1024,256,2048,1024,2048,2048,4096,4096,1024,1024,512,512,2048,2048,2048,2048,512,4096,4096,4096,4096,512,1024,1024,256,256,8192,8192,256,2048,2048,2048,512,512,2048,1024,2048,256,256,256,256,256,2048,2048,4096,1024,1024,2048,2048,2048,2048,2048,512,2048,2048,1024,2048,512,512,512,512,1024,1024,256,512,512,1024,1024,1024,512,256,256,256,2048,2048,2048,2048,1024,256,512,512,512", "vec/num_buffers": "1,1.6385,8,8,7.00811,7.00811,8,5.5245,5.5245,8,1.93594,1,1,8,1.28547,8,8,7.80691,7.80691,8,8,8,8,6.27463,6.27463,8,8,8,8,5.59686,8,8,8,8,8,8,6.46258,1.06588,1.06588,5.48402,5.48402,1,8,8,8,8,8,6.93623,1,8,3.83979,1.74544,1.74544,1.74544,1.74544,8,8,8,6.42249,8,8,8,8,8,8,8,8,6.55504,7.16565,8,8,8,8,8,8,8,1.92549,8,6.51592,8,8,8,7.70015,2.42998,4.80314,4.80314,8,6.57305,8,8,8,2.66067,1,1,1", "vec/num_threads": "2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2", "env/num_agents": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "env/player_pieces": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "env/env_pieces": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "policy/hidden_size": "128,256,128,128,256,256,256,256,256,256,128,512,512,128,256,64,256,128,128,256,256,128,128,256,256,256,256,256,256,128,128,128,128,128,128,256,512,256,256,512,512,256,128,128,256,128,128,256,256,256,128,1024,1024,1024,1024,128,128,256,512,64,256,256,256,256,128,128,128,256,256,128,256,256,256,256,512,512,1024,128,256,128,128,128,256,256,256,256,256,128,128,128,256,128,512,512,512", "policy/num_layers": "1,2.24893,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1.54565,1.54565,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,6.31197,6.31197,1,1,1,1,1.28066,1.28066,1.0097,1,1,1,2.07449,2.07449,2.07449,2.07449,1,1,1,1,1.43055,1,1,1,1,1,1.28635,1.40236,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1.11137,1.14354,1,1,1,1.12177,2.38299,2.38299,1,1.68964,1,1,1", "policy/expansion_factor": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "legacy/torch_deterministic": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "legacy/cpu_offload": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "legacy/compile": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "legacy/compile_fullgraph": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "train/gpus": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "train/seed": "42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42", "train/total_timesteps": "15.6612,12.8499,12.0378,12.0378,10,10,10,10,10,10,17.9628,10,10,19.3099,17.0841,31.8957,10,10,10,13.2723,13.2723,10,10,10,10,10,10,10,10,18.5254,10,10,10,10,11.6827,10.0156,20.506,16.1958,16.1958,13.8069,13.8069,16.1249,10,10,12.2194,10,10,10,11.2682,10.0457,12.6782,13.2472,13.2472,13.2472,13.2472,10,10,18.3222,15.6716,13.8368,10,10,10,10,10.7354,19.9397,10,13.2623,16.1771,10,10,10,10,10,10,10,13.9806,19.1769,10,10.3659,24.0441,24.0441,10,10.6712,17.694,17.694,21.8516,10,10,10,12.4078,14.8643,23.0093,23.0093,23.0093", "train/learning_rate": "0.0630302,0.0402848,0.0184006,0.0184006,0.0220417,0.0220417,0.0121421,0.0138344,0.0138344,0.00646975,0.0809812,0.0119934,0.0119934,0.0187688,0.0199769,0.0367783,0.1,0.0343975,0.0343975,0.00847027,0.00847027,0.0185719,0.0185719,0.0490544,0.0490544,0.0211927,0.0211927,0.0211927,0.0211927,0.1,0.0180168,0.0180168,0.0180168,0.0180168,0.052834,0.0665443,0.0356982,0.0381015,0.0381015,0.0466112,0.0466112,0.0387654,0.0349966,0.0349966,0.0208469,0.0697316,0.0697316,0.0744309,0.00755324,0.0256026,0.0283517,0.0299094,0.0299094,0.0299094,0.0299094,0.0220394,0.0220394,0.0187447,0.0270148,0.1,0.041727,0.041727,0.041727,0.041727,0.0172698,0.0783978,0.0298397,0.00916653,0.034986,0.0213659,0.0373563,0.0373563,0.0373563,0.0186676,0.0385026,0.0385026,0.0165879,0.0195338,0.0294486,0.0159036,0.00274585,0.00274585,0.0204129,0.1,0.0565587,0.0565587,0.026706,0.025501,0.019844,0.019844,0.0512872,0.035176,0.0118399,0.0118399,0.0118399", "train/anneal_lr": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "train/min_lr_ratio": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "train/gamma": "0.870946,0.929583,0.8,0.8,0.884752,0.884752,0.8,0.8,0.8,0.8,0.966871,0.8,0.8,0.916575,0.846749,0.84882,0.8,0.80178,0.80178,0.8,0.8,0.963227,0.963227,0.8,0.8,0.8,0.8,0.8,0.8,0.925237,0.909485,0.909485,0.909485,0.909485,0.808144,0.885675,0.806449,0.966788,0.966788,0.998935,0.998935,0.873415,0.8,0.8,0.801885,0.853734,0.853734,0.855754,0.858587,0.8,0.955957,0.8,0.8,0.8,0.8,0.887193,0.887193,0.8,0.955751,0.8,0.800675,0.800675,0.800675,0.800675,0.915738,0.8,0.8,0.8,0.8,0.905881,0.8,0.8,0.8,0.923279,0.990301,0.990301,0.847045,0.938068,0.8,0.89148,0.957507,0.957507,0.8,0.8491,0.970829,0.970829,0.899871,0.8,0.86579,0.86579,0.8,0.95712,0.842123,0.842123,0.842123", "train/gae_lambda": "0.906587,0.930142,0.931576,0.931576,0.931037,0.931037,0.911727,0.836196,0.836196,0.981595,0.979153,0.928177,0.928177,0.95687,0.971706,0.883035,0.849897,0.976429,0.976429,0.962627,0.962627,0.893443,0.893443,0.820321,0.820321,0.845586,0.845586,0.845586,0.845586,0.958804,0.900115,0.900115,0.900115,0.900115,0.941731,0.964146,0.964493,0.983489,0.983489,0.820069,0.820069,0.853055,0.948472,0.948472,0.976332,0.830839,0.830839,0.987757,0.961817,0.943969,0.951474,0.983037,0.983037,0.983037,0.983037,0.825544,0.825544,0.953383,0.990527,0.971196,0.852855,0.852855,0.852855,0.852855,0.954313,0.816791,0.965603,0.962919,0.939211,0.94437,0.90238,0.90238,0.90238,0.979557,0.912077,0.912077,0.985617,0.966549,0.906306,0.927367,0.910565,0.910565,0.955613,0.817044,0.986395,0.986395,0.922463,0.853141,0.818382,0.818382,0.989232,0.974683,0.970792,0.970792,0.970792", "train/replay_ratio": "2.90685,3.46583,2.97987,2.97987,2.89396,2.89396,2.33001,4,4,3.72895,2.71576,2.63989,2.63989,3.86578,3.6439,2.62958,2.458,3.55245,3.55245,3.16619,3.16619,2.11609,2.11609,3.15691,3.15691,3.42527,3.42527,3.42527,3.42527,1.98259,4,4,4,4,3.08657,2.78358,3.52388,2.61191,2.61191,2.63007,2.63007,4,3.76946,3.76946,3.7871,1.50175,1.50175,3.99704,3.23097,3.66015,1.18263,3.85902,3.85902,3.85902,3.85902,2.58505,2.58505,4,2.77178,4,3.48428,3.48428,3.48428,3.48428,3.24632,3.71712,3.00888,2.38969,3.81356,2.71282,2.33124,2.33124,2.33124,1.99593,2.74635,2.74635,3.80936,3.2629,2.96949,3.20306,4,4,3.04271,3.32686,1.53649,1.53649,2.91466,3.20115,3.22712,3.22712,4,3.08621,3.22803,3.22803,3.22803", "train/clip_coef": "0.216327,0.01,0.709302,0.709302,0.503242,0.503242,0.628893,0.586456,0.586456,0.767251,0.274943,0.487222,0.487222,0.432337,0.585187,0.852559,0.656729,0.670123,0.670123,0.511829,0.511829,0.753235,0.753235,0.919547,0.919547,0.542822,0.542822,0.542822,0.542822,0.302228,0.302874,0.302874,0.302874,0.302874,0.364746,0.848948,0.560423,0.258937,0.258937,0.961149,0.961149,0.138275,0.624279,0.624279,0.635597,0.258748,0.258748,0.709113,0.464588,0.693504,0.23381,0.398193,0.398193,0.398193,0.398193,0.492824,0.492824,0.487254,0.721774,0.481425,0.649563,0.649563,0.649563,0.649563,0.599847,0.542199,0.669116,0.797742,0.486336,0.718476,0.78167,0.78167,0.78167,0.391754,0.561095,0.561095,0.660707,0.629369,0.626597,0.694331,0.449886,0.449886,0.523384,0.1938,0.29557,0.29557,0.760175,0.748423,0.810324,0.810324,0.47642,0.238193,0.562679,0.562679,0.562679", "train/vf_coef": "3.3318,2.18366,4.79364,4.79364,4.80603,4.80603,5,2.88562,2.88562,5,2.65002,4.21863,4.21863,5,3.19012,4.01201,4.88708,4.67622,4.67622,5,5,5,5,3.83999,3.83999,3.64601,3.64601,3.64601,3.64601,0.733243,5,5,5,5,4.56455,4.47157,4.95769,3.27547,3.27547,0.777844,0.777844,2.60633,4.36665,4.36665,4.47548,4.79317,4.79317,3.93273,3.27382,5,0.942288,2.12033,2.12033,2.12033,2.12033,5,5,5,5,5,3.66871,3.66871,3.66871,3.66871,5,3.77895,5,5,4.05935,4.78669,3.40828,3.40828,3.40828,4.85641,4.8554,4.8554,2.55475,5,5,5,5,5,2.91915,3.34377,1.00258,1.00258,5,5,5,5,4.61546,1.772,3.15129,3.15129,3.15129", "train/vf_clip_coef": "0.701642,0.01,1.74856,1.74856,2.6196,2.6196,0.174615,0.610622,0.610622,1.1462,0.01,0.934893,0.934893,1.79995,0.01,1.28578,0.77266,0.90115,0.90115,1.99178,1.99178,0.0809315,0.0809315,2.68158,2.68158,1.04718,1.04718,1.04718,1.04718,0.01,3.11012,3.11012,3.11012,3.11012,0.969347,2.61769,2.3215,1.19302,1.19302,1.13611,1.13611,1.15563,2.26112,2.26112,2.11947,0.866284,0.866284,1.10154,0.01,2.69213,0.01,0.0576325,0.0576325,0.0576325,0.0576325,1.13438,1.13438,1.532,2.25087,2.89552,2.00652,2.00652,2.00652,2.00652,2.22064,0.887248,2.45394,1.65714,0.847646,0.332072,1.26155,1.26155,1.26155,1.54603,2.57692,2.57692,0.464315,2.7644,2.07619,1.6916,3.35235,3.35235,1.26584,0.01,0.01,0.01,1.31864,0.993666,2.76904,2.76904,2.98634,0.01,0.513174,0.513174,0.513174", "train/max_grad_norm": "2.11616,2.69921,2.0866,2.0866,1.44015,1.44015,2.12632,2.55974,2.55974,1.74894,5,3.73587,3.73587,2.9936,3.34842,2.52444,2.17418,0.383265,0.383265,0.552251,0.552251,3.5207,3.5207,2.42855,2.42855,2.85305,2.85305,2.85305,2.85305,2.65838,1.57878,1.57878,1.57878,1.57878,2.8032,1.23368,4.11326,4.40143,4.40143,3.90937,3.90937,1.95455,2.9109,2.9109,0.935458,2.4475,2.4475,0.230859,5,0.1,1.92209,4.67767,4.67767,4.67767,4.67767,3.27323,3.27323,1.23536,2.79825,1.56546,1.8567,1.8567,1.8567,1.8567,2.28002,2.57998,2.04307,3.11731,2.01619,1.72577,1.86144,1.86144,1.86144,3.09033,1.62966,1.62966,3.08468,3.67203,2.47233,2.19673,2.2241,2.2241,1.06937,2.56084,3.12085,3.12085,0.1,2.80857,3.36412,3.36412,0.1,3.3565,4.28656,4.28656,4.28656", "train/ent_coef": "0.0182941,0.00747087,0.00264033,0.00264033,0.000150109,0.000150109,0.0109092,0.00290661,0.00290661,5.71915e-05,0.0214302,0.00154664,0.00154664,0.000413018,0.000226245,0.00521465,0.0011742,0.00467953,0.00467953,3.24222e-05,3.24222e-05,0.00671011,0.00671011,0.00578578,0.00578578,0.000922445,0.000922445,0.000922445,0.000922445,0.0287466,3.63768e-05,3.63768e-05,3.63768e-05,3.63768e-05,5.74717e-05,0.00329322,0.00126934,0.00420683,0.00420683,2.00038e-05,2.00038e-05,0.00175002,0.000520561,0.000520561,0.000289507,9.67563e-05,9.67563e-05,4.88402e-05,0.00949843,0.00297759,0.00344796,0.00342386,0.00342386,0.00342386,0.00342386,0.00720725,0.00720725,0.00345135,0.0378194,0.00837018,0.012245,0.012245,0.012245,0.012245,0.00420049,0.00773537,0.0005373,0.00831526,0.033352,0.00855501,0.0412477,0.0412477,0.0412477,0.000657787,0.000279799,0.000279799,0.0026852,0.00781832,0.00257424,0.0113859,0.0113356,0.0113356,0.00133439,0.000287665,0.0190346,0.0190346,0.0181807,0.0223913,0.0211736,0.0211736,0.00198813,0.00614566,0.000952628,0.000952628,0.000952628", "train/beta1": "0.5,0.542704,0.848052,0.848052,0.5,0.5,0.540076,0.5,0.5,0.701638,0.5,0.719449,0.719449,0.745269,0.5,0.5,0.5,0.5,0.5,0.878636,0.878636,0.5,0.5,0.5,0.5,0.743433,0.743433,0.743433,0.743433,0.5,0.792967,0.792967,0.792967,0.792967,0.5,0.5,0.5,0.5,0.5,0.990143,0.990143,0.5,0.553537,0.553537,0.77477,0.575109,0.575109,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.595915,0.595915,0.5,0.507429,0.5,0.652552,0.652552,0.652552,0.652552,0.740731,0.5,0.745365,0.656961,0.5,0.5,0.700143,0.700143,0.700143,0.677028,0.5,0.5,0.5,0.577481,0.625625,0.5,0.574821,0.574821,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.542312,0.542312,0.542312", "train/beta2": "0.998222,0.976609,0.975388,0.975388,0.9,0.9,0.96173,0.94924,0.94924,0.9,0.999758,0.995263,0.995263,0.999228,0.998714,0.99269,0.967863,0.99166,0.99166,0.986336,0.986336,0.996532,0.996532,0.961319,0.961319,0.9,0.9,0.9,0.9,0.999493,0.997935,0.997935,0.997935,0.997935,0.973692,0.989229,0.9,0.994826,0.994826,0.997414,0.997414,0.999545,0.989534,0.989534,0.9,0.988898,0.988898,0.907136,0.993675,0.985249,0.982909,0.990252,0.990252,0.990252,0.990252,0.980166,0.980166,0.989799,0.995089,0.991922,0.9,0.9,0.9,0.9,0.995243,0.999189,0.959236,0.998255,0.9,0.992167,0.9,0.9,0.9,0.9,0.9,0.9,0.942805,0.972364,0.961365,0.995776,0.947287,0.947287,0.993768,0.978417,0.998733,0.998733,0.948518,0.997901,0.996226,0.996226,0.9,0.998663,0.988503,0.988503,0.988503", "train/eps": "8.23139e-08,2.27365e-09,0.0001,0.0001,1.36384e-05,1.36384e-05,0.0001,1.61639e-05,1.61639e-05,1.81264e-05,6.63573e-08,2.91513e-11,2.91513e-11,0.0001,6.98735e-08,8.4227e-05,2.78107e-05,1.29931e-05,1.29931e-05,3.02623e-07,3.02623e-07,0.0001,0.0001,0.0001,0.0001,0.0001,0.0001,0.0001,0.0001,1.52734e-05,2.65074e-09,2.65074e-09,2.65074e-09,2.65074e-09,0.0001,0.0001,2.70371e-05,4.59122e-11,4.59122e-11,2.84097e-09,2.84097e-09,2.28211e-07,0.0001,0.0001,2.86585e-05,2.93106e-05,2.93106e-05,3.16384e-05,6.03118e-11,0.0001,0.0001,9.76874e-09,9.76874e-09,9.76874e-09,9.76874e-09,0.0001,0.0001,4.1062e-06,2.66699e-05,6.21783e-05,1.66529e-06,1.66529e-06,1.66529e-06,1.66529e-06,0.0001,0.0001,0.0001,0.0001,0.0001,1.84263e-06,2.06802e-05,2.06802e-05,2.06802e-05,1.40885e-05,0.0001,0.0001,1.32747e-09,1.4106e-05,3.71793e-07,0.0001,8.25424e-06,8.25424e-06,2.86162e-07,7.43882e-08,9.93508e-05,9.93508e-05,0.0001,1.07694e-05,0.0001,0.0001,0.0001,2.49843e-08,4.63465e-10,4.63465e-10,4.63465e-10", "train/minibatch_size": "4096,4096,8192,8192,8192,8192,8192,8192,8192,16384,4096,8192,8192,4096,4096,16384,4096,16384,16384,8192,8192,16384,16384,8192,8192,16384,16384,16384,16384,4096,8192,8192,8192,8192,4096,4096,4096,8192,8192,4096,4096,8192,16384,16384,16384,8192,8192,8192,4096,16384,4096,8192,8192,8192,8192,4096,4096,4096,8192,8192,8192,8192,8192,8192,8192,8192,16384,8192,8192,8192,8192,8192,8192,4096,16384,16384,4096,4096,8192,8192,4096,4096,4096,8192,4096,4096,8192,4096,4096,4096,8192,4096,8192,8192,8192", "train/horizon": "32,64,32,32,64,64,32,16,16,16,32,128,128,32,64,128,32,32,32,32,32,64,64,32,32,32,32,32,32,8,32,32,32,32,64,32,32,512,512,8,8,64,32,32,32,64,64,32,64,64,64,128,128,128,128,32,32,16,16,16,32,32,32,32,64,32,16,64,32,64,32,32,32,64,64,64,128,64,16,64,32,32,64,64,32,32,32,16,32,32,32,128,256,256,256", "train/vtrace_rho_clip": "1.49861,2.89585,2.22028,2.22028,3.76624,3.76624,1.96485,3.5381,3.5381,2.69329,1.44941,2.24978,2.24978,1.50806,1.49828,1.2361,2.24639,1.61979,1.61979,2.49786,2.49786,1.36183,1.36183,2.08974,2.08974,2.59065,2.59065,2.59065,2.59065,4.85908,3.24545,3.24545,3.24545,3.24545,4.15248,0.359514,4.29098,2.39578,2.39578,3.25222,3.25222,1.62329,2.07075,2.07075,3.18958,2.62023,2.62023,2.16098,0.724387,3.60291,3.59159,1.88052,1.88052,1.88052,1.88052,1.52157,1.52157,3.64003,4.73429,4.08236,2.39605,2.39605,2.39605,2.39605,2.50456,0.305542,3.20061,1.20873,3.24696,3.16895,3.45335,3.45335,3.45335,3.93998,4.11269,4.11269,1.2092,4.37966,2.0626,1.30472,4.15217,4.15217,3.05418,1.53455,4.27145,4.27145,2.95795,2.0032,2.09917,2.09917,2.64061,1.17785,1.66017,1.66017,1.66017", "train/vtrace_c_clip": "1.24681,0.746954,0.889035,0.889035,0.1,0.1,0.68055,0.462624,0.462624,0.923621,0.608007,1.51373,1.51373,0.1,1.92726,0.962766,1.74924,0.760544,0.760544,1.52028,1.52028,0.642844,0.642844,0.693426,0.693426,0.443165,0.443165,0.443165,0.443165,1.71636,2.12576,2.12576,2.12576,2.12576,1.19727,2.20514,1.31082,0.730526,0.730526,0.522963,0.522963,0.976517,1.47402,1.47402,0.908779,0.632125,0.632125,0.863614,1.03521,0.433468,0.482375,1.68864,1.68864,1.68864,1.68864,0.154972,0.154972,0.487032,1.00294,0.467615,0.817707,0.817707,0.817707,0.817707,0.593782,1.34124,1.1112,1.48439,0.583224,0.1,1.02313,1.02313,1.02313,0.720065,0.1,0.1,0.725297,0.1,1.46784,0.999587,0.343254,0.343254,0.400372,1.17213,1.1412,1.1412,0.594362,1.01147,0.412564,0.412564,0.1,1.57187,0.76912,0.76912,0.76912", "train/prio_alpha": "1,0.821691,1,1,1,1,1,0.745231,0.745231,0.962584,0.830617,1,1,0.680685,1,0.690906,0.858877,0.793132,0.793132,1,1,0.660137,0.660137,0.649708,0.649708,1,1,1,1,1,0.833804,0.833804,0.833804,0.833804,0.781286,0.759199,0.895154,0.905435,0.905435,0.271862,0.271862,1,0.734012,0.734012,0.933853,0.805019,0.805019,1,1,0.914418,1,1,1,1,1,1,1,1,0.429023,0.606528,0.766865,0.766865,0.766865,0.766865,0.823944,0.670174,1,0.945939,0.721584,1,1,1,1,0.83291,0.735105,0.735105,0.925154,0.79037,0.783191,0.887395,0.762137,0.762137,0.930848,0.99969,0.90369,0.90369,0.818513,1,0.961773,0.961773,0.700262,0.946355,1,1,1", "train/prio_beta0": "0.445087,0.425062,0.426298,0.426298,0.528799,0.528799,0.687096,0.149913,0.149913,0.536145,0.820636,0.731128,0.731128,0.807524,1,0.401274,0.990651,0.770607,0.770607,0.746205,0.746205,0.522008,0.522008,0.900165,0.900165,0.378617,0.378617,0.378617,0.378617,1,0.728834,0.728834,0.728834,0.728834,0.547491,0.593562,0.637065,0.648397,0.648397,0.287517,0.287517,0.744908,0.840242,0.840242,0.499599,0.740047,0.740047,0.285216,1,0.400905,0.816888,0.631898,0.631898,0.631898,0.631898,0.998511,0.998511,0.708445,0.981588,0.666674,0.686975,0.686975,0.686975,0.686975,0.763778,0.74001,0.545282,0.523581,0.309861,0.309692,0.646506,0.646506,0.646506,0.577083,0.677613,0.677613,0.610047,1,0.539887,0.761109,0.969425,0.969425,0.574578,0.64951,0.822404,0.822404,0.519767,0.773339,0.985108,0.985108,0.415928,0.566285,0.848015,0.848015,0.848015", "train/use_rnn": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "no_model_upload": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "tsne1": "53.4844,52.5637,57.5414,57.5414,64.259,64.259,57.7217,61.2614,61.2614,60.9465,51.9212,52.86,52.86,55.306,53.7767,58.1764,57.6959,59.0399,59.0399,54.5503,54.5502,57.9841,57.984,58.9485,58.9485,60.3233,60.3233,60.3233,60.3233,-23.1172,51.14,51.1401,51.1402,51.14,55.3019,57.4603,62.5997,51.4557,51.4557,-32.3888,-32.3888,53.6529,58.7897,58.7897,61.0297,54.9604,54.9604,62.7364,52.9815,59.9421,-23.2877,54.3301,54.3301,54.3301,54.3301,56.166,56.1661,59.7531,65.3322,60.0576,61.1006,61.1006,61.1006,61.1006,55.4427,58.169,57.8814,57.3401,61.7444,58.839,60.1016,60.1016,60.1016,64.5564,66.0208,66.0208,54.5655,65.6198,58.1689,57.4483,65.9457,65.9448,55.216,53.8085,-23.1793,-23.1793,59.4634,57.5717,56.8881,56.8881,62.3852,52.2212,53.3904,53.3904,53.3904", "tsne2": "16.456,16.6621,10.7698,10.7698,7.92849,7.92845,12.7524,11.084,11.084,7.42575,16.8403,19.9875,19.9875,12.7994,18.0022,15.3375,12.9794,14.1183,14.1183,9.26825,9.26841,16.5208,16.5209,12.3256,12.3256,7.91933,7.91933,7.91933,7.91929,-53.1917,7.66697,7.66699,7.66635,7.66629,15.3186,14.7671,9.48149,17.6388,17.6388,0.781942,0.781942,16.8861,13.2558,13.2558,7.72496,14.8983,14.8983,7.90882,18.5344,14.2567,-53.158,19.2924,19.2924,19.2924,19.2924,13.5315,13.5326,13.7353,13.0811,13.5199,8.94552,8.94552,8.94552,8.94552,12.7992,14.0503,10.5075,11.9861,9.67333,15.678,9.28475,9.28475,9.28475,8.18914,7.30861,7.30861,18.5827,12.7361,11.5783,14.5479,12.4651,12.4651,16.1446,17.0062,-53.1621,-53.1621,15.2876,13.4307,13.8305,13.8305,8.57892,16.8259,18.9169,18.9169,18.9169"}, "drive": {"SPS": "291661,137354,390798,220322,1.44802e+06,299267,421626,430405,440311,433649,432940,432939,436663,427828,437553,767501,388362,390047,390982,317831,316485,434880,861876,303138,1.379e+06,1.37458e+06,414070,421202,420457,428431,438691,429928,429330,432935,436690,428456,443592,373319,2.10413e+06,460402,619446,629263,638410,643207,644489,644898,677793,686696,695048,700976,506314,401703,340657,335193,605867,651875,691165,384631,387746,389135,390129,876497,932973,1.70836e+06,416772,426782,498871,410989,411121,393861", "agent_steps": "17.0394,16.9083,477.626,17.3015,41.1566,81.7889,333.971,556.27,778.568,1000.87,1223.16,1445.46,1667.76,1889.53,1999.63,69.0177,17.0394,50.5938,83.8861,5.24288,13.6315,15.6494,30.9581,22.5444,25.8081,76.5815,42.9916,128.188,333.971,556.27,778.568,1000.87,1223.16,1445.46,1667.76,1889.53,1999.63,470.811,17.6292,232.956,19.2076,56.7841,94.1671,131.963,169.582,207.197,243.88,282.115,319.816,338.166,162.791,22.9376,652.214,689.963,46.9238,511.705,697.827,43.2538,128.975,214.696,300.417,16.9685,50.3328,17.236,17.0394,16.7032,15.948,482.345,758.12,17.8258", "uptime": "58.5271,123.138,1225.65,78.5639,28.389,273.046,813.984,1340.07,1847.95,2356.1,2869.66,3383.29,3894.32,4407.63,4665.22,90.8259,43.9688,130.131,215.359,16.5209,42.9018,36.1129,35.8558,74.2873,18.6648,55.6045,104.529,308.378,811.746,1340.16,1849.76,2361.32,2879.21,3395.36,3905.91,4419.26,4676.17,1251.75,8.3902,513.689,31.0971,91.1604,150.051,208.783,267.027,325.153,381.412,436.326,491.081,517.425,308.259,57.307,1929.84,2040.71,78.3698,778.412,1057.07,112.879,334.589,555.35,775.453,19.415,56.2697,10.1063,40.8828,39.3921,34.1089,1179.34,1850.39,45.2222", "epoch": "32.5,64.5,455.5,16.5,314,78,318.5,530.5,742.5,954.5,1166.5,1378.5,1590.5,1802,1907,2106.25,32.5,96.5,160,2.5,6.5,59.6977,472.383,43,787.6,2337.08,82,244.5,318.5,530.5,742.5,954.5,1166.5,1378.5,1590.5,1802,1907,449,269,1777.31,146.543,433.228,718.438,1006.8,1293.81,1580.79,1860.66,2152.37,2440,2580,310.5,87.5,622,658,89.5,976,1331,165,492,819,1146,517.839,1536.03,263,65,254.871,121.673,460,723,17", "perf/rollout": "1.13549,0.272318,2.34963,2.34716,0.471723,2.2926,2.21015,2.16162,2.1046,2.14131,2.14518,2.14555,2.12505,2.17468,2.11592,0.56664,1.21682,1.21095,1.2077,3.24623,3.2087,0.84944,0.571193,1.18932,0.564176,0.569502,1.18022,1.1579,2.21747,2.17302,2.11342,2.1626,2.16562,2.14572,2.12452,2.17108,2.08627,2.40701,0.478402,0.639902,0.592081,0.586166,0.599027,0.596005,0.59725,0.594267,0.601588,0.681244,0.678665,0.672122,0.915554,0.575453,2.35777,2.4048,0.736386,0.679223,0.630005,0.590116,0.584553,0.58225,0.580617,0.574593,0.570537,0.543531,0.592725,0.589173,0.625729,2.32364,2.32282,2.40723", "perf/eval_gpu": "0.0937583,0.0960271,0.247356,0.261541,0.0677235,0.253738,0.125175,0.128886,0.129269,0.127537,0.128305,0.127303,0.128273,0.130819,0.121455,0.0478286,0.134956,0.135084,0.135021,0.308136,0.292491,0.086143,0.0539094,0.130115,0.0699399,0.0703618,0.118809,0.119653,0.126809,0.126945,0.129235,0.12881,0.125212,0.125385,0.130779,0.129512,0.125989,0.251777,0.0820194,0.0378626,0.0318558,0.0321361,0.0329506,0.0329054,0.0331104,0.0329028,0.0356811,0.0412398,0.0414372,0.0420537,0.132364,0.0594377,0.24456,0.24252,0.0457741,0.0449537,0.0446741,0.0642278,0.0642108,0.0642438,0.0643366,0.0532183,0.0558864,0.0926582,0.0567305,0.0380195,0.0837322,0.221043,0.22079,0.25546", "perf/eval_env": "1.03008,0.161757,2.0924,2.0761,0.389948,2.03266,2.07577,2.0247,1.96938,2.00731,2.00928,2.01075,1.98837,2.03598,1.98842,0.405684,1.07696,1.07096,1.0678,2.74511,2.73222,0.758994,0.414051,1.05428,0.460996,0.4677,1.05596,1.03292,2.07879,2.03388,1.9766,2.02176,2.03209,2.01107,1.98637,2.03365,1.95394,2.14885,0.374892,0.501507,0.495016,0.496069,0.488914,0.480281,0.481352,0.478818,0.500219,0.569393,0.57255,0.569124,0.779152,0.513213,2.10723,2.15635,0.600587,0.58582,0.562845,0.523161,0.517631,0.515205,0.513483,0.454019,0.447944,0.423307,0.533011,0.516061,0.538601,2.09626,2.09564,2.14555", "perf/train_misc": "0.0300951,0.0913267,0.0291902,0.228617,0.0277392,0.0956962,0.032018,0.0320265,0.0320233,0.0320428,0.0320337,0.0320348,0.0320219,0.0320163,0.0320737,0.0080973,0.00817011,0.00699499,0.00697473,0.331417,0.0886262,0.00603823,0.00719599,0.0435596,0.00922888,0.00920192,0.0087423,0.00817297,0.0319786,0.0320089,0.0319963,0.031979,0.0319818,0.0320582,0.0319731,0.031984,0.0319301,0.0422667,0.0263177,0.00973802,0.0119436,0.0115891,0.012064,0.0121354,0.0121674,0.0121749,0.0129656,0.0148471,0.0149784,0.0152658,0.0161931,0.00788711,0.0762069,0.076925,0.0229858,0.0217198,0.0216553,0.00564864,0.00566058,0.00563538,0.00563519,0.00789559,0.00825391,0.0136927,0.0090447,0.0035166,0.00672383,0.0449028,0.0449767,0.0470126", "perf/train_forward": "0.745356,1.68322,0.299329,2.99204,0.135072,1.10906,0.237711,0.237558,0.237607,0.23746,0.237471,0.237479,0.237518,0.237486,0.237765,0.0557922,0.147737,0.126139,0.126065,12.1998,3.34755,0.0305407,0.0363997,0.565254,0.0389634,0.0388282,0.0844469,0.0790579,0.238349,0.23832,0.238291,0.238335,0.238326,0.238291,0.238318,0.23831,0.238682,0.35675,0.119822,0.0362954,0.0477874,0.0466157,0.0485999,0.048754,0.0490307,0.0487676,0.0521309,0.0596414,0.0604213,0.0602511,0.105837,0.0689578,0.636137,0.635732,0.114169,0.107693,0.107685,0.08557,0.0855802,0.0856245,0.0856117,0.0328444,0.0344542,0.0558026,0.0269531,0.0377186,0.0523099,0.178812,0.178808,0.283059", "perf/train": "0.775451,1.77454,0.32852,3.22066,0.162811,1.20476,0.269729,0.269585,0.269631,0.269502,0.269505,0.269513,0.269539,0.269502,0.269838,0.0638895,0.155907,0.133134,0.13304,12.5313,3.43618,0.0365789,0.0435957,0.608813,0.0481923,0.0480301,0.0931892,0.0872308,0.270327,0.270329,0.270287,0.270314,0.270308,0.270349,0.270291,0.270294,0.270612,0.399017,0.146139,0.0460334,0.059731,0.0582048,0.060664,0.0608894,0.061198,0.0609425,0.0650965,0.0744885,0.0753997,0.0755169,0.122031,0.0768449,0.712344,0.712657,0.137155,0.129413,0.12934,0.0912186,0.0912408,0.0912599,0.0912469,0.04074,0.0427081,0.0694953,0.0359978,0.0412352,0.0590337,0.223715,0.223785,0.330071", "util/gpu_percent": "57.8594,100,31.8308,100,63.2809,100,23.3491,25.1651,25.7311,26.4292,26.6085,26.7642,24.3302,25.8863,12,31.3579,14.7812,14.5625,11.9365,100,100,11.6047,30.2783,49.8706,44.0833,44.4833,11.4294,11.6111,24.1462,25.4198,28.2028,26.7547,25.8915,25.7972,25.2123,25.5498,100,35.8765,76.4231,17.3982,22.9468,23.0435,23.4719,23.6629,24.2727,23.4494,24.5366,25.5616,26.4507,32,20.371,18.0349,65,100,28.5449,29.4011,31.8644,20.211,20.156,19.7706,21.3364,29.2258,31.8448,57.5625,12.6929,17.8065,21.7857,20.687,20.3435,36.697", "util/gpu_mem": "15.0833,14.5785,22.7449,21.3934,6.86803,21.7272,31.8611,32.0064,32.0182,32.0657,32.067,32.0595,32.0642,32.0756,32.0996,5.2152,17.013,17.013,17.013,53.9369,53.9369,9.12336,5.70372,13.2351,5.17449,5.17449,14.6274,14.6274,21.9226,21.9226,21.9226,21.9226,21.9226,21.9226,21.9226,21.9226,21.9226,21.6132,6.3388,6.2818,6.57492,6.57492,6.57492,6.57492,6.57492,6.57492,6.57492,6.57492,6.57492,6.57492,12.7221,8.78954,32.3438,32.3438,13.0152,13.0152,13.0152,10.1248,10.1248,10.1248,10.1248,19.0317,19.0317,7.9672,8.14632,17.081,6.52606,20.7664,20.7664,21.1735", "util/vram_used_gb": "3.1571,3.03601,4.995,4.67078,1.1864,4.75085,7.1818,7.21667,7.21951,7.2309,7.2312,7.22941,7.23054,7.23326,7.23901,0.789917,3.62,3.62,3.62,12.4774,12.4774,1.72742,0.907104,2.71375,0.780151,0.780151,3.04773,3.04773,4.79773,4.79773,4.79773,4.79773,4.79773,4.79773,4.79773,4.79773,4.79773,4.72351,1.05945,1.04578,1.11609,1.11609,1.11609,1.11609,1.11609,1.11609,1.11609,1.11609,1.11609,1.11609,2.5907,1.64734,7.29761,7.29761,2.66101,2.66101,2.66101,1.96765,1.96765,1.96765,1.96765,4.10425,4.10425,1.45007,1.49304,3.63632,1.10437,4.52039,4.52039,4.61804", "util/vram_total_gb": "23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272", "util/cpu_mem_gb": "4.33538,1.81491,4.32188,4.32989,2.75,7.51954,7.44965,7.45026,7.45083,7.45118,7.45166,7.45224,7.45301,7.45306,7.45306,2.74359,4.305,4.305,4.305,4.61279,4.61292,4.29451,2.74931,4.30899,2.79293,2.79293,4.30438,4.30462,7.52936,7.52936,7.52936,7.52982,7.53028,7.5311,7.53131,7.53173,7.5318,7.50946,2.88669,2.79867,4.32856,4.32856,4.32856,4.32879,4.32905,4.32933,4.32954,4.32954,4.32954,4.32954,2.71804,4.29609,7.43383,7.43383,4.36064,4.36176,4.36303,4.29538,4.29575,4.29639,4.29706,2.65843,2.65843,1.95685,4.29222,2.71488,2.69355,7.50552,7.50559,7.50772", "env/perf": "0.335392,0.274262,0.892034,0.449675,0.537931,0.729029,0.889556,0.930164,0.947856,0.959161,0.965919,0.970483,0.974835,0.97676,0.979004,0.578282,0.335712,0.659138,0.711356,0.171697,0.189477,0.174995,0.523039,0.454748,0.451216,0.550955,0.538369,0.763178,0.889556,0.930164,0.947856,0.959161,0.965919,0.970483,0.974835,0.97676,0.979004,0.894515,0.146327,0.841822,0.433522,0.69164,0.761061,0.795218,0.817315,0.837339,0.851502,0.861811,0.864146,0.866178,0.802763,0.481589,0.940317,0.944539,0.54847,0.873733,0.89514,0.639612,0.833447,0.859056,0.866353,0.32616,0.558889,0.0752308,0.342166,0.256781,0.197245,0.913685,0.93689,0.347715", "env/score": "0.335392,0.274262,0.892034,0.449675,0.537931,0.729029,0.889556,0.930164,0.947856,0.959161,0.965919,0.970483,0.974835,0.97676,0.979004,0.578282,0.335712,0.659138,0.711356,0.171697,0.189477,0.174995,0.523039,0.454748,0.451216,0.550955,0.538369,0.763178,0.889556,0.930164,0.947856,0.959161,0.965919,0.970483,0.974835,0.97676,0.979004,0.894515,0.146327,0.841822,0.433522,0.69164,0.761061,0.795218,0.817315,0.837339,0.851502,0.861811,0.864146,0.866178,0.802763,0.481589,0.940317,0.944539,0.54847,0.873733,0.89514,0.639612,0.833447,0.859056,0.866353,0.32616,0.558889,0.0752308,0.342166,0.256781,0.197245,0.913685,0.93689,0.347715", "env/episode_return": "-3.67888,-4.52858,0.925528,-0.246831,-0.348188,1.53531,0.893867,0.937775,0.956079,0.96735,0.973683,0.977966,0.980705,0.9826,0.98558,-0.239188,-0.838684,0.491042,0.642294,-1.56592,-1.36247,-1.88163,-0.598721,1.40412,-0.324,0.278035,0.437472,0.867252,0.893867,0.937775,0.956079,0.96735,0.973683,0.977966,0.980705,0.9826,0.98558,0.91915,-8.60046,0.827211,-0.788615,0.475879,0.660883,0.732459,0.775353,0.811881,0.829897,0.847946,0.851563,0.852699,0.798849,-0.0173046,0.948567,0.953428,0.0458123,0.869702,0.895964,0.230969,0.814966,0.853119,0.865735,-1.64124,-0.00545676,-4.08417,-1.2542,0.359883,-1.29123,0.938559,0.95704,-1.03292", "env/episode_length": "90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90,90", "env/offroad_rate": "0.587534,0.482853,0.0213933,0.210625,0.334206,0.199062,0.0267006,0.0247149,0.0215503,0.0184637,0.0138112,0.0113753,0.0120133,0.0102606,0.0078125,0.161256,0.509535,0.101625,0.0767512,0.699917,0.702373,0.757368,0.39365,0.19182,0.382246,0.202499,0.26758,0.0411339,0.0267006,0.0247149,0.0215503,0.0184637,0.0138112,0.0113753,0.0120133,0.0102606,0.0078125,0.0199977,0.733362,0.0382581,0.374634,0.109116,0.0801594,0.0618279,0.0510073,0.0403767,0.0326767,0.0277719,0.0263324,0.02849,0.0537214,0.173793,0.012998,0.0114746,0.234509,0.0363238,0.0264426,0.223018,0.0515107,0.0425902,0.0390431,0.425205,0.157705,0.650082,0.384698,0.716315,0.701577,0.0104473,0.00593485,0.310619", "env/collision_rate": "0.292786,0.305248,0.0579634,0.245477,0.189426,0.0914821,0.038396,0.0338987,0.0282322,0.0238987,0.0199786,0.0174609,0.0146804,0.0138877,0.0119222,0.184769,0.291737,0.141457,0.102417,0.305714,0.289158,0.313295,0.208204,0.169036,0.246991,0.219438,0.246475,0.157373,0.038396,0.0338987,0.0282322,0.0238987,0.0199786,0.0174609,0.0146804,0.0138877,0.0119222,0.0634743,0.315656,0.0622458,0.222513,0.128107,0.0957992,0.0775034,0.0680556,0.0553347,0.0489011,0.0442454,0.0428864,0.0410256,0.072429,0.240904,0.039024,0.0358887,0.173901,0.047152,0.0363782,0.139004,0.0629203,0.0508619,0.0466316,0.241016,0.165739,0.254801,0.298826,0.371362,0.326228,0.0433056,0.0304645,0.281859", "env/dnf_rate": "0.0391827,0.14822,0.0407871,0.191039,0.074132,0.0346859,0.0594068,0.0235708,0.0133465,0.0086667,0.00732076,0.00657567,0.00608538,0.00570954,0.00585938,0.154148,0.0834713,0.134434,0.13568,0.119518,0.105796,0.0758326,0.0363721,0.265111,0.0893115,0.124524,0.0675416,0.0559707,0.0594068,0.0235708,0.0133465,0.0086667,0.00732076,0.00657567,0.00608538,0.00570954,0.00585938,0.0317971,0.11959,0.0751579,0.12403,0.119134,0.0958911,0.0897683,0.0835997,0.0823572,0.0800977,0.0777795,0.0775147,0.0774929,0.09299,0.1873,0.0154352,0.0146484,0.141083,0.0567283,0.0510516,0.0858031,0.0712226,0.0643471,0.061557,0.18432,0.18635,0.244499,0.143093,0.0233233,0.0808952,0.0365601,0.0290448,0.195895", "env/n": "5760,2868.75,11500.3,11520,10041.2,11404.5,11515.2,11515.2,11515.2,11515.2,11553.8,11515.2,11515.2,11530.9,24576,5319.6,5760,5760,5721.4,22522.5,23546.2,5000.93,5817.76,5734.4,9284.27,9318.4,5754.5,5764.74,11515.2,11515.2,11515.2,11515.2,11553.8,11515.2,11515.2,11530.9,24576,11529.5,14308,3497.91,4399.95,4451.09,4647.13,4693.15,4653.41,4647.13,4993.9,5721.78,5767.61,12285,5764.13,4096,11558.6,24576,5751.4,5760.76,5760.76,4096,4096,4096,4096,5907,6279.1,11443.1,4096,2939.87,3740.73,11506.3,11506.3,11419.2", "env/completion_rate": "0.470304,0.356899,0.94696,0.551028,0.656812,0.78209,0.930126,0.969484,0.981537,0.98795,0.990044,0.991381,0.992287,0.992976,0.993205,0.670321,0.466785,0.756033,0.78118,0.242118,0.273651,0.241975,0.636299,0.521509,0.576536,0.69799,0.693392,0.907984,0.930126,0.969484,0.981537,0.98795,0.990044,0.991381,0.992287,0.992976,0.993205,0.958599,0.204006,0.898269,0.540446,0.779344,0.840043,0.8631,0.878134,0.888911,0.897019,0.902128,0.903185,0.903867,0.863205,0.594528,0.980109,0.981364,0.637711,0.92006,0.931875,0.720808,0.89479,0.912159,0.917587,0.412005,0.64808,0.0967272,0.485842,0.492983,0.259683,0.955925,0.967279,0.46395", "env/clean_collision_rate": "0.292786,0.305248,0.0579634,0.245477,0.189426,0.0914821,0.038396,0.0338987,0.0282322,0.0238987,0.0199786,0.0174609,0.0146804,0.0138877,0.0119222,0.184769,0.291737,0.141457,0.102417,0.305714,0.289158,0.313295,0.208204,0.169036,0.246991,0.219438,0.246475,0.157373,0.038396,0.0338987,0.0282322,0.0238987,0.0199786,0.0174609,0.0146804,0.0138877,0.0119222,0.0634743,0.315656,0.0622458,0.222513,0.128107,0.0957992,0.0775034,0.0680556,0.0553347,0.0489011,0.0442454,0.0428864,0.0410256,0.072429,0.240904,0.039024,0.0358887,0.173901,0.047152,0.0363782,0.139004,0.0629203,0.0508619,0.0466316,0.241016,0.165739,0.254801,0.298826,0.371362,0.326228,0.0433056,0.0304645,0.281859", "wandb": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "slowly": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "save_frames": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "fps": "15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15", "rank": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "world_size": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "gpu_id": "2,3,1,2,5,4,0,0,0,0,0,0,0,0,0,1,4,4,4,4,4,1,2,4,2,2,4,4,1,1,1,1,1,1,1,1,1,5,5,4,2,2,2,2,2,2,2,2,2,2,3,3,0,0,3,3,3,2,2,2,2,0,0,3,1,0,4,2,2,1", "profile": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "checkpoint_interval": "200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200", "eval_episodes": "10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000", "cudagraphs": "10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10", "seed": "73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73", "reset_state": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "vec/total_agents": "4096,256,4096,4096,2048,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,2048,4096,4096,4096,4096,4096,4096,2048,4096,2048,2048,4096,4096,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,2048,2048,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,2048,4096,8192,8192,4096,4096,4096,4096,4096,4096,4096,2048,2048,1024,4096,2048,2048,8192,8192,8192", "vec/num_buffers": "2.22671,3.54971,1.22215,1,5.11233,1,2,2,2,2,2,2,2,2,2,3.35822,1.31263,1.31263,1.31263,3.23923,3.23923,1,3.73945,1.45416,4.43068,4.43068,1.17148,1.17148,2,2,2,2,2,2,2,2,2,1,7.22577,2.57628,3.73482,3.73482,3.73482,3.73482,3.73482,3.73482,3.73482,3.73482,3.73482,3.73482,1.77288,1.94438,1.39489,1.39489,3.13563,3.13563,3.13563,1.44364,1.44364,1.44364,1.44364,3.55634,3.55634,5.45199,1.59803,2.27371,1.44723,1.82946,1.82946,1.79107", "vec/num_threads": "2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2", "env/width": "1280,1280,1280,1280,1280,1280,1280,1280,1280,1280,1280,1280,1280,1280,1280,1280,1280,1280,1280,1280,1280,1280,1280,1280,1280,1280,1280,1280,1280,1280,1280,1280,1280,1280,1280,1280,1280,1280,1280,1280,1280,1280,1280,1280,1280,1280,1280,1280,1280,1280,1280,1280,1280,1280,1280,1280,1280,1280,1280,1280,1280,1280,1280,1280,1280,1280,1280,1280,1280,1280", "env/height": "1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024", "env/human_agent_idx": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "env/reward_vehicle_collision": "-0.246646,0,-0.068559,-0.463109,-0.362726,-0.361008,-0.2,-0.2,-0.2,-0.2,-0.2,-0.2,-0.2,-0.2,-0.2,-0.467384,-0.202898,-0.202898,-0.202898,-0.85018,-0.85018,-0.418551,-0.242855,-0.433262,-0.182872,-0.182872,-0.0193166,-0.0193166,-0.2,-0.2,-0.2,-0.2,-0.2,-0.2,-0.2,-0.2,-0.2,-0.134668,-0.126706,-0.236188,-0.301464,-0.301464,-0.301464,-0.301464,-0.301464,-0.301464,-0.301464,-0.301464,-0.301464,-0.301464,-0.209726,-0.105497,-0.180622,-0.180622,-0.264144,-0.264144,-0.264144,-0.24847,-0.24847,-0.24847,-0.24847,-0.466612,-0.466612,-0.59034,-0.141314,-0.0494662,0,-0.09428,-0.09428,-0.148704", "env/reward_offroad_collision": "-0.845749,-0.87309,-0.241206,-0.793702,-0.294032,-0.877321,-0.2,-0.2,-0.2,-0.2,-0.2,-0.2,-0.2,-0.2,-0.2,-0.439851,-0.133815,-0.133815,-0.133815,-0.0240556,-0.0240556,-0.125496,-0.269338,-0.657336,-0.168583,-0.168583,-0.0892112,-0.0892112,-0.2,-0.2,-0.2,-0.2,-0.2,-0.2,-0.2,-0.2,-0.2,-0.312225,-0.936014,-0.262831,-0.234226,-0.234226,-0.234226,-0.234226,-0.234226,-0.234226,-0.234226,-0.234226,-0.234226,-0.234226,-0.115188,-0.265977,-0.350697,-0.350697,-0.135312,-0.135312,-0.135312,-0.137536,-0.137536,-0.137536,-0.137536,-0.255305,-0.255305,-0.257587,-0.315763,0,-0.2425,-0.236269,-0.236269,-0.342785", "env/reward_goal_post_respawn": "1,0.278874,0,0.820225,0,0.922032,0,0,0,0,0,0,0,0,0,0,0,0,0,0.351274,0.351274,0,0,0.947806,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.528379,0.00599768,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.172083,0,0,0,0,0,0.0346156", "env/reward_vehicle_collision_post_respawn": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "env/resample_frequency": "10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000", "env/num_maps": "500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500", "policy/hidden_size": "512,256,256,256,64,256,256,256,256,256,256,256,256,256,256,64,512,512,512,512,512,128,64,256,128,128,256,256,256,256,256,256,256,256,256,256,256,512,128,128,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,512,512,512,512,128,128,128,128,512,256,512,512,512", "policy/num_layers": "7.97573,7.75815,4.52845,6.21631,2.975,7.8984,4,4,4,4,4,4,4,4,4,5.8513,4.81591,4.81591,4.81591,7.27077,7.27077,3.77045,4.26938,6.25306,3.42811,3.42811,4.74978,4.74978,4,4,4,4,4,4,4,4,4,3.54513,2.33164,1.48765,1.76645,1.76645,1.76645,1.76645,1.76645,1.76645,1.76645,1.76645,1.76645,1.76645,3.04602,4.06986,5.34506,5.34506,2.32308,2.32308,2.32308,3.23286,3.23286,3.23286,3.23286,2.60711,2.60711,1.60105,1.18253,2.23647,3.87773,1.89578,1.89578,2.59347", "policy/expansion_factor": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "train/gpus": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "train/seed": "42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42", "train/total_timesteps": "300,300,1227.84,300,730.922,484.364,2000,2000,2000,2000,2000,2000,2000,2000,2000,412.342,300,300,300,365.558,365.558,300,544.057,400.348,454.365,454.365,766.952,766.952,2000,2000,2000,2000,2000,2000,2000,2000,2000,769.267,300,323.427,338.227,338.227,338.227,338.227,338.227,338.227,338.227,338.227,338.227,338.227,584.257,406.533,690.139,690.139,837.074,837.074,837.074,771.775,771.775,771.775,771.775,300,300,300,300,300,300,1239.25,1239.25,312.172", "train/learning_rate": "0.000186984,0.000108476,0.0009099,0.000335267,0.00105275,8.05314e-05,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.000389627,0.00155125,0.00155125,0.00155125,0.00691575,0.00691575,0.000474392,0.00111483,0.000751322,0.00153242,0.00153242,0.00115674,0.00115674,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.00151291,2.55462e-05,0.00193271,0.00116422,0.00116422,0.00116422,0.00116422,0.00116422,0.00116422,0.00116422,0.00116422,0.00116422,0.00116422,0.000794589,0.00202925,0.000938078,0.000938078,0.00075095,0.00075095,0.00075095,0.000668591,0.000668591,0.000668591,0.000668591,0.00105617,0.00105617,0.0234083,0.000710114,0.00166302,0.000934827,0.000859919,0.000859919,0.00117122", "train/anneal_lr": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "train/min_lr_ratio": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "train/gamma": "0.976305,0.994777,0.966439,0.908347,0.94818,0.94814,0.98,0.98,0.98,0.98,0.98,0.98,0.98,0.98,0.98,0.8217,0.974239,0.974239,0.974239,0.880102,0.880102,0.993693,0.803175,0.934947,0.886697,0.886697,0.991229,0.991229,0.98,0.98,0.98,0.98,0.98,0.98,0.98,0.98,0.98,0.971961,0.999603,0.94079,0.931081,0.931081,0.931081,0.931081,0.931081,0.931081,0.931081,0.931081,0.931081,0.931081,0.8,0.889529,0.972683,0.972683,0.960601,0.960601,0.960601,0.965923,0.965923,0.965923,0.965923,0.8,0.8,0.99978,0.8,0.915633,0.988541,0.943493,0.943493,0.8", "train/gae_lambda": "0.612109,0.533059,0.949057,0.883466,0.994883,0.897005,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.965134,0.978844,0.978844,0.978844,0.524491,0.524491,0.992794,0.974697,0.857993,0.987369,0.987369,0.983324,0.983324,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.926732,0.977524,0.993335,0.979661,0.979661,0.979661,0.979661,0.979661,0.979661,0.979661,0.979661,0.979661,0.979661,0.985448,0.989599,0.955094,0.955094,0.980349,0.980349,0.980349,0.912605,0.912605,0.912605,0.912605,0.990687,0.990687,0.994271,0.993317,0.974661,0.984885,0.98034,0.98034,0.993868", "train/replay_ratio": "1.16114,3.78226,1.47238,2.65776,1.17444,1.71402,1,1,1,1,1,1,1,1,1,1.2845,0.801415,0.801415,0.801415,2.6482,2.6482,1.19284,0.868439,1.79483,0.498726,0.498726,1.01206,1.01206,1,1,1,1,1,1,1,1,1,0.698893,1.44448,1.20408,1.03338,1.03338,1.03338,1.03338,1.03338,1.03338,1.03338,1.03338,1.03338,1.03338,0.502744,0.943751,1.36069,1.36069,0.976902,0.976902,0.976902,1.14362,1.14362,1.14362,1.14362,1.16299,1.16299,2.52466,1.08153,0.470199,0.655191,0.761389,0.761389,0.581104", "train/clip_coef": "0.396187,0.612425,0.0389939,0.649597,0.218647,0.69987,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.12718,0.201865,0.201865,0.201865,0.45339,0.45339,0.316201,0.0875444,0.54314,0.180155,0.180155,0.151296,0.151296,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.143329,0.980073,0.01,0.123828,0.123828,0.123828,0.123828,0.123828,0.123828,0.123828,0.123828,0.123828,0.123828,0.112629,0.147018,0.114305,0.114305,0.300225,0.300225,0.300225,0.145669,0.145669,0.145669,0.145669,0.01,0.01,0.0163394,0.126128,0.221721,0.216892,0.211021,0.211021,0.209777", "train/vf_coef": "1.28513,0.171563,2.31583,2.0596,1.89443,2.84193,2,2,2,2,2,2,2,2,2,2.26819,2.31224,2.31224,2.31224,0.698215,0.698215,1.98508,2.44635,2.47404,1.59988,1.59988,1.93443,1.93443,2,2,2,2,2,2,2,2,2,2.2697,4.68231,2.52718,2.02675,2.02675,2.02675,2.02675,2.02675,2.02675,2.02675,2.02675,2.02675,2.02675,2.0375,2.13799,1.86363,1.86363,2.34318,2.34318,2.34318,2.17664,2.17664,2.17664,2.17664,2.35157,2.35157,2.78327,1.79806,2.55944,2.07299,2.05935,2.05935,2.1433", "train/vf_clip_coef": "2.32231,4.65614,0.839121,2.79672,0.01,1.16484,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.01,0.01,0.01,0.01,0.0954769,0.0954769,0.01,0.241333,1.92542,0.01,0.01,0.01,0.01,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.01,4.33357,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.195724,0.195724,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,3.6728,0.309344,0.567397,0.01,0.381386,0.381386,0.409243", "train/max_grad_norm": "3.21537,4.69354,1.46654,3.34302,3.4841,2.93703,1.5,1.5,1.5,1.5,1.5,1.5,1.5,1.5,1.5,4.1079,2.09133,2.09133,2.09133,1.61074,1.61074,3.02235,3.86034,2.73845,2.87623,2.87623,2.2842,2.2842,1.5,1.5,1.5,1.5,1.5,1.5,1.5,1.5,1.5,2.57287,3.65892,0.915228,1.86535,1.86535,1.86535,1.86535,1.86535,1.86535,1.86535,1.86535,1.86535,1.86535,2.1087,2.37811,0.434595,0.434595,2.57133,2.57133,2.57133,1.33042,1.33042,1.33042,1.33042,4.77667,4.77667,2.52807,1.66556,3.25267,3.27535,3.66108,3.66108,3.61775", "train/ent_coef": "0.00213476,0.0851249,0.0029225,0.00281862,0.000342654,8.26723e-05,0.005,0.005,0.005,0.005,0.005,0.005,0.005,0.005,0.005,0.00257279,0.000581904,0.000581904,0.000581904,2.05534e-05,2.05534e-05,0.000425936,0.00147283,0.000588636,0.00318649,0.00318649,0.00115254,0.00115254,0.005,0.005,0.005,0.005,0.005,0.005,0.005,0.005,0.005,0.00231347,0.0604561,0.000791949,0.00105907,0.00105907,0.00105907,0.00105907,0.00105907,0.00105907,0.00105907,0.00105907,0.00105907,0.00105907,0.000382594,0.00368994,0.00294361,0.00294361,0.00281028,0.00281028,0.00281028,0.00052786,0.00052786,0.00052786,0.00052786,0.00148114,0.00148114,0.00399677,0.000967643,0.0009429,0.000475428,0.00430891,0.00430891,0.000471991", "train/beta1": "0.957801,0.936471,0.973158,0.986308,0.997544,0.944134,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.998518,0.896235,0.896235,0.896235,0.997242,0.997242,0.983134,0.997694,0.985993,0.993244,0.993244,0.984144,0.984144,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.966802,0.955545,0.984937,0.971425,0.971425,0.971425,0.971425,0.971425,0.971425,0.971425,0.971425,0.971425,0.971425,0.96819,0.801834,0.986194,0.986194,0.884121,0.884121,0.884121,0.988713,0.988713,0.988713,0.988713,0.998125,0.998125,0.80486,0.949893,0.607275,0.865714,0.931016,0.931016,0.964669", "train/beta2": "0.999965,0.99993,0.999676,0.999953,0.99889,0.99999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999888,0.997676,0.997676,0.997676,0.989394,0.989394,0.972111,0.999459,0.999965,0.9994,0.9994,0.99297,0.99297,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999265,0.999628,0.999636,0.997901,0.997901,0.997901,0.997901,0.997901,0.997901,0.997901,0.997901,0.997901,0.997901,0.993066,0.991426,0.999079,0.999079,0.991134,0.991134,0.991134,0.999861,0.999861,0.999861,0.999861,0.999296,0.999296,0.998755,0.998154,0.991327,0.960414,0.993608,0.993608,0.998359", "train/eps": "5.766e-06,5.63928e-12,1.05085e-11,1.33645e-05,1.20254e-11,0.0001,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1.55037e-12,3.69387e-13,3.69387e-13,3.69387e-13,4.42597e-09,4.42597e-09,3.68484e-13,3.483e-11,7.17775e-06,4.74641e-11,4.74641e-11,2.03718e-11,2.03718e-11,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1.19594e-12,1.38742e-11,3.15593e-12,5.92803e-10,5.92803e-10,5.92803e-10,5.92803e-10,5.92803e-10,5.92803e-10,5.92803e-10,5.92803e-10,5.92803e-10,5.92803e-10,1e-14,2.26225e-10,6.78284e-12,6.78284e-12,2.21327e-12,2.21327e-12,2.21327e-12,6.67633e-14,6.67633e-14,6.67633e-14,6.67633e-14,5.9123e-11,5.9123e-11,2.18943e-13,4.69392e-10,1.08632e-13,4.12564e-12,4.74421e-12,4.74421e-12,4.79508e-10", "train/minibatch_size": "4096,8192,16384,4096,4096,4096,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,16384,16384,16384,32768,32768,16384,8192,4096,4096,4096,16384,16384,8192,8192,8192,8192,8192,8192,8192,8192,8192,4096,8192,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,8192,8192,8192,8192,8192,8192,65536,4096,4096,4096,4096,4096,4096", "train/horizon": "128,1024,256,256,64,128,128,128,128,128,128,128,128,128,128,16,128,128,128,512,512,64,32,128,16,16,128,128,128,128,128,128,128,128,128,128,128,128,32,64,32,32,32,32,32,32,32,32,32,32,256,64,128,128,128,128,128,64,64,64,64,16,16,64,64,32,64,128,128,128", "train/vtrace_rho_clip": "4.34127,2.57976,0.716532,3.79234,1.77837,3.32309,1,1,1,1,1,1,1,1,1,0.499063,0.72555,0.72555,0.72555,1.38992,1.38992,1.11338,0.1,3.66642,1.16188,1.16188,0.1,0.1,1,1,1,1,1,1,1,1,1,1.47816,4.24319,1.26919,1.04399,1.04399,1.04399,1.04399,1.04399,1.04399,1.04399,1.04399,1.04399,1.04399,1.15875,2.41534,1.73897,1.73897,1.24908,1.24908,1.24908,0.218592,0.218592,0.218592,0.218592,0.1,0.1,0.736585,0.179739,1.64999,0.73822,0.929244,0.929244,1.57981", "train/vtrace_c_clip": "0.411375,4.30884,1.92922,0.400133,0.892849,1.65077,1,1,1,1,1,1,1,1,1,2.18384,0.645834,0.645834,0.645834,4.87601,4.87601,1.68171,2.67834,1.571,1.85212,1.85212,1.14388,1.14388,1,1,1,1,1,1,1,1,1,0.90209,0.966788,1.55439,1.96779,1.96779,1.96779,1.96779,1.96779,1.96779,1.96779,1.96779,1.96779,1.96779,1.05459,0.534415,1.10711,1.10711,0.778843,0.778843,0.778843,1.60458,1.60458,1.60458,1.60458,1.96357,1.96357,3.01106,1.74917,1.08939,2.85261,1.01578,1.01578,0.1", "train/prio_alpha": "0.184354,0.689696,0.623541,0.0982117,1,0,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,1,0.973362,0.973362,0.973362,0.587709,0.587709,0.817919,1,0.200429,1,1,0.846154,0.846154,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,1,0.357926,0.888127,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0.996439,0.996439,0.996439,0.63451,0.63451,0.63451,0.63451,0.941216,0.941216,0.994543,0.886412,0.982472,1,1,1,1", "train/prio_beta0": "0.0628753,1,0.293264,0.0338353,0.686472,0,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.576309,0.0506423,0.0506423,0.0506423,0.862976,0.862976,0.222917,0.358584,0.0583876,0.523334,0.523334,0.435837,0.435837,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.239967,0.373894,0.507966,0.328968,0.328968,0.328968,0.328968,0.328968,0.328968,0.328968,0.328968,0.328968,0.328968,0.452383,0.116815,0.235947,0.235947,0.3058,0.3058,0.3058,0.442687,0.442687,0.442687,0.442687,0.116516,0.116516,0.55336,0.375472,0.460162,0.31709,0.415831,0.415831,0.191827", "no_model_upload": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "tsne1": "-28.3209,4.01133,-7.91885,-28.3116,-13.7878,-28.3034,-9.68166,-10.1528,-9.92416,-10.5054,-9.2906,-10.2723,-9.51405,-10.3415,-9.88949,-16.1245,-9.13756,-9.13756,-9.13756,-34.8033,-34.8033,-7.72522,-16.2936,-28.308,-14.4786,-14.4786,-7.68085,-7.68085,-9.28706,-10.2518,-10.5111,-9.46297,-9.22421,-10.3876,-9.86479,-9.69563,-9.2951,-12.3471,-4.95097,-12.2789,-13.5488,-13.042,-13.042,-13.5488,-13.042,-13.5488,-13.042,-13.4295,-13.0592,-13.5488,-16.0344,-14.4261,-10.7476,-10.7477,-12.6217,-12.6217,-12.6217,-8.34923,-8.34934,-8.34923,-8.34934,-16.6013,-16.6013,-27.522,-15.8019,-14.5265,-13.0315,-13.289,-13.289,-15.7408", "tsne2": "-15.9327,-41.5585,7.8024,-15.9221,12.6867,-15.9402,6.72804,7.88666,6.65032,7.25151,7.1171,7.55248,6.81217,7.70369,7.21576,12.4012,5.03002,5.03002,5.03002,31.5364,31.5364,6.10535,12.1992,-15.9325,11.9767,11.9767,6.70792,6.70792,7.1523,6.68979,7.14983,7.86242,7.49175,6.76759,7.93761,7.96779,7.69553,7.33829,18.5663,11.6467,10.6696,10.9653,10.9653,10.6696,10.9653,10.6696,10.9653,11.1398,10.5269,10.6696,10.3748,9.20896,9.21537,9.21532,8.11078,8.11062,8.11062,9.56004,9.5601,9.56004,9.5601,12.1473,12.1473,40.6681,10.8498,6.21369,9.2414,7.48651,7.48651,9.84948"}, "drone": {"SPS": "1.02449e+06,882963,880354,883967,885711,2.27619e+06,821403,854139,855003,853929,854514,853784,842607,1.32085e+06,1.37929e+06,1.38521e+06,1.38174e+06,1.0644e+06,1.2819e+06,1.37413e+06,1.13571e+06,458009,553078,568724,642966,649923,497377,1.11945e+06,105483,1.88486e+06,562883,552235,517103,2.37114e+06,1.54124e+06,976266,1.41485e+06,1.31977e+06,1.17499e+06,1.43405e+06,1.28478e+06,1.0685e+06,1.06821e+06,1.07012e+06,1.4571e+06,1.50598e+06,1.50692e+06,1.50697e+06,1.508e+06,1.50627e+06,622472,634053,629805,627505,627379,1.65666e+06,1.47816e+06,2.6486e+06,2.65729e+06,2.65776e+06,2.65762e+06,1.20589e+06,2.41614e+06,1.93417e+06,1.51162e+06,794259,2.11578e+06,102170,101876,1.15754e+06,1.43333e+06,3.67613e+06,950679,1.32018e+06,1.31014e+06,2.83716e+06,1.10833e+06,1.48084e+06,1.61349e+06,1.64683e+06,110828,111169,1.09388e+06,1.09437e+06,1.08863e+06,1.51009e+06,1.45766e+06,441877,458909,1.47926e+06,1.51403e+06,1.50355e+06,1.84895e+06,1.21835e+06,1.2115e+06,983700,298210,297076,2.34371e+06,152606,972422,101247,103052,101278,1.45347e+06,1.83398e+06,2.05692e+06,1.90215e+06,614080,613599,613501,613889,613567,559614,612894,1.87117e+06,1.93759e+06,2.11139e+06,1.98996e+06,2.0273e+06,2.03704e+06,1.96804e+06,1.98632e+06,2.05671e+06,2.06287e+06,2.0604e+06,2.05806e+06,2.05555e+06,259452,273647,320766,1.05399e+06,569476,526636,939427,499786,498284,508923,496830,515492,728424,732247,728570,2.22717e+06,1.37306e+06,985208,982828,2.05636e+06,813374,702390,787567,814626,688755,718616,1.77037e+06,2.59607e+06,795019,1.14384e+06,2.80739e+06,990486,1.00151e+06,1.28459e+06,1.30112e+06,3.26305e+06,1.44833e+06,1.44593e+06,1.43948e+06,685461,1.8719e+06,1.91337e+06,2.84634e+06,308082,2.07265e+06,2.08467e+06,978369,993949,1.02366e+06,1.33897e+06,1.40423e+06,1.30646e+06,1.2393e+06,1.15864e+06,328575,328649,328761,328259,328261,328034,3.22996e+06,1.28423e+06,483640,373319,1.01159e+06,1.01943e+06,1.03306e+06,358862,1.25521e+06,1.16587e+06,1.41244e+06,1.41125e+06,1.48664e+06,498644,1.77521e+06,1.50667e+06,793486,1.43461e+06,1.11018e+06,692443,811193,2.16159e+06,938795,463190,1.0585e+06,654990,1.38238e+06,3.14775e+06,409993,1.17913e+06,930766,932919,529773,2.40042e+06,1.31233e+06,1.44374e+06,430680,446527,466598,1.28827e+06,1.04285e+06,1.5946e+06,1.71807e+06,1.34454e+06,1.39388e+06,539472", "agent_steps": "2.37802,30.6708,35.1273,39.8459,41.4188,2.88358,2.49037,7.20896,16.1219,20.5783,25.0348,29.4912,33.9331,2.62144,7.20896,11.7965,16.384,20.6875,25.4061,29.8189,34.1879,81.7889,64.0942,67.6332,47.5042,49.9384,80.6093,5.78355,2.52314,2.81805,2.5559,7.07789,11.4033,3.14573,2.88358,8.69171,2.62144,2.62144,2.62144,3.08565,8.48691,68.6162,77.7631,81.6579,2.64765,25.0348,29.6223,34.2098,38.6662,39.977,23.414,28.5082,33.62,38.7318,43.8209,29.7533,34.3671,15.0733,20.1851,25.2969,30.4087,15.6631,3.64544,2.93274,2.75251,15.2044,2.62144,14.7456,20.5783,34.1115,2.75251,4.23799,61.7349,7.97355,12.9237,3.53894,2.62144,2.77873,2.94912,7.53664,80.3471,84.9347,16.6789,21.0043,25.4935,11.9369,57.8683,2.76408,13.0841,2.7263,29.583,34.2098,2.81805,11.7965,3.77196,4.85622,20.3162,26.0833,24.6415,2.31014,34.0787,3.34234,9.96147,16.5806,8.12646,2.81805,15.4665,2.88358,18.0879,23.1997,28.3116,33.4234,38.5352,43.5159,45.7441,2.81805,12.2552,2.88358,3.04742,8.02816,12.3863,16.6134,21.463,25.7556,30.1138,34.4719,38.6499,39.977,2.92426,8.32307,69.206,3.2768,14.8767,20.7913,9.86317,22.7082,27.5251,32.6369,37.7084,42.5219,28.5737,33.62,54.526,17.7603,87.7678,5.8327,16.6052,3.12934,24.9037,29.3077,33.8457,38.2566,2.40299,7.07789,2.81805,31.632,5.49758,2.62144,3.40787,3.24039,8.47053,3.11296,8.22477,4.90701,29.6223,34.2098,38.6662,2.21512,2.88358,12.3208,3.40787,4.52198,21.1681,25.7338,2.5559,7.14342,5.50502,12.1242,16.384,20.6176,24.9474,29.2509,21.6269,26.4765,31.2643,35.9862,40.7634,42.8605,3.93216,2.56901,2.5559,20.4472,35.5018,39.9301,41.4843,8.51683,2.6979,7.24173,13.0417,20.8404,50.004,65.501,2.75251,2.7263,23.8551,20.8404,2.62144,2.40994,7.62839,2.88358,10.9554,32.0471,2.59335,33.8166,2.62144,3.80109,2.52831,2.53718,2.99281,8.01178,4.78413,3.14573,3.65363,2.68698,79.5607,84.2793,53.4774,9.50272,2.35461,2.88358,23.0687,2.62144,11.7965,3.11706", "uptime": "2.47389,35.3748,40.4371,45.7737,47.5536,1.27821,3.13324,8.69441,19.1127,24.3305,29.5486,34.7664,39.9815,2.01527,5.36904,8.68606,12.008,15.6362,19.5938,22.9426,26.3065,197,110.234,116.549,77.4357,81.1873,164.185,5.1922,23.9719,1.52319,4.61475,12.5782,20.7782,1.33867,1.88365,8.49869,1.88592,2.01226,2.2647,2.13622,6.16029,64.896,73.4582,77.1038,1.83822,17.1891,20.2334,23.2776,26.2333,27.1025,37.5895,45.6655,53.7676,61.9124,70.009,18.7577,21.6165,5.75222,7.67829,9.60196,11.5245,12.7996,1.52483,1.53068,1.82973,19.5583,1.43672,144.488,201.686,30.5386,1.94507,1.23949,65.1904,6.19464,9.93112,1.25439,2.38809,1.84287,1.84292,4.64214,724.458,765.86,15.4544,19.407,23.5198,8.12442,41.1246,6.18204,28.8353,1.86631,21.2592,24.3222,1.54335,9.79826,3.15045,4.9652,68.434,87.8144,10.6787,15.1603,35.1664,33.0466,99.3394,165.252,5.69687,1.55959,7.58735,1.52091,29.562,37.8928,46.2232,54.553,62.8827,71.4262,75.5417,1.53189,6.41945,1.39976,1.54558,4.00582,6.15005,8.27804,10.7223,12.8458,14.9583,17.0737,19.1022,19.7475,11.078,31.7095,215.986,3.157,26.2346,36.9095,11.81,45.3318,54.9658,65.1746,75.2033,84.7256,40.4279,47.317,74.4175,8.05505,63.1941,5.95904,16.8291,1.53013,32.8177,38.6745,44.8708,50.3165,3.51927,10.0989,1.6106,12.0871,7.02144,2.31168,1.23605,3.16913,8.50062,2.44292,6.37494,1.51079,21.2103,24.381,27.4627,3.56378,1.55362,6.50445,1.20402,14.8506,10.8714,13.0564,2.64341,7.25804,5.42169,9.4979,12.58,15.6516,19.197,22.9123,65.8538,80.6119,95.1787,109.548,124.1,130.488,1.23545,2.07031,5.29995,55.519,35.0444,39.4278,40.9472,21.868,2.20503,5.93345,9.3977,14.9273,33.7155,129.242,1.56446,1.84402,30.1402,15.5069,2.37606,3.77551,10.3631,1.36679,11.0773,70.4335,2.49857,52.5587,1.91655,1.22277,6.59962,2.44876,3.19917,8.57087,9.029,1.31087,2.79024,1.87826,178.473,189.244,119.832,7.47218,2.4821,1.8235,13.5153,1.98693,8.59124,5.82821", "epoch": "36.2857,117,134,152,158,11,38,110,246,314,382,450,517.778,20,55,90,125,157.833,193.833,227.5,260.833,624,489,516,724.857,762,1230,176.5,38.5,43,19.5,54,87,12,44,132.625,20,20,20,94.1667,259,523.5,593.286,623,40.4,382,452,522,590,610,714.538,870,1026,1182,1337.31,227,262.2,115,154,193,232,119.5,111.25,44.75,21,58,5,112.5,157,520.5,21,32.3333,471,60.8333,98.6,27,20,84.8,45,115,306.5,324,254.5,320.5,389,182.143,883,42.1765,199.647,41.6,451.4,522,21.5,90,57.5556,148.2,77.5,99.5,94,70.5,260,51,152,253,124,21.5,472,44,138,177,216,255,294,332,349,21.5,93.5,11,46.5,122.5,189,253.5,327.5,393,459.5,526,589.75,610,44.6207,127,264,25,227,317.25,150.5,173.25,210,249,287.692,324.417,436,513,416,271,669.615,89,253.375,47.75,190,223.6,258.222,291.875,18.3333,54,21.5,120.667,167.773,20,26,49.4444,129.25,95,251,149.75,226,261,295,33.8,44,188,104,69,323,392.667,39,109,84,185,250,314.6,380.667,446.333,330,404,477.056,549.105,622,654,15,9.8,39,78,541.714,609.286,633,129.957,41.1667,110.5,99.5,159,763,249.867,21,83.2,91,159,20,73.5455,232.8,11,167.167,244.5,39.5714,129,20,58,77.1579,38.7143,45.6667,122.25,36.5,12,111.5,41,607,643,204,145,71.8571,44,176,20,90,47.5625", "env/perf": "4.382e-05,0.961099,0.971547,0.978523,0.979147,3.71772e-05,0.000169102,0.661805,0.930388,0.954746,0.959263,0.968452,0.976243,8.73662e-05,0.544365,0.800083,0.870891,0.912505,0.948332,0.966457,0.971538,0.985828,0.983825,0.984323,0.986564,0.98683,0.981096,0.353305,0.102957,3.41552e-05,0.157473,0.797865,0.889996,3.95231e-05,5.06135e-05,0.755748,4.67929e-05,3.91125e-05,2.8285e-05,0.0843157,0.569749,0.988292,0.989742,0.989882,4.06293e-05,0.917839,0.952255,0.969513,0.97412,0.974454,0.938829,0.957668,0.970626,0.983432,0.986095,0.9362,0.952045,0.646196,0.753579,0.828299,0.86905,0.926209,0.00024062,4.19313e-05,4.20675e-05,0.846001,2.3378e-05,0.892034,0.943666,0.966055,5.77942e-05,5.34219e-05,0.98682,0.649932,0.804225,4.07159e-05,4.03722e-05,5.365e-05,0.056025,0.517474,0.977087,0.977722,0.893595,0.932329,0.945652,0.726281,0.983877,0.233548,0.909832,3.53985e-05,0.937773,0.954024,3.73067e-05,0.791537,0.234747,0.362505,0.920246,0.950441,0.854656,0.0137049,0.970854,0.399635,0.889791,0.934678,0.553998,3.80418e-05,0.765909,3.86144e-05,0.946615,0.963407,0.97378,0.979629,0.985369,0.987976,0.988349,4.15722e-05,0.689035,3.36864e-05,0.0233254,0.509134,0.751471,0.803863,0.875071,0.903374,0.945986,0.969431,0.97118,0.973502,0.311732,0.818857,0.987993,0.134713,0.923732,0.94487,0.804592,0.937762,0.960832,0.972798,0.980201,0.982797,0.954403,0.970401,0.978436,0.832735,0.979802,0.433674,0.9111,3.91871e-05,0.949997,0.967458,0.975627,0.98048,0.0224626,0.63268,3.07719e-05,0.898934,0.461272,3.86054e-05,3.58987e-05,0.366556,0.69624,0.100084,0.648492,0.000116861,0.950859,0.967411,0.97488,0.000267628,5.44345e-05,0.702282,2.36179e-05,0.517012,0.89273,0.921783,0.118752,0.549372,0.415624,0.806024,0.865118,0.886903,0.90945,0.930425,0.963396,0.968714,0.980567,0.986694,0.988327,0.989239,3.52517e-05,3.34459e-05,0.0585383,0.929379,0.973826,0.978465,0.979226,0.76903,0.00315367,0.562283,0.837793,0.880749,0.971545,0.981258,3.80712e-05,7.11478e-05,0.935646,0.911265,3.14876e-05,0.0275234,0.74268,3.70147e-05,0.844016,0.959881,0.0716305,0.970213,5.3913e-05,3.68597e-05,0.0270939,0.0164414,0.2213,0.738268,0.384421,3.73719e-05,0.127496,4.45572e-05,0.985755,0.986191,0.982955,0.670441,3.09987e-05,6.22009e-05,0.943531,2.96085e-05,0.767464,0.316774", "env/score": "0.0582739,842.482,859.884,870.113,872.954,0.0213557,0.223163,415.475,748.461,787.266,811.279,827.154,842.872,0.0903851,351.968,639.828,724.012,774.753,814.448,841.011,849.27,887.886,880.526,881.629,878.543,879.815,887.238,254.383,62.0445,0.0202427,83.1774,602.068,711.923,0.0226757,0.323033,578.231,0.0261022,0.0228198,0.0370508,44.6109,420.602,881.721,886.54,887.165,0.0245926,780.78,831.098,853.843,867.205,869.398,800.213,827.456,852.29,871.299,876.483,807.718,831.403,464.362,604.119,680.687,724.423,742.345,0.135103,0.0237179,0.0313569,709.492,0.0133864,735.06,790.983,843.004,0.100516,0.0337725,876.834,434.497,656.374,0.0322499,0.027277,0.0486285,18.8366,331.936,887.531,889.083,743.733,790.105,818.104,507.594,872.405,137.102,728.207,0.029238,817.087,842.497,0.0230387,643.433,157.151,251.032,782.222,827.712,689.519,4.40903,841.212,281.559,706.422,770.53,389.344,0.021647,581.816,0.0219805,779.632,817.318,838.228,854.041,867.781,875.298,878.383,0.0286243,496.002,0.0191123,6.0388,324.188,558.881,657.941,721.853,755.343,800.888,829.25,838.636,843.057,208.03,642.36,887.402,75.4097,762.202,798.701,637.628,801.7,830.387,851.478,865.652,873.569,818.926,842.804,877.197,659.848,876.594,325.195,775.695,0.0251769,811.824,841.782,858.107,866.869,5.0223,424.719,0.0225014,732.61,350.985,0.0246232,0.0209639,243.83,507.205,52.9244,468.828,0.0642284,818.973,841.979,854.612,0.122724,0.123324,544.605,0.0124007,389.141,716.307,769.716,68.0668,403.609,299.474,646.886,722.459,759.721,788.035,814.695,826.063,843.4,864.215,877.176,884.418,886.685,0.0219032,0.0192651,29.6647,785.856,859.034,868.099,870.334,620.119,0.604871,363.514,675.22,743.44,870.346,884.697,0.0219083,0.0879082,801.181,757.779,0.0584246,13.4178,556.861,0.0220791,702.963,842.842,36.6517,845.245,0.0320421,0.0216447,20.9936,5.03261,135.715,521.826,273.499,0.0231074,81.9198,0.026955,887.009,887.667,881.491,485.274,0.0174724,0.0572068,742.606,0.0370402,586.77,211.414", "env/rings_passed": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "env/ring_collisions": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "env/collisions": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "env/oob": "1,0.000747317,0,0,9.76563e-05,1,0.999414,0.0854158,0.00508003,0.00428071,0.0133576,0.0110004,0.00855467,0.997483,0.119484,0.0383614,0.0320969,0.0279743,0.0101761,0.00596217,0.00679663,0,0,0,0.000180375,9.93937e-05,0,0.440785,0.743104,1,0.689564,0.067514,0.0281543,1,1,0.0286599,1,1,1,0.710561,0.158861,0,0,0,1,0.000246002,0,0,0,0,0.00500507,0.00298185,0.00277656,0,0,0.000138427,0.000687285,0.0167465,0.0118737,0.00686894,0.0133311,0,1,1,1,0.0103303,1,0.0467051,0.0167728,0,1,1,0.000198236,0.0739032,0.0348915,1,1,1,0.801722,0.187203,0,0,0.0230226,0.0142198,0.0174716,0.0245303,0.000199183,0.530225,0.0186337,1,0.00576558,0.000882832,1,0.127574,0.508318,0.464505,0.000464757,0.000433671,0.00999204,0.892293,0.00320434,0.428925,0.0150682,0.0134472,0.0652112,1,0.00187349,1,0.000820075,0.000434175,0.000163666,0.00117163,0,0,0,1,0.0211504,1,0.83084,0.0692097,0.0709656,0.0764924,0.0535974,0.0432471,0.0168748,0.0041299,0.00548037,0.00359928,0.5201,0.101298,0.000195274,0.62627,0.0247495,0.0187199,0.047124,0.00108777,0.00138434,0.00183606,0.000603833,0.000852628,0.011802,0.00331371,0,0.00453627,0.000414881,0.436102,0.01638,1,0.0140035,0.00665498,0.00437535,0.00179728,0.911772,0.096727,1,0.00631716,0.363303,1,1,0.436344,0.219115,0.723044,0.114501,1,0.00046496,0.000644111,0.000456069,0.989462,0.969601,0.0858535,1,0.323241,0,0,0.742626,0.159563,0.36056,0.0136226,0.00524264,0.00409304,0.0114815,0.00461144,0,0.00565867,0.00161281,0,0.000700452,0,1,1,0.845809,0.00830219,0,0.000470699,0,0.0321539,0.977456,0.112209,0.0208741,0.0243656,0,0,1,1,0.00439908,0.0220689,1,0.661977,0.0251909,1,0.0136217,0.000182216,0.709725,0.00862554,1,1,0.750308,0.815518,0.547212,0.109069,0.388423,1,0.623678,1,0,0,0.000975705,0.147319,1,1,0,1,0.132476,0.473539", "env/timeout": "0,0.999253,1,1,0.999902,0,0.000586338,0.914584,0.99492,0.995719,0.986642,0.989,0.991445,0.00251716,0.880516,0.961639,0.967903,0.972026,0.989824,0.994038,0.993203,1,1,1,0.99982,0.999901,1,0.559215,0.256896,0,0.310436,0.932486,0.971846,0,0,0.97134,0,0,0,0.289439,0.841139,1,1,1,0,0.999754,1,1,1,1,0.994995,0.997018,0.997223,1,1,0.999862,0.999313,0.983253,0.988126,0.993131,0.986669,1,0,0,0,0.98967,0,0.953295,0.983227,1,0,0,0.999802,0.926318,0.965108,0,0,0,0.198278,0.812797,1,1,0.976977,0.98578,0.982528,0.97547,0.999801,0.469775,0.981366,0,0.994234,0.999117,0,0.872426,0.491682,0.535495,0.999535,0.999566,0.990008,0.107707,0.996796,0.571075,0.984932,0.986553,0.934789,0,0.998127,0,0.99918,0.999566,0.999836,0.998828,1,1,1,0,0.97885,0,0.16916,0.93079,0.929034,0.923508,0.946403,0.956753,0.983125,0.99587,0.99452,0.996401,0.4799,0.898702,0.999805,0.37373,0.97525,0.98128,0.952876,0.998912,0.998616,0.998164,0.999396,0.999147,0.988198,0.996686,1,0.995464,0.999585,0.563898,0.98362,0,0.985997,0.993345,0.995625,0.998203,0.0882282,0.903273,0,0.993683,0.636762,0,0,0.563656,0.780885,0.276956,0.885499,0,0.999535,0.999356,0.999544,0.0105381,0.0303988,0.914146,0,0.676759,1,1,0.257374,0.840437,0.63944,0.986377,0.994757,0.995907,0.988519,0.995389,1,0.994341,0.998387,1,0.9993,1,0,0,0.154191,0.991698,1,0.999529,1,0.967846,0.0225443,0.887791,0.979126,0.975634,1,1,0,0,0.995601,0.977931,0,0.338023,0.974809,0,0.986378,0.999818,0.290275,0.991374,0,0,0.249692,0.184482,0.452788,0.890931,0.611577,0,0.376322,0,1,1,0.999024,0.852681,0,0,1,0,0.867524,0.526461", "env/episode_return": "0.398458,24.8637,25.4612,25.9663,26.0835,-3.19043,-1.33944,11.1653,20.4987,21.7648,22.5478,23.1426,23.8337,-0.703513,36.3735,59.9111,66.3837,69.214,72.4939,74.9406,75.7117,53.614,31.0152,31.1028,62.6675,62.8181,139.571,9.11068,2.7892,-3.51407,0.00854106,10.0647,12.5963,-2.59576,-3.23841,22.7771,-1.04068,-2.06637,0.0743566,1.14853,20.0973,26.2874,26.6066,26.6395,-1.64735,55.0418,57.6895,59.2284,60.113,60.2582,28.6534,30.0025,31.3794,32.9553,33.4566,63.0764,65.1293,30.5464,40.9799,45.1618,46.3858,32.2169,-2.41568,-3.73726,-0.817435,22.4427,-4.78472,71.2631,76.5989,67.5728,-1.46758,-6.36455,46.4448,22.3254,34.3231,-2.03284,-4.60093,-1.3433,-1.14669,11.7374,90.0301,90.2165,64.5628,66.4353,68.661,33.7543,69.7546,1.20293,27.8399,-0.806249,39.3111,40.1557,-3.84177,15.515,7.48564,13.4181,17.4073,18.7669,45.2764,-2.34978,49.9955,12.8459,37.0022,40.1067,16.6563,-0.895716,41.819,-1.79997,22.627,24.1836,25.2484,26.0691,26.8476,27.3461,27.5127,-1.02114,6.26556,-1.19332,-2.3295,18.5535,32.1456,37.7297,43.2065,46.1249,51.3841,55.2568,56.4914,56.6566,8.27112,33.7465,39.7822,45.6804,25.6761,27.5474,21.4947,38.1925,39.269,40.4021,41.1945,41.7016,55.3398,57.2332,31.1346,19.4197,57.6788,11.222,37.8971,0.102743,31.999,33.1881,34.0751,34.5297,0.174585,44.8959,-2.40839,10.4008,17.5842,-2.17106,-70.3074,2.02751,4.98242,-0.0479073,24.1678,-3.89744,54.3648,56.1113,57.2633,-0.0717762,0.499443,125.896,-3.60424,8.94391,12.8862,13.6662,6.96002,42.5475,4.19895,19.6503,21.1624,21.5104,22.5034,23.295,31.0487,31.9482,33.1454,34.0276,34.5599,34.6915,-1.08579,-3.63869,0.335757,25.7537,64.9573,66.1016,66.3259,32.5265,-0.215078,19.6385,26.0622,30.3117,43.7505,58.3509,-1.95631,-16.1109,17.1137,35.2034,-1.14204,-0.318249,13.1724,-8.49031,37.4759,50.3423,0.651878,29.8427,-5.26517,-1.51231,-4.35866,1.27688,0.488331,13.6781,8.74045,-1.54576,10.1647,-2.15589,49.9167,50.0433,38.9087,29.2941,-0.877638,-1.9126,3.52673,-0.760295,30.5318,11.541", "env/episode_length": "145.315,1023.4,1024,1024,1023.92,112.757,204.146,963.247,1019.85,1020.34,1012.94,1014.93,1016.97,200.331,930.174,991.913,996.66,1000.44,1015.38,1019,1018.24,1024,1024,1024,1023.84,1023.91,1024,642.707,453.422,116.775,463.078,969.754,1000.84,113.564,208.851,1001.79,110.691,113.45,155.704,415.889,890.402,1024,1024,1024,116.931,1023.78,1024,1024,1024,1024,1019.8,1021.55,1021.65,1024,1024,1023.89,1023.52,1009.8,1014.09,1018.36,1013.01,1024,119.548,108.851,124.594,1015.53,94.9114,985.406,1010.16,1024,176.835,114.368,1023.83,966.61,993.919,128.5,119.732,143.135,337.913,863.921,1024,1024,1005.06,1012.14,1009.3,1003.62,1023.85,574.737,1008.47,144.536,1019.11,1023.26,118.761,921.562,585.375,640.019,1023.64,1023.68,1016.65,261.924,1021.61,669.243,1011.74,1013.33,970.237,112.047,1022.64,112.605,1023.36,1023.69,1023.88,1023.17,1024,1024,1024,126.165,1006.92,110.36,327.024,966.246,965.285,962.232,980.153,988.283,1010,1020.79,1019.41,1021.08,596.352,942.82,1023.84,504.169,1004.44,1012.18,986.92,1023.1,1022.89,1022.45,1023.53,1023.29,1014.33,1021.31,1024,1020.52,1023.66,659.438,1011.13,123.598,1012.3,1018.36,1020.37,1022.49,278.651,943.141,131.718,1018.68,722.673,116.475,111.36,656.226,851.16,402.008,929.052,113.957,1023.63,1023.53,1023.63,172.589,266.654,955.546,106.417,756.993,1024,1024,408.502,893.626,715.168,1012.86,1019.86,1020.63,1014.72,1020.31,1024,1019.6,1022.69,1024,1023.41,1024,118.526,112.307,360.836,1017.17,1024,1023.63,1024,997.052,216.249,932.567,1008.22,1002.83,1024,1024,113.6,144.907,1020.46,1004.96,184.202,486.342,1002.73,114.476,1013.18,1023.86,461.329,1016.92,110.202,113.496,452.204,338.636,575.43,934.981,692.695,117.942,500.839,115.506,1024,1024,1023.17,905.312,111.098,147.647,1024,149.756,909.139,625.946", "env/ema_dist": "2.80243,0.0033077,0.00126762,0.00105963,0.001281,2.7316,3.12448,0.368341,0.0179019,0.0138525,0.0399697,0.0334113,0.0245892,3.04338,0.403757,0.104387,0.0849882,0.0734798,0.0294102,0.0176213,0.020393,0.000837044,0.000744159,0.000693199,0.00160323,0.00128245,0.00129178,1.36974,2.28181,2.72703,2.31051,0.197515,0.0862482,2.73794,2.87129,0.118782,2.71591,2.73983,2.92125,2.24497,0.487049,0.000911008,0.000723495,0.000695684,2.75414,0.00365223,0.00177029,0.00174789,0.00159888,0.00153199,0.0193842,0.0134218,0.0115126,0.00211798,0.00161904,0.00749756,0.00823211,0.090027,0.0556559,0.0398192,0.0497972,0.0195275,2.82904,2.69967,2.85963,0.0353107,2.61622,0.130236,0.0479524,0.00228439,3.07748,2.77094,0.00153708,0.297437,0.113621,2.92847,2.77252,2.91796,2.40476,0.601971,0.000777135,0.000778905,0.0699238,0.0434662,0.0488613,0.178315,0.00283184,1.72155,0.0567996,2.8891,0.0177768,0.00530369,2.76139,0.355844,1.56678,1.50714,0.00382239,0.00252295,0.0435388,2.74036,0.00915665,1.30501,0.0461243,0.041413,0.27256,2.71403,0.0308439,2.72741,0.00603681,0.00357702,0.00254876,0.00447828,0.00125181,0.000995635,0.000874576,2.8273,0.0986139,2.71292,2.57093,0.319931,0.221691,0.227871,0.157001,0.138108,0.0568441,0.0196293,0.0217916,0.0173109,1.60307,0.277731,0.00121094,1.89986,0.0751098,0.0555211,0.143599,0.00531962,0.006087,0.00617527,0.00328801,0.00337357,0.0387475,0.0126787,0.000869701,0.033723,0.00254737,1.38799,0.0477108,2.79119,0.0382375,0.019036,0.0134617,0.00670161,2.82103,0.322241,2.81776,0.0380185,1.11226,2.74114,2.74011,1.3869,0.598239,2.21032,0.335375,2.75023,0.00426914,0.00461297,0.00369975,2.91088,3.2717,0.301905,2.65838,1.00568,0.0347208,0.0419379,2.13966,0.459428,1.13748,0.0502661,0.02518,0.0244888,0.0402158,0.0195473,0.00188385,0.0150025,0.00509777,0.000826689,0.00244802,0.000729037,2.77802,2.72415,2.72348,0.0238079,0.00129794,0.00223668,0.00107178,0.125393,3.02019,0.359441,0.0753208,0.07848,0.00151019,0.000750696,2.72044,2.95757,0.0148222,0.0901912,3.07857,2.32231,0.148055,2.72794,0.0520258,0.00206327,2.27699,0.0235118,2.73454,2.72924,2.62317,2.41311,1.77266,0.323235,1.2056,2.76707,2.0323,2.75715,0.000744965,0.000710317,0.00314525,0.504026,2.70073,3.05647,0.0209016,2.93177,0.386767,1.42904", "env/ema_vel": "4.1665,0.0110616,0.00623093,0.00495996,0.00534187,3.79605,4.0699,0.527887,0.0424614,0.0366744,0.0818889,0.0641224,0.0519096,4.19565,0.892316,0.265026,0.216122,0.176341,0.0714543,0.0434056,0.0478886,0.00463462,0.00316222,0.00305584,0.00607402,0.00538369,0.00553915,1.91419,3.78072,3.98416,3.03032,0.418341,0.174165,3.82123,4.5637,0.244572,3.58381,3.77884,4.16371,3.16241,0.878293,0.00464437,0.00409892,0.00408341,3.86899,0.0161985,0.00994257,0.00784742,0.00757399,0.00765633,0.0428548,0.0259697,0.0238093,0.00504338,0.00440968,0.0184149,0.0160527,0.268848,0.157626,0.101746,0.12492,0.0683032,3.6711,3.57166,3.71859,0.0871354,2.91049,0.261269,0.101517,0.00950197,4.23141,3.50311,0.00438512,0.656162,0.188038,3.70459,3.86409,4.10521,3.43122,0.891725,0.00382111,0.00379775,0.129047,0.0879095,0.106987,0.477482,0.00773166,2.44921,0.119074,4.05241,0.0416672,0.0117625,3.94205,0.701185,2.44513,1.93259,0.0160787,0.0111898,0.1208,3.59858,0.0230942,1.9598,0.103844,0.0864041,0.527543,3.79144,0.1107,3.7825,0.0151527,0.0102482,0.00717047,0.00972581,0.00352418,0.00302432,0.00292981,4.024,0.258029,3.72573,3.84839,0.804362,0.548351,0.520347,0.355372,0.272811,0.12403,0.043498,0.0511479,0.0394373,2.46015,0.569331,0.00386849,2.75744,0.146045,0.104094,0.276154,0.0150132,0.0147475,0.0166743,0.00807899,0.00926133,0.0713859,0.0292161,0.00359049,0.0807471,0.00739221,1.80522,0.106663,3.98991,0.0897029,0.0459472,0.0319063,0.0164396,4.09683,0.69992,4.19806,0.0880868,1.62798,3.7287,3.67634,2.01533,1.20378,3.04417,0.69753,3.69171,0.0158688,0.0133232,0.0111536,3.95841,4.18792,0.502246,3.76444,1.53283,0.131453,0.122156,3.52616,0.880309,1.68041,0.125278,0.058548,0.0467209,0.0769081,0.0363962,0.00781929,0.037518,0.0139279,0.00373224,0.00743581,0.00308576,3.92116,3.80039,3.72431,0.0522086,0.00647236,0.0076423,0.00515545,0.261796,4.10948,0.794937,0.176055,0.140691,0.00632214,0.0040862,3.89237,3.76271,0.035316,0.204325,3.97833,3.29538,0.37068,3.90931,0.11613,0.00947588,3.40839,0.0540076,3.4433,3.8352,3.48768,3.67773,2.57539,0.63143,1.82422,3.89776,2.71674,3.76641,0.00448587,0.00431781,0.00967431,0.801549,3.81836,3.72488,0.0681227,4.19341,0.809176,2.24864", "env/ema_omega": "12.8944,0.252853,0.180201,0.135251,0.131448,13.5001,5.3492,1.63106,0.469508,0.308252,0.348003,0.275156,0.210131,7.40413,3.01104,1.50747,0.996364,0.687554,0.362131,0.218005,0.187799,0.0871779,0.102618,0.0995393,0.0822307,0.0803199,0.115821,5.0839,7.23464,14.4572,4.50804,1.67871,0.822985,11.6608,11.2541,1.46829,8.46736,13.6177,10.014,6.96742,3.4072,0.0706187,0.0622386,0.0614391,14.8092,0.529099,0.305187,0.190386,0.159048,0.156775,0.392426,0.260504,0.186625,0.0969869,0.0820454,0.383781,0.283474,2.09948,1.56602,1.06995,0.891164,0.340353,5.74812,10.7771,7.36512,1.03453,12.9733,1.00032,0.453248,0.209132,5.52469,8.63262,0.0819953,2.49544,1.546,7.24594,13.0709,10.7243,8.66502,4.49268,0.146626,0.142236,0.780751,0.512121,0.468077,1.09221,0.0930527,5.82031,0.651534,11.4296,0.444568,0.293024,14.3673,2.67303,6.94685,4.13325,0.51481,0.324517,0.915318,9.9524,0.184755,4.25738,0.799885,0.465668,2.90442,15.7527,1.38004,15.0858,0.33567,0.227606,0.162997,0.129166,0.0901968,0.0740672,0.0720172,10.0671,1.92803,15.8728,7.57202,2.65305,1.80283,1.66452,1.12091,0.792899,0.40291,0.173593,0.171662,0.145434,5.03049,1.87781,0.076016,6.85231,0.54769,0.431616,1.59402,0.40273,0.25723,0.18407,0.127031,0.112457,0.355805,0.194866,0.137461,1.01625,0.12698,3.43012,0.681212,16.5705,0.383829,0.230716,0.169974,0.123924,6.30507,2.53913,16.8085,0.571279,3.93342,13.7761,13.4096,5.14236,3.98476,7.78936,3.25084,10.0539,0.308724,0.200698,0.15063,10.1557,4.34688,2.30264,18.9603,3.89077,0.447232,0.205029,7.47852,3.72613,4.39272,1.30833,0.86462,0.702364,0.64026,0.457294,0.230563,0.245784,0.131814,0.0830392,0.0777782,0.0665078,10.8033,16.355,4.91145,0.538241,0.163998,0.137354,0.129729,1.46548,7.29243,3.53334,1.05858,0.891125,0.177625,0.118743,14.9908,8.35545,0.441682,0.47253,8.80649,4.46034,1.36325,16.0909,1.04701,0.253675,6.05098,0.290593,9.08972,13.0482,4.7703,8.75097,4.60631,1.92479,6.02902,11.0972,5.55329,12.347,0.0883002,0.0856501,0.112812,2.11101,17.9979,6.17038,0.230479,7.08111,3.01177,6.5247", "env/n": "3975.29,781.4,724.714,755.8,10240,12390.7,2472.44,510.222,536.222,513.5,545.667,515.625,493.111,4468.6,962.2,937.4,950.6,699,833,921.5,742.333,10103,383.263,10003,374.143,10061,10030,2314.62,241.447,9666,1478.33,402.545,393.364,13088.3,3548.8,620.375,7556.6,7618.6,4790.83,3952.83,887.429,638.214,614.071,10116,7373.6,891.4,923.6,917.6,758.4,10052,380.846,385.385,384.846,382.846,363.308,1024,999.8,1482.67,1559.67,1949.33,1812.33,740.125,11750,10765,6872,516.333,12664.7,134.545,128.6,706.333,5259,18860.3,10089,914.833,914.4,13180.7,6173.33,6632.8,4580,1229.5,254.583,10240,715.667,712.833,660.571,942.429,10041,1004.41,305.588,6553.4,906,895.6,9335,1022.4,2539.44,1759.53,248.5,258.682,1528.33,605.935,606.143,186.644,63.198,66.2376,996,9959,1161.25,10050,399.308,370.769,393.538,375,388.538,371.308,10134,8781.5,1251,12025.7,5662,1363,1261.33,1259.75,1153,1348.67,1130,1298.33,1035,10002,630.862,208.519,10242,2101,397,351.188,572.8,372.417,382.462,386.154,375.462,370.833,453.727,447.909,10103,1340.8,881.846,2036.65,636.562,9974.25,518,450.8,503.667,494,2186,594,8390.25,1619.33,1161.77,6336.17,14131,1527.33,722,3826.14,789.833,16758.5,892.6,905,764.8,2807.1,4980.25,1261.75,15390.7,473.178,1255.75,1291.67,2558.14,743.286,1728.56,827,831.4,822.6,724.167,712,259.278,250.789,249.278,259.632,244.556,10049,16065.3,7823.2,1265.47,259.355,621.143,571.286,10023,237.348,3726.17,765.333,909.375,916,10001,483.867,9538.75,6565,498.833,919.4,4072.67,1480.55,496.3,12577,577.333,386.643,2247.14,513.375,7851,16572.3,1100.16,2868.86,1883.44,616,985.542,12470,3121.12,7578.2,309.276,10112,10249,898.286,5763.14,6517.4,1044.6,5811,1082.2,996.562", "perf/rollout": "0.259857,0.220414,0.211361,0.219497,0.217712,0.395705,0.171341,0.149397,0.14846,0.149167,0.148576,0.149253,0.146838,0.280132,0.260188,0.257382,0.259045,0.304007,0.292096,0.262491,0.308739,0.0956731,0.200452,0.179152,0.168874,0.110233,0.0805464,0.221064,0.0482285,0.385029,0.136091,0.143239,0.199626,0.418513,0.261169,0.261955,0.251068,0.283634,0.228772,0.311308,0.346396,0.205407,0.19682,0.0816495,0.273891,0.262407,0.262036,0.262002,0.224108,0.0748265,0.166994,0.161172,0.164983,0.167176,0.157998,0.271793,0.281276,0.433075,0.43096,0.43085,0.430895,0.248741,0.398008,0.344344,0.245961,0.141583,0.548203,0.0853768,0.088933,0.231865,0.268511,0.440977,0.0715754,0.237372,0.247293,0.46804,0.234403,0.359147,0.283361,0.289206,0.133943,0.126061,0.220517,0.220338,0.20654,0.220179,0.102973,0.181094,0.151311,0.316285,0.305264,0.305579,0.330718,0.217466,0.287876,0.209766,0.0777346,0.0800799,0.40184,0.0525807,0.184399,0.0462978,0.0411018,0.0443046,0.304803,0.342494,0.34861,0.374844,0.114354,0.114799,0.114856,0.114451,0.114835,0.144675,0.114332,0.339206,0.327505,0.415178,0.352655,0.346704,0.343789,0.350535,0.349502,0.337986,0.336191,0.337029,0.288669,0.142323,0.106665,0.082564,0.0833821,0.191776,0.126641,0.145737,0.208766,0.160756,0.171092,0.153324,0.165744,0.139024,0.152588,0.149284,0.0425973,0.373057,0.255482,0.214063,0.208049,0.440462,0.149966,0.179595,0.16552,0.144348,0.168868,0.149801,0.331901,0.452114,0.209714,0.235489,0.446928,0.264588,0.262271,0.256033,0.249668,0.515978,0.257882,0.258858,0.222728,0.192153,0.32938,0.320879,0.457727,0.0997522,0.366836,0.361783,0.213501,0.205366,0.218483,0.306423,0.281818,0.329946,0.324766,0.346425,0.0824602,0.0822464,0.0794044,0.0822502,0.0797016,0.0417259,0.534129,0.366866,0.114109,0.0691243,0.218315,0.192695,0.0624442,0.134224,0.16962,0.199916,0.279407,0.279805,0.14708,0.176886,0.330967,0.367934,0.146117,0.252429,0.23017,0.266781,0.20022,0.458208,0.288164,0.21901,0.245438,0.15129,0.265316,0.545442,0.214351,0.311107,0.252058,0.244784,0.155236,0.425088,0.329488,0.271986,0.150628,0.104747,0.0499902,0.277594,0.434335,0.278076,0.269213,0.263088,0.247652,0.140845", "perf/eval_gpu": "0.0366564,0.0247738,0.0255491,0.0236729,0.0225545,0.0227333,0.0184414,0.015621,0.0157908,0.0158396,0.0155278,0.0158771,0.0156006,0.0433759,0.0255177,0.0245826,0.0264351,0.114539,0.063119,0.0274353,0.102297,0.0238458,0.0849944,0.0665389,0.0514965,0.0323139,0.0286977,0.031045,0.0283666,0.0683925,0.0306729,0.0302053,0.0699125,0.021414,0.0150594,0.0779324,0.0231479,0.0440936,0.0287829,0.0568174,0.0900098,0.0333568,0.0320896,0.0132651,0.0372338,0.0309647,0.0306817,0.0307432,0.0261748,0.00861832,0.0480351,0.046452,0.0467982,0.0476885,0.0439533,0.0155802,0.0442614,0.0168351,0.0167033,0.0167614,0.0167349,0.0450442,0.0176972,0.0287421,0.0131811,0.0115424,0.0495948,0.0489293,0.0543048,0.0388878,0.0305986,0.0240219,0.00669464,0.016483,0.0173509,0.0218624,0.0347252,0.0852917,0.0229006,0.0199499,0.0697786,0.060029,0.0338158,0.0338547,0.0315659,0.0298222,0.0190735,0.0828398,0.0610974,0.059525,0.0493812,0.0509545,0.0352378,0.0186591,0.0593843,0.0391628,0.0134385,0.013394,0.0139949,0.0247145,0.0215401,0.0279621,0.0229917,0.0260953,0.0617253,0.043632,0.0267557,0.057815,0.0161175,0.0158874,0.0159947,0.0158383,0.0159819,0.0441759,0.0164132,0.0415963,0.0287513,0.0527958,0.0336716,0.028955,0.0288687,0.0337339,0.0325938,0.0285442,0.0280579,0.0280767,0.0240575,0.0119732,0.0483678,0.0272677,0.018823,0.0238406,0.0229367,0.0483322,0.0439319,0.0464389,0.0531442,0.03864,0.0521892,0.0315075,0.0275388,0.0257218,0.00714616,0.0250904,0.027566,0.0356024,0.0340612,0.0465195,0.0158806,0.0565461,0.0292671,0.017498,0.0264253,0.0176705,0.0327284,0.0155285,0.0563826,0.034756,0.0133707,0.0760572,0.0807346,0.0420485,0.0385271,0.0223209,0.0269286,0.0278233,0.0252579,0.0657936,0.0265339,0.0219088,0.0209138,0.0406732,0.0349634,0.0296119,0.0382819,0.0312912,0.0420771,0.0661781,0.0446523,0.0854333,0.0969124,0.133297,0.0162831,0.0162296,0.0164589,0.0164993,0.015876,0.0083131,0.0322487,0.123575,0.0262174,0.010944,0.0377432,0.0355531,0.0107869,0.0589657,0.0259745,0.0167514,0.040103,0.0376884,0.0159576,0.0488849,0.036141,0.0882731,0.0119085,0.0214982,0.0297217,0.0902626,0.0483276,0.0679656,0.121722,0.0914888,0.0513029,0.0192322,0.0322196,0.0486126,0.0769296,0.105951,0.0771815,0.0732337,0.0417199,0.0257613,0.0813747,0.0343375,0.0541705,0.0297395,0.0110682,0.0545447,0.18831,0.0261434,0.0104336,0.0310199,0.0187254,0.0312749", "perf/eval_env": "0.196188,0.176917,0.166772,0.177464,0.18385,0.354871,0.136569,0.0904042,0.106298,0.114475,0.115684,0.113965,0.109167,0.211376,0.21405,0.213666,0.215527,0.15546,0.183416,0.20548,0.16551,0.062301,0.0822511,0.0798571,0.0819365,0.0561154,0.0446245,0.164083,0.0146549,0.277067,0.089522,0.0852931,0.0791138,0.375206,0.234629,0.142689,0.185991,0.218354,0.178201,0.19384,0.161383,0.155838,0.148997,0.0623378,0.188955,0.195619,0.195742,0.195554,0.167687,0.0560133,0.072646,0.0820594,0.0913136,0.0841111,0.0890996,0.223073,0.20063,0.366833,0.358283,0.36427,0.358934,0.146246,0.354733,0.284065,0.223233,0.105856,0.411623,0.0269356,0.0241559,0.163328,0.222087,0.368528,0.0525707,0.158287,0.182365,0.425468,0.185004,0.199658,0.242099,0.240952,0.0485694,0.0491982,0.142774,0.142368,0.146451,0.145581,0.0682035,0.0706788,0.0672841,0.212492,0.221219,0.217836,0.260217,0.156586,0.172414,0.141352,0.0480888,0.0542652,0.284915,0.0220185,0.131621,0.0136772,0.0132044,0.0131362,0.192791,0.253723,0.294719,0.268377,0.0808043,0.0856629,0.0856475,0.0854524,0.0856193,0.0798628,0.0793917,0.277857,0.266338,0.277568,0.287649,0.289067,0.287019,0.240788,0.246782,0.236003,0.231988,0.232704,0.198312,0.098436,0.0431583,0.0456258,0.0539471,0.154418,0.0905315,0.0779372,0.132823,0.0804172,0.0843996,0.0886805,0.0793327,0.0862559,0.10444,0.104774,0.0312623,0.308093,0.176236,0.15735,0.146683,0.258369,0.116346,0.101935,0.109173,0.11779,0.10313,0.104235,0.278495,0.321027,0.108101,0.185671,0.330817,0.131029,0.124283,0.186312,0.184737,0.402594,0.204912,0.204987,0.172694,0.0899596,0.277963,0.273211,0.386,0.0441616,0.283319,0.277957,0.156573,0.155087,0.151731,0.197572,0.195965,0.186763,0.167459,0.157133,0.0544399,0.0541355,0.0487361,0.0568311,0.0548529,0.0288935,0.480207,0.171895,0.0738047,0.0470467,0.129073,0.108474,0.0371266,0.0492606,0.119509,0.123584,0.172057,0.216671,0.109463,0.110059,0.248429,0.214986,0.103646,0.19241,0.156516,0.123752,0.106021,0.349778,0.111372,0.0882843,0.159287,0.110801,0.21755,0.452613,0.0812697,0.150487,0.143497,0.138165,0.0877701,0.350215,0.168096,0.215903,0.0699196,0.0613051,0.0358414,0.182549,0.140398,0.222746,0.22884,0.206586,0.181504,0.07316", "perf/train_misc": "0.0267219,0.0289908,0.0275818,0.0288898,0.0289801,0.0318297,0.0230697,0.0203367,0.0202926,0.020273,0.0203367,0.0203047,0.0199973,0.0361983,0.0272773,0.0272312,0.027225,0.0209154,0.0254256,0.0273254,0.022955,0.00633888,0.00835919,0.00844301,0.00876772,0.00600694,0.00867574,0.0204516,0.00321973,0.00699826,0.0246382,0.0183495,0.0183939,0.0465161,0.0506786,0.0164075,0.0311007,0.0250402,0.026601,0.0140337,0.0116887,0.0121601,0.0116548,0.00495616,0.0117881,0.0100916,0.0100762,0.0100761,0.00860947,0.00286106,0.00990969,0.00995287,0.0100764,0.00999673,0.00935202,0.0223151,0.0207743,0.0293447,0.0293397,0.0293309,0.0292911,0.036364,0.0409618,0.030519,0.0379547,0.0313931,0.0837318,0.00560271,0.00557996,0.0108144,0.0235166,0.0251642,0.0105626,0.0349318,0.0355199,0.0243655,0.0247309,0.0100598,0.0422141,0.0385039,0.0149731,0.0148737,0.0192923,0.0192264,0.0176509,0.0356921,0.00346464,0.0138785,0.0120241,0.0192188,0.0165866,0.0162673,0.0230191,0.0297602,0.0176496,0.0167918,0.0165811,0.0166659,0.0357809,0.00310289,0.0115611,0.00301139,0.00269118,0.0026896,0.0109349,0.0172322,0.0259051,0.0172013,0.0128916,0.0129144,0.0129261,0.0129513,0.0129479,0.0122841,0.0129036,0.0160402,0.0122843,0.014228,0.0190149,0.016472,0.016504,0.0158754,0.0160993,0.0164064,0.0163227,0.0163592,0.0139925,0.00686602,0.00837376,0.00749582,0.0111812,0.0381246,0.0140354,0.0131774,0.0226894,0.0194198,0.0200429,0.0200676,0.0195374,0.0194947,0.0156432,0.0156425,0.00449722,0.0272898,0.0173141,0.0208656,0.0190485,0.0114691,0.0210619,0.0214206,0.0215137,0.0203345,0.0167297,0.0130798,0.0353529,0.0292074,0.0149385,0.0237143,0.0728507,0.0272897,0.0238516,0.0127056,0.0118835,0.0177781,0.0150394,0.0150356,0.0129138,0.0213522,0.0380993,0.0327796,0.0107985,0.00788787,0.0126642,0.012614,0.0231678,0.019838,0.0124146,0.0177151,0.0179694,0.0176227,0.0160906,0.0151051,0.0117735,0.0117929,0.0114228,0.0115457,0.0112584,0.00594739,0.0181402,0.0330275,0.0152661,0.0161445,0.0114799,0.0102399,0.00342016,0.0155543,0.0373313,0.0292358,0.0169694,0.0169551,0.00718214,0.0171187,0.0460513,0.00719736,0.0312607,0.021863,0.0212381,0.0160484,0.0170823,0.0287052,0.0223696,0.0102503,0.0232192,0.0330876,0.0219245,0.00777749,0.0104415,0.031364,0.0171242,0.0144556,0.0179099,0.0303036,0.00774722,0.00879779,0.0130514,0.0109948,0.0120155,0.0120745,0.0125898,0.0265668,0.0473945,0.0604113,0.0456709,0.0152709", "perf/train_forward": "0.390362,0.639861,0.609626,0.640118,0.63993,0.386137,0.496858,0.443008,0.442866,0.443211,0.443271,0.443351,0.436975,0.482338,0.376651,0.376631,0.376232,0.286914,0.349735,0.376386,0.313912,0.4702,0.503451,0.50314,0.419402,0.286261,0.537885,0.380282,0.652368,0.251425,0.707507,0.544384,0.544257,0.346164,0.371337,0.357778,0.468064,0.491467,0.52478,0.30644,0.259859,0.395064,0.378241,0.1581,0.380272,0.335851,0.335898,0.335927,0.287916,0.0959846,0.44238,0.44804,0.448145,0.448156,0.422355,0.33764,0.321804,0.179408,0.179468,0.179427,0.179347,0.340462,0.182312,0.28275,0.436556,0.486246,0.315722,1.19163,1.19158,0.379118,0.463622,0.188762,0.192486,0.38789,0.395642,0.182013,0.570533,0.262713,0.330018,0.30697,2.21622,2.21528,0.417987,0.417969,0.385218,0.368233,0.117865,0.568893,0.534535,0.331948,0.291363,0.286811,0.353949,0.396645,0.360456,0.406951,0.784132,0.78524,0.232526,0.634654,0.477297,0.677245,0.59687,0.610817,0.314327,0.352019,0.228181,0.254258,0.51234,0.512376,0.512482,0.51235,0.512617,0.521544,0.512757,0.341353,0.268083,0.457128,0.282919,0.249528,0.249541,0.239646,0.242875,0.249567,0.249665,0.249583,0.213432,0.105062,0.700146,0.634607,0.722069,0.494612,0.548753,0.543527,0.394937,0.581966,0.598654,0.598791,0.583821,0.582673,0.460656,0.460468,0.132388,0.215625,0.379539,0.454082,0.418453,0.184359,0.472597,0.459303,0.459644,0.457867,0.707077,0.566128,0.377192,0.188722,0.396019,0.543792,0.17994,0.383932,0.342646,0.361476,0.341041,0.0723154,0.359679,0.359877,0.308311,0.514861,0.297365,0.260712,0.14163,0.574284,0.243454,0.242447,0.493822,0.432722,0.433084,0.300804,0.305475,0.30075,0.274124,0.25849,0.702877,0.702912,0.683282,0.69374,0.673634,0.351339,0.108254,0.498822,0.619549,0.615411,0.407669,0.366077,0.124057,0.500494,0.48814,0.387882,0.352185,0.352641,0.197758,0.830445,0.342525,0.257085,0.482364,0.364074,0.578045,0.372597,0.403278,0.340137,0.318239,0.619287,0.40841,0.615285,0.4772,0.0657129,0.457507,0.282348,0.423387,0.363377,0.644844,0.337298,0.296699,0.40237,0.568273,0.470616,0.498825,0.333995,0.185323,0.351781,0.292042,0.464083,0.362922,0.591138", "perf/train": "0.417084,0.668852,0.637208,0.669007,0.66891,0.417967,0.519928,0.463345,0.463158,0.463484,0.463608,0.463655,0.456972,0.518536,0.403928,0.403862,0.403457,0.307829,0.37516,0.403711,0.336867,0.476539,0.511811,0.511583,0.42817,0.292268,0.546561,0.400734,0.655588,0.258423,0.732145,0.562734,0.562651,0.392681,0.422016,0.374186,0.499165,0.516507,0.551381,0.320473,0.271548,0.407224,0.389896,0.163057,0.39206,0.345942,0.345974,0.346003,0.296526,0.0988457,0.45229,0.457993,0.458221,0.458152,0.431707,0.359955,0.342579,0.208752,0.208808,0.208758,0.208638,0.376826,0.223274,0.313269,0.474511,0.517639,0.399454,1.19723,1.19716,0.389932,0.487139,0.213926,0.203049,0.422822,0.431162,0.206378,0.595264,0.272773,0.372232,0.345474,2.23119,2.23016,0.43728,0.437196,0.402869,0.403925,0.12133,0.582771,0.546559,0.351166,0.30795,0.303078,0.376968,0.426405,0.378106,0.423743,0.800713,0.801906,0.268307,0.637757,0.488858,0.680256,0.599561,0.613507,0.325262,0.369251,0.254086,0.271459,0.525231,0.525291,0.525408,0.525301,0.525564,0.533828,0.52566,0.357394,0.280368,0.471356,0.301933,0.266,0.266045,0.255522,0.258975,0.265973,0.265987,0.265942,0.227425,0.111928,0.70852,0.642103,0.73325,0.532737,0.562788,0.556705,0.417627,0.601386,0.618697,0.618859,0.603358,0.602168,0.4763,0.47611,0.136885,0.242915,0.396853,0.474947,0.437501,0.195828,0.493659,0.480724,0.481157,0.478202,0.723807,0.579208,0.412545,0.217929,0.410958,0.567507,0.25279,0.411222,0.366498,0.374181,0.352925,0.0900936,0.374718,0.374913,0.321224,0.536213,0.335464,0.293492,0.152428,0.582172,0.256118,0.255061,0.51699,0.45256,0.445499,0.318519,0.323444,0.318373,0.290214,0.273595,0.714651,0.714704,0.694705,0.705286,0.684892,0.357286,0.126394,0.53185,0.634815,0.631556,0.419149,0.376317,0.127477,0.516048,0.525471,0.417118,0.369155,0.369596,0.20494,0.847563,0.388576,0.264283,0.513624,0.385937,0.599283,0.388646,0.42036,0.368842,0.340609,0.629537,0.43163,0.648372,0.499125,0.0734904,0.467948,0.313712,0.440511,0.377832,0.662754,0.367601,0.304446,0.411167,0.581324,0.481611,0.510841,0.346069,0.197912,0.378348,0.339437,0.524494,0.408593,0.606409", "util/gpu_percent": "75.7143,89.4,87.2857,87.4,100,54.6667,91,88.5556,90,90,87.4444,81.125,86.3333,71.6,76.6,78.2,77,82.3333,76.6667,77,83.1667,100,88.4737,77,95.4286,98,99,82.75,99.8816,63.25,94.6667,87.6364,78.2727,50.3333,68,85.375,76.4,81.8,82.1667,75.3333,61.2857,90.0714,91.5,94,77.4,81.8,82.2,82.6,83,83,94.0769,96.6154,96.6923,96.6923,96.4615,67.75,75.8,46.3333,47.3333,47.3333,47.6667,75.875,33.5,61.5,76,100,19.6667,100,100,90,81.8,47.3333,91,77.3333,77.8,46.6667,85.8333,72.4,61.8,66,100,100,88.1667,88,89.2857,77,85,93.8235,95.8824,79.6,79.8,82,71,81.6,79.6667,85.3333,97.8636,97.5,54.3333,98.7391,86.2857,99.6733,99.3168,99.495,90.8,67.75,60,51.75,92.3077,91.3846,95,92.4615,91.2308,95.6923,91,77,69.5,74.6667,66,67,66.3333,66.75,64.5,68,66.5,65.6667,65.25,69,97.6897,98.7778,100,81,95.5333,95.6875,87.1,85.75,90.6923,94.5385,91.3077,90.5,92.4545,92.6364,97,56.4,68.7692,89.4118,88.4375,46,88.125,74.7,81.2222,89.5,82.6667,91.2222,56.5,46,93.7273,87.8333,37,80,77,85.5714,86.1667,28,80.4,80.2,79.4,94.2,48,62.5,25.6667,95.1556,63.25,62.6667,89.8571,90.4286,91.625,77.2,80.4,79.8,68.3333,71.3333,94.4444,94.0526,94.6667,100,100,100,33.3333,79.2,97.2,98.2903,90.2857,90.2857,91,94.6957,81.5,81.5,81.125,84.3333,80,99.9333,74.25,76.4,63.8333,79,85.3333,77.4545,85.8,71,67.4167,96.8571,83.5714,100,78.6,43,80.1579,80.7143,87,85,92.6667,68,65.25,70,93.1034,96,100,81.5714,70,76.6,63.4,72.8,74.6,94.125", "util/gpu_mem": "5.32105,6.60748,6.73776,6.73776,6.73776,6.11082,5.777,5.777,5.777,5.777,5.777,5.777,5.777,20.6601,20.6601,20.6601,20.6601,19.8676,19.8676,20.6601,20.6601,23.2248,8.481,8.529,7.74736,7.74736,7.20185,5.40247,10.5808,7.03901,6.64005,6.64005,6.64005,5.72815,5.10122,5.70372,6.09454,6.0294,6.0294,5.64673,5.64673,6.83546,6.83546,6.83546,6.60748,6.60748,6.60748,6.60748,6.60748,6.60748,6.30623,6.30623,6.30623,6.30623,6.30623,21.1323,21.1323,5.28848,5.28848,5.28848,5.28848,5.47575,17.2404,5.20706,5.76886,6.21667,5.69558,11.509,11.509,6.68076,6.0294,5.45132,5.89099,5.50017,5.50017,5.45132,6.09454,5.94798,5.12564,5.12564,10.7518,10.7518,5.70372,5.70372,5.70372,5.15821,19.7917,20.9297,21.2605,20.6194,20.6194,20.6194,5.82585,5.67115,5.78514,5.50017,7.86135,7.86135,5.53274,8.73255,7.24256,24.3574,24.53,24.4045,6.04569,6.07825,5.10936,18.7821,21.8651,21.8651,21.8651,21.8651,21.8651,21.1336,20.2802,20.253,20.253,9.07451,5.5246,5.5246,5.5246,5.5246,5.5246,5.5246,5.5246,5.5246,5.5246,5.5246,22.5795,22.8974,8.7244,5.67115,21.3928,20.8976,19.6944,6.64005,6.64005,6.75028,6.77032,6.77032,6.02126,6.02126,6.64005,5.12564,6.28995,5.70372,5.70372,5.54903,21.2626,20.6286,20.9104,21.2626,7.24256,7.24256,5.50017,5.53274,5.79328,6.09454,17.7887,5.48027,5.58159,5.94798,5.94798,4.95466,6.22481,6.22481,6.22481,18.9356,5.12564,5.12564,5.19078,7.49351,5.75257,5.75257,5.70372,5.70372,6.55049,5.61416,5.61416,5.61416,5.61416,5.63587,7.20185,7.20185,7.20185,7.20185,7.20185,7.20185,19.4958,15.4118,6.42836,7.45425,6.55049,6.55049,6.55049,19.8945,5.32105,5.32105,6.34694,6.34694,6.30623,22.6878,15.4357,6.77032,6.21667,6.0864,6.62377,5.54088,5.54088,20.1553,5.45132,9.53046,20.6194,6.48535,6.28995,20.2692,6.30623,18.0624,5.83399,5.83399,6.91688,6.07011,6.54235,7.92649,7.16114,7.16114,7.54381,6.23295,5.46528,5.40247,19.2515,5.3699,5.3699,6.35508", "util/vram_used_gb": "0.815308,1.1239,1.15515,1.15515,1.15515,1.00476,0.924683,0.924683,0.924683,0.924683,0.924683,0.924683,0.924683,4.49487,4.49487,4.49487,4.49487,4.30478,4.30478,4.49487,4.49487,5.11011,1.57333,1.58484,1.39734,1.39734,1.26648,0.834839,2.07703,1.22742,1.13171,1.13171,1.13171,0.912964,0.762573,0.907104,1.00085,0.985229,0.985229,0.893433,0.893433,1.17859,1.17859,1.17859,1.1239,1.1239,1.1239,1.1239,1.1239,1.1239,1.05164,1.05164,1.05164,1.05164,1.05164,4.60815,4.60815,0.807495,0.807495,0.807495,0.807495,0.852417,3.67456,0.787964,0.922729,1.03015,0.905151,2.29968,2.29968,1.14148,0.985229,0.846558,0.952026,0.858276,0.858276,0.846558,1.00085,0.965698,0.768433,0.768433,2.11804,2.11804,0.907104,0.907104,0.907104,0.776245,4.28656,4.55956,4.63891,4.48511,4.48511,4.48511,0.936401,0.899292,0.926636,0.858276,1.42468,1.42468,0.866089,1.63367,1.27625,5.3818,5.42321,5.3931,0.989136,0.996948,0.764526,4.04437,4.78394,4.78394,4.78394,4.78394,4.78394,4.60846,4.40375,4.39722,4.39722,1.7157,0.864136,0.864136,0.864136,0.864136,0.864136,0.864136,0.864136,0.864136,0.864136,0.864136,4.95532,5.03157,1.63171,0.899292,4.67065,4.55185,4.26323,1.13171,1.13171,1.15816,1.16296,1.16296,0.983276,0.983276,1.13171,0.768433,1.04773,0.907104,0.907104,0.869995,4.6394,4.48733,4.55492,4.6394,1.27625,1.27625,0.858276,0.866089,0.928589,1.00085,3.80609,0.853502,0.877808,0.965698,0.965698,0.727417,1.0321,1.0321,1.0321,4.08121,0.768433,0.768433,0.784058,1.33644,0.918823,0.918823,0.907104,0.907104,1.11023,0.88562,0.88562,0.88562,0.88562,0.890828,1.26648,1.26648,1.26648,1.26648,1.26648,1.26648,4.21558,3.23591,1.08093,1.32703,1.11023,1.11023,1.11023,4.31123,0.815308,0.815308,1.0614,1.0614,1.05164,4.98129,3.24164,1.16296,1.03015,0.998901,1.12781,0.868042,0.868042,4.37378,0.846558,1.82507,4.48511,1.0946,1.04773,4.40112,1.05164,3.87175,0.938354,0.938354,1.19812,0.994995,1.10828,1.44031,1.25671,1.25671,1.34851,1.03406,0.849906,0.834839,4.15698,0.827026,0.827026,1.06335", "util/vram_total_gb": "23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272", "util/cpu_mem_gb": "1.12024,1.23692,1.23692,1.23692,1.23692,1.11197,1.11364,1.11364,1.11364,1.11364,1.11364,1.11364,1.11364,1.05776,1.05776,1.05776,1.05776,1.05776,1.05776,1.05776,1.05776,1.14934,1.2122,1.2122,1.23597,1.23597,1.15221,1.09122,1.3036,1.13838,1.21789,1.21789,1.21789,1.12058,1.09145,1.14866,1.10923,1.1481,1.14513,1.10316,1.10316,1.23443,1.23443,1.23443,1.11664,1.11664,1.11664,1.11664,1.11664,1.11664,1.13471,1.13471,1.13471,1.13471,1.13471,1.02944,1.02944,1.0995,1.0995,1.0995,1.0995,1.12012,1.00015,1.09707,1.10346,1.19925,1.12159,1.25674,1.25674,1.14785,1.1469,1.0972,1.13953,1.12878,1.12878,1.10094,1.19281,1.10776,1.09582,1.09582,1.23595,1.23595,1.14708,1.14708,1.14708,1.10685,1.08633,1.08754,1.08754,1.05906,1.05906,1.05906,1.14006,1.12912,1.13791,1.11866,1.22015,1.22015,1.11795,1.10968,1.12902,1.07475,1.07475,1.07475,1.19404,1.16494,1.08788,1.02658,1.05688,1.05688,1.05688,1.05688,1.05688,1.05688,1.05688,1.05743,1.05743,1.09876,1.10846,1.10846,1.10846,1.10846,1.10846,1.10846,1.10846,1.10846,1.10846,1.10846,1.08973,1.08973,1.2559,1.12938,1.05326,1.05326,1.04786,1.21714,1.21714,1.21714,1.21714,1.21714,1.14775,1.14775,1.21773,1.09703,1.13958,1.1434,1.1434,1.0924,1.0673,1.0673,1.0673,1.0673,1.12804,1.12804,1.12807,1.11943,1.14148,1.19039,1.00643,1.12746,1.12746,1.10622,1.10622,1.0803,1.15802,1.15802,1.15802,1.0568,1.09616,1.09616,1.08213,1.15985,1.08957,1.08957,1.14618,1.14618,1.14978,1.12864,1.12864,1.12864,1.12864,1.12864,1.11611,1.11611,1.11611,1.11611,1.11611,1.11611,1.04088,1.2372,1.16438,1.20237,1.14762,1.14762,1.14762,1.05997,1.10635,1.10635,1.19928,1.19928,1.11308,1.14303,1.04318,1.10765,1.19861,1.12984,1.15081,1.10675,1.10675,1.10115,1.12856,1.43619,1.05864,1.20084,1.14173,1.02525,1.13225,1.01743,1.15673,1.15673,1.19693,1.1301,1.11779,1.11699,1.25203,1.25203,1.27235,1.14034,1.13676,1.10195,1.01804,1.11936,1.11936,1.13154", "wandb": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "slowly": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "save_frames": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "fps": "15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15", "rank": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "world_size": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "gpu_id": "5,3,3,3,3,4,4,4,4,4,4,4,4,0,0,0,0,0,0,0,0,0,4,4,3,3,3,4,5,3,1,1,1,1,1,2,1,3,2,4,4,5,5,5,3,3,3,3,3,3,2,2,2,2,2,0,0,1,1,1,1,2,0,4,3,2,4,3,3,1,3,5,3,3,3,1,5,2,1,1,1,1,1,1,1,3,0,0,0,0,0,0,1,3,2,2,5,5,3,1,1,0,0,0,4,2,1,0,0,0,0,0,0,0,0,0,0,3,1,1,1,1,1,1,1,1,1,1,0,0,3,2,0,0,0,2,2,2,2,2,1,1,2,4,4,2,2,1,0,0,0,0,3,3,2,3,2,4,0,2,2,2,2,4,4,4,4,0,4,4,4,3,3,3,1,1,4,2,2,2,2,2,3,3,3,3,3,3,0,0,4,1,5,5,5,0,1,1,2,2,5,0,0,4,4,2,3,4,4,0,1,4,0,4,3,0,5,0,1,1,3,2,1,1,2,2,3,3,3,3,0,5,5,4", "profile": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "checkpoint_interval": "200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200", "eval_episodes": "10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000", "cudagraphs": "10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10", "seed": "73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73", "reset_state": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "vec/total_agents": "2048,2048,2048,2048,2048,4096,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,1024,1024,1024,512,512,1024,1024,512,1024,1024,1024,1024,4096,4096,1024,4096,2048,2048,1024,1024,1024,1024,1024,2048,2048,2048,2048,2048,2048,512,512,512,512,512,4096,4096,4096,4096,4096,4096,2048,4096,2048,4096,2048,8192,1024,1024,1024,2048,4096,2048,2048,2048,4096,2048,1024,2048,2048,2048,2048,1024,1024,1024,2048,1024,1024,1024,1024,1024,1024,2048,2048,1024,1024,2048,2048,4096,1024,2048,1024,1024,1024,1024,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,8192,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,1024,1024,2048,2048,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,2048,2048,1024,1024,2048,2048,2048,2048,2048,2048,2048,2048,4096,512,2048,8192,1024,1024,1024,1024,4096,2048,2048,2048,1024,2048,2048,4096,1024,2048,2048,1024,1024,1024,1024,1024,1024,1024,1024,2048,2048,2048,2048,2048,2048,4096,1024,1024,2048,1024,1024,1024,1024,2048,2048,1024,1024,2048,2048,2048,1024,2048,2048,2048,1024,1024,2048,1024,512,1024,2048,2048,2048,512,2048,1024,1024,1024,4096,1024,2048,1024,1024,2048,1024,512,2048,4096,2048,2048,1024", "vec/num_buffers": "8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,7.98775,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8", "vec/num_threads": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "env/task": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "env/num_drones": "64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64", "env/max_rings": "10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10", "env/alpha_dist": "0.1,0.1,0.1,0.1,0.1,0.490501,0.130371,0.130371,0.130371,0.130371,0.130371,0.130371,0.130371,0.205127,0.205127,0.205127,0.205127,0.205127,0.205127,0.205127,0.205127,0.187421,0.220668,0.220668,0.424835,0.424835,0.1,0.411787,0.1,1.2218,0.200532,0.200532,0.200532,0.801138,0.828701,0.1,0.1,0.1,0.1,0.350573,0.350573,0.124855,0.124855,0.124855,0.357541,0.357541,0.357541,0.357541,0.357541,0.357541,0.126233,0.126233,0.126233,0.126233,0.126233,0.174792,0.174792,0.758502,0.758502,0.758502,0.758502,0.136032,0.102099,0.182973,0.106187,0.32915,1.06927,0.1,0.1,0.485232,0.154016,0.657279,1.41875,0.14151,0.14151,0.439524,0.397114,0.1,0.962173,0.962173,0.217143,0.217143,0.144497,0.144497,0.144497,0.180825,0.803198,1.29219,1.29219,0.189121,0.189121,0.189121,0.671599,0.966303,0.14183,0.315962,0.1,0.1,0.295726,0.182794,1.27675,0.307698,0.307698,0.307698,0.235136,0.328776,0.269564,0.339703,0.313887,0.313887,0.313887,0.313887,0.313887,0.313887,0.313887,0.246492,0.246492,0.452999,0.782192,0.782192,0.782192,0.782192,0.782192,0.782192,0.782192,0.782192,0.782192,0.782192,0.582114,0.582114,0.763319,0.132207,0.1,0.1,0.75036,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.583364,0.250225,0.868751,0.572394,0.572394,0.109277,0.191225,0.191225,0.191225,0.191225,0.1,0.1,0.941933,0.984343,0.1,0.378868,0.140706,0.295359,0.295359,0.583595,0.583595,0.230959,0.1,0.1,0.1,0.143231,0.1,0.1,0.125328,0.699359,0.520203,0.520203,0.127039,0.127039,0.942329,0.87196,0.87196,0.87196,0.87196,0.87196,0.484025,0.484025,0.484025,0.484025,0.484025,0.484025,0.246419,0.849336,0.1,0.228531,0.550702,0.550702,0.550702,0.542956,0.1,0.1,0.19172,0.19172,0.539766,0.293343,0.741969,0.346362,0.263806,0.369857,0.238387,0.275108,0.275108,2.98144,0.405207,0.156752,0.375907,0.4774,0.114273,0.420117,0.325375,0.296834,0.525296,0.525296,0.726028,0.369514,0.16915,0.117258,0.409355,0.409355,0.276241,0.74962,0.366858,0.1,0.176638,0.247395,0.247395,0.473525", "env/alpha_hover": "0.241681,0.0211257,0.0211257,0.0211257,0.0211257,0.0356321,0.0225677,0.0225677,0.0225677,0.0225677,0.0225677,0.0225677,0.0225677,0.0859656,0.0859656,0.0859656,0.0859656,0.0859656,0.0859656,0.0859656,0.0859656,0.055381,0.0310608,0.0310608,0.0680222,0.0680222,0.158088,0.035824,0.0305227,0.0405351,0.0190187,0.0190187,0.0190187,0.217807,0.0173501,0.0452484,0.00569742,0.0460159,0.121636,0.0364828,0.0364828,0.0213115,0.0213115,0.0213115,0.0624032,0.0624032,0.0624032,0.0624032,0.0624032,0.0624032,0.0304152,0.0304152,0.0304152,0.0304152,0.0304152,0.0789947,0.0789947,0.0730751,0.0730751,0.0730751,0.0730751,0.0589436,0.0113324,0.0180897,0.0197006,0.0236079,0.0242388,0.0986714,0.0986714,0.079214,0.0802032,0.0411623,0.0405286,0.0495819,0.0495819,0.0136238,0.0889003,0.0840372,0.026533,0.026533,0.0972154,0.0972154,0.0812899,0.0812899,0.0812899,0.0916015,0.0717363,0.0321259,0.0321259,0.0461387,0.0461387,0.0461387,0.0565821,0.0220669,0.0390542,0.0673145,0.0156173,0.0156173,0.0751254,0.0499344,0.0492134,0.0497094,0.0497094,0.0497094,0.0424138,0.0346943,0.0774527,0.0440104,0.0261026,0.0261026,0.0261026,0.0261026,0.0261026,0.0261026,0.0261026,0.0127045,0.0127045,0.0547803,0.071445,0.071445,0.071445,0.071445,0.071445,0.071445,0.071445,0.071445,0.071445,0.071445,0.0477036,0.0477036,0.0335019,0.370765,0.0374611,0.0374611,0.0218298,0.0390387,0.0390387,0.0390387,0.0390387,0.0390387,0.071475,0.071475,0.0251325,0.0269153,0.0569853,0.0471948,0.0471948,0.222425,0.0386943,0.0386943,0.0386943,0.0386943,0.109706,0.109706,0.0319433,0.0093345,0.0374585,0.125859,0.0946901,0.0101924,0.0101924,0.0471314,0.0471314,0.00541677,0.0702245,0.0702245,0.0702245,0.0945859,0.258963,0.258963,0.00383328,0.0264718,0.0225268,0.0225268,0.0776437,0.0776437,0.0168303,0.0176213,0.0176213,0.0176213,0.0176213,0.0176213,0.0295811,0.0295811,0.0295811,0.0295811,0.0295811,0.0295811,0.140964,0.0375276,0.0241946,0.022041,0.0698117,0.0698117,0.0698117,0.0590442,0.0403076,0.0403076,0.0473577,0.0473577,0.0414732,0.0594053,0.0176461,0.245494,0.0188698,0.05136,0.0371454,0.0291135,0.0291135,0.00513893,0.05165,0.0534173,0.0366372,0.0270524,0.014828,0.216304,0.0348136,0.0675818,0.0213778,0.0213778,0.0325477,0.0253771,0.142018,0.0680777,0.0491941,0.0491941,0.0352386,0.0749472,0.103918,0.0349557,0.00532269,0.0525497,0.0525497,0.0505252", "env/alpha_omega": "0.000172151,0.000790323,0.000790323,0.000790323,0.000790323,0.00100536,0.00123536,0.00123536,0.00123536,0.00123536,0.00123536,0.00123536,0.00123536,0.000546574,0.000546574,0.000546574,0.000546574,0.000546574,0.000546574,0.000546574,0.000546574,0.00389946,0.00158073,0.00158073,0.00042106,0.00042106,0.00166406,0.000110179,0.000400676,0.00030214,0.000879642,0.000879642,0.000879642,0.000635187,0.000697593,0.000704765,0.000654649,0.000932328,0.0001,0.000724167,0.000724167,0.00191501,0.00191501,0.00191501,0.000430263,0.000430263,0.000430263,0.000430263,0.000430263,0.000430263,0.00169028,0.00169028,0.00169028,0.00169028,0.00169028,0.00115732,0.00115732,0.0017485,0.0017485,0.0017485,0.0017485,0.00219217,0.00262813,0.0019863,0.00052842,0.0014993,0.00137689,0.000421701,0.000421701,0.000595325,0.00150653,0.00353663,0.00179095,0.000274044,0.000274044,0.000858678,0.00189458,0.000807825,0.000522709,0.000522709,0.00139064,0.00139064,0.000400625,0.000400625,0.000400625,0.000829623,0.000759819,0.00234164,0.00234164,0.000283678,0.000283678,0.000283678,0.0010716,0.000180052,0.0001,0.00314284,0.00306409,0.00306409,0.000580128,0.00139183,0.00197708,0.0022073,0.0022073,0.0022073,0.000215173,0.0001,0.000610334,0.000482217,0.00243863,0.00243863,0.00243863,0.00243863,0.00243863,0.00243863,0.00243863,0.000289615,0.000289615,0.0001,0.00135588,0.00135588,0.00135588,0.00135588,0.00135588,0.00135588,0.00135588,0.00135588,0.00135588,0.00135588,0.00273049,0.00273049,0.000917599,0.000345813,0.00358244,0.00358244,0.000295589,0.000103104,0.000103104,0.000103104,0.000103104,0.000103104,0.000226313,0.000226313,0.000965886,0.000290497,0.00149479,0.00488053,0.00488053,0.0001,0.000567558,0.000567558,0.000567558,0.000567558,0.000838765,0.000838765,0.0001,0.00103135,0.000401063,0.000757933,0.0333331,0.000458186,0.000458186,0.00151028,0.00151028,0.00219633,0.000328246,0.000328246,0.000328246,0.000141659,0.00110111,0.00110111,0.0011334,0.00170796,0.0013392,0.0013392,0.000349323,0.000349323,0.0012549,0.000255177,0.000255177,0.000255177,0.000255177,0.000255177,0.00246641,0.00246641,0.00246641,0.00246641,0.00246641,0.00246641,0.000488262,0.000657348,0.000879679,0.0001,0.0023095,0.0023095,0.0023095,0.0013486,0.00026091,0.00026091,0.00141724,0.00141724,0.000638639,0.00193114,0.00011178,0.0120228,0.00275362,0.00081683,0.000494964,0.000781125,0.000781125,0.000495772,0.000695192,0.000885321,0.00106934,0.000185551,0.00356123,0.000502947,0.00456828,0.000230458,0.002565,0.002565,0.000720085,0.000433168,0.00133062,0.00107838,0.00373678,0.00373678,0.000880778,0.00578865,0.0001,0.00177767,0.00187754,0.000341679,0.000341679,0.000394978", "env/alpha_shaping": "10,10,10,10,10,10,7.2881,7.2881,7.2881,7.2881,7.2881,7.2881,7.2881,10,10,10,10,10,10,10,10,9.37974,5.78018,5.78018,5.00387,5.00387,10,3.85965,9.31848,10,1.39092,1.39092,1.39092,2.56282,4.21986,2.61192,10,10,2.86084,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,4.01526,4.01526,4.01526,4.01526,2.45163,10,5.99503,4.21204,10,1.71033,5.63956,5.63956,5.35666,2.1586,2.92023,10,5.83727,5.83727,4.16437,2.88894,2.00001,3.40148,3.40148,10,10,8.76221,8.76221,8.76221,4.83463,10,6.27995,6.27995,4.93015,4.93015,4.93015,10,3.26361,3.40071,10,10,10,3.29612,4.32218,10,7.93784,7.93784,7.93784,2.67472,10,6.02823,9.23789,6.35588,6.35588,6.35588,6.35588,6.35588,6.35588,6.35588,1.6757,1.6757,3.75699,3.9754,3.9754,3.9754,3.9754,3.9754,3.9754,3.9754,3.9754,3.9754,3.9754,10,10,10,10,4.87706,4.87706,9.85987,10,10,10,10,10,2.06146,2.06146,10,6.78446,10,10,10,5.46108,3.37931,3.37931,3.37931,3.37931,4.10749,4.10749,10,3.98676,10,10,5.34735,2.00781,2.00781,10,10,10,2.28404,2.28404,2.28404,10,6.70172,6.70172,10,4.44342,2.57476,2.57476,10,10,3.75941,10,10,10,10,10,10,10,10,10,10,10,2.0864,5.55384,10,10,10,10,10,10,10,10,1.77951,1.77951,10,10,10,10,5.54609,10,4.20698,2.81663,2.81663,1.24825,10,10,10,7.60915,10,5.42565,2.01532,7.94343,10,10,2.87295,8.45848,5.40577,3.7452,10,10,10,10,7.56995,8.47124,1.31846,10,10,4.75031", "env/hover_target_dist": "5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5", "env/hover_dist": "0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1", "env/hover_omega": "0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1", "env/hover_vel": "0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1", "policy/hidden_size": "64,128,128,128,128,512,256,256,256,256,256,256,256,128,128,128,128,128,128,128,128,512,512,512,256,256,512,512,1024,256,256,256,256,256,64,128,256,128,128,256,256,128,128,128,256,256,256,256,256,256,512,512,512,512,512,256,256,256,256,256,256,256,128,128,256,128,128,1024,1024,256,128,256,256,128,128,256,64,256,128,128,1024,1024,128,128,128,64,128,256,256,128,128,128,128,256,128,128,512,512,128,1024,512,1024,1024,1024,64,64,256,128,512,512,512,512,512,512,512,256,256,512,128,128,128,128,128,128,128,128,128,128,512,512,512,256,512,512,256,256,256,256,256,256,256,256,256,128,256,128,128,256,256,256,256,256,512,512,128,128,256,64,256,128,128,256,256,64,128,128,128,256,128,128,64,512,512,512,128,128,256,256,256,256,256,256,512,512,512,512,512,512,128,64,256,512,256,256,256,512,128,128,128,128,256,512,64,256,128,256,256,256,256,128,128,256,128,256,256,128,512,256,128,128,512,256,256,256,256,256,256,256,32,256,256,128,128,512", "policy/num_layers": "4.11436,5.64281,5.64281,5.64281,5.64281,1,4.30071,4.30071,4.30071,4.30071,4.30071,4.30071,4.30071,3.52285,3.52285,3.52285,3.52285,3.52285,3.52285,3.52285,3.52285,5.03368,4.00404,4.00404,5.40688,5.40688,5.52213,1.38654,6.25005,3.99468,4.37403,4.37403,4.37403,1,3.00331,4.18387,3.28822,4.7909,4.07351,2.7506,2.7506,5.53953,5.53953,5.53953,5.63088,5.63088,5.63088,5.63088,5.63088,5.63088,3.52491,3.52491,3.52491,3.52491,3.52491,3.17844,3.17844,1,1,1,1,1.36985,1.22784,1.38622,2.04705,3.57617,1.13586,7.18361,7.18361,4.889,4.76185,1,3.41408,2.37686,2.37686,1,6.58785,3.78021,1.38589,1.38589,6.46584,6.46584,4.70642,4.70642,4.70642,2.66093,6.42032,6.5227,6.5227,3.99629,3.99629,3.99629,3.32429,2.80255,3.5929,5.74661,5.55184,5.55184,1,5.96793,3.71716,6.11454,6.11454,6.11454,6.21,4.61039,1.72967,3.61501,4.87428,4.87428,4.87428,4.87428,4.87428,4.87428,4.87428,3.96835,3.96835,3.1805,3.80354,3.80354,3.80354,3.80354,3.80354,3.80354,3.80354,3.80354,3.80354,3.80354,7.26392,7.26392,7.13963,2.01806,3.85235,3.85235,2.56839,4.61566,4.61566,4.61566,4.61566,4.61566,4.33946,4.33946,4.05346,1,3.53808,4.07508,4.07508,1.65508,4.79727,4.79727,4.79727,4.79727,3.47703,3.47703,2.56442,1.37813,3.8973,6.20784,1,2.08876,2.08876,3.53098,3.53098,1.17666,5.43569,5.43569,5.43569,3.95799,1.18794,1.18794,2.06699,6.89441,1,1,4.97229,4.97229,4.77098,2.00691,2.00691,2.00691,2.00691,2.00691,6.54892,6.54892,6.54892,6.54892,6.54892,6.54892,1,2.56968,6.19475,4.93566,4.25865,4.25865,4.25865,4.90134,3.15926,3.15926,3.94904,3.94904,4.73682,5.86952,1.86013,3.22731,3.53603,2.61333,4.55891,3.81197,3.81197,2.89889,2.91906,6.56986,3.77287,3.30532,3.72363,2.99142,3.41596,1,5.06395,5.06395,3.10401,2.0749,5.73114,5.30462,6.18052,6.18052,7.06837,3.87683,2.49206,2.15206,1,1.54132,1.54132,3.96014", "policy/expansion_factor": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "train/gpus": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "train/seed": "42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42", "train/total_timesteps": "40,41.4188,41.4188,41.4188,41.4188,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,81.8582,67.635,67.635,49.9709,49.9709,80.6323,93.3574,44.5825,40,40,40,40,40.8025,40,46.6916,40,40,40,47.3778,47.3778,81.7663,81.7663,81.7663,40,40,40,40,40,40,45.9193,45.9193,45.9193,45.9193,45.9193,40,40,47.5457,47.5457,47.5457,47.5457,53.0846,40,40,40,53.0343,40,52.7199,52.7199,40,40,60.0299,61.865,42.5874,42.5874,42.5213,40,40,40,40,85.146,85.146,40.425,40.425,40.425,63.0256,57.9063,46.237,46.237,40,40,40,40,40,59.6694,81.9765,52.1548,52.1548,46.1166,40,40,59.4555,59.4555,59.4555,42.3325,40,50.5773,40,45.8215,45.8215,45.8215,45.8215,45.8215,45.8215,45.8215,40,40,40,40,40,40,40,40,40,40,40,40,40,48.9873,48.9873,69.4146,52.2246,51.9305,51.9305,55.4722,44.63,44.63,44.63,44.63,44.63,45.9741,45.9741,54.5481,60.3336,104.332,95.6142,95.6142,43.0203,40,40,40,40,40,40,40,47.7296,91.5293,40,40,47.7107,47.7107,44.3821,44.3821,59.5485,40,40,40,40,40,40,41.5734,78.71,40,40,40,40,88.2838,40,40,40,40,40,42.8812,42.8812,42.8812,42.8812,42.8812,42.8812,40,40,41.9328,72.8732,41.5478,41.5478,41.5478,50.0194,40,40,72.6862,72.6862,50.0284,69.0505,40,40,85.0355,40,40,42.9317,42.9317,40,63.4395,51.7862,40,40,40,44.4414,44.6635,40,44.7043,44.7043,83.7899,40,56.71,40,84.3933,84.3933,53.6569,50.6489,40,40,44.8178,40,40,50.7218", "train/learning_rate": "0.00508679,0.0150032,0.0150032,0.0150032,0.0150032,0.00632526,0.0122753,0.0122753,0.0122753,0.0122753,0.0122753,0.0122753,0.0122753,0.00464528,0.00464528,0.00464528,0.00464528,0.00464528,0.00464528,0.00464528,0.00464528,0.00410113,0.00982879,0.00982879,0.00896602,0.00896602,0.00578662,0.00296757,0.00619657,0.0433526,0.00916091,0.00916091,0.00916091,0.00295262,0.0126009,0.00470812,0.00438503,0.00946917,0.00581777,0.022122,0.022122,0.00728435,0.00728435,0.00728435,0.0121244,0.0121244,0.0121244,0.0121244,0.0121244,0.0121244,0.00733511,0.00733511,0.00733511,0.00733511,0.00733511,0.00321909,0.00321909,0.0114855,0.0114855,0.0114855,0.0114855,0.0041517,0.00469228,0.0249919,0.00304535,0.00140136,0.0135752,0.00662379,0.00662379,0.00708449,0.0133679,0.010012,0.0130649,0.00802549,0.00802549,0.00720092,0.00875656,0.0140236,0.00982236,0.00982236,0.00384615,0.00384615,0.00828685,0.00828685,0.00828685,0.0025215,0.0131281,0.00885454,0.00885454,0.0109995,0.0109995,0.0109995,0.0310573,0.00272993,0.00662848,0.0135365,0.00149799,0.00149799,0.0201684,0.00397711,0.00771877,0.00539491,0.00539491,0.00539491,0.00720581,0.0051029,0.00758178,0.018683,0.00793159,0.00793159,0.00793159,0.00793159,0.00793159,0.00793159,0.00793159,0.0135497,0.0135497,0.00459484,0.00975033,0.00975033,0.00975033,0.00975033,0.00975033,0.00975033,0.00975033,0.00975033,0.00975033,0.00975033,0.00296574,0.00296574,0.00549649,0.0180927,0.00400409,0.00400409,0.00560263,0.0051202,0.0051202,0.0051202,0.0051202,0.0051202,0.00668641,0.00668641,0.00892932,0.00591071,0.00880608,0.00584214,0.00584214,0.00417111,0.00342433,0.00342433,0.00342433,0.00342433,0.004031,0.004031,0.0134119,0.0251701,0.0168294,0.00448123,0.00418043,0.0102857,0.0102857,0.0183663,0.0183663,0.0036831,0.0119687,0.0119687,0.0119687,0.0021174,0.00588222,0.00588222,0.0746326,0.00288644,0.0105451,0.0105451,0.0261207,0.0261207,0.00618644,0.00484414,0.00484414,0.00484414,0.00484414,0.00484414,0.00581364,0.00581364,0.00581364,0.00581364,0.00581364,0.00581364,0.00374319,0.00105347,0.00669926,0.00161812,0.0199935,0.0199935,0.0199935,0.00270664,0.00576605,0.00576605,0.0133474,0.0133474,0.00758541,0.00573472,0.0549048,0.00806271,0.00325237,0.00308697,0.0366799,0.00284258,0.00284258,0.0234992,0.00189519,0.00653208,0.017658,0.00364046,0.00606916,0.00578011,0.00867978,0.00686111,0.0118567,0.0118567,0.0149985,0.0135611,0.00931087,0.0220085,0.00566644,0.00566644,0.00628284,0.00676929,0.0223442,0.0260658,0.00319595,0.00491137,0.00491137,0.00864821", "train/anneal_lr": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "train/min_lr_ratio": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "train/gamma": "0.987788,0.990086,0.990086,0.990086,0.990086,0.987332,0.984305,0.984305,0.984305,0.984305,0.984305,0.984305,0.984305,0.980553,0.980553,0.980553,0.980553,0.980553,0.980553,0.980553,0.980553,0.982289,0.975977,0.975977,0.972346,0.972346,0.980472,0.991833,0.984371,0.981367,0.983686,0.983686,0.983686,0.991486,0.988987,0.981892,0.995063,0.972517,0.97678,0.987502,0.987502,0.983099,0.983099,0.983099,0.980356,0.980356,0.980356,0.980356,0.980356,0.980356,0.982457,0.982457,0.982457,0.982457,0.982457,0.98388,0.98388,0.982502,0.982502,0.982502,0.982502,0.992953,0.999782,0.994801,0.990459,0.985915,0.990898,0.985085,0.985085,0.973868,0.978051,0.990725,0.984092,0.990229,0.990229,0.980911,0.986544,0.973458,0.98518,0.98518,0.982957,0.982957,0.975324,0.975324,0.975324,0.990051,0.978881,0.975707,0.975707,0.981399,0.981399,0.981399,0.983035,0.992017,0.987652,0.987497,0.991083,0.991083,0.985025,0.98496,0.973333,0.985767,0.985767,0.985767,0.989527,0.987023,0.987633,0.990157,0.977823,0.977823,0.977823,0.977823,0.977823,0.977823,0.977823,0.994117,0.994117,0.993177,0.981094,0.981094,0.981094,0.981094,0.981094,0.981094,0.981094,0.981094,0.981094,0.981094,0.973382,0.973382,0.986836,0.989197,0.985452,0.985452,0.983463,0.984575,0.984575,0.984575,0.984575,0.984575,0.975568,0.975568,0.981699,0.991193,0.980849,0.983448,0.983448,0.98398,0.973097,0.973097,0.973097,0.973097,0.982824,0.982824,0.97956,0.986611,0.985487,0.993482,0.991503,0.98829,0.98829,0.992699,0.992699,0.998554,0.983509,0.983509,0.983509,0.987826,0.978374,0.978374,0.99787,0.983944,0.989869,0.989869,0.986898,0.986898,0.979723,0.989045,0.989045,0.989045,0.989045,0.989045,0.973992,0.973992,0.973992,0.973992,0.973992,0.973992,0.98342,0.974797,0.975193,0.982414,0.974183,0.974183,0.974183,0.981901,0.987116,0.987116,0.988798,0.988798,0.983153,0.983454,0.996884,0.979492,0.986236,0.97666,0.98776,0.980505,0.980505,0.983328,0.990232,0.987061,0.975823,0.986077,0.991234,0.980064,0.976306,0.987575,0.976369,0.976369,0.991474,0.990862,0.983508,0.990382,0.97797,0.97797,0.98644,0.974384,0.923852,0.942019,0.98938,0.990701,0.990701,0.982534", "train/gae_lambda": "0.932021,0.938987,0.938987,0.938987,0.938987,0.948523,0.920907,0.920907,0.920907,0.920907,0.920907,0.920907,0.920907,0.92196,0.92196,0.92196,0.92196,0.92196,0.92196,0.92196,0.92196,0.957872,0.896362,0.896362,0.900911,0.900911,0.862703,0.948703,0.853349,0.904821,0.92859,0.92859,0.92859,0.940531,0.672794,0.916276,0.969743,0.901949,0.945052,0.905764,0.905764,0.957224,0.957224,0.957224,0.788212,0.788212,0.788212,0.788212,0.788212,0.788212,0.920037,0.920037,0.920037,0.920037,0.920037,0.943655,0.943655,0.964604,0.964604,0.964604,0.964604,0.928479,0.935231,0.941111,0.931619,0.893459,0.936575,0.839066,0.839066,0.875412,0.873856,0.965352,0.894647,0.790057,0.790057,0.950818,0.975152,0.914911,0.979249,0.979249,0.798111,0.798111,0.836037,0.836037,0.836037,0.869933,0.791166,0.942677,0.942677,0.871031,0.871031,0.871031,0.892825,0.846958,0.919546,0.909334,0.929709,0.929709,0.83658,0.954676,0.952493,0.907012,0.907012,0.907012,0.941935,0.920612,0.959745,0.821231,0.919942,0.919942,0.919942,0.919942,0.919942,0.919942,0.919942,0.9063,0.9063,0.919295,0.883828,0.883828,0.883828,0.883828,0.883828,0.883828,0.883828,0.883828,0.883828,0.883828,0.934023,0.934023,0.819231,0.871452,0.945542,0.945542,0.877031,0.957576,0.957576,0.957576,0.957576,0.957576,0.824024,0.824024,0.874411,0.936278,0.867797,0.889838,0.889838,0.861949,0.890591,0.890591,0.890591,0.890591,0.940528,0.940528,0.886404,0.886972,0.935363,0.860654,0.952384,0.909416,0.909416,0.876075,0.876075,0.900218,0.907464,0.907464,0.907464,0.959412,0.923783,0.923783,0.908606,0.861189,0.937551,0.937551,0.877332,0.877332,0.933799,0.837789,0.837789,0.837789,0.837789,0.837789,0.895166,0.895166,0.895166,0.895166,0.895166,0.895166,0.940033,0.854222,0.957993,0.919474,0.916854,0.916854,0.916854,0.851217,0.92661,0.92661,0.911138,0.911138,0.921256,0.911199,0.929634,0.88632,0.952068,0.864593,0.938943,0.927442,0.927442,0.94407,0.887832,0.928786,0.956814,0.948626,0.94064,0.938174,0.953381,0.940044,0.969892,0.969892,0.923785,0.891224,0.956751,0.978389,0.898702,0.898702,0.933999,0.949691,0.834734,0.970453,0.964686,0.806239,0.806239,0.928466", "train/replay_ratio": "3.19091,2.41528,2.41528,2.41528,2.41528,1.32813,3.43177,3.43177,3.43177,3.43177,3.43177,3.43177,3.43177,2.40073,2.40073,2.40073,2.40073,2.40073,2.40073,2.40073,2.40073,3.81115,3.27002,3.27002,4,4,2.74913,3.44748,3.65735,1.93854,3.71453,3.71453,3.71453,1.91409,2.78202,2.69527,3.05733,3.28198,4,3.28116,3.28116,2.8314,2.8314,2.8314,1.93431,1.93431,1.93431,1.93431,1.93431,1.93431,2.99393,2.99393,2.99393,2.99393,2.99393,2.44114,2.44114,1.05177,1.05177,1.05177,1.05177,3.99644,1.61844,3.9108,3.74738,4,1.53557,3.34266,3.34266,2.97358,3.06197,1.01393,3.23108,3.35604,3.35604,1.20743,3.72177,2.09905,3.49296,3.49296,3.59072,3.59072,2.7726,2.7726,2.7726,3.63641,2.00387,3.93679,3.93679,1.83051,1.83051,1.83051,2.26595,3.08931,4,3.17248,4,4,2.59363,3.37323,2.65583,4,4,4,2.31701,3.26177,1.89678,2.13616,2.61207,2.61207,2.61207,2.61207,2.61207,2.61207,2.61207,1.59036,1.59036,0.759969,2.25498,2.25498,2.25498,2.25498,2.25498,2.25498,2.25498,2.25498,2.25498,2.25498,3.86874,3.86874,2.77975,3.59671,3.59809,3.59809,4,4,4,4,4,4,3.46889,3.46889,2.65995,1.85796,2.88459,3.12194,3.12194,2.6833,3.11924,3.11924,3.11924,3.11924,3.97338,3.97338,1.87248,1.88801,3.41569,3.61361,1.25897,4,4,3.41938,3.41938,0.822488,2.52435,2.52435,2.52435,4,2.60474,2.60474,2.46875,3.78638,1.67068,1.67068,3.14342,3.14342,3.39921,2.15505,2.15505,2.15505,2.15505,2.15505,4,4,4,4,4,4,0.643685,1.2603,4,3.94234,3.42863,3.42863,3.42863,4,3.76887,3.76887,2.85679,2.85679,2.32083,2.17151,2.50956,2.98878,4,3.64765,3.24955,4,4,1.46757,4,3.04353,3.16248,4,2.84652,0.284801,4,3.38183,2.51035,2.51035,3.16035,1.22905,1.93969,2.71789,3.24826,3.24826,3.04366,2.95215,2.14916,2.20479,2.75627,4,4,3.64672", "train/clip_coef": "0.275262,0.164613,0.164613,0.164613,0.164613,0.129772,0.0778085,0.0778085,0.0778085,0.0778085,0.0778085,0.0778085,0.0778085,0.161315,0.161315,0.161315,0.161315,0.161315,0.161315,0.161315,0.161315,0.0393562,0.01,0.01,0.0399939,0.0399939,0.01,0.0947239,0.180005,0.0953105,0.169893,0.169893,0.169893,0.144467,0.0995573,0.0572409,0.186542,0.01,0.1091,0.01,0.01,0.0626515,0.0626515,0.0626515,0.01,0.01,0.01,0.01,0.01,0.01,0.0400339,0.0400339,0.0400339,0.0400339,0.0400339,0.11466,0.11466,0.0741054,0.0741054,0.0741054,0.0741054,0.173566,0.40503,0.01,0.105753,0.148945,0.11724,0.178987,0.178987,0.0414872,0.118716,0.125938,0.0749951,0.153613,0.153613,0.198718,0.0482012,0.01,0.166414,0.166414,0.0290503,0.0290503,0.01,0.01,0.01,0.16989,0.01,0.0799009,0.0799009,0.01,0.01,0.01,0.01,0.159493,0.140303,0.01,0.129123,0.129123,0.138791,0.01,0.140107,0.0806223,0.0806223,0.0806223,0.101622,0.198094,0.01,0.01,0.0929891,0.0929891,0.0929891,0.0929891,0.0929891,0.0929891,0.0929891,0.0873394,0.0873394,0.150982,0.067834,0.067834,0.067834,0.067834,0.067834,0.067834,0.067834,0.067834,0.067834,0.067834,0.0903095,0.0903095,0.120531,0.133404,0.126607,0.126607,0.148914,0.135585,0.135585,0.135585,0.135585,0.135585,0.0523801,0.0523801,0.01,0.089791,0.01,0.0232591,0.0232591,0.239777,0.0772373,0.0772373,0.0772373,0.0772373,0.224345,0.224345,0.148575,0.105641,0.0372415,0.0973663,0.142111,0.201432,0.201432,0.01,0.01,0.25114,0.132646,0.132646,0.132646,0.0732559,0.138196,0.138196,0.146002,0.0988369,0.166691,0.166691,0.150955,0.150955,0.102233,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.171419,0.01,0.171565,0.196298,0.01,0.01,0.01,0.124768,0.0813967,0.0813967,0.143934,0.143934,0.01,0.084524,0.142123,0.0227055,0.13874,0.227425,0.110217,0.131131,0.131131,0.156289,0.101473,0.0825034,0.107515,0.198864,0.0859002,0.027732,0.01,0.266157,0.107382,0.107382,0.13718,0.112751,0.0767622,0.062639,0.01,0.01,0.129161,0.0935204,0.01,0.01,0.141891,0.177632,0.177632,0.223881", "train/vf_coef": "4.76057,5,5,5,5,5,4.04614,4.04614,4.04614,4.04614,4.04614,4.04614,4.04614,4.02014,4.02014,4.02014,4.02014,4.02014,4.02014,4.02014,4.02014,5,5,5,5,5,2.80141,3.10915,3.49199,3.63747,5,5,5,5,4.47305,5,4.87632,5,5,5,5,5,5,5,5,5,5,5,5,5,4.14462,4.14462,4.14462,4.14462,4.14462,5,5,5,5,5,5,4.53047,2.12611,5,5,4.343,5,2.62815,2.62815,5,4.36274,4.58311,4.36795,5,5,5,5,5,4.97288,4.97288,4.48374,4.48374,4.84482,4.84482,4.84482,5,5,4.50381,4.50381,5,5,5,5,4.61208,5,4.85518,3.64323,3.64323,5,5,5,4.72028,4.72028,4.72028,3.7957,4.4688,3.49194,5,3.62376,3.62376,3.62376,3.62376,3.62376,3.62376,3.62376,4.88016,4.88016,4.95178,4.42222,4.42222,4.42222,4.42222,4.42222,4.42222,4.42222,4.42222,4.42222,4.42222,3.4511,3.4511,3.26146,4.52636,5,5,3.5715,4.89794,4.89794,4.89794,4.89794,4.89794,5,5,5,4.37547,5,3.94131,3.94131,4.87343,5,5,5,5,4.24902,4.24902,4.90772,5,4.47861,4.09619,4.28947,5,5,4.77353,4.77353,2.76784,4.11864,4.11864,4.11864,4.83519,4.70901,4.70901,2.2821,3.80407,5,5,5,5,4.15325,2.95929,2.95929,2.95929,2.95929,2.95929,5,5,5,5,5,5,4.85889,5,4.16817,3.32309,4.26628,4.26628,4.26628,4.96893,5,5,4.04534,4.04534,4.79129,3.52649,3.67974,4.38531,4.52103,5,4.01575,3.74708,3.74708,5,4.41096,5,4.32163,5,5,4.83859,3.84715,3.82103,4.94377,4.94377,5,5,3.85587,5,3.79986,3.79986,3.70239,5,4.06726,3.13535,5,5,5,4.61162", "train/vf_clip_coef": "1.74936,4.95327,4.95327,4.95327,4.95327,1.7323,3.73982,3.73982,3.73982,3.73982,3.73982,3.73982,3.73982,2.68639,2.68639,2.68639,2.68639,2.68639,2.68639,2.68639,2.68639,4.28589,3.27406,3.27406,5,5,4.9097,2.07538,5,3.49076,3.06768,3.06768,3.06768,2.74824,2.60084,5,5,5,0.891572,2.44269,2.44269,4.38598,4.38598,4.38598,2.169,2.169,2.169,2.169,2.169,2.169,3.99274,3.99274,3.99274,3.99274,3.99274,3.06807,3.06807,1.53388,1.53388,1.53388,1.53388,2.58861,0.47427,3.23068,0.285396,2.80241,3.4575,3.73203,3.73203,4.13144,2.43908,2.09347,3.74502,1.92158,1.92158,2.43864,4.9309,2.35476,2.51733,2.51733,3.58487,3.58487,2.85772,2.85772,2.85772,1.4702,3.8172,4.04531,4.04531,3.52841,3.52841,3.52841,2.7776,1.29079,1.93054,2.35918,1.07094,1.07094,3.55805,4.97521,4.30514,5,5,5,5,1.49416,1.64025,4.12664,4.91719,4.91719,4.91719,4.91719,4.91719,4.91719,4.91719,1.81147,1.81147,2.06953,3.42278,3.42278,3.42278,3.42278,3.42278,3.42278,3.42278,3.42278,3.42278,3.42278,2.8073,2.8073,2.55271,2.21794,4.00962,4.00962,1.98088,0.882682,0.882682,0.882682,0.882682,0.882682,3.60376,3.60376,4.00637,0.576209,5,2.15622,2.15622,1.05082,4.90333,4.90333,4.90333,4.90333,3.73224,3.73224,2.51546,2.94863,4.97824,3.31939,1.46018,0.858086,0.858086,2.25195,2.25195,0.970715,2.09847,2.09847,2.09847,1.62841,3.1311,3.1311,1.26695,3.78604,2.50527,2.50527,3.69204,3.69204,5,1.96065,1.96065,1.96065,1.96065,1.96065,3.01821,3.01821,3.01821,3.01821,3.01821,3.01821,2.9007,1.23624,3.34964,1.95188,3.74541,3.74541,3.74541,3.14251,0.795649,0.795649,3.56534,3.56534,3.23899,5,0.548674,3.16035,2.10434,1.32286,4.26809,1.28398,1.28398,3.20735,3.97273,3.9167,2.157,2.21575,1.9922,1.6104,4.60502,0.420291,4.35731,4.35731,5,1.4212,2.60407,2.11754,3.72726,3.72726,2.06993,4.74481,2.35356,2.6557,2.90146,2.23222,2.23222,3.49821", "train/max_grad_norm": "0.344324,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.235895,0.1,0.1,0.1,0.1,0.1,0.427298,1.22179,0.1,0.1,0.1,0.1,0.641543,0.1,1.26424,0.1,0.1,0.182723,0.420045,0.420045,0.622312,0.622312,0.622312,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.109978,0.109978,0.1,0.1,0.1,0.1,0.1,0.1,0.224052,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.498858,0.498858,0.1,0.1,0.353015,0.1,0.1,1.16974,1.16974,0.1,0.1,0.1,0.1,0.520608,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.421417,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.127421,0.692201,0.692201,0.692201,0.692201,0.692201,0.692201,0.692201,0.692201,0.692201,0.692201,0.1,0.1,0.1,0.299385,0.1,0.1,0.660503,0.341142,0.341142,0.341142,0.341142,0.341142,0.1,0.1,0.1,0.1,0.1,0.778778,0.778778,1.14578,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.688201,0.688201,0.1,0.1,0.1,0.193472,0.193472,0.193472,0.1,0.1,0.1,0.1,0.188645,0.534796,0.534796,0.484835,0.484835,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.469095,0.1,0.1,0.1,0.1,0.1,0.1,0.170914,0.170914,0.1,0.1,0.1,0.1,0.1,0.888133,0.1,0.1,0.258284,0.203855,0.203855,0.1,0.1,0.756389,0.714645,0.261197,0.238154,0.1,0.331002,0.1,0.1,0.1,0.1,0.164425,0.1,0.1,0.1,0.1,0.1,0.1,0.1,1.11813,0.1,0.1,0.1,0.1", "train/ent_coef": "0.000647442,1e-05,1e-05,1e-05,1e-05,4.16448e-05,1e-05,1e-05,1e-05,1e-05,1e-05,1e-05,1e-05,0.000146845,0.000146845,0.000146845,0.000146845,0.000146845,0.000146845,0.000146845,0.000146845,2.0032e-05,0.000146943,0.000146943,1e-05,1e-05,0.000273319,0.00254611,0.00180684,0.000969022,0.000137114,0.000137114,0.000137114,3.64277e-05,2.20353e-05,2.0197e-05,2.98389e-05,5.68014e-05,2.53788e-05,1.62987e-05,1.62987e-05,1e-05,1e-05,1e-05,1e-05,1e-05,1e-05,1e-05,1e-05,1e-05,1e-05,1e-05,1e-05,1e-05,1e-05,0.000217517,0.000217517,0.000582827,0.000582827,0.000582827,0.000582827,0.000418192,0.0013211,4.40449e-05,0.000646521,0.000582027,1e-05,5.60105e-05,5.60105e-05,0.00102195,1e-05,0.00019458,0.000431157,0.00061456,0.00061456,1e-05,1.62453e-05,7.00109e-05,0.000216613,0.000216613,2.99989e-05,2.99989e-05,0.000730788,0.000730788,0.000730788,1e-05,0.000192562,0.000967598,0.000967598,2.74763e-05,2.74763e-05,2.74763e-05,0.000151693,0.000206475,1.71614e-05,6.6044e-05,1e-05,1e-05,1e-05,1e-05,0.00051026,1.08894e-05,1.08894e-05,1.08894e-05,1e-05,2.09935e-05,0.00148797,8.03717e-05,0.000663397,0.000663397,0.000663397,0.000663397,0.000663397,0.000663397,0.000663397,1.79218e-05,1.79218e-05,1e-05,9.62597e-05,9.62597e-05,9.62597e-05,9.62597e-05,9.62597e-05,9.62597e-05,9.62597e-05,9.62597e-05,9.62597e-05,9.62597e-05,0.000223387,0.000223387,0.000190899,0.000592265,1e-05,1e-05,0.000225983,1e-05,1e-05,1e-05,1e-05,1e-05,1.00813e-05,1.00813e-05,5.80959e-05,0.000374552,8.21843e-05,4.71306e-05,4.71306e-05,0.000126485,7.80621e-05,7.80621e-05,7.80621e-05,7.80621e-05,1e-05,1e-05,1e-05,2.31238e-05,1.8897e-05,0.000110862,8.81793e-05,0.00173964,0.00173964,1e-05,1e-05,0.00119682,0.000168124,0.000168124,0.000168124,2.10471e-05,5.49369e-05,5.49369e-05,5.13608e-05,3.18023e-05,1e-05,1e-05,3.60677e-05,3.60677e-05,0.000226911,0.000328335,0.000328335,0.000328335,0.000328335,0.000328335,4.46027e-05,4.46027e-05,4.46027e-05,4.46027e-05,4.46027e-05,4.46027e-05,0.000154851,0.0019352,1e-05,0.000285772,5.33691e-05,5.33691e-05,5.33691e-05,3.11424e-05,7.32726e-05,7.32726e-05,5.37468e-05,5.37468e-05,0.000107137,0.000365268,0.000203709,0.000206556,1e-05,1e-05,1e-05,1e-05,1e-05,1e-05,0.00102294,1e-05,1e-05,1.79122e-05,0.00121711,0.00395522,9.36062e-05,4.67794e-05,7.01038e-05,7.01038e-05,1e-05,0.000109709,1.60114e-05,4.26345e-05,0.000116224,0.000116224,4.14141e-05,1e-05,0.00660552,0.000236813,1e-05,0.000272624,0.000272624,0.000106629", "train/beta1": "0.903224,0.8311,0.8311,0.8311,0.8311,0.85158,0.862547,0.862547,0.862547,0.862547,0.862547,0.862547,0.862547,0.946075,0.946075,0.946075,0.946075,0.946075,0.946075,0.946075,0.946075,0.937749,0.90808,0.90808,0.891953,0.891953,0.91608,0.901968,0.865047,0.813388,0.944887,0.944887,0.944887,0.950966,0.947685,0.893527,0.93362,0.845644,0.920693,0.90536,0.90536,0.922293,0.922293,0.922293,0.916045,0.916045,0.916045,0.916045,0.916045,0.916045,0.798523,0.798523,0.798523,0.798523,0.798523,0.957806,0.957806,0.957651,0.957651,0.957651,0.957651,0.929609,0.979409,0.895805,0.873405,0.96008,0.914564,0.91716,0.91716,0.854441,0.835406,0.968891,0.914371,0.955036,0.955036,0.788636,0.815998,0.915848,0.921679,0.921679,0.935469,0.935469,0.96141,0.96141,0.96141,0.934563,0.922574,0.869578,0.869578,0.973712,0.973712,0.973712,0.893751,0.962804,0.963182,0.932301,0.93782,0.93782,0.866467,0.937924,0.853783,0.942803,0.942803,0.942803,0.936562,0.804762,0.940475,0.823709,0.924056,0.924056,0.924056,0.924056,0.924056,0.924056,0.924056,0.948724,0.948724,0.946104,0.914207,0.914207,0.914207,0.914207,0.914207,0.914207,0.914207,0.914207,0.914207,0.914207,0.962738,0.962738,0.890455,0.877887,0.948685,0.948685,0.892758,0.893978,0.893978,0.893978,0.893978,0.893978,0.945078,0.945078,0.820692,0.937762,0.840007,0.943279,0.943279,0.98369,0.974444,0.974444,0.974444,0.974444,0.952922,0.952922,0.912835,0.920811,0.93996,0.920402,0.90035,0.941795,0.941795,0.929658,0.929658,0.924967,0.897248,0.897248,0.897248,0.935266,0.89944,0.89944,0.8902,0.907105,0.928577,0.928577,0.855615,0.855615,0.874992,0.957341,0.957341,0.957341,0.957341,0.957341,0.917391,0.917391,0.917391,0.917391,0.917391,0.917391,0.950889,0.790374,0.815146,0.95453,0.861823,0.861823,0.861823,0.812838,0.909965,0.909965,0.897725,0.897725,0.948042,0.923177,0.966419,0.822684,0.923802,0.903648,0.843535,0.854343,0.854343,0.959153,0.898134,0.93283,0.86882,0.965592,0.841098,0.946773,0.948745,0.95588,0.924339,0.924339,0.930824,0.927669,0.905801,0.81969,0.856331,0.856331,0.905247,0.920837,0.982567,0.961294,0.978445,0.960087,0.960087,0.860058", "train/beta2": "0.99999,0.999842,0.999842,0.999842,0.999842,0.999986,0.999952,0.999952,0.999952,0.999952,0.999952,0.999952,0.999952,0.999978,0.999978,0.999978,0.999978,0.999978,0.999978,0.999978,0.999978,0.99999,0.99999,0.99999,0.99999,0.99999,0.999908,0.999944,0.999978,0.999987,0.999901,0.999901,0.999901,0.999901,0.999938,0.99999,0.99993,0.999792,0.99994,0.99999,0.99999,0.999972,0.999972,0.999972,0.999861,0.999861,0.999861,0.999861,0.999861,0.999861,0.99999,0.99999,0.99999,0.99999,0.99999,0.99999,0.99999,0.999857,0.999857,0.999857,0.999857,0.99999,0.99999,0.99999,0.999916,0.998465,0.99999,0.999503,0.999503,0.999976,0.995264,0.999904,0.999957,0.99999,0.99999,0.999923,0.999918,0.999976,0.999976,0.999976,0.999959,0.999959,0.999985,0.999985,0.999985,0.999937,0.99999,0.999931,0.999931,0.99985,0.99985,0.99985,0.9999,0.999984,0.999892,0.99999,0.99999,0.99999,0.99999,0.99999,0.999797,0.999904,0.999904,0.999904,0.99999,0.99999,0.999831,0.999983,0.999968,0.999968,0.999968,0.999968,0.999968,0.999968,0.999968,0.99999,0.99999,0.99999,0.99988,0.99988,0.99988,0.99988,0.99988,0.99988,0.99988,0.99988,0.99988,0.99988,0.999688,0.999688,0.999946,0.99999,0.99999,0.99999,0.99999,0.99999,0.99999,0.99999,0.99999,0.99999,0.99999,0.99999,0.999936,0.999523,0.999954,0.999964,0.999964,0.999954,0.999984,0.999984,0.999984,0.999984,0.99999,0.99999,0.99999,0.99998,0.999974,0.999812,0.999777,0.99999,0.99999,0.999908,0.999908,0.999986,0.999746,0.999746,0.999746,0.999927,0.999984,0.999984,0.999593,0.999958,0.99999,0.99999,0.99999,0.99999,0.99999,0.99999,0.99999,0.99999,0.99999,0.99999,0.999873,0.999873,0.999873,0.999873,0.999873,0.999873,0.999988,0.999798,0.998023,0.999945,0.999984,0.999984,0.999984,0.99999,0.99999,0.99999,0.998871,0.998871,0.999976,0.999858,0.999816,0.99999,0.999916,0.99999,0.999988,0.99999,0.99999,0.99999,0.999333,0.99999,0.99999,0.999985,0.999968,0.999954,0.999989,0.999988,0.999968,0.999968,0.999945,0.999973,0.999936,0.999965,0.999955,0.999955,0.999785,0.999957,0.999951,0.99999,0.99999,0.999956,0.999956,0.999924", "train/eps": "1.0073e-14,1e-14,1e-14,1e-14,1e-14,9.20235e-08,2.65083e-12,2.65083e-12,2.65083e-12,2.65083e-12,2.65083e-12,2.65083e-12,2.65083e-12,1.58311e-10,1.58311e-10,1.58311e-10,1.58311e-10,1.58311e-10,1.58311e-10,1.58311e-10,1.58311e-10,1.1152e-11,1.30599e-10,1.30599e-10,2.85368e-09,2.85368e-09,1.04696e-10,2.82911e-11,1.20932e-12,4.38851e-13,1.66013e-10,1.66013e-10,1.66013e-10,9.80396e-12,8.48833e-12,1.8118e-13,6.41134e-11,1.02311e-13,1e-14,8.49912e-13,8.49912e-13,1e-14,1e-14,1e-14,1.72206e-11,1.72206e-11,1.72206e-11,1.72206e-11,1.72206e-11,1.72206e-11,1.41466e-11,1.41466e-11,1.41466e-11,1.41466e-11,1.41466e-11,3.96937e-08,3.96937e-08,6.66079e-12,6.66079e-12,6.66079e-12,6.66079e-12,5.44886e-10,1e-14,1e-14,1e-14,1.98672e-14,3.87606e-14,8.49628e-09,8.49628e-09,6.37014e-12,3.07747e-13,1.64912e-09,3.47581e-13,1.08488e-11,1.08488e-11,6.33825e-09,1.27836e-13,7.11261e-07,3.90321e-12,3.90321e-12,1.89334e-12,1.89334e-12,2.351e-12,2.351e-12,2.351e-12,1.42429e-14,1e-14,1.51286e-13,1.51286e-13,1e-14,1e-14,1e-14,6.83916e-13,1e-14,2.38434e-12,1.19603e-12,1.07739e-12,1.07739e-12,2.75902e-10,9.86182e-10,8.39318e-13,4.64821e-12,4.64821e-12,4.64821e-12,1e-14,2.6154e-10,4.8505e-11,2.33453e-12,1.43406e-10,1.43406e-10,1.43406e-10,1.43406e-10,1.43406e-10,1.43406e-10,1.43406e-10,5.86287e-13,5.86287e-13,7.74127e-11,1e-14,1e-14,1e-14,1e-14,1e-14,1e-14,1e-14,1e-14,1e-14,1e-14,8.51566e-13,8.51566e-13,1.7373e-12,1.93491e-09,2.02997e-09,2.02997e-09,1.50884e-13,1.14771e-11,1.14771e-11,1.14771e-11,1.14771e-11,1.14771e-11,7.78245e-12,7.78245e-12,8.83839e-11,7.04644e-10,2.89914e-10,1.06765e-12,1.06765e-12,1.39452e-10,6.99308e-12,6.99308e-12,6.99308e-12,6.99308e-12,6.45917e-10,6.45917e-10,6.05636e-13,2.0382e-11,1e-14,9.38009e-10,1.60015e-09,3.30411e-12,3.30411e-12,2.26283e-09,2.26283e-09,6.5517e-14,1.2682e-07,1.2682e-07,1.2682e-07,1.62366e-09,2.29525e-13,2.29525e-13,1e-14,9.49869e-13,1.30457e-12,1.30457e-12,8.47913e-12,8.47913e-12,1.01157e-09,8.99994e-11,8.99994e-11,8.99994e-11,8.99994e-11,8.99994e-11,1e-14,1e-14,1e-14,1e-14,1e-14,1e-14,1.92299e-11,1.72519e-08,3.77601e-12,1e-14,8.75739e-10,8.75739e-10,8.75739e-10,2.98763e-12,1e-14,1e-14,7.68783e-12,7.68783e-12,3.38708e-14,2.75335e-12,6.23053e-11,5.51334e-11,1.14069e-12,1e-14,1.57326e-13,1.36464e-13,1.36464e-13,7.71019e-10,2.1165e-12,1.55926e-13,3.14791e-07,5.37653e-13,1.2899e-14,3.66939e-12,4.21261e-14,4.16119e-14,9.77418e-13,9.77418e-13,9.03377e-09,1.6424e-08,7.57499e-13,8.17975e-11,3.41076e-12,3.41076e-12,1.07274e-10,4.86552e-10,3.82597e-09,1.73431e-10,8.17788e-13,1e-14,1e-14,2.12623e-14", "train/minibatch_size": "4096,4096,4096,4096,4096,8192,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,8192,8192,8192,8192,8192,4096,4096,4096,16384,4096,4096,4096,8192,4096,4096,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,4096,4096,4096,4096,4096,8192,8192,4096,4096,4096,4096,4096,4096,8192,8192,4096,8192,4096,4096,8192,8192,8192,4096,4096,4096,8192,8192,8192,4096,4096,4096,4096,4096,4096,4096,4096,8192,4096,4096,4096,4096,4096,8192,4096,8192,4096,4096,4096,8192,4096,8192,4096,4096,4096,8192,16384,4096,8192,4096,4096,4096,4096,4096,4096,4096,8192,8192,16384,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,8192,4096,4096,16384,4096,4096,4096,4096,8192,8192,4096,8192,4096,8192,8192,4096,4096,8192,8192,8192,8192,8192,8192,4096,4096,4096,16384,4096,8192,8192,4096,4096,8192,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,8192,4096,4096,4096,8192,8192,8192,4096,4096,4096,8192,8192,8192,4096,4096,16384,4096,8192,8192,4096,4096,8192,4096,8192,4096,4096,8192,4096,4096,4096,4096,4096,4096,8192,8192,16384,4096,4096,4096,8192,4096,4096,4096,4096,4096,4096", "train/horizon": "32,128,128,128,128,64,32,32,32,32,32,32,32,64,64,64,64,64,64,64,64,128,128,128,128,128,64,32,128,64,128,128,128,64,16,64,32,64,64,32,32,128,128,128,32,32,32,32,32,32,64,64,64,64,64,32,32,32,32,32,32,64,8,32,32,128,64,128,128,64,64,32,64,64,64,32,64,32,32,32,128,128,64,64,64,32,64,64,64,64,64,64,64,64,64,32,128,128,64,32,64,64,64,64,64,64,16,32,64,64,64,64,64,64,64,64,64,32,32,32,32,32,32,32,32,32,32,32,64,64,128,64,64,64,64,128,128,128,128,128,64,64,128,32,64,64,64,32,64,64,64,64,64,64,64,64,64,64,16,64,64,32,32,8,64,64,64,64,32,32,8,64,32,32,64,64,64,64,64,64,64,64,32,32,32,32,32,32,64,256,64,128,64,64,64,64,32,32,128,128,32,128,64,32,128,64,64,32,32,128,64,256,64,128,64,32,64,32,64,64,128,64,32,32,128,128,128,64,64,32,32,64,64,64", "train/vtrace_rho_clip": "2.92481,3.379,3.379,3.379,3.379,1.75616,2.78083,2.78083,2.78083,2.78083,2.78083,2.78083,2.78083,2.96177,2.96177,2.96177,2.96177,2.96177,2.96177,2.96177,2.96177,3.74188,3.56818,3.56818,2.58438,2.58438,5,3.07246,4.69085,3.27872,4.70412,4.70412,4.70412,2.35415,3.10203,2.93769,3.05846,2.58632,3.40894,3.34528,3.34528,3.09196,3.09196,3.09196,2.49199,2.49199,2.49199,2.49199,2.49199,2.49199,3.27623,3.27623,3.27623,3.27623,3.27623,1.87622,1.87622,1.46214,1.46214,1.46214,1.46214,3.31686,5,2.67727,2.85492,3.14203,3.80154,5,5,3.03282,5,2.22347,5,2.52393,2.52393,1.38111,3.10255,2.67085,2.50359,2.50359,4.14604,4.14604,4.4955,4.4955,4.4955,2.82626,4.96357,2.83012,2.83012,2.73809,2.73809,2.73809,3.49397,1.9508,3.0755,4.54791,2.12211,2.12211,3.21137,4.14471,5,3.85613,3.85613,3.85613,3.5031,4.14803,1.82989,2.89615,3.87302,3.87302,3.87302,3.87302,3.87302,3.87302,3.87302,3.12482,3.12482,3.26571,3.32822,3.32822,3.32822,3.32822,3.32822,3.32822,3.32822,3.32822,3.32822,3.32822,4.91472,4.91472,3.94007,3.00342,4.6556,4.6556,1.88384,2.26437,2.26437,2.26437,2.26437,2.26437,2.5994,2.5994,3.02048,0.810921,3.56639,3.07062,3.07062,1.7143,4.91664,4.91664,4.91664,4.91664,4.14079,4.14079,1.67886,3.00613,2.26723,5,1.38597,1.86472,1.86472,3.43065,3.43065,4.53412,3.85997,3.85997,3.85997,2.73815,3.09019,3.09019,5,4.82149,1.49702,1.49702,4.0662,4.0662,3.77978,2.23062,2.23062,2.23062,2.23062,2.23062,3.54863,3.54863,3.54863,3.54863,3.54863,3.54863,3.23362,1.6416,3.31113,3.25142,3.05997,3.05997,3.05997,3.24627,3.41508,3.41508,4.43466,4.43466,3.92512,4.68407,2.4606,2.13539,2.47101,2.33758,1.99195,2.91352,2.91352,2.8803,2.8424,3.8304,3.63926,3.20164,5,2.11552,3.68372,2.56815,3.48055,3.48055,4.27903,2.9977,4.43107,3.02295,4.04908,4.04908,3.29696,4.8863,1.44182,3.22963,2.31095,2.5914,2.5914,4.83343", "train/vtrace_c_clip": "2.56151,1.63678,1.63678,1.63678,1.63678,2.12449,1.6118,1.6118,1.6118,1.6118,1.6118,1.6118,1.6118,1.70274,1.70274,1.70274,1.70274,1.70274,1.70274,1.70274,1.70274,3.06845,2.54717,2.54717,3.35321,3.35321,4.60263,2.72465,3.73836,2.88213,2.15015,2.15015,2.15015,2.25157,2.70803,1.65582,3.19825,1.35808,2.40892,2.61268,2.61268,1.31092,1.31092,1.31092,3.11738,3.11738,3.11738,3.11738,3.11738,3.11738,2.54308,2.54308,2.54308,2.54308,2.54308,3.91506,3.91506,1.82475,1.82475,1.82475,1.82475,2.26623,0.274503,2.80763,2.70122,2.7759,2.34946,5,5,3.64358,3.91163,2.88902,4.47115,2.55318,2.55318,3.37843,0.898918,3.21177,2.48576,2.48576,4.28977,4.28977,4.91498,4.91498,4.91498,2.47767,3.88358,3.73328,3.73328,3.34152,3.34152,3.34152,3.12887,2.40139,2.6638,3.74329,2.44731,2.44731,3.04332,4.16858,4.90438,2.66363,2.66363,2.66363,1.87659,2.08763,4.09364,2.51839,5,5,5,5,5,5,5,3.13623,3.13623,2.48231,4.37219,4.37219,4.37219,4.37219,4.37219,4.37219,4.37219,4.37219,4.37219,4.37219,4.34807,4.34807,5,2.50724,1.95632,1.95632,2.36141,2.28621,2.28621,2.28621,2.28621,2.28621,1.93657,1.93657,2.10518,1.83175,3.75584,2.35472,2.35472,1.59635,3.1918,3.1918,3.1918,3.1918,2.22026,2.22026,3.19508,2.54213,1.17968,3.90324,2.9577,2.73149,2.73149,2.35852,2.35852,1.31197,3.54122,3.54122,3.54122,2.76449,2.71434,2.71434,2.23376,3.6822,2.43225,2.43225,3.19193,3.19193,4.19018,2.98317,2.98317,2.98317,2.98317,2.98317,3.90982,3.90982,3.90982,3.90982,3.90982,3.90982,3.08828,2.02847,3.94966,2.02014,3.77806,3.77806,3.77806,2.61249,3.04313,3.04313,3.02529,3.02529,4.01974,5,2.75842,3.60964,2.28386,2.6414,1.4642,2.66866,2.66866,2.60526,3.33541,1.53178,3.84886,2.25273,3.35617,1.86575,3.12936,2.95063,5,5,3.5553,2.50914,5,2.81626,4.87134,4.87134,5,3.88249,2.72117,2.99045,2.586,2.51508,2.51508,1.56142", "train/prio_alpha": "0.558399,0.556055,0.556055,0.556055,0.556055,0.30033,0.67355,0.67355,0.67355,0.67355,0.67355,0.67355,0.67355,0.516982,0.516982,0.516982,0.516982,0.516982,0.516982,0.516982,0.516982,0.484297,0.401597,0.401597,0.521482,0.521482,0.422921,0.96258,0.407084,0.678636,0.447682,0.447682,0.447682,0.329187,0.380771,0.725645,0.529637,0.512362,0.477818,0.16315,0.16315,0.499572,0.499572,0.499572,0.562907,0.562907,0.562907,0.562907,0.562907,0.562907,0.279386,0.279386,0.279386,0.279386,0.279386,0.386051,0.386051,0.384232,0.384232,0.384232,0.384232,0.586935,0.122738,0.566682,0.683235,0.130892,0.563044,0.366076,0.366076,0.748311,0.24043,0.285512,0.647336,0.512447,0.512447,0.412075,0.634874,0.13652,0.463068,0.463068,0.415768,0.415768,0.143503,0.143503,0.143503,0.367406,0.499605,0.321156,0.321156,0.471508,0.471508,0.471508,0.342071,0.321199,0.263314,0.313007,0.6878,0.6878,0.31151,0.439025,0.377351,0.506439,0.506439,0.506439,0.355865,0.579205,0.0438803,0.234164,0.595438,0.595438,0.595438,0.595438,0.595438,0.595438,0.595438,0.165113,0.165113,0.274937,0.427293,0.427293,0.427293,0.427293,0.427293,0.427293,0.427293,0.427293,0.427293,0.427293,0.188327,0.188327,0.529478,0.450013,0.674462,0.674462,0.433938,0.220834,0.220834,0.220834,0.220834,0.220834,0.710972,0.710972,0.489304,0.331938,0.381051,0.40165,0.40165,0.425219,0.35896,0.35896,0.35896,0.35896,0.677955,0.677955,0.359181,0.518821,0.672177,0,0.0785122,0.606172,0.606172,0.261299,0.261299,0.133245,0.254679,0.254679,0.254679,0.115876,0.37573,0.37573,0.152648,0.407779,0.428913,0.428913,0.574947,0.574947,0.464109,0.636564,0.636564,0.636564,0.636564,0.636564,0.444315,0.444315,0.444315,0.444315,0.444315,0.444315,0.0877892,0.849401,0.342325,0.577325,0.556497,0.556497,0.556497,0.305078,0.0507519,0.0507519,0.2202,0.2202,0.502902,0.222458,0.708915,0.643037,0.444178,0.390802,0.740041,0.270662,0.270662,0.728834,0.253416,0.303301,0.5347,0.488051,0.504801,0.301381,0.431506,0.713735,0.198955,0.198955,0.341896,0.198499,0.466955,0.390929,0.369218,0.369218,0.479425,0.490901,0.587023,0.535052,0.393744,0.388873,0.388873,0.471809", "train/prio_beta0": "0.817084,1,1,1,1,0.441805,0.870102,0.870102,0.870102,0.870102,0.870102,0.870102,0.870102,0.80892,0.80892,0.80892,0.80892,0.80892,0.80892,0.80892,0.80892,1,1,1,0.884177,0.884177,1,0.88873,0.873399,0.770054,1,1,1,0.473405,1,0.917541,0.522277,1,0.881471,1,1,1,1,1,0.809484,0.809484,0.809484,0.809484,0.809484,0.809484,0.894142,0.894142,0.894142,0.894142,0.894142,0.686643,0.686643,0.542608,0.542608,0.542608,0.542608,1,0.554515,0.992058,0.766093,0.494954,0.819132,0.882591,0.882591,0.966038,0.353954,0.560894,0.836501,0.973199,0.973199,0.813962,1,1,0.948001,0.948001,1,1,0.84807,0.84807,0.84807,0.754942,0.930857,0.780805,0.780805,1,1,1,0.817544,0.774642,1,0.946444,1,1,1,1,0.75072,1,1,1,1,0.965901,0.34687,0.934596,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0.943677,1,1,1,0.904555,1,1,1,1,1,0.640808,0.640808,1,0.603395,1,1,1,0.63321,1,1,1,1,1,1,1,0.774645,1,0.653566,0.58976,1,1,0.721855,0.721855,0.590253,0.868982,0.868982,0.868982,0.937274,1,1,0.846022,0.916735,1,1,0.701758,0.701758,1,0.939317,0.939317,0.939317,0.939317,0.939317,0.923723,0.923723,0.923723,0.923723,0.923723,0.923723,0.660411,1,0.342875,1,1,1,1,0.896271,1,1,0.736516,0.736516,1,1,0.960052,0.916761,0.89103,0.65308,1,1,1,0.763934,0.697882,1,0.835047,0.912982,0.804707,0.481268,1,1,1,1,1,0.946204,0.806975,0.957751,1,1,1,0.85144,1,1,0.99514,1,1,0.690197", "no_model_upload": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "legacy/torch_deterministic": "1,1,1,1,1", "legacy/cpu_offload": "0,0,0,0,0", "legacy/compile": "0,0,0,0,0", "legacy/compile_fullgraph": "1,1,1,1,1", "train/use_rnn": "1,1,1,1,1", "tsne1": "31.9488,42.6299,42.6299,42.6299,42.6298,26.1801,40.6892,40.7971,40.675,40.675,40.8043,40.7974,40.6747,30.1512,30.0368,30.3418,30.0636,30.3891,30.0861,30.1224,30.3893,44.966,43.992,43.9921,42.8862,42.8862,46.681,26.5297,47.9633,41.0654,45.0773,45.0774,45.0773,26.537,33.4587,42.0494,39.0177,42.6759,33.7997,35.5695,35.5694,43.4071,43.4071,43.4059,31.2314,31.2311,31.2308,31.2311,31.231,31.2311,42.7129,42.7129,42.7129,42.7129,42.7129,27.9262,27.9266,24.0957,24.0957,24.0957,24.0957,31.236,8.47692,33.7418,31.0079,37.7485,33.1393,47.8243,47.8243,41.9111,37.9278,26.4874,44.2782,31.41,31.4099,29.4543,42.6796,28.9849,32.2881,32.2881,47.4706,47.4707,40.33,40.33,40.33,33.8507,38.3963,38.7462,38.7462,35.0702,35.0701,35.0701,35.0485,32.5025,34.7327,39.6769,31.8915,31.8915,33.6845,45.7883,44.3734,46.2786,46.2786,46.2785,43.8811,31.2977,14.9393,34.6525,46.0909,46.2711,46.2692,46.0919,46.273,46.0919,46.091,32.1301,32.1301,29.3381,37.2285,37.5346,37.1667,37.545,36.9467,37.1459,37.0182,37.1246,37.5388,37.109,46.5548,46.5548,43.9507,31.2088,46.4756,46.4756,32.1857,34.5485,34.5485,34.5485,34.5485,34.5485,39.8038,39.8041,43.3403,23.7017,43.4458,33.1192,33.1192,26.0567,45.0724,45.0716,45.0724,45.0724,47.0184,47.0184,33.667,32.7141,41.4758,37.7654,26.1195,30.63,30.63,35.4502,35.4503,8.58643,29.2206,29.2206,29.2184,35.2275,34.0002,33.9997,8.94151,46.6323,30.8044,30.8062,39.3661,39.3667,43.3213,27.4217,27.4221,27.4219,27.4214,27.4222,40.1958,40.2001,40.1989,40.1958,40.1989,40.2001,27.2765,27.8302,38.3463,32.0237,42.405,42.4054,42.4052,41.9358,35.6757,35.6757,37.8617,37.8606,37.811,45.98,29.1146,41.5213,33.5862,33.5733,41.3109,35.0816,35.0817,32.297,38.3114,44.1971,29.3835,33.4975,38.1778,23.5063,46.8775,31.2479,40.5188,40.5186,45.1693,28.4719,38.459,31.3547,44.4426,44.4426,43.6405,44.2094,28.1908,27.9846,33.679,32.73,32.73,44.5528", "tsne2": "-4.9703,-12.919,-12.919,-12.919,-12.9193,4.92978,-9.68658,-9.59539,-9.69768,-9.69768,-9.59554,-9.59482,-9.6978,-1.33389,-1.42839,-1.403,-1.62599,-1.49906,-1.64987,-1.669,-1.51983,-4.0849,-4.59768,-4.59769,-2.99018,-2.99018,1.87675,-2.51133,-0.138537,0.197949,-6.29911,-6.29907,-6.29911,5.676,-0.350462,-12.1534,-7.15682,-11.4888,-6.01604,-3.59711,-3.59716,-11.9767,-11.9767,-11.9737,4.16129,4.16138,4.16119,4.16138,4.16237,4.16153,-6.14886,-6.14886,-6.14886,-6.14886,-6.14886,3.8081,3.80809,4.11973,4.11973,4.11973,4.11973,-3.4551,6.93684,-4.13618,-6.77242,-3.09218,3.17392,1.3653,1.3653,-0.579921,-0.403156,4.99973,2.68117,-4.32176,-4.32198,4.78451,-11.3963,2.68136,-4.10807,-4.10806,-1.59369,-1.59377,2.58865,2.58865,2.58865,-5.69471,3.99838,-2.93475,-2.93475,4.73558,4.73591,4.73591,2.54573,-6.06462,-5.31181,2.02162,-8.47115,-8.47115,2.18132,-3.17696,3.05771,-3.9594,-3.95941,-3.95939,-12.6484,1.35343,-9.92913,2.1656,2.79388,2.81567,2.8189,2.79557,2.81481,2.79557,2.79681,5.88735,5.88767,6.35213,4.93815,4.74688,4.91415,4.5695,4.49626,4.26299,4.78713,4.26655,4.73014,4.28094,-0.154375,-0.154375,1.73114,-3.45968,-5.53865,-5.53865,-6.51527,-8.34983,-8.34974,-8.34988,-8.34974,-8.34996,-8.77883,-8.7788,-5.26742,3.3071,-1.29056,-2.98028,-2.98026,6.66142,-1.47642,-1.47642,-1.47642,-1.47642,-5.83316,-5.83316,4.67546,3.11777,-11.4161,0.740542,4.68251,-5.28887,-5.28887,-2.17801,-2.17799,6.96988,1.90984,1.9092,1.90699,-8.57189,0.216005,0.216177,7.17779,-1.12203,5.57019,5.57,-1.04291,-1.04259,-1.05113,-1.86314,-1.86402,-1.86309,-1.8627,-1.86333,-4.50012,-4.50041,-4.49779,-4.50012,-4.49779,-4.50041,5.46506,-3.58577,-1.26753,-7.9431,-1.44149,-1.4416,-1.44159,-5.75592,-5.96736,-5.96736,0.255392,0.255375,3.80982,1.83977,-3.33039,-0.476492,-7.028,-6.28237,-10.5819,-7.14474,-7.14446,3.1851,-2.94445,-11.3423,1.11877,-7.10166,2.70847,4.41471,-2.99152,-7.65606,4.02969,4.02984,-2.92859,5.33165,5.44454,2.46718,1.26549,1.26549,1.6112,-2.0661,-3.46063,-1.12142,0.444345,-5.24099,-5.24099,-7.299"}, "enduro": {"SPS": "2.09792e+06,1.9454e+06,2.2193e+06,2.17816e+06,2.16072e+06,2.00159e+06,2.41056e+06,2.42999e+06,2.44468e+06,1.71525e+06,1.86347e+06,2.23443e+06,2.38875e+06,1.79479e+06,1.83007e+06,1.8281e+06,1.81959e+06,2.54003e+06,2.52102e+06,2.51686e+06,2.45839e+06,2.40067e+06,2.32646e+06,2.30814e+06,2.30594e+06,2.30192e+06,2.29646e+06,2.27638e+06,1.88492e+06,1.81015e+06,2.23551e+06,1.40568e+06,1.38256e+06,2.33937e+06,2.27382e+06,2.0517e+06,2.41972e+06,2.30262e+06,1.71193e+06,2.01178e+06,5.63157e+06,2.39003e+06,2.48853e+06,1.87525e+06,1.8442e+06,1.81258e+06,2.0933e+06,2.34351e+06,2.63798e+06,2.21279e+06,2.21504e+06,3.31676e+06,2.38007e+06,2.28315e+06,2.38264e+06,1.48932e+06,1.47491e+06,1.49397e+06,1.55438e+06,3.27703e+06,1.88642e+06,2.3504e+06,1.84002e+06,1.88229e+06,1.86654e+06,2.00355e+06,2.04231e+06,2.05991e+06,1.2885e+06,2.32453e+06,2.22186e+06,2.24357e+06,2.3344e+06,2.43199e+06,1.79455e+06,1.76948e+06,2.30819e+06,2.36686e+06,2.55604e+06,2.46974e+06,2.4106e+06,2.52724e+06,2.42217e+06,1.8221e+06,2.35771e+06,1.97492e+06,2.10185e+06,1.99253e+06,2.0049e+06,2.0278e+06,1.45856e+06,1.45665e+06,2.60346e+06,2.29065e+06,2.36054e+06,2.25301e+06,2.14007e+06,2.201e+06,2.13652e+06,1.82436e+06,1.8221e+06,1.78206e+06,2.33849e+06,2.29076e+06,1.94858e+06,1.94059e+06,1.9122e+06,1.73801e+06,2.05507e+06,2.35866e+06,2.20911e+06,2.21301e+06,1.54406e+06,2.48296e+06,2.36253e+06,2.34503e+06,1.84382e+06,1.7372e+06,2.00491e+06,2.2582e+06,2.24071e+06,2.18294e+06,2.21226e+06,2.99056e+06,3.04048e+06,2.53055e+06,2.50943e+06,2.15319e+06,2.64953e+06,1.60391e+06,2.45061e+06,2.37498e+06,2.32725e+06,2.33562e+06,2.29023e+06,1.80879e+06,1.74094e+06,1.79337e+06,1.68076e+06,1.80449e+06,1.92142e+06,1.74858e+06,2.46282e+06,2.45304e+06,2.47335e+06,2.39321e+06,2.29868e+06,2.27699e+06,2.29823e+06,2.55771e+06,4.3299e+06,2.06546e+06,2.40656e+06,2.30998e+06,1.80661e+06,2.17818e+06,1.88318e+06,2.43898e+06,3.42769e+06,2.57702e+06,2.6724e+06,2.50333e+06,2.40684e+06,2.64896e+06,2.64462e+06,2.6971e+06,2.38738e+06,2.22871e+06,2.28952e+06,2.28571e+06,2.1806e+06,2.54268e+06,2.52423e+06,2.41322e+06,1.437e+06,2.11414e+06,2.09219e+06,2.45646e+06,1.88979e+06,2.27742e+06,2.28726e+06,1.87407e+06,2.29685e+06,2.307e+06,2.27836e+06,2.22717e+06,3.61018e+06,2.02001e+06,1.95668e+06,2.46336e+06,2.54842e+06,2.00822e+06,2.03394e+06,2.08457e+06,1.92862e+06,2.13197e+06,2.10807e+06,2.13561e+06,2.04113e+06,2.11311e+06,2.15224e+06,2.03767e+06,1.97647e+06,1.90931e+06,2.34086e+06,1.85341e+06,1.86578e+06,1.88093e+06,1.77949e+06,1.83196e+06,2.4096e+06,1.73625e+06,2.44208e+06,2.35315e+06,2.34595e+06,2.32485e+06,2.34776e+06,1.37122e+06,1.88622e+06,1.87059e+06,1.87994e+06,1.71016e+06,1.67424e+06,1.72131e+06,2.00784e+06,1.85701e+06,2.57338e+06,1.90807e+06,1.32249e+06,1.288e+06,1.28287e+06,1.45332e+06,1.43445e+06,1.4294e+06,1.448e+06,1.40898e+06,1.35267e+06,1.62246e+06,1.61809e+06,1.61118e+06,1.59252e+06,2.56696e+06,2.37582e+06,2.29659e+06,2.40905e+06,1.41008e+06,2.20166e+06,2.15017e+06,2.23319e+06,2.50709e+06,1.96844e+06,1.61531e+06,1.39201e+06,2.51017e+06,2.50927e+06,2.38022e+06,1.9736e+06,2.00217e+06,1.98873e+06,1.85641e+06,1.92341e+06,1.78708e+06,1.70392e+06,1.88334e+06,977458,2.42018e+06,2.3664e+06,4.06926e+06,2.4584e+06,2.22246e+06,1.9758e+06,2.39727e+06,2.40655e+06,2.30817e+06,2.29432e+06,2.07982e+06,2.49279e+06,2.38014e+06,2.04522e+06,2.35823e+06,2.24615e+06,2.31818e+06,2.25861e+06,2.33768e+06,2.00916e+06,1.94227e+06,2.01184e+06,1.89774e+06,1.81929e+06,1.84546e+06,2.29566e+06,1.50968e+06,1.50771e+06,2.39637e+06,1.40549e+06,1.38652e+06,1.35011e+06,2.14421e+06,1.27455e+06,1.24826e+06,1.27807e+06,1.36428e+06,3.75061e+06,3.36811e+06,1.15794e+06,2.38751e+06,2.40496e+06,1.70539e+06,1.7975e+06,2.46882e+06,2.39383e+06,2.38782e+06,2.41116e+06,2.42435e+06,2.20613e+06,2.20424e+06,2.16758e+06,2.38004e+06,2.32754e+06,2.35222e+06,1.94836e+06,2.01901e+06,1.98602e+06,1.96179e+06,2.30692e+06,2.30601e+06,2.25288e+06,2.10333e+06,1.86188e+06,1.76143e+06,2.39543e+06,1.64842e+06,1.64875e+06,1.63984e+06,1.60516e+06,1.83107e+06,2.07e+06,1.99407e+06,1.97805e+06,1.97326e+06,1.93162e+06,2.24958e+06,2.08025e+06,1.26624e+06,1.24972e+06,2.11351e+06,2.2001e+06,2.16507e+06,2.14093e+06,2.4206e+06,2.37207e+06,2.35864e+06,2.33729e+06,2.149e+06,2.55095e+06,2.48392e+06,2.46518e+06,2.4607e+06,2.37438e+06,1.25076e+06,2.33966e+06,1.62739e+06,1.62799e+06,1.55204e+06,1.84671e+06,2.33327e+06,2.33442e+06,2.24256e+06,2.17716e+06,2.20224e+06,2.19637e+06,2.21726e+06,2.10156e+06,2.14103e+06,2.40785e+06,2.25295e+06,2.2366e+06,2.17218e+06,2.20472e+06,2.20147e+06,1.96743e+06,1.87408e+06,1.84698e+06,1.68848e+06,2.25784e+06,2.26986e+06", "agent_steps": "599.982,599.982,27.4104,128.131,461.21,599.982,155.222,199.557,398.983,568.918,32.9974,379.65,28.885,100.024,166.691,233.357,599.982,100.024,166.691,233.357,599.982,21.4385,58.9578,98.2467,137.535,176.824,216.113,353.616,19.9229,54.2638,569.115,30.933,87.3595,599.982,552.075,599.982,166.691,531.595,599.917,599.982,25.0348,599.982,599.982,599.982,162.202,583.729,599.982,33.1448,555.975,246.956,493.847,24.6415,27.9675,471.106,35.1273,165.675,231.866,595.984,599.917,22.8065,599.982,539.361,166.724,233.374,599.982,74.3178,267.125,35.1191,599.917,35.1273,233.357,599.982,193.954,498.598,88.1132,528.417,233.357,599.982,35.1273,100.024,166.691,599.982,524.96,526.057,599.982,166.724,599.982,166.724,233.374,599.982,166.691,233.357,17.9241,290.292,35.1273,233.357,34.1279,599.982,599.982,27.4596,128.057,460.587,35.1273,233.357,150.602,210.764,541.721,599.982,599.982,444.367,233.357,599.982,501.285,15.5976,206.602,247.857,599.982,230.818,18.2845,49.5124,115.474,247.398,296.845,18.5795,14.7128,134.267,483.262,447.545,510.788,35.1191,35.1601,100.073,166.724,233.374,599.982,35.1273,100.024,166.691,233.357,599.982,398.328,132.448,100.024,166.691,599.982,35.1273,166.691,233.357,599.982,24.3958,16.8264,458.293,599.982,575.865,599.982,599.982,599.982,593.691,78.2172,211.583,544.014,14.4507,33.8493,366.69,500.023,599.982,580.125,34.3736,97.7142,162.791,585.892,166.724,233.374,599.982,11.1411,166.724,599.982,574.423,34.1115,91.5538,152.568,548.995,599.982,164.97,230.949,593.838,15.0077,599.917,577.372,207.602,533.758,28.033,78.7415,131.203,472.22,199.459,512.754,33.62,95.486,159.089,572.522,165.773,232.063,596.574,599.982,35.1601,100.073,166.724,233.374,599.982,599.032,147.259,28.5409,80.2488,133.726,240.681,481.296,599.785,35.1601,166.724,599.982,32.5714,92.3402,153.879,599.982,599.982,599.982,599.982,87.3595,203.751,523.502,34.0787,96.8294,161.317,225.804,580.452,93.995,96.2068,160.236,224.264,576.324,599.982,529.727,35.1273,599.982,599.917,35.1191,599.998,194.953,141.156,166.691,599.982,599.917,166.691,233.357,599.982,93.5199,155.812,560.726,31.7194,87.8838,204.8,526.254,575.013,599.785,29.6059,83.4601,26.6076,99.5983,35.1273,599.982,390.136,100.024,166.691,599.982,599.982,20.7913,57.0327,599.982,27.1811,76.1856,599.982,599.982,599.982,24.9364,416.629,599.982,35.1273,166.691,599.982,459.964,95.2566,571.212,534.118,31.6539,89.5222,208.667,32.9646,35.1928,599.917,35.0945,166.396,19.0054,77.0703,599.785,166.691,599.982,599.982,595.919,35.1273,100.024,166.691,233.357,599.982,166.724,233.374,599.982,465.895,91.7832,152.961,599.982,88.2442,205.881,529.302,86.1143,200.868,516.358,599.982,35.1273,599.982,599.982,91.4555,152.404,213.352,548.405,166.724,28.4099,79.8556,133.038,186.221,478.74,33.7838,575.209,33.9476,96.4035,15.5238,35.1191,100.008,233.341,24.2811,67.4857,112.443,202.359,210.272,35.1273,100.024,166.691,233.357,599.982,599.785,166.691,32.0471,90.7018,211.55,599.917,33.8903,96.3133,160.506,90.6691,151.06,211.452,543.621,207.602,533.725,34.3736,97.7142,162.791,227.869,585.761,599.982,599.982,166.724,599.982,485.949,196.772,505.807", "uptime": "285.144,345.002,12.6233,58.7747,212.213,294.637,63.8361,82.2631,165.411,303.062,17.536,175.919,12.1259,53.9134,91.8737,128.437,334.043,38.9053,65.2764,91.7553,241.203,8.80798,24.8182,41.7975,58.8283,75.88,92.9807,155.923,10.5473,29.308,260.399,21.8004,62.5401,249.31,245.396,289.98,68.3245,236.46,357.066,293.863,4.6203,259.704,244.355,318.073,86.6758,319.928,280.26,14.0631,211.183,117.072,230.12,7.28267,11.9563,211.433,14.8981,111.136,155.878,410.645,385.565,6.80849,310.32,226.705,90.4979,126.363,322.842,36.3044,132.269,17.2409,421.118,15.0486,104.16,268.546,81.9889,211.639,48.8341,297.762,102.067,261.117,13.6356,39.5553,67.1539,248.831,205.283,291.119,256.893,87.4321,278.34,82.8601,116.36,298.104,111.4,157.2,6.83407,121.732,14.7745,102.807,16.2413,272.653,281.941,15.326,70.4471,263.571,15.04,101.455,76.2308,107.342,278.687,342.207,283.112,189.222,106.861,274.974,264.472,6.46752,86.5797,104.046,322.921,134.905,9.24678,23.8858,53.4561,116.509,138.87,6.72099,5.79347,52.0995,190.722,206.165,202.698,22.2519,14.5417,41.5916,70.1271,98.7406,259.071,19.5758,57.0105,94.6237,133.68,342.33,205.349,81.3914,39.9801,67.1226,243.398,14.6857,71.4387,100.737,262.915,9.52473,4.37058,189.164,241.898,252.832,325.089,284.323,322.8,247.581,21.7303,86.3787,215.51,5.94776,14.1002,137.943,188.368,226.18,252.783,18.8607,46.5613,75.012,268.188,64.812,91.1616,236.395,8.03317,85.5444,292.745,229.151,18.069,40.6037,67.2405,249.433,268.568,70.4781,99.3234,259.098,4.63882,298.311,305.283,85.0563,217.175,14.2224,38.945,65.4707,240.086,93.543,242.986,15.5365,45.492,76.3531,267.378,80.6311,114.533,308.059,252.661,19.0771,54.3404,89.9312,126.354,327.856,245.769,84.2018,11.7997,33.6234,56.4051,102.237,206.449,437.315,18.8041,89.068,317.435,19.2185,54.4057,91.3144,294.363,337.401,239.131,289.437,70.2873,158.761,422.614,23.3365,66.9573,111.979,156.935,408.986,67.7715,58.658,98.1905,137.853,359.32,236.713,220.117,15.7646,267.422,420.288,15.864,280.549,85.4888,55.7685,86.8172,322.251,398.679,65.1517,91.7236,242.148,50.5081,81.9365,288.568,16.6032,48.8381,112.477,292.07,295.442,608.194,12.105,34.7583,6.43309,39.841,15.5927,287.885,166.635,41.5025,70.1024,257.668,283.207,8.21049,23.2648,224.527,11.2746,32.925,263.974,271.878,258.311,12.7314,229.91,293.228,18.5449,89.9802,334.283,200.037,65.4549,383.675,216.342,22.8057,64.4154,153.17,15.6276,27.4892,480.089,30.11,127.365,5.11439,21.9804,478.556,68.7045,249.078,359.799,323.05,14.07,40.998,68.9907,96.7978,253.002,74.9443,105.139,274.175,198.433,39.2425,65.1901,313.194,42.432,101.185,262.269,37.2437,86.7191,226.979,289.939,18.6811,333.794,246.863,53.6592,92.2485,129.595,338.385,90.8027,13.5207,39.1541,65.9438,92.8734,243.471,14.7867,267.064,26.6439,76.6049,7.37197,15.9449,45.9755,107.994,9.99217,28.1187,47.1247,85.4632,96.9944,13.7465,39.677,66.8036,93.8937,246.104,480.993,70.2062,19.9434,56.0674,131.306,319.838,14.8427,41.5593,69.4119,40.5555,69.0124,96.4816,247.968,100.173,255.17,14.1783,41.6842,70.7319,100.125,262.556,293.663,247.388,90.1327,329.089,291.879,88.1216,224.701", "epoch": "9155,18310,1673,7820.5,28150,9155,2368.5,3045,6088,8681,1007,5793,881.5,3052.5,5087,7121.5,18310,3052.5,5087,7121.5,18310,1308.5,3598.5,5996.5,8394.5,10792.5,13190.5,21583,152,414,17368,236,666.5,9155,16848,18310,5087,32446,4577,9155,95.5,9155,18310,9155,2475,8907,9155,1011.5,16967,7536.5,15071,376,853.5,14377,1072,1264,1769,4547,4577,174,18310,4115,2544,3561,9155,567,2038,2143.5,4577,1072,7121.5,18310,2959.5,7608,1344.5,8063,7121.5,18310,1072,3052.5,5087,18310,32041,8027,9155,2544,9155,2544,3561,9155,5087,7121.5,547,8859,1072,7121.5,1041.5,18310,9155,209.5,977,3514,1072,7121.5,1149,1608,4133,9155,9155,13561,7121.5,18310,7649,238,3152.5,3782,9155,1761,558,1511,3524,7550,9059,283.5,224.5,4097.5,14748,6829,7794,2143.5,536.5,1527,2544,3561,9155,1072,3052.5,5087,7121.5,18310,12156,1010.5,3052.5,5087,18310,1072,5087,7121.5,18310,744.5,513.5,6993,18310,8787,9155,18310,9155,18118,2387,6457,16602,220.5,1033,11190.5,15259.5,18310,8852,524.5,1491,2484,8940,2544,3561,9155,85,2544,9155,17530,520.5,1397,2328,8377,18310,10069,14096,36245,458,4577,8810,6335.5,16289,855.5,2403,4004,14411,3043.5,7824,513,1457,2427.5,8736,2529.5,3541,9103,9155,536.5,1527,2544,3561,9155,18281,4494,435.5,1224.5,2040.5,3672.5,7344,2288,536.5,2544,9155,497,1409,2348,18310,9155,9155,9155,666.5,1554.5,3994,520,1477.5,2461.5,3445.5,8857,2868.5,734,1222.5,1711,4397,9155,16166,1072,18310,4577,2143.5,36621,5949.5,8615.5,5087,18310,4577,5087,7121.5,18310,1427,2377.5,8556,968,670.5,1562.5,4015,4387,2288,903.5,2547,406,3039.5,1072,18310,5953,3052.5,5087,18310,9155,634.5,1740.5,9155,1659,4650,9155,18310,9155,1522,25429,9155,1072,5087,18310,14037,1453.5,8716,16300,241.5,683,1592,503,268.5,4577,535.5,2539,145,588,2288,5087,18310,9155,18186,1072,3052.5,5087,7121.5,18310,2544,3561,9155,7109,2801,4668,9155,2693,6283,16153,1314,3065,7879,9155,1072,18310,9155,1395.5,2325.5,3255.5,8368,2544,433.5,1218.5,2030,2841.5,7305,515.5,8777,259,735.5,1895,2143.5,6104,14242,741,2059.5,3431.5,6175.5,3208.5,1072,3052.5,5087,7121.5,18310,2288,5087,244.5,692,1614,4577,2068.5,5878.5,9796.5,1383.5,2305,3226.5,8295,6335.5,16288,524.5,1491,2484,3477,8938,9155,18310,2544,9155,14830,3002.5,7718", "perf/rollout": "0.023752,0.0121112,0.00571839,0.0058735,0.00593925,0.0259762,0.0228274,0.0226214,0.0224569,0.030997,0.0133736,0.0260043,0.0111919,0.0132664,0.0124681,0.0124868,0.0125794,0.0110788,0.0111688,0.0111887,0.0114982,0.00595574,0.0061593,0.00620145,0.006214,0.0062264,0.00624294,0.00630307,0.0506076,0.0534093,0.011961,0.0531854,0.0547052,0.0235052,0.0122411,0.0131969,0.0116195,0.00596571,0.0537417,0.0253212,0.040244,0.0248895,0.0117362,0.0252707,0.0284374,0.0289881,0.0267816,0.0115351,0.0114207,0.0126294,0.0125139,0.0154945,0.0120157,0.012532,0.0112853,0.0493811,0.0501997,0.0490737,0.0497429,0.0347945,0.0135844,0.0461819,0.0262233,0.0253314,0.0256205,0.0479271,0.0465138,0.00644154,0.0634322,0.0119263,0.0125511,0.0124094,0.0235268,0.0223558,0.026484,0.0269847,0.0128493,0.0124347,0.0109009,0.0113307,0.011649,0.0110202,0.00610447,0.0289917,0.0224247,0.0259095,0.0245476,0.0246673,0.0244669,0.0240834,0.0169857,0.0169948,0.0116338,0.0133126,0.0120729,0.0127152,0.0126005,0.0126922,0.0239401,0.0454424,0.0453154,0.0452812,0.0114498,0.0117186,0.0497224,0.0499558,0.0509782,0.0281129,0.0251758,0.0121028,0.0121743,0.0121584,0.034128,0.0238969,0.0252258,0.0254133,0.0259297,0.047807,0.0137385,0.011833,0.0119143,0.0122925,0.0120983,0.0210957,0.0198224,0.0119708,0.0120721,0.0255194,0.0224895,0.00691114,0.0215345,0.0223475,0.0228924,0.0228124,0.0233495,0.0127313,0.0134413,0.0127899,0.0141397,0.0126903,0.0142305,0.0565441,0.0115114,0.0115553,0.0114458,0.0112308,0.0115712,0.0116918,0.0115387,0.0110557,0.00742676,0.029165,0.0121987,0.0238864,0.0289543,0.0127411,0.0248542,0.0124393,0.00822665,0.0117395,0.0112722,0.0228952,0.0110586,0.0113697,0.01139,0.0111601,0.0241771,0.0248299,0.023492,0.0235268,0.024761,0.0224761,0.0226552,0.0238647,0.050867,0.0243648,0.0246465,0.0114975,0.0241611,0.0237699,0.0236156,0.0298123,0.0120728,0.00631688,0.00661466,0.00656414,0.00887541,0.0452836,0.0240154,0.0118622,0.0114033,0.013925,0.0137545,0.0132914,0.0145175,0.0264579,0.0267015,0.0263561,0.0277124,0.0265648,0.0259383,0.0228697,0.0251118,0.0243497,0.0234926,0.0260032,0.0256274,0.0252399,0.0273243,0.0260735,0.0122006,0.0113938,0.021812,0.0226268,0.0226926,0.0229133,0.0224886,0.10065,0.0257978,0.0260653,0.0258193,0.0293522,0.0302082,0.0291624,0.0141227,0.0235629,0.0221348,0.0288904,0.0561657,0.0586831,0.0581951,0.02412,0.0247003,0.0248029,0.0242473,0.0254941,0.0185669,0.0504048,0.0506946,0.0502238,0.0503209,0.0222354,0.0123672,0.0131683,0.0124278,0.0701053,0.00631973,0.00649619,0.0119984,0.00586464,0.0123728,0.0159755,0.0650909,0.0112698,0.0112732,0.0119729,0.0260349,0.0255076,0.0257249,0.0150715,0.0509948,0.056268,0.0594554,0.0520349,0.114471,0.0111073,0.0113891,0.0153402,0.0115314,0.0120592,0.013813,0.0248101,0.0109658,0.011539,0.0116155,0.0258448,0.011659,0.0122579,0.0297828,0.0060779,0.00639296,0.024837,0.0123193,0.0235412,0.00701124,0.00728559,0.0270581,0.0119242,0.0126987,0.0123324,0.0124738,0.026114,0.0261168,0.0122802,0.0510582,0.0524932,0.0549039,0.0222822,0.0563693,0.0583432,0.0310749,0.0270288,0.0285146,0.0323957,0.126231,0.0123068,0.0122037,0.0232751,0.0152411,0.0114916,0.0118824,0.0119187,0.0117981,0.0116885,0.0242285,0.024257,0.0246871,0.0241539,0.0127364,0.01255,0.0241485,0.0140485,0.0143262,0.0145092,0.0224863,0.0224286,0.0231245,0.0258093,0.0133399,0.0142875,0.0230806,0.0348029,0.0336347,0.0333046,0.034153,0.0235902,0.0250317,0.0261977,0.026453,0.0265336,0.0271895,0.024321,0.0266368,0.0519209,0.05313,0.00302028,0.00615899,0.00625994,0.00633849,0.011244,0.011512,0.0115771,0.0117228,0.0230444,0.0109323,0.011255,0.0113397,0.0113511,0.0118251,0.0982773,0.0114874,0.0478995,0.0478518,0.0485893,0.0502641,0.00601671,0.00598031,0.0063119,0.0250348,0.0238696,0.0239491,0.0236404,0.013025,0.0126691,0.0219045,0.02372,0.0239871,0.024975,0.0243542,0.0237987,0.015301,0.0277789,0.0282454,0.0146525,0.0257251,0.025604", "perf/eval_gpu": "0.00842699,0.00476093,0.00216373,0.00212752,0.00209911,0.0101831,0.00826514,0.00817102,0.00807089,0.0108289,0.00459477,0.0111437,0.0042145,0.00543689,0.00481361,0.00481298,0.00482818,0.00407589,0.00407272,0.00406643,0.004096,0.00229833,0.00227984,0.00227778,0.00227128,0.00226681,0.00226871,0.00225148,0.0191647,0.0192453,0.00475062,0.0201173,0.0200943,0.00843551,0.00506411,0.00398653,0.00416946,0.0020893,0.0167661,0.00946785,0.00857942,0.00987827,0.00420529,0.0094518,0.0128701,0.0128596,0.00824238,0.00426394,0.00403672,0.00472887,0.00477761,0.00414412,0.00493881,0.00490205,0.00413985,0.0189716,0.0190475,0.0190406,0.0187884,0.00798651,0.00407444,0.0165732,0.0103812,0.0103956,0.0103314,0.0166138,0.0161183,0.00225192,0.0212557,0.00494584,0.0048992,0.00489774,0.00862376,0.00806737,0.0121513,0.012067,0.00453768,0.0046439,0.00409648,0.00408754,0.00416732,0.00401064,0.00210963,0.0139876,0.00815209,0.00887153,0.00887824,0.00894988,0.00892017,0.00879271,0.00478383,0.00477984,0.00398966,0.00407354,0.00521819,0.00522315,0.00506827,0.0046811,0.0088849,0.0184559,0.0180261,0.0177695,0.00430707,0.00426539,0.0193033,0.0192743,0.0189927,0.00964345,0.00905014,0.00463052,0.00447012,0.00445277,0.00882428,0.0104918,0.0101738,0.0101656,0.0105924,0.0169787,0.00452318,0.00430504,0.00426624,0.00430348,0.00423742,0.0061847,0.00707567,0.00417143,0.00422054,0.00815835,0.00814671,0.00288445,0.00806939,0.00812363,0.00823993,0.00820724,0.00827362,0.0049077,0.00486936,0.00484449,0.00488645,0.00473001,0.00454984,0.020293,0.0041699,0.00416904,0.00408104,0.00419094,0.00420263,0.00421764,0.00416034,0.00413285,0.00323619,0.00988288,0.00432443,0.00862462,0.00968001,0.00468021,0.00981299,0.0039017,0.00206773,0.00415102,0.00398416,0.0106671,0.00419938,0.00407203,0.00407309,0.00406211,0.00818822,0.0111892,0.00975622,0.00973861,0.0100001,0.00824137,0.00822654,0.00850215,0.0262961,0.00989317,0.00974753,0.00416049,0.00965982,0.00974854,0.00971938,0.0101675,0.00450085,0.00245963,0.00268232,0.00246657,0.0032599,0.0163527,0.0100785,0.00422213,0.00406498,0.00542246,0.00529992,0.00525888,0.00529924,0.00815094,0.0081157,0.00840392,0.00838703,0.00823743,0.00797699,0.00858196,0.010342,0.00876368,0.00823535,0.00971943,0.00960758,0.00958918,0.00971343,0.00969856,0.00451787,0.00425686,0.00817441,0.00814176,0.00813881,0.00813218,0.00795908,0.0378758,0.011447,0.0113713,0.0111645,0.0115698,0.0115474,0.0114972,0.00467667,0.00931099,0.00779672,0.0119791,0.028758,0.0291464,0.0292598,0.0097661,0.00970256,0.00973495,0.00975349,0.00968838,0.0051632,0.0190995,0.0192532,0.0190707,0.0190629,0.00800017,0.0045157,0.00532388,0.00524318,0.019112,0.00279105,0.00275342,0.00470666,0.00208875,0.00517037,0.00549409,0.0296084,0.00406032,0.00403377,0.00414061,0.00985696,0.009733,0.00972155,0.00397883,0.0215034,0.0208655,0.0207671,0.0196018,0.0400505,0.00416345,0.00415172,0.00429033,0.00420385,0.00397315,0.00415808,0.0102729,0.00435092,0.00446628,0.00436753,0.00792889,0.0039561,0.0039452,0.00860878,0.00202009,0.0020143,0.00895786,0.00481767,0.00840673,0.0025557,0.00253886,0.0112733,0.00509443,0.0051355,0.00503523,0.00397636,0.0106009,0.010749,0.00444531,0.0219508,0.0218801,0.0223305,0.00902807,0.0211273,0.0205724,0.0147847,0.0117559,0.00808539,0.00801857,0.0404372,0.00455776,0.00464181,0.00856274,0.00533102,0.00418316,0.00417604,0.0041913,0.00412401,0.00403927,0.00901274,0.00895681,0.00900102,0.0083497,0.00461671,0.00459447,0.00925868,0.00471827,0.00465088,0.00478077,0.00832356,0.00827737,0.00834882,0.00777918,0.00484084,0.00490454,0.00805325,0.0104634,0.0088807,0.0080995,0.00802774,0.00903275,0.00841151,0.00824828,0.00824423,0.00824428,0.00823235,0.00789067,0.00802509,0.0183544,0.0180812,0.00133394,0.00242412,0.00237794,0.00236886,0.00431168,0.00428346,0.00427503,0.00428288,0.00847696,0.00408479,0.00405331,0.00409243,0.00407686,0.00412597,0.0372788,0.00412911,0.0210945,0.0207403,0.0211875,0.0193266,0.00214092,0.00213609,0.00215176,0.00971723,0.00871375,0.00870076,0.00849162,0.00465522,0.00455326,0.00810779,0.00843994,0.00846038,0.00847908,0.00847713,0.00842025,0.0043627,0.00894107,0.00922558,0.00526507,0.010192,0.0101755", "perf/eval_env": "0.0110923,0.00463337,0.00237175,0.0026226,0.00270937,0.0113151,0.0103118,0.0103785,0.0106366,0.0107567,0.00661831,0.00901639,0.00482152,0.0053028,0.00534202,0.005392,0.00564082,0.0050545,0.00515137,0.00519258,0.00548689,0.00243248,0.0026644,0.00270819,0.00273548,0.00275556,0.0027704,0.00282978,0.0237333,0.0264785,0.00415038,0.0258392,0.0273886,0.0108048,0.00437677,0.00745775,0.0052373,0.00275502,0.0297192,0.0115889,0.0266635,0.0092752,0.0054538,0.0113352,0.011056,0.0116325,0.0147723,0.00481721,0.00535956,0.00557276,0.0057399,0.00954111,0.00329973,0.00384438,0.00484191,0.0217638,0.0219508,0.021915,0.0223226,0.0237262,0.0076225,0.0215292,0.0109699,0.0107365,0.0111179,0.0211048,0.0222661,0.00223583,0.0207853,0.00473085,0.00537449,0.00554532,0.0104711,0.010825,0.00863219,0.00921737,0.00569359,0.00560012,0.00474947,0.00517943,0.00527889,0.0050991,0.00282818,0.00890541,0.0102177,0.0112943,0.0114332,0.0109488,0.0109712,0.0112677,0.0109128,0.010926,0.0057334,0.00726396,0.00485106,0.00543961,0.00348465,0.00572539,0.0108523,0.0154618,0.0166671,0.0175607,0.00494846,0.0053363,0.0210617,0.021382,0.0231161,0.0148199,0.011518,0.00438127,0.00558172,0.00553221,0.0179327,0.00685166,0.0089211,0.00918907,0.00911016,0.0214757,0.00531722,0.0051446,0.0053945,0.0055063,0.00562174,0.0100206,0.00739031,0.00538292,0.00537906,0.013543,0.0106216,0.00257427,0.00942417,0.00993644,0.0100276,0.0100882,0.010283,0.00521591,0.00571954,0.00557848,0.00600232,0.00572122,0.00472827,0.0158973,0.00512702,0.00518943,0.00520482,0.00479513,0.0051156,0.00522793,0.00522019,0.00466441,0.00224144,0.0108387,0.00562946,0.0107988,0.0150885,0.00578691,0.0107437,0.00687004,0.00525636,0.00536321,0.00536544,0.00792756,0.00477472,0.00532192,0.00534411,0.00527745,0.0114024,0.00817,0.00854624,0.008597,0.00904732,0.0100515,0.0102689,0.0108198,0.0111834,0.00877911,0.00921157,0.00534555,0.00984398,0.0086267,0.00869409,0.00991669,0.00567274,0.00263472,0.00267481,0.00272149,0.00260905,0.0208151,0.00871316,0.0054582,0.00546451,0.0043316,0.00461442,0.00452996,0.00497442,0.0144309,0.0145592,0.0131794,0.0144948,0.0143946,0.0145213,0.00992692,0.010055,0.0108418,0.0112127,0.0105673,0.0110627,0.0110974,0.0115571,0.0114815,0.00532611,0.00507785,0.00931141,0.0101401,0.0102286,0.0104871,0.0106875,0.0456452,0.00690362,0.00734393,0.00759006,0.00787897,0.00888831,0.00866119,0.00736113,0.00865796,0.0108251,0.00972403,0.0146553,0.0152286,0.0153817,0.0097113,0.0103861,0.0104649,0.0106186,0.0112517,0.011225,0.0216502,0.0217808,0.0220188,0.022425,0.0104966,0.00552758,0.00436287,0.00436631,0.0459837,0.00208881,0.00230436,0.00416655,0.00264935,0.00444559,0.00543624,0.0224966,0.00510528,0.00518886,0.00562572,0.0107524,0.0108113,0.0110504,0.00959225,0.0171299,0.0195707,0.0212669,0.0222917,0.059876,0.0047886,0.00510406,0.00867303,0.00510613,0.00623507,0.00749849,0.00890962,0.00410704,0.004276,0.00453655,0.0143391,0.00598437,0.00658651,0.0116712,0.00314112,0.00341968,0.0113191,0.0055094,0.0109656,0.00333694,0.00380096,0.0113806,0.0040999,0.00448466,0.00456663,0.0066508,0.00896542,0.00902213,0.00556227,0.0164018,0.0175699,0.0177292,0.00788486,0.0274745,0.030628,0.00698517,0.00732602,0.0170914,0.0210411,0.0404103,0.00535477,0.00519633,0.0105187,0.00796934,0.00499243,0.00544607,0.00541411,0.00545293,0.00575794,0.0104883,0.0105541,0.0110928,0.0112738,0.0054224,0.00543849,0.0108168,0.00733848,0.00749,0.00733156,0.0100741,0.0102622,0.0106371,0.014838,0.00664291,0.0074413,0.0108783,0.0211769,0.0215741,0.0220366,0.0231036,0.0103137,0.0128458,0.0141152,0.0143833,0.014466,0.0151656,0.0128754,0.0148322,0.0260526,0.0273432,0.000904437,0.00249193,0.00267382,0.00277354,0.0046326,0.00496857,0.00505983,0.00515149,0.0104302,0.00484139,0.00521614,0.00522107,0.00528797,0.00556252,0.043934,0.00522535,0.0134527,0.0141259,0.0141302,0.0217249,0.00254381,0.00267165,0.00275358,0.0104899,0.0106715,0.0107783,0.0111895,0.00555461,0.00580303,0.00978322,0.0105165,0.0107044,0.0109852,0.011106,0.011064,0.00618646,0.0147315,0.0151244,0.00753441,0.0112462,0.0114599", "perf/train_misc": "0.000423936,0.000278528,0.000107587,0.000107947,0.000104448,0.000267456,0.000349198,0.00034947,0.000347296,0.000269312,0.000138846,0.000120576,0.000178218,0.000226593,0.000226128,0.000225284,0.000221504,0.000135339,0.000135437,0.000135413,0.00013312,7.33582e-05,7.39311e-05,7.41128e-05,7.38437e-05,7.39979e-05,7.40201e-05,7.3728e-05,0.0011709,0.00117158,0.000136192,0.00122912,0.00122873,0.000272384,8.4992e-05,0.00013824,0.000176519,0.000104512,0.000955296,0.000271136,0.000615657,0.000118784,8.992e-05,0.000351296,0.000122952,0.000119808,0.000268288,0.000222514,8.3968e-05,8.6923e-05,0.000106464,0.000304537,0.000144269,0.000147456,0.000220353,0.00135995,0.00135962,0.00136381,0.00122346,0.000472341,0.000227136,0.000573504,0.000411965,0.000412229,0.000415808,0.00155215,0.00155955,0.000137598,0.0013271,0.00013558,0.000136707,0.000137408,0.000273896,0.000268288,0.000270778,0.000273408,8.78622e-05,8.7808e-05,0.000177014,0.000177557,0.000179085,0.000175424,7.5776e-05,0.000119776,0.00042176,0.000415372,0.000342208,0.000414105,0.000413747,0.0004096,0.000229143,0.000228887,8.70643e-05,9.1104e-05,8.59477e-05,8.62096e-05,0.000143271,9.1008e-05,0.000347136,0.0019755,0.00197932,0.00200618,0.000183174,0.000183327,0.000473752,0.000475209,0.000472064,0.0003512,0.000350976,0.00013824,0.000137739,0.00013824,0.00063696,0.000119355,0.000119461,0.000118784,0.000339968,0.00206223,0.000136723,0.00013507,0.000135225,0.000137106,0.000134144,0.000103939,0.00015675,8.60565e-05,8.8256e-05,0.000216064,0.00019648,0.00010871,0.000412604,0.00041297,0.000413175,0.000413047,0.000411616,0.000229084,0.00023122,0.00022916,0.000230577,0.000228224,0.000227328,0.00122498,0.000136996,0.000137042,0.000137056,0.000221615,0.000226238,0.000224083,0.00021728,0.000132638,0,0.000246784,8.7808e-05,0.000269312,0.000273408,8.9984e-05,0.000344064,8.912e-05,7.84326e-05,8.69651e-05,8.2848e-05,0.000120295,0.000178792,8.75349e-05,8.74261e-05,8.5696e-05,0.000329728,0.00027361,0.000273467,0.000273475,0.000273312,0.000274162,0.000274139,0.000272224,0.000725597,0.00033859,0.000334848,0.00013824,0.000486573,0.000269303,0.00026914,0.000283648,8.4768e-05,7.42568e-05,7.59148e-05,7.68e-05,0,0.00107008,0.000339968,8.65127e-05,8.4992e-05,0.000172656,0.000172324,0.000173548,0.00017408,0.000351745,0.000354528,0.000269222,0.000268894,0.000268629,0.000267456,0.00069683,0.000705364,0.000694272,0.000269248,0.000345429,0.000345179,0.000345234,0.000345777,0.000351232,8.704e-05,0.000273325,0.000412641,0.000412387,0.000412484,0.000412333,0.000415744,0.00391578,0.000273126,0.00027321,0.000279552,0.000276396,0.000273907,0.000276193,8.4992e-05,0.000564,0.0002696,0.000117984,0.000473553,0.000476204,0.000472064,0.000924806,0.000924915,0.000924909,0.000926027,0.000931936,0.000138025,0.0010804,0.00107951,0.00108078,0.0010712,0.000271456,9.1136e-05,8.79092e-05,8.896e-05,0.000954368,7.68171e-05,7.5776e-05,0.000135483,7.44414e-05,0.000136267,0.000139168,0.000724928,0.000132513,0.00013168,0.000134208,0.00027044,0.000270212,0.000269312,0.000136804,0.000469573,0.00046772,0.00046592,0.000473088,0.00533094,0.000220932,0.000220971,9.93125e-05,0.000137433,0.000134533,0.000136192,0.000118784,0.000129527,0.000132052,0.000135104,0.000550208,0.000139407,0.000139338,0.000200704,7.48203e-05,7.49172e-05,0.000196608,8.496e-05,0.000269312,8.51526e-05,7.2704e-05,0.000119808,0.000222459,0.000223561,0.000224256,0.00014016,0.000768618,0.000784384,9.4048e-05,0.00156786,0.00156745,0.00156829,0.000626435,0.00119792,0.00120422,0.000807769,0.00080739,0.000395092,0.000395266,0.0047647,8.62734e-05,8.9952e-05,0.000683008,8.9952e-05,0.000136049,0.000135683,0.000136807,0.000136331,0.000138208,0.000337827,0.000337818,0.000335456,0.000343008,8.98936e-05,8.99013e-05,0.000340992,9.02621e-05,9.05209e-05,8.8064e-05,0.000344507,0.000344471,0.000346112,0.000416768,0.0001377,0.000139264,0.000346112,0.000359474,0.00034961,0.000346569,0.000347136,0.000707961,0.000352241,0.000352511,0.000352312,0.000352242,0.000352256,0.000481657,0.000484352,0.00230899,0.0023116,6.75641e-05,7.40182e-05,7.50111e-05,7.52013e-05,0.000208357,0.000208548,0.00020856,0.000208448,0.000422994,0.000176294,0.00017628,0.00017865,0.000178362,0.000181248,0.00471654,0.000223183,0.00136309,0.00136393,0.0013627,0.000969728,0.000102583,0.000102485,0.000102442,0.000347685,0.00034204,0.000341947,0.000338944,0.000139307,0.000137024,0.000420251,0.000422386,0.00042149,0.000421833,0.000415776,0.000345088,0.000135168,0.000269919,0.00026928,9.0112e-05,0.000118038,0.000116544", "perf/train_forward": "0.00692736,0.00433152,0.00139871,0.00139878,0.00140902,0.00635904,0.00386,0.00386431,0.0038953,0.00679219,0.00394378,0.00304947,0.00222598,0.0050677,0.00506855,0.00506998,0.00504627,0.00156349,0.00156407,0.00156495,0.00157696,0.000685952,0.000685347,0.000685617,0.000685747,0.000685997,0.000686072,0.000683008,0.0176579,0.017637,0.00241459,0.0387575,0.0387296,0.00410726,0.00195584,0.00249651,0.00160012,0.000899008,0.0216617,0.00683213,0.0059425,0.00227123,0.0011991,0.00916685,0.00678532,0.00679322,0.0041472,0.00209424,0.00075776,0.00195555,0.00195379,0.00385425,0.00153767,0.00152986,0.00212524,0.0370837,0.0370836,0.0372429,0.03315,0.00483371,0.00342016,0.0088064,0.0088985,0.00889949,0.00891904,0.0158885,0.0159498,0.00130937,0.036649,0.00191748,0.00192133,0.00192717,0.0041387,0.00418099,0.00963525,0.00963994,0.00118852,0.00118707,0.00161932,0.0016248,0.00162705,0.0016343,0.000459776,0.00672256,0.00478208,0.00676606,0.00613581,0.00766709,0.00767193,0.00768,0.00511019,0.00511022,0.000766617,0.000768,0.00161177,0.0016104,0.00243934,0.0019712,0.00623002,0.0242214,0.0244775,0.0264499,0.00225215,0.00225501,0.0169402,0.0169436,0.016982,0.00909376,0.00623002,0.00151142,0.00238385,0.00237978,0.00753664,0.00225691,0.00225614,0.00225894,0.00905216,0.0254905,0.00243234,0.00243363,0.00243497,0.00243488,0.00243712,0.000851398,0.00234941,0.000755749,0.000754688,0.00457523,0.00189645,0.00308987,0.00468911,0.0046951,0.00470049,0.00470217,0.00472576,0.00510752,0.00510602,0.00510596,0.00510778,0.00512,0.00213811,0.0173208,0.00153418,0.00153566,0.00154419,0.00211429,0.00231205,0.00231744,0.00235917,0.00152498,0,0.00196915,0.00119808,0.00407962,0.00690893,0.00198349,0.0094167,0.000782336,0.00112789,0.000767756,0.000772096,0.00309201,0.00226483,0.000778461,0.000778665,0.000774144,0.00277299,0.00472293,0.00473047,0.00473714,0.00489062,0.00289035,0.00289128,0.00289382,0.039486,0.00613466,0.00619315,0.00158323,0.00988394,0.00462955,0.00463048,0.00466944,0.00196403,0.00057886,0.000579122,0.000579584,0,0.0185795,0.00899891,0.00121763,0.00122163,0.00213797,0.00213657,0.00213675,0.00214118,0.00379039,0.00386662,0.00405086,0.00405731,0.00405997,0.00409498,0.00845107,0.00866734,0.00925286,0.00411341,0.00909349,0.00909487,0.00911373,0.00913697,0.00926515,0.00117555,0.00706265,0.00468362,0.0046883,0.00469423,0.00472701,0.0048128,0.0864748,0.00854778,0.00855573,0.00863232,0.00855236,0.00855349,0.00855521,0.00197859,0.0110244,0.00291533,0.00520294,0.0423672,0.0424801,0.0433705,0.0199221,0.0199155,0.0199236,0.0199294,0.0199557,0.00550911,0.0291529,0.0292385,0.0297694,0.0305234,0.00289075,0.0011879,0.000944565,0.000950272,0.0218051,0.000915229,0.000917504,0.00241498,0.000455776,0.00400599,0.00400224,0.0280832,0.00152505,0.00152633,0.00152781,0.00678872,0.00679389,0.00681062,0.0023851,0.0168409,0.0168551,0.0168591,0.0169083,0.148279,0.00208853,0.00210213,0.000825594,0.00153232,0.00242189,0.00249856,0.00227139,0.00238819,0.00238834,0.00239206,0.00494458,0.00124262,0.00124176,0.00192717,0.000689881,0.000689861,0.00309453,0.00197427,0.00411034,0.000934345,0.000933888,0.00526438,0.00497128,0.00497593,0.00505856,0.0015401,0.0163909,0.016385,0.00116326,0.0405079,0.04049,0.0405029,0.00752242,0.0451861,0.0454257,0.0199203,0.0200471,0.00598515,0.00598457,0.095191,0.00119971,0.0012073,0.0144507,0.00276275,0.00154222,0.00154252,0.00154289,0.0015435,0.00154214,0.00499311,0.00499733,0.00507405,0.0028631,0.00117818,0.00117802,0.00898253,0.00196876,0.00196989,0.00196915,0.00545993,0.00546869,0.00547226,0.00480768,0.00400543,0.00404275,0.00376832,0.00624935,0.00621799,0.00618136,0.00615629,0.0113024,0.00619689,0.00619421,0.00619499,0.00619594,0.00620544,0.00422801,0.00421478,0.0490713,0.049168,0.000673732,0.00110385,0.00110428,0.00110468,0.00195076,0.00195164,0.00195384,0.00196257,0.00688897,0.00162109,0.00162353,0.00162909,0.00163333,0.00163123,0.106701,0.00214609,0.031133,0.031157,0.0343283,0.019583,0.000794628,0.000795136,0.000794734,0.00539885,0.00540253,0.00540354,0.0054231,0.00235118,0.00236954,0.00478501,0.00478354,0.00478586,0.00478984,0.00483328,0.00548454,0.0010711,0.00678124,0.00683213,0.00452403,0.00302506,0.00301773", "perf/train": "0.0073513,0.00461005,0.0015063,0.00150673,0.00151347,0.0066265,0.0042092,0.00421378,0.00424259,0.0070615,0.00408262,0.00317005,0.0024042,0.00529429,0.00529467,0.00529526,0.00526778,0.00169883,0.00169951,0.00170037,0.00171008,0.00075931,0.000759278,0.00075973,0.000759591,0.000759995,0.000760092,0.000756736,0.0188288,0.0188086,0.00255078,0.0399866,0.0399583,0.00437965,0.00204083,0.00263475,0.00177664,0.00100352,0.022617,0.00710326,0.00655816,0.00239002,0.00128902,0.00951814,0.00690828,0.00691302,0.00441549,0.00231675,0.000841728,0.00204247,0.00206026,0.00415879,0.00168194,0.00167731,0.0023456,0.0384436,0.0384432,0.0386067,0.0343734,0.00530605,0.0036473,0.0093799,0.00931047,0.00931172,0.00933485,0.0174406,0.0175094,0.00144697,0.0379761,0.00205306,0.00205804,0.00206458,0.0044126,0.00444928,0.00990603,0.00991334,0.00127639,0.00127488,0.00179634,0.00180236,0.00180613,0.00180973,0.000535552,0.00684234,0.00520384,0.00718143,0.00647802,0.0080812,0.00808567,0.0080896,0.00533933,0.00533911,0.000853681,0.000859104,0.00169772,0.00169661,0.00258261,0.00206221,0.00657715,0.0261969,0.0264568,0.0284561,0.00243532,0.00243834,0.017414,0.0174188,0.0174541,0.00944496,0.00658099,0.00164966,0.00252159,0.00251802,0.0081736,0.00237627,0.00237561,0.00237773,0.00939213,0.0275527,0.00256906,0.0025687,0.0025702,0.00257199,0.00257126,0.000955337,0.00250616,0.000841805,0.000842944,0.0047913,0.00209293,0.00319858,0.00510172,0.00510807,0.00511367,0.00511522,0.00513738,0.0053366,0.00533724,0.00533512,0.00533836,0.00534822,0.00236544,0.0185457,0.00167118,0.0016727,0.00168125,0.0023359,0.00253829,0.00254153,0.00257645,0.00165762,0,0.00221594,0.00128589,0.00434893,0.00718234,0.00207347,0.00976077,0.000871456,0.00120633,0.000854721,0.000854944,0.0032123,0.00244362,0.000865996,0.000866091,0.00085984,0.00310272,0.00499654,0.00500394,0.00501062,0.00516394,0.00316452,0.00316542,0.00316605,0.0402116,0.00647325,0.006528,0.00172147,0.0103705,0.00489885,0.00489962,0.00495309,0.0020488,0.000653117,0.000655037,0.000656384,0,0.0196495,0.00933888,0.00130414,0.00130662,0.00231063,0.00230889,0.0023103,0.00231526,0.00414214,0.00422115,0.00432008,0.0043262,0.0043286,0.00436243,0.0091479,0.00937271,0.00994714,0.00438266,0.00943891,0.00944005,0.00945897,0.00948274,0.00961638,0.00126259,0.00733598,0.00509626,0.00510069,0.00510672,0.00513935,0.00522854,0.0903905,0.00882091,0.00882894,0.00891187,0.00882876,0.0088274,0.0088314,0.00206358,0.0115884,0.00318493,0.00532093,0.0428408,0.0429563,0.0438426,0.0208469,0.0208404,0.0208485,0.0208554,0.0208876,0.00564714,0.0302333,0.030318,0.0308502,0.0315946,0.00316221,0.00127904,0.00103247,0.00103923,0.0227594,0.000992046,0.00099328,0.00255046,0.000530217,0.00414226,0.00414141,0.0288081,0.00165756,0.00165801,0.00166202,0.00705916,0.0070641,0.00707994,0.00252191,0.0173105,0.0173229,0.0173251,0.0173814,0.15361,0.00230946,0.0023231,0.000924906,0.00166975,0.00255643,0.00263475,0.00239018,0.00251772,0.00252039,0.00252717,0.00549478,0.00138202,0.0013811,0.00212787,0.000764702,0.000764778,0.00329114,0.00205923,0.00437965,0.0010195,0.00100659,0.00538419,0.00519374,0.00519949,0.00528282,0.00168026,0.0171596,0.0171693,0.00125731,0.0420758,0.0420575,0.0420712,0.00814885,0.046384,0.0466299,0.020728,0.0208545,0.00638024,0.00637983,0.0999557,0.00128599,0.00129725,0.0151337,0.0028527,0.00167827,0.0016782,0.00167969,0.00167983,0.00168035,0.00533094,0.00533515,0.0054095,0.00320611,0.00126808,0.00126792,0.00932352,0.00205902,0.00206041,0.00205722,0.00580444,0.00581316,0.00581837,0.00522445,0.00414313,0.00418202,0.00411443,0.00660882,0.0065676,0.00652793,0.00650342,0.0120104,0.00654913,0.00654672,0.00654731,0.00654819,0.0065577,0.00470966,0.00469914,0.0513803,0.0514796,0.000741296,0.00117787,0.00117929,0.00117988,0.00215911,0.00216018,0.0021624,0.00217102,0.00731196,0.00179738,0.00179981,0.00180774,0.00181169,0.00181248,0.111417,0.00236927,0.0324961,0.0325209,0.035691,0.0205527,0.000897211,0.000897621,0.000897176,0.00574653,0.00574457,0.00574549,0.00576205,0.00249049,0.00250656,0.00520526,0.00520593,0.00520735,0.00521167,0.00524906,0.00582963,0.00120627,0.00705116,0.00710141,0.00461414,0.00314309,0.00313427", "util/gpu_percent": "85,89,80.27,82.3737,83,88,79.9763,80.0871,82,85,77.9188,92,83.1895,85.5093,87.772,87.6436,86,81.8727,81.3032,81.4636,79,82.9986,81.9354,81.5296,81.5897,81.4729,81.4746,80,79.0803,76.0909,81,88.2134,87.1667,82,90,68,78.8541,78,75,86,77.2317,89,80,88,92.6542,93,70,80.6102,78,84.1726,81,76.1047,87.9597,83,80.7115,91.0356,90.3564,91,89,58.5063,75,83,88.6952,87.645,90,81.5463,83,80.2025,85,87.4888,85.3717,85,83.1158,82,95.3672,95,81.5556,83,82.9699,81.7822,80.8138,69,77,76,82,79.354,86,86.06,85.7994,85,56.2442,55.9218,70.0969,67,89.8163,88.1323,83.7304,84,87,91.5522,90.9923,91,82.8957,82.1037,88.4205,88.244,85,73,85,85,83.9995,85,74,89.6703,88.1405,88,92,85.6918,73.3971,82.0109,81.864,77.8481,81,54.0514,64.7802,76.094,76,71,81,88.7534,82.8703,81.4081,79.5349,81.0334,81,85.467,84.3673,87.1607,82.061,87,75,83.1114,79.6824,79.5435,79,81.9865,79.6221,81.0816,81,80.794,95,77,80,82,77,84,88,65,69.0597,74.3279,78,90.5843,83.7691,78.2773,78.3014,78,79,89.0362,91.9114,91.8077,90,80.3471,79.5054,81,98.6696,90.3736,90,81,88.3509,90.826,91.4694,78,82,83.7037,83.4907,83,86.9293,73,93,80.1238,80,85.2195,86.6715,87.8364,83,66.8126,67,66.8561,64.1637,69.6309,68,85.5385,84.8922,83,83,85.5799,86.3923,87.0836,83.6962,87,84,88.4808,82.9646,81.1556,81.0466,80.6042,83,96,94.5498,94.293,95,88.9062,89.0639,90.4153,72,90,81,94,98.6982,97.3874,98,91.9603,91.4461,90.8953,90.8547,90,58.1532,89.5665,89.6291,89.0532,89,83,83,87.48,91,56,91.0395,91,85.3582,76.3778,90.8771,82,76,79.4742,79.4184,78,85.7487,86.42,86,53.8534,92.0404,86.6368,83,85,75,81.9887,80.406,73.3849,79.9837,72.6061,70,91,88.8722,86.4541,87,71,70.2586,67.8371,81,67.7631,68.1775,85,84,83,73.8563,74,91,93.0612,91.0722,92,56,92.7273,93,82,94.2804,93.9516,92.756,90.1483,87.8714,88,89.8119,95.1862,79.3149,71.8085,88,83.1396,84,87,79,79.3409,78.2507,75.8983,78.6696,79,85.4376,84.8889,86,79,80.5453,82.3701,88,70.0429,70.0663,71,85.0583,85.1589,83,69,77.6051,77,81,52.6828,52.1333,51.3527,48,87.6745,76.3839,76.9076,76.3379,76.3707,75,71.1573,64,85.4903,84.8592,88.8691,83.9943,83.4072,82.7754,83.6996,83.043,83.0503,81.4446,85.2871,82.877,81.9636,81.687,79.9744,80,85,80.8958,94.7627,95.3275,95.5401,87,78.0246,79.7486,77.1618,82.3872,82.3779,82.3905,82,81.5116,84,83.1106,79.8338,80.0634,76.715,80,82,63,76.7316,74,78,83.3485,86", "util/gpu_mem": "6.47721,20.8338,5.15007,5.15007,5.15007,7.06344,5.85842,5.85842,5.85842,24.8939,6.81918,26.0582,5.3699,5.93984,5.93984,5.93984,5.93984,5.38619,5.38619,5.38619,5.38619,5.10122,5.10122,5.10122,5.10122,5.10122,5.10122,5.10122,22.8421,22.8421,23.0701,7.53567,7.53567,6.47721,7.31584,5.78514,5.05236,4.83253,23.6889,7.57638,6.51792,7.98348,6.01312,7.57638,14.0167,14.0167,6.13525,21.8651,5.38619,7.07158,7.07158,5.4269,5.86656,5.86656,5.05236,8.56971,8.56971,8.56971,8.56971,5.58974,5.10936,7.35655,6.24109,6.24109,6.24109,6.39579,6.39579,5.01165,9.26992,5.41875,5.41875,5.41875,6.47721,6.47721,9.09079,9.09079,5.93984,5.93984,5.05236,5.05236,5.05236,5.05236,4.83253,14.4482,5.85842,6.60748,6.45279,6.45279,6.45279,6.45279,5.4269,5.4269,5.15821,5.15821,6.4935,6.4935,6.4935,7.07158,6.45279,7.22628,7.22628,7.22628,5.3699,5.3699,10.8413,10.8413,10.8413,7.20999,6.45279,5.61416,5.93984,5.93984,5.49203,24.7962,24.7962,24.7962,24.8939,6.71333,6.01312,6.01312,6.01312,6.01312,6.01312,5.50017,6.46907,5.38619,5.38619,7.42983,5.83399,6.22481,5.85842,5.85842,5.85842,5.85842,5.85842,5.93984,5.93984,5.93984,5.93984,5.93984,5.4269,24.0553,5.38619,5.38619,5.38619,5.05236,5.05236,5.05236,5.05236,5.38619,8.59413,5.74443,6.01312,23.2899,7.20999,7.07158,24.3891,5.15821,5.81771,5.51646,5.51646,8.71626,5.3699,5.38619,5.38619,5.38619,5.51646,7.08426,7.08786,7.08786,7.08786,5.85842,5.85842,5.85842,12.372,6.95759,6.95759,5.38619,6.44464,6.82732,6.82732,6.82732,7.07158,21.6452,21.4921,21.6452,6.1841,7.35655,7.95091,6.01312,6.01312,5.37804,5.37804,5.37804,5.37804,22.3292,22.3292,6.13525,6.13525,6.13525,6.13525,22.6467,22.4934,22.6467,6.47721,7.57638,7.57638,7.57638,7.57638,7.57638,5.93984,6.02126,5.85842,5.85842,5.85842,5.85842,5.85842,10.4831,8.3173,8.3173,8.3173,8.3173,8.3173,8.3173,6.81918,6.92502,5.85842,12.3394,20.9944,20.9944,20.9944,6.44464,6.44464,6.44464,6.44464,6.44464,7.59267,8.56971,8.56971,8.56971,8.56971,5.85842,5.93984,5.6793,5.6793,7.38097,5.58974,5.58974,6.25738,4.83253,7.31584,7.31584,10.8413,5.38619,5.38619,5.38619,7.70665,7.70665,7.70665,5.4269,11.5415,11.5415,11.5415,10.8413,9.18036,21.8651,21.8651,5.50017,5.38619,5.78514,5.78514,7.95091,6.25738,6.25738,6.25738,5.17449,4.85696,4.85696,5.85842,4.9628,4.9628,6.45279,7.07158,6.47721,5.19892,5.19892,11.9405,6.1841,6.1841,6.1841,5.15821,6.81918,6.81918,5.93984,24.7799,24.7799,24.7799,6.16782,9.16407,9.16407,7.31584,7.31584,6.59934,6.59934,10.5075,5.93984,5.93984,6.46093,7.86135,5.38619,5.38619,5.38619,5.38619,5.38619,5.8747,5.8747,5.8747,5.64673,5.93984,5.93984,7.57638,6.81918,6.81918,6.81918,6.47721,6.47721,6.47721,5.49203,6.81918,6.81918,5.85842,22.1723,22.3683,22.5246,22.5246,5.8747,6.0864,6.0864,6.0864,6.0864,6.0864,5.17449,5.17449,6.86803,6.86803,5.2722,5.6793,5.6793,5.6793,4.91395,4.91395,4.91395,4.91395,6.47721,5.05236,5.05236,5.05236,5.05236,5.05236,10.4831,5.05236,8.58599,8.58599,8.58599,6.9983,21.4905,21.4905,21.4905,23.1268,23.2867,23.2899,23.2899,22.7526,22.7526,5.85842,5.85842,5.85842,5.85842,5.85842,6.47721,5.18264,24.0227,24.0227,25.9361,8.71626,8.71626", "util/vram_used_gb": "1.09265,4.53656,0.774292,0.774292,0.774292,1.23328,0.944214,0.944214,0.944214,5.5105,1.17468,5.78979,0.827026,0.963745,0.963745,0.963745,0.963745,0.830933,0.830933,0.830933,0.830933,0.762573,0.762573,0.762573,0.762573,0.762573,0.762573,0.762573,5.01831,5.01831,5.073,1.34656,1.34656,1.09265,1.29382,0.926636,0.750854,0.69812,5.22144,1.35632,1.10242,1.45398,0.981323,1.35632,2.90125,2.90125,1.01062,4.78394,0.830933,1.23523,1.23523,0.840698,0.946167,0.946167,0.750854,1.5946,1.5946,1.5946,1.5946,0.879761,0.764526,1.30359,1.03601,1.03601,1.03601,1.07312,1.07312,0.741089,1.76257,0.838745,0.838745,0.838745,1.09265,1.09265,1.7196,1.7196,0.963745,0.963745,0.750854,0.750854,0.750854,0.750854,0.69812,3.00476,0.944214,1.1239,1.08679,1.08679,1.08679,1.08679,0.840698,0.840698,0.776245,0.776245,1.09656,1.09656,1.09656,1.23523,1.08679,1.27234,1.27234,1.27234,0.827026,0.827026,2.13953,2.13953,2.13953,1.26843,1.08679,0.88562,0.963745,0.963745,0.856323,5.48706,5.48706,5.48706,5.5105,1.14929,0.981323,0.981323,0.981323,0.981323,0.981323,0.858276,1.0907,0.830933,0.830933,1.32117,0.938354,1.0321,0.944214,0.944214,0.944214,0.944214,0.944214,0.963745,0.963745,0.963745,0.963745,0.963745,0.840698,5.30933,0.830933,0.830933,0.830933,0.750854,0.750854,0.750854,0.750854,0.830933,1.60046,0.91687,0.981323,5.12573,1.26843,1.23523,5.3894,0.776245,0.934448,0.862183,0.862183,1.62976,0.827026,0.830933,0.830933,0.830933,0.862183,1.23827,1.23914,1.23914,1.23914,0.944214,0.944214,0.944214,2.50671,1.20789,1.20789,0.830933,1.08484,1.17664,1.17664,1.17664,1.23523,4.7312,4.69446,4.7312,1.02234,1.30359,1.44617,0.981323,0.981323,0.828979,0.828979,0.828979,0.828979,4.89526,4.89526,1.01062,1.01062,1.01062,1.01062,4.97144,4.93466,4.97144,1.09265,1.35632,1.35632,1.35632,1.35632,1.35632,0.963745,0.983276,0.944214,0.944214,0.944214,0.944214,0.944214,2.05359,1.53406,1.53406,1.53406,1.53406,1.53406,1.53406,1.17468,1.20007,0.944214,2.4989,4.57507,4.57507,4.57507,1.08484,1.08484,1.08484,1.08484,1.08484,1.36023,1.5946,1.5946,1.5946,1.5946,0.944214,0.963745,0.901245,0.901245,1.30945,0.879761,0.879761,1.03992,0.69812,1.29382,1.29382,2.13953,0.830933,0.830933,0.830933,1.38757,1.38757,1.38757,0.840698,2.3075,2.3075,2.3075,2.13953,1.74109,4.78394,4.78394,0.858276,0.830933,0.926636,0.926636,1.44617,1.03992,1.03992,1.03992,0.780151,0.703979,0.703979,0.944214,0.72937,0.72937,1.08679,1.23523,1.09265,0.786011,0.786011,2.4032,1.02234,1.02234,1.02234,0.776245,1.17468,1.17468,0.963745,5.48315,5.48315,5.48315,1.01843,1.73718,1.73718,1.29382,1.29382,1.12195,1.12195,2.05945,0.963745,0.963745,1.08875,1.42468,0.830933,0.830933,0.830933,0.830933,0.830933,0.94812,0.94812,0.94812,0.893433,0.963745,0.963745,1.35632,1.17468,1.17468,1.17468,1.09265,1.09265,1.09265,0.856323,1.17468,1.17468,0.944214,4.85763,4.90464,4.94214,4.94214,0.94812,0.998901,0.998901,0.998901,0.998901,0.998901,0.780151,0.780151,1.1864,1.1864,0.803589,0.901245,0.901245,0.901245,0.717651,0.717651,0.717651,0.717651,1.09265,0.750854,0.750854,0.750854,0.750854,0.750854,2.05359,0.750854,1.59851,1.59851,1.59851,1.21765,4.69409,4.69409,4.69409,5.08659,5.12495,5.12573,5.12573,4.99683,4.99683,0.944214,0.944214,0.944214,0.944214,0.944214,1.09265,0.782104,5.30151,5.30151,5.7605,1.62976,1.62976", "util/vram_total_gb": "23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272", "util/cpu_mem_gb": "1.18863,1.10217,1.10547,1.11821,1.16331,1.22139,1.17771,1.17866,1.18504,1.15306,1.12362,1.16809,1.12938,1.13922,1.14354,1.14802,1.17144,1.13221,1.13585,1.14025,1.1633,1.10723,1.11187,1.11708,1.12217,1.12745,1.13273,1.15036,1.18551,1.1861,1.09439,1.26659,1.26724,1.19058,1.18256,1.15376,1.13503,1.17215,1.16934,1.20858,1.20254,1.23064,1.16693,1.20939,1.22816,1.2405,1.16825,1.0472,1.15906,1.14743,1.16438,1.12155,1.1469,1.17552,1.12716,1.29639,1.29709,1.30047,1.29994,1.14739,1.1586,1.26491,1.20696,1.20911,1.22131,1.2559,1.25799,1.11479,1.34481,1.1465,1.15742,1.18145,1.18173,1.19023,1.23842,1.25174,1.14605,1.16919,1.12895,1.13217,1.13533,1.16381,1.17162,1.27501,1.19248,1.17948,1.20391,1.19486,1.19649,1.20796,1.11772,1.12211,1.11178,1.12907,1.14476,1.1558,1.148,1.17405,1.20679,1.29,1.2913,1.29702,1.12928,1.14034,1.29409,1.29472,1.29914,1.18237,1.20679,1.16365,1.14692,1.1708,1.16489,1.13798,1.14201,1.14296,1.1554,1.25747,1.12645,1.12834,1.13163,1.14037,1.14424,1.1272,1.13461,1.13199,1.15558,1.16456,1.18484,1.11932,1.17466,1.17591,1.17725,1.17916,1.191,1.1365,1.13982,1.14333,1.14738,1.17262,1.15601,1.24509,1.13016,1.1343,1.16257,1.13062,1.13644,1.14062,1.1646,1.12367,1.12575,1.21548,1.16711,1.11045,1.18362,1.1738,1.12766,1.15176,1.10646,1.13468,1.15751,1.20879,1.12851,1.14964,1.1584,1.1647,1.18744,1.22027,1.22168,1.2233,1.23595,1.17747,1.17869,1.19048,1.48028,1.22215,1.23484,1.16141,1.19094,1.21945,1.22085,1.23277,1.1713,1.05286,1.06168,1.11005,1.13866,1.26676,1.23638,1.13569,1.15747,1.15824,1.16126,1.16421,1.18725,1.07439,1.08393,1.15298,1.15465,1.15627,1.16875,1.09697,1.09906,1.11015,1.19022,1.19238,1.19391,1.19541,1.19692,1.20822,1.17242,1.13005,1.17516,1.17629,1.17754,1.17999,1.18695,1.4705,1.24751,1.25044,1.26309,1.24159,1.24286,1.24432,1.15687,1.20377,1.19184,1.25939,1.41791,1.41929,1.42047,1.19484,1.19627,1.19763,1.19826,1.2092,1.11559,1.29665,1.29727,1.29785,1.30136,1.19243,1.16779,1.16204,1.19746,1.19785,1.12441,1.19942,1.14735,1.11706,1.16036,1.18893,1.30006,1.13432,1.13865,1.1618,1.19685,1.1984,1.20892,1.10965,1.33778,1.33839,1.34267,1.30114,1.43421,1.05105,1.0536,1.12612,1.12861,1.1191,1.15388,1.23009,1.14362,1.14769,1.17589,1.16893,1.12242,1.12406,1.19139,1.10253,1.10759,1.20842,1.1702,1.19223,1.10465,1.15524,1.22407,1.15327,1.15981,1.18838,1.1435,1.21974,1.23286,1.16893,1.2974,1.29803,1.29882,1.195,1.27401,1.27803,1.24909,1.25215,1.16978,1.17052,1.55701,1.14642,1.17394,1.18283,1.16444,1.12485,1.12873,1.13314,1.13761,1.16133,1.19607,1.19757,1.20874,1.18293,1.13715,1.14111,1.20772,1.12441,1.13203,1.1533,1.17129,1.1751,1.18553,1.16758,1.12481,1.15897,1.18588,1.0551,1.05592,1.05761,1.06886,1.19445,1.16534,1.16651,1.16756,1.16864,1.17775,1.14619,1.16261,1.24584,1.24639,1.10311,1.10967,1.11792,1.13569,1.13395,1.13558,1.13766,1.14334,1.17973,1.12995,1.13293,1.13622,1.14005,1.16411,1.47398,1.13757,1.38245,1.38292,1.38419,1.3265,1.02773,1.03549,1.0442,1.09594,1.09686,1.09854,1.10949,1.06429,1.08574,1.172,1.17305,1.17437,1.17611,1.18739,1.18926,1.16059,1.0849,1.09875,1.06709,1.2075,1.21754", "env/perf": "1,0.996094,0.567166,1,1,1,1,1,1,0.996094,0.65864,0.996094,0.608337,1,1,1,1,1,1,1,1,0.451414,0.999931,1,1,1,1,1,0.340586,0.967849,0.996094,0.631459,0.996094,1,0.996191,0.996094,1,1,0.996094,1,0.0317118,0.996094,1,1,1,1,0.996094,0.662719,1,1,1,0.252977,0.551045,0.984375,0.684407,1,1,1,1,0.172172,0.996094,1,1,1,1,1,1,0.725466,0.996094,0.688575,1,1,1,1,0.996094,0.996094,1,1,0.64575,1,1,1,1,0.996094,1,1,1,1,1,1,1,1,0.203703,0.996094,0.687561,1,0.662884,1,1,0.579444,0.92732,0.996191,0.686348,1,1,1,1,0.996094,1,0.996191,1,1,0.996094,0.138257,0.996094,0.996094,0.996094,1,0.319224,0.947725,1,1,1,0.112332,0.0583283,1,1,0.996094,1,0.688566,0.684152,1,1,1,1,0.688311,1,1,1,1,0.996094,0.918626,1,1,1,0.686326,1,1,1,0.51202,0,0.996094,1,1,0.996094,1,1,0.996191,0.878,1,1,0.0790299,0.670404,1,1,1,1,0.679025,0.996094,0.941929,0.996094,1,1,1,0.0948134,0.965731,0.996094,1,0.678501,0.996094,0.938322,0.996094,1,1,1,1,0,1,0.996094,1,1,0.563922,0.996094,0.83949,0.996094,0.996094,0.996094,0.647998,0.996094,0.940645,0.996094,1,1,1,1,0.689107,1,1,1,1,1,1,0.594323,1,1,1,1,1,0.678857,0.954369,0.984375,0.649451,0.984375,0.927782,0.996094,0.996094,1,0.996094,0.984375,0.984375,0.984375,0.670449,1,1,1,1,1,1,1,1,1,1,1,0.680811,0.996094,1,0.688455,0.996191,0.996094,1,0.954851,0.996094,1,1,1,1,1,1,1,0.648938,0.996094,0.996094,0.996094,1,0.996094,0.622971,1,0.140071,1,0.679818,0.996094,0.996094,0.92117,0.958832,0.996094,0.996094,0.379228,0.98207,1,0.548502,0.996094,1,1,1,0.532503,0.996191,1,0.685904,0.947775,0.996094,0.996191,0.996094,0.996094,1,0.637776,0.996094,0.996094,0.655189,0.686965,0.996094,0.678619,0.950431,0.11919,0.901501,0.996094,1,1,1,0.996094,0.668905,1,1,1,1,1,1,1,1,1,1,1,0.995541,0.994986,0.996094,1,1,1,0.996094,0.685133,0.996094,1,1,1,1,1,1,0.594436,0.996094,0.929774,0.996094,0.996094,0.665261,0.996191,0.69445,0.996094,0.300474,0.693993,1,1,0.51482,0.999966,1,1,1,0.681607,1,1,1,1,1,1,0.643077,0.984375,0.984375,1,0.67326,1,1,1,1,1,1,1,1,0.674759,1,1,1,1,1,1,0.965731,0.996094,0.996094,1,1", "env/score": "3.85668e+06,3.88217e+06,120062,575483,2.91515e+06,3.83439e+06,773100,1.02889e+06,2.60805e+06,3.69783e+06,164554,2.51635e+06,134661,547781,920968,1.31751e+06,3.89868e+06,465843,828964,1.21878e+06,3.71666e+06,105248,319345,544319,772198,1.00118e+06,1.23136e+06,2.47863e+06,71437.6,206035,3.58987e+06,148941,444159,3.73462e+06,3.55649e+06,3.8704e+06,795099,3.42525e+06,3.89373e+06,3.85255e+06,18784.8,3.89649e+06,3.62672e+06,3.87916e+06,850070,3.78505e+06,3.86893e+06,149136,3.23018e+06,1.30861e+06,3.20554e+06,61118.4,114588,2.97228e+06,170134,900733,1.28682e+06,3.88362e+06,3.9617e+06,46226.1,3.88386e+06,3.35861e+06,926928,1.31247e+06,3.88233e+06,337644,1.84916e+06,179693,3.92014e+06,171161,1.25978e+06,3.85298e+06,1.00241e+06,3.21118e+06,445286,3.43316e+06,1.26104e+06,3.86762e+06,153330,457096,824523,3.76593e+06,3.22204e+06,3.35993e+06,3.73512e+06,909759,3.84244e+06,914432,1.3034e+06,3.91539e+06,905511,1.3047e+06,43856.5,1.68702e+06,172676,1.2657e+06,160180,3.84964e+06,3.84854e+06,123389,576078,2.98017e+06,175140,1.25954e+06,797675,1.14866e+06,3.55558e+06,3.9413e+06,3.91822e+06,2.76567e+06,1.28444e+06,3.86842e+06,3.25075e+06,32449.3,1.04756e+06,1.66042e+06,3.87803e+06,1.26245e+06,67972.8,196403,554960,1.31788e+06,2.04231e+06,32712.2,22750.7,563525,2.90728e+06,2.85245e+06,2.95145e+06,181234,170138,525073,903988,1.28933e+06,3.8392e+06,183639,553524,939397,1.32793e+06,3.92952e+06,2.58198e+06,592307,458324,829593,3.78321e+06,178873,908388,1.29885e+06,3.87334e+06,105329,14065.5,2.71497e+06,3.68386e+06,3.6227e+06,3.93762e+06,3.89292e+06,3.89049e+06,3.70275e+06,201703,1.10505e+06,3.47319e+06,26245.4,157071,1.85834e+06,2.63301e+06,3.6429e+06,3.61093e+06,179361,537899,869769,3.82139e+06,796609,1.16949e+06,3.73389e+06,27215.3,916057,3.94069e+06,3.57438e+06,173560,466518,778103,3.58048e+06,3.87517e+06,860932,1.25502e+06,3.82495e+06,13929.5,3.86423e+06,3.74583e+06,1.03374e+06,3.284e+06,122366,401700,586143,3.09542e+06,1.0828e+06,3.32219e+06,150114,480512,808390,3.6905e+06,892778,1.27441e+06,3.85339e+06,3.74879e+06,184630,560722,949462,1.34127e+06,3.96781e+06,3.65244e+06,775748,129301,389576,688605,1.29945e+06,3.15e+06,3.92583e+06,185543,919771,3.91823e+06,162476,490861,798241,3.86517e+06,3.89117e+06,3.61322e+06,3.84636e+06,463849,1.13604e+06,3.44012e+06,166348,521174,896313,1.27438e+06,3.81534e+06,497635,497776,872509,1.2512e+06,3.80561e+06,3.59518e+06,3.22676e+06,175227,3.86045e+06,3.9128e+06,181271,3.92623e+06,1.00718e+06,595064,894628,3.94437e+06,3.91395e+06,786315,1.17462e+06,3.74899e+06,489611,848921,3.68063e+06,151750,435274,1.10971e+06,3.43207e+06,3.69537e+06,3.96914e+06,148778,417366,37828.9,445538,172151,3.86498e+06,2.49154e+06,474414,870080,3.8025e+06,3.86478e+06,77009,235727,3.52221e+06,112366,363619,3.87526e+06,3.84773e+06,3.80487e+06,114881,2.71107e+06,3.91688e+06,184624,896914,3.92322e+06,2.82877e+06,507473,3.75414e+06,3.31446e+06,154518,472939,1.15536e+06,152059,186961,3.99574e+06,184849,910323,33107.3,196057,3.90643e+06,807356,3.79236e+06,3.91161e+06,3.868e+06,158060,514377,890298,1.27051e+06,3.82862e+06,911321,1.29919e+06,3.90199e+06,2.86354e+06,443817,773576,3.91078e+06,452707,1.13123e+06,3.47666e+06,431204,1.07392e+06,3.33854e+06,3.87288e+06,182154,3.90583e+06,3.75322e+06,487321,841770,1.19791e+06,3.6064e+06,916878,138955,433254,693069,1.05268e+06,3.22186e+06,156450,3.63023e+06,181129,534266,67781.1,181308,544492,1.29214e+06,110184,321621,544667,1.03742e+06,1.11141e+06,163972,503310,873445,1.26754e+06,3.84252e+06,3.95633e+06,843467,160725,488798,1.1651e+06,3.86636e+06,158831,478571,800626,451259,793938,1.13898e+06,3.51701e+06,1.11958e+06,3.42825e+06,169797,522826,891735,1.25704e+06,3.74798e+06,3.83183e+06,3.69805e+06,920274,3.90868e+06,3.24814e+06,1.01179e+06,3.26968e+06", "env/episode_return": "0.0722549,0.0739212,0.0757179,0.0594469,0.0660369,0.0738838,0.0695388,0.0672147,0.0669965,0.0772228,0.0850308,0.0735981,0.0832487,0.0635828,0.0568911,0.0669451,0.0735252,0.0555593,0.0605043,0.061292,0.0666865,0.0791237,0.0630075,0.0671525,0.0713316,0.0634942,0.0704896,0.0746424,0.0766203,0.0661408,0.0716585,0.0746785,0.0619239,0.0716275,0.0773606,0.071521,0.059962,0.0695866,0.0731841,0.0747433,0.0498345,0.0822298,0.0662963,0.0817397,0.0723813,0.0786666,0.0737255,0.0877887,0.069927,0.0719527,0.0743781,0.124623,0.0715505,0.0694191,0.0705454,0.0622323,0.0688765,0.0793075,0.0772111,0.138614,0.0720616,0.0697861,0.0679193,0.0664232,0.0707311,0.0625442,0.0656498,0.0762338,0.0745764,0.073893,0.0716891,0.0764639,0.0581832,0.0694033,0.0583534,0.0794334,0.0694626,0.0801246,0.0749623,0.0644975,0.0610945,0.0715028,0.070753,0.077741,0.0673262,0.0648339,0.076936,0.0660123,0.0790441,0.081961,0.0696883,0.0691682,0.0691139,0.0559417,0.0808752,0.0668198,0.0654559,0.0785142,0.0713329,0.0742158,0.0501676,0.0732165,0.0701315,0.0684869,0.0689922,0.0694525,0.0774126,0.0780296,0.0801431,0.0689051,0.0655489,0.0745185,0.0632372,0.0573288,0.0724485,0.0654677,0.0699133,0.0661187,0.073575,0.0711961,0.0610137,0.0733428,0.0690088,0.0824636,0.0719424,0.0625346,0.0598293,0.0740089,0.0602734,0.0624007,0.0712975,0.0629176,0.0695218,0.0620859,0.0724383,0.0805657,0.0697102,0.0715418,0.0682706,0.077795,0.0640901,0.0641277,0.0583267,0.0586749,0.0666941,0.0692467,0.0579045,0.0628856,0.0756818,0.0737402,0.0303264,0.0618367,0.0662691,0.0736071,0.079119,0.0783612,0.074283,0.0703607,0.0634947,0.0669588,0.0692902,0.0538477,0.0770363,0.0582844,0.0691101,0.0690608,0.0671016,0.0782985,0.0556046,0.0630774,0.0783523,0.0556808,0.0625138,0.0679158,0.0554307,0.0635327,0.0796699,0.0731921,0.0845478,0.0614552,0.0636452,0.0788859,0.0770711,0.0660512,0.074321,0.0736926,0.0305124,0.0710277,0.075165,0.0699239,0.0678992,0.0656741,0.05809,0.059319,0.0727828,0.059505,0.0730842,0.0784033,0.0641491,0.060436,0.0697342,0.0586668,0.0611435,0.0715314,0.0662433,0.0793594,0.0664487,0.0690252,0.0711423,0.0809821,0.0740203,0.0597961,0.0745183,0.0555111,0.0673508,0.0681601,0.0712429,0.0780752,0.0847283,0.0709628,0.0813829,0.0811187,0.0575498,0.0634489,0.0729903,0.0798129,0.0704403,0.0837126,0.0663836,0.0691577,0.0829029,0.075255,0.0597108,0.064085,0.065544,0.0762929,0.0554259,0.0658219,0.0766493,0.0687607,0.080162,0.0659405,0.0664491,0.0689029,0.0725052,0.0781531,0.078616,0.0821228,0.0619133,0.0585046,0.0693309,0.0816597,0.0771725,0.0647326,0.0631598,0.0689238,0.0593685,0.0622611,0.0763265,0.0854421,0.0629438,0.0612177,0.0723322,0.0787457,0.0844708,0.0736867,0.0629233,0.069267,0.0635287,0.0653407,0.0708534,0.0670743,0.0587572,0.0655479,0.0666752,0.0724975,0.0773494,0.0620164,0.0677395,0.0750331,0.0609682,0.0818624,0.0820158,0.0716919,0.0807261,0.0771234,0.0845596,0.0951028,0.0624003,0.0813168,0.0650177,0.0658065,0.07324,0.0702601,0.0650702,0.0570276,0.0603362,0.0730909,0.0736119,0.0835066,0.091855,0.0669964,0.0824685,0.0502045,0.0737152,0.0634768,0.0779487,0.0721825,0.0800885,0.0657381,0.0615298,0.059009,0.0636053,0.0728649,0.0607072,0.067649,0.0759823,0.0650703,0.0607811,0.0606217,0.0817941,0.0661442,0.0698448,0.0761219,0.0519889,0.0667311,0.0703319,0.0717287,0.0726305,0.0788023,0.0669107,0.0647272,0.0719232,0.0724976,0.0782547,0.051489,0.0749601,0.0677354,0.0670361,0.0651677,0.0790508,0.0612106,0.0649777,0.0760387,0.056581,0.071935,0.0692414,0.0566956,0.0713401,0.0811715,0.0574852,0.0644269,0.060707,0.0630471,0.0699027,0.0559795,0.0662595,0.0603854,0.0675431,0.079406,0.0570087,0.0778392,0.0608831,0.0612823,0.0763334,0.0744888,0.0569927,0.0527551,0.0549171,0.0586649,0.057151,0.0741662,0.0644111,0.0760482,0.0765222,0.0624319,0.0619043,0.0685139,0.0664395,0.0743158,0.0656729,0.0601414,0.0800972,0.0782996,0.0712694,0.0782584", "env/episode_length": "2.58311e+06,2.55524e+06,75127.4,386496,1.96179e+06,2.55169e+06,519336,692506,1.75053e+06,2.44013e+06,103960,1.67922e+06,83754.1,365199,617792,885897,2.60024e+06,311781,560442,826358,2.51243e+06,64050.7,207806,360740,514211,667663,821148,1.64744e+06,42976.3,131120,2.40055e+06,94536.8,295444,2.51134e+06,2.35645e+06,2.57961e+06,536811,2.28496e+06,2.5901e+06,2.56795e+06,13921,2.57569e+06,2.4333e+06,2.55125e+06,566489,2.49431e+06,2.56835e+06,93157.4,2.1774e+06,873001,2.12183e+06,36345,71952.7,2.00742e+06,108300,602506,861128,2.57246e+06,2.60128e+06,27140.9,2.57988e+06,2.26332e+06,621240,881669,2.58974e+06,221516,1.23906e+06,115193,2.58538e+06,109131,845494,2.56495e+06,674594,2.14124e+06,293315,2.26536e+06,847995,2.56745e+06,97071.1,303383,552731,2.527e+06,2.16965e+06,2.22272e+06,2.51553e+06,608244,2.56022e+06,612812,873241,2.59263e+06,603043,869801,27283.4,1.15678e+06,109141,841524,102209,2.5624e+06,2.55326e+06,76159.8,386470,1.99334e+06,111796,851357,534764,769749,2.35473e+06,2.59184e+06,2.58197e+06,1.86999e+06,861536,2.57732e+06,2.17553e+06,20887.3,703239,1.11263e+06,2.57689e+06,850019,41130.8,124896,370887,884587,1.36603e+06,20046.7,14756.1,377028,1.96829e+06,1.91957e+06,1.99556e+06,114708,108535,349980,607809,868238,2.57648e+06,116275,365757,625962,886440,2.6059e+06,1.73582e+06,397487,305953,559235,2.54212e+06,113852,610756,875945,2.5954e+06,65713.3,13921,1.85964e+06,2.45864e+06,2.41547e+06,2.58869e+06,2.57213e+06,2.57827e+06,2.48489e+06,127148,745498,2.32727e+06,17414.4,98940.1,1.25813e+06,1.77905e+06,2.45679e+06,2.42721e+06,113768,357017,583157,2.53764e+06,537987,792251,2.50547e+06,17884.5,608428,2.59516e+06,2.38975e+06,109291,309210,519970,2.37955e+06,2.55544e+06,575651,840519,2.54163e+06,13921,2.58078e+06,2.47455e+06,698302,2.21863e+06,77470,267460,394758,2.07319e+06,728316,2.22153e+06,94994.1,319318,540936,2.45448e+06,599395,856405,2.56533e+06,2.50128e+06,116865,369459,629723,890152,2.60954e+06,2.44369e+06,518946,80712.8,258285,463405,878063,2.10954e+06,2.58306e+06,115610,605965,2.56946e+06,102545,326096,535492,2.56634e+06,2.58135e+06,2.42352e+06,2.53236e+06,303723,751363,2.25625e+06,104847,343899,595788,847691,2.51313e+06,330118,326171,576302,826379,2.48393e+06,2.41618e+06,2.17229e+06,112114,2.58428e+06,2.5736e+06,114498,2.59291e+06,682171,400583,590241,2.58673e+06,2.57909e+06,531135,795114,2.51183e+06,324164,566571,2.43135e+06,95151.7,288337,742205,2.27488e+06,2.44064e+06,2.59255e+06,92286.9,274866,23645.1,295992,109137,2.57933e+06,1.67128e+06,316275,584560,2.55236e+06,2.57341e+06,47297.7,153269,2.37648e+06,70233.9,241514,2.56295e+06,2.54505e+06,2.53788e+06,70937.2,1.80609e+06,2.56534e+06,114758,594858,2.5951e+06,1.90736e+06,334168,2.47329e+06,2.21585e+06,98111.7,314315,776598,97025.5,116665,2.59956e+06,115164,602391,20794.4,124714,2.58613e+06,543552,2.52211e+06,2.59127e+06,2.54861e+06,101257,343213,597874,856666,2.57436e+06,612219,872588,2.59198e+06,1.9433e+06,293965,519137,2.58279e+06,299924,756659,2.30006e+06,286559,723851,2.2326e+06,2.58472e+06,115544,2.58477e+06,2.52042e+06,321815,559836,797911,2.3867e+06,614576,88133.3,286033,460918,699872,2.12457e+06,100501,2.4371e+06,114546,353595,41117.8,115305,363343,870446,68540.9,212166,365907,703011,751081,104164,335209,586401,853167,2.57012e+06,2.60117e+06,568397,101985,324180,782182,2.56016e+06,100296,319060,538608,300837,534811,768362,2.35032e+06,748702,2.27909e+06,108071,349232,600986,848782,2.5232e+06,2.56028e+06,2.49497e+06,610959,2.57884e+06,2.14121e+06,675320,2.1619e+06", "env/reward": "0.0722549,0.0739212,0.0757179,0.0594469,0.0660369,0.0738838,0.0695388,0.0672147,0.0669965,0.0772228,0.0850308,0.0735981,0.0832487,0.0635828,0.0568911,0.0669451,0.0735252,0.0555593,0.0605043,0.061292,0.0666865,0.0791237,0.0630075,0.0671525,0.0713316,0.0634942,0.0704896,0.0746424,0.0766203,0.0661408,0.0716585,0.0746785,0.0619239,0.0716275,0.0773606,0.071521,0.059962,0.0695866,0.0731841,0.0747433,0.0498345,0.0822298,0.0662963,0.0817397,0.0723813,0.0786666,0.0737255,0.0877887,0.069927,0.0719527,0.0743781,0.124623,0.0715505,0.0694191,0.0705454,0.0622323,0.0688765,0.0793075,0.0772111,0.138614,0.0720616,0.0697861,0.0679193,0.0664232,0.0707311,0.0625442,0.0656498,0.0762338,0.0745764,0.073893,0.0716891,0.0764639,0.0581832,0.0694033,0.0583534,0.0794334,0.0694626,0.0801246,0.0749623,0.0644975,0.0610945,0.0715028,0.070753,0.077741,0.0673262,0.0648339,0.076936,0.0660123,0.0790441,0.081961,0.0696883,0.0691682,0.0691139,0.0559417,0.0808752,0.0668198,0.0654559,0.0785142,0.0713329,0.0742158,0.0501676,0.0732165,0.0701315,0.0684869,0.0689922,0.0694525,0.0774126,0.0780296,0.0801431,0.0689051,0.0655489,0.0745185,0.0632372,0.0573288,0.0724485,0.0654677,0.0699133,0.0661187,0.073575,0.0711961,0.0610137,0.0733428,0.0690088,0.0824636,0.0719424,0.0625346,0.0598293,0.0740089,0.0602734,0.0624007,0.0712975,0.0629176,0.0695218,0.0620859,0.0724383,0.0805657,0.0697102,0.0715418,0.0682706,0.077795,0.0640901,0.0641277,0.0583267,0.0586749,0.0666941,0.0692467,0.0579045,0.0628856,0.0756818,0.0737402,0.0303264,0.0618367,0.0662691,0.0736071,0.079119,0.0783612,0.074283,0.0703607,0.0634947,0.0669588,0.0692902,0.0538477,0.0770363,0.0582844,0.0691101,0.0690608,0.0671016,0.0782985,0.0556046,0.0630774,0.0783523,0.0556808,0.0625138,0.0679158,0.0554307,0.0635327,0.0796699,0.0731921,0.0845478,0.0614552,0.0636452,0.0788859,0.0770711,0.0660512,0.074321,0.0736926,0.0305124,0.0710277,0.075165,0.0699239,0.0678992,0.0656741,0.05809,0.059319,0.0727828,0.059505,0.0730842,0.0784033,0.0641491,0.060436,0.0697342,0.0586668,0.0611435,0.0715314,0.0662433,0.0793594,0.0664487,0.0690252,0.0711423,0.0809821,0.0740203,0.0597961,0.0745183,0.0555111,0.0673508,0.0681601,0.0712429,0.0780752,0.0847283,0.0709628,0.0813829,0.0811187,0.0575498,0.0634489,0.0729903,0.0798129,0.0704403,0.0837126,0.0663836,0.0691577,0.0829029,0.075255,0.0597108,0.064085,0.065544,0.0762929,0.0554259,0.0658219,0.0766493,0.0687607,0.080162,0.0659405,0.0664491,0.0689029,0.0725052,0.0781531,0.078616,0.0821228,0.0619133,0.0585046,0.0693309,0.0816597,0.0771725,0.0647326,0.0631598,0.0689238,0.0593685,0.0622611,0.0763265,0.0854421,0.0629438,0.0612177,0.0723322,0.0787457,0.0844708,0.0736867,0.0629233,0.069267,0.0635287,0.0653407,0.0708534,0.0670743,0.0587572,0.0655479,0.0666752,0.0724975,0.0773494,0.0620164,0.0677395,0.0750331,0.0609682,0.0818624,0.0820158,0.0716919,0.0807261,0.0771234,0.0845596,0.0951028,0.0624003,0.0813168,0.0650177,0.0658065,0.07324,0.0702601,0.0650702,0.0570276,0.0603362,0.0730909,0.0736119,0.0835066,0.091855,0.0669964,0.0824685,0.0502045,0.0737152,0.0634768,0.0779487,0.0721825,0.0800885,0.0657381,0.0615298,0.059009,0.0636053,0.0728649,0.0607072,0.067649,0.0759823,0.0650703,0.0607811,0.0606217,0.0817941,0.0661442,0.0698448,0.0761219,0.0519889,0.0667311,0.0703319,0.0717287,0.0726305,0.0788023,0.0669107,0.0647272,0.0719232,0.0724976,0.0782547,0.051489,0.0749601,0.0677354,0.0670361,0.0651677,0.0790508,0.0612106,0.0649777,0.0760387,0.056581,0.071935,0.0692414,0.0566956,0.0713401,0.0811715,0.0574852,0.0644269,0.060707,0.0630471,0.0699027,0.0559795,0.0662595,0.0603854,0.0675431,0.079406,0.0570087,0.0778392,0.0608831,0.0612823,0.0763334,0.0744888,0.0569927,0.0527551,0.0549171,0.0586649,0.057151,0.0741662,0.0644111,0.0760482,0.0765222,0.0624319,0.0619043,0.0685139,0.0664395,0.0743158,0.0656729,0.0601414,0.0800972,0.0782996,0.0712694,0.0782584", "env/step_rew_car_passed_no_crash": "0.0108145,0.012637,0.027719,0.00819529,0.00914726,0.0113594,0.00844386,0.00815633,0.00930117,0.0128526,0.0292052,0.0119771,0.035076,0.00728457,0.00754156,0.00835512,0.0120262,0.00830306,0.00702429,0.00775595,0.00967481,0.0328078,0.00805278,0.00819216,0.00932838,0.00936109,0.0103839,0.0119275,0.0298628,0.0234497,0.0100813,0.0223588,0.0115213,0.010109,0.0128758,0.0107251,0.00743081,0.010944,0.0116265,0.0122824,0.0114837,0.0134895,0.00973867,0.014313,0.00953111,0.0144674,0.0116405,0.0332894,0.00969756,0.0102032,0.0123029,0.0735799,0.0224534,0.00898457,0.0223173,0.00970606,0.0105531,0.0132528,0.0131193,0.081696,0.0118614,0.00952236,0.00832849,0.00840068,0.0116686,0.00592284,0.00870394,0.0263938,0.011798,0.0271772,0.00883685,0.0118936,0.00793121,0.0117813,0.00906298,0.0128611,0.00924851,0.0123023,0.0276203,0.0119539,0.00792597,0.0106972,0.00961923,0.0129559,0.00882519,0.00863312,0.0115259,0.00969247,0.0104833,0.0133478,0.00950873,0.0100127,0.0206622,0.00622002,0.0256246,0.00955898,0.0220202,0.0122251,0.0123729,0.034346,0.00682462,0.010646,0.0205984,0.00831945,0.00845125,0.00936171,0.0126274,0.0139037,0.0141421,0.00917667,0.0091836,0.0118272,0.0102294,0.0177779,0.009735,0.00901127,0.0100158,0.00870329,0.0336291,0.0221428,0.00611063,0.00980177,0.00994141,0.0332638,0.030174,0.00787448,0.00855976,0.0104103,0.00839345,0.0168155,0.0231696,0.00721136,0.00819317,0.00840945,0.0107635,0.0279233,0.00884556,0.00938012,0.0102892,0.0128683,0.00860185,0.00646721,0.00624107,0.00726475,0.00981914,0.0225334,0.00673992,0.00784303,0.0104279,0.029408,0.00117184,0.0069832,0.0100776,0.0105505,0.0130691,0.0135126,0.0129256,0.0100169,0.0103496,0.00809516,0.0106184,0.0173457,0.0306276,0.00767663,0.00845392,0.00865557,0.00898643,0.0226473,0.00739988,0.00719287,0.0126052,0.00633862,0.00802936,0.00966387,0.0157008,0.00960632,0.0140889,0.0107214,0.0296177,0.00803592,0.00883585,0.0121916,0.0132967,0.00864372,0.0093027,0.0116712,0.000885062,0.0109446,0.0128066,0.0087065,0.00960332,0.0200049,0.00731709,0.00701527,0.0107906,0.0081684,0.0107551,0.025787,0.00812162,0.00789892,0.0104471,0.00758322,0.00859752,0.0110626,0.00993955,0.0282367,0.0089703,0.009526,0.0107023,0.0137263,0.00987969,0.00754662,0.0280625,0.0079523,0.00773192,0.00889737,0.0105057,0.0134219,0.0317783,0.00933531,0.0139611,0.0261156,0.00734318,0.00725295,0.0133223,0.0113168,0.0104501,0.0138542,0.00903382,0.0107693,0.0148219,0.0245155,0.00745417,0.00798284,0.00918101,0.012665,0.00648659,0.0108587,0.010772,0.0122431,0.0143661,0.00955381,0.008954,0.0196258,0.0108157,0.0140027,0.0252331,0.0140439,0.00718294,0.00632738,0.00943981,0.0141646,0.0128122,0.00700346,0.00790918,0.0104766,0.00834044,0.00887541,0.0129867,0.0318384,0.00838297,0.00910748,0.0117268,0.0132037,0.0153155,0.030606,0.0130995,0.0274743,0.012539,0.0233579,0.010912,0.00995029,0.00688301,0.00745162,0.0104447,0.0110033,0.0296967,0.0156635,0.00864287,0.028246,0.00752668,0.0130001,0.0131877,0.0104517,0.0310608,0.0123505,0.0143301,0.0368254,0.00846639,0.0123275,0.00843402,0.00825159,0.0127127,0.010597,0.0162743,0.0069984,0.00686607,0.0252033,0.0266398,0.0147029,0.0357754,0.00838259,0.0365071,0.00871506,0.0124994,0.0080792,0.0126899,0.0116308,0.0144831,0.0198826,0.00687389,0.00762098,0.0082063,0.00939814,0.00875107,0.00966622,0.0121298,0.00792187,0.0074288,0.00818593,0.013088,0.00722553,0.00938542,0.0131874,0.00823556,0.00834184,0.0111863,0.01105,0.0207876,0.0128502,0.00988916,0.00810044,0.00921043,0.00981003,0.0123612,0.00615526,0.0228839,0.0081402,0.00892164,0.0105193,0.0126251,0.0193888,0.00894589,0.0264696,0.00650963,0.0269201,0.0209995,0.00655672,0.00870198,0.0255667,0.00822637,0.00869689,0.00763086,0.00707033,0.0249417,0.00749827,0.00780819,0.00794333,0.0102873,0.0138054,0.00636956,0.024823,0.00708504,0.007452,0.0124809,0.028948,0.00761779,0.0084174,0.00617764,0.0071633,0.00818525,0.0106066,0.00842787,0.0109994,0.0244511,0.00719108,0.0075887,0.00881701,0.00985254,0.0113324,0.00939844,0.00887816,0.0136079,0.0132996,0.0101359,0.012482", "env/crashed_penalty": "-0.01,-0.01,-0.00999708,-0.00999727,-0.01,-0.01,-0.00999999,-0.00999999,-0.01,-0.01,-0.00999762,-0.01,-0.00999724,-0.00999999,-0.00999999,-0.00999999,-0.01,-0.00999999,-0.00999999,-0.00999999,-0.01,-0.00999999,-0.00999999,-0.00999999,-0.00999999,-0.00999999,-0.00999999,-0.01,-0.00999999,-0.00999999,-0.01,-0.00999999,-0.00999999,-0.01,-0.01,-0.01,-0.00999999,-0.01,-0.01,-0.01,-0.0100001,-0.01,-0.01,-0.01,-0.00999999,-0.01,-0.01,-0.00999999,-0.01,-0.00999999,-0.01,-0.01,-0.00999999,-0.01,-0.00999999,-0.00999999,-0.00999999,-0.01,-0.01,-0.01,-0.01,-0.01,-0.00999999,-0.00999999,-0.01,-0.00999999,-0.00999998,-0.00999999,-0.01,-0.00999999,-0.00999999,-0.01,-0.00999999,-0.01,-0.00999999,-0.01,-0.00999999,-0.01,-0.00999999,-0.00999792,-0.00999999,-0.01,-0.00999905,-0.01,-0.01,-0.00999999,-0.01,-0.00999999,-0.00999999,-0.01,-0.00999999,-0.00999999,-0.00999999,-0.01,-0.00999559,-0.00999999,-0.00999999,-0.01,-0.01,-0.00999709,-0.00999999,-0.01,-0.00999999,-0.00999999,-0.00999999,-0.00999999,-0.01,-0.01,-0.01,-0.01,-0.00999999,-0.00999905,-0.01,-0.00999999,-0.00999999,-0.00999998,-0.01,-0.00999999,-0.00999999,-0.00999154,-0.00999999,-0.00999999,-0.01,-0.01,-0.01,-0.00999999,-0.01,-0.01,-0.01,-0.00999999,-0.00999999,-0.00999999,-0.00999999,-0.00999999,-0.01,-0.00999999,-0.00999999,-0.00999999,-0.00999999,-0.01,-0.01,-0.00999999,-0.00999999,-0.00999999,-0.01,-0.00999999,-0.00999999,-0.00999999,-0.01,-0.00999999,-0.01,-0.01,-0.01,-0.01,-0.01,-0.01,-0.01,-0.01,-0.01,-0.00999768,-0.01,-0.00999999,-0.00999999,-0.00999999,-0.00999999,-0.01,-0.01,-0.00999999,-0.00999999,-0.00999999,-0.01,-0.00999999,-0.00999999,-0.01,-0.00999999,-0.00999999,-0.01,-0.01,-0.00999999,-0.00999999,-0.00999999,-0.01,-0.01,-0.00999999,-0.00999999,-0.01,-0.01,-0.01,-0.01,-0.00999999,-0.01,-0.00999999,-0.00999999,-0.00999999,-0.01,-0.00999999,-0.01,-0.00999769,-0.00999999,-0.00999999,-0.01,-0.00999999,-0.00999999,-0.01,-0.01,-0.00999999,-0.00999999,-0.00999999,-0.00999999,-0.01,-0.01,-0.00999762,-0.00999999,-0.00999999,-0.00999999,-0.00999999,-0.01,-0.01,-0.00999999,-0.00999999,-0.01,-0.00999999,-0.00999999,-0.00999999,-0.01,-0.01,-0.01,-0.01,-0.00999999,-0.00999999,-0.01,-0.00999999,-0.00999999,-0.00999999,-0.00999999,-0.01,-0.00999999,-0.00999999,-0.00999999,-0.00999999,-0.01,-0.01,-0.01,-0.00999999,-0.01,-0.01,-0.00999999,-0.01,-0.00999999,-0.00999999,-0.00999999,-0.01,-0.01,-0.00999999,-0.00999792,-0.01,-0.00999999,-0.00999999,-0.01,-0.00999999,-0.00999999,-0.00999999,-0.01,-0.01,-0.01,-0.00999999,-0.00999999,-0.01,-0.00999999,-0.00999999,-0.01,-0.01,-0.00999999,-0.00999999,-0.01,-0.01,-0.00999999,-0.00999636,-0.01,-0.00999999,-0.00999999,-0.01,-0.01,-0.01,-0.00999999,-0.01,-0.01,-0.00999999,-0.00999999,-0.01,-0.01,-0.00999999,-0.01,-0.01,-0.00999999,-0.00999999,-0.00999999,-0.00999999,-0.00999999,-0.01,-0.00999999,-0.00999999,-0.01,-0.01,-0.01,-0.00999999,-0.01,-0.01,-0.01,-0.00999999,-0.00999999,-0.00999999,-0.00999999,-0.01,-0.00999999,-0.00999999,-0.01,-0.01,-0.00999999,-0.00999999,-0.01,-0.00999999,-0.00999999,-0.01,-0.00999754,-0.00999999,-0.01,-0.01,-0.00999999,-0.01,-0.01,-0.00999999,-0.00999999,-0.00999999,-0.01,-0.00999999,-0.00999999,-0.00999999,-0.00999999,-0.00999999,-0.01,-0.00999999,-0.01,-0.00999999,-0.00999999,-0.00999999,-0.00999999,-0.00999999,-0.00999999,-0.00999999,-0.00999999,-0.00999999,-0.00999999,-0.00999999,-0.00999999,-0.00999999,-0.00999999,-0.00999999,-0.01,-0.01,-0.00999999,-0.00999999,-0.00999999,-0.00999999,-0.01,-0.00999999,-0.00999999,-0.00999999,-0.00999999,-0.00999999,-0.00999999,-0.01,-0.00999999,-0.01,-0.00999999,-0.00999999,-0.00999999,-0.00999999,-0.01,-0.01,-0.01,-0.00999999,-0.01,-0.01,-0.00999999,-0.01", "env/passed_cars": "128249,138445,2637.52,15451.1,92254.6,131134,21923.5,30219,84000.7,129490,4141.35,84977.4,3090,15517.8,27421.5,40235.7,131874,12229.7,23242.2,35455.1,118817,2450.49,8797.45,15999.6,23617.3,31460.9,39530.3,84633.5,1454.64,4971.39,117782,3556.25,12186.2,120098,123554,130221,21840.5,113774,132518,131265,192.292,137878,118057,139289,26274.7,136062,131977,3517.43,102781,41554.1,111404,1236.02,2505.44,93670.7,4069.94,27520.7,40889.6,136784,142514,886.516,132712,107395,28127.7,40716.2,131722,8602.26,58541.1,4389.39,134844,4226.11,38639.1,130627,28723.4,106212,12766.1,121413,38671.3,133838,3662.98,12464.7,24100,124674,104157,118284,119752,27222.3,129921,27802.8,41098.9,137414,27992.2,41758.3,746.055,47160.6,4433.96,41115,3765.91,132679,133573,2779.95,15504.6,97234.1,4187.18,37224.5,23129.5,34993.3,123236,139146,138893,86256.2,39719.6,131824,106911,488.682,31509,52609.7,129290,37724,1348.97,4699.51,15174.1,40349.5,65751.2,535.318,305.929,15383.1,90583.9,91187.4,92224.4,4556.08,4064.33,14555.7,26461.6,39061.3,127071,4772.66,16457,29295.4,42561,137208,81687.7,16223.1,12075.9,23501.9,122861,4348.28,26202.4,38493.2,126506,2275.55,38.0435,79621.7,123173,121233,141697,137768,134626,120531,4960.69,32552.9,114702,359.999,3760.9,55811.4,81625.2,115593,117809,4596.99,15429.6,25947.2,131203,21812.8,33319.2,120680,363.836,28979.8,140584,118039,4379.34,13202,23614.3,123743,137459,25897.9,39187,131949,16.2312,128644,132424,29960.1,104346,2760.09,10749.3,16754.7,102924,32075.4,110043,3481.82,13010.5,23705,121639,25715.5,38037,128214,125641,4813.75,16859,30036.5,43756.4,142076,121273,22622.8,2923.74,10094.1,19079.9,38579.4,103357,138815,5058.54,29870.1,142152,4029.99,13716.7,23307.6,133354,133695,116876,137519,13845.2,37320.2,124724,4052.58,14872.8,27204.1,39959.9,133042,13551.4,14799.5,27683.9,41340.2,140296,115602,103708,4257.1,128088,140897,4744.37,139858,28655.4,15730.2,28991.5,143267,138233,21722.6,33945.2,123584,13886,25537.3,128199,3729.43,11838.8,33828.8,117818,130649,145784,3585.77,11259.9,623.062,11718.4,4055.87,128703,81222.5,13006.3,25453.6,125731,129536,1555.94,5662.69,111646,2429.01,9303.53,136473,134991,127805,2625.52,92196.7,142333,4868.84,27754.7,134512,89108.6,14878.2,132296,110999,3673.47,12803.2,33014.1,3528.15,5113.91,148658,4962.86,28358.8,546.38,4826.78,135391,23223,130790,135450,137162,3714.84,14193.2,26230,38342.9,125196,27008.1,40072.7,134320,87230.2,12176.6,22466.9,137429,12673.3,35300.2,121669,11453.9,31323.4,110337,130410,4664.01,134280,121159,14128.7,25990.7,38165.6,125791,26222.9,3322.58,12397.8,21280.8,33667.4,114035,3584.85,117505,4591.61,15242.8,1309.75,4513.84,15259.8,39217.5,2393.52,8029.29,14425.1,29292.2,32333,3903.68,13711.1,25263.6,37834.4,126333,140844,23572.2,3984.32,13766.8,34978.6,134734,3789.33,12831.3,22719.3,11884.3,22344.1,33377.7,116435,34530.4,117261,4096.99,14330,25758.1,37437.5,122030,126471,118969,29000.1,137882,115546,31403.8,114517", "env/passed_by_enemy": "23832.5,22519.7,406.707,3159.94,17478.3,23286.4,4432.61,6064.91,15940,21687.2,634.651,15633.5,454.233,2985.96,5298.44,7777.2,23816.6,2471.96,4799.21,7318.69,23680.2,304.595,1533.9,2972.83,4404.73,5830.52,7256.92,14968,176.102,791.043,21483.3,570.827,2391.73,22714.4,21289,23259.3,4460.35,20412,23320.6,23563.9,95.2849,23445.6,21831.4,23007.5,4837.76,22706,22282.1,513.562,19798.1,7476.82,18790.9,135.909,387.227,18493.9,656.824,5333.32,7803.91,23796.9,23133.3,94.5371,23112.2,20645.3,5396.45,7846.57,24164.7,1571.56,10854.9,718.421,21961.3,701.632,7424.09,23199.4,5613.7,18468,2240.18,20379,7472.86,23295.8,595.684,2444.74,4769.21,23654.7,19490.2,20296,22810.4,5118,23119.3,5468.62,7907.4,23745.4,5141.39,7598.62,124.549,10294,673.072,7295.13,626.395,23876.1,23354,386.37,3116.69,17833.8,693.119,7531.42,4497.66,6665.66,21329.5,22930.3,23138.9,17137.5,7551.38,23627.5,19775.4,108.227,6082.69,9848.75,22517.5,7457.61,172.344,757.239,2975.79,7692.3,12088.7,86.1056,76.671,3085.85,18258.6,17404,17955.1,717.231,664.647,2795.38,5217.25,7657.6,24098,751.222,3035.62,5490.23,7926.44,23928.8,15481.8,3213.41,2358.91,4672.37,22907.1,700.614,5036.58,7424.8,23077.1,338.65,190.89,17049.5,21731.9,21494.2,23279.7,23268.5,22777.5,22564.6,765.749,6356.9,21027.9,98.7043,578.873,11121.1,15952.8,22234.3,22177,716.096,2869.92,4958.31,22738.3,4434.23,6783.27,22488.5,101.642,5205.53,23326.5,21515.1,682.352,2483.41,4499.04,22017.8,22557.8,4869.23,7336.91,23120.9,230.486,23180,22394.7,6128.07,20711.4,440.217,2108.29,3415.88,19293.4,6059.32,19937.2,560.29,2498.03,4527.77,21276.2,5016.89,7288.18,22307.7,22262.7,755.503,3014.09,5389.63,7757.68,23214.6,21768.6,4309.69,431.541,1906.22,3783.57,7634.68,18961.5,22255.6,708.943,5183.13,23058.7,635.995,2682.6,4623.99,23100.7,23117.6,21244.8,22487.4,2400.94,6562.69,20016,622.67,2667.9,4899.07,7075.65,21518.1,2540.77,2501.21,4738.35,6971.56,21321.6,21747,19545.7,714.8,23370.8,23230.2,725.872,23634.8,5900.48,3184.86,4959.78,23073.2,22927.4,4470.66,6915.38,22843.1,2571.22,4799.52,21754.8,549.724,2278.96,6421.78,20353.8,22154.3,22955.7,500.193,2014.74,109.554,2287.47,656.685,22985.2,15298.1,2538.16,5003.84,23836.6,22866.5,216.513,1022.84,21648.5,374.025,1845.09,23347.1,23031.5,22749.2,371.09,16698.5,22239,689.952,5014.56,22866.8,17319.1,2607.53,21726.8,20132.8,595.125,2431.36,6303.28,595.102,707.373,22276.2,700.725,4988.15,98.5203,765.394,23175.6,4666.65,23119.6,22627.2,22820.2,618.085,2694.05,5024.56,7478.9,23679.3,5330.13,7750.96,23619.7,17258,2300.97,4466.29,22911.6,2340.36,6565.47,20677.5,2188.14,6196.29,20399.6,23701.9,728.389,22482.6,22481.8,2563.38,4735.43,6901.42,21335.4,4967.56,525.818,2275.73,3930.86,6089.42,19064.5,619.213,21745.8,692.811,2730.43,175.904,722.02,2941.69,7588.47,353.287,1525.15,2922.97,6024.05,6552.63,622.899,2610.81,4877.53,7295.71,22788,22864.8,4670.81,621.932,2542.9,6603.8,22968.5,594.787,2461.8,4425.44,2307.69,4437.46,6571,20995.2,6425,20738.6,667.897,2827.5,5172.12,7482.26,23419.9,22654.3,22842.1,5256.12,23091.3,19379.5,5816.66,19461.9", "env/cars_to_pass": "2.15127,2.72207,6.05046,2.15527,2.03691,2.06553,2.09634,2.18897,2.15811,2.73789,9.16354,3.00068,4.44247,2.01739,2.03993,2.08188,2.15381,2.13639,2.17755,2.20129,2.52969,8.55151,2.14936,2.16748,2.03268,2.14405,2.01229,2.0458,21.9159,3.59575,2.78174,9.57335,4.77992,2.06025,2.7951,2.80605,2.03938,2.07207,2.76914,2.10918,99.4462,2.83154,2.0377,2.03193,2.1707,2.03965,2.64023,4.54266,2.09814,2.06329,1.94424,2.33785,13.6964,5.38359,6.84803,2.25867,2.19329,2.10654,1.94336,19.9349,2.80352,2.16396,2.08768,2.15838,2.14346,1.85975,2.00997,2.77996,2.62188,8.26553,1.95114,2.0249,1.68464,1.77813,2.64008,2.83125,2.09122,2.0042,11.1626,2.33147,2.19815,2.32549,2.10322,2.85068,2.10322,2.02088,2.06113,2.15721,2.13166,2.09717,1.89127,2.07626,36.8081,2.88691,6.82488,2.09307,8.11037,2.18213,2.07549,6.17678,16.3872,2.80086,5.48306,2.1259,2.02787,2.07568,2.09805,2.79785,1.98047,2.98027,2.17855,2.14941,2.92861,51.4836,2.81019,2.83996,2.6915,2.14234,16.6418,2.11513,2.0961,1.98844,2.01836,27.4653,44.1255,2.17159,2.37666,2.91436,2.01123,4.83025,6.94351,2.13162,2.14266,2.1585,2.4793,8.30344,2.19399,2.27646,2.0865,2.13271,2.97988,18.1037,1.90054,2.04459,2.00928,5.20223,1.97237,1.90565,2.00771,8.68775,199.157,2.98223,1.94053,1.99336,2.75586,2.02949,1.92871,2.87958,2.19278,2.0578,2.0707,63.7055,6.16552,2.11229,2.05611,2.11992,2.18613,8.85779,2.751,13.4019,2.75322,1.98726,1.97899,2.03096,55.2706,8.80971,2.77207,2.04805,7.52559,2.84709,14.3991,2.95732,1.86699,2.11026,2.08244,2.03057,199.721,2.12529,2.81416,2.15207,2.40996,13.6569,3.04146,33.8166,2.93633,2.73251,3.02783,7.65363,2.69752,13.7467,2.74824,1.95485,1.92715,1.87451,1.94043,8.68355,2.03721,1.9848,1.94788,1.95723,1.90664,2.10396,5.85809,1.87496,2.11353,2.08941,2.11006,1.78076,8.81934,11.0439,5.06973,10.9864,5.16403,16.3017,2.75508,2.89268,1.88135,2.66982,5.13486,5.27457,5.0043,3.88447,1.9332,1.85333,1.71084,1.83965,1.8602,1.80423,2.02443,1.95279,1.76553,2.00967,2.04727,11.5502,2.81875,1.97559,4.48673,2.85262,3.06369,2.04443,10.9818,2.77285,1.98008,1.97637,1.97296,2.03066,2.08756,2.06564,1.96035,9.1474,2.91809,2.79485,2.90146,2.03047,2.71318,4.44536,2.07926,37.1497,2.49988,6.6052,2.82021,2.92686,17.6421,10.2197,3.23867,2.78848,18.9917,2.79228,2.03203,8.25989,3.02313,2.02764,1.99941,2.05488,6.53375,2.99629,1.76494,6.81628,12.4025,2.76328,2.91347,2.62016,2.62734,2.09648,7.55916,2.70807,2.56501,9.99847,7.86237,2.56875,7.57104,11.7037,35.1691,2.17537,2.8501,2.18728,2.01611,1.96455,2.81494,8.97421,1.84518,2.06266,2.23741,2.19805,2.10175,2.03832,2.00029,1.91523,2.0885,2.40412,1.95576,2.85223,3.08269,2.75381,1.93708,2.07119,2.21074,2.94434,8.62513,2.61689,2.09326,2.0782,2.00134,2.01127,1.95049,1.85654,12.775,2.87819,15.9062,2.74356,2.75889,8.84807,2.79275,3.00924,2.61732,6.21649,3.22519,2.13162,1.8677,9.56448,2.21059,1.96543,2.04394,2.16722,5.9239,1.84182,1.85407,1.88119,1.87061,1.96367,1.82423,12.0212,5.01705,5.16599,2.04785,5.16738,1.85305,1.93668,1.83095,1.95192,2.05522,1.97002,2.28657,2.27754,6.51165,2.09596,2.18289,2.07015,2.21729,1.98516,2.09736,8.89704,2.78457,2.82998,2.02627,2.01348", "env/days_completed": "187.078,186.428,5.89924,33.6828,147.766,185.672,40.2915,52.7346,128.738,176.947,7.63377,123.127,6.5113,26.5378,45.1881,63.9511,187.465,25.7924,44.43,63.1922,186.688,4.51414,15.0311,26.0544,37.079,48.1024,59.1278,118.484,3.40586,12.4889,176.354,7.02242,22.6849,186.418,171.476,186.455,44.7364,168.066,186.467,186.871,0.317121,185.955,184.426,186.852,42.1509,180.637,186.494,7.63115,173.277,66.2395,155.949,2.52977,5.74584,148.297,8.24201,43.8748,62.4531,185.387,187.363,1.72172,186.623,169.031,45.1425,63.8505,187.355,18.5455,91.6992,8.95225,186.675,8.29472,63.7518,187.27,51.0824,156.656,22.4602,166.139,62.3573,185.875,7.57814,25.4873,44.1297,186.398,164.854,162.795,186.223,44.9785,186.555,45.0957,63.8036,187.316,44.2954,63.0643,2.03703,97.1095,8.28275,63.7011,7.81877,186.324,186.105,6.04883,31.3886,147.462,8.28484,63.7802,39.8641,56.7443,170.602,186.693,187.066,142.11,63.1503,186.667,158.346,1.38257,53.6501,83.0586,186.443,63.0144,3.19224,11.5083,29.9496,66.9664,101.551,1.12333,0.583286,33.6832,151.984,143.107,159.566,8.33538,8.23875,26.3704,45.0605,63.7685,187.273,8.34008,26.53,45.2317,63.9432,187.461,129.369,31.4685,24.9497,43.6078,185.871,8.29819,45.1112,63.869,187.387,5.15498,0,145.385,184.914,178.832,186.553,186.398,187.227,183.438,9.42284,56.8526,170.48,0.790298,7.83315,98.9524,136.373,185.059,179.512,8.11503,25.8056,42.04,182.764,43.9216,62.6204,186.129,0.948132,43.9412,186.697,179.285,8.03866,23.0715,38.1037,171.795,185.887,44.109,62.664,184.863,0,186.934,179.029,55.2577,166.971,5.91232,19.9854,29.2004,150.361,54.0179,161.623,7.49034,24.6362,40.4458,178.232,44.4302,63.033,185.91,184.629,8.35817,26.5675,45.2636,63.9716,187.484,184.922,39.4748,6.3006,20.628,35.6245,65.6305,154.094,186.641,8.2371,43.4878,184.566,7.47605,23.9421,38.903,186.447,186.592,186.156,185.119,22.1969,54.3531,162.457,7.90632,25.454,43.5485,61.6441,181.281,24.729,24.9266,42.8949,60.8591,179.93,184.207,163.867,8.21472,186.596,187.281,8.3468,186.782,52.0244,36.6562,43.1746,186.396,186.828,43.7646,62.5091,186.023,24.4953,41.9849,176.25,7.3148,22.1866,54.8672,164.967,178.887,186.658,6.79328,21.7583,1.40071,25.3135,8.18547,186.541,125.053,23.6779,43.3533,186.42,186.498,3.79228,13.5379,182.094,5.66687,19.1631,185.5,185.402,186.062,5.38325,134.542,185.574,8.30644,43.2098,186.725,145.653,24.9542,178.619,166.047,7.18416,23.2929,56.5885,7.52784,8.33306,186.752,8.22511,43.2572,1.1919,9.21809,186.396,42.8432,185.102,187.328,185.291,7.96954,26.0649,44.7182,63.4683,186.984,45.08,63.788,187.301,147.219,23.272,40.3615,187.113,22.5892,55.4149,166.287,22.4098,54.5839,163.215,186.693,8.29888,186.713,186.574,23.6578,40.7589,57.861,171.992,45.1473,6.33207,20.6917,33.1784,50.4199,152.764,7.77206,179.387,8.31529,25.7527,3.00473,8.4304,26.6084,63.9935,5.18725,17.1039,29.64,54.8356,56.2529,8.16919,26.2294,44.8613,63.6371,187.152,187.34,44.7188,7.32693,23.5098,56.8798,186.16,7.88685,25.2395,43.0277,23.1199,40.0622,57.0034,170.668,56.3995,168.113,8.01399,25.7329,43.9849,62.2382,183.293,186.93,185.828,43.9828,186.717,154.463,51.0195,157.809", "env/days_failed": "1.42188,2.07227,1.30034,1.77021,1.73438,2.82812,2.76172,2.76172,2.76172,2.55273,1.13251,3.37305,1.09931,1.03098,1.08266,1.03125,1.03516,1.77639,1.84073,1.79007,1.8125,1.00236,1.01352,1.01562,1.01562,1.01562,1.01562,1.01562,1.69454,2.23832,3.14648,1.16463,1.32864,2.08203,3.02237,2.04492,1.53434,1.43359,2.0332,1.62891,1.02434,2.54492,4.07422,1.64844,2.86328,2.86328,2.00586,1.17616,3.22266,2.55078,2.55078,0.434715,1.60919,4.20312,1.12021,2.11328,2.11328,2.11328,1.13672,1.00631,1.87695,2.46875,1.13672,1.13672,1.14473,1.79813,1.80078,0.407566,1.82451,1.0675,1.23047,1.23047,2.83955,2.84375,1.75854,2.36133,2.625,2.625,1.78408,2.08149,2.14102,2.10156,2.64609,4.70508,2.27734,1.30078,1.94531,1.18359,1.18359,1.18359,1.97539,1.91797,2.49547,4.39053,1.07947,1.28125,1.26108,2.17578,2.39453,1.16546,4.04362,2.03643,1.07739,1.20211,1.89844,1.89844,1.89844,1.80664,1.43359,2.38851,1.83203,1.8335,2.1543,2.50844,3.82608,3.94141,2.05664,1.25,1.44959,1.88794,1.94617,1.94922,1.94922,1.0081,1.00723,3.49441,3.51631,2.39258,3.93359,1.02444,1.13262,1.21267,1.21875,1.21875,1.22656,1.02214,1.03879,1.03906,1.03906,1.03906,2.13086,5.19981,2.6191,2.66297,2.62891,1.06403,1.15959,1.11328,1.11328,1.19879,1.89696,3.11514,3.58594,2.66797,1.94727,2.10156,1.27344,3.06055,1.0517,2.01953,2.01953,2.77296,1.16469,3.44141,3.44141,3.44141,2.98828,1.03604,1.11486,3.13726,1.73633,2.35761,2.3668,2.37109,1.70404,2.3381,1.80273,2.21484,1.03645,2.12185,4.20891,2.70508,2.61328,1.68811,1.63672,1.63672,1.64241,1.56641,3.4707,2.502,2.52861,1.46051,1.61176,7.11317,2.13867,1.45105,1.87695,1.44641,1.66035,3.69642,2.26758,1.58556,1.58812,1.58984,3.87109,1.0132,1.01562,1.01562,1.01562,1.01562,3.57812,1.35264,1.20859,1.39038,1.40002,1.40625,1.40625,1.85938,1.13427,2.79147,3.93359,1.16914,1.47114,3.77321,2.05273,1.9082,2.34375,3.38086,1.81662,2.32703,4.04297,1.1592,1.21875,1.21875,1.21875,1.21875,1.14391,1.57031,1.57031,1.57031,1.57031,4.29297,4.63281,1.1475,1.9043,1.21875,1.01301,1.71618,2.18501,2.45438,3.09616,2.10352,1.67188,2.50618,2.47325,2.47656,1.24073,1.24351,1.25,1.09009,1.97039,2.10144,2.5332,2.61328,1.8418,1.02182,1.1592,1.85475,2.13364,1.17675,1.95898,4.44727,3.89093,2.91748,2.08008,2.00195,1.55278,1.96552,6.40625,1.46667,1.7172,3,3.09766,2.4375,1.1135,1.95566,2.92578,1.05578,3.06096,1.77539,3.8452,1.27825,1.88086,3.45312,1.20369,1.32904,1.46205,1.22913,1.04661,1.74805,1.12832,2.928,1.00699,1.07127,2.10352,3.42759,3.39844,1.17188,2.20898,1.39268,1.50391,1.55253,1.51398,1.51562,1.19922,1.19922,1.19922,3.28125,1.98563,2.06108,1.38672,1.66599,1.84976,2.21289,1.25645,1.28125,1.28516,1.80664,1.06334,1.78711,1.92578,1.50781,1.50781,1.50781,1.50781,1.13198,1.14154,1.2184,3.65509,1.33498,1.73633,1.20842,2.11144,0.710625,0.800359,0.86577,0.929416,0.955823,0.984375,1.13528,1.33125,1.41033,1.44062,2.25033,1.19303,1.33943,1.40951,1.34518,1.34766,1.16016,1.55197,1.16616,1.44249,1.98349,2.33984,1.12288,1.28735,1.51139,1.82371,1.82812,1.83177,1.83203,1.36019,1.38672,1.13707,1.1875,1.19234,1.20091,1.20703,1.57031,2.67188,2.29644,1.7832,2.03711,3.69141,3.69141", "env/collisions_player_vs_car": "4833.57,4802.85,115.605,730.494,3732.83,4752.83,997.72,1332.91,3325.72,4471.8,170.436,3104.49,121.735,692.371,1188.19,1712.62,4845.02,593.12,1087.7,1608.01,4697.12,87.529,359.17,654.208,945.358,1232.23,1515.05,2994.67,55.637,225.491,4552.19,155.561,543.35,4848.54,4351.64,4831.94,1058.89,4328.37,4894.33,4638.34,17.8343,4719.94,4719.9,4564.73,1094.1,4524.48,5003.73,149.053,4218.64,1712.24,3994.08,44.6079,111.972,3817.32,185.852,1113.28,1589.69,4615.22,4724.98,30.5984,4879.76,4345.35,1200.01,1701.96,4794.57,419.813,2397.69,201.465,4881.66,174.023,1608.83,4785.59,1361.54,4199.39,567.853,4129.43,1659.07,4799.95,158.576,560.78,1053.14,4749.01,4337.47,4108.04,4932.44,1179.13,4760.74,1092.56,1567.1,4585.66,1144,1650.34,40.1374,2365.48,185.061,1637.25,173.636,4663.79,4657.36,115.963,753.597,3769.99,193.436,1662.77,1042.82,1488.01,4336.46,4645.85,4691.59,3629.05,1651.05,4739.03,4021.06,32.3514,1369.53,2144.88,4829.82,1639.7,55.989,214.394,731.504,1738.95,2647.63,26.0511,23.1994,712.469,3723.2,3692.81,4026.34,182.214,188.41,680.214,1180.54,1678.26,4747.44,183.564,657.766,1143.13,1624.84,4676.86,3359.45,793.269,603.282,1115.99,4881.65,194.292,1226.28,1763,5018.11,103.755,10.902,3779.47,4777.39,4584.25,4700.05,4707.37,4889.45,4677.32,202.985,1512.03,4509.51,30.2738,166.134,2516.81,3516.12,4810.77,4733.48,187.777,679.308,1139.9,4798.51,1086.01,1592.89,4836.33,29.1916,1157.52,4742.53,4526.41,166.12,580.413,979.292,4270.46,4795.62,1137.42,1652.13,4802.14,4.93419,4863.17,4485.98,1361.04,4187.98,126.019,503.358,743.362,3860.67,1480.16,4223.55,155.266,606.509,1044.6,4624.48,1149.43,1653.42,4852.85,4924.81,191.131,685.291,1186.93,1679.4,4786.69,4754,1025.34,129.865,508.728,930.461,1754.78,4048.85,4861.7,178.697,1107.54,4615.33,158.419,584.864,994.297,4786.49,4850.84,4777.28,4684.9,548.48,1377.1,4050.57,172.661,655.309,1153.96,1648.22,4728.69,641.502,626.264,1117.94,1589.02,4600.74,4672.51,4219.91,187.626,4918.96,4667.44,182.586,4720,1331.63,798.395,1113.79,4689.42,4736.61,1060.16,1587.82,4831.92,610.332,1077.84,4451.37,154.751,535.141,1407.02,4200.3,4461.99,4636.16,142.956,532.237,35.1715,540.142,179.533,4934.3,3172.62,607.972,1136.93,4767.31,4841.05,67.3275,282.692,4642.95,108.3,449.063,4662.54,4685.05,4830.88,104.447,3311.81,4731.54,167.576,1106.02,4755.54,3703.45,637.841,4627.31,4272.48,157.769,588.87,1492.75,160.51,183.021,4753.35,174.116,1119.2,31.8868,213.018,4703.66,1053.75,4686.57,4955.33,4490.89,178.704,688.881,1199.91,1704.75,4924.51,1149.11,1645.27,4767.1,3972.73,570.351,1013.07,4823.57,569.061,1452.84,4249.82,552.403,1410.69,4176.73,4804.97,191.214,4882.32,4871.88,602.672,1063.1,1519.9,4442.83,1208.62,145.486,526.837,857.431,1305.65,3869.26,179.043,4807.42,189.366,689.288,56.5308,193.915,703.576,1728.11,104.733,396.868,713.34,1395.54,1507.09,179.218,661.801,1173.84,1713.74,5040.58,4744.64,1155.29,167.791,615.029,1522.32,4799.19,164.853,626.547,1070.14,600.62,1084.46,1548.93,4532.14,1460.8,4242.11,181.643,670.63,1172.37,1655.13,4791.54,4875.8,4892.57,1131.76,4685.15,3873.62,1288.71,3977.89", "env/collisions_player_vs_road": "5092.53,4966.94,166.176,839.036,4006.76,4978.97,1218.51,1576.31,3679.88,4734.74,239.266,3297.17,175.303,772.575,1296.31,1840.83,5030.17,768.45,1319.87,1883.25,5061.43,132.473,425.937,729.558,1028.35,1322.74,1611.17,3111.74,119.565,340.216,4946.06,233.855,649.504,5183.67,4559.12,5099.42,1228.19,4756.54,5180.04,4832.86,37.0355,4862.07,4980.92,4794.57,1185.64,4690.02,5364.98,202.428,4484.7,1975.53,4366.48,80.8387,169.815,4052.27,251.963,1215.97,1701.66,4748.44,4905.04,58.9933,5142.82,4581.49,1312.51,1838.22,4962.77,583.342,2676.1,260.324,5171.52,262.863,1804.99,5068.73,1594.87,4637.03,664.864,4342.83,1773.37,4950.59,232.404,683.756,1207.69,5084.11,4539.62,4245.51,5156.59,1329.38,5042.01,1197.52,1695.58,4791.68,1261.93,1789,77.2918,2466.31,250.641,1760.16,239.941,4844.6,4813.06,188.294,940.554,4100.03,272.088,1836.07,1180.67,1639.42,4513.02,4758.68,4851.59,3834.51,1840.48,4972.68,4179.7,60.5408,1466.85,2252.69,5248.18,1840.44,97.0116,274.786,820.193,1849.23,2769.1,63.5127,41.9849,833.628,3988.38,3968.15,4140.83,285.339,267.867,796.081,1322.68,1845.61,5032.24,238.917,734.314,1239.29,1731.65,4825.17,3637.88,920.475,694.62,1233.89,5144.07,290.992,1500.37,2088.64,5539.65,159.076,83.2115,3957.46,5078.91,4868.92,4850.09,4867.12,5182.04,4959.67,267.45,1621.75,4679.3,54.1118,232.319,2740.76,3782.38,5121.86,4968.43,244.564,779.165,1273.88,4998.72,1222.32,1766.53,5153.61,72.4459,1285.53,4972.71,4980.93,252,685.445,1093.95,4434.05,4978.63,1277.66,1812.97,5016.92,95.3866,5288.74,4639.2,1511.88,4460.76,177.277,573.672,827.482,3955.23,1671.91,4496.14,226.514,733.841,1196.72,4872.46,1320.03,1853.46,5153.89,5109.19,268.884,797.689,1320.83,1833.33,5023.01,5013.27,1134.96,193.933,605.51,1055.6,1917.83,4243.13,5172.79,241.643,1210.85,4795.61,218.94,673.876,1105.97,5050.95,5071.57,5277.8,4859.26,658.664,1514.39,4312.95,279.836,855.115,1408.61,1943.97,5119.63,816.842,745.043,1279.28,1774.45,4873.38,5025.18,4420.35,303.516,5304.3,4930.93,281.147,4904.49,1455.81,864.996,1225.72,4862.12,5015.99,1195.09,1752.33,5087.73,772.467,1271.08,4698.7,239.297,641.008,1540.59,4396.82,4607.07,4830.16,206.761,647.89,66.3222,706.49,299.919,5343.69,3251.56,762.767,1336.62,5133.28,5192.1,122.936,353.285,4902.91,159.329,536.866,4901.9,4961.72,5071.41,170.204,3508.26,4981.77,220.703,1227.54,5153.42,4026.84,756.159,4855.21,4360.91,242.99,727.428,1729.01,219.342,281.55,5049.66,226.63,1244.78,57.5296,270.652,4980.23,1176.04,4854.48,5245.28,4644.08,253.571,805.828,1334.46,1864.43,5177.64,1275.76,1790.9,4970.32,4106.1,685.108,1171.76,5157.26,679.141,1595.01,4420.42,656.601,1640.38,4484.02,5085.32,256.742,5218.75,5173.78,708.338,1185.86,1655.75,4634.38,1378.87,211.515,619.457,962.957,1422.59,4019.81,273.09,5260.21,263.374,809.032,118.413,261.473,813.309,1892.99,180.385,543.31,909.35,1671.59,1833.54,259.445,812.631,1378.21,1974.49,5583.99,4959.91,1384.12,243.105,744.465,1773.46,5044.39,233.808,745.216,1225.06,690.739,1197.77,1681.97,4821.84,1595.47,4407.92,257.871,792.62,1325.86,1840.79,5130.75,5349.74,5061.46,1277.93,4913.35,3983.21,1425.85,4155.52", "env/n": "10240,10240,256,241.762,10240,10240,256,256,10240,10240,256,10240,256,256,242.571,256,10240,256,243.833,256,10240,256,256,256,256,256,256,10240,256,256,10240,256,256,10240,10239,10240,244.412,10240,10240,10240,1024,10240,10240,10240,256,10240,10240,256,10240,256,10240,512,256,10240,256,256,256,10240,10240,512,10240,10240,256,256,10240,256,9728,256,10240,256,256,10240,256,10240,256,10240,256,10240,256,256,244.307,10240,10240,10240,10240,256,10240,256,256,10240,242.466,256,256,10240,256,256,256,10240,10240,256,238.389,10239,256,256,256,256,10240,10240,10240,10239,256,10240,10240,256,256,8960,10240,256,256,256,256,256,10240,512,512,246.764,10240,10240,10240,256,256,256,256,256,10240,256,256,256,256,10240,10240,239.149,256,246.883,10240,256,242.519,256,10240,256,512,10240,10240,10240,10240,10240,10240,10239,512,256,10240,256,256,256,256,10240,10240,256,256,242.132,10240,256,256,10240,256,248.227,10240,10240,256,256,241.208,10240,10240,243.385,256,10240,512,10240,10240,256,10240,256,256,204.527,10240,256,10240,256,256,241.803,10240,256,256,10240,10240,256,256,256,256,10240,10240,241.448,256,256,256,256,10240,10240,256,248.319,10240,256,256,241.504,10240,10240,10240,10240,256,256,10240,256,256,256,256,10240,256,256,256,256,10240,10240,10240,256,10240,10240,256,10239,256,246.524,234.782,10240,10240,247.199,256,10240,256,256,10240,256,256,256,10240,10240,10240,256,256,512,256,256,10240,10240,236.818,234.94,10240,10240,256,256,10240,256,256,10240,10240,10240,256,10239,10240,256,234.677,10240,10239,256,10240,10240,256,256,256,256,256,10240,256,247.31,512,512,10240,247.935,10240,10240,10240,256,256,243.202,256,10240,256,256,10240,10240,256,242.968,10240,255.857,255.715,10240,256,256,10240,10240,256,10240,10240,256,256,256,10240,256,256,256,239.02,256,10240,256,10239,256,256,256,256,256,256,256,256,256,256,256,256,256,243.045,256,10240,10240,243.939,256,256,256,10240,256,256,228.8,256,256,256,10240,256,10240,256,256,256,256,10240,10240,10240,248.227,10240,10240,256,10240", "wandb": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "rank": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "world_size": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "gpu_id": "5,0,5,5,5,3,5,5,5,0,1,0,3,2,2,2,2,5,5,5,5,2,2,2,2,2,2,2,0,0,0,4,4,4,3,2,4,5,0,4,4,1,1,2,5,5,1,0,2,3,3,1,1,1,4,5,5,5,2,5,3,3,1,1,1,1,1,3,1,4,4,4,5,5,2,2,2,2,5,5,5,5,2,1,2,1,3,3,3,3,2,2,4,4,5,5,2,1,4,5,5,5,1,1,5,5,5,1,4,2,2,2,1,0,0,0,0,1,2,2,2,2,2,5,4,3,3,2,2,4,3,3,3,3,3,5,5,5,5,5,4,0,1,1,1,1,1,1,1,3,5,5,1,0,5,4,0,5,2,4,4,5,4,5,5,5,3,5,5,5,5,5,5,5,4,3,3,5,4,1,1,1,3,0,0,0,4,3,3,2,2,3,3,3,3,0,0,1,1,1,1,0,0,0,2,4,4,4,4,4,1,4,3,3,3,3,3,5,1,1,1,1,1,1,4,1,4,3,3,3,3,2,2,2,2,2,1,1,1,1,1,2,4,3,3,1,1,1,1,2,5,5,3,3,3,3,1,1,1,4,2,2,2,5,4,0,0,3,1,4,4,4,3,3,3,4,3,3,5,4,4,1,4,1,5,5,2,3,3,3,3,1,1,3,0,0,0,1,3,3,5,5,5,5,2,5,5,1,4,4,4,4,4,4,4,4,4,5,1,1,3,1,1,1,2,2,2,2,5,5,3,0,0,0,0,2,1,1,1,1,1,4,4,3,3,4,3,3,3,5,5,5,5,5,5,5,5,5,5,1,2,4,4,4,5,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,5,0,0,0,3,3", "profile": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "checkpoint_interval": "200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200", "eval_episodes": "10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000", "cudagraphs": "10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10", "seed": "73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73", "vec/total_agents": "256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,1024,256,256,256,256,256,256,256,256,256,256,512,256,256,256,256,256,256,256,512,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,512,512,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,512,256,256,256,256,256,256,256,512,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,512,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,512,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,512,512,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256", "vec/num_buffers": "4.21722,5.00124,4.76828,4.76828,4.76828,4.93252,4.95369,4.95369,4.95369,5.24013,3.41452,5.48275,4.14424,4.65502,4.65502,4.65502,4.65502,4.99969,4.99969,4.99969,4.99969,4.00702,4.00702,4.00702,4.00702,4.00702,4.00702,4.00702,3.7991,3.7991,5.25895,3.04728,3.04728,4.68497,5.1073,3.62607,4.13605,4.50868,3.4088,4.21174,5.83562,5.53404,4.34368,4.44933,4.02808,4.02808,3.87473,4.52759,4.14545,4.08359,4.08359,4.71625,6.28694,6.28694,4.62307,4.84937,4.84937,4.84937,4.90073,3.46973,3.53632,4.04648,4.68589,4.68589,4.68589,4.64147,4.64147,5.4648,5.8128,4.77623,4.77623,4.77623,4.93684,4.93684,5.8177,5.8177,4.42432,4.42432,4.55026,4.55026,4.55026,4.55026,4.87132,5.15111,4.12474,4.35436,4.06757,4.40981,4.40981,4.40981,2.56751,2.56751,3.83006,3.83006,4.76119,4.76119,6.65484,4.75269,4.72085,5.97297,5.97297,5.97297,4.67072,4.67072,4.07774,4.07774,4.07774,3.5051,4.42074,5.36002,4.93208,4.93208,3.39312,5.0287,5.0287,5.0287,5.48274,4.01987,4.84123,4.84123,4.84123,4.84123,4.84123,4.29352,5.80188,4.39312,4.39312,3.80506,4.66913,4.89045,4.42425,4.42425,4.42425,4.42425,4.42425,4.15111,4.15111,4.15111,4.15111,4.15111,5.12519,6.44803,4.40667,4.40667,4.40667,4.37313,4.37313,4.37313,4.37313,4.64352,7.24574,5.23734,4.93274,4.12128,3.83728,4.91253,4.30803,3.37587,4.97691,4.21005,4.21005,4.73905,4.76697,4.32578,4.32578,4.32578,4.82673,5.07421,5.07421,5.07421,5.07421,4.67959,4.67959,4.67959,6.20341,5.39027,5.39027,4.38706,4.88046,5.51358,5.51358,5.51358,4.37763,4.27403,4.27403,4.27403,7.6194,4.75103,5.61867,4.97113,4.97113,5.73237,5.73237,5.73237,5.73237,3.98555,3.98555,3.99565,3.99565,3.99565,3.99565,4.74039,4.74039,4.74039,4.49109,4.62902,4.62902,4.62902,4.62902,4.62902,4.4984,4.19579,4.72526,4.72526,4.72526,4.72526,4.72526,4.58957,6.01036,6.01036,6.01036,6.49963,6.49963,6.49963,3.76003,5.07822,4.71436,5.03351,6.03957,6.03957,6.03957,4.03655,4.03655,4.03655,4.03655,4.03655,2.89361,4.97511,4.97511,4.97511,4.97511,4.70565,4.8868,5.04041,5.04041,2.73424,5.71218,5.71218,5.8417,4.55999,5.276,5.276,4.1828,4.83018,4.83018,4.83018,4.73613,4.73613,4.73613,2.78784,5.45029,5.45029,5.45029,4.95611,3.1419,4.58408,4.58408,4.30382,4.67535,3.81495,3.81495,5.07379,5.59148,5.59148,5.59148,3.26914,3.93321,3.93321,4.37945,3.99733,3.99733,4.49156,4.12482,4.99373,3.78836,3.78836,4.87142,5.26691,5.26691,5.26691,3.80505,5.13042,5.13042,4.35411,5.42633,5.42633,5.42633,5.71889,3.66627,3.66627,6.05368,6.05368,4.35197,4.35197,5.26534,4.70873,4.70873,4.16856,3.71243,4.12354,4.12354,4.12354,4.12354,4.12354,4.60073,4.60073,4.60073,4.95555,4.89933,4.89933,4.59664,3.67741,3.67741,3.67741,4.95553,4.95553,4.95553,3.71208,3.09835,3.09835,4.97468,2.38295,2.38295,2.38295,2.38295,4.4741,3.73553,3.73553,3.73553,3.73553,3.73553,3.24379,3.24379,3.38272,3.38272,5.65109,4.82881,4.82881,4.82881,4.00912,4.00912,4.00912,4.00912,4.40193,4.50891,4.50891,4.50891,4.50891,4.50891,4.92133,4.49479,6.98954,6.98954,6.98954,4.67218,4.55155,4.55155,4.55155,4.07394,4.07394,4.07394,4.07394,4.14279,4.14279,4.22225,4.22225,4.22225,4.22225,4.22225,4.38275,4.85602,3.30449,3.30449,3.98064,4.12205,4.12205", "vec/num_threads": "2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2", "env/width": "152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152,152", "env/height": "210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210,210", "env/car_width": "16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16", "env/car_height": "11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11", "env/max_enemies": "10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10", "env/continuous": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "policy/hidden_size": "256,128,256,256,256,128,128,128,128,256,256,128,256,256,256,256,256,128,128,128,128,128,128,128,128,128,128,128,64,64,256,128,128,256,256,256,128,128,128,256,64,128,256,256,256,256,256,128,128,256,256,128,128,128,128,256,256,256,256,128,128,256,128,128,128,128,128,128,256,64,64,64,256,256,256,256,128,128,128,128,128,128,128,256,128,256,128,128,128,128,256,256,128,128,128,128,256,256,128,256,256,256,256,256,256,256,256,256,128,256,128,128,256,128,128,128,256,256,256,256,256,256,256,64,128,128,128,256,256,256,128,128,128,128,128,256,256,256,256,256,128,128,128,128,128,128,128,128,128,128,256,64,256,256,256,256,256,128,256,128,128,128,256,128,128,128,128,128,128,128,128,128,128,128,128,128,128,128,256,128,128,128,256,64,64,64,64,256,256,256,256,64,64,64,64,128,128,256,256,256,256,256,256,256,256,256,256,256,256,256,128,512,128,128,128,128,128,256,256,256,256,256,256,256,256,512,128,256,512,512,512,256,256,256,256,256,256,256,256,256,256,128,128,64,64,256,128,128,256,128,256,256,256,128,128,128,256,256,256,128,256,256,256,256,128,128,128,64,128,256,256,256,256,256,256,128,64,64,128,256,256,128,256,256,128,128,256,256,256,256,128,256,256,128,128,128,128,256,256,256,256,256,128,128,128,128,128,512,256,128,128,128,128,128,128,128,128,128,128,128,256,256,256,256,256,256,256,256,256,256,128,128,128,128,128,128,128,128,128,128,128,128,128,256,256,256,256,256,256,64,64,64,64,256,128,128,128,128,128,256,128,128,128,128,64,64,64,64,256,256,256,256,128,128,128,128,128,128,128,256,128,256,256,512,128,128", "policy/num_layers": "1.57339,2.44982,1.1042,1.1042,1.1042,3.16797,1.58095,1.58095,1.58095,2.11796,2.22087,3.52854,1.3478,2.27772,2.27772,2.27772,2.27772,1,1,1,1,2.68359,2.68359,2.68359,2.68359,2.68359,2.68359,2.68359,2.27105,2.27105,1.22167,3.14695,3.14695,1,2.46081,1,1.26473,1,2.11664,2.21077,1,2.74861,1.73755,2.27836,4.29554,4.29554,1,1,1,2.23432,2.23432,1,1.09217,1.09217,1.5755,2.35403,2.35403,2.35403,2.20446,1.47048,2.73461,1,3.27126,3.27126,3.27126,1.6668,1.6668,1,2.53428,2.25313,2.25313,2.25313,1,1,3.05912,3.05912,2.62684,2.62684,1.26469,1.26469,1.26469,1.26469,1.61376,4.3711,1.44301,1,2.60757,2.53838,2.53838,2.53838,2.60339,2.60339,1.10127,1.10127,3.76908,3.76908,1.46128,2.08152,2.29467,1,1,1,1,1,2.73208,2.73208,2.73208,2.01775,2.53136,1.18258,2.11063,2.11063,1,2.65025,2.65025,2.65025,2.34435,1,1.75167,1.75167,1.75167,1.75167,1.75167,1.11819,1,1.43029,1.43029,1.74609,1,3.00597,1.82884,1.82884,1.82884,1.82884,1.82884,2.53624,2.53624,2.53624,2.53624,2.53624,1.82608,1.32709,1,1,1,1,1,1,1,1.50051,3.22054,1.03002,1.6489,1,2.2944,2.68045,2.90553,1.27057,1.19908,1,1,3.19199,1.02011,1.05526,1.05526,1.05526,1,2.20523,2.20523,2.20523,2.20523,1.58429,1.58429,1.58429,4.79174,2.2696,2.2696,1.5797,2.52781,2.35666,2.35666,2.35666,2.57968,2.82606,2.82606,2.82606,3.26227,1,2.42332,1,1,2.19043,2.19043,2.19043,2.19043,1,1,1.23108,1.23108,1.23108,1.23108,1.41428,1.41428,1.41428,1,2.28377,2.28377,2.28377,2.28377,2.28377,2.11543,1.83478,1,1,1,1,1,2.43871,2.62647,2.62647,2.62647,2.00488,2.00488,2.00488,2.90223,1.44082,1.89991,3.84765,3.44646,3.44646,3.44646,2.49167,2.49167,2.49167,2.49167,2.49167,3.19069,2.35621,2.35621,2.35621,2.35621,1,2.23113,2.22086,2.22086,2.24078,3.09748,3.09748,1.52362,1,2.23883,2.23883,2.28778,1,1,1,2.10644,2.10644,2.10644,2.5071,2.75482,2.75482,2.75482,2.69668,3.1989,1.02783,1.02783,1.47361,1.57827,1,1,2.47407,1.19448,1.19448,1.19448,1.49654,1.54712,1.54712,1.45847,1.58387,1.58387,2.05679,2.34574,1,3.5901,3.5901,3.01988,2.34248,2.34248,2.34248,1.4852,2.4246,2.4246,2.08415,3.34597,3.34597,3.34597,1.23335,3.12583,3.12583,2.38932,2.38932,1.82807,1.82807,2.13481,2.07504,2.07504,1.42,3.72159,1,1,1,1,1,2.02369,2.02369,2.02369,1,2.64666,2.64666,2.0082,2.42123,2.42123,2.42123,1,1,1,1.77903,2.38569,2.38569,1.0347,2.24857,2.24857,2.24857,2.24857,2.18722,2.59124,2.59124,2.59124,2.59124,2.59124,1,1,2.35292,2.35292,2.51669,2.86316,2.86316,2.86316,1,1,1,1,1.55292,1,1,1,1,1,2.067,1.83858,2.69532,2.69532,2.69532,2.13045,1,1,1,1,1,1,1,2.07054,2.07054,1.07419,1.07419,1.07419,1.07419,1.07419,1,1.26973,2.67031,2.67031,2.40534,3.04148,3.04148", "policy/expansion_factor": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "legacy/torch_deterministic": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "legacy/cpu_offload": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "legacy/compile": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "legacy/compile_fullgraph": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "train/gpus": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "train/seed": "42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42", "train/total_timesteps": "600,600,461.223,461.223,461.223,600,399.039,399.039,399.039,568.957,561.796,379.69,487.549,600,600,600,600,600,600,600,600,353.625,353.625,353.625,353.625,353.625,353.625,353.625,324.798,324.798,569.118,523.642,523.642,600,552.105,600,600,531.609,600,600,320.626,600,600,600,583.762,583.762,600,564.242,555.988,493.852,493.852,379.174,471.129,471.129,600,596.04,596.04,596.04,600,344.777,600,539.402,600,600,600,267.191,267.191,600,600,600,600,600,498.645,498.645,528.431,528.431,600,600,600,600,600,600,524.964,526.096,600,600,600,600,600,600,600,600,290.304,290.304,600,600,582.081,600,600,460.618,460.618,460.618,600,600,541.788,541.788,541.788,600,600,444.371,600,600,501.31,247.921,247.921,247.921,600,593.128,296.847,296.847,296.847,296.847,296.847,269.998,200.295,483.277,483.277,447.578,510.811,600,600,600,600,600,600,600,600,600,600,600,398.329,476.514,600,600,600,600,600,600,600,406.894,238.479,458.305,600,575.921,600,600,600,593.691,469.134,544.026,544.026,227.704,577.068,600,600,600,580.143,585.91,585.91,585.91,585.91,600,600,600,532.022,600,600,574.444,581.277,548.998,548.998,548.998,600,593.839,593.839,593.839,205.784,600,577.386,533.773,533.773,472.25,472.25,472.25,472.25,512.771,512.771,572.53,572.53,572.53,572.53,596.625,596.625,596.625,600,600,600,600,600,600,599.055,530.009,481.318,481.318,481.318,481.318,481.318,600,600,600,600,553.905,553.905,553.905,600,600,600,600,523.509,523.509,523.509,580.474,580.474,580.474,580.474,580.474,563.857,576.401,576.401,576.401,576.401,600,529.753,600,600,600,600,600,501.26,508.148,600,600,600,600,600,600,560.744,560.744,560.744,538.564,526.329,526.329,526.329,575.03,600,500.601,500.601,414.608,597.515,600,600,390.163,600,600,600,600,342.071,342.071,600,456.984,456.984,600,600,600,416.635,416.635,600,600,600,600,459.987,571.239,571.239,534.126,536.394,536.394,536.394,560.737,600,600,598.754,598.754,277.168,277.168,600,600,600,600,595.937,600,600,600,600,600,600,600,600,465.939,550.592,550.592,600,529.319,529.319,529.319,516.383,516.383,516.383,600,600,600,600,548.419,548.419,548.419,548.419,600,478.765,478.765,478.765,478.765,478.765,575.21,575.21,577.756,577.756,247.285,600,600,600,404.673,404.673,404.673,404.673,540.597,600,600,600,600,600,600,600,543.773,543.773,543.773,600,577.765,577.765,577.765,543.656,543.656,543.656,543.656,533.757,533.757,585.813,585.813,585.813,585.813,585.813,600,600,600,600,485.964,505.838,505.838", "train/learning_rate": "0.0133273,0.00338139,0.0144813,0.0144813,0.0144813,0.00695839,0.00585075,0.00585075,0.00585075,0.00745363,0.00885012,0.0159806,0.0129999,0.00605676,0.00605676,0.00605676,0.00605676,0.00955684,0.00955684,0.00955684,0.00955684,0.0136314,0.0136314,0.0136314,0.0136314,0.0136314,0.0136314,0.0136314,0.0108057,0.0108057,0.00751056,0.0102497,0.0102497,0.0201353,0.00958073,0.0150442,0.0116294,0.0108298,0.00865487,0.0115666,0.0258951,0.0228388,0.0127927,0.00796391,0.0103638,0.0103638,0.0160707,0.0127813,0.0207046,0.0095851,0.0095851,0.0101451,0.0169662,0.0169662,0.007899,0.00344023,0.00344023,0.00344023,0.00605967,0.0123209,0.0070123,0.0151183,0.0130386,0.0130386,0.0130386,0.0102366,0.0102366,0.0156648,0.00966496,0.0136819,0.0136819,0.0136819,0.00820697,0.00820697,0.0118756,0.0118756,0.0107583,0.0107583,0.00514066,0.00514066,0.00514066,0.00514066,0.0116235,0.00840536,0.00843398,0.010796,0.00706111,0.00604774,0.00604774,0.00604774,0.0025316,0.0025316,0.0134051,0.0134051,0.0218906,0.0218906,0.0161143,0.0109462,0.00392775,0.0157212,0.0157212,0.0157212,0.00966842,0.00966842,0.0205266,0.0205266,0.0205266,0.0103066,0.0146356,0.0191292,0.00841808,0.00841808,0.00944599,0.013625,0.013625,0.013625,0.011175,0.00721527,0.0110854,0.0110854,0.0110854,0.0110854,0.0110854,0.0696353,0.0118098,0.0135181,0.0135181,0.0161519,0.0137736,0.00727725,0.0104927,0.0104927,0.0104927,0.0104927,0.0104927,0.00455632,0.00455632,0.00455632,0.00455632,0.00455632,0.0163849,0.00863017,0.00830681,0.00830681,0.00830681,0.0109154,0.0109154,0.0109154,0.0109154,0.0207408,0.00208772,0.0233281,0.0126482,0.00960741,0.00889032,0.00954856,0.0127162,0.0200505,0.0154362,0.0172752,0.0172752,0.0116449,0.00898535,0.017573,0.017573,0.017573,0.00616636,0.0153419,0.0153419,0.0153419,0.0153419,0.0165824,0.0165824,0.0165824,0.0180455,0.0125279,0.0125279,0.0117995,0.008793,0.00958926,0.00958926,0.00958926,0.014627,0.0104827,0.0104827,0.0104827,0.007015,0.0107649,0.00332214,0.0236743,0.0236743,0.0113987,0.0113987,0.0113987,0.0113987,0.0183011,0.0183011,0.0169292,0.0169292,0.0169292,0.0169292,0.0084618,0.0084618,0.0084618,0.00452688,0.00752646,0.00752646,0.00752646,0.00752646,0.00752646,0.0159187,0.00863139,0.0148273,0.0148273,0.0148273,0.0148273,0.0148273,0.00953418,0.0141593,0.0141593,0.0141593,0.0175072,0.0175072,0.0175072,0.0167162,0.00807675,0.0136336,0.0161444,0.0118985,0.0118985,0.0118985,0.00759185,0.00759185,0.00759185,0.00759185,0.00759185,0.0178039,0.00662173,0.00662173,0.00662173,0.00662173,0.00779204,0.00961259,0.0284422,0.0284422,0.00896553,0.0157256,0.0157256,0.0195616,0.0284991,0.00803711,0.00803711,0.0155745,0.0105377,0.0105377,0.0105377,0.0107633,0.0107633,0.0107633,0.00977693,0.0218252,0.0218252,0.0218252,0.0110533,0.00766477,0.0120055,0.0120055,0.0166207,0.0119045,0.015469,0.015469,0.0136214,0.0116626,0.0116626,0.0116626,0.00679486,0.014191,0.014191,0.00532408,0.0189998,0.0189998,0.00930167,0.00562967,0.00902363,0.0212931,0.0212931,0.0118791,0.00710952,0.00710952,0.00710952,0.00763192,0.00348173,0.00348173,0.0084145,0.00990833,0.00990833,0.00990833,0.00595497,0.00773455,0.00773455,0.00583201,0.00583201,0.0100567,0.0100567,0.011183,0.00818747,0.00818747,0.00570306,0.0173535,0.0100464,0.0100464,0.0100464,0.0100464,0.0100464,0.0137906,0.0137906,0.0137906,0.0104427,0.015256,0.015256,0.00820301,0.0142647,0.0142647,0.0142647,0.0135998,0.0135998,0.0135998,0.0138106,0.00813166,0.00813166,0.0172961,0.00805612,0.00805612,0.00805612,0.00805612,0.00830533,0.00734924,0.00734924,0.00734924,0.00734924,0.00734924,0.0116007,0.0116007,0.0113775,0.0113775,0.0172428,0.016682,0.016682,0.016682,0.0157444,0.0157444,0.0157444,0.0157444,0.00610647,0.00961001,0.00961001,0.00961001,0.00961001,0.00961001,0.0109483,0.00861771,0.00898097,0.00898097,0.00898097,0.006939,0.0133097,0.0133097,0.0133097,0.00956194,0.00956194,0.00956194,0.00956194,0.0120477,0.0120477,0.0114054,0.0114054,0.0114054,0.0114054,0.0114054,0.0136118,0.0180043,0.00995885,0.00995885,0.0118902,0.0119058,0.0119058", "train/anneal_lr": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "train/min_lr_ratio": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "train/gamma": "0.982655,0.987595,0.989955,0.989955,0.989955,0.987964,0.993434,0.993434,0.993434,0.995064,0.992269,0.98315,0.988196,0.965048,0.965048,0.965048,0.965048,0.99107,0.99107,0.99107,0.99107,0.979826,0.979826,0.979826,0.979826,0.979826,0.979826,0.979826,0.985315,0.985315,0.994378,0.987775,0.987775,0.986229,0.991006,0.991983,0.986236,0.99153,0.980059,0.988178,0.985192,0.981859,0.989558,0.987351,0.979013,0.979013,0.99282,0.986821,0.986934,0.99621,0.99621,0.972496,0.985901,0.985901,0.983498,0.985266,0.985266,0.985266,0.987032,0.989881,0.98826,0.985436,0.975714,0.975714,0.975714,0.987774,0.987774,0.988215,0.994345,0.992009,0.992009,0.992009,0.995988,0.995988,0.983168,0.983168,0.98011,0.98011,0.993201,0.993201,0.993201,0.993201,0.988051,0.979839,0.976771,0.986534,0.994213,0.991477,0.991477,0.991477,0.989226,0.989226,0.977092,0.977092,0.979006,0.979006,0.977126,0.985426,0.986963,0.987398,0.987398,0.987398,0.9847,0.9847,0.983785,0.983785,0.983785,0.982358,0.979245,0.976852,0.986381,0.986381,0.983133,0.986802,0.986802,0.986802,0.992142,0.994366,0.98418,0.98418,0.98418,0.98418,0.98418,0.990675,0.973847,0.992848,0.992848,0.984196,0.961721,0.988636,0.980825,0.980825,0.980825,0.980825,0.980825,0.98872,0.98872,0.98872,0.98872,0.98872,0.980148,0.977099,0.986817,0.986817,0.986817,0.992346,0.992346,0.992346,0.992346,0.990225,0.992677,0.95767,0.985409,0.989093,0.985794,0.975599,0.982449,0.986881,0.985997,0.982626,0.982626,0.984559,0.987991,0.988275,0.988275,0.988275,0.988465,0.975582,0.975582,0.975582,0.975582,0.985656,0.985656,0.985656,0.985303,0.984357,0.984357,0.994239,0.993349,0.98293,0.98293,0.98293,0.984311,0.988197,0.988197,0.988197,0.993944,0.993341,0.99086,0.986673,0.986673,0.967512,0.967512,0.967512,0.967512,0.985973,0.985973,0.989503,0.989503,0.989503,0.989503,0.992818,0.992818,0.992818,0.986942,0.992978,0.992978,0.992978,0.992978,0.992978,0.990283,0.982935,0.988856,0.988856,0.988856,0.988856,0.988856,0.990137,0.98709,0.98709,0.98709,0.986265,0.986265,0.986265,0.990584,0.98888,0.990547,0.9849,0.987812,0.987812,0.987812,0.992731,0.992731,0.992731,0.992731,0.992731,0.985072,0.992887,0.992887,0.992887,0.992887,0.992988,0.984401,0.991718,0.991718,0.987992,0.985245,0.985245,0.981135,0.940244,0.985675,0.985675,0.990963,0.987957,0.987957,0.987957,0.989781,0.989781,0.989781,0.990432,0.988218,0.988218,0.988218,0.986757,0.985253,0.987542,0.987542,0.967179,0.992973,0.995231,0.995231,0.970961,0.990087,0.990087,0.990087,0.994675,0.987372,0.987372,0.986996,0.981666,0.981666,0.984511,0.990728,0.991095,0.982757,0.982757,0.995317,0.991689,0.991689,0.991689,0.99358,0.986464,0.986464,0.963255,0.985771,0.985771,0.985771,0.984491,0.99505,0.99505,0.987388,0.987388,0.965181,0.965181,0.989568,0.984621,0.984621,0.99067,0.976196,0.985956,0.985956,0.985956,0.985956,0.985956,0.983143,0.983143,0.983143,0.975243,0.985041,0.985041,0.992957,0.983103,0.983103,0.983103,0.986117,0.986117,0.986117,0.989693,0.990986,0.990986,0.988807,0.992215,0.992215,0.992215,0.992215,0.979453,0.988307,0.988307,0.988307,0.988307,0.988307,0.986125,0.986125,0.983571,0.983571,0.980336,0.983153,0.983153,0.983153,0.991254,0.991254,0.991254,0.991254,0.994143,0.989645,0.989645,0.989645,0.989645,0.989645,0.99103,0.985737,0.990761,0.990761,0.990761,0.992511,0.989777,0.989777,0.989777,0.981878,0.981878,0.981878,0.981878,0.984571,0.984571,0.992047,0.992047,0.992047,0.992047,0.992047,0.994004,0.965404,0.99451,0.99451,0.980263,0.980038,0.980038", "train/gae_lambda": "0.818265,0.901675,0.943377,0.943377,0.943377,0.943335,0.895863,0.895863,0.895863,0.901618,0.920938,0.897485,0.88116,0.950068,0.950068,0.950068,0.950068,0.897885,0.897885,0.897885,0.897885,0.908362,0.908362,0.908362,0.908362,0.908362,0.908362,0.908362,0.822771,0.822771,0.92748,0.810731,0.810731,0.937697,0.94103,0.904139,0.943081,0.88963,0.959733,0.891096,0.995,0.889848,0.93797,0.701729,0.82139,0.82139,0.903294,0.919231,0.962458,0.863124,0.863124,0.87839,0.93297,0.93297,0.932399,0.866835,0.866835,0.866835,0.860988,0.769483,0.886083,0.889895,0.823725,0.823725,0.823725,0.854525,0.854525,0.885851,0.883697,0.899804,0.899804,0.899804,0.907021,0.907021,0.779799,0.779799,0.955914,0.955914,0.787685,0.787685,0.787685,0.787685,0.85602,0.912692,0.884573,0.803904,0.927098,0.892009,0.892009,0.892009,0.955735,0.955735,0.924941,0.924941,0.829596,0.829596,0.768334,0.865483,0.916945,0.793195,0.793195,0.793195,0.894591,0.894591,0.921535,0.921535,0.921535,0.862047,0.890548,0.899888,0.875265,0.875265,0.912432,0.962921,0.962921,0.962921,0.887603,0.855907,0.966268,0.966268,0.966268,0.966268,0.966268,0.789162,0.92517,0.7977,0.7977,0.950425,0.904857,0.936168,0.868553,0.868553,0.868553,0.868553,0.868553,0.891989,0.891989,0.891989,0.891989,0.891989,0.84603,0.891918,0.920734,0.920734,0.920734,0.865984,0.865984,0.865984,0.865984,0.76778,0.988215,0.791092,0.86678,0.919366,0.862687,0.949013,0.912981,0.902753,0.903887,0.902281,0.902281,0.924739,0.887249,0.869112,0.869112,0.869112,0.816523,0.902772,0.902772,0.902772,0.902772,0.913506,0.913506,0.913506,0.949352,0.864795,0.864795,0.94349,0.804823,0.845661,0.845661,0.845661,0.935316,0.893967,0.893967,0.893967,0.986464,0.809782,0.86568,0.841287,0.841287,0.903061,0.903061,0.903061,0.903061,0.894177,0.894177,0.894407,0.894407,0.894407,0.894407,0.911226,0.911226,0.911226,0.879762,0.8425,0.8425,0.8425,0.8425,0.8425,0.92831,0.798569,0.884199,0.884199,0.884199,0.884199,0.884199,0.894941,0.841456,0.841456,0.841456,0.873927,0.873927,0.873927,0.967668,0.816076,0.949335,0.946199,0.924094,0.924094,0.924094,0.804838,0.804838,0.804838,0.804838,0.804838,0.840659,0.831737,0.831737,0.831737,0.831737,0.959472,0.941586,0.892771,0.892771,0.71581,0.816277,0.816277,0.899258,0.952239,0.89386,0.89386,0.825972,0.950697,0.950697,0.950697,0.877229,0.877229,0.877229,0.852613,0.874492,0.874492,0.874492,0.807167,0.818598,0.884011,0.884011,0.798892,0.859909,0.927789,0.927789,0.899861,0.900473,0.900473,0.900473,0.886712,0.893587,0.893587,0.930734,0.90649,0.90649,0.839242,0.890969,0.844419,0.917054,0.917054,0.9128,0.940694,0.940694,0.940694,0.890415,0.947014,0.947014,0.939655,0.921938,0.921938,0.921938,0.855717,0.833231,0.833231,0.875883,0.875883,0.84881,0.84881,0.884557,0.914889,0.914889,0.904812,0.950226,0.893053,0.893053,0.893053,0.893053,0.893053,0.878985,0.878985,0.878985,0.837413,0.77796,0.77796,0.889615,0.960929,0.960929,0.960929,0.840895,0.840895,0.840895,0.861812,0.942718,0.942718,0.923135,0.851329,0.851329,0.851329,0.851329,0.942398,0.898276,0.898276,0.898276,0.898276,0.898276,0.80161,0.80161,0.872489,0.872489,0.859936,0.926304,0.926304,0.926304,0.920063,0.920063,0.920063,0.920063,0.731686,0.891817,0.891817,0.891817,0.891817,0.891817,0.921446,0.952655,0.852812,0.852812,0.852812,0.91661,0.887407,0.887407,0.887407,0.918317,0.918317,0.918317,0.918317,0.865316,0.865316,0.855614,0.855614,0.855614,0.855614,0.855614,0.922539,0.91383,0.88131,0.88131,0.889671,0.950878,0.950878", "train/replay_ratio": "2.68529,2.94716,2.34387,2.34387,2.34387,1.97942,2.00523,2.00523,2.00523,1.82935,2.5359,1.71117,1.73436,2.06396,2.06396,2.06396,2.06396,2.7155,2.7155,2.7155,2.7155,1.54521,1.54521,1.54521,1.54521,1.54521,1.54521,1.54521,1.1619,1.1619,2.74265,2.4195,2.4195,1.86614,1.905,2.88134,1.75708,2.59353,1.81705,1.51432,1.4296,1.36895,1.6814,2.1923,1.94156,1.94156,1.59764,2.3121,1.79604,1.74896,1.74896,2.53043,2.2723,2.2723,2.17312,2.63802,2.63802,2.63802,2.32268,1.45992,2.21746,1.12519,1.37599,1.37599,1.37599,1.60191,1.60191,3.0044,2.70623,2.35276,2.35276,2.35276,1.71954,1.71954,1.73145,1.73145,1.9651,1.9651,1.88377,1.88377,1.88377,1.88377,1.61117,1.78251,2.88805,2.53084,2.17162,2.5732,2.5732,2.5732,2.27849,2.27849,1.52373,1.52373,1.92834,1.92834,2.14409,1.61625,2.42583,1.94056,1.94056,1.94056,1.9829,1.9829,1.60208,1.60208,1.60208,2.43017,2.27684,1.45849,2.10474,2.10474,2.0239,1.85682,1.85682,1.85682,2.06185,2.08443,2.05567,2.05567,2.05567,2.05567,2.05567,1.32303,2.29561,1.64114,1.64114,2.14659,0.527167,2.23844,2.50628,2.50628,2.50628,2.50628,2.50628,2.21777,2.21777,2.21777,2.21777,2.21777,2.08001,2.29308,2.51296,2.51296,2.51296,2.27021,2.27021,2.27021,2.27021,2.04638,0.442228,0.887966,1.85159,1.78183,1.8043,1.3137,2.30614,1.92472,1.89207,1.83334,1.83334,1.3336,1.78443,1.75747,1.75747,1.75747,1.03089,1.5002,1.5002,1.5002,1.5002,1.9288,1.9288,1.9288,2.59031,2.30999,2.30999,2.25205,1.56223,1.81185,1.81185,1.81185,1.91061,1.8938,1.8938,1.8938,0.443489,2.20064,2.14144,1.16181,1.16181,1.72411,1.72411,1.72411,1.72411,2.24086,2.24086,1.92007,1.92007,1.92007,1.92007,2.47419,2.47419,2.47419,1.61222,2.31268,2.31268,2.31268,2.31268,2.31268,1.98619,2.65853,2.57565,2.57565,2.57565,2.57565,2.57565,2.08077,1.69569,1.69569,1.69569,1.52807,1.52807,1.52807,1.68485,1.89767,1.58963,1.87107,1.56072,1.56072,1.56072,3.10196,3.10196,3.10196,3.10196,3.10196,2.30576,2.06402,2.06402,2.06402,2.06402,1.56426,1.42283,1.96286,1.96286,1.99125,1.04342,1.04342,2.62747,1.45715,2.47275,2.47275,2.55172,2.21691,2.21691,2.21691,1.68059,1.68059,1.68059,2.03779,1.51807,1.51807,1.51807,1.77767,2.87276,2.17106,2.17106,1.38922,2.5052,2.23365,2.23365,0.977996,2.49098,2.49098,2.49098,1.96651,2.43743,2.43743,1.41526,1.44031,1.44031,1.06391,1.54071,1.71144,1.92937,1.92937,1.9794,2.27239,2.27239,2.27239,2.32116,2.57584,2.57584,1.95121,1.50108,1.50108,1.50108,2.1138,2.35475,2.35475,2.73489,2.73489,2.31158,2.31158,2.60652,1.64484,1.64484,2.25792,1.43944,2.56129,2.56129,2.56129,2.56129,2.56129,1.08226,1.08226,1.08226,1.19613,1.70001,1.70001,2.19271,1.71095,1.71095,1.71095,2.29848,2.29848,2.29848,1.42659,2.51389,2.51389,2.29948,2.11953,2.11953,2.11953,2.11953,2.38941,2.27425,2.27425,2.27425,2.27425,2.27425,1.69583,1.69583,2.26829,2.26829,1.44929,1.80398,1.80398,1.80398,2.46492,2.46492,2.46492,2.46492,2.53625,1.79039,1.79039,1.79039,1.79039,1.79039,2.60721,2.01422,2.67832,2.67832,2.67832,1.90112,2.59631,2.59631,2.59631,2.49398,2.49398,2.49398,2.49398,2.31271,2.31271,2.86955,2.86955,2.86955,2.86955,2.86955,2.1081,1.01667,1.79921,1.79921,1.02581,1.49334,1.49334", "train/clip_coef": "0.642272,0.736551,0.955188,0.955188,0.955188,0.758841,0.582186,0.582186,0.582186,0.651689,0.820264,0.773738,0.814352,1,1,1,1,0.826822,0.826822,0.826822,0.826822,0.915672,0.915672,0.915672,0.915672,0.915672,0.915672,0.915672,1,1,0.781808,0.758811,0.758811,1,0.764018,0.552777,0.68842,0.4541,0.883737,0.882489,1,0.996795,0.791495,0.46353,0.961337,0.961337,0.694804,1,0.618718,1,1,0.989389,0.844297,0.844297,0.925727,0.766246,0.766246,0.766246,0.531095,1,0.870929,1,0.985701,0.985701,0.985701,0.812614,0.812614,0.958082,0.555297,0.656328,0.656328,0.656328,0.762898,0.762898,0.934698,0.934698,1,1,0.530328,0.530328,0.530328,0.530328,0.911414,0.815612,0.779477,0.859339,1,0.501535,0.501535,0.501535,0.519621,0.519621,0.711825,0.711825,1,1,0.947256,0.89644,0.667819,1,1,1,0.751329,0.751329,0.533319,0.533319,0.533319,0.649936,0.560238,0.956158,0.969339,0.969339,0.917896,1,1,1,0.535495,0.757008,0.855822,0.855822,0.855822,0.855822,0.855822,1,1,1,1,0.817704,0.923958,0.807276,0.630099,0.630099,0.630099,0.630099,0.630099,1,1,1,1,1,0.991597,0.797115,0.653583,0.653583,0.653583,0.660367,0.660367,0.660367,0.660367,0.788733,0.836641,1,0.561776,0.505491,0.773215,0.785351,0.441264,0.86434,0.749488,0.972834,0.972834,1,0.807027,0.762155,0.762155,0.762155,0.976655,0.989597,0.989597,0.989597,0.989597,0.774548,0.774548,0.774548,0.972239,0.452178,0.452178,0.693055,1,0.673328,0.673328,0.673328,0.870501,0.593603,0.593603,0.593603,1,0.700837,0.902494,0.965763,0.965763,1,1,1,1,0.379876,0.379876,0.413845,0.413845,0.413845,0.413845,1,1,1,0.790428,0.556988,0.556988,0.556988,0.556988,0.556988,1,0.759294,0.892972,0.892972,0.892972,0.892972,0.892972,1,0.567988,0.567988,0.567988,1,1,1,1,0.607161,1,1,0.346713,0.346713,0.346713,0.646443,0.646443,0.646443,0.646443,0.646443,1,0.257977,0.257977,0.257977,0.257977,0.624962,0.754813,1,1,0.613052,0.840698,0.840698,0.830916,1,0.745889,0.745889,0.813274,0.885779,0.885779,0.885779,0.654969,0.654969,0.654969,0.864469,0.815569,0.815569,0.815569,0.504793,0.387424,0.551398,0.551398,1,0.781906,0.716087,0.716087,1,1,1,1,0.715569,0.815742,0.815742,0.593632,1,1,0.592346,0.828228,0.80105,0.656988,0.656988,0.546649,0.398794,0.398794,0.398794,0.637269,0.596876,0.596876,1,1,1,1,1,0.262543,0.262543,0.57289,0.57289,1,1,0.701146,0.83165,0.83165,0.666382,1,1,1,1,1,1,1,1,1,1,0.913664,0.913664,0.817748,0.777631,0.777631,0.777631,0.800781,0.800781,0.800781,0.514452,0.72266,0.72266,0.983538,0.995681,0.995681,0.995681,0.995681,0.86973,0.667251,0.667251,0.667251,0.667251,0.667251,0.737104,0.737104,0.51295,0.51295,1,0.742511,0.742511,0.742511,1,1,1,1,0.65633,0.648225,0.648225,0.648225,0.648225,0.648225,0.344852,0.821588,0.809838,0.809838,0.809838,0.648043,0.784006,0.784006,0.784006,0.966815,0.966815,0.966815,0.966815,0.9886,0.9886,1,1,1,1,1,0.893925,1,0.726945,0.726945,0.789309,0.93471,0.93471", "train/vf_coef": "1.01324,0.342007,0.193027,0.193027,0.193027,0.1,0.1,0.1,0.1,0.1,0.782512,0.1,0.1,0.538575,0.538575,0.538575,0.538575,0.1,0.1,0.1,0.1,0.977532,0.977532,0.977532,0.977532,0.977532,0.977532,0.977532,0.15189,0.15189,0.1,0.1,0.1,0.1,0.1,0.76187,0.1,0.1,0.538497,0.422239,0.623984,0.574733,0.760258,1.80113,0.66007,0.66007,0.1,0.1,0.1,0.205725,0.205725,1.18567,0.1,0.1,0.1,0.140712,0.140712,0.140712,0.403659,0.619125,0.1,0.1,0.936876,0.936876,0.936876,0.787588,0.787588,0.1,0.1,0.756366,0.756366,0.756366,0.1,0.1,0.917388,0.917388,0.1,0.1,0.1,0.1,0.1,0.1,0.950126,0.236379,0.1,0.988194,0.1,0.219124,0.219124,0.219124,0.1,0.1,0.1,0.1,0.71903,0.71903,0.522395,0.1,0.1,0.530197,0.530197,0.530197,0.1,0.1,0.1,0.1,0.1,1.19358,1.21149,0.1,0.1,0.1,0.574472,0.1,0.1,0.1,0.622741,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.401491,0.1,0.1,0.1,0.242712,0.980045,0.855023,0.855023,0.855023,0.855023,0.855023,0.464464,0.464464,0.464464,0.464464,0.464464,1.13306,0.469857,0.888399,0.888399,0.888399,1.24306,1.24306,1.24306,1.24306,0.1,3.17831,0.869478,0.956555,0.886392,0.895916,0.352817,0.341586,0.401032,0.1,0.228594,0.228594,0.1,0.1,0.456406,0.456406,0.456406,0.403582,0.972274,0.972274,0.972274,0.972274,0.1,0.1,0.1,0.1,0.751306,0.751306,0.1,0.1,0.77146,0.77146,0.77146,0.246633,0.1,0.1,0.1,0.1,0.56111,0.201295,0.924926,0.924926,0.896187,0.896187,0.896187,0.896187,0.68611,0.68611,0.763792,0.763792,0.763792,0.763792,0.683526,0.683526,0.683526,0.1,0.305585,0.305585,0.305585,0.305585,0.305585,0.881299,0.694593,0.918215,0.918215,0.918215,0.918215,0.918215,0.1,0.530325,0.530325,0.530325,0.286424,0.286424,0.286424,0.1,0.344651,0.1,0.429421,0.20819,0.20819,0.20819,1.45,1.45,1.45,1.45,1.45,0.1,0.1,0.1,0.1,0.1,0.1,0.994663,1.08626,1.08626,0.509708,0.647621,0.647621,0.68207,1.71763,0.956719,0.956719,0.92743,0.15628,0.15628,0.15628,0.1,0.1,0.1,0.1,0.225886,0.225886,0.225886,0.1,0.667407,0.263859,0.263859,0.1,0.1,0.410165,0.410165,0.675338,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.542582,0.542582,1.18338,0.1,0.755454,0.1,0.1,0.1,0.1,0.1,0.1,0.119346,1.2127,1.2127,0.722334,0.5863,0.5863,0.5863,0.1,0.420144,0.420144,0.763972,0.763972,0.1,0.1,0.1,0.477234,0.477234,0.382393,0.401468,0.1,0.1,0.1,0.1,0.1,0.762613,0.762613,0.762613,0.624227,0.1,0.1,0.1,0.414663,0.414663,0.414663,0.1,0.1,0.1,0.1,0.205113,0.205113,0.1,1.00363,1.00363,1.00363,1.00363,0.397417,0.328435,0.328435,0.328435,0.328435,0.328435,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.863018,0.863018,0.863018,0.863018,0.1,0.550258,0.550258,0.550258,0.550258,0.550258,0.1,0.1,0.925994,0.925994,0.925994,0.1,0.154388,0.154388,0.154388,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,1.61997,0.1,0.1,0.931496,0.704868,0.704868", "train/vf_clip_coef": "0.80008,0.915789,1.70025,1.70025,1.70025,1.7312,2.1401,2.1401,2.1401,0.937812,1.25961,1.24067,1.44426,0.01,0.01,0.01,0.01,0.664395,0.664395,0.664395,0.664395,1.75503,1.75503,1.75503,1.75503,1.75503,1.75503,1.75503,2.0855,2.0855,0.959775,1.98396,1.98396,0.872666,1.98524,0.755012,1.35094,0.173563,1.42397,1.01535,0.01,1.60835,1.08288,1.32852,2.12949,2.12949,0.722133,1.04508,1.46382,1.30887,1.30887,0.01,2.1341,2.1341,1.37075,1.20647,1.20647,1.20647,0.779337,1.14441,1.52206,0.608112,1.27814,1.27814,1.27814,0.936335,0.936335,1.58539,1.2195,1.31828,1.31828,1.31828,0.420066,0.420066,1.7699,1.7699,0.539904,0.539904,1.59255,1.59255,1.59255,1.59255,1.19942,1.68022,0.912106,0.485896,1.54692,2.03569,2.03569,2.03569,0.905934,0.905934,1.4977,1.4977,1.55907,1.55907,1.06883,0.674817,0.830462,1.50286,1.50286,1.50286,0.549227,0.549227,1.86507,1.86507,1.86507,0.368403,1.27811,1.31541,0.13166,0.13166,1.37543,1.08006,1.08006,1.08006,1.7987,0.804237,0.749839,0.749839,0.749839,0.749839,0.749839,0.521473,0.01,1.79221,1.79221,1.44591,0.146031,1.47926,1.27746,1.27746,1.27746,1.27746,1.27746,1.11529,1.11529,1.11529,1.11529,1.11529,1.80194,0.853139,0.583418,0.583418,0.583418,1.48031,1.48031,1.48031,1.48031,1.24303,1.80051,1.86396,1.57383,0.709072,1.67883,1.20659,0.808727,1.22622,0.56192,1.01379,1.01379,1.78027,0.833156,1.1031,1.1031,1.1031,0.536874,1.17282,1.17282,1.17282,1.17282,1.16773,1.16773,1.16773,0.58618,1.70226,1.70226,1.07509,0.728852,1.70833,1.70833,1.70833,1.04867,1.86699,1.86699,1.86699,0.01,1.18663,1.239,0.875033,0.875033,0.517918,0.517918,0.517918,0.517918,1.49277,1.49277,0.770289,0.770289,0.770289,0.770289,2.01702,2.01702,2.01702,1.42897,1.16721,1.16721,1.16721,1.16721,1.16721,0.93854,0.831653,1.69234,1.69234,1.69234,1.69234,1.69234,0.922779,1.18058,1.18058,1.18058,2.27047,2.27047,2.27047,1.03069,0.403637,1.48911,2.049,2.40221,2.40221,2.40221,0.206484,0.206484,0.206484,0.206484,0.206484,2.04498,1.31349,1.31349,1.31349,1.31349,0.661903,1.69022,1.03055,1.03055,0.920915,0.883886,0.883886,1.68413,1.86869,0.638094,0.638094,1.86147,0.98213,0.98213,0.98213,1.24252,1.24252,1.24252,1.45374,2.14991,2.14991,2.14991,1.4577,2.24607,0.727479,0.727479,1.24367,0.755362,0.736533,0.736533,1.53691,0.68787,0.68787,0.68787,2.0279,1.71627,1.71627,0.360842,0.633269,0.633269,1.52402,1.45437,0.620811,1.98603,1.98603,2.24122,1.38383,1.38383,1.38383,1.04949,0.01,0.01,0.997378,1.24839,1.24839,1.24839,1.05003,0.491552,0.491552,0.0791267,0.0791267,1.67712,1.67712,1.42965,0.01,0.01,0.366805,0.821358,0.848456,0.848456,0.848456,0.848456,0.848456,0.442081,0.442081,0.442081,0.846275,2.68404,2.68404,1.42773,0.854754,0.854754,0.854754,1.46668,1.46668,1.46668,1.08505,0.123732,0.123732,1.29178,1.38714,1.38714,1.38714,1.38714,0.859128,1.3652,1.3652,1.3652,1.3652,1.3652,1.32221,1.32221,1.27269,1.27269,1.7741,2.05943,2.05943,2.05943,1.35538,1.35538,1.35538,1.35538,1.98087,0.01,0.01,0.01,0.01,0.01,1.94516,0.469421,0.944192,0.944192,0.944192,1.35424,1.14209,1.14209,1.14209,0.765166,0.765166,0.765166,0.765166,1.65246,1.65246,1.41915,1.41915,1.41915,1.41915,1.41915,1.20285,1.64836,0.693495,0.693495,0.467138,1.13948,1.13948", "train/max_grad_norm": "0.1,2.66618,0.659034,0.659034,0.659034,0.1,3.71056,3.71056,3.71056,1.7427,1.67123,0.83622,1.37745,1.29747,1.29747,1.29747,1.29747,2.52927,2.52927,2.52927,2.52927,1.08789,1.08789,1.08789,1.08789,1.08789,1.08789,1.08789,0.794945,0.794945,2.16925,0.772991,0.772991,0.1,0.833634,3.04644,2.58443,1.90346,0.1,0.245086,0.1,0.654314,3.40722,1.57732,0.923403,0.923403,2.57018,1.44402,1.58012,0.1,0.1,0.122695,0.1,0.1,1.26712,1.70028,1.70028,1.70028,0.269711,1.20273,2.34284,0.1,1.30024,1.30024,1.30024,0.46526,0.46526,0.815851,3.29217,1.24058,1.24058,1.24058,2.56875,2.56875,0.447611,0.447611,0.1,0.1,2.6435,2.6435,2.6435,2.6435,2.372,0.6077,3.33788,2.27357,0.713583,2.64123,2.64123,2.64123,2.78102,2.78102,1.24827,1.24827,0.147503,0.147503,0.455486,3.76079,1.98278,0.98891,0.98891,0.98891,2.6215,2.6215,1.60828,1.60828,1.60828,0.681114,1.51336,0.205266,0.1,0.1,2.92744,0.1,0.1,0.1,2.50726,0.461187,3.49992,3.49992,3.49992,3.49992,3.49992,0.528305,0.1,0.621828,0.621828,0.1,1.15495,1.84003,1.21533,1.21533,1.21533,1.21533,1.21533,1.48596,1.48596,1.48596,1.48596,1.48596,0.368757,1.26805,2.26973,2.26973,2.26973,2.28781,2.28781,2.28781,2.28781,0.891084,4.78128,0.843254,1.19071,2.11444,3.2509,2.25209,0.58619,1.07581,0.725769,0.1,0.1,0.1,1.39304,1.56398,1.56398,1.56398,1.0144,2.29604,2.29604,2.29604,2.29604,2.25264,2.25264,2.25264,0.487389,1.05423,1.05423,2.18448,0.1,2.75844,2.75844,2.75844,0.1,1.62905,1.62905,1.62905,0.1,3.48331,1.58174,1.39376,1.39376,0.934919,0.934919,0.934919,0.934919,1.92557,1.92557,0.805844,0.805844,0.805844,0.805844,0.90013,0.90013,0.90013,1.43204,2.82564,2.82564,2.82564,2.82564,2.82564,0.605074,0.369938,0.844569,0.844569,0.844569,0.844569,0.844569,0.827799,2.22063,2.22063,2.22063,0.986892,0.986892,0.986892,0.1,3.7456,2.20617,1.64306,2.778,2.778,2.778,2.75622,2.75622,2.75622,2.75622,2.75622,1.15325,1.26717,1.26717,1.26717,1.26717,2.05993,1.81026,0.375068,0.375068,2.31534,0.353437,0.353437,0.1,1.02955,2.73227,2.73227,2.50178,2.76307,2.76307,2.76307,2.21469,2.21469,2.21469,2.75614,1.68336,1.68336,1.68336,1.60197,0.343404,1.23155,1.23155,0.1,1.23856,2.43859,2.43859,0.380899,0.1,0.1,0.1,2.23946,1.13237,1.13237,1.00549,0.1,0.1,2.05085,1.29087,1.35491,0.1,0.1,1.92473,3.47544,3.47544,3.47544,2.57324,2.73992,2.73992,0.1,2.29373,2.29373,2.29373,0.87723,2.0642,2.0642,2.00364,2.00364,0.936257,0.936257,0.875576,3.07993,3.07993,2.52859,0.1,0.483991,0.483991,0.483991,0.483991,0.483991,2.02171,2.02171,2.02171,0.708161,0.1,0.1,0.1,0.1,0.1,0.1,1.1188,1.1188,1.1188,0.777965,1.88887,1.88887,0.64628,0.1,0.1,0.1,0.1,0.884899,1.93506,1.93506,1.93506,1.93506,1.93506,1.53957,1.53957,1.18801,1.18801,1.90174,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,2.30269,2.30269,2.30269,2.30269,2.30269,1.19965,3.59773,0.80834,0.80834,0.80834,1.55111,0.1,0.1,0.1,1.01194,1.01194,1.01194,1.01194,0.1,0.1,0.714845,0.714845,0.714845,0.714845,0.714845,0.1,1.06019,0.809766,0.809766,1.62865,1.8632,1.8632", "train/ent_coef": "0.000550098,0.000130582,0.00253943,0.00253943,0.00253943,0.000951857,0.00140118,0.00140118,0.00140118,0.00117904,0.000722335,0.00245877,0.00608047,0.00122774,0.00122774,0.00122774,0.00122774,0.00268663,0.00268663,0.00268663,0.00268663,0.00246004,0.00246004,0.00246004,0.00246004,0.00246004,0.00246004,0.00246004,0.000925541,0.000925541,0.00175544,0.00231176,0.00231176,0.000625751,0.000875174,0.00149451,0.00180187,0.00166297,0.00041921,0.00388499,3.00766e-05,0.00107125,0.00119687,0.00216841,0.00196348,0.00196348,0.00102685,0.00338845,0.00152361,0.000986806,0.000986806,0.00021866,0.0027523,0.0027523,0.000842743,0.00389441,0.00389441,0.00389441,0.000427084,0.00268779,0.000493344,0.000530466,0.00119951,0.00119951,0.00119951,0.000735711,0.000735711,0.000397232,0.000732879,0.000870366,0.000870366,0.000870366,0.000197106,0.000197106,0.00108762,0.00108762,0.000675833,0.000675833,0.00271851,0.00271851,0.00271851,0.00271851,0.0014868,0.00146423,0.000663571,0.00196324,0.0018869,0.00451237,0.00451237,0.00451237,0.00121211,0.00121211,0.00204453,0.00204453,0.00116093,0.00116093,0.00340238,0.00284743,0.00146242,0.00144893,0.00144893,0.00144893,0.00105777,0.00105777,0.000210489,0.000210489,0.000210489,0.00214403,0.00137927,0.00160373,0.00285084,0.00285084,0.00411609,0.000248692,0.000248692,0.000248692,0.00102585,0.000314355,0.000185251,0.000185251,0.000185251,0.000185251,0.000185251,1e-05,0.000131027,0.00554245,0.00554245,0.000776914,0.00132762,0.00150129,0.000222364,0.000222364,0.000222364,0.000222364,0.000222364,0.00270566,0.00270566,0.00270566,0.00270566,0.00270566,0.000211829,0.000831549,0.000290723,0.000290723,0.000290723,0.000487674,0.000487674,0.000487674,0.000487674,0.00353638,0.0174913,0.00212579,0.000995811,0.00098191,0.000693436,0.0013184,0.000610369,0.00408963,0.00445695,0.00184557,0.00184557,0.000283521,0.000906525,0.000752054,0.000752054,0.000752054,0.00114492,0.000815062,0.000815062,0.000815062,0.000815062,0.00153484,0.00153484,0.00153484,0.00155523,0.000284341,0.000284341,0.000560085,0.00673127,0.00152943,0.00152943,0.00152943,0.00117424,0.00102808,0.00102808,0.00102808,2.30693e-05,0.00241562,0.00293308,0.00262687,0.00262687,0.00166902,0.00166902,0.00166902,0.00166902,0.000330364,0.000330364,0.000921129,0.000921129,0.000921129,0.000921129,0.002352,0.002352,0.002352,0.00174237,0.000638182,0.000638182,0.000638182,0.000638182,0.000638182,0.000417486,0.00156826,0.000756271,0.000756271,0.000756271,0.000756271,0.000756271,0.000426436,0.00054675,0.00054675,0.00054675,0.00252783,0.00252783,0.00252783,0.00130459,0.000154268,0.000299492,0.000504201,0.0012945,0.0012945,0.0012945,0.0017047,0.0017047,0.0017047,0.0017047,0.0017047,0.00280369,0.00116532,0.00116532,0.00116532,0.00116532,0.00091084,0.000827514,0.000430766,0.000430766,0.000290654,0.00272613,0.00272613,0.00100749,0.00262848,0.000114355,0.000114355,0.000562155,0.000800591,0.000800591,0.000800591,0.000710331,0.000710331,0.000710331,0.00147801,0.000921092,0.000921092,0.000921092,0.0005719,0.00152687,0.000386828,0.000386828,1.35198e-05,0.00607309,0.000786486,0.000786486,0.00219541,0.00332753,0.00332753,0.00332753,0.00215028,0.00155167,0.00155167,0.00176231,0.00360162,0.00360162,0.00328984,0.000602443,0.000217429,0.00233745,0.00233745,0.00145405,0.00156643,0.00156643,0.00156643,0.00100506,0.000171146,0.000171146,0.00109201,0.000344862,0.000344862,0.000344862,0.00425116,0.000376885,0.000376885,0.000328976,0.000328976,0.00236452,0.00236452,0.0024446,0.0015575,0.0015575,0.000788279,0.00411707,0.00139764,0.00139764,0.00139764,0.00139764,0.00139764,0.00187464,0.00187464,0.00187464,0.00252125,0.00174528,0.00174528,0.000829462,0.00134384,0.00134384,0.00134384,0.0030714,0.0030714,0.0030714,0.00226565,0.000660758,0.000660758,0.0010085,0.000625622,0.000625622,0.000625622,0.000625622,0.000642383,0.00153039,0.00153039,0.00153039,0.00153039,0.00153039,0.00219035,0.00219035,0.00132311,0.00132311,0.00213164,0.00239119,0.00239119,0.00239119,0.00101305,0.00101305,0.00101305,0.00101305,0.00141546,0.000240629,0.000240629,0.000240629,0.000240629,0.000240629,0.0007084,0.00027224,0.00200804,0.00200804,0.00200804,0.000551738,0.00168303,0.00168303,0.00168303,0.00154791,0.00154791,0.00154791,0.00154791,0.00077377,0.00077377,0.0029493,0.0029493,0.0029493,0.0029493,0.0029493,0.000344105,0.00259058,0.00173333,0.00173333,0.00171007,0.00153053,0.00153053", "train/beta1": "0.655929,0.933751,0.5,0.5,0.5,0.5,0.897225,0.897225,0.897225,0.895488,0.871366,0.844432,0.778354,0.860671,0.860671,0.860671,0.860671,0.794852,0.794852,0.794852,0.794852,0.840696,0.840696,0.840696,0.840696,0.840696,0.840696,0.840696,0.898266,0.898266,0.801049,0.5,0.5,0.5,0.785284,0.83329,0.868416,0.814421,0.805829,0.5,0.682366,0.817385,0.839433,0.86883,0.710531,0.710531,0.879,0.828677,0.824026,0.866403,0.866403,0.938508,0.5,0.5,0.838698,0.888386,0.888386,0.888386,0.876881,0.86862,0.792104,0.736182,0.5,0.5,0.5,0.806024,0.806024,0.690282,0.817993,0.883114,0.883114,0.883114,0.967912,0.967912,0.5,0.5,0.733086,0.733086,0.933186,0.933186,0.933186,0.933186,0.873792,0.660783,0.5,0.807449,0.693389,0.838386,0.838386,0.838386,0.900372,0.900372,0.5,0.5,0.697429,0.697429,0.752584,0.591001,0.889889,0.828199,0.828199,0.828199,0.690356,0.690356,0.5,0.5,0.5,0.836149,0.785021,0.5,0.580732,0.580732,0.721983,0.76819,0.76819,0.76819,0.775371,0.767796,0.8069,0.8069,0.8069,0.8069,0.8069,0.659353,0.914852,0.813817,0.813817,0.884704,0.764033,0.834832,0.871725,0.871725,0.871725,0.871725,0.871725,0.838024,0.838024,0.838024,0.838024,0.838024,0.5,0.689283,0.845013,0.845013,0.845013,0.933049,0.933049,0.933049,0.933049,0.5,0.992138,0.604638,0.755281,0.867305,0.864504,0.919943,0.936885,0.719474,0.657891,0.838893,0.838893,0.5,0.805025,0.5,0.5,0.5,0.822811,0.932206,0.932206,0.932206,0.932206,0.5,0.5,0.5,0.945852,0.908284,0.908284,0.875943,0.859152,0.738407,0.738407,0.738407,0.571871,0.750792,0.750792,0.750792,0.899915,0.886599,0.870052,0.516819,0.516819,0.5,0.5,0.5,0.5,0.857239,0.857239,0.806012,0.806012,0.806012,0.806012,0.806336,0.806336,0.806336,0.868411,0.942861,0.942861,0.942861,0.942861,0.942861,0.5,0.529105,0.847943,0.847943,0.847943,0.847943,0.847943,0.784872,0.861559,0.861559,0.861559,0.652217,0.652217,0.652217,0.791485,0.799971,0.912377,0.843053,0.901993,0.901993,0.901993,0.753994,0.753994,0.753994,0.753994,0.753994,0.761374,0.868222,0.868222,0.868222,0.868222,0.832524,0.612115,0.757854,0.757854,0.842755,0.859183,0.859183,0.527777,0.561713,0.892229,0.892229,0.742449,0.726743,0.726743,0.726743,0.877132,0.877132,0.877132,0.913924,0.5,0.5,0.5,0.782084,0.832562,0.908741,0.908741,0.5,0.659757,0.896041,0.896041,0.656599,0.793063,0.793063,0.793063,0.862057,0.5,0.5,0.902811,0.53651,0.53651,0.879231,0.884393,0.876636,0.746587,0.746587,0.793376,0.862075,0.862075,0.862075,0.742486,0.93139,0.93139,0.729088,0.733406,0.733406,0.733406,0.738214,0.893995,0.893995,0.928694,0.928694,0.83079,0.83079,0.691041,0.956067,0.956067,0.905469,0.844208,0.70838,0.70838,0.70838,0.70838,0.70838,0.649589,0.649589,0.649589,0.5,0.709898,0.709898,0.889104,0.873263,0.873263,0.873263,0.795057,0.795057,0.795057,0.715515,0.940915,0.940915,0.5,0.889582,0.889582,0.889582,0.889582,0.657176,0.833162,0.833162,0.833162,0.833162,0.833162,0.702713,0.702713,0.834666,0.834666,0.864208,0.849818,0.849818,0.849818,0.815057,0.815057,0.815057,0.815057,0.772336,0.917001,0.917001,0.917001,0.917001,0.917001,0.618217,0.835604,0.93686,0.93686,0.93686,0.873819,0.788228,0.788228,0.788228,0.685319,0.685319,0.685319,0.685319,0.568914,0.568914,0.733476,0.733476,0.733476,0.733476,0.733476,0.804446,0.589407,0.868506,0.868506,0.791476,0.877735,0.877735", "train/beta2": "0.999984,0.999739,0.999316,0.999316,0.999316,0.99989,0.991069,0.991069,0.991069,0.999487,0.998472,0.999871,0.999887,0.99988,0.99988,0.99988,0.99988,0.999926,0.999926,0.999926,0.999926,0.999975,0.999975,0.999975,0.999975,0.999975,0.999975,0.999975,0.999979,0.999979,0.999986,0.999539,0.999539,0.999336,0.999376,0.999907,0.995933,0.999454,0.999744,0.999938,0.99999,0.99993,0.998986,0.998661,0.999752,0.999752,0.986148,0.999173,0.999783,0.998913,0.998913,0.99999,0.999849,0.999849,0.999935,0.999393,0.999393,0.999393,0.999138,0.999827,0.999536,0.999041,0.99999,0.99999,0.99999,0.999957,0.999957,0.999907,0.999746,0.998719,0.998719,0.998719,0.996737,0.996737,0.999968,0.999968,0.999781,0.999781,0.999169,0.999169,0.999169,0.999169,0.99999,0.999986,0.98786,0.999925,0.999968,0.999891,0.999891,0.999891,0.99841,0.99841,0.999987,0.999987,0.999939,0.999939,0.999823,0.987553,0.998724,0.999983,0.999983,0.999983,0.999915,0.999915,0.999898,0.999898,0.999898,0.999859,0.982608,0.999796,0.999227,0.999227,0.999955,0.999715,0.999715,0.999715,0.978032,0.999987,0.987762,0.987762,0.987762,0.987762,0.987762,0.999888,0.99999,0.999916,0.999916,0.999856,0.999968,0.99969,0.999718,0.999718,0.999718,0.999718,0.999718,0.999978,0.999978,0.999978,0.999978,0.999978,0.999987,0.999984,0.997764,0.997764,0.997764,0.991051,0.991051,0.991051,0.991051,0.999883,0.994346,0.99994,0.998815,0.999815,0.992944,0.998195,0.99857,0.999816,0.999854,0.999882,0.999882,0.999104,0.999114,0.999799,0.999799,0.999799,0.999982,0.998994,0.998994,0.998994,0.998994,0.999989,0.999989,0.999989,0.999988,0.986134,0.986134,0.999351,0.999975,0.999379,0.999379,0.999379,0.99999,0.997572,0.997572,0.997572,0.999868,0.923182,0.997363,0.999898,0.999898,0.999971,0.999971,0.999971,0.999971,0.999956,0.999956,0.999722,0.999722,0.999722,0.999722,0.999987,0.999987,0.999987,0.999809,0.992272,0.992272,0.992272,0.992272,0.992272,0.999812,0.999627,0.999924,0.999924,0.999924,0.999924,0.999924,0.999848,0.999694,0.999694,0.999694,0.9999,0.9999,0.9999,0.99999,0.991646,0.995194,0.999981,0.993131,0.993131,0.993131,0.981301,0.981301,0.981301,0.981301,0.981301,0.999982,0.994557,0.994557,0.994557,0.994557,0.999901,0.999748,0.999973,0.999973,0.99962,0.999947,0.999947,0.99999,0.999964,0.999439,0.999439,0.999662,0.99853,0.99853,0.99853,0.9,0.9,0.9,0.999568,0.99996,0.99996,0.99996,0.999896,0.999422,0.978686,0.978686,0.999893,0.999815,0.996772,0.996772,0.999807,0.999719,0.999719,0.999719,0.993698,0.999964,0.999964,0.999348,0.999963,0.999963,0.999913,0.999904,0.999124,0.999959,0.999959,0.998704,0.976378,0.976378,0.976378,0.977261,0.995753,0.995753,0.999748,0.999946,0.999946,0.999946,0.99999,0.996719,0.996719,0.998022,0.998022,0.999957,0.999957,0.999976,0.997853,0.997853,0.998332,0.999976,0.999924,0.999924,0.999924,0.999924,0.999924,0.999972,0.999972,0.999972,0.999971,0.999849,0.999849,0.999961,0.999985,0.999985,0.999985,0.999963,0.999963,0.999963,0.925502,0.998794,0.998794,0.999963,0.999978,0.999978,0.999978,0.999978,0.999943,0.99999,0.99999,0.99999,0.99999,0.99999,0.99999,0.99999,0.999692,0.999692,0.999969,0.99998,0.99998,0.99998,0.996581,0.996581,0.996581,0.996581,0.999105,0.989398,0.989398,0.989398,0.989398,0.989398,0.921176,0.999543,0.999754,0.999754,0.999754,0.99999,0.999881,0.999881,0.999881,0.998991,0.998991,0.998991,0.998991,0.999906,0.999906,0.999552,0.999552,0.999552,0.999552,0.999552,0.999671,0.999945,0.99994,0.99994,0.99999,0.999976,0.999976", "train/eps": "6.18154e-10,8.35521e-07,3.32183e-11,3.32183e-11,3.32183e-11,9.79571e-11,2.06982e-09,2.06982e-09,2.06982e-09,4.91436e-07,1.01717e-08,2.49425e-08,1.35133e-11,1.30369e-08,1.30369e-08,1.30369e-08,1.30369e-08,2.24606e-13,2.24606e-13,2.24606e-13,2.24606e-13,1.78423e-12,1.78423e-12,1.78423e-12,1.78423e-12,1.78423e-12,1.78423e-12,1.78423e-12,4.47096e-10,4.47096e-10,5.54904e-12,2.63152e-12,2.63152e-12,1.32645e-09,1.63719e-07,1.81407e-08,1.02007e-08,2.63618e-09,1.6071e-10,5.02313e-07,8.31512e-09,1.61105e-09,1.59414e-08,3.45766e-09,3.22712e-07,3.22712e-07,7.13904e-10,2.32159e-05,1.69232e-11,8.87819e-07,8.87819e-07,2.63365e-10,1.86895e-11,1.86895e-11,1.18222e-08,5.0999e-11,5.0999e-11,5.0999e-11,1.21398e-09,5.19002e-06,5.70568e-08,1.3525e-09,3.5621e-11,3.5621e-11,3.5621e-11,5.04208e-11,5.04208e-11,2.4553e-11,1.71133e-06,4.14917e-07,4.14917e-07,4.14917e-07,5.0909e-10,5.0909e-10,9.86797e-11,9.86797e-11,7.48942e-07,7.48942e-07,1.73863e-08,1.73863e-08,1.73863e-08,1.73863e-08,1.30746e-11,8.89275e-12,1.53263e-10,1.34566e-11,8.32219e-08,3.30597e-13,3.30597e-13,3.30597e-13,2.51593e-10,2.51593e-10,5.99109e-11,5.99109e-11,1.63659e-10,1.63659e-10,4.56848e-10,3.45296e-11,7.00956e-11,1.30758e-10,1.30758e-10,1.30758e-10,1.37546e-12,1.37546e-12,2.94127e-09,2.94127e-09,2.94127e-09,6.97233e-09,1.76915e-10,1.04663e-09,2.3398e-08,2.3398e-08,3.99301e-11,9.44833e-07,9.44833e-07,9.44833e-07,6.94366e-10,4.74628e-08,1.39084e-09,1.39084e-09,1.39084e-09,1.39084e-09,1.39084e-09,8.63875e-10,2.2789e-12,9.57267e-07,9.57267e-07,3.45219e-07,1.01767e-09,8.06595e-08,3.72943e-07,3.72943e-07,3.72943e-07,3.72943e-07,3.72943e-07,2.62125e-09,2.62125e-09,2.62125e-09,2.62125e-09,2.62125e-09,5.07639e-12,1.20003e-09,1.14639e-08,1.14639e-08,1.14639e-08,1.37228e-07,1.37228e-07,1.37228e-07,1.37228e-07,2.29943e-10,7.40511e-14,4.19121e-09,3.61824e-07,1.31019e-09,2.20951e-08,2.43128e-12,1.40347e-05,1.76483e-09,2.38279e-08,2.56239e-07,2.56239e-07,3.75506e-08,3.21245e-13,1.14641e-08,1.14641e-08,1.14641e-08,8.35342e-10,1.22208e-09,1.22208e-09,1.22208e-09,1.22208e-09,8.19476e-14,8.19476e-14,8.19476e-14,1.75919e-06,1.86053e-06,1.86053e-06,7.05719e-07,4.12701e-08,6.18113e-11,6.18113e-11,6.18113e-11,1.8729e-09,3.8618e-07,3.8618e-07,3.8618e-07,3.72577e-10,4.57525e-10,2.26066e-11,5.81926e-09,5.81926e-09,3.4313e-10,3.4313e-10,3.4313e-10,3.4313e-10,3.21826e-09,3.21826e-09,5.50099e-13,5.50099e-13,5.50099e-13,5.50099e-13,3.85989e-07,3.85989e-07,3.85989e-07,6.42344e-11,6.17091e-10,6.17091e-10,6.17091e-10,6.17091e-10,6.17091e-10,1.41029e-09,5.02649e-09,2.61927e-09,2.61927e-09,2.61927e-09,2.61927e-09,2.61927e-09,1.05694e-08,2.36212e-10,2.36212e-10,2.36212e-10,5.21034e-08,5.21034e-08,5.21034e-08,2.88592e-08,6.33056e-09,2.73637e-09,3.63211e-10,9.39652e-09,9.39652e-09,9.39652e-09,5.37975e-09,5.37975e-09,5.37975e-09,5.37975e-09,5.37975e-09,1.72078e-12,7.53673e-09,7.53673e-09,7.53673e-09,7.53673e-09,1.45966e-12,4.05515e-07,1.00132e-09,1.00132e-09,2.10887e-06,6.80379e-08,6.80379e-08,1.85672e-09,9.96794e-07,8.30296e-11,8.30296e-11,2.0313e-07,4.36553e-09,4.36553e-09,4.36553e-09,1.18968e-08,1.18968e-08,1.18968e-08,2.26049e-09,7.93536e-12,7.93536e-12,7.93536e-12,4.22179e-08,7.09782e-05,1.32231e-07,1.32231e-07,3.12658e-11,9.59384e-08,2.93996e-10,2.93996e-10,0.0001,1.18746e-08,1.18746e-08,1.18746e-08,4.3706e-07,1.72705e-08,1.72705e-08,2.27426e-09,5.77209e-08,5.77209e-08,1e-14,1.18983e-09,1.81095e-07,4.66128e-13,4.66128e-13,2.46273e-06,1.864e-11,1.864e-11,1.864e-11,9.46383e-08,1.00789e-06,1.00789e-06,3.70425e-09,2.44165e-07,2.44165e-07,2.44165e-07,2.52278e-11,0.0001,0.0001,1.67815e-11,1.67815e-11,4.02657e-11,4.02657e-11,6.24275e-08,2.04819e-10,2.04819e-10,6.47282e-10,1.80655e-11,9.6602e-10,9.6602e-10,9.6602e-10,9.6602e-10,9.6602e-10,1.00363e-08,1.00363e-08,1.00363e-08,3.18939e-09,5.78173e-07,5.78173e-07,7.06629e-11,2.1575e-09,2.1575e-09,2.1575e-09,6.00218e-11,6.00218e-11,6.00218e-11,1.61119e-05,8.18756e-08,8.18756e-08,3.627e-09,3.57748e-11,3.57748e-11,3.57748e-11,3.57748e-11,1.84825e-08,1e-14,1e-14,1e-14,1e-14,1e-14,3.63024e-09,3.63024e-09,3.72904e-10,3.72904e-10,3.13855e-13,1.28389e-11,1.28389e-11,1.28389e-11,1.1738e-09,1.1738e-09,1.1738e-09,1.1738e-09,3.45489e-11,5.46521e-08,5.46521e-08,5.46521e-08,5.46521e-08,5.46521e-08,9.1963e-09,4.39621e-10,1.80325e-06,1.80325e-06,1.80325e-06,5.21684e-14,1.15908e-05,1.15908e-05,1.15908e-05,6.25741e-08,6.25741e-08,6.25741e-08,6.25741e-08,1.1194e-09,1.1194e-09,2.04444e-07,2.04444e-07,2.04444e-07,2.04444e-07,2.04444e-07,6.86196e-08,7.59185e-09,1.8359e-09,1.8359e-09,5.77341e-10,3.44579e-08,3.44579e-08", "train/minibatch_size": "32768,16384,16384,16384,16384,32768,32768,32768,32768,32768,32768,65536,16384,16384,16384,16384,16384,32768,32768,32768,32768,16384,16384,16384,16384,16384,16384,16384,16384,16384,32768,32768,32768,32768,32768,32768,16384,16384,32768,32768,65536,65536,32768,32768,65536,65536,32768,16384,32768,32768,32768,32768,32768,32768,16384,32768,32768,32768,32768,32768,16384,32768,16384,16384,16384,16384,16384,16384,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,16384,16384,16384,16384,16384,65536,32768,32768,32768,32768,32768,32768,16384,16384,32768,32768,32768,32768,32768,32768,32768,16384,16384,16384,16384,16384,65536,65536,65536,32768,32768,16384,32768,32768,16384,65536,65536,65536,32768,16384,32768,32768,32768,32768,32768,65536,65536,32768,32768,65536,16384,16384,32768,32768,32768,32768,32768,16384,16384,16384,16384,16384,16384,32768,32768,32768,32768,16384,16384,16384,16384,32768,32768,16384,32768,32768,32768,32768,32768,32768,32768,32768,32768,65536,16384,32768,32768,32768,16384,32768,32768,32768,32768,32768,32768,32768,65536,32768,32768,32768,16384,32768,32768,32768,32768,16384,16384,16384,32768,32768,32768,32768,32768,16384,16384,16384,16384,32768,32768,32768,32768,32768,32768,16384,16384,16384,32768,32768,32768,32768,32768,32768,32768,16384,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,16384,32768,65536,65536,65536,65536,16384,16384,16384,16384,16384,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,16384,16384,32768,16384,32768,32768,65536,32768,32768,32768,32768,32768,32768,32768,65536,65536,65536,65536,32768,16384,16384,65536,32768,32768,32768,32768,32768,32768,32768,16384,32768,32768,32768,16384,16384,32768,32768,32768,16384,16384,65536,16384,16384,16384,32768,16384,16384,32768,16384,16384,16384,16384,32768,32768,16384,16384,65536,65536,32768,32768,32768,16384,32768,32768,32768,32768,32768,32768,16384,16384,16384,16384,32768,32768,32768,32768,32768,32768,32768,32768,32768,16384,32768,32768,32768,32768,32768,32768,32768,16384,32768,32768,32768,32768,32768,16384,16384,16384,16384,8192,16384,16384,16384,16384,16384,16384,16384,32768,16384,16384,16384,16384,16384,32768,16384,32768,32768,32768,32768,16384,16384,16384,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,16384,32768,32768,32768,65536,65536", "train/horizon": "256,128,64,64,64,256,256,256,256,256,128,256,128,128,128,128,128,128,128,128,128,64,64,64,64,64,64,64,512,512,128,512,512,256,128,128,128,64,512,256,256,256,128,256,256,256,256,128,128,128,128,128,128,128,128,512,512,512,512,256,128,512,256,256,256,512,512,64,512,128,128,128,256,256,256,256,128,128,128,128,128,128,64,256,256,256,256,256,256,256,128,128,128,128,128,128,128,128,256,512,512,512,128,128,512,512,512,256,256,128,128,128,256,256,256,256,256,512,128,128,128,128,128,128,128,128,128,256,256,64,256,256,256,256,256,128,128,128,128,128,128,512,128,128,128,128,128,128,128,128,64,256,128,256,256,128,256,128,64,128,128,256,128,128,128,128,256,256,256,256,256,256,256,256,512,256,256,128,256,256,256,256,128,64,64,64,64,512,256,128,128,128,128,128,128,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,128,128,256,256,256,256,256,1024,256,256,256,256,256,256,128,256,256,256,512,512,512,256,256,256,256,256,128,512,512,512,512,256,128,128,128,512,64,64,128,64,128,128,512,128,128,128,256,256,256,128,512,512,512,512,1024,128,128,128,128,128,128,256,128,128,128,256,128,128,256,64,64,256,128,256,64,64,256,128,128,128,128,256,256,128,512,512,512,256,512,512,256,256,256,256,1024,128,128,256,128,128,128,128,128,128,256,256,256,256,128,128,256,128,128,128,256,256,256,256,128,128,256,256,256,256,256,256,256,256,256,256,256,256,256,512,512,32,64,64,64,128,128,128,128,256,128,128,128,128,128,1024,128,512,512,512,512,64,64,64,256,256,256,256,128,128,256,256,256,256,256,256,128,256,256,128,256,256", "train/vtrace_rho_clip": "2.37151,2.8262,3.17147,3.17147,3.17147,2.50343,1.75315,1.75315,1.75315,2.48564,1.67191,2.71032,5,3.92351,3.92351,3.92351,3.92351,3.35974,3.35974,3.35974,3.35974,2.58586,2.58586,2.58586,2.58586,2.58586,2.58586,2.58586,2.4295,2.4295,4.0823,4.16428,4.16428,3.33384,3.56513,3.07,3.85915,2.79636,4.00659,3.56784,2.96953,2.15316,3.3272,4.8733,2.45204,2.45204,3.10373,5,3.50943,3.97056,3.97056,3.17641,2.93052,2.93052,2.9935,4.40909,4.40909,4.40909,3.93311,2.86826,3.64963,4.31064,2.48263,2.48263,2.48263,3.83195,3.83195,4.59897,1.6596,2.59801,2.59801,2.59801,1.53739,1.53739,1.70718,1.70718,3.00456,3.00456,2.38563,2.38563,2.38563,2.38563,3.98734,2.62997,2.99198,4.56286,3.76382,4.45577,4.45577,4.45577,4.70954,4.70954,2.62867,2.62867,1.09434,1.09434,3.34904,3.52106,3.24111,2.8388,2.8388,2.8388,5,5,2.48183,2.48183,2.48183,2.74123,3.06227,3.06238,2.72509,2.72509,4.42675,3.64257,3.64257,3.64257,3.36447,4.45027,3.26139,3.26139,3.26139,3.26139,3.26139,2.39055,2.9335,4.23443,4.23443,2.7404,2.86361,3.75744,3.69547,3.69547,3.69547,3.69547,3.69547,4.62638,4.62638,4.62638,4.62638,4.62638,2.55356,3.25425,2.98769,2.98769,2.98769,2.47904,2.47904,2.47904,2.47904,4.37973,4.40526,1.81547,5,4.18368,2.14603,3.02982,3.43597,2.53577,2.34292,3.66417,3.66417,2.87863,4.42795,4.68076,4.68076,4.68076,2.75028,1.84455,1.84455,1.84455,1.84455,4.14299,4.14299,4.14299,3.67912,3.56572,3.56572,1.9948,3.45497,3.70806,3.70806,3.70806,4.49144,3.1896,3.1896,3.1896,2.07008,2.97533,3.14217,4.66068,4.66068,2.36568,2.36568,2.36568,2.36568,4.11339,4.11339,4.28436,4.28436,4.28436,4.28436,5,5,5,4.37229,2.4289,2.4289,2.4289,2.4289,2.4289,3.78223,2.11455,4.66606,4.66606,4.66606,4.66606,4.66606,2.96283,3.11011,3.11011,3.11011,2.66997,2.66997,2.66997,5,3.33476,3.00635,3.02692,4.85099,4.85099,4.85099,1.97122,1.97122,1.97122,1.97122,1.97122,4.38864,2.53378,2.53378,2.53378,2.53378,3.36541,3.48487,3.22012,3.22012,4.61788,4.09632,4.09632,3.41884,3.16307,2.48108,2.48108,3.10353,2.65292,2.65292,2.65292,3.13933,3.13933,3.13933,3.35318,2.31296,2.31296,2.31296,2.52248,4.61504,2.74744,2.74744,2.50506,3.73616,2.31952,2.31952,4.35883,4.75717,4.75717,4.75717,2.81337,1.71435,1.71435,2.98413,4.71806,4.71806,4.63278,3.40386,2.61223,3.668,3.668,4.10239,2.06913,2.06913,2.06913,3.53166,3.40334,3.40334,3.98918,5,5,5,4.40235,3.98582,3.98582,2.83641,2.83641,3.14036,3.14036,2.7312,3.00433,3.00433,3.51746,2.79844,3.82102,3.82102,3.82102,3.82102,3.82102,1.69083,1.69083,1.69083,2.19915,2.92029,2.92029,4.34219,4.26172,4.26172,4.26172,2.67746,2.67746,2.67746,4.25341,3.19608,3.19608,3.35302,3.36453,3.36453,3.36453,3.36453,3.78007,5,5,5,5,5,2.55121,2.55121,4.01144,4.01144,3.02331,3.93263,3.93263,3.93263,3.05414,3.05414,3.05414,3.05414,3.63912,3.13014,3.13014,3.13014,3.13014,3.13014,4.48411,3.21668,4.86741,4.86741,4.86741,4.16647,2.70195,2.70195,2.70195,2.9024,2.9024,2.9024,2.9024,3.18816,3.18816,4.64879,4.64879,4.64879,4.64879,4.64879,4.62553,2.27144,3.25005,3.25005,2.00356,1.91157,1.91157", "train/vtrace_c_clip": "4.29932,4.45783,3.20906,3.20906,3.20906,4.41765,5,5,5,5,4.56332,3.71911,3.8784,2.77085,2.77085,2.77085,2.77085,4.15862,4.15862,4.15862,4.15862,5,5,5,5,5,5,5,5,5,3.13476,5,5,3.87,3.84768,4.09994,3.58429,3.28787,3.32434,3.38887,3.30946,3.66124,5,5,2.94695,2.94695,4.44797,3.90191,3.68456,4.73825,4.73825,5,3.78259,3.78259,5,3.63733,3.63733,3.63733,5,4.83263,3.9088,2.77215,5,5,5,3.18145,3.18145,3.7668,3.46549,5,5,5,4.67898,4.67898,5,5,3.19232,3.19232,4.63516,4.63516,4.63516,4.63516,1.06001,2.50664,4.84303,2.77806,5,4.51321,4.51321,4.51321,4.36439,4.36439,4.37765,4.37765,4.57923,4.57923,5,3.84482,5,5,5,5,2.74598,2.74598,4.82494,4.82494,4.82494,5,4.22083,3.96639,4.46109,4.46109,1.81529,5,5,5,4.79073,4.19728,4.65172,4.65172,4.65172,4.65172,4.65172,3.75971,4.68009,4.26014,4.26014,3.81874,5,3.89108,4.91681,4.91681,4.91681,4.91681,4.91681,3.28863,3.28863,3.28863,3.28863,3.28863,3.95147,4.97274,4.21267,4.21267,4.21267,5,5,5,5,4.24366,0.599177,4.48626,3.81987,4.41586,4.36278,2.50374,5,4.80454,3.36381,3.64036,3.64036,4.33643,4.05661,4.40885,4.40885,4.40885,5,5,5,5,5,2.12315,2.12315,2.12315,2.60155,3.69188,3.69188,4.51226,3.36546,3.04997,3.04997,3.04997,3.1653,5,5,5,2.39362,5,4.58527,4.91683,4.91683,4.28851,4.28851,4.28851,4.28851,3.61668,3.61668,4.21741,4.21741,4.21741,4.21741,4.47046,4.47046,4.47046,3.83265,4.75956,4.75956,4.75956,4.75956,4.75956,2.52504,4.96312,4.20778,4.20778,4.20778,4.20778,4.20778,3.92201,3.61786,3.61786,3.61786,4.58067,4.58067,4.58067,2.37655,4.61364,4.8155,3.99738,2.86699,2.86699,2.86699,4.65916,4.65916,4.65916,4.65916,4.65916,4.09462,4.69021,4.69021,4.69021,4.69021,2.61891,2.20505,3.28432,3.28432,4.98701,4.44707,4.44707,2.3013,5,4.70337,4.70337,3.8007,4.25731,4.25731,4.25731,2.88893,2.88893,2.88893,3.34497,3.47156,3.47156,3.47156,4.13901,4.39073,4.81137,4.81137,4.38717,4.32391,3.30696,3.30696,4.23343,4.82957,4.82957,4.82957,5,5,5,3.91224,3.3625,3.3625,1.8222,3.46197,4.15989,3.28332,3.28332,3.04903,5,5,5,3.84249,5,5,4.29204,4.00222,4.00222,4.00222,4.40311,3.36401,3.36401,5,5,5,5,3.95363,4.39069,4.39069,5,4.12668,4.50188,4.50188,4.50188,4.50188,4.50188,5,5,5,4.23565,4.55666,4.55666,4.79633,4.04512,4.04512,4.04512,5,5,5,2.51226,3.59668,3.59668,4.31591,3.92445,3.92445,3.92445,3.92445,5,1.6712,1.6712,1.6712,1.6712,1.6712,3.72067,3.72067,2.91574,2.91574,3.86188,4.1885,4.1885,4.1885,4.56868,4.56868,4.56868,4.56868,4.0838,3.94223,3.94223,3.94223,3.94223,3.94223,2.50475,4.69925,2.65421,2.65421,2.65421,1.36657,3.43331,3.43331,3.43331,2.61741,2.61741,2.61741,2.61741,4.53245,4.53245,3.65202,3.65202,3.65202,3.65202,3.65202,2.54985,4.80412,4.22913,4.22913,5,5,5", "train/prio_alpha": "0.789736,0.477615,0.692313,0.692313,0.692313,0.758731,0.894819,0.894819,0.894819,0.476815,0.555449,0.769471,1,0.691138,0.691138,0.691138,0.691138,1,1,1,1,1,1,1,1,1,1,1,0.762107,0.762107,0.99835,0.691766,0.691766,0.65177,1,0.68649,0.420009,0.737953,1,0.796801,0.570337,0.812044,0.450294,0.764598,0.998427,0.998427,0.790996,1,1,0.708207,0.708207,0.747905,0.91063,0.91063,1,1,1,1,0.487932,0.644396,0.659222,0.878292,0.781825,0.781825,0.781825,1,1,0.775622,0.969548,0.351222,0.351222,0.351222,0.732285,0.732285,0.764839,0.764839,0.79134,0.79134,0.589996,0.589996,0.589996,0.589996,0.841165,0.895781,0.782129,0.89324,0.892317,0.871891,0.871891,0.871891,1,1,0.809283,0.809283,0.945168,0.945168,0.852348,0.594888,0.766965,0.972013,0.972013,0.972013,0.655145,0.655145,1,1,1,0.607486,0.693493,0.914116,0.746717,0.746717,0.784106,0.388161,0.388161,0.388161,0.844112,0.882381,0.489991,0.489991,0.489991,0.489991,0.489991,0.769171,0.836519,1,1,0.732354,0.764509,1,0.571591,0.571591,0.571591,0.571591,0.571591,1,1,1,1,1,0.524186,0.77917,0.651756,0.651756,0.651756,0.898062,0.898062,0.898062,0.898062,0.734066,0.787732,0.93037,1,1,0.676749,1,0.697884,0.836,0.906946,0.894,0.894,0.275125,0.896056,0.840909,0.840909,0.840909,0.629654,0.493087,0.493087,0.493087,0.493087,0.868831,0.868831,0.868831,0.845553,0.8716,0.8716,0.836493,0.744612,0.403334,0.403334,0.403334,0.770781,1,1,1,0.850195,0.833647,0.475032,0.519499,0.519499,0.796482,0.796482,0.796482,0.796482,1,1,0.839854,0.839854,0.839854,0.839854,0.989317,0.989317,0.989317,0.812804,0.771611,0.771611,0.771611,0.771611,0.771611,1,0.762745,1,1,1,1,1,1,0.701404,0.701404,0.701404,0.849451,0.849451,0.849451,0.833096,0.735991,0.449951,1,0.785954,0.785954,0.785954,0.507015,0.507015,0.507015,0.507015,0.507015,0.678281,0.890807,0.890807,0.890807,0.890807,0.842828,0.935423,0.967782,0.967782,0.485347,0.767509,0.767509,0.608007,0.738427,0.551993,0.551993,0.744368,0.593239,0.593239,0.593239,1,1,1,0.563617,0.744056,0.744056,0.744056,0.982155,0.478774,0.896874,0.896874,0.603065,0.993513,0.737578,0.737578,1,0.96924,0.96924,0.96924,0.907923,0.616377,0.616377,1,0.722211,0.722211,0.768652,0.899902,0.495358,1,1,1,0.783623,0.783623,0.783623,0.646939,0.809644,0.809644,0.565985,0.755721,0.755721,0.755721,0.717116,0.85038,0.85038,0.552705,0.552705,0.73424,0.73424,0.652491,0.606116,0.606116,0.599736,0.963577,1,1,1,1,1,0.711794,0.711794,0.711794,0.872072,1,1,1,0.801028,0.801028,0.801028,0.854177,0.854177,0.854177,0.86865,0.414273,0.414273,0.91762,0.897767,0.897767,0.897767,0.897767,0.913609,0.646413,0.646413,0.646413,0.646413,0.646413,0.680512,0.680512,0.836182,0.836182,0.759725,0.922498,0.922498,0.922498,0.77166,0.77166,0.77166,0.77166,0.261073,0.645151,0.645151,0.645151,0.645151,0.645151,0.981678,0.389764,1,1,1,0.701461,1,1,1,0.784752,0.784752,0.784752,0.784752,0.956073,0.956073,1,1,1,1,1,0.79062,0.777762,1,1,0.610369,0.85607,0.85607", "train/prio_beta0": "0.573826,0.399616,0.696437,0.696437,0.696437,0.477735,0.572507,0.572507,0.572507,0.390331,0.230634,0.571805,0.434149,1,1,1,1,0.876735,0.876735,0.876735,0.876735,0.161561,0.161561,0.161561,0.161561,0.161561,0.161561,0.161561,0.588803,0.588803,1,0.982619,0.982619,0.864063,0.776915,0.678151,0.253609,0.710227,0.693777,0.931273,1,0.488533,0.0559141,0.0581595,0.707163,0.707163,0.497312,0.678569,0.856959,0.843219,0.843219,0.688892,0.560137,0.560137,0.320181,0.496154,0.496154,0.496154,0.181967,1,0.560067,0.653328,0.371355,0.371355,0.371355,0.816474,0.816474,0.521382,0.362313,0.190194,0.190194,0.190194,0.556578,0.556578,0.488691,0.488691,0.591888,0.591888,0.199,0.199,0.199,0.199,1,0.598565,0.30195,1,0.420828,0.686759,0.686759,0.686759,0.80509,0.80509,1,1,0.256024,0.256024,0.787515,0.448108,0.409082,0.753249,0.753249,0.753249,1,1,0.634504,0.634504,0.634504,0.454708,0.239036,0.484331,0.742907,0.742907,0.908632,0.132784,0.132784,0.132784,0.273921,0.893727,0.370807,0.370807,0.370807,0.370807,0.370807,0.886089,0.460001,0.861128,0.861128,0.875578,0.37078,0.771855,0.248194,0.248194,0.248194,0.248194,0.248194,0.636608,0.636608,0.636608,0.636608,0.636608,0.901778,0.920825,0.373288,0.373288,0.373288,0.509211,0.509211,0.509211,0.509211,0.831427,0.44902,0.744829,0.463269,0.846478,0.273073,0.663647,0.37711,0.79327,0.91861,0.893662,0.893662,0.270232,0.807305,0.404762,0.404762,0.404762,0.505532,0.345018,0.345018,0.345018,0.345018,0.981907,0.981907,0.981907,0.701234,0.420859,0.420859,0.576236,0.875567,0.264652,0.264652,0.264652,0.822342,0.81797,0.81797,0.81797,1,0.338444,0.482074,1,1,0.616572,0.616572,0.616572,0.616572,0.707643,0.707643,0.759826,0.759826,0.759826,0.759826,1,1,1,0.594481,0.351733,0.351733,0.351733,0.351733,0.351733,0.94417,0.821677,0.919203,0.919203,0.919203,0.919203,0.919203,0.860566,0.485922,0.485922,0.485922,0.454238,0.454238,0.454238,0.760268,0.527471,0.18149,0.502746,0.62121,0.62121,0.62121,0.170313,0.170313,0.170313,0.170313,0.170313,0.970378,0.175253,0.175253,0.175253,0.175253,1,0.759853,0.336238,0.336238,0.0722844,0.704272,0.704272,0.944833,0.921751,0.17099,0.17099,0.676369,0.335262,0.335262,0.335262,0.347762,0.347762,0.347762,0.244636,0.244783,0.244783,0.244783,0.952354,0.398143,0.474241,0.474241,0.879066,0.786684,0.175977,0.175977,0.782613,1,1,1,0.35364,1,1,0.924651,0.663667,0.663667,0.779733,0.562821,0.397229,0.57213,0.57213,0.539744,0.530853,0.530853,0.530853,0.507622,0.382319,0.382319,0.624051,0.45078,0.45078,0.45078,0.915352,0.656241,0.656241,0.192283,0.192283,0.526773,0.526773,0.476804,0.603796,0.603796,0.0536928,0.8134,0.516498,0.516498,0.516498,0.516498,0.516498,0.179578,0.179578,0.179578,0.49549,0.915388,0.915388,0.374843,0.912309,0.912309,0.912309,0.802177,0.802177,0.802177,0.409516,0.462328,0.462328,0.707951,0.367672,0.367672,0.367672,0.367672,0.69988,1,1,1,1,1,0.636022,0.636022,1,1,0.393688,0.630296,0.630296,0.630296,0.962028,0.962028,0.962028,0.962028,0.148553,0.59461,0.59461,0.59461,0.59461,0.59461,0.464359,0.416216,0.80346,0.80346,0.80346,0.948536,0.721183,0.721183,0.721183,0.881468,0.881468,0.881468,0.881468,0.748924,0.748924,0.70564,0.70564,0.70564,0.70564,0.70564,1,0.685485,0.757825,0.757825,0.52161,1,1", "train/max_minibatch_size": "32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768", "train/use_rnn": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "no_model_upload": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "tsne1": "12.4258,12.999,14.4367,14.4367,14.4367,15.6672,7.11592,7.11586,7.11586,15.0924,13.8037,8.52044,1.65885,-3.7353,-3.73677,-3.73646,-3.7365,-1.95362,-1.95345,-1.95362,-1.95362,15.6769,15.6769,15.6769,15.6769,15.6769,15.6769,15.6769,13.4442,13.4441,-2.52705,13.5196,13.5196,12.8079,3.53845,11.099,15.795,8.81748,1.83817,12.2742,7.46224,8.82876,14.4784,16.6266,9.40113,9.40121,9.82133,-0.8179,-0.781858,3.67791,3.67791,10.3812,14.9614,14.9615,13.608,2.09777,2.09779,2.09779,18.1818,4.8349,11.1677,1.78913,17.417,17.417,17.417,1.60886,1.6089,10.0401,8.74583,17.9024,17.9022,17.9024,8.5724,8.5724,16.7433,16.7433,7.20008,7.20008,11.1816,11.1816,11.1816,11.1816,-5.07457,10.0832,16.443,-2.91867,10.9263,-1.34718,-1.34722,-1.34737,0.227386,0.227662,14.5473,14.5473,14.8296,14.8293,6.24373,13.8351,10.3967,6.08338,6.08327,6.08337,-4.17599,-4.17599,19.7284,19.7284,19.7284,15.5083,11.6278,15.7983,12.3224,12.3224,-4.40457,20.2311,20.2311,20.2311,10.7365,0.7327,13.587,13.587,13.587,13.587,13.587,7.55767,10.4416,2.43642,2.43642,4.16705,14.781,-1.234,17.0659,17.0659,17.0658,17.0643,17.0643,-1.00815,-1.00835,-1.00815,-1.00815,-1.00815,15.0902,7.27293,12.2832,12.2832,12.2832,6.73656,6.73663,6.73659,6.73666,13.3316,-4.6159,18.1635,3.13645,1.26152,10.6257,0.126589,16.1119,6.82132,8.40402,2.86695,2.86721,18.2147,0.412191,15.5213,15.5213,15.5213,14.5104,16.0202,16.0192,16.0203,16.0206,12.4787,12.4787,12.4787,-2.27631,4.88537,4.88542,7.37569,2.62727,16.8967,16.8972,16.8967,12.2786,6.26298,6.26293,6.26298,6.84883,3.39684,13.7714,11.8373,11.8376,16.9675,16.9675,16.9675,16.9675,1.96499,1.96501,0.760126,0.760152,0.760152,0.760152,-1.72087,-1.72087,-1.72087,2.42908,9.70042,9.70042,9.70042,9.70042,9.70042,12.3829,13.0906,-0.451174,-0.451161,-0.449516,-0.451161,-0.451161,4.93217,10.3205,10.3205,10.3205,13.0775,13.0774,13.0775,1.49897,9.72181,16.06,9.00176,1.47681,1.47682,1.47682,14.0505,14.0491,14.0491,14.0491,14.0493,0.144786,9.05886,9.05932,9.05933,9.05886,-3.50274,9.45619,12.2709,12.2709,17.0012,4.64084,4.64084,12.954,18.1709,13.3607,13.3607,8.4482,14.3563,14.3558,14.3563,2.69063,2.69063,2.69063,15.5692,18.2051,18.2051,18.2051,4.18093,18.0098,6.71512,6.71512,8.11195,8.01535,12.2451,12.2451,2.51354,1.02313,1.02333,1.02337,6.28912,15.6704,15.6703,3.50937,11.241,11.241,-5.57473,2.77081,15.0066,4.9911,4.99105,2.92072,6.74322,6.74337,6.74322,11.8,8.50078,8.50078,7.57498,10.5986,10.5986,10.5979,0.208713,3.42127,3.42127,13.6063,13.6064,9.24279,9.24279,10.2924,11.4398,11.4398,13.6679,5.13872,9.88888,9.88731,9.88888,9.88942,9.88838,16.5689,16.5689,16.5689,16.9746,3.59757,3.59806,10.933,2.70325,2.7032,2.70324,6.42032,6.42079,6.42016,2.06527,14.2023,14.2023,13.7176,11.4085,11.4087,11.4096,11.4097,8.63428,-5.34907,-5.34907,-5.36003,-5.34907,-5.36003,10.5451,10.5443,-1.94146,-1.94146,16.733,4.56793,4.57097,4.56771,3.9441,3.9441,3.9441,3.9441,18.9202,9.50581,9.50563,9.50542,9.50587,9.50585,1.94372,13.0302,-2.51,-2.51069,-2.51069,-5.07889,1.51621,1.51621,1.51621,8.00248,8.00201,8.00201,8.00118,13.5647,13.5647,0.228816,0.229869,0.228287,0.228287,0.229869,1.4535,18.0858,3.8705,3.87058,14.6711,5.7274,5.7274", "tsne2": "-69.0283,-47.8021,-73.5349,-73.5349,-73.5349,-71.403,-45.0736,-45.0726,-45.0726,-46.5717,-45.8874,-61.6687,-60.6712,-64.1613,-64.1629,-64.1628,-64.1628,-57.7495,-57.7498,-57.7495,-57.7495,-61.1358,-61.1358,-61.1358,-61.1358,-61.1358,-61.1358,-61.1358,-57.9213,-57.9303,-58.7487,-76.1853,-76.1853,-73.544,-64.6031,-48.4895,-49.3665,-51.349,-63.4482,-73.6245,-74.9098,-61.6858,-49.0643,-43.6701,-69.3699,-69.3673,-47.127,-69.0963,-58.4322,-67.3042,-67.3042,-63.5364,-71.8917,-71.8918,-60.5813,-58.8496,-58.849,-58.849,-44.976,-67.2086,-52.3005,-64.2754,-72.0293,-72.0293,-72.0293,-63.0863,-63.0862,-66.903,-44.5301,-46.7799,-46.7799,-46.7799,-46.5497,-46.5497,-71.0797,-71.0797,-68.9956,-68.9956,-43.0066,-43.0068,-43.0066,-43.0068,-60.5382,-69.2692,-68.1849,-59.1488,-65.9138,-55.4422,-55.4425,-55.4423,-54.69,-54.6903,-75.5817,-75.5817,-63.6026,-63.6024,-64.7043,-51.5457,-46.2857,-62.7206,-62.7206,-62.7205,-60.0601,-60.0601,-70.1648,-70.1648,-70.1648,-46.188,-46.4627,-72.4471,-71.4995,-71.4995,-60.396,-47.6616,-47.6616,-47.6616,-45.8252,-64.8253,-49.7376,-49.7376,-49.7376,-49.7376,-49.7376,-74.9527,-63.3503,-68.8982,-68.8982,-66.1541,-56.7049,-64.126,-45.3454,-45.3453,-45.3455,-45.3461,-45.346,-63.418,-63.418,-63.418,-63.418,-63.418,-74.1929,-65.0006,-47.6517,-47.6517,-47.6517,-48.381,-48.3811,-48.381,-48.3811,-75.0174,19.2513,-73.9507,-52.8464,-55.0302,-44.9503,-59.0665,-45.0928,-64.9367,-71.6344,-67.8653,-67.8646,-67.4828,-60.5535,-69.1934,-69.1934,-69.1934,-56.8462,-52.6314,-52.6293,-52.6314,-52.6296,-78.3058,-78.3082,-78.3082,-70.6269,-50.7666,-50.7668,-47.8498,-67.0164,-49.6775,-49.6777,-49.6775,-73.7449,-55.6999,-55.6999,-55.6999,-74.788,-45.6691,-53.1026,-75.5773,-75.5778,-73.4138,-73.4138,-73.4138,-73.4138,-54.2589,-54.2588,-56.7587,-56.7587,-56.7587,-56.7587,-67.5607,-67.5607,-67.5607,-60.0504,-45.3847,-45.3847,-45.3847,-45.3847,-45.3847,-73.0975,-70.4665,-66.7667,-66.7667,-66.7677,-66.7667,-66.7667,-63.218,-47.4371,-47.4371,-47.4371,-66.5844,-66.582,-66.5844,-65.4242,-48.5564,-51.8753,-61.4107,-51.691,-51.6913,-51.6913,-41.1237,-41.1249,-41.1249,-41.1249,-41.125,-61.4423,-41.6274,-41.628,-41.6278,-41.6278,-58.3407,-70.9198,-63.5282,-63.5277,-44.3731,-68.6326,-68.6326,-73.8646,-74.6906,-45.0927,-45.0927,-59.5217,-50.7609,-50.7611,-50.7609,-46.1114,-46.1114,-46.1114,-49.5991,-69.1948,-69.1948,-69.1948,-62.2251,-43.9085,-49.524,-49.524,-75.1228,-66.685,-45.5301,-45.5298,-69.6788,-67.5602,-67.5603,-67.5603,-47.7131,-76.0714,-76.0714,-62.7814,-73.9651,-73.9651,-57.7707,-60.4586,-46.7209,-59.1922,-59.1962,-52.5994,-43.6059,-43.6059,-43.6059,-49.0645,-48.9648,-48.9648,-68.0629,-54.9397,-54.9396,-54.9398,-61.4395,-50.6785,-50.6785,-43.3993,-43.3992,-62.8477,-62.8477,-58.4113,-50.7101,-50.7114,-43.4295,-64.4175,-65.9678,-65.9673,-65.9691,-65.9676,-65.9677,-57.188,-57.188,-57.188,-72.6346,-70.0131,-70.0123,-61.5465,-65.7846,-65.7845,-65.7846,-64.0471,-64.0465,-64.0467,-46.6061,-47.4116,-47.4115,-72.1972,-62.3519,-62.3491,-62.3514,-62.3508,-66.0916,-58.5002,-58.5002,-58.5022,-58.5002,-58.5022,-57.8293,-57.8294,-60.6136,-60.6136,-60.7309,-59.8593,-59.8606,-59.8595,-72.2007,-72.2007,-72.2006,-72.2006,-45.1112,-50.4615,-50.4615,-50.4616,-50.4615,-50.4615,-46.6874,-50.2348,-69.9597,-69.9598,-69.9598,-58.0288,-73.2271,-73.2271,-73.2271,-70.8149,-70.8143,-70.8143,-70.8144,-71.8748,-71.8748,-69.5182,-69.517,-69.5179,-69.5179,-69.517,-65.6007,-74.1479,-63.2256,-63.2267,-55.0524,-66.4989,-66.4989"}, "freeway": {"SPS": "1.12328e+06,1.12043e+06,1.61078e+06,441510,441913,441050,439752,1.6575e+06,431442,992371,2.76691e+06,2.72927e+06,2.71153e+06,218029,4.74389e+06,1.0004e+06,698540,681065,677895,2.75067e+06,2.74841e+06,409579,409548,409985,794255,2.23255e+06,2.22629e+06,2.21619e+06,2.16936e+06,718938,720310,2.14293e+06,1.28177e+06,1.27091e+06,2.42658e+06,997725,4.09136e+06,473677,999585,1.5333e+06,1.15923e+06,1.15688e+06,561977,8.5244e+06,126003,125899,125955,1.64854e+06,1.62441e+06,1.6221e+06,985956,874872,5.13003e+06,1.99487e+06,1.99549e+06,127771,451814,119888,119802,119777,1.13455e+06,3.36742e+06,171165,171028,170931,1.26049e+06,266367,265724,139312,139191,2.99706e+06,1.97257e+06,1.97658e+06,5.13711e+06,1.35584e+06,1.35037e+06,5.92325e+06,4.27663e+06,385169,380637,378521,376833,1.01408e+06,652448,496535,2.10875e+06,144254,144317,3.53811e+06,3.50916e+06,2.60514e+06,125965,155412,155296,155235,155126,154942,1.5153e+06,1.47603e+06,651402,642766,634154,636586,7.01007e+06,919994,1.02557e+06,1.01997e+06,4.89942e+06,2.47876e+06,2.24971e+06,2.21976e+06,3.70644e+06,3.67411e+06,3.66223e+06,487399,573562,696030,1.16673e+06,5.46191e+06,5.43842e+06,5.4389e+06,1.24185e+06,1.35275e+06,3.33638e+06,3.26537e+06,3.22939e+06,3.22076e+06,3.21685e+06,493012,492399,491950,492404,112047,112020,309444,242322,151765,151835,151707,151662,151273,801316,790142,4.91049e+06,5.23728e+06,634323,633037,471151,476173,684862,683700,683203,2.60404e+06,1.15701e+06,3.00399e+06,2.6355e+06,2.56552e+06,2.54892e+06,2.25078e+06,2.2437e+06,1.2234e+06,96030.4,3.73726e+06,3.7184e+06,1.2915e+06,5.3376e+06,824661,394837,1.40044e+06,2.04587e+06,7.93875e+06,3.19538e+06,373543,1.90393e+06,3.9222e+06,4.39227e+06,1.13258e+06,209514,2.69654e+06,2.68802e+06,2.688e+06,2.69149e+06,1.77189e+06,1.74957e+06,1.74234e+06,309593,303626,295516,483095,482468,483467,214980,1.01482e+06,1.6522e+06,1.06003e+06,1.0491e+06,1.04416e+06,1.05126e+06,6.27e+06,6.17273e+06,6.11032e+06,6.07674e+06,6.0793e+06,1.15268e+06,1.15049e+06,3.18074e+06,2.31105e+06,2.30237e+06,494324,238695,238702,818832,250985,1.82158e+06,1.31612e+06,802856,805308,6.52259e+06,475860,3.81949e+06,3.84662e+06,2.40565e+06,144445,1.2109e+06,1.21726e+06,1.2291e+06,95907.7,96020.4,521654,658925,256841,943542,1.92834e+06,922512,230684,1.18693e+06,3.09782e+06,3.11103e+06,4.00918e+06,3.89686e+06,3.91681e+06,2.67992e+06,769164,761339,765825,765979,766043,4.1166e+06,4.11733e+06,1.63002e+06,1.62197e+06,1.68688e+06,1.69876e+06,897548,1.10369e+06,4.35844e+06,4.3313e+06,3.38829e+06,3.35385e+06,3.33279e+06,3.33597e+06,3.32344e+06,1.25161e+06,1.24712e+06,4.29494e+06,4.20596e+06,4.1866e+06", "agent_steps": "298.844,339.739,185.598,163.578,272.105,380.633,434.635,51.1181,134.218,337.641,63.701,165.937,441.45,314.573,252.183,50.3316,236.716,331.088,378.012,187.564,262.537,150.995,249.561,396.362,54.526,119.538,198.967,278.397,317.981,440.402,499.122,67.6332,143.655,380.633,317.194,41.943,261.095,442.499,143.131,515.899,124.256,206.045,47.7102,51.9045,57.6717,389.022,443.548,45.8752,262.668,299.893,174.588,247.464,46.1373,267.387,304.087,180.879,115.343,51.3802,148.111,246.678,79.1675,223.347,126.091,209.977,293.601,186.122,171.966,285.213,126.353,293.601,62.6524,263.193,299.893,142.344,130.023,216.531,45.8752,45.8752,125.829,207.618,289.407,327.156,394.265,293.601,157.286,68.9439,147.063,244.58,222.298,354.943,77.0703,240.124,57.1474,159.384,265.29,370.672,422.576,182.452,483.394,147.849,245.891,343.933,392.167,47.9724,50.8559,50.3316,138.412,45.8752,64.2253,167.772,446.169,120.062,199.754,279.446,402.653,45.6131,424.673,9.1095,200.802,281.018,320.864,436.208,516.948,41.6809,112.525,187.498,262.472,299.893,127.926,211.812,295.698,335.544,167.772,278.921,132.645,234.881,43.2538,123.47,205.259,287.048,327.68,239.075,381.682,45.8752,144.703,132.121,216.007,156.5,260.309,152.568,254.018,355.467,336.593,149.422,45.8752,112.591,187.564,262.537,144.703,240.91,599.261,148.898,253.231,403.702,54.526,45.8752,381.682,145.752,394.265,287.834,46.7927,299.893,138.412,71.8275,58.4581,39.5837,354.419,318.767,123.732,206.045,288.096,328.729,42.9916,116.654,194.249,201.327,281.018,318.767,144.703,239.075,333.447,228.59,176.685,62.3903,42.4673,115.343,191.889,231.735,45.8752,112.722,187.695,262.668,299.893,58.7203,436.208,394.265,236.454,377.487,57.4095,293.601,327.156,266.338,115.343,65.1428,79.6918,119.8,199.492,46.1373,55.5745,297.271,338.69,52.4288,71.3032,64.2253,180.355,480.248,208.667,291.504,467.665,169.869,318.767,56.361,296.223,24.6415,50.3316,73.6625,267.911,305.136,113.246,263.193,299.893,41.6809,48.2345,138.936,231.211,323.486,369.099,274.203,313,118.489,197.132,275.775,314.573,398.459,38.7973,147.325,245.367,112.722,187.695,262.668,299.893,252.183,130.023,216.007,50.0695,125.043,112.722", "uptime": "273.392,309.782,115.011,370.979,616.906,862.474,985.543,30.8374,310.724,340.624,22.925,60.2003,161.648,1446.43,52.068,50.2608,339.295,475.959,545.092,67.0624,94.3262,368.027,608.683,966.638,68.7794,53.3298,88.9593,124.689,142.592,610.501,692.393,31.5254,111.508,297.184,133.63,42.1869,55.1927,943.018,143.218,330.12,106.558,177.202,84.9212,6.14775,457.56,3089.73,3522.79,27.7786,160.663,183.585,175.176,280.851,9.04405,128.342,146.743,1415.6,253.986,428.623,1235.68,2058.53,69.6303,65.5369,735.724,1225.96,1715.05,147.916,646.358,1071.83,906.344,2107.65,20.8903,132.32,150.923,27.2079,95.839,159.832,7.84164,10.8142,326.873,540.002,756.137,855.822,388.965,454.03,316.407,32.5537,1018.09,1694.05,63.1806,102.028,29.5317,1907.08,367.567,1025.73,1707.89,2386.95,2721.52,120.657,322.717,226.588,377.61,531.638,607.719,7.0093,55.253,49.0546,135.199,9.39408,25.8911,69.8349,195.084,32.0401,53.6434,75.381,841.818,79.4832,611.207,7.8369,36.2983,51.0177,58.3491,349.645,378.866,12.5887,34.0411,57.1571,80.4113,92.0318,256.884,427.2,597.613,678.633,1497.07,2489.22,427.857,968.11,285.124,813.357,1352.41,1891.39,2159.44,296.421,475.605,9.37128,27.4682,207.994,340.407,334.774,553.651,221.821,370.093,518.545,127.856,130.665,15.0102,39.3242,68.0458,97.425,63.8746,106.698,487.988,1550.05,67.1178,107.457,42.1956,8.59949,467.119,368.665,280.711,140.013,6.03422,92.7184,369.782,37.6716,14.8318,9.19002,312.389,1523.99,45.6316,76.2204,106.748,121.864,24.252,66.1493,110.601,655.35,915.014,1039.9,298.892,494.366,689.639,1062.48,173.696,38.0407,40.0272,109.235,182.384,219.743,7.31538,18.0707,30.2863,42.5969,48.7247,50.8471,380.231,120.964,101.025,162.185,116.055,1228.93,1369.51,323.674,459.511,35.623,60.3995,148.372,247.474,7.23617,116.384,77.0142,87.8594,23.0174,493.503,53.7333,149.011,394.203,2174.75,3038.05,893.3,257.051,1236.37,59.7811,153.874,26.791,218.207,61.9688,85.1582,97.1572,28.0986,66.1422,75.5679,15.6278,62.5535,181.636,302.198,422.773,482.33,65.6067,75.0362,72.1322,120.513,168.291,191.103,443.5,35.898,33.2235,55.81,32.8129,55.0591,77.4905,88.675,75.07,103.463,172.333,11.5846,29.2735,26.6555", "epoch": "142.5,162,177,312,519,726,829,97.5,32,322,121.5,316.5,842,37.5,240.5,24,451.5,631.5,721,715.5,1001.5,72,119,189,52,456,759,1062,1213,105,119,258,137,363,302.5,40,498,211,136.5,492,118.5,196.5,45.5,99,55,371,423,87.5,501,572,166.5,118,44,127.5,145,172.5,27.5,98,282.5,470.5,75.5,852,240.5,400.5,560,177.5,41,68,120.5,280,119.5,251,286,271.5,248,413,87.5,87.5,30,49.5,69,78,47,35,37.5,131.5,280.5,466.5,424,677,73.5,114.5,54.5,152,253,353.5,403,174,461,141,234.5,328,374,91.5,48.5,48,132,87.5,122.5,320,851,114.5,190.5,266.5,96,43.5,405,278,383,536,612,104,493,318,858.5,1430.5,2002.5,2288,30.5,50.5,70.5,80,80,133,126.5,28,82.5,235.5,391.5,547.5,625,228,364,87.5,138,31.5,51.5,298.5,496.5,291,484.5,678,321,285,175,429.5,715.5,1001.5,276,459.5,1143,71,241.5,385,104,87.5,91,69.5,94,274.5,178.5,286,66,68.5,111.5,151,338,38,236,393,549.5,627,82,222.5,370.5,48,67,76,69,114,159,54.5,168.5,59.5,40.5,110,183,110.5,87.5,215,358,501,572,112,832,376,225.5,360,109.5,35,39,63.5,27.5,248.5,76,228.5,380.5,44,53,283.5,323,100,136,122.5,344,916,99.5,139,892,162,38,107.5,282.5,23.5,48,281,255.5,291,108,251,286,79.5,46,132.5,220.5,308.5,352,523,597,113,188,263,300,95,148,281,468,215,358,501,572,240.5,62,103,191,477,215", "perf/rollout": "0.248733,0.253245,0.148493,0.101315,0.0985815,0.10134,0.106166,0.0837101,0.887883,0.17483,0.0599869,0.0623751,0.0635834,1.62472,0.128144,0.266727,0.105802,0.12522,0.128819,0.0309373,0.0310073,0.472489,0.473076,0.467384,0.108056,0.0255592,0.0258855,0.0264264,0.0288303,0.880376,0.869956,0.0362076,0.170088,0.177022,0.112878,0.0971924,0.0743093,0.363165,0.149223,0.17019,0.18184,0.18387,0.170137,0.0381153,0.440471,0.442974,0.44212,0.0601015,0.0638823,0.0641243,0.212902,0.260465,0.136305,0.247858,0.247374,0.661269,0.548045,0.349431,0.349088,0.349203,0.170182,0.038089,0.199157,0.199924,0.20015,0.153386,1.42263,1.46216,0.46268,0.464787,0.0417853,0.129061,0.127984,0.0572569,0.0760877,0.0777522,0.0767538,0.0449658,0.818945,0.965101,1.02585,1.07588,0.820498,1.02293,0.658343,0.0617451,0.222787,0.224033,0.0396409,0.0408154,0.113627,0.923703,0.433697,0.435552,0.434461,0.436095,0.444391,0.194172,0.211583,0.132807,0.15451,0.17628,0.169731,0.0464241,0.100707,0.199462,0.204963,0.0704868,0.0370562,0.0587108,0.0617626,0.123706,0.126032,0.126979,0.712638,0.283333,0.281213,0.0103039,0.0352704,0.0356885,0.0356936,0.665182,0.151486,0.0195866,0.0204024,0.0208483,0.0209776,0.021045,0.555122,0.564118,0.571288,0.563398,0.826245,0.831556,0.202104,1.64,0.354703,0.349886,0.351249,0.353115,0.359392,0.190054,0.208365,0.0610922,0.0717658,0.605858,0.61905,0.108473,0.0966232,0.079169,0.080209,0.0805404,0.185457,0.0602526,0.0258112,0.037851,0.0405843,0.0412459,0.0516276,0.0522241,0.0806346,1.31521,0.0892785,0.0907216,0.0725851,0.0713034,0.505838,0.413747,0.519158,0.142775,0.0286194,0.0926158,0.40507,0.118147,0.0564681,0.0580087,0.16824,0.802478,0.0517824,0.0524085,0.0524206,0.0521615,0.0806426,0.0844237,0.085674,0.823417,1.05347,1.45805,0.310565,0.315622,0.306237,0.937258,0.144994,0.140669,0.174965,0.184462,0.189267,0.260315,0.0390141,0.0403234,0.0412054,0.0416829,0.04163,0.0735497,0.0737956,0.12132,0.141783,0.143455,0.0943562,1.04525,1.04483,0.963713,0.667758,0.0432084,0.168298,0.0852351,0.0847364,0.124303,0.150765,0.0783622,0.0764163,0.0738516,0.219417,0.0627255,0.059929,0.0558267,1.33213,1.31259,0.0937836,0.145833,1.16648,0.0571251,0.0948274,0.122947,0.200893,0.0332026,0.120192,0.118731,0.112953,0.12054,0.119158,0.0673021,0.178864,0.193023,0.184912,0.184253,0.184236,0.0589645,0.0589306,0.136212,0.139189,0.114311,0.109573,0.580297,0.064875,0.0577018,0.0584789,0.0643716,0.0658934,0.0668575,0.0667455,0.123537,0.246979,0.253236,0.0332485,0.0345035,0.0658809", "perf/eval_gpu": "0.0751753,0.0786208,0.0210105,0.041572,0.0432406,0.0441541,0.0403592,0.0150274,0.187094,0.0676627,0.00666752,0.00663645,0.00643112,0.643285,0.00614343,0.0213987,0.0537429,0.046196,0.0423432,0.00433719,0.00429252,0.171879,0.166002,0.178973,0.0334019,0.00579844,0.00577685,0.00573629,0.00682776,0.406294,0.331815,0.00464469,0.0246681,0.0239394,0.0198799,0.0228076,0.00426731,0.185182,0.0347348,0.0218902,0.032439,0.0322741,0.0508217,0.00482056,0.330317,0.327333,0.323015,0.00917195,0.00944464,0.00959058,0.0523297,0.038151,0.0105645,0.0325373,0.0326532,0.556532,0.115803,0.283305,0.276,0.284463,0.0274145,0.00287312,0.14264,0.143041,0.141555,0.0249611,0.719709,0.761058,0.348252,0.349666,0.00839282,0.0180323,0.0178453,0.00322172,0.0164822,0.0163639,0.00447202,0.0050288,0.326018,0.287696,0.271631,0.267478,0.182076,0.269126,0.0701302,0.00767121,0.15815,0.163616,0.0075406,0.00807823,0.00776014,0.724873,0.332628,0.328696,0.312777,0.312338,0.315956,0.0310369,0.03044,0.0494868,0.0446657,0.0390856,0.0429804,0.00853952,0.0219673,0.0260452,0.0261421,0.0037861,0.00666935,0.00617642,0.00616628,0.00929268,0.00930054,0.00929129,0.35508,0.0531281,0.07981,0.00275531,0.00387557,0.00389611,0.00400218,0.076686,0.0203514,0.00223256,0.00213611,0.00213025,0.00212759,0.00201464,0.0652813,0.0663394,0.066895,0.0668096,0.595905,0.588933,0.0732073,0.564197,0.275159,0.271668,0.270746,0.275545,0.271443,0.0749853,0.0693913,0.0043623,0.00743241,0.102491,0.102176,0.0436319,0.0343539,0.0223523,0.0221101,0.0223204,0.0103651,0.0218686,0.00367064,0.00363003,0.00348943,0.00347429,0.0110962,0.0109517,0.0150936,0.991113,0.00975522,0.0102554,0.00982164,0.0038692,0.093628,0.10176,0.0575553,0.0137131,0.00476734,0.00856315,0.14604,0.0102503,0.00346177,0.00607592,0.0347286,0.143032,0.0110358,0.0110634,0.0106169,0.00999089,0.0110147,0.0109437,0.0109404,0.145677,0.167898,0.651381,0.0914629,0.0912273,0.0958818,0.374428,0.0305249,0.0216815,0.0333535,0.0342211,0.0342536,0.057665,0.00525817,0.00521463,0.00522056,0.00522501,0.00524091,0.0160099,0.0160968,0.0105105,0.0136249,0.013872,0.0317501,0.147353,0.14556,0.100632,0.0897612,0.00719978,0.0219785,0.0226039,0.021026,0.00719267,0.031175,0.016894,0.0153396,0.00754939,0.156599,0.0173036,0.016898,0.0172218,0.996042,0.997786,0.0348099,0.0301585,0.175966,0.0137869,0.0215939,0.0485402,0.0757089,0.00527309,0.00687638,0.00696231,0.010375,0.010088,0.00989083,0.0108458,0.0542497,0.0630534,0.056052,0.055,0.0585395,0.00357535,0.0036132,0.0212372,0.0208706,0.0214162,0.0222521,0.0758002,0.0306514,0.00432753,0.00439214,0.00572429,0.00572412,0.00582675,0.00572709,0.0082841,0.064096,0.0637925,0.00192148,0.00190747,0.00288344", "perf/eval_env": "0.164367,0.164509,0.112779,0.0406125,0.0404646,0.0379156,0.0449348,0.0517299,0.517144,0.0784003,0.049464,0.0525567,0.0513458,0.951409,0.104136,0.222347,0.0486469,0.0569967,0.0582824,0.0177166,0.017993,0.251375,0.246268,0.203235,0.0671731,0.0184436,0.0188224,0.0193071,0.0196275,0.420546,0.45327,0.0277897,0.124685,0.127401,0.0650762,0.0697745,0.0478411,0.166143,0.088331,0.100833,0.12383,0.124065,0.0887967,0.0319719,0.079876,0.084091,0.0873481,0.0386941,0.0364432,0.0357749,0.129483,0.19501,0.123754,0.14627,0.146117,0.0850709,0.384609,0.0501604,0.0540909,0.0500154,0.129142,0.0249382,0.039263,0.0401632,0.0410465,0.103069,0.590731,0.589129,0.0835175,0.0828903,0.0317344,0.0855751,0.0897488,0.0493161,0.038605,0.0399462,0.070588,0.0385073,0.470718,0.543311,0.574603,0.587601,0.628442,0.733765,0.542128,0.049466,0.0503839,0.0428582,0.0304732,0.0310537,0.0868891,0.151026,0.0788362,0.0807742,0.097097,0.0980212,0.0979127,0.131121,0.115962,0.0709707,0.0816442,0.101792,0.0798466,0.0336577,0.0735989,0.166368,0.171624,0.0601725,0.0286409,0.0382441,0.0372364,0.0745291,0.0760062,0.076636,0.335797,0.22616,0.149381,0.00704326,0.0303434,0.0307235,0.030585,0.511433,0.0825944,0.0148249,0.0157635,0.0161625,0.0162964,0.0168611,0.369751,0.358468,0.354425,0.362042,0.167385,0.172367,0.0927844,0.794917,0.0621723,0.0593034,0.0616909,0.0579923,0.0688993,0.0935646,0.103803,0.0535877,0.0627632,0.364115,0.379577,0.0467965,0.0485819,0.0454567,0.0445753,0.0432796,0.156345,0.0352347,0.0202326,0.0247944,0.0274863,0.0285481,0.0384545,0.0391337,0.0474239,0.240977,0.0778367,0.0786883,0.0557919,0.0600705,0.300819,0.278298,0.406416,0.0970756,0.021492,0.0810394,0.220381,0.0975385,0.0454252,0.0505217,0.112566,0.63727,0.0386135,0.0392847,0.0397335,0.0400478,0.0598276,0.0595453,0.0561443,0.655563,0.761043,0.733341,0.165999,0.16255,0.150828,0.412912,0.0931966,0.116043,0.112465,0.113859,0.118279,0.188466,0.0323253,0.0336998,0.03459,0.0349997,0.035073,0.0477809,0.0435229,0.0799133,0.124009,0.125252,0.0460302,0.772583,0.800429,0.664524,0.488593,0.0337658,0.129254,0.045896,0.0438452,0.105218,0.0771803,0.059399,0.0594889,0.0596316,0.0474797,0.037083,0.0359164,0.0357416,0.254799,0.237563,0.0461169,0.0941546,0.632706,0.0348623,0.0699012,0.0680807,0.100529,0.0250879,0.096945,0.101137,0.0746981,0.0914448,0.0913791,0.0474702,0.0998824,0.103354,0.104036,0.0956601,0.0892362,0.0489736,0.0488115,0.0752133,0.0772681,0.0739704,0.073445,0.347883,0.0193552,0.0419984,0.0411771,0.0407236,0.0415946,0.0395122,0.0396261,0.102566,0.176618,0.182919,0.0286303,0.0296666,0.0600934", "perf/train_misc": "0.0308386,0.0308439,0.0111454,0.00582844,0.00583123,0.00583076,0.00588595,0.00786218,0.141573,0.0139653,0.00410727,0.00411696,0.00413104,1.04399,0.0104464,0.0635665,0.00393813,0.00393728,0.00393232,0.00292867,0.00292817,0.0445649,0.0445818,0.0444977,0.0282618,0.00473827,0.00473777,0.00474015,0.00473306,0.0431296,0.0432458,0.00347327,0.0212178,0.0211508,0.00797248,0.0207386,0.00528337,0.0450089,0.0150109,0.00652902,0.00707643,0.00708267,0.0319049,0.00250267,0.0364194,0.036473,0.0363203,0.0140721,0.0141269,0.0141668,0.00829774,0.0544373,0.0059582,0.03119,0.0308808,0.0324535,0.256706,0.0124295,0.0124686,0.0124436,0.0082675,0.00337764,0.00630532,0.00631531,0.00631764,0.00757704,0.112185,0.112258,0.0194771,0.0195352,0.00693788,0.0149708,0.0150518,0.00518697,0.00453166,0.00452729,0.000913807,0.00601161,0.221487,0.221302,0.220654,0.21984,0.342865,0.205029,0.25159,0.00503659,0.00662054,0.00661134,0.00569738,0.00565322,0.0322634,0.0950781,0.0303563,0.0303628,0.0304216,0.0304393,0.0305039,0.00519129,0.00520909,0.0156178,0.0156338,0.0156376,0.0156006,0.00147291,0.0227208,0.0144632,0.0144626,0.00378892,0.0103407,0.0103619,0.0103035,0.00932893,0.00934679,0.00934018,0.073514,0.0304028,0.011134,0.000170255,0.00593984,0.0059416,0.00595053,0.0671129,0.0150917,0.00122207,0.00121891,0.00121926,0.00121732,0.00120109,0.258665,0.258352,0.2583,0.258297,0.123325,0.12327,0.0366996,0.901909,0.00589516,0.00590634,0.0059126,0.00589387,0.00581235,0.0229808,0.0228618,0.00306281,0.0165964,0.114517,0.114304,0.00615329,0.00615582,0.00529718,0.00530657,0.00530632,0.0163883,0.00850106,0.00414329,0.00414703,0.00413839,0.00414158,0.00943005,0.00944087,0.00321328,0.125409,0.0163143,0.0162487,0.0119746,0.00247495,0.0669205,0.0626572,0.0931686,0.0153796,0.000380665,0.0296532,0.0535586,0.0231962,0.00763959,0.000229462,0.010325,1.73924,0.00745734,0.00746229,0.0074578,0.00740557,0.00563212,0.00563502,0.00563371,0.282328,0.282551,0.28455,0.0444995,0.0444827,0.0444953,0.276614,0.011694,0.014062,0.0122292,0.0122505,0.012241,0.0201432,0.00302425,0.00302348,0.00302309,0.00302639,0.00301373,0.00551371,0.0054743,0.00897946,0.0103892,0.0104049,0.0113693,0.902934,0.898272,0.0972832,0.520453,0.00177142,0.0156262,0.00524672,0.00523868,0.00245263,0.0498829,0.00826988,0.00829853,0.00855967,0.0111383,0.00600191,0.00601047,0.00606515,0.125371,0.125151,0.00539446,0.0258418,0.797998,0.0174113,0.0165964,0.0135406,0.0734727,0.00947158,0.0279454,0.0278999,0.00814877,0.00815627,0.00819098,0.00230006,0.0156805,0.0156914,0.015677,0.0156721,0.0156303,0.00676626,0.00677382,0.018706,0.018731,0.0187638,0.0187382,0.0985323,0.0186319,0.00411613,0.00411753,0.00450452,0.00451035,0.00450989,0.00453018,0.0128458,0.0306742,0.0306565,0.00288884,0.00289157,0.0111713", "perf/train_forward": "1.58701,1.58684,0.490973,1.07995,1.08391,1.08398,1.08131,0.224434,8.65412,0.868027,0.125108,0.125289,0.125307,37.542,0.0820499,1.7654,0.640637,0.640703,0.640025,0.0612061,0.0612087,4.60284,4.6025,4.60535,1.18338,0.0868843,0.08688,0.0868922,0.0870851,4.91037,4.90695,0.0823668,0.626138,0.626123,0.311895,0.932294,0.0482981,4.02181,0.88427,0.506829,0.715316,0.715009,1.66304,0.0207014,7.84293,7.84889,7.84153,0.243329,0.244218,0.244429,0.841887,2.06795,0.061912,0.77168,0.771803,7.51077,8.47871,4.01311,4.01581,4.01544,0.745521,0.0361462,2.8596,2.86312,2.86349,0.670517,14.214,14.2189,7.04325,7.04893,0.125965,0.387112,0.387943,0.0392446,0.305717,0.305658,0.0106669,0.0713785,9.83498,9.8361,9.83358,9.84195,7.1166,11.639,7.53502,0.181537,3.4055,3.40218,0.102578,0.102462,0.256027,15.6278,6.28054,6.28221,6.28852,6.28945,6.284,0.493082,0.493409,1.46092,1.46084,1.46096,1.46171,0.0267153,1.01562,0.808069,0.808113,0.0324409,0.163825,0.163819,0.163814,0.14946,0.149624,0.149641,7.81897,1.51385,1.21393,0.0174166,0.0545446,0.0545336,0.0546325,2.64239,0.609101,0.0183182,0.0183193,0.0183191,0.0183007,0.0182845,7.69172,7.69246,7.69372,7.68501,17.7655,17.7632,3.14917,32.0834,3.09661,3.10122,3.10296,3.10211,3.10283,1.09518,1.09501,0.0423223,0.111638,5.88932,5.89169,0.997927,0.997917,0.680986,0.681184,0.681405,0.200401,0.384055,0.0572343,0.057238,0.0572417,0.0572301,0.171569,0.171738,0.344801,20.397,0.174613,0.174367,0.320993,0.0242817,4.51019,4.83386,2.38089,0.354081,0.00394716,0.205277,5.15587,0.408908,0.0692208,0.00129246,0.74623,37.5726,0.134937,0.13491,0.134888,0.134886,0.209371,0.209357,0.209324,12.4387,12.7394,12.4455,3.98459,3.98548,3.98583,18.2925,0.875947,0.479564,0.801612,0.802349,0.802376,1.71423,0.0413945,0.0413856,0.0413832,0.0413751,0.0414382,0.375483,0.375546,0.19926,0.301298,0.301486,0.954558,33.1951,33.2063,4.06004,15.519,0.0986637,0.612307,0.56558,0.560939,0.0337329,2.00223,0.187604,0.187816,0.135917,3.39904,0.364114,0.364496,0.364299,20.4053,20.4008,0.905859,1.4188,30.7077,0.480781,0.431942,1.00016,4.27066,0.177788,0.189863,0.190217,0.140156,0.140116,0.139891,0.125765,1.168,1.1679,1.16807,1.16819,1.16851,0.0612494,0.0612332,0.487789,0.488114,0.488467,0.48895,3.99479,0.153938,0.0581684,0.0581624,0.085533,0.0855698,0.0855916,0.0855951,0.178834,1.39773,1.39748,0.0246064,0.0246191,0.04778", "perf/train": "1.61785,1.61768,0.502119,1.08578,1.08974,1.08981,1.0872,0.232296,8.7957,0.881993,0.129215,0.129406,0.129438,38.586,0.0924963,1.82897,0.644575,0.644641,0.643957,0.0641347,0.0641369,4.64741,4.64708,4.64984,1.21164,0.0916225,0.0916178,0.0916324,0.0918181,4.9535,4.95019,0.08584,0.647355,0.647274,0.319867,0.953032,0.0535815,4.06682,0.899281,0.513358,0.722392,0.722091,1.69494,0.0232041,7.87935,7.88536,7.87785,0.257401,0.258345,0.258596,0.850184,2.12239,0.0678702,0.80287,0.802684,7.54322,8.73541,4.02554,4.02828,4.02788,0.753789,0.0395238,2.86591,2.86944,2.86981,0.678094,14.3262,14.3312,7.06272,7.06846,0.132903,0.402083,0.402995,0.0444315,0.310249,0.310186,0.0115807,0.0773901,10.0565,10.0574,10.0542,10.0618,7.45946,11.8441,7.78661,0.186574,3.41212,3.40879,0.108275,0.108116,0.288291,15.7229,6.31089,6.31258,6.31894,6.31989,6.31451,0.498273,0.498618,1.47654,1.47647,1.4766,1.47732,0.0281882,1.03834,0.822532,0.822576,0.0362298,0.174166,0.174181,0.174118,0.158789,0.15897,0.158981,7.89248,1.54425,1.22507,0.0175869,0.0604844,0.0604752,0.060583,2.70951,0.624193,0.0195403,0.0195382,0.0195384,0.0195181,0.0194856,7.95039,7.95081,7.95202,7.94331,17.8888,17.8865,3.18587,32.9853,3.10251,3.10712,3.10887,3.108,3.10864,1.11817,1.11787,0.0453851,0.128235,6.00384,6.006,1.00408,1.00407,0.686284,0.686491,0.686711,0.216789,0.392556,0.0613776,0.061385,0.0613801,0.0613717,0.180999,0.181179,0.348015,20.5224,0.190927,0.190615,0.332968,0.0267566,4.57711,4.89652,2.47406,0.36946,0.00432783,0.23493,5.20943,0.432104,0.0768604,0.00152192,0.756555,39.3118,0.142394,0.142372,0.142346,0.142292,0.215004,0.214992,0.214958,12.721,13.0219,12.7301,4.02909,4.02996,4.03033,18.5691,0.887641,0.493626,0.813841,0.814599,0.814617,1.73437,0.0444187,0.0444091,0.0444063,0.0444015,0.0444519,0.380997,0.38102,0.20824,0.311687,0.311891,0.965927,34.0981,34.1046,4.15732,16.0395,0.100435,0.627933,0.570827,0.566178,0.0361855,2.05211,0.195873,0.196114,0.144477,3.41018,0.370116,0.370506,0.370364,20.5307,20.5259,0.911254,1.44464,31.5057,0.498192,0.448539,1.0137,4.34413,0.18726,0.217809,0.218117,0.148305,0.148272,0.148082,0.128065,1.18368,1.18359,1.18374,1.18387,1.18415,0.0680156,0.068007,0.506495,0.506845,0.507231,0.507688,4.09332,0.17257,0.0622846,0.0622799,0.0900375,0.0900802,0.0901015,0.0901253,0.19168,1.42841,1.42813,0.0274952,0.0275107,0.0589513", "util/gpu_percent": "100,100,94.2479,99.7585,99.8454,99.5845,100,88.3409,100,100,85.2056,85.6286,76,100,55.8958,100,98.55,96.5222,100,84.7028,84.5874,100,100,100,100,90.0627,89.8977,90.0792,88,100,100,87.1258,91.8791,100,91.4884,98.2769,55.0653,100,94.6778,100,92.8333,93.0385,100,67.9407,100,100,100,93.0357,90.6014,100,94.6,100,40.5789,87.7778,100,100,100,100,100,100,93.7941,65.7214,100,100,100,93.7119,100,100,100,100,91.6705,89.6338,100,61.0056,95.103,93.903,25.6429,76.4554,100,100,100,100,100,100,100,89.72,100,100,92.0237,91,83.5119,100,100,100,100,100,100,90.1043,100,100,100,100,100,80.7798,98.7805,89.2593,87.1494,50.0268,93.8791,87.3286,66,70.4868,67.6711,64.8289,100,100,100,78.0117,79.5621,79.2614,80,100,100,71.9489,68.736,69.0017,69.0822,65,100,100,100,100,100,100,100,100,100,100,100,100,100,99.4286,100,63.8214,72.3407,100,100,99.0556,99.5101,98.6218,98.5515,98.5648,24,98.0688,85.4215,75.528,72.9441,72.7692,90.8798,90.1957,100,100,81.6042,58,94.4576,44.8304,100,100,100,87.1795,64.5798,100,100,89.1509,73.7438,11.5314,100,100,88.4586,90.2611,88.3974,100,87.3534,87.3176,87.4459,100,100,100,100,100,100,100,96.9911,91.3864,94.2121,100,98.2192,100,74.8393,76.2727,75.6573,74.4895,78,96.9948,100,85,84.9778,55,98.133,100,100,100,100,90.371,91.0909,97.8487,97.3816,50.193,100,92.175,79,85.0073,100,97.2617,97.9301,100,100,100,100,100,100,97.6902,95.35,99,100,94.2644,76.7083,100,76.2113,74.0423,100,91.1406,100,100,100,100,100,69.6711,66,92.4933,93.4533,95.16,100,100,90.5675,71.9626,70.1551,74.4406,73.3566,72.1888,57,75.7292,100,100,62.3725,59.9874,61.8322", "util/gpu_mem": "17.0455,17.0455,15.5311,40.8685,40.8455,40.8382,40.8685,10.2225,39.8078,16.6466,11.395,11.395,11.395,39.1994,8.91981,10.6459,22.8915,22.8915,22.8915,8.95238,8.95238,25.2771,25.2771,25.2771,11.1507,7.99977,7.99977,7.99977,7.99977,40.5352,40.5352,7.6578,25.8139,25.8139,14.6925,9.83986,8.74069,22.8833,14.6843,14.782,22.0936,22.0936,29.9834,6.52606,29.7145,29.7145,29.7145,22.3373,22.3373,22.3373,24.1046,29.7117,6.95759,31.4401,31.4401,27.9884,14.9123,25.3504,25.3504,25.3504,19.9196,6.77032,38.1496,38.1496,38.1496,16.4674,34.046,34.046,45.1273,45.1273,8.58599,11.11,11.11,8.50457,15.2706,15.2706,17.1346,6.24924,33.4349,33.4349,33.4349,33.4349,39.0447,34.4857,14.8553,12.543,42.4974,42.4974,24.0553,24.0553,8.55342,34.8928,24.7479,24.7479,24.7479,24.7479,24.7479,23.6813,23.6813,18.4215,18.4215,18.4215,18.4215,6.54235,9.83986,29.9582,29.9582,21.8569,8.29288,8.29288,8.29288,9.24549,9.24549,9.24549,40.4863,9.76658,23.0543,11.5171,8.91981,8.91981,8.91981,26.4007,14.3749,21.8131,21.8407,21.8407,21.8407,21.8407,15.6532,15.6532,15.6532,15.6532,31.9535,31.9535,18.9345,25.2119,41.5529,41.5529,41.5529,41.5529,41.5529,28.1996,28.1996,21.3603,7.9672,38.9551,38.9551,38.7434,38.7434,35.2587,35.2587,35.2587,10.2958,10.8657,7.38097,7.38097,7.38097,7.38097,8.3743,8.3743,36.7242,31.5383,9.90499,9.90499,8.26031,6.76218,29.7308,23.6243,19.0485,13.4875,5.81771,7.74736,32.4665,9.01752,6.51792,4.47428,32.409,18.9996,8.3743,8.3743,8.3743,8.3743,10.3365,10.3365,10.3365,28.1507,28.2261,28.3298,24.471,24.471,24.471,23.8197,17.1677,27.4749,14.953,14.953,14.953,24.0069,8.16261,8.16261,8.16261,8.16261,8.16261,15.2706,15.2706,10.8088,12.0545,12.0545,14.2203,27.3696,27.3696,18.4541,13.976,11.7288,14.0656,32.7291,32.7916,9.17221,10.0841,13.577,13.577,7.60895,26.2948,13.8132,13.8132,13.8132,31.5383,31.5383,23.8685,13.1129,38.4503,8.0649,10.7925,16.1336,14.4231,8.08933,21.5557,21.5557,11.2077,11.2077,11.2077,27.2714,18.6658,18.7546,18.7961,18.7961,18.7961,9.09079,9.09079,10.7925,10.7925,10.7925,10.7925,35.9263,7.31499,8.57785,8.57785,25.0893,25.0893,25.0893,25.0893,25.7651,16.5163,16.5163,6.04569,6.04569,6.64819", "util/vram_used_gb": "3.62781,3.62781,3.26453,9.34253,9.33702,9.33526,9.34253,1.99109,9.0881,3.5321,2.27234,2.27234,2.27234,8.94214,1.67859,2.09265,5.03015,5.03015,5.03015,1.6864,1.6864,5.60242,5.60242,5.60242,2.21375,1.45789,1.45789,1.45789,1.45789,9.26257,9.26257,1.37585,5.7312,5.7312,3.06335,1.89929,1.63562,5.0282,3.0614,3.08484,4.83875,4.83875,6.73139,1.10437,6.66687,6.66687,6.66687,4.89722,4.89722,4.89722,5.32117,6.66619,1.20789,7.08081,7.08081,6.25281,3.11609,5.62,5.62,5.62,4.31726,1.16296,8.69031,8.69031,8.69031,3.48914,7.70593,7.70593,10.3641,10.3641,1.59851,2.20398,2.20398,1.57898,3.20203,3.20203,3.64917,1.03796,7.55933,7.55933,7.55933,7.55933,8.90503,7.8114,3.10242,2.54773,9.73328,9.73328,5.30933,5.30933,1.5907,7.90906,5.47546,5.47546,5.47546,5.47546,5.47546,5.2196,5.2196,3.95789,3.95789,3.95789,3.95789,1.10828,1.89929,6.72534,6.72534,4.78198,1.5282,1.5282,1.5282,1.75671,1.75671,1.75671,9.25085,1.88171,5.06921,2.30164,1.67859,1.67859,1.67859,5.87195,2.98718,4.77148,4.77808,4.77808,4.77808,4.77808,3.29382,3.29382,3.29382,3.29382,7.20398,7.20398,4.08093,5.58679,9.50671,9.50671,9.50671,9.50671,9.50671,6.30347,6.30347,4.66284,1.45007,8.88354,8.88354,8.83276,8.83276,7.99683,7.99683,7.99683,2.00867,2.14539,1.30945,1.30945,1.30945,1.30945,1.54773,1.54773,8.34839,7.10437,1.91492,1.91492,1.52039,1.16101,6.67078,5.20593,4.10828,2.77429,0.934448,1.39734,7.32703,1.70203,1.10242,0.612183,7.31323,4.09656,1.54773,1.54773,1.54773,1.54773,2.01843,2.01843,2.01843,6.29175,6.30984,6.33472,5.40906,5.40906,5.40906,5.25281,3.6571,6.12964,3.12585,3.12585,3.12585,5.29773,1.49695,1.49695,1.49695,1.49695,1.49695,3.20203,3.20203,2.13171,2.43054,2.43054,2.95007,6.10437,6.10437,3.9657,2.89148,2.35242,2.91296,7.39002,7.40503,1.73914,1.95789,2.79578,2.79578,1.36414,5.84656,2.85242,2.85242,2.85242,7.10437,7.10437,5.26453,2.68445,8.76245,1.47351,2.12781,3.40906,2.99873,1.47937,4.70972,4.70972,2.22742,2.22742,2.22742,6.08081,4.01648,4.03779,4.04773,4.04773,4.04773,1.7196,1.7196,2.12781,2.12781,2.12781,2.12781,8.15698,1.29362,1.59656,1.59656,5.55737,5.55737,5.55737,5.55737,5.71948,3.50085,3.50085,0.989136,0.989136,1.13367", "util/vram_total_gb": "23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272", "util/cpu_mem_gb": "1.39772,1.39772,1.26643,1.40482,1.40525,1.40525,1.40525,1.16881,1.729,1.29488,1.16668,1.16694,1.16814,1.69308,1.17394,1.40775,1.21209,1.21253,1.21253,1.13383,1.13443,1.63151,1.63151,1.63151,1.3871,1.12001,1.12063,1.12125,1.12138,1.54826,1.54826,1.14738,1.16368,1.16417,1.27398,1.40057,1.14001,1.57952,1.43076,1.37734,1.37823,1.37823,1.65952,1.13963,1.85598,1.85634,1.85634,1.10225,1.10279,1.10323,1.6374,1.40643,1.13395,1.21655,1.21655,1.79832,1.54697,1.50679,1.50679,1.50679,1.3536,1.1243,1.44225,1.44225,1.44227,1.45049,1.65851,1.65851,1.76117,1.76117,1.15547,1.27358,1.27358,1.14539,1.29902,1.29948,1.0219,1.15028,1.35318,1.35318,1.35318,1.35318,1.60262,2.07167,1.58549,1.17461,1.47808,1.47808,1.08468,1.08502,1.19996,2.42574,1.44618,1.44618,1.44618,1.44618,1.44618,1.33906,1.33965,1.34507,1.34507,1.34507,1.34507,1.22888,1.40069,1.23314,1.23314,1.06839,1.19203,1.19244,1.1935,1.21841,1.21888,1.21889,2.05762,1.18089,1.18615,1.09062,1.1443,1.14456,1.14479,1.39519,1.25192,1.03455,1.03567,1.03714,1.03839,1.03906,1.65476,1.65476,1.65476,1.65476,2.30924,2.30924,1.80119,2.06319,1.5055,1.50595,1.50595,1.50595,1.50595,1.13626,1.13675,1.07574,1.17924,2.12551,2.12551,1.3696,1.3696,1.1709,1.17122,1.17156,1.172,1.26826,1.12801,1.1286,1.12913,1.12958,1.14897,1.14938,1.17575,2.06516,1.17616,1.17616,1.2532,1.14825,1.77098,2.26625,1.49279,1.18198,1.1585,1.16847,2.50552,1.2753,1.16746,1.08947,1.36559,1.95704,1.14824,1.14824,1.14861,1.14872,1.24314,1.24317,1.2438,1.49798,1.49798,1.49798,1.72411,1.72411,1.72411,2.16022,1.50134,1.09004,1.377,1.377,1.377,1.53238,1.14578,1.14578,1.14609,1.14627,1.14627,1.29814,1.29961,1.27658,1.22247,1.22247,1.24463,2.62122,2.62122,1.47598,1.63551,1.15292,1.23225,1.13383,1.13383,1.22515,1.41674,1.19448,1.19448,1.15498,1.47756,1.25298,1.25298,1.25444,2.06471,2.06471,1.28562,1.49985,2.34953,1.23796,1.2503,1.40164,1.73287,1.14455,1.11022,1.11034,1.17643,1.17643,1.17643,1.21403,1.81012,1.8106,1.8106,1.8106,1.8106,1.15139,1.15139,1.24966,1.25011,1.25011,1.25011,1.6314,1.33666,1.16566,1.16606,1.0901,1.0901,1.0901,1.0901,1.08926,1.34677,1.34685,1.12959,1.13006,1.13629", "env/perf": "0.986635,1.00154,0.856211,0.912185,0.985957,1.02498,1.03648,0.550399,0.854349,0.996624,0.561917,0.800331,0.991742,1.00106,0.818158,0.55666,0.942686,0.998508,1.01516,0.850746,0.921272,0.893195,0.977007,1.02619,0.606184,0.790351,0.89702,0.957572,0.975428,1.01598,1.02495,0.588837,0.821892,0.994193,0.959393,0.478908,0.823541,1.02717,0.846952,1.00499,0.819753,0.926347,0.625124,0.411084,0.693955,1.03915,1.04716,0.513291,0.941588,0.97173,0.855419,0.937589,0.420833,0.940115,0.972038,0.931196,0.769955,0.659883,0.908437,0.973852,0.656101,0.851849,0.868205,0.961099,0.997159,0.871189,0.915123,0.995089,0.906485,1.00976,0.547972,0.947259,0.981461,0.627179,0.814429,0.919657,0.374026,0.403741,0.829566,0.9419,0.994585,1.00973,1.00512,0.976761,0.881761,0.613066,0.90624,0.967204,0.847728,0.952808,0.58192,0.970295,0.651462,0.93178,0.9843,1.03209,1.04377,0.847837,1.0045,0.866696,0.957589,1.00358,1.01544,0.440975,0.582514,0.581713,0.830934,0.414589,0.579122,0.832947,0.998636,0.692138,0.819028,0.895965,1.0206,0.598777,1.02068,0.324248,0.809388,0.901975,0.924972,1.00839,1.01203,0.462899,0.724882,0.843437,0.907704,0.920551,0.847582,0.948221,0.999806,1.01888,0.933093,0.990589,0.860328,0.959664,0.603499,0.879528,0.963397,1.0062,1.02906,0.937863,1.00452,0.432207,0.649239,0.835579,0.93181,0.902919,0.972949,0.880509,0.969294,1.00441,0.984674,0.823745,0.543169,0.769441,0.871266,0.932414,0.813218,0.912016,1.02181,0.91189,0.883914,0.969649,0.583957,0.386556,1.00693,0.875476,0.99894,0.958371,0.385064,0.915044,0.873053,0.619603,0.485087,0.399856,1.00215,1.00425,0.798779,0.897407,0.960023,0.978779,0.507543,0.775529,0.880831,0.928016,0.992832,1.00589,0.858663,0.96452,1.00312,0.952295,0.85864,0.59518,0.513765,0.808781,0.887949,0.933229,0.417715,0.623058,0.78231,0.865508,0.891514,0.608645,1.01094,0.970252,0.908461,0.988217,0.667352,0.996791,1.01738,0.952487,0.796375,0.588448,0.680361,0.824553,0.923523,0.36118,0.64165,0.908592,0.95004,0.571973,0.698397,0.633928,0.8761,1.01448,0.963668,1.00641,1.03066,0.892773,1.00198,0.639893,0.96318,0.357682,0.635371,0.655279,0.913533,0.942004,0.629453,0.87599,0.916112,0.419209,0.594407,0.850726,0.936497,0.994819,1.01062,0.874301,0.904345,0.787102,0.901759,0.971422,0.993858,1.00526,0.390064,0.745337,0.866028,0.676369,0.819207,0.904142,0.932872,0.880512,0.808587,0.919283,0.455581,0.683146,0.601447", "env/score": "19.8875,20.1672,17.4334,18.5087,19.8685,20.606,20.8271,11.6216,17.4167,20.0663,11.7919,16.3876,19.9782,20.1697,16.7312,11.6543,19.0537,20.1041,20.4169,17.3536,18.6635,18.1278,19.6899,20.6193,12.5949,16.2167,18.206,19.3394,19.6724,20.4391,20.6011,12.3002,16.8071,20.0348,19.3935,10.1859,16.8487,20.6388,17.2592,20.2476,16.7922,18.7632,13.003,8.85047,14.3023,20.8813,21.0329,10.8826,19.0557,19.6227,17.3888,18.9782,9.02655,19.0234,19.6282,18.8654,15.805,13.6817,18.4374,19.6513,13.5986,17.3845,17.6857,19.416,20.0951,17.7321,18.5584,20.0443,18.3881,20.3194,11.5242,19.1324,19.7875,13.1144,16.6675,18.6268,8.0249,8.66997,16.9337,19.0429,20.0377,20.3219,20.2305,19.7336,17.9316,12.7814,18.4041,19.5432,17.2824,19.2452,12.1777,19.586,13.4804,18.8509,19.8347,20.7326,20.9544,17.2847,20.219,17.6376,19.3289,20.197,20.4259,9.4461,12.1714,12.1541,16.9642,8.94346,12.1424,16.995,20.097,14.3908,16.7737,18.207,20.5243,12.4377,20.5149,7.00288,16.5713,18.3087,18.7399,20.2849,20.3427,9.8699,14.9798,17.2199,18.4206,18.6585,17.2845,19.1623,20.1326,20.4888,18.8785,19.9586,17.5246,19.387,12.5781,17.8569,19.4422,20.2458,20.6858,18.964,20.2113,9.265,13.5589,17.0547,18.8541,18.3298,19.6356,17.9186,19.5647,20.2199,19.8569,16.8379,11.4524,15.7951,17.6939,18.8493,16.6415,18.491,20.5454,18.4949,17.9533,19.5742,12.1907,8.3591,20.2924,17.8049,20.1034,19.3401,8.38712,18.5811,17.756,12.909,10.2981,8.57149,20.1726,20.2172,16.3534,18.2133,19.3859,19.7372,10.7424,15.9082,17.8877,18.7945,20.005,20.2517,17.5316,19.4998,20.2163,19.2502,17.4492,12.4265,10.8412,16.5456,18.0002,18.8806,8.97114,13.0333,16.0503,17.6143,18.1077,12.7055,20.3272,19.5971,18.4297,19.9144,13.7711,20.0767,20.4652,19.2437,16.2922,12.3157,14.0612,16.8517,18.7003,7.77807,13.3119,18.4188,19.2188,12.0208,14.3824,13.1261,17.8108,20.3968,19.4492,20.2648,20.7053,18.0865,20.1886,13.2924,19.4585,7.7395,13.1782,13.594,18.517,19.0415,13.2093,17.8391,18.5817,9.00116,12.4462,17.3652,18.9601,20.0611,20.3536,17.7881,18.3541,16.1558,18.2874,19.5957,20.0217,20.2484,8.38419,15.359,17.618,14.012,16.7309,18.316,18.8556,17.889,16.5514,18.621,9.72799,14.16,12.6412", "env/episode_return": "39.8271,40.3989,34.8503,37.0478,39.8351,41.3371,41.7959,22.9721,34.8102,40.2195,23.2472,32.6761,40.0585,40.4583,33.3258,23.0801,38.1666,40.3137,40.9531,34.625,37.32,36.217,39.4573,41.3701,25.0393,32.328,36.4199,38.7346,39.4098,40.9858,41.324,24.3478,33.5417,40.1622,38.8322,20.0277,33.5929,41.4121,34.4484,40.585,33.5187,37.5611,25.7671,17.2665,28.4246,41.9057,42.2164,21.3961,38.1394,39.3009,34.7871,37.978,17.5827,38.0572,39.2969,37.7732,31.5167,27.17,36.9106,39.3868,26.9802,34.7073,35.3496,38.9053,40.2937,35.4072,37.0981,40.1752,36.7962,40.7526,22.7988,38.2831,39.6316,25.9718,33.2857,37.2954,15.6015,16.903,33.807,38.1296,40.1623,40.7469,40.5455,39.4991,35.8417,25.2803,36.8197,39.153,34.4972,38.5432,24.0611,39.2627,26.7553,37.7472,39.7526,41.5919,42.0455,34.5369,40.5556,35.2079,38.7196,40.4961,40.9674,18.4131,24.0724,24.133,33.9074,17.4629,23.9652,33.9427,40.3166,28.6299,33.4894,36.4097,41.1716,24.6067,41.1566,13.5942,33.0314,36.5886,37.469,40.6512,40.7995,19.3546,29.8068,34.3882,36.8404,37.3247,34.487,38.3618,40.3376,41.0622,37.8233,40.0327,34.9895,38.8488,24.9583,35.7325,38.9658,40.6055,41.5019,37.9977,40.5445,18.054,26.92,33.9976,37.7203,36.6572,39.3312,35.8316,39.2218,40.5603,39.7883,33.6392,22.6392,31.5086,35.3857,37.7474,33.1856,36.9885,41.2103,36.9876,35.8895,39.2127,24.124,16.3406,40.6661,35.5935,40.2953,38.7475,16.3553,37.1554,35.5189,25.5858,20.2658,16.6823,40.4372,40.5118,32.6295,36.4423,38.8389,39.5566,21.1247,31.7021,35.7599,37.6342,40.1075,40.6077,34.9589,39.0362,40.514,38.5636,34.9198,24.6087,21.3258,33.0005,36.0101,37.7876,17.5483,25.8333,31.9964,35.1917,36.2016,25.2655,40.7688,39.273,36.852,39.8943,27.417,40.259,41.0512,38.5384,32.5326,24.3409,28.0088,33.6288,37.4306,15.1287,26.4824,36.7877,38.4436,23.7583,28.6178,26.0898,35.6322,40.9174,38.9853,40.6525,41.5424,36.1966,40.471,26.3994,38.9783,15.0675,26.1814,27.0055,37.0494,38.1317,26.2033,35.6285,37.1521,17.5618,24.7207,34.7108,37.9734,40.2137,40.8132,35.5097,36.6802,32.1835,36.5813,39.2585,40.1334,40.5849,16.3127,30.5102,35.1352,27.7414,33.3243,36.5775,37.6853,35.7559,32.9897,37.262,19.0926,28.1383,25.0878", "env/episode_length": "8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160,8160", "env/up_action_frac": "0.770858,0.763327,0.674619,0.659657,0.658726,0.659934,0.659743,0.806584,0.687651,0.730492,0.898845,0.798302,0.700845,0.649796,0.853071,0.628545,0.645813,0.640111,0.642901,0.805396,0.763543,0.769645,0.715943,0.69536,0.639557,0.74773,0.706355,0.689532,0.701221,0.691882,0.687481,0.658502,0.799714,0.716491,0.766982,0.85303,0.787572,0.689592,0.802843,0.758577,0.717401,0.69967,0.753565,0.685662,0.74545,0.661213,0.654484,0.914221,0.737677,0.728907,0.731093,0.702255,0.961459,0.76762,0.757298,0.703491,0.722817,0.736799,0.67482,0.666597,0.806616,0.749054,0.690866,0.670902,0.667835,0.768447,0.720416,0.696262,0.661847,0.639001,0.802604,0.709727,0.70606,0.761476,0.67472,0.673041,0.916842,0.885242,0.713685,0.677445,0.668468,0.663403,0.657358,0.730111,0.664186,0.830991,0.683252,0.667046,0.764181,0.707091,0.849628,0.652609,0.734767,0.701946,0.675683,0.67089,0.669679,0.801746,0.735687,0.701769,0.6518,0.643106,0.644311,0.990954,0.749573,0.664633,0.692583,0.838071,0.885967,0.776713,0.682728,0.655317,0.659347,0.665178,0.655979,0.746067,0.664176,0.771182,0.803395,0.763498,0.756821,0.720342,0.665954,0.792996,0.690389,0.669892,0.66986,0.677557,0.761752,0.726324,0.721456,0.720114,0.659817,0.638079,0.800367,0.66935,0.637886,0.650536,0.646084,0.648442,0.652323,0.671277,0.672099,0.982422,0.729383,0.753122,0.718126,0.661228,0.676873,0.668442,0.663136,0.661645,0.76892,0.651854,0.649499,0.628738,0.631144,0.639837,0.764494,0.723307,0.713115,0.755338,0.787961,0.745801,0.795578,0.675977,0.745349,0.762204,0.705209,0.741656,0.556251,0.793617,0.653171,0.786946,0.731819,0.939013,0.670737,0.685612,0.691062,0.66811,0.66946,0.669379,0.871341,0.749522,0.709557,0.676132,0.663875,0.661178,0.778157,0.744928,0.734671,0.65828,0.622457,0.758363,0.854832,0.765136,0.671319,0.776492,0.762379,0.728391,0.678731,0.664518,0.665121,0.624334,0.65897,0.656163,0.786639,0.753835,0.632875,0.694996,0.691017,0.718418,0.690548,0.736233,0.631378,0.65863,0.651424,0.842049,0.612282,0.813712,0.790258,0.800261,0.685011,0.655018,0.672703,0.653301,0.678432,0.675041,0.667815,0.679315,0.71476,0.661536,0.704482,0.743926,0.654798,0.718225,0.729654,0.70995,0.69184,0.721302,0.714669,0.866617,0.68065,0.693584,0.660626,0.658322,0.659783,0.80014,0.787552,0.840813,0.751916,0.718691,0.711168,0.658453,0.758829,0.877227,0.809801,0.903595,0.803402,0.762207,0.751425,0.703553,0.755376,0.736307,0.699387,0.62486,0.669762", "env/hits": "34.9305,33.3902,43.5495,37.4182,30.064,27.0388,26.0235,74.7035,44.8567,32.2443,80.9695,51.5919,29.9001,27.9887,55.3383,69.4339,34.7848,29.8126,28.3126,49.4453,41.2033,44.1853,32.2953,26.344,61.0764,52.8327,40.2953,35.0646,34.0806,28.6271,27.3743,71.4384,49.8224,32.0988,37.1414,84.0077,52.0239,26.1349,48.2619,32.8875,49.5755,38.2508,69.6069,95.0652,62.6252,26.3305,25.4221,85.2841,37.6348,34.7093,40.6771,39.1088,98.5631,39.3184,36.0406,37.1316,52.3179,65.1462,38.6771,33.5887,67.1336,48.1314,44.1117,33.6934,30.36,47.1152,43.1257,32.0923,38.8421,27.7886,72.2068,39.1333,35.5905,71.3834,46.9845,36.6853,96.3328,95.3187,48.7561,35.8888,30.629,28.7191,31.0576,37.2722,43.3509,74.2018,41.387,35.4632,48.2788,35.3182,74.3214,31.0763,66.2709,37.8669,33.4284,28.9073,27.9434,45.7889,29.7658,48.2682,34.5309,29.614,28.6119,99.5443,73.1461,63.1497,43.9439,93.5639,78.3009,45.6299,27.5716,60.3152,49.189,42.8345,28.5935,71.6111,27.0253,88.0918,53.1712,43.8522,41.7981,32.9804,29.5703,89.0024,59.1223,46.5275,41.1644,40.0828,49.7974,36.5576,32.567,31.2121,33.8079,27.7673,47.8143,32.4432,65.3055,38.2635,31.1166,28.1074,25.7656,33.9072,28.2114,99.1987,65.0107,52.9447,39.2635,41.5748,34.9906,41.7273,31.6386,28.8067,33.7051,43.6709,73.4652,50.2542,40.6036,34.8638,52.1795,41.035,30.2746,42.0486,42.2052,33.2441,72.3055,88.9466,32.869,43.0614,32.4016,33.0125,89.7066,43.3306,40.6183,68.5504,80.8097,97.3751,30.6261,32.4335,50.4573,39.5694,33.6891,31.9422,84.7162,53.5136,42.3507,36.0007,30.1829,29.0272,52.4381,37.6144,32.8946,34.7375,37.1387,70.7599,83.4614,51.0851,39.7796,38.5548,89.9896,69.0702,52.7363,45.212,42.8353,59.8395,29.6606,32.8893,41.7165,33.6406,56.5202,29.3946,27.4171,34.8735,48.4359,76.2321,54.1088,49.6395,38.1132,94.1029,58.4301,45.1336,39.535,74.4946,58.3285,61.1176,41.2054,29.0344,32.4503,28.3236,28.8576,38.3257,30.435,63.6097,35.3804,90.8186,62.3344,61.381,38.3342,34.8933,67.3115,46.4914,42.4945,95.569,64.0053,44.769,37.118,32.5331,31.1451,47.7234,43.369,54.8104,39.45,33.2336,31.085,31.2491,96.7486,63.966,50.8421,72.4923,54.7679,44.9336,41.8079,43.562,53.6797,39.3586,86.2564,61.9402,64.9287", "env/n": "8192,16384,8192,2048,2048,2048,10240,8192,4096,16384,8192,8192,16384,8192,16384,8192,4096,4096,12288,8192,8192,4096,4096,12288,4096,8192,8192,8192,16384,8192,16384,4096,8192,16384,8192,4096,16384,12288,4096,12288,4096,4096,2048,8192,2048,2048,10240,8192,8192,16384,2048,8192,8192,16384,16384,2048,8192,2048,2048,2048,4096,8192,2048,2048,2048,4096,4096,4096,2048,2048,8192,8192,16384,16384,4096,4096,8192,8192,8192,8192,8192,16384,16384,16384,8192,8192,2048,2048,8192,16384,16384,2048,4096,4096,4096,4096,12288,4096,12288,4096,4096,4096,12288,2048,4096,4096,4096,8192,8192,8192,16384,8192,8192,8192,12288,4096,16384,1024,16384,16384,16384,16384,16384,4096,4096,4096,4096,12288,8192,8192,8192,16384,2048,2048,2048,8192,2048,2048,2048,2048,10240,8192,16384,8192,16384,4096,4096,2048,2048,4096,4096,4096,16384,4096,8192,8192,8192,8192,8192,8192,12288,2048,16384,16384,4096,8192,16384,2048,16384,16384,2048,16384,2048,8192,8192,2048,12288,16384,8192,8192,8192,16384,4096,4096,4096,4096,4096,12288,4096,4096,4096,4096,4096,8192,4096,4096,4096,4096,8192,8192,8192,8192,16384,4096,12288,16384,8192,16384,4096,8192,16384,8192,8192,4096,8192,4096,4096,8192,4096,16384,16384,8192,2048,4096,4096,12288,2048,2048,12288,4096,16384,4096,8192,4096,2048,8192,16384,16384,16384,16384,16384,4096,2048,2048,2048,2048,10240,16384,16384,8192,8192,8192,16384,16384,512,8192,8192,8192,8192,8192,16384,16384,8192,8192,8192,8192,16384", "wandb": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "rank": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "world_size": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "gpu_id": "4,4,4,0,0,0,0,3,0,3,2,2,2,0,4,2,5,5,5,4,4,1,1,1,3,2,2,2,2,2,2,1,0,0,2,2,3,2,3,5,5,5,0,1,4,4,4,0,0,0,2,0,4,0,0,2,5,2,2,2,1,1,5,5,5,5,1,1,3,3,1,5,5,1,4,4,0,1,0,0,0,0,0,4,3,1,1,1,0,0,2,1,5,5,5,5,5,3,3,1,1,1,1,5,1,0,0,0,4,4,4,4,4,4,2,2,5,1,3,3,3,4,3,0,0,0,0,0,5,5,5,5,5,5,2,2,2,2,2,2,2,0,0,0,5,0,0,0,0,0,0,0,2,1,1,1,1,1,5,5,0,2,5,5,1,5,3,4,3,4,1,2,1,1,3,4,0,1,5,5,5,5,4,4,4,0,0,0,2,2,2,4,2,0,1,1,1,5,5,5,5,5,5,5,5,2,2,2,4,4,4,3,5,1,4,0,0,4,3,4,4,4,3,3,3,3,2,2,1,1,0,3,1,5,5,3,0,0,3,3,3,0,4,4,4,4,4,2,2,1,1,1,1,0,5,1,1,0,0,0,0,0,3,3,3,3,2", "profile": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "checkpoint_interval": "200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200", "eval_episodes": "10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000", "cudagraphs": "10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10", "seed": "73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73", "vec/total_agents": "8192,8192,8192,2048,2048,2048,2048,8192,4096,8192,8192,8192,8192,8192,16384,8192,4096,4096,4096,8192,8192,4096,4096,4096,4096,8192,8192,8192,8192,8192,8192,4096,8192,8192,8192,4096,16384,4096,4096,4096,4096,4096,2048,8192,2048,2048,2048,8192,8192,8192,2048,8192,8192,16384,16384,2048,8192,2048,2048,2048,4096,8192,2048,2048,2048,4096,4096,4096,2048,2048,8192,8192,8192,16384,4096,4096,8192,8192,8192,8192,8192,8192,16384,8192,8192,8192,2048,2048,8192,8192,16384,2048,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,2048,4096,4096,4096,8192,8192,8192,8192,8192,8192,8192,4096,4096,8192,1024,16384,16384,16384,16384,8192,4096,4096,4096,4096,4096,8192,8192,8192,8192,2048,2048,2048,8192,2048,2048,2048,2048,2048,8192,8192,8192,16384,4096,4096,2048,2048,4096,4096,4096,16384,4096,8192,8192,8192,8192,8192,8192,4096,2048,16384,16384,4096,8192,8192,2048,16384,16384,2048,16384,2048,8192,8192,2048,4096,8192,8192,8192,8192,8192,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,8192,4096,4096,4096,4096,8192,8192,8192,8192,8192,4096,4096,8192,8192,8192,4096,8192,8192,8192,8192,4096,8192,4096,4096,8192,4096,16384,16384,8192,2048,4096,4096,4096,2048,2048,4096,4096,8192,4096,8192,4096,2048,8192,16384,16384,16384,16384,16384,4096,2048,2048,2048,2048,2048,16384,16384,8192,8192,8192,8192,8192,512,8192,8192,8192,8192,8192,8192,16384,8192,8192,8192,8192,16384", "vec/num_buffers": "6.73364,6.73364,7.88354,8,8,8,8,6.61385,5.38227,8,8,8,8,4.87372,7.34146,7.57271,5.82487,5.82487,5.82487,8,8,6.87916,6.87916,6.87916,7.29808,6.68485,6.68485,6.68485,6.68485,5.10541,5.10541,7.91033,6.31711,6.31711,8,6.98723,6.33161,6.53734,8,6.39727,6.43157,6.43157,8,6.08671,8,8,8,8,8,8,6.20107,8,3.45245,8,8,6.01494,5.10847,6.12272,6.12272,6.12272,6.08258,6.80349,8,8,8,7.22556,4.19268,4.19268,7.20918,7.20918,7.52188,8,8,8,8,8,3.62281,5.6721,4.90003,4.90003,4.90003,4.90003,6.69906,5.15104,6.61522,8,8,8,8,8,8,7.61332,8,8,8,8,8,5.72859,5.72859,7.66065,7.66065,7.66065,7.66065,6.71344,6.68074,5.19529,5.19529,6.18391,8,8,8,7.58219,7.58219,7.58219,6.29429,2.22255,4.98134,2.77301,7.5109,7.5109,7.5109,6.36111,7.3384,6.73289,6.73289,6.73289,6.73289,6.73289,7.36367,7.36367,7.36367,7.36367,7.62418,7.62418,8,6.61263,6.39502,6.39502,6.39502,6.39502,6.39502,6.21955,6.21955,7.2381,7.73743,7.31388,7.31388,8,8,8,8,8,5.57095,7.46572,6.25037,6.25037,6.25037,6.25037,6.94776,6.94776,7.63207,5.92431,6.8738,6.8738,7.55262,6.992,7.67143,6.86721,8,7.91813,5.04003,6.67587,8,8,8,1,7.73084,6.95007,6.21248,6.21248,6.21248,6.21248,6.80684,6.80684,6.80684,3.43656,3.43656,3.43656,8,8,8,6.92679,8,4.5769,6.12285,6.12285,6.12285,5.48683,6.2566,6.2566,6.2566,6.2566,6.2566,8,8,8,7.77588,7.77588,7.31735,8,8,4.71028,6.97516,6.50471,6.9732,7.12027,7.12027,7.08359,7.27251,8,8,5.70276,8,7.33854,7.33854,7.33854,5.79891,5.79891,8,8,7.36023,7.06394,7.65565,6.028,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,7.93278,7.93278,7.93278,7.93278,7.08789,6.19347,8,8,7.93884,7.93884,7.93884,7.93884,8,5.507,5.507,7.95511,7.95511,7.74947", "vec/num_threads": "2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2", "vec/num_agents": "4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096", "env/frameskip": "4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4", "env/width": "1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216,1216", "env/height": "720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720,720", "env/player_width": "64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64", "env/player_height": "64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64", "env/car_width": "64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64", "env/car_height": "40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40", "env/lane_size": "64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64", "env/difficulty": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "env/level": "-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1", "env/enable_human_player": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "env/env_randomization": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "env/use_dense_rewards": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "policy/hidden_size": "256,256,256,512,512,512,512,256,512,512,256,256,256,512,128,128,512,512,512,256,256,512,512,512,256,256,256,256,256,512,512,256,256,256,256,128,128,512,256,128,256,256,256,128,1024,1024,1024,256,256,256,256,256,128,256,256,1024,256,1024,1024,1024,256,128,1024,1024,1024,128,1024,1024,1024,1024,256,256,256,128,256,256,256,64,512,512,512,512,256,256,256,256,1024,1024,256,256,128,1024,1024,1024,1024,1024,1024,256,256,512,512,512,512,32,128,256,256,64,128,128,128,128,128,128,512,256,512,256,128,128,128,256,256,128,128,128,128,128,256,256,256,256,1024,1024,512,512,1024,1024,1024,1024,1024,512,512,128,128,256,256,512,512,512,512,512,128,256,128,128,128,128,256,256,256,1024,128,128,128,64,256,256,256,256,32,128,512,128,64,64,256,256,256,256,256,256,128,128,128,256,256,256,512,512,512,512,256,256,256,256,256,256,128,128,128,128,128,256,256,128,256,256,512,256,256,256,256,256,256,512,512,64,256,256,256,128,1024,256,256,256,1024,1024,512,256,256,256,256,256,512,256,128,128,256,256,256,128,256,256,256,256,256,128,128,256,256,256,256,256,64,128,128,128,128,128,128,256,256,256,64,64,128", "policy/num_layers": "8,8,8,8,8,8,8,8,5.70902,8,5.88718,5.88718,5.88718,7.42727,5.65647,7.51631,8,8,8,6.44672,6.44672,7.11303,7.11303,7.11303,6.63346,5.73586,5.73586,5.73586,5.73586,7.25895,7.25895,4.91179,8,8,7.09765,8,6.78393,6.19458,6.43046,7.30078,7.34779,7.34779,6.01251,4.97481,8,8,8,7.59577,7.59577,7.59577,7.11201,8,3.75701,8,8,8,7.29464,8,8,8,6.81575,6.44789,7.84158,7.84158,7.84158,8,5.8425,5.8425,8,8,5.44049,7.41918,7.41918,5.6309,8,8,1,7.1342,7.41979,7.41979,7.41979,7.41979,8,8,6.75453,6.43203,8,8,5.61441,5.61441,7.11112,8,7.92109,7.92109,7.92109,7.92109,7.92109,8,8,5.88816,5.88816,5.88816,5.88816,1,8,7.54915,7.54915,5.29196,8,8,8,5.87654,5.87654,5.87654,6.69166,8,8,7.16516,6.23819,6.23819,6.23819,8,7.01943,5.57626,5.57626,5.57626,5.57626,5.57626,6.3573,6.3573,6.3573,6.3573,7.22212,7.22212,7.11775,6.85379,8,8,8,8,8,6.46814,6.46814,5.97824,6.38084,6.47749,6.47749,7.88359,7.88359,6.41718,6.41718,6.41718,8,8,8,8,8,8,5.73144,5.73144,7.87794,8,7.44076,7.44076,7.95504,5.93438,8,8,8,7.53739,2.41173,6.23985,7.44343,7.77732,5.97023,1,8,5.21748,5.01478,5.01478,5.01478,5.01478,8,8,8,6.53432,6.53432,6.53432,6.46769,6.46769,6.46769,7.99448,8,6.3665,7.93123,7.93123,7.93123,7.14221,5.81995,5.81995,5.81995,5.81995,5.81995,8,8,7.76875,5.87434,5.87434,7.75611,8,8,8,7.15044,6.901,7.43573,5.67761,5.67761,5.22467,7.14523,7.23337,7.23337,8,8,7.93738,7.93738,7.93738,8,8,8,8,8,6.52633,7.02521,8,6.60934,8,6.13086,6.13086,5.53443,5.53443,5.53443,8,7.15474,7.15474,7.15474,7.15474,7.15474,6.92536,6.92536,7.64436,7.64436,7.64436,7.64436,7.05694,1.41517,5.90654,5.90654,7.52061,7.52061,7.52061,7.52061,4.09157,8,8,6.30374,6.30374,4.31093", "policy/expansion_factor": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "policy/num_units": "64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64", "legacy/torch_deterministic": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "legacy/cpu_offload": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "legacy/compile": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "legacy/compile_fullgraph": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "train/gpus": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "train/seed": "42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42", "train/total_timesteps": "340.346,340.346,492.582,434.768,434.768,434.768,434.768,340.968,351.058,338.326,441.818,441.818,441.818,355.961,402.663,337.534,378.274,378.274,378.274,300,300,397.83,397.83,397.83,402.255,318.022,318.022,318.022,318.022,499.294,499.294,507.536,381.46,381.46,361.919,300,417.518,443.535,380.415,516.395,329.159,329.159,365.853,348.261,443.758,443.758,443.758,300,300,300,463.052,394.705,300,305.713,305.713,480.133,300,394.028,394.028,394.028,599.026,357.046,335.332,335.332,335.332,494.783,449.254,449.254,335.388,335.388,434.61,300,300,378.702,345.831,345.831,300,300,329.707,329.707,329.707,329.707,400.891,300,412.179,482.913,390.658,390.658,355.323,355.323,481.489,382.136,423.141,423.141,423.141,423.141,423.141,483.483,483.483,392.453,392.453,392.453,392.453,365.787,372.086,366.772,366.772,300,446.544,446.544,446.544,318.836,318.836,318.836,406.483,331.647,425.633,322.234,321.305,321.305,321.305,437.081,517.237,300,300,300,300,300,336.632,336.632,336.632,336.632,443.21,443.21,351.431,374.091,327.726,327.726,327.726,327.726,327.726,382.632,382.632,300,384.26,340.213,340.213,415.995,415.995,406.034,406.034,406.034,337.457,397.436,300,300,300,300,385.005,385.005,599.326,392.886,404.398,404.398,403.051,300,384.011,387.096,396.787,329.196,357.171,300,363.981,508.4,399.837,300,355.345,324.363,329.148,329.148,329.148,329.148,310.422,310.422,310.422,322.263,322.263,322.263,381.309,381.309,381.309,361.293,470.491,432.996,305.507,305.507,305.507,370.889,300,300,300,300,300,436.613,436.613,394.892,377.521,377.521,424.16,333.992,333.992,303.542,302.296,487.428,567.757,319.187,319.187,300,407.944,339.379,339.379,352.332,553.15,480.571,480.571,480.571,332.236,332.236,467.677,449.87,322.355,415.921,337.784,388.114,384.639,521.58,305.537,305.537,300,300,300,300,369.123,369.123,369.123,369.123,369.123,313.035,313.035,315.037,315.037,315.037,315.037,399.432,305.742,392.127,392.127,300,300,300,300,402.204,344.817,344.817,333.144,333.144,300", "train/learning_rate": "0.00152127,0.00152127,0.00385988,0.000625968,0.000625968,0.000625968,0.000625968,0.00412852,0.00284,0.00516008,0.00615423,0.00615423,0.00615423,0.00365774,0.00369198,0.00278742,0.00306105,0.00306105,0.00306105,0.00233531,0.00233531,0.000961463,0.000961463,0.000961463,0.00260024,0.0022722,0.0022722,0.0022722,0.0022722,0.00216717,0.00216717,0.002883,0.00169834,0.00169834,0.00374629,0.00380403,0.003776,0.00120073,0.00154033,0.00409475,0.00286769,0.00286769,0.0022472,0.00604883,0.000778628,0.000778628,0.000778628,0.002916,0.002916,0.002916,0.00497801,0.00110046,0.0070343,0.00260292,0.00260292,0.000672642,0.00426459,0.000825942,0.000825942,0.000825942,0.00576814,0.00366593,0.00101084,0.00101084,0.00101084,0.002724,0.00188728,0.00188728,0.00111157,0.00111157,0.0115536,0.00336622,0.00336622,0.00387754,0.00167976,0.00167976,0.00270204,0.00291231,0.00120129,0.00120129,0.00120129,0.00120129,0.0043963,0.00297012,0.000948477,0.00474367,0.000766538,0.000766538,0.00351598,0.00351598,0.00504497,0.00133928,0.000767042,0.000767042,0.000767042,0.000767042,0.000767042,0.00447644,0.00447644,0.00107757,0.00107757,0.00107757,0.00107757,0.1,0.00193408,0.00391506,0.00391506,0.0049251,0.00287411,0.00287411,0.00287411,0.00511234,0.00511234,0.00511234,0.00204001,0.00135987,0.00213283,0.0384823,0.00351045,0.00351045,0.00351045,0.00162925,0.00307857,0.00276786,0.00276786,0.00276786,0.00276786,0.00276786,0.00116912,0.00116912,0.00116912,0.00116912,0.00091958,0.00091958,0.000737402,0.000991515,0.00128573,0.00128573,0.00128573,0.00128573,0.00128573,0.00180511,0.00180511,0.003678,0.00758466,0.00201768,0.00201768,0.000906621,0.000906621,0.000800381,0.000800381,0.000800381,0.00430569,0.00127976,0.00274302,0.00274302,0.00274302,0.00274302,0.00264833,0.00264833,0.00254599,0.000624811,0.00357256,0.00357256,0.00383847,0.0185829,0.00262071,0.00230848,0.00217849,0.00302668,0.1,0.00277473,0.00260887,0.00527807,0.00513517,0.00792386,0.00230003,0.00126346,0.00329293,0.00329293,0.00329293,0.00329293,0.00253995,0.00253995,0.00253995,0.00332277,0.00332277,0.00332277,0.000887085,0.000887085,0.000887085,0.000624059,0.00132233,0.00471908,0.00351369,0.00351369,0.00351369,0.00286347,0.0118668,0.0118668,0.0118668,0.0118668,0.0118668,0.00349657,0.00349657,0.00931268,0.00247602,0.00247602,0.00178132,0.00383093,0.00383093,0.00321644,0.00258431,0.00238279,0.00324341,0.00198894,0.00198894,0.0100167,0.00118613,0.00500492,0.00500492,0.00501236,0.00108349,0.00288486,0.00288486,0.00288486,0.00119642,0.00119642,0.000825551,0.0009797,0.00182287,0.00270395,0.00365545,0.00378708,0.00118956,0.00288692,0.00333925,0.00333925,0.00610559,0.00610559,0.00610559,0.00237453,0.00386872,0.00386872,0.00386872,0.00386872,0.00386872,0.00460085,0.00460085,0.00240995,0.00240995,0.00240995,0.00240995,0.00198486,0.000125802,0.00434911,0.00434911,0.00587793,0.00587793,0.00587793,0.00587793,0.00490128,0.0022365,0.0022365,0.00277691,0.00277691,0.008857", "train/anneal_lr": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "train/min_lr_ratio": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "train/gamma": "0.991755,0.991755,0.986837,0.986086,0.986086,0.986086,0.986086,0.976207,0.990653,0.988377,0.991427,0.991427,0.991427,0.995664,0.976657,0.993927,0.988356,0.988356,0.988356,0.983658,0.983658,0.99619,0.99619,0.99619,0.99104,0.981032,0.981032,0.981032,0.981032,0.992008,0.992008,0.987813,0.980439,0.980439,0.97569,0.982581,0.980095,0.995941,0.989287,0.971414,0.981137,0.981137,0.994485,0.98852,0.987337,0.987337,0.987337,0.983883,0.983883,0.983883,0.995362,0.984539,0.978131,0.986784,0.986784,0.987125,0.997538,0.976284,0.976284,0.976284,0.989722,0.975159,0.979504,0.979504,0.979504,0.98369,0.990411,0.990411,0.989956,0.989956,0.996829,0.988767,0.988767,0.983177,0.985729,0.985729,0.997848,0.985858,0.99356,0.99356,0.99356,0.99356,0.992374,0.990575,0.989047,0.984337,0.973499,0.973499,0.990613,0.990613,0.99182,0.990521,0.979909,0.979909,0.979909,0.979909,0.979909,0.981469,0.981469,0.989116,0.989116,0.989116,0.989116,0.999115,0.991631,0.989742,0.989742,0.9914,0.991281,0.991281,0.991281,0.972269,0.972269,0.972269,0.984291,0.995783,0.990923,0.96488,0.977921,0.977921,0.977921,0.986642,0.979441,0.979789,0.979789,0.979789,0.979789,0.979789,0.992227,0.992227,0.992227,0.992227,0.994176,0.994176,0.987246,0.996752,0.987563,0.987563,0.987563,0.987563,0.987563,0.987143,0.987143,0.99414,0.98382,0.995644,0.995644,0.98281,0.98281,0.983191,0.983191,0.983191,0.983247,0.984068,0.987257,0.987257,0.987257,0.987257,0.978924,0.978924,0.970838,0.987898,0.988734,0.988734,0.995112,0.984011,0.982562,0.996794,0.986839,0.990852,0.997732,0.960424,0.993827,0.992046,0.993135,0.998441,0.984903,0.990987,0.985862,0.985862,0.985862,0.985862,0.989423,0.989423,0.989423,0.995695,0.995695,0.995695,0.984449,0.984449,0.984449,0.992345,0.993618,0.987015,0.989514,0.989514,0.989514,0.993315,0.983706,0.983706,0.983706,0.983706,0.983706,0.976381,0.976381,0.974329,0.985908,0.985908,0.993986,0.996986,0.996986,0.994374,0.995234,0.976757,0.991735,0.982876,0.982876,0.98851,0.991759,0.987395,0.987395,0.982643,0.994406,0.982787,0.982787,0.982787,0.987729,0.987729,0.975236,0.993459,0.994142,0.994792,0.979054,0.975197,0.988521,0.993026,0.989843,0.989843,0.979021,0.979021,0.979021,0.979892,0.979717,0.979717,0.979717,0.979717,0.979717,0.991542,0.991542,0.990866,0.990866,0.990866,0.990866,0.990898,0.99089,0.980427,0.980427,0.989991,0.989991,0.989991,0.989991,0.982734,0.989533,0.989533,0.99334,0.99334,0.985344", "train/gae_lambda": "0.75802,0.75802,0.578952,0.584047,0.584047,0.584047,0.584047,0.883771,0.83791,0.677822,0.875766,0.875766,0.875766,0.698663,0.750679,0.887959,0.774898,0.774898,0.774898,0.858657,0.858657,0.663233,0.663233,0.663233,0.2,0.892606,0.892606,0.892606,0.892606,0.885437,0.885437,0.659194,0.806035,0.806035,0.846299,0.822293,0.782307,0.775985,0.529097,0.782634,0.623709,0.623709,0.853232,0.878622,0.707717,0.707717,0.707717,0.89032,0.89032,0.89032,0.738713,0.717114,0.771405,0.821409,0.821409,0.74015,0.861793,0.889052,0.889052,0.889052,0.712408,0.847955,0.258451,0.258451,0.258451,0.778866,0.850191,0.850191,0.897095,0.897095,0.680342,0.921453,0.921453,0.664443,0.498405,0.498405,0.947953,0.929277,0.564466,0.564466,0.564466,0.564466,0.791824,0.68983,0.651737,0.687845,0.712001,0.712001,0.920123,0.920123,0.826035,0.271075,0.72458,0.72458,0.72458,0.72458,0.72458,0.827594,0.827594,0.804115,0.804115,0.804115,0.804115,0.956316,0.744772,0.741168,0.741168,0.873459,0.869372,0.869372,0.869372,0.736169,0.736169,0.736169,0.669037,0.67313,0.813376,0.662245,0.889048,0.889048,0.889048,0.76898,0.736935,0.893713,0.893713,0.893713,0.893713,0.893713,0.748271,0.748271,0.748271,0.748271,0.406805,0.406805,0.433489,0.874584,0.736236,0.736236,0.736236,0.736236,0.736236,0.678743,0.678743,0.907183,0.70334,0.800272,0.800272,0.845712,0.845712,0.821405,0.821405,0.821405,0.868866,0.809385,0.855803,0.855803,0.855803,0.855803,0.880282,0.880282,0.738249,0.933721,0.759081,0.759081,0.2,0.704207,0.714893,0.72235,0.778175,0.789286,0.918685,0.911884,0.708735,0.782464,0.583652,0.6892,0.827639,0.769482,0.75141,0.75141,0.75141,0.75141,0.737726,0.737726,0.737726,0.733448,0.733448,0.733448,0.749392,0.749392,0.749392,0.86309,0.837799,0.66182,0.731344,0.731344,0.731344,0.85029,0.851441,0.851441,0.851441,0.851441,0.851441,0.736425,0.736425,0.840633,0.774767,0.774767,0.48144,0.630636,0.630636,0.91792,0.440554,0.500636,0.776141,0.728792,0.728792,0.795974,0.636906,0.874674,0.874674,0.832738,0.418049,0.595687,0.595687,0.595687,0.747558,0.747558,0.819061,0.803563,0.774179,0.620824,0.625263,0.79457,0.764023,0.762687,0.873677,0.873677,0.732016,0.732016,0.732016,0.756529,0.851329,0.851329,0.851329,0.851329,0.851329,0.844827,0.844827,0.82079,0.82079,0.82079,0.82079,0.791539,0.99023,0.854235,0.854235,0.819901,0.819901,0.819901,0.819901,0.869537,0.753444,0.753444,0.904039,0.904039,0.912175", "train/replay_ratio": "2.73089,2.73089,2.32807,3.81937,3.81937,3.81937,3.81937,1.91643,4,1.51959,1.91577,1.91577,1.91577,4,1.32255,2.92272,2.41822,2.41822,2.41822,1.46406,1.46406,4,4,4,3.78347,2.3839,2.3839,2.3839,2.3839,2.4917,2.4917,2.63837,2.2915,2.2915,1.6626,2.72879,1.49808,4,4,3.18529,3.27079,3.27079,3.53878,0.588602,3.89884,3.89884,3.89884,1.7236,1.7236,1.7236,3.36851,2.51123,1.21929,1.83426,1.83426,3.47775,3.79474,4,4,4,3.94317,1.7093,3.82545,3.82545,3.82545,3.71402,3.06902,3.06902,4,4,1.67526,1.59137,1.59137,1.39216,2.91431,2.91431,0.694728,1.46363,3.28452,3.28452,3.28452,3.28452,2.54271,3.7863,4,2.33826,4,4,1.37497,1.37497,2.16331,3.08125,3.79984,3.79984,3.79984,3.79984,3.79984,2.4897,2.4897,4,4,4,4,1.65537,3.00605,3.69548,3.69548,0.901438,2.47701,2.47701,2.47701,1.94566,1.94566,1.94566,4,4,2.26992,3.98096,1.647,1.647,1.647,3.243,3.29822,2.00825,2.00825,2.00825,2.00825,2.00825,4,4,4,4,3.91591,3.91591,4,4,3.55897,3.55897,3.55897,3.55897,3.55897,2.47601,2.47601,1.40663,1.07236,3.23893,3.23893,4,4,3.3878,3.3878,3.3878,2.13647,2.81839,2.0821,2.0821,2.0821,2.0821,2.19738,2.19738,3.78217,4,2.08083,2.08083,4,1.07707,4,4,2.40704,1.95116,1.10156,1.98411,3.45101,2.54014,1.90147,0.367729,2.62121,4,1.73289,1.73289,1.73289,1.73289,3.61444,3.61444,3.61444,4,4,4,4,4,4,3.93138,3.01167,2.96898,3.13172,3.13172,3.13172,3.39691,1.35577,1.35577,1.35577,1.35577,1.35577,3.51501,3.51501,1.92332,2.19674,2.19674,3.80158,4,4,2.92661,4,2.55849,3.26531,3.33415,3.33415,0.923703,3.40146,1.04393,1.04393,2.05067,3.66349,3.97813,3.97813,3.97813,4,4,3.41119,3.44686,3.72715,3.03541,1.79995,3.40239,4,2.54892,1.87262,1.87262,1.07588,1.07588,1.07588,2.81387,3.39725,3.39725,3.39725,3.39725,3.39725,1.8457,1.8457,2.03499,2.03499,2.03499,2.03499,2.90639,2.60643,1.90273,1.90273,2.0712,2.0712,2.0712,2.0712,1.67234,2.8167,2.8167,1.52905,1.52905,1.59129", "train/clip_coef": "0.218349,0.218349,0.012319,0.01,0.01,0.01,0.01,0.207684,0.300162,0.0402883,0.222483,0.222483,0.222483,0.391942,0.144283,0.321564,0.188971,0.188971,0.188971,0.209241,0.209241,0.292247,0.292247,0.292247,0.0685502,0.0843471,0.0843471,0.0843471,0.0843471,0.204996,0.204996,0.0512717,0.174785,0.174785,0.130522,0.200701,0.121553,0.328406,0.328558,0.215733,0.0705636,0.0705636,0.326965,0.375251,0.0960086,0.0960086,0.0960086,0.310728,0.310728,0.310728,0.2128,0.0623047,0.4105,0.330876,0.330876,0.01,0.372194,0.0815793,0.0815793,0.0815793,0.243779,0.0290298,0.01,0.01,0.01,0.101223,0.191079,0.191079,0.161063,0.161063,0.198631,0.0987234,0.0987234,0.197051,0.01,0.01,0.302284,0.219611,0.26348,0.26348,0.26348,0.26348,0.241383,0.251667,0.227417,0.296881,0.0421795,0.0421795,0.10247,0.10247,0.300557,0.173476,0.0812942,0.0812942,0.0812942,0.0812942,0.0812942,0.351381,0.351381,0.182055,0.182055,0.182055,0.182055,0.46324,0.140702,0.111071,0.111071,0.534525,0.232465,0.232465,0.232465,0.169547,0.169547,0.169547,0.10344,0.134495,0.158656,0.104904,0.153438,0.153438,0.153438,0.106595,0.01,0.0714794,0.0714794,0.0714794,0.0714794,0.0714794,0.280962,0.280962,0.280962,0.280962,0.0759661,0.0759661,0.209244,0.319846,0.126835,0.126835,0.126835,0.126835,0.126835,0.0629824,0.0629824,0.340941,0.177817,0.308278,0.308278,0.21398,0.21398,0.0383706,0.0383706,0.0383706,0.227231,0.01,0.220477,0.220477,0.220477,0.220477,0.225487,0.225487,0.0543803,0.142574,0.168047,0.168047,0.182856,0.198706,0.245597,0.259399,0.110061,0.18087,0.320275,0.156265,0.255148,0.159016,0.214577,0.13455,0.01,0.314615,0.127817,0.127817,0.127817,0.127817,0.205258,0.205258,0.205258,0.187683,0.187683,0.187683,0.147017,0.147017,0.147017,0.160885,0.178474,0.202955,0.239128,0.239128,0.239128,0.216706,0.16741,0.16741,0.16741,0.16741,0.16741,0.0530518,0.0530518,0.211562,0.245876,0.245876,0.0989217,0.323607,0.323607,0.366739,0.313907,0.11298,0.180466,0.140832,0.140832,0.187621,0.315703,0.236688,0.236688,0.326413,0.0763379,0.0324118,0.0324118,0.0324118,0.0617136,0.0617136,0.01,0.249008,0.385112,0.190318,0.0832107,0.216122,0.215575,0.113315,0.243664,0.243664,0.088825,0.088825,0.088825,0.168517,0.166932,0.166932,0.166932,0.166932,0.166932,0.0513821,0.0513821,0.265334,0.265334,0.265334,0.265334,0.216385,0.321569,0.205326,0.205326,0.278498,0.278498,0.278498,0.278498,0.0983047,0.135136,0.135136,0.233084,0.233084,0.205233", "train/vf_coef": "5,5,5,5,5,5,5,4.57307,4.10519,4.91316,2.94066,2.94066,2.94066,5,3.15041,4.41266,5,5,5,3.05268,3.05268,5,5,5,5,3.71415,3.71415,3.71415,3.71415,3.49652,3.49652,1.83089,3.00166,3.00166,4.00611,2.02519,3.50434,4.40918,5,5,3.85875,3.85875,3.92737,2.21335,5,5,5,4.37558,4.37558,4.37558,4.60041,5,1.90876,3.53375,3.53375,5,2.68439,4.84107,4.84107,4.84107,5,3.58207,5,5,5,5,4.50311,4.50311,5,5,4.22185,4.34134,4.34134,3.41447,5,5,2.29492,1.95143,5,5,5,5,5,2.04539,4.83541,3.96107,5,5,4.45463,4.45463,4.82709,5,5,5,5,5,5,3.80962,3.80962,3.29042,3.29042,3.29042,3.29042,2.3877,4.46459,3.33717,3.33717,3.49392,5,5,5,3.28319,3.28319,3.28319,5,5,3.10904,0.82197,3.83372,3.83372,3.83372,5,5,4.53547,4.53547,4.53547,4.53547,4.53547,5,5,5,5,4.90861,4.90861,4.59262,4.01019,4.9627,4.9627,4.9627,4.9627,4.9627,3.61522,3.61522,3.44517,2.53144,5,5,5,5,5,5,5,5,5,1.97496,1.97496,1.97496,1.97496,5,5,5,5,3.51248,3.51248,3.34662,3.30748,5,4.42131,5,2.77218,3.24511,4.0282,3.95598,4.48855,4.72274,2.30161,5,5,4.13725,4.13725,4.13725,4.13725,2.94971,2.94971,2.94971,2.37121,2.37121,2.37121,3.56615,3.56615,3.56615,4.298,5,3.68965,3.21431,3.21431,3.21431,2.52813,2.62466,2.62466,2.62466,2.62466,2.62466,5,5,4.39809,3.39948,3.39948,4.25571,4.44271,4.44271,2.02094,5,5,5,3.90003,3.90003,2.08848,5,3.19743,3.19743,4.6754,4.57416,5,5,5,4.16828,4.16828,5,5,3.35782,4.48563,4.71074,2.58137,5,5,3.94064,3.94064,5,5,5,2.63114,3.93414,3.93414,3.93414,3.93414,3.93414,4.26632,4.26632,3.53063,3.53063,3.53063,3.53063,1.8875,4.87514,3.36419,3.36419,3.21857,3.21857,3.21857,3.21857,3.61379,2.38265,2.38265,2.75675,2.75675,2.62054", "train/vf_clip_coef": "2.42859,2.42859,2.50999,0.01,0.01,0.01,0.01,0.01,1.16666,0.806605,1.24413,1.24413,1.24413,2.39305,1.61239,2.14027,2.63764,2.63764,2.63764,0.184948,0.184948,0.733908,0.733908,0.733908,0.5642,0.01,0.01,0.01,0.01,1.99129,1.99129,1.98694,0.01,0.01,1.52667,0.01,0.444463,0.01,1.1138,2.63677,0.01,0.01,0.01,0.677468,1.08904,1.08904,1.08904,0.664079,0.664079,0.664079,0.01,0.0338825,0.01,0.258027,0.258027,0.0615325,0.184576,0.01,0.01,0.01,2.5725,0.128435,0.837853,0.837853,0.837853,2.01166,1.36699,1.36699,1.21359,1.21359,0.01,1.43978,1.43978,0.01,0.01,0.01,0.78829,1.7881,3.48765,3.48765,3.48765,3.48765,2.29747,0.721524,2.76952,2.11286,1.39613,1.39613,0.320001,0.320001,1.82384,0.8503,1.04898,1.04898,1.04898,1.04898,1.04898,2.40753,2.40753,0.127902,0.127902,0.127902,0.127902,1.06675,3.59432,0.01,0.01,1.68582,2.41108,2.41108,2.41108,0.01,0.01,0.01,0.01,1.95332,0.645678,1.95766,0.01,0.01,0.01,2.22876,1.29779,0.471636,0.471636,0.471636,0.471636,0.471636,3.17444,3.17444,3.17444,3.17444,0.01,0.01,0.561066,3.92505,1.72367,1.72367,1.72367,1.72367,1.72367,0.01,0.01,0.354002,0.828984,0.01,0.01,0.01,0.01,0.01,0.01,0.01,3.05368,1.18044,0.01,0.01,0.01,0.01,0.85609,0.85609,3.15176,0.01,0.179612,0.179612,0.01,1.45878,1.00079,0.544869,1.59662,1.14364,0.120019,0.01,0.461038,1.56026,0.01,1.12365,0.01,3.89834,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.387004,0.387004,0.387004,0.01,0.01,0.01,0.01,0.700791,0.01,1.60072,1.60072,1.60072,1.20202,1.37477,1.37477,1.37477,1.37477,1.37477,0.01,0.01,2.36547,1.32507,1.32507,0.01,3.92642,3.92642,1.00632,0.0987646,2.1108,0.987557,0.01,0.01,1.12134,4.2631,1.04847,1.04847,3.35494,0.662555,0.837644,0.837644,0.837644,0.01,0.01,0.01,0.01,2.45837,0.806495,1.21289,0.676053,0.30249,2.08336,0.402246,0.402246,0.703924,0.703924,0.703924,0.01,0.01,0.01,0.01,0.01,0.01,0.903944,0.903944,0.76889,0.76889,0.76889,0.76889,0.145157,0.345194,0.339339,0.339339,0.0498227,0.0498227,0.0498227,0.0498227,0.067537,1.00451,1.00451,0.01,0.01,0.01", "train/max_grad_norm": "3.64835,3.64835,0.180912,1.10486,1.10486,1.10486,1.10486,5,3.51186,4.75091,3.82525,3.82525,3.82525,3.83196,3.06594,2.4689,2.56554,2.56554,2.56554,1.68062,1.68062,1.25796,1.25796,1.25796,3.18337,5,5,5,5,0.711777,0.711777,3.77263,4.8374,4.8374,4.27637,4.49406,5,1.95029,2.80528,0.204168,0.16808,0.16808,2.77326,3.67514,1.22515,1.22515,1.22515,1.47763,1.47763,1.47763,1.56356,0.962858,4.32809,4.5856,4.5856,0.71807,5,2.41724,2.41724,2.41724,0.677005,5,0.929691,0.929691,0.929691,0.690254,0.373579,0.373579,2.03404,2.03404,4.78261,3.87427,3.87427,4.91237,1.73134,1.73134,1.12764,2.24953,4.67311,4.67311,4.67311,4.67311,2.92259,4.14946,3.73267,3.87177,1.05917,1.05917,4.11171,4.11171,0.155405,1.82209,0.826544,0.826544,0.826544,0.826544,0.826544,0.681121,0.681121,2.91552,2.91552,2.91552,2.91552,1.41503,2.70827,4.9372,4.9372,3.92543,0.940011,0.940011,0.940011,2.25379,2.25379,2.25379,2.1961,3.64753,4.88342,4.66419,5,5,5,0.632099,0.57155,4.88723,4.88723,4.88723,4.88723,4.88723,1.41669,1.41669,1.41669,1.41669,1.89688,1.89688,2.17187,3.46232,1.67896,1.67896,1.67896,1.67896,1.67896,2.10638,2.10638,5,3.11999,3.89126,3.89126,2.27446,2.27446,2.72394,2.72394,2.72394,2.46039,2.36432,4.07729,4.07729,4.07729,4.07729,4.20764,4.20764,0.1,3.34966,5,5,4.16924,2.65692,2.12128,1.07882,2.4895,5,0.744004,5,2.01114,0.750847,3.86885,0.70373,1.19592,2.08296,4.37152,4.37152,4.37152,4.37152,4.66782,4.66782,4.66782,4.50657,4.50657,4.50657,1.98722,1.98722,1.98722,2.29883,2.56109,2.32555,5,5,5,4.31398,3.0892,3.0892,3.0892,3.0892,3.0892,1.14628,1.14628,0.297546,4.57191,4.57191,3.09785,3.37718,3.37718,5,3.99934,1.69956,1.18675,1.93505,1.93505,4.43294,2.28833,4.21256,4.21256,2.64603,1.19946,1.65705,1.65705,1.65705,2.59766,2.59766,1.57084,3.35752,4.43392,3.69684,4.08318,5,2.15105,1.76135,1.30927,1.30927,4.59734,4.59734,4.59734,5,0.436447,0.436447,0.436447,0.436447,0.436447,3.45157,3.45157,3.96709,3.96709,3.96709,3.96709,5,0.942154,5,5,5,5,5,5,3.0868,4.57092,4.57092,2.2179,2.2179,4.5527", "train/ent_coef": "0.0013113,0.0013113,0.00334483,0.0176368,0.0176368,0.0176368,0.0176368,4.90586e-05,6.88464e-05,0.000520825,7.35355e-05,7.35355e-05,7.35355e-05,0.00200517,4.67594e-05,0.021945,0.000880428,0.000880428,0.000880428,0.000569115,0.000569115,0.000304793,0.000304793,0.000304793,0.00248157,0.000931538,0.000931538,0.000931538,0.000931538,1e-05,1e-05,3.23726e-05,0.000409075,0.000409075,0.000367834,0.00179279,0.00161322,0.000475056,0.000128801,0.000182099,0.0028444,0.0028444,0.00158504,0.0154305,0.00361265,0.00361265,0.00361265,0.0013685,0.0013685,0.0013685,0.000430938,0.00100373,8.10772e-05,0.000449075,0.000449075,0.00258504,0.000539039,0.00371062,0.00371062,0.00371062,0.00013389,4.32866e-05,0.0186845,0.0186845,0.0186845,0.000343825,1e-05,1e-05,0.00810691,0.00810691,4.87981e-05,3.59761e-05,3.59761e-05,8.79054e-05,0.00701552,0.00701552,0.000194525,0.00378698,0.00396404,0.00396404,0.00396404,0.00396404,0.0033127,0.000644917,0.00838471,0.000372581,0.00834489,0.00834489,0.00260872,0.00260872,0.00282754,0.00177506,0.00328871,0.00328871,0.00328871,0.00328871,0.00328871,1.89946e-05,1.89946e-05,0.00460249,0.00460249,0.00460249,0.00460249,0.00241487,0.00675452,0.000558606,0.000558606,0.000236278,0.00307586,0.00307586,0.00307586,0.0121206,0.0121206,0.0121206,0.000505346,0.000742265,0.00155526,0.0386542,4.69809e-05,4.69809e-05,4.69809e-05,0.000280819,0.00537313,0.00331737,0.00331737,0.00331737,0.00331737,0.00331737,0.000583852,0.000583852,0.000583852,0.000583852,0.00479532,0.00479532,0.000261048,0.00503038,0.0354112,0.0354112,0.0354112,0.0354112,0.0354112,0.00135346,0.00135346,0.000129524,0.0020685,0.000110546,0.000110546,0.00434337,0.00434337,0.0133993,0.0133993,0.0133993,0.00140869,0.0270716,0.0191283,0.0191283,0.0191283,0.0191283,0.00112891,0.00112891,7.26947e-05,0.000833818,0.00023521,0.00023521,0.000123854,0.00290644,5.15351e-05,9.41718e-05,0.00105063,0.0010051,0.000819303,1e-05,0.00487087,0.00166746,0.000377199,0.00025101,0.00885843,0.00145978,0.00453436,0.00453436,0.00453436,0.00453436,0.00147029,0.00147029,0.00147029,0.000947892,0.000947892,0.000947892,0.00113754,0.00113754,0.00113754,0.000342692,0.0530915,0.00126998,0.00119637,0.00119637,0.00119637,0.000677157,0.00356874,0.00356874,0.00356874,0.00356874,0.00356874,0.0215481,0.0215481,0.0335774,0.00041596,0.00041596,0.000695474,0.00574789,0.00574789,0.00200597,0.00126343,0.00499825,0.0169612,0.000412326,0.000412326,0.000366622,0.0454876,1e-05,1e-05,0.00387832,0.0116902,0.00267572,0.00267572,0.00267572,0.000288076,0.000288076,0.0067386,0.00105162,0.0020416,0.00516653,0.00119224,0.000163296,0.000456445,0.000708423,0.00156204,0.00156204,0.000196078,0.000196078,0.000196078,0.00143637,0.00259402,0.00259402,0.00259402,0.00259402,0.00259402,0.000108842,0.000108842,4.87989e-05,4.87989e-05,4.87989e-05,4.87989e-05,0.000108127,0.00445284,3.41695e-05,3.41695e-05,6.82589e-05,6.82589e-05,6.82589e-05,6.82589e-05,0.00143348,7.96187e-05,7.96187e-05,0.00665258,0.00665258,6.98847e-05", "train/beta1": "0.98296,0.98296,0.980774,0.997277,0.997277,0.997277,0.997277,0.975962,0.971158,0.97818,0.971073,0.971073,0.971073,0.972444,0.970349,0.962999,0.966398,0.966398,0.966398,0.952914,0.952914,0.993264,0.993264,0.993264,0.979393,0.980897,0.980897,0.980897,0.980897,0.984339,0.984339,0.934539,0.96204,0.96204,0.990682,0.987169,0.94965,0.989615,0.984756,0.976886,0.988153,0.988153,0.978971,0.795638,0.993757,0.993757,0.993757,0.986316,0.986316,0.986316,0.984203,0.979651,0.832726,0.978161,0.978161,0.992647,0.954383,0.989798,0.989798,0.989798,0.951823,0.963982,0.99064,0.99064,0.99064,0.993365,0.969344,0.969344,0.992412,0.992412,0.899868,0.976495,0.976495,0.969628,0.98835,0.98835,0.942615,0.951079,0.988088,0.988088,0.988088,0.988088,0.986391,0.9811,0.97808,0.95799,0.995615,0.995615,0.963747,0.963747,0.972281,0.975089,0.991495,0.991495,0.991495,0.991495,0.991495,0.964501,0.964501,0.990452,0.990452,0.990452,0.990452,0.948653,0.978966,0.973669,0.973669,0.966414,0.97411,0.97411,0.97411,0.952768,0.952768,0.952768,0.98807,0.981181,0.983737,0.992569,0.9806,0.9806,0.9806,0.991372,0.976752,0.960198,0.960198,0.960198,0.960198,0.960198,0.994161,0.994161,0.994161,0.994161,0.973348,0.973348,0.994061,0.986517,0.991881,0.991881,0.991881,0.991881,0.991881,0.969261,0.969261,0.95091,0.910367,0.983901,0.983901,0.99459,0.99459,0.990965,0.990965,0.990965,0.969194,0.995076,0.984255,0.984255,0.984255,0.984255,0.976384,0.976384,0.987575,0.994075,0.973725,0.973725,0.981769,0.776139,0.995162,0.990127,0.980573,0.983471,0.923782,0.972913,0.987301,0.968162,0.943658,0.86503,0.984367,0.990604,0.975239,0.975239,0.975239,0.975239,0.957467,0.957467,0.957467,0.984203,0.984203,0.984203,0.987669,0.987669,0.987669,0.993447,0.995215,0.982659,0.927544,0.927544,0.927544,0.958794,0.884024,0.884024,0.884024,0.884024,0.884024,0.991476,0.991476,0.921393,0.984904,0.984904,0.983959,0.974258,0.974258,0.97447,0.958564,0.985655,0.974606,0.972525,0.972525,0.920294,0.995764,0.971481,0.971481,0.9514,0.995349,0.987553,0.987553,0.987553,0.981002,0.981002,0.995685,0.992012,0.991858,0.973729,0.943072,0.997164,0.994615,0.950524,0.979075,0.979075,0.98317,0.98317,0.98317,0.962845,0.973978,0.973978,0.973978,0.973978,0.973978,0.97287,0.97287,0.976464,0.976464,0.976464,0.976464,0.98768,0.99713,0.959631,0.959631,0.983787,0.983787,0.983787,0.983787,0.972737,0.980797,0.980797,0.961442,0.961442,0.881475", "train/beta2": "0.978864,0.978864,0.998135,0.998292,0.998292,0.998292,0.998292,0.99991,0.995992,0.992604,0.998814,0.998814,0.998814,0.9,0.994802,0.995308,0.971413,0.971413,0.971413,0.999856,0.999856,0.999742,0.999742,0.999742,0.996008,0.9,0.9,0.9,0.9,0.993633,0.993633,0.999409,0.999468,0.999468,0.980029,0.999611,0.999735,0.998773,0.999853,0.999302,0.998279,0.998279,0.999585,0.997175,0.999816,0.999816,0.999816,0.99985,0.99985,0.99985,0.998749,0.996641,0.994809,0.996472,0.996472,0.983664,0.999852,0.999781,0.999781,0.999781,0.999717,0.9,0.994771,0.994771,0.994771,0.99931,0.999321,0.999321,0.999911,0.999911,0.993015,0.998311,0.998311,0.972152,0.934911,0.934911,0.997868,0.989632,0.990939,0.990939,0.990939,0.990939,0.925407,0.99974,0.996716,0.999741,0.999473,0.999473,0.974509,0.974509,0.997723,0.998402,0.999943,0.999943,0.999943,0.999943,0.999943,0.997067,0.997067,0.988076,0.988076,0.988076,0.988076,0.989681,0.95815,0.99998,0.99998,0.994108,0.997101,0.997101,0.997101,0.998668,0.998668,0.998668,0.999239,0.998135,0.999032,0.998349,0.960783,0.960783,0.960783,0.997125,0.999542,0.914444,0.914444,0.914444,0.914444,0.914444,0.9,0.9,0.9,0.9,0.998948,0.998948,0.999835,0.995635,0.999684,0.999684,0.999684,0.999684,0.999684,0.998681,0.998681,0.959984,0.998576,0.999331,0.999331,0.997966,0.997966,0.999896,0.999896,0.999896,0.996135,0.999896,0.998721,0.998721,0.998721,0.998721,0.999149,0.999149,0.998474,0.998225,0.99942,0.99942,0.99634,0.989338,0.999904,0.998467,0.973474,0.995343,0.988779,0.997748,0.959146,0.999588,0.994986,0.996089,0.992944,0.953409,0.969898,0.969898,0.969898,0.969898,0.999647,0.999647,0.999647,0.926333,0.926333,0.926333,0.999264,0.999264,0.999264,0.999913,0.999314,0.999118,0.999826,0.999826,0.999826,0.999916,0.993824,0.993824,0.993824,0.993824,0.993824,0.999784,0.999784,0.998495,0.983443,0.983443,0.997445,0.982286,0.982286,0.998831,0.983502,0.996707,0.999447,0.999809,0.999809,0.999931,0.985783,0.938844,0.938844,0.99883,0.997904,0.997921,0.997921,0.997921,0.999342,0.999342,0.999024,0.998445,0.99982,0.993016,0.992187,0.99832,0.999186,0.999463,0.99972,0.99972,0.9,0.9,0.9,0.999483,0.943583,0.943583,0.943583,0.943583,0.943583,0.947816,0.947816,0.999593,0.999593,0.999593,0.999593,0.99477,0.999982,0.998797,0.998797,0.971707,0.971707,0.971707,0.971707,0.9,0.999894,0.999894,0.999743,0.999743,0.976462", "train/eps": "1e-14,1e-14,1.78318e-09,4.28525e-11,4.28525e-11,4.28525e-11,4.28525e-11,2.06889e-13,6.08814e-05,1e-14,4.00378e-12,4.00378e-12,4.00378e-12,8.47836e-11,2.72004e-10,6.62368e-12,7.22411e-13,7.22411e-13,7.22411e-13,1.63069e-12,1.63069e-12,1.67968e-07,1.67968e-07,1.67968e-07,1.19735e-06,3.05806e-12,3.05806e-12,3.05806e-12,3.05806e-12,3.23874e-09,3.23874e-09,6.10599e-14,2.28077e-13,2.28077e-13,1e-14,4.19097e-12,1e-14,2.88488e-08,5.29298e-09,3.22196e-08,4.2867e-08,4.2867e-08,1.90135e-07,7.30105e-14,5.39318e-07,5.39318e-07,5.39318e-07,9.85477e-14,9.85477e-14,9.85477e-14,1.70172e-08,8.17017e-10,3.52564e-11,1e-14,1e-14,4.18065e-08,7.38516e-13,6.03309e-09,6.03309e-09,6.03309e-09,4.26437e-10,2.10788e-12,6.18158e-12,6.18158e-12,6.18158e-12,9.67958e-09,2.25711e-08,2.25711e-08,1.11681e-11,1.11681e-11,1e-14,1e-14,1e-14,1.26725e-14,5.36606e-07,5.36606e-07,2.42483e-14,8.30457e-13,1.65178e-13,1.65178e-13,1.65178e-13,1.65178e-13,8.08597e-14,1e-14,2.55001e-11,2.11245e-11,1.75546e-09,1.75546e-09,5.64429e-13,5.64429e-13,5.64945e-08,2.9857e-06,6.19484e-08,6.19484e-08,6.19484e-08,6.19484e-08,6.19484e-08,5.17268e-07,5.17268e-07,1.00774e-09,1.00774e-09,1.00774e-09,1.00774e-09,1e-14,1e-14,1e-14,1e-14,1.52508e-14,6.82607e-09,6.82607e-09,6.82607e-09,8.60381e-14,8.60381e-14,8.60381e-14,1.26954e-07,1e-14,4.07635e-13,9.32067e-14,1.88539e-12,1.88539e-12,1.88539e-12,6.22997e-06,1.0293e-09,7.18357e-10,7.18357e-10,7.18357e-10,7.18357e-10,7.18357e-10,2.09447e-08,2.09447e-08,2.09447e-08,2.09447e-08,4.63009e-11,4.63009e-11,2.73985e-08,2.19661e-14,2.74579e-08,2.74579e-08,2.74579e-08,2.74579e-08,2.74579e-08,1.65164e-10,1.65164e-10,1e-14,1.14342e-14,9.57967e-10,9.57967e-10,9.84101e-08,9.84101e-08,7.77537e-09,7.77537e-09,7.77537e-09,4.22262e-14,2.25804e-11,1.65284e-13,1.65284e-13,1.65284e-13,1.65284e-13,3.71404e-13,3.71404e-13,4.36708e-07,1.30936e-07,4.24651e-14,4.24651e-14,7.25078e-12,1.39688e-14,2.85793e-07,1.11108e-08,1.26028e-13,1e-14,1e-14,1e-14,1.11978e-08,4.65039e-11,1.51532e-12,1.90246e-13,6.46473e-08,1e-14,7.67385e-12,7.67385e-12,7.67385e-12,7.67385e-12,1.57236e-10,1.57236e-10,1.57236e-10,5.76827e-13,5.76827e-13,5.76827e-13,3.04427e-05,3.04427e-05,3.04427e-05,4.66805e-06,1.75524e-10,2.68586e-09,1.10329e-14,1.10329e-14,1.10329e-14,5.99043e-14,1e-14,1e-14,1e-14,1e-14,1e-14,8.01457e-07,8.01457e-07,1.12977e-09,7.26246e-14,7.26246e-14,8.17535e-06,2.19115e-12,2.19115e-12,9.17071e-13,1.72463e-13,4.90595e-09,4.87153e-09,5.78247e-09,5.78247e-09,1e-14,2.35937e-10,2.62422e-12,2.62422e-12,7.23902e-12,5.54279e-10,6.374e-09,6.374e-09,6.374e-09,5.67957e-08,5.67957e-08,3.53365e-09,4.83876e-08,5.21562e-13,2.17752e-11,2.7067e-14,1.33107e-10,4.95244e-07,8.49725e-09,6.85685e-13,6.85685e-13,1.33065e-12,1.33065e-12,1.33065e-12,1.07252e-12,1.91232e-09,1.91232e-09,1.91232e-09,1.91232e-09,1.91232e-09,7.41252e-12,7.41252e-12,1e-14,1e-14,1e-14,1e-14,4.24279e-11,7.23851e-10,1.47992e-11,1.47992e-11,7.77692e-14,7.77692e-14,7.77692e-14,7.77692e-14,1.08257e-14,6.50297e-10,6.50297e-10,1e-14,1e-14,1e-14", "train/minibatch_size": "32768,32768,32768,32768,32768,32768,32768,16384,32768,16384,32768,32768,32768,16384,32768,16384,32768,32768,32768,16384,16384,32768,32768,32768,16384,16384,16384,16384,16384,65536,65536,16384,16384,16384,32768,16384,32768,32768,32768,65536,65536,65536,16384,16384,16384,16384,16384,8192,8192,8192,65536,16384,32768,32768,32768,16384,16384,16384,16384,16384,65536,16384,32768,32768,32768,65536,32768,32768,32768,32768,16384,16384,16384,32768,32768,32768,65536,16384,16384,16384,16384,16384,32768,65536,16384,32768,32768,32768,16384,16384,16384,16384,16384,16384,16384,16384,16384,65536,65536,32768,32768,32768,32768,65536,16384,32768,32768,16384,16384,16384,16384,32768,32768,32768,65536,16384,32768,32768,32768,32768,32768,65536,32768,16384,16384,16384,16384,16384,16384,16384,16384,16384,16384,16384,16384,16384,32768,32768,32768,32768,32768,16384,16384,32768,16384,32768,32768,32768,32768,32768,32768,32768,32768,16384,16384,16384,16384,16384,16384,16384,65536,16384,32768,32768,16384,32768,65536,32768,32768,32768,65536,16384,32768,16384,16384,32768,32768,8192,16384,16384,16384,16384,32768,32768,32768,16384,16384,16384,32768,32768,32768,16384,32768,32768,32768,32768,32768,65536,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,16384,16384,16384,32768,8192,32768,32768,32768,32768,65536,8192,32768,32768,16384,16384,32768,32768,32768,16384,16384,32768,16384,16384,8192,16384,32768,8192,8192,16384,16384,32768,32768,32768,65536,32768,32768,32768,32768,32768,32768,32768,16384,16384,16384,16384,32768,4096,32768,32768,32768,32768,32768,32768,32768,32768,32768,16384,16384,16384", "train/horizon": "256,256,128,256,256,256,256,64,1024,128,64,64,64,1024,64,256,128,128,128,32,32,512,512,512,256,32,32,32,32,512,512,64,128,128,128,256,32,512,256,256,256,256,512,64,512,512,512,64,64,64,512,256,128,128,128,512,512,256,256,256,256,32,256,256,256,256,1024,1024,512,512,64,128,128,32,128,128,64,64,512,512,512,512,512,1024,512,64,256,256,64,64,64,1024,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,64,64,64,64,128,128,128,1024,256,128,32,32,32,32,256,128,32,32,32,32,32,512,512,512,512,1024,1024,512,1024,256,256,256,256,256,128,128,64,64,1024,1024,256,256,128,128,128,64,128,32,32,32,32,64,64,128,1024,64,64,128,64,512,1024,256,64,128,64,1024,128,64,128,256,1024,64,64,64,64,128,128,128,1024,1024,1024,512,512,512,1024,256,128,256,256,256,512,64,64,64,64,64,128,128,128,128,128,128,1024,1024,512,512,64,128,128,128,128,256,64,64,64,256,128,128,128,1024,1024,128,256,1024,128,128,256,512,32,64,64,64,64,64,128,512,512,512,512,512,32,32,128,128,128,128,512,512,64,64,64,64,64,64,64,256,256,32,32,32", "train/vtrace_rho_clip": "2.61224,2.61224,2.11924,1.35861,1.35861,1.35861,1.35861,2.51421,2.34675,1.65838,1.89971,1.89971,1.89971,1.36426,1.43864,2.54472,2.87093,2.87093,2.87093,2.26666,2.26666,1.90018,1.90018,1.90018,2.75519,1.13506,1.13506,1.13506,1.13506,2.43378,2.43378,1.3477,1.57556,1.57556,1.16193,1.93883,2.38078,2.04269,1.35151,2.27015,0.512114,0.512114,2.36866,1.95566,0.943396,0.943396,0.943396,2.25929,2.25929,2.25929,2.26817,0.544845,2.01269,2.54199,2.54199,0.322244,2.43266,2.68855,2.68855,2.68855,3.0324,2.23143,1.92693,1.92693,1.92693,1.6208,1.62144,1.62144,2.93341,2.93341,2.02813,1.47971,1.47971,1.28151,0.883828,0.883828,0.627048,4.09466,2.14126,2.14126,2.14126,2.14126,2.05283,1.2253,2.8282,2.19815,1.02922,1.02922,1.68092,1.68092,1.56216,1.6436,1.81246,1.81246,1.81246,1.81246,1.81246,1.43592,1.43592,2.05768,2.05768,2.05768,2.05768,3.44766,2.13932,3.37861,3.37861,0.1,2.00711,2.00711,2.00711,0.85741,0.85741,0.85741,2.26204,2.09961,1.17758,4.22614,2.05879,2.05879,2.05879,2.5002,2.55574,1.48386,1.48386,1.48386,1.48386,1.48386,2.46532,2.46532,2.46532,2.46532,2.19785,2.19785,1.75488,2.65116,2.04457,2.04457,2.04457,2.04457,2.04457,2.41022,2.41022,0.896553,1.63852,1.30857,1.30857,2.24059,2.24059,0.497704,0.497704,0.497704,2.18569,0.885257,3.11757,3.11757,3.11757,3.11757,0.820363,0.820363,1.3537,1.96504,2.3679,2.3679,2.61069,2.73423,2.64423,2.56521,3.2205,1.68633,2.2284,1.34284,2.20892,3.70409,1.58866,0.382178,1.38688,2.79469,1.21696,1.21696,1.21696,1.21696,2.19582,2.19582,2.19582,2.28355,2.28355,2.28355,2.10264,2.10264,2.10264,1.24797,2.12786,1.50969,1.56589,1.56589,1.56589,2.65834,1.50929,1.50929,1.50929,1.50929,1.50929,1.02589,1.02589,1.1953,1.59652,1.59652,2.01243,1.62583,1.62583,1.33286,2.84182,1.89528,1.15264,1.60645,1.60645,1.8209,2.61997,1.85193,1.85193,1.39863,1.34326,2.01097,2.01097,2.01097,2.44088,2.44088,1.60555,2.25913,1.29174,0.649102,1.69733,3.01716,1.57341,1.12383,1.29291,1.29291,1.60179,1.60179,1.60179,1.60725,2.23296,2.23296,2.23296,2.23296,2.23296,2.06989,2.06989,2.21754,2.21754,2.21754,2.21754,2.1825,2.65911,1.58174,1.58174,3.12872,3.12872,3.12872,3.12872,1.88863,1.66787,1.66787,1.63068,1.63068,1.10205", "train/vtrace_c_clip": "1.67948,1.67948,2.21058,1.54673,1.54673,1.54673,1.54673,1.37439,0.7405,1.87568,1.41788,1.41788,1.41788,1.02522,1.9744,0.729512,1.51153,1.51153,1.51153,1.90973,1.90973,1.02224,1.02224,1.02224,0.793112,2.24513,2.24513,2.24513,2.24513,0.70277,0.70277,1.85287,1.58927,1.58927,1.86587,1.36355,2.08499,1.5677,1.04,1.46104,1.46275,1.46275,1.00589,1.75793,1.54583,1.54583,1.54583,1.77591,1.77591,1.77591,1.2614,0.95553,1.77196,1.38631,1.38631,1.63408,0.779468,1.10627,1.10627,1.10627,0.767908,1.39098,1.73654,1.73654,1.73654,0.77411,0.92203,0.92203,0.647753,0.647753,2.16032,0.922692,0.922692,2.17567,2.35558,2.35558,0.328277,1.31861,0.888845,0.888845,0.888845,0.888845,1.0977,1.22596,1.46344,0.901824,0.676091,0.676091,1.45211,1.45211,1.58385,2.13404,1.40292,1.40292,1.40292,1.40292,1.40292,1.61865,1.61865,1.80655,1.80655,1.80655,1.80655,2.20856,1.77142,1.4429,1.4429,0.620503,1.49456,1.49456,1.49456,2.46817,2.46817,2.46817,0.897632,0.74133,1.65834,0.519604,1.94422,1.94422,1.94422,1.3587,1.65003,1.98739,1.98739,1.98739,1.98739,1.98739,1.59706,1.59706,1.59706,1.59706,0.705576,0.705576,1.05327,0.758571,1.17818,1.17818,1.17818,1.17818,1.17818,1.28664,1.28664,0.79436,1.8604,0.946376,0.946376,0.990452,0.990452,1.56411,1.56411,1.56411,1.25411,1.05305,1.9962,1.9962,1.9962,1.9962,2.22143,2.22143,1.12222,0.887484,1.29213,1.29213,1.51425,1.14264,0.988307,0.861563,2.50333,1.18402,1.08868,1.74326,1.37205,0.980847,2.46613,1.51333,1.18141,1.1701,2.30366,2.30366,2.30366,2.30366,1.40535,1.40535,1.40535,1.16519,1.16519,1.16519,1.44717,1.44717,1.44717,0.3899,0.922583,1.15615,1.3499,1.3499,1.3499,1.40644,1.65146,1.65146,1.65146,1.65146,1.65146,1.23511,1.23511,1.47245,1.22901,1.22901,1.08566,1.12907,1.12907,0.769412,1.31072,1.73607,1.4955,1.24062,1.24062,2.09408,0.961489,1.94047,1.94047,1.33434,2.03942,1.2977,1.2977,1.2977,0.421313,0.421313,0.823691,0.911572,0.820469,1.6125,1.73162,0.102353,1.18804,2.03749,1.06846,1.06846,1.43027,1.43027,1.43027,1.35317,1.83835,1.83835,1.83835,1.83835,1.83835,2.89715,2.89715,1.8096,1.8096,1.8096,1.8096,1.21911,2.36932,1.99206,1.99206,1.50643,1.50643,1.50643,1.50643,1.89646,1.79661,1.79661,1.5238,1.5238,1.10916", "train/prio_alpha": "0.906745,0.906745,0.653017,1,1,1,1,0.936852,0.557575,0.421101,0.746212,0.746212,0.746212,0.847748,0.876028,1,0.800152,0.800152,0.800152,1,1,0.721296,0.721296,0.721296,0.5193,1,1,1,1,0.327487,0.327487,0.793896,0.904598,0.904598,0.603728,0.914337,0.506508,0.969656,0.766508,0.469407,0.671212,0.671212,0.897651,0.94526,0.891079,0.891079,0.891079,0.926251,0.926251,0.926251,0.909095,0.850468,1,1,1,0.990305,0.801082,0.861652,0.861652,0.861652,0.616383,0.631739,0.891262,0.891262,0.891262,0.456904,0.519433,0.519433,1,1,0.739809,0.7292,0.7292,0.802919,0.681891,0.681891,0.968596,1,0.608034,0.608034,0.608034,0.608034,1,0.69365,0.516603,0.549838,0.807664,0.807664,0.7004,0.7004,0.712622,1,0.678436,0.678436,0.678436,0.678436,0.678436,0.245182,0.245182,0.990231,0.990231,0.990231,0.990231,0.752001,0.966665,0.86046,0.86046,1,0.682021,0.682021,0.682021,1,1,1,1,1,0.765552,0.0555704,0.698823,0.698823,0.698823,0.220538,0.509538,0.852992,0.852992,0.852992,0.852992,0.852992,1,1,1,1,1,1,0.87601,0.841461,0.814287,0.814287,0.814287,0.814287,0.814287,0.695756,0.695756,0.856556,1,0.995328,0.995328,1,1,1,1,1,0.762074,0.803361,0.890479,0.890479,0.890479,0.890479,0.743516,0.743516,0.531628,0.820033,0.741968,0.741968,0.956714,1,0.663426,0.758827,0.804588,1,1,1,0.514894,0.674482,0.807657,0.852606,0.703238,1,0.902951,0.902951,0.902951,0.902951,0.96611,0.96611,0.96611,1,1,1,1,1,1,0.81262,0.916435,0.657886,1,1,1,0.842787,0.905113,0.905113,0.905113,0.905113,0.905113,0.875227,0.875227,0.468286,0.875914,0.875914,0.651511,0.747213,0.747213,0.536211,1,0.527347,0.719035,0.871973,0.871973,1,1,0.746571,0.746571,0.976938,0.990561,0.700519,0.700519,0.700519,0.560175,0.560175,0.808376,0.626737,1,0.747953,0.960656,1,0.820218,0.640466,0.692647,0.692647,0.769677,0.769677,0.769677,0.951603,0.859579,0.859579,0.859579,0.859579,0.859579,0.757056,0.757056,0.977653,0.977653,0.977653,0.977653,0.797954,0.522781,0.858772,0.858772,0.752916,0.752916,0.752916,0.752916,0.663825,0.706885,0.706885,1,1,1", "train/prio_beta0": "0.533193,0.533193,0.386786,0.912387,0.912387,0.912387,0.912387,0.580622,1,0.707571,1,1,1,0.857124,0.932174,0.758187,0.774591,0.774591,0.774591,0.915127,0.915127,0.342677,0.342677,0.342677,0.780955,1,1,1,1,0.367597,0.367597,1,0.809835,0.809835,0.646381,0.52414,0.428861,0.658317,0.768825,0.498088,0.6997,0.6997,0.715085,0.638212,0.987352,0.987352,0.987352,1,1,1,1,1,0.695207,0.757042,0.757042,0.8456,0.984082,1,1,1,0.344256,1,0.900765,0.900765,0.900765,0.661691,0.289546,0.289546,0.962987,0.962987,1,0.732576,0.732576,1,1,1,0.378697,0.942952,1,1,1,1,0.488161,0.38504,1,0.787365,1,1,0.859103,0.859103,0.450394,1,1,1,1,1,1,0.58358,0.58358,0.509319,0.509319,0.509319,0.509319,0,0.599343,1,1,1,0.506033,0.506033,0.506033,0.77289,0.77289,0.77289,0.831815,0.327795,0.98505,0.137712,0.936554,0.936554,0.936554,0.863584,0.56973,0.90885,0.90885,0.90885,0.90885,0.90885,1,1,1,1,1,1,0.554182,0.762782,0.995962,0.995962,0.995962,0.995962,0.995962,0.633669,0.633669,0.735078,0.768244,0.706826,0.706826,0.594832,0.594832,0.703173,0.703173,0.703173,0.573963,0.78222,0.651419,0.651419,0.651419,0.651419,0.729027,0.729027,0.272803,0.937581,0.654176,0.654176,0.0606086,0.850707,0.808236,0.808455,0.695953,0.812619,0,0.884594,0.637539,0.665208,0.472639,0.269463,0.846223,0.887054,1,1,1,1,0.369252,0.369252,0.369252,0.688441,0.688441,0.688441,0.552591,0.552591,0.552591,0.550353,0.947918,0.570002,0.332502,0.332502,0.332502,0.517063,0.760588,0.760588,0.760588,0.760588,0.760588,0.909778,0.909778,0.274458,0.881253,0.881253,0.897367,0.824835,0.824835,0.97906,0.386547,0.477886,0.462015,0.768412,0.768412,0.857592,1,0.802895,0.802895,0.376429,0.681447,0.583265,0.583265,0.583265,0.85702,0.85702,0.79956,0.905307,0.888216,0.652816,0.768609,0.388247,1,0.371459,1,1,1,1,1,0.528794,0.703818,0.703818,0.703818,0.703818,0.703818,0.875797,0.875797,0.818899,0.818899,0.818899,0.818899,1,0.432417,0.671466,0.671466,0.950548,0.950548,0.950548,0.950548,0.852899,0.952096,0.952096,0.739269,0.739269,0.889668", "train/use_rnn": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "no_model_upload": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "tsne1": "-2.71277,-2.71283,15.9129,13.2712,13.2712,13.2712,13.2712,-10.5982,19.7246,-9.3888,-13.0552,-13.0552,-13.0553,2.61266,-13.6849,0.132172,-1.52348,-1.52343,-1.52391,-10.8104,-10.8104,18.1475,18.1475,18.1475,21.5092,-1.39164,-1.39164,-1.39169,-1.39169,20.2569,20.2569,-12.8227,-10.459,-10.4588,-9.68681,-8.70003,-11.8868,17.7294,19.2294,18.5863,13.0033,13.0033,18.0813,-13.7791,16.6211,16.6211,16.6211,-9.7206,-9.72048,-9.72054,19.0183,11.8323,-13.3906,-11.2726,-11.2726,16.4864,-11.3505,17.3555,17.3555,17.3555,18.3649,-2.44903,12.5796,12.5796,12.5796,18.5529,20.0585,20.0582,15.5042,15.5042,-9.18917,-9.68383,-9.68391,-7.38931,7.94578,7.94578,-6.61639,-13.3294,-1.948,-1.948,-1.948,-1.948,-2.58828,-9.29966,-1.39852,-13.8609,15.4491,15.449,-7.45107,-7.45107,15.3,14.9347,17.1679,17.168,17.1679,17.1679,17.1682,19.9877,19.9877,15.4079,15.4079,15.4079,15.4079,-2.79262,-1.98226,-10.4582,-10.4582,-12.0552,15.136,15.136,15.136,-11.4101,-11.4103,-11.4103,18.729,-5.7617,-11.3384,-25.4845,-6.77123,-6.77123,-6.77123,19.3118,15.8729,-0.371241,-0.371047,-0.371047,-0.367863,-0.366503,3.32508,3.32508,3.32508,3.32508,14.023,14.0229,18.0672,-1.71224,15.5326,15.5318,15.5324,15.5316,15.5317,13.8392,13.8394,-7.84442,-13.0477,20.8211,20.8211,16.7062,16.7062,13.863,13.8627,13.8627,-2.36916,12.1664,-14.9139,-14.9139,-14.9139,-14.9139,-8.60467,-8.6047,18.3745,18.3663,-11.6175,-11.6176,-6.59458,-13.9263,19.4723,19.0863,-2.39197,-11.5078,-2.98512,-9.12165,10.9112,14.4911,-10.9557,-5.07545,12.4971,-1.13189,-6.56432,-6.56436,-6.56436,-6.56436,-8.38403,-8.38403,-8.38403,-4.63553,-4.63466,-4.63544,17.0672,17.0672,17.0672,17.8988,12.2712,14.6385,-8.19781,-8.19781,-8.19781,-9.09203,-13.136,-13.1359,-13.1359,-13.1359,-13.136,12.8063,12.8063,16.0398,-11.3621,-11.3621,20.2453,-1.24695,-1.24695,-11.945,-5.87253,16.0021,15.6017,15.2365,15.2365,-13.6233,-0.376466,-5.47972,-5.47972,13.5358,13.3709,15.9913,15.9913,15.9913,18.7895,18.7895,13.2235,19.6103,-2.1526,-4.2316,-8.62192,-8.09011,18.6311,15.1016,-9.66725,-9.66724,-3.08425,-3.08425,-3.08425,-9.01624,10.1567,10.1565,10.1565,10.1567,10.1567,-5.4624,-5.4624,-10.1442,-10.1442,-10.1442,-10.1442,-12.1979,9.18951,-12.6169,-12.6169,-8.16699,-8.16692,-8.16698,-8.16776,-2.97617,-12.6548,-12.6548,-12.6473,-12.6473,-8.18314", "tsne2": "46.8059,46.8057,38.2155,49.9891,49.9891,49.9891,49.9891,36.9049,46.0931,34.9881,39.2147,39.2147,39.2146,45.7281,38.5701,48.3877,46.4262,46.4253,46.4252,27.8513,27.8513,42.2098,42.2098,42.2098,47.7322,38.4517,38.4517,38.4516,38.4516,39.5553,39.5553,40.0798,39.0191,39.0182,35.565,44.5365,35.7468,44.3374,43.1793,38.7348,43.574,43.574,45.7678,30.7002,51.4367,51.4367,51.4367,27.5047,27.5048,27.5048,44.296,45.8119,36.7622,37.8864,37.8864,52.0479,42.4179,48.5793,48.5793,48.5793,39.2753,37.97,51.8805,51.8805,51.8805,38.8161,40.486,40.4858,48.4675,48.4675,38.2983,36.269,36.2687,38.3642,43.9497,43.9497,4.02143,28.631,51.0528,51.0528,51.0528,51.0528,47.2814,46.8813,51.0746,39.6252,50.6946,50.6946,34.6305,34.6305,36.8589,52.9425,50.4872,50.4872,50.4872,50.4872,50.4873,38.754,38.754,44.6917,44.6917,44.6917,44.6917,1.51468,47.7698,42.5305,42.5305,33.5093,36.9909,36.9909,36.9909,30.7986,30.7988,30.7989,44.4181,47.0887,39.8365,5.23998,38.7854,38.7854,38.7854,38.2311,39.4134,37.8217,37.8216,37.8216,37.8281,37.8233,45.6658,45.6658,45.6658,45.6658,52.2548,52.2549,43.1366,49.9426,49.8074,49.8076,49.8072,49.8077,49.8077,41.511,41.5107,37.8134,31.0017,44.4227,44.4227,45.483,45.4834,46.6822,46.6827,46.6827,45.4775,47.1894,29.1544,29.1543,29.1544,29.1544,34.7183,34.7182,38.7777,48.0367,36.5723,36.5723,46.1904,31.5806,43.4685,43.9626,46.3691,38.4939,1.63949,37.6109,42.7157,37.6081,34.9587,3.09907,45.5072,49.0967,33.9645,33.9645,33.9645,33.9645,45.1861,45.1861,45.1861,43.6384,43.638,43.6386,44.3807,44.3807,44.3807,45.1043,47.3721,41.9265,46.8537,46.8537,46.8537,46.6808,31.7279,31.7278,31.7278,31.7278,31.7279,45.4764,45.4764,37.2967,39.0778,39.0778,47.2869,50.1382,50.1382,42.2351,46.8974,38.5377,40.0361,43.1856,43.1856,32.9595,49.5761,39.2704,39.2704,36.0974,51.1751,41.0489,41.0489,41.0489,47.6138,47.6138,46.1993,46.8858,49.8616,33.8122,35.5632,45.4887,48.9219,36.0508,28.6611,28.6609,38.5579,38.5579,38.5579,45.4064,42.9224,42.9222,42.9221,42.9225,42.9225,38.1982,38.1982,37.7896,37.7896,37.7896,37.7896,41.903,-18.6544,37.0473,37.0473,39.5691,39.5693,39.5692,39.5683,39.0788,41.5823,41.5823,29.7658,29.7658,37.6918"}, "g2048": {"SPS": "3.38139e+06,3.35346e+06,7.4616e+06,6.25157e+06,1.09132e+07,1.66128e+06,1.6596e+06,1.42407e+06,1.42487e+06,1.42579e+06,1.42615e+06,1.42194e+06,3.05716e+06,3.09576e+06,1.55602e+06,1.56151e+06,1.36731e+06,4.55521e+06,4.55949e+06,510881,510688,4.8642e+06,4.89893e+06,4.9213e+06,2.45671e+06,5.58211e+06,702579,702529,702522,460523,1.56987e+06,1.57392e+06,1.00411e+06,1.00455e+06,3.83333e+06,1.90175e+06,1.943e+06,1.94217e+06,1.61649e+06,933144,932946,932738,6.73333e+06,6.81329e+06,6.82825e+06,271126,271043,270970,5.43226e+06,1.36123e+06,2.04011e+06,2.04249e+06,2.04329e+06,1.11152e+06,1.11184e+06,5.00099e+06,4.99317e+06,1.35815e+06,1.35859e+06,2.97592e+06,1.82497e+06,3.49814e+06,9.84453e+06,1.01561e+07,689061,689027,688590,689005,4.2801e+06,4.09267e+06,2.17315e+06,2.17898e+06,2.17801e+06,5.07811e+06,1.84339e+06,2.79651e+06,2.83376e+06,2.846e+06,2.85116e+06,2.84552e+06,2.86578e+06,2.86457e+06,3.2654e+06,3.27741e+06,3.28947e+06,3.4062e+06,3.50992e+06,3.43862e+06,3.42768e+06,9.39981e+06,4.8443e+06,3.53875e+06,323547,1.25717e+06,2.40348e+06,4.73647e+06,4.72587e+06,4.71233e+06,4.71218e+06,1.64313e+06,2.13943e+06,2.13997e+06,4.26312e+06,4.2958e+06,4.28695e+06,175528,175656,175487,454760,416605,2.34836e+06,2.35962e+06,2.35549e+06,2.35823e+06,5.7563e+06,5.7309e+06,5.74063e+06,4.97292e+06,2.24008e+06,2.23655e+06,5.64654e+06,4.79636e+06,4.85309e+06,4.88406e+06,2.49553e+06,2.49534e+06,2.49371e+06,1.94259e+06,5.37621e+06,2.39467e+06,8.89633e+06,1.9893e+06,1.96498e+06,1.91801e+06,1.6016e+06,3.48343e+06,2.86935e+06,4.44035e+06,577214,3.57105e+06,3.97539e+06,3.98904e+06,4.58367e+06", "agent_steps": "1168.11,155.189,89.1715,12.2683,22.0201,759.693,867.172,82.8375,247.464,411.566,575.663,656.671,67.1089,198.181,114.819,343.409,135.791,68.9439,204.472,1288.44,1472.2,11.01,29.8844,48.7588,627.573,75.595,990.38,1386.22,1583.35,1966.6,391.643,446.693,899.678,1027.08,48.3656,4.60624,12.2225,19.8902,1012.92,25.1658,34.603,38.7973,52.1667,150.733,247.202,30.4087,41.943,47.1859,6.29146,50.3316,483.394,675.283,769.655,964.164,1100.48,242.221,1686.1,1263.53,1443.36,99.6147,1509.43,132.606,8.9129,18.3501,14.1558,23.0687,31.9816,36.1759,65.766,9.43718,125.829,375.914,999.293,327.156,1149.24,8.25754,22.9376,37.6177,52.2322,58.196,37.7487,60.8174,101.712,301.99,502.268,73.4003,218.37,359.924,502.511,14.4179,66.0603,496.239,4.45645,394.789,481.296,311.427,515.899,721.905,821.559,36.1234,34.603,56.6231,76.0218,225.444,374.866,22.5444,37.2244,51.9045,1883.24,159.121,57.4095,170.656,283.902,397.145,45.6131,131.858,218.104,95.6826,318.767,362.807,183.501,83.9937,251.058,416.023,38.5352,53.4774,59.7688,406.585,101.974,88.0804,93.6346,351.273,492.461,255.59,1472.72,6.60603,192.676,75.8201,2012.22,6.02931,133.205,397.41,6.29146", "uptime": "346.583,46.4613,11.9344,1.96888,2.0236,460.054,524.761,58.1643,173.73,288.879,403.949,460.751,22.0281,64.5578,73.897,220.428,99.5885,15.1695,44.8715,2522.12,2881.79,2.2845,6.13018,9.97615,256.594,13.6394,1410.43,1973.81,2254.44,4269.44,249.746,284.802,897.382,1024.25,12.6662,2.43738,6.3819,10.3289,628.641,26.959,37.0739,41.5696,7.79288,22.3008,36.4457,112.161,154.716,174.06,1.15878,36.9803,238.078,332.052,378.253,868.058,990.712,48.4713,337.236,936.063,1068.4,33.5379,826.566,37.9397,0.91471,1.84392,20.5475,33.4816,46.423,52.5139,15.3631,2.3147,57.9412,172.857,458.185,65.0448,624.025,2.96646,8.16924,13.3343,18.4632,20.5538,13.2494,21.2957,31.2141,92.3706,153.373,21.6331,63.4016,104.188,145.752,1.539,13.6681,140.468,13.7612,316.367,200.467,65.9429,109.166,152.821,173.981,22.0999,16.2373,26.5269,17.914,52.7529,87.5817,128.471,212.049,295.67,4138.93,383.827,24.4946,72.5629,120.591,168.643,7.92795,22.9431,37.9823,19.2995,141.84,161.521,32.5118,17.571,52.1583,86.028,15.5142,21.501,24.0219,209.695,19.1368,36.7831,10.5684,177.587,248.612,133.729,922.124,1.89818,67.1861,17.1952,3488.57,1.73866,33.5215,99.8698,1.3786", "epoch": "1114,296,340.162,23.4,21,724.5,827,316,944,1570,2195.98,2505,128,378,219,655,259,263,780,2457.5,2808,21,57,93,1197,288.372,944.5,1322,1510,3751,373.5,426,1716,1959,184.5,140.571,373,607,1932,24,33,37,199,575,943,29,40,45,3,96,461,644,734,1839,2099,462,3215.98,2410,2753,190,2879,505.853,17,35,27,44,61,69,250.878,9,240,717,1906,624,2192,31.5,87.5,143.5,199.25,222,72,116,388,1152,1916,280,833.016,1373,1916.93,27.5,126,946.5,17,753,918,594,984,1376.92,1567,68.9,33,54,145,430,715,21.5,35.5,49.5,1796,303.5,219,651,1083,1514.99,174,503,832,365,304,346,350,320.411,957.712,1587,73.5,102,114,775.5,389,336,178.594,335,469.647,487.5,2809,12.6,735,144.615,1919,11.5,508.139,1516,12", "env/perf": "0.126067,0.0299552,0.00960377,0.00194112,0.00226034,0.102578,0.111672,0.0247216,0.0577985,0.0758375,0.0860502,0.0915701,0.0132259,0.0357218,0.0315675,0.0647894,0.0342798,0.0114207,0.0298029,0.146245,0.163784,0.00325995,0.00567832,0.00731036,0.0885113,0.010917,0.118777,0.155984,0.163909,0.174915,0.0656526,0.0732298,0.118324,0.142051,0.00886674,0.00268255,0.00491722,0.00597857,0.111746,0.00758242,0.00955616,0.0104362,0.00746545,0.0202404,0.029738,0.00782993,0.0113122,0.0139424,0.00131724,0.0101866,0.0742005,0.0926591,0.101067,0.117669,0.129906,0.0387069,0.107054,0.134295,0.151978,0.0240688,0.131569,0.0266557,0.00156573,0.00224993,0.00507701,0.00770801,0.00948088,0.00983199,0.0101748,0.00203433,0.0256505,0.0604731,0.106335,0.046178,0.113418,0.00368205,0.00690884,0.00858292,0.0104572,0.0108918,0.00819318,0.0121252,0.0235752,0.052708,0.0719437,0.0167713,0.0369595,0.0593481,0.0731478,0.00184157,0.00925865,0.0634929,0.00193243,0.067106,0.0647295,0.0549884,0.0843539,0.10008,0.105964,0.00767769,0.00729104,0.012969,0.0126389,0.0390992,0.0567395,0.00761745,0.0125342,0.016038,0.173486,0.03517,0.0217466,0.0483266,0.0543824,0.061779,0.00714663,0.0227974,0.0340663,0.014581,0.0557907,0.0601687,0.0294377,0.0137058,0.0444378,0.0632303,0.00924757,0.0114278,0.0118665,0.062568,0.0197089,0.0235116,0.00923548,0.059093,0.0742757,0.0491627,0.137268,0.00176308,0.0300597,0.011784,0.167584,0.00154244,0.0296693,0.0595171,0.00139866", "env/score": "10327.7,2453.93,786.732,159.023,185.172,8403.22,9148.49,2025.19,4734.85,6212.61,7049.23,7501.49,1083.47,2926.33,2586.01,5307.55,2808.2,935.579,2441.46,11980.4,13418,267.052,465.162,598.857,7250.95,894.317,9730.22,12778.2,13428,14329.7,5378.25,5999.26,9693.11,11637.4,726.365,219.755,402.819,489.765,9154.37,621.154,782.844,854.944,611.564,1658.1,2436.15,641.431,926.698,1142.21,107.91,834.487,6078.5,7590.63,8279.71,9639.43,10642.1,3170.87,8769.83,11001.4,12450.3,1971.72,10778.6,2183.64,128.266,184.316,415.909,631.44,776.674,805.436,833.523,166.654,2101.29,4953.95,8711.07,3782.92,9291.29,301.631,565.97,703.113,856.657,892.263,671.187,993.302,1931.28,4317.84,5893.62,1373.91,3027.73,4861.8,5992.26,150.869,758.463,5201.35,158.305,5497.32,5302.64,4504.66,6910.27,8198.54,8680.7,628.959,597.284,1062.42,1035.38,3203.01,4648.1,624.023,1026.8,1313.84,14212.6,2881.12,1781.49,3958.91,4455,5060.93,585.451,1867.57,2790.72,1194.48,4570.37,4929.22,2411.54,1122.78,3640.36,5179.83,757.562,936.172,972.115,5125.56,1614.56,1926.07,756.563,4840.9,6084.66,4027.41,11245.5,144.432,2462.49,965.342,13729.3,126.355,2430.52,4875.65,114.582", "env/merge_score": "200149,41685.5,11539.7,1697.77,1979.68,154560,170073,34463,87859.3,119954,137811,147099,16448.2,50324.7,45931,98114.8,47531.8,13762.3,40616.1,237294,273485,3399.54,6486.15,8724.24,140656,13425.9,183111,254346,268977,288946,95736.1,108676,186833,230397,10543.9,2707.98,5187.94,6326.1,176325,8709.08,11375.2,12545.7,8604.87,26799.8,41300.2,8581.63,13104.5,16782.6,1100.53,12534.6,109657,141264,155530,189524,209316,54293.3,174981,218911,248477,32456.9,218955,35810.1,1325.05,1968.07,5362.2,8716.39,10946.3,11420.1,12859,1783.86,36071.5,93592.5,171673,63824.2,184750,3896.8,7999.1,10296.8,12857.6,13532.9,9738.01,15085.9,33129.2,78241.9,111422,21406.3,50964.9,86866.4,111809,1589.8,11577.2,94044,1670.96,105105,97062.4,79406.2,126791,154542,163915,8817.04,8805.95,16808,16191.7,56084.6,83424,8414.03,15027.5,20072.7,277482,52596.2,29684,66835.4,77394.8,87993,8271.74,29934.3,46885.3,18420.5,79084.8,86244.8,40608.6,16526.2,59966.5,89011.2,10477.2,13210.8,13800.3,97389.4,25468.6,32190.7,11061.3,84242.7,111298,73424.5,230192,1523.05,41049.2,14816.4,273660,1418.44,39717,86415.9,1177.77", "env/episode_return": "402.646,101.227,32.2858,5.77098,7.00912,329.474,359.736,87.4206,204.004,269.532,304.688,323.009,42.0899,115.604,109.718,216.14,110.832,36.4689,98.7561,481.501,549.501,10.5086,19.9194,26.8374,307.795,34.1353,381.381,518.793,546.6,582.475,209.888,237.026,382.413,464.575,29.9991,7.71232,15.623,18.1874,373.07,26.4441,33.8923,37.0493,24.6905,70.7374,104.222,25.7802,37.536,47.1117,3.51385,36.9103,241.349,304.481,331.793,401.37,437.9,124.96,373.99,452.445,506.274,79.4871,459.371,85.9734,4.41085,6.85131,16.8079,26.3574,32.6122,33.8999,26.9499,6.18486,91.5633,216.107,370.787,143.27,392.67,11.6466,22.8853,30.2575,37.4133,38.9494,28.8803,43.0782,83.6466,182.146,249.607,54.621,94.3503,191.952,248.024,5.36921,28.8405,211.009,5.66794,238.729,215.075,178.011,274.012,329.362,348.144,27.0577,27.0076,48.2649,42.6648,135.03,191.974,25.4896,43.0913,55.8328,557.789,125.894,72.4576,146.64,163.701,173.233,22.0055,78.0012,115.848,46.6384,182.976,197.9,97.3568,43.0657,137.988,195.109,30.8622,38.0675,39.5992,223.838,54.2816,79.8494,31.5016,193.814,249.604,165.481,480.858,5.13616,99.4122,38.3964,557.219,4.54282,97.0472,196.93,3.65646", "env/episode_length": "8277.05,2058.15,724.204,169.279,182.401,6366.43,6920.68,1751.78,3955,5189.14,5876.58,6209.11,985.743,2580.09,2279.02,4511.68,2350.26,859.012,2104.61,9463.45,10772,298.839,481.782,591.465,5975.35,875.676,7363.31,9916.7,10423,11110.2,4312.58,4790.22,7767.92,9349.8,652.222,271.438,417.19,486.162,7256.65,577.338,711.009,769.649,567.209,1467.75,2088.66,567.165,794.877,970.026,133.396,777.422,4788.31,5958.85,6487.02,7749.74,8425.25,2627.64,7241.46,8777.63,9786.68,1700.44,8793.69,1855.18,145.759,183.772,394.028,577.609,688.841,711.802,989.5,172.216,1827.65,4182.33,7088,3120.55,7569.29,337.172,587.42,684.33,805.002,844.322,642.865,909.608,1723.3,3599.81,4901.71,1208.16,3057.11,4030.91,4912.25,162.002,813.284,4239.13,166.506,4639.44,4372.37,3702.26,5473.14,6486.99,6803.42,580.915,591.345,994.091,926.428,2722.4,3798.94,547.831,884.843,1127.9,10636.4,2506.8,1606.2,3275.78,3799.77,4403.59,589.847,1590.7,2311.28,1087.35,3578.1,3848.99,2040.04,941.74,2851.05,4028.01,668.4,804.035,833.209,4328.87,1599.78,1657.99,700.83,3753.15,4790.86,3552.1,9198.64,157.76,2061.94,911.498,10575.2,161.013,1984.07,3902.41,140.919", "env/lifetime_max_tile": "13922.8,3282.28,1080.05,183.058,221.95,11040.8,12666.1,2417.49,6373.65,8664.7,10427.9,11900.6,1337.09,3941.85,3198.79,7532.48,3918.78,1245.74,3509.46,15226.7,16925.6,315.457,640.531,861.906,10409.1,1332.39,12705.8,16242.1,17846.4,18546.7,6984.7,7972.51,11879.5,14365.3,871.86,358.125,662.105,948.44,14460.9,788.005,1032.99,1206.98,790.8,2206.08,3415.2,698.444,1033.46,1321.04,111.892,1052.09,7664.2,9728.51,11084.3,13725.9,15701,4616.89,15364.1,16325.2,18096.1,2624.71,15505.9,3376.36,149.421,240.928,535.584,818.608,1030.85,1201.69,1095.83,184.061,2679.73,6806.54,13833.4,5705,15167.7,330.939,705.145,937.015,1157.82,1316.67,791.109,1240.33,2748.31,6736.53,9037.09,1920.89,4692.55,7418.77,9609.86,170.591,1012,7901.87,212.294,7613.3,8263.76,6007.99,9555.63,12470.8,14019.7,925.249,625.576,1115.18,1261.89,4204.19,6569.79,749.089,1207.62,1588.93,18775.1,3460.17,2345.91,6296.9,8030.39,9098.09,683.128,2248.07,3542.8,1742.63,5235.2,6168.61,2945.22,1481.57,4979.8,7551.8,898.18,1188.89,1363.58,7121.84,2240.38,2435,950.996,5865.64,7890.16,5332.32,15899.1,154.578,3443.34,1253.09,19343.9,129.975,3593.96,7923.14,122.363", "env/reached_16384": "0.377259,0.000155091,0,0,0,0.195118,0.258074,3.95617e-05,0.00526256,0.0505267,0.101017,0.132673,0,0,0.000283855,0.00824465,0.000817583,0,0,0.513521,0.619732,0,0,0,0.0985045,0,0.336332,0.56252,0.587537,0.644646,0.00817715,0.0247097,0.310151,0.471253,0,0,0,0,0.251023,0,0,0,0,0,0,0,0,0,0,0,0.0453763,0.126194,0.174289,0.275324,0.370636,0.00333747,0.205152,0.409878,0.533852,1.81232e-05,0.367233,7.83495e-05,0,0,0,0,0,0,0,0,2.27873e-05,0.0117207,0.214093,0.000433299,0.257713,0,0,0,0,0,0,0,0,0.00341586,0.0300131,0,0.000146243,0.010606,0.0415369,0,0,0.0101265,0,0.0221441,0.0240854,0.00697802,0.0852586,0.174698,0.213332,0,0,0,0,0.00023936,0.00534809,0,0,0,0.614996,0.00130451,0,0.00198355,0.00738519,0.0205205,0,0,0,0,0.000498308,0.0019859,0.000205115,0,0.000149506,0.00724918,0,0,0,0.0109997,0,3.98646e-05,0,0.0024362,0.0297688,0.00209817,0.395049,0,0.000139035,0,0.595424,0,7.39002e-05,0.00548378,0", "env/reached_32768": "0.0112214,0,0,0,0,0.000151064,0.00109649,0,0,0.000271473,0.00026045,0.00189962,0,0,0,0,0,0,0,0.0118018,0.0367486,0,0,0,0,0,0.00403301,0.0375718,0.0609172,0.0880152,0,0,0.00232063,0.0146985,0,0,0,0,0.00558938,0,0,0,0,0,0,0,0,0,0,0,0,0.000116987,0.00029827,0.00347816,0.00847796,0,0.00272841,0.015533,0.0336026,0,0.0161838,0,0,0,0,0,0,0,0,0,0,0,0.00119772,0,0.00619071,0,0,0,0,0,0,0,0,0,8.63734e-05,0,0,0,0,0,0,0,0,0,0,0,0,0.000167965,0.000298924,0,0,0,0,0,0,0,0,0,0.0950114,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0221579,0,0,0,0.0681455,0,0,0,0", "env/reached_65536": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "env/reached_131072": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "env/n": "10070,938.823,5513.68,9927.4,17386,101.762,10032,532.013,152.166,119.378,103.65,10002,1769.75,439.048,753.56,161.206,435.527,4005.21,1112.74,37.8419,10014,5530.67,3586.5,2956.5,10030,4440.77,68.836,56.6976,10030,10021,187.151,10077,63.4139,10001,3030.4,2293,1425,1222.71,10019,1139.33,971.444,10388,5540,1511.96,1061.04,960.182,747.364,10249,6331,494.421,236.935,191.747,10058,83.9885,10026,1391.08,302.647,90.093,10029,1986.69,10010,1437.11,13626,12701,456.882,320.647,286.882,9513,2201.69,6950,653.918,194.899,10019,736.681,10015,2691.75,1640,1386.38,1146,10053,1125.27,870.091,1214.58,349.242,256.781,1916.04,479.844,353.529,292.588,12107.8,4143.71,508.553,1172.52,131.04,268.384,590.092,405.8,352.227,10036,847.8,767.8,542.364,3570.86,541.281,401.193,908.857,582.286,474.5,10083,180.091,1481.68,352.625,301.958,268.917,3166.12,869.087,608.208,3205.35,347.977,10071,1776.69,3748.93,736.673,532.34,1177.7,1044.78,10151,224.36,2237.1,1210.86,6680.88,430.06,347.779,317.685,10019,5461.4,820.569,3951.46,10008,2769.25,1103.85,393.584,9069.33", "perf/rollout": "0.0846722,0.170413,0.207369,0.154661,0.287104,0.154645,0.155122,0.117922,0.117237,0.116793,0.116085,0.0295556,0.138218,0.13003,0.132976,0.130807,0.142438,0.127401,0.126938,0.114647,0.114762,0.125412,0.119647,0.116737,0.112586,0.197635,0.208783,0.208872,0.209404,0.119954,0.10663,0.105286,0.19804,0.19803,0.147763,0.275259,0.267993,0.268198,0.143265,0.104599,0.10456,0.104902,0.17389,0.167171,0.165817,0.331737,0.331963,0.331128,0.16192,0.104197,0.293393,0.291962,0.291451,0.13038,0.0650632,0.118364,0.11792,0.128989,0.128641,0.164572,0.120315,0.141858,0.229181,0.220875,0.0835839,0.083345,0.0834658,0.0832407,0.16119,0.11694,0.174505,0.172318,0.0572865,0.242683,0.108677,0.0936252,0.0848452,0.0819747,0.0779848,0.0586281,0.0837373,0.0840847,0.194079,0.191657,0.189358,0.179034,0.170949,0.1732,0.173469,0.203944,0.13611,0.134149,0.0618221,0.199148,0.103542,0.189036,0.190437,0.189795,0.0317538,0.0666502,0.0750586,0.0750193,0.173665,0.168869,0.170139,0.365594,0.363294,0.362931,0.366402,0.230602,0.0880227,0.0846938,0.0845168,0.0835796,0.243404,0.246996,0.245942,0.178048,0.239638,0.24115,0.132336,0.19163,0.19308,0.189282,0.0879308,0.0879992,0.0884047,0.200314,0.226774,0.0933286,0.281078,0.321692,0.315558,0.198745,0.0514574,0.111458,0.17125,0.249818,0.297137,0.0957742,0.243919,0.242231,0.121924", "perf/eval_gpu": "0.0407639,0.0508039,0.0480827,0.0540349,0.0825914,0.0969369,0.0969795,0.0836328,0.0837032,0.0836374,0.0835701,0.0212882,0.0511515,0.0503625,0.0891546,0.0893566,0.0832135,0.0579874,0.0582855,0.095267,0.0953649,0.032682,0.0282375,0.0258657,0.0451463,0.0517176,0.178959,0.178634,0.178806,0.0904895,0.0753954,0.0744236,0.0835033,0.0835281,0.0433472,0.183717,0.182817,0.182893,0.0838046,0.078183,0.078339,0.0785559,0.0567838,0.0535818,0.0539647,0.295588,0.295824,0.295829,0.0381264,0.078562,0.0569914,0.056992,0.0569847,0.0886835,0.0445005,0.0373963,0.0372981,0.0681007,0.0688682,0.0352288,0.0814542,0.0579221,0.0757691,0.0647407,0.0699063,0.0699432,0.0700805,0.0697099,0.0619864,0.0271828,0.079603,0.0795831,0.0229951,0.0534267,0.0686521,0.0461588,0.0380148,0.0342655,0.0323441,0.0250959,0.0244777,0.0242866,0.0609514,0.0609323,0.0600981,0.0487198,0.0512806,0.0485617,0.0482359,0.0338962,0.0424332,0.0475913,0.0505559,0.0742085,0.0392494,0.0574684,0.0556721,0.0553676,0.0090435,0.0403964,0.0196184,0.0199986,0.0603121,0.0594438,0.061825,0.327702,0.327311,0.328034,0.250918,0.207703,0.033591,0.0332547,0.03342,0.0333772,0.0888086,0.0881776,0.0884561,0.0667855,0.118329,0.119413,0.0497373,0.0551527,0.0582454,0.0603771,0.047184,0.0477998,0.0485196,0.135248,0.0872461,0.038555,0.0369775,0.194845,0.192669,0.134072,0.0365913,0.0532196,0.0610011,0.0722139,0.25652,0.0159129,0.0845112,0.0834269,0.0352017", "perf/eval_env": "0.0395292,0.115483,0.144751,0.0912506,0.194631,0.0566238,0.0570523,0.0303906,0.0296325,0.0292466,0.0286919,0.00729567,0.0801948,0.0726793,0.0412409,0.0387313,0.0568145,0.0591102,0.0583003,0.0187052,0.018677,0.0664253,0.0626589,0.0639801,0.0616124,0.131394,0.0279608,0.0283786,0.0286454,0.0289008,0.0292198,0.0288297,0.113704,0.113663,0.0964609,0.036284,0.0362159,0.0362693,0.0572361,0.0215732,0.0216882,0.0216981,0.103642,0.101352,0.0996467,0.0343094,0.0342571,0.0334339,0.113247,0.0204797,0.234806,0.233373,0.232886,0.039027,0.0193098,0.0732817,0.0728251,0.0586148,0.05762,0.125167,0.0374493,0.0719874,0.134407,0.139258,0.0108182,0.0106367,0.0105264,0.0106961,0.0890337,0.0852707,0.0916306,0.0894658,0.0311725,0.183121,0.0374325,0.0375757,0.0362564,0.0376233,0.0366765,0.0270694,0.0534612,0.0527032,0.125252,0.122848,0.121617,0.12268,0.111597,0.117131,0.117744,0.139461,0.0848332,0.0776398,0.0095243,0.12354,0.0590084,0.121628,0.123812,0.123711,0.0211081,0.0206092,0.0521738,0.0517535,0.103723,0.0996953,0.0986895,0.0346182,0.0326092,0.0315861,0.114675,0.0214322,0.0466593,0.0438824,0.043502,0.0425615,0.140789,0.144876,0.14363,0.0955984,0.119021,0.119346,0.0740937,0.127029,0.125049,0.120056,0.035978,0.0354646,0.0353698,0.0610593,0.128482,0.0492394,0.235116,0.124555,0.120577,0.0605858,0.0140598,0.0497024,0.106207,0.172002,0.039158,0.0760233,0.149731,0.149424,0.0793145", "perf/train_misc": "0.0353004,0.0176807,0.0287525,0.100231,0.0534304,0.0101056,0.0100854,0.00786731,0.00773536,0.00773199,0.00769576,0.00192819,0.0350907,0.0336322,0.00828556,0.00808352,0.00773819,0.0195474,0.0191551,0.0172516,0.0171766,0.0986899,0.0755608,0.0756521,0.0269773,0.0215208,0.0158844,0.0158811,0.015873,0.0191672,0.0149779,0.0150721,0.037775,0.0376812,0.0228767,0.00905396,0.00881931,0.00882478,0.00360957,0.0237595,0.023701,0.0235623,0.0374769,0.0365034,0.036508,0.0459424,0.0459944,0.0458353,0.241574,0.0149373,0.0789115,0.0789136,0.0788562,0.0120612,0.00600269,0.0403434,0.03977,0.00961517,0.00961517,0.0429217,0.0118028,0.0105711,0.0702283,0.0487731,0.00771115,0.00772653,0.00772687,0.00771683,0.0172449,0.173035,0.0110572,0.010823,0.00363622,0.0293527,0.00908717,0.06198,0.0514249,0.0513916,0.049607,0.0368681,0.0709921,0.0710203,0.0111549,0.0109983,0.0109921,0.0136998,0.0142911,0.0134241,0.0133083,0.0696137,0.025665,0.0123671,0.00329389,0.00967863,0.0207701,0.0229958,0.022992,0.0227041,0.00380006,0.0148201,0.163424,0.163421,0.0286355,0.0275833,0.0275775,0.062342,0.0622482,0.0622783,0.0186563,0.00283638,0.0229031,0.0223191,0.0223384,0.0222642,0.0156887,0.0152356,0.0152349,0.0115859,0.0237894,0.023764,0.0419833,0.020958,0.0216196,0.0216486,0.0236472,0.023673,0.0236797,0.00544238,0.0265009,0.0171472,0.0614645,0.0161567,0.015902,0.00936878,0.00717312,0.105067,0.0133426,0.02728,0.00777514,0.216056,0.013357,0.0132745,0.144979", "perf/train_forward": "0.499717,0.445198,0.399357,0.525801,0.331252,0.466129,0.465562,0.621417,0.611052,0.611025,0.608011,0.152682,0.535272,0.512975,0.545977,0.532477,0.629839,0.494586,0.48542,0.894431,0.892339,0.577606,0.446178,0.445388,0.500058,0.405128,1.26361,1.2636,1.26592,0.997551,0.546032,0.546872,0.807499,0.807019,0.458338,0.337534,0.329234,0.329213,0.50183,0.993949,0.994571,0.99424,0.421447,0.410873,0.410815,3.48667,3.48801,3.48393,2.02361,0.649022,0.654827,0.654823,0.6565,0.798757,0.399928,0.475247,0.469402,0.633588,0.633508,0.511929,0.442035,0.506807,0.491986,0.348416,0.668882,0.669317,0.669418,0.670417,0.444742,0.950783,0.550963,0.538942,0.179898,0.346688,0.45136,0.609702,0.510085,0.510146,0.491862,0.363915,0.576047,0.576021,0.442648,0.436546,0.436547,0.431063,0.449744,0.422681,0.418761,0.43983,0.509517,0.593807,0.988654,0.625476,0.529603,0.451451,0.451493,0.445916,0.0753388,0.523923,0.740709,0.739543,0.428764,0.413057,0.41305,5.54912,5.54531,5.54755,1.93756,1.0453,0.572782,0.558741,0.560038,0.558805,0.388674,0.377436,0.377424,0.44777,0.672473,0.671455,0.482935,0.418518,0.431638,0.432396,0.517915,0.51792,0.517935,0.603792,0.384884,0.554946,0.310157,0.716592,0.710049,0.611838,0.268586,0.686337,0.459115,0.406782,1.50826,0.730482,0.403293,0.401043,0.759447", "perf/train": "0.535017,0.462879,0.42811,0.626032,0.384682,0.476234,0.475647,0.629284,0.618787,0.618757,0.615707,0.15461,0.570362,0.546607,0.554262,0.54056,0.637578,0.514133,0.504575,0.911682,0.909516,0.676296,0.521738,0.52104,0.527035,0.426649,1.2795,1.27948,1.28179,1.01672,0.56101,0.561944,0.845274,0.8447,0.481214,0.346588,0.338053,0.338038,0.505439,1.01771,1.01827,1.0178,0.458924,0.447376,0.447323,3.53261,3.534,3.52977,2.26519,0.663959,0.733738,0.733737,0.735356,0.810818,0.405931,0.515591,0.509172,0.643203,0.643123,0.55485,0.453838,0.517378,0.562215,0.397189,0.676593,0.677044,0.677144,0.678134,0.461987,1.12382,0.56202,0.549765,0.183535,0.376041,0.460447,0.671682,0.56151,0.561538,0.541469,0.400783,0.647039,0.647041,0.453803,0.447545,0.447539,0.444763,0.464035,0.436105,0.43207,0.509444,0.535182,0.606174,0.991948,0.635154,0.550373,0.474447,0.474485,0.46862,0.0791388,0.538744,0.904133,0.902964,0.4574,0.440641,0.440628,5.61146,5.60756,5.60983,1.95622,1.04813,0.595685,0.58106,0.582377,0.581069,0.404363,0.392672,0.392658,0.459355,0.696263,0.695219,0.524918,0.439476,0.453258,0.454044,0.541562,0.541593,0.541615,0.609234,0.411385,0.572093,0.371621,0.732749,0.725951,0.621207,0.275759,0.791404,0.472458,0.434062,1.51604,0.946538,0.41665,0.414317,0.904426", "util/gpu_percent": "100,81.7347,82.5676,91.4,86,93.5097,100,96.1656,96.5096,96.3269,96.3376,96,89.3492,91.1129,94.578,94.9817,92.9186,96.9574,96.617,98.1353,100,93.5,93.6667,94,100,86.6279,100,100,100,100,93.9623,100,88.4385,100,86.8,91.1429,99,99,100,99.2222,99.4444,100,90.9583,91.1304,91.913,100,100,100,99,99.2632,76.3478,77.9121,19,96.042,100,95.1176,95.0654,93.3924,75,83.2553,100,94.5776,97.5,95,99.8824,100,100,100,88.4286,98.2,87.6415,87.0629,92,70.1594,98,96.625,97.375,97.625,97.875,98,96.7273,97.1818,80.875,80.8737,81.1667,76.0435,82.0469,80.8529,80.2647,76.25,91.1707,93.5395,99.2121,87.412,92.4138,84.4462,83.5385,83.3485,81,99.6,100,94.2727,86.2105,87.1228,86.5965,100,100,100,100,99.3861,96.75,96.8194,96.9583,96.875,80.9167,80.8261,81.625,92.2833,88.7907,100,94.1717,82.3393,83.3846,83.4151,96.9,97.6667,100,91.7558,82.4576,94.6577,70.9688,88,87.9118,92.4074,95,98.4,83.4306,75.4615,100,85.5,76.6139,77.5149,95.3333", "util/gpu_mem": "10.2225,8.76511,6.93316,6.4365,6.68076,16.6384,16.6384,15.9626,15.9626,15.9626,15.9626,15.9626,6.9983,6.9983,13.7724,13.7724,15.7021,9.44904,9.44904,13.3816,13.3816,6.00498,6.00498,6.00498,7.60081,6.65634,20.2535,20.2535,20.2535,13.2106,14.7739,14.7739,9.75844,9.75844,7.86949,5.88285,5.88285,5.88285,26.0994,11.9731,11.9731,11.9731,6.55863,6.55863,6.55863,19.1462,19.1462,19.1462,8.01605,11.338,7.096,7.096,7.096,13.7724,13.7724,6.80289,6.80289,28.3054,28.3054,6.07011,14.3505,10.133,5.72815,5.72815,13.7643,13.7643,13.7643,13.7643,8.94424,6.44464,11.395,11.395,11.395,6.07011,11.5985,6.24924,6.24924,6.24924,6.24924,6.24924,5.99683,5.99683,8.65113,8.65113,8.65113,22.3536,22.3536,22.3536,22.3536,7.55196,8.2196,28.2728,22.7531,28.1018,23.8599,8.03233,8.03233,8.03233,8.03233,9.14779,5.89099,5.89099,6.9983,6.9983,6.9983,14.204,14.204,14.204,24.2838,63.086,6.96573,6.96573,6.96573,6.96573,23.6889,23.6889,23.6889,9.07451,12.0789,12.0789,8.69998,7.86949,7.86949,7.86949,8.63484,8.63484,8.63484,22.1994,6.81103,10.2062,6.05383,31.3831,31.2898,13.7724,14.5215,7.07972,23.868,6.64819,41.5448,5.49203,6.72147,6.72147,6.25738", "util/vram_used_gb": "1.99109,1.64148,1.20203,1.08289,1.14148,3.53015,3.53015,3.36804,3.36804,3.36804,3.36804,3.36804,1.21765,1.21765,2.84265,2.84265,3.30554,1.80554,1.80554,2.7489,2.7489,0.97937,0.97937,0.97937,1.36218,1.13562,4.39734,4.39734,4.39734,2.70789,3.08289,3.08289,1.87976,1.87976,1.42664,0.950073,0.950073,0.950073,5.79968,2.41101,2.41101,2.41101,1.11218,1.11218,1.11218,4.13171,4.13171,4.13171,1.46179,2.25867,1.24109,1.24109,1.24109,2.84265,2.84265,1.17078,1.17078,6.32886,6.32886,0.994995,2.98132,1.9696,0.912964,0.912964,2.8407,2.8407,2.8407,2.8407,1.68445,1.08484,2.27234,2.27234,2.27234,0.994995,2.32117,1.03796,1.03796,1.03796,1.03796,1.03796,0.977417,0.977417,1.61414,1.61414,1.61414,4.90112,4.90112,4.90112,4.90112,1.35046,1.51062,6.32104,4.99695,6.28003,5.26245,1.4657,1.4657,1.4657,1.4657,1.73328,0.952026,0.952026,1.21765,1.21765,1.21765,2.94617,2.94617,2.94617,5.36414,14.6721,1.20984,1.20984,1.20984,1.20984,5.22144,5.22144,5.22144,1.7157,2.4364,2.4364,1.62585,1.42664,1.42664,1.42664,1.61023,1.61023,1.61023,4.86414,1.17273,1.98718,0.991089,7.06714,7.04477,2.84265,3.02234,1.23718,5.2644,1.13367,9.50476,0.856323,1.15125,1.15125,1.03992", "util/vram_total_gb": "23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272", "util/cpu_mem_gb": "1.10684,1.06996,1.06645,1.08924,1.11383,1.06979,1.06979,1.06741,1.06742,1.0679,1.06795,1.06839,1.07956,1.07956,1.0741,1.0741,1.06707,1.07884,1.07884,1.0663,1.0673,1.09549,1.09549,1.09549,1.08418,1.08403,1.07989,1.08076,1.08113,1.06443,1.08269,1.08269,1.05475,1.0548,1.06438,1.13449,1.13449,1.13449,1.0684,1.1604,1.1604,1.1604,1.07223,1.07223,1.07223,1.08619,1.08619,1.08619,1.16,1.10545,1.06541,1.06541,1.06541,1.07785,1.07805,1.09141,1.0919,0.986878,0.987316,1.06826,1.06586,1.09364,1.1138,1.1138,1.18553,1.18553,1.18553,1.18553,1.0669,1.10809,1.05873,1.059,1.05949,1.06891,1.07188,1.07915,1.07915,1.07915,1.07915,1.07915,1.08913,1.08913,1.0715,1.0715,1.0715,0.987576,0.987576,0.987576,0.987576,1.08431,1.08207,1.00795,1.07935,0.978641,1.00097,1.0761,1.0761,1.0761,1.0761,1.18618,1.08788,1.08788,1.08279,1.08279,1.08279,1.13044,1.13044,1.13044,1.06096,0.996548,1.08967,1.08967,1.08967,1.08967,0.986729,0.986729,0.986729,1.0894,1.06201,1.06201,1.07793,1.06465,1.06465,1.06465,1.10719,1.10719,1.10719,1.07368,1.06809,1.07335,1.06573,0.988876,0.988876,1.07633,1.06995,1.08346,0.97507,1.07043,1.07797,1.08408,1.06093,1.06093,1.08551", "wandb": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "slowly": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "save_frames": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "fps": "15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15", "rank": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "world_size": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "gpu_id": "3,3,4,4,4,5,5,3,3,3,3,3,5,5,5,5,1,4,4,1,1,3,3,3,1,2,4,4,4,4,3,3,5,5,2,4,4,4,5,5,5,5,3,3,3,4,4,4,5,2,2,2,2,2,2,1,1,0,0,2,4,1,4,4,2,2,2,2,1,4,3,3,3,1,3,2,2,2,2,2,2,2,2,2,2,0,0,0,0,4,5,0,5,0,0,1,1,1,1,3,5,5,1,1,1,4,4,4,3,0,5,5,5,5,0,0,0,1,2,2,5,1,1,1,5,5,5,4,4,5,5,0,0,5,1,4,0,2,3,4,4,4,4", "profile": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "checkpoint_interval": "200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200", "eval_episodes": "10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000", "cudagraphs": "10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10", "seed": "73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73", "reset_state": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "vec/total_agents": "16384,8192,8192,16384,16384,16384,16384,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,16384,16384,8192,8192,8192,8192,4096,16384,16384,16384,16384,16384,16384,16384,16384,8192,512,512,512,8192,8192,8192,8192,8192,8192,8192,16384,16384,16384,16384,8192,16384,16384,16384,8192,8192,8192,8192,8192,8192,8192,16384,4096,8192,8192,4096,4096,4096,4096,8192,16384,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,4096,4096,4096,4096,4096,4096,4096,16384,8192,8192,4096,8192,8192,8192,8192,8192,8192,4096,16384,16384,8192,8192,8192,8192,8192,8192,16384,8192,4096,4096,4096,4096,8192,8192,8192,4096,16384,16384,16384,8192,8192,8192,8192,8192,8192,8192,8192,8192,16384,16384,16384,8192,16384,16384,8192,8192,16384,16384,4096,4096,16384", "vec/num_buffers": "6.16023,2.13915,4.99965,6.50643,5.34169,2.25761,2.25761,4.62583,4.62583,4.62583,4.62583,4.62583,3.30056,3.30056,3.46385,3.46385,2.05612,6.2541,6.2541,3.41265,3.41265,7.94172,7.94172,7.94172,3.68695,3.00441,4.69838,4.69838,4.69838,2.85992,4.79993,4.79993,1.57451,1.57451,3.74532,5.43148,5.43148,5.43148,2.65663,6.28947,6.28947,6.28947,5.34671,5.34671,5.34671,4.91425,4.91425,4.91425,5.22922,6.44509,1,1,1,3.84894,3.84894,5.00544,5.00544,2.8239,2.8239,2.31587,3.86297,4.71778,6.19097,6.19097,6.71226,6.71226,6.71226,6.71226,3.63998,5.13772,2.92963,2.92963,2.92963,2.00744,3.39392,6.76068,6.76068,6.76068,6.76068,6.76068,5.93914,5.93914,2.82751,2.82751,2.82751,2.4639,2.4639,2.4639,2.4639,7.26216,4.40972,4.07305,4.96056,1.64291,3.32187,3.1997,3.1997,3.1997,3.1997,6.63699,5.65331,5.65331,3.69807,3.69807,3.69807,4.3845,4.3845,4.3845,1.70725,3.67587,4.77867,4.77867,4.77867,4.77867,3.92409,3.92409,3.92409,4.65978,2.83395,2.83395,6.95085,3.7056,3.7056,3.7056,5.82745,5.82745,5.82745,3.76145,3.6575,4.00161,3.79901,2.99163,2.99163,3.17244,4.49185,6.66776,2.23407,2.9853,3.13621,6.40333,2.52385,2.52385,5.58664", "vec/num_threads": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "vec/seed": "73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73", "env/scaffolding_ratio": "0.573586,0.592592,0.511024,0.615427,0.666635,0.483101,0.483101,0.519637,0.519637,0.519637,0.519637,0.519637,0.558124,0.558124,0.396364,0.396364,0.511901,0.252839,0.252839,0.435639,0.435639,0.518119,0.518119,0.518119,0.465644,0.432255,0.608862,0.608862,0.608862,0.588542,0.270403,0.270403,0.653988,0.653988,0.585596,0.571243,0.571243,0.571243,0.648886,0.387054,0.387054,0.387054,0.557532,0.557532,0.557532,0.455412,0.455412,0.455412,0.8,0.698557,0.560858,0.560858,0.560858,0.529765,0.529765,0.473759,0.473759,0.384917,0.384917,0.29359,0.509485,0.487448,0.718304,0.718304,0.705797,0.705797,0.705797,0.705797,0.446609,0.650323,0.583203,0.583203,0.583203,0.370346,0.479671,0.542888,0.542888,0.542888,0.542888,0.542888,0.693639,0.693639,0.507118,0.507118,0.507118,0.434599,0.434599,0.434599,0.434599,0.71432,0.333897,0.244075,0.2882,0.532059,0.356459,0.403812,0.403812,0.403812,0.403812,0.583412,0.76969,0.76969,0.528187,0.528187,0.528187,0.571521,0.571521,0.571521,0.473548,0.716961,0.368788,0.368788,0.368788,0.368788,0.712278,0.712278,0.712278,0.512994,0.513998,0.513998,0.581524,0.428337,0.428337,0.428337,0.560674,0.560674,0.560674,0.48661,0.457131,0.477781,0.461504,0.246593,0.246593,0.373481,0.484436,0.605973,0.526796,0.426359,0.356634,0.799924,0.531977,0.531977,0.572942", "policy/hidden_size": "256,256,256,128,128,512,512,512,512,512,512,512,256,256,512,512,512,256,256,1024,1024,256,256,256,256,128,1024,1024,1024,1024,512,512,512,512,256,64,64,64,512,512,512,512,256,256,256,1024,1024,1024,128,512,256,256,256,512,512,256,256,512,512,256,512,256,128,128,512,512,512,512,256,128,512,512,512,256,512,256,256,256,256,256,256,256,256,256,256,256,256,256,256,128,256,256,1024,512,256,256,256,256,256,256,256,256,256,256,256,1024,1024,1024,1024,1024,256,256,256,256,256,256,256,256,512,512,256,256,256,256,256,256,256,512,256,256,128,512,512,512,512,256,512,256,1024,64,512,512,128", "policy/num_layers": "4.23884,4.27513,2.63367,7.15641,7.4601,5.12216,5.12216,5.1368,5.1368,5.1368,5.1368,5.1368,4.33045,4.33045,4.37166,4.37166,5.38345,4.38242,4.38242,3.00581,3.00581,2.74729,2.74729,2.74729,5.21261,4.56724,3.28121,3.28121,3.28121,3.19502,4.05477,4.05477,4.2605,4.2605,3.49346,7.84948,7.84948,7.84948,5.20598,5.26292,5.26292,5.26292,3.27584,3.27584,3.27584,5.5926,5.5926,5.5926,6.57972,5.16808,4.64797,4.64797,4.64797,4.42859,4.42859,3.10491,3.10491,4.07473,4.07473,3.77341,4.56613,5.14953,5.66327,5.66327,7.21482,7.21482,7.21482,7.21482,4.08861,6.96909,3.72524,3.72524,3.72524,3.49816,3.21207,4.31523,4.31523,4.31523,4.31523,4.31523,3.62177,3.62177,4.11101,4.11101,4.11101,3.06084,3.06084,3.06084,3.06084,4.80578,3.70691,4.46766,4.79205,4.72445,4.31049,3.49323,3.49323,3.49323,3.49323,6.00767,3.47013,3.47013,4.79225,4.79225,4.79225,6.69609,6.69609,6.69609,4.34815,5.07013,4.7806,4.7806,4.7806,4.7806,4.48157,4.48157,4.48157,4.41843,3.49817,3.49817,3.92445,3.9718,3.9718,3.9718,6.52906,6.52906,6.52906,4.82719,4.74564,5.48811,3.23104,5.15537,5.15537,4.62312,4.60361,5.8982,2.59743,4.29899,4.6366,5.77518,2.90252,2.90252,7.19", "policy/expansion_factor": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "train/gpus": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "train/seed": "42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42", "train/total_timesteps": "1168.28,1225.35,677.339,72.0434,37.1682,868.007,868.007,656.83,656.83,656.83,656.83,656.83,522.77,522.77,913.621,913.621,1078.86,541.169,541.169,1472.47,1472.47,72.6657,72.6657,72.6657,627.774,592.339,1584.08,1584.08,1584.08,1966.71,446.825,446.825,1027.54,1027.54,369.327,30,30,30,1013.28,38.8532,38.8532,38.8532,386.516,386.516,386.516,47.6036,47.6036,47.6036,30,79.9567,770.094,770.094,770.094,1100.96,1100.96,1923.91,1923.91,1443.54,1443.54,786.867,1509.66,1058.22,36.4756,36.4756,36.4896,36.4896,36.4896,36.4896,510.242,58.0721,999.793,999.793,999.793,866.038,1149.34,58.3804,58.3804,58.3804,58.3804,58.3804,93.1853,93.1853,800.343,800.343,800.343,571.561,571.561,571.561,571.561,81.2295,514.973,790.614,34.6101,1050.73,1278.89,822.083,822.083,822.083,822.083,40.7382,87.2641,87.2641,594.776,594.776,594.776,58.9043,58.9043,58.9043,1883.86,1270.91,452.758,452.758,452.758,452.758,343.163,343.163,343.163,744.931,363.171,363.171,1443.9,661.599,661.599,661.599,59.7949,59.7949,59.7949,1080.05,802.411,695.701,721.9,560.276,560.276,679.781,1472.85,43.5769,1533.14,616.682,2012.24,35.1736,1053.26,1053.26,35.8881", "train/learning_rate": "0.00186521,0.00239806,0.0014572,0.00220204,0.00253487,0.00165431,0.00165431,0.00188481,0.00188481,0.00188481,0.00188481,0.00188481,0.00183379,0.00183379,0.00208823,0.00208823,0.00241956,0.00185445,0.00185445,0.00230856,0.00230856,0.003,0.003,0.003,0.00228686,0.00255642,0.00193789,0.00193789,0.00193789,0.00198773,0.00147657,0.00147657,0.00215459,0.00215459,0.00255878,0.0015234,0.0015234,0.0015234,0.00203065,0.003,0.003,0.003,0.00180867,0.00180867,0.00180867,0.003,0.003,0.003,0.00271607,0.003,0.00151291,0.00151291,0.00151291,0.00208837,0.00208837,0.00201154,0.00201154,0.00224872,0.00224872,0.00239112,0.00177129,0.00202186,0.00272315,0.00272315,0.00264268,0.00264268,0.00264268,0.00264268,0.00211075,0.00245239,0.00202782,0.00202782,0.00202782,0.00177591,0.00187388,0.003,0.003,0.003,0.003,0.003,0.00298683,0.00298683,0.00207672,0.00207672,0.00207672,0.00151217,0.00151217,0.00151217,0.00151217,0.00293938,0.00146392,0.00162795,0.003,0.00145884,0.00152124,0.00201988,0.00201988,0.00201988,0.00201988,0.003,0.00278553,0.00278553,0.00138683,0.00138683,0.00138683,0.003,0.003,0.003,0.00175847,0.00190952,0.00160272,0.00160272,0.00160272,0.00160272,0.00189383,0.00189383,0.00189383,0.00151738,0.00207857,0.00207857,0.00255927,0.00195151,0.00195151,0.00195151,0.003,0.003,0.003,0.00148966,0.00240763,0.00166059,0.00153822,0.002003,0.002003,0.002027,0.00215887,0.00266306,0.00225462,0.00225125,0.00189378,0.00252477,0.00224136,0.00224136,0.00265951", "train/anneal_lr": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "train/min_lr_ratio": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "train/gamma": "0.998789,0.998646,0.995813,0.997951,0.997706,0.998239,0.998239,0.99763,0.99763,0.99763,0.99763,0.99763,0.998286,0.998286,0.998757,0.998757,0.998546,0.998473,0.998473,0.998507,0.998507,0.963858,0.963858,0.963858,0.997524,0.997673,0.998447,0.998447,0.998447,0.997423,0.998118,0.998118,0.998401,0.998401,0.990445,0.999626,0.999626,0.999626,0.998935,0.98261,0.98261,0.98261,0.998448,0.998448,0.998448,0.989638,0.989638,0.989638,0.998523,0.990247,0.99837,0.99837,0.99837,0.998593,0.998593,0.997826,0.997826,0.99816,0.99816,0.9964,0.998157,0.998934,0.999044,0.999044,0.983226,0.983226,0.983226,0.983226,0.998323,0.998514,0.997583,0.997583,0.997583,0.998806,0.998288,0.994511,0.994511,0.994511,0.994511,0.994511,0.993271,0.993271,0.998331,0.998331,0.998331,0.998535,0.998535,0.998535,0.998535,0.998596,0.997601,0.998447,0.995807,0.997654,0.998208,0.998866,0.998866,0.998866,0.998866,0.981821,0.988986,0.988986,0.998137,0.998137,0.998137,0.984315,0.984315,0.984315,0.998038,0.998551,0.999349,0.999349,0.999349,0.999349,0.998045,0.998045,0.998045,0.998421,0.996863,0.996863,0.998939,0.999313,0.999313,0.999313,0.995991,0.995991,0.995991,0.998295,0.997879,0.997225,0.998195,0.996172,0.996172,0.998788,0.997774,0.994539,0.99816,0.997945,0.996984,0.99877,0.998878,0.998878,0.994334", "train/gae_lambda": "0.408564,0.644731,0.2,0.753377,0.344005,0.592641,0.592641,0.517693,0.517693,0.517693,0.517693,0.517693,0.532016,0.532016,0.2,0.2,0.676426,0.704621,0.704621,0.2,0.2,0.410836,0.410836,0.410836,0.2,0.695792,0.640499,0.640499,0.640499,0.716881,0.578668,0.578668,0.2,0.2,0.550767,0.666833,0.666833,0.666833,0.805292,0.2,0.2,0.2,0.358455,0.358455,0.358455,0.2,0.2,0.2,0.583742,0.2,0.539264,0.539264,0.539264,0.711157,0.711157,0.666766,0.666766,0.696214,0.696214,0.579365,0.66966,0.743162,0.643354,0.643354,0.713199,0.713199,0.713199,0.713199,0.2,0.540693,0.619264,0.619264,0.619264,0.782553,0.577081,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.623525,0.623525,0.623525,0.623525,0.762231,0.2,0.812934,0.351184,0.744615,0.616577,0.692979,0.692979,0.692979,0.692979,0.26324,0.2,0.2,0.772795,0.772795,0.772795,0.656072,0.656072,0.656072,0.492207,0.2,0.2,0.2,0.2,0.2,0.494756,0.494756,0.494756,0.714201,0.85328,0.85328,0.509813,0.2,0.2,0.2,0.2,0.2,0.2,0.645431,0.48825,0.679355,0.697523,0.777362,0.777362,0.752247,0.620139,0.851016,0.2,0.46081,0.487498,0.798388,0.642264,0.642264,0.881184", "train/replay_ratio": "2.29085,2.04474,1.51819,0.708694,0.25,1.32606,1.32606,1.81095,1.81095,1.81095,1.81095,1.81095,2.08103,2.08103,1.93647,1.93647,1.78124,1.72233,1.72233,2.35307,2.35307,1.54151,1.54151,1.54151,2.21946,2.46254,1.99836,1.99836,1.99836,2.61912,1.92167,1.92167,2.70519,2.70519,2.496,3.13268,3.13268,3.13268,1.61929,2.67527,2.67527,2.67527,1.17878,1.17878,1.17878,2.93516,2.93516,2.93516,0.992584,1.80924,2.61012,2.61012,2.61012,2.84668,2.84668,1.65346,1.65346,2.2381,2.2381,2.52563,1.6022,1.84906,0.25,0.25,2.61767,2.61767,2.61767,2.61767,1.6439,1.12391,1.63627,1.63627,1.63627,1.18947,2.10196,1.93276,1.93276,1.93276,1.93276,1.93276,2.17882,2.17882,2.01219,2.01219,2.01219,2.5484,2.5484,2.5484,2.5484,1.3852,1.96395,2.17931,3.60828,2.2249,3.3122,1.81887,1.81887,1.81887,1.81887,2.63893,2.80901,2.80901,1.35525,1.35525,1.35525,3.33211,3.33211,3.33211,2.22654,2.00606,3.04786,3.04786,3.04786,3.04786,1.06371,1.06371,1.06371,1.43937,1.54586,1.54586,1.67399,1.76974,1.76974,1.76974,1.94238,1.94238,1.94238,1.52613,1.05216,2.82825,1.55277,1.01824,1.01824,1.44488,1.93833,1.16014,1.79684,1.11287,1.87196,2.0567,1.0572,1.0572,1.07158", "train/clip_coef": "0.01,0.11104,0.01,0.506174,0.531516,0.01,0.01,0.224262,0.224262,0.224262,0.224262,0.224262,0.234635,0.234635,0.0121648,0.0121648,0.188368,0.10957,0.10957,0.01,0.01,0.429136,0.429136,0.429136,0.0321217,0.01,0.01,0.01,0.01,0.0247072,0.01,0.01,0.01,0.01,0.01,0.769506,0.769506,0.769506,0.175129,0.311953,0.311953,0.311953,0.01,0.01,0.01,0.124087,0.124087,0.124087,0.509202,0.372405,0.01,0.01,0.01,0.01,0.01,0.0386475,0.0386475,0.01,0.01,0.01,0.192011,0.01,0.582912,0.582912,0.343649,0.343649,0.343649,0.343649,0.187239,0.553597,0.286803,0.286803,0.286803,0.01,0.06028,0.474917,0.474917,0.474917,0.474917,0.474917,0.420081,0.420081,0.0930173,0.0930173,0.0930173,0.0691551,0.0691551,0.0691551,0.0691551,0.596092,0.179192,0.01,0.392357,0.01,0.01,0.01,0.01,0.01,0.01,0.639026,0.365786,0.365786,0.01,0.01,0.01,0.228233,0.228233,0.228233,0.0455916,0.172545,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.548698,0.548698,0.548698,0.383518,0.01,0.01,0.0712029,0.01,0.01,0.01,0.0526584,0.473524,0.01,0.01,0.01,0.647145,0.165974,0.165974,0.683836", "train/vf_coef": "0.221585,0.450165,1.17745,3.65045,4.78441,1.08381,1.08381,0.863669,0.863669,0.863669,0.863669,0.863669,0.651264,0.651264,1.10343,1.10343,0.604886,0.563431,0.563431,0.20233,0.20233,4.04218,4.04218,4.04218,0.398428,0.948753,0.1,0.1,0.1,0.1,0.949914,0.949914,0.1,0.1,0.465982,1.00869,1.00869,1.00869,0.641843,5,5,5,1.18665,1.18665,1.18665,4.73752,4.73752,4.73752,3.72719,4.9073,0.742809,0.742809,0.742809,0.1,0.1,0.12327,0.12327,0.1,0.1,0.687973,0.1,0.926637,4.587,4.587,4.89074,4.89074,4.89074,4.89074,0.903336,4.08371,0.707529,0.707529,0.707529,0.479744,0.1,5,5,5,5,5,5,5,0.922335,0.922335,0.922335,0.1,0.1,0.1,0.1,5,0.562649,0.110847,5,0.1,0.1,0.1,0.1,0.1,0.1,5,5,5,0.591269,0.591269,0.591269,4.40785,4.40785,4.40785,0.1,0.914472,0.885744,0.885744,0.885744,0.885744,0.515861,0.515861,0.515861,0.1,0.515459,0.515459,0.634075,0.860551,0.860551,0.860551,5,5,5,0.614176,1.0782,0.590292,0.332921,0.700498,0.700498,0.1,0.399201,2.87036,0.642885,0.60184,0.1,5,0.664717,0.664717,3.57363", "train/vf_clip_coef": "0.01,0.01,0.340699,3.37236,2.81198,1.23558,1.23558,0.01,0.01,0.01,0.01,0.01,0.860068,0.860068,0.01,0.01,0.231018,0.01,0.01,0.0974943,0.0974943,1.85602,1.85602,1.85602,0.01,0.01,0.01,0.01,0.01,0.256042,0.073821,0.073821,0.01,0.01,0.01,4.99798,4.99798,4.99798,0.01,2.92709,2.92709,2.92709,0.159045,0.159045,0.159045,2.2966,2.2966,2.2966,3.38181,2.0665,0.01,0.01,0.01,0.01,0.01,0.154331,0.154331,0.01,0.01,0.369602,0.01,0.01,3.04306,3.04306,1.15128,1.15128,1.15128,1.15128,0.01,2.95906,0.01,0.01,0.01,0.01,0.01,2.93253,2.93253,2.93253,2.93253,2.93253,2.15968,2.15968,0.01,0.01,0.01,0.153618,0.153618,0.153618,0.153618,3.28048,0.01,0.01,2.08453,0.01,0.01,0.01,0.01,0.01,0.01,3.17953,2.6429,2.6429,0.01,0.01,0.01,1.37636,1.37636,1.37636,0.01,0.01,0.01,0.01,0.01,0.01,1.10251,1.10251,1.10251,0.244093,0.01,0.01,0.778775,0.01,0.01,0.01,2.15321,2.15321,2.15321,0.0263951,1.14748,0.01,0.01,0.01,0.01,0.01,0.01,4.4746,0.398757,0.01,0.286554,1.83175,0.01,0.01,2.89002", "train/max_grad_norm": "1.3088,0.68508,0.638195,0.621249,1.08518,1.02229,1.02229,1.0287,1.0287,1.0287,1.0287,1.0287,0.884571,0.884571,1.23694,1.23694,1.09193,1.03855,1.03855,0.810332,0.810332,0.1,0.1,0.1,1.15444,1.63007,0.822588,0.822588,0.822588,1.12276,1.199,1.199,0.93411,0.93411,0.992447,0.489883,0.489883,0.489883,0.602836,0.1,0.1,0.1,1.08925,1.08925,1.08925,0.1,0.1,0.1,0.293467,0.1,0.901072,0.901072,0.901072,0.865394,0.865394,1.36849,1.36849,1.14364,1.14364,1.33789,1.09226,1.09524,0.660985,0.660985,0.1,0.1,0.1,0.1,0.841184,0.679297,1.03199,1.03199,1.03199,1.1421,0.732671,0.137017,0.137017,0.137017,0.137017,0.137017,0.1,0.1,1.20657,1.20657,1.20657,1.08128,1.08128,1.08128,1.08128,0.681901,1.23639,1.14483,0.1,1.26712,0.957438,1.19004,1.19004,1.19004,1.19004,0.1,0.149986,0.149986,1.05902,1.05902,1.05902,0.1,0.1,0.1,0.595841,0.735692,1.16033,1.16033,1.16033,1.16033,1.33396,1.33396,1.33396,1.22713,1.3412,1.3412,1.16869,0.857069,0.857069,0.857069,0.228648,0.228648,0.228648,1.16316,1.19869,1.24485,1.23535,1.04799,1.04799,1.12203,1.12794,0.281741,1.02042,1.21388,0.325746,0.259603,0.94958,0.94958,0.772789", "train/ent_coef": "0.0563344,0.0540499,0.0334563,0.00141389,0.0136321,0.0216601,0.0216601,0.0380299,0.0380299,0.0380299,0.0380299,0.0380299,0.0411098,0.0411098,0.0190479,0.0190479,0.0188201,0.010166,0.010166,0.026401,0.026401,2.6449e-05,2.6449e-05,2.6449e-05,0.036105,0.00650164,0.0141757,0.0141757,0.0141757,0.0262458,0.0483764,0.0483764,0.0352672,0.0352672,0.0177311,0.0434001,0.0434001,0.0434001,0.018989,0.00352364,0.00352364,0.00352364,0.0135653,0.0135653,0.0135653,0.0363582,0.0363582,0.0363582,0.00253225,0.000382526,0.0197696,0.0197696,0.0197696,0.015709,0.015709,0.0257339,0.0257339,0.0208185,0.0208185,0.00698193,0.0171791,0.0149062,0.000313808,0.000313808,0.0023469,0.0023469,0.0023469,0.0023469,0.0108534,0.000254449,0.00664504,0.00664504,0.00664504,0.0132113,0.0165702,3.99017e-05,3.99017e-05,3.99017e-05,3.99017e-05,3.99017e-05,0.000476199,0.000476199,0.053104,0.053104,0.053104,0.023287,0.023287,0.023287,0.023287,0.00666716,0.0150373,0.00334561,0.00207698,0.00449647,0.0197022,0.0124428,0.0124428,0.0124428,0.0124428,0.0113626,0.00498108,0.00498108,0.00856186,0.00856186,0.00856186,0.00459514,0.00459514,0.00459514,0.0207937,0.0481535,0.0175325,0.0175325,0.0175325,0.0175325,0.00693511,0.00693511,0.00693511,0.0381635,0.00393848,0.00393848,0.0299107,0.0707857,0.0707857,0.0707857,0.00119628,0.00119628,0.00119628,0.026375,0.0123578,0.0134351,0.0155545,0.0121647,0.0121647,0.00337537,0.0152927,0.000375812,0.00604347,0.0135352,0.0160003,0.00176965,0.0298507,0.0298507,0.000214854", "train/beta1": "0.98632,0.98586,0.98278,0.992126,0.969476,0.991859,0.991859,0.987087,0.987087,0.987087,0.987087,0.987087,0.986181,0.986181,0.991364,0.991364,0.973746,0.995688,0.995688,0.971985,0.971985,0.975065,0.975065,0.975065,0.989776,0.990567,0.975985,0.975985,0.975985,0.97806,0.997532,0.997532,0.987619,0.987619,0.978818,0.940025,0.940025,0.940025,0.966641,0.862055,0.862055,0.862055,0.990754,0.990754,0.990754,0.854784,0.854784,0.854784,0.990834,0.79764,0.987171,0.987171,0.987171,0.987159,0.987159,0.98957,0.98957,0.981226,0.981226,0.983949,0.987624,0.989323,0.996677,0.996677,0.91552,0.91552,0.91552,0.91552,0.986908,0.982339,0.973661,0.973661,0.973661,0.9897,0.990596,0.886734,0.886734,0.886734,0.886734,0.886734,0.851139,0.851139,0.989808,0.989808,0.989808,0.993008,0.993008,0.993008,0.993008,0.987648,0.991508,0.99205,0.737299,0.979568,0.988395,0.99309,0.99309,0.99309,0.99309,0.90417,0.951839,0.951839,0.987315,0.987315,0.987315,0.825804,0.825804,0.825804,0.986549,0.989122,0.991971,0.991971,0.991971,0.991971,0.990354,0.990354,0.990354,0.989954,0.990055,0.990055,0.987267,0.995815,0.995815,0.995815,0.95523,0.95523,0.95523,0.979164,0.991128,0.976906,0.99024,0.975206,0.975206,0.990224,0.984884,0.993302,0.98791,0.979378,0.980643,0.992078,0.984407,0.984407,0.997557", "train/beta2": "0.990783,0.99821,0.99027,0.999964,0.999934,0.998073,0.998073,0.952857,0.952857,0.952857,0.952857,0.952857,0.962193,0.962193,0.999794,0.999794,0.997688,0.998504,0.998504,0.994187,0.994187,0.999778,0.999778,0.999778,0.99854,0.999525,0.996358,0.996358,0.996358,0.947415,0.998511,0.998511,0.998363,0.998363,0.998927,0.999901,0.999901,0.999901,0.998919,0.99999,0.99999,0.99999,0.999638,0.999638,0.999638,0.999959,0.999959,0.999959,0.999989,0.999983,0.992024,0.992024,0.992024,0.985383,0.985383,0.99967,0.99967,0.994178,0.994178,0.999447,0.990704,0.998328,0.99999,0.99999,0.99999,0.99999,0.99999,0.99999,0.998991,0.999966,0.998524,0.998524,0.998524,0.999848,0.998887,0.999926,0.999926,0.999926,0.999926,0.999926,0.99999,0.99999,0.996412,0.996412,0.996412,0.998397,0.998397,0.998397,0.998397,0.99993,0.969147,0.999805,0.99999,0.999864,0.998214,0.999766,0.999766,0.999766,0.999766,0.999915,0.99999,0.99999,0.999789,0.999789,0.999789,0.999982,0.999982,0.999982,0.996869,0.999461,0.995484,0.995484,0.995484,0.995484,0.999826,0.999826,0.999826,0.997987,0.996949,0.996949,0.969965,0.993075,0.993075,0.993075,0.999973,0.999973,0.999973,0.986849,0.999669,0.99882,0.999968,0.998804,0.998804,0.999204,0.997377,0.999942,0.998477,0.999277,0.977736,0.999978,0.99157,0.99157,0.999978", "train/eps": "0.0001,6.45663e-07,5.00265e-07,1.53512e-05,0.0001,7.56445e-05,7.56445e-05,8.33236e-06,8.33236e-06,8.33236e-06,8.33236e-06,8.33236e-06,8.89407e-08,8.89407e-08,1.55187e-05,1.55187e-05,1.68729e-07,4.08314e-07,4.08314e-07,0.0001,0.0001,0.0001,0.0001,0.0001,7.68331e-07,1.77337e-05,3.88686e-06,3.88686e-06,3.88686e-06,0.0001,6.12065e-08,6.12065e-08,2.03857e-08,2.03857e-08,1.94886e-07,1.16559e-13,1.16559e-13,1.16559e-13,2.5003e-07,0.0001,0.0001,0.0001,2.28235e-06,2.28235e-06,2.28235e-06,0.0001,0.0001,0.0001,0.0001,2.58149e-05,8.21123e-08,8.21123e-08,8.21123e-08,3.04691e-06,3.04691e-06,0.0001,0.0001,1.82223e-06,1.82223e-06,4.51391e-06,1.54601e-05,6.71538e-09,0.0001,0.0001,5.40947e-07,5.40947e-07,5.40947e-07,5.40947e-07,1.16156e-06,0.0001,5.117e-07,5.117e-07,5.117e-07,0.0001,0.0001,6.26024e-07,6.26024e-07,6.26024e-07,6.26024e-07,6.26024e-07,3.15025e-05,3.15025e-05,8.64929e-06,8.64929e-06,8.64929e-06,3.70899e-09,3.70899e-09,3.70899e-09,3.70899e-09,0.0001,1.97754e-08,1.98227e-07,5.28706e-05,3.74561e-06,7.19619e-07,6.7486e-07,6.7486e-07,6.7486e-07,6.7486e-07,3.99622e-05,0.0001,0.0001,3.11287e-05,3.11287e-05,3.11287e-05,2.27087e-05,2.27087e-05,2.27087e-05,0.0001,1.72054e-08,1.38416e-06,1.38416e-06,1.38416e-06,1.38416e-06,8.02973e-06,8.02973e-06,8.02973e-06,7.80616e-08,9.39456e-08,9.39456e-08,2.07972e-05,1.67279e-07,1.67279e-07,1.67279e-07,0.0001,0.0001,0.0001,1.101e-06,8.16236e-09,3.145e-07,1.00368e-06,4.62446e-06,4.62446e-06,0.0001,9.08616e-05,5.82978e-05,0.0001,2.6657e-07,0.0001,0.0001,1.12254e-06,1.12254e-06,0.0001", "train/minibatch_size": "32768,32768,32768,8192,8192,32768,32768,32768,32768,32768,32768,32768,16384,16384,32768,32768,32768,32768,32768,16384,16384,8192,8192,8192,16384,32768,32768,32768,32768,16384,32768,32768,16384,16384,32768,16384,16384,16384,65536,16384,16384,16384,16384,16384,16384,16384,16384,16384,16384,16384,16384,16384,16384,32768,32768,16384,16384,32768,32768,16384,32768,32768,4096,4096,16384,16384,16384,16384,32768,8192,32768,32768,32768,16384,32768,8192,8192,8192,8192,8192,8192,8192,32768,32768,32768,32768,32768,32768,32768,32768,32768,65536,32768,32768,32768,32768,32768,32768,32768,16384,8192,8192,16384,16384,16384,8192,8192,8192,32768,65536,16384,16384,16384,16384,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,16384,16384,16384,65536,16384,32768,32768,32768,32768,32768,32768,8192,32768,16384,65536,8192,16384,16384,8192", "train/horizon": "64,64,32,32,64,64,64,32,32,32,32,32,64,64,64,64,64,32,32,32,32,64,64,64,64,64,64,64,64,32,64,64,32,32,32,64,64,64,64,128,128,128,32,32,32,64,64,64,128,64,64,64,64,64,64,64,64,64,64,64,32,64,64,64,128,128,128,128,32,64,64,64,64,64,64,32,32,32,32,32,64,64,64,64,64,64,64,64,64,32,64,64,64,64,64,64,64,64,64,128,64,64,64,64,64,128,128,128,64,64,64,64,64,64,32,32,32,64,64,64,32,32,32,32,64,64,64,64,32,32,32,64,64,64,32,32,32,64,64,32,64,64,32", "train/vtrace_rho_clip": "3.24865,0.701262,1.50482,1.51704,0.636509,0.537299,0.537299,1.94873,1.94873,1.94873,1.94873,1.94873,1.78861,1.78861,1.54448,1.54448,1.32317,1.50777,1.50777,3.18075,3.18075,1.15318,1.15318,1.15318,0.976128,0.195341,3.63546,3.63546,3.63546,4.237,1.17649,1.17649,2.43448,2.43448,1.97851,1.70072,1.70072,1.70072,1.86093,2.08574,2.08574,2.08574,0.340532,0.340532,0.340532,1.59729,1.59729,1.59729,1.94837,1.26818,2.38251,2.38251,2.38251,3.08495,3.08495,3.48811,3.48811,3.24229,3.24229,0.617653,3.66722,1.77496,0.893789,0.893789,2.8493,2.8493,2.8493,2.8493,1.42774,1.74781,1.48651,1.48651,1.48651,0.822729,1.55458,0.521401,0.521401,0.521401,0.521401,0.521401,1.29435,1.29435,2.02979,2.02979,2.02979,1.13127,1.13127,1.13127,1.13127,1.43645,1.32438,1.49597,2.30709,0.921344,2.40095,1.05088,1.05088,1.05088,1.05088,1.88367,0.786966,0.786966,0.584129,0.584129,0.584129,1.33226,1.33226,1.33226,4.04244,2.44158,1.69438,1.69438,1.69438,1.69438,1.22383,1.22383,1.22383,1.40782,1.70278,1.70278,2.25437,1.57432,1.57432,1.57432,1.85239,1.85239,1.85239,1.75215,1.9537,1.26013,0.915032,1.27251,1.27251,1.92016,2.9153,2.38801,1.5121,1.47279,3.77837,2.34741,1.27942,1.27942,1.08181", "train/vtrace_c_clip": "3.66132,2.28905,3.39267,4.06095,4.60048,1.83704,1.83704,3.83069,3.83069,3.83069,3.83069,3.83069,3.55367,3.55367,2.68099,2.68099,2.85495,2.87355,2.87355,3.78755,3.78755,5,5,5,3.11829,1.92859,3.23039,3.23039,3.23039,4.70199,2.18612,2.18612,2.0758,2.0758,3.27707,4.154,4.154,4.154,3.52017,4.99692,4.99692,4.99692,3.08394,3.08394,3.08394,5,5,5,5,5,1.34317,1.34317,1.34317,3.85378,3.85378,4.87265,4.87265,3.95664,3.95664,2.466,3.87545,3.29927,3.20486,3.20486,5,5,5,5,3.62264,4.84646,3.251,3.251,3.251,1.31403,2.39622,5,5,5,5,5,4.78133,4.78133,3.5476,3.5476,3.5476,2.5226,2.5226,2.5226,2.5226,5,3.13634,2.79384,5,2.62351,2.6637,2.48604,2.48604,2.48604,2.48604,5,4.7416,4.7416,1.61295,1.61295,1.61295,5,5,5,4.73622,2.72315,1.93108,1.93108,1.93108,1.93108,2.56866,2.56866,2.56866,2.47584,1.70484,1.70484,4.53933,3.13206,3.13206,3.13206,5,5,5,2.29411,1.82213,2.30471,3.16593,1.66892,1.66892,1.71171,4.43274,4.7314,1.39657,2.15414,5,5,2.04647,2.04647,5", "train/prio_alpha": "0.840422,1,1,0.140971,0.101577,1,1,0.956891,0.956891,0.956891,0.956891,0.956891,0.818065,0.818065,0.80735,0.80735,1,0.867096,0.867096,1,1,0.333766,0.333766,0.333766,1,1,0.97212,0.97212,0.97212,0.828149,1,1,1,1,1,0.122027,0.122027,0.122027,1,0.737323,0.737323,0.737323,1,1,1,0.739437,0.739437,0.739437,0.300526,0.279213,1,1,1,1,1,1,1,1,1,1,0.795026,1,0.276366,0.276366,0.757254,0.757254,0.757254,0.757254,1,0.273104,1,1,1,1,1,0.190295,0.190295,0.190295,0.190295,0.190295,0.38517,0.38517,1,1,1,0.771777,0.771777,0.771777,0.771777,0.731742,1,0.810291,0.833401,0.985853,1,0.983985,0.983985,0.983985,0.983985,0.461974,0.19506,0.19506,1,1,1,0.611567,0.611567,0.611567,0.945231,0.982335,0.77878,0.77878,0.77878,0.77878,0.96005,0.96005,0.96005,0.825066,1,1,0.811194,1,1,1,0.512958,0.512958,0.512958,0.840383,1,1,0.910419,1,1,0.952113,0.902882,0.27265,1,1,1,0.265936,1,1,0", "train/prio_beta0": "0.731897,0.723831,0.76045,0.81982,0.998248,0.873117,0.873117,0.689963,0.689963,0.689963,0.689963,0.689963,0.865855,0.865855,0.893521,0.893521,0.672652,0.934669,0.934669,0.730825,0.730825,1,1,1,0.888505,0.582637,0.708358,0.708358,0.708358,0.584062,0.918183,0.918183,0.917205,0.917205,1,0.805145,0.805145,0.805145,0.837036,0.8833,0.8833,0.8833,0.852499,0.852499,0.852499,0.897495,0.897495,0.897495,0.735111,0.776168,0.705713,0.705713,0.705713,0.732865,0.732865,1,1,0.555562,0.555562,0.798019,0.701331,0.707486,0.968418,0.968418,0.768726,0.768726,0.768726,0.768726,0.866809,0.863253,0.809744,0.809744,0.809744,0.845286,0.960704,0.927877,0.927877,0.927877,0.927877,0.927877,0.94363,0.94363,0.955856,0.955856,0.955856,0.681272,0.681272,0.681272,0.681272,0.821481,0.610517,0.898255,0.879183,0.72985,0.669899,0.756806,0.756806,0.756806,0.756806,0.831527,0.858866,0.858866,0.847209,0.847209,0.847209,0.851213,0.851213,0.851213,0.559367,1,0.895953,0.895953,0.895953,0.895953,1,1,1,0.672875,1,1,0.811326,0.788432,0.788432,0.788432,0.841354,0.841354,0.841354,0.630044,0.734138,1,0.837844,0.924566,0.924566,0.80002,0.845676,0.818304,1,0.569025,0.654657,0.733909,0.723249,0.723249,0.764742", "train/env": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "no_model_upload": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "tsne1": "-41.4774,-42.2784,-49.5456,27.8317,28.7557,-44.5726,-44.5726,-40.0161,-40.0161,-40.016,-40.0159,-40.0159,-38.5206,-38.5206,-50.3191,-50.3191,-42.1676,-41.3029,-41.3029,-48.8453,-48.8453,28.6088,28.6088,28.6088,-50.8345,-40.6455,-43.1419,-43.1419,-43.1419,-42.4849,-43.5754,-43.5754,-50.0785,-50.0785,-41.0392,3.26425,3.26425,3.26427,-41.8137,27.8988,27.8988,27.8988,-47.1553,-47.1553,-47.1553,27.8893,27.8773,27.8893,27.382,28.9435,-44.6332,-44.6332,-44.6332,-42.6558,-42.6558,-40.8353,-40.8353,-42.427,-42.427,-41.2316,-42.1375,-40.2707,28.6121,28.6121,24.3874,24.3874,24.3874,24.3874,-50.0514,27.8233,-41.9322,-41.9322,-41.9322,-43.0889,-42.7351,29.6312,29.6312,29.6312,29.6312,29.6312,28.8655,28.8656,-50.8181,-50.8182,-50.8181,-39.0187,-39.0187,-39.0188,-39.0187,26.7104,-50.0747,-40.3896,26.6376,-41.8,-43.2909,-41.6984,-41.6984,-41.6985,-41.6984,27.6946,29.4487,29.4487,-43.0424,-43.0426,-43.0421,25.2359,25.2357,25.2359,-43.4864,-49.1567,-51.599,-51.5986,-51.5986,-51.5986,-45.5013,-45.5013,-45.5013,-39.7927,-43.3069,-43.307,-40.5925,-49.8001,-49.8001,-49.8001,28.2241,28.2241,28.2242,-40.9313,-45.195,-40.9331,-40.8238,-43.5808,-43.5808,-42.7171,-41.7197,27.5217,-50.0285,-45.0127,-43.7276,27.1912,-43.881,-43.881,27.7806", "tsne2": "44.3802,38.5554,39.6491,14.6836,15.3575,35.8337,35.8337,42.8213,42.8213,42.8216,42.8216,42.8216,42.1884,42.1884,41.001,41.001,39.4766,38.4779,38.4779,42.772,42.772,17.0773,17.0773,17.0773,40.6706,35.7105,44.2971,44.2971,44.2971,45.6263,37.6705,37.6705,42.3077,42.3077,39.1201,-39.5077,-39.5077,-39.5071,40.614,20.4498,20.4498,20.4498,38.2843,38.2843,38.2843,21.2479,21.246,21.2479,15.2745,19.1341,41.1296,41.1296,41.1296,43.4285,43.4285,45.528,45.528,43.7431,43.7431,36.2006,44.6039,38.9927,14.5724,14.5724,20.4926,20.4926,20.4926,20.4926,39.8548,15.1418,39.9215,39.9215,39.9215,35.0542,38.2397,18.15,18.15,18.15,18.15,18.15,18.7877,18.7878,40.1111,40.1111,40.1111,38.3228,38.3228,38.3229,38.3228,15.5892,39.0881,37.6329,20.9194,36.9901,41.8586,37.5788,37.5788,37.5788,37.5788,19.5076,19.5358,19.5358,34.9594,34.9595,34.9596,21.2292,21.2295,21.2292,44.9909,40.9159,41.6647,41.6648,41.6648,41.6648,37.0476,37.0476,37.0476,38.0651,36.7016,36.7017,43.9309,40.0189,40.0189,40.0189,19.239,19.239,19.2392,40.5024,38.868,37.9995,37.1228,36.3264,36.3264,36.4952,44.4702,14.435,41.3581,38.9276,45.1438,15.0255,39.1346,39.1346,14.642"}, "go": {"SPS": "1.09672e+06,147250,147258,1.14235e+06,775068,1.05164e+06,771387,475969,1.85815e+06,789930,354193,742645,759954,703093,702830,702439,370917,372714,391733,256576,256740,257215,257178,257140,162775,163059,162821,162754,1.0384e+06,988552,858424,889317,1.09349e+06,1.07159e+06,305393,306527,635658,328853,1.10522e+06,1.12285e+06,1.08768e+06,999441,508705,474312,1.01337e+06,254694,909511,327388,161143,169579,168727,268045,275679,1.02837e+06,1.264e+06,497607,464986,569898,556264,573191,569493,569916,2.29711e+06,807742,1.36305e+06,667876", "agent_steps": "33.8788,120.586,157.286,6.11412,17.0019,80.085,5.64464,5.47846,9.17941,5.68078,16.9083,27.263,62.3903,133.693,151.257,159.646,37.4804,62.1937,86.8352,116.13,137.101,158.073,179.044,189.268,99.0904,114.295,129.237,136.315,5.89053,6.16901,17.0183,28.1512,6.29146,17.6947,5.70163,16.81,11.2722,7.61344,43.9183,95.2839,146.817,9.89812,19.1037,5.68568,6.09485,9.38894,6.01293,5.41954,36.3069,108.528,132.514,5.60035,16.8755,80.7324,6.39362,21.7252,36.1431,50.3316,72.876,83.8861,94.8836,99.8769,10.1362,5.79851,6.70925,9.04553", "uptime": "29.0929,817.788,1067.04,5.51299,22.8921,70.543,7.7083,12.0983,4.93855,7.37617,47.3708,36.6911,83.5092,179.978,204.849,216.783,96.1467,162.843,227.265,457.276,538.988,620.577,702.116,741.868,598.685,691.985,783.699,827.17,5.71781,6.04581,18.1309,30.8262,5.8478,16.2821,18.5351,55.0611,18.2722,22.9048,40.5257,85.9941,133.064,10.0138,37.6264,12.1113,6.10797,35.7251,6.71839,16.7045,222.056,650.095,791.757,21.0902,62.3769,70.4753,5.5132,40.7707,71.0604,87.7724,127.542,147.276,166.537,175.303,4.05935,7.26136,5.3319,13.4027", "epoch": "1033.9,115,150,186.588,259.429,1222,86.1304,167.189,140.067,86.6818,258,104,238,510,577,609,571.906,949,1325,221.5,261.5,301.5,341.5,361,189,218,246.5,260,44.9412,753.053,2077.43,3436.43,24,67.5,87,256.5,43,116.172,1340.28,2907.83,4480.5,151.033,583,347.026,46.5,286.528,367,82.6957,138.5,414,505.5,170.909,515,4927.52,195.118,331.5,551.5,192,278,320,361.952,381,9.66667,707.826,102.375,276.048", "env/perf": "0.891806,0.999111,0.999633,0.179011,0.679358,0.970852,0.135347,0.017663,0.00479326,0.0138481,0.962473,0.950934,0.976073,0.993308,0.994072,0.993652,0.978359,0.982478,0.985314,0.996975,0.998511,0.999262,0.999368,0.999438,0.998417,0.997803,0.999045,0.999119,0.00816089,0.252367,0.857988,0.883886,0.341669,0.978914,0.327817,0.873017,0.547035,0.696296,0.981106,0.989274,0.990815,0.46606,0.935694,0.208027,0.0115452,0.779062,0.00897072,0.321915,0.989145,0.996811,0.99808,0.4682,0.93025,0.978965,0.232511,0.984674,0.988026,0.988306,0.994994,0.996066,0.996118,0.996829,0.00305198,0.329973,0.0230855,0.488029", "env/score": "56.9703,79.6856,80.0838,-22.8277,31.7475,72.4144,-24.4403,-45.7803,-49.3451,-47.5284,62.6903,66.1276,74.3024,79.3251,79.6604,79.7221,78.1909,78.6624,78.8554,79.1288,79.9372,80.2806,80.3615,80.376,79.484,79.5594,79.8513,79.9758,-53.7403,-21.4767,56.339,60.3822,-8.33507,33.6755,-10.1537,43.1669,0.740208,26.2252,67.8046,76.5029,78.4419,0.434352,60.2989,-17.7307,-51.5191,40.2396,-28.5656,-13.4186,74.9885,79.4904,79.9724,-2.54883,60.0136,73.7966,-18.629,72.2131,73.6393,75.7629,78.3153,78.7242,78.8491,78.8682,-70.4028,-9.62406,-31.2057,-2.30635", "env/episode_length": "240.647,123.78,123.556,243.508,242.063,170.399,243.998,243.951,243.985,243.472,241.552,179.108,202.163,153.486,153.541,153.893,228.197,226.294,222.889,111.802,111.029,110.55,110.386,110.318,154.546,154.547,154.074,153.94,243.472,237.149,212.533,206.894,243.862,243.855,243.144,243.88,239.738,234.957,236.559,240.843,236.339,243.517,242.941,242.065,243.945,162.177,243.996,243.748,171.594,238.536,238.64,234.595,241.759,243.948,242.079,195.254,159.888,131.666,131.188,130.45,129.992,130.015,236.689,243.518,243.998,243.517", "env/episode_return": "20.569,36.1207,36.2277,-2.10216,27.5255,21.258,-5.42099,-34.9372,-159.429,-27.8348,36.6708,38.3612,46.4149,39.7219,39.8249,39.8393,77.5914,77.8529,77.0931,33.8715,34.1124,34.1792,34.1836,34.2169,32.2448,32.3794,32.4587,32.4812,-20.6605,-20.5472,38.7555,41.6133,-4.16994,33.7485,-7.52694,29.2034,16.4609,16.1196,57.1986,60.6575,60.1458,-0.355433,44.9488,-4.71791,-14.4201,24.1564,-12.8725,-0.611069,48.2502,64.7731,65.091,24.7281,75.5524,58.0616,-3.81644,54.7949,46.6412,35.3432,36.724,36.7577,36.6283,36.6406,-122.326,-2.03199,-9.57647,-5.06506", "env/n": "2798,8471.24,8486.41,2866.88,2140.05,3845.59,2025.74,1239.81,4644.93,2075.41,1082.98,2934.38,2604.85,3415.29,3414.97,10239,1139.77,1158.6,1176.24,4690.45,4722.4,4743.15,4749.7,14240,3393.38,3392,3403.39,10217,2685.82,2511.84,2445.71,2598.38,3141.87,3220,803.298,806.946,2176.81,983.281,2876.44,2885.5,2703.77,2650.57,1348.53,1208.63,2645.33,1060.94,2267.48,991.609,1576.17,1098.89,1098.52,726.318,813.304,2563.83,3172.24,1706.73,2050.68,3982,3995.95,4018.24,3939,10092,7737.22,2007.43,3456,1710.02", "perf/rollout": "0.273226,0.807994,0.806034,0.20222,0.252776,0.385818,0.233396,0.242614,0.518407,0.251426,0.12975,0.282644,0.266357,0.319451,0.322278,0.32266,0.186104,0.18628,0.152065,0.382726,0.382003,0.378083,0.378616,0.378971,0.396056,0.392936,0.397748,0.399092,0.31761,0.334155,0.368682,0.357524,0.165862,0.178814,0.128591,0.124357,0.273158,0.229,0.365508,0.363371,0.352445,0.220405,0.123756,0.174457,0.243852,0.163646,0.248171,0.108544,0.294829,0.213834,0.221621,0.131714,0.130602,0.418607,0.420223,0.199983,0.245738,0.298536,0.324751,0.293178,0.291964,0.149035,0.5586,0.208711,0.312827,0.150252", "perf/eval_gpu": "0.0851234,0.132183,0.131971,0.101451,0.128449,0.0372609,0.104644,0.134231,0.1023,0.122544,0.0273445,0.0312427,0.0313936,0.0374081,0.0308315,0.0309262,0.0229492,0.0221826,0.022402,0.0405323,0.0402309,0.0404881,0.0405768,0.0404169,0.084228,0.0843717,0.0842057,0.0842502,0.155478,0.131941,0.109431,0.114168,0.0427553,0.0413704,0.0540492,0.0554394,0.0419928,0.100474,0.132227,0.133693,0.120906,0.126077,0.0560138,0.116147,0.100907,0.0248374,0.133909,0.0826197,0.0443794,0.0462409,0.0453726,0.056229,0.0566955,0.115979,0.238295,0.0251785,0.0250042,0.0248871,0.024881,0.0248058,0.0242627,0.0124993,0.0811348,0.127591,0.166204,0.100661", "perf/eval_env": "0.150459,0.66531,0.665086,0.0643538,0.0655183,0.323345,0.103395,0.0391874,0.399195,0.0716683,0.0954509,0.23821,0.219246,0.267663,0.278475,0.277828,0.149483,0.149978,0.11816,0.336294,0.335589,0.331941,0.332173,0.334406,0.295751,0.291908,0.297054,0.297283,0.112984,0.137188,0.196458,0.181872,0.116086,0.131059,0.054855,0.0521938,0.222312,0.0664716,0.17938,0.176736,0.18432,0.0264667,0.0503315,0.020095,0.0874499,0.118375,0.0692238,0.0101173,0.245438,0.162448,0.170202,0.0448421,0.037297,0.252014,0.0498345,0.162385,0.19975,0.266726,0.28684,0.261951,0.261146,0.13364,0.453474,0.0283495,0.108286,0.0197609", "perf/train_misc": "0.00875852,0.142435,0.142552,0.0136276,0.0145082,0.0244611,0.0430863,0.00655926,0.00393622,0.00874839,0.0109935,0.0463636,0.0463574,0.0463727,0.0464015,0.0464332,0.0141764,0.0142842,0.0142874,0.0592757,0.0593905,0.0592803,0.059335,0.0591626,0.150464,0.150624,0.150596,0.150535,0.0173898,0.0163795,0.0141219,0.0146035,0.067219,0.0540186,0.0048829,0.00460661,0.0666385,0.0230063,0.0114884,0.0117513,0.010807,0.0595664,0.0118355,0.00306072,0.01275,0.00813443,0.0083266,0.00305281,0.0261202,0.026162,0.0260982,0.00960784,0.0107058,0.00713591,0.00889656,0.0145827,0.0145861,0.0383519,0.0384142,0.0383198,0.0374369,0.0190004,0.0260691,0.0137389,0.0115536,0.0216164", "perf/train_forward": "0.331686,6.16834,6.17146,0.409071,0.400779,0.211692,0.390018,0.40161,0.0995431,0.403919,0.599304,0.376671,0.376723,0.380888,0.376684,0.376056,0.500997,0.502214,0.502257,1.59961,1.59992,1.59979,1.60054,1.60132,2.67353,2.67102,2.67051,2.67376,0.335033,0.253794,0.219884,0.229672,0.61922,0.500209,0.544182,0.513594,0.559028,0.472084,0.23814,0.243441,0.223886,0.380506,0.508033,0.447429,0.432069,0.4994,0.359261,0.672074,1.30537,1.30547,1.30538,0.511327,0.571434,0.181858,0.185536,0.443774,0.443741,0.582274,0.582072,0.582295,0.568572,0.290871,0.389288,0.384652,0.314521,0.460306", "perf/train": "0.340444,6.31078,6.31401,0.422699,0.415287,0.236153,0.433105,0.408169,0.103479,0.412667,0.610297,0.423035,0.423081,0.427261,0.423085,0.422489,0.515173,0.516498,0.516545,1.65889,1.65931,1.65908,1.65988,1.66048,2.82399,2.82164,2.8211,2.8243,0.352423,0.270174,0.234006,0.244275,0.686439,0.554228,0.549065,0.518201,0.625666,0.495091,0.249628,0.255192,0.234693,0.440073,0.519869,0.45049,0.444819,0.507535,0.367588,0.675127,1.33149,1.33163,1.33148,0.520935,0.58214,0.188994,0.194432,0.458356,0.458327,0.620626,0.620486,0.620615,0.606009,0.309872,0.415357,0.398391,0.326075,0.481922", "util/gpu_percent": "93.55,100,100,97.6471,98.3333,60.8148,85.4348,96.4595,43.8667,89.8636,92.6429,75.6471,76.7941,72.8235,68.5152,91,85.2812,84.9149,89.9362,100,100,100,100,100,100,100,100,100,82.8824,87.3158,85.2857,87.9524,90.8,92.7857,94.6316,94.2143,83.7857,91.2031,88.72,89.75,87.7308,98.8667,98.9474,98.3421,98.6111,85.3333,94.5714,99.7391,100,100,100,96.3636,98.0893,79.2069,91.6471,80.5,76.9545,77,80.9524,77.8571,81.9524,100,61.6667,95.913,81.3125,98.8095", "util/gpu_mem": "7.52753,15.0589,15.0589,6.15967,8.74883,5.19892,5.14193,8.71736,10.0108,8.3173,6.4365,19.4958,19.4958,19.3093,19.4958,19.4958,16.4909,16.4909,16.5239,9.5956,9.5956,9.5956,9.5956,9.5956,12.0952,12.0952,12.0952,12.0952,8.18703,4.92209,4.92209,4.92209,6.26552,6.26552,10.1655,10.1655,6.52606,7.00644,6.2818,6.2818,6.2818,5.98055,6.42836,12.3394,9.95385,6.22481,7.05529,23.849,8.54528,8.54528,8.54528,7.09403,7.096,5.99683,7.52753,5.73629,5.73629,7.11229,7.11229,7.11229,7.11229,7.11229,14.4808,17.2323,7.82064,15.5957", "util/vram_used_gb": "1.3446,3.15125,3.15125,1.01648,1.63757,0.786011,0.772339,1.63002,1.94031,1.53406,1.08289,4.21558,4.21558,4.17085,4.21558,4.21558,3.49476,3.49477,3.50269,1.8407,1.8407,1.8407,1.8407,1.8407,2.44031,2.44031,2.44031,2.44031,1.50281,0.719604,0.719604,0.719604,1.04187,1.04187,1.97742,1.97742,1.10437,1.2196,1.04578,1.04578,1.04578,0.973511,1.08093,2.4989,1.92664,1.0321,1.23132,5.25986,1.58875,1.58875,1.58875,1.24062,1.24109,0.977417,1.3446,0.914917,0.914917,1.245,1.245,1.245,1.245,1.245,3.01257,3.67261,1.41492,3.28003", "util/vram_total_gb": "23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272", "util/cpu_mem_gb": "1.08622,1.32091,1.32091,1.08004,1.20972,1.0774,1.08813,1.17632,1.05996,1.11036,1.07532,1.0756,1.0756,1.0756,1.0756,1.0756,0.999928,0.999928,0.999928,1.15993,1.15993,1.16013,1.16042,1.16042,1.42559,1.42559,1.42559,1.42559,1.20761,1.06554,1.06554,1.06554,1.09147,1.09147,1.11765,1.11765,1.12091,1.18555,1.09177,1.09177,1.09177,1.16282,1.10155,1.11135,1.2243,1.07389,1.07607,1.16442,1.16306,1.16306,1.16306,1.13712,1.13712,1.07229,1.15911,1.0728,1.0728,1.12235,1.12235,1.12235,1.12235,1.12235,1.366,0.985493,1.09132,1.00542", "wandb": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "slowly": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "save_frames": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "fps": "15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15", "rank": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "world_size": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "gpu_id": "4,4,4,5,4,4,2,4,2,2,3,0,0,0,0,0,0,0,0,5,5,5,5,5,4,4,4,4,4,4,4,4,1,1,2,2,4,1,5,5,5,2,3,5,5,3,3,2,2,2,2,2,2,1,2,1,1,2,2,2,2,2,4,0,2,0", "profile": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "checkpoint_interval": "200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200", "eval_episodes": "10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000", "cudagraphs": "10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10", "seed": "73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73", "reset_state": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "vec/total_agents": "512,2048,2048,512,256,1024,256,256,1024,512,1024,1024,1024,1024,1024,1024,1024,1024,1024,2048,2048,2048,2048,2048,512,512,512,512,512,256,256,256,2048,2048,512,512,1024,256,256,256,256,256,512,256,512,512,256,512,1024,1024,1024,256,256,256,256,1024,1024,2048,2048,2048,2048,2048,2048,256,512,256", "vec/num_buffers": "6.73662,4.10441,4.10441,5.56331,6.81173,5.18121,2.65981,8,2.67773,6.62272,4.1184,5.58202,5.58202,5.58202,5.58202,5.58202,5.52761,5.52761,5.52761,4.59686,4.59686,4.59686,4.59686,4.59686,4.16737,4.16737,4.16737,4.16737,5.87508,5.963,5.963,5.963,3.60827,3.60827,4.30939,4.30939,3.83652,6.93373,4.61143,4.61143,4.61143,5.35646,6.34558,7.62357,8,4.1536,4.74129,7.96583,3.83191,3.83191,3.83191,6.2879,6.2879,4.98399,7.42522,4.9976,4.9976,5.7443,5.7443,5.7443,5.7443,5.7443,5.13984,5.1882,4.64285,3.6441", "vec/num_threads": "2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2", "env/width": "950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950,950", "env/height": "750,750,750,750,750,750,750,750,750,750,750,750,750,750,750,750,750,750,750,750,750,750,750,750,750,750,750,750,750,750,750,750,750,750,750,750,750,750,750,750,750,750,750,750,750,750,750,750,750,750,750,750,750,750,750,750,750,750,750,750,750,750,750,750,750,750", "env/grid_size": "9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9", "env/board_width": "600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600", "env/board_height": "600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600,600", "env/grid_square_size": "64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64", "env/moves_made": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "env/komi": "7.5,7.5,7.5,7.5,7.5,7.5,7.5,7.5,7.5,7.5,7.5,7.5,7.5,7.5,7.5,7.5,7.5,7.5,7.5,7.5,7.5,7.5,7.5,7.5,7.5,7.5,7.5,7.5,7.5,7.5,7.5,7.5,7.5,7.5,7.5,7.5,7.5,7.5,7.5,7.5,7.5,7.5,7.5,7.5,7.5,7.5,7.5,7.5,7.5,7.5,7.5,7.5,7.5,7.5,7.5,7.5,7.5,7.5,7.5,7.5,7.5,7.5,7.5,7.5,7.5,7.5", "env/last_capture_position": "-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1", "env/reward_move_pass": "-0.613644,-0.707523,-0.707523,-0.662477,-0.792482,-0.621431,-0.84752,-0.588681,-0.644649,-0.532334,-0.818257,-0.841709,-0.841709,-0.841709,-0.841709,-0.841709,-0.647325,-0.647325,-0.647325,-0.803521,-0.803521,-0.803521,-0.803521,-0.803521,-0.779737,-0.779737,-0.779737,-0.779737,-0.861832,-0.648545,-0.648545,-0.648545,-0.820963,-0.820963,-0.597484,-0.597484,-0.705329,-0.720413,-0.518441,-0.518441,-0.518441,-0.531696,-0.616783,-0.42107,-0.461064,-0.53504,-0.566749,-0.53751,-0.770978,-0.770978,-0.770978,-0.902957,-0.902957,-0.609543,-0.523287,-0.8282,-0.8282,-0.679629,-0.679629,-0.679629,-0.679629,-0.679629,-0.355373,-0.475646,-0.670133,-0.791059", "env/reward_move_valid": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "env/reward_move_invalid": "-0.0611524,-0.143812,-0.143812,0,-0.101844,-0.105566,0,-0.158344,-0.88182,-0.0917679,-0.102895,-0.180925,-0.180925,-0.180925,-0.180925,-0.180925,-0.171265,-0.171265,-0.171265,-0.200965,-0.200965,-0.200965,-0.200965,-0.200965,-0.105269,-0.105269,-0.105269,-0.105269,-0.119331,-0.188049,-0.188049,-0.188049,-0.0514018,-0.0514018,-0.115803,-0.115803,-0.151777,-0.236858,-0.0864746,-0.0864746,-0.0864746,0,-0.150557,0,-0.0629782,-0.337505,-0.0440707,0,-0.223686,-0.223686,-0.223686,-0.14614,-0.14614,-0.080259,0,-0.0947726,-0.0947726,-0.224743,-0.224743,-0.224743,-0.224743,-0.224743,-0.794112,0,-0.0204418,-0.0190514", "env/reward_opponent_capture": "-0.191709,-0.250987,-0.250987,-0.0972668,-0.0703586,-0.338001,-0.328071,-0.325678,-0.709621,-0.39764,-0.217917,-0.238603,-0.238603,-0.238603,-0.238603,-0.238603,-0.362575,-0.362575,-0.362575,-0.451406,-0.451406,-0.451406,-0.451406,-0.451406,-0.303179,-0.303179,-0.303179,-0.303179,-0.0570423,-0.339374,-0.339374,-0.339374,-0.377903,-0.377903,-0.302685,-0.302685,-0.0120276,-0.127316,-0.102283,-0.102283,-0.102283,-0.239928,-0.286497,-0.343133,-0.124339,-0.373136,-0.257463,-0.0155865,-0.255505,-0.255505,-0.255505,0,0,-0.121085,-0.226769,-0.193132,-0.193132,-0.489919,-0.489919,-0.489919,-0.489919,-0.489919,-0.788501,-0.315114,-0.275938,-0.238003", "env/reward_player_capture": "0.304121,0.582527,0.582527,0.501051,0.584611,0.323246,0.716657,0.22238,0.017126,0.147772,0.442583,0.552232,0.552232,0.552232,0.552232,0.552232,0.815985,0.815985,0.815985,0.615467,0.615467,0.615467,0.615467,0.615467,0.45339,0.45339,0.45339,0.45339,0.21587,0.653518,0.653518,0.653518,0.679441,0.679441,0.503977,0.503977,0.420762,0.418342,0.553628,0.553628,0.553628,0.122785,0.570937,0.344406,0.175702,0.80789,0.409402,0.137029,0.6373,0.6373,0.6373,0.717972,0.717972,0.57182,0.312275,0.660619,0.660619,0.573479,0.573479,0.573479,0.573479,0.573479,0.361869,0.691232,0.524691,0.969585", "env/selfplay": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "policy/hidden_size": "512,1024,1024,512,512,256,512,1024,512,1024,1024,512,512,512,512,512,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,256,256,256,256,512,512,1024,1024,512,1024,512,512,512,256,512,1024,1024,1024,512,1024,1024,1024,1024,1024,1024,512,256,1024,1024,512,512,512,512,512,128,512,512,512", "policy/num_layers": "2.62376,4.17425,4.17425,2.30236,2.83514,1.38882,1,2.66395,1.82922,1.4219,2.27081,1.5119,1.5119,1.5119,1.5119,1.5119,1.51468,1.51468,1.51468,2.89469,2.89469,2.89469,2.89469,2.89469,2.34402,2.34402,2.34402,2.34402,3.5475,2.74331,2.74331,2.74331,1.51348,1.51348,4.74906,4.74906,1.57903,1.86901,1.6302,1.6302,1.6302,1.00495,4.0137,3.20603,1,2.96206,2.55367,4.04348,3.23954,3.23954,3.23954,2.56745,2.56745,1.76419,3.3048,1.14296,1.14296,2.30005,2.30005,2.30005,2.30005,2.30005,4.86339,2.31552,1.26358,2.58044", "policy/expansion_factor": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "train/gpus": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "train/seed": "42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42", "train/total_timesteps": "120.634,165.7,165.7,105.014,100,158.573,100,100,147.253,100,100,159.825,159.825,159.825,159.825,159.825,222.762,222.762,222.762,189.669,189.669,189.669,189.669,189.669,136.548,136.548,136.548,136.548,100,100,100,100,100,100,100,100,195.231,132.635,154.612,154.612,154.612,172.728,112.352,100,100,163.362,100,100,216.653,216.653,216.653,100,100,160.399,116.229,129.21,129.21,100,100,100,100,100,142.902,100,120.827,157.328", "train/learning_rate": "0.000732366,0.00296805,0.00296805,0.000272485,0.00151169,0.000501125,0.000180973,0.0043295,0.000122834,0.000784971,0.00052522,0.001151,0.001151,0.001151,0.001151,0.001151,0.000421344,0.000421344,0.000421344,0.00267062,0.00267062,0.00267062,0.00267062,0.00267062,0.000884657,0.000884657,0.000884657,0.000884657,0.00047535,0.00161691,0.00161691,0.00161691,0.000880379,0.000880379,0.00320365,0.00320365,0.000565634,0.00177924,0.00034529,0.00034529,0.00034529,0.00224536,0.00183552,0.00208888,0.000733455,0.00368621,0.000491256,0.00179311,0.00033256,0.00033256,0.00033256,0.00102256,0.00102256,0.000598111,0.0018906,0.000416265,0.000416265,0.00175082,0.00175082,0.00175082,0.00175082,0.00175082,0.0381615,0.00129544,0.000689857,0.00389454", "train/anneal_lr": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "train/min_lr_ratio": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "train/gamma": "0.969218,0.958262,0.958262,0.955918,0.986092,0.969838,0.8,0.995376,0.999706,0.87633,0.989055,0.972762,0.972762,0.972762,0.972762,0.972762,0.989475,0.989475,0.989475,0.936664,0.936664,0.936664,0.936664,0.936664,0.971438,0.971438,0.971438,0.971438,0.971711,0.987408,0.987408,0.987408,0.930386,0.930386,0.965113,0.965113,0.996527,0.973976,0.925771,0.925771,0.925771,0.891856,0.93727,0.994394,0.978537,0.998271,0.8,0.995301,0.987033,0.987033,0.987033,0.97495,0.97495,0.99028,0.985757,0.954486,0.954486,0.967956,0.967956,0.967956,0.967956,0.967956,0.999539,0.992417,0.943741,0.8", "train/gae_lambda": "0.994317,0.995,0.995,0.984633,0.995,0.989602,0.993729,0.994597,0.958026,0.995,0.985013,0.995,0.995,0.995,0.995,0.995,0.995,0.995,0.995,0.995,0.995,0.995,0.995,0.995,0.995,0.995,0.995,0.995,0.995,0.995,0.995,0.995,0.995,0.995,0.995,0.995,0.995,0.968918,0.983152,0.983152,0.983152,0.995,0.995,0.993494,0.986945,0.995,0.99257,0.995,0.994504,0.994504,0.994504,0.99352,0.99352,0.978776,0.994329,0.964345,0.964345,0.995,0.995,0.995,0.995,0.995,0.612984,0.995,0.973946,0.995", "train/replay_ratio": "3.06576,2.55291,2.55291,2.91126,3.77717,2.94385,3.08479,2.32453,1.1312,2.7668,3.17021,3.04036,3.04036,3.04036,3.04036,3.04036,4,4,4,3.44678,3.44678,3.44678,3.44678,3.44678,3.23773,3.23773,3.23773,3.23773,3.08311,3.12766,3.12766,3.12766,3.20902,3.20902,2.47368,2.47368,3.93354,3.51136,3.75422,3.75422,3.75422,3.44376,3.12412,2.54725,2.17691,4,4,3.19443,3.36826,3.36826,3.36826,3.2893,3.2893,3.75945,2.23062,3.32117,3.32117,3.4135,3.4135,3.4135,3.4135,3.4135,0.932826,3.41724,4,3.19279", "train/clip_coef": "0.513828,0.616732,0.616732,0.48666,0.467347,0.485313,0.829189,0.497146,0.974704,0.670855,0.445214,0.560709,0.560709,0.560709,0.560709,0.560709,0.60718,0.60718,0.60718,0.558557,0.558557,0.558557,0.558557,0.558557,0.606229,0.606229,0.606229,0.606229,0.388356,0.454795,0.454795,0.454795,0.454881,0.454881,0.491132,0.491132,0.320569,0.462051,0.465704,0.465704,0.465704,0.319406,0.324156,0.538022,0.35233,0.546897,0.603314,0.487612,0.485564,0.485564,0.485564,0.395212,0.395212,0.386363,0.47732,0.423039,0.423039,0.387528,0.387528,0.387528,0.387528,0.387528,0.0954962,0.535028,0.375472,0.863617", "train/vf_coef": "3.09452,2.03792,2.03792,3.23393,3.33808,3.45729,1.36664,2.49875,3.78532,2.77633,2.37085,2.44927,2.44927,2.44927,2.44927,2.44927,2.80417,2.80417,2.80417,2.16129,2.16129,2.16129,2.16129,2.16129,2.33881,2.33881,2.33881,2.33881,2.93315,2.34951,2.34951,2.34951,2.76141,2.76141,0.975067,0.975067,2.64876,2.13828,3.58533,3.58533,3.58533,1.93564,3.38594,2.2875,3.03025,1.969,3.43627,2.32639,1.57182,1.57182,1.57182,3.44585,3.44585,3.40508,3.53114,2.96072,2.96072,2.40276,2.40276,2.40276,2.40276,2.40276,4.80613,2.91167,3.47998,0.991578", "train/vf_clip_coef": "4.13237,1.55899,1.55899,3.55811,4.02625,2.4493,2.3313,5,3.31212,3.84778,1.14914,2.15903,2.15903,2.15903,2.15903,2.15903,2.14882,2.14882,2.14882,1.62927,1.62927,1.62927,1.62927,1.62927,2.40164,2.40164,2.40164,2.40164,4.92149,3.73367,3.73367,3.73367,2.78804,2.78804,3.40858,3.40858,3.32045,3.36529,2.38262,2.38262,2.38262,4.04827,4.62879,4.87567,4.2937,2.1154,1.38559,3.2994,2.36673,2.36673,2.36673,2.7011,2.7011,2.96082,3.86418,4.7686,4.7686,0.408599,0.408599,0.408599,0.408599,0.408599,4.2799,4.2727,2.80757,0.981319", "train/max_grad_norm": "0.1,0.1,0.1,0.1,0.1,0.904971,0.1,0.1,4.82378,0.1,0.994334,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.169071,0.169071,0.169071,0.169071,0.169071,1.22698,1.22698,1.22698,1.22698,0.1,0.1,0.1,0.1,0.4837,0.4837,0.1,0.1,0.1,0.462778,0.1,0.1,0.1,0.618837,0.312788,0.1,1.25204,0.1,1.02344,0.1,0.1,0.1,0.1,0.803565,0.803565,0.1,0.405499,0.1,0.1,0.1,0.1,0.1,0.1,0.1,4.11336,0.71684,0.114489,0.1", "train/ent_coef": "0.00250648,0.000599246,0.000599246,0.000684814,0.00779848,0.00399374,2.22366e-05,0.0018952,6.48154e-05,0.0164883,5.82478e-05,0.000472652,0.000472652,0.000472652,0.000472652,0.000472652,0.00194984,0.00194984,0.00194984,0.000332666,0.000332666,0.000332666,0.000332666,0.000332666,0.000839546,0.000839546,0.000839546,0.000839546,0.000721055,0.00457461,0.00457461,0.00457461,8.45837e-05,8.45837e-05,0.0028375,0.0028375,0.000341377,0.00547954,7.39777e-05,7.39777e-05,7.39777e-05,0.00741276,0.00117217,0.0107547,0.00505673,0.00304663,0.000162392,0.0146288,0.000302763,0.000302763,0.000302763,0.0058536,0.0058536,0.000633977,0.000307267,0.0038819,0.0038819,9.15087e-05,9.15087e-05,9.15087e-05,9.15087e-05,9.15087e-05,0.0139333,0.00199369,9.20746e-05,0.000517531", "train/beta1": "0.963147,0.894282,0.894282,0.991201,0.990984,0.995225,0.97944,0.94855,0.994299,0.91145,0.990951,0.975278,0.975278,0.975278,0.975278,0.975278,0.954321,0.954321,0.954321,0.884501,0.884501,0.884501,0.884501,0.884501,0.99269,0.99269,0.99269,0.99269,0.986221,0.993185,0.993185,0.993185,0.984216,0.984216,0.992591,0.992591,0.977209,0.993273,0.995692,0.995692,0.995692,0.979398,0.996145,0.955368,0.920773,0.944805,0.992752,0.988589,0.972678,0.972678,0.972678,0.99558,0.99558,0.983201,0.991945,0.960094,0.960094,0.922967,0.922967,0.922967,0.922967,0.922967,0.661824,0.997991,0.998318,0.992275", "train/beta2": "0.999987,0.999844,0.999844,0.999985,0.999956,0.999984,0.994213,0.99999,0.983274,0.999884,0.997163,0.998343,0.998343,0.998343,0.998343,0.998343,0.999706,0.999706,0.999706,0.99944,0.99944,0.99944,0.99944,0.99944,0.999792,0.999792,0.999792,0.999792,0.99999,0.999938,0.999938,0.999938,0.99982,0.99982,0.999814,0.999814,0.999518,0.999986,0.999933,0.999933,0.999933,0.999845,0.999939,0.999988,0.99999,0.999908,0.999965,0.99999,0.999684,0.999684,0.999684,0.999936,0.999936,0.999913,0.999976,0.99999,0.99999,0.998096,0.998096,0.998096,0.998096,0.998096,0.922651,0.99999,0.999972,0.999768", "train/eps": "1.29989e-13,2.58766e-10,2.58766e-10,2.44341e-11,2.52116e-10,1.20747e-09,1.51339e-10,1e-14,2.68299e-11,1.2012e-11,8.89302e-11,1.52986e-08,1.52986e-08,1.52986e-08,1.52986e-08,1.52986e-08,7.40223e-10,7.40223e-10,7.40223e-10,6.62521e-09,6.62521e-09,6.62521e-09,6.62521e-09,6.62521e-09,5.48481e-08,5.48481e-08,5.48481e-08,5.48481e-08,2.30243e-12,1.43257e-09,1.43257e-09,1.43257e-09,2.99757e-09,2.99757e-09,4.99572e-11,4.99572e-11,5.84517e-09,8.44763e-12,2.93928e-09,2.93928e-09,2.93928e-09,1.57646e-11,8.54048e-10,2.36054e-12,2.0383e-12,3.4736e-11,2.05038e-09,1.12985e-13,8.04059e-09,8.04059e-09,8.04059e-09,5.92353e-11,5.92353e-11,5.18856e-09,3.32109e-14,6.99956e-11,6.99956e-11,4.36248e-08,4.36248e-08,4.36248e-08,4.36248e-08,4.36248e-08,1.59943e-08,8.85289e-11,2.80591e-09,1.02153e-09", "train/minibatch_size": "16384,4096,4096,8192,16384,4096,4096,8192,65536,16384,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,16384,4096,4096,4096,4096,4096,8192,8192,4096,4096,16384,16384,16384,4096,4096,16384,16384,4096,16384,32768,4096,4096,4096,4096,4096,16384,16384,4096,4096,4096,4096,4096,4096,4096,32768,4096,32768,4096", "train/horizon": "64,512,512,64,256,64,256,128,64,128,64,256,256,256,256,256,64,64,64,256,256,256,256,256,1024,1024,1024,1024,256,32,32,32,128,128,128,128,256,256,128,128,128,256,64,64,256,64,64,128,256,256,256,128,128,64,128,64,64,128,128,128,128,128,512,32,128,128", "train/vtrace_rho_clip": "2.88138,3.57543,3.57543,3.30068,4.34963,3.96122,5,3.17479,2.83067,3.36168,2.44524,2.6691,2.6691,2.6691,2.6691,2.6691,1.57951,1.57951,1.57951,3.22396,3.22396,3.22396,3.22396,3.22396,2.34891,2.34891,2.34891,2.34891,4.04418,4.22621,4.22621,4.22621,3.4147,3.4147,3.14726,3.14726,4.28424,2.51901,2.18666,2.18666,2.18666,2.51157,2.10344,2.10428,3.77374,0.47455,1.79867,3.30932,3.14107,3.14107,3.14107,3.54409,3.54409,4.36813,2.1731,3.74916,3.74916,2.52867,2.52867,2.52867,2.52867,2.52867,1.29232,4.10417,3.22147,4.2482", "train/vtrace_c_clip": "0.1,0.59892,0.59892,0.468331,0.1,0.1,1.21513,1.03063,1.20504,0.1,0.408429,0.509814,0.509814,0.509814,0.509814,0.509814,0.708434,0.708434,0.708434,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.257275,0.394156,0.394156,0.394156,0.1,0.1,0.1,0.1,0.1,0.1,0.638156,0.638156,0.638156,0.1,0.1,0.1,0.1,0.1,0.389606,0.1,0.1,0.1,0.1,0.1,0.1,1.07676,0.1,0.1,0.1,0.167431,0.167431,0.167431,0.167431,0.167431,2.95764,0.1,0.494833,0.1", "train/prio_alpha": "0.186009,0.364489,0.364489,0,0,0.248565,0,0.192092,0.777755,0.185697,0.15841,0.369759,0.369759,0.369759,0.369759,0.369759,0.186654,0.186654,0.186654,0.420125,0.420125,0.420125,0.420125,0.420125,0.235053,0.235053,0.235053,0.235053,0.220797,0,0,0,0.127389,0.127389,0.154959,0.154959,0.103504,0.114091,0,0,0,0.440681,0,0.241972,0.175774,0.066254,0.198126,0.321465,0.189832,0.189832,0.189832,0,0,0,0.33242,0,0,0.630507,0.630507,0.630507,0.630507,0.630507,0.833523,0,0.193656,0", "train/prio_beta0": "1,1,1,0.909515,1,1,0.71313,1,0.558592,0.777128,0.66464,0.740368,0.740368,0.740368,0.740368,0.740368,0.72787,0.72787,0.72787,0.967425,0.967425,0.967425,0.967425,0.967425,0.899545,0.899545,0.899545,0.899545,1,0.692111,0.692111,0.692111,1,1,1,1,0.897374,1,0.809042,0.809042,0.809042,0.892539,0.98864,1,0.991342,0.626271,0.59752,0.877153,0.83125,0.83125,0.83125,0.952673,0.952673,0.781807,1,1,1,0.785757,0.785757,0.785757,0.785757,0.785757,0.0133288,1,0.821874,0.575361", "no_model_upload": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "tsne1": "31.2898,29.7959,29.7959,30.4929,30.1831,30.056,26.9538,32.2796,-4.50363,31.5314,32.4447,31.1309,31.1309,31.1309,31.1309,31.1309,32.7891,32.7891,32.7892,30.6375,30.6371,30.6375,30.6371,30.6371,29.3811,29.3819,29.3819,29.3811,30.7568,29.4567,29.4567,29.4567,29.9892,29.9892,32.3416,32.3416,30.6985,31.9556,27.8677,27.8677,27.8677,32.6169,30.9266,32.0799,31.4886,33.273,26.9665,31.7817,30.8477,30.8477,30.8477,31.214,31.214,29.0837,31.2929,30.865,30.865,32.1319,32.1319,32.1319,32.1319,32.1323,14.6298,30.1531,28.2243,26.9394", "tsne2": "-21.5015,-29.3211,-29.3211,-22.8157,-21.8123,-25.1674,-25.7452,-21.6835,19.7938,-22.1921,-27.7456,-27.9353,-27.9353,-27.9353,-27.9353,-27.9353,-26.8407,-26.8407,-26.8411,-29.231,-29.2305,-29.231,-29.2305,-29.2305,-27.7237,-27.724,-27.724,-27.7237,-21.3466,-23.892,-23.892,-23.892,-26.202,-26.202,-23.0294,-23.0294,-25.9469,-24.2185,-22.1467,-22.1467,-22.1467,-24.2657,-23.5357,-21.596,-21.5934,-26.6104,-22.4619,-21.2267,-27.0328,-27.0328,-27.0328,-24.3618,-24.3618,-22.134,-20.7663,-23.4603,-23.4603,-30.0234,-30.0234,-30.0234,-30.0234,-30.0228,32.0645,-23.6888,-21.8817,-25.7422"}, "maze": {"SPS": "1.16829e+06,1.17082e+06,2.11362e+06,2.11568e+06,808718,558917,556979,558115,2.0516e+06,2.05272e+06,6.22045e+06,4.31165e+06,4.28166e+06,4.29257e+06,1.55863e+06,2.84473e+06,8.14008e+06,297006,4.28242e+06,2.70517e+06,1.38044e+06,949658,4.73861e+06,356415,2.95074e+06,2.94168e+06,783224,777936,776746,720311,2.35182e+06,2.35045e+06,2.34883e+06,2.97925e+06,653096,1.15704e+06,1.18202e+06,667072,675534,688770,693718,216882,1.33016e+07,3.12632e+06,1.62934e+06,1.63039e+06,1.0042e+06,3.21433e+06,1.4814e+06,5.91214e+06,237357,237461,237028,236960,237289,529048,4.13917e+06,214727,214375,309798,5.15944e+06,1.49382e+06,1.49404e+06,1.59085e+06,1.58734e+06,5.1942e+06,486643,1.49547e+06,1.50516e+06,1.50385e+06,1.50417e+06,2.24285e+06,2.1201e+06,222604,222486,224687,224720,2.13626e+06,5.74783e+06,5.74982e+06,1.16618e+06,1.17205e+06,1.17217e+06,2.60137e+06,2.47091e+06,2.47017e+06,2.48078e+06,2.45811e+06,3.70452e+06,3.67661e+06,945951,3.34062e+06,3.36107e+06,1.93289e+06,1.93396e+06,6.00253e+06,5.83333e+06,419654,4.07987e+06,3.24763e+06,3.88414e+06,1.33172e+06,1.33166e+06,1.33437e+06,4.57477e+06,606421,2.08884e+06,831237,830744,999294,971155,3.99332e+06,4.46369e+06,3.63822e+06,3.63156e+06,4.0035e+06,1.24141e+06", "agent_steps": "64.8806,108.069,123.732,173.146,244.056,86.1798,143.589,200.999,47.3825,78.9053,37.5521,186.909,261.62,298.844,151.781,29.6223,62.6524,122.552,80.3471,37.5521,24.0845,74.0557,37.7487,20.054,60.6863,101.057,22.5444,67.5021,112.46,126.845,37.5521,62.5213,87.4906,24.3794,85.8522,34.6685,106.168,126.812,211.288,295.764,337.904,267.452,15.4665,48.3656,142.475,199.426,70.4512,37.7487,29.8844,55.8367,24.1172,72.1551,120.193,168.231,192.152,94.0769,51.5113,253.297,289.407,78.7087,105.251,79.102,131.793,154.042,246.415,88.5391,61.3417,37.4211,112.067,186.712,261.358,3.2768,36.0448,293.208,335.02,56.4265,93.9131,171.639,61.3417,102.105,129.892,181.666,207.356,105.906,77.5291,129.171,180.814,206.569,52.4288,87.294,58.7203,52.3633,87.2284,142.803,199.885,45.6131,75.7596,29.5567,95.2893,48.1034,37.5521,46.7927,77.9223,109.052,30.2776,86.7369,180.879,91.3572,152.175,83.755,29.7861,55.9677,58.7858,73.1382,121.635,170.131,60.031", "uptime": "55.3794,92.2943,58.1556,81.526,313.205,156.301,259.21,362.161,22.8513,38.2129,5.91038,43.2002,60.7474,69.4196,97.1501,10.533,7.58557,414.897,18.6714,13.5392,17.5051,77.733,8.0164,56.2063,20.1373,33.8398,28.7301,86.4199,144.279,176.112,15.8552,26.4802,37.1053,8.16668,131.087,29.875,89.7471,190.201,316.588,439.925,501.203,1231.96,1.23605,15.2647,87.4061,122.343,70.151,11.5891,20.1041,9.32754,101.528,303.903,506.477,709.195,810.152,180.058,12.2346,1177.98,1346.14,253.549,20.366,52.1167,87.417,95.877,153.958,16.9768,126.954,25.2706,74.8511,124.519,174.195,1.45742,17.0207,1324.21,1512.02,250.296,417.114,79.9146,10.6205,17.7031,111.739,156.03,177.946,40.2949,31.224,52.1303,73.0677,83.4869,13.8421,23.2962,62.6501,15.2913,25.6923,73.931,103.457,7.63914,12.6504,70.3902,23.1334,14.478,9.43345,34.9283,58.3585,81.7137,6.61229,142.331,86.7804,109.602,182.773,83.4897,30.5227,13.7986,12.9348,19.6646,33.0169,45.998,48.4922", "epoch": "495,824.5,472,660.5,1862,657.5,1095.5,1533.5,361.5,602,286.5,713,998,1140,1158,226,239,935,613,286.5,367.5,282.5,144,153,231.5,385.5,172,515,858,1935.5,286.5,477,667.5,93,327.5,264.5,405,967.5,1612,2256.5,2578,2040.5,29.5,184.5,1087,1521.5,537.5,144,114,213,184,550.5,917,1283.5,1466,1435.5,196.5,1932.5,2208,600.5,401.5,603.5,1005.5,2350.5,3760,675.5,468,285.5,855,1424.5,1994,25,275,2237,2556,430.5,716.5,1309.5,468,779,495.5,693,791,808,591.5,985.5,1379.5,1576,200,333,224,399.5,665.5,1089.5,1525,174,289,225.5,363.5,183.5,286.5,357,594.5,832,115.5,1323.5,690,348.5,580.5,319.5,454.5,213.5,448.5,279,464,649,458", "env/perf": "0.761396,0.872843,0.840234,0.875284,0.965615,0.870705,0.963988,0.979342,0.669442,0.786503,0.388874,0.852175,0.869803,0.870255,0.885999,0.398664,0.480222,0.88893,0.706061,0.49124,0.400198,0.775139,0.586663,0.370711,0.74212,0.796167,0.40112,0.768313,0.886019,0.886473,0.665469,0.758452,0.798025,0.395352,0.831611,0.491218,0.830874,0.952569,0.984538,0.992337,0.993037,0.98786,0.0626051,0.614609,0.885485,0.909848,0.772641,0.533012,0.442984,0.630387,0.464941,0.881883,0.953347,0.976655,0.977422,0.885067,0.644482,0.987248,0.988511,0.811251,0.744129,0.818158,0.885672,0.885759,0.926544,0.731811,0.752106,0.47918,0.866218,0.923874,0.948156,0.366883,0.464223,0.991824,0.992872,0.801665,0.911341,0.870624,0.661941,0.738179,0.908185,0.933806,0.938982,0.807236,0.781581,0.852902,0.875505,0.876934,0.700124,0.755401,0.718488,0.675641,0.748554,0.858905,0.893716,0.491161,0.663281,0.439515,0.775649,0.601595,0.483941,0.683976,0.800087,0.850719,0.442432,0.856586,0.880133,0.842269,0.926958,0.830738,0.424434,0.677181,0.682525,0.731249,0.826473,0.846118,0.706817", "env/score": "0.761396,0.872843,0.840234,0.875284,0.965615,0.870705,0.963988,0.979342,0.669442,0.786503,0.388874,0.852175,0.869803,0.870255,0.885999,0.398664,0.480222,0.88893,0.706061,0.49124,0.400198,0.775139,0.586663,0.370711,0.74212,0.796167,0.40112,0.768313,0.886019,0.886473,0.665469,0.758452,0.798025,0.395352,0.831611,0.491218,0.830874,0.952569,0.984538,0.992337,0.993037,0.98786,0.0626051,0.614609,0.885485,0.909848,0.772641,0.533012,0.442984,0.630387,0.464941,0.881883,0.953347,0.976655,0.977422,0.885067,0.644482,0.987248,0.988511,0.811251,0.744129,0.818158,0.885672,0.885759,0.926544,0.731811,0.752106,0.47918,0.866218,0.923874,0.948156,0.366883,0.464223,0.991824,0.992872,0.801665,0.911341,0.870624,0.661941,0.738179,0.908185,0.933806,0.938982,0.807236,0.781581,0.852902,0.875505,0.876934,0.700124,0.755401,0.718488,0.675641,0.748554,0.858905,0.893716,0.491161,0.663281,0.439515,0.775649,0.601595,0.483941,0.683976,0.800087,0.850719,0.442432,0.856586,0.880133,0.842269,0.926958,0.830738,0.424434,0.677181,0.682525,0.731249,0.826473,0.846118,0.706817", "env/episode_return": "0.761396,0.872843,0.840234,0.875284,0.965615,0.870705,0.963988,0.979342,0.669442,0.786503,0.388874,0.852175,0.869803,0.870255,0.885999,0.398664,0.480222,0.88893,0.706061,0.49124,0.400198,0.775139,0.586663,0.370711,0.74212,0.796167,0.40112,0.768313,0.886019,0.886473,0.665469,0.758452,0.798025,0.395352,0.831611,0.491218,0.830874,0.952569,0.984538,0.992337,0.993037,0.98786,0.0626051,0.614609,0.885485,0.909848,0.772641,0.533012,0.442984,0.630387,0.464941,0.881883,0.953347,0.976655,0.977422,0.885067,0.644482,0.987248,0.988511,0.811251,0.744129,0.818158,0.885672,0.885759,0.926544,0.731811,0.752106,0.47918,0.866218,0.923874,0.948156,0.366883,0.464223,0.991824,0.992872,0.801665,0.911341,0.870624,0.661941,0.738179,0.908185,0.933806,0.938982,0.807236,0.781581,0.852902,0.875505,0.876934,0.700124,0.755401,0.718488,0.675641,0.748554,0.858905,0.893716,0.491161,0.663281,0.439515,0.775649,0.601595,0.483941,0.683976,0.800087,0.850719,0.442432,0.856586,0.880133,0.842269,0.926958,0.830738,0.424434,0.677181,0.682525,0.731249,0.826473,0.846118,0.706817", "env/episode_length": "684.794,447.618,531.47,440.603,200.818,454.404,216.023,154.704,874.097,660.221,1269.01,491.385,443.37,445.011,400.177,1199,1149.44,400.497,810.347,1138.41,1174.1,650.694,995.959,1204.09,739.252,623.117,1170.35,671.308,405.638,407.798,877.557,703.683,616.437,855.673,562.307,1023.05,542.121,250.308,128.98,95.7828,92.7216,112.109,1248.59,969.95,443.001,378.081,662.828,1088.65,1089.21,933.774,1111.69,433.09,233.049,154.616,149.207,425.394,912.69,135.463,133.214,607.925,715.433,582.494,420.974,420.626,319.072,791.99,719.613,1073.98,466.684,306.305,230.823,204.283,1085.05,119.507,111.708,605.909,350.295,450.256,887.362,753.826,384.6,314.725,295.41,613.27,655.629,494.198,434.509,431.12,823.567,715.7,782.2,874.081,725.202,478.398,399.276,1142.04,869.974,1130.12,678.002,967.428,1166.57,827.796,605.363,496.531,1012.71,485.94,420.826,528.977,313.125,540.377,1139.28,870.885,843.281,780.03,573.854,517.908,772.307", "env/n": "195.337,297.294,496.947,596.793,10615,314.016,623.97,849.783,153.467,199.813,103.432,536.589,592.933,10274,330.622,110.953,228.179,347.209,161.988,117.3,58.7466,410.08,265.632,108.413,355.818,421.779,112.749,198.927,329.009,163.581,151.447,187.424,212.311,204.081,494.908,131.47,493.212,557.208,1037.73,1371.9,11202,1172.83,331.086,274.918,299.069,346.818,201.768,245.958,237.559,284.106,127.499,316.68,581.341,850.59,10807,165.642,288.385,969.152,10793,222.387,365.319,229.575,313.373,158.801,10006,165.785,186.952,134.202,285.629,434.886,569.206,83.4286,129.053,1101.2,10662,224.773,378.472,293.569,149.238,174.585,689.157,835.543,10456,214.149,202.855,265.931,302.208,10019,318.564,366.436,339.43,151.861,180.812,277.548,329.191,235.339,301.27,120.489,389.5,274.951,115.016,160.042,220.109,263.662,231.304,140.778,623.863,516.03,849.599,488.414,61.7048,302.43,156.252,343.914,458.324,505.389,171.439", "perf/rollout": "0.0222733,0.0220799,0.037505,0.0373778,0.0397573,0.0489267,0.0497087,0.0489032,0.0215074,0.021457,0.0142767,0.0272901,0.027844,0.0276177,0.022018,0.0221775,0.0200227,0.0837187,0.0125204,0.0260517,0.0190052,0.058379,0.017225,0.0518943,0.0504442,0.050718,0.0354162,0.0365423,0.0367022,0.018944,0.018543,0.0185729,0.0186105,0.019633,0.0670225,0.0212681,0.049944,0.0454906,0.0428789,0.0392611,0.0379934,0.0706688,0.0352405,0.0346797,0.026609,0.0265493,0.0219948,0.0435621,0.0460425,0.020532,0.0683409,0.0678967,0.0685886,0.0678376,0.0686464,0.0362695,0.0306178,0.0808311,0.0804722,0.0531648,0.0209955,0.0370551,0.0370166,0.0189379,0.0190494,0.0134677,0.0469717,0.0211862,0.0204236,0.0204645,0.020324,0.0170983,0.0259323,0.0644319,0.0648909,0.0750794,0.0749882,0.0244518,0.0122187,0.0122094,0.0359117,0.0351683,0.0350933,0.019897,0.017272,0.017281,0.0169714,0.0175989,0.0382832,0.0388094,0.0673108,0.0223958,0.0221555,0.0237599,0.0236374,0.0197861,0.0213852,0.0415788,0.031352,0.0398069,0.0197468,0.0239832,0.024048,0.0239314,0.0210005,0.0231919,0.0303793,0.0379838,0.0381739,0.0521858,0.0231151,0.0309674,0.0207282,0.0354533,0.0355918,0.0289335,0.0249405", "perf/eval_gpu": "0.011344,0.0113053,0.00815954,0.00817006,0.0182936,0.0255037,0.0257596,0.0252498,0.00439181,0.00437449,0.00122477,0.00540329,0.00544131,0.00530946,0.00792449,0.00760581,0.00217525,0.0518196,0.00275139,0.00284773,0.00784644,0.0253142,0.00298229,0.039306,0.00354151,0.00354242,0.0167208,0.0166759,0.0166678,0.0111773,0.00403678,0.00404347,0.00404774,0.00360538,0.0298153,0.00781743,0.0177791,0.0221105,0.0225085,0.0225188,0.022385,0.0518662,0.00519193,0.00694839,0.00863646,0.00853986,0.00994506,0.00575378,0.0101987,0.00258324,0.0500573,0.0491249,0.0486582,0.0491165,0.0481582,0.0211427,0.00310455,0.06091,0.0616476,0.0393438,0.00286165,0.00639881,0.00643049,0.00727206,0.00721177,0.00241861,0.020313,0.00950226,0.00871024,0.00868901,0.00866338,0.00369856,0.00631236,0.0382769,0.038479,0.0462161,0.0463555,0.00758083,0.00236268,0.00236345,0.0127782,0.0128124,0.0128992,0.00339813,0.00411228,0.00411858,0.00420849,0.00417566,0.00300827,0.00301007,0.0254252,0.00298626,0.00295348,0.00757092,0.00760973,0.0030799,0.00306683,0.0266558,0.00363877,0.00538562,0.00320703,0.00900607,0.00906687,0.00902433,0.00330857,0.0125704,0.00785252,0.0156087,0.0156507,0.0210946,0.0092834,0.00352578,0.00238939,0.00343756,0.00344233,0.00350925,0.0109236", "perf/eval_env": "0.007681,0.00766628,0.0228681,0.0221949,0.0177815,0.0155001,0.0157805,0.0147734,0.016173,0.016147,0.0106847,0.0197917,0.0203311,0.0204093,0.0123612,0.0121213,0.0167299,0.010818,0.00865469,0.0163961,0.0065756,0.0238012,0.0129073,0.00975696,0.045046,0.0453026,0.0162925,0.0174965,0.0176417,0.00522566,0.0121829,0.0112732,0.0113015,0.0147405,0.0341581,0.0123795,0.0214641,0.0138293,0.0118506,0.0108942,0.0104876,0.00929337,0.0269598,0.0173152,0.0111185,0.0119636,0.0084562,0.0308759,0.026449,0.0167934,0.0092628,0.00973713,0.0102163,0.0101483,0.0111808,0.00667747,0.0256922,0.0104188,0.00963317,0.0107411,0.0169679,0.0269424,0.0261447,0.00685709,0.00688732,0.00998615,0.0253374,0.00849934,0.00881335,0.00888016,0.00882233,0.0128775,0.0138226,0.0230915,0.0232318,0.0267881,0.0265897,0.0111245,0.00858166,0.00857574,0.0204236,0.0197685,0.0196202,0.0111303,0.00943609,0.00952211,0.00961649,0.010617,0.0241597,0.0242466,0.0378309,0.0173446,0.0172353,0.0100219,0.0105745,0.0150204,0.0153607,0.0126339,0.0265354,0.0331553,0.013708,0.0131225,0.0128708,0.0128927,0.0164289,0.00655141,0.0204731,0.0201475,0.0201013,0.027361,0.0123448,0.0250051,0.0120828,0.028047,0.0277793,0.0193859,0.0121187", "perf/train_misc": "0.000867186,0.000867374,0.00136082,0.0013608,0.00110099,0.00142842,0.00143099,0.00143623,0.000913221,0.000913192,0.000925021,0.00120894,0.00120856,0.00120237,0.00105381,0.000938812,0.00164759,0.00331054,0.000675576,0.00143767,0.000742426,0.00206122,0.00334766,0.00157001,0.00221125,0.00221327,0.00152593,0.00147922,0.0014844,0.000745934,0.00127103,0.00126986,0.0012701,0.00297956,0.00207971,0.00113979,0.00275929,0.0020517,0.00205765,0.00206151,0.00203571,0.00138081,0.00110974,0.00161149,0.00093217,0.000931123,0.000956381,0.00207073,0.00189856,0.00219914,0.00253115,0.00245621,0.00246015,0.00246578,0.00246784,0.0010546,0.00231817,0.00142079,0.00142336,0.00114629,0.0021119,0.000792571,0.000791633,0.000443024,0.000434176,0.000820778,0.00104451,0.0015629,0.001533,0.00153283,0.00153343,0.00313525,0.00157599,0.0020662,0.00205722,0.00102448,0.00102499,0.000829588,0.000737623,0.00073721,0.00200247,0.00200134,0.00200602,0.000816528,0.000794559,0.000794631,0.00079211,0.000786432,0.00293982,0.00293934,0.00155702,0.000899504,0.00089955,0.000969671,0.000971727,0.00187344,0.00187399,0.000736873,0.00233236,0.00172893,0.000633744,0.00147991,0.00148025,0.00147976,0.00190156,0.000743415,0.00233672,0.00235779,0.00235871,0.00207964,0.000311644,0.00202239,0.000623314,0.00208153,0.00207889,0.00207914,0.000945701", "perf/train_forward": "0.0890019,0.0889778,0.0849559,0.0849631,0.121032,0.184132,0.18428,0.184492,0.0412883,0.0412993,0.00565474,0.0320394,0.0320476,0.0321362,0.0608416,0.0247562,0.0103054,0.354203,0.0172151,0.0207397,0.0280633,0.215384,0.0344787,0.325678,0.0358443,0.0358524,0.134237,0.130212,0.130316,0.071141,0.0356376,0.0356379,0.0356383,0.0691455,0.332401,0.0925475,0.168845,0.148733,0.148708,0.148676,0.148865,0.53249,0.00470082,0.0472183,0.0527188,0.0527294,0.107213,0.0356896,0.135106,0.0213647,0.495524,0.481695,0.482179,0.482556,0.483918,0.0861629,0.0300543,0.528364,0.52609,0.368146,0.0274599,0.0497021,0.0497277,0.0215677,0.0215716,0.0107621,0.221238,0.0660969,0.0649113,0.0649072,0.0649086,0.0470791,0.0348325,0.522531,0.521726,0.507687,0.508131,0.0358873,0.00966314,0.00966386,0.186603,0.1865,0.186719,0.0294061,0.034695,0.0347028,0.0347117,0.0347034,0.0292047,0.0291954,0.208468,0.0156649,0.015668,0.0428498,0.0428571,0.0216395,0.021656,0.278241,0.0303135,0.0389638,0.0131034,0.0726068,0.0726201,0.0726104,0.0359829,0.0840289,0.0925642,0.274996,0.275024,0.207954,0.0445075,0.0324164,0.00776307,0.0341753,0.0341854,0.0341737,0.079525", "perf/train": "0.0898691,0.0898452,0.0863167,0.0863239,0.122133,0.18556,0.185711,0.185929,0.0422015,0.0422125,0.00657976,0.0332483,0.0332562,0.0333386,0.0618954,0.025695,0.011953,0.357513,0.0178907,0.0221774,0.0288057,0.217446,0.0378263,0.327248,0.0380556,0.0380657,0.135762,0.131691,0.131801,0.0718869,0.0369086,0.0369078,0.0369084,0.072125,0.334481,0.0936873,0.171605,0.150785,0.150765,0.150738,0.150901,0.53387,0.00581055,0.0488298,0.053651,0.0536605,0.108169,0.0377603,0.137004,0.0235638,0.498055,0.484151,0.484639,0.485022,0.486386,0.0872175,0.0323725,0.529784,0.527514,0.369292,0.0295718,0.0504947,0.0505193,0.0220107,0.0220058,0.0115829,0.222283,0.0676598,0.0664443,0.06644,0.0664421,0.0502143,0.0364084,0.524597,0.523783,0.508711,0.509156,0.0367169,0.0104008,0.0104011,0.188605,0.188501,0.188725,0.0302226,0.0354895,0.0354975,0.0355038,0.0354898,0.0321445,0.0321348,0.210025,0.0165644,0.0165675,0.0438194,0.0438289,0.0235129,0.02353,0.278978,0.0326459,0.0406927,0.0137372,0.0740867,0.0741004,0.0740902,0.0378845,0.0847723,0.0949009,0.277353,0.277383,0.210034,0.0448191,0.0344388,0.00838639,0.0362568,0.0362643,0.0362528,0.0804707", "util/gpu_percent": "99.2128,99.6758,92.6508,92.9415,97,98.8379,99.0936,98.9132,81.8792,82.2656,57.6211,86.8,88.3684,88,96.4924,84.5211,68.2737,99.8491,91.8816,63.0053,96.4074,99.3883,92.2947,99.1377,56.5195,56.3117,93.9271,92.5539,92.6239,99.199,93.0895,92.466,92.3737,90.3189,94.6927,94.7462,98.9033,98.0978,98.4419,99.3509,100,99.9519,55.2414,87.7623,94.7471,96.0207,98.9106,70.9895,90.2247,78.5745,99.7902,99.8224,99.8093,99.8852,100,99.1579,75.8385,99.8714,100,99.4025,83.1063,71.6592,71.4726,92.8255,92,79.0037,90.2765,97.8737,98.9578,98.8842,98.4112,80.3469,86.8488,99.6682,99,96.2657,96.7972,95.584,84.5659,84.9068,97.0152,98.198,96,83.9412,94.5711,94.5305,91.6371,95,64.0526,66.6316,87.604,67.9286,68.4774,95.3647,94.1402,86.0696,84.5478,99.3356,65.095,64.877,76.7526,97.0675,95.3487,96.6582,86.6174,98.9909,96.0812,99.0862,99.1595,98.5078,88.2643,76.8451,55.9866,70.4649,71.2162,74.7081,98.4754", "util/gpu_mem": "14.6192,14.6192,30.463,30.463,15.9789,19.0566,19.0566,19.0566,9.00123,9.00123,5.81771,8.9361,8.9361,8.9361,10.4912,22.8716,6.07011,18.7635,7.49496,5.64673,7.69851,18.0388,6.72961,14.6111,7.33212,7.33212,10.3854,10.3854,10.3854,10.7925,23.3225,23.3225,23.3225,10.1004,20.0825,10.4668,13.1211,11.7125,11.7125,11.7125,11.7125,33.8099,6.89245,9.44904,11.0693,11.0693,14.3505,7.26699,27.9553,21.7999,18.3401,18.3401,18.3401,18.3401,18.3401,11.9486,7.38097,32.9631,32.9631,23.0217,7.18557,11.0937,11.0937,9.55489,9.55489,6.15967,36.8871,8.44758,8.44758,8.44758,8.44758,6.64819,6.46907,27.1738,26.0478,30.4473,30.4473,10.247,6.34694,6.34694,14.4157,14.4157,14.4157,24.2181,10.0108,10.0108,10.0108,10.0108,6.15153,6.15153,18.0144,6.6889,6.6889,10.247,10.247,6.85174,6.85174,26.8811,6.78661,8.20332,23.0945,8.46386,8.46386,8.46386,7.82064,11.8998,23.9087,16.5082,16.5082,16.728,15.1077,7.94277,6.15967,7.73922,7.73922,7.73922,28.8428", "util/vram_used_gb": "3.04578,3.04578,6.84644,6.84644,3.37195,4.11023,4.11023,4.11023,1.69812,1.69812,0.934448,1.6825,1.6825,1.6825,2.05554,5.02538,0.994995,4.03992,1.33679,0.893433,1.38562,3.86609,1.1532,3.04382,1.29773,1.29773,2.03015,2.03015,2.03015,2.12781,5.13354,5.13354,5.13354,1.96179,4.35632,2.04968,2.6864,2.34851,2.34851,2.34851,2.34851,7.64929,1.19226,1.80554,2.19421,2.19421,2.98132,1.2821,6.24487,4.76831,3.93835,3.93835,3.93835,3.93835,3.93835,2.40515,1.30945,7.44617,7.44617,5.0614,1.26257,2.20007,2.20007,1.83093,1.83093,1.01648,8.38745,1.56531,1.56531,1.56531,1.56531,1.13367,1.0907,6.05741,5.78729,6.84265,6.84265,1.99695,1.0614,1.0614,2.99695,2.99695,2.99695,5.34839,1.94031,1.94031,1.94031,1.94031,1.01453,1.01453,3.86023,1.14343,1.14343,1.99695,1.99695,1.1825,1.1825,5.98718,1.16687,1.50671,5.07886,1.56921,1.56921,1.56921,1.41492,2.39343,5.27417,3.4989,3.4989,3.55164,3.16296,1.44421,1.01648,1.39539,1.39539,1.39539,6.45776", "util/vram_total_gb": "23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272", "util/cpu_mem_gb": "1.22192,1.22265,1.15442,1.15448,1.22031,1.32325,1.32387,1.32387,1.14207,1.14207,1.15697,1.18913,1.18937,1.18974,1.1836,1.07579,1.16652,1.67121,1.15337,1.14527,1.20274,1.37031,1.19559,1.21224,1.17454,1.17473,1.1824,1.1824,1.18271,1.20507,1.0973,1.09747,1.09793,1.21071,1.18821,1.15543,1.40541,1.30397,1.30502,1.30583,1.30616,1.53357,1.19486,1.21831,1.22033,1.22125,1.2076,1.19033,1.10889,1.09413,1.36546,1.36574,1.36594,1.36638,1.36692,1.33062,1.19126,1.3964,1.3964,1.21527,1.18083,1.15117,1.15183,1.18985,1.19326,1.1494,1.07755,1.22058,1.22156,1.22286,1.22391,1.18928,1.18956,1.10797,1.10816,1.14774,1.1478,1.22468,1.1545,1.15521,1.19921,1.19965,1.1997,1.08298,1.18489,1.18551,1.18641,1.18685,1.17596,1.17604,1.18119,1.15525,1.15563,1.22431,1.22491,1.19699,1.19699,1.18061,1.16788,1.17007,1.08876,1.19211,1.19236,1.1928,1.17516,1.21502,1.11952,1.2077,1.20849,1.25861,1.14047,1.19722,1.14827,1.19037,1.19065,1.19097,1.12743", "wandb": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "rank": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "world_size": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "gpu_id": "1,1,0,0,4,2,2,2,1,1,3,5,5,5,4,0,2,3,4,5,4,2,4,1,1,1,1,1,1,1,0,0,0,1,1,5,1,2,2,2,2,5,4,1,2,2,4,2,0,0,3,3,3,3,3,2,2,1,1,5,1,1,1,2,2,2,0,4,4,4,4,3,4,0,0,2,2,4,3,3,3,3,3,0,5,5,5,5,2,2,1,4,4,1,1,2,2,1,5,3,0,4,4,4,1,3,0,4,4,5,2,3,1,3,3,3,0", "profile": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "checkpoint_interval": "200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200", "eval_episodes": "10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000", "cudagraphs": "10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10", "seed": "73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73", "vec/total_agents": "1024,1024,2048,2048,512,512,512,512,2048,2048,4096,2048,2048,2048,1024,1024,4096,256,2048,2048,512,1024,4096,1024,4096,4096,1024,1024,1024,512,2048,2048,2048,8192,2048,2048,1024,512,512,512,512,512,4096,2048,1024,1024,1024,2048,2048,4096,512,512,512,512,512,256,4096,512,512,1024,4096,2048,2048,512,512,2048,1024,1024,1024,1024,1024,8192,1024,512,512,1024,1024,1024,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,4096,4096,2048,2048,2048,1024,1024,4096,4096,1024,4096,4096,2048,1024,1024,1024,4096,512,2048,2048,2048,1024,512,4096,2048,4096,4096,4096,1024", "vec/num_buffers": "7.02416,7.02416,7.60713,7.60713,3.69499,5.24494,5.24494,5.24494,3.60196,3.60196,7.35765,5.2668,5.2668,5.2668,4.64014,4.73744,6.99469,8,6.35467,4.90078,6.81162,7.59471,8,5.73769,4.64705,4.64705,3.10881,3.10881,3.10881,5.55379,7.24114,7.24114,7.24114,7.36691,3.55712,4.85235,8,5.96311,5.96311,5.96311,5.96311,8,6.66194,7.46443,6.04224,6.04224,6.01589,5.73479,5.81904,6.5034,7.32192,7.32192,7.32192,7.32192,7.32192,6.82017,7.56976,7.28837,7.28837,5.21086,6.54295,3.64705,3.64705,5.15738,5.15738,5.99346,2.54239,6.07406,6.07406,6.07406,6.07406,3.02135,5.3623,2.4644,2.4644,2.70742,2.70742,7.22773,6.249,6.249,5.89008,5.89008,5.89008,6.50087,8,8,8,8,5.28431,5.28431,3.13313,5.01954,5.01954,7.31432,7.31432,7.55147,7.55147,4.02592,4.51052,3.25023,6.62779,4.28758,4.28758,4.28758,6.601,5.29944,5.9169,5.46257,5.46257,4.38072,2.78637,7.48512,5.06044,6.05229,6.05229,6.05229,4.15821", "vec/num_threads": "2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2", "env/max_size": "47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47", "env/num_maps": "8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192", "env/map_size": "-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1", "policy/hidden_size": "512,512,256,256,512,512,512,512,256,256,128,128,128,128,256,256,128,1024,256,128,256,512,128,1024,128,128,512,512,512,512,256,256,256,256,512,512,256,512,512,512,512,1024,128,256,256,256,512,128,512,128,1024,1024,1024,1024,1024,512,128,1024,1024,1024,128,256,256,256,256,128,512,256,256,256,256,256,128,1024,1024,1024,1024,256,128,128,512,512,512,256,256,256,256,256,128,128,512,128,128,256,256,64,64,1024,128,128,128,256,256,256,256,512,256,512,512,512,512,128,128,128,128,128,256", "policy/num_layers": "4.54523,4.54523,4.91105,4.91105,5.10404,6.11121,6.11121,6.11121,4.23237,4.23237,1.93196,3.93009,3.93009,3.93009,5.06946,2.97111,1.81211,4.97891,2.00414,3.34238,4.5698,5.22357,3.77429,4.05693,4.57601,4.57601,5.61774,5.61774,5.61774,5.0778,4.44056,4.44056,4.44056,4.78117,7.2347,5.49867,5.31038,5.88042,5.88042,5.88042,5.88042,6.99986,1.30293,3.1078,5.61327,5.61327,4.11883,3.95971,3.59286,2.99603,5.90249,5.90249,5.90249,5.90249,5.90249,5.0941,3.46911,6.16077,6.16077,4.15355,3.72711,6.58366,6.58366,4.21659,4.21659,2.09218,8,5.54785,5.54785,5.54785,5.54785,7.65063,4.24216,6.2164,6.2164,6.6446,6.6446,4.55412,2.2581,2.2581,4.1578,4.1578,4.1578,3.40466,4.51958,4.51958,4.51958,4.51958,3.15809,3.15809,6.32269,3.31204,3.31204,4.57482,4.57482,4.3605,4.3605,5.47537,3.38641,6.51457,4.53267,6.18876,6.18876,6.18876,2.22291,6.15416,4.66877,5.62255,5.62255,5.8277,5.46866,4.05216,2.63926,4.04446,4.04446,4.04446,8", "policy/expansion_factor": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "legacy/torch_deterministic": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "legacy/cpu_offload": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "legacy/compile": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "legacy/compile_fullgraph": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "train/gpus": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "train/seed": "42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42", "train/total_timesteps": "172.868,172.868,197.906,197.906,244.1,229.646,229.646,229.646,126.117,126.117,100,298.903,298.903,298.903,242.82,236.365,100,326.713,128.408,100,192.276,196.91,100,159.913,161.548,161.548,179.943,179.943,179.943,202.906,100,100,100,193.557,228.501,276.548,282.474,337.992,337.992,337.992,337.992,305.651,121.331,128.574,227.879,227.879,187.824,100,238.211,148.438,192.161,192.161,192.161,192.161,192.161,250.69,136.861,289.471,289.471,209.656,168.281,210.864,210.864,246.42,246.42,141.585,163.357,298.652,298.652,298.652,298.652,128.051,287.822,335.109,335.109,150.101,150.101,274.504,163.27,163.27,207.399,207.399,207.399,169.315,206.659,206.659,206.659,206.659,139.228,139.228,156.295,139.491,139.491,228.398,228.398,120.885,120.885,235.693,253.785,128.02,100,124.6,124.6,124.6,240.496,231.241,206.601,243.259,243.259,133.748,237.86,148.707,156.499,194.426,194.426,194.426,159.916", "train/learning_rate": "0.00168777,0.00168777,0.00142394,0.00142394,0.000888893,0.000903435,0.000903435,0.000903435,0.000946142,0.000946142,0.00226719,0.00108928,0.00108928,0.00108928,0.00107575,0.00142399,0.00211128,0.00064951,0.00112057,0.000917177,0.000841037,0.000983734,0.00108399,0.000896384,0.00135288,0.00135288,0.000888292,0.000888292,0.000888292,0.000723829,0.00107279,0.00107279,0.00107279,0.00128203,0.00066191,0.000985871,0.000695421,0.000755471,0.000755471,0.000755471,0.000755471,0.000968341,0.000437037,0.00138795,0.000548193,0.000548193,0.000969944,0.00120844,0.00161155,0.00127014,0.000838448,0.000838448,0.000838448,0.000838448,0.000838448,0.000772044,0.0016067,0.00108008,0.00108008,0.000684398,0.00105883,0.00131503,0.00131503,0.000837583,0.000837583,0.00131948,0.000809496,0.000816107,0.000816107,0.000816107,0.000816107,0.0211585,0.000755556,0.000560376,0.000560376,0.00120444,0.00120444,0.00128941,0.0014627,0.0014627,0.000847367,0.000847367,0.000847367,0.00155083,0.00153397,0.00153397,0.00153397,0.00153397,0.00111981,0.00111981,0.00126096,0.00104422,0.00104422,0.000803087,0.000803087,0.00147252,0.00147252,0.00122139,0.00125279,0.00166074,0.00150737,0.000672573,0.000672573,0.000672573,0.00169933,0.000559774,0.000933413,0.000778061,0.000778061,0.00131635,0.00177709,0.00154728,0.00200895,0.00114194,0.00114194,0.00114194,0.0010705", "train/anneal_lr": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "train/min_lr_ratio": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "train/gamma": "0.981954,0.981954,0.989751,0.989751,0.994591,0.996721,0.996721,0.996721,0.995781,0.995781,0.930654,0.99251,0.99251,0.99251,0.98975,0.973798,0.963098,0.988894,0.994578,0.973217,0.987985,0.98735,0.990426,0.969755,0.988982,0.988982,0.995614,0.995614,0.995614,0.993638,0.990683,0.990683,0.990683,0.984314,0.996322,0.990931,0.989561,0.993628,0.993628,0.993628,0.993628,0.99193,0.999615,0.972115,0.996261,0.996261,0.987172,0.996675,0.985349,0.976762,0.990357,0.990357,0.990357,0.990357,0.990357,0.996731,0.960621,0.99663,0.99663,0.98948,0.991452,0.990055,0.990055,0.995933,0.995933,0.993594,0.988969,0.990025,0.990025,0.990025,0.990025,0.999259,0.986323,0.998674,0.998674,0.993194,0.993194,0.983679,0.991399,0.991399,0.994718,0.994718,0.994718,0.987816,0.97983,0.97983,0.97983,0.97983,0.988649,0.988649,0.998077,0.99309,0.99309,0.995993,0.995993,0.97573,0.97573,0.985787,0.993403,0.98892,0.966476,0.981714,0.981714,0.981714,0.98848,0.993851,0.987395,0.994067,0.994067,0.994173,0.98874,0.994738,0.988086,0.991634,0.991634,0.991634,0.99163", "train/gae_lambda": "0.96944,0.96944,0.966362,0.966362,0.9459,0.887765,0.887765,0.887765,0.973624,0.973624,0.959209,0.967397,0.967397,0.967397,0.957872,0.957567,0.968546,0.913293,0.965631,0.985516,0.937909,0.95907,0.96265,0.932373,0.966221,0.966221,0.906707,0.906707,0.906707,0.946392,0.920043,0.920043,0.920043,0.977321,0.960157,0.96537,0.975918,0.942137,0.942137,0.942137,0.942137,0.94241,0.975952,0.947576,0.952455,0.952455,0.929823,0.935629,0.948754,0.964682,0.942011,0.942011,0.942011,0.942011,0.942011,0.927636,0.978543,0.94179,0.94179,0.948568,0.960083,0.954947,0.954947,0.971875,0.971875,0.968521,0.955442,0.958435,0.958435,0.958435,0.958435,0.852673,0.966751,0.948796,0.948796,0.955156,0.955156,0.969961,0.969673,0.969673,0.976594,0.976594,0.976594,0.952577,0.97917,0.97917,0.97917,0.97917,0.944435,0.944435,0.954672,0.941558,0.941558,0.948269,0.948269,0.959734,0.959734,0.918537,0.964498,0.952158,0.946656,0.917068,0.917068,0.917068,0.965316,0.904748,0.969598,0.9526,0.9526,0.955498,0.96783,0.965375,0.960949,0.975487,0.975487,0.975487,0.941974", "train/replay_ratio": "2.64217,2.64217,3.03723,3.03723,2.98983,3.60352,3.60352,3.60352,3.12655,3.12655,2.51521,2.93962,2.93962,2.93962,3.69269,3.17156,2.09993,2.83481,2.31299,2.81686,3.192,2.33315,2.35236,2.53808,2.8153,2.8153,2.80724,2.80724,2.80724,3.16358,2.31925,2.31925,2.31925,2.43705,2.76013,2.09388,3.49093,2.85958,2.85958,2.85958,2.85958,3.45498,0.339435,2.15665,3.11381,3.11381,3.16821,2.82059,2.47583,2.80826,3.2942,3.2942,3.2942,3.2942,3.2942,3.09208,2.90466,3.42078,3.42078,3.32644,2.69854,2.63039,2.63039,3.2574,3.2574,2.93225,3.28443,2.92258,2.92258,2.92258,2.92258,1.32531,2.85426,2.80657,2.80657,3.11762,3.11762,2.64998,2.68867,2.68867,2.67344,2.67344,2.67344,2.93527,2.5985,2.5985,2.5985,2.5985,1.96104,1.96104,2.12294,3.23455,3.23455,3.18879,3.18879,2.29246,2.29246,2.13611,2.91607,2.18751,2.10276,2.81592,2.81592,2.81592,2.25745,3.0091,3.27316,3.15321,3.15321,2.44851,2.2997,2.59403,2.19162,2.66433,2.66433,2.66433,3.08652", "train/clip_coef": "0.129282,0.129282,0.107267,0.107267,0.145179,0.106774,0.106774,0.106774,0.118904,0.118904,0.182304,0.309681,0.309681,0.309681,0.17122,0.119734,0.27151,0.201097,0.211842,0.201131,0.171605,0.140992,0.195992,0.249502,0.189062,0.189062,0.115436,0.115436,0.115436,0.0846799,0.1738,0.1738,0.1738,0.18045,0.114775,0.191316,0.188283,0.1304,0.1304,0.1304,0.1304,0.114107,0.446901,0.133238,0.103844,0.103844,0.134878,0.178223,0.227774,0.258804,0.148349,0.148349,0.148349,0.148349,0.148349,0.214403,0.215463,0.201154,0.201154,0.114233,0.289397,0.0751099,0.0751099,0.146517,0.146517,0.122286,0.130675,0.112016,0.112016,0.112016,0.112016,0.157376,0.140566,0.151328,0.151328,0.0940684,0.0940684,0.164788,0.16575,0.16575,0.202243,0.202243,0.202243,0.157606,0.139215,0.139215,0.139215,0.139215,0.190765,0.190765,0.200782,0.124265,0.124265,0.137859,0.137859,0.134633,0.134633,0.129713,0.144453,0.18931,0.201923,0.136175,0.136175,0.136175,0.291709,0.155734,0.149794,0.179365,0.179365,0.140986,0.112732,0.282118,0.110368,0.112173,0.112173,0.112173,0.17788", "train/vf_coef": "2.1233,2.1233,1.52969,1.52969,4.18645,3.67622,3.67622,3.67622,3.48574,3.48574,3.83424,2.90426,2.90426,2.90426,2.03001,2.22129,3.7546,4.21973,5,3.53938,2.56945,2.97583,2.05273,1.71283,2.69789,2.69789,4.35424,4.35424,4.35424,2.09684,3.79312,3.79312,3.79312,4.08315,4.42091,3.26131,2.78023,3.03966,3.03966,3.03966,3.03966,1.90892,2.37966,3.83882,2.35799,2.35799,1.64647,3.81062,2.07192,3.57021,2.76046,2.76046,2.76046,2.76046,2.76046,3.92205,3.26477,1.92979,1.92979,2.94243,2.95163,4.69454,4.69454,2.09196,2.09196,5,4.7677,3.22498,3.22498,3.22498,3.22498,4.64438,4.14668,4.37098,4.37098,5,5,1.50746,4.63288,4.63288,2.2352,2.2352,2.2352,5,2.07438,2.07438,2.07438,2.07438,4.5156,4.5156,5,2.68468,2.68468,2.32512,2.32512,2.83588,2.83588,5,2.39725,2.93203,4.12791,4.98889,4.98889,4.98889,2.22091,3.95792,1.23988,1.04337,1.04337,5,4.6966,2.99874,5,3.9206,3.9206,3.9206,3.59173", "train/vf_clip_coef": "2.11158,2.11158,2.48508,2.48508,1.28398,0.553268,0.553268,0.553268,2.28403,2.28403,2.63772,0.962528,0.962528,0.962528,1.83599,0.01,2.4084,0.557282,3.0551,1.64754,1.47694,2.03481,3.06083,0.01,1.48974,1.48974,0.432981,0.432981,0.432981,1.73352,0.909508,0.909508,0.909508,3.18133,0.429435,0.01,0.758108,3.48152,3.48152,3.48152,3.48152,1.99353,2.33623,1.69015,3.23433,3.23433,3.31205,0.01,0.01,3.36093,0.01,0.01,0.01,0.01,0.01,2.88891,0.01,3.12374,3.12374,0.01,1.58818,1.33322,1.33322,3.26855,3.26855,2.73014,0.01,2.77788,2.77788,2.77788,2.77788,0.634579,2.10355,0.082196,0.082196,0.0962249,0.0962249,2.83243,2.41752,2.41752,0.01,0.01,0.01,3.55848,3.63843,3.63843,3.63843,3.63843,2.59282,2.59282,0.01,0.0284124,0.0284124,1.61655,1.61655,0.531681,0.531681,0.197112,0.01,1.87997,1.11723,0.01,0.01,0.01,1.66383,2.19947,1.81619,0.877915,0.877915,0.697589,1.42384,2.71359,3.54594,0.664648,0.664648,0.664648,1.48182", "train/max_grad_norm": "2.72562,2.72562,1.77961,1.77961,0.529133,0.908628,0.908628,0.908628,5,5,5,4.43862,4.43862,4.43862,1.45251,4.77437,4.08375,1.14817,0.629042,2.31889,0.979414,1.18776,3.90813,3.08903,5,5,3.02155,3.02155,3.02155,1.18419,4.24468,4.24468,4.24468,3.44029,3.10689,2.98416,0.1,1.41109,1.41109,1.41109,1.41109,2.78624,4.2303,0.420199,1.93038,1.93038,2.6285,4.82729,3.02044,3.36269,0.748381,0.748381,0.748381,0.748381,0.748381,2.56148,4.16729,2.12533,2.12533,3.78647,3.54074,3.31769,3.31769,1.83316,1.83316,0.986734,3.83187,1.35655,1.35655,1.35655,1.35655,0.248629,1.9525,0.362512,0.362512,4.98077,4.98077,0.856446,1.8904,1.8904,4.17896,4.17896,4.17896,0.1,1.72249,1.72249,1.72249,1.72249,2.00481,2.00481,4.22541,5,5,0.138498,0.138498,3.9445,3.9445,4.78538,5,3.58412,2.73197,3.12532,3.12532,3.12532,3.99657,0.1,2.40395,3.31776,3.31776,3.93706,4.51813,0.570842,2.83475,4.76513,4.76513,4.76513,3.58735", "train/ent_coef": "3.07413e-05,3.07413e-05,2.00547e-05,2.00547e-05,0.000142906,2.74582e-05,2.74582e-05,2.74582e-05,0.000137812,0.000137812,4.22916e-05,8.42641e-05,8.42641e-05,8.42641e-05,1.32216e-05,4.13929e-05,0.000110485,0.000162968,8.98576e-05,4.08122e-05,1e-05,7.27121e-05,5.91329e-05,0.000165216,1e-05,1e-05,2.31658e-05,2.31658e-05,2.31658e-05,1e-05,0.000152677,0.000152677,0.000152677,0.000605114,0.000158833,7.27008e-05,1e-05,1e-05,1e-05,1e-05,1e-05,0.000148856,0.00750641,4.39856e-05,1e-05,1e-05,3.73373e-05,2.1914e-05,4.31394e-05,0.000346958,1.22484e-05,1.22484e-05,1.22484e-05,1.22484e-05,1.22484e-05,0.00019754,2.66664e-05,3.44791e-05,3.44791e-05,0.000154435,0.000198936,0.000135452,0.000135452,2.62232e-05,2.62232e-05,0.000415761,0.000122899,1e-05,1e-05,1e-05,1e-05,0.110544,7.57633e-05,0.00010331,0.00010331,4.3402e-05,4.3402e-05,0.000137456,0.000568706,0.000568706,0.000473478,0.000473478,0.000473478,0.000105,0.000103279,0.000103279,0.000103279,0.000103279,7.37153e-05,7.37153e-05,0.000423486,4.94739e-05,4.94739e-05,1e-05,1e-05,0.000315256,0.000315256,0.000404036,0.000241177,0.000653402,0.000482798,9.39673e-05,9.39673e-05,9.39673e-05,0.000344826,5.38757e-05,3.43134e-05,8.04956e-05,8.04956e-05,0.000183905,0.000135626,0.000213282,0.000448385,1.34812e-05,1.34812e-05,1.34812e-05,3.46797e-05", "train/beta1": "0.988735,0.988735,0.994643,0.994643,0.990044,0.988746,0.988746,0.988746,0.99209,0.99209,0.98435,0.993295,0.993295,0.993295,0.994264,0.972539,0.988124,0.988706,0.984108,0.992733,0.987135,0.989865,0.991764,0.983315,0.98477,0.98477,0.992704,0.992704,0.992704,0.995463,0.991177,0.991177,0.991177,0.978702,0.996285,0.973122,0.991829,0.994379,0.994379,0.994379,0.994379,0.995174,0.984865,0.976913,0.994242,0.994242,0.992605,0.983886,0.995473,0.982677,0.989645,0.989645,0.989645,0.989645,0.989645,0.985774,0.9774,0.994128,0.994128,0.990061,0.987519,0.991318,0.991318,0.990074,0.990074,0.986463,0.996355,0.992709,0.992709,0.992709,0.992709,0.995786,0.995861,0.985818,0.985818,0.990833,0.990833,0.979287,0.983477,0.983477,0.99247,0.99247,0.99247,0.979753,0.990924,0.990924,0.990924,0.990924,0.971257,0.971257,0.988149,0.988326,0.988326,0.992831,0.992831,0.982755,0.982755,0.984883,0.990869,0.992782,0.96886,0.995536,0.995536,0.995536,0.976054,0.993276,0.993978,0.994824,0.994824,0.991545,0.984669,0.980439,0.989764,0.992061,0.992061,0.992061,0.990952", "train/beta2": "0.969854,0.969854,0.993844,0.993844,0.983905,0.996763,0.996763,0.996763,0.99966,0.99966,0.999229,0.999508,0.999508,0.999508,0.994593,0.998911,0.99134,0.995233,0.9,0.997611,0.999532,0.997299,0.99977,0.997242,0.999846,0.999846,0.999959,0.999959,0.999959,0.995194,0.999967,0.999967,0.999967,0.96735,0.999964,0.999517,0.999562,0.991022,0.991022,0.991022,0.991022,0.998689,0.99907,0.980417,0.993711,0.993711,0.995259,0.998966,0.999245,0.999948,0.95229,0.95229,0.95229,0.95229,0.95229,0.998972,0.999838,0.997708,0.997708,0.990883,0.999649,0.999968,0.999968,0.993193,0.993193,0.9,0.99999,0.996686,0.996686,0.996686,0.996686,0.977016,0.996036,0.997574,0.997574,0.99999,0.99999,0.9,0.9,0.9,0.996361,0.996361,0.996361,0.970463,0.951173,0.951173,0.951173,0.951173,0.904686,0.904686,0.99994,0.999337,0.999337,0.996581,0.996581,0.998854,0.998854,0.999954,0.999649,0.999945,0.999275,0.99999,0.99999,0.99999,0.988122,0.9,0.985694,0.996668,0.996668,0.99999,0.99999,0.987559,0.9,0.99976,0.99976,0.99976,0.999971", "train/eps": "6.67858e-05,6.67858e-05,0.0001,0.0001,3.24682e-06,3.56716e-07,3.56716e-07,3.56716e-07,3.30516e-06,3.30516e-06,0.0001,0.0001,0.0001,0.0001,0.0001,2.21366e-05,0.0001,3.39886e-08,2.75048e-05,1.06084e-05,8.56302e-05,0.0001,5.80456e-06,0.0001,0.0001,0.0001,1.18473e-07,1.18473e-07,1.18473e-07,6.76015e-06,0.0001,0.0001,0.0001,4.48632e-07,1.25024e-06,0.0001,0.0001,4.95035e-07,4.95035e-07,4.95035e-07,4.95035e-07,0.0001,5.52297e-06,2.71907e-08,2.22282e-05,2.22282e-05,0.0001,5.26887e-06,6.83564e-06,0.0001,1.91038e-08,1.91038e-08,1.91038e-08,1.91038e-08,1.91038e-08,0.0001,4.37528e-07,7.82828e-09,7.82828e-09,3.18839e-06,1.73246e-07,0.0001,0.0001,4.40779e-07,4.40779e-07,3.70907e-06,0.0001,0.0001,0.0001,0.0001,0.0001,8.98291e-09,1.09928e-05,2.84155e-06,2.84155e-06,0.0001,0.0001,0.0001,7.81558e-07,7.81558e-07,0.0001,0.0001,0.0001,0.0001,5.82496e-05,5.82496e-05,5.82496e-05,5.82496e-05,0.0001,0.0001,2.86461e-05,0.0001,0.0001,0.0001,0.0001,5.04913e-07,5.04913e-07,7.35065e-07,5.29838e-07,0.0001,2.23053e-05,0.0001,0.0001,0.0001,1.01865e-05,1.64817e-08,0.0001,0.0001,0.0001,0.0001,0.0001,4.19486e-06,5.28249e-05,6.93446e-05,6.93446e-05,6.93446e-05,7.47969e-08", "train/minibatch_size": "32768,32768,65536,65536,32768,32768,32768,32768,32768,32768,32768,65536,65536,65536,32768,32768,32768,16384,32768,16384,16384,32768,16384,16384,32768,32768,16384,16384,16384,16384,16384,16384,16384,32768,32768,16384,32768,16384,16384,16384,16384,32768,32768,32768,32768,32768,32768,32768,32768,32768,16384,16384,16384,16384,16384,16384,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,16384,16384,16384,16384,8192,16384,16384,16384,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,16384,16384,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,16384,16384,16384,32768,16384,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768", "train/horizon": "128,128,128,128,256,256,256,256,64,64,32,128,128,128,128,128,64,512,64,64,128,256,64,128,64,64,128,128,128,128,64,64,64,32,128,64,256,256,256,256,256,256,128,128,128,128,128,128,128,64,256,256,256,256,256,256,64,256,256,128,64,64,64,128,128,64,128,128,128,128,128,16,128,256,256,128,128,128,64,64,128,128,128,64,64,64,64,64,64,64,128,64,64,128,128,64,64,128,64,64,64,128,128,128,64,128,128,128,128,256,128,64,64,64,64,64,128", "train/vtrace_rho_clip": "4.94078,4.94078,5,5,4.20981,4.03983,4.03983,4.03983,5,5,4.03792,4.87042,4.87042,4.87042,5,4.67151,4.51951,3.84847,5,5,4.38118,4.80963,5,4.36807,5,5,4.63808,4.63808,4.63808,5,5,5,5,5,5,4.51891,5,5,5,5,5,5,4.30574,5,5,5,5,4.65711,4.6561,5,5,5,5,5,5,4.86207,5,5,5,3.95168,5,4.74953,4.74953,3.95157,3.95157,5,4.86974,5,5,5,5,2.8896,5,3.44151,3.44151,5,5,4.75611,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,4.66431,4.66431,5,4.72705,4.3809,4.93306,5,5,5,5,4.17962,5,4.9812,4.9812,5,4.75292,5,4.74405,5,5,5,5", "train/vtrace_c_clip": "2.60561,2.60561,2.25803,2.25803,1.87786,2.76852,2.76852,2.76852,2.93331,2.93331,1.40093,2.18612,2.18612,2.18612,2.815,2.47974,2.01376,2.98797,3.24925,2.35552,2.80071,1.86809,2.13879,2.90285,1.00554,1.00554,1.6043,1.6043,1.6043,2.54586,1.22627,1.22627,1.22627,1.14605,1.23975,2.21869,3.97665,2.33779,2.33779,2.33779,2.33779,2.78237,2.7473,3.02475,2.43147,2.43147,2.81591,1.915,2.36341,2.2129,3.03881,3.03881,3.03881,3.03881,3.03881,1.48458,1.22569,3.19397,3.19397,1.76192,1.26833,1.85314,1.85314,2.08516,2.08516,2.35258,1.67468,3.20541,3.20541,3.20541,3.20541,4.63958,2.8973,1.04956,1.04956,1.2963,1.2963,2.49154,2.77422,2.77422,2.44388,2.44388,2.44388,2.72583,1.81824,1.81824,1.81824,1.81824,2.11111,2.11111,1.65806,1.16602,1.16602,2.89272,2.89272,1.23208,1.23208,1.96762,1.06742,1.40397,2.31431,1.80504,1.80504,1.80504,1.34163,1.74858,3.10948,2.25885,2.25885,2.13189,2.37694,1.0695,2.02131,1.07405,1.07405,1.07405,2.61092", "train/prio_alpha": "0.744131,0.744131,0.757657,0.757657,1,0.94751,0.94751,0.94751,0.552583,0.552583,0.479598,0.461028,0.461028,0.461028,0.844588,0.528868,0.593431,0.987212,0.549648,0.391679,0.897088,1,0.523476,0.604956,0.566466,0.566466,0.984864,0.984864,0.984864,0.966227,0.392541,0.392541,0.392541,0.522601,0.793052,0.739471,0.597238,0.998067,0.998067,0.998067,0.998067,1,0.119306,0.449006,0.582465,0.582465,0.779119,0.54715,0.586178,0.498442,0.665134,0.665134,0.665134,0.665134,0.665134,1,0.659939,1,1,0.56605,0.513621,0.63544,0.63544,0.440543,0.440543,0.609024,0.823011,0.94301,0.94301,0.94301,0.94301,0.712872,0.790326,1,1,0.793248,0.793248,0.956828,0.437326,0.437326,0.694306,0.694306,0.694306,0.783807,0.767128,0.767128,0.767128,0.767128,0.60479,0.60479,0.858703,0.63351,0.63351,0.777324,0.777324,0.453283,0.453283,0.787349,0.628564,0.700411,0.533136,0.812178,0.812178,0.812178,0.597427,0.971138,0.655143,0.643808,0.643808,0.89024,0.66308,0.565388,0.455611,0.513585,0.513585,0.513585,0.60396", "train/prio_beta0": "1,1,1,1,1,0.901006,0.901006,0.901006,0.764934,0.764934,0.864871,1,1,1,1,1,0.988155,0.966936,0.772631,1,0.788336,0.975459,0.772448,1,1,1,0.633273,0.633273,0.633273,1,0.917817,0.917817,0.917817,0.852045,0.655441,0.805602,1,0.884829,0.884829,0.884829,0.884829,1,0.925024,1,1,1,0.97333,1,1,0.755178,1,1,1,1,1,1,1,1,1,1,0.879643,0.814514,0.814514,0.98507,0.98507,1,0.851906,0.945271,0.945271,0.945271,0.945271,0.58613,0.833795,1,1,0.727874,0.727874,1,0.989227,0.989227,1,1,1,0.864581,1,1,1,1,0.827611,0.827611,0.666998,0.974922,0.974922,0.999741,0.999741,0.732862,0.732862,0.619819,0.971814,0.872603,0.945824,0.813829,0.813829,0.813829,0.813882,1,0.922318,1,1,0.704366,0.505427,1,0.74499,1,1,1,0.769882", "train/use_rnn": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "train/env": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "no_model_upload": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "tsne1": "57.552,57.552,58.1834,58.1834,62.4493,62.5086,62.5087,62.5087,54.6157,54.6157,52.7513,53.3277,53.3277,53.3277,59.2761,55.7172,52.5162,63.1657,52.9247,54.0153,60.7347,61.573,51.7588,57.6466,52.4348,52.4348,59.0354,59.0354,59.0354,61.0823,54.4354,54.4354,54.4355,52.0746,58.1535,57.5119,60.1205,61.3479,61.3479,61.3479,61.3479,60.0503,50.3903,55.4383,58.4235,58.4235,58.5061,53.1479,57.1201,52.2352,64.6423,64.6423,64.6416,64.6416,64.6423,62.2469,51.9455,60.8096,60.8096,57.4328,51.771,55.882,55.8836,58.2784,58.2784,52.8415,57.6752,60.2673,60.2673,60.2673,60.2674,15.7543,59.0661,63.0856,63.0856,58.0222,58.0222,55.0179,52.5928,52.5928,56.7214,56.7214,56.7214,55.8476,55.9045,55.9045,55.9045,55.9045,52.4187,52.4187,57.5553,52.3225,52.3225,59.8565,59.8565,51.1692,51.1699,57.5525,51.6143,51.9683,53.7182,57.6835,57.6837,57.6835,51.7373,54.4683,57.8731,57.0555,57.0555,57.4985,56.9106,55.1187,52.2461,52.9238,52.9238,52.922,55.2616", "tsne2": "33.3001,33.3001,33.7694,33.7694,35.7093,35.4581,35.4581,35.4581,39.3442,39.3442,38.7543,39.8178,39.8178,39.8178,33.957,38.534,38.4204,36.0663,30.8637,37.2713,34.2061,33.9479,37.987,37.8099,40.5591,40.5591,41.2629,41.2629,41.2629,33.6218,41.1277,41.1277,41.1285,37.1301,41.7264,39.7921,35.1025,32.5027,32.5027,32.5027,32.5027,31.5781,38.433,34.5901,32.6062,32.6062,32.9808,41.5084,37.766,37.7408,34.5992,34.5992,34.5989,34.5989,34.5992,32.5911,41.1849,31.3213,31.3213,38.5305,39.1526,40.7709,40.7695,31.7939,31.7939,30.6736,41.8145,33.3773,33.3774,33.3774,33.3772,11.6492,35.3395,36.7521,36.7521,42.8519,42.8519,31.2188,30.6315,30.6315,38.1874,38.1874,38.187,33.5467,32.182,32.182,32.182,32.182,31.16,31.16,42.3303,41.6068,41.6068,34.4997,34.4997,39.938,39.9402,42.8574,41.1634,38.6579,37.989,41.0409,41.0409,41.0409,38.7534,30.5051,34.242,36.99,36.99,42.2127,42.7029,33.7128,30.8449,41.1052,41.1052,41.105,39.563"}, "moba": {"SPS": "3.32114e+06,2.01933e+06,4.26908e+06,2.48516e+06,2.75471e+06,2.70892e+06,2.79415e+06,2.96419e+06,3.12348e+06,3.28048e+06,3.63059e+06,2.3459e+06,2.36516e+06,1.91425e+06,3.78229e+06,4.18657e+06,4.33735e+06,4.32456e+06,3.53318e+06,3.49461e+06,3.69883e+06,3.70389e+06", "agent_steps": "8.9129,7.20896,10.2892,11.01,7.20896,8.9129,12.3208,12.5829,3.40787,6.32422,10.7479,5.96378,9.56826,3.14573,15.5976,8.65075,13.8936,17.8258,7.20896,9.30611,12.7795,17.236", "uptime": "3.23152,4.05927,2.78037,5.43708,3.21629,3.8453,5.06092,5.00076,1.2136,2.12246,3.3506,2.85775,4.38137,1.82931,4.66406,2.46005,3.67221,4.58021,2.47941,3.07952,4.01689,5.22192", "epoch": "34,55,78.5,21,55,68,94,96,52,96.5,164,45.5,73,96,119,66,106,136,55,71,97.5,131.5", "perf/rollout": "0.365036,0.254334,0.454439,0.410489,0.412504,0.414407,0.39735,0.398256,0.41441,0.40554,0.39353,0.271679,0.266721,0.23812,0.373607,0.398903,0.376837,0.378746,0.38247,0.366539,0.364479,0.353299", "perf/eval_gpu": "0.095776,0.0753507,0.105182,0.0534891,0.114326,0.113839,0.113917,0.115044,0.117865,0.124516,0.131895,0.110711,0.110596,0.0803141,0.0997382,0.100317,0.100719,0.10048,0.0762301,0.0720137,0.0790231,0.076403", "perf/eval_env": "0.264262,0.175691,0.306889,0.353814,0.285673,0.288202,0.270523,0.261788,0.242052,0.229592,0.214823,0.138863,0.134339,0.133363,0.258209,0.286291,0.258085,0.263597,0.293153,0.279899,0.274647,0.266596", "perf/train_misc": "0.0226601,0.0265402,0.0177002,0.0253384,0.0180289,0.0183366,0.0182019,0.0193355,0.0148345,0.0156626,0.0172218,0.0156928,0.0156536,0.0193668,0.0210177,0.0209346,0.020942,0.0209566,0.0240966,0.0226361,0.024721,0.0240156", "perf/train_forward": "0.243259,0.368894,0.14832,0.196389,0.170048,0.169994,0.169874,0.179566,0.175969,0.185667,0.201273,0.326497,0.326458,0.358084,0.228859,0.206275,0.206243,0.205988,0.223293,0.210038,0.229792,0.223296", "perf/train": "0.265919,0.395435,0.16602,0.221727,0.188076,0.188331,0.188076,0.198901,0.190804,0.201329,0.218494,0.34219,0.342112,0.377451,0.249877,0.227209,0.227185,0.226945,0.24739,0.232674,0.254513,0.247311", "util/gpu_percent": "67,64.5,50.75,68,70,69,71,70,80,82.5,82,91,91.3333,86,64.5,60,67,68,55,61,60.5,62.5", "util/gpu_mem": "9.74848,8.43588,8.65056,10.8403,13.5106,13.5106,13.5106,16.0463,8.35614,8.35614,8.35614,9.84662,9.84662,6.80433,8.91431,8.98216,8.98216,8.98216,8.65056,8.65056,8.65056,8.65056", "util/vram_used_gb": "2.61737,2.1994,2.26776,2.96503,2.76526,2.76526,2.76526,3.37351,2.17401,2.17401,2.17401,2.64862,2.64862,1.67987,2.35175,2.37335,2.37335,2.37335,2.26776,2.26776,2.26776,2.26776", "util/vram_total_gb": "31.356,31.356,31.356,31.356,23.5126,23.5126,23.5126,23.5126,31.356,31.356,31.356,31.356,31.356,31.356,31.356,31.356,31.356,31.356,31.356,31.356,31.356,31.356", "util/cpu_mem_gb": "1.86853,1.86338,1.9057,2.46035,1.71946,1.71947,1.71947,1.72031,1.6308,1.6308,1.6308,1.67892,1.67893,1.59361,1.90585,1.88058,1.88058,1.88058,1.90736,1.90736,1.90736,1.90736", "env/perf": "0.463415,0.477778,0.335411,1,0.32,0.5,0.831973,0.784863,0,0.0526316,0.715144,0.00914634,0.6422,0,0.966442,0.285714,0.933333,0.98514,0.324324,0.61442,0.952381,1", "env/score": "0.463415,0.477778,0.335411,1,0.32,0.5,0.831973,0.784863,0,0.0526316,0.715144,0.00914634,0.6422,0,0.966442,0.285714,0.933333,0.98514,0.324324,0.61442,0.952381,1", "env/episode_return": "447.712,166.458,340.39,183.161,184.382,270.274,232.683,292.958,113.221,467.756,733.604,813.403,939.668,23.1793,398.721,138.251,124.205,133.911,180.272,255.276,156.898,125.591", "env/episode_length": "4036.52,3360.68,3628.27,2590,3338.01,3844.64,3074.54,3316.91,3075.38,4903.02,4224.36,4935.89,4011.88,2959.62,2882.86,3927.23,2808.35,2763.74,3333.62,3872.13,2384.78,1932.37", "env/radiant_victory": "0.463415,0.477778,0.335411,1,0.32,0.5,0.831973,0.784863,0,0.0526316,0.715144,0.00914634,0.6422,0,0.966442,0.285714,0.933333,0.98514,0.324324,0.61442,0.952381,1", "env/dire_victory": "0.536585,0.522222,0.664589,0,0.68,0.5,0.168027,0.215137,1,0.947368,0.284856,0.990854,0.3578,1,0.0335581,0.714286,0.0666667,0.0148601,0.689189,0.38558,0.047619,0", "env/radiant_level": "9.74439,8.43667,10.1943,6.8,9.57333,11.8525,10.7059,11.9853,5.375,10.962,13.7012,11.2755,11.9956,3.125,9.35357,9.74286,9.28,9.7687,9.57838,11.395,8.81487,8.10558", "env/dire_level": "7.32488,6.37333,6.29047,5,5.99734,6.63354,5.4418,6.19383,5.5,8.4303,8.96601,8.68808,7.98801,5.1375,5.49344,6.95476,5.31733,5.31302,5.96216,6.73103,4.60022,3.80065", "env/radiant_towers_alive": "2.14634,2.99444,3.43123,6,3.04,3.17089,6.54458,6.31891,2,0.474968,4.20625,0.774051,4.11336,0.375,7.17403,2.0119,7.32,7.78059,3.14865,3.49843,8.31582,9.1946", "env/dire_towers_alive": "5.09756,6.62222,7.46009,6,7.6,6.64557,6.00215,5.43384,12,7.47064,3.45385,8.17954,4.47138,12,5.7286,7.65476,5.54667,5.74607,7.21622,5.91223,5.65705,5.87779", "env/radiant_support_episode_return": "30.789,14.7387,31.604,12.6151,14.8052,23.6071,17.1128,27.6992,8.99606,35.1682,46.528,61.0283,65.449,4.11379,29.6283,12.8877,13.0471,13.3813,18.1536,25.0022,16.4175,12.9448", "env/radiant_support_reward_death": "0,0,0,0,0,0,-0.000222808,0,0,0,0,0,-0.000210802,0,0,0,0,0,0,-0.000513368,0,0", "env/radiant_support_reward_xp": "0.022571,0,0.0714163,0,0.0233431,0.00126394,0.00981669,0.00537578,0,0.020322,0.0585135,0.267211,0.0108202,0,0.0114602,0.00981886,0.00219942,0.00795328,0.034993,0.0210554,0.0343379,0.0157013", "env/radiant_support_reward_distance": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "env/radiant_support_reward_tower": "0,0.00450734,0.0046723,0,0.00856159,0.0121921,0.0167339,0.0235227,0,0.0119227,0.00283164,0,0.00606061,0,0.068778,0.0111917,0.037604,0.0301999,0.0173546,0.0201291,0.0423899,0.0276306", "env/radiant_support_level": "5.69268,5.58889,6.8919,4,6.01333,7.76582,6.40389,8.07342,3.25,6.75513,7.88005,6.95088,7.24332,2.8125,5.6814,6.70833,6.62667,6.73208,6.78378,7.99687,6.26529,5.65634", "env/radiant_support_kills": "3.86829,4.38889,7.17269,1,5.13333,8.01266,8.1776,10.0526,1.875,4.43373,6.75601,4.13415,5.15892,0.75,5.51598,5.20833,8.53333,9.69821,6.97297,8.51411,8.77705,9.86803", "env/radiant_support_deaths": "4.71707,4.57778,3.40945,5,4.01333,4.99051,2.94219,3.87876,0.625,5.1043,8.3387,7.81064,7.91515,1.25,4.97637,5.77381,3.13333,2.95083,3.48649,4.16301,2.35705,1.219", "env/radiant_support_damage_dealt": "15404.6,13824.9,17326.2,10256,14205.5,18927.3,15720.7,20464.2,4475.62,16990,21938.7,19371.8,21955.5,4860.56,14359.9,18494.8,16448.9,16598.5,15112.3,19516.2,14484.5,12248.5", "env/radiant_support_damage_received": "7936.04,7441.64,7707.34,6834,6986.11,9001.03,6384.36,8732.65,1598.75,9224.16,13067.1,11364.1,12925.8,2402.38,7604.33,9592.71,7343.73,7062.57,6626.93,8536.62,5965.62,3929.62", "env/radiant_support_healing_dealt": "2749.08,2603.15,5452.71,1676,5174.55,7283.63,8136.69,8974.49,1150.75,3692.97,4561.53,2782.76,4367.57,990.062,3129.55,3745.51,5537.49,6072.51,6028.88,7717.18,9300.18,9786.85", "env/radiant_support_healing_received": "1837.03,1799.57,2666.24,1392,2033,2778.76,2154.42,3437.57,693.625,2546.54,3334.63,2351.79,3225.35,845.5,1667.22,2486.8,2509.95,2461.82,2200.72,2935.54,2527.41,1884.87", "env/radiant_support_creeps_killed": "9.68781,6.92222,9.28506,9,6.45333,8.52215,8.0032,10.868,3.625,12.3479,15.5978,12.314,13.8527,2.75,7.24827,10.3155,9.13333,8.35184,8.89189,11.1097,8.64298,6.7875", "env/radiant_support_neutrals_killed": "8.2878,8.62222,8.66486,5,7.92,8.81329,6.36731,6.26753,2.625,7.875,7.64856,10.5512,14.1695,3.8125,6.40504,11,7.44,7.28409,6.28378,7.41066,3.72745,2.21606", "env/radiant_support_towers_killed": "0.24878,0.355556,0.246951,0,0.28,0.177215,0.188898,0.339745,0,0.167202,0.307212,0.112127,0.225814,0,0.432322,0.244048,0.4,0.466346,0.121622,0.30094,0.276327,0.239091", "env/radiant_support_usage_auto": "157.283,146.517,168.877,110,146.693,182.158,156.276,186.02,51.125,162.438,204.993,190.144,207.991,59,148.646,185.655,160.52,162.053,151.554,183.53,144.17,127.004", "env/radiant_support_usage_q": "21.8439,18.6333,19.8637,17,18.52,23.3481,17.1171,16.7213,5.5,22.7137,31.1341,31.2341,31.6938,4.0625,22.3418,25.4821,18.72,18.4631,16.3919,20.1034,11.1661,7.43819", "env/radiant_support_usage_w": "61.3073,51.2833,50.1901,41,48.8667,54.6392,40.6936,46.8298,54,80.2036,64.6228,78.1616,59.1154,40.8125,39.8404,56.5357,35.0533,34.2528,48.6757,55.4671,32.1265,24.0491", "env/radiant_support_usage_e": "23.322,20.9056,23.6609,18,20.8267,25.6867,22.1946,26.2543,8.75,24.0732,29.905,27.9417,29.6065,9.0625,20.6025,26.1905,22.24,21.7563,21.3514,25.6552,20.029,17.853", "env/n": "205,47.5,136,1,75,316,137.333,164.333,8,101,106,100,69,16,169,168,75,247,74,319,207.5,209.5", "wandb": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "slowly": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "save_frames": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "fps": "15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15", "rank": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "world_size": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "gpu_id": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "profile": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "checkpoint_interval": "200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200", "eval_episodes": "10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000", "cudagraphs": "10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10", "seed": "73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73", "reset_state": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "vec/total_agents": "2048,2048,2048,4096,2048,2048,2048,2048,1024,1024,1024,1024,1024,1024,2048,2048,2048,2048,2048,2048,2048,2048", "vec/num_buffers": "1.13938,1,2.61976,1,2.24842,2.24842,2.24842,2.24842,4.89051,4.89051,4.89051,4.38079,4.38079,3.41297,2.16675,3.25248,3.25248,3.25248,2.24842,2.24842,2.24842,2.24842", "vec/num_threads": "16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16", "env/vision_range": "5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5", "env/agent_speed": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "env/script_opponents": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "env/reward_death": "-0.182462,-0.208679,0,-0.0941503,-0.163764,-0.163764,-0.163764,-0.163764,-0.510114,-0.510114,-0.510114,-0.104347,-0.104347,-0.468262,0,-0.441887,-0.441887,-0.441887,-0.163764,-0.163764,-0.163764,-0.163764", "env/reward_xp": "0.0153214,0.00754691,0.0108597,0.0130862,0.00665677,0.00665677,0.00665677,0.00665677,0.0122541,0.0122541,0.0122541,0.0214239,0.0214239,0.00912908,0.0147383,0.00471305,0.00471305,0.00471305,0.00665677,0.00665677,0.00665677,0.00665677", "env/reward_distance": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "env/reward_tower": "0.895544,0.81132,1,1,0.642119,0.642119,0.642119,0.642119,0.906126,0.906126,0.906126,1,1,0.518152,0.886971,0.9401,0.9401,0.9401,0.642119,0.642119,0.642119,0.642119", "policy/hidden_size": "64,32,64,32,64,64,64,64,64,64,64,256,256,128,128,64,64,64,64,64,64,64", "policy/num_layers": "5.16375,8,5.39383,5.89374,5.61447,5.61447,5.61447,5.61447,6.29171,6.29171,6.29171,6.24221,6.24221,5.92911,5.19277,5.14265,5.14265,5.14265,5.61447,5.61447,5.61447,5.61447", "policy/expansion_factor": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "legacy/torch_deterministic": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "legacy/cpu_offload": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "legacy/compile": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "legacy/compile_fullgraph": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "train/gpus": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "train/seed": "42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42", "train/total_timesteps": "39.5146,61.4377,106.025,46.7364,39.0561,39.0561,39.0561,39.0561,30.2902,30.2902,30.2902,30,30,69.7054,47.1586,30,30,30,39.0561,39.0561,39.0561,39.0561", "train/learning_rate": "0.0079814,0.00705233,0.00845286,0.0102081,0.00343957,0.00343957,0.00343957,0.00343957,0.00363033,0.00363033,0.00363033,0.00220511,0.00220511,0.00813611,0.00428343,0.00798657,0.00798657,0.00798657,0.00343957,0.00343957,0.00343957,0.00343957", "train/anneal_lr": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "train/min_lr_ratio": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "train/gamma": "0.989094,0.986203,0.993287,0.974267,0.991949,0.991949,0.991949,0.991949,0.991555,0.991555,0.991555,0.980058,0.980058,0.97326,0.985418,0.981674,0.981674,0.981674,0.991949,0.991949,0.991949,0.991949", "train/gae_lambda": "0.888878,0.900374,0.936194,0.921566,0.945677,0.945677,0.945677,0.945677,0.924351,0.924351,0.924351,0.922202,0.922202,0.984069,0.918487,0.97692,0.97692,0.97692,0.945677,0.945677,0.945677,0.945677", "train/replay_ratio": "1.0856,0.861018,0.476084,0.386253,0.832202,0.832202,0.832202,0.832202,0.660042,0.660042,0.660042,0.681213,0.681213,3.58379,0.667758,1.10591,1.10591,1.10591,0.832202,0.832202,0.832202,0.832202", "train/clip_coef": "0.601499,0.444301,0.2629,0.593814,0.565744,0.565744,0.565744,0.565744,0.459743,0.459743,0.459743,0.507608,0.507608,0.206246,0.568743,0.971591,0.971591,0.971591,0.565744,0.565744,0.565744,0.565744", "train/vf_coef": "4.4564,4.15565,3.52828,3.51057,3.37665,3.37665,3.37665,3.37665,2.87076,2.87076,2.87076,1.74159,1.74159,0.252624,3.79743,3.94547,3.94547,3.94547,3.37665,3.37665,3.37665,3.37665", "train/vf_clip_coef": "1.44799,2.63338,1.50287,2.37981,1.27302,1.27302,1.27302,1.27302,0.316028,0.316028,0.316028,1.9055,1.9055,4.05115,1.99465,2.67299,2.67299,2.67299,1.27302,1.27302,1.27302,1.27302", "train/max_grad_norm": "1.44066,1.84417,1.99394,0.536964,1.08622,1.08622,1.08622,1.08622,1.83496,1.83496,1.83496,3.26296,3.26296,4.34471,2.74782,1.58825,1.58825,1.58825,1.08622,1.08622,1.08622,1.08622", "train/ent_coef": "0.00294799,0.0123166,0.00479752,0.00319387,0.00109913,0.00109913,0.00109913,0.00109913,0.0047499,0.0047499,0.0047499,0.00620598,0.00620598,0.00011612,0.00304071,0.00283048,0.00283048,0.00283048,0.00109913,0.00109913,0.00109913,0.00109913", "train/beta1": "0.748485,0.5,0.848864,0.879495,0.837952,0.837952,0.837952,0.837952,0.913862,0.913862,0.913862,0.86776,0.86776,0.995917,0.858368,0.838909,0.838909,0.838909,0.837952,0.837952,0.837952,0.837952", "train/beta2": "0.999819,0.998745,0.999925,0.998878,0.943593,0.943593,0.943593,0.943593,0.962441,0.962441,0.962441,0.999989,0.999989,0.99998,0.998941,0.999688,0.999688,0.999688,0.943593,0.943593,0.943593,0.943593", "train/eps": "6.28587e-11,1.41123e-10,4.59409e-09,4.28974e-10,1.89701e-12,1.89701e-12,1.89701e-12,1.89701e-12,1.23442e-13,1.23442e-13,1.23442e-13,1.17451e-11,1.17451e-11,2.9502e-06,3.04096e-10,9.34533e-14,9.34533e-14,9.34533e-14,1.89701e-12,1.89701e-12,1.89701e-12,1.89701e-12", "train/minibatch_size": "16384,4096,8192,4096,8192,8192,8192,8192,8192,8192,8192,8192,8192,16384,8192,16384,16384,16384,8192,8192,8192,8192", "train/horizon": "128,64,64,128,64,64,64,64,64,64,64,128,128,32,64,64,64,64,64,64,64,64", "train/vtrace_rho_clip": "1.45555,1.49254,1.21769,1.21331,1.76073,1.76073,1.76073,1.76073,1.19111,1.19111,1.19111,1.83675,1.83675,4.93899,1.09457,0.982471,0.982471,0.982471,1.76073,1.76073,1.76073,1.76073", "train/vtrace_c_clip": "1.19292,1.105,1.85936,1.486,1.32578,1.32578,1.32578,1.32578,1.65444,1.65444,1.65444,1.7072,1.7072,2.42509,2.08863,1.40028,1.40028,1.40028,1.32578,1.32578,1.32578,1.32578", "train/prio_alpha": "0.789705,0.797177,1,1,1,1,1,1,1,1,1,0.569946,0.569946,0.909433,1,0.832363,0.832363,0.832363,1,1,1,1", "train/prio_beta0": "0.52691,0.241458,0.600453,0.480309,0.5692,0.5692,0.5692,0.5692,0.198518,0.198518,0.198518,0.383371,0.383371,0.266424,0.257641,0.276278,0.276278,0.276278,0.5692,0.5692,0.5692,0.5692", "train/use_rnn": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "no_model_upload": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "tsne1": "0.172505,-10.5723,-0.621838,-0.715586,-1.10324,-0.959075,-1.10324,-0.959075,-2.58884,-2.58882,-2.58963,-5.74913,-5.74916,-26.7659,-0.555908,1.03282,1.03282,1.03282,-1.30839,-1.30839,-1.30839,-1.30839", "tsne2": "8.18046,-4.99705,7.82155,8.30077,9.89798,10.1254,9.89798,10.1254,9.11896,9.11891,9.11946,13.1331,13.1332,6.95418,7.76257,8.30345,8.30345,8.30345,10.1603,10.1603,10.1603,10.1603"}, "nmmo3": {"SPS": "324465,620336,621162,621783,623793,622127,622253,622619,623824,622559,622647,622585,366162,437277,437001,1.38235e+06,371917,257874,441761,290299,628785,629515,630149,630022,633643,630918,634171,631079,629978,629036,629451,630380,631416,631697,631717,631712,632013,631756,632766,630698,630534,632479,631260,630987,631026,635677,251603,251739,3.25624e+06,3.25666e+06,3.2622e+06,3.26788e+06,3.27091e+06,3.27074e+06,3.27303e+06,3.27471e+06,3.27342e+06,3.27137e+06,3.27045e+06,3.27126e+06,3.2697e+06,3.27173e+06,3.26956e+06,3.26713e+06,3.26678e+06,3.26592e+06,3.26816e+06,3.26834e+06,3.26808e+06,3.26544e+06,3.26302e+06,3.26678e+06,3.27079e+06,3.26896e+06,3.26733e+06,3.2665e+06,3.26281e+06,3.26148e+06,3.26348e+06,3.26603e+06,3.26795e+06,3.26683e+06,3.26229e+06,3.25743e+06,3.25506e+06,3.26697e+06,3.27294e+06,3.27021e+06,3.27415e+06,3.2645e+06,3.25989e+06,3.26087e+06,3.26403e+06,3.27353e+06,3.27187e+06,3.18978e+06,1.36553e+06,3.26523e+06,3.25382e+06,3.28126e+06,3.28698e+06,3.25007e+06,3.24642e+06,3.24905e+06,3.26287e+06,3.25778e+06,3.24612e+06,3.24544e+06,3.17711e+06,578791,578485,674020,398833,662829,662691,662962,663065,662668,663012,662643,662552,662187,662727,662497,661947,662348,662963,662534,662320,662064,662226,662229,662422,662317,661922,1.38285e+06,353184,438548,3.25624e+06,3.25667e+06,3.2622e+06,3.26788e+06,3.27091e+06,3.27074e+06,3.27303e+06,3.27471e+06,3.27342e+06,3.27137e+06,3.27045e+06,3.27126e+06,3.2697e+06,3.27173e+06,3.26956e+06,3.26713e+06,3.26678e+06,3.26592e+06,3.26816e+06,3.26834e+06,3.26807e+06,3.26544e+06,3.26302e+06,3.26678e+06,3.27079e+06,3.26896e+06,3.26733e+06,3.2665e+06,3.2628e+06,3.26148e+06,3.26348e+06,3.26603e+06,3.26795e+06,3.26683e+06,3.26229e+06,3.25742e+06,3.25506e+06,3.26697e+06,3.27294e+06,3.27021e+06,3.27415e+06,3.2645e+06,3.25989e+06,3.26087e+06,3.26403e+06,3.27353e+06,3.27187e+06,3.2661e+06,3.19246e+06,482696,482945,482306,483318,482876,3.25624e+06,3.25666e+06,3.2622e+06,3.26788e+06,3.27091e+06,3.27074e+06,3.27303e+06,3.27471e+06,3.27342e+06,3.27137e+06,3.27045e+06,3.27126e+06,3.2697e+06,3.27173e+06,3.26956e+06,3.26713e+06,3.26678e+06,3.26592e+06,3.26816e+06,3.26834e+06,3.26808e+06,3.26544e+06,3.26302e+06,3.26678e+06,3.27079e+06,3.26896e+06,3.26733e+06,3.26649e+06,3.2628e+06,3.26148e+06,3.26348e+06,3.26603e+06,3.26795e+06,3.26683e+06,3.26229e+06,3.25743e+06,3.25506e+06,3.26697e+06,3.27294e+06,3.27021e+06,3.27415e+06,3.2645e+06,3.25989e+06,3.26087e+06,3.26403e+06,3.27353e+06,3.2661e+06,3.19321e+06,421675,524340,524507,708724,708891,709189,358770,319521,546772,547206,621001,621850,622343,622688,622690,623031,622993,622831,622813,622903,621611,621749,623681,623059,623286,623390,623089,623052,623168,623105,623271,3.25624e+06,3.25667e+06,3.2622e+06,3.26788e+06,3.27091e+06,3.27074e+06,3.27303e+06,3.27471e+06,3.27342e+06,3.27137e+06,3.27045e+06,3.27126e+06,3.2697e+06,3.27173e+06,3.26956e+06,3.26713e+06,3.26678e+06,3.26592e+06,3.26816e+06,3.26834e+06,3.26808e+06,3.26544e+06,3.26302e+06,3.26678e+06,3.27079e+06,3.26896e+06,3.26733e+06,3.2665e+06,3.26281e+06,3.26348e+06,3.26603e+06,3.26795e+06,3.26683e+06,3.26229e+06,3.25743e+06,3.25506e+06,3.26697e+06,3.27294e+06,3.27021e+06,3.27415e+06,3.2645e+06,3.25989e+06,3.26087e+06,3.26403e+06,3.27353e+06,3.27187e+06,3.2661e+06,3.18739e+06,627228,628493,628991,629001,629313,634075,630508,629230,629224,629334,631704,630141,629338,625354,624576,624690,629135,630535,630695,630474,630461,631525,617230,473577,474107,474288,474687,475572,707502,270255,263420,324106,325288,325346,325207,324864,380538,381215,272807,489571,489815,489870,291105,3.25624e+06,3.25667e+06,3.2622e+06,3.26788e+06,3.27091e+06,3.27074e+06,3.27303e+06,3.27471e+06,3.27342e+06,3.27137e+06,3.27045e+06,3.27126e+06,3.2697e+06,3.27173e+06,3.26956e+06,3.26713e+06,3.26678e+06,3.26592e+06,3.26816e+06,3.26834e+06,3.26808e+06,3.26544e+06,3.26302e+06,3.26678e+06,3.27079e+06,3.26896e+06,3.26733e+06,3.2665e+06,3.26281e+06,3.26148e+06,3.26348e+06,3.26603e+06,3.26795e+06,3.26683e+06,3.26229e+06,3.25743e+06,3.25506e+06,3.26697e+06,3.27294e+06,3.27021e+06,3.27415e+06,3.2645e+06,3.25989e+06,3.26087e+06,3.27353e+06,3.27187e+06,617682,3.25624e+06,3.25667e+06,3.2622e+06,3.26788e+06,3.27091e+06,3.27074e+06,3.27303e+06,3.27471e+06,3.27342e+06,3.27137e+06,3.27045e+06,3.27126e+06,3.2697e+06,3.27173e+06,3.26956e+06,3.26713e+06,3.26678e+06,3.26592e+06,3.26816e+06,3.26834e+06,3.26808e+06,3.26544e+06,3.26302e+06,3.26678e+06,3.27079e+06,3.26896e+06,3.26733e+06,3.2665e+06,3.2628e+06,3.26148e+06,3.26348e+06,3.26603e+06,3.26795e+06,3.26683e+06,3.26229e+06,3.25743e+06,3.25506e+06,3.26697e+06,3.27294e+06,3.27021e+06,3.27415e+06,3.2645e+06,3.25989e+06,3.26087e+06,3.26403e+06,3.27353e+06,3.27187e+06,3.2661e+06,1.393e+06,260777,261038,260930,260935,261035,653562,302709,302569,302528,299968,299779,299305,590261,486369,1.43737e+06,1.44978e+06,391173,427250,426855,427248,427214", "agent_steps": "70.91,1428.95,1837.11,2245.26,2653.42,3061.58,3469.74,3877.9,4286.05,4694.21,5102.37,5510.53,23.3308,25.1249,75.5642,3.2768,15.9908,17.9569,4.03046,30.933,1428.95,1837.11,2245.26,2653.42,3061.58,3469.74,3877.9,4286.05,4694.21,5102.37,5510.53,5918.69,14081.9,14490,14898.2,15306.3,15714.5,16122.6,16530.8,16939,17347.1,17755.3,18163.4,18571.6,18979.7,19999.5,22.8065,68.0264,6554.12,19657.7,32759.6,45861.6,58963.5,72065.5,85167.4,98269.4,111371,124473,137575,150677,163779,176881,189983,203085,216187,229289,242391,255493,268595,281697,294799,307901,321003,334105,347207,360309,373410,386512,399614,412716,425818,438920,452022,465124,478226,491328,504430,517532,530634,543736,556838,569940,583042,596144,609246,641999,1.31072,10206.3,30615.8,51023.7,71431.6,846942,867350,887757,908165,928573,948981,969389,999999,24.9037,74.1868,19.1365,3.93216,5250.74,5465.18,5679.61,5893.52,6107.96,6322.39,6536.3,6750.73,6965.17,7179.08,7393.51,7607.94,7821.85,8250.72,8464.63,8679.06,8893.5,9107.41,9321.84,9536.27,9750.18,10179.1,1.17965,1.31072,4.81577,6554.12,19657.7,32759.6,45861.6,58963.5,72065.5,85167.4,98269.4,111371,124473,137575,150677,163779,176881,189983,203085,216187,229289,242391,255493,268595,281697,294799,307901,321003,334105,347207,360309,373410,386512,399614,412716,425818,438920,452022,465124,478226,491328,504430,517532,530634,543736,556838,569940,583042,596144,609246,622348,641999,27.0008,80.4782,133.912,186.909,213.123,6554.12,19657.7,32759.6,45861.6,58963.5,72065.5,85167.4,98269.4,111371,124473,137575,150677,163779,176881,189983,203085,216187,229289,242391,255493,268595,281697,294799,307901,321003,334105,347207,360309,373410,386512,399614,412716,425818,438920,452022,465124,478226,491328,504430,517532,530634,543736,556838,569940,583042,596144,622348,641999,16.1219,245.891,280.494,169.869,237.502,271.057,18.6122,12.9761,1.17965,5.37395,1837.11,2245.26,2653.42,3061.58,3469.74,3877.9,4286.05,4694.21,5102.37,5510.53,5918.69,14081.9,14490,14898.2,15306.3,15714.5,16122.6,16530.8,16939,17347.1,17755.3,6554.12,19657.7,32759.6,45861.6,58963.5,72065.5,85167.4,98269.4,111371,124473,137575,150677,163779,176881,189983,203085,216187,229289,242391,255493,268595,281697,294799,307901,321003,334105,347207,360309,373410,399614,412716,425818,438920,452022,465124,478226,491328,504430,517532,530634,543736,556838,569940,583042,596144,609246,622348,641999,1837.11,2245.26,2653.42,3061.58,3469.74,3877.9,4286.05,4694.21,5102.37,5510.53,5918.69,14081.9,14490,14898.2,15306.3,15714.5,16122.6,16530.8,16939,17347.1,17755.3,18163.4,18979.7,443.81,739.508,1035.21,1330.91,1626.6,23.3308,268.435,15.9908,18.0879,53.7395,89.3911,125.043,142.606,23.3308,161.481,1.11411,17.5636,22.5444,66.8467,14.1558,6554.12,19657.7,32759.6,45861.6,58963.5,72065.5,85167.4,98269.4,111371,124473,137575,150677,163779,176881,189983,203085,216187,229289,242391,255493,268595,281697,294799,307901,321003,334105,347207,360309,373410,386512,399614,412716,425818,438920,452022,465124,478226,491328,504430,517532,530634,543736,556838,569940,596144,609246,20.4472,6554.12,19657.7,32759.6,45861.6,58963.5,72065.5,85167.4,98269.4,111371,124473,137575,150677,163779,176881,189983,203085,216187,229289,242391,255493,268595,281697,294799,307901,321003,334105,347207,360309,373410,386512,399614,412716,425818,438920,452022,465124,478226,491328,504430,517532,530634,543736,556838,569940,583042,596144,609246,622348,1.17965,15.9908,47.7102,79.4296,111.018,126.616,86.7697,91.4883,127.926,146.014,62.6524,145.883,166.461,31.9816,3.93216,10.6168,31.5884,199.229,69.9924,116.392,162.791,185.598", "uptime": "218.551,2308.34,2965.84,3622.58,4278.5,4933.12,5589.14,6244.89,6900.2,7554.75,8210.34,8865.86,63.7624,57.4371,172.802,2.38183,43.0423,69.6278,9.13055,106.546,2277.82,2926.43,3574.26,4222.3,4869.04,5513.56,6158.76,6804.15,7451.55,8100.4,8748.83,9396.49,22346.5,22992.8,23638.9,24285.1,24931,25576.9,26222.5,26868.6,27515.9,28162.9,28808,29455,30101.9,31715.7,90.6766,270.348,2015.33,6037.37,10057.8,14069.4,18077.2,22083,26086.5,30089.2,34091.5,38095,42101.7,46106.3,50112.8,54118,58124.2,62133.6,66143.1,70154,74165.3,78174,82183.5,86193.9,90207.5,94220.3,98228.7,102236,106246,110254,114269,118286,122301,126315,130324,134335,138347,142367,146391,150411,154415,158421,162425,166431,170449,174468,178484,182493,186494,196514,0.981901,3129.81,9384.56,15633.3,21847.6,258833,265117,271403,277677,283920,290205,296491,305923,43.032,128.189,28.4341,9.87066,8055.95,8379.36,8702.96,9025.59,9349.09,9672.64,9995.26,10319,10642.7,10965.6,11289.2,11613.1,11936,12583.3,12906.1,13229.8,13553.6,13876.7,14200.5,14524.2,14847.2,15494.6,0.874654,3.7356,10.9755,2015.33,6037.37,10057.8,14069.4,18077.2,22083,26086.5,30089.2,34091.5,38095,42101.7,46106.3,50112.8,54118,58124.2,62133.6,66143.1,70154,74165.3,78174,82183.5,86193.9,90207.5,94220.3,98228.7,102236,106246,110254,114269,118286,122301,126315,130324,134335,138347,142367,146391,150411,154415,158421,162425,166431,170449,174468,178484,182493,186494,190503,196514,55.9513,166.7,277.348,387.107,441.352,2015.33,6037.37,10057.8,14069.4,18077.2,22083,26086.5,30089.2,34091.5,38095,42101.7,46106.3,50112.8,54118,58124.2,62133.6,66143.1,70154,74165.3,78174,82183.5,86193.9,90207.5,94220.3,98228.7,102236,106246,110254,114269,118286,122301,126315,130324,134335,138347,142367,146391,150411,154415,158421,162425,166431,170449,174468,178484,182493,190503,196514,38.2538,468.905,534.895,239.754,335.178,382.508,51.9496,40.6145,2.15174,9.846,2968.84,3625.62,4281.71,4937.37,5592.84,6248.17,6903.23,7558.52,8213.87,8869.17,9525.03,22660.4,23315.7,23970.5,24625.5,25280.3,25935.2,26590.3,27245.4,27900.3,28555.3,2015.33,6037.37,10057.8,14069.4,18077.2,22083,26086.5,30089.2,34091.5,38095,42101.7,46106.3,50112.8,54118,58124.2,62133.6,66143.1,70154,74165.3,78174,82183.5,86193.9,90207.5,94220.3,98228.7,102236,106246,110254,114269,122301,126315,130324,134335,138347,142367,146391,150411,154415,158421,162425,166431,170449,174468,178484,182493,186494,190503,196514,2936.68,3586.74,4235.83,4884.67,5533.55,6179.76,6824.67,7473.21,8121.9,8770.47,9418.73,22360,23008.5,23658.6,24312.1,24965.5,25617.1,26264.5,26911.8,27559.2,28206.5,28853.4,30149.2,940.258,1564.21,2187.78,2811.04,3433.37,32.9386,994.026,60.772,55.8231,165.636,275.187,384.791,438.811,61.4068,423.858,4.0893,35.887,46.0483,136.476,48.6042,2015.33,6037.37,10057.8,14069.4,18077.2,22083,26086.5,30089.2,34091.5,38095,42101.7,46106.3,50112.8,54118,58124.2,62133.6,66143.1,70154,74165.3,78174,82183.5,86193.9,90207.5,94220.3,98228.7,102236,106246,110254,114269,118286,122301,126315,130324,134335,138347,142367,146391,150411,154415,158421,162425,166431,170449,174468,182493,186494,33.1119,2015.33,6037.37,10057.8,14069.4,18077.2,22083,26086.5,30089.2,34091.5,38095,42101.7,46106.3,50112.8,54118,58124.2,62133.6,66143.1,70154,74165.3,78174,82183.5,86193.9,90207.5,94220.3,98228.7,102236,106246,110254,114269,118286,122301,126315,130324,134335,138347,142367,146391,150411,154415,158421,162425,166431,170449,174468,178484,182493,186494,190503,0.860008,61.3374,182.893,304.426,425.485,485.266,132.81,302.294,422.697,482.476,209.001,486.57,555.218,54.2014,8.07813,7.45101,21.9072,509.388,163.949,272.604,381.257,434.637", "epoch": "270.5,2725.5,3504,4282.5,5061,5839.5,6618,7396.5,8175,8953.5,9732,10510.5,44.5,95.8438,288.255,12.5,30.5,68.5,61.5,118,2725.5,3504,4282.5,5061,5839.5,6618,7396.5,8175,8953.5,9732,10510.5,11289,26859,27637.5,28416,29194.5,29973,30751.5,31530,32308.5,33087,33865.5,34644,35422.5,36201,38146,87,259.5,2083.5,6249,10414,14579,18744,22909,27074,31239,35404,39569,43734,47899,52064,56229,60394,64559,68724,72889,77054,81219,85384,89549,93714,97879,102044,106209,110374,114539,118704,122869,127034,131199,135364,139529,143694,147859,152024,156189,160354,164519,168684,172849,177014,181179,185344,189509,193674,204086,2.5,3244.5,9732.5,16220,22707.5,269236,275723,282210,288698,295186,301673,308160,317891,95,283,36.5,30,5007.5,5212,5416.5,5620.5,5825,6029.5,6233.5,6438,6642.5,6846.5,7051,7255.5,7459.5,7868.5,8072.5,8277,8481.5,8685.5,8890,9094.5,9298.5,9707.5,4.5,2.5,73.4828,2083.5,6249,10414,14579,18744,22909,27074,31239,35404,39569,43734,47899,52064,56229,60394,64559,68724,72889,77054,81219,85384,89549,93714,97879,102044,106209,110374,114539,118704,122869,127034,131199,135364,139529,143694,147859,152024,156189,160354,164519,168684,172849,177014,181179,185344,189509,193674,197839,204086,103,307,510.833,713,813,2083.5,6249,10414,14579,18744,22909,27074,31239,35404,39569,43734,47899,52064,56229,60394,64559,68724,72889,77054,81219,85384,89549,93714,97879,102044,106209,110374,114539,118704,122869,127034,131199,135364,139529,143694,147859,152024,156189,160354,164519,168684,172849,177014,181179,185344,189509,197839,204086,61.5,938,1070,324,453,517,35.5,49.5,4.5,20.5,3504,4282.5,5061,5839.5,6618,7396.5,8175,8953.5,9732,10510.5,11289,26859,27637.5,28416,29194.5,29973,30751.5,31530,32308.5,33087,33865.5,2083.5,6249,10414,14579,18744,22909,27074,31239,35404,39569,43734,47899,52064,56229,60394,64559,68724,72889,77054,81219,85384,89549,93714,97879,102044,106209,110374,114539,118704,127034,131199,135364,139529,143694,147859,152024,156189,160354,164519,168684,172849,177014,181179,185344,189509,193674,197839,204086,3504,4282.5,5061,5839.5,6618,7396.5,8175,8953.5,9732,10510.5,11289,26859,27637.5,28416,29194.5,29973,30751.5,31530,32308.5,33087,33865.5,34644,36201,846.5,1410.5,1974.5,2538.5,3102.5,44.5,512,30.5,34.5,102.5,170.5,238.5,272,44.5,308,8.5,33.5,43,127.5,27,2083.5,6249,10414,14579,18744,22909,27074,31239,35404,39569,43734,47899,52064,56229,60394,64559,68724,72889,77054,81219,85384,89549,93714,97879,102044,106209,110374,114539,118704,122869,127034,131199,135364,139529,143694,147859,152024,156189,160354,164519,168684,172849,177014,181179,189509,193674,78,2083.5,6249,10414,14579,18744,22909,27074,31239,35404,39569,43734,47899,52064,56229,60394,64559,68724,72889,77054,81219,85384,89549,93714,97879,102044,106209,110374,114539,118704,122869,127034,131199,135364,139529,143694,147859,152024,156189,160354,164519,168684,172849,177014,181179,185344,189509,193674,197839,4.5,61,182,303,423.5,483,331,349,488,557,239,556.5,635,122,30,40.5,120.5,380,133.5,222,310.5,354", "env/perf": "0.0257273,0.0654934,0.0779807,0.0855004,0.0910541,0.0952511,0.0987761,0.102176,0.104277,0.106301,0.108864,0.110181,0.0251187,0.0251934,0.0256293,0.0250006,0.0250042,0.0250842,0.0250006,0.0253349,0.0687944,0.0807262,0.0874944,0.0928354,0.0969331,0.0997664,0.103082,0.105085,0.107332,0.109192,0.110185,0.11244,0.131881,0.133165,0.134384,0.13526,0.135809,0.136848,0.137758,0.13831,0.138602,0.139405,0.139715,0.139754,0.140123,0.140584,0.0252752,0.0256839,0.0791797,0.127681,0.143094,0.168337,0.179988,0.186188,0.189987,0.192729,0.194316,0.196604,0.198082,0.199237,0.200904,0.201896,0.203082,0.204789,0.205807,0.206657,0.208,0.208603,0.210123,0.211467,0.212001,0.213322,0.213826,0.214565,0.215699,0.216368,0.217147,0.217259,0.217839,0.219114,0.21992,0.220965,0.221794,0.223481,0.224749,0.225918,0.226839,0.227247,0.227772,0.22889,0.229712,0.230946,0.231036,0.231655,0.231838,0.232867,0.0250005,0.0936235,0.136833,0.173112,0.184817,0.233067,0.233528,0.233996,0.234455,0.234877,0.235181,0.23521,0.236936,0.0251097,0.0254284,0.0250013,0.0250006,0.107338,0.109281,0.109968,0.110955,0.112111,0.113637,0.114632,0.117197,0.117385,0.119189,0.120789,0.120999,0.121906,0.123168,0.1243,0.126391,0.127513,0.128952,0.130316,0.130578,0.130761,0.131367,0.025,0.0250005,0.0250007,0.0791808,0.127572,0.143014,0.168387,0.180157,0.186372,0.190027,0.192684,0.194331,0.196604,0.198068,0.19917,0.200998,0.201871,0.202945,0.204696,0.205774,0.206536,0.208016,0.208581,0.210119,0.211408,0.212261,0.21344,0.213921,0.214826,0.215696,0.216357,0.216871,0.217244,0.217792,0.219013,0.220125,0.220932,0.221851,0.223467,0.224532,0.22587,0.226766,0.227151,0.227963,0.228979,0.229895,0.230744,0.231158,0.231572,0.231667,0.231927,0.232487,0.0251849,0.0259065,0.0261616,0.0263474,0.0264482,0.0792312,0.127674,0.142946,0.168153,0.180028,0.186344,0.189998,0.192701,0.194411,0.196596,0.198295,0.199249,0.200816,0.201944,0.203115,0.204655,0.205817,0.206656,0.207925,0.208578,0.210152,0.211429,0.212149,0.213376,0.213897,0.214742,0.215577,0.216315,0.216875,0.217225,0.2181,0.219097,0.220063,0.220868,0.221896,0.223424,0.224664,0.225941,0.226782,0.227195,0.227762,0.228877,0.229867,0.230842,0.230964,0.231477,0.231965,0.232914,0.0250397,0.0264662,0.0265086,0.0261199,0.0262705,0.0262993,0.0250698,0.0250013,0.025,0.025001,0.0750105,0.0836701,0.0897074,0.0951085,0.098539,0.102274,0.104297,0.106579,0.107883,0.109926,0.111405,0.131373,0.132759,0.133642,0.134547,0.135496,0.136519,0.13737,0.137911,0.138422,0.139074,0.079258,0.127611,0.142957,0.168298,0.180086,0.186304,0.19013,0.192723,0.194405,0.196689,0.198289,0.199148,0.200911,0.201939,0.203211,0.204659,0.205812,0.206392,0.20791,0.208502,0.210057,0.211581,0.212104,0.213312,0.213834,0.214625,0.215607,0.216265,0.216989,0.218074,0.219169,0.219897,0.221004,0.221937,0.223457,0.224575,0.22581,0.226792,0.227335,0.227796,0.228982,0.22981,0.230751,0.231055,0.231473,0.231852,0.232177,0.232542,0.0738594,0.0825647,0.0899443,0.0942339,0.0981072,0.101718,0.104374,0.106477,0.108397,0.110293,0.111544,0.131817,0.13281,0.134183,0.135151,0.135856,0.136712,0.137626,0.138418,0.138813,0.139222,0.139706,0.139964,0.0412625,0.0550309,0.0633813,0.0683335,0.0718248,0.0250022,0.0264842,0.0250056,0.0250472,0.0255168,0.0259104,0.0260861,0.0261763,0.0251226,0.0261986,0.025,0.0250217,0.0250931,0.0254116,0.0250039,0.0791935,0.127618,0.143025,0.168307,0.180085,0.186395,0.189981,0.192732,0.194244,0.196742,0.198164,0.199109,0.20093,0.201764,0.202904,0.204515,0.205879,0.206418,0.207906,0.208626,0.210182,0.211574,0.212208,0.21328,0.213915,0.214749,0.21573,0.216164,0.216969,0.217192,0.218061,0.218791,0.220087,0.220881,0.221747,0.22345,0.224612,0.225777,0.22667,0.227211,0.22776,0.228853,0.229767,0.230676,0.231429,0.231924,0.0250277,0.0791614,0.127729,0.143081,0.168293,0.179989,0.186526,0.190011,0.19264,0.194384,0.196551,0.198253,0.199303,0.200977,0.202026,0.202946,0.204559,0.206003,0.206688,0.207926,0.208483,0.210153,0.211434,0.212156,0.213355,0.213894,0.214693,0.215569,0.216401,0.21695,0.217335,0.217906,0.218951,0.220077,0.220913,0.221889,0.223387,0.224654,0.225857,0.226844,0.227291,0.2279,0.228902,0.229752,0.23084,0.230967,0.231512,0.231699,0.23204,0.025,0.025004,0.0255168,0.0258599,0.0260654,0.0261796,0.0255991,0.025931,0.0261255,0.0263021,0.0256352,0.0262309,0.0263206,0.0251449,0.0250006,0.0250006,0.0250012,0.0263574,0.0255013,0.0259783,0.0261678,0.0262032", "env/score": "1.02909,2.61973,3.11923,3.42001,3.64217,3.81004,3.95104,4.08703,4.17106,4.25204,4.35455,4.40723,1.00475,1.00773,1.02517,1.00002,1.00017,1.00337,1.00003,1.0134,2.75178,3.22905,3.49978,3.71341,3.87733,3.99066,4.12329,4.20338,4.29326,4.36769,4.40741,4.49759,5.27525,5.3266,5.37538,5.41038,5.43236,5.47392,5.5103,5.53241,5.54409,5.57619,5.5886,5.59015,5.60492,5.62335,1.01101,1.02736,3.16719,5.10723,5.72377,6.73348,7.19951,7.44752,7.59948,7.70917,7.77265,7.86417,7.92326,7.9695,8.03616,8.07584,8.12329,8.19155,8.23227,8.26626,8.31999,8.34414,8.40492,8.45867,8.48006,8.53289,8.55304,8.58258,8.62797,8.65471,8.68589,8.69037,8.71357,8.76455,8.79682,8.83859,8.87176,8.93923,8.98997,9.03673,9.07355,9.08987,9.11086,9.15559,9.18846,9.23783,9.24144,9.26622,9.27352,9.31466,1.00002,3.74494,5.47333,6.92447,7.39266,9.32268,9.3411,9.35984,9.37819,9.39508,9.40725,9.40842,9.47743,1.00439,1.01714,1.00005,1.00002,4.29353,4.37122,4.39872,4.43818,4.48444,4.54549,4.58528,4.68789,4.69542,4.76754,4.83156,4.83996,4.87625,4.92671,4.972,5.05565,5.10051,5.15808,5.21266,5.22311,5.23042,5.25468,1,1.00002,1.00003,3.16723,5.1029,5.72057,6.73547,7.20627,7.45486,7.60107,7.70735,7.77325,7.86416,7.92274,7.96681,8.03991,8.07485,8.1178,8.18783,8.23095,8.26143,8.32062,8.34326,8.40475,8.45631,8.49043,8.53761,8.55684,8.59303,8.62783,8.65428,8.67485,8.68975,8.71167,8.76052,8.80501,8.83727,8.87405,8.93868,8.98126,9.0348,9.07066,9.08603,9.1185,9.15918,9.19582,9.22974,9.24633,9.26289,9.26668,9.27709,9.29947,1.0074,1.03626,1.04646,1.0539,1.05793,3.16925,5.10696,5.71786,6.72612,7.2011,7.45376,7.59993,7.70805,7.77646,7.86383,7.93178,7.96996,8.03263,8.07777,8.12459,8.1862,8.23266,8.26624,8.31699,8.34312,8.40609,8.45715,8.48595,8.53505,8.55588,8.58969,8.62307,8.65262,8.67502,8.689,8.724,8.76389,8.80251,8.83471,8.87583,8.93695,8.98656,9.03765,9.07129,9.08781,9.11048,9.15506,9.19467,9.23369,9.23856,9.25909,9.27862,9.31655,1.00159,1.05865,1.06034,1.04479,1.05082,1.05197,1.00279,1.00005,1,1.00004,3.00042,3.3468,3.5883,3.80434,3.94156,4.09095,4.17186,4.26316,4.31532,4.39702,4.4562,5.25493,5.31036,5.34568,5.38187,5.41984,5.46077,5.49481,5.51646,5.53687,5.56294,3.17032,5.10445,5.71829,6.73193,7.20345,7.45217,7.60519,7.7089,7.77621,7.86757,7.93155,7.96592,8.03645,8.07756,8.12844,8.18635,8.23249,8.25566,8.31639,8.34009,8.40227,8.46322,8.48417,8.53247,8.55337,8.58498,8.62429,8.65061,8.67957,8.72294,8.76675,8.79588,8.84014,8.87748,8.93829,8.98298,9.03242,9.07169,9.09341,9.11184,9.15928,9.19239,9.23004,9.2422,9.25891,9.27409,9.28706,9.30168,2.95437,3.30259,3.59777,3.76936,3.92429,4.06872,4.17495,4.25908,4.33588,4.41173,4.46176,5.2727,5.31242,5.36731,5.40606,5.43425,5.46849,5.50504,5.53671,5.55252,5.56889,5.58824,5.59856,1.6505,2.20124,2.53525,2.73334,2.87299,1.00009,1.05937,1.00022,1.00189,1.02067,1.03642,1.04345,1.04705,1.0049,1.04795,1,1.00087,1.00372,1.01646,1.00016,3.16774,5.10471,5.72099,6.73228,7.2034,7.45581,7.59926,7.7093,7.76975,7.86968,7.92657,7.96434,8.03718,8.07056,8.11617,8.18061,8.23517,8.25671,8.31625,8.34506,8.40728,8.46297,8.48834,8.53122,8.55659,8.58996,8.6292,8.64655,8.67877,8.68766,8.72246,8.75163,8.80348,8.83526,8.8699,8.93801,8.98448,9.03109,9.06679,9.08846,9.11041,9.15414,9.1907,9.22706,9.25715,9.27697,1.00111,3.16646,5.10918,5.72325,6.73172,7.19957,7.46102,7.60045,7.70558,7.77535,7.86204,7.9301,7.97213,8.03907,8.08103,8.11784,8.18237,8.24011,8.26751,8.31705,8.3393,8.4061,8.45737,8.48625,8.53422,8.55574,8.58772,8.62274,8.65604,8.67802,8.69338,8.71624,8.75805,8.80307,8.8365,8.87555,8.93548,8.98617,9.03427,9.07376,9.09165,9.116,9.15606,9.19008,9.23361,9.23868,9.26049,9.26797,9.2816,1,1.00016,1.02067,1.0344,1.04262,1.04718,1.02396,1.03724,1.04502,1.05208,1.02541,1.04924,1.05282,1.0058,1.00002,1.00002,1.00005,1.0543,1.02005,1.03913,1.04671,1.04813", "env/episode_return": "0.303126,4.71161,5.90974,6.62698,7.13117,7.5308,7.86049,8.18277,8.38449,8.59587,8.84123,8.97372,-0.538845,-0.0134112,0.131379,-0.998276,-0.189747,-0.100888,-0.123135,0.0249046,5.02672,6.13289,6.78668,7.28812,7.67384,7.95001,8.26759,8.46461,8.68593,8.87091,8.96854,9.17249,10.9114,11.0222,11.1413,11.2302,11.2757,11.3753,11.4586,11.5152,11.5398,11.615,11.6484,11.6474,11.681,11.7178,0.00318764,0.0941757,5.66665,10.5383,11.9914,14.4235,15.5126,16.0291,16.3362,16.5548,16.6782,16.8601,16.9786,17.0626,17.1979,17.28,17.3673,17.5093,17.5848,17.6517,17.7621,17.8128,17.9292,18.0335,18.0708,18.1787,18.2129,18.2704,18.3651,18.4153,18.4724,18.4863,18.5372,18.637,18.6998,18.7805,18.8413,18.9754,19.0712,19.1622,19.2311,19.2612,19.3064,19.3945,19.4598,19.5564,19.5628,19.6079,19.6234,19.6731,-0.896152,7.10095,11.3697,14.9071,15.9256,19.7505,19.7863,19.8275,19.8642,19.8964,19.9208,19.9234,20.0442,-0.682222,-0.540993,-0.840345,-0.519636,7.97174,8.12343,8.18706,8.26059,8.37838,8.52665,8.62339,8.85096,8.87873,9.05326,9.20494,9.24189,9.31263,9.4198,9.51584,9.7043,9.82166,9.93645,10.0575,10.0939,10.108,10.1651,-0.415672,-0.128588,-0.385624,5.66575,10.5283,11.9881,14.4305,15.5262,16.0421,16.3394,16.5519,16.6777,16.8606,16.9749,17.0556,17.2047,17.2764,17.3582,17.5024,17.5907,17.6415,17.7613,17.8083,17.927,18.028,18.0902,18.1908,18.2198,18.2897,18.3641,18.4177,18.4544,18.4866,18.5348,18.6305,18.7164,18.7764,18.8474,18.9708,19.0523,19.1592,19.2248,19.25,19.3213,19.4009,19.4731,19.5426,19.5706,19.5997,19.6112,19.6296,19.6681,-0.171317,0.00487088,0.0554354,0.109083,0.134386,5.6704,10.536,11.9825,14.4114,15.5145,16.0457,16.3374,16.5549,16.6872,16.861,16.9932,17.0641,17.1919,17.2828,17.3712,17.5016,17.5887,17.6522,17.7533,17.8038,17.9308,18.0297,18.0838,18.1823,18.218,18.2833,18.3548,18.4115,18.451,18.4853,18.5568,18.6356,18.7133,18.7728,18.8491,18.9693,19.0638,19.1639,19.2217,19.2563,19.3052,19.3921,19.4727,19.5477,19.5544,19.5956,19.6375,19.7115,-0.345572,0.325168,0.336049,-0.277946,-0.236246,-0.227868,-0.882885,-0.334946,-0.17736,-0.177089,5.61243,6.44377,7.01722,7.5102,7.84696,8.21282,8.41593,8.62652,8.75286,8.9436,9.07802,10.8867,10.999,11.0705,11.1661,11.2607,11.3459,11.4349,11.4768,11.5238,11.5831,5.67106,10.532,11.9835,14.4212,15.5196,16.0373,16.3459,16.5554,16.6821,16.8678,16.9943,17.0549,17.1973,17.2848,17.379,17.4981,17.589,17.6318,17.7516,17.8002,17.9231,18.0425,18.0808,18.177,18.2123,18.2775,18.3569,18.4068,18.4597,18.5532,18.6428,18.6997,18.7825,18.8516,18.97,19.0589,19.1552,19.2264,19.2641,19.3114,19.4036,19.4691,19.5442,19.5623,19.5958,19.6262,19.649,19.671,5.51603,6.34429,7.02911,7.42086,7.7873,8.12698,8.39306,8.60217,8.78805,8.96748,9.08264,10.9232,11.018,11.1433,11.2298,11.2914,11.3765,11.4615,11.5378,11.573,11.6082,11.6564,11.6813,1.93624,3.63577,4.50995,5.04187,5.40958,-0.409885,0.0564082,-0.307037,-0.232704,-0.0740045,-0.0320615,-0.00136696,0.0216363,-0.349436,-0.0758413,-0.27096,-0.800124,-0.408118,-0.250592,-0.42862,5.66604,10.5323,11.9888,14.4236,15.5192,16.0435,16.3372,16.5575,16.6747,16.8721,16.9845,17.0543,17.198,17.2676,17.3534,17.4907,17.5954,17.6344,17.7488,17.8137,17.9302,18.0411,18.0869,18.1758,18.2164,18.2854,18.3692,18.4014,18.4616,18.4831,18.5528,18.6129,18.7158,18.7682,18.8379,18.9701,19.0607,19.1489,19.2179,19.2577,19.3067,19.3962,19.4641,19.5386,19.5912,19.6311,-0.00615218,5.6638,10.5429,11.9922,14.4234,15.5113,16.0556,16.3393,16.5465,16.684,16.8565,16.99,17.0674,17.2023,17.2896,17.3569,17.4943,17.6032,17.6561,17.7545,17.8011,17.9298,18.0339,18.082,18.1798,18.2181,18.2793,18.3556,18.4171,18.4621,18.4923,18.5435,18.6258,18.7135,18.7729,18.8484,18.9646,19.0628,19.1589,19.2288,19.2617,19.3182,19.3997,19.4642,19.5496,19.5576,19.5982,19.6134,19.6389,-0.93647,-0.246245,-0.00370235,0.0663562,0.10584,0.114793,0.0828004,0.0769,0.12827,0.166545,-0.107414,-0.0105064,0.0129351,-0.524832,-0.342436,-0.992987,-0.976485,0.0308391,-0.709884,-0.579577,-0.528673,-0.533216", "env/episode_length": "118.901,428.18,491.261,514.938,535.298,551.48,563.104,579.891,586.334,594.425,605.678,608.606,77.7387,96.3832,99.2357,46.0597,84.9134,83.9174,47.1175,100.335,445.164,498.395,518.639,541.292,557.013,569.25,583.021,590.175,599.618,606.997,609.158,620.184,756.362,768.348,775.968,781.269,785.905,791.761,801.221,802.473,807.344,811.792,813.874,811.592,815.243,816.588,96.4942,105.67,521.422,731.581,804.001,899.603,941.505,967.439,984.159,995.939,1003.32,1014.36,1021.03,1028.7,1037.76,1041.97,1050.48,1057.88,1062.31,1069.07,1076.66,1084.17,1087.99,1093.29,1096.87,1103.14,1106.17,1109.8,1116.32,1118.82,1123.12,1124.93,1128.44,1137.67,1143.33,1149.6,1157.48,1169.51,1180.65,1189.33,1198.38,1204.48,1214.09,1224.53,1231.61,1238.77,1241.04,1246.49,1246.72,1251.36,31.8164,578.567,759.901,912.332,956.2,1224.46,1227.26,1230.51,1234.78,1236.33,1238.33,1239.03,1253.67,92.7749,99.4119,92.2972,43.7496,563.615,578.39,580.328,583.603,587.315,602.496,597.538,610.291,597.601,605.508,619.017,611.736,620.805,634.579,646.172,664.461,668.608,684.802,692.817,697.648,697.715,702.031,35.1955,36.4417,48.8203,520.904,730.824,803.14,899.152,942.562,968.978,984.334,995.278,1003.86,1013.98,1021.06,1028.32,1038.76,1041.76,1049.21,1057.29,1062.65,1067.67,1076.05,1084.35,1087.83,1092.19,1098.29,1103.92,1106.72,1111.73,1115.92,1119.83,1121.49,1124.04,1128.55,1137.28,1144.05,1150.18,1158.21,1169.74,1179.15,1189.62,1198.99,1203.64,1215.41,1226.57,1231.88,1236.95,1240.88,1245.81,1245.82,1247.41,1246.03,100.528,123.462,143.037,169.257,178.121,521.687,732.274,803.049,898.206,941.693,968.799,984.477,995.102,1004.1,1014.14,1022.56,1028.47,1036.62,1041.97,1050.14,1056.63,1062.37,1068.65,1076.35,1083.43,1088.24,1093.56,1097.14,1103.12,1107.25,1110.99,1115.02,1119.74,1121.22,1124.24,1130.4,1136.99,1143.33,1150.25,1157.64,1169.85,1180.28,1189.69,1197.72,1204.22,1214,1225.31,1232.04,1237.52,1240.29,1244.66,1247.11,1252.37,94.6044,176.143,189.598,143.536,164.608,170.914,85.0159,83.8943,42.0344,40.4456,479.706,514.497,536.172,558.159,570.178,584.305,595.8,601.156,604.707,612.512,621.872,755.013,769.349,774.393,782.477,789.925,797.705,802.271,804.412,809.005,816.84,521.575,730.787,803.09,898.891,941.457,968.729,984.729,994.844,1004.42,1014.87,1022.74,1027.89,1037.37,1042.56,1050.75,1057.12,1062.03,1067.66,1075.96,1083.17,1087.68,1093.85,1097.22,1103.09,1106.98,1110.63,1115.96,1119.05,1122.14,1130.41,1137.8,1142.09,1150.79,1158.53,1170.39,1179.59,1189.58,1198.35,1205.1,1214.75,1226.88,1231.57,1236.66,1240.02,1244.68,1246.85,1248.26,1247.1,476.142,508.351,541.174,551.469,569.51,582.754,595.388,600.332,606.009,614.655,618.583,747.024,753.658,768.036,775.647,780.801,785.487,791.65,799.456,801.045,805.264,807.197,807.616,241.269,291.565,322.894,333.715,342.484,104.026,145.552,84.0988,98.8876,110.409,114.421,123.278,126.453,98.0161,139.038,42.7743,85.0168,89.2747,95.3509,79.6393,521.213,730.68,803.127,899.184,942.11,969.72,983.981,996.16,1002.66,1014.53,1021.24,1027.56,1037.98,1040.79,1049.15,1055.58,1062.66,1066.77,1075.6,1084.22,1088.56,1093.74,1097.8,1102.11,1107.57,1110.85,1115.79,1118.63,1121.26,1123.68,1130.29,1136.11,1144.44,1149.94,1157.43,1169.77,1180.15,1188.24,1198.39,1203.73,1213.97,1224.56,1231.52,1235.92,1244.89,1247.69,99.7898,521.091,732.053,803.901,898.491,941.793,968.903,983.727,994.681,1004.35,1013.37,1022.55,1028.31,1037.9,1042.73,1049.03,1056.56,1063.05,1068.55,1075.73,1082.96,1088.41,1093.2,1098.12,1103.39,1106.89,1110.98,1115.54,1119.18,1122.29,1124.81,1129.41,1136.88,1144.3,1150.01,1157.9,1169.09,1180.52,1188.44,1199.03,1204.15,1214.96,1224.63,1231.52,1237.54,1240.71,1245.8,1246.01,1247.72,43.9982,99.7238,118.804,131.113,146.65,153.294,137.121,108.288,130.276,140.511,106.452,136.85,143.664,102.274,39.8991,56.4291,85.377,149.918,118.448,134.445,154.103,157.606", "env/return_comb_lvl": "0.248155,1.86062,2.41861,2.77014,3.03868,3.24476,3.42473,3.59893,3.70699,3.81223,3.95239,4.02748,0.0862206,0.104835,0.218995,0.000960571,0.0296362,0.0825593,0.00573009,0.17788,2.02559,2.55822,2.86837,3.13429,3.33723,3.47833,3.64579,3.75036,3.87003,3.97384,4.02121,4.15393,5.2539,5.33007,5.41153,5.47081,5.5034,5.56674,5.62442,5.66438,5.67802,5.73094,5.75421,5.75722,5.77515,5.80435,0.186168,0.249842,2.66085,5.02835,5.648,6.31197,6.78845,7.06045,7.23007,7.35617,7.4333,7.53972,7.60807,7.67019,7.74413,7.78844,7.84496,7.91694,7.96561,8.00096,8.07221,8.09113,8.16567,8.23289,8.26265,8.32598,8.35325,8.39157,8.44806,8.48171,8.52288,8.52759,8.55373,8.61237,8.65246,8.69989,8.74236,8.8218,8.88443,8.94096,8.98567,8.99586,9.02912,9.08425,9.12886,9.18463,9.19386,9.22538,9.23596,9.29774,5.91575e-05,3.36619,5.4954,6.5366,7.00323,9.34828,9.3704,9.39936,9.4215,9.44485,9.46046,9.46522,9.5359,0.112485,0.2291,0.00894219,0.00368174,3.9889,4.08822,4.1378,4.19106,4.27013,4.3562,4.43584,4.56656,4.60302,4.71865,4.80977,4.84314,4.87545,4.95387,5.02083,5.15496,5.23457,5.30799,5.3937,5.41857,5.43292,5.46448,1.95604e-05,0.00370611,0.0104008,2.66052,5.02381,5.64383,6.31402,6.79607,7.06827,7.23133,7.35467,7.43518,7.53955,7.60729,7.66593,7.74937,7.78779,7.8402,7.91515,7.96473,7.99748,8.07365,8.09051,8.16383,8.22825,8.27497,8.33263,8.35862,8.40213,8.4473,8.4813,8.50926,8.52944,8.55495,8.60823,8.66139,8.69823,8.74675,8.82042,8.87387,8.94339,8.98427,8.99193,9.03577,9.08715,9.13596,9.17642,9.19884,9.21916,9.2299,9.24536,9.28143,0.150632,0.26046,0.272693,0.289183,0.300513,2.66312,5.02798,5.63837,6.30324,6.7902,7.06973,7.23057,7.35592,7.43853,7.53985,7.61756,7.67067,7.74022,7.79099,7.84617,7.9127,7.96646,8.00324,8.06943,8.09077,8.16651,8.23013,8.26854,8.32788,8.35579,8.39902,8.44293,8.4786,8.50989,8.52568,8.56654,8.61223,8.65763,8.6943,8.74722,8.81993,8.87979,8.94411,8.98295,8.99472,9.02631,9.08038,9.13653,9.17953,9.19034,9.2186,9.24755,9.27933,0.0531101,0.313262,0.314024,0.253924,0.2515,0.248934,0.102152,0.00487245,0.000150112,0.000373721,2.29658,2.69435,2.98579,3.2518,3.42167,3.60905,3.70277,3.8251,3.89823,4.01245,4.08936,5.24592,5.32329,5.37557,5.4343,5.49789,5.55582,5.61881,5.64399,5.67818,5.71128,2.66422,5.02576,5.64098,6.31017,6.79238,7.06534,7.23443,7.35641,7.43802,7.54376,7.61762,7.66473,7.74489,7.79187,7.85133,7.91446,7.96648,7.99173,8.0678,8.08952,8.16286,8.23582,8.26634,8.32685,8.3535,8.39512,8.44307,8.47659,8.51451,8.56587,8.61632,8.65247,8.70278,8.74905,8.82254,8.87698,8.93656,8.98396,8.99919,9.03002,9.0869,9.13306,9.17811,9.19362,9.21666,9.23795,9.2548,9.29132,2.2727,2.65238,3.00702,3.21708,3.40329,3.58772,3.72548,3.82624,3.9269,4.02946,4.0948,5.27167,5.33678,5.41887,5.47782,5.52003,5.57571,5.63094,5.67994,5.709,5.72955,5.76396,5.78407,0.90757,1.41655,1.78543,1.95882,2.10517,0.01773,0.318035,0.0166923,0.124079,0.247382,0.253275,0.264688,0.274886,0.0963074,0.266642,0.000848718,0.050436,0.0801197,0.215771,0.00800759,2.66033,5.02658,5.64554,6.31062,6.79278,7.0687,7.22905,7.35603,7.43069,7.54663,7.61261,7.6641,7.7459,7.78237,7.83742,7.90671,7.96988,7.99417,8.06697,8.09332,8.16777,8.23779,8.27127,8.3228,8.35691,8.39953,8.44759,8.47322,8.51553,8.52494,8.56469,8.60007,8.66051,8.69532,8.74067,8.82047,8.88054,8.93679,8.97908,8.99446,9.02866,9.08365,9.13149,9.17411,9.21452,9.2409,0.104488,2.65981,5.03261,5.64554,6.31099,6.78883,7.07534,7.23017,7.35156,7.43703,7.53958,7.6148,7.67186,7.74677,7.79221,7.83925,7.9098,7.97569,8.00667,8.06798,8.08712,8.1666,8.23093,8.26987,8.32683,8.35725,8.39676,8.44298,8.48243,8.51539,8.53308,8.55788,8.60547,8.66036,8.69665,8.74656,8.81654,8.88034,8.93874,8.98727,8.99765,9.03357,9.08334,9.13092,9.18107,9.19135,9.21974,9.23252,9.24937,0.000404423,0.00904928,0.221044,0.260258,0.276275,0.279988,0.246505,0.245422,0.268313,0.28134,0.235307,0.274722,0.285116,0.112273,0.00121828,0.00094631,0.00963282,0.307528,0.186695,0.261351,0.270612,0.260991", "env/return_prof_lvl": "0.0566081,3.51462,4.10351,4.43983,4.64933,4.8208,4.95099,5.07566,5.15563,5.24519,5.33142,5.37957,0.00637348,0.0121296,0.0427765,3.7485e-05,0.000196034,0.00457361,0,0.0221896,3.65078,4.17924,4.49579,4.70044,4.85904,4.9764,5.10523,5.18482,5.26933,5.33551,5.37907,5.43291,5.90703,5.93019,5.95876,5.97901,5.98662,6.01332,6.02966,6.04315,6.0505,6.06585,6.07203,6.06986,6.08341,6.08962,0.0171948,0.042941,3.56229,5.78693,6.532,8.19041,8.70191,8.90634,9.02384,9.10021,9.14365,9.20416,9.24867,9.2661,9.31645,9.35098,9.37596,9.4327,9.45462,9.48447,9.51414,9.54098,9.57289,9.60444,9.61036,9.64693,9.65288,9.66811,9.69944,9.7121,9.72481,9.73508,9.75569,9.78753,9.80357,9.83029,9.84266,9.88355,9.90756,9.93273,9.95193,9.96682,9.96867,9.99483,10.0079,10.0408,10.0375,10.0465,10.0505,10.0285,3.97836e-05,4.20607,6.09112,8.39106,8.8754,10.0819,10.0923,10.1001,10.1118,10.1176,10.1245,10.1225,10.1621,0.00699244,0.0304824,9.67691e-05,0,4.47995,4.51431,4.52495,4.53884,4.56657,4.61264,4.62793,4.71335,4.70545,4.74983,4.80153,4.80422,4.8357,4.84684,4.8645,4.90158,4.93162,4.95904,4.98457,4.99027,4.99081,5.01024,0,1.76629e-05,0,3.56225,5.78249,6.53358,8.19551,8.70758,8.91061,9.02607,9.09913,9.14093,9.2051,9.24625,9.26372,9.31748,9.3483,9.37228,9.4275,9.46052,9.47879,9.5119,9.53706,9.57349,9.60419,9.61582,9.6511,9.65422,9.67551,9.6992,9.71426,9.72214,9.7341,9.7516,9.78576,9.8104,9.82812,9.8434,9.88156,9.90116,9.92685,9.94763,9.96127,9.97669,9.99709,10.0133,10.0363,10.0399,10.0447,10.0449,10.0461,10.0441,0.0123403,0.0734701,0.104385,0.130207,0.140382,3.5637,5.78466,6.53395,8.18756,8.70265,8.91255,9.02446,9.10087,9.14633,9.2051,9.25275,9.26714,9.31534,9.35083,9.37865,9.42958,9.45698,9.48248,9.50822,9.53293,9.57409,9.60345,9.61619,9.64819,9.65517,9.67247,9.69504,9.7112,9.71818,9.73644,9.76101,9.78686,9.81133,9.82926,9.84547,9.88038,9.90572,9.93109,9.94614,9.9637,9.97099,9.99587,10.0124,10.038,10.0333,10.0417,10.0514,10.0883,0.00220906,0.120755,0.1292,0.0957864,0.123576,0.12846,0.00341485,9.81549e-05,0,1.89582e-05,3.93881,4.33662,4.5912,4.79101,4.93662,5.09191,5.18594,5.25947,5.30352,5.36534,5.41079,5.89307,5.91776,5.93157,5.95575,5.97921,5.99755,6.01612,6.02947,6.03697,6.05488,3.56362,5.78377,6.53192,8.19027,8.70492,8.90879,9.02835,9.10101,9.14136,9.20726,9.25329,9.26407,9.31518,9.35225,9.38009,9.42388,9.45779,9.47523,9.509,9.53085,9.57067,9.60957,9.61596,9.64437,9.65167,9.67144,9.69676,9.70926,9.72171,9.75812,9.78921,9.80377,9.82929,9.84543,9.87825,9.90331,9.9304,9.94893,9.967,9.97238,10.0002,10.0125,10.0357,10.0374,10.0442,10.051,10.0548,10.0419,3.86476,4.28284,4.57717,4.74106,4.89801,5.03191,5.14169,5.23596,5.30822,5.37029,5.40869,5.90613,5.92557,5.95342,5.97198,5.98626,6.00806,6.0305,6.04933,6.05221,6.06115,6.07146,6.07682,1.85271,2.9884,3.45869,3.80268,4.00896,0.000132426,0.141684,0.000331918,0.00267748,0.0368649,0.0719149,0.0886323,0.100779,0.00773611,0.0969663,1.75967e-05,0.00108854,0.00567019,0.0270548,0.000231389,3.56263,5.78339,6.53241,8.19149,8.70443,8.9117,9.026,9.10316,9.14272,9.20854,9.24994,9.26451,9.31451,9.34591,9.37024,9.42488,9.4601,9.47521,9.5069,9.53949,9.57241,9.6064,9.61685,9.64729,9.6524,9.67457,9.70386,9.70706,9.7231,9.7353,9.75842,9.7776,9.81046,9.82348,9.84123,9.88029,9.90173,9.92451,9.94646,9.96529,9.96928,9.9965,10.0093,10.035,10.0414,10.0531,0.00150759,3.56092,5.78667,6.53591,8.19167,8.70068,8.91588,9.02722,9.09773,9.14437,9.2014,9.25225,9.2695,9.31755,9.35614,9.37163,9.42527,9.46136,9.4826,9.51119,9.53401,9.57299,9.60642,9.61314,9.64645,9.65361,9.6713,9.69532,9.71269,9.72266,9.73548,9.75702,9.78441,9.80875,9.82649,9.84477,9.87954,9.9038,9.93253,9.94826,9.96568,9.97588,10,10.01,10.0385,10.0348,10.0431,10.0446,10.051,0,0.000186536,0.0274876,0.0553426,0.074468,0.0788022,0.0390025,0.0679715,0.091467,0.114428,0.040073,0.0881797,0.100238,0.00831016,0,6.44103e-05,5.96375e-05,0.107557,0.0323214,0.0755788,0.100013,0.100917", "env/return_item_atk_lvl": "2.67687e-05,0.0700529,0.0847391,0.0925789,0.0991294,0.103971,0.107781,0.11147,0.114475,0.117103,0.119915,0.122567,6.05146e-05,2.68063e-05,2.4365e-05,0,6.24729e-07,2.66474e-05,0,3.39198e-05,0.0738146,0.0873751,0.0943311,0.100484,0.105372,0.10914,0.11302,0.115749,0.118571,0.121336,0.123674,0.12696,0.146938,0.147878,0.148739,0.149714,0.149942,0.151048,0.151624,0.152391,0.152477,0.153103,0.153187,0.153449,0.153711,0.153255,0.000223031,0.000743118,0.0778948,0.139208,0.154818,0.188364,0.204203,0.209492,0.212931,0.214992,0.215833,0.217715,0.218825,0.219352,0.220585,0.221495,0.22205,0.224017,0.22449,0.224934,0.22607,0.226609,0.227959,0.229003,0.2289,0.230182,0.230304,0.230826,0.231698,0.232257,0.232493,0.232782,0.233191,0.234218,0.234847,0.235738,0.236102,0.237425,0.238003,0.238671,0.239243,0.239629,0.240113,0.240786,0.241051,0.241968,0.241757,0.242227,0.242241,0.24237,0,0.0969552,0.151033,0.197101,0.209327,0.24486,0.245119,0.245424,0.245709,0.246154,0.246461,0.24632,0.248945,1.60357e-05,1.685e-05,0,0,0.101151,0.101779,0.102745,0.104001,0.104677,0.106228,0.107094,0.108282,0.108501,0.109366,0.110676,0.110983,0.112346,0.113082,0.113815,0.114628,0.115491,0.116209,0.117024,0.117468,0.117463,0.117644,0,1.67577e-06,0,0.0778432,0.139026,0.154756,0.188405,0.204309,0.209761,0.212805,0.21494,0.215804,0.217814,0.218733,0.219204,0.220707,0.221422,0.22184,0.223796,0.224633,0.224757,0.226197,0.226577,0.227751,0.22885,0.229108,0.230172,0.230209,0.23075,0.231847,0.232223,0.232431,0.232897,0.233319,0.234183,0.23503,0.235526,0.23614,0.237192,0.237686,0.238686,0.239155,0.239474,0.240185,0.240795,0.241461,0.241823,0.241825,0.242228,0.242318,0.242357,0.243424,3.3072e-05,1.24477e-05,2.06263e-05,1.97378e-05,1.10615e-05,0.0779312,0.139165,0.154658,0.188245,0.204085,0.209724,0.212854,0.215135,0.215912,0.217771,0.218856,0.219375,0.220598,0.221601,0.222097,0.223875,0.224602,0.224976,0.225934,0.226713,0.227737,0.228764,0.229224,0.230044,0.230192,0.230884,0.231553,0.232182,0.232318,0.232732,0.233684,0.234153,0.235092,0.23553,0.236098,0.237224,0.237895,0.23873,0.239149,0.239524,0.240096,0.240681,0.241291,0.24196,0.241727,0.242166,0.242563,0.241715,1.067e-05,1.90958e-05,9.38609e-06,0.000122385,5.83549e-05,5.41935e-05,1.57427e-05,8.47163e-07,0,0,0.0808294,0.0906803,0.0972833,0.103021,0.10747,0.112065,0.114906,0.118007,0.120075,0.122893,0.125148,0.146155,0.147334,0.147746,0.148667,0.149479,0.150515,0.151222,0.151664,0.152069,0.152376,0.0779417,0.139115,0.15466,0.188371,0.204272,0.209742,0.213009,0.215113,0.215831,0.217851,0.218911,0.219416,0.220558,0.221493,0.22215,0.223749,0.224583,0.224726,0.225827,0.226629,0.227791,0.22909,0.229057,0.230019,0.229957,0.23078,0.231576,0.231976,0.232323,0.233373,0.234171,0.234837,0.235678,0.236289,0.237159,0.237964,0.238626,0.23919,0.239757,0.240008,0.240802,0.241202,0.24198,0.241909,0.242014,0.242539,0.242705,0.243398,0.0800722,0.0899403,0.0980566,0.102959,0.107289,0.111414,0.11452,0.117467,0.120241,0.123299,0.125445,0.146812,0.147447,0.148345,0.149165,0.149851,0.150742,0.151201,0.151957,0.152517,0.152917,0.153168,0.153503,0.0280276,0.0553081,0.0713538,0.0767845,0.0810143,0,0,1.87853e-06,1.39603e-05,9.16942e-05,5.21868e-05,2.47817e-05,1.13676e-05,3.28572e-05,3.04458e-05,0,4.23791e-06,2.82337e-05,5.38622e-05,9.12197e-07,0.0778686,0.139158,0.154849,0.188256,0.204229,0.209808,0.212788,0.215008,0.215837,0.217744,0.218587,0.219133,0.220566,0.221312,0.221939,0.223602,0.224726,0.224791,0.225765,0.226766,0.227824,0.228894,0.229145,0.230033,0.230187,0.230823,0.231772,0.231919,0.232369,0.232691,0.233376,0.233914,0.235012,0.235476,0.235999,0.237244,0.237866,0.238629,0.23906,0.239648,0.239918,0.240612,0.241202,0.241933,0.242109,0.24241,9.79347e-06,0.0778298,0.13919,0.154902,0.188357,0.204178,0.209929,0.212937,0.214924,0.215835,0.21764,0.218804,0.219468,0.220725,0.22161,0.221948,0.223693,0.224813,0.225038,0.225893,0.226501,0.227847,0.228902,0.229109,0.230074,0.230132,0.230717,0.231497,0.232169,0.232447,0.232934,0.233366,0.234126,0.23496,0.235594,0.236255,0.237396,0.237955,0.238776,0.239168,0.239719,0.240162,0.240792,0.241246,0.241972,0.241725,0.242037,0.242233,0.242469,0,1.10298e-06,0.000103782,6.62293e-05,5.89055e-05,4.73168e-05,0.00013364,1.08375e-05,1.88501e-06,1.19767e-05,8.69753e-05,3.86658e-05,5.5823e-05,3.87181e-05,0,7.82473e-07,0,4.69934e-05,0.00019888,0.000139786,4.53744e-05,5.36382e-05", "env/return_item_def_lvl": "0.000610631,0.128106,0.14898,0.16058,0.168459,0.174519,0.179369,0.184807,0.188182,0.192036,0.19599,0.198945,8.69866e-05,0.000116549,0.000579899,1.2384e-06,7.20031e-07,6.44443e-05,6.1285e-07,0.000190446,0.133663,0.151816,0.162894,0.171453,0.178154,0.182942,0.18814,0.190949,0.194963,0.198647,0.201051,0.20419,0.230191,0.23071,0.232633,0.233356,0.233878,0.234939,0.236063,0.236973,0.236477,0.237525,0.238151,0.237772,0.238494,0.237742,0.000311697,0.000893954,0.131336,0.22226,0.255576,0.336782,0.394822,0.407842,0.411999,0.417205,0.416294,0.421025,0.421262,0.420386,0.423329,0.424168,0.423803,0.430655,0.431402,0.429544,0.43169,0.433948,0.437107,0.438274,0.437188,0.439838,0.438012,0.438646,0.440965,0.442056,0.442326,0.442021,0.44322,0.446079,0.447352,0.449274,0.449538,0.452687,0.452711,0.455058,0.453249,0.456182,0.457256,0.457481,0.458659,0.461098,0.45969,0.460052,0.460425,0.465605,0,0.158021,0.238362,0.374304,0.40241,0.448514,0.449376,0.450491,0.450221,0.451399,0.451834,0.451406,0.453322,3.99773e-05,0.000117463,0,5.74558e-07,0.160477,0.162811,0.163325,0.164608,0.16613,0.167891,0.168807,0.171524,0.171279,0.17313,0.174708,0.174997,0.177,0.177506,0.178831,0.180228,0.181494,0.182828,0.183845,0.18426,0.183855,0.184764,0,0,0,0.131452,0.221953,0.255241,0.336907,0.39495,0.407898,0.412002,0.417393,0.416415,0.421114,0.420991,0.420338,0.423244,0.423856,0.423681,0.430699,0.431727,0.429566,0.431534,0.43355,0.43735,0.438223,0.437611,0.440268,0.438218,0.439237,0.440976,0.442432,0.442127,0.441439,0.443288,0.445656,0.447677,0.449169,0.449872,0.452507,0.452162,0.454548,0.453097,0.455593,0.457128,0.457657,0.459053,0.460791,0.459823,0.460047,0.460085,0.460789,0.461709,0.000157097,0.000938048,0.00129468,0.00164505,0.00180302,0.131409,0.222238,0.255525,0.336955,0.394622,0.408205,0.412008,0.417203,0.416556,0.421292,0.42163,0.420289,0.422987,0.424001,0.423594,0.430753,0.43169,0.429615,0.431744,0.433364,0.437173,0.438204,0.437609,0.440035,0.437991,0.439216,0.440591,0.44222,0.442017,0.441887,0.443596,0.445884,0.448027,0.448869,0.449751,0.452499,0.4525,0.454556,0.453065,0.45578,0.457349,0.457633,0.458936,0.460975,0.459585,0.460015,0.461059,0.461877,2.24614e-05,0.00108989,0.00076966,0.00095977,0.000927905,0.000898063,1.82326e-05,1.65617e-06,0,0,0.142364,0.155774,0.1656,0.172709,0.178834,0.184475,0.188873,0.192662,0.194831,0.198007,0.200383,0.227914,0.229146,0.229153,0.230774,0.231542,0.232793,0.233511,0.23439,0.234807,0.235972,0.13132,0.222116,0.255277,0.336709,0.395235,0.407846,0.412363,0.417177,0.416772,0.421389,0.421756,0.420022,0.423351,0.424018,0.42382,0.430678,0.431625,0.42892,0.431471,0.433481,0.437012,0.438692,0.437485,0.439732,0.438233,0.438569,0.440725,0.442051,0.442023,0.44342,0.445907,0.447563,0.449512,0.449821,0.452374,0.452442,0.454609,0.453225,0.45582,0.457581,0.457664,0.458801,0.460678,0.459761,0.460044,0.460723,0.460955,0.464502,0.140336,0.15465,0.165851,0.171712,0.17863,0.183903,0.188473,0.192824,0.196426,0.199646,0.202535,0.229472,0.230399,0.231883,0.23303,0.232715,0.233979,0.234845,0.235706,0.235743,0.236921,0.237274,0.236636,0.0677145,0.107581,0.125001,0.136291,0.143792,4.49534e-07,0.00102563,4.31412e-06,2.72365e-05,0.000679819,0.00160822,0.00176591,0.00215984,0.000102047,0.00118116,5.43624e-07,8.82444e-06,6.52631e-05,0.000500327,2.75122e-06,0.131373,0.222056,0.255292,0.336813,0.394722,0.407605,0.412128,0.417257,0.416418,0.42148,0.421486,0.420175,0.423461,0.423732,0.423531,0.430653,0.431567,0.429324,0.43152,0.433739,0.436911,0.43854,0.437381,0.440134,0.438119,0.438982,0.441461,0.442257,0.442014,0.44194,0.444285,0.444992,0.447879,0.449306,0.449411,0.452553,0.452407,0.454618,0.453103,0.455859,0.457041,0.458151,0.458877,0.460692,0.460255,0.460582,1.96848e-05,0.131306,0.222322,0.255311,0.336849,0.394452,0.40828,0.412123,0.416923,0.416921,0.420942,0.421603,0.420204,0.423341,0.424344,0.423766,0.430661,0.431871,0.429608,0.431862,0.433817,0.437195,0.438741,0.437435,0.44013,0.438279,0.438643,0.441016,0.442658,0.442077,0.441816,0.443555,0.445575,0.447536,0.449121,0.450098,0.452528,0.452465,0.454874,0.452989,0.455949,0.457385,0.458099,0.459159,0.460702,0.459712,0.460012,0.460111,0.461042,0,1.69654e-06,0.00054378,0.00116763,0.00165672,0.0018217,0.000459091,0.000648661,0.00121112,0.00129348,0.000784231,0.00234065,0.00245621,5.8823e-05,0,7.62428e-07,8.39772e-07,0.00113959,0.000334053,0.00075186,0.000770602,0.000759874", "env/return_market_buy": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "env/return_market_sell": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "env/return_death": "-0.00227339,-0.861788,-0.846108,-0.83615,-0.82443,-0.81326,-0.80238,-0.788108,-0.780789,-0.7707,-0.758486,-0.754846,-0.631586,-0.13052,-0.130997,-0.999276,-0.21958,-0.188112,-0.128865,-0.17539,-0.857125,-0.84376,-0.834713,-0.818541,-0.805949,-0.796807,-0.784594,-0.777276,-0.766974,-0.758426,-0.756464,-0.745495,-0.626606,-0.616624,-0.610328,-0.602691,-0.598181,-0.590723,-0.583171,-0.581733,-0.577671,-0.572404,-0.56919,-0.570921,-0.569769,-0.567217,-0.20071,-0.200244,-0.76572,-0.638483,-0.599034,-0.604001,-0.576772,-0.555018,-0.542677,-0.533741,-0.530856,-0.522475,-0.518233,-0.51346,-0.506551,-0.505105,-0.499488,-0.494995,-0.491357,-0.48816,-0.481984,-0.479825,-0.474428,-0.471107,-0.468285,-0.464214,-0.461575,-0.458718,-0.455044,-0.452866,-0.450079,-0.451162,-0.448626,-0.443147,-0.438437,-0.434712,-0.429402,-0.420109,-0.411524,-0.405193,-0.399005,-0.397258,-0.388749,-0.382795,-0.376658,-0.372032,-0.370022,-0.366194,-0.365793,-0.361172,-0.89625,-0.72629,-0.606226,-0.591998,-0.564767,-0.372993,-0.370908,-0.367867,-0.364949,-0.363585,-0.362471,-0.362023,-0.356106,-0.801756,-0.80071,-0.849384,-0.523319,-0.758725,-0.743697,-0.741758,-0.737918,-0.729128,-0.716311,-0.716284,-0.708756,-0.70952,-0.697712,-0.69174,-0.691452,-0.687861,-0.671492,-0.662137,-0.647091,-0.641515,-0.629613,-0.62166,-0.616647,-0.617044,-0.612028,-0.415692,-0.132313,-0.396022,-0.766314,-0.638991,-0.599288,-0.604324,-0.576732,-0.554402,-0.542857,-0.534272,-0.530625,-0.523006,-0.518414,-0.513565,-0.506114,-0.504953,-0.499811,-0.494744,-0.490886,-0.489073,-0.481983,-0.479429,-0.475384,-0.47152,-0.467299,-0.463368,-0.461468,-0.457898,-0.455189,-0.452535,-0.451523,-0.45133,-0.4484,-0.443316,-0.4381,-0.434688,-0.428753,-0.420915,-0.412573,-0.404322,-0.399334,-0.398311,-0.388524,-0.381755,-0.376663,-0.372695,-0.369736,-0.366501,-0.366075,-0.365011,-0.362576,-0.334478,-0.330008,-0.322956,-0.31197,-0.308337,-0.765757,-0.63808,-0.600018,-0.604562,-0.577024,-0.55451,-0.542524,-0.534193,-0.530151,-0.523007,-0.517575,-0.513372,-0.507195,-0.504613,-0.499309,-0.495327,-0.49102,-0.488081,-0.482073,-0.480005,-0.474747,-0.470821,-0.467716,-0.463854,-0.461166,-0.458297,-0.455344,-0.452737,-0.451457,-0.451441,-0.448067,-0.443552,-0.438814,-0.435153,-0.429454,-0.420721,-0.412107,-0.404616,-0.399581,-0.397423,-0.389522,-0.382438,-0.376384,-0.372705,-0.370603,-0.366902,-0.36505,-0.359737,-0.400925,-0.109956,-0.107959,-0.628737,-0.612306,-0.606205,-0.988485,-0.339919,-0.17751,-0.177482,-0.846157,-0.83365,-0.822659,-0.808339,-0.797641,-0.784685,-0.776563,-0.76872,-0.763801,-0.755088,-0.747661,-0.62638,-0.618483,-0.613494,-0.60339,-0.597403,-0.590733,-0.584749,-0.582683,-0.578204,-0.571391,-0.766037,-0.638739,-0.599366,-0.604347,-0.57723,-0.554369,-0.542286,-0.534301,-0.529868,-0.52243,-0.517317,-0.513367,-0.50669,-0.504809,-0.498419,-0.494632,-0.491518,-0.488798,-0.482533,-0.480299,-0.475176,-0.470684,-0.46809,-0.463943,-0.461087,-0.458427,-0.455248,-0.453069,-0.450895,-0.447584,-0.442761,-0.438958,-0.434746,-0.429023,-0.420289,-0.411823,-0.405024,-0.398923,-0.397627,-0.388562,-0.38193,-0.37646,-0.372282,-0.370436,-0.367108,-0.366085,-0.364289,-0.370131,-0.841845,-0.835515,-0.818999,-0.811955,-0.799926,-0.787969,-0.77711,-0.770331,-0.763734,-0.75521,-0.748834,-0.630848,-0.622173,-0.609225,-0.602168,-0.597476,-0.591972,-0.585967,-0.579181,-0.576521,-0.572352,-0.569498,-0.56973,-0.919785,-0.932071,-0.930524,-0.932704,-0.929359,-0.427748,-0.404337,-0.324068,-0.3595,-0.35902,-0.358909,-0.356477,-0.356202,-0.453614,-0.44066,-0.271827,-0.851661,-0.494001,-0.493969,-0.436863,-0.766157,-0.638912,-0.599262,-0.603616,-0.576979,-0.554292,-0.542816,-0.533926,-0.531015,-0.52231,-0.51808,-0.513585,-0.506469,-0.505715,-0.499725,-0.495194,-0.490929,-0.489081,-0.482346,-0.479667,-0.474706,-0.470561,-0.467727,-0.464488,-0.461264,-0.458471,-0.455458,-0.453067,-0.451405,-0.451732,-0.448011,-0.443649,-0.438051,-0.435344,-0.429405,-0.420441,-0.411866,-0.405626,-0.399774,-0.397542,-0.388157,-0.382724,-0.376754,-0.373131,-0.367098,-0.365907,-0.112177,-0.766072,-0.63788,-0.599435,-0.604426,-0.576828,-0.553863,-0.543151,-0.53463,-0.530154,-0.523082,-0.517434,-0.513617,-0.50613,-0.504706,-0.49965,-0.495077,-0.490497,-0.487853,-0.482415,-0.480378,-0.474789,-0.471069,-0.467547,-0.463727,-0.461163,-0.45812,-0.455252,-0.452853,-0.450466,-0.450978,-0.44834,-0.443756,-0.438108,-0.434965,-0.429316,-0.421414,-0.4118,-0.406003,-0.398928,-0.397262,-0.388831,-0.382515,-0.377169,-0.372582,-0.36996,-0.366684,-0.366035,-0.364953,-0.936875,-0.255483,-0.25288,-0.250477,-0.246618,-0.245871,-0.2033,-0.237153,-0.232723,-0.230525,-0.383666,-0.375787,-0.374925,-0.645514,-0.343654,-0.993999,-0.986178,-0.385435,-0.929435,-0.917402,-0.900117,-0.89593", "env/min_comb_prof": "1.02909,2.61973,3.11923,3.42001,3.64217,3.81004,3.95104,4.08703,4.17106,4.25204,4.35455,4.40723,1.00475,1.00773,1.02517,1.00002,1.00017,1.00337,1.00003,1.0134,2.75178,3.22905,3.49978,3.71341,3.87733,3.99066,4.12329,4.20338,4.29326,4.36769,4.40741,4.49759,5.27525,5.3266,5.37538,5.41038,5.43236,5.47392,5.5103,5.53241,5.54409,5.57619,5.5886,5.59015,5.60492,5.62335,1.01101,1.02736,3.16719,5.10723,5.72377,6.73348,7.19951,7.44752,7.59948,7.70917,7.77265,7.86417,7.92326,7.9695,8.03616,8.07584,8.12329,8.19155,8.23227,8.26626,8.31999,8.34414,8.40492,8.45867,8.48006,8.53289,8.55304,8.58258,8.62797,8.65471,8.68589,8.69037,8.71357,8.76455,8.79682,8.83859,8.87176,8.93923,8.98997,9.03673,9.07355,9.08987,9.11086,9.15559,9.18846,9.23783,9.24144,9.26622,9.27352,9.31466,1.00002,3.74494,5.47333,6.92447,7.39266,9.32268,9.3411,9.35984,9.37819,9.39508,9.40725,9.40842,9.47743,1.00439,1.01714,1.00005,1.00002,4.29353,4.37122,4.39872,4.43818,4.48444,4.54549,4.58528,4.68789,4.69542,4.76754,4.83156,4.83996,4.87625,4.92671,4.972,5.05565,5.10051,5.15808,5.21266,5.22311,5.23042,5.25468,1,1.00002,1.00003,3.16723,5.1029,5.72057,6.73547,7.20627,7.45486,7.60107,7.70735,7.77325,7.86416,7.92274,7.96681,8.03991,8.07485,8.1178,8.18783,8.23095,8.26143,8.32062,8.34326,8.40475,8.45631,8.49043,8.53761,8.55684,8.59303,8.62783,8.65428,8.67485,8.68975,8.71167,8.76052,8.80501,8.83727,8.87405,8.93868,8.98126,9.0348,9.07066,9.08603,9.1185,9.15918,9.19582,9.22974,9.24633,9.26289,9.26668,9.27709,9.29947,1.0074,1.03626,1.04646,1.0539,1.05793,3.16925,5.10696,5.71786,6.72612,7.2011,7.45376,7.59993,7.70805,7.77646,7.86383,7.93178,7.96996,8.03263,8.07777,8.12459,8.1862,8.23266,8.26624,8.31699,8.34312,8.40609,8.45715,8.48595,8.53505,8.55588,8.58969,8.62307,8.65262,8.67502,8.689,8.724,8.76389,8.80251,8.83471,8.87583,8.93695,8.98656,9.03765,9.07129,9.08781,9.11048,9.15506,9.19467,9.23369,9.23856,9.25909,9.27862,9.31655,1.00159,1.05865,1.06034,1.04479,1.05082,1.05197,1.00279,1.00005,1,1.00004,3.00042,3.3468,3.5883,3.80434,3.94156,4.09095,4.17186,4.26316,4.31532,4.39702,4.4562,5.25493,5.31036,5.34568,5.38187,5.41984,5.46077,5.49481,5.51646,5.53687,5.56294,3.17032,5.10445,5.71829,6.73193,7.20345,7.45217,7.60519,7.7089,7.77621,7.86757,7.93155,7.96592,8.03645,8.07756,8.12844,8.18635,8.23249,8.25566,8.31639,8.34009,8.40227,8.46322,8.48417,8.53247,8.55337,8.58498,8.62429,8.65061,8.67957,8.72294,8.76675,8.79588,8.84014,8.87748,8.93829,8.98298,9.03242,9.07169,9.09341,9.11184,9.15928,9.19239,9.23004,9.2422,9.25891,9.27409,9.28706,9.30168,2.95437,3.30259,3.59777,3.76936,3.92429,4.06872,4.17495,4.25908,4.33588,4.41173,4.46176,5.2727,5.31242,5.36731,5.40606,5.43425,5.46849,5.50504,5.53671,5.55252,5.56889,5.58824,5.59856,1.6505,2.20124,2.53525,2.73334,2.87299,1.00009,1.05937,1.00022,1.00189,1.02067,1.03642,1.04345,1.04705,1.0049,1.04795,1,1.00087,1.00372,1.01646,1.00016,3.16774,5.10471,5.72099,6.73228,7.2034,7.45581,7.59926,7.7093,7.76975,7.86968,7.92657,7.96434,8.03718,8.07056,8.11617,8.18061,8.23517,8.25671,8.31625,8.34506,8.40728,8.46297,8.48834,8.53122,8.55659,8.58996,8.6292,8.64655,8.67877,8.68766,8.72246,8.75163,8.80348,8.83526,8.8699,8.93801,8.98448,9.03109,9.06679,9.08846,9.11041,9.15414,9.1907,9.22706,9.25715,9.27697,1.00111,3.16646,5.10918,5.72325,6.73172,7.19957,7.46102,7.60045,7.70558,7.77535,7.86204,7.9301,7.97213,8.03907,8.08103,8.11784,8.18237,8.24011,8.26751,8.31705,8.3393,8.4061,8.45737,8.48625,8.53422,8.55574,8.58772,8.62274,8.65604,8.67802,8.69338,8.71624,8.75805,8.80307,8.8365,8.87555,8.93548,8.98617,9.03427,9.07376,9.09165,9.116,9.15606,9.19008,9.23361,9.23868,9.26049,9.26797,9.2816,1,1.00016,1.02067,1.0344,1.04262,1.04718,1.02396,1.03724,1.04502,1.05208,1.02541,1.04924,1.05282,1.0058,1.00002,1.00002,1.00005,1.0543,1.02005,1.03913,1.04671,1.04813", "env/purchases": "0,0.00978435,0.0136445,0.0164581,0.0188378,0.021475,0.0247143,0.0253733,0.0317512,0.0339153,0.0397539,0.041616,8.08398e-06,2.10881e-05,0,0,0,3.79701e-05,0,3.57233e-05,0.0136706,0.0187149,0.0200687,0.0276204,0.0277254,0.0343136,0.0338138,0.0366056,0.0465428,0.0597367,0.0560332,0.0637281,0.160952,0.159349,0.163773,0.161361,0.168758,0.165623,0.160701,0.165902,0.164486,0.165102,0.166279,0.170182,0.168751,0.179928,6.61968e-05,7.16507e-06,0.0257717,0.0958608,0.243486,0.502692,0.612837,0.62073,0.597758,0.600781,0.576917,0.582968,0.571599,0.550751,0.557746,0.549356,0.540633,0.578263,0.571393,0.54852,0.551503,0.562826,0.576939,0.575572,0.563506,0.573954,0.553885,0.553269,0.559909,0.562127,0.557064,0.554653,0.556638,0.56887,0.570364,0.577585,0.576751,0.58566,0.579063,0.586641,0.571671,0.589314,0.592509,0.58956,0.589547,0.599734,0.589897,0.589978,0.589277,0.598159,0,0.0475031,0.142932,0.679985,0.607016,0.5492,0.550427,0.553394,0.551227,0.554622,0.558368,0.554958,0.556981,2.11035e-06,1.43726e-05,0,0,0.0021521,0.00176487,0.00153349,0.0029465,0.00246686,0.00311315,0.00420538,0.00523677,0.00192328,0.00240626,0.00255708,0.00234954,0.00267247,0.0029306,0.00359378,0.00312389,0.00382577,0.00379727,0.00416777,0.00443275,0.00420007,0.00470862,0,0,0,0.0256805,0.0951995,0.244237,0.503525,0.612405,0.620866,0.597339,0.602688,0.577317,0.586225,0.571162,0.549885,0.556978,0.550709,0.539662,0.577974,0.573637,0.548453,0.553007,0.561841,0.576427,0.57574,0.563892,0.574057,0.557552,0.553121,0.559796,0.564911,0.558085,0.55216,0.557868,0.565419,0.572787,0.577956,0.577117,0.583111,0.577803,0.585583,0.571175,0.58702,0.590056,0.588115,0.591524,0.596981,0.590145,0.58813,0.589132,0.591972,0.597548,6.34158e-05,4.80501e-06,5.19972e-06,6.22912e-06,0,0.0257433,0.0954332,0.243947,0.502683,0.612038,0.621219,0.597744,0.600682,0.578835,0.585406,0.571151,0.552568,0.556085,0.550405,0.540999,0.577599,0.572728,0.548701,0.551441,0.562695,0.575419,0.57463,0.56448,0.573381,0.55336,0.552959,0.558204,0.565703,0.557766,0.552832,0.561374,0.56848,0.573348,0.576359,0.577585,0.584158,0.577599,0.585721,0.572877,0.587111,0.592082,0.587832,0.590391,0.599371,0.590331,0.588476,0.594577,0.587521,4.20177e-05,0,0,8.71594e-06,2.33141e-06,0,8.53886e-06,0,0,0,0.01142,0.0165128,0.0182868,0.0210873,0.0255465,0.0320421,0.0381716,0.0368904,0.0435585,0.0461088,0.0507708,0.144644,0.148052,0.140331,0.145858,0.154101,0.160469,0.15823,0.163605,0.170215,0.174921,0.0256054,0.0955145,0.244093,0.501356,0.613644,0.623267,0.598421,0.600722,0.57715,0.584869,0.571922,0.550103,0.557101,0.547889,0.541094,0.576194,0.572458,0.546431,0.550183,0.562627,0.575124,0.575734,0.563224,0.572247,0.553688,0.55137,0.558954,0.563266,0.556694,0.559653,0.565735,0.572123,0.577496,0.575505,0.58402,0.578014,0.585921,0.570881,0.58865,0.593705,0.586782,0.589918,0.598094,0.590007,0.589462,0.591021,0.594219,0.607751,0.0151529,0.0179528,0.0227881,0.0252511,0.0282631,0.0317657,0.042397,0.0486445,0.0489399,0.0498377,0.0575991,0.140623,0.143648,0.149108,0.151382,0.158621,0.152827,0.154956,0.155547,0.158766,0.165239,0.166908,0.167717,0.000806011,0.00190175,0.00287506,0.00245026,0.0020773,0,0,0,0.000100491,1.88932e-05,1.93278e-05,7.04051e-06,6.18276e-05,0,6.02567e-06,0,0,2.33566e-06,8.7142e-05,0,0.0256247,0.0954138,0.243091,0.501738,0.611472,0.619574,0.598908,0.603142,0.576338,0.586127,0.571516,0.550106,0.556318,0.550183,0.540177,0.576882,0.572291,0.54757,0.552009,0.562522,0.574864,0.57565,0.563314,0.574902,0.556401,0.553997,0.562274,0.561031,0.556822,0.553429,0.562081,0.562414,0.573071,0.578489,0.575163,0.585846,0.577211,0.587333,0.568194,0.586633,0.590632,0.590743,0.592268,0.599219,0.589673,0.589322,3.00765e-06,0.0258486,0.0957599,0.243779,0.501476,0.61265,0.623151,0.597535,0.601066,0.577161,0.584326,0.571836,0.551114,0.557401,0.550953,0.541508,0.574983,0.573548,0.549367,0.554847,0.564208,0.576921,0.574831,0.561583,0.573139,0.555994,0.552117,0.558817,0.564512,0.557325,0.553116,0.559402,0.565301,0.569615,0.577577,0.575818,0.585646,0.578767,0.586763,0.569388,0.588268,0.592505,0.589011,0.59092,0.599394,0.588423,0.588352,0.587972,0.592872,0,0,1.55927e-05,8.68459e-06,0,0,2.12009e-05,5.88588e-06,0,0,2.47611e-06,0,0,7.52177e-06,0,0,3.76053e-06,0,5.08869e-06,1.71779e-05,3.36302e-06,0", "env/sales": "4.18214e-06,0.00979371,0.0136478,0.0164678,0.0188747,0.0214607,0.0247166,0.0253493,0.0318544,0.0338888,0.0396949,0.0418744,0.00013015,0.000334468,4.62905e-05,0,0,0.000397748,0,0.000283951,0.0136826,0.0188033,0.0200651,0.0275665,0.0277502,0.0343414,0.0338192,0.0365803,0.0467022,0.0594842,0.0563128,0.063669,0.160943,0.159472,0.163667,0.161345,0.168639,0.165737,0.160716,0.165757,0.16449,0.165194,0.166186,0.170209,0.168768,0.175339,0.000484625,7.76658e-05,0.0262108,0.0957461,0.243789,0.503036,0.612922,0.620657,0.597864,0.600813,0.57691,0.582986,0.571546,0.550669,0.557686,0.549469,0.540645,0.578284,0.571378,0.548508,0.551549,0.562843,0.57701,0.575586,0.56344,0.573909,0.553936,0.553226,0.55988,0.562099,0.557083,0.554699,0.556601,0.568816,0.570346,0.577574,0.576798,0.585621,0.579157,0.586716,0.571716,0.589318,0.592485,0.589536,0.589582,0.59976,0.590036,0.589903,0.589335,0.591035,0,0.0476887,0.143007,0.680364,0.607073,0.549196,0.550412,0.55344,0.551209,0.554625,0.558343,0.554965,0.559765,3.07698e-05,5.17059e-05,2.34751e-06,6.40467e-06,0.00224597,0.0017032,0.00151622,0.0029963,0.00235818,0.00313607,0.00422798,0.00524919,0.00192599,0.0024155,0.00255316,0.00219454,0.00261124,0.00278591,0.00336657,0.00302637,0.00391402,0.00367829,0.00405682,0.00439586,0.00424439,0.0047615,0,0,0,0.026104,0.0950731,0.244531,0.503809,0.612542,0.620871,0.597334,0.602702,0.577268,0.586208,0.571134,0.549828,0.556991,0.550656,0.539713,0.578,0.573535,0.548442,0.553047,0.561829,0.576457,0.575729,0.564034,0.574069,0.557523,0.553151,0.559705,0.564971,0.558125,0.552167,0.557863,0.565454,0.572835,0.577911,0.577204,0.583119,0.577782,0.585509,0.571187,0.586937,0.590106,0.588115,0.591552,0.596902,0.59029,0.58809,0.589115,0.591932,0.597448,0.000301318,6.99698e-06,1.3865e-05,1.59456e-05,0,0.0261583,0.095314,0.244223,0.502997,0.612121,0.621253,0.597842,0.600664,0.578909,0.585386,0.571166,0.55255,0.556154,0.550433,0.54087,0.577689,0.572755,0.54873,0.551515,0.562704,0.575412,0.574559,0.564493,0.573404,0.553417,0.552959,0.558224,0.565617,0.557765,0.552961,0.561252,0.568476,0.573371,0.576343,0.577592,0.584177,0.577558,0.585773,0.572817,0.587196,0.592022,0.587908,0.590433,0.599431,0.590391,0.588477,0.594622,0.588218,0.000291736,0,0,5.51844e-05,1.94946e-05,0,0.000292451,2.11659e-06,0,0,0.0114046,0.0165237,0.0182983,0.021052,0.0255238,0.0321102,0.0381523,0.0369576,0.0435425,0.0462516,0.0509274,0.144728,0.147911,0.14038,0.145869,0.153989,0.160475,0.158324,0.163559,0.170174,0.174904,0.0260354,0.0953961,0.244371,0.501732,0.613776,0.623254,0.598426,0.600649,0.577242,0.584874,0.571958,0.550139,0.557134,0.547937,0.541025,0.576206,0.572407,0.54639,0.550222,0.562638,0.575135,0.575708,0.563233,0.57227,0.553807,0.551477,0.558891,0.563257,0.556693,0.55974,0.5657,0.572176,0.577451,0.575455,0.584078,0.577982,0.5859,0.570926,0.588658,0.593726,0.586838,0.589958,0.598086,0.590061,0.58948,0.590969,0.594203,0.598685,0.015023,0.0181112,0.0228016,0.0251957,0.0283492,0.0317102,0.0424833,0.0486094,0.0490858,0.0499586,0.0575986,0.140599,0.143681,0.149063,0.151486,0.158562,0.152908,0.154896,0.15564,0.158784,0.165256,0.166922,0.167644,0.00189888,0.00201514,0.00294587,0.00247455,0.00208348,5.8283e-06,0,2.59529e-05,0.000536412,5.70906e-05,2.59507e-05,6.78942e-06,0,3.5187e-05,1.20725e-05,0,6.13192e-05,7.88694e-05,0.00032958,3.6361e-05,0.0260392,0.0953106,0.243406,0.502072,0.611542,0.619613,0.598915,0.603022,0.576364,0.586212,0.571497,0.550142,0.556339,0.550211,0.540076,0.576823,0.572253,0.547613,0.552022,0.562561,0.574787,0.575653,0.563393,0.574897,0.556412,0.553947,0.562287,0.561091,0.556765,0.553511,0.562114,0.562394,0.573062,0.578503,0.575253,0.585821,0.577129,0.587375,0.568228,0.586643,0.590625,0.590784,0.592275,0.599297,0.589677,0.589413,9.29806e-05,0.0262755,0.0956644,0.244057,0.501744,0.612792,0.623024,0.597642,0.600979,0.57716,0.584337,0.571875,0.551078,0.557417,0.551021,0.541373,0.575078,0.573501,0.54934,0.554914,0.564112,0.576942,0.574802,0.561643,0.573124,0.55605,0.552052,0.558808,0.564576,0.557249,0.553219,0.559307,0.565308,0.569668,0.577566,0.575746,0.585681,0.5788,0.586746,0.569343,0.588307,0.592461,0.58912,0.59089,0.599431,0.588493,0.588311,0.58792,0.592906,0,0,0.000207132,7.2128e-05,2.31348e-05,7.39536e-05,0.00038373,2.07352e-05,0,0,5.21602e-05,6.40197e-06,0,0.00017678,0,0,3.81436e-05,0,0.000520836,0.000400369,6.99502e-05,0", "env/equip_attack": "0.00245115,7.09346,8.62942,9.46276,10.1668,10.6835,11.0873,11.4787,11.8017,12.0939,12.3785,12.673,0.00795205,0.00308949,0.0027423,0,8.23384e-05,0.0026544,0,0.00477588,7.48035,8.88932,9.63983,10.3161,10.8459,11.237,11.6263,11.9471,12.2686,12.5975,12.8,13.1712,15.4102,15.493,15.5967,15.7372,15.7593,15.8755,15.9449,16.0153,16.0218,16.0932,16.1036,16.1381,16.1685,16.1291,0.0250897,0.0832581,8.02399,14.4925,16.0611,19.4939,21.2578,21.8676,22.2404,22.4901,22.5993,22.808,22.9192,22.9967,23.1159,23.2316,23.2988,23.499,23.5511,23.6147,23.7679,23.8129,23.9598,24.0668,24.0623,24.2064,24.2463,24.3047,24.3959,24.4609,24.4995,24.5131,24.5655,24.6726,24.7501,24.8401,24.8795,25.0292,25.1047,25.1855,25.2367,25.2704,25.3367,25.4042,25.4409,25.5339,25.5109,25.5762,25.573,25.6132,0,9.99402,15.738,20.419,21.8598,25.8337,25.8565,25.8855,25.921,25.9649,26.0009,25.9861,26.2434,0.00239088,0.002614,0,0,11.9135,11.9805,12.0985,12.2717,12.3401,12.5561,12.6735,12.8347,12.8699,12.9479,13.1256,13.1678,13.3632,13.4625,13.5594,13.6676,13.7829,13.8754,13.9877,14.042,14.0231,14.0611,0,0.000344887,0,8.01782,14.4749,16.0545,19.4958,21.2616,21.894,22.2326,22.4901,22.5954,22.8153,22.9164,22.9869,23.1275,23.2194,23.2785,23.4736,23.5712,23.5985,23.7781,23.8105,23.9279,24.0474,24.0928,24.2128,24.2351,24.3034,24.4163,24.458,24.4852,24.5342,24.5837,24.6694,24.7696,24.8211,24.8879,25.0041,25.0688,25.1715,25.2278,25.264,25.3367,25.4058,25.4874,25.5223,25.5215,25.5703,25.5783,25.5886,25.7423,0.00411495,0.00151384,0.00266356,0.00224308,0.00110865,8.02689,14.4897,16.0471,19.4754,21.2496,21.8894,22.2333,22.5032,22.6065,22.8199,22.928,23.0032,23.1147,23.2406,23.2999,23.4843,23.5668,23.6146,23.7413,23.8202,23.9376,24.041,24.1006,24.2012,24.2339,24.3183,24.3833,24.4456,24.4749,24.5088,24.622,24.6679,24.7754,24.811,24.8781,25.0076,25.0859,25.1847,25.2291,25.2659,25.3277,25.399,25.4671,25.5377,25.5142,25.5668,25.6079,25.438,0.00123709,0.00283142,0.00117173,0.0173264,0.00808968,0.0075434,0.00468527,6.77731e-05,0,0,8.21119,9.28813,10.0345,10.6346,11.1203,11.6221,11.8848,12.2521,12.4853,12.7833,13.0355,15.3632,15.4747,15.5207,15.6429,15.7246,15.8277,15.9203,15.9559,16.0162,16.0486,8.02807,14.4844,16.0443,19.492,21.2695,21.8822,22.2533,22.5037,22.6033,22.8214,22.9347,23.0059,23.1123,23.2261,23.3118,23.4688,23.567,23.5913,23.7382,23.8171,23.9384,24.0675,24.0771,24.2037,24.2088,24.3057,24.3835,24.4281,24.4746,24.5831,24.6751,24.7564,24.8347,24.9036,25.0057,25.0997,25.1765,25.2286,25.2929,25.3248,25.4117,25.4656,25.5307,25.5288,25.5456,25.6007,25.6276,25.6872,8.11979,9.16603,10.0592,10.5977,11.0336,11.484,11.8388,12.1616,12.4583,12.7604,12.9858,15.4167,15.4853,15.5733,15.6822,15.7471,15.8468,15.8823,15.9648,16.0235,16.0684,16.1001,16.1334,2.84985,5.6264,7.28853,7.89186,8.36148,0,0,0.000241337,0.00156015,0.00983306,0.00537928,0.00269914,0.00148386,0.00348065,0.00324023,0,0.00070834,0.00328183,0.00652235,0.000128959,8.01627,14.4904,16.0704,19.4801,21.2685,21.8896,22.2206,22.4914,22.6007,22.8099,22.8951,22.9779,23.1117,23.2108,23.2879,23.4509,23.5806,23.5916,23.7324,23.8288,23.9429,24.0571,24.0888,24.2008,24.2263,24.3074,24.405,24.4186,24.4841,24.51,24.5846,24.6459,24.7719,24.8103,24.8723,25.01,25.0741,25.1739,25.2193,25.2799,25.316,25.3979,25.4551,25.5331,25.5546,25.5857,0.00106814,8.01614,14.4952,16.0704,19.4882,21.2582,21.9057,22.247,22.4841,22.6004,22.8028,22.9197,23.0146,23.1278,23.2381,23.2868,23.4629,23.586,23.6226,23.7473,23.8004,23.941,24.0526,24.0877,24.198,24.2257,24.304,24.3752,24.4486,24.4911,24.5384,24.5907,24.6679,24.7681,24.8213,24.8965,25.029,25.0969,25.1822,25.2295,25.2924,25.3402,25.4109,25.4671,25.5394,25.5129,25.5523,25.5676,25.6017,0,0.000137359,0.0130432,0.00834959,0.00701308,0.00532466,0.0153598,0.00124277,0.00025418,0.00107664,0.00859943,0.00360163,0.0055823,0.00803396,0,6.25978e-05,0,0.00531876,0.0337214,0.0244545,0.00811767,0.00977846", "env/equip_defense": "0.0244253,5.12424,5.95919,6.4232,6.73834,6.98075,7.17476,7.39228,7.52727,7.68144,7.8396,7.95781,0.00450682,0.0053702,0.0267199,6.10277e-05,3.16331e-05,0.00257777,5.0674e-05,0.0108919,5.34653,6.07263,6.51576,6.85811,7.12616,7.31767,7.5256,7.63795,7.79852,7.94586,8.04205,8.16762,9.20765,9.2284,9.30533,9.33426,9.35511,9.39756,9.44253,9.4789,9.4591,9.50101,9.52604,9.51088,9.53975,9.50971,0.0139862,0.0401127,5.25343,8.89039,10.223,13.4713,15.7929,16.3137,16.48,16.6882,16.6518,16.841,16.8505,16.8155,16.9332,16.9667,16.9521,17.2263,17.2561,17.1818,17.2676,17.358,17.4843,17.531,17.4876,17.5936,17.5206,17.5459,17.6387,17.6823,17.6932,17.681,17.7289,17.8433,17.8942,17.9711,17.9817,18.1076,18.1086,18.2025,18.1302,18.2475,18.2904,18.2994,18.3465,18.4441,18.3878,18.4023,18.4172,18.6242,0,6.32082,9.53446,14.9721,16.0964,17.9408,17.9753,18.0199,18.0091,18.0562,18.0736,18.0565,18.1329,0.0024346,0.00715346,0,4.72771e-05,7.3741,7.48135,7.50497,7.56391,7.63387,7.71482,7.75688,7.88175,7.87049,7.95555,8.02805,8.04134,8.13336,8.15664,8.2175,8.28168,8.33986,8.40115,8.4479,8.46697,8.44835,8.49013,0,0,0,5.2581,8.87812,10.2096,13.4763,15.798,16.3159,16.4801,16.6957,16.6566,16.8446,16.8397,16.8135,16.9298,16.9543,16.9473,17.228,17.2691,17.1827,17.2614,17.3421,17.494,17.5289,17.5045,17.6108,17.5288,17.5695,17.6391,17.6973,17.6852,17.6577,17.7316,17.8264,17.9072,17.9669,17.995,18.1004,18.0866,18.182,18.1241,18.2239,18.2853,18.3064,18.3623,18.4318,18.3931,18.402,18.4036,18.4317,18.4683,0.00787257,0.0470083,0.0648801,0.0824382,0.0903548,5.25636,8.88951,10.221,13.4782,15.7849,16.3282,16.4803,16.6881,16.6622,16.8517,16.8652,16.8116,16.9195,16.9601,16.9438,17.2302,17.2676,17.1846,17.2698,17.3346,17.487,17.5282,17.5044,17.6014,17.5197,17.5687,17.6238,17.6889,17.6808,17.6756,17.744,17.8355,17.9212,17.9549,17.9902,18.1001,18.1002,18.1824,18.1228,18.2314,18.2941,18.3055,18.3576,18.4391,18.3836,18.4008,18.4425,18.4751,0.00102874,0.0680296,0.048041,0.0550093,0.053183,0.0514726,0.00211336,6.62467e-05,0,0,5.69455,6.23094,6.62401,6.90838,7.15338,7.37901,7.55491,7.70648,7.79324,7.92028,8.01532,9.11655,9.16585,9.1661,9.23096,9.26168,9.31171,9.34044,9.37559,9.39229,9.43887,5.25281,8.88465,10.2111,13.4684,15.8094,16.3138,16.4945,16.6871,16.6709,16.8556,16.8702,16.8009,16.9341,16.9608,16.9528,17.2272,17.2651,17.1568,17.2589,17.3393,17.4805,17.5477,17.4995,17.5893,17.5294,17.5428,17.6291,17.6822,17.681,17.7369,17.8364,17.9026,17.9806,17.993,18.0951,18.0978,18.1845,18.1291,18.2329,18.3034,18.3067,18.3521,18.4273,18.3906,18.4019,18.4291,18.4384,18.5801,5.61343,6.18599,6.63406,6.8685,7.14519,7.35612,7.53891,7.71295,7.85704,7.98584,8.10138,9.17887,9.21596,9.27534,9.32119,9.30862,9.35916,9.39379,9.42824,9.42973,9.47684,9.49095,9.46543,2.70858,4.30325,5.00006,5.45165,5.75167,1.94958e-05,0.0617544,0.000184747,0.0011851,0.02958,0.0699761,0.0768377,0.093978,0.00435998,0.0504656,0.000187336,0.000560093,0.00311026,0.0238442,0.000155549,5.25491,8.88225,10.2117,13.4725,15.7889,16.3042,16.4851,16.6903,16.6567,16.8592,16.8595,16.807,16.9385,16.9493,16.9413,17.2261,17.2627,17.173,17.2608,17.3496,17.4765,17.5417,17.4953,17.6054,17.5248,17.5593,17.6585,17.6904,17.6807,17.6777,17.7715,17.7998,17.9153,17.9724,17.9766,18.1022,18.0964,18.1849,18.1243,18.2345,18.2818,18.3262,18.3552,18.4278,18.4104,18.4234,0.000859265,5.25222,8.89288,10.2124,13.474,15.7781,16.3312,16.4849,16.6769,16.6769,16.8377,16.8641,16.8082,16.9337,16.9738,16.9506,17.2265,17.2749,17.1844,17.2745,17.3527,17.4878,17.5497,17.4975,17.6053,17.5313,17.5458,17.6408,17.7064,17.6832,17.6728,17.7423,17.8231,17.9015,17.9649,18.0041,18.1013,18.0987,18.1951,18.1197,18.2381,18.2955,18.3241,18.3665,18.4283,18.3886,18.4007,18.4046,18.4418,0,8.48513e-05,0.0271967,0.058398,0.0828594,0.0911108,0.0209037,0.0291557,0.0544371,0.0581388,0.0313692,0.093626,0.0982485,0.00478315,0,3.04971e-05,3.35909e-05,0.0573244,0.0228372,0.0514002,0.0526814,0.0519481", "env/r": "258.101,250.466,252.376,250.923,251.647,252.812,252.837,253.874,254.752,254.32,254.472,254.881,257.667,258.986,260.747,256.142,258.212,257.814,257.779,254.752,248.502,250.75,251.374,251.025,252.944,252.59,253.76,253.72,254.585,253.254,253.564,253.746,253.918,253.383,253.285,253.224,253.709,253.734,253.769,253.028,253.435,253.683,253.334,253.164,253.88,251.401,257.377,257.878,254.192,253.39,253.177,252.934,254.805,254.461,254.386,254.163,253.344,253.774,253.906,254.123,253.937,253.765,253.421,253.735,254.357,254.679,254.89,254.98,255.277,255.457,255.992,255.387,255.208,255.395,255.883,254.818,254.513,254.294,253.666,253.856,253.285,253.39,252.681,252.746,252.26,251.951,251.58,252.261,250.209,249.513,249.694,249.369,249.458,249.104,249.384,250.353,256.508,260.227,254.091,253.808,254.507,253.596,253.622,253.896,253.859,253.685,253.939,253.969,252.349,258.08,258.953,255.902,256.348,250.176,251.861,249.148,249.843,251.062,250.708,253.087,251.399,253.296,254.391,252.438,252.043,249.238,253.105,252.593,251.938,253.393,252.962,252.617,251.815,253.282,252.642,254.189,255.426,258.15,254.396,253.589,253.102,252.849,254.916,254.432,254.536,254.223,253.73,253.873,253.919,254.437,253.919,253.653,253.546,253.964,254.335,254.581,254.731,255.193,255.218,255.339,255.865,255.651,255.316,255.176,255.863,254.682,254.614,254.415,253.777,253.674,253.685,253.506,252.731,252.65,252.093,251.779,251.455,252.475,250.246,249.267,249.835,249.196,249.554,249.245,249.547,249.854,249.076,258.213,257.893,257.805,257.307,256.675,254.437,253.596,252.965,252.732,254.773,254.701,254.54,254.285,253.448,253.725,253.852,254.072,253.867,253.879,253.256,253.758,254.47,254.54,254.997,255.027,255.401,255.548,255.586,255.127,255.454,255.328,255.978,254.653,254.823,254.19,253.53,253.984,253.667,253.486,252.604,252.429,252.133,251.962,251.613,252.395,250.15,249.369,249.826,249.381,249.353,249.497,249.724,248.407,256.767,256.73,258.135,258.742,259.374,259.349,255.807,257.455,253.772,256.587,254.644,254.187,253.82,254.829,254.293,253.98,253.864,254.042,254.649,254.329,253.851,254.125,253.908,253.636,253.754,253.472,253.876,253.722,253.962,253.201,253.593,254.312,253.44,253.128,252.753,254.903,254.736,254.569,254.193,253.716,253.774,253.866,254.187,253.94,253.653,253.54,253.938,254.659,254.479,254.841,255.042,255.146,255.31,255.912,255.396,255.271,255.383,255.883,254.543,254.592,253.753,253.541,253.412,253.434,252.598,252.628,251.886,251.567,251.704,252.48,250.186,249.352,249.898,249.415,249.262,249.113,249.473,249.712,249.541,261.612,260.203,258.751,258.623,258.638,257.439,257.655,256.632,255.814,256.158,257.035,254.401,254.331,254.468,254.618,254.747,254.513,254.957,254.529,254.629,254.643,254.978,254.904,275.664,267.38,261.502,259.828,258.698,253.762,256.854,256.363,255.062,255.082,255.404,255.533,257.892,254.506,256.329,261.228,257.3,257.428,257.021,257.6,254.322,253.54,253.125,252.823,254.769,254.703,254.584,254.281,253.426,253.909,253.917,254.029,253.898,253.892,253.513,253.977,254.601,254.487,254.809,255.023,255.325,255.32,255.908,255.511,255.321,255.231,255.774,254.65,254.433,254.188,253.711,253.735,253.682,253.48,252.546,252.258,252.126,251.981,251.625,252.517,250.234,249.264,249.695,249.286,249.096,249.489,258.932,254.265,253.436,253.177,252.771,254.76,254.724,254.398,254.235,253.636,253.964,253.848,254.191,254.051,253.61,253.638,253.865,254.585,254.423,254.555,254.969,255.2,255.297,256.002,255.524,255.271,255.285,255.687,254.806,254.56,254.379,253.737,253.997,253.462,253.553,252.406,252.539,252.138,251.717,251.589,252.457,250.044,249.607,249.818,249.1,249.286,249.229,249.466,249.892,255.41,255.82,257.185,257.42,257.532,258.638,258.317,256.637,257.029,255.621,255.043,256.383,254.869,255.538,257.75,255.961,256.432,256.854,257.993,258.114,257.769,259.653", "env/c": "255.201,252.03,250.422,251.064,252.135,252.12,253.767,253.946,252.848,253.087,252.793,252.986,255.941,255.68,255.481,254.172,255.532,256.714,256.864,255.741,250.681,250.482,251.397,252.882,252.406,250.95,251.633,251.301,251.252,251.028,250.708,251.052,250.157,250.253,250.637,250.318,250.749,249.985,249.241,250.445,250.093,249.989,250.312,250.432,249.829,252.247,255.71,255.625,250.687,252.696,251.687,251.634,251.461,252.252,252.88,253.285,253.616,253.631,253.762,254.544,254.885,254.803,255.056,254.57,254.972,254.774,255.082,256.443,255.732,255.561,255.524,255.43,255.1,255.263,255.252,254.989,255.317,255.564,255.42,255.59,255.514,255.328,255.553,254.918,254.718,254.677,254.008,252.243,253.867,254.308,254.788,254.397,254.786,254.797,254.572,254.688,255.995,252.594,252.899,253.039,253.811,253.997,254.01,254.025,253.825,253.57,253.665,253.866,254.197,256.921,254.949,256.342,256.346,257.57,257.204,256.188,260.069,256.102,260.059,258.18,259.306,256.519,258.395,257.719,255.264,256.374,257.226,258.056,254.13,254.682,255.305,254.261,255.988,256.097,255.347,256.267,257.374,257.504,250.67,252.849,251.685,251.731,251.498,252.166,252.965,253.337,253.655,253.507,253.745,254.585,254.958,254.912,255.226,254.561,255.082,254.972,255.102,256.38,255.765,255.594,255.43,255.475,255.074,255.463,255.083,254.975,255.268,255.441,255.662,255.473,255.533,255.217,255.65,255.202,254.729,254.465,254.1,252.35,253.962,254.542,254.437,254.425,254.538,255.031,254.81,254.721,254.98,256.718,256.554,255.876,255.71,257.721,250.644,252.762,251.433,251.788,251.338,252.276,252.883,253.272,253.228,253.649,254.007,254.443,255.141,255.012,255.124,254.839,254.728,254.954,255.28,256.349,256.011,255.69,255.39,255.363,254.959,255.456,255.107,255.196,255.332,255.618,255.338,255.463,255.763,255.132,255.561,255.25,254.732,254.505,253.944,252.309,254.122,254.443,254.33,254.24,254.768,254.65,254.738,254.633,255.083,255.84,254.918,255.424,255.43,256.344,256.262,253.889,256.569,256.369,251.405,250.917,252.257,253.139,252.083,253.119,253.424,252.576,252.217,253.844,253.947,253.762,254.268,254.549,254.581,254.436,254.682,254.213,254.253,254.4,255.149,250.599,252.812,251.685,251.65,251.513,252.102,252.893,253.307,253.668,253.657,253.814,254.349,254.866,255.007,255.096,254.603,254.913,254.84,255.086,256.545,255.848,255.544,255.69,255.355,254.989,255.303,255.117,255.149,255.253,255.551,255.865,255.21,255.373,255.955,255.024,254.91,254.498,253.966,252.3,254.134,254.641,254.764,254.506,254.901,254.824,254.703,254.698,254.012,249.972,249.623,251.03,250.908,251.08,252.095,250.999,250.572,251.527,251.874,250.226,251.932,251.371,251.801,251.729,252.24,252.153,252.352,251.785,251.624,252.121,252.175,252.265,250.692,250.454,251.767,250.569,251.278,256.49,256.664,255.311,255.081,255.062,254.886,254.803,254.802,256.86,256.161,256.499,255.773,255.696,255.875,253.919,250.649,252.788,251.622,251.612,251.46,252.143,253.133,253.431,253.629,253.677,253.653,254.444,254.876,255.028,255.022,254.635,254.805,254.824,255.076,256.332,255.803,255.585,255.449,255.368,255.02,255.233,255.069,254.901,254.974,255.35,255.377,255.889,255.328,255.3,255.707,255.162,254.898,254.539,254.033,252.309,254.146,254.437,254.604,254.246,254.63,254.945,254.558,250.741,252.721,251.712,251.538,251.606,252.133,252.945,253.429,253.454,253.573,253.922,254.317,254.942,254.768,255.341,254.829,254.839,254.684,255.152,256.418,255.758,255.492,255.284,255.495,255.159,255.373,255.172,254.885,255.13,255.298,255.577,255.717,255.467,255.373,255.834,255.021,254.843,254.296,254.11,252.33,253.995,254.421,254.671,254.361,254.775,254.829,254.706,254.559,263.204,255.87,255.112,255.881,254.681,254.537,254.981,256.005,256.021,254.788,256.055,255.716,255.161,256.722,258.301,261.067,257.768,255.06,255.195,255.624,255.263,255.93", "env/n": "2151.22,1218.89,1061.73,1013.1,975.185,946.734,927.18,900.895,890.846,878.584,862.845,858.572,6693.36,5294.89,4388.07,5309.71,6386.52,3117.47,6432,2613.78,1171.46,1046.87,1006.09,964.561,937.346,917.173,895.923,884.944,871.334,860.843,857.731,842.641,691.56,680.911,674.15,669.715,665.625,660.943,652.988,652.01,648.085,644.681,642.793,644.811,641.879,10243,2695.76,2414.2,1343.97,715.254,651.685,582.001,556.046,541.128,532.019,525.74,521.822,516.187,512.799,509.039,504.552,502.532,498.467,494.992,492.937,489.872,486.41,482.994,481.349,479.029,477.424,474.754,473.439,471.949,469.159,468.121,466.304,465.599,464.115,460.358,458.093,455.631,452.541,447.82,443.653,440.468,437.122,434.914,431.467,427.77,425.362,422.904,422.127,420.264,420.195,10106,12985.2,1121.99,689.011,574.016,547.51,427.833,426.852,425.739,424.279,423.729,423.043,422.813,10056,5625.86,5120.95,5852.26,5548.55,1852.46,1805.28,1800.22,1792.15,1779.08,1732.6,1750.12,1711.86,1750.68,1725.07,1691.21,1707.82,1682.27,1646.17,1618.31,1574.2,1563.15,1528.31,1508.14,1499.64,1499.86,1488.93,6340,11260.8,6151.1,1344.7,715.978,652.379,582.334,555.398,540.245,531.892,526.039,521.573,516.333,512.812,509.18,504.093,502.631,499.085,495.281,492.764,490.448,486.721,482.921,481.425,479.511,476.851,474.435,473.185,471.137,469.338,467.667,466.97,465.978,464.102,460.564,457.803,455.358,452.234,447.799,444.246,440.29,436.883,435.201,430.995,427.093,425.302,423.488,422.163,420.553,420.523,419.938,10031,5281.18,4150.02,3585.51,3048.95,14432,1343.52,714.592,652.444,582.918,555.95,540.376,531.826,526.121,521.408,516.307,512.065,509.133,505.12,502.511,498.658,495.603,492.885,490.058,486.51,483.364,481.291,478.896,477.31,474.763,472.994,471.417,469.684,467.732,467.082,465.905,463.288,460.658,458.122,455.362,452.436,447.744,443.798,440.302,437.384,435.002,431.486,427.504,425.204,423.314,422.389,420.924,420.086,10049,2769.23,2935.14,13655,3585.78,3131.95,18029,6220.5,3183.36,5200,6036.75,1086.89,1014.31,973.506,935.573,916.031,894.089,876.746,868.749,864.01,853.069,840.434,692.818,680,675.526,668.659,662.479,655.746,652.196,650.4,646.933,640.38,1343.51,716.05,652.418,582.48,556.072,540.444,531.669,526.27,521.228,515.976,511.945,509.418,504.786,502.241,498.379,495.351,493.085,490.48,486.752,483.456,481.519,478.774,477.258,474.795,473.12,471.557,469.326,468.014,466.701,463.285,460.327,458.614,455.134,452.109,447.564,444.053,440.308,437.15,434.663,431.261,426.976,425.376,423.593,422.471,420.867,420.191,419.677,10037,1096,1026.79,965.036,946.686,916.813,895.802,877.484,870.533,862.109,850.492,844.444,700.213,693.954,681.141,674.762,670.051,665.873,660.891,654.548,653.119,649.812,648.318,648.013,2149.12,1780.51,1609.41,1557.43,1518.87,5291.18,14250,6221.45,5467.71,4635.85,4465.34,4149.71,16174,5474.64,3696.33,2762.38,6229.67,5895.07,5339.39,6526.34,1344.18,716.115,652.338,582.333,555.623,539.846,532.077,525.585,522.126,516.113,512.671,509.635,504.438,503.13,499.104,496.088,492.768,490.88,486.864,483.021,481.139,478.777,477.113,475.224,472.856,471.48,469.393,468.184,467.09,466.094,463.398,460.969,457.683,455.442,452.527,447.816,443.82,440.814,437.133,435.15,431.523,427.796,425.387,423.837,420.847,419.885,5412.47,1343.49,714.802,651.722,582.803,555.881,540.282,532.208,526.365,521.31,516.669,512.035,509.224,504.523,502.185,499.176,495.65,492.588,490.073,486.875,483.553,481.142,479.078,476.907,474.639,473.143,471.417,469.513,467.979,466.636,465.647,463.702,460.685,457.723,455.444,452.35,448.058,443.689,440.778,436.835,435.041,431.175,427.762,425.395,423.29,422.247,420.51,420.449,419.859,4714.38,2681.5,2153.45,1954.75,1755.42,13522,3751.87,2358.37,1969.9,14861,2397.1,1877.11,14331,5202.84,9067.74,4554.86,2991.32,13537,4315.48,3816.99,3337.7,13090", "perf/rollout": "0.171058,0.314883,0.314734,0.314635,0.31255,0.314934,0.314918,0.314767,0.313078,0.31488,0.314914,0.314978,0.298918,0.306068,0.266128,0.139092,0.304234,0.167448,0.413368,0.181883,0.310417,0.310364,0.309803,0.310211,0.305897,0.309698,0.305717,0.309761,0.311289,0.312555,0.312051,0.310867,0.310016,0.309712,0.30975,0.309778,0.309417,0.309649,0.308421,0.311215,0.311451,0.308971,0.310528,0.310935,0.310857,0.304597,0.166566,0.166277,0.30779,0.306202,0.314498,0.316911,0.317372,0.317396,0.319463,0.321026,0.320633,0.320563,0.319807,0.319903,0.320719,0.31958,0.32118,0.321548,0.321118,0.321312,0.321173,0.32089,0.32096,0.306391,0.305901,0.302635,0.302383,0.303878,0.301868,0.306138,0.308189,0.306414,0.31292,0.316975,0.320544,0.316496,0.310362,0.301569,0.317177,0.320058,0.320476,0.320556,0.320657,0.317345,0.316316,0.306263,0.309592,0.313389,0.308229,0.310767,0.284164,0.310966,0.317726,0.308233,0.305005,0.324581,0.325753,0.325147,0.319849,0.321227,0.326188,0.326215,0.325917,0.301882,0.30244,0.295476,0.198192,0.65103,0.651558,0.650822,0.650536,0.651615,0.650766,0.652139,0.652379,0.653309,0.652445,0.652937,0.654389,0.653295,0.6518,0.652846,0.652579,0.653266,0.652919,0.652947,0.65253,0.652839,0.653908,0.140965,0.292648,0.413389,0.304949,0.319846,0.324253,0.324997,0.324747,0.325026,0.323741,0.323599,0.323844,0.323984,0.315534,0.30869,0.32345,0.323894,0.323909,0.324631,0.325786,0.32619,0.325783,0.32547,0.325703,0.326812,0.32622,0.320983,0.308196,0.305901,0.313617,0.315205,0.325758,0.325825,0.32467,0.317827,0.31744,0.318256,0.314177,0.328403,0.328357,0.312204,0.321388,0.321377,0.320942,0.320946,0.321678,0.324402,0.324195,0.308752,0.315899,0.326009,0.303681,0.289838,0.289225,0.287596,0.288759,0.289687,0.318438,0.320236,0.320628,0.320817,0.320948,0.31904,0.305507,0.306191,0.307479,0.323973,0.32205,0.321503,0.316617,0.311831,0.315597,0.322384,0.324656,0.32499,0.325012,0.32494,0.322032,0.310253,0.309417,0.308179,0.310102,0.311602,0.309801,0.306883,0.306077,0.306982,0.309315,0.305823,0.3056,0.306647,0.305336,0.305865,0.321481,0.324972,0.32609,0.325973,0.321937,0.316795,0.303804,0.325318,0.325639,0.324719,0.324369,0.3274,0.168992,0.295639,0.295481,0.294368,0.294273,0.293843,0.308065,0.169315,0.132911,0.138048,0.31306,0.312776,0.312639,0.312627,0.312692,0.312331,0.312505,0.312688,0.312741,0.312678,0.314443,0.314672,0.312198,0.31313,0.312874,0.312772,0.313177,0.313261,0.313125,0.313184,0.313046,0.318462,0.319553,0.320181,0.318342,0.318906,0.318598,0.318488,0.320541,0.320585,0.321645,0.320484,0.320529,0.320722,0.313717,0.314439,0.309562,0.305176,0.305013,0.303793,0.308004,0.3045,0.306555,0.30768,0.31917,0.320294,0.321233,0.320762,0.321304,0.320176,0.308998,0.304634,0.306636,0.309156,0.314801,0.32473,0.325576,0.313116,0.316236,0.321222,0.309344,0.323117,0.322255,0.314628,0.304833,0.31697,0.322708,0.321602,0.303049,0.312916,0.312188,0.312221,0.312217,0.312096,0.306033,0.310586,0.312362,0.312535,0.312469,0.309394,0.312082,0.313209,0.318483,0.319542,0.319362,0.313424,0.311552,0.311445,0.31171,0.311778,0.310395,0.330056,0.289443,0.29189,0.293198,0.29312,0.291961,0.294029,0.331866,0.333827,0.365847,0.360892,0.361054,0.360872,0.362228,0.334595,0.331794,0.107439,0.301548,0.298315,0.297566,0.366053,0.305256,0.307609,0.315032,0.31631,0.315526,0.315516,0.309606,0.309982,0.310953,0.319673,0.320594,0.324637,0.324933,0.324123,0.324525,0.325126,0.32522,0.325313,0.324942,0.324966,0.325026,0.325482,0.325384,0.325251,0.324748,0.325199,0.325537,0.325951,0.326799,0.32691,0.326904,0.326806,0.326283,0.32666,0.327525,0.327753,0.328672,0.319721,0.305878,0.30536,0.306552,0.320644,0.328004,0.327248,0.32276,0.321788,0.279568,0.319968,0.318638,0.3089,0.310039,0.31057,0.306535,0.315016,0.322055,0.322609,0.323103,0.323266,0.322733,0.323421,0.308697,0.318973,0.322577,0.311189,0.303684,0.304649,0.304485,0.3049,0.304691,0.307395,0.311669,0.31628,0.32307,0.323077,0.322489,0.31671,0.320603,0.319309,0.31993,0.319892,0.320478,0.320395,0.321494,0.321986,0.320973,0.321218,0.322937,0.32062,0.32276,0.316612,0.305919,0.321714,0.312842,0.322079,0.322805,0.139071,0.168746,0.168333,0.168466,0.168373,0.168048,0.280033,0.172936,0.17326,0.173918,0.168633,0.168733,0.170138,0.29988,0.303976,0.133665,0.13316,0.333933,0.305151,0.305781,0.305324,0.305656", "perf/eval_gpu": "0.111027,0.174733,0.174758,0.174709,0.169987,0.17564,0.175641,0.175493,0.172483,0.175421,0.175374,0.175317,0.170434,0.187279,0.162377,0.0693206,0.182335,0.0943165,0.106195,0.121489,0.165623,0.166056,0.169259,0.170305,0.160734,0.168791,0.160634,0.167865,0.169841,0.168353,0.167882,0.167166,0.16765,0.168124,0.168191,0.16813,0.167901,0.167234,0.164279,0.160934,0.161342,0.154552,0.154069,0.160992,0.161631,0.153319,0.0930069,0.092479,0.155758,0.153474,0.163137,0.168823,0.169209,0.168766,0.170861,0.171411,0.171974,0.172089,0.170994,0.170743,0.171971,0.170859,0.172661,0.172628,0.172057,0.172057,0.171894,0.171107,0.171671,0.160493,0.163062,0.149177,0.148984,0.149715,0.148629,0.152871,0.157774,0.154175,0.164185,0.168558,0.170854,0.166666,0.160753,0.151374,0.164324,0.169843,0.170735,0.170872,0.170535,0.166195,0.166516,0.157647,0.16213,0.163876,0.159626,0.120372,0.12923,0.162293,0.166053,0.155185,0.15167,0.170094,0.171873,0.170887,0.164229,0.165894,0.172233,0.172192,0.170643,0.159148,0.159433,0.169088,0.0573094,0.363753,0.364039,0.363913,0.363342,0.364335,0.363766,0.364405,0.364322,0.364671,0.363509,0.364013,0.365249,0.364619,0.363594,0.364319,0.363658,0.363899,0.362652,0.36314,0.362301,0.36363,0.364344,0.0390186,0.152096,0.105164,0.155574,0.169367,0.172046,0.172557,0.172726,0.171889,0.169027,0.171004,0.170195,0.171027,0.160308,0.155264,0.171189,0.171058,0.171399,0.16853,0.168006,0.167371,0.171229,0.172115,0.170108,0.170859,0.16542,0.162907,0.15215,0.147126,0.15673,0.160724,0.17248,0.171395,0.171219,0.16461,0.164178,0.16204,0.155645,0.174263,0.174454,0.153743,0.169839,0.170606,0.168451,0.170405,0.168324,0.170699,0.170725,0.153718,0.162319,0.171032,0.145802,0.148031,0.148294,0.14756,0.148569,0.148634,0.172061,0.172357,0.172779,0.173241,0.170601,0.167789,0.151006,0.152636,0.154135,0.169883,0.171912,0.172454,0.164553,0.158956,0.164831,0.165278,0.171198,0.173276,0.17325,0.173108,0.172377,0.165606,0.164775,0.161501,0.164821,0.168312,0.163111,0.154629,0.151518,0.152148,0.150634,0.15387,0.15245,0.157623,0.145866,0.139611,0.162756,0.16824,0.169152,0.170054,0.164631,0.158238,0.142299,0.167071,0.170379,0.169936,0.168965,0.172307,0.093568,0.175727,0.175525,0.168025,0.167314,0.168065,0.179908,0.109025,0.0616435,0.0609405,0.15791,0.157581,0.157409,0.157522,0.157362,0.156977,0.157156,0.157352,0.157333,0.157224,0.170182,0.172263,0.164702,0.170657,0.170684,0.170505,0.170891,0.170865,0.170754,0.170834,0.170783,0.168514,0.163184,0.171115,0.166285,0.168383,0.16626,0.166891,0.169484,0.167844,0.171262,0.170048,0.169886,0.169915,0.165831,0.163081,0.152168,0.156199,0.15641,0.151929,0.154487,0.149961,0.151727,0.154761,0.164534,0.166452,0.16758,0.167136,0.163814,0.167309,0.147795,0.143413,0.14857,0.163759,0.154158,0.165968,0.168792,0.150436,0.156958,0.165539,0.152361,0.168874,0.167354,0.157936,0.149919,0.164079,0.16962,0.170201,0.140981,0.171534,0.169664,0.170328,0.170593,0.170498,0.152061,0.166082,0.170804,0.170871,0.170759,0.164483,0.166903,0.171235,0.166773,0.1668,0.166714,0.161298,0.160975,0.160779,0.161066,0.161253,0.158143,0.133442,0.138635,0.143505,0.147239,0.147166,0.143059,0.162615,0.210983,0.21266,0.233965,0.235082,0.236994,0.236943,0.238995,0.21333,0.211621,0.0240631,0.171519,0.169523,0.16878,0.231645,0.158547,0.165465,0.166604,0.166732,0.167346,0.165312,0.163552,0.164665,0.165715,0.166017,0.169022,0.172104,0.173049,0.17173,0.17047,0.173118,0.172791,0.172009,0.172652,0.171513,0.172071,0.17223,0.17213,0.172481,0.171838,0.172245,0.172623,0.169051,0.167803,0.167164,0.168004,0.167756,0.16784,0.168411,0.169168,0.169773,0.17094,0.160081,0.151568,0.149735,0.143752,0.16184,0.167132,0.168856,0.166219,0.165028,0.137487,0.166848,0.163076,0.160735,0.165612,0.163054,0.155693,0.160459,0.170341,0.170911,0.170088,0.169828,0.17001,0.172394,0.157329,0.167374,0.169681,0.15726,0.148523,0.151953,0.153871,0.151656,0.151565,0.149226,0.154513,0.161371,0.170377,0.171055,0.1721,0.165345,0.169248,0.168299,0.16705,0.168856,0.169365,0.166376,0.17107,0.17162,0.166329,0.17071,0.169539,0.168302,0.172542,0.162859,0.151659,0.169673,0.160225,0.169947,0.16921,0.0561148,0.108499,0.108329,0.108337,0.10828,0.10784,0.13775,0.11148,0.111517,0.111662,0.108548,0.108547,0.107851,0.149175,0.0901735,0.039689,0.0421735,0.21164,0.18093,0.180448,0.175344,0.178598", "perf/eval_env": "0.0584349,0.13819,0.138029,0.137978,0.140523,0.137331,0.137326,0.137298,0.138546,0.137467,0.137572,0.137687,0.126808,0.115656,0.101012,0.0679183,0.12035,0.0716016,0.0829149,0.0587722,0.142787,0.140486,0.138288,0.137743,0.141849,0.138613,0.141683,0.139733,0.139579,0.142292,0.142108,0.141556,0.140232,0.139613,0.13961,0.139688,0.139555,0.140217,0.14152,0.146983,0.146848,0.15119,0.153464,0.146695,0.146097,0.148526,0.0719567,0.072151,0.145141,0.144825,0.146645,0.145739,0.145856,0.146234,0.14643,0.147096,0.146567,0.146232,0.146474,0.146791,0.146484,0.146573,0.146414,0.146801,0.146929,0.147143,0.147072,0.147269,0.147088,0.142204,0.140565,0.144546,0.144698,0.146931,0.14406,0.14592,0.14475,0.145612,0.145181,0.146078,0.14746,0.146736,0.145751,0.143242,0.147985,0.147831,0.147522,0.147443,0.147885,0.147547,0.146916,0.14419,0.144687,0.146702,0.144538,0.160766,0.150042,0.145446,0.148041,0.146288,0.145398,0.151482,0.151234,0.151317,0.150761,0.150916,0.151435,0.151544,0.152087,0.140097,0.140446,0.124729,0.069573,0.284341,0.284576,0.283968,0.284248,0.284322,0.284065,0.284775,0.285118,0.285678,0.286005,0.285985,0.286177,0.285729,0.285266,0.285603,0.286033,0.286478,0.287399,0.286926,0.287359,0.286305,0.286649,0.0849008,0.138565,0.0829547,0.141574,0.146641,0.149332,0.149482,0.14939,0.14999,0.150818,0.149338,0.149918,0.149548,0.147831,0.14553,0.14987,0.150146,0.149672,0.151608,0.152388,0.152848,0.151066,0.150329,0.151334,0.15154,0.153525,0.151074,0.146497,0.145989,0.148409,0.147383,0.149862,0.150512,0.150356,0.14856,0.148434,0.149049,0.148568,0.151545,0.151191,0.148368,0.149108,0.148243,0.149416,0.147765,0.150509,0.151136,0.150763,0.146582,0.14798,0.151124,0.146775,0.139224,0.138439,0.137509,0.137719,0.138587,0.144124,0.145565,0.145592,0.145411,0.147058,0.147836,0.146005,0.147736,0.148129,0.151931,0.147903,0.146881,0.148408,0.147974,0.14835,0.152859,0.150328,0.149549,0.149625,0.149631,0.147539,0.141837,0.141694,0.143203,0.141945,0.140563,0.142278,0.145294,0.149516,0.148605,0.149886,0.145252,0.145891,0.143933,0.146895,0.148926,0.152319,0.15363,0.153996,0.153304,0.153313,0.1511,0.147049,0.154188,0.152607,0.15249,0.152079,0.152602,0.0735668,0.116886,0.116922,0.124751,0.125361,0.124237,0.124948,0.0587377,0.0435667,0.0470433,0.15053,0.150482,0.150473,0.150362,0.150491,0.150441,0.150481,0.150549,0.150619,0.150608,0.141757,0.140426,0.143361,0.140422,0.14014,0.140187,0.14026,0.140373,0.140324,0.140317,0.140224,0.147348,0.15102,0.146473,0.148055,0.147373,0.148189,0.1488,0.148429,0.149135,0.14776,0.14776,0.148129,0.148416,0.144958,0.146923,0.14914,0.144695,0.143957,0.145462,0.147611,0.14709,0.148077,0.14719,0.150843,0.150718,0.150833,0.150668,0.152494,0.149905,0.150474,0.148792,0.147276,0.141592,0.151101,0.154231,0.153003,0.151703,0.15181,0.151574,0.148161,0.151776,0.151853,0.149693,0.145491,0.147991,0.149873,0.148874,0.150775,0.139511,0.14064,0.140001,0.139743,0.139717,0.147921,0.141611,0.139661,0.139747,0.139788,0.142061,0.142703,0.140015,0.149942,0.151009,0.150917,0.149899,0.148728,0.148837,0.148783,0.148711,0.149184,0.167005,0.145839,0.144484,0.143024,0.14259,0.144849,0.129283,0.119091,0.119444,0.130116,0.123932,0.122456,0.122293,0.121468,0.119524,0.118558,0.0424046,0.128411,0.127151,0.127197,0.132365,0.141886,0.138874,0.145876,0.146998,0.145581,0.146469,0.142553,0.141944,0.142128,0.150214,0.148301,0.149688,0.149246,0.149656,0.150852,0.149587,0.150078,0.150677,0.149912,0.150319,0.150237,0.150701,0.150731,0.15019,0.150183,0.150334,0.150272,0.153995,0.155683,0.1562,0.155819,0.15601,0.155576,0.155433,0.155676,0.155515,0.155259,0.153561,0.147663,0.147446,0.150055,0.152648,0.156679,0.155429,0.153755,0.153217,0.139434,0.148829,0.150107,0.143934,0.14117,0.143612,0.143958,0.147973,0.148676,0.148637,0.149193,0.149741,0.149336,0.148309,0.145084,0.147314,0.14887,0.146959,0.145657,0.144155,0.142919,0.144952,0.144856,0.148654,0.148283,0.147952,0.149356,0.148595,0.147586,0.146516,0.147828,0.147526,0.14861,0.147749,0.147934,0.149911,0.147237,0.147331,0.149788,0.147835,0.149093,0.149005,0.148,0.148292,0.14544,0.148598,0.147189,0.149509,0.149907,0.0753458,0.0587096,0.0584809,0.0585791,0.0585709,0.0587473,0.13967,0.0598296,0.0600485,0.0605918,0.0585179,0.0586121,0.05968,0.14097,0.106586,0.082813,0.0804209,0.120468,0.122605,0.123597,0.127119,0.125491", "perf/train_misc": "0.0105742,0.010349,0.0103481,0.0103417,0.0103444,0.0103433,0.0103477,0.0103419,0.0103477,0.010344,0.010343,0.0103428,0.031381,0.0224235,0.0183888,0.00396707,0.0279096,0.0144112,0.0179779,0.0101202,0.0102316,0.0102356,0.010236,0.0102386,0.0102333,0.0102318,0.0102364,0.0102323,0.0102324,0.0102312,0.0102311,0.0102312,0.0102254,0.0102245,0.0102244,0.0102243,0.0102241,0.0102303,0.0102338,0.0102266,0.0102248,0.0102227,0.0102234,0.0102247,0.0102247,0.0102042,0.0150661,0.0141441,0.0103344,0.010306,0.0103079,0.0103037,0.0103041,0.0103,0.0103032,0.0103013,0.0103003,0.0102989,0.010297,0.0103014,0.0103006,0.0103016,0.0103022,0.0103021,0.0103029,0.0103031,0.0103042,0.0102994,0.0103011,0.0103011,0.0103011,0.0102989,0.0103034,0.0103023,0.0103019,0.010299,0.0103013,0.0103023,0.0103008,0.0102978,0.0102977,0.0103002,0.0102976,0.0103008,0.0102988,0.0102993,0.0103034,0.0103045,0.0103047,0.0103021,0.010303,0.0102988,0.010302,0.0102981,0.0102993,0.0102707,0.0210987,0.010292,0.0102923,0.0102902,0.0102935,0.0102875,0.0102868,0.0102865,0.0102871,0.0102889,0.0102837,0.0102856,0.0103322,0.0170398,0.0161082,0.0168253,0.0225647,0.0222005,0.0222024,0.0222058,0.0222024,0.0222059,0.0222042,0.0222046,0.022204,0.0222087,0.0222049,0.0222058,0.0222117,0.0222073,0.022202,0.0222071,0.0222139,0.0222174,0.0222135,0.0222187,0.0222173,0.0222145,0.0222097,0.00641286,0.0936309,0.0177748,0.0104251,0.0103957,0.0103956,0.0103953,0.0103972,0.0103952,0.0103956,0.0103961,0.0103952,0.0103912,0.0103917,0.0103911,0.0103903,0.0103948,0.0103879,0.0103909,0.0103918,0.0103928,0.0103958,0.0103927,0.0103915,0.0103929,0.010394,0.0103901,0.0103886,0.0103926,0.0103925,0.0103907,0.0103889,0.0103915,0.0103905,0.0103937,0.0103953,0.0103934,0.0103927,0.0103915,0.0103879,0.010388,0.0103899,0.0103901,0.0103954,0.0103927,0.0103934,0.0103932,0.0103941,0.0103933,0.0103874,0.0103905,0.0104049,0.0232227,0.022038,0.0219262,0.0220364,0.0220466,0.0103952,0.0103654,0.0103624,0.0103679,0.0103674,0.0103661,0.0103663,0.0103652,0.0103646,0.0103599,0.0103634,0.0103638,0.0103641,0.0103668,0.0103666,0.0103656,0.0103686,0.0103645,0.0103635,0.0103635,0.0103642,0.0103671,0.0103647,0.0103643,0.0103653,0.0103619,0.010363,0.0103645,0.0103659,0.010363,0.0103629,0.0103618,0.0103659,0.0103668,0.0103644,0.0103621,0.0103632,0.0103631,0.0103639,0.0103598,0.0103589,0.0103618,0.0103664,0.0103649,0.0103679,0.0103633,0.0103655,0.0103179,0.00883582,0.0199862,0.0197745,0.0138251,0.0138181,0.0137382,0.0281962,0.0119731,0.0146934,0.00542294,0.0103455,0.0103428,0.0103405,0.0103394,0.0103441,0.0103473,0.0103461,0.0103478,0.0103444,0.0103435,0.0103372,0.0103324,0.010336,0.0103331,0.0103337,0.0103327,0.0103294,0.0103314,0.010332,0.0103322,0.0103311,0.0103271,0.0103265,0.0103275,0.0103263,0.0103252,0.0103211,0.0103238,0.0103239,0.0103216,0.0103192,0.0103208,0.0103224,0.01032,0.0103258,0.0103214,0.0103201,0.0103203,0.0103199,0.0103187,0.0103179,0.0103168,0.0103226,0.010322,0.0103235,0.0103212,0.0103209,0.0103169,0.0103195,0.0103177,0.0103147,0.0103211,0.0103193,0.0103191,0.0103193,0.0103207,0.0103159,0.0103165,0.0103206,0.0103229,0.0103297,0.0103274,0.0103218,0.0103224,0.0103199,0.0103193,0.010317,0.0103168,0.0102871,0.0102493,0.0102486,0.0102475,0.0102476,0.0102495,0.0102487,0.0102473,0.010249,0.0102445,0.010244,0.0102459,0.0102398,0.0102384,0.0102393,0.010238,0.0102398,0.0102426,0.010243,0.0102379,0.0102394,0.0102391,0.0102379,0.0102409,0.0184731,0.0184751,0.018473,0.0184734,0.0184725,0.0162004,0.0262225,0.0327883,0.0206821,0.0178054,0.0178129,0.0178056,0.0178053,0.0207913,0.0184978,0.00951688,0.023793,0.0233025,0.0206298,0.0238738,0.010418,0.0103903,0.0103886,0.0103877,0.0103884,0.0103885,0.0103907,0.0103883,0.0103874,0.0103876,0.0103863,0.010385,0.0103856,0.0103835,0.0103828,0.0103836,0.0103864,0.0103882,0.0103889,0.0103865,0.0103869,0.0103891,0.0103861,0.0103882,0.0103842,0.0103858,0.0103883,0.0103847,0.0103855,0.0103845,0.0103816,0.0103875,0.0103878,0.0103857,0.01038,0.0103815,0.0103813,0.010386,0.0103865,0.0103867,0.0103821,0.0103818,0.0103822,0.0103823,0.0103871,0.0103877,0.021763,0.0103908,0.0103643,0.0103611,0.0103631,0.0103623,0.0103607,0.0103615,0.0103611,0.0103608,0.0103589,0.0103597,0.0103592,0.0103591,0.0103644,0.0103675,0.0103639,0.0103673,0.0103675,0.0103652,0.0103591,0.0103647,0.0103675,0.0103666,0.0103644,0.0103667,0.0103642,0.0103634,0.0103628,0.0103652,0.0103639,0.0103649,0.0103631,0.0103584,0.0103636,0.0103644,0.0103632,0.0103637,0.0103593,0.0103628,0.0103615,0.010359,0.0103622,0.0103581,0.0103625,0.0103581,0.0103633,0.0103645,0.0103655,0.00639361,0.0144715,0.0132608,0.0132593,0.0132675,0.0133192,0.0189414,0.0112596,0.0112552,0.0111944,0.0114974,0.0115042,0.0115293,0.0152705,0.0241357,0.00308209,0.00271011,0.0178432,0.0204114,0.0204152,0.0204207,0.0203273", "perf/train_forward": "0.626146,0.519625,0.51865,0.517984,0.517363,0.517154,0.516948,0.516696,0.516683,0.51658,0.516449,0.516451,1.24103,0.901151,0.740395,0.0678762,1.27723,0.902149,0.332329,0.74445,0.512975,0.511932,0.511718,0.511391,0.51107,0.510734,0.510484,0.510464,0.510361,0.510372,0.510308,0.51026,0.509902,0.509836,0.509774,0.509768,0.509713,0.509746,0.509641,0.509643,0.509662,0.50961,0.509576,0.509563,0.509608,0.50992,0.915192,0.86075,0.63604,0.630359,0.62891,0.626705,0.626052,0.625725,0.625777,0.625735,0.625713,0.62566,0.625704,0.625615,0.625708,0.625595,0.625685,0.625596,0.625596,0.625602,0.62568,0.625665,0.625655,0.625554,0.625522,0.625526,0.625521,0.625648,0.62578,0.625574,0.62569,0.625645,0.625632,0.625705,0.625533,0.625461,0.625461,0.625471,0.625467,0.625487,0.625727,0.625858,0.625859,0.625858,0.62573,0.625613,0.625605,0.625604,0.625425,0.627558,0.34816,0.626465,0.623398,0.620062,0.619669,0.618919,0.618885,0.618897,0.618872,0.6189,0.618852,0.618902,0.618676,0.621377,0.587494,0.538026,0.522089,0.908322,0.908184,0.908214,0.908285,0.908169,0.908248,0.907725,0.907691,0.90774,0.907296,0.907368,0.907093,0.9074,0.907444,0.907399,0.90814,0.908094,0.908007,0.907938,0.907913,0.907844,0.907874,0.104708,4.21799,0.323821,0.635954,0.63027,0.628858,0.626583,0.625945,0.625703,0.625634,0.625586,0.625601,0.625579,0.625518,0.625506,0.625549,0.625557,0.625581,0.625516,0.625483,0.625506,0.625596,0.625632,0.625494,0.625461,0.625433,0.625421,0.625457,0.625531,0.625624,0.625541,0.625556,0.625577,0.625573,0.625586,0.6255,0.62535,0.625368,0.625416,0.625439,0.62545,0.625626,0.625778,0.625779,0.625766,0.625651,0.625534,0.625493,0.625447,0.625332,0.625285,0.626098,0.81484,0.774076,0.77034,0.773776,0.77388,0.636005,0.630331,0.628914,0.62664,0.625983,0.62574,0.625715,0.625661,0.625689,0.625641,0.625587,0.625574,0.62565,0.625602,0.625605,0.625568,0.625555,0.625582,0.625613,0.625684,0.625566,0.625504,0.625482,0.625451,0.625499,0.625641,0.625742,0.625576,0.62555,0.625659,0.625643,0.62566,0.625585,0.625422,0.625376,0.625472,0.625448,0.62549,0.62564,0.625827,0.625847,0.625838,0.625699,0.625595,0.62554,0.625512,0.625401,0.624542,0.483979,0.684042,0.683385,0.431464,0.431409,0.43126,1.30373,0.710811,0.804489,0.335285,0.520578,0.51976,0.519225,0.518786,0.51868,0.518482,0.518383,0.518394,0.518363,0.518356,0.518273,0.518138,0.517938,0.517876,0.517806,0.517746,0.517775,0.517746,0.517715,0.517715,0.517672,0.634321,0.630333,0.628933,0.626674,0.62599,0.625742,0.625683,0.625636,0.625666,0.625654,0.625604,0.625587,0.625614,0.625638,0.625655,0.625619,0.625548,0.625599,0.625661,0.62572,0.625602,0.625527,0.625486,0.625482,0.625555,0.625631,0.625673,0.625559,0.62555,0.625667,0.625685,0.625578,0.625408,0.625439,0.625487,0.625478,0.625526,0.625637,0.625844,0.62585,0.625845,0.625697,0.625634,0.625573,0.625507,0.625394,0.6254,0.625033,0.512408,0.511436,0.510711,0.510718,0.510409,0.510293,0.510368,0.510302,0.510199,0.51013,0.510066,0.50951,0.509448,0.509487,0.509458,0.509503,0.509437,0.509459,0.509427,0.509417,0.509433,0.509414,0.509432,0.798797,0.79494,0.793235,0.792288,0.791286,0.485302,1.57483,1.9244,1.43043,1.2329,1.23237,1.23302,1.22806,1.15096,1.02456,0.613883,0.872037,0.846853,0.751811,1.70442,0.635983,0.630283,0.628864,0.626607,0.625966,0.625706,0.625654,0.625606,0.625612,0.625593,0.625541,0.625518,0.625571,0.625565,0.625598,0.625538,0.625497,0.625522,0.625617,0.625645,0.625516,0.625482,0.625454,0.625435,0.625468,0.62554,0.625631,0.625553,0.625583,0.625591,0.625589,0.6256,0.625494,0.625361,0.625377,0.625422,0.625455,0.625463,0.625643,0.625795,0.625802,0.625793,0.625682,0.625556,0.625473,0.62535,0.586932,0.636004,0.630315,0.628913,0.626641,0.625994,0.625747,0.625683,0.625636,0.625644,0.625631,0.625572,0.625563,0.625603,0.625605,0.625622,0.62557,0.625533,0.625559,0.625654,0.625684,0.625549,0.625512,0.625489,0.62547,0.62551,0.62558,0.625669,0.625586,0.625596,0.625627,0.625624,0.625639,0.625552,0.625386,0.625404,0.625459,0.625484,0.625499,0.625671,0.625828,0.625839,0.625813,0.625693,0.625592,0.625542,0.625493,0.625381,0.625329,0.109179,0.897134,0.822508,0.822732,0.822982,0.821232,0.502975,0.682066,0.682739,0.68011,0.693582,0.694119,0.697227,0.599202,0.57498,0.0522274,0.0447654,0.990802,0.901367,0.901409,0.9013,0.901489", "perf/train": "0.63672,0.529974,0.528998,0.528326,0.527707,0.527497,0.527296,0.527038,0.52703,0.526924,0.526792,0.526794,1.27242,0.923574,0.758784,0.0718433,1.30514,0.91656,0.350306,0.75457,0.523207,0.522167,0.521954,0.521629,0.521303,0.520966,0.52072,0.520696,0.520593,0.520604,0.520539,0.520491,0.520128,0.52006,0.519998,0.519992,0.519937,0.519976,0.519875,0.51987,0.519887,0.519832,0.519799,0.519788,0.519832,0.520124,0.930258,0.874894,0.646375,0.640665,0.639218,0.637009,0.636356,0.636026,0.63608,0.636036,0.636013,0.635959,0.636001,0.635916,0.636009,0.635897,0.635988,0.635898,0.635899,0.635905,0.635984,0.635965,0.635956,0.635855,0.635823,0.635825,0.635824,0.635951,0.636082,0.635873,0.635992,0.635947,0.635932,0.636003,0.635831,0.635761,0.635758,0.635771,0.635766,0.635786,0.636031,0.636162,0.636164,0.63616,0.636033,0.635912,0.635907,0.635902,0.635724,0.637829,0.369259,0.636757,0.633691,0.630353,0.629963,0.629207,0.629172,0.629184,0.629159,0.629189,0.629135,0.629187,0.629008,0.638417,0.603602,0.554851,0.544654,0.930522,0.930386,0.93042,0.930487,0.930374,0.930452,0.92993,0.929895,0.929949,0.929501,0.929574,0.929304,0.929607,0.929646,0.929606,0.930354,0.930312,0.93022,0.930157,0.93013,0.930059,0.930084,0.111121,4.31162,0.341596,0.646379,0.640666,0.639253,0.636979,0.636342,0.636099,0.636029,0.635982,0.635996,0.63597,0.63591,0.635897,0.635939,0.635951,0.635969,0.635907,0.635874,0.635899,0.635992,0.636024,0.635886,0.635853,0.635827,0.635811,0.635845,0.635924,0.636016,0.635932,0.635945,0.635968,0.635964,0.63598,0.635896,0.635743,0.635761,0.635807,0.635827,0.635838,0.636015,0.636168,0.636175,0.636158,0.636045,0.635927,0.635887,0.63584,0.635719,0.635675,0.636503,0.838063,0.796115,0.792266,0.795812,0.795926,0.6464,0.640696,0.639277,0.637008,0.636351,0.636106,0.636081,0.636026,0.636053,0.636001,0.635951,0.635938,0.636014,0.635969,0.635972,0.635933,0.635923,0.635947,0.635976,0.636048,0.635931,0.635871,0.635847,0.635815,0.635864,0.636003,0.636105,0.63594,0.635916,0.636022,0.636006,0.636021,0.635951,0.635788,0.63574,0.635834,0.635811,0.635853,0.636004,0.636187,0.636206,0.6362,0.636066,0.63596,0.635908,0.635875,0.635767,0.63486,0.492815,0.704028,0.703159,0.445289,0.445227,0.444998,1.33193,0.722785,0.819182,0.340708,0.530924,0.530103,0.529566,0.529126,0.529024,0.52883,0.528729,0.528742,0.528707,0.5287,0.528611,0.528471,0.528274,0.52821,0.52814,0.528078,0.528104,0.528078,0.528047,0.528047,0.528003,0.644648,0.640659,0.639261,0.637,0.636315,0.636063,0.636006,0.63596,0.635988,0.635973,0.635925,0.635909,0.635934,0.635964,0.635977,0.63594,0.635869,0.635919,0.635979,0.636037,0.635918,0.63585,0.635808,0.635806,0.635876,0.635952,0.63599,0.635879,0.635867,0.635982,0.636006,0.635897,0.635727,0.635759,0.635807,0.635794,0.635842,0.635958,0.636167,0.63618,0.636172,0.636019,0.635956,0.635893,0.635826,0.635711,0.635717,0.63532,0.522657,0.521685,0.520958,0.520965,0.520659,0.520542,0.520615,0.520551,0.520444,0.520374,0.520312,0.51975,0.519686,0.519726,0.519696,0.519742,0.51968,0.519702,0.519665,0.519657,0.519672,0.519651,0.519673,0.81727,0.813415,0.811708,0.810762,0.809759,0.501502,1.60105,1.95719,1.45111,1.25071,1.25019,1.25083,1.24587,1.17176,1.04305,0.6234,0.89583,0.870156,0.772441,1.72829,0.646401,0.640673,0.639252,0.636995,0.636354,0.636094,0.636045,0.635995,0.636,0.635981,0.635927,0.635903,0.635957,0.635949,0.635981,0.635922,0.635884,0.63591,0.636005,0.636031,0.635903,0.635871,0.63584,0.635823,0.635853,0.635926,0.636019,0.635938,0.635968,0.635976,0.63597,0.635988,0.635882,0.635746,0.635757,0.635804,0.635836,0.635849,0.636029,0.636182,0.636184,0.636175,0.636064,0.635938,0.63586,0.635738,0.608695,0.646395,0.640679,0.639274,0.637004,0.636356,0.636108,0.636045,0.635997,0.636005,0.63599,0.635932,0.635922,0.635962,0.63597,0.63599,0.635934,0.6359,0.635927,0.636019,0.636044,0.635914,0.63588,0.635856,0.635835,0.635877,0.635945,0.636032,0.635949,0.635962,0.63599,0.635989,0.636002,0.635911,0.63575,0.635768,0.635823,0.635848,0.635859,0.636033,0.63619,0.636198,0.636176,0.636051,0.635954,0.6359,0.635857,0.635746,0.635695,0.115573,0.911605,0.835769,0.835991,0.83625,0.834551,0.521917,0.693326,0.693994,0.691304,0.705079,0.705623,0.708757,0.614472,0.599116,0.0553095,0.0474755,1.00865,0.921779,0.921825,0.92172,0.921816", "util/gpu_percent": "94.3704,86.6144,86.7368,86.6272,86.9807,86.6697,86.7394,86.6594,86.914,86.6761,86.6496,86.6902,99.8523,92.8229,94.3182,65.375,99,93.125,66.5,94.3702,86.8663,86.7561,86.671,87.027,87.518,87.2003,87.5334,87.0642,86.8046,86.5456,86.937,86.9191,86.8947,86.8779,86.9589,86.9846,86.9499,86.8805,87.1836,86.59,86.9345,87.2609,87.0141,86.8419,86.8922,100,94.8671,95.343,87.0751,87.2389,86.4855,86.0101,86.0932,86.0679,86.0471,85.9061,85.9938,86.0002,85.9582,85.9599,86.0058,85.9801,85.9088,85.8312,85.9321,85.7613,85.8497,85.9918,85.9323,87.3784,87.2643,87.7947,87.7827,87.7188,87.8346,87.4351,87.1261,87.3078,86.704,86.2706,85.9928,86.4233,86.7484,87.6855,86.3995,85.9498,85.7962,85.8876,85.9803,86.1954,86.4216,87.3164,86.8727,86.5253,87.0173,60,79.75,85.3534,84.6373,85.7144,86.0687,84.0558,84.0262,84.0635,84.6754,84.4214,83.9769,83.998,100,90.5957,90.5957,89.0278,87.7586,92.7059,92.9512,92.9363,93.0931,92.8488,92.7843,92.6324,92.5805,93.3186,93.2696,92.5512,93.0588,92.8529,92.8039,92.6618,92.9512,92.8284,92.7794,92.2829,92.5686,92.3333,93.2549,80.625,100,64.5862,87.9599,86.3998,85.7032,85.758,85.7496,85.8401,85.9522,85.8154,85.878,85.9222,86.7733,87.5239,86.0451,85.9791,85.8269,85.8591,85.7515,85.6816,85.7705,85.8706,85.7309,85.7328,85.7318,86.266,87.4744,87.8283,87.0094,86.8487,85.7697,86.0046,85.7815,86.583,86.6627,86.5654,87.007,85.528,85.5275,87.1601,86.128,86.0792,86.2348,86.1157,86.3224,85.807,85.9234,87.6137,86.8305,85.6838,63,91.3529,90.5294,91.5882,90.5347,68,86.1738,86.1599,86.0886,86.0754,86.1508,86.4447,87.6994,87.5448,87.3246,85.8086,86.0122,86.0149,86.5597,86.9505,86.7258,86.0502,85.7085,85.6773,85.6992,85.7777,85.9597,87.2507,87.2043,87.2351,87.1433,87.1573,87.2569,87.6411,87.5385,87.4401,87.3496,87.6641,87.6752,87.6442,87.8574,88.0178,86.1782,85.7825,85.5424,85.5018,86.0315,86.6192,88.0941,85.6742,85.6725,85.6586,85.9366,100,94.6311,100,100,88.9845,89.1938,63,99.8,94.398,100,81.625,86.8254,87.0051,87.0513,86.9692,87.0321,87.0848,86.973,86.9627,87.0257,87.0321,86.7163,86.7009,87.0167,86.8883,86.8201,86.8151,86.9692,86.715,86.8985,86.8126,86.8342,86.0194,86.1455,86.0149,86.1013,86.0699,86.1637,86.2545,86.1059,86.0483,86.086,86.1496,86.1287,86.0089,86.6341,86.7357,87.2053,87.431,87.3906,87.6046,87.2103,87.4567,87.3652,87.3136,86.1306,86.1212,85.9265,85.9981,86.0305,85.9923,87.3983,87.8557,87.684,87.1424,86.7047,85.6615,85.4439,86.9064,86.4555,85.934,87.2749,85.8216,85.7854,86.8343,87.7652,86.3765,85.7426,85.8283,61,86.6714,86.6542,86.5802,86.5064,86.896,87.383,86.9487,86.4859,86.6752,87.0913,87.0988,86.7535,86.545,85.9512,85.9383,86.0026,86.5013,86.6958,86.6208,86.7009,86.8689,86.8999,85.3209,88.0904,87.8794,87.7713,87.9415,87.844,87.7727,100,100,100,100,100,100,100,99.4886,96.2989,76.125,90.9697,89.9529,89.5714,100,87.6397,87.51,86.7347,86.6727,86.7481,86.7589,87.3023,87.2838,87.1697,86.2884,86.1606,85.8031,85.7421,85.8845,85.8029,85.7858,85.6471,85.7527,85.7868,85.8053,85.709,85.8329,85.5719,85.6187,85.8499,85.6744,85.7073,85.6992,85.7457,85.6927,85.7236,85.4543,85.4672,85.5088,85.5678,85.5676,85.4218,86.5412,87.6653,87.8807,87.9116,86.3241,85.5116,85.5712,86.0255,86.2367,90.7013,86.2559,86.2828,87.4247,87.3325,87.2557,87.5806,86.848,85.9753,86.0603,85.9133,85.909,86.0836,85.8098,87.4432,86.3947,86.0118,87.072,87.9652,87.8581,87.9196,87.714,87.7923,87.5899,87.0415,86.6012,85.9774,85.9193,85.9522,86.6888,86.1962,86.2881,86.383,86.2199,86.1354,86.223,86.2154,86.2226,86.2074,86.1683,86.1076,86.0475,86.1261,86.5724,87.6127,86.1205,87.0526,86.0831,85.9042,72.25,97.5124,89.9752,100,90.8833,100,87.9364,94.5252,94.2806,100,94.3774,94.9177,100,92.1405,79.5263,70.325,67.9875,90,93.2045,94.5955,93.4773,100", "util/gpu_mem": "30.3495,53.6189,53.6189,53.6189,53.6189,53.6189,53.6189,53.6189,53.6189,53.6189,53.6189,53.6189,26.9462,27.3451,27.3451,42.6602,34.0216,30.3495,10.8983,34.6974,43.849,43.849,43.849,43.849,43.849,43.849,43.849,43.849,43.849,43.849,43.849,43.849,43.849,43.849,43.849,43.849,43.849,43.849,43.849,43.849,43.849,43.849,43.849,43.849,43.849,43.849,21.8737,21.8737,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,35.7558,44.5818,44.5818,44.5818,44.5818,44.5818,44.5818,44.5818,44.5818,44.5818,44.5818,44.5818,44.5818,27.3451,27.3451,33.183,10.5401,60.8169,60.8169,60.8169,60.8169,60.8169,60.8169,60.8169,60.8169,60.8169,60.8169,60.8169,60.8169,60.8169,60.8169,60.8169,60.8169,60.8169,60.8169,60.8169,60.8169,60.8169,60.8169,41.6099,29.3481,10.8983,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,25.2282,25.2282,25.2282,25.2282,25.2282,52.5388,52.5388,52.5388,52.5388,52.5388,52.5388,52.5388,52.5388,52.5388,52.5388,52.5388,52.5388,52.5388,52.5388,52.5388,52.5388,52.5388,52.5388,52.5388,52.5388,52.5388,52.5388,52.5388,52.5388,52.5388,52.5388,52.5388,52.5388,52.5388,52.5388,52.5388,52.5388,52.5388,52.5388,52.5388,52.5388,52.5388,52.5388,52.5388,52.5388,52.5388,52.5388,52.5388,52.5388,52.5388,52.5388,52.5388,52.5388,30.3495,25.2282,25.2282,33.183,33.183,33.183,34.0216,47.293,25.9854,25.9854,53.6189,53.6189,53.6189,53.6189,53.6189,53.6189,53.6189,53.6189,53.6189,53.6189,53.6128,54.0098,54.0178,54.0178,54.0178,54.0178,54.0178,54.0178,54.0178,54.0178,54.0178,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,43.849,43.849,43.849,43.849,43.849,43.849,43.849,43.849,43.849,43.849,43.849,43.849,43.849,43.849,43.849,43.849,43.849,43.849,43.849,43.849,43.849,43.849,43.849,30.488,30.488,30.488,30.488,30.488,45.6565,38.5078,30.032,42.9859,42.9859,42.9859,42.9859,42.9859,38.5078,38.5078,15.8812,26.9462,33.183,33.183,42.9859,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,22.7531,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,44.6143,26.6694,30.3495,30.3495,30.3495,30.3495,30.3495,22.7531,30.3495,30.3495,30.3495,30.3495,30.3495,30.3495,25.9936,12.9012,26.6856,26.6856,55.4513,34.0216,34.0216,34.0216,34.0216", "util/vram_used_gb": "6.81921,12.4011,12.4011,12.4011,12.4011,12.4011,12.4011,12.4011,12.4011,12.4011,12.4011,12.4011,6.00281,6.09851,6.09851,9.77234,7.70007,6.81921,2.1532,7.86218,10.0575,10.0575,10.0575,10.0575,10.0575,10.0575,10.0575,10.0575,10.0575,10.0575,10.0575,10.0575,10.0575,10.0575,10.0575,10.0575,10.0575,10.0575,10.0575,10.0575,10.0575,10.0575,10.0575,10.0575,10.0575,10.0575,4.78601,4.78601,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,8.11609,10.2333,10.2333,10.2333,10.2333,10.2333,10.2333,10.2333,10.2333,10.2333,10.2333,10.2333,10.2333,6.09851,6.09851,7.4989,2.06726,14.1278,14.1278,14.1278,14.1278,14.1278,14.1278,14.1278,14.1278,14.1278,14.1278,14.1278,14.1278,14.1278,14.1278,14.1278,14.1278,14.1278,14.1278,14.1278,14.1278,14.1278,14.1278,9.52039,6.57898,2.1532,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,5.5907,5.5907,5.5907,5.5907,5.5907,12.142,12.142,12.142,12.142,12.142,12.142,12.142,12.142,12.142,12.142,12.142,12.142,12.142,12.142,12.142,12.142,12.142,12.142,12.142,12.142,12.142,12.142,12.142,12.142,12.142,12.142,12.142,12.142,12.142,12.142,12.142,12.142,12.142,12.142,12.142,12.142,12.142,12.142,12.142,12.142,12.142,12.142,12.142,12.142,12.142,12.142,12.142,12.142,6.81921,5.5907,5.5907,7.4989,7.4989,7.4989,7.70007,10.8837,5.77234,5.77234,12.4011,12.4011,12.4011,12.4011,12.4011,12.4011,12.4011,12.4011,12.4011,12.4011,12.3997,12.4949,12.4968,12.4968,12.4968,12.4968,12.4968,12.4968,12.4968,12.4968,12.4968,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.0575,10.0575,10.0575,10.0575,10.0575,10.0575,10.0575,10.0575,10.0575,10.0575,10.0575,10.0575,10.0575,10.0575,10.0575,10.0575,10.0575,10.0575,10.0575,10.0575,10.0575,10.0575,10.0575,6.85242,6.85242,6.85242,6.85242,6.85242,10.4911,8.77625,6.74304,9.85046,9.85046,9.85046,9.85046,9.85046,8.77625,8.77625,3.34851,6.00281,7.4989,7.4989,9.85046,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,4.99695,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,10.2411,5.9364,6.81921,6.81921,6.81921,6.81921,6.81921,4.99695,6.81921,6.81921,6.81921,6.81921,6.81921,6.81921,5.77429,2.63367,5.94031,5.94031,12.8407,7.70007,7.70007,7.70007,7.70007", "util/vram_total_gb": "23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272", "util/cpu_mem_gb": "1.41653,1.14552,1.14718,1.14881,1.15092,1.15284,1.15478,1.1568,1.15807,1.16005,1.162,1.16416,1.45726,1.42285,1.42319,1.19114,1.45183,1.4151,1.39324,1.42204,1.22586,1.22795,1.22984,1.23127,1.23309,1.23542,1.2375,1.23955,1.24176,1.24393,1.2461,1.24822,1.28928,1.29185,1.29422,1.29685,1.29907,1.30131,1.30401,1.30646,1.30819,1.31014,1.31261,1.31428,1.31676,1.32107,1.41614,1.41627,1.40067,1.41183,1.4231,1.43428,1.44544,1.45563,1.4687,1.47993,1.49124,1.50274,1.51498,1.52696,1.53848,1.54976,1.56101,1.57229,1.58374,1.59481,1.606,1.61792,1.62915,1.64031,1.65206,1.6644,1.67654,1.68779,1.6993,1.71071,1.72199,1.73264,1.74433,1.75633,1.76776,1.7787,1.79072,1.80245,1.81429,1.8262,1.83815,1.84961,1.86104,1.87242,1.88394,1.89585,1.90767,1.91895,1.93065,1.95941,1.2095,1.37658,1.39396,1.41119,1.4283,2.10875,2.12707,2.14532,2.16327,2.18194,2.20031,2.21776,2.24524,1.42265,1.42271,1.45489,1.39753,1.3179,1.31828,1.31874,1.31896,1.31986,1.32032,1.32077,1.32141,1.3217,1.322,1.32222,1.32323,1.32374,1.32597,1.3261,1.32617,1.32658,1.32658,1.32699,1.32707,1.32707,1.32764,1.18164,1.22252,1.39156,1.40053,1.41187,1.42286,1.4341,1.4448,1.45573,1.46655,1.4782,1.48993,1.50201,1.51357,1.52494,1.53656,1.54805,1.55938,1.57096,1.58281,1.59493,1.60616,1.61787,1.62962,1.64148,1.6529,1.66359,1.67509,1.68589,1.69752,1.70884,1.72073,1.73169,1.74358,1.75555,1.76689,1.77847,1.79026,1.80176,1.81344,1.82549,1.83701,1.8483,1.85981,1.87105,1.8833,1.89499,1.90637,1.91798,1.92888,1.93999,1.95762,1.41673,1.41713,1.41713,1.41713,1.41713,1.32286,1.33454,1.34532,1.35523,1.36666,1.37789,1.38906,1.4003,1.41144,1.4228,1.43464,1.44535,1.45704,1.46832,1.47993,1.4908,1.50231,1.51413,1.52541,1.53733,1.54945,1.56039,1.57178,1.5829,1.59433,1.60654,1.61859,1.62991,1.64175,1.6527,1.66416,1.6761,1.68808,1.69901,1.70968,1.72158,1.73386,1.74538,1.75753,1.76834,1.77991,1.79171,1.80352,1.81488,1.82579,1.83785,1.86088,1.8779,1.41549,1.41762,1.41762,1.45812,1.45812,1.45812,1.45067,1.41438,1.21895,1.21999,1.14525,1.14689,1.14902,1.15145,1.15363,1.15554,1.15741,1.1596,1.16207,1.16391,1.16641,1.20833,1.2102,1.21202,1.21415,1.21624,1.21851,1.22066,1.22275,1.22459,1.2276,1.40027,1.41212,1.42299,1.43452,1.44506,1.45661,1.46895,1.48113,1.49233,1.50472,1.51658,1.52756,1.53897,1.55058,1.56208,1.57349,1.5851,1.59661,1.60883,1.62088,1.63171,1.64307,1.65428,1.66583,1.67769,1.68874,1.70065,1.71215,1.72431,1.74762,1.75927,1.77098,1.78156,1.79345,1.80551,1.81683,1.82775,1.83984,1.85178,1.86323,1.87446,1.88586,1.89767,1.9087,1.91943,1.93114,1.94259,1.96154,1.22743,1.22952,1.23176,1.23411,1.23631,1.23842,1.2406,1.24196,1.24375,1.24563,1.2473,1.28926,1.29151,1.29362,1.29584,1.29797,1.3001,1.30231,1.30435,1.30682,1.30898,1.31099,1.31523,1.21549,1.21617,1.21686,1.21775,1.21933,1.45659,1.4579,1.45512,1.46217,1.46378,1.46378,1.46378,1.46378,1.45612,1.45835,1.17438,1.45395,1.45674,1.4581,1.46209,1.40165,1.4136,1.4247,1.43598,1.44701,1.45781,1.46836,1.47963,1.49112,1.50199,1.51351,1.52532,1.53654,1.54794,1.55922,1.57098,1.58267,1.59408,1.60575,1.61789,1.62893,1.64103,1.65237,1.66473,1.67644,1.6879,1.69966,1.71111,1.72209,1.73363,1.74557,1.75694,1.76841,1.7793,1.79056,1.80236,1.81465,1.82661,1.83711,1.84869,1.86032,1.87173,1.8834,1.89507,1.91823,1.93003,1.41602,1.40072,1.41192,1.42238,1.43332,1.44492,1.45717,1.46899,1.47971,1.49081,1.5028,1.5146,1.52615,1.53737,1.54846,1.56008,1.57146,1.58287,1.59437,1.60592,1.61732,1.62941,1.64079,1.65267,1.66424,1.67546,1.68649,1.69796,1.70937,1.72052,1.73189,1.74503,1.75657,1.76729,1.77905,1.78993,1.80119,1.81272,1.82407,1.83562,1.84672,1.85812,1.86972,1.88124,1.89289,1.90442,1.91571,1.92714,1.93866,1.17733,1.41451,1.41549,1.4155,1.4155,1.4155,1.41671,1.41705,1.41705,1.41705,1.41556,1.41556,1.41556,1.41038,1.39763,1.17072,1.17118,1.4571,1.45134,1.45179,1.45179,1.45179", "wandb": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "rank": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,0,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "world_size": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,1,6,6,6,6,6,6,6,6,6,6,6,6,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,1,1,1,1,1,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,1,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "gpu_id": "3,0,0,0,0,0,0,0,0,0,0,0,2,3,3,3,3,2,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,3,3,1,5,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,1,4,4,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,1,1,1,2,1,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3,3,3,3,3,3,3,3,3,2,4,3,3,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,1,1,1,1,1,1,2,3,3,3,1,1,1,1,3,4,4,2,2,2,2,2", "profile": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "checkpoint_interval": "200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200", "eval_episodes": "10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000", "cudagraphs": "10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10", "seed": "73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73", "vec/total_agents": "4096,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,4096,4096,4096,8192,4096,1024,4096,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,4096,4096,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,4096,4096,8192,2048,16384,16384,16384,16384,16384,16384,16384,16384,16384,16384,16384,16384,16384,16384,16384,16384,16384,16384,16384,16384,16384,16384,4096,8192,1024,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,4096,4096,4096,4096,4096,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,4096,4096,4096,8192,8192,8192,8192,4096,4096,4096,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,2048,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,4096,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,2048,4096,4096,8192,8192,8192,8192,8192", "vec/num_buffers": "4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4.2718,4.2718,4.2718,4.2718,4.2718,4.2718,4.2718,4.2718,4.2718,4.2718,4.2718,4.2718,4.2718,4.2718,4.2718,4.2718,4.2718,4.2718,4.2718,4.2718,4.2718,4.2718,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,6.64425,6.64425,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4", "vec/num_threads": "2,0,0,0,0,0,0,0,0,0,0,0,2,2,2,0,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,0,4,4,4,4,4,4,4,4,4,4,4,4,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,2,2,2,2,2,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,0,2,2,2,2,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,2,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,2,2,2,2,2", "env/num_agents": "1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024", "env/width": "512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512", "env/height": "512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512", "env/num_enemies": "2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048", "env/num_resources": "2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048", "env/num_weapons": "1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024", "env/num_gems": "512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512", "env/tiers": "5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5", "env/levels": "40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40", "env/teleportitis_prob": "0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001,0.001", "env/enemy_respawn_ticks": "2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2", "env/item_respawn_ticks": "100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100", "env/x_window": "7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7", "env/y_window": "5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5", "env/reward_combat_level": "1,1,1,1,1,1,1,1,1,1,1,1,0.899204,0.917005,0.917005,0.964298,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0.428575,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0.340839,0.279908,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0.926518,0.926518,0.926518,1,1,0.268975,0.268975,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0.990616,1,1,1,1,1,1,1,0.93663,0.93663,0.949194,0.963757,0.920054,0.920054,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0.862822,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0.750843,1,1,1,1,1,0.905859,1,1,1,1,1,1,1,1,1,1,1,0.972491,0.972491,0.972491,0.972491", "env/reward_prof_level": "1,1,1,1,1,1,1,1,1,1,1,1,0.963323,0.945101,0.945101,1,0.959276,0.895991,0,0.989881,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0.87087,0.87087,0.87087,0.87087,0.87087,0.87087,0.87087,0.87087,0.87087,0.87087,0.87087,0.87087,0.87087,0.87087,0.87087,0.87087,0.87087,0.87087,0.87087,0.87087,0.87087,0.87087,1,0.819419,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0.904269,0.904269,1,1,1,0.947175,1,0.305859,0.305859,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0.914274,1,1,1,1,1,1,1,0.985106,0.985106,0.375726,1,1,1,0.917053,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0.854647,0.779491,0.779491,0.779491,0.779491,0.779491,1,0.947893,0.947893,0.947893,0.881833,0.881833,0.881833,1,0,0.94007,0.94007,1,1,1,1,1", "env/reward_item_level": "1,1,1,1,1,1,1,1,1,1,1,1,0.772044,0.868116,0.868116,0.811699,0.91048,1,0.483759,0.699406,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0.891442,0.891442,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0.933708,1,1,1,1,1,1,1,1,1,1,1,1,0.65682,0.65682,0.471392,0.486119,0.870489,0.870489,0.870489,0.870489,0.870489,0.870489,0.870489,0.870489,0.870489,0.870489,0.870489,0.870489,0.870489,0.870489,0.870489,0.870489,0.870489,0.870489,0.870489,0.870489,0.870489,0.870489,0.945732,0.388713,0.370189,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0.798197,0.798197,0.798197,0.798197,0.798197,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0.873351,0.640836,0.640836,0.697896,0.697896,0.697896,0.345092,1,0.691123,0.691123,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0.922318,0.664325,0.934062,0.919296,0.919296,0.919296,0.919296,0.919296,0.936211,0.936211,0.116075,0.630212,0.839327,0.839327,0.707489,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0.916355,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0.985342,0.799772,0.799772,0.799772,0.799772,0.799772,0.878488,0.889925,0.889925,0.889925,1,1,1,0.491919,0.351976,1,1,0.795187,0.585103,0.585103,0.585103,0.585103", "env/reward_market": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "env/reward_death": "-0.00234773,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-0.63581,-0.132699,-0.132699,-1,-0.222526,-0.19,-0.128997,-0.179063,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-0.204109,-0.204109,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-0.896266,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-0.813471,-0.813471,-0.863254,-0.523758,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-0.415713,-0.132314,-0.396604,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-0.341527,-0.341527,-0.341527,-0.341527,-0.341527,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-0.408412,-0.120736,-0.120736,-0.66396,-0.66396,-0.66396,-1,-0.343532,-0.177571,-0.177571,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-0.440906,-0.426452,-0.327254,-0.368385,-0.368385,-0.368385,-0.368385,-0.368385,-0.463887,-0.463887,-0.271993,-0.86244,-0.500555,-0.500555,-0.440454,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-0.114666,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-0.937444,-0.260668,-0.260668,-0.260668,-0.260668,-0.260668,-0.214372,-0.242264,-0.242264,-0.242264,-0.392716,-0.392716,-0.392716,-0.659657,-0.343921,-1,-1,-0.407401,-0.958394,-0.958394,-0.958394,-0.958394", "policy/hidden_size": "1024,512,512,512,512,512,512,512,512,512,512,512,512,512,512,64,1024,1024,64,1024,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,1024,1024,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,128,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,32,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,64,128,64,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,1024,512,512,512,512,512,1024,1024,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,1024,1024,1024,1024,1024,1024,1024,1024,1024,32,512,512,512,1024,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,256,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,32,1024,1024,1024,1024,1024,256,1024,1024,1024,1024,1024,1024,1024,64,64,64,1024,1024,1024,1024,1024", "policy/num_layers": "2.03425,4,4,4,4,4,4,4,4,4,4,4,2.79077,3.27803,3.27803,5.01001,1.77464,2.68928,2.0826,3.20288,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,2.77787,2.77787,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,2.92345,4,4,4,4,4,4,4,4,4,4,4,4,3.00903,3.00903,2.87775,2.63673,4.36129,4.36129,4.36129,4.36129,4.36129,4.36129,4.36129,4.36129,4.36129,4.36129,4.36129,4.36129,4.36129,4.36129,4.36129,4.36129,4.36129,4.36129,4.36129,4.36129,4.36129,4.36129,3.52817,5.0706,2.9813,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,2.36039,2.36039,2.36039,2.36039,2.36039,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,2.43181,2.55486,2.55486,2.92511,2.92511,2.92511,1.75821,2.78276,5.11582,5.11582,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,2.512,2.512,2.512,2.512,2.512,2.99178,2.72063,2.20584,3.21904,3.21904,3.21904,3.21904,3.21904,2.98577,2.98577,4.13293,2.36673,2.68184,2.68184,3.80622,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,2.91038,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,2.82116,2.86045,2.86045,2.86045,2.86045,2.86045,2.81892,2.52419,2.52419,2.52419,2.0797,2.0797,2.0797,1.57442,3.31051,1.70036,1.70036,2.41234,1,1,1,1", "policy/expansion_factor": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "legacy/torch_deterministic": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "legacy/cpu_offload": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "legacy/compile": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "legacy/compile_fullgraph": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "train/gpus": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,1,6,6,6,6,6,6,6,6,6,6,6,6,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,1,1,1,1,1,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,1,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "train/seed": "42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42", "train/total_timesteps": "113.024,20000,20000,20000,20000,20000,20000,20000,20000,20000,20000,20000,183.049,197.849,197.849,5000,125.355,142.242,30,246.504,20000,20000,20000,20000,20000,20000,20000,20000,20000,20000,20000,20000,20000,20000,20000,20000,20000,20000,20000,20000,20000,20000,20000,20000,20000,20000,180.719,180.719,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,5000,166667,166667,166667,166667,166667,166667,166667,166667,166667,166667,166667,166667,196.898,196.898,149.881,30,10500.3,10500.3,10500.3,10500.3,10500.3,10500.3,10500.3,10500.3,10500.3,10500.3,10500.3,10500.3,10500.3,10500.3,10500.3,10500.3,10500.3,10500.3,10500.3,10500.3,10500.3,10500.3,5000,5000,36.8806,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,213.203,213.203,213.203,213.203,213.203,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,127.145,280.54,280.54,271.235,271.235,271.235,146.079,102.222,5870.82,5870.82,20000,20000,20000,20000,20000,20000,20000,20000,20000,20000,20000,20000,20000,20000,20000,20000,20000,20000,20000,20000,20000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,20000,20000,20000,20000,20000,20000,20000,20000,20000,20000,20000,20000,20000,20000,20000,20000,20000,20000,20000,20000,20000,20000,20000,14485.5,14485.5,14485.5,14485.5,14485.5,183.247,268.463,125.218,143.039,143.039,143.039,143.039,143.039,184.405,184.405,6797.55,136.885,177.117,177.117,111.392,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,160.633,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,107000,5000,126.637,126.637,126.637,126.637,126.637,230.66,146.071,146.071,146.071,166.72,166.72,166.72,252.804,30,5000,5000,199.485,185.674,185.674,185.674,185.674", "train/learning_rate": "0.0148773,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.0281875,0.0134111,0.0134111,0.0362086,0.0112641,0.012987,1e-05,0.0186137,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.0209566,0.0209566,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.0622395,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.0246104,0.0246104,0.0160558,0.000335725,0.00055908,0.00055908,0.00055908,0.00055908,0.00055908,0.00055908,0.00055908,0.00055908,0.00055908,0.00055908,0.00055908,0.00055908,0.00055908,0.00055908,0.00055908,0.00055908,0.00055908,0.00055908,0.00055908,0.00055908,0.00055908,0.00055908,0.0694922,0.075969,0.000150548,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.0122169,0.0122169,0.0122169,0.0122169,0.0122169,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.0176529,0.0127498,0.0127498,0.0205532,0.0205532,0.0205532,0.0195285,0.0129244,0.0773635,0.0773635,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000758874,0.000758874,0.000758874,0.000758874,0.000758874,0.0188596,0.011661,0.0183337,0.018044,0.018044,0.018044,0.018044,0.018044,0.0205489,0.0205489,0.0275759,0.0273274,0.01481,0.01481,0.0165216,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.00961588,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.000457315,0.1,0.0115632,0.0115632,0.0115632,0.0115632,0.0115632,0.0114668,0.0162264,0.0162264,0.0162264,0.0137308,0.0137308,0.0137308,0.0274405,0.00032181,0.0577618,0.0577618,0.0220753,0.0173033,0.0173033,0.0173033,0.0173033", "train/anneal_lr": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "train/min_lr_ratio": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "train/gamma": "0.8,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.8,0.8,0.8,0.899271,0.8,0.8,0.993314,0.8,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.8,0.8,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.991513,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.8,0.8,0.821745,0.99819,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.963125,0.98901,0.982061,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.8,0.8,0.8,0.8,0.8,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.979701,0.979701,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.99671,0.8,0.8,0.8,0.8,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.8,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.764754,0.91563,0.806163,0.806163,0.806163,0.806163,0.806163,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.994718,0.898429,0.898429,0.845817,0.8,0.8,0.8,0.8", "train/gae_lambda": "0.988773,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.995,0.956821,0.956821,0.993062,0.986763,0.994004,0.915619,0.995,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.973877,0.973877,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.980704,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.979495,0.979495,0.92712,0.728976,0.995,0.995,0.995,0.995,0.995,0.995,0.995,0.995,0.995,0.995,0.995,0.995,0.995,0.995,0.995,0.995,0.995,0.995,0.995,0.995,0.995,0.995,0.993514,0.994412,0.800117,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.995,0.995,0.995,0.995,0.995,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.975416,0.985662,0.985662,0.974586,0.974586,0.974586,0.967382,0.970582,0.977606,0.977606,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.995,0.995,0.995,0.995,0.995,0.978883,0.99313,0.990805,0.989567,0.989567,0.989567,0.989567,0.989567,0.981145,0.981145,0.797154,0.994636,0.995,0.995,0.995,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.991879,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.996006,0.985071,0.893937,0.893937,0.893937,0.893937,0.893937,0.986422,0.981466,0.981466,0.981466,0.961399,0.961399,0.961399,0.987129,0.747488,0.994729,0.994729,0.994403,0.990276,0.990276,0.990276,0.990276", "train/replay_ratio": "3.11573,1,1,1,1,1,1,1,1,1,1,1,2.76804,3.17648,3.17648,0.25,3.00566,4,4,2.80934,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3.42683,3.42683,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0.25,1,1,1,1,1,1,1,1,1,1,1,1,2.2114,2.2114,1.66882,3.86931,0.886472,0.886472,0.886472,0.886472,0.886472,0.886472,0.886472,0.886472,0.886472,0.886472,0.886472,0.886472,0.886472,0.886472,0.886472,0.886472,0.886472,0.886472,0.886472,0.886472,0.886472,0.886472,0.25,2.86394,4,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3.3663,3.3663,3.3663,3.3663,3.3663,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2.19796,2.99983,2.99983,1.56174,1.56174,1.56174,3.18159,3.68135,1.22012,1.22012,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1.7519,1.7519,1.7519,1.7519,1.7519,1.91795,3.431,2.68206,2.14479,2.14479,2.14479,2.14479,2.14479,2.22276,2.22276,3.80313,1.90151,2.5892,2.5892,2.48411,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,3.04133,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0.25,4,4,4,4,4,2.8219,3.28699,3.28699,3.28699,3.41992,3.41992,3.41992,1.99921,3.76252,0.25,0.25,2.56686,2.53143,2.53143,2.53143,2.53143", "train/clip_coef": "0.296275,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.190513,0.330784,0.330784,0.0316087,0.198328,0.19079,0.0474441,0.310514,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.391196,0.391196,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.01,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.269715,0.269715,0.222386,0.01,0.441089,0.441089,0.441089,0.441089,0.441089,0.441089,0.441089,0.441089,0.441089,0.441089,0.441089,0.441089,0.441089,0.441089,0.441089,0.441089,0.441089,0.441089,0.441089,0.441089,0.441089,0.441089,0.01,0.649385,0.200544,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.213303,0.213303,0.213303,0.213303,0.213303,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.353074,0.218929,0.218929,0.224135,0.224135,0.224135,0.261902,0.219568,0.948642,0.948642,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.208586,0.208586,0.208586,0.208586,0.208586,0.32032,0.274454,0.30182,0.349766,0.349766,0.349766,0.349766,0.349766,0.344489,0.344489,0.602095,0.261048,0.28505,0.28505,0.348953,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.183051,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.330982,0.266606,0.266606,0.266606,0.266606,0.266606,0.246094,0.304814,0.304814,0.304814,0.322054,0.322054,0.322054,0.218299,0.0517105,0.386017,0.386017,0.166034,0.24187,0.24187,0.24187,0.24187", "train/vf_coef": "0.1,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.1,0.1,0.1,1.10916,0.387445,0.410673,0.608003,0.605263,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.1,0.1,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,1.65401,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.652218,0.652218,0.764634,0.1,0.52607,0.52607,0.52607,0.52607,0.52607,0.52607,0.52607,0.52607,0.52607,0.52607,0.52607,0.52607,0.52607,0.52607,0.52607,0.52607,0.52607,0.52607,0.52607,0.52607,0.52607,0.52607,1.52928,4.07308,0.292522,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.1,0.1,0.1,0.1,0.1,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.110727,0.12865,0.12865,0.390741,0.390741,0.390741,0.1,0.112671,0.179615,0.179615,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.530392,0.1,0.1,0.1,0.1,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.244892,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,0.397909,2.46457,0.1,0.1,0.1,0.1,0.1,0.52226,0.1,0.1,0.1,0.1,0.1,0.1,0.839916,0.1,2.31954,2.31954,0.1,0.1,0.1,0.1,0.1", "train/vf_clip_coef": "1.70707,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.8388,2.09481,2.09481,0.01,1.43578,2.48765,5,0.769104,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,1.86742,1.86742,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.01,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,1.51566,1.51566,1.68881,5,0.300727,0.300727,0.300727,0.300727,0.300727,0.300727,0.300727,0.300727,0.300727,0.300727,0.300727,0.300727,0.300727,0.300727,0.300727,0.300727,0.300727,0.300727,0.300727,0.300727,0.300727,0.300727,1.16411,4.6584,5,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,1.07771,1.07771,1.07771,1.07771,1.07771,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.142043,0.438572,0.438572,1.86634,1.86634,1.86634,1.7289,2.31695,2.76189,2.76189,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.629725,0.629725,0.629725,0.629725,0.629725,1.79918,1.9086,2.49573,1.0659,1.0659,1.0659,1.0659,1.0659,1.17487,1.17487,3.5497,2.5528,0.137088,0.137088,1.90895,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,2.28423,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,2.42013,0.946668,0.946668,0.946668,0.946668,0.946668,1.86156,1.49521,1.49521,1.49521,0.835621,0.835621,0.835621,0.639287,4.18976,1.83229,1.83229,1.78336,1.56189,1.56189,1.56189,1.56189", "train/max_grad_norm": "0.1,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.1,0.581343,0.581343,0.1,0.1,0.1,0.501046,0.1,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.356664,0.356664,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.13411,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.1,0.1,0.1,1.54969,1.01577,1.01577,1.01577,1.01577,1.01577,1.01577,1.01577,1.01577,1.01577,1.01577,1.01577,1.01577,1.01577,1.01577,1.01577,1.01577,1.01577,1.01577,1.01577,1.01577,1.01577,1.01577,1.72748,4.3135,1.45329,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.1,0.1,0.1,0.1,0.1,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.1,0.1,0.1,0.45064,0.45064,0.45064,0.1,0.564015,3.47009,3.47009,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,1.29953,1.29953,1.29953,1.29953,1.29953,0.44433,0.1,0.45934,0.1,0.1,0.1,0.1,0.1,0.1,0.1,1.93865,0.1,0.1,0.1,0.1,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.1,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.607558,0.645487,0.1,0.1,0.1,0.1,0.1,0.1,0.685963,0.685963,0.685963,0.1,0.1,0.1,0.165319,1.62251,0.818134,0.818134,0.1,0.1,0.1,0.1,0.1", "train/ent_coef": "0.000120221,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.00148048,0.000182484,0.000182484,0.00146355,0.00028153,0.000888704,0.00385666,4.34283e-05,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.00301862,0.00301862,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.00226356,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.00091415,0.00091415,0.00161647,0.000180205,0.00220223,0.00220223,0.00220223,0.00220223,0.00220223,0.00220223,0.00220223,0.00220223,0.00220223,0.00220223,0.00220223,0.00220223,0.00220223,0.00220223,0.00220223,0.00220223,0.00220223,0.00220223,0.00220223,0.00220223,0.00220223,0.00220223,0.00644907,0.0105238,0.00216307,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.000126189,0.000126189,0.000126189,0.000126189,0.000126189,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0138185,2.28056e-05,2.28056e-05,0.00201026,0.00201026,0.00201026,0.00624143,0.0087832,1.21253e-05,1.21253e-05,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.00775893,0.00775893,0.00775893,0.00775893,0.00775893,0.00040153,5.12483e-05,0.000842172,0.00216394,0.00216394,0.00216394,0.00216394,0.00216394,7.55462e-05,7.55462e-05,0.0174388,0.000862718,0.00418013,0.00418013,0.00166584,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,5.2987e-05,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.0121008,0.00375396,0.000417816,0.000417816,0.000417816,0.000417816,0.000417816,0.000187917,0.000945469,0.000945469,0.000945469,0.00030243,0.00030243,0.00030243,0.00454733,4.46898e-05,0.00662181,0.00662181,0.000740099,0.00282999,0.00282999,0.00282999,0.00282999", "train/beta1": "0.80641,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.930606,0.739404,0.739404,0.973221,0.922126,0.832158,0.999,0.639266,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.877809,0.877809,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.994928,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.663889,0.663889,0.911622,0.998472,0.953662,0.953662,0.953662,0.953662,0.953662,0.953662,0.953662,0.953662,0.953662,0.953662,0.953662,0.953662,0.953662,0.953662,0.953662,0.953662,0.953662,0.953662,0.953662,0.953662,0.953662,0.953662,0.991074,0.996289,0.999,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.847416,0.847416,0.847416,0.847416,0.847416,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.79917,0.651556,0.651556,0.820799,0.820799,0.820799,0.951596,0.875382,0.990918,0.990918,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.779051,0.779051,0.779051,0.779051,0.779051,0.836505,0.735196,0.928266,0.714697,0.714697,0.714697,0.714697,0.714697,0.709857,0.709857,0.998961,0.956029,0.819611,0.819611,0.798284,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.94845,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.990906,0.838025,0.838025,0.838025,0.838025,0.838025,0.60189,0.785533,0.785533,0.785533,0.826875,0.826875,0.826875,0.848282,0.999,0.95425,0.95425,0.934513,0.937452,0.937452,0.937452,0.937452", "train/beta2": "0.999865,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999257,0.999976,0.999976,0.999803,0.999871,0.999433,0.999983,0.999756,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.998602,0.998602,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999025,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999298,0.999298,0.999766,0.99974,0.999691,0.999691,0.999691,0.999691,0.999691,0.999691,0.999691,0.999691,0.999691,0.999691,0.999691,0.999691,0.999691,0.999691,0.999691,0.999691,0.999691,0.999691,0.999691,0.999691,0.999691,0.999691,0.999644,0.999926,0.999982,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999935,0.999935,0.999935,0.999935,0.999935,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999699,0.999461,0.999461,0.999458,0.999458,0.999458,0.998764,0.999926,0.999189,0.999189,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.998649,0.998649,0.998649,0.998649,0.998649,0.997755,0.99999,0.999631,0.999022,0.999022,0.999022,0.999022,0.999022,0.999407,0.999407,0.97905,0.99909,0.999588,0.999588,0.998901,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999922,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.999,0.969351,0.999916,0.999916,0.999916,0.999916,0.999916,0.999982,0.999838,0.999838,0.999838,0.999902,0.999902,0.999902,0.999664,0.999953,0.992859,0.992859,0.99971,0.999266,0.999266,0.999266,0.999266", "train/eps": "9.96105e-13,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,9.7889e-14,2.96204e-13,2.96204e-13,3.75974e-10,9.93477e-14,7.28951e-14,0.0001,5.59649e-10,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1.08131e-12,1.08131e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,6.62159e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,6.43074e-12,6.43074e-12,1e-14,0.0001,1.80246e-13,1.80246e-13,1.80246e-13,1.80246e-13,1.80246e-13,1.80246e-13,1.80246e-13,1.80246e-13,1.80246e-13,1.80246e-13,1.80246e-13,1.80246e-13,1.80246e-13,1.80246e-13,1.80246e-13,1.80246e-13,1.80246e-13,1.80246e-13,1.80246e-13,1.80246e-13,1.80246e-13,1.80246e-13,3.98303e-10,1.02309e-06,0.0001,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,5.65139e-12,5.65139e-12,5.65139e-12,5.65139e-12,5.65139e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-14,2.93633e-11,2.93633e-11,8.40713e-14,8.40713e-14,8.40713e-14,3.93846e-12,2.59089e-12,3.46805e-08,3.46805e-08,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,4.08201e-14,4.08201e-14,4.08201e-14,4.08201e-14,4.08201e-14,3.01368e-14,2.08877e-13,2.24951e-14,1.20587e-12,1.20587e-12,1.20587e-12,1.20587e-12,1.20587e-12,2.13003e-13,2.13003e-13,1.59165e-08,1.28755e-09,4.95789e-14,4.95789e-14,7.89577e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1.32538e-13,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,1e-12,2.6755e-09,6.06109e-14,6.06109e-14,6.06109e-14,6.06109e-14,6.06109e-14,1.17842e-12,3.94672e-12,3.94672e-12,3.94672e-12,3.24623e-12,3.24623e-12,3.24623e-12,1e-14,3.44925e-05,1.00121e-08,1.00121e-08,2.42181e-12,1.93028e-11,1.93028e-11,1.93028e-11,1.93028e-11", "train/minibatch_size": "32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,16384,32768,32768,65536,32768,32768,16384,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,16384,16384,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,8192,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,65536,16384,16384,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,65536,16384,16384,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,16384,16384,16384,16384,16384,65536,32768,16384,32768,32768,32768,32768,32768,32768,32768,16384,16384,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,32768,16384,32768,32768,65536,32768,32768,32768,32768", "train/horizon": "64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64", "train/vtrace_rho_clip": "1.47797,1,1,1,1,1,1,1,1,1,1,1,0.93671,1.92891,1.92891,2.12877,1.7045,1.78727,3.43714,0.59568,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0.608817,0.608817,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0.767235,1,1,1,1,1,1,1,1,1,1,1,1,1.86283,1.86283,1.24545,3.39692,1.63654,1.63654,1.63654,1.63654,1.63654,1.63654,1.63654,1.63654,1.63654,1.63654,1.63654,1.63654,1.63654,1.63654,1.63654,1.63654,1.63654,1.63654,1.63654,1.63654,1.63654,1.63654,2.71471,2.18617,3.5073,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1.6449,1.6449,1.6449,1.6449,1.6449,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1.14079,0.790136,0.790136,1.1749,1.1749,1.1749,1.21642,0.870086,4.60719,4.60719,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0.608515,0.608515,0.608515,0.608515,0.608515,0.502384,2.66607,0.934475,2.08831,2.08831,2.08831,2.08831,2.08831,2.09834,2.09834,3.6896,0.497387,1.29951,1.29951,2.24629,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1.52894,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0.831859,0.543604,0.543604,0.543604,0.543604,0.543604,2.14191,1.61901,1.61901,1.61901,1.0515,1.0515,1.0515,1.56739,3.64727,1.63049,1.63049,2.16547,2.18396,2.18396,2.18396,2.18396", "train/vtrace_c_clip": "1.74916,1,1,1,1,1,1,1,1,1,1,1,1.54944,1.62797,1.62797,1.76116,4.44996,2.04037,3.30159,4.89592,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1.51303,1.51303,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0.1,1,1,1,1,1,1,1,1,1,1,1,1,4.23576,4.23576,3.2577,4.81648,2.15503,2.15503,2.15503,2.15503,2.15503,2.15503,2.15503,2.15503,2.15503,2.15503,2.15503,2.15503,2.15503,2.15503,2.15503,2.15503,2.15503,2.15503,2.15503,2.15503,2.15503,2.15503,0.1,2.01064,3.02648,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4.27745,4.27745,4.27745,4.27745,4.27745,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1.24473,3.08338,3.08338,3.16423,3.16423,3.16423,5,3.28299,3.94838,3.94838,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1.19624,1.19624,1.19624,1.19624,1.19624,1.85846,5,3.22826,1.31895,1.31895,1.31895,1.31895,1.31895,3.61816,3.61816,0.134598,4.9953,1.59863,1.59863,2.08945,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4.0289,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1.21024,2.25872,2.25872,2.25872,2.25872,2.25872,5,2.4834,2.4834,2.4834,2.75217,2.75217,2.75217,4.08913,3.3506,1.03901,1.03901,3.07082,4.80357,4.80357,4.80357,4.80357", "train/prio_alpha": "0.441057,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.631522,0.780789,0.780789,0.96253,0.1,0.500926,0.99,0.1,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.500971,0.500971,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.980247,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.372335,0.372335,0.616319,0.99,0.942676,0.942676,0.942676,0.942676,0.942676,0.942676,0.942676,0.942676,0.942676,0.942676,0.942676,0.942676,0.942676,0.942676,0.942676,0.942676,0.942676,0.942676,0.942676,0.942676,0.942676,0.942676,1,0.93775,0.99,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.1,0.1,0.1,0.1,0.1,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.563336,0.1,0.1,0.679577,0.679577,0.679577,0.666062,0.1,0.0374007,0.0374007,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,1,1,1,1,1,0.1,0.29876,0.248084,0.768484,0.768484,0.768484,0.768484,0.768484,0.695625,0.695625,0.419705,0.491193,0.863761,0.863761,0.699896,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.103038,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.781951,0.34501,0.34501,0.34501,0.34501,0.34501,0.248095,0.381109,0.381109,0.381109,0.5358,0.5358,0.5358,0.626096,0.99,0.804111,0.804111,0.29502,0.1,0.1,0.1,0.1", "train/prio_beta0": "0.1,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.1,0.576593,0.576593,0,0.1,0.1,0.895693,0.679902,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.1,0.1,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.0975731,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.1,0.1,0.476268,0.946256,0.234331,0.234331,0.234331,0.234331,0.234331,0.234331,0.234331,0.234331,0.234331,0.234331,0.234331,0.234331,0.234331,0.234331,0.234331,0.234331,0.234331,0.234331,0.234331,0.234331,0.234331,0.234331,0,0.923004,0.904499,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.1,0.1,0.1,0.1,0.1,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.1,0.1,0.1,0.523282,0.523282,0.523282,0.434197,0.679222,0.894314,0.894314,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.378079,0.378079,0.378079,0.378079,0.378079,0.1,0.1,0.471174,0.18597,0.18597,0.18597,0.18597,0.18597,0.34415,0.34415,0.574217,0.1,0.1,0.1,0.1,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.1,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0,0.568383,0.568383,0.568383,0.568383,0.568383,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.765641,0.930075,0,0,0.299464,0.662089,0.662089,0.662089,0.662089", "train/checkpoint_interval": "10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000", "train/use_rnn": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "no_model_upload": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "vec/seed": "73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73", "slowly": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "save_frames": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "fps": "15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15", "tsne1": "-70.0092,-82.3845,-80.1944,-77.3054,-77.6139,-80.7951,-82.8545,-80.5067,-78.3193,-77.7861,-81.7665,-76.9943,-70.2859,-66.6856,-66.6856,-6.65009,-70.4191,-69.7333,61.6795,-68.2565,-79.8514,-80.6016,-81.3379,-79.8257,-81.8009,-79.7439,-79.5484,-77.0276,-78.4636,-77.6208,-80.8603,-76.4989,-79.1645,-79.3819,-83.3029,-81.0851,-78.9364,-76.489,-81.379,-79.1534,-83.3237,-77.5156,-82.5173,-79.3164,-78.3516,-78.6738,-70.5621,-70.5621,-52.731,-49.4857,-52.4639,-50.3231,-52.2269,-54.736,-48.2392,-47.2629,-53.3834,-49.2776,-48.0336,-50.0372,-49.2776,-46.4527,-48.4879,-54.4138,-51.3744,-53.0038,-50.7617,-46.6372,-54.5222,-53.6769,-52.7807,-49.9381,-51.5248,-47.7,-52.1584,-50.1339,-48.6652,-54.7042,-52.1145,-52.1766,-50.731,-50.731,-47.3304,-52.6392,-46.4402,-53.9203,-51.8007,-49.4857,-49.4683,-51.711,-47.6495,-52.1145,-51.3744,-53.2822,-50.7418,-51.3954,-6.69281,-87.2838,-87.2838,-87.2838,-87.2838,-87.2838,-86.8336,-86.8336,-87.2838,-86.8336,-86.8336,-86.8336,-86.8336,-71.4721,-71.4721,-64.6968,61.6716,-56.4968,-56.566,-56.4968,-56.4968,-56.566,-56.566,-56.566,-56.566,-56.4968,-56.4968,-56.4968,-56.4968,-56.566,-56.566,-56.4968,-56.4968,-56.4968,-56.4968,-56.4968,-56.4968,-56.566,-56.4968,-6.71431,0.198949,61.6788,-51.3785,-51.3785,-49.0688,-45.0338,-49.9087,-51.3785,-51.3785,-49.0688,-51.3785,-51.3785,-49.0688,-51.0958,-43.6443,-51.8639,-49.0688,-51.3785,-51.3785,-48.8225,-53.6471,-48.1108,-51.3785,-51.3785,-47.5162,-51.3785,-51.3785,-51.3785,-46.8378,-51.3785,-51.3785,-51.3785,-54.1564,-48.5563,-47.5828,-47.7726,-51.3785,-51.3785,-48.4017,-51.3785,-51.3785,-48.8738,-51.0958,-51.3785,-51.3785,-51.5278,-51.3785,-51.3785,-51.2415,-49.1604,-47.5828,-70.9155,-70.9155,-70.9155,-70.9155,-70.9155,-45.0338,-51.3785,-51.3785,-51.3785,-53.798,-51.3785,-51.3785,-46.5625,-50.5694,-51.3785,-53.063,-48.1108,-51.3785,-53.493,-49.0688,-51.3785,-53.063,-49.9649,-47.5828,-47.5828,-55.2537,-49.9087,-48.3254,-47.5162,-51.3785,-51.3785,-50.1607,-51.3785,-51.3785,-50.1607,-47.5162,-47.5162,-51.3785,-50.1607,-51.3785,-46.425,-50.1607,-50.1607,-48.7147,-48.3254,-47.5162,-47.5162,-47.5162,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-69.6228,-71.8626,-71.8626,-64.6702,-64.6702,-64.6702,-65.1731,-67.3025,19.7835,19.7835,-81.677,-77.942,-80.8296,-78.7126,-81.4345,-79.3506,-78.3787,-78.4411,-80.3848,-80.2235,-79.8401,-82.4972,-80.2235,-76.8166,-76.2711,-79.8789,-79.2627,-79.0551,-81.7738,-80.1458,-82.0505,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-82.3436,-77.4835,-82.431,-79.8216,-80.956,-82.1647,-81.469,-77.9824,-77.5167,-83.3623,-79.017,-81.0625,-79.063,-80.4175,-81.1987,-80.7991,-81.5157,-80.2896,-78.253,-78.3705,-82.9825,-78.9739,-80.1677,-56.2612,-56.2612,-56.2612,-56.2612,-56.2612,-71.5884,-70.7273,-66.2266,-68.0446,-68.0446,-68.0446,-68.0446,-68.0446,-65.5944,-65.5944,-9.74902,-72.1073,-69.7651,-69.7651,-69.0262,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-70.8947,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-51.3785,-6.66816,-67.226,-67.226,-67.226,-67.226,-67.226,-71.4918,-70.2447,-70.2447,-70.2447,-70.6284,-70.6284,-70.6284,-64.8028,61.654,-6.68924,-6.68924,-65.7493,-67.2541,-67.2541,-67.2541,-67.2541", "tsne2": "14.3214,1.07209,4.77434,2.3394,1.80529,2.94909,2.95824,1.61613,3.55089,2.96325,3.1043,3.37911,12.3526,15.0025,15.0025,0.757835,18.3456,14.3576,28.1848,19.0574,3.86264,3.90518,2.47956,2.33323,4.25325,-1.66635,2.97401,1.28347,4.5241,4.08057,1.02932,2.50824,0.769889,1.36229,2.25566,4.72136,3.22525,0.47019,1.30015,3.94653,0.455008,-0.00961101,1.7479,4.87297,2.60143,1.41317,13.4496,13.4496,-7.81423,-9.51097,-10.3421,-8.56361,-8.40293,-11.8733,-8.01478,-10.2129,-9.59629,-8.53206,-9.21943,-7.25555,-8.53206,-10.9182,-9.56339,-9.80515,-8.10984,-9.16411,-7.2113,-10.2859,-11.2667,-8.68805,-9.77879,-8.93642,-10.3435,-9.77858,-10.3365,-9.35417,-6.44909,-10.4994,-9.38922,-7.53602,-9.43289,-9.43289,-9.04462,-8.75673,-12.1792,-11.0972,-10.1017,-9.51097,-7.59105,-8.7793,-8.45638,-9.38922,-8.10984,-8.17662,-8.63951,-9.47818,1.56801,7.00481,7.00481,7.00481,7.00481,7.00481,7.55146,7.55146,7.00481,7.55146,7.55146,7.55146,7.55146,15.9498,15.9498,16.0134,28.1884,17.8651,19.036,17.8651,17.8651,19.036,19.036,19.036,19.036,17.8651,17.8651,17.8651,17.8651,19.036,19.036,17.8651,17.8651,17.8651,17.8651,17.8651,17.8651,19.036,17.8651,0.860056,50.6109,28.1776,-13.6635,-13.6635,-10.9395,-6.97517,-4.19401,-13.6635,-13.6635,-10.9395,-13.6635,-13.6635,-10.9395,-10.198,-9.12599,-4.35367,-10.9395,-13.6635,-13.6635,-9.10838,-10.7896,-10.3549,-13.6635,-13.6635,-13.0473,-13.6635,-13.6635,-13.6635,-9.50589,-13.6635,-13.6635,-13.6635,-9.16562,-11.6732,-11.2744,-4.31181,-13.6635,-13.6635,-8.62364,-13.6635,-13.6635,-7.76641,-10.198,-13.6635,-13.6635,-7.2211,-13.6635,-13.6635,-8.9773,-9.96992,-11.2744,17.9955,17.9955,17.9955,17.9955,17.9955,-6.97517,-13.6635,-13.6635,-13.6635,-10.0744,-13.6635,-13.6635,-11.6469,-7.86424,-13.6635,-10.505,-10.3549,-13.6635,-4.70867,-10.9395,-13.6635,-10.505,-8.09572,-11.2744,-11.2744,-5.67619,-4.19401,-11.9665,-13.0473,-13.6635,-13.6635,-10.3841,-13.6635,-13.6635,-10.3841,-13.0473,-13.0473,-13.6635,-10.3841,-13.6635,-5.38451,-10.3841,-10.3841,-9.94985,-11.9665,-13.0473,-13.0473,-13.0473,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,11.7302,17.9402,17.9402,15.8338,15.8338,15.8338,16.8033,18.2206,-52.5581,-52.5581,1.77343,1.10655,0.474515,-0.689022,-1.95218,-0.354528,0.0796612,0.75381,2.41346,-0.748008,0.74621,0.305819,-0.748008,-0.486472,1.50282,1.77371,-1.10224,0.242302,0.723043,1.11616,-0.344427,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-1.3055,0.652693,3.67649,0.0838692,2.02522,2.42006,0.171667,-0.585112,-1.32346,1.3586,2.46897,-0.388471,1.93429,0.137744,3.55478,-1.44011,-0.968331,-2.2443,1.90411,-1.53191,-0.501382,-2.15702,3.19659,-0.717545,-0.717545,-0.717545,-0.717545,-0.717545,19.0113,16.6429,17.2278,12.6861,12.6861,12.6861,12.6861,12.6861,14.6954,14.6954,-24.8258,15.2604,11.8798,11.8798,13.3361,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,18.6237,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-13.6635,-0.159023,16.4367,16.4367,16.4367,16.4367,16.4367,16.5857,14.8546,14.8546,14.8546,14.4239,14.4239,14.4239,16.3257,28.243,-0.0179138,-0.0179138,17.2142,18.9857,18.9857,18.9857,18.9857"}, "pacman": {"SPS": "7.67996e+06,2.07022e+06,2.10547e+06,2.72879e+06,7.6211e+06,2.3599e+06,3.15722e+06,7.32941e+06,2.68785e+06,3.34501e+06,407918,408026,408419,257158,256849,4.75262e+06,7.26111e+06,2.19083e+06,2.17542e+06,2.16197e+06,2.17079e+06,2.12619e+06,183243,185301,185227,185206,185214,2.25197e+06,2.27238e+06,495862,495520,495190,5.70159e+06,3.4098e+06,3.52469e+06,4.26944e+06,195245,195068,5.08457e+06,8.44672e+06,5.07652e+06,5.2625e+06,5.20951e+06,5.18745e+06,891359,375723,375880,768754,268732,268408,268107,268479,6.71982e+06,4.31079e+06,3.2924e+06,3.3233e+06,3.34776e+06,3.35764e+06,8.59011e+06,515032,516251,518993,513883,509498,505624,501698,501966,3.02241e+06,1.29729e+06,2.38695e+06,2.39457e+06,917484,885504,898759,881479,896832,1.32589e+06,1.347e+06,2.0151e+06,1.28883e+06,6.30026e+06,6.73874e+06,7.66502e+06,7.76422e+06,7.58252e+06,7.55516e+06,7.54987e+06,7.76492e+06,7.7609e+06,266946,1.47265e+06,1.48582e+06,6.50973e+06,1.81874e+06,2.8314e+06,3.10973e+06,151561,151438,151499,1.53891e+06,1.5228e+06,1.57003e+06,1.57732e+06,493080,3.41371e+06,3.41061e+06,3.78638e+06,4.14458e+06,4.069e+06,4.12623e+06,3.6532e+06,3.64553e+06,3.69402e+06,3.69107e+06,1.02735e+06,1.71017e+06,1.71019e+06,5.83408e+06,1.35395e+06,6.97969e+06,7.49852e+06,2.68256e+06,2.83618e+06,3.18364e+06,432548,443111,454910,1.05904e+06,1.06159e+06,2.38706e+06,2.41143e+06,5.20236e+06,5.19915e+06,5.20269e+06,5.20269e+06,2.00762e+06,1.49269e+06,1.49286e+06,1.49147e+06,1.49156e+06,1.49153e+06,1.48925e+06,1.48752e+06,1.46278e+06,2.33319e+06,2.33282e+06,2.33837e+06,2.33763e+06,2.32658e+06,2.33479e+06,843718,844119,841811,845479,281986,689153,225461,225676,225832,1.97151e+06,1.96475e+06,1.97189e+06,1.96798e+06,1.96465e+06,1.97127e+06,4.85983e+06,4.89666e+06,4.86667e+06,4.90799e+06,4.86256e+06,4.98738e+06,389514,4.53712e+06,7.0346e+06,3.91536e+06,161018,6.70303e+06,6.72917e+06,196518,194786,521689,524950,523862,524214,522605,519654,1.72e+06,3.19937e+06,3.53876e+06,170922,2.21859e+06,6.66147e+06,2.15073e+06,2.15433e+06,7.50726e+06,4.02369e+06,4.94887e+06,5.15577e+06,322689,322389,3.69647e+06,5.86046e+06,2.00092e+06,2.02921e+06,3.08036e+06,3.13944e+06,3.13691e+06,3.15289e+06,3.1282e+06,3.12789e+06,1.62152e+06,1.61578e+06,1.62904e+06,1.62396e+06,1.6544e+06,228295,7.32157e+06,2.10255e+06,4.22716e+06,4.56541e+06,3.19709e+06,3.22918e+06,3.24588e+06,967025,2.93948e+06,2.96163e+06,6.88228e+06,1.01217e+06,1.0059e+06,3.5458e+06,3.48886e+06,980859,5.302e+06,5.45411e+06,6.73873e+06", "agent_steps": "2.88358,124.781,143.917,16.7772,8.65075,5.57056,2.81805,2.80166,2.81805,2.81805,6.16038,18.2845,30.3432,109.576,126.353,2.88358,2.88358,126.616,149.684,172.753,195.559,206.569,83.3618,106.955,130.548,154.141,177.734,4.32538,12.8451,30.933,51.1181,91.7504,4.71859,2.88358,8.45414,2.81805,109.576,126.353,3.67002,3.01466,8.45414,13.9592,19.5297,25.1003,20.8404,13.1072,21.6269,7.20896,169.869,196.084,221.774,233.832,8.45414,4.16154,4.1943,20.5128,28.7048,36.8968,10.3547,101.188,141.033,180.879,220.725,260.571,300.417,340.263,359.662,6.68467,6.48806,15.2044,25.1658,166.461,196.608,226.755,256.901,271.581,2.88358,8.45414,204.997,23.0687,3.01466,8.84736,18.6122,25.9523,33.2923,40.6323,47.9724,55.3124,62.6524,5.76717,2.81805,8.38861,2.81805,36.9623,2.89997,36.1759,103.285,121.635,139.985,2.88358,8.45414,3.2768,9.63379,7.07789,2.88358,8.45414,2.81805,10.2236,16.9083,23.593,4.52198,13.4349,22.3478,31.2607,7.2745,11.2722,18.7433,3.86662,9.04397,2.88358,8.45414,8.65075,8.65075,14.1558,4.12877,20.2506,28.3116,2.80166,8.35584,2.88358,8.45414,40.108,56.0988,72.0896,87.8182,8.65075,23.3308,32.5059,41.812,51.1181,60.2931,69.4682,78.6432,83.0996,9.96147,16.5151,23.0687,36.1759,42.7295,49.2831,86.5075,111.149,160.432,185.074,174.326,7.07789,164.626,185.598,195.035,17.8258,24.9037,31.9816,39.0595,46.1373,53.2152,9.43718,15.4665,21.4958,33.8166,39.8459,45.8752,2.22822,5.30842,8.65075,5.60333,5.24288,9.8304,16.3185,81.7889,99.6147,13.8936,22.9376,31.9816,41.0255,50.0695,59.1135,4.06323,3.86662,8.65075,10.7479,2.80166,2.88358,12.0586,19.9229,3.53894,1.57286,2.88358,8.45414,28.3116,46.6616,4.71859,3.60448,2.88358,8.45414,28.8358,37.0934,45.3509,53.4774,61.6038,69.7303,84.4104,99.6147,114.819,129.499,136.315,10.4858,17.1704,40.7634,2.88358,8.45414,19.9229,25.428,36.438,24.1172,4.71859,13.8936,2.88358,85.7211,96.9933,11.01,18.0879,5.30842,2.81805,8.38861,2.88358", "uptime": "0.402766,60.9501,70.0995,6.23354,1.17242,2.39209,0.902322,0.402038,1.05343,0.850785,15.1352,44.8484,74.3617,423.946,489.282,0.621527,0.412665,58.0917,68.6484,79.3119,89.8532,94.9215,453.425,580.886,708.235,835.616,962.999,1.94231,5.69522,62.3458,103.075,185.071,0.871373,0.873409,2.46308,0.700853,560.627,646.604,0.748342,0.390653,1.66826,2.73026,3.80398,4.90082,23.693,34.9185,57.5891,9.40151,631.434,729.034,824.819,869.788,1.37867,1.00985,1.32737,6.20415,8.65861,11.1058,1.32471,196.424,273.806,350.689,427.742,505.707,584.233,663.412,702.045,2.2471,5.02649,6.39512,10.5943,184.98,218.491,252.802,287.233,304.37,2.17171,6.39583,102.763,17.9655,0.499723,1.39316,2.58918,3.53579,4.49706,5.45934,6.43453,7.39504,8.34077,21.6053,1.92873,5.68503,0.458452,20.4017,1.03723,11.6534,680.236,801.379,922.499,1.90137,5.52954,2.12103,6.1333,14.4184,0.863217,2.48679,0.75982,2.53262,4.16637,5.79925,1.25636,3.70831,6.14827,8.5655,7.1365,6.6531,11.022,0.692009,6.74846,0.4226,1.19085,3.32517,3.04462,4.87042,9.98783,46.4713,64.5665,2.67484,7.90399,1.20649,3.51897,7.79942,10.8728,13.9469,16.9709,4.34172,15.7148,21.8648,28.1009,34.3419,40.4943,46.6517,52.8146,55.8097,4.37687,7.18672,9.99155,15.5944,18.4051,21.2179,102.481,131.678,190.149,219.339,616.8,10.3189,729.18,822.155,863.962,9.17347,12.7692,16.3676,19.9594,23.5604,27.1553,1.98513,3.2186,4.44646,7.72506,8.96356,10.193,5.72564,1.1999,1.25985,1.47293,32.5611,1.5058,2.4711,415.624,506.698,26.9028,44.152,61.3935,78.65,95.9163,113.322,2.38404,1.21061,2.49153,62.8332,1.27349,0.447766,5.71083,9.3592,0.493375,0.420414,0.619312,1.70701,87.616,144.504,1.29043,0.650022,1.45126,4.20719,9.22494,11.8827,14.5136,17.1066,19.7058,22.2964,51.8189,61.2086,70.6089,79.6605,83.8426,45.9431,2.50744,19.3086,0.702329,1.95118,6.39441,8.10632,11.537,24.9892,1.60855,4.71676,0.433565,83.8604,95.0537,3.19816,5.21377,5.43151,0.560127,1.58527,0.446717", "epoch": "22,238,274.5,128,33,42.5,43,85.5,43,43,47,139.5,231.5,104.5,120.5,22,22,241.5,285.5,329.5,373,394,159,204,249,294,339,33,98,59,97.5,175,18,22,64.5,43,104.5,120.5,28,11.5,64.5,106.5,149,191.5,79.5,50,82.5,55,162,187,211.5,223,64.5,63.5,32,156.5,219,281.5,39.5,96.5,134.5,172.5,210.5,248.5,286.5,324.5,343,25.5,49.5,29,48,317.5,375,432.5,490,518,22,64.5,391,44,23,67.5,35.5,49.5,63.5,77.5,91.5,105.5,119.5,22,43,128,43,70.5,88.5,138,98.5,116,133.5,22,64.5,25,73.5,54,22,64.5,43,78,129,180,34.5,102.5,170.5,238.5,55.5,86,143,29.5,34.5,22,64.5,33,33,54,31.5,154.5,216,85.5,255,22,64.5,76.5,107,137.5,167.5,33,89,124,159.5,195,230,265,300,317,38,63,88,138,163,188,165,212,306,353,332.5,108,78.5,88.5,93,68,95,122,149,176,203,36,59,82,129,152,175,17,40.5,33,85.5,20,75,124.5,78,95,53,87.5,122,156.5,191,225.5,15.5,59,33,41,85.5,22,23,38,13.5,12,22,64.5,54,89,72,27.5,22,64.5,110,141.5,173,204,235,266,80.5,95,109.5,123.5,130,20,65.5,155.5,22,64.5,38,48.5,69.5,92,18,53,22,163.5,185,42,69,40.5,43,128,22", "env/perf": "0.243924,0.855335,0.87515,0.669096,0.449251,0.532095,0.387421,0.0544475,0.299877,0.2684,0.545597,0.702481,0.734386,0.884581,0.902829,0.347619,0.111688,0.861408,0.891746,0.907731,0.91461,0.916977,0.86553,0.905987,0.923064,0.935971,0.940938,0.488616,0.648051,0.730083,0.798282,0.864685,0.417388,0.381094,0.558368,0.202935,0.895003,0.90918,0.407462,0.149867,0.593664,0.648749,0.664221,0.671523,0.699097,0.701395,0.713137,0.571992,0.937389,0.951231,0.963801,0.965909,0.561308,0.42994,0.433963,0.683495,0.696611,0.706305,0.495079,0.876768,0.921249,0.943601,0.958208,0.964124,0.96637,0.968009,0.969207,0.519003,0.553169,0.678566,0.697645,0.911981,0.932436,0.941031,0.946446,0.946718,0.441764,0.627919,0.926668,0.703856,0.332065,0.562267,0.653641,0.674415,0.678652,0.687257,0.691052,0.694892,0.695241,0.532347,0.395001,0.597742,0.297094,0.734653,0.406272,0.703805,0.89294,0.914451,0.927455,0.403454,0.641026,0.467901,0.641659,0.566569,0.367657,0.548587,0.198051,0.626426,0.661769,0.678619,0.449534,0.655295,0.676585,0.687248,0.557453,0.679242,0.693701,0.379215,0.651439,0.255617,0.449415,0.60758,0.641124,0.658226,0.500453,0.709582,0.729367,0.4555,0.621104,0.420952,0.586508,0.691483,0.712118,0.72928,0.741952,0.624975,0.711436,0.74736,0.774858,0.800724,0.822166,0.83441,0.841985,0.843897,0.644048,0.685058,0.69535,0.727025,0.734945,0.741772,0.853153,0.876301,0.917182,0.922121,0.923406,0.584655,0.938139,0.953334,0.957856,0.688224,0.720914,0.722333,0.7409,0.754386,0.762475,0.623423,0.659304,0.670757,0.69127,0.697621,0.70156,0.335756,0.486299,0.492795,0.495541,0.521863,0.58425,0.643162,0.857329,0.880417,0.68967,0.728798,0.754169,0.775582,0.794279,0.808555,0.477782,0.428155,0.603347,0.66593,0.201121,0.234342,0.664303,0.68827,0.303129,0.176943,0.349724,0.602142,0.750036,0.787142,0.461263,0.366302,0.407413,0.605399,0.701172,0.724132,0.741477,0.753381,0.762976,0.768822,0.84021,0.873609,0.892826,0.905356,0.908563,0.663195,0.643418,0.73361,0.401731,0.57619,0.670955,0.685814,0.701768,0.715192,0.456168,0.657661,0.21087,0.848825,0.854845,0.645287,0.662858,0.52887,0.268972,0.53842,0.187695", "env/score": "58.5419,205.28,210.036,160.583,107.82,127.703,92.981,13.0674,71.9706,64.4159,130.943,168.595,176.253,212.299,216.679,83.4284,26.8051,206.738,214.019,217.855,219.506,220.075,207.727,217.436,221.535,224.632,225.825,117.268,155.532,175.22,191.588,207.524,100.173,91.4626,134.008,48.7045,214.801,218.203,97.791,35.9681,142.479,155.7,159.413,161.165,167.783,168.335,171.153,137.278,224.973,228.295,231.312,231.82,134.714,103.186,104.151,164.039,167.187,169.513,118.819,210.424,221.1,226.464,229.969,231.388,231.927,232.32,232.612,124.561,132.761,162.856,167.435,218.875,223.784,225.847,227.147,227.213,106.023,150.701,222.4,168.926,79.6956,134.944,156.874,161.859,162.876,164.942,165.852,166.774,166.858,127.763,94.8004,143.458,71.3025,176.317,97.5052,168.913,214.306,219.468,222.589,96.8289,153.846,112.296,153.998,135.977,88.2376,131.661,47.5323,150.342,158.825,162.869,107.888,157.271,162.38,164.939,133.789,163.018,166.488,91.0115,156.345,61.3482,107.859,145.819,153.87,157.974,120.109,170.3,175.048,109.32,149.065,101.028,140.762,165.956,170.908,175.027,178.068,149.994,170.745,179.366,185.966,192.174,197.32,200.259,202.076,202.535,154.572,164.414,166.884,174.486,176.387,178.025,204.757,210.312,220.123,221.309,221.617,140.317,225.154,228.801,229.885,165.174,173.019,173.36,177.816,181.052,182.994,149.622,158.233,160.982,165.905,167.429,168.374,80.5815,116.712,118.271,118.93,125.247,140.22,154.359,205.759,211.3,165.521,174.912,181.001,186.14,190.627,194.053,114.668,102.757,144.803,159.823,48.2691,56.242,159.433,165.185,72.7511,42.4663,83.9338,144.514,180.009,188.914,110.703,87.9125,97.779,145.296,168.281,173.792,177.954,180.811,183.114,184.517,201.65,209.666,214.278,217.285,218.057,159.167,154.42,176.066,96.4154,138.286,161.029,164.595,168.424,171.646,109.48,157.839,50.6088,203.718,205.163,154.869,159.086,126.929,64.5534,129.221,45.0469", "env/episode_return": "58.5419,205.28,210.036,160.583,107.82,127.703,92.981,13.0674,71.9706,64.4159,130.943,168.595,176.253,212.299,216.679,83.4284,26.8051,206.738,214.019,217.855,219.506,220.075,207.727,217.436,221.535,224.632,225.825,117.268,155.532,175.22,191.588,207.524,100.173,91.4626,134.008,48.7045,214.801,218.203,97.791,35.9681,142.479,155.7,159.413,161.165,167.783,168.335,171.153,137.278,224.973,228.295,231.312,231.82,134.714,103.186,104.151,164.039,167.187,169.513,118.819,210.424,221.1,226.464,229.969,231.388,231.927,232.32,232.612,124.561,132.761,162.856,167.435,218.875,223.784,225.847,227.147,227.213,106.023,150.701,222.4,168.926,79.6956,134.944,156.874,161.859,162.876,164.942,165.852,166.774,166.858,127.763,94.8004,143.458,71.3025,176.317,97.5052,168.913,214.306,219.468,222.589,96.8289,153.846,112.296,153.998,135.977,88.2376,131.661,47.5323,150.342,158.825,162.869,107.888,157.271,162.38,164.939,133.789,163.018,166.488,91.0115,156.345,61.3482,107.859,145.819,153.87,157.974,120.109,170.3,175.048,109.32,149.065,101.028,140.762,165.956,170.908,175.027,178.068,149.994,170.745,179.366,185.966,192.174,197.32,200.259,202.076,202.535,154.572,164.414,166.884,174.486,176.387,178.025,204.757,210.312,220.123,221.309,221.617,140.317,225.154,228.801,229.885,165.174,173.019,173.36,177.816,181.052,182.994,149.622,158.233,160.982,165.905,167.429,168.374,80.5815,116.712,118.271,118.93,125.247,140.22,154.359,205.759,211.3,165.521,174.912,181.001,186.14,190.627,194.053,114.668,102.757,144.803,159.823,48.2691,56.242,159.433,165.185,72.7511,42.4663,83.9338,144.514,180.009,188.914,110.703,87.9125,97.779,145.296,168.281,173.792,177.954,180.811,183.114,184.517,201.65,209.666,214.278,217.285,218.057,159.167,154.42,176.066,96.4154,138.286,161.029,164.595,168.424,171.646,109.48,157.839,50.6088,203.718,205.163,154.869,159.086,126.929,64.5534,129.221,45.0469", "env/episode_length": "72.8834,288.669,300.396,186.53,135.576,148.584,112.79,64.9688,93.3742,81.2225,142.214,192.152,207.702,316.248,335.468,101.28,59.7181,302.815,324.689,337.285,345.02,264.362,296.449,334.83,345.604,360.935,363.098,138.975,178.359,220.089,260.899,307.63,119.772,108.387,148.868,68.9921,316.564,328.685,114.119,64.5679,162.984,171.936,173.868,174.915,191.958,183.939,189.502,160.792,359.521,372.837,382.98,375.56,153.622,121.462,126.9,187.001,192.156,197.274,130.915,313.728,350.199,373.897,389.944,405.875,448.145,453.393,462.437,133.038,149.305,177.21,182.985,399.273,409.259,442.052,458.638,172.247,109.824,161.601,291.771,194.805,105.144,153.075,170.467,172.987,175.073,176.939,177.947,178.711,179.012,90.8472,102.882,156.53,87.7398,211.586,116.175,191.266,316.902,339.497,355.249,117.276,173.772,112.687,161.659,147.582,102.26,140.229,78.7263,165.964,173.121,178.684,127.277,171.221,177.794,181.452,142.962,177.95,183.363,108.114,166.117,82.0001,123.466,156.467,171.733,172.442,125.574,198.823,208.22,126.228,166.644,117.408,156.819,187.137,197.022,205.353,213.489,155.988,204.185,222.354,234.767,250.128,262.274,268.944,273.147,106.821,175.552,184.695,188.346,200.355,203.358,205.725,293.931,313.039,351.453,346.107,361.934,156.451,377.5,398.68,225.579,185.041,199.533,200.688,208.894,215.691,220.373,165.371,172.288,175.081,181.494,183.858,185.045,97.5973,137.738,128.219,140.402,131.971,161.996,171.666,281.263,298.171,185.869,201.833,216.037,230.777,243.507,253.694,121,121.122,164.376,174.728,69.9998,75.7233,173.642,181.627,91.3843,74.2675,107.046,165.757,213.107,237.267,136.156,105.986,118.613,163.063,201.953,212.351,221.003,225.103,229.606,232.207,289.804,311.584,320.665,329.895,321.961,168.857,164.776,200.252,118.485,153.121,175.155,181.431,187.288,199.133,127.92,173.348,67.2214,288.362,293.761,168.991,171.554,132.913,81.0726,146.896,60.9717", "env/n": "1570.23,1810.19,1739.81,696.529,1846.05,915.988,567.306,488.959,680.906,752.094,939.075,670.837,624.098,3273.94,3089.62,1232.28,1830.07,1718.14,1603.18,1533,1498.07,10363,1748.31,1563.62,1503.47,1462.27,1442.8,964.138,728.754,2357.54,1993.5,1697.08,2145.54,1164.07,852.571,821.059,3280.75,3171.81,1118.85,3369.05,800.31,758.881,751.977,749.952,1338.23,1397.64,1358.12,851.394,2894.12,2801.52,2728.21,10964,849.024,535.77,1046.54,698.306,679.81,663.452,1916.62,3307.95,2910.55,2676.76,2478.74,2323.53,2209.18,2134.89,10600,1904.1,901.571,2889.21,2806.89,1314.45,1271.74,1154.22,1126.23,10046,1065,769.738,10037,2663.55,1209.62,851.227,2976.79,2938.29,2917.29,2885.5,2877.86,2860,2865.71,1919.16,556.106,395.6,676.624,2456.85,284.727,1361.71,3277.78,3060.29,2935.28,1099.84,745.238,1034.35,770.021,881.196,1234.81,916.905,783.071,788.49,752.941,733.686,1062.57,759.897,734.059,720.029,901.345,731.684,712.228,1155.79,1534.09,1483.49,1044.79,1579.95,1531.76,1516.95,977.048,646.661,621.951,260.635,194.089,1087.79,821.81,2786.13,2648.32,2539.13,2446.6,1582.38,1275.34,1173.14,1108.39,1041.51,996.029,972.657,957.657,10533,1477.84,1411.16,1384.16,1305.28,1284.48,1272.8,1770.85,1658.74,1518.45,1528.34,1380.82,429.502,5053.2,4272.8,11444,1389.37,1297.67,1289,1242.85,1206.52,1179.59,1555.17,1502.87,1484.78,1436.3,1421.26,1413.22,1264.55,970.913,1960.95,488.118,1920.9,802.878,763.26,3688,3486.12,1379.4,1280.65,1200.29,1125.24,1069.77,1026.5,2029.37,579.188,1567.14,1487.44,453.7,1508.3,2993.07,2871,2640.35,1555.87,1189.05,771.5,2432.63,2189.14,490.287,1192.35,1069.28,798.286,1288.42,1229.31,1182.39,1160.97,1139.9,1128.32,3565.86,3347.8,3239.43,3176.57,12587,3019.23,1508.27,1295.5,1076.05,848.024,2872.09,2796.2,2733.9,1295.62,2046.11,1492.4,1624.7,1802.36,1776.76,1532.63,1517.67,930.337,761.706,442.165,1792.26", "perf/rollout": "0.0125996,0.0497063,0.0453106,0.0256059,0.0243795,0.0334101,0.0125065,0.00369452,0.0163444,0.0154429,0.0482982,0.0482515,0.047736,0.362326,0.360229,0.0187669,0.0146044,0.0605465,0.0621633,0.0637149,0.0626358,0.0676665,0.230747,0.224027,0.224069,0.223992,0.223785,0.0154558,0.0148403,0.075284,0.0754782,0.0751784,0.0216946,0.0321569,0.0308714,0.0134471,0.396694,0.399086,0.0181991,0.0265351,0.0193226,0.0183911,0.0186559,0.0188895,0.0657558,0.119931,0.119198,0.0219441,0.461564,0.467049,0.466539,0.468059,0.0156968,0.00899591,0.0149027,0.0139341,0.0136424,0.0135596,0.0230332,0.215207,0.209902,0.198668,0.217826,0.228042,0.228786,0.237962,0.236193,0.031049,0.0348136,0.121975,0.122509,0.0659735,0.0737842,0.0715742,0.078393,0.0751271,0.0332651,0.0324559,0.0847576,0.0506495,0.0169151,0.0153308,0.0399571,0.0390502,0.0407172,0.0408747,0.0409997,0.0390262,0.0390491,0.147432,0.0180242,0.0175643,0.00846576,0.044274,0.00813556,0.0443932,0.472051,0.472608,0.470018,0.0157476,0.0160316,0.018505,0.0178755,0.0479296,0.0230914,0.0229918,0.0165386,0.0215499,0.0222161,0.0217209,0.0215152,0.0212505,0.0209417,0.0209704,0.0312752,0.0322693,0.0322521,0.0183462,0.0535687,0.0157804,0.0143793,0.0241066,0.0530234,0.0415255,0.0566571,0.054011,0.0493988,0.00818401,0.00800256,0.0310055,0.0304396,0.0397066,0.0397853,0.0397011,0.0397111,0.0380118,0.0227858,0.0227727,0.0229438,0.0228992,0.0227989,0.0229413,0.0230956,0.0259039,0.0214124,0.0214333,0.0211537,0.0212039,0.0217484,0.0213419,0.0749761,0.074522,0.0750521,0.0691315,0.197111,0.0177362,0.829151,0.813986,0.804531,0.0284916,0.0289633,0.0284768,0.0287707,0.0290251,0.0285926,0.0337549,0.033319,0.0339645,0.033162,0.0328745,0.0322492,0.0674145,0.0174323,0.02721,0.0108556,0.165992,0.013748,0.0136708,0.538872,0.58411,0.080388,0.0772118,0.0782667,0.0779209,0.079588,0.0824378,0.0660087,0.0160995,0.0538109,0.142743,0.0105378,0.017964,0.054309,0.0538739,0.0263373,0.0161231,0.0178451,0.0163448,0.128808,0.129209,0.013298,0.0136629,0.0410336,0.0401313,0.0365172,0.0349687,0.0350354,0.0346081,0.0352568,0.0353039,0.131116,0.133603,0.128109,0.13009,0.117686,0.256451,0.0253309,0.0631726,0.0187988,0.0164009,0.067071,0.0654105,0.0645523,0.043806,0.0513721,0.0507218,0.0139321,0.0545499,0.0569736,0.0414646,0.0428321,0.0400146,0.00924687,0.00873982,0.0181266", "perf/eval_gpu": "0.0050919,0.0173562,0.016247,0.0080879,0.0070293,0.0134398,0.00371928,0.00117387,0.00731359,0.00703965,0.0314786,0.0315114,0.0314511,0.231219,0.23315,0.00652078,0.00571597,0.019843,0.0191841,0.0190743,0.0192031,0.0192046,0.19579,0.199491,0.197991,0.201458,0.201691,0.00597748,0.00583927,0.0442231,0.0439636,0.043961,0.00779358,0.00646528,0.00626339,0.00443911,0.311168,0.307249,0.00616009,0.00805937,0.00573177,0.00566113,0.00562221,0.00558327,0.0341267,0.0870961,0.0871968,0.010112,0.372758,0.381665,0.376864,0.364035,0.00391242,0.00373671,0.00598143,0.0051087,0.0051374,0.00510991,0.00653308,0.108357,0.110267,0.116074,0.102738,0.0994924,0.103506,0.103829,0.111851,0.0132403,0.0184446,0.044151,0.0446109,0.0389897,0.0465829,0.0450056,0.0503712,0.0491375,0.0165168,0.0160207,0.0165585,0.0170958,0.00365981,0.0036981,0.012209,0.0119562,0.0123559,0.0121878,0.0123957,0.0117883,0.0118002,0.111685,0.00893081,0.00884878,0.00334521,0.0152348,0.0036964,0.0115008,0.362413,0.359058,0.366791,0.00727885,0.00710541,0.00870792,0.0081095,0.0308054,0.00647735,0.00631055,0.00552497,0.00524169,0.00532165,0.00527126,0.00672091,0.00673519,0.00669676,0.00667368,0.0135001,0.0164743,0.0164682,0.00564568,0.020444,0.00416248,0.0042155,0.00939037,0.00687178,0.00685636,0.0390573,0.0351121,0.0308042,0.00494737,0.00482019,0.0133258,0.0132569,0.0140233,0.0140879,0.013994,0.0139478,0.0139636,0.00805894,0.00805566,0.00805454,0.00801505,0.007943,0.00803522,0.00803504,0.0093116,0.00759368,0.00761152,0.00756538,0.00751136,0.00766969,0.00756923,0.0319404,0.0325771,0.0315462,0.0326493,0.1563,0.00918805,0.625202,0.653165,0.670953,0.0111472,0.0111749,0.0111033,0.0111552,0.011209,0.0111219,0.0101419,0.0100173,0.011271,0.00990476,0.0100026,0.00961509,0.0495364,0.00496979,0.00909684,0.00294047,0.126425,0.00439435,0.00439373,0.341011,0.395026,0.0454849,0.0452192,0.0453878,0.0452287,0.0453676,0.0461593,0.0168141,0.00589274,0.012012,0.104994,0.00562217,0.00563158,0.0111593,0.0111594,0.00791469,0.00678787,0.00566628,0.00544774,0.0846326,0.0842781,0.00443704,0.00531379,0.00670185,0.00657471,0.00876999,0.00851109,0.0084809,0.00849127,0.0085237,0.00858576,0.0270774,0.0270997,0.0272417,0.0267974,0.0265059,0.181954,0.00895114,0.0305612,0.00484298,0.0043284,0.020192,0.0196663,0.0194142,0.0262919,0.013091,0.0132373,0.0046022,0.0191422,0.0191909,0.00943386,0.00982305,0.0238174,0.00272936,0.00261942,0.00603102", "perf/eval_env": "0.00638037,0.0250691,0.0253302,0.0164754,0.0161539,0.0191757,0.00800929,0.00186417,0.00857073,0.007942,0.0155408,0.0154816,0.0150243,0.10516,0.103899,0.0110643,0.00772704,0.0341152,0.0355458,0.0364875,0.0355944,0.0360732,0.0266234,0.0205839,0.0213757,0.018958,0.0189002,0.0084177,0.00798999,0.0259102,0.0261683,0.025768,0.0120038,0.0235324,0.0225607,0.00811526,0.0796782,0.0824557,0.0109103,0.0154744,0.0118958,0.0113146,0.0114552,0.0114917,0.0301843,0.0313341,0.0305047,0.0105076,0.0692044,0.0626574,0.0661857,0.0727686,0.0110614,0.00415837,0.00579355,0.00547465,0.00532063,0.00529582,0.0154015,0.08496,0.0812088,0.0747294,0.0904961,0.0946453,0.0915303,0.0914196,0.0855999,0.0157891,0.0155678,0.0761002,0.0762189,0.0243233,0.0239926,0.0234311,0.0244039,0.0229431,0.0154759,0.0151633,0.0468749,0.031214,0.0115447,0.0102552,0.0238556,0.0234999,0.0241104,0.024402,0.0242489,0.0235738,0.0236042,0.0332435,0.00757946,0.00718271,0.00397886,0.0262172,0.00405897,0.0289466,0.0858908,0.0908074,0.0854086,0.00711238,0.00640416,0.0078031,0.00753782,0.0158605,0.0146583,0.0143769,0.0105206,0.0150594,0.0154186,0.0151723,0.012907,0.0125354,0.0124019,0.0124012,0.0158035,0.0150381,0.0150244,0.0112521,0.0310157,0.00943146,0.00848092,0.012611,0.033036,0.0300433,0.0163667,0.0176261,0.0173509,0.00169636,0.00161303,0.0168886,0.016395,0.0198558,0.0197669,0.0199459,0.0199883,0.0209207,0.0127631,0.0127654,0.0129348,0.012925,0.0129432,0.0130011,0.01304,0.0137521,0.0115568,0.0115389,0.0113569,0.0114354,0.011707,0.0115255,0.033806,0.0328841,0.0340349,0.0294264,0.0314228,0.00755495,0.161533,0.140416,0.126676,0.0123947,0.0126978,0.0124667,0.0125809,0.0127428,0.0125516,0.0218696,0.0216963,0.0214631,0.0220506,0.02169,0.0215164,0.0170825,0.0109844,0.0167144,0.00673765,0.0381044,0.00839578,0.0083523,0.164532,0.169812,0.0334922,0.0305818,0.0314699,0.0312817,0.0328037,0.0348913,0.0461766,0.00973737,0.0387769,0.0366221,0.00461094,0.0111929,0.0330114,0.0327239,0.0169181,0.00766017,0.0109272,0.00989286,0.0358006,0.0365865,0.00815571,0.00668013,0.0332742,0.0327602,0.0240781,0.0237207,0.0237717,0.0234697,0.0238747,0.0237018,0.0903099,0.0911991,0.0900455,0.0908432,0.0862135,0.0723007,0.0143655,0.0311707,0.011867,0.0109946,0.0434023,0.0428815,0.0426246,0.011957,0.0365583,0.0359618,0.00830879,0.0287493,0.0319763,0.0299744,0.0287738,0.0149095,0.00490825,0.00454891,0.0107566", "perf/train_misc": "0.000755515,0.00970612,0.00970632,0.0011741,0.00235531,0.00133945,0.00061794,0.000104649,0.000406595,0.000353598,0.00497628,0.00445081,0.00445646,0.0672386,0.0673737,0.00154665,0.000463643,0.0082721,0.00826307,0.00827323,0.00827457,0.00824435,0.0227417,0.022789,0.0227793,0.0227832,0.0228052,0.00244862,0.00209342,0.0256915,0.0256983,0.0256832,0.00414896,0.00132883,0.00105059,0.000354943,0.0556108,0.0557106,0.00124099,0.00151974,0.000536584,0.00053621,0.000536618,0.00053602,0.00762865,0.00489988,0.00491506,0.00572128,0.0519735,0.0520304,0.0520254,0.0517898,0.000905717,0.000334098,0.0022541,0.00189235,0.00188537,0.00188716,0.00157498,0.0792852,0.0793868,0.0793932,0.0793333,0.0793133,0.0793058,0.0792468,0.0789342,0.00259945,0.0018708,0.0062058,0.00620619,0.0148596,0.0198557,0.0149007,0.014999,0.0149248,0.00438694,0.0034857,0.00918016,0.0190085,0.000939219,0.000745929,0.00436497,0.00438613,0.00438832,0.00438153,0.00438199,0.00438581,0.00438425,0.0091833,0.000825193,0.000727986,0.000248139,0.0114327,0.000245041,0.00228357,0.0621191,0.0621954,0.0621648,0.00300627,0.00238839,0.00435642,0.00356025,0.00443084,0.00143846,0.00114615,0.000169825,0.000755657,0.000754416,0.000753865,0.00121793,0.00104827,0.00104611,0.00104673,0.00314581,0.00110697,0.00110602,0.000905019,0.00552399,0.000819357,0.000650961,0.00745119,0.00518865,0.00519923,0.00541037,0.00464234,0.0031604,0.000323623,0.000302238,0.00156492,0.00124333,0.00731278,0.00731738,0.00731283,0.00732249,0.00680241,0.0095267,0.00952345,0.00951706,0.0095115,0.00950622,0.00951868,0.00951699,0.0095191,0.00494592,0.00495013,0.00494996,0.004946,0.00495589,0.00494152,0.0187984,0.0187803,0.0187715,0.0187954,0.0160594,0.00114534,0.0736849,0.0739237,0.073556,0.00602978,0.0060297,0.00603513,0.0060399,0.0060173,0.00601442,0.00176219,0.00175842,0.00176209,0.00176021,0.00176322,0.00176277,0.00154401,0.00117001,0.00113235,0.00063953,0.0136886,0.000829032,0.000828697,0.07135,0.0715184,0.0103771,0.0103692,0.010367,0.010362,0.0103807,0.0103802,0.00837404,0.000442204,0.00277417,0.00930773,0.000132475,0.000561878,0.0334903,0.0334577,0.00234913,0.00132596,0.00133628,0.00105764,0.0197696,0.0197608,0.000430142,0.0008817,0.00242884,0.00191896,0.00458007,0.00458044,0.00457763,0.00458225,0.00457762,0.0045775,0.0379677,0.0379654,0.0379641,0.0378745,0.0379339,0.0191129,0.00140073,0.00269519,0.00254406,0.00201712,0.0104177,0.0104036,0.0104125,0.0053508,0.00467108,0.00355599,0.00110663,0.0265809,0.0265981,0.00366886,0.0036653,0.00280017,0.000318024,0.000279316,0.000403423", "perf/train_forward": "0.00522206,0.193594,0.193652,0.0210773,0.00743879,0.0236252,0.00862004,0.000676637,0.00859617,0.00422047,0.299599,0.268023,0.268507,3.6468,3.65517,0.00953137,0.00407238,0.170224,0.170223,0.170223,0.170234,0.170302,2.61293,2.57516,2.57495,2.5763,2.57663,0.047325,0.0404916,0.953181,0.953708,0.954892,0.0279876,0.00647458,0.00512624,0.00195682,4.91868,4.92855,0.00785336,0.0064763,0.00583779,0.00583963,0.00584317,0.0058398,0.220363,0.572191,0.572726,0.157359,3.37574,3.37602,3.37879,3.3722,0.00265264,0.00646433,0.0274218,0.0233005,0.0232928,0.023297,0.00568801,1.7406,1.74098,1.74141,1.74187,1.74962,1.76467,1.77212,1.77243,0.0652912,0.0715136,0.0889532,0.0889253,0.490003,0.50053,0.504208,0.525982,0.493312,0.0760127,0.0607532,0.165707,0.336588,0.00402589,0.0031634,0.0238652,0.0238226,0.0238248,0.0238226,0.0238504,0.0238714,0.0238821,1.03673,0.0289665,0.025684,0.00169426,0.231942,0.00324773,0.0373529,6.37999,6.39144,6.38805,0.0839936,0.0669443,0.0750099,0.0614827,0.240213,0.0177724,0.0141093,0.000554162,0.00911673,0.00911432,0.00911661,0.0154866,0.0133277,0.0133256,0.0133322,0.102326,0.0430818,0.0431038,0.00400738,0.134241,0.00302846,0.00237093,0.0654371,0.0338538,0.0338809,0.290665,0.241661,0.235321,0.0238478,0.022412,0.0283451,0.0225164,0.0531741,0.0531774,0.0531851,0.053138,0.0854952,0.142924,0.142958,0.142936,0.142985,0.143094,0.143141,0.143361,0.143442,0.0856162,0.0856058,0.0856041,0.0855995,0.0855706,0.0856181,0.526739,0.526856,0.528066,0.529389,1.67459,0.0799865,8.39643,8.40463,8.36827,0.0980569,0.0981069,0.0980544,0.0980769,0.0980068,0.0980469,0.0183046,0.0183047,0.0196266,0.0182908,0.0184128,0.0183127,0.356078,0.0120746,0.0087995,0.00550263,1.85878,0.00476801,0.00476378,4.73018,4.72726,0.411459,0.411447,0.411365,0.411379,0.411361,0.411329,0.108308,0.00431695,0.0178105,1.38124,0.00430347,0.00167673,0.155295,0.155263,0.0100032,0.0237106,0.0100509,0.00784377,1.47454,1.47483,0.00419327,0.00991506,0.0280627,0.0222587,0.0437592,0.0437636,0.0438788,0.0437701,0.0437471,0.0437795,0.477065,0.477094,0.477251,0.477024,0.477478,2.02056,0.00895113,0.0585566,0.012773,0.0101473,0.0864559,0.0863708,0.0862906,0.221549,0.044716,0.0340319,0.00544116,0.436456,0.436964,0.0285858,0.0286269,0.103257,0.00314806,0.00276486,0.00157358", "perf/train": "0.00597758,0.2033,0.203358,0.0222514,0.0097941,0.0249646,0.00923798,0.000781286,0.00900277,0.00457407,0.304576,0.272473,0.272964,3.71404,3.72254,0.011078,0.00453602,0.178496,0.178486,0.178496,0.178509,0.178547,2.63567,2.59794,2.59773,2.59908,2.59944,0.0497736,0.0425851,0.978873,0.979407,0.980575,0.0321365,0.00780341,0.00617684,0.00231177,4.97429,4.98426,0.00909435,0.00799604,0.00637437,0.00637584,0.00637979,0.00637582,0.227992,0.577091,0.577641,0.16308,3.42772,3.42805,3.43082,3.42399,0.00355835,0.00679843,0.0296759,0.0251929,0.0251782,0.0251841,0.00726299,1.81988,1.82037,1.8208,1.82121,1.82893,1.84398,1.85137,1.85137,0.0678907,0.0733844,0.095159,0.0951315,0.504862,0.520386,0.519109,0.540981,0.508237,0.0803996,0.0642389,0.174887,0.355597,0.00496511,0.00390933,0.0282302,0.0282087,0.0282131,0.0282041,0.0282324,0.0282572,0.0282664,1.04591,0.0297917,0.026412,0.0019424,0.243375,0.00349277,0.0396365,6.44211,6.45363,6.45021,0.0869999,0.0693327,0.0793663,0.065043,0.244644,0.0192109,0.0152554,0.000723987,0.00987239,0.00986874,0.00987048,0.0167045,0.014376,0.0143717,0.0143789,0.105472,0.0441887,0.0442099,0.0049124,0.139765,0.00384781,0.00302189,0.0728883,0.0390425,0.0390801,0.296075,0.246303,0.238481,0.0241715,0.0227142,0.02991,0.0237597,0.0604869,0.0604948,0.060498,0.0604605,0.0922976,0.152451,0.152481,0.152453,0.152496,0.1526,0.15266,0.152878,0.152961,0.0905621,0.090556,0.0905541,0.0905455,0.0905265,0.0905596,0.545537,0.545636,0.546837,0.548184,1.69065,0.0811318,8.47012,8.47855,8.44183,0.104087,0.104137,0.104089,0.104117,0.104024,0.104061,0.0200668,0.0200631,0.0213887,0.020051,0.020176,0.0200755,0.357622,0.0132446,0.00993185,0.00614216,1.87247,0.00559705,0.00559247,4.80153,4.79878,0.421836,0.421816,0.421732,0.421741,0.421742,0.421709,0.116682,0.00475915,0.0205846,1.39055,0.00443595,0.00223861,0.188785,0.188721,0.0123524,0.0250365,0.0113872,0.0089014,1.49431,1.4946,0.00462342,0.0107968,0.0304916,0.0241776,0.0483393,0.0483441,0.0484564,0.0483523,0.0483247,0.048357,0.515033,0.51506,0.515215,0.514899,0.515412,2.03968,0.0103519,0.0612518,0.0153171,0.0121644,0.0968735,0.0967744,0.0967032,0.2269,0.049387,0.0375879,0.0065478,0.463037,0.463562,0.0322547,0.0322922,0.106057,0.00346608,0.00304418,0.001977", "util/gpu_percent": "27.5116,98.9459,100,73.3647,85,69.881,57.3176,28.2353,55.0941,50.7294,94.4516,95.2065,94.4891,100,100,48.8372,65.3023,93.9091,96.25,94.2955,97.0465,97,100,100,100,100,100,91.5077,97.8154,99.641,99.7105,99.7949,85.1143,31.6977,45.4524,61.6706,100,100,57.3455,57.9545,68.5714,69.5,70.3488,66.3333,90.2308,96.7879,96.7188,96.9358,100,100,100,100,65.2857,71.8333,85.6508,97.8548,98,98,81.7692,100,100,100,100,100,100,100,100,93.3,83.2959,60.1053,55.0526,100,99.9123,99.7586,99.9298,100,84.186,82.2143,82,99.7241,53.6,69.1136,97.1429,98.7143,99,99,98.2143,98.7143,99,97.4419,82.5294,85.2353,51.3882,99.7,42.8068,73.1905,100,100,100,99.1163,98.5476,98.6122,98.8333,94.0093,72.4651,72.5714,29.5176,69.5882,67.4118,66.8431,66.7941,80.25,78.9706,80.6324,89.9,73.0175,75.4386,35.5862,88.1364,33.2093,63.2857,97.8571,63.9524,71.1429,95.4032,94.0161,93.6885,99.1882,99,71.3721,67.0952,94.7333,95.6129,95.6667,95.3667,93.1429,99.4571,99.3714,99.1667,99.4857,99.1429,99.3143,99.3143,100,99,99.44,99.64,99,99.16,99.2,99.3404,99.2766,99.1489,97.9574,100,95.2326,100,100,100,99.3333,99.5556,99.4815,99.1481,99,99.2963,78.7391,77.6957,76.6087,77.6522,77.6087,78.5217,100,74.9375,85.0952,54.6706,100,80.449,80,100,100,100,100,100,100,99.2857,84.8529,76.2333,41.7521,52.9524,100,49.0353,1,94.0667,97.8667,41.5,52.9565,35.0233,79.0476,100,100,62.965,71.7407,62.0698,56.2857,80.5161,87.5,88.7097,87.4194,81.3871,80.6129,95,96.6,96.9286,96.6429,100,100,83.3077,66.2045,30.8372,78,93.8182,91,78.2,99.1351,63.6571,66.9714,53.814,99.1364,98.9524,66.6296,67.7407,91.1875,37.6235,78.5059,23", "util/gpu_mem": "5.84214,12.0463,12.0463,6.53421,5.78514,6.3388,5.13378,5.4269,21.4254,4.88952,7.20185,7.20185,7.20185,15.9545,15.9545,5.30477,6.94131,11.5904,11.5904,11.5904,11.5904,11.5904,34.7029,31.8853,31.5331,30.3004,30.3004,6.39579,6.39579,13.6422,13.6422,13.6422,6.56677,4.9628,4.9628,17.9353,20.1965,20.1965,5.2722,6.61563,7.37283,7.37283,7.37283,7.37283,6.41208,11.6392,11.6392,21.4417,24.5199,24.5199,24.5199,24.5199,5.09307,7.24256,21.7429,21.7429,21.7429,21.7429,6.13525,16.8013,16.8013,16.8013,16.8013,16.8013,16.8013,16.8013,16.8013,24.2588,7.03901,7.95906,7.95906,26.4002,26.0399,26.2101,26.0133,26.4002,5.0198,5.0198,10.9879,10.3447,5.76072,5.76072,23.8924,23.8924,23.8924,23.8924,23.8924,23.8924,23.8924,12.7791,6.0294,6.0294,5.50832,12.0463,4.66155,7.9672,21.9714,21.9714,21.9714,7.47868,7.47868,6.07011,6.07011,21.9575,6.19224,6.19224,4.6127,6.72147,6.72147,6.72147,5.89913,5.89913,5.89913,5.89913,6.66448,23.3795,23.3795,5.31291,6.55863,5.39433,5.39433,6.58306,6.56677,6.56677,23.9071,24.2137,24.5194,22.7933,22.7933,6.3388,6.3388,8.79768,8.79768,8.79768,8.79768,6.27366,7.39726,7.39726,7.39726,7.39726,7.39726,7.39726,7.39726,7.39726,23.5586,23.5586,23.5586,23.5586,23.5586,23.5586,11.7695,11.7695,11.7695,11.7695,31.2553,7.9672,33.4354,33.4354,33.4354,7.57638,7.57638,7.57638,7.57638,7.57638,7.57638,21.9872,21.9872,21.9872,20.4023,20.8958,21.9872,18.4052,6.07011,6.77032,4.79996,11.1914,5.777,5.777,23.5998,23.5998,7.29955,7.29955,7.29955,7.29955,7.29955,7.29955,6.00498,5.13378,6.03754,11.9161,7.74736,20.0331,7.85321,7.85321,6.13525,8.24403,5.58974,5.58974,13.0641,13.0641,5.29662,6.57492,5.66301,5.66301,6.46093,6.46093,6.46093,6.46093,6.46093,6.46093,14.7739,14.7739,14.7739,14.7739,14.7739,12.5186,21.5313,6.76218,5.2152,5.2152,7.64152,7.64152,7.64152,9.77472,6.15967,6.15967,5.50017,8.8791,8.8791,6.24924,6.24924,6.24924,5.45946,5.45946,5.9317", "util/vram_used_gb": "0.940308,2.42859,2.42859,1.10632,0.926636,1.05945,0.770386,0.840698,4.67847,0.711792,1.26648,1.26648,1.26648,3.36609,3.36609,0.811401,1.20398,2.31921,2.31921,2.31921,2.31921,2.31921,7.86351,7.18762,7.10314,6.80743,6.80743,1.07312,1.07312,2.8114,2.8114,2.8114,1.11414,0.72937,0.72937,3.84125,4.38367,4.38367,0.803589,1.12585,1.3075,1.3075,1.3075,1.3075,1.07703,2.33093,2.33093,4.68237,5.42078,5.42078,5.42078,5.42078,0.76062,1.27625,4.75464,4.75464,4.75464,4.75464,1.01062,3.56921,3.56921,3.56921,3.56921,3.56921,3.56921,3.56921,3.56921,5.35815,1.22742,1.44812,1.44812,5.87183,5.78541,5.82623,5.77903,5.87183,0.743042,0.743042,2.17468,2.02039,0.920776,0.920776,5.27026,5.27026,5.27026,5.27026,5.27026,5.27026,5.27026,2.60437,0.985229,0.985229,0.860229,2.42859,0.657104,1.45007,4.80945,4.80945,4.80945,1.33289,1.33289,0.994995,0.994995,4.8061,1.02429,1.02429,0.645386,1.15125,1.15125,1.15125,0.953979,0.953979,0.953979,0.953979,1.13757,5.14722,5.14722,0.813354,1.11218,0.832886,0.832886,1.11804,1.11414,1.11414,5.27379,5.34733,5.42065,5.00659,5.00659,1.05945,1.05945,1.64929,1.64929,1.64929,1.64929,1.04382,1.31335,1.31335,1.31335,1.31335,1.31335,1.31335,1.31335,1.31335,5.19019,5.19019,5.19019,5.19019,5.19019,5.19019,2.36218,2.36218,2.36218,2.36218,7.03648,1.45007,7.55945,7.55945,7.55945,1.35632,1.35632,1.35632,1.35632,1.35632,1.35632,4.81323,4.81323,4.81323,4.43304,4.55142,4.81323,3.95398,0.994995,1.16296,0.690308,2.22351,0.924683,0.924683,5.20007,5.20007,1.28992,1.28992,1.28992,1.28992,1.28992,1.28992,0.97937,0.770386,0.987183,2.39734,1.39734,4.34448,1.42273,1.42273,1.01062,1.51648,0.879761,0.879761,2.67273,2.67273,0.809448,1.11609,0.897339,0.897339,1.08875,1.08875,1.08875,1.08875,1.08875,1.08875,3.08289,3.08289,3.08289,3.08289,3.08289,2.54187,4.70386,1.16101,0.789917,0.789917,1.37195,1.37195,1.37195,1.88367,1.01648,1.01648,0.858276,1.66882,1.66882,1.03796,1.03796,1.03796,0.848511,0.848511,0.961792", "util/vram_total_gb": "23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272", "util/cpu_mem_gb": "1.15167,1.2865,1.2865,1.13164,1.16483,1.11842,1.10952,1.12193,1.0369,1.11575,1.1209,1.1209,1.1209,1.29784,1.29784,1.12745,1.14403,1.26161,1.26161,1.26161,1.26161,1.26161,1.22021,1.22021,1.22021,1.22021,1.22021,1.15062,1.15103,1.29874,1.29874,1.29874,1.16645,1.12639,1.12639,1.02492,1.2848,1.2848,1.13054,1.17589,1.14901,1.14921,1.1495,1.1495,1.13964,1.12467,1.12467,1.07077,1.40898,1.40898,1.40898,1.40898,1.15126,1.12343,1.09954,1.09954,1.09954,1.09954,1.16171,1.38656,1.38656,1.38656,1.38656,1.38656,1.38656,1.38656,1.38656,1.1139,1.11341,1.15878,1.15878,1.16961,1.16961,1.16961,1.16961,1.16961,1.11619,1.11619,1.25613,1.28027,1.15745,1.15762,1.14354,1.14354,1.14354,1.14354,1.14354,1.14354,1.14354,1.1349,1.10717,1.10717,1.11939,1.28798,1.10046,1.16648,1.31722,1.31722,1.31722,1.17495,1.17495,1.14587,1.14608,1.03738,1.13604,1.13604,1.11296,1.1554,1.1554,1.15588,1.13799,1.13799,1.13838,1.13848,1.14427,1.03392,1.03398,1.12646,1.1576,1.15472,1.15472,1.16278,1.20649,1.20649,1.03804,1.03804,1.0381,1.03698,1.03698,1.11897,1.11897,1.28054,1.28054,1.2807,1.28103,1.15979,1.21581,1.21581,1.21581,1.21581,1.21581,1.21581,1.21581,1.21581,1.14626,1.14626,1.14626,1.14674,1.14674,1.14674,1.25997,1.25997,1.26009,1.26046,1.23972,1.11604,1.42398,1.42398,1.42398,1.23936,1.23936,1.23985,1.23985,1.23985,1.23985,1.09039,1.09039,1.09039,1.09039,1.09039,1.09039,1.11766,1.14669,1.17062,1.1286,1.13013,1.15291,1.15291,1.35913,1.35913,1.1291,1.1291,1.1291,1.1291,1.1291,1.12945,1.14616,1.11495,1.15358,1.16061,1.10732,1.04562,1.23775,1.23775,1.16077,1.15932,1.1335,1.1335,1.22355,1.22355,1.11744,1.14634,1.15385,1.15385,1.18018,1.18018,1.18018,1.18018,1.18018,1.18018,1.38701,1.38701,1.38701,1.38701,1.38701,1.17868,1.07472,1.13348,1.1514,1.1514,1.17982,1.17982,1.17982,1.26773,1.1451,1.1451,1.1333,1.26382,1.26382,1.16213,1.16213,1.11235,1.11921,1.11961,1.13343", "wandb": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "rank": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "world_size": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "gpu_id": "5,5,5,1,4,4,2,3,0,2,5,5,5,1,1,4,4,2,2,2,2,2,0,0,0,0,0,2,2,1,1,1,3,3,3,0,5,5,4,1,3,3,3,3,3,2,2,0,1,1,1,1,1,4,0,0,0,0,1,2,2,2,2,2,2,2,2,0,3,1,1,0,0,0,0,0,5,5,2,2,1,1,0,0,0,0,0,0,0,2,2,2,3,4,5,2,2,2,2,2,2,2,2,0,1,1,2,2,2,2,5,5,5,5,1,0,0,4,2,2,2,2,1,1,0,0,0,0,0,4,4,5,5,5,5,1,2,2,2,2,2,2,2,2,0,0,0,0,0,0,4,4,4,4,0,1,5,5,5,4,4,4,4,4,4,0,0,0,0,0,0,3,1,2,2,4,4,4,3,3,1,1,1,1,1,1,3,4,3,2,1,0,3,3,3,2,4,4,2,2,3,1,4,4,1,1,1,1,1,1,2,2,2,2,2,3,0,1,2,2,3,3,3,2,4,4,1,5,5,4,4,4,2,2,2", "profile": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "checkpoint_interval": "200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200", "eval_episodes": "10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000", "cudagraphs": "10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10", "seed": "73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73", "vec/total_agents": "2048,8192,8192,2048,4096,2048,2048,2048,2048,2048,1024,1024,1024,8192,8192,2048,2048,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,2048,2048,8192,8192,8192,4096,2048,2048,1024,8192,8192,2048,4096,4096,4096,4096,4096,2048,2048,2048,2048,16384,16384,16384,16384,4096,1024,2048,2048,2048,2048,4096,16384,16384,16384,16384,16384,16384,16384,16384,2048,2048,4096,4096,4096,4096,4096,4096,4096,1024,1024,8192,8192,4096,4096,4096,4096,4096,4096,4096,4096,4096,1024,512,512,1024,8192,1024,4096,8192,8192,8192,4096,4096,1024,1024,1024,2048,2048,2048,4096,4096,4096,2048,2048,2048,2048,1024,2048,2048,2048,2048,4096,4096,2048,8192,8192,1024,1024,1024,512,512,2048,2048,8192,8192,8192,8192,2048,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,8192,8192,8192,8192,2048,1024,8192,8192,8192,2048,2048,2048,2048,2048,2048,4096,4096,4096,4096,4096,4096,2048,2048,4096,2048,2048,4096,4096,16384,16384,2048,2048,2048,2048,2048,2048,2048,2048,4096,4096,2048,2048,8192,8192,4096,2048,2048,2048,4096,4096,2048,2048,4096,4096,4096,4096,4096,4096,4096,4096,16384,16384,16384,16384,16384,4096,2048,2048,4096,4096,4096,4096,4096,2048,4096,4096,2048,4096,4096,4096,4096,1024,2048,2048,2048", "vec/num_buffers": "5.91617,7.92929,7.92929,2.76471,4.95839,1,2.846,5.86024,1.74503,1,1.05919,1.05919,1.05919,5.45454,5.45454,3.78717,4.41434,5.09788,5.09788,5.09788,5.09788,5.09788,8,8,8,8,8,4.8334,4.8334,8,8,8,6.09772,2.7411,2.7411,2.62646,4.74154,4.74154,3.19198,5.84119,3.63625,3.63625,3.63625,3.63625,1.15916,1,1,3.52786,8,8,8,8,3.32902,4.58934,8,8,8,8,4.46583,6.73684,6.73684,6.73684,6.73684,6.73684,6.73684,6.73684,6.73684,4.10207,1,1.58017,1.58017,6.56274,6.56274,6.56274,6.56274,6.56274,1,1,5.26923,6.30801,4.09,4.09,7.28742,7.28742,7.28742,7.28742,7.28742,7.28742,7.28742,1.68504,2.93075,2.93075,4.0275,7.72702,1,3.94085,5.5772,5.5772,5.5772,7.24825,7.24825,4.14017,4.14017,1.51349,3.40804,3.40804,1,3.81814,3.81814,3.81814,3.73255,3.73255,3.73255,3.73255,2.33313,1,1,3.46327,2.57628,4.35209,4.35209,5.25083,4.49518,4.49518,1.01336,1.01336,1.01336,5.04469,5.04469,1,1,8,8,8,8,3.64893,7.3283,7.3283,7.3283,7.3283,7.3283,7.3283,7.3283,7.3283,8,8,8,8,8,8,6.78112,6.78112,6.78112,6.78112,5.14754,2.56505,5.8391,5.8391,5.8391,7.44273,7.44273,7.44273,7.44273,7.44273,7.44273,3.37436,3.37436,3.37436,3.37436,3.37436,3.37436,1,4.85976,4.55816,3.1664,1.37251,4.70467,4.70467,4.62825,4.62825,1,1,1,1,1,1,2.27517,1.28658,2.48524,2.29434,1.0602,3.08239,6.18452,6.18452,4.80767,5.6388,3.66818,3.66818,5.46786,5.46786,2.35362,5.31682,2.18696,2.18696,4.31014,4.31014,4.31014,4.31014,4.31014,4.31014,6.64731,6.64731,6.64731,6.64731,6.64731,2.07888,4.12009,1,3.80159,3.80159,3.43597,3.43597,3.43597,6.90791,2.58348,2.58348,4.33883,6.63624,6.63624,3.65476,3.65476,1.61707,4.86753,4.86753,3.11241", "vec/num_threads": "2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2", "vec/num_envs": "4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096", "env/randomize_starting_position": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "env/min_start_timeout": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "env/max_start_timeout": "49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49,49", "env/frightened_time": "35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35", "env/max_mode_changes": "6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6", "env/scatter_mode_length": "70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70", "env/chase_mode_length": "140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140,140", "policy/hidden_size": "64,256,256,256,64,256,512,128,256,256,512,512,512,1024,1024,256,256,256,256,256,256,256,1024,1024,1024,1024,1024,256,256,512,512,512,512,64,64,64,1024,1024,128,128,256,256,256,256,256,1024,1024,256,1024,1024,1024,1024,64,256,256,256,256,256,128,512,512,512,512,512,512,512,512,256,512,128,128,512,512,512,512,512,128,128,256,256,64,64,256,256,256,256,256,256,256,1024,1024,1024,256,256,128,256,1024,1024,1024,512,512,512,512,512,256,256,128,256,256,256,256,256,256,256,256,512,512,128,256,64,64,512,512,512,512,512,512,1024,1024,256,256,128,128,128,128,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,512,512,512,512,1024,512,1024,1024,1024,256,256,256,256,256,256,128,128,128,128,128,128,1024,128,256,128,1024,256,256,1024,1024,512,512,512,512,512,512,256,128,128,1024,512,64,256,256,256,128,128,128,1024,1024,128,256,128,128,128,128,128,128,128,128,256,256,256,256,256,1024,256,256,128,128,256,256,256,512,512,512,128,256,256,256,256,512,512,512,64", "policy/num_layers": "3.27277,7.33989,7.33989,3.67522,1,3.86936,1,1,4.24709,4.08581,8,8,8,6.06,6.06,1.52634,3.34041,7.99398,7.99398,7.99398,7.99398,7.99398,8,8,8,8,8,4.86655,4.86655,8,8,8,1,1,1,1.58859,7.44857,7.44857,2.34798,2.87963,2.39309,2.39309,2.39309,2.39309,7.21284,5.19611,5.19611,7.84457,8,8,8,8,1.75616,2.28708,3.61925,3.61925,3.61925,3.61925,1.76152,8,8,8,8,8,8,8,8,5.86917,4.80987,5.79106,5.79106,5.39388,5.39388,5.39388,5.39388,5.39388,5.29245,5.29245,6.05812,8,2.40391,2.40391,1.81445,1.81445,1.81445,1.81445,1.81445,1.81445,1.81445,6.39366,1.03137,1.03137,1,7.33486,4.07985,4.10295,8,8,8,5.59171,5.59171,2.74031,2.74031,7.22546,2.83715,2.83715,1.56805,3.65909,3.65909,3.65909,3.43515,3.43515,3.43515,3.43515,6.18286,3.7493,3.7493,1,6.29522,2.21448,2.21448,1,1.36947,1.36947,8,8,8,2.06038,2.06038,3.78039,3.78039,5.1013,5.1013,5.1013,5.1013,3.32451,5.04431,5.04431,5.04431,5.04431,5.04431,5.04431,5.04431,5.04431,5.09518,5.09518,5.09518,5.09518,5.09518,5.09518,6.72444,6.72444,6.72444,6.72444,6.37491,6.13725,7.91544,7.91544,7.91544,4.96586,4.96586,4.96586,4.96586,4.96586,4.96586,5.79566,5.79566,5.79566,5.79566,5.79566,5.79566,6.04797,3.0981,3.05446,3.32847,8,1.25134,1.25134,8,8,6.86678,6.86678,6.86678,6.86678,6.86678,6.86678,3.17409,3.65819,2.47036,8,6.47379,1.94616,2.7368,2.7368,1.35486,5.06243,2.71302,2.71302,4.22021,4.22021,3.94335,2.23683,6.45144,6.45144,4.6046,4.6046,4.6046,4.6046,4.6046,4.6046,7.13059,7.13059,7.13059,7.13059,7.13059,7.78873,1,5.63974,2.19575,2.19575,2.70697,2.70697,2.70697,5.36983,1.72252,1.72252,1,5.55239,5.55239,2.46803,2.46803,5.76835,1,1,3.28701", "policy/expansion_factor": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "legacy/torch_deterministic": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "legacy/cpu_offload": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "legacy/compile": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "legacy/compile_fullgraph": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "train/gpus": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "train/seed": "42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42", "train/total_timesteps": "50,172.431,172.431,100.08,50,98.2736,50,50,50,50,108.663,108.663,108.663,150.103,150.103,50,50,206.621,206.621,206.621,206.621,206.621,213.267,213.267,213.267,213.267,213.267,76.7961,76.7961,182.885,182.885,182.885,82.2057,50,50,50,151.728,151.728,63.8321,50,50,50,50,50,123.368,76.9401,76.9401,128.429,234.103,234.103,234.103,234.103,50,73.9865,73.6323,73.6323,73.6323,73.6323,60.9174,360.312,360.312,360.312,360.312,360.312,360.312,360.312,360.312,118.059,114.973,89.321,89.321,271.634,271.634,271.634,271.634,271.634,50,50,205.21,135.908,52.5357,52.5357,66.3356,66.3356,66.3356,66.3356,66.3356,66.3356,66.3356,99.8336,50,50,50,94.3853,51.9287,50,167.23,167.23,167.23,50,50,56.8551,56.8551,125.414,50,50,50,60.55,60.55,60.55,80.1335,80.1335,80.1335,80.1335,129.836,67.2145,67.2145,68.2692,52.4683,50,50,50,50.4408,50.4408,72.5487,72.5487,72.5487,50,50,50,50,143.298,143.298,143.298,143.298,50,83.1543,83.1543,83.1543,83.1543,83.1543,83.1543,83.1543,83.1543,59.2253,59.2253,59.2253,59.2253,59.2253,59.2253,222.279,222.279,222.279,222.279,209.11,126.694,196.585,196.585,196.585,63.7174,63.7174,63.7174,63.7174,63.7174,63.7174,54.8565,54.8565,54.8565,54.8565,54.8565,54.8565,193.6,93.4146,50,99.7729,90.3379,58.4311,58.4311,161.697,161.697,81.567,81.567,81.567,81.567,81.567,81.567,70.6055,69.0453,50,63.742,50,50,70.5941,70.5941,60.7524,70.8716,50,50,166.577,166.577,84.1606,63.7241,50,50,73.7487,73.7487,73.7487,73.7487,73.7487,73.7487,136.735,136.735,136.735,136.735,136.735,59.4021,61.0634,104.542,50,50,50,50,50,86.0085,82.1543,82.1543,50,102.374,102.374,64.261,64.261,93.5505,50,50,50.463", "train/learning_rate": "0.1,0.00861677,0.00861677,0.0507121,0.0304515,0.1,0.1,0.1,0.1,0.1,0.00523009,0.00523009,0.00523009,0.00443576,0.00443576,0.1,0.1,0.00644585,0.00644585,0.00644585,0.00644585,0.00644585,0.00399141,0.00399141,0.00399141,0.00399141,0.00399141,0.0113447,0.0113447,0.012327,0.012327,0.012327,0.0591791,0.0827057,0.0827057,0.0114783,0.00626412,0.00626412,0.1,0.1,0.1,0.1,0.1,0.1,0.0137767,0.0264824,0.0264824,0.00382065,0.00559215,0.00559215,0.00559215,0.00559215,0.0361797,0.0387502,0.013755,0.013755,0.013755,0.013755,0.1,0.00778529,0.00778529,0.00778529,0.00778529,0.00778529,0.00778529,0.00778529,0.00778529,0.1,0.0209069,0.0182061,0.0182061,0.00552197,0.00552197,0.00552197,0.00552197,0.00552197,0.0228643,0.0228643,0.00972151,0.0126003,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.019809,0.1,0.1,0.1,0.00760283,0.1,0.1,0.00633535,0.00633535,0.00633535,0.0121868,0.0121868,0.0250362,0.0250362,0.00474709,0.0874094,0.0874094,0.1,0.0302975,0.0302975,0.0302975,0.0194877,0.0194877,0.0194877,0.0194877,0.00979469,0.0187054,0.0187054,0.1,0.0301117,0.1,0.1,0.0147647,0.1,0.1,0.0132259,0.0132259,0.0132259,0.0300846,0.0300846,0.1,0.1,0.0117301,0.0117301,0.0117301,0.0117301,0.0116465,0.0098056,0.0098056,0.0098056,0.0098056,0.0098056,0.0098056,0.0098056,0.0098056,0.00626353,0.00626353,0.00626353,0.00626353,0.00626353,0.00626353,0.00790186,0.00790186,0.00790186,0.00790186,0.00614112,0.0121794,0.00595624,0.00595624,0.00595624,0.0124143,0.0124143,0.0124143,0.0124143,0.0124143,0.0124143,0.0496394,0.0496394,0.0496394,0.0496394,0.0496394,0.0496394,0.0949159,0.0356303,0.0554928,0.0113976,0.0132149,0.0420038,0.0420038,0.00802529,0.00802529,0.00473989,0.00473989,0.00473989,0.00473989,0.00473989,0.00473989,0.0371217,0.1,0.1,0.0102801,0.1,0.1,0.0179078,0.0179078,0.0558727,0.0420737,0.1,0.1,0.00746926,0.00746926,0.1,0.093878,0.0665349,0.0665349,0.0176266,0.0176266,0.0176266,0.0176266,0.0176266,0.0176266,0.0118659,0.0118659,0.0118659,0.0118659,0.0118659,0.0175116,0.1,0.0232305,0.1,0.1,0.0146223,0.0146223,0.0146223,0.008793,0.0656125,0.0656125,0.0117071,0.0121924,0.0121924,0.1,0.1,0.0178275,0.0369034,0.0369034,0.1", "train/anneal_lr": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "train/min_lr_ratio": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "train/gamma": "0.93961,0.998191,0.998191,0.987977,0.983403,0.96949,0.961536,0.952964,0.969373,0.8,0.992421,0.992421,0.992421,0.996825,0.996825,0.956938,0.963033,0.997529,0.997529,0.997529,0.997529,0.997529,0.99308,0.99308,0.99308,0.99308,0.99308,0.994976,0.994976,0.998061,0.998061,0.998061,0.965937,0.916116,0.916116,0.949639,0.995432,0.995432,0.954968,0.971411,0.950483,0.950483,0.950483,0.950483,0.986629,0.967659,0.967659,0.996078,0.994828,0.994828,0.994828,0.994828,0.959329,0.968772,0.994309,0.994309,0.994309,0.994309,0.897141,0.997155,0.997155,0.997155,0.997155,0.997155,0.997155,0.997155,0.997155,0.96023,0.957044,0.977928,0.977928,0.99791,0.99791,0.99791,0.99791,0.99791,0.971166,0.971166,0.996185,0.997141,0.924925,0.924925,0.967134,0.967134,0.967134,0.967134,0.967134,0.967134,0.967134,0.967931,0.977128,0.977128,0.931682,0.995876,0.914309,0.957172,0.996541,0.996541,0.996541,0.98968,0.98968,0.964082,0.964082,0.993331,0.911175,0.911175,0.989819,0.978764,0.978764,0.978764,0.988109,0.988109,0.988109,0.988109,0.995544,0.969594,0.969594,0.915534,0.958295,0.889528,0.889528,0.981312,0.963644,0.963644,0.9927,0.9927,0.9927,0.967495,0.967495,0.968747,0.968747,0.996271,0.996271,0.996271,0.996271,0.932423,0.996575,0.996575,0.996575,0.996575,0.996575,0.996575,0.996575,0.996575,0.988362,0.988362,0.988362,0.988362,0.988362,0.988362,0.995852,0.995852,0.995852,0.995852,0.994632,0.991881,0.996395,0.996395,0.996395,0.996276,0.996276,0.996276,0.996276,0.996276,0.996276,0.944452,0.944452,0.944452,0.944452,0.944452,0.944452,0.970676,0.982426,0.886907,0.993497,0.9838,0.947866,0.947866,0.992732,0.992732,0.9935,0.9935,0.9935,0.9935,0.9935,0.9935,0.975417,0.950553,0.978634,0.976288,0.884479,0.921076,0.972937,0.972937,0.920108,0.988643,0.966045,0.966045,0.992253,0.992253,0.961548,0.932614,0.948004,0.948004,0.996602,0.996602,0.996602,0.996602,0.996602,0.996602,0.99816,0.99816,0.99816,0.99816,0.99816,0.951797,0.956692,0.98778,0.953199,0.953199,0.986825,0.986825,0.986825,0.996462,0.95294,0.95294,0.959794,0.998052,0.998052,0.93759,0.93759,0.971538,0.919813,0.919813,0.947231", "train/gae_lambda": "0.995,0.923807,0.923807,0.93235,0.99349,0.989038,0.987773,0.993188,0.991401,0.960982,0.995,0.995,0.995,0.995,0.995,0.991483,0.983972,0.968059,0.968059,0.968059,0.968059,0.968059,0.930206,0.930206,0.930206,0.930206,0.930206,0.988858,0.988858,0.992672,0.992672,0.992672,0.944595,0.995,0.995,0.794933,0.995,0.995,0.877683,0.995,0.995,0.995,0.995,0.995,0.994402,0.986585,0.986585,0.995,0.961397,0.961397,0.961397,0.961397,0.995,0.995,0.993073,0.993073,0.993073,0.993073,0.995,0.977428,0.977428,0.977428,0.977428,0.977428,0.977428,0.977428,0.977428,0.995,0.966988,0.936126,0.936126,0.981582,0.981582,0.981582,0.981582,0.981582,0.904503,0.904503,0.970583,0.989701,0.992146,0.992146,0.983083,0.983083,0.983083,0.983083,0.983083,0.983083,0.983083,0.989743,0.971169,0.971169,0.995,0.970068,0.988906,0.977108,0.993036,0.993036,0.993036,0.992806,0.992806,0.994529,0.994529,0.96507,0.985818,0.985818,0.967689,0.976371,0.976371,0.976371,0.904814,0.904814,0.904814,0.904814,0.986327,0.980918,0.980918,0.995,0.993215,0.993157,0.993157,0.978752,0.965802,0.965802,0.995,0.995,0.995,0.993653,0.993653,0.992083,0.992083,0.957537,0.957537,0.957537,0.957537,0.995,0.975851,0.975851,0.975851,0.975851,0.975851,0.975851,0.975851,0.975851,0.976164,0.976164,0.976164,0.976164,0.976164,0.976164,0.98609,0.98609,0.98609,0.98609,0.988593,0.99447,0.9791,0.9791,0.9791,0.933155,0.933155,0.933155,0.933155,0.933155,0.933155,0.990339,0.990339,0.990339,0.990339,0.990339,0.990339,0.995,0.957507,0.994444,0.966296,0.993805,0.995,0.995,0.995,0.995,0.995,0.995,0.995,0.995,0.995,0.995,0.989703,0.991624,0.986837,0.995,0.99082,0.92267,0.99399,0.99399,0.965234,0.644204,0.993919,0.993919,0.989339,0.989339,0.911698,0.993626,0.985735,0.985735,0.945521,0.945521,0.945521,0.945521,0.945521,0.945521,0.90004,0.90004,0.90004,0.90004,0.90004,0.993573,0.988592,0.988721,0.984552,0.984552,0.995,0.995,0.995,0.994318,0.988098,0.988098,0.986887,0.990129,0.990129,0.995,0.995,0.995,0.982713,0.982713,0.989108", "train/replay_ratio": "0.665672,1.80788,1.80788,1.68737,0.361923,1.71739,1.07301,1.16313,1.04758,0.25,1.82968,1.82968,1.82968,1.5865,1.5865,0.972931,0.25,1.60678,1.60678,1.60678,1.60678,1.60678,2.35037,2.35037,2.35037,2.35037,2.35037,1.84491,1.84491,2.80757,2.80757,2.80757,0.497578,1.56215,1.56215,1.19319,2.47273,2.47273,0.762893,0.425702,0.841912,0.841912,0.841912,0.841912,1.4038,1.62097,1.62097,2.4775,1.52988,1.52988,1.52988,1.52988,1.00982,1.50667,0.849042,0.849042,0.849042,0.849042,0.791698,2.44869,2.44869,2.44869,2.44869,2.44869,2.44869,2.44869,2.44869,1.22627,1.47687,1.48747,1.48747,1.96343,1.96343,1.96343,1.96343,1.96343,1.41905,1.41905,1.78296,2.0118,1.3056,1.3056,0.908537,0.908537,0.908537,0.908537,0.908537,0.908537,0.908537,1.84356,1.2103,1.2103,0.622009,2.16465,1.00569,1.14667,2.81946,2.81946,2.81946,0.886314,0.886314,1.49325,1.49325,1.66314,1.53622,1.53622,0.25,0.866491,0.866491,0.866491,0.757019,0.757019,0.757019,0.757019,2.31012,1.59382,1.59382,0.909163,0.956818,0.747811,0.747811,1.33557,1.17627,1.17627,2.52163,2.52163,2.52163,1.32895,1.32895,1.80639,1.80639,0.728232,0.728232,0.728232,0.728232,1.19089,1.61513,1.61513,1.61513,1.61513,1.61513,1.61513,1.61513,1.61513,1.62277,1.62277,1.62277,1.62277,1.62277,1.62277,1.96872,1.96872,1.96872,1.96872,1.82983,2.34038,2.49451,2.49451,2.49451,1.04322,1.04322,1.04322,1.04322,1.04322,1.04322,0.842541,0.842541,0.842541,0.842541,0.842541,0.842541,1.55024,1.41998,0.25,0.636483,1.88807,0.961963,0.961963,2.16679,2.16679,1.86471,1.86471,1.86471,1.86471,1.86471,1.86471,1.09928,1.39639,1.58721,1.57425,0.25,0.457021,1.92101,1.92101,0.448439,2.14096,1.43889,1.43889,2.5617,2.5617,1.2635,0.883487,1.37324,1.37324,1.49988,1.49988,1.49988,1.49988,1.49988,1.49988,2.21768,2.21768,2.21768,2.21768,2.21768,1.31105,0.745471,0.849699,1.38682,1.38682,1.3713,1.3713,1.3713,1.75538,1.10507,1.10507,1.19282,1.80787,1.80787,1.09407,1.09407,0.974826,0.387237,0.387237,0.25", "train/clip_coef": "0.0627955,0.151095,0.151095,0.107535,0.199909,0.112242,0.174332,0.01,0.01,0.0724731,0.0378168,0.0378168,0.0378168,0.0709902,0.0709902,0.102109,0.179093,0.126588,0.126588,0.126588,0.126588,0.126588,0.01,0.01,0.01,0.01,0.01,0.143234,0.143234,0.105292,0.105292,0.105292,0.17832,0.191648,0.191648,0.208707,0.01,0.01,0.143962,0.0931055,0.01,0.01,0.01,0.01,0.225232,0.10846,0.10846,0.142264,0.05886,0.05886,0.05886,0.05886,0.0786672,0.14647,0.234623,0.234623,0.234623,0.234623,0.148238,0.159604,0.159604,0.159604,0.159604,0.159604,0.159604,0.159604,0.159604,0.178654,0.227945,0.154295,0.154295,0.0432495,0.0432495,0.0432495,0.0432495,0.0432495,0.128521,0.128521,0.126507,0.140557,0.0669285,0.0669285,0.204365,0.204365,0.204365,0.204365,0.204365,0.204365,0.204365,0.0415701,0.0567626,0.0567626,0.0763742,0.0766698,0.149733,0.11807,0.01,0.01,0.01,0.176382,0.176382,0.192543,0.192543,0.136022,0.0841106,0.0841106,0.101391,0.14701,0.14701,0.14701,0.154849,0.154849,0.154849,0.154849,0.0832816,0.124738,0.124738,0.146784,0.115968,0.111439,0.111439,0.15808,0.129419,0.129419,0.151501,0.151501,0.151501,0.22777,0.22777,0.157837,0.157837,0.128711,0.128711,0.128711,0.128711,0.173015,0.225196,0.225196,0.225196,0.225196,0.225196,0.225196,0.225196,0.225196,0.113382,0.113382,0.113382,0.113382,0.113382,0.113382,0.168424,0.168424,0.168424,0.168424,0.01,0.107084,0.200141,0.200141,0.200141,0.0778182,0.0778182,0.0778182,0.0778182,0.0778182,0.0778182,0.141085,0.141085,0.141085,0.141085,0.141085,0.141085,0.067546,0.186421,0.195415,0.131713,0.148232,0.112073,0.112073,0.01,0.01,0.109862,0.109862,0.109862,0.109862,0.109862,0.109862,0.228719,0.14363,0.101783,0.126232,0.318865,0.164367,0.195462,0.195462,0.174686,0.0934416,0.01,0.01,0.0882719,0.0882719,0.01,0.0569999,0.124081,0.124081,0.18159,0.18159,0.18159,0.18159,0.18159,0.18159,0.161996,0.161996,0.161996,0.161996,0.161996,0.237289,0.0432878,0.160145,0.049478,0.049478,0.167883,0.167883,0.167883,0.144175,0.149069,0.149069,0.084685,0.199572,0.199572,0.01,0.01,0.182673,0.0879885,0.0879885,0.152681", "train/vf_coef": "0.994993,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,1.0634,0.1,0.1,0.1,0.1,0.1,0.970971,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.442424,0.442424,0.1,0.696345,0.1,0.1,0.1,0.1,0.78023,0.498508,0.498508,0.238947,0.1,0.1,0.1,0.1,0.1,0.701125,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.197876,0.1,0.1,0.1,0.1,0.1,0.1,0.1,1.11457,1.11457,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.559145,0.1,0.214747,0.214747,0.214747,0.524183,0.524183,0.1,0.1,0.1,0.1,0.1,1.79545,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.10578,0.1,0.1,0.1,0.16206,0.1,0.1,0.1,0.1,0.1,1.14026,1.14026,0.1,0.1,0.1,0.1,0.1,0.1,0.771006,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.107388,0.107388,0.107388,0.107388,0.107388,0.107388,0.1,0.1,0.1,0.1,0.1,0.1,0.308172,0.308172,0.308172,0.234665,0.234665,0.234665,0.234665,0.234665,0.234665,0.128371,0.128371,0.128371,0.128371,0.128371,0.128371,0.407436,0.1,0.382734,0.1,0.426964,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.309333,0.1,0.1,0.1,1.31539,0.150931,0.1,0.1,0.1,1.12714,0.470075,0.470075,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.465336,0.1,0.1,0.134734,0.134734,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1", "train/vf_clip_coef": "5,3.85567,3.85567,3.9448,5,2.63366,5,4.30293,2.28915,2.1016,4.49165,4.49165,4.49165,4.47719,4.47719,4.39437,4.56246,4.78053,4.78053,4.78053,4.78053,4.78053,4.06913,4.06913,4.06913,4.06913,4.06913,4.27206,4.27206,4.15797,4.15797,4.15797,5,4.43123,4.43123,2.90875,5,5,0.01,5,4.14429,4.14429,4.14429,4.14429,4.16729,1.62754,1.62754,3.77072,3.39437,3.39437,3.39437,3.39437,5,5,1.82477,1.82477,1.82477,1.82477,5,4.21315,4.21315,4.21315,4.21315,4.21315,4.21315,4.21315,4.21315,4.36298,1.59263,2.69276,2.69276,5,5,5,5,5,1.51171,1.51171,3.6265,5,5,5,5,5,5,5,5,5,5,0.724731,5,5,3.74822,5,4.08266,4.99656,5,5,5,2.61148,2.61148,1.27318,1.27318,3.22418,5,5,0.897327,5,5,5,3.25116,3.25116,3.25116,3.25116,3.98857,2.29561,2.29561,5,3.40447,5,5,4.28798,4.37903,4.37903,5,5,5,5,5,4.41041,4.41041,3.04478,3.04478,3.04478,3.04478,2.8048,2.15588,2.15588,2.15588,2.15588,2.15588,2.15588,2.15588,2.15588,2.41936,2.41936,2.41936,2.41936,2.41936,2.41936,4.04015,4.04015,4.04015,4.04015,5,5,3.83298,3.83298,3.83298,1.97,1.97,1.97,1.97,1.97,1.97,2.3473,2.3473,2.3473,2.3473,2.3473,2.3473,1.60393,3.28515,5,4.02195,2.10711,5,5,3.26429,3.26429,3.23775,3.23775,3.23775,3.23775,3.23775,3.23775,4.48516,3.22425,5,3.3249,2.93273,2.65016,4.56331,4.56331,4.90347,1.89781,4.33191,4.33191,5,5,3.11311,4.27866,3.25145,3.25145,4.19612,4.19612,4.19612,4.19612,4.19612,4.19612,4.32203,4.32203,4.32203,4.32203,4.32203,3.74545,5,3.60883,4.22653,4.22653,1.59446,1.59446,1.59446,5,4.38235,4.38235,3.77576,5,5,3.90878,3.90878,2.45913,4.92239,4.92239,2.55823", "train/max_grad_norm": "0.541135,0.78852,0.78852,2.64966,1.86121,0.1,0.445126,0.1,0.781997,0.1,0.383596,0.383596,0.383596,0.569427,0.569427,0.251423,1.7449,0.382311,0.382311,0.382311,0.382311,0.382311,0.1,0.1,0.1,0.1,0.1,0.948235,0.948235,1.8592,1.8592,1.8592,1.71675,0.1,0.1,0.1,1.17776,1.17776,0.765156,1.02221,0.1,0.1,0.1,0.1,0.772649,1.25736,1.25736,0.1,0.701251,0.701251,0.701251,0.701251,0.548469,0.29837,1.25992,1.25992,1.25992,1.25992,0.687677,0.764306,0.764306,0.764306,0.764306,0.764306,0.764306,0.764306,0.764306,2.1375,0.581395,0.828816,0.828816,0.1,0.1,0.1,0.1,0.1,1.07395,1.07395,0.604348,0.1,0.1,0.1,0.274112,0.274112,0.274112,0.274112,0.274112,0.274112,0.274112,0.1,0.301749,0.301749,0.1,1.25036,0.126156,0.374121,1.69756,1.69756,1.69756,0.964571,0.964571,0.907151,0.907151,1.17661,0.1,0.1,2.19022,1.63127,1.63127,1.63127,3.79113,3.79113,3.79113,3.79113,0.863698,0.1,0.1,1.65649,0.702542,0.1,0.1,1.50747,2.17144,2.17144,1.88713,1.88713,1.88713,0.788574,0.788574,0.724818,0.724818,1.08501,1.08501,1.08501,1.08501,0.1,0.900662,0.900662,0.900662,0.900662,0.900662,0.900662,0.900662,0.900662,2.0478,2.0478,2.0478,2.0478,2.0478,2.0478,1.31053,1.31053,1.31053,1.31053,1.2768,0.304076,0.1,0.1,0.1,0.58983,0.58983,0.58983,0.58983,0.58983,0.58983,0.1,0.1,0.1,0.1,0.1,0.1,0.1,1.89328,0.449808,1.69345,0.18442,0.1,0.1,1.3812,1.3812,1.95035,1.95035,1.95035,1.95035,1.95035,1.95035,2.51308,0.1,0.71779,1.51889,1.18477,0.1,0.1,0.1,1.59061,2.02058,0.805111,0.805111,0.1,0.1,0.579326,1.62747,0.313258,0.313258,2.83851,2.83851,2.83851,2.83851,2.83851,2.83851,0.611312,0.611312,0.611312,0.611312,0.611312,0.752311,0.812639,1.41533,0.1,0.1,0.1,0.1,0.1,0.770383,0.1,0.1,0.2685,0.97194,0.97194,0.1,0.1,0.33355,2.13935,2.13935,1.00871", "train/ent_coef": "0.000203468,0.037412,0.037412,0.0264803,0.134761,0.00983139,0.0137879,0.0109929,0.00726707,0.0250471,0.0440233,0.0440233,0.0440233,0.0519635,0.0519635,0.000132885,0.00471055,0.0561913,0.0561913,0.0561913,0.0561913,0.0561913,0.0182611,0.0182611,0.0182611,0.0182611,0.0182611,0.00479475,0.00479475,0.00866692,0.00866692,0.00866692,0.00377268,0.000809162,0.000809162,0.0990349,0.0441086,0.0441086,0.0346486,0.017534,0.00819379,0.00819379,0.00819379,0.00819379,0.0157441,0.000416138,0.000416138,0.052921,0.105062,0.105062,0.105062,0.105062,0.0114393,0.00704467,0.0496293,0.0496293,0.0496293,0.0496293,0.00129124,0.0161019,0.0161019,0.0161019,0.0161019,0.0161019,0.0161019,0.0161019,0.0161019,0.00758407,0.0200377,0.00147261,0.00147261,0.00858358,0.00858358,0.00858358,0.00858358,0.00858358,0.00102355,0.00102355,0.2,0.00327813,0.00729277,0.00729277,0.00245771,0.00245771,0.00245771,0.00245771,0.00245771,0.00245771,0.00245771,0.00868896,0.00524869,0.00524869,0.00278288,0.0473976,0.00275499,0.021249,0.0328764,0.0328764,0.0328764,0.0124156,0.0124156,0.00102005,0.00102005,0.0053448,0.0105192,0.0105192,0.0977175,0.0701863,0.0701863,0.0701863,0.004147,0.004147,0.004147,0.004147,0.0309062,0.0011675,0.0011675,0.0115965,0.00268795,0.0117438,0.0117438,0.000767394,0.000200528,0.000200528,0.0143001,0.0143001,0.0143001,0.00167151,0.00167151,0.00446979,0.00446979,0.0435406,0.0435406,0.0435406,0.0435406,0.0121521,0.0496705,0.0496705,0.0496705,0.0496705,0.0496705,0.0496705,0.0496705,0.0496705,0.0136226,0.0136226,0.0136226,0.0136226,0.0136226,0.0136226,0.00792416,0.00792416,0.00792416,0.00792416,0.0091416,0.0752402,0.126712,0.126712,0.126712,0.0791345,0.0791345,0.0791345,0.0791345,0.0791345,0.0791345,0.00391762,0.00391762,0.00391762,0.00391762,0.00391762,0.00391762,0.00437411,0.00371925,0.00991048,0.00163867,0.0661805,0.00472841,0.00472841,0.0291336,0.0291336,0.00797926,0.00797926,0.00797926,0.00797926,0.00797926,0.00797926,0.0102074,0.000560604,0.000606748,0.0774711,0.000408403,0.0199477,0.000730736,0.000730736,0.000954376,0.136585,0.00147876,0.00147876,0.0200783,0.0200783,0.0016611,0.00145559,0.0929243,0.0929243,0.0129021,0.0129021,0.0129021,0.0129021,0.0129021,0.0129021,0.0279066,0.0279066,0.0279066,0.0279066,0.0279066,0.0192223,0.00148062,0.0154971,0.00190423,0.00190423,0.00211811,0.00211811,0.00211811,0.0710765,0.00171807,0.00171807,0.00117202,0.0375865,0.0375865,0.00463897,0.00463897,0.00476856,0.00358081,0.00358081,0.00233906", "train/beta1": "0.5,0.869836,0.869836,0.5,0.768423,0.5,0.662618,0.529272,0.625432,0.887313,0.900265,0.900265,0.900265,0.86399,0.86399,0.5,0.5,0.884984,0.884984,0.884984,0.884984,0.884984,0.830243,0.830243,0.830243,0.830243,0.830243,0.919859,0.919859,0.799459,0.799459,0.799459,0.589553,0.705781,0.705781,0.5,0.806967,0.806967,0.602975,0.672469,0.754903,0.754903,0.754903,0.754903,0.803433,0.68059,0.68059,0.86038,0.935747,0.935747,0.935747,0.935747,0.784272,0.724353,0.802482,0.802482,0.802482,0.802482,0.5,0.721299,0.721299,0.721299,0.721299,0.721299,0.721299,0.721299,0.721299,0.5,0.675189,0.803525,0.803525,0.90081,0.90081,0.90081,0.90081,0.90081,0.621917,0.621917,0.894473,0.872841,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.794646,0.5,0.5,0.5,0.898873,0.5,0.5,0.826696,0.826696,0.826696,0.806874,0.806874,0.683925,0.683925,0.892474,0.5,0.5,0.5,0.826584,0.826584,0.826584,0.765021,0.765021,0.765021,0.765021,0.893605,0.774486,0.774486,0.627841,0.534711,0.5,0.5,0.80115,0.5,0.5,0.812914,0.812914,0.812914,0.618683,0.618683,0.701711,0.701711,0.893648,0.893648,0.893648,0.893648,0.721294,0.844394,0.844394,0.844394,0.844394,0.844394,0.844394,0.844394,0.844394,0.911764,0.911764,0.911764,0.911764,0.911764,0.911764,0.877174,0.877174,0.877174,0.877174,0.895999,0.887004,0.895691,0.895691,0.895691,0.84381,0.84381,0.84381,0.84381,0.84381,0.84381,0.623841,0.623841,0.623841,0.623841,0.623841,0.623841,0.825049,0.7894,0.668952,0.836027,0.685533,0.60292,0.60292,0.877533,0.877533,0.870717,0.870717,0.870717,0.870717,0.870717,0.870717,0.5,0.5,0.778258,0.747026,0.873668,0.5,0.635966,0.635966,0.612832,0.998937,0.54537,0.54537,0.922842,0.922842,0.610633,0.5,0.605625,0.605625,0.874671,0.874671,0.874671,0.874671,0.874671,0.874671,0.852025,0.852025,0.852025,0.852025,0.852025,0.783728,0.595719,0.796793,0.5,0.5,0.802033,0.802033,0.802033,0.885636,0.5,0.5,0.746698,0.861724,0.861724,0.5,0.5,0.850981,0.77313,0.77313,0.746438", "train/beta2": "0.999675,0.999196,0.999196,0.999931,0.997086,0.998265,0.999681,0.999953,0.999527,0.999876,0.999855,0.999855,0.999855,0.990162,0.990162,0.999843,0.999276,0.987562,0.987562,0.987562,0.987562,0.987562,0.997781,0.997781,0.997781,0.997781,0.997781,0.997772,0.997772,0.99358,0.99358,0.99358,0.999979,0.999753,0.999753,0.999912,0.999724,0.999724,0.999561,0.999893,0.999892,0.999892,0.999892,0.999892,0.998636,0.998548,0.998548,0.999512,0.995602,0.995602,0.995602,0.995602,0.999758,0.999905,0.999485,0.999485,0.999485,0.999485,0.999853,0.995655,0.995655,0.995655,0.995655,0.995655,0.995655,0.995655,0.995655,0.99855,0.99823,0.999472,0.999472,0.99532,0.99532,0.99532,0.99532,0.99532,0.999763,0.999763,0.993218,0.987542,0.999782,0.999782,0.996765,0.996765,0.996765,0.996765,0.996765,0.996765,0.996765,0.998837,0.999913,0.999913,0.999708,0.998643,0.999142,0.999956,0.999709,0.999709,0.999709,0.99886,0.99886,0.999905,0.999905,0.998423,0.999971,0.999971,0.999185,0.999844,0.999844,0.999844,0.998514,0.998514,0.998514,0.998514,0.999266,0.999492,0.999492,0.999514,0.998821,0.999611,0.999611,0.999897,0.999975,0.999975,0.998881,0.998881,0.998881,0.999886,0.999886,0.999582,0.999582,0.972505,0.972505,0.972505,0.972505,0.99953,0.996242,0.996242,0.996242,0.996242,0.996242,0.996242,0.996242,0.996242,0.99946,0.99946,0.99946,0.99946,0.99946,0.99946,0.998377,0.998377,0.998377,0.998377,0.994025,0.997511,0.970811,0.970811,0.970811,0.999224,0.999224,0.999224,0.999224,0.999224,0.999224,0.998072,0.998072,0.998072,0.998072,0.998072,0.998072,0.996445,0.999704,0.99992,0.999736,0.999713,0.999488,0.999488,0.995083,0.995083,0.998944,0.998944,0.998944,0.998944,0.998944,0.998944,0.999698,0.99966,0.999684,0.999512,0.999891,0.99933,0.999452,0.999452,0.999835,0.936883,0.999847,0.999847,0.977561,0.977561,0.999821,0.999752,0.999252,0.999252,0.999795,0.999795,0.999795,0.999795,0.999795,0.999795,0.998326,0.998326,0.998326,0.998326,0.998326,0.999797,0.999964,0.995041,0.999634,0.999634,0.998674,0.998674,0.998674,0.996434,0.999905,0.999905,0.999538,0.965648,0.965648,0.999339,0.999339,0.998669,0.999738,0.999738,0.999928", "train/eps": "1.08338e-06,0.0001,0.0001,0.0001,1.17489e-05,0.0001,2.23395e-08,1.38479e-09,1.58827e-05,1.15277e-09,0.0001,0.0001,0.0001,2.52477e-06,2.52477e-06,3.81498e-07,6.23205e-09,6.78793e-06,6.78793e-06,6.78793e-06,6.78793e-06,6.78793e-06,0.0001,0.0001,0.0001,0.0001,0.0001,1.05355e-05,1.05355e-05,0.0001,0.0001,0.0001,2.69687e-07,1.15455e-09,1.15455e-09,4.53243e-08,2.33823e-05,2.33823e-05,1.85711e-06,1.53681e-09,3.27412e-08,3.27412e-08,3.27412e-08,3.27412e-08,0.0001,6.54322e-05,6.54322e-05,0.0001,0.0001,0.0001,0.0001,0.0001,6.02107e-07,3.19013e-05,1.94626e-09,1.94626e-09,1.94626e-09,1.94626e-09,3.62483e-07,0.0001,0.0001,0.0001,0.0001,0.0001,0.0001,0.0001,0.0001,0.0001,3.92411e-05,3.78131e-07,3.78131e-07,0.0001,0.0001,0.0001,0.0001,0.0001,1.50569e-08,1.50569e-08,0.0001,3.22912e-07,1.15241e-07,1.15241e-07,2.20171e-08,2.20171e-08,2.20171e-08,2.20171e-08,2.20171e-08,2.20171e-08,2.20171e-08,4.90901e-07,6.49102e-08,6.49102e-08,2.32768e-06,6.8457e-05,1.07968e-05,4.86612e-07,7.93993e-08,7.93993e-08,7.93993e-08,3.43491e-07,3.43491e-07,6.3151e-05,6.3151e-05,4.57324e-07,5.24187e-06,5.24187e-06,8.89039e-09,0.0001,0.0001,0.0001,4.80422e-07,4.80422e-07,4.80422e-07,4.80422e-07,5.59629e-07,0.0001,0.0001,9.54758e-09,8.13274e-09,3.10719e-07,3.10719e-07,3.43225e-07,2.52012e-05,2.52012e-05,0.0001,0.0001,0.0001,5.86024e-08,5.86024e-08,2.26621e-07,2.26621e-07,3.69521e-07,3.69521e-07,3.69521e-07,3.69521e-07,0.0001,1.44778e-07,1.44778e-07,1.44778e-07,1.44778e-07,1.44778e-07,1.44778e-07,1.44778e-07,1.44778e-07,4.38415e-09,4.38415e-09,4.38415e-09,4.38415e-09,4.38415e-09,4.38415e-09,0.0001,0.0001,0.0001,0.0001,0.0001,0.0001,0.0001,0.0001,0.0001,1.24168e-09,1.24168e-09,1.24168e-09,1.24168e-09,1.24168e-09,1.24168e-09,4.4959e-06,4.4959e-06,4.4959e-06,4.4959e-06,4.4959e-06,4.4959e-06,8.41866e-06,8.57448e-06,9.20002e-09,0.0001,1.4388e-06,3.96245e-07,3.96245e-07,4.90522e-05,4.90522e-05,6.85372e-09,6.85372e-09,6.85372e-09,6.85372e-09,6.85372e-09,6.85372e-09,6.39381e-06,2.17019e-07,7.68891e-07,4.08611e-06,7.02685e-08,6.79028e-09,1.96902e-06,1.96902e-06,6.36556e-07,4.87062e-12,3.04957e-05,3.04957e-05,2.25672e-05,2.25672e-05,4.07297e-07,1.25934e-06,1.47509e-07,1.47509e-07,6.7704e-05,6.7704e-05,6.7704e-05,6.7704e-05,6.7704e-05,6.7704e-05,9.44867e-05,9.44867e-05,9.44867e-05,9.44867e-05,9.44867e-05,2.08235e-07,3.57863e-07,6.66512e-07,2.67769e-07,2.67769e-07,3.61514e-05,3.61514e-05,3.61514e-05,9.86336e-08,1.48892e-08,1.48892e-08,2.50353e-05,4.6389e-07,4.6389e-07,2.22987e-08,2.22987e-08,1.80123e-06,2.97292e-09,2.97292e-09,1.89702e-07", "train/minibatch_size": "16384,16384,16384,16384,4096,16384,8192,32768,16384,4096,4096,4096,4096,4096,4096,8192,16384,16384,16384,16384,16384,16384,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,4096,16384,16384,16384,8192,8192,8192,16384,32768,32768,32768,32768,4096,8192,8192,4096,8192,8192,8192,8192,16384,32768,4096,4096,4096,4096,16384,8192,8192,8192,8192,8192,8192,8192,8192,16384,8192,16384,16384,8192,8192,8192,8192,8192,4096,4096,16384,8192,32768,32768,16384,16384,16384,16384,16384,16384,16384,8192,8192,8192,16384,16384,8192,16384,8192,8192,8192,4096,4096,4096,4096,4096,16384,16384,16384,16384,16384,16384,8192,8192,8192,8192,8192,16384,16384,16384,4096,16384,16384,4096,8192,8192,8192,8192,8192,8192,8192,16384,16384,8192,8192,8192,8192,4096,4096,4096,4096,4096,4096,4096,4096,4096,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,16384,16384,16384,4096,4096,4096,4096,4096,4096,16384,16384,16384,16384,16384,16384,16384,16384,8192,4096,4096,16384,16384,8192,8192,4096,4096,4096,4096,4096,4096,4096,16384,16384,4096,8192,16384,4096,4096,8192,32768,16384,16384,8192,8192,16384,16384,8192,8192,8192,8192,8192,8192,8192,8192,16384,16384,16384,16384,16384,4096,16384,8192,8192,8192,8192,8192,8192,8192,8192,8192,16384,4096,4096,8192,8192,4096,8192,8192,32768", "train/horizon": "64,64,64,64,64,64,32,16,32,32,128,128,128,128,128,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,128,128,64,64,32,32,32,32,128,128,128,64,64,64,64,64,32,64,64,64,64,64,64,64,64,64,64,64,64,64,64,128,64,128,128,128,128,128,128,128,128,128,64,64,32,32,128,128,128,128,128,128,128,256,128,128,64,64,32,64,128,128,128,32,32,128,128,128,64,64,32,32,32,32,64,64,64,64,128,64,64,64,128,32,32,128,32,32,128,128,128,64,64,64,64,64,64,64,64,128,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,256,64,256,256,256,128,128,128,128,128,128,64,64,64,64,64,64,64,64,64,32,128,32,32,64,64,128,128,128,128,128,128,128,32,64,64,16,64,64,64,64,64,64,64,128,128,32,64,32,32,64,64,64,64,64,64,64,64,64,64,64,128,128,128,32,32,128,128,128,128,64,64,64,128,128,64,64,128,32,32,64", "train/vtrace_rho_clip": "1.85715,1.89688,1.89688,2.03162,1.93628,1.3315,1.60386,1.53065,1.84835,3.67018,0.857834,0.857834,0.857834,2.28774,2.28774,3.92898,2.8745,2.22204,2.22204,2.22204,2.22204,2.22204,1.79663,1.79663,1.79663,1.79663,1.79663,1.90756,1.90756,1.71738,1.71738,1.71738,2.64402,3.0219,3.0219,1.52681,3.04613,3.04613,0.97104,3.46952,3.11525,3.11525,3.11525,3.11525,2.95336,2.2108,2.2108,2.56927,2.03672,2.03672,2.03672,2.03672,2.2523,1.37315,1.74447,1.74447,1.74447,1.74447,2.70723,2.05192,2.05192,2.05192,2.05192,2.05192,2.05192,2.05192,2.05192,1.6628,0.272966,1.59969,1.59969,1.14012,1.14012,1.14012,1.14012,1.14012,1.19771,1.19771,2.07372,0.844096,3.53138,3.53138,2.43475,2.43475,2.43475,2.43475,2.43475,2.43475,2.43475,2.81386,4.20356,4.20356,2.22152,1.43408,1.68307,2.88261,4.09583,4.09583,4.09583,2.36167,2.36167,1.45136,1.45136,1.63693,3.45558,3.45558,1.20464,2.45674,2.45674,2.45674,2.06585,2.06585,2.06585,2.06585,0.793832,1.56093,1.56093,1.77833,1.4608,3.08321,3.08321,1.20123,1.38041,1.38041,0.795072,0.795072,0.795072,3.44241,3.44241,1.23986,1.23986,1.20622,1.20622,1.20622,1.20622,3.26874,1.17378,1.17378,1.17378,1.17378,1.17378,1.17378,1.17378,1.17378,2.05757,2.05757,2.05757,2.05757,2.05757,2.05757,1.76854,1.76854,1.76854,1.76854,1.14584,0.794085,3.07087,3.07087,3.07087,1.44083,1.44083,1.44083,1.44083,1.44083,1.44083,2.67075,2.67075,2.67075,2.67075,2.67075,2.67075,2.51263,2.47882,2.48059,1.152,2.6958,2.27074,2.27074,1.48962,1.48962,0.713277,0.713277,0.713277,0.713277,0.713277,0.713277,2.43672,0.656539,3.28334,2.50372,3.39376,2.37636,2.61127,2.61127,2.33823,4.36967,2.45995,2.45995,0.67553,0.67553,2.38053,1.98304,1.94889,1.94889,1.3168,1.3168,1.3168,1.3168,1.3168,1.3168,1.10352,1.10352,1.10352,1.10352,1.10352,1.67218,2.26264,2.25538,3.31514,3.31514,1.70986,1.70986,1.70986,1.53176,3.31684,3.31684,2.54821,1.24299,1.24299,3.58337,3.58337,1.74184,3.44238,3.44238,2.27516", "train/vtrace_c_clip": "0.688256,0.1,0.1,0.188733,0.849027,0.762969,0.1,0.759586,0.1,0.564024,0.195457,0.195457,0.195457,0.1,0.1,0.777595,1.27832,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.603972,0.472364,0.472364,1.09555,0.220394,0.220394,0.598076,0.895999,0.767857,0.767857,0.767857,0.767857,0.1,0.860245,0.860245,0.1,0.298427,0.298427,0.298427,0.298427,0.589796,0.524771,0.1,0.1,0.1,0.1,0.407227,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.744095,1.18231,0.771214,0.771214,0.1,0.1,0.1,0.1,0.1,0.405895,0.405895,0.465232,0.398833,0.451532,0.451532,0.832835,0.832835,0.832835,0.832835,0.832835,0.832835,0.832835,0.1,0.219398,0.219398,0.29944,0.1,0.866711,0.1,0.1,0.1,0.1,0.414453,0.414453,0.1,0.1,0.1,1.16786,1.16786,0.158324,0.754361,0.754361,0.754361,0.58536,0.58536,0.58536,0.58536,0.1,0.707287,0.707287,0.240578,0.948126,1.28353,1.28353,0.3165,0.643317,0.643317,0.1,0.1,0.1,0.441035,0.441035,0.446256,0.446256,0.1,0.1,0.1,0.1,0.730473,0.237923,0.237923,0.237923,0.237923,0.237923,0.237923,0.237923,0.237923,0.156351,0.156351,0.156351,0.156351,0.156351,0.156351,0.1,0.1,0.1,0.1,0.239062,0.178738,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.942791,0.942791,0.942791,0.942791,0.942791,0.942791,0.34173,0.1,0.825512,0.1,0.287099,0.33554,0.33554,0.35762,0.35762,0.479311,0.479311,0.479311,0.479311,0.479311,0.479311,0.743583,0.838496,0.844399,0.315072,0.225747,1.41532,0.681437,0.681437,1.40699,3.56129,0.489991,0.489991,0.482408,0.482408,0.1,0.1,0.591729,0.591729,0.1,0.1,0.1,0.1,0.1,0.1,0.315958,0.315958,0.315958,0.315958,0.315958,0.859807,0.488014,0.596834,0.1,0.1,0.317951,0.317951,0.317951,0.1,0.751095,0.751095,0.1,0.1,0.1,0.427971,0.427971,0.1,0.995602,0.995602,1.11938", "train/prio_alpha": "0.926079,1,1,1,1,1,0.909005,1,1,0.823049,0.779788,0.779788,0.779788,0.964806,0.964806,1,1,0.907075,0.907075,0.907075,0.907075,0.907075,1,1,1,1,1,0.889084,0.889084,1,1,1,0.874297,0.955774,0.955774,1,1,1,1,1,0.750149,0.750149,0.750149,0.750149,0.747448,1,1,1,1,1,1,1,1,0.741623,0.951743,0.951743,0.951743,0.951743,0.9766,1,1,1,1,1,1,1,1,0.88565,0.931732,1,1,0.988247,0.988247,0.988247,0.988247,0.988247,0.881789,0.881789,0.58347,0.870397,0.812119,0.812119,1,1,1,1,1,1,1,1,1,1,0.811113,0.831043,0.898917,1,1,1,1,0.561163,0.561163,1,1,1,0.997929,0.997929,1,1,1,1,0.904061,0.904061,0.904061,0.904061,1,0.903593,0.903593,0.979063,0.996843,0.808508,0.808508,1,1,1,0.998857,0.998857,0.998857,0.940689,0.940689,1,1,0.70377,0.70377,0.70377,0.70377,1,0.763895,0.763895,0.763895,0.763895,0.763895,0.763895,0.763895,0.763895,0.516239,0.516239,0.516239,0.516239,0.516239,0.516239,1,1,1,1,0.955638,0.762604,1,1,1,0.879547,0.879547,0.879547,0.879547,0.879547,0.879547,1,1,1,1,1,1,1,1,1,1,0.974692,1,1,1,1,0.763691,0.763691,0.763691,0.763691,0.763691,0.763691,0.763289,0.955519,1,1,0.967244,0.971553,0.932713,0.932713,1,0.624656,1,1,0.77802,0.77802,1,1,1,1,1,1,1,1,1,1,0.945761,0.945761,0.945761,0.945761,0.945761,0.831832,0.991512,1,0.738005,0.738005,0.809994,0.809994,0.809994,0.811073,1,1,1,1,1,0.957544,0.957544,0.985116,1,1,0.941448", "train/prio_beta0": "1,0.826262,0.826262,0.636095,1,0.984441,1,1,1,0.999185,0.63103,0.63103,0.63103,0.693767,0.693767,0.794979,1,0.433323,0.433323,0.433323,0.433323,0.433323,0.533282,0.533282,0.533282,0.533282,0.533282,0.869334,0.869334,0.578056,0.578056,0.578056,1,0.801936,0.801936,0.858541,0.627683,0.627683,0.973676,0.923966,1,1,1,1,0.791608,0.925066,0.925066,0.577342,0.57987,0.57987,0.57987,0.57987,0.753614,1,0.533651,0.533651,0.533651,0.533651,0.996534,0.57867,0.57867,0.57867,0.57867,0.57867,0.57867,0.57867,0.57867,0.595407,1,0.80874,0.80874,0.868123,0.868123,0.868123,0.868123,0.868123,0.889261,0.889261,0.415454,0.691974,1,1,1,1,1,1,1,1,1,1,0.815728,0.815728,1,0.483484,0.959147,0.937139,0.609384,0.609384,0.609384,0.585391,0.585391,1,1,0.601429,1,1,1,0.843477,0.843477,0.843477,0.452804,0.452804,0.452804,0.452804,0.53683,0.780664,0.780664,1,0.560798,1,1,1,1,1,0.904641,0.904641,0.904641,1,1,1,1,0.818141,0.818141,0.818141,0.818141,0.895315,0.618342,0.618342,0.618342,0.618342,0.618342,0.618342,0.618342,0.618342,0.378657,0.378657,0.378657,0.378657,0.378657,0.378657,0.451371,0.451371,0.451371,0.451371,0.983538,0.659758,0.760374,0.760374,0.760374,0.578394,0.578394,0.578394,0.578394,0.578394,0.578394,1,1,1,1,1,1,0.745747,0.625375,0.824163,0.847359,1,0.78659,0.78659,0.629449,0.629449,0.721173,0.721173,0.721173,0.721173,0.721173,0.721173,0.300071,0.938824,0.913106,0.752467,1,1,0.946273,0.946273,1,0.958821,1,1,0.653509,0.653509,1,0.949468,0.691917,0.691917,0.635158,0.635158,0.635158,0.635158,0.635158,0.635158,0.269736,0.269736,0.269736,0.269736,0.269736,1,1,0.455414,0.95532,0.95532,0.941969,0.941969,0.941969,1,0.989483,0.989483,0.755606,0.991022,0.991022,1,1,1,1,1,1", "train/use_rnn": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "no_model_upload": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "tsne1": "-27.7584,-42.1387,-42.1387,-25.139,-38.6023,-28.2913,-31.8848,-29.4706,-29.0495,-35.5153,-39.808,-39.808,-39.808,-45.6542,-45.6542,-28.7507,-30.4488,-43.8172,-43.8173,-43.8186,-43.8186,-43.8188,-46.1405,-46.1405,-46.143,-46.1405,-46.1405,-39.4138,-39.4138,-46.08,-46.08,-46.08,-32.1463,-32.3841,-32.3841,-27.4474,-49.0632,-49.0632,-27.828,-32.9607,-33.9298,-33.9298,-33.9298,-33.9298,-38.6213,-29.3614,-29.3614,-39.0435,-47.1658,-47.1658,-47.1658,-47.1658,-33.6259,-32.0253,-31.9112,-31.9143,-31.9151,-31.9116,-27.9662,-47.3194,-47.2055,-47.2904,-47.5486,-47.2958,-47.321,-47.2055,-47.3213,-25.1445,-29.0476,-32.4195,-32.4193,-41.9526,-41.9526,-41.9524,-41.9524,-41.9526,-26.9456,-26.9457,-43.9107,-42.2356,-26.1161,-26.1161,-29.5169,-29.5169,-29.5169,-29.5169,-29.5169,-29.5169,-29.5169,-29.5597,-29.446,-29.446,-27.9758,-44.46,-27.6828,-28.6448,-49.9304,-49.9304,-49.9303,-34.3517,-34.3514,-29.084,-29.084,-37.3362,-27.7094,-27.7096,-27.582,-38.7986,-38.7987,-38.7986,-35.5473,-35.5473,-35.5473,-35.5472,-38.9974,-30.3741,-30.3742,-30.9062,-25.178,-26.4023,-26.4019,-37.2041,-31.6195,-31.6195,-41.508,-41.5074,-41.508,-30.1607,-30.1607,-31.615,-31.615,-33.7261,-33.7257,-33.7262,-33.7257,-31.1153,-33.5939,-33.4046,-33.401,-33.3159,-33.3159,-33.5939,-33.4015,-33.3169,-34.2123,-34.2096,-34.2096,-34.2096,-34.2092,-34.2092,-45.1138,-45.1138,-45.1138,-45.1138,-41.6492,-40.2847,-49.5452,-49.5452,-49.5452,-31.5039,-31.5039,-31.7895,-31.5039,-31.8112,-31.7898,-29.3167,-29.317,-29.317,-29.317,-29.317,-29.3167,-30.1375,-34.8555,-32.3784,-38.2658,-29.8818,-30.9676,-30.9676,-47.2941,-47.2923,-36.2995,-36.2997,-36.2996,-36.2995,-36.2995,-36.2997,-24.7466,-28.3236,-33.3264,-45.2798,-35.0709,-27.7361,-33.4628,-33.4633,-31.9988,-37.2098,-28.7209,-28.7209,-43.3167,-43.3167,-29.357,-28.8718,-26.2874,-26.2874,-37.5872,-37.5872,-37.5872,-37.5864,-37.5868,-37.5854,-45.4646,-45.4647,-45.4646,-45.4646,-45.4646,-36.8697,-29.9494,-35.0994,-27.4479,-27.4479,-30.9927,-30.9927,-30.9927,-40.5656,-29.2391,-29.2391,-32.9254,-40.3256,-40.3256,-28.4414,-28.4414,-30.2909,-34.2711,-34.2711,-30.4837", "tsne2": "-61.6826,-53.3721,-53.3721,-59.9784,-54.0562,-59.1539,-61.4663,-60.1928,-58.3551,-62.5913,-46.7081,-46.7081,-46.7081,-48.2803,-48.2803,-65.5082,-63.4463,-54.7344,-54.7344,-54.7352,-54.7352,-54.7353,-50.3566,-50.3566,-50.3569,-50.3565,-50.3565,-49.2749,-49.2749,-52.3964,-52.3964,-52.3964,-63.827,-58.0261,-58.0261,-57.9179,-50.7813,-50.7813,-55.3092,-61.0276,-59.7214,-59.7214,-59.7214,-59.7214,-48.911,-51.8335,-51.8335,-47.9366,-48.9978,-48.9978,-48.9978,-48.9978,-57.3971,-59.7222,-44.2874,-44.2873,-44.2877,-44.2875,-62.5043,-52.4297,-51.9504,-51.9556,-52.1787,-51.9554,-52.4293,-51.9504,-52.4294,-59.9534,-52.6413,-54.8487,-54.8493,-49.2072,-49.2072,-49.2073,-49.2073,-49.2072,-52.8209,-52.8212,-55.6521,-50.3418,-63.0984,-63.0984,-63.2821,-63.2821,-63.2821,-63.2821,-63.2821,-63.2821,-63.2821,-50.613,-67.1311,-67.1311,-60.9828,-54.4016,-60.738,-63.1753,-50.9888,-50.9888,-50.9888,-43.9125,-43.9128,-51.3405,-51.3396,-46.2927,-63.3534,-63.3537,-55.7682,-55.6167,-55.6167,-55.6164,-51.946,-51.946,-51.946,-51.9461,-46.6092,-53.0701,-53.0699,-61.0429,-58.0514,-62.7551,-62.7552,-48.1152,-65.1972,-65.1971,-47.1515,-47.1501,-47.1515,-67.3822,-67.3822,-60.0615,-60.0615,-48.1916,-48.1922,-48.1916,-48.1922,-50.4011,-45.3542,-45.0728,-45.0659,-45.5416,-45.5416,-45.3542,-45.0664,-45.5424,-42.1016,-42.0974,-42.0974,-42.0974,-42.0969,-42.0971,-51.9344,-51.9344,-51.9344,-51.9344,-48.205,-46.848,-48.3106,-48.3106,-48.3106,-45.1463,-45.1463,-45.3562,-45.1463,-45.327,-45.3561,-57.425,-57.426,-57.4261,-57.4261,-57.426,-57.4249,-52.9478,-53.9301,-62.6031,-52.1116,-50.0857,-61.8273,-61.8273,-49.8638,-49.8627,-45.7717,-45.7719,-45.7716,-45.7717,-45.7717,-45.7717,-59.1121,-59.8617,-57.7889,-47.747,-62.666,-57.8515,-65.5858,-65.5861,-63.3229,42.3383,-61.0983,-61.0983,-48.6036,-48.6036,-58.8606,-61.7258,-57.6761,-57.6761,-52.9295,-52.9295,-52.9295,-52.9284,-52.9295,-52.9286,-54.9808,-54.9809,-54.9808,-54.9808,-54.9808,-48.3739,-62.06,-53.0533,-64.7159,-64.7159,-52.0337,-52.0337,-52.0337,-48.9528,-64.8194,-64.8194,-56.2866,-50.4315,-50.4315,-64.7059,-64.7059,-50.6002,-62.8074,-62.8061,-57.0538"}, "pong": {"SPS": "1.13682e+06,8.80494e+06,6.10194e+06,6.30126e+06,9.75903e+06,349084,8.70169e+06,1.26809e+06,1.28313e+06,1.28301e+06,1.28118e+06,1.90938e+06,1.95546e+06,1.9571e+06,1.96194e+06,1.96231e+06,1.46567e+06,1.47161e+06,1.47204e+06,1.47393e+06,5.17268e+06,5.18422e+06,1.91494e+06,1.90829e+06,2.00173e+06,2.46953e+06,3.0012e+06,501854,3.5671e+06,5.7198e+06,5.81278e+06,4.28541e+06,1.78006e+06,6.97495e+06,7.11701e+06,1.48427e+06,1.48413e+06,1.25222e+06,405027,1.41608e+06,6.68526e+06,6.86543e+06,6.86447e+06,6.86413e+06,4.38375e+06,4.38562e+06,2.18439e+06,2.74947e+06,731291,728253,1.21219e+06,1.05836e+07,1.05836e+07,933131,7.52246e+06,7.5642e+06,3.50229e+06,3.5586e+06,3.55933e+06,2.65349e+06,4.84145e+06,8.05637e+06,8.19275e+06,1.47736e+07,1.1334e+07,1.13323e+07,1.15435e+07,3.14086e+06,1.12705e+07,2.85203e+06,2.86856e+06,2.86775e+06,651165,650624,1.13777e+07,1.13777e+07,3.73703e+06,3.78274e+06,3.78131e+06,9.9964e+06,8.64529e+06,8.64529e+06,8.77987e+06,1.12155e+07,1.19828e+06,1.11055e+07,1.1284e+07,1.15125e+07,1.15067e+07,1.14925e+07,4.03907e+06,2.5885e+06,3.20154e+06,1.57545e+07,1.62804e+07,3.9374e+06,9.20728e+06,8.76795e+06,8.9172e+06,2.43239e+06,1.05977e+07,1.05977e+07,1.13102e+07,1.4096e+06,1.09857e+07,1.09857e+07,1.41638e+06,5.26605e+06,5.29497e+06,2.54564e+06,2.55973e+06,2.55891e+06,4.49782e+06,4.49727e+06,1.43131e+06,1.43027e+06,1.4305e+06,1.43161e+06,1.62146e+07,9.70874e+06,6.1275e+06,547987,1.11452e+07,4.96387e+06,6.31931e+06,6.87655e+06,6.88762e+06,952008,9.02204e+06,9.32115e+06,9.38184e+06,9.42824e+06,9.4104e+06,7.30029e+06,4.67077e+06,1.06018e+07,1.06018e+07,720204,2.05369e+06,1.598e+06,9.41438e+06,9.4851e+06,9.63977e+06,9.724e+06,1.14507e+07,1.14507e+07,1.95083e+06,2.55109e+06,1.39177e+06,1.17894e+06,2.894e+06", "agent_steps": "1.03219,4.1943,0.753664,2.06438,1.40902,4.98074,0.933888,0.638976,1.88416,4.37453,4.98074,0.65536,1.90054,3.14573,4.39091,4.98074,0.647168,1.89235,3.13754,4.38272,3.12934,4.98074,2.42483,6.38976,4.98074,2.37568,2.68698,1.83501,2.71974,1.27795,3.65363,3.14573,4.98074,0.688128,4.39091,4.39091,4.98074,3.63725,6.16038,2.06438,0.753664,2.06438,3.40787,4.75136,3.21126,4.48922,1.89235,1.04038,1.90054,4.98074,1.2288,4.98074,4.98074,1.1223,0.835584,2.27738,0.671744,1.88416,3.12934,3.08019,0.65536,1.31072,3.75194,1.27795,0.8192,2.26099,3.75194,4.38272,1.2288,0.647168,1.88006,3.12934,1.90054,3.14573,4.98074,4.98074,0.647168,1.89235,3.13754,0.704512,4.98074,4.98074,1.17965,1.6384,1.1223,0.688128,1.88416,3.12934,4.37453,4.98074,0.851968,6.22592,2.82624,0.753664,4.98074,7.20896,1.76947,0.8192,2.27738,4.45645,4.98074,4.98074,0.688128,4.98074,4.98074,4.98074,4.98074,0.671744,0.663552,0.65536,1.89235,4.38272,2.3593,3.89939,1.88416,3.12934,4.37453,4.98074,1.40902,0.688128,3.08019,2.85082,0.688128,0.999424,1.78586,4.39091,4.98074,0.917504,0.688128,1.90054,3.14573,4.39091,4.98074,1.26157,1.14688,4.98074,4.98074,4.98074,2.98189,1.23699,0.835584,2.32653,5.40672,6.16038,4.98074,4.98074,4.98074,0.98304,0.884736,2.85082,0.647168", "uptime": "0.933062,0.495879,0.13906,0.350013,0.161577,14.2314,0.122441,0.520089,1.49046,3.4306,3.90353,0.360676,0.997262,1.63406,2.26926,2.56983,0.460331,1.30617,2.15228,2.99766,0.627149,0.985113,1.29425,3.37169,2.50704,0.981341,0.924044,3.62362,0.783733,0.242841,0.652647,0.755043,2.83362,0.116981,0.638646,2.98144,3.37883,2.92328,15.2726,1.48011,0.129338,0.322231,0.517926,0.71365,0.754476,1.04595,0.880594,0.396839,2.63234,6.85411,1.03852,0.470653,0.470653,1.21874,0.129011,0.319452,0.211729,0.553698,0.903417,1.17972,0.15258,0.179427,0.479087,0.102133,0.0864527,0.213837,0.344021,1.42078,0.125543,0.243368,0.673539,1.10907,2.95546,4.86798,0.437804,0.437804,0.191307,0.52161,0.850905,0.0854731,0.576164,0.576164,0.154272,0.160962,0.956343,0.0771939,0.18389,0.293095,0.401268,0.453968,0.230137,2.42791,0.902972,0.0632285,0.326049,1.84902,0.211888,0.10898,0.273681,1.87196,0.470026,0.470026,0.0760588,3.57243,0.453428,0.453428,3.55523,0.143106,0.14165,0.280355,0.764085,1.73739,0.546678,0.889119,1.34158,2.21193,3.08241,3.50623,0.101578,0.0872198,0.521272,5.24129,0.076311,0.219191,0.30071,0.663173,0.748967,0.98151,0.0955298,0.22731,0.360294,0.492557,0.555146,0.192032,0.267249,0.469848,0.469848,6.93863,1.47551,0.793626,0.103248,0.261389,0.581767,0.659978,0.435011,0.435011,2.57822,0.408278,0.661167,2.43633,0.242709", "epoch": "31.5,128,23,63,21.5,38,28.5,19.5,57.5,133.5,152,10,29,48,67,76,39.5,115.5,191.5,267.5,95.5,152,74,195,76,72.5,41,28,83,39,111.5,48,38,10.5,67,67,76,55.5,47,31.5,23,63,104,145,98,137,115.5,63.5,29,76,37.5,152,152,68.5,25.5,69.5,20.5,57.5,95.5,47,20,40,114.5,19.5,25,69,114.5,267.5,37.5,79,229.5,382,29,48,152,152,39.5,115.5,191.5,21.5,152,152,36,50,68.5,21,57.5,95.5,133.5,152,26,380,172.5,11.5,76,110,27,25,69.5,34,152,152,21,76,152,152,38,41,40.5,40,115.5,267.5,72,119,57.5,95.5,133.5,152,21.5,10.5,47,43.5,21,30.5,54.5,67,76,28,10.5,29,48,67,76,38.5,35,152,152,38,45.5,75.5,25.5,71,165,188,152,152,76,15,13.5,43.5,39.5", "env/perf": "0.560857,0.967456,0.165088,0.623307,0.242492,0.999825,0.223531,0.287777,0.876579,0.99839,0.999969,0.241059,0.92908,0.991381,0.999404,0.999725,0.477002,0.863697,0.994331,0.99965,0.918055,0.998983,0.925913,1,0.999851,0.824985,0.847051,0.701407,0.873813,0.352611,0.965825,0.921613,0.999969,0.0230688,0.985771,0.998548,0.999795,0.996889,0.999985,0.95135,0.10254,0.674746,0.955568,0.99847,0.993017,0.999604,0.754363,0.568225,0.934556,0.999828,0.655782,0.988731,0.988731,0.682665,0.231779,0.795863,0.220149,0.664283,0.942812,0.937406,0.134799,0.366717,0.92518,0.128575,0.0990815,0.634713,0.959451,0.996465,0.243433,0.248938,0.74548,0.934371,0.986948,0.997034,0.998469,0.998469,0.167405,0.726485,0.922907,0.0810285,0.996343,0.996343,0.235872,0.310831,0.615937,0.0747765,0.420203,0.80347,0.985545,0.994993,0.226487,0.999968,0.910064,0.00340515,0.945512,1,0.458169,0.131247,0.638708,0.998521,0.998469,0.998469,0.0607302,0.999684,0.988731,0.988731,0.999773,0.00182676,0.00129409,0.469112,0.786006,0.997459,0.841495,0.99504,0.905844,0.975319,0.998012,0.999979,0.117981,0.0714921,0.812,0.988058,0.0779278,0.22854,0.536679,0.994101,0.999966,0.551636,0.0712982,0.511673,0.916552,0.994146,0.998408,0.330769,0.379402,0.988731,0.988731,0.999934,0.947421,0.619278,0.195499,0.808493,0.999558,0.999687,0.998469,0.998469,0.999777,0.505414,0.497831,0.962272,0.181306", "env/score": "3.81802,20.2264,-16.3017,7.09566,-12.38,20.9962,-13.804,-8.91662,17.3804,20.9642,20.9993,-11.3951,19.1046,20.8083,20.9869,20.9939,0.111858,17.4201,20.8747,20.9923,18.845,20.9775,19.1545,21,20.9967,16.1681,16.4392,9.50233,17.5938,-6.2776,20.1712,19.0962,20.9993,-20.4616,20.6807,20.968,20.9955,20.931,20.9997,19.802,-18.32,8.90672,19.9657,20.9663,20.8416,20.9913,13.3331,4.37693,19.383,20.9962,7.50925,20.7484,20.7484,8.19911,-13.1503,14.5642,-13.4506,9.30409,19.6001,19.1864,-17.0629,-6.31454,19.0571,-17.5135,-18.3416,6.89648,20.0321,20.922,-12.7867,-11.7884,13.0735,19.3647,20.7076,20.9346,20.9663,20.9663,-14.2548,12.5398,19.1023,-18.9661,20.9192,20.9192,-12.6573,-8.58843,6.3481,-19.0824,-4.55702,14.8759,20.6719,20.8891,-12.9322,20.9993,18.6741,-20.9245,19.7106,21,-1.39774,-17.2577,6.9825,20.9673,20.9663,20.9663,-19.5037,20.9931,20.7484,20.7484,20.995,-20.9595,-20.9715,-0.529249,14.6408,20.944,15.6858,20.8892,18.6587,20.4356,20.9562,20.9995,-17.8456,-19.1725,14.9319,20.7325,-19.0195,-12.658,2.52781,20.8658,20.9993,3.55,-19.1526,0.620362,18.8034,20.87,20.9649,-8.01324,-5.85014,20.7484,20.7484,20.9986,19.7504,6.86797,-14.3684,14.8478,20.9903,20.9931,20.9663,20.9663,20.9951,0.692379,0.245261,20.0862,-14.4809", "env/episode_return": "3.81802,20.2264,-16.3017,7.09566,-12.38,20.9962,-13.804,-8.91662,17.3804,20.9642,20.9993,-11.3951,19.1046,20.8083,20.9869,20.9939,0.111858,17.4201,20.8747,20.9923,18.845,20.9775,19.1545,21,20.9967,16.1681,16.4392,9.50233,17.5938,-6.2776,20.1712,19.0962,20.9993,-20.4616,20.6807,20.968,20.9955,20.931,20.9997,19.802,-18.32,8.90672,19.9657,20.9663,20.8416,20.9913,13.3331,4.37693,19.383,20.9962,7.50925,20.7484,20.7484,8.19911,-13.1503,14.5642,-13.4506,9.30409,19.6001,19.1864,-17.0629,-6.31454,19.0571,-17.5135,-18.3416,6.89648,20.0321,20.922,-12.7867,-11.7884,13.0735,19.3647,20.7076,20.9346,20.9663,20.9663,-14.2548,12.5398,19.1023,-18.9661,20.9192,20.9192,-12.6573,-8.58843,6.3481,-19.0824,-4.55702,14.8759,20.6719,20.8891,-12.9322,20.9993,18.6741,-20.9245,19.7106,21,-1.39774,-17.2577,6.9825,20.9673,20.9663,20.9663,-19.5037,20.9931,20.7484,20.7484,20.995,-20.9595,-20.9715,-0.529249,14.6408,20.944,15.6858,20.8892,18.6587,20.4356,20.9562,20.9995,-17.8456,-19.1725,14.9319,20.7325,-19.0195,-12.658,2.52781,20.8658,20.9993,3.55,-19.1526,0.620362,18.8034,20.87,20.9649,-8.01324,-5.85014,20.7484,20.7484,20.9986,19.7504,6.86797,-14.3684,14.8478,20.9903,20.9931,20.9663,20.9663,20.9951,0.692379,0.245261,20.0862,-14.4809", "env/episode_length": "45.0103,36.0216,50.535,62.333,46.6377,35.0068,49.1011,37.0692,44.3657,41.0564,40.9645,31.2485,36.62,35.2979,35,35.0066,39.5741,39.103,35.5282,35,41.1055,35.0882,43.507,35.0053,35,44.8308,41.0466,40.1828,39.4735,31.7078,35.0039,39.1856,40.9397,40.1683,35.6914,35.0527,35.0181,40.4187,46.4591,37.1479,53.6023,45.7953,42.7037,35.2451,35.121,35,58.9962,43.638,39.2624,35.0103,40.2965,36.7118,36.7118,44.4558,39.6385,45.7781,48.7118,71.0454,51.8381,43.0948,28.0725,48.8319,38.0319,40.0536,28.065,40.6447,35.1222,35.3693,36.4695,32.4409,49.4601,38.3148,35.4879,35.1186,35.0244,35.0244,32.9176,52.7981,42.5544,26.5717,35.2383,35.2383,46.0164,33.1507,41.1513,29.5696,44.4314,38.3956,35.6075,35.3973,52.2645,35,40.1629,27.7287,43.6482,41.0014,37.2298,46.671,62.4863,38.5259,35.0244,35.0244,27.068,41.2724,36.7118,36.7118,35.0614,18.507,17.299,34.4417,34.8932,35,36.6502,35.1499,60.566,54.7843,53.8223,53.9449,34.7677,32.852,59.5988,35.2452,26.0162,40.0199,41.1097,35,35,40.8728,32.1009,36.546,35.0901,35,35.0226,47.2038,51.0619,36.7118,36.7118,35,39.2799,44.6566,33.9518,36.717,35,35,35.0244,35.0244,35.0102,38.9813,55.0336,36.0556,46.9397", "env/n": "32.3833,43.8431,26.1795,24.7073,39.7353,3382,20.8,47.5263,32.3158,37.5,2903,100.053,77.1579,88.0526,85.3158,3465,19.2368,17.9605,22.2763,21.9211,32.9737,3287,33.3265,4331,3646,29.75,65.6667,70.7455,35.0727,37.1127,45.8243,65.2105,2919,73,95.9474,91.3158,3321,81.8636,3093,77.8,27.1538,27.4634,44.4878,41.2927,45.8974,41.2308,11.9079,15.4918,75.5263,3393,40.8056,3092,3092,19.5597,24.1905,36.3913,29.2222,19.0263,29.8421,69.5806,47.1622,25.4932,38.6711,65.7,61.9535,29.3333,43.8043,22.4079,32.3382,11.1544,5.81579,9.71242,89.4737,86.0526,3322,3322,24.6447,11.0395,17.0132,58.7647,3193,3193,34.4462,38.914,17.0821,55.9143,21,36.5263,44.6316,3317,33.2766,4226,17.5877,134.125,2291,4137,74.4118,39.1163,21.9348,166.556,3322,3322,60.4286,2878,3092,3092,3404,45.137,45.7568,19.5867,19.6711,22.1974,42.5319,43.8723,23.6053,28.2368,28.5263,2197,63.4167,110.167,55.8387,87.8214,55.7714,28.6538,28.78,103.526,2702,33.6727,109.111,59.2105,91.2632,76.9474,3586,24.2059,22.9344,3092,3092,3459,74.4,16.027,29.7727,40.2979,44.234,4202,3322,3322,3447,74.4815,77.3462,75.6786,20.1447", "perf/rollout": "0.00695709,0.00169335,0.00170416,0.00168898,0.00204507,0.0320437,0.00169079,0.00727146,0.00672284,0.00672131,0.00674152,0.00782248,0.00655124,0.00651889,0.00643518,0.00642991,0.00336927,0.00335804,0.0033505,0.00333517,0.00191148,0.00189614,0.00655651,0.00660062,0.00431538,0.00378741,0.00757413,0.0111663,0.00194339,0.00217419,0.00212206,0.00382792,0.015178,0.00335761,0.00336395,0.00973038,0.0097239,0.00881205,0.0283594,0.0086919,0.00168248,0.00166917,0.00166437,0.00166474,0.00322402,0.00322217,0.00219387,0.00296223,0.0137578,0.0137985,0.00686831,0.29582,0.29582,0.00399925,0.00201638,0.00202514,0.00325318,0.00321577,0.00321241,0.0037697,0.00324475,0.00200419,0.00199232,0.00206582,0.00166137,0.00165862,0.00165061,0.00163326,0.00167772,0.00147659,0.00147166,0.00147157,0.013773,0.0138804,0.269021,0.269021,0.00292704,0.00292672,0.00292561,0.00170276,0.333078,0.333078,0.00167758,0.00169788,0.00345937,0.00172115,0.00166998,0.00166443,0.00166641,0.0016675,0.00327649,0.00188518,0.00190298,0.00214703,0.00208998,0.0039084,0.00334906,0.00166124,0.00166582,0.0129694,0.296929,0.296929,0.0016699,0.0141125,0.281068,0.281068,0.01721,0.00163007,0.00162968,0.0033434,0.00332257,0.00332387,0.00195724,0.00195593,0.00701023,0.00701438,0.00700947,0.00701404,0.00206957,0.00331865,0.00329178,0.0160182,0.00171074,0.0016681,0.00178153,0.00226001,0.00225067,0.00735659,0.00337491,0.003355,0.00333293,0.00330195,0.00330973,0.00171474,0.00194386,0.295741,0.295741,0.0194564,0.0065565,0.00339657,0.00170545,0.00170364,0.00169216,0.00165534,0.262313,0.262313,0.00508332,0.00650035,0.0151607,0.00604157,0.00291997", "perf/eval_gpu": "0.00463386,0.00090393,0.000903155,0.000897977,0.000962433,0.0229462,0.00090232,0.00468334,0.00437566,0.00437079,0.00434312,0.00423973,0.00354981,0.00354484,0.00354778,0.00354001,0.00221339,0.00219765,0.00219299,0.00219149,0.00115521,0.00114893,0.00421376,0.00425381,0.00282046,0.00229948,0.00467317,0.00780697,0.00116915,0.00114906,0.0011021,0.0023138,0.00938036,0.00179225,0.00178164,0.00681482,0.00680131,0.00597366,0.0188155,0.00574573,0.000903744,0.000899375,0.000899014,0.000897636,0.00176875,0.00176983,0.00144153,0.00179899,0.00923614,0.00923096,0.00458317,0.224643,0.224643,0.00284125,0.000993113,0.000991107,0.00177151,0.00176741,0.00176619,0.00231408,0.00177471,0.000985858,0.00097791,0.000981132,0.000899269,0.000896411,0.000893037,0.000908777,0.000898057,0.0008906,0.000886629,0.000885946,0.00922522,0.00921637,0.194726,0.194726,0.0017745,0.00176965,0.00176963,0.000899143,0.261987,0.261987,0.000901165,0.000901335,0.00229948,0.000899193,0.000895307,0.000892195,0.000892539,0.000896939,0.00178801,0.00114651,0.00116171,0.00100166,0.000980383,0.00236348,0.00179083,0.000897142,0.000892971,0.00713247,0.22264,0.22264,0.00089734,0.00948289,0.21384,0.21384,0.0114915,0.000898176,0.000889522,0.00196489,0.00195931,0.0019589,0.00115915,0.00115963,0.00471176,0.00471236,0.00471324,0.00471805,0.000955946,0.00180182,0.00179211,0.0113451,0.000909414,0.000906966,0.00099887,0.00118239,0.00117579,0.00485325,0.00179807,0.00178932,0.00178798,0.00178627,0.00179028,0.000922439,0.00118165,0.225182,0.225182,0.013575,0.00356736,0.00224181,0.000901484,0.000899152,0.000898371,0.000896619,0.191632,0.191632,0.00315089,0.00356344,0.0100833,0.00406406,0.00177359", "perf/eval_env": "0.00106847,0.000476434,0.000489597,0.000479018,0.000717244,0.00426272,0.000472522,0.00128161,0.00109065,0.0010943,0.00112547,0.00203221,0.00153631,0.0015091,0.00144407,0.0014371,0.000526104,0.00052925,0.000525195,0.000511948,0.00044542,0.000439599,0.0010651,0.00106741,0.00089023,0.000743918,0.00143957,0.00152607,0.000463845,0.00049709,0.000496944,0.000904629,0.00284631,0.00095922,0.000966235,0.00142651,0.00143239,0.00142096,0.00451501,0.0014586,0.000464905,0.000454775,0.00045093,0.000452071,0.000715442,0.000710421,0.000374443,0.00053238,0.00204089,0.00207543,0.00103992,0.0493684,0.0493684,0.000521671,0.000520347,0.000518294,0.000705609,0.000709375,0.000705552,0.000844496,0.0007408,0.000502366,0.0004974,0.00072303,0.000453085,0.000451033,0.000446948,0.000352903,0.000469688,0.000267113,0.000266253,0.000266224,0.00204579,0.00216255,0.0487447,0.0487447,0.000516625,0.000519632,0.000517617,0.000492901,0.0483929,0.0483929,0.000465387,0.000485571,0.00052821,0.000511328,0.000464063,0.000462304,0.00046252,0.000454319,0.000737369,0.000359419,0.000364829,0.000688976,0.000663224,0.000929097,0.000944,0.000457888,0.000465982,0.00295826,0.0488543,0.0488543,0.000462208,0.00216572,0.0458986,0.0458986,0.00283098,0.00036169,0.000370724,0.000485544,0.000471213,0.000470759,0.000489858,0.000487705,0.00104887,0.00104969,0.00104671,0.00104963,0.000752748,0.000910882,0.000888272,0.0021584,0.000487573,0.000451409,0.000473068,0.00071653,0.00071507,0.00120933,0.000964824,0.000955909,0.000935502,0.000904125,0.000904279,0.000457652,0.000453491,0.0495995,0.0495995,0.00295204,0.00151944,0.000525367,0.000494446,0.000493979,0.000484355,0.00045444,0.0449593,0.0449593,0.000998553,0.00147003,0.00255336,0.00100011,0.000517006", "perf/train_misc": "0.00102921,0.000194355,0.000325984,0.00031333,0.000691965,0.0139436,0.000252641,0.00152696,0.00118303,0.0011802,0.00119706,0.00441791,0.00274641,0.00275391,0.00275783,0.00279245,0.00050304,0.00050124,0.00050048,0.000502482,0.000310365,0.000317568,0.000637672,0.000623744,0.00117875,0.000493314,0.000755694,0.0034424,0.000554749,0.000316698,0.000312269,0.000663651,0.00217907,0.000604009,0.000592268,0.000719468,0.000731104,0.00148331,0.0131574,0.00133373,0.000291286,0.000280831,0.000279735,0.00028045,0.000272743,0.000271121,0.000228363,0.000219129,0.00345166,0.0034857,0.00125218,0.0239996,0.0239996,0.000520683,0.000282701,0.000277779,0.000564249,0.000555855,0.000554823,0.00125981,0.000314349,0.000250213,0.000243528,0.000355551,0.000159411,0.000159711,0.000154178,0.000257261,0.000160655,0.000133266,0.00013185,0.000131918,0.00395194,0.00396193,0.0218832,0.0218832,0.000131664,0.000127491,0.00012828,0.00019771,0.0259975,0.0259975,0.000195989,0.000158734,0.000503632,0.000157827,0.000156884,0.000151426,0.000150627,0.000151584,0.0004607,0.000252128,0.000226057,0.000303516,0.000285856,0.000678912,0.000375119,0.000252701,0.000244102,0.00412763,0.0225366,0.0225366,0.000158948,0.0019753,0.0235115,0.0235115,0.0021463,0.000154275,0.000154053,0.000272047,0.000270664,0.000271688,0.000314037,0.00031297,0.000692366,0.000691894,0.000691081,0.00068096,0.000296332,0.000340519,0.000552415,0.00408707,0.000159857,0.000535129,0.000287789,0.000639016,0.000626688,0.00157971,0.000383147,0.000368807,0.000366707,0.000367011,0.000367616,0.000255631,0.000321573,0.0232816,0.0232816,0.0043735,0.00258727,0.000443459,0.000219613,0.00021569,0.000211625,0.00020976,0.0224367,0.0224367,0.00117456,0.00123326,0.00283769,0.00131295,0.000243361", "perf/train_forward": "0.0206405,0.00167655,0.00318327,0.00303846,0.00379555,0.329515,0.00167477,0.0222629,0.0174518,0.0174507,0.0174019,0.037602,0.0239476,0.0239709,0.0239359,0.0239206,0.00713205,0.00710521,0.00711357,0.00711808,0.00395302,0.00396493,0.00974001,0.00973824,0.027095,0.00882601,0.0132743,0.13874,0.00650979,0.00309229,0.00304217,0.0106246,0.0561336,0.00520708,0.00508343,0.0335268,0.0335002,0.0418083,0.281281,0.036038,0.00278169,0.00266524,0.00266976,0.00266974,0.00382108,0.00382213,0.00493169,0.00263322,0.0721357,0.0723681,0.0187161,0.137267,0.137267,0.0128666,0.0019082,0.00187269,0.00538732,0.00526694,0.00527941,0.0194596,0.00302927,0.00166578,0.00160747,0.00185549,0.000927213,0.000922801,0.000882987,0.00316712,0.000928475,0.00112742,0.00110785,0.00110814,0.0826443,0.082565,0.134911,0.134911,0.0011838,0.00113955,0.00114008,0.00123675,0.201475,0.201475,0.0017134,0.000924533,0.0095465,0.000926844,0.000925832,0.000881464,0.000881566,0.000881664,0.00422205,0.00403046,0.00283009,0.00154751,0.00147456,0.0118784,0.00322379,0.00167917,0.00160998,0.0365249,0.138076,0.138076,0.00092815,0.0302121,0.135269,0.135269,0.072876,0.00119046,0.00117275,0.00267946,0.0026543,0.00265699,0.00486023,0.00485683,0.0150324,0.0150301,0.0150488,0.0150528,0.00152016,0.00287594,0.00668242,0.0992342,0.000927977,0.00423906,0.00296528,0.00643854,0.00644301,0.0306431,0.00328905,0.00313754,0.00311761,0.00312152,0.00313754,0.00236245,0.00459674,0.137236,0.137236,0.158073,0.0225357,0.00625221,0.00140949,0.00138066,0.00134124,0.00134144,0.137354,0.137354,0.027095,0.0177094,0.0421467,0.0480309,0.00234554", "perf/train": "0.0216697,0.00187091,0.00350926,0.00335179,0.00448751,0.343459,0.00192742,0.0237898,0.0186348,0.0186309,0.0185989,0.0420199,0.026694,0.0267248,0.0266938,0.0267131,0.00763508,0.00760645,0.00761405,0.00762056,0.00426339,0.0042825,0.0103777,0.010362,0.0282738,0.00931932,0.01403,0.142182,0.00706454,0.00340898,0.00335443,0.0112882,0.0583127,0.00581109,0.0056757,0.0342463,0.0342313,0.0432916,0.294438,0.0373717,0.00307298,0.00294608,0.0029495,0.00295019,0.00409383,0.00409325,0.00516006,0.00285235,0.0755874,0.0758538,0.0199683,0.161266,0.161266,0.0133873,0.0021909,0.00215047,0.00595157,0.0058228,0.00583423,0.0207194,0.00334362,0.00191599,0.001851,0.00221104,0.00108662,0.00108251,0.00103717,0.00342438,0.00108913,0.00126068,0.0012397,0.00124006,0.0865963,0.0865269,0.156794,0.156794,0.00131547,0.00126704,0.00126836,0.00143446,0.227473,0.227473,0.00190939,0.00108327,0.0100501,0.00108467,0.00108272,0.00103289,0.00103219,0.00103325,0.00468275,0.00428259,0.00305615,0.00185103,0.00176042,0.0125573,0.00359891,0.00193187,0.00185408,0.0406526,0.160613,0.160613,0.0010871,0.0321874,0.15878,0.15878,0.0750223,0.00134474,0.00132681,0.00295151,0.00292496,0.00292868,0.00517426,0.0051698,0.0157248,0.015722,0.0157399,0.0157338,0.0018165,0.00321646,0.00723484,0.103321,0.00108783,0.00477419,0.00325307,0.00707756,0.0070697,0.0322229,0.00367219,0.00350634,0.00348431,0.00348853,0.00350515,0.00261808,0.00491832,0.160518,0.160518,0.162446,0.025123,0.00669567,0.0016291,0.00159635,0.00155286,0.0015512,0.159791,0.159791,0.0282696,0.0189426,0.0449844,0.0493439,0.0025889", "util/gpu_percent": "79.5667,0,0,53.3415,0,100,0,43.2632,87.5526,86,86,24.8947,89,89,89.1053,90,57.4737,84,84,84,83,83,82.2245,82,94,84,82,99.6,39.4,54.9296,75,45.7368,93,0,32.8421,92,92,93.3636,89,92,1,1,1,1,1,57.5128,85.9737,3,94.3684,95,71.2917,78,78,76.7388,31.7143,36,1,1,51.5263,85.7097,0,5,5,0,0,22.7556,64,82,0,28.6577,70,69.8954,95,95,63,63,24.8026,65,65,21.0294,83,83,1,1,52.1493,0,0,0,0,0,0,83,80,1,1,88,27.1961,0,0,86,78,78,0,86,31,31,90,1,1,35.1333,85,85,74.0426,87,85.7368,85.4211,86.3158,87,3,1,2,93.9643,1,23.1538,3,19.6842,86,65.5273,0,46.1053,73,73,73,4,30.6557,25,25,92,88.5333,44.1014,7,7,7,7,64,64,97,0,63.8462,98.6429,13.4474", "util/gpu_mem": "8.80302,8.88445,8.73789,8.73789,8.67275,9.54395,8.66461,7.22348,7.22348,7.22348,7.22348,8.74603,8.74603,8.74603,8.74603,8.74603,8.75417,8.75417,8.75417,8.75417,8.80302,8.80302,6.71053,6.71053,8.83559,8.81931,9.25083,9.7475,8.8763,8.90073,8.90073,8.83559,7.23976,8.69718,8.69718,10.8711,10.8711,8.17609,9.24269,9.25898,8.73789,8.73789,8.73789,8.73789,8.90073,8.90073,9.13685,8.92515,8.94958,8.94958,8.74603,10.9573,10.9573,9.06357,8.82745,8.82745,8.7786,8.7786,8.7786,8.73789,6.35228,8.82745,8.82745,8.76231,8.75417,8.75417,8.75417,6.66168,8.75417,8.73789,8.73789,8.73789,8.94958,8.94958,14.4253,14.4253,8.77046,8.77046,8.77046,8.75417,10.7823,10.7823,8.88445,8.75417,8.82745,8.75417,8.75417,8.75417,8.75417,8.75417,8.68904,8.78674,8.8763,8.91701,8.91701,9.03914,8.77046,8.66461,8.66461,7.81784,14.7159,14.7159,8.74603,8.94958,10.7971,10.7971,8.55876,8.72975,8.72975,8.94144,8.94144,8.94144,8.8763,8.8763,9.09614,9.09614,9.09614,9.09614,8.76231,8.77046,8.77046,9.27526,8.74603,8.74603,8.88445,8.81117,8.81117,8.76231,8.77046,8.77046,8.77046,8.77046,8.77046,8.73789,9.00657,10.7955,10.7955,9.97547,8.74603,8.75417,8.66461,8.66461,8.66461,8.66461,14.1284,14.1284,9.06357,8.81117,8.94958,9.83706,8.77046", "util/vram_used_gb": "1.65057,1.6701,1.63495,1.63495,1.61932,1.82831,1.61737,1.27167,1.27167,1.27167,1.27167,1.6369,1.6369,1.6369,1.6369,1.6369,1.63885,1.63885,1.63885,1.63885,1.65057,1.65057,1.14862,1.14862,1.65839,1.65448,1.758,1.87714,1.66815,1.67401,1.67401,1.65839,1.27557,1.62518,1.62518,2.14667,2.14667,1.50018,1.75604,1.75995,1.63495,1.63495,1.63495,1.63495,1.67401,1.67401,1.73065,1.67987,1.68573,1.68573,1.6369,2.15277,2.15277,1.71307,1.65643,1.65643,1.64471,1.64471,1.64471,1.63495,1.06268,1.65643,1.65643,1.64081,1.63885,1.63885,1.63885,1.1369,1.63885,1.63495,1.63495,1.63495,1.68573,1.68573,2.98468,2.98468,1.64276,1.64276,1.64276,1.63885,2.11078,2.11078,1.6701,1.63885,1.65643,1.63885,1.63885,1.63885,1.63885,1.63885,1.62323,1.64667,1.66815,1.67792,1.67792,1.70721,1.64276,1.61737,1.61737,1.41425,3.05438,3.05438,1.6369,1.68573,2.11432,2.11432,1.59198,1.633,1.633,1.68378,1.68378,1.68378,1.66815,1.66815,1.72089,1.72089,1.72089,1.72089,1.64081,1.64276,1.64276,1.76385,1.6369,1.6369,1.6701,1.65253,1.65253,1.64081,1.64276,1.64276,1.64276,1.64276,1.64276,1.63495,1.6994,2.11395,2.11395,1.93182,1.6369,1.63885,1.61737,1.61737,1.61737,1.61737,2.91345,2.91345,1.71307,1.65253,1.68573,1.89862,1.64276", "util/vram_total_gb": "23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5126,23.5126,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5126,23.5126,23.5272,23.5272,23.5272,23.5272,23.5126,23.5126,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5126,23.5126,23.5272,23.5272,23.5126,23.5126,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5126,23.5126,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5126,23.5126,23.5272,23.5272,23.5272,23.5272,23.5272", "util/cpu_mem_gb": "1.01831,1.00273,1.00096,1.00096,1.00309,1.0608,1.00103,1.01082,1.01082,1.01082,1.01082,1.0097,1.0097,1.0097,1.0097,1.0097,1.0076,1.0076,1.0076,1.0076,1.00148,1.00148,1.00866,1.00915,1.01101,1.00269,1.01083,1.03928,1.00111,1.0066,1.0066,1.00825,1.02687,1.00372,1.0039,1.01419,1.01419,1.01326,1.06999,1.01738,1.00074,1.00074,1.00074,1.00074,1.0056,1.00564,1.00254,1.00261,1.0357,1.0357,1.0138,0.846672,0.846672,1.00831,1.00325,1.00325,1.00148,1.00148,1.00148,1.00707,1.00066,1.00382,1.00382,1.00246,1.00016,1.00016,1.00016,0.999019,0.999733,1.00036,1.00036,1.0006,1.03509,1.03509,0.846458,0.846458,1.00442,1.00442,1.0048,0.998589,0.734669,0.734669,1.00146,0.999611,1.00729,1.00159,1.00159,1.00186,1.00208,1.00208,1.00415,1.0017,1.0023,1.00415,1.00415,1.00513,1.00116,1.00109,1.00109,1.01823,0.846695,0.846695,0.999649,1.02635,0.846474,0.846474,1.03257,1.00084,0.997852,1.00888,1.00907,1.00941,1.00407,1.00407,1.01496,1.01496,1.01496,1.01496,0.999897,1.00043,1.00367,1.03156,0.999146,0.999985,1.00126,1.00441,1.00441,1.01838,1.00243,1.00243,1.00243,1.00243,1.00243,1.00243,1.00307,0.846466,0.846466,1.03593,1.01095,1.00444,0.998783,0.998783,0.999271,0.999271,0.846493,0.846493,1.02584,1.00827,1.02785,1.0224,1.00335", "wandb": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "rank": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "world_size": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "gpu_id": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "profile": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "checkpoint_interval": "200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200", "eval_episodes": "10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000", "cudagraphs": "10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10", "seed": "73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73", "vec/total_agents": "256,1024,1024,1024,2048,256,1024,256,256,256,256,512,512,512,512,512,256,256,256,256,1024,1024,256,256,1024,512,512,512,1024,1024,1024,1024,512,1024,1024,512,512,512,256,512,1024,1024,1024,1024,512,512,512,256,256,256,256,1024,1024,256,1024,1024,512,512,512,1024,512,1024,1024,2048,1024,1024,1024,512,1024,256,256,256,256,256,1024,1024,256,256,256,1024,1024,1024,1024,1024,256,1024,1024,1024,1024,1024,512,512,512,2048,2048,1024,1024,1024,1024,512,1024,1024,1024,256,1024,1024,512,512,512,256,256,256,1024,1024,256,256,256,256,2048,1024,1024,256,1024,1024,1024,2048,2048,256,1024,1024,1024,1024,1024,1024,1024,1024,1024,512,512,256,1024,1024,1024,1024,1024,1024,1024,512,256,1024,256", "vec/num_buffers": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1.45299,1.45299,1.45299,1.45299,1,1,1,1,1,1,1,2.50826,1,2.65521,2.65521,1,1,1.49673,1.49673,1,1,1,1.92028,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2.64622,2.64622,1,1,1,1.16376,1.33025,2.41735,2.41735,1.50668,1.13338,1.13338,1.13338,1,1,1,1,1,1.14173,1.14173,1,1,1.98534,1.98534,1.98534,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2.77776,2.77776,1,1,1,1,1,1,1,1,1,1,1,1,1.06854,1,2.60395,2.60395,2.60395,1,1,1,1,1,1,1,1,1,1,1,1,1.06673,1,1,1,1.38452,1.38452,1.38452,1.38452,1.38452,1.23155,1,1,1,1,1.22576,1,1,1,1,1,1,1,2.12714,1,1,2.08433,1.20074", "vec/num_threads": "16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16", "env/width": "500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500", "env/height": "640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640,640", "env/paddle_width": "20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20", "env/paddle_height": "70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70,70", "env/ball_width": "32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32", "env/ball_height": "32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32", "env/paddle_speed": "8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8", "env/ball_initial_speed_x": "10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10", "env/ball_initial_speed_y": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "env/ball_speed_y_increment": "3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3", "env/ball_max_speed_y": "13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13", "env/max_score": "21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21,21", "env/frameskip": "8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,7,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,7,7,7,7,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,6,6,6,6,8,8,7,8,8,8,8,8,8,8,8,8,8,8,8,7,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8", "env/continuous": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "policy/hidden_size": "64,32,32,32,32,256,32,128,128,128,128,128,128,128,128,128,128,128,128,128,32,32,128,128,32,64,128,256,128,32,32,32,128,32,32,256,256,256,64,128,32,32,32,32,64,64,128,256,64,64,64,32,32,256,32,32,128,128,128,32,32,32,32,32,32,32,32,256,32,128,128,128,64,64,32,32,64,64,64,32,32,32,32,32,128,32,32,32,32,32,64,64,128,32,32,64,32,32,32,128,32,32,32,64,32,32,128,64,64,128,128,128,32,32,128,128,128,128,32,32,32,256,32,128,64,32,32,32,32,32,32,32,32,32,64,32,32,256,128,128,32,32,32,32,32,32,32,64,64,128,128", "policy/num_layers": "3.00039,2.40179,2.18143,2.18143,1,3.70554,1,2.74396,2.74396,2.74396,2.74396,1.43253,1.43253,1.43253,1.43253,1.43253,2.39563,2.39563,2.39563,2.39563,3.59786,3.59786,2.77043,2.77043,5.3748,3.06502,2.67593,5.88949,2.73088,2.36363,2.36363,3.26368,3.23817,1,1,4.06587,4.06587,3.70224,3.59706,4.83884,2.8001,2.8001,2.8001,2.8001,2.52106,2.52106,4.11442,1.06107,3.30951,3.30951,2.55596,1,1,3.35717,1.21021,1.21021,1.90076,1.90076,1.90076,3.21911,1,1,1,1.61339,1,1,1,1.18172,1.93987,1.03901,1.03901,1.03901,3.34669,3.34669,1,1,1.43639,1.43639,1.43639,1,1,1,2.76126,1,3.01319,1,1,1,1,1,1.11069,3.92421,2.28341,1.31302,1.31302,3.45735,1,1,1,1.24308,1,1,1,2.40426,1,1,4.24365,1.36251,1.45581,1.73459,1.73459,1.73459,4.60343,4.60343,3.71603,3.71603,3.71603,3.71603,1,1,2.2546,3.55548,1,1.875,2.51189,3.12003,3.12003,3.08371,1,1,1,1,1,2.57724,3.36255,1,1,4.43515,1.18572,2.99816,1,1,1,1,1,1,5.08878,2.42111,2.67927,7.08579,1.08932", "policy/expansion_factor": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "legacy/torch_deterministic": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "legacy/cpu_offload": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "legacy/compile": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "legacy/compile_fullgraph": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "train/gpus": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "train/seed": "42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42", "train/total_timesteps": "7.94166,6.66784,5.4641,5.4641,9.82759,5,6.87712,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,6.39787,6.39787,5,6.31562,7.03077,14.2434,7.18967,9.70307,9.70307,5,5,5,5,5,5,5.79344,6.21862,5.42431,5.42281,5.42281,5.42281,5.42281,5.13184,5.13184,5,8.12417,5,5,9.56279,5,5,8.86063,6.00041,6.00041,5,5,5,8.13258,5,9.99055,9.99055,8.75273,5.98043,5.98043,5.98043,5,9.25122,5,5,5,5,5,5,5,5,5,5,5,5,5,8.8773,12.5237,8.83951,5,5,5,5,5,6.41689,6.23565,7.51639,5,5,7.24134,13.4413,6.02057,6.02057,5,5,5,5,5.01168,5,5,5.02224,5,5,5,5,5,6.19727,6.19727,5,5,5,5,10.0338,5,8.07273,7.5139,5,7.31362,13.5555,5,5,7.15582,5,5,5,5,5,9.38451,8.47068,5,5,5,7.85091,9.77192,6.16281,6.16281,6.16281,6.16281,5,5,5,7.37806,6.75279,7.49613,5", "train/learning_rate": "0.1,0.1,0.0433993,0.0433993,0.0405439,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.0878587,0.0586232,0.0831725,0.0804395,0.1,0.1,0.0967872,0.1,0.1,0.1,0.1,0.1,0.1,0.0143578,0.1,0.0404152,0.0404152,0.0404152,0.0404152,0.1,0.1,0.1,0.0275441,0.1,0.1,0.054078,0.1,0.1,0.0446808,0.1,0.1,0.1,0.1,0.1,0.0605591,0.0871341,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.0535439,0.0535439,0.1,0.1,0.1,0.1,0.1,0.068015,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.044617,0.1,0.1,0.1,0.1,0.0320222,0.0320222,0.0353645,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.0914225,0.0666117,0.0666117,0.0666117,0.042082,0.042082,0.0359374,0.0359374,0.0359374,0.0359374,0.1,0.0610919,0.027306,0.1,0.1,0.0868428,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.096046,0.0480936,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.0542063,0.0246945,0.1", "train/anneal_lr": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "train/min_lr_ratio": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "train/gamma": "0.980504,0.930403,0.8,0.8,0.943177,0.995027,0.914936,0.992889,0.992889,0.992889,0.992889,0.977696,0.977696,0.977696,0.977696,0.977696,0.991933,0.991933,0.991933,0.991933,0.982697,0.982697,0.970856,0.970856,0.993861,0.994498,0.965082,0.916448,0.918338,0.974833,0.974833,0.930599,0.998037,0.957361,0.957361,0.992113,0.992113,0.98602,0.974062,0.975102,0.866585,0.866585,0.866585,0.866585,0.979864,0.979864,0.86685,0.981895,0.993726,0.993726,0.944506,0.934713,0.934713,0.982187,0.918282,0.918282,0.963867,0.963867,0.963867,0.970557,0.979078,0.93501,0.93501,0.838554,0.981305,0.981305,0.981305,0.865048,0.945897,0.8654,0.8654,0.8654,0.929454,0.929454,0.934713,0.934713,0.969892,0.969892,0.969892,0.938747,0.934713,0.934713,0.936133,0.899811,0.968705,0.934713,0.934713,0.934713,0.934713,0.934713,0.916513,0.964405,0.921959,0.974196,0.974196,0.98529,0.973119,0.936682,0.936682,0.991239,0.934713,0.934713,0.906039,0.947295,0.934713,0.934713,0.987262,0.992232,0.983258,0.956014,0.956014,0.956014,0.944231,0.944231,0.985994,0.985994,0.985994,0.985994,0.940911,0.934132,0.925642,0.9878,0.923141,0.933087,0.946966,0.920388,0.920388,0.962131,0.982639,0.982639,0.982639,0.982639,0.982639,0.863756,0.856758,0.934713,0.934713,0.987109,0.988133,0.982768,0.978462,0.978462,0.978462,0.978462,0.934713,0.934713,0.980563,0.987912,0.98821,0.985063,0.973075", "train/gae_lambda": "0.950936,0.995,0.991413,0.991413,0.989299,0.991189,0.993717,0.992128,0.992128,0.992128,0.992128,0.980848,0.980848,0.980848,0.980848,0.980848,0.967222,0.967222,0.967222,0.967222,0.99432,0.99432,0.985612,0.985612,0.995,0.995,0.994242,0.995,0.995,0.995,0.995,0.995,0.991573,0.976865,0.976865,0.979539,0.979539,0.994163,0.961564,0.988969,0.98053,0.98053,0.98053,0.98053,0.995,0.995,0.994964,0.986016,0.987245,0.987245,0.991993,0.991989,0.991989,0.971398,0.994575,0.994575,0.994065,0.994065,0.994065,0.995,0.978638,0.959698,0.959698,0.991492,0.968226,0.968226,0.968226,0.956806,0.992878,0.961191,0.961191,0.961191,0.992277,0.992277,0.991989,0.991989,0.994725,0.994725,0.994725,0.970975,0.991989,0.991989,0.992153,0.993192,0.994159,0.991989,0.991989,0.991989,0.991989,0.991989,0.992512,0.995,0.989284,0.991047,0.991047,0.995,0.995,0.992272,0.992272,0.992791,0.991989,0.991989,0.988237,0.994431,0.991989,0.991989,0.954845,0.982842,0.976204,0.994922,0.994922,0.994922,0.993866,0.993866,0.987423,0.987423,0.987423,0.987423,0.989411,0.995,0.98876,0.961696,0.987915,0.986636,0.995,0.995,0.995,0.982887,0.985203,0.985203,0.985203,0.985203,0.985203,0.977655,0.995,0.991989,0.991989,0.962462,0.97909,0.994862,0.995,0.995,0.995,0.995,0.991989,0.991989,0.995,0.995,0.967598,0.989323,0.983643", "train/replay_ratio": "3.12751,4,4,4,3.53985,4,3.10817,3.68963,3.68963,3.68963,3.68963,4,4,4,4,4,4,4,4,4,4,4,3.9407,3.9407,3.76114,3.63886,4,4,4,4,4,4,4,3.54522,3.54522,3.96139,3.96139,4,4,3.62814,3.93495,3.93495,3.93495,3.93495,3.83107,3.83107,3.60247,3.10021,3.51174,3.51174,3.99671,3.05148,3.05148,4,3.53669,3.53669,4,4,4,4,4,3.2238,3.2238,3.44118,3.44895,3.44895,3.44895,4,3.44432,4,4,4,4,4,3.05148,3.05148,3.60268,3.60268,3.60268,4,3.05148,3.05148,4,3.05511,4,3.05148,3.05148,3.05148,3.05148,3.05148,3.46737,4,3.5218,2.85618,2.85618,4,4,3.28371,3.28371,4,3.05148,3.05148,3.80512,4,3.05148,3.05148,4,4,4,4,4,4,4,4,4,4,4,4,2.61819,3.7916,3.31063,4,3.65467,3.9105,3.5313,3.41099,3.41099,4,4,4,4,4,4,3.16254,4,3.05148,3.05148,4,3.81157,3.61191,2.94579,2.94579,2.94579,2.94579,3.05148,3.05148,3.77788,3.61594,4,4,3.8003", "train/clip_coef": "0.332484,0.821643,0.907985,0.907985,0.704026,0.212873,0.9389,0.147554,0.147554,0.147554,0.147554,0.22418,0.22418,0.22418,0.22418,0.22418,0.343518,0.343518,0.343518,0.343518,0.366621,0.366621,0.219313,0.219313,0.337193,0.37945,0.45448,0.285982,0.605696,0.454761,0.454761,0.536595,0.528763,0.715091,0.715091,0.174121,0.174121,0.0565402,0.179337,0.332806,0.693442,0.693442,0.693442,0.693442,0.34475,0.34475,0.375969,0.38062,0.193284,0.193284,0.133777,0.822764,0.822764,0.0876291,0.721569,0.721569,0.384944,0.384944,0.384944,0.24555,0.730967,1,1,0.945887,0.709703,0.709703,0.709703,0.417396,0.920318,0.370232,0.370232,0.370232,0.135083,0.135083,0.822764,0.822764,0.158136,0.158136,0.158136,0.696506,0.822764,0.822764,0.691269,0.664672,0.206311,0.822764,0.822764,0.822764,0.822764,0.822764,0.206396,0.463664,0.300216,0.778074,0.778074,0.537943,0.785145,0.713407,0.713407,0.435798,0.822764,0.822764,1,0.0775286,0.822764,0.822764,0.192012,0.418545,0.341938,0.406391,0.406391,0.406391,0.583457,0.583457,0.186603,0.186603,0.186603,0.186603,0.850845,0.89123,0.795574,0.134384,0.820027,0.475342,0.797425,0.618035,0.618035,0.303984,1,1,1,1,1,0.85219,0.865681,0.822764,0.822764,0.229346,0.119856,0.137007,0.743873,0.743873,0.743873,0.743873,0.822764,0.822764,0.440954,0.326697,0.246491,0.323433,0.280905", "train/vf_coef": "4.82036,5,5,5,5,4.38492,5,4.988,4.988,4.988,4.988,3.72307,3.72307,3.72307,3.72307,3.72307,4.33534,4.33534,4.33534,4.33534,5,5,4.15232,4.15232,4.13455,5,4.12525,3.91724,5,5,5,3.9014,3.77887,4.8492,4.8492,3.09905,3.09905,4.32007,5,4.33679,3.5718,3.5718,3.5718,3.5718,4.6254,4.6254,4.10181,4.82425,3.01332,3.01332,2.94417,5,5,4.39638,3.52211,3.52211,4.20619,4.20619,4.20619,5,4.65398,5,5,5,4.23411,4.23411,4.23411,4.20782,3.8829,3.02824,3.02824,3.02824,3.46375,3.46375,5,5,4.75651,4.75651,4.75651,3.99096,5,5,4.17073,3.936,4.39352,5,5,5,5,5,3.54067,5,5,4.47042,4.47042,5,4.69775,4.66725,4.66725,4.82898,5,5,5,4.69205,5,5,4.14292,3.44591,3.35169,3.429,3.429,3.429,5,5,3.44784,3.44784,3.44784,3.44784,5,5,5,3.7188,5,4.51742,5,4.44858,4.44858,5,3.81724,3.81724,3.81724,3.81724,3.81724,4.22121,5,5,5,4.28308,5,3.39991,3.90153,3.90153,3.90153,3.90153,5,5,5,5,3.82491,5,4.40297", "train/vf_clip_coef": "5,4.93889,5,5,5,5,5,5,5,5,5,5,5,5,5,5,4.21639,4.21639,4.21639,4.21639,3.80059,3.80059,5,5,4.33647,5,5,4.4668,5,3.26586,3.26586,5,5,5,5,4.8361,4.8361,5,4.50944,4.72505,4.01741,4.01741,4.01741,4.01741,5,5,4.83335,5,3.76382,3.76382,5,4.95789,4.95789,5,4.71406,4.71406,5,5,5,5,4.25169,4.43002,4.43002,5,4.8905,4.8905,4.8905,5,5,4.66711,4.66711,4.66711,5,5,4.95789,4.95789,5,5,5,4.86419,4.95789,4.95789,4.10899,4.63416,4.66625,4.95789,4.95789,4.95789,4.95789,4.95789,4.65235,4.57209,4.8083,4.10018,4.10018,4.38135,5,5,5,4.34343,4.95789,4.95789,4.02601,4.54071,4.95789,4.95789,4.39533,5,5,5,5,5,4.01245,4.01245,5,5,5,5,5,5,5,4.6076,4.25545,4.3898,5,3.9702,3.9702,4.62768,4.16951,4.16951,4.16951,4.16951,4.16951,5,4.74845,4.95789,4.95789,4.38638,4.83886,5,3.92318,3.92318,3.92318,3.92318,4.95789,4.95789,5,4.28332,4.46159,5,3.88864", "train/max_grad_norm": "2.07145,0.1,0.927825,0.927825,1.7359,1.20567,2.95785,0.660313,0.660313,0.660313,0.660313,1.57694,1.57694,1.57694,1.57694,1.57694,1.76086,1.76086,1.76086,1.76086,1.11288,1.11288,1.40989,1.40989,1.35662,0.1,1.82799,2.6447,0.908762,0.1,0.1,0.76888,1.28748,2.36622,2.36622,2.12496,2.12496,0.721294,1.75157,0.822413,4.2659,4.2659,4.2659,4.2659,1.27234,1.27234,1.58238,1.46957,2.10444,2.10444,0.419395,0.752747,0.752747,1.5888,0.1,0.1,1.17618,1.17618,1.17618,1.59937,0.859178,0.208092,0.208092,0.671708,2.68679,2.68679,2.68679,1.42754,1.39743,1.82302,1.82302,1.82302,2.43003,2.43003,0.752747,0.752747,1.9679,1.9679,1.9679,0.529914,0.752747,0.752747,1.68509,2.76827,0.884127,0.752747,0.752747,0.752747,0.752747,0.752747,2.04846,0.1,1.16105,0.419209,0.419209,0.1,1.17889,2.35892,2.35892,0.567368,0.752747,0.752747,2.01785,1.57529,0.752747,0.752747,1.43674,2.62216,1.26835,0.89485,0.89485,0.89485,0.1,0.1,0.974583,0.974583,0.974583,0.974583,1.87712,1.57985,2.90278,0.968083,1.37335,0.1,1.2952,1.31109,1.31109,1.28502,2.01385,2.01385,2.01385,2.01385,2.01385,0.709413,0.1,0.752747,0.752747,2.05256,1.06694,0.636717,0.812321,0.812321,0.812321,0.812321,0.752747,0.752747,0.435032,0.110862,2.28464,1.22951,1.66372", "train/ent_coef": "1.05274e-05,0.000837012,0.000928481,0.000928481,0.00090285,1e-05,0.0143077,1.01368e-05,1.01368e-05,1.01368e-05,1.01368e-05,1.94027e-05,1.94027e-05,1.94027e-05,1.94027e-05,1.94027e-05,1.0455e-05,1.0455e-05,1.0455e-05,1.0455e-05,1.09858e-05,1.09858e-05,1.65103e-05,1.65103e-05,5.65974e-05,1.58532e-05,0.000158832,0.000149359,1.41538e-05,9.82076e-05,9.82076e-05,1e-05,0.000249272,0.0191293,0.0191293,1e-05,1e-05,4.71842e-05,1e-05,0.000234792,0.0072444,0.0072444,0.0072444,0.0072444,6.04028e-05,6.04028e-05,1e-05,1e-05,1e-05,1e-05,9.43148e-05,0.000402915,0.000402915,2.05779e-05,0.00110973,0.00110973,0.000187339,0.000187339,0.000187339,6.1608e-05,0.000228278,0.000598231,0.000598231,0.00729358,0.00537041,0.00537041,0.00537041,1e-05,0.00487791,1e-05,1e-05,1e-05,7.98965e-05,7.98965e-05,0.000402915,0.000402915,1e-05,1e-05,1e-05,0.0114249,0.000402915,0.000402915,0.000120466,0.00728303,1.84668e-05,0.000402915,0.000402915,0.000402915,0.000402915,0.000402915,0.000147701,3.00513e-05,7.69371e-05,0.00150687,0.00150687,3.8464e-05,0.0076036,0.000316694,0.000316694,1e-05,0.000402915,0.000402915,0.00546722,0.000104188,0.000402915,0.000402915,9.5514e-05,9.93626e-05,1e-05,0.000183704,0.000183704,0.000183704,0.000405309,0.000405309,0.000127544,0.000127544,0.000127544,0.000127544,0.00338022,0.0421521,0.0233766,1e-05,0.00453531,0.000183574,0.00334322,1e-05,1e-05,0.00131997,0.00845334,0.00845334,0.00845334,0.00845334,0.00845334,0.000566675,0.000696192,0.000402915,0.000402915,1e-05,2.19662e-05,6.17371e-05,0.00703612,0.00703612,0.00703612,0.00703612,0.000402915,0.000402915,0.000135109,3.78203e-05,1e-05,0.000638732,0.000125259", "train/beta1": "0.655755,0.5,0.5,0.5,0.5,0.5,0.526872,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.63127,0.63127,0.63127,0.63127,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.587151,0.562194,0.5,0.5,0.65907,0.65907,0.5,0.5,0.501325,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.73738,0.513241,0.513241,0.5,0.5,0.5,0.616188,0.5,0.5,0.578537,0.578537,0.578537,0.5,0.500975,0.609573,0.609573,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.56629,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.566833,0.566833,0.749103,0.5,0.5,0.5,0.5,0.5,0.5,0.556474,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.756783,0.756783,0.756783,0.756783,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.631891,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.680572,0.66537,0.773395,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.688108,0.729848,0.5,0.5", "train/beta2": "0.99009,0.99575,0.931763,0.931763,0.987255,0.991466,0.964697,0.973231,0.973231,0.973231,0.973231,0.9,0.9,0.9,0.9,0.9,0.994395,0.994395,0.994395,0.994395,0.938371,0.938371,0.969821,0.969821,0.904368,0.9,0.9,0.987936,0.9,0.979509,0.979509,0.945087,0.98436,0.9,0.9,0.970149,0.970149,0.994927,0.9904,0.9,0.971875,0.971875,0.971875,0.971875,0.900219,0.900219,0.994876,0.9,0.996634,0.996634,0.9,0.947709,0.947709,0.915879,0.9,0.9,0.988807,0.988807,0.988807,0.9,0.989711,0.968984,0.968984,0.980793,0.923424,0.923424,0.923424,0.9,0.961869,0.981223,0.981223,0.981223,0.993192,0.993192,0.947709,0.947709,0.9,0.9,0.9,0.92361,0.947709,0.947709,0.9,0.983215,0.99427,0.947709,0.947709,0.947709,0.947709,0.947709,0.990647,0.936383,0.901181,0.9,0.9,0.9,0.9,0.987433,0.987433,0.975808,0.947709,0.947709,0.945203,0.993376,0.947709,0.947709,0.996399,0.929442,0.991882,0.991153,0.991153,0.991153,0.98573,0.98573,0.9,0.9,0.9,0.9,0.9,0.967085,0.989169,0.996636,0.989628,0.9,0.9,0.9,0.9,0.995171,0.989014,0.989014,0.989014,0.989014,0.989014,0.9,0.946867,0.947709,0.947709,0.991364,0.946879,0.988725,0.959773,0.959773,0.959773,0.959773,0.947709,0.947709,0.974171,0.9,0.992276,0.9,0.9", "train/eps": "4.52368e-05,3.16556e-08,8.04247e-06,8.04247e-06,0.0001,5.32132e-08,4.97625e-07,3.7534e-07,3.7534e-07,3.7534e-07,3.7534e-07,1.42354e-05,1.42354e-05,1.42354e-05,1.42354e-05,1.42354e-05,2.69605e-05,2.69605e-05,2.69605e-05,2.69605e-05,0.0001,0.0001,9.51624e-06,9.51624e-06,1.23981e-05,0.0001,1.47953e-07,3.26321e-05,3.09567e-07,0.0001,0.0001,0.0001,6.29113e-05,4.85039e-05,4.85039e-05,4.48745e-05,4.48745e-05,1.5069e-07,0.0001,1.99254e-05,0.0001,0.0001,0.0001,0.0001,4.1782e-07,4.1782e-07,1.46024e-06,0.0001,8.85564e-05,8.85564e-05,6.30253e-05,0.0001,0.0001,4.12776e-08,4.86526e-06,4.86526e-06,9.4614e-08,9.4614e-08,9.4614e-08,1.08208e-06,0.0001,4.6856e-05,4.6856e-05,5.49505e-06,0.0001,0.0001,0.0001,0.0001,5.40652e-07,0.0001,0.0001,0.0001,1.33805e-06,1.33805e-06,0.0001,0.0001,0.0001,0.0001,0.0001,0.0001,0.0001,0.0001,0.0001,3.25169e-05,1.33024e-07,0.0001,0.0001,0.0001,0.0001,0.0001,1.75914e-06,0.0001,0.0001,4.21422e-07,4.21422e-07,3.50308e-05,2.28075e-05,1.69934e-07,1.69934e-07,1.34052e-05,0.0001,0.0001,3.04651e-05,2.3276e-05,0.0001,0.0001,1.03387e-07,7.21772e-08,0.0001,0.0001,0.0001,0.0001,0.0001,0.0001,0.0001,0.0001,0.0001,0.0001,3.40761e-05,0.0001,0.0001,3.39675e-08,0.0001,0.0001,0.0001,6.50073e-07,6.50073e-07,0.0001,6.71943e-08,6.71943e-08,6.71943e-08,6.71943e-08,6.71943e-08,7.13689e-05,6.33656e-07,0.0001,0.0001,6.25655e-07,0.0001,4.84891e-07,0.0001,0.0001,0.0001,0.0001,0.0001,0.0001,1.75843e-07,0.0001,1.84914e-06,3.79507e-07,2.30246e-07", "train/minibatch_size": "4096,32768,16384,16384,16384,4096,16384,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,16384,16384,8192,8192,8192,8192,16384,4096,8192,16384,16384,16384,16384,16384,16384,16384,16384,8192,4096,8192,16384,16384,16384,16384,16384,16384,8192,8192,4096,4096,4096,32768,32768,4096,16384,16384,8192,8192,8192,8192,16384,16384,16384,32768,32768,32768,32768,8192,32768,8192,8192,8192,4096,4096,32768,32768,16384,16384,16384,32768,32768,32768,32768,32768,4096,32768,32768,32768,32768,32768,8192,8192,8192,32768,32768,16384,32768,16384,16384,8192,32768,32768,32768,8192,32768,32768,16384,16384,16384,8192,8192,8192,16384,16384,8192,8192,8192,8192,32768,32768,16384,4096,32768,8192,16384,16384,16384,4096,32768,32768,32768,32768,32768,16384,16384,32768,32768,8192,4096,4096,16384,16384,16384,16384,32768,32768,8192,8192,8192,8192,8192", "train/horizon": "128,32,32,32,32,512,32,128,128,128,128,128,128,128,128,128,64,64,64,64,32,32,128,128,64,64,128,128,32,32,32,64,256,64,64,128,128,128,512,128,32,32,32,32,64,64,32,64,256,256,128,32,32,64,32,32,64,64,64,64,64,32,32,32,32,32,32,32,32,32,32,32,256,256,32,32,64,64,64,32,32,32,32,32,64,32,32,32,32,32,64,32,32,32,32,64,64,32,32,256,32,32,32,256,32,32,256,32,32,64,64,64,32,32,128,128,128,128,32,64,64,256,32,32,32,32,32,128,64,64,64,64,64,32,32,32,32,256,128,64,32,32,32,32,32,32,64,128,256,64,64", "train/vtrace_rho_clip": "4.27097,5,5,5,4.8478,4.44461,5,3.93408,3.93408,3.93408,3.93408,4.53779,4.53779,4.53779,4.53779,4.53779,4.66369,4.66369,4.66369,4.66369,3.96129,3.96129,3.93121,3.93121,4.57034,4.81541,4.26767,4.04593,3.63436,4.4133,4.4133,3.30113,4.32525,5,5,4.79355,4.79355,4.93779,4.94608,3.32384,4.90729,4.90729,4.90729,4.90729,4.27392,4.27392,4.53285,3.94338,3.56193,3.56193,4.31273,4.87841,4.87841,3.23016,5,5,4.04251,4.04251,4.04251,3.83493,4.75784,4.48187,4.48187,5,4.16946,4.16946,4.16946,4.44398,4.93401,4.84814,4.84814,4.84814,3.6442,3.6442,4.87841,4.87841,4.50327,4.50327,4.50327,4.71109,4.87841,4.87841,3.95888,4.64602,4.97304,4.87841,4.87841,4.87841,4.87841,4.87841,3.51441,3.34942,3.78681,3.25783,3.25783,4.38847,5,4.87958,4.87958,3.56231,4.87841,4.87841,4.51687,3.67184,4.87841,4.87841,3.80259,4.72205,4.7491,4.37092,4.37092,4.37092,3.31941,3.31941,3.87749,3.87749,3.87749,3.87749,5,5,5,2.72954,3.08844,5,4.60519,3.57458,3.57458,4.12392,5,5,5,5,5,5,4.40581,4.87841,4.87841,4.59721,3.72659,2.80953,4.07078,4.07078,4.07078,4.07078,4.87841,4.87841,5,3.44712,3.34996,5,3.616", "train/vtrace_c_clip": "0.204552,1.10388,1.82918,1.82918,1.41052,0.1,1.60465,0.1,0.1,0.1,0.1,0.840882,0.840882,0.840882,0.840882,0.840882,0.207587,0.207587,0.207587,0.207587,0.785771,0.785771,0.1,0.1,0.814381,0.1,0.553195,0.917512,0.473109,0.625526,0.625526,1.02161,0.1,1.54816,1.54816,0.1,0.1,0.1,0.1,0.582331,1.31014,1.31014,1.31014,1.31014,0.966801,0.966801,0.339064,0.22797,0.210623,0.210623,0.1,1.48608,1.48608,0.298036,1.0113,1.0113,0.312122,0.312122,0.312122,0.741106,0.1,1.56693,1.56693,1.65905,1.43123,1.43123,1.43123,0.1,0.914319,0.437204,0.437204,0.437204,0.957354,0.957354,1.48608,1.48608,0.791487,0.791487,0.791487,0.855348,1.48608,1.48608,0.938061,0.636434,0.1,1.48608,1.48608,1.48608,1.48608,1.48608,0.502555,0.1,0.1,1.20029,1.20029,0.1,0.952341,0.935297,0.935297,0.191251,1.48608,1.48608,0.459943,0.1,1.48608,1.48608,0.1,0.1,0.1,0.731986,0.731986,0.731986,1.08719,1.08719,0.1,0.1,0.1,0.1,1.11854,0.871452,1.23205,0.437754,0.834551,0.1,1.149,1.32057,1.32057,0.1,0.977461,0.977461,0.977461,0.977461,0.977461,1.41128,1.20613,1.48608,1.48608,0.234997,0.1,0.1,1.20342,1.20342,1.20342,1.20342,1.48608,1.48608,0.1,0.73874,0.1,0.716308,0.1", "train/prio_alpha": "0.630873,0.711344,0.596017,0.596017,0.294366,0.347214,0.362532,0.566724,0.566724,0.566724,0.566724,0.352416,0.352416,0.352416,0.352416,0.352416,0.764608,0.764608,0.764608,0.764608,0.357104,0.357104,0.564996,0.564996,0.918557,0.310954,0.374604,0.857054,0.75128,0.666324,0.666324,0.713554,0.647547,0.426737,0.426737,0.452961,0.452961,0.660915,0.402089,0.569888,0.151169,0.151169,0.151169,0.151169,0.513577,0.513577,0.631673,0.459517,0.556842,0.556842,0.733756,0.242089,0.242089,0.765241,0.612444,0.612444,0.705276,0.705276,0.705276,0.927346,1,0.611866,0.611866,0.595427,0.377826,0.377826,0.377826,0.455637,0.606411,0.373934,0.373934,0.373934,0.4769,0.4769,0.242089,0.242089,0.701246,0.701246,0.701246,0.201843,0.242089,0.242089,0.541798,0.418245,0.326373,0.242089,0.242089,0.242089,0.242089,0.242089,0.527651,0.499565,0.372444,0.5322,0.5322,0.550131,0.417669,0.529986,0.529986,0.491826,0.242089,0.242089,0.395521,0.404867,0.242089,0.242089,0.377108,0.607716,0.766491,0.781205,0.781205,0.781205,0.308286,0.308286,0.708842,0.708842,0.708842,0.708842,0.426775,0.251907,0.64382,0.775412,0.481467,0.755455,0.411282,0.690811,0.690811,0.534285,0.497506,0.497506,0.497506,0.497506,0.497506,0.545112,0.563305,0.242089,0.242089,0.528375,0.67134,0.609134,0.281657,0.281657,0.281657,0.281657,0.242089,0.242089,0.557717,0.56081,0.481843,1,0.716172", "train/prio_beta0": "0.704828,0.919559,1,1,0.885244,0.454634,1,0.395495,0.395495,0.395495,0.395495,0.791265,0.791265,0.791265,0.791265,0.791265,0.721734,0.721734,0.721734,0.721734,0.410591,0.410591,0.60186,0.60186,0.48639,0.678869,0.756229,0.428703,0.60261,0.677075,0.677075,0.540114,0.781082,0.992412,0.992412,0.395823,0.395823,0.611575,0.605706,0.633389,1,1,1,1,0.748643,0.748643,0.426189,0.353516,0.699224,0.699224,0.727251,0.807575,0.807575,0.57891,0.784143,0.784143,0.356227,0.356227,0.356227,0.855736,0.577375,1,1,1,1,1,1,0.620808,0.901396,0.831962,0.831962,0.831962,0.815274,0.815274,0.807575,0.807575,0.397869,0.397869,0.397869,1,0.807575,0.807575,0.939328,0.733684,0.809778,0.807575,0.807575,0.807575,0.807575,0.807575,0.620287,0.758975,0.645603,0.672183,0.672183,0.52028,0.654516,0.588823,0.588823,0.576547,0.807575,0.807575,0.677808,0.751098,0.807575,0.807575,0.757885,0.500279,0.781452,0.506672,0.506672,0.506672,0.743627,0.743627,0.806592,0.806592,0.806592,0.806592,0.783762,0.628581,0.974189,0.741476,0.59448,0.75893,0.541156,0.285499,0.285499,0.779738,1,1,1,1,1,0.651146,0.80059,0.807575,0.807575,0.625545,0.748295,0.492657,0.956384,0.956384,0.956384,0.956384,0.807575,0.807575,0.743671,0.616689,0.627931,0.569583,0.592889", "train/use_rnn": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "no_model_upload": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "slowly": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "save_frames": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "fps": "15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15", "reset_state": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "tsne1": "80.6513,75.9761,72.7498,72.7498,76.1916,82.7484,77.652,82.1296,82.1296,82.1296,82.1296,71.5344,71.5344,71.5344,71.5344,71.5344,80.6108,80.6109,80.6109,80.6108,73.5119,73.5119,81.8113,81.8113,71.2339,71.4282,71.8862,81.9254,70.2928,77.6714,77.6714,73.1151,79.9066,70.0518,70.0518,78.9234,78.9234,81.3892,83.3432,71.9641,79.6965,79.6965,79.6965,79.6965,71.9334,71.9332,82.5322,74.1524,83.9097,83.9101,72.2911,74.0605,74.165,74.9971,70.1866,70.1866,80.8776,80.8794,80.8795,71.0138,78.5313,74.757,74.757,73.8519,70.8751,70.8751,70.8751,70.2259,76.5948,83.344,83.344,83.3439,83.5513,83.5513,74.165,74.2537,73.271,73.271,73.271,71.915,73.3306,73.6519,70.9806,77.6527,82.5133,73.5957,73.0725,73.0725,73.2726,73.2726,82.7441,72.8296,70.8884,71.6076,71.6076,71.6488,70.2638,77.8392,77.8392,79.1975,72.9722,73.8959,75.721,82.95,74.2498,74.165,80.3691,72.6372,80.3283,81.1247,81.125,81.125,76.7747,76.7741,73.9308,73.9307,73.9307,73.9308,70.5915,75.935,77.6932,83.0557,76.8046,70.3175,70.0921,71.4511,71.4512,81.3087,77.3121,77.3121,77.3121,77.3121,77.3121,69.9405,72.9518,73.7123,73.7068,79.7229,78.361,79.5249,74.8801,74.8801,74.8801,74.88,72.9081,73.3306,77.7608,73.4931,79.5969,70.5128,72.3368", "tsne2": "6.87848,-9.01507,-9.53439,-9.53439,-5.42978,6.12916,-7.03875,5.84947,5.84947,5.84947,5.84947,6.87765,6.87764,6.87767,6.87764,6.87766,6.31835,6.31828,6.31828,6.31835,2.11091,2.11091,4.74069,4.74069,3.5118,5.36032,4.99671,3.08268,4.72068,-0.709484,-0.709484,1.83055,3.31517,-4.75271,-4.75271,4.69249,4.69249,4.90542,5.50272,5.68176,-6.93479,-6.93479,-6.93479,-6.93479,4.63277,4.63281,2.27612,6.58849,5.09771,5.09785,7.34769,-6.67263,-5.84439,6.9328,-2.33801,-2.33801,3.79616,3.79633,3.7963,3.65669,-0.377919,-8.54707,-8.54707,-9.53568,-5.17816,-5.17813,-5.17813,5.76859,-8.18248,1.70579,1.70579,1.70582,4.14058,4.14058,-5.84439,-6.39944,4.70938,4.70938,4.70938,-5.02676,-6.83049,-5.47803,-3.10344,-6.08581,5.07073,-6.17799,-6.08825,-6.08825,-5.63903,-5.63903,3.43544,3.0205,5.59411,-2.45354,-2.45354,4.05015,-3.82377,-5.20354,-5.20354,6.06493,-6.64807,-6.82076,-6.6059,4.45166,-6.40584,-5.84439,4.60616,4.00155,2.11945,2.88559,2.88554,2.88554,-2.95651,-2.95653,7.63754,7.63761,7.63761,7.63754,-4.0574,-6.53956,-6.99183,6.59808,-4.66725,4.66461,-3.51471,1.59418,1.5943,7.57382,-8.65886,-8.65886,-8.65886,-8.65886,-8.65886,-2.45055,-9.23768,-6.84597,-5.49229,5.41954,6.82033,6.93401,-4.02161,-4.02161,-4.02161,-4.02149,-6.40054,-6.83049,-0.145707,6.56669,6.04739,3.90946,5.56867"}, "slimevolley": {"SPS": "433653,804843,949239,945795,1.09783e+06,1.0985e+06,716178,715441,714834,6.7105e+06,6.69643e+06,1.41893e+06,1.41695e+06,1.41276e+06,2.56513e+06,1.21661e+07,1.276e+07,134030,133889,1.14676e+06,1.09525e+07,1.10453e+07,4.31064e+06,562692,562938,554552,565118,109541,6.58044e+06,2.63794e+06,1.74478e+06,378475,7.7336e+06,7.77117e+06,9.52923e+06,5.47214e+06,3.99292e+06,1.23369e+07,1.42547e+07,1.44926e+07,1.45281e+07,3.03563e+06,329518,329072,4.24695e+06,2.39857e+07,6.28071e+06,6.28458e+06,3.9762e+06,1.03914e+07,1.25166e+07,7.37279e+06,8.70302e+06,4.06452e+06,4.0643e+06,7.58853e+06,6.19053e+06,2.87414e+06,1.24106e+07,1.2495e+07,767733,1.10245e+06,1.19593e+06,2.7468e+06,4.88735e+06,2.77528e+06,1.41762e+07,758888,4.21415e+06,1.91324e+06,1.87591e+06,966165,968565,967623,635888,2.08893e+06,1.91397e+07,346169,345807,346613,346619,6.61742e+06,2.99019e+06,2.03287e+06,2.02817e+06,522227,1.08517e+07,4.81411e+06,1.7295e+07,1.7256e+07,3.4665e+06,106049,1.10015e+06,1.46778e+06,1.62309e+06,1.60102e+06,1.2686e+07,1.11686e+06,1.04333e+06,1.29098e+07,4.01853e+06,1.48002e+06,1.49178e+06,9.88347e+06,1.7758e+06,943901,944006,2.22991e+06,2.22851e+06,2.23188e+06,1.53975e+06,1.53972e+06,4.60347e+06,173060,173261,953289,953067,4.64906e+06,2.31465e+06,2.31459e+06,1.54291e+06,1.54009e+06,5.9487e+06,2.04532e+06,473032,473238,2.66022e+06,2.06028e+06,2.06081e+06,1.13474e+07,615320,133324,2.69456e+06,2.6939e+06,2.08867e+07,2.10913e+07,8.95011e+06,447757,447401,1.14462e+07,453869,7.27275e+06,3.63642e+06,525566,525850,532573,292700,309179,308556,308186,6.38709e+06,906318,6.30964e+06,6.30654e+06,6.30772e+06,1.43908e+07,948456,950934,950964,472863,7.60297e+06,1.03598e+07,1.03435e+07,2.92307e+07,7.68306e+06,7.24778e+06,7.21954e+06,3.30975e+06,3.30869e+06,1.66444e+07,1.31413e+06,6.77108e+06,7.85982e+06,7.85443e+06,3.29659e+06,3.28947e+06,3.83999e+06,1.51978e+07,1.54152e+07,5.43368e+06,2.05399e+07,2.07209e+07,2.18259e+06,1.03525e+07,1.03504e+07,816533,3.02628e+06,511383,1.84913e+07,1.64105e+06,366468,366764,4.16002e+06,3.00929e+06,1.50008e+07,4.08368e+06,1.21733e+07,3.96875e+06,136981,137931,446523,446376,446226,3.95266e+06,5.11401e+06,9.06472e+06,1.94127e+06,426242,1.0068e+07,1.01597e+07,5.38638e+06,5.40049e+06,2.0021e+06,3.70285e+06,4.32193e+06,1.87157e+06,2.79086e+06,2.79047e+06", "agent_steps": "62.6524,87.5561,62.9473,88.1132,68.6817,96.0758,12.714,37.5521,62.5213,12.6976,37.5194,37.5521,62.5213,87.4906,24.0845,12.9106,37.5521,14.9422,44.4334,98.1729,12.9106,37.5521,37.5521,12.6157,37.5521,62.5213,87.4906,43.3848,35.3567,133.038,18.6122,53.7395,12.9106,37.5521,14.3524,41.8775,22.3805,15.5976,13.3038,37.5521,62.5213,87.5561,37.5521,62.5213,40.1736,15.7286,48.8899,81.3957,15.2371,62.6524,13.1072,37.7487,13.3693,43.778,72.876,37.0278,92.6679,42.7622,12.9106,37.5521,87.5561,17.1049,19.4642,62.5213,37.5521,87.5561,38.273,115.147,37.5521,100.925,76.415,12.6157,37.5521,62.5213,73.4659,13.5004,13.271,12.5829,37.5521,62.5213,87.4906,40.4357,38.6662,43.2538,71.8275,37.5521,14.6801,37.7487,19.0054,54.657,37.5521,12.5829,37.5521,21.4794,12.5993,37.5194,16.0563,38.0109,37.7487,18.4812,87.5561,14.6473,43.3521,13.3038,37.5194,37.5521,62.5213,37.5521,62.5213,87.4906,72.6139,101.581,37.5521,37.5521,62.5213,37.5521,62.5213,80.4782,37.5521,62.5213,62.5213,87.4906,13.5332,12.9434,12.5829,37.5521,12.6484,12.6157,37.5194,37.5521,37.5521,12.5829,82.0511,114.688,14.6801,41.6809,13.3693,37.5521,62.5213,13.1072,37.7487,13.9264,16.7772,12.5829,37.5521,62.5213,47.317,12.714,37.5521,62.5213,28.0166,11.2722,49.6763,82.7064,115.606,45.6786,13.3038,38.7973,64.6185,16.5806,41.6809,16.7117,48.9554,15.2044,17.4326,12.9106,37.5521,37.5521,62.5213,53.2808,18.4156,12.714,50.9215,84.738,12.6976,37.5194,37.5521,13.3693,37.7487,21.6269,19.9229,57.4095,16.8428,13.3038,37.5521,37.5521,13.4021,12.5829,14.1558,18.0224,37.5521,62.5213,91.7504,24.2483,13.3693,17.1704,71.041,24.2811,12.5829,37.5521,12.6157,37.5521,62.5213,12.714,33.6855,14.8111,115.343,87.4906,12.714,37.5521,12.6976,37.5194,12.5993,12.714,37.5521,56.066,37.5521,62.5213", "uptime": "144.854,108.961,66.1872,92.8208,62.6626,87.6072,17.7878,52.4651,87.4107,1.92417,5.61432,26.5464,44.158,61.8454,9.43952,1.08967,3.1636,111.56,331.63,85.696,1.21616,3.44938,8.75303,22.4532,66.757,111.752,157.025,395.958,5.42649,52.0332,10.7021,142.124,1.70586,4.88058,1.53209,7.69172,5.67657,1.2888,0.968877,2.64925,4.36924,28.8366,113.782,189.607,9.45673,0.701504,7.79695,12.9709,3.86921,6.05813,1.10593,5.18235,1.58725,10.7893,17.9487,4.92703,14.9529,14.8984,1.06853,3.04198,114.085,15.9507,16.3164,22.7655,7.75802,31.5328,2.73332,154.732,8.92669,52.7499,40.7357,13.1217,38.9032,64.6945,115.6,6.48528,0.71437,36.4113,108.624,180.75,252.782,6.15657,12.952,21.3549,35.4495,71.8928,1.38128,7.86065,1.13769,3.19846,10.8322,118.73,34.2085,14.7141,7.7582,23.8881,1.31368,34.0867,36.2218,1.46549,21.7842,10.0247,29.3775,1.36535,20.8773,39.8347,66.2854,16.8562,28.1684,39.3479,47.2031,66.0196,8.19751,217.167,362.417,39.4223,65.6188,17.395,16.3119,27.0984,40.5938,56.8491,2.30924,6.3608,26.6647,79.4128,4.79547,6.1506,18.2356,3.34709,60.9883,94.2954,30.4784,42.5945,0.730029,2.01246,1.67069,83.8528,139.626,1.19187,83.196,1.97843,4.64065,23.9924,71.4822,118.728,161.872,41.1334,121.566,202.535,4.43544,12.4502,7.86318,13.1004,18.3154,3.22438,14.0529,40.9208,68.0748,35.107,5.53227,1.64096,4.75744,0.578364,2.30608,1.79835,5.20495,11.3713,18.9165,3.2367,14.0711,1.9031,6.51254,10.8173,3.87446,11.4063,9.78763,0.91649,2.50508,4.01173,1.02886,2.83539,7.73635,1.32217,3.66486,46.0184,5.15056,24.665,0.800341,11.0784,102.476,170.594,22.0477,8.1107,0.903982,4.22565,5.89723,6.17268,92.2057,275.704,28.271,84.1357,140.084,3.23733,6.65574,1.67216,59.3122,204.974,1.3075,3.74656,2.37966,6.98138,6.53893,3.56719,8.68162,30.0027,13.4913,22.4385", "epoch": "239,334,960.5,1344.5,262,366.5,97,286.5,477,387.5,1145,286.5,477,667.5,735,98.5,286.5,57,169.5,374.5,197,573,286.5,192.5,573,954,1335,165.5,1079,507.5,142,410,98.5,286.5,109.5,319.5,341.5,119,101.5,286.5,477,167,286.5,477,306.5,120,186.5,310.5,232.5,239,100,144,51,167,278,282.5,353.5,652.5,197,573,334,130.5,148.5,477,573,334,146,878.5,286.5,385,291.5,192.5,573,954,560.5,206,202.5,192,573,954,1335,617,147.5,165,274,573,56,144,72.5,208.5,286.5,192,286.5,655.5,384.5,1145,122.5,290,144,70.5,167,223.5,661.5,101.5,1145,286.5,477,573,954,1335,277,387.5,573,286.5,477,286.5,477,307,286.5,477,954,1335,206.5,197.5,192,573,96.5,385,1145,286.5,286.5,192,313,437.5,112,318,25.5,286.5,477,50,144,212.5,128,192,573,954,180.5,97,286.5,477,427.5,21.5,189.5,315.5,441,348.5,101.5,296,493,126.5,318,127.5,373.5,29,266,98.5,286.5,286.5,477,406.5,281,194,388.5,646.5,387.5,1145,286.5,25.5,72,82.5,76,219,514,101.5,286.5,573,204.5,96,54,275,286.5,477,350,185,51,262,135.5,741,96,286.5,192.5,573,954,194,514,56.5,220,667.5,194,573,387.5,1145,384.5,194,573,855.5,573,954", "env/perf": "0.978272,0.979499,0.965314,0.991051,0.960683,0.984079,0.58745,0.913452,0.971464,0.385771,0.59615,0.7509,0.946839,0.97728,0.53368,0.00935698,0.474919,0.610105,0.939082,0.979199,0.0586341,0.48421,0.604939,0.538543,0.813372,0.964013,0.997557,0.945019,0.46133,0.974616,0.511048,0.938312,0.178664,0.578214,0.249578,0.706557,0.44876,0.207187,0.00690702,0.458052,0.575556,0.956066,0.928891,0.981765,0.713998,0.00345404,0.74267,0.924974,0.43236,0.776585,0.174583,0.600691,0.241626,0.772185,0.8902,0.472221,0.933595,0.769964,0.0436197,0.503746,0.977775,0.542191,0.544792,0.836881,0.667604,0.949598,0.48354,0.994103,0.673457,0.965666,0.953881,0.481305,0.848792,0.95457,0.99279,0.460903,0.00302034,0.379154,0.928952,0.987184,0.994588,0.635543,0.757499,0.820295,0.933485,0.861453,0.237662,0.67761,0.285356,0.533712,0.611355,0.390513,0.747245,0.541053,0.447371,0.717375,0.31259,0.796128,0.839083,0.320654,0.945178,0.499051,0.838825,0.183082,0.648806,0.838085,0.95111,0.788183,0.929611,0.970895,0.955219,0.981689,0.646113,0.817274,0.948649,0.860685,0.946529,0.887023,0.748536,0.838218,0.877204,0.958292,0.421396,0.443915,0.407199,0.732486,0.224972,0.344461,0.705936,0.567785,0.726877,0.511723,0.942114,0.971563,0.0464537,0.501461,0.22982,0.750203,0.958574,0.150748,0.916259,0.387289,0.443042,0.412492,0.749923,0.937231,0.944762,0.621961,0.921811,0.977563,0.451627,0.00357152,0.833994,0.927665,0.951517,0.534607,0.505817,0.928589,0.97771,0.620322,0.680219,0.379061,0.591205,0.00304117,0.40378,0.375203,0.632792,0.736623,0.887264,0.55244,0.530686,0.00318953,0.709285,0.856546,0.436435,0.695721,0.664922,0.030412,0.478984,0.443744,0.1213,0.526095,0.481214,0.18161,0.528046,0.769495,0.446614,0.422919,0.00304253,0.523469,0.859143,0.956234,0.968199,0.538345,0.00309435,0.442272,0.682446,0.47742,0.389297,0.829506,0.493049,0.806289,0.930716,0.430515,0.477615,0.256153,0.976863,0.994363,0.118761,0.496139,0.404095,0.540599,0.452235,0.404201,0.602934,0.849698,0.724801,0.885462", "env/score": "4.78272,4.79499,4.65314,4.91051,4.60683,4.84079,0.874504,4.13452,4.71464,-1.14229,0.961497,2.509,4.46839,4.7728,0.3368,-4.90643,-0.250815,1.26681,4.39196,4.79199,-4.41366,-0.157899,1.04939,0.38543,3.13372,4.64013,4.97557,4.45018,-0.386703,4.74616,0.110476,4.38312,-3.21336,0.782145,-2.50422,2.06557,-0.512395,-2.92813,-4.93093,-0.419477,0.755557,4.56066,4.28891,4.81765,2.13998,-4.96546,2.4267,4.24974,-0.676395,2.76585,-3.25418,1.00691,-2.58374,2.72185,3.902,-0.277795,4.33594,2.69964,-4.5638,0.0374552,4.77775,0.421906,0.44792,3.36881,1.67604,4.49598,-0.164595,4.94102,1.73457,4.72917,4.53881,-0.18695,3.48792,4.5457,4.9279,-0.390972,-4.9698,-1.20846,4.28952,4.87184,4.94588,1.35543,2.57499,3.20295,4.33485,3.61454,-2.62338,1.7761,-2.14644,0.33712,1.11355,-1.09487,2.47245,0.410528,-0.526293,2.17375,-1.8741,2.96128,3.39083,-1.79346,4.45178,-0.00948574,3.38825,-3.16918,1.48806,3.38085,4.5111,2.88183,4.29611,4.70895,4.55218,4.81689,1.46113,3.17274,4.48649,3.60685,4.46529,3.87023,2.48536,3.38218,3.77204,4.58292,-0.786042,-0.560845,-0.928013,2.32486,-2.75028,-1.55539,2.05936,0.677849,2.26877,0.117234,4.42114,4.71563,-4.53546,0.0146057,-2.7018,2.50203,4.58574,-3.49252,4.16258,-1.12711,-0.569584,-0.875079,2.49923,4.37231,4.44762,1.21961,4.21811,4.77563,-0.483734,-4.96428,3.33994,4.27665,4.51517,0.34607,0.0581694,4.28589,4.7771,1.20322,1.8022,-1.20939,0.912052,-4.96959,-0.962199,-1.24797,1.32792,2.36623,3.87263,0.524403,0.306861,-4.9681,2.09285,3.56546,-0.635651,1.95721,1.64922,-4.69588,-0.21016,-0.562558,-3.787,0.260953,-0.187859,-3.1839,0.280459,2.69495,-0.533858,-0.761728,-4.96957,0.234694,3.59143,4.56234,4.68199,0.383455,-4.96906,-0.577283,1.82446,-0.225801,-1.09764,3.29506,-0.0695054,3.06289,4.30717,-0.694852,-0.223845,-2.43847,4.79709,4.94363,-3.81239,-0.0386114,-0.959052,0.40599,-0.477646,-0.957987,1.02934,3.49698,2.24801,3.85462", "env/episode_return": "4.81316,4.80605,4.69113,4.92303,4.65286,4.86067,1.92944,4.22511,4.76901,0.44295,1.02269,2.57825,4.49872,4.79016,1.01368,0.0533155,0.4187,2.01147,4.4757,4.83243,0.0998782,0.28071,1.21357,1.43014,3.33707,4.68935,4.98914,4.53917,0.558677,4.78026,1.0586,4.46959,0.205406,0.869973,0.291708,2.13154,0.415313,0.223405,0.0411668,0.435541,0.826562,4.59751,4.33752,4.84491,2.19991,0.0345404,2.53244,4.29549,0.439402,2.87973,0.181939,1.08788,0.190422,2.82957,3.96941,0.70421,4.40907,2.84236,0.088513,0.405178,4.79679,1.44737,1.26149,3.43512,1.8214,4.62216,0.365597,4.99879,1.81968,4.74724,4.6179,1.10747,3.54232,4.57727,4.98239,0.74984,0.0302034,1.09489,4.34933,4.89205,4.95254,1.49255,2.66774,3.30437,4.38322,3.68749,0.219656,1.83155,0.26793,0.486948,1.19523,0.529878,2.56992,1.18698,0.742798,2.23161,0.258264,3.02531,3.54981,0.27709,4.5538,1.15075,3.42857,0.218875,1.59532,3.45069,4.54046,2.96624,4.32005,4.71764,4.58902,4.83777,1.53389,3.22406,4.50972,3.68663,4.5119,3.92383,2.59643,3.45796,3.98967,4.80504,0.496321,0.80222,0.8926,2.49091,0.231378,0.505339,2.12743,0.851335,2.32719,0.964256,4.55644,4.75254,0.0933262,0.366847,0.17771,2.61136,4.6199,0.176952,4.25091,0.395378,0.544841,0.76604,2.61943,4.41735,4.51773,2.17596,4.37292,4.90746,0.536355,0.0334499,3.44092,4.31657,4.53456,0.516985,1.78513,4.36784,4.82586,2.08446,1.88913,0.411235,1.05951,0.0304117,0.4185,0.424063,1.39488,2.57747,3.93167,0.627344,1.39357,0.0318953,2.13467,3.59301,0.754602,2.01372,1.86537,0.0762153,0.366081,0.539651,0.127736,0.434547,0.648461,0.182569,0.649769,2.79928,0.697248,0.661192,0.0304253,0.968336,3.6976,4.61065,4.84962,1.14613,0.0309435,0.654095,1.86323,0.485351,0.682195,3.33905,1.31251,3.12768,4.32871,0.389851,0.647459,0.200481,4.82274,4.98417,0.126402,0.365157,0.336388,0.582253,0.61221,0.279048,1.13753,3.56854,2.34061,3.89139", "env/episode_length": "2120.78,2126.13,2264.93,1931.44,2303.78,2075.3,2583.91,2540.71,2186.3,2484.16,2998.45,2898.71,2410.78,2168.96,2808.28,1028.3,2995.15,2566.37,2436.56,2105.93,1445.78,3001,2982.2,2692.52,2820.9,2212.98,1661.87,2375.21,2775.63,2169.19,2726.24,2421.87,1775.33,2998.68,2240.85,2903.05,2747.78,2041.03,968.144,2988.26,2997.38,2294.67,2465.75,2080.11,2885.72,868.936,2781.44,2405.72,2673.26,2683.95,1866.92,2990.33,2137.22,2767.78,2484.19,2690.52,2510.83,2801.48,1261.74,2988.7,2165.12,2755.8,2739.83,2613.95,2830.06,2360.86,2989.89,1518.61,2946.01,2141.96,2295.6,2563.26,2765.54,2362.79,1648.21,2678.7,773.645,2041.87,2448.96,2007.36,1878.81,2928.34,2763.83,2747.65,2492.19,2746.55,2139.94,2915.71,2359.19,3000.29,2994.53,2467.75,2904.15,2768.18,2553.45,2960.42,2369.48,2865.3,2742.4,2408.25,2422.21,2634.84,2789.97,2047.9,2982.37,2761.14,2387.6,2812.58,2505.65,2236.08,2344.28,2112.12,2975.42,2819.55,2411.79,2736.33,2399.2,2542.15,2850.16,2763.61,2632.34,2179.63,2618.73,2591.13,2324.66,2948.15,1803.14,2193.8,2962.1,2966.28,2951.75,2769.71,2393.69,2180.3,1425.62,3001,2093.33,2893.77,2339.91,1696.05,2544.78,2539.76,2665.39,2445.92,2920.07,2458.95,2360.94,2619.44,2487.26,1954.5,2671.41,1026.23,2546.77,2486.58,2363.41,2978.7,2398.94,2464.67,2114.81,2637.79,2889.58,2541.03,2968.07,750.73,2618.71,2535.97,2968.51,2718.07,2600.96,3000.74,2612.04,753.329,2872.72,2713.89,2546.62,2961.69,2870.14,1327.17,2994.66,2727.26,1680.89,2994.61,2838.72,1958.54,2836.96,2913.48,2631.72,2441.51,753.736,2765.65,2746.47,2352.46,2448.49,2763.6,749.607,2734.31,2860.25,2793.7,2379.21,2817.12,2476.58,2864.81,2517,2722.56,2783.3,2108.2,2191.47,1673.91,1789.81,3000.76,2650.3,3000.81,2651.53,2650.85,2997.57,2781.05,2924.38,2696.37", "env/n": "124.863,124.021,29.3229,34.0599,114.752,127.202,54.1111,52.0947,60.4712,16.2699,10.8336,45.4526,54.9162,60.6789,12.6346,135.844,43.5526,123.558,107.696,125.642,56.3854,21.7428,43.6105,27.9237,23.3176,30.2441,39.6142,111.064,13.4033,112.938,52.6165,54.674,99.9355,43.5316,49.852,48.533,26.8438,68.5302,133.039,43.1895,43.0942,201.106,53.8211,63.1728,46.2402,147.889,69.6532,89.4194,27.6123,89,90.7778,88.8737,148.918,82.6396,78.1261,53.7004,123.8,19.5276,63.6092,21.8924,121.547,50.7383,51.3048,44.4921,21.979,170.053,90.0515,86.384,43.3368,10069,100.655,31.5105,23.8425,27.8425,81.317,26.7631,83.4861,49.9895,27.105,32.7113,34.874,20.3455,93.1735,95.3211,107.312,23.9843,151.57,86.6211,116.821,88.6812,43.3632,34.8031,44.3474,13.5567,16.3522,10.9633,66.7735,45.5389,94.5579,128.412,331.064,28.5252,23.3864,64.7056,11.1481,48.3316,55.1361,22.0315,26.0367,29.5092,112.919,124.927,21.8714,46.7737,54.6073,47.5632,55.1675,79.3252,44.9316,48.9738,25.3123,30.3018,29.2,29.4271,41.832,22.2257,106.363,21.4254,11.156,43.2947,44.0158,26.4226,108.608,117.621,106.657,45.3033,302.042,45.4789,56.4241,201.326,104.379,31.1957,56.2869,36.1706,22.5013,26.7428,112.175,50.709,53.6053,68.2304,29.1315,520.75,68.6032,116.468,97.128,43.9957,55.5573,55.2741,62.3756,58.824,44.5735,55.3525,43.9919,659.319,27.4028,52.5914,43.3263,44.3474,47.9215,45.0815,30.1851,86.6976,39.4574,48.3411,15.2074,11.2883,43.4579,417.935,175.213,99.2562,190.255,85.7931,12.1502,63.3056,43.5421,22.3911,28.4799,75.3613,329.882,27.4625,47.8474,55.9634,162.889,52.3863,342.198,29.4212,188.093,13.2169,72.7906,46.6368,34.9684,22.8845,26.1837,26.1671,26.1642,166,10019,79.0842,48.9363,21.8425,14.3138,10.9554,14.872,28.2891,21.6457,23.6088,22.1234,24.2257", "perf/rollout": "0.0376991,0.0239644,0.0083608,0.00843314,0.0225962,0.0224471,0.0141422,0.0141526,0.0141402,0.00259887,0.00260554,0.0138484,0.0138595,0.0139163,0.00279348,0.00667676,0.00628108,0.111138,0.112561,0.0293403,0.0031481,0.00308585,0.0085585,0.0137211,0.0137132,0.0161649,0.0134874,0.122076,0.00274613,0.0143635,0.0123625,0.0394004,0.00640678,0.0063218,0.00545607,0.00453909,0.0052372,0.00437271,0.00448753,0.0043309,0.00430261,0.0318219,0.0396651,0.0398175,0.0075997,0.00391733,0.00738869,0.00733132,0.00568159,0.00593159,0.00622802,0.0167422,0.0145406,0.00772936,0.00772923,0.00639424,0.00537824,0.00272407,0.00319562,0.00315375,0.0291415,0.0160099,0.0124179,0.00969529,0.00410175,0.00861001,0.00988432,0.022837,0.00839281,0.00854731,0.0100349,0.0126954,0.0126762,0.0126901,0.0187174,0.00619298,0.0022512,0.0277873,0.0278098,0.0276479,0.0276417,0.00221358,0.0159758,0.0192823,0.0193591,0.0189379,0.0172688,0.0151126,0.00838472,0.00840658,0.00904886,0.0399092,0.0135815,0.00841236,0.00618891,0.00707492,0.00660266,0.0144552,0.0203333,0.0161527,0.0165586,0.00684117,0.00671254,0.00507036,0.00717814,0.0156185,0.0156079,0.0061605,0.00617553,0.00614845,0.0213162,0.0212832,0.00566109,0.0744368,0.0728422,0.0145359,0.0145794,0.00740132,0.0101634,0.0101698,0.00727007,0.00726068,0.00564138,0.00624617,0.0261942,0.026086,0.0219373,0.00598633,0.00597866,0.00499204,0.0346433,0.0472036,0.00752026,0.00746202,0.00425485,0.00418401,0.0259632,0.0410244,0.0413492,0.0137069,0.0352965,0.00578746,0.0117383,0.0268531,0.0268131,0.0253123,0.0696192,0.0250591,0.0250709,0.0250217,0.00549222,0.0902963,0.00951163,0.00952684,0.00951766,0.0063027,0.0106849,0.0106784,0.0106981,0.0310988,0.00505284,0.00693408,0.00694348,0.010373,0.00295602,0.00852043,0.00858436,0.00519978,0.00521589,0.00442476,0.0060602,0.00523952,0.00495761,0.00496731,0.00302942,0.0030407,0.00667086,0.0191125,0.0186125,0.0168749,0.00818218,0.00805081,0.00331491,0.00402942,0.00402287,0.0125298,0.00717733,0.0444584,0.0090199,0.0166303,0.0272596,0.0269306,0.00665667,0.0111669,0.0139441,0.00423988,0.0135094,0.00482335,0.0888154,0.082258,0.0157284,0.0158034,0.0158483,0.00569092,0.00483676,0.0151639,0.0131681,0.025132,0.00523009,0.00515428,0.00274363,0.00272032,0.00727846,0.0072262,0.00493422,0.0124232,0.00506699,0.00507008", "perf/eval_gpu": "0.0247894,0.0124377,0.00502262,0.00501823,0.0111546,0.0111632,0.0072836,0.00730084,0.0073058,0.000934793,0.000923449,0.00705578,0.00701684,0.00700246,0.00116924,0.0024152,0.00239634,0.0800968,0.0791387,0.0195135,0.00115606,0.00115928,0.00288134,0.00686388,0.0068608,0.0095424,0.00685915,0.107731,0.000977126,0.00499632,0.00578558,0.0264843,0.00268963,0.00270433,0.00167822,0.00158726,0.00182538,0.00133162,0.0014755,0.00148479,0.00148702,0.0123959,0.0262781,0.0262869,0.00226335,0.00114953,0.00189294,0.00189628,0.00293544,0.00142413,0.00252023,0.00578495,0.0038556,0.0029517,0.00291151,0.0020465,0.00165574,0.00110868,0.00102723,0.00102669,0.0160023,0.00952326,0.00584814,0.00609006,0.00207959,0.00421678,0.00261776,0.014182,0.00261443,0.00404953,0.00319557,0.00577157,0.00576261,0.00576152,0.0121696,0.00288101,0.000659214,0.0198049,0.0198184,0.0198125,0.0198126,0.000790773,0.00554418,0.00799034,0.00800025,0.0120884,0.00580315,0.00452641,0.00256165,0.00256546,0.00319065,0.0333755,0.00691292,0.00511789,0.00291877,0.00388914,0.00234606,0.00796141,0.00906881,0.00503497,0.00396738,0.00345145,0.00344724,0.00132486,0.0037508,0.00898966,0.00898979,0.00328221,0.00330103,0.00329469,0.0101431,0.0100608,0.00226965,0.06131,0.0590021,0.00799025,0.00798983,0.00274326,0.00452193,0.00452385,0.00402218,0.00402045,0.00238445,0.00286968,0.0177501,0.0177448,0.00894586,0.00288605,0.00288651,0.0013373,0.0213043,0.0411299,0.00231606,0.00232568,0.00130065,0.00130066,0.0117708,0.0273257,0.0273041,0.0051371,0.0216987,0.00215759,0.00528835,0.0184102,0.0183943,0.0178243,0.0435234,0.0184438,0.018444,0.0184218,0.00193196,0.0720572,0.00262912,0.00263758,0.00263538,0.00264362,0.0050307,0.00506362,0.00505665,0.0178934,0.00146999,0.00264979,0.00264474,0.00230964,0.00107858,0.00289813,0.00287872,0.00162665,0.00162123,0.0013203,0.00274896,0.00186958,0.00187607,0.00187805,0.00140394,0.0014067,0.00227081,0.00425889,0.00424418,0.00584356,0.00277013,0.00276461,0.00166661,0.00158617,0.00158776,0.00574649,0.00390786,0.0275571,0.00182682,0.0105915,0.0137575,0.013761,0.00156872,0.00470116,0.00269128,0.00140753,0.00306725,0.00252289,0.0719964,0.0663317,0.00895925,0.00894952,0.00895086,0.00235885,0.00200226,0.00402733,0.00308718,0.0184549,0.00215225,0.0021557,0.00102076,0.00101591,0.00387503,0.00401831,0.00198872,0.00575616,0.00226425,0.00226281", "perf/eval_env": "0.0105655,0.00979413,0.00270634,0.00278062,0.0100879,0.00993657,0.0051216,0.00510596,0.00508663,0.00134499,0.00136329,0.00503729,0.00501475,0.00504304,0.00129882,0.00272912,0.00258946,0.0209104,0.0230728,0.00936068,0.00135703,0.0013032,0.00484963,0.00541869,0.005418,0.00518173,0.0051952,0.0103641,0.00128965,0.00908903,0.00532142,0.0100605,0.0026636,0.00254596,0.00324626,0.0023262,0.00276701,0.00246579,0.0024431,0.00229107,0.00225918,0.0188142,0.0105057,0.0106369,0.00495068,0.0020731,0.00484683,0.00475571,0.0014373,0.00390903,0.00185314,0.00962509,0.00946233,0.00400263,0.00404183,0.00346973,0.00322422,0.00127176,0.00171983,0.00167623,0.0106429,0.0052508,0.0053051,0.00322333,0.0016101,0.00376718,0.00640158,0.00528161,0.00495045,0.00385189,0.00612224,0.00545063,0.00544413,0.00546129,0.0052797,0.00268233,0.00125894,0.00538345,0.00539508,0.00534158,0.00533683,0.00101977,0.0096867,0.00997339,0.0100272,0.0053846,0.0100999,0.00983857,0.00488065,0.00492842,0.00505682,0.00314846,0.00541514,0.00159588,0.00255263,0.0024588,0.00329624,0.00526428,0.00993535,0.00960457,0.0118399,0.00274741,0.00264033,0.00326397,0.00269172,0.00536207,0.00535215,0.00252233,0.0025223,0.00250357,0.00987685,0.00992588,0.00246139,0.0102569,0.0109606,0.00529696,0.00533888,0.0039205,0.00496401,0.00496795,0.00261714,0.00260664,0.0026225,0.00273474,0.00585792,0.00576892,0.0101132,0.00238352,0.00237424,0.00317732,0.0104857,0.00223103,0.00402551,0.00402356,0.0024475,0.00237644,0.00854502,0.0107579,0.011093,0.00691668,0.0101348,0.00265861,0.00522587,0.00591017,0.00588976,0.00498282,0.0204775,0.00534533,0.00536737,0.00535195,0.00269141,0.0129997,0.00620526,0.00621171,0.00620604,0.00217261,0.00498453,0.0049457,0.00496997,0.0103416,0.00305586,0.00341451,0.00343773,0.00675281,0.00124358,0.00495309,0.00505313,0.00305661,0.00308279,0.00254927,0.00250026,0.00272214,0.00248075,0.00248712,0.00131075,0.00131872,0.00342949,0.013169,0.0127212,0.00970911,0.00415387,0.00410429,0.00132779,0.00175018,0.00174197,0.00532714,0.00265868,0.0117599,0.00660358,0.00290244,0.010553,0.0102423,0.00458379,0.00521973,0.010272,0.00240641,0.00938045,0.000842276,0.0117041,0.0108832,0.0053125,0.00539588,0.00544124,0.00269773,0.00187784,0.00960704,0.00925186,0.00540077,0.00232158,0.00226631,0.00126788,0.00125168,0.00267084,0.00258795,0.0025977,0.00521212,0.00245718,0.00246106", "perf/train_misc": "0.00976216,0.0074028,0.0018504,0.00185019,0.00718874,0.00718175,0.00589619,0.00589633,0.00589564,0.000264471,0.000264396,0.0025186,0.00252007,0.00252431,0.000663672,0.000406436,0.000405883,0.0277649,0.0253152,0.0126585,0.000389301,0.000389861,0.00203313,0.00292847,0.00292674,0.00293517,0.00291989,0.00961456,0.00026801,0.0209916,0.00348238,0.00378003,0.000801817,0.000800946,0.000971806,0.00269857,0.00128787,0.000979314,0.000598507,0.000597743,0.000598366,0.0266962,0.00435394,0.0043559,0.00254362,0.000308535,0.00750444,0.00750056,0.000666432,0.00433978,0.000600042,0.0017327,0.00206787,0.00868088,0.00867421,0.00146009,0.0107293,0.00229541,0.000304901,0.000304593,0.0077314,0.00338989,0.00533703,0.00292812,0.00116553,0.0165224,0.00117143,0.0033727,0.00165733,0.030987,0.0204348,0.00214638,0.00214416,0.00214774,0.00330959,0.00151155,0.000241034,0.00214338,0.00214527,0.0021462,0.00214599,0.00125109,0.00556003,0.00497527,0.00497401,0.00135755,0.000919597,0.00385766,0.0013544,0.00135414,0.00194285,0.00215751,0.00327634,0.000679575,0.000484357,0.000490072,0.000543834,0.00336296,0.0124856,0.000568742,0.0314214,0.00182359,0.0018238,0.00121571,0.000531433,0.00436802,0.00436848,0.000893034,0.000893163,0.000895973,0.00693543,0.0069351,0.000654607,0.00340255,0.00340813,0.00338766,0.00338802,0.0068694,0.00292666,0.0029334,0.00110791,0.00110755,0.000570345,0.0020026,0.00208552,0.00208499,0.00176787,0.000488197,0.000488378,0.00125195,0.00399309,0.00218737,0.0169821,0.0170001,0.000309042,0.00030882,0.00280839,0.00228631,0.00228232,0.000866815,0.009296,0.00034907,0.00173221,0.00182267,0.00182395,0.00181946,0.0134205,0.00605111,0.00606306,0.0060602,0.000534206,0.00195668,0.00550663,0.0055074,0.00551073,0.000302691,0.00681927,0.00682166,0.0068164,0.00452268,0.00142335,0.000592072,0.000591997,0.00212031,0.000787486,0.00124168,0.0012422,0.00527662,0.00527073,0.000656153,0.00213703,0.000489171,0.00128625,0.00128445,0.000565381,0.000565885,0.00269786,0.00285142,0.00285186,0.00403016,0.00066515,0.000665456,0.000740231,0.00108406,0.00108442,0.00220273,0.000844915,0.00647993,0.000981497,0.00107848,0.00872665,0.00872412,0.016515,0.00233966,0.000698018,0.00127029,0.00600475,0.000262849,0.00757829,0.00716158,0.00282802,0.00283092,0.00282815,0.0010578,0.000908154,0.00183455,0.0789849,0.00337001,0.000152901,0.000152918,0.000359304,0.000359048,0.000483173,0.00133399,0.000793416,0.00102837,0.00112673,0.00112672", "perf/train_forward": "0.556733,0.293953,0.0584703,0.0585101,0.208596,0.208636,0.162638,0.162589,0.162684,0.00186695,0.00186128,0.0757702,0.0757924,0.0758575,0.00912623,0.0034403,0.00343725,1.99384,1.81939,0.186203,0.00228297,0.00228218,0.0195615,0.0995658,0.0995241,0.101591,0.0993059,2.26005,0.00182392,0.0634123,0.0590082,0.302886,0.009541,0.0095387,0.00710917,0.0164326,0.00962723,0.00507717,0.00391667,0.00391677,0.0039168,0.113593,0.353331,0.353519,0.0204769,0.00107268,0.0265064,0.0265469,0.00996621,0.0146379,0.00347329,0.0168631,0.0133153,0.0477087,0.047722,0.00920656,0.0257362,0.017535,0.00162067,0.00161746,0.304261,0.101702,0.0914974,0.034821,0.00804725,0.068787,0.0072168,0.146267,0.0208355,0.0968417,0.108746,0.052616,0.0526151,0.0526665,0.183818,0.0234676,0.00075289,0.158987,0.159097,0.159081,0.159096,0.00618127,0.0657993,0.10433,0.104338,0.105008,0.0057814,0.0351996,0.0052106,0.00521031,0.0265758,0.575446,0.102026,0.0130611,0.0133643,0.0133665,0.00302171,0.0992746,0.217915,0.00338781,0.0818719,0.0351664,0.0351576,0.00675549,0.0112604,0.118578,0.118552,0.0220708,0.0220729,0.022121,0.141636,0.141681,0.00774259,0.690028,0.681907,0.119299,0.119296,0.041799,0.0432622,0.0432593,0.0339058,0.0339054,0.00462014,0.0234629,0.110045,0.110027,0.0253593,0.00928324,0.00927683,0.00507692,0.178745,0.44211,0.0722184,0.0723314,0.0015335,0.00153138,0.0295516,0.24911,0.249118,0.00816376,0.532685,0.00272185,0.022341,0.0958362,0.0958085,0.0956411,0.820825,0.392483,0.393325,0.393438,0.00407088,0.485998,0.0262182,0.0262167,0.0262207,0.00233212,0.119998,0.119946,0.119966,0.241061,0.0105219,0.0049526,0.00495254,0.00519169,0.00458874,0.00812103,0.00812057,0.0288108,0.028806,0.00257397,0.0413663,0.00381427,0.0102107,0.0102129,0.00618073,0.00618001,0.024378,0.0122731,0.0122709,0.0270465,0.00372804,0.0037311,0.0107763,0.00732907,0.00732503,0.0652965,0.014904,0.216972,0.00390842,0.022042,0.321358,0.321388,0.03933,0.0298275,0.00263331,0.0103437,0.0232363,0.00301811,0.920613,0.865811,0.127953,0.127938,0.127924,0.00963758,0.00681715,0.0117202,0.176788,0.27873,0.00099492,0.00099349,0.00282409,0.00282075,0.00914504,0.00984275,0.00922786,0.0213573,0.0170794,0.0170783", "perf/train": "0.566495,0.301356,0.0603207,0.0603603,0.215785,0.215818,0.168534,0.168486,0.16858,0.00213142,0.00212568,0.0782888,0.0783124,0.0783818,0.0097899,0.00384674,0.00384313,2.0216,1.8447,0.198862,0.00267227,0.00267204,0.0215946,0.102494,0.102451,0.104526,0.102226,2.26967,0.00209193,0.0844038,0.0624906,0.306666,0.0103428,0.0103396,0.00808098,0.0191312,0.0109151,0.00605648,0.00451518,0.00451451,0.00451516,0.140289,0.357685,0.357875,0.0230205,0.00138122,0.0340108,0.0340475,0.0106326,0.0189777,0.00407334,0.0185958,0.0153832,0.0563895,0.0563963,0.0106666,0.0364655,0.0198304,0.00192557,0.00192206,0.311993,0.105092,0.0968344,0.0377491,0.00921278,0.0853095,0.00838823,0.14964,0.0224928,0.127829,0.129181,0.0547624,0.0547592,0.0548143,0.187128,0.0249792,0.000993924,0.161131,0.161242,0.161227,0.161242,0.00743236,0.0713594,0.109305,0.109312,0.106365,0.006701,0.0390573,0.006565,0.00656445,0.0285186,0.577603,0.105303,0.0137407,0.0138487,0.0138566,0.00356555,0.102638,0.230401,0.00395656,0.113293,0.03699,0.0369814,0.00797121,0.0117918,0.122946,0.122921,0.0229638,0.0229661,0.0230169,0.148572,0.148616,0.0083972,0.693431,0.685315,0.122687,0.122684,0.0486684,0.0461889,0.0461927,0.0350137,0.035013,0.00519048,0.0254655,0.11213,0.112112,0.0271271,0.00977144,0.0097652,0.00632887,0.182738,0.444298,0.0892005,0.0893315,0.00184255,0.0018402,0.03236,0.251396,0.2514,0.00903057,0.541981,0.00307092,0.0240732,0.0976588,0.0976324,0.0974606,0.834246,0.398534,0.399389,0.399498,0.00460508,0.487954,0.0317249,0.0317241,0.0317315,0.00263481,0.126817,0.126768,0.126782,0.245583,0.0119452,0.00554467,0.00554454,0.007312,0.00537623,0.00936272,0.00936276,0.0340875,0.0340768,0.00323013,0.0435033,0.00430344,0.011497,0.0114974,0.00674611,0.00674589,0.0270759,0.0151245,0.0151228,0.0310767,0.00439319,0.00439656,0.0115166,0.00841313,0.00840945,0.0674993,0.0157489,0.223452,0.00488991,0.0231205,0.330084,0.330112,0.055845,0.0321672,0.00333132,0.011614,0.029241,0.00328096,0.928191,0.872973,0.130781,0.130769,0.130752,0.0106954,0.00772531,0.0135547,0.255773,0.2821,0.00114782,0.00114641,0.00318339,0.0031798,0.00962821,0.0111767,0.0100213,0.0223857,0.0182061,0.018205", "util/gpu_percent": "98.5474,98.4526,94.1016,94.6667,95.181,95.0192,98.9524,98.8947,98.7696,55.8816,63.0079,96.8263,96.712,96.8316,79.1017,80.9892,85.3158,100,100,95.8113,76.3935,88.1155,85.4842,93.9474,94.0997,94.0866,93.8688,100,67.2712,90.7847,90.6057,96.1868,83.6237,95.9263,80.949,95,74.0685,67.3349,73.85,88.7421,89.2565,89.3617,96.9579,97.445,81.6912,43.6728,91.8065,93.9194,91.5727,94.4,83.2222,64.6105,64.0722,97.5135,97.7207,84.4296,95.78,96.9977,61.8814,78.231,95.6421,93.832,93.3904,93,87.9685,97.4316,79.1443,97.576,87.0053,98,96.5345,89.4211,89.021,89.2493,96.2054,86.6534,41.3778,94.6299,94.5249,94.6562,94.8635,94.2482,87.7041,90.4679,90.3486,93.4724,37.9065,79.4421,80.2985,89.5217,89.8526,99.9108,93.9579,92.2446,81.6873,79.9397,71.2222,93.5078,97.5158,50.6544,92.0426,90.328,91.925,82.9056,78.6868,94.5474,95.6387,88.6457,87.1654,89.1417,92.6486,93.2455,83.0761,97.8053,99.4921,95.0263,94.9791,97.2439,88.6579,89.2199,92.1864,88.916,63.1525,87.2917,91.6457,92.2966,69.2368,74.9828,76.9528,80.5474,92.3947,99.9738,97.832,98,62.8856,84.7251,91.5625,95.6158,95.3874,76.4947,99.5263,58.2295,76.3267,90.9816,91.6903,92.6457,97.3667,98.5397,98.5895,97.5131,71.0806,99.025,88.4841,89.6667,85.96,92,95.5208,95.8122,95.4924,95.468,87.3602,78.9918,89.1935,67.4043,79.1356,66.7634,63.3368,95.1105,95.1204,84.1296,95.2904,55.7241,92.5853,93.6977,79.8723,80.4744,94.4632,52.2174,76.4468,74.525,72.7163,92,87.8706,81.1,96.1737,91.2073,79.8216,91.8377,30.8471,90.7678,95.0789,96.3246,94.7273,84.3699,43.7143,82.4431,83.4444,91.0068,97.9948,98.1421,94.5158,94.6457,94.706,77.6286,89.5634,63.3981,100,97.6842,49.3448,59.9816,76.2899,80.6488,73.8047,79.2812,78.9895,78.0158,86.126,86.0919", "util/gpu_mem": "6.26552,6.16782,4.72668,4.72668,4.97909,4.97909,4.93023,4.93023,4.93023,3.98576,3.98576,5.06051,5.06051,5.06051,3.96134,4.69412,4.69412,7.7148,7.7148,5.85028,4.56384,4.56384,4.46614,19.6097,19.6097,19.3938,19.6097,13.3165,4.09975,20.0576,4.25445,7.63338,4.79182,4.79182,4.88138,4.75925,3.96134,19.6505,4.57199,4.57199,4.57199,5.4269,7.63338,7.63338,4.40915,4.66155,4.84881,4.84881,4.69412,4.81625,20.0657,4.1486,4.33587,5.40247,5.40247,4.41729,4.72668,19.8459,19.4469,19.4469,5.1175,19.734,4.25445,5.81771,18.8005,5.40247,4.56384,20.6682,4.38472,4.98723,4.49871,4.31144,4.31144,4.31144,6.03754,4.16489,16.8903,6.44464,6.44464,6.44464,6.44464,4.66969,4.63712,4.47428,4.47428,6.89245,4.22188,4.48242,4.66969,4.66969,4.6127,13.0397,4.49871,4.34401,19.9273,19.6375,4.42543,4.76739,4.40915,4.46614,4.8081,4.24631,4.24631,4.43357,18.8012,4.66155,4.66155,5.10122,5.10122,5.10122,19.6342,19.6342,4.28702,26.4545,26.5211,4.90581,4.90581,5.3699,4.28702,4.28702,4.79996,4.79996,4.10789,4.09161,4.89767,4.89767,4.28702,4.35215,4.35215,4.44171,20.1987,12.3232,4.97909,4.97909,4.59641,4.59641,5.92356,10.7111,10.7111,4.68597,6.77847,4.27887,4.31958,4.89767,4.89767,4.89767,20.816,5.98869,5.98869,5.98869,4.17303,30.4147,19.7237,19.7237,19.7237,4.84067,4.38472,4.38472,4.38472,5.90727,4.50685,19.6423,19.6423,5.06865,4.47428,4.14046,4.14046,4.44986,4.44986,4.59641,4.31958,4.02647,4.90581,4.90581,16.4181,16.4181,4.43357,4.67783,4.67783,4.22188,4.88952,4.88952,4.23002,4.90581,4.90581,4.22188,18.9394,4.97909,4.44986,4.7104,4.67783,4.67783,4.70226,4.17303,4.23816,19.3655,4.85696,4.56384,25.5597,25.6092,4.94652,4.94652,4.94652,4.11603,4.35215,19.2108,4.63712,7.52753,4.27887,4.27887,4.23002,4.23002,19.1126,17.6502,4.36844,4.42543,4.49871,4.49871", "util/vram_used_gb": "1.04187,1.01843,0.672729,0.672729,0.733276,0.733276,0.721558,0.721558,0.721558,0.494995,0.494995,0.752808,0.752808,0.752808,0.489136,0.664917,0.664917,1.38953,1.38953,0.942261,0.633667,0.633667,0.610229,4.24292,4.24292,4.19112,4.24292,2.73328,0.522339,4.35034,0.559448,1.37,0.688354,0.688354,0.709839,0.680542,0.489136,4.25269,0.63562,0.63562,0.63562,0.840698,1.37,1.37,0.596558,0.657104,0.702026,0.702026,0.664917,0.694214,4.35229,0.534058,0.578979,0.834839,0.834839,0.598511,0.672729,4.29956,4.20386,4.20386,0.766479,4.27273,0.559448,0.934448,4.0488,0.834839,0.633667,4.49683,0.590698,0.735229,0.618042,0.57312,0.57312,0.57312,0.987183,0.537964,3.59058,1.08484,1.08484,1.08484,1.08484,0.659058,0.651245,0.612183,0.612183,1.19226,0.551636,0.614136,0.659058,0.659058,0.645386,2.66687,0.618042,0.580933,4.31909,4.24959,0.600464,0.682495,0.596558,0.610229,0.692261,0.557495,0.557495,0.602417,4.04896,0.657104,0.657104,0.762573,0.762573,0.762573,4.24878,4.24878,0.567261,5.88486,5.90082,0.715698,0.715698,0.827026,0.567261,0.567261,0.690308,0.690308,0.524292,0.520386,0.713745,0.713745,0.567261,0.582886,0.582886,0.60437,4.38419,2.495,0.733276,0.733276,0.641479,0.641479,0.959839,2.10828,2.10828,0.662964,1.16492,0.565308,0.575073,0.713745,0.713745,0.713745,4.53228,0.975464,0.975464,0.975464,0.539917,6.83484,4.27026,4.27026,4.27026,0.700073,0.590698,0.590698,0.590698,0.955933,0.619995,4.25073,4.25073,0.754761,0.612183,0.532104,0.532104,0.606323,0.606323,0.641479,0.575073,0.504761,0.715698,0.715698,3.47729,3.47729,0.602417,0.661011,0.661011,0.551636,0.711792,0.711792,0.553589,0.715698,0.715698,0.551636,4.08212,0.733276,0.606323,0.668823,0.661011,0.661011,0.66687,0.539917,0.555542,4.18433,0.703979,0.633667,5.67021,5.68209,0.725464,0.725464,0.725464,0.526245,0.582886,4.14722,0.651245,1.3446,0.565308,0.565308,0.553589,0.553589,4.12367,3.77287,0.586792,0.600464,0.618042,0.618042", "util/vram_total_gb": "23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272", "util/cpu_mem_gb": "1.1343,1.12803,1.09872,1.09924,1.10833,1.10855,1.1203,1.12037,1.12079,1.0864,1.08789,1.12426,1.12474,1.12573,1.08957,1.10978,1.10978,1.29629,1.29629,1.08714,1.09469,1.09557,1.09745,1.02701,1.02753,1.02798,1.02856,1.17566,1.08975,1.01536,1.09898,1.12279,1.1156,1.11575,1.09434,1.10047,1.08759,1.01705,1.10164,1.10169,1.10213,1.09585,1.1246,1.1246,1.08911,1.0983,1.10172,1.10172,1.12179,1.10575,1.04044,1.09519,1.10504,1.1062,1.1065,1.09989,1.10239,1.01643,1.00896,1.0097,1.12955,1.02519,1.09952,1.08739,1.0118,1.10239,1.10632,1.09177,1.10033,1.0986,1.09958,1.10244,1.10325,1.10413,1.11005,1.09218,1.01062,1.1388,1.13921,1.13986,1.14091,1.09557,1.09323,1.10694,1.10694,1.09868,1.09546,1.09159,1.10639,1.10651,1.09982,1.17189,1.10619,1.12331,1.01197,1.01369,1.10191,1.10526,1.10262,1.10583,1.10043,1.09323,1.09397,1.09517,1.01584,1.1012,1.10161,1.09163,1.09188,1.09259,1.02349,1.02381,1.09665,1.04161,1.04161,1.1086,1.10873,1.10995,1.09221,1.09266,1.09731,1.09816,1.08998,1.08795,1.15594,1.15649,1.10996,1.09258,1.09429,1.09193,1.04402,1.20379,1.10794,1.10806,1.09856,1.09894,1.21882,1.12324,1.12324,1.13031,1.1824,1.09449,1.09681,1.15805,1.15827,1.15912,1.10965,1.10119,1.10126,1.10168,1.09405,1.21255,1.01752,1.0176,1.01801,1.12264,1.09606,1.09606,1.09621,1.13089,1.09871,1.02354,1.02389,1.11923,1.09488,1.08945,1.08953,1.0962,1.09668,1.09573,1.10233,1.08938,1.10302,1.10361,1.0066,1.00838,1.10238,1.11885,1.11885,1.09499,1.12384,1.12384,1.08711,1.11486,1.11486,1.10297,1.01199,1.18703,1.1005,1.15914,1.12867,1.12915,1.09942,1.09686,1.09582,1.00961,1.1147,1.11537,1.07293,1.07296,1.10757,1.10826,1.10914,1.08892,1.09905,1.02554,1.10506,1.10276,1.09371,1.0946,1.08908,1.09079,1.01047,1.00884,1.08983,1.09829,1.09193,1.09282", "wandb": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "rank": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "world_size": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "gpu_id": "2,3,1,1,3,3,5,5,5,3,3,3,3,3,1,5,5,2,2,4,2,2,5,0,0,0,0,3,1,0,4,4,1,1,2,3,1,0,5,5,5,3,3,3,1,3,1,1,5,2,0,4,3,4,4,3,2,0,0,0,4,0,2,5,0,2,1,0,3,2,3,3,3,3,3,5,0,5,5,5,5,3,2,5,5,5,3,1,5,5,3,2,1,2,0,0,2,4,2,2,5,3,3,5,0,5,5,3,3,3,0,0,4,0,0,4,4,3,3,3,4,4,3,5,1,1,3,2,2,1,0,4,2,2,3,3,4,2,2,2,4,2,1,5,5,5,0,4,4,4,1,3,0,0,0,4,5,5,5,5,3,0,0,5,1,2,2,5,5,2,1,3,1,1,0,0,3,5,5,1,4,4,4,4,4,2,0,2,2,1,2,2,2,1,4,0,4,3,0,0,2,2,2,3,4,0,4,3,3,3,3,3,0,0,5,4,3,3", "profile": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "checkpoint_interval": "200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200", "eval_episodes": "10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000", "cudagraphs": "10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10", "seed": "73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73", "vec/total_agents": "1024,2048,1024,1024,2048,2048,1024,1024,1024,1024,1024,1024,1024,1024,1024,2048,2048,256,256,8192,2048,2048,2048,512,512,512,512,1024,1024,16384,1024,512,2048,2048,4096,4096,1024,4096,4096,4096,4096,16384,512,512,4096,4096,8192,8192,1024,8192,2048,2048,2048,8192,8192,2048,16384,4096,2048,2048,1024,1024,1024,8192,4096,16384,4096,512,2048,16384,8192,512,512,512,1024,1024,4096,256,256,256,256,4096,4096,2048,2048,512,2048,4096,4096,4096,2048,256,1024,256,512,512,2048,1024,2048,2048,16384,1024,1024,4096,512,1024,1024,2048,2048,2048,2048,2048,1024,512,512,1024,1024,8192,2048,2048,1024,1024,1024,1024,256,256,512,512,512,4096,512,256,8192,8192,4096,4096,2048,512,512,2048,1024,1024,1024,256,256,256,512,1024,1024,1024,1024,2048,8192,8192,8192,2048,2048,2048,2048,512,4096,2048,2048,8192,2048,2048,2048,4096,4096,4096,1024,1024,4096,4096,1024,1024,2048,4096,4096,2048,4096,4096,1024,4096,4096,512,1024,256,8192,256,512,512,16384,1024,4096,2048,8192,512,256,256,512,512,512,1024,1024,2048,16384,1024,1024,1024,1024,1024,512,1024,2048,512,2048,2048", "vec/num_buffers": "1,2.73541,1.83429,1.83429,1,1,2.23956,2.23956,2.23956,1,1,2.81925,2.81925,2.81925,1.53941,4.03888,4.03888,1,1,1.65748,4.27568,4.27568,2.14518,1,1,1,1,2.67072,2.0996,2.27825,1,1,4.15793,4.15793,3.87045,4.94197,1.30843,4.32217,4.70296,4.70296,4.70296,1.52352,1.22966,1.22966,1,5.04995,4.91385,4.91385,4.05954,5.92228,6.34086,1.37291,2.94982,5.98769,5.98769,3.49798,6.23484,4.33894,3.88453,3.88453,1,1,1,3.04434,3.07858,5.92888,3.28321,2.25178,2.42202,5.34475,3.52909,1.7992,1.7992,1.7992,1,1.33065,4.94051,1.24344,1.24344,1.24344,1.24344,5.31038,1.89457,1,1,1,1,1,4.75683,4.75683,2.71268,2.23142,1,2.70516,1,1,3.94506,1,1,2.14272,3.42111,1,1,3.21619,1,1,1,1,1,1,1,1,2.04848,1,1,1.30171,1.30171,5.5889,1,1,1,1,1,1,1,1,1,1,1,3.3623,1,3.47553,5.82015,5.82015,4.79803,4.79803,5.3548,1.06229,1.06229,3.94641,2.36047,2.13995,1,1,1,1,1,1.20129,1.20129,1.20129,2.04472,3.89558,3.78673,3.78673,3.78673,5.04903,1,1,1,1,3.95001,3.69098,3.69098,6.84389,4.67344,1.78105,1.78105,3.28523,3.28523,4.79409,2.60613,1.69973,4.38492,4.38492,1,1,3.62268,3.23084,3.23084,1.62685,5.09825,5.09825,1,6.17686,6.17686,1,1,1,3.48119,2.8122,1,1,4.25408,1.42829,2.81973,2.74546,4.52129,4.19724,1,1,1,1,1,1,3.5654,2.31043,4.9995,1.39171,2.08307,2.08307,2.74301,2.74301,1,1,1,1,1,1", "vec/num_threads": "2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2", "env/num_agents": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "env/gamma": "0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99,0.99", "policy/hidden_size": "256,256,256,256,128,128,256,256,256,64,64,128,128,128,32,64,64,256,256,512,128,128,128,128,128,128,128,1024,32,256,128,512,64,64,128,128,32,64,64,64,64,256,512,512,128,64,128,128,32,64,32,32,32,256,256,64,128,128,64,64,128,128,128,512,128,256,64,128,64,256,128,128,128,128,256,128,128,256,256,256,256,128,128,64,64,512,128,128,128,128,128,1024,64,32,256,256,128,128,128,128,128,128,128,64,64,256,256,256,256,256,128,128,64,1024,1024,128,128,128,128,128,128,128,128,128,64,64,64,128,128,128,256,1024,128,128,64,64,128,512,512,32,256,128,128,64,64,64,128,512,512,512,32,512,128,128,128,32,128,128,128,256,64,128,128,32,64,128,128,128,128,128,64,64,128,128,128,128,64,64,64,128,32,32,256,32,32,64,128,64,32,32,128,128,128,64,32,128,64,32,1024,1024,256,256,256,256,64,64,128,512,128,128,128,128,128,128,128,128,128,128", "policy/num_layers": "7.93575,6.49693,5.65608,5.65608,6.41829,6.41829,4.33358,4.33358,4.33358,1.90181,1.90181,5.58192,5.58192,5.58192,3.58449,2.01508,2.01508,8,8,4.28155,1,1,2.94332,6.0217,6.0217,6.0217,6.0217,7.37442,1,3.80873,3.23173,6.44511,3.40178,3.40178,2.25559,2.25511,1.8224,2.35944,3.42802,3.42802,3.42802,3.54412,6.10311,6.10311,3.57959,1.86817,2.66665,2.66665,3.2698,2.11905,1.04421,2.76966,1.96505,2.54901,2.54901,1.23109,3.35863,4.12506,1.57846,1.57846,6.19206,5.53246,3.96538,2.9435,3.65519,3.41426,2.99013,6.15739,3.93935,3.69619,4.87903,4.31595,4.31595,4.31595,7.29933,3.98493,1,8,8,8,8,2.90449,4.42067,5.03619,5.03619,5.09076,1,3.71487,1.23411,1.23411,3.66737,7.38294,6.43274,3.26022,3.5701,3.5701,1.97732,5.82453,4.97118,1,3.33886,4.80738,4.80738,2.14071,4.29332,4.28244,4.28244,4.82216,4.82216,4.82216,5.44466,5.44466,2.25538,6.26592,6.26592,6.87143,6.87143,4.00802,4.34431,4.34431,6.07023,6.07023,1.98572,2.87034,8,8,2.55692,3.61042,3.61042,1.69677,5.01282,6.38641,3.38099,3.38099,2.96686,2.96686,2.07811,6.79698,6.79698,2.64632,7.24027,1,2.951,8,8,8,8,6.54852,6.54852,6.54852,1,6.62046,3.5789,3.5789,3.5789,2.08036,5.81269,5.81269,5.81269,6.26844,3.31328,2.35193,2.35193,1.94654,1.15102,1,1,2.68791,2.68791,1,4.11508,1,3.28873,3.28873,2.9026,2.9026,2.42232,1.6387,1.6387,1.28683,2.78616,2.78616,2.11494,3.78814,3.78814,5.16255,3.81841,5.83536,3.60432,3.38548,6.18205,6.18205,3.90792,2.68241,1.65765,2.96035,2.03037,2.02399,5.77128,5.77128,6.27583,6.27583,6.27583,1.84561,1.93941,1.98258,3.29715,6.80367,1,1,1.91795,1.91795,3.62877,1.46599,3.32271,3.31436,4.11189,4.11189", "policy/expansion_factor": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "legacy/torch_deterministic": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "legacy/cpu_offload": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "legacy/compile": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "legacy/compile_fullgraph": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "train/gpus": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "train/seed": "42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42", "train/total_timesteps": "100,100,100.699,100.699,109.74,109.74,100,100,100,100,100,100,100,100,190.905,100,100,118.137,118.137,112.164,100,100,100,100,100,100,100,115.439,281.216,151.803,146.966,143.197,100,100,108.334,111.492,177.427,118.11,100,100,100,100,100,100,106.897,119.269,129.887,129.887,120.368,100,101.567,100,104.048,116.609,116.609,292.898,105.817,113.958,100,100,100,134.909,154.138,100,100,100,101.862,131.541,100,100.936,121.98,100,100,100,117.312,106.394,100,100,100,100,100,107.747,102.64,114.577,114.577,100,114.358,100,145.039,145.039,100,100,100,171.327,100,100,125.167,101.162,100,144.414,100,115.412,115.412,100.025,100,100,100,100,100,100,116.061,116.061,100,100,100,100,100,128.493,100,100,100,100,106.418,101.835,100,100,100,100,100,100,100,100,130.899,130.899,110.785,110.785,102.797,100,100,101.683,100,109.649,132.579,100,100,100,125.727,100,100,100,222.419,141.356,132.081,132.081,132.081,121.753,103.41,103.41,103.41,131.499,110.892,130.334,130.334,109.44,136.227,100,100,100,100,141.839,145.609,100,135.451,135.451,100,100,100,100,100,169.21,152.386,152.386,133.164,100,100,100,105.65,100,100,143.61,100,100,104.6,192.024,100,134.117,113.417,193.384,100,100,100,100,100,100,267.744,114.609,115.684,100,100,100,100,100,100,100,100,149.471,100,100", "train/learning_rate": "0.000822523,0.000587858,0.000900688,0.000900688,0.0013149,0.0013149,0.00146101,0.00146101,0.00146101,0.00287586,0.00287586,0.00113729,0.00113729,0.00113729,0.00136082,0.00147629,0.00147629,0.00113774,0.00113774,0.00216105,0.000821309,0.000821309,0.0022272,0.000883245,0.000883245,0.000883245,0.000883245,0.00090844,0.00661575,0.00216739,0.00144807,0.000918733,0.00214939,0.00214939,0.00245922,0.00167443,0.00302771,0.00322597,0.00250035,0.00250035,0.00250035,0.00157966,0.000732823,0.000732823,0.00131328,0.00320727,0.00319762,0.00319762,0.0025515,0.00449873,0.00237629,0.00378174,0.00183926,0.0026454,0.0026454,0.00302669,0.00117464,0.00183967,0.00217451,0.00217451,0.000759215,0.00257383,0.00109196,0.00205723,0.00184803,0.00219497,0.00216839,0.00125183,0.00205241,0.00202621,0.00148145,0.00108739,0.00108739,0.00108739,0.00102436,0.00149861,0.00274039,0.00094398,0.00094398,0.00094398,0.00094398,0.00200997,0.00270531,0.00233514,0.00233514,0.00159351,0.00210885,0.00132471,0.00355977,0.00355977,0.00138398,0.00109489,0.00117033,0.0017568,0.00141009,0.00141009,0.00289385,0.000932473,0.00106577,0.00577045,0.00216239,0.000927879,0.000927879,0.00297705,0.00108883,0.00111026,0.00111026,0.00216343,0.00216343,0.00216343,0.00147818,0.00147818,0.00219745,0.00107022,0.00107022,0.000729906,0.000729906,0.0020087,0.00215741,0.00215741,0.00127054,0.00127054,0.00251067,0.00156934,0.00183114,0.00183114,0.00114006,0.00104367,0.00104367,0.00295811,0.000739844,0.00166701,0.00232103,0.00232103,0.00301312,0.00301312,0.00238988,0.000661348,0.000661348,0.00341146,0.00101581,0.00190559,0.00111801,0.000824336,0.000824336,0.000824336,0.000850526,0.00141665,0.00141665,0.00141665,0.00315467,0.01168,0.00216547,0.00216547,0.00216547,0.00494207,0.000884894,0.000884894,0.000884894,0.000968114,0.0027853,0.00346342,0.00346342,0.00195756,0.00311153,0.0031551,0.0031551,0.00153883,0.00153883,0.00213275,0.000893237,0.00210133,0.00182321,0.00182321,0.00199652,0.00199652,0.00205388,0.00369068,0.00369068,0.00340358,0.00352085,0.00352085,0.00207074,0.00302582,0.00302582,0.00132859,0.00177141,0.00072064,0.00180731,0.00203362,0.000739756,0.000739756,0.00296777,0.00173638,0.00208767,0.00249243,0.00225465,0.00215793,0.000646799,0.000646799,0.000537524,0.000537524,0.000537524,0.00150401,0.00331062,0.00247837,0.00207143,0.00117736,0.00202136,0.00202136,0.00196138,0.00196138,0.00203805,0.00149604,0.00173395,0.000946053,0.00146569,0.00146569", "train/anneal_lr": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "train/min_lr_ratio": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "train/gamma": "0.99504,0.990585,0.992424,0.992424,0.995153,0.995153,0.991431,0.991431,0.991431,0.987818,0.987818,0.992736,0.992736,0.992736,0.993085,0.982731,0.982731,0.991014,0.991014,0.995837,0.986442,0.986442,0.996064,0.993924,0.993924,0.993924,0.993924,0.994463,0.995277,0.996056,0.98861,0.992472,0.995704,0.995704,0.976174,0.992128,0.983666,0.990502,0.990385,0.990385,0.990385,0.986638,0.991303,0.991303,0.992325,0.973828,0.995648,0.995648,0.990823,0.994124,0.98393,0.992452,0.965876,0.989934,0.989934,0.991799,0.985293,0.982204,0.99266,0.99266,0.99392,0.992115,0.982313,0.99422,0.992719,0.982449,0.984254,0.995355,0.989813,0.993646,0.993031,0.992291,0.992291,0.992291,0.992152,0.98338,0.992036,0.996043,0.996043,0.996043,0.996043,0.994532,0.984702,0.994774,0.994774,0.987651,0.973065,0.9906,0.97958,0.97958,0.993494,0.994341,0.99521,0.99135,0.995821,0.995821,0.978202,0.992858,0.992356,0.973168,0.991576,0.988854,0.988854,0.990465,0.992316,0.990869,0.990869,0.992942,0.992942,0.992942,0.996028,0.996028,0.988609,0.993315,0.993315,0.994534,0.994534,0.996523,0.99476,0.99476,0.998092,0.998092,0.989956,0.993272,0.994639,0.994639,0.995875,0.992499,0.992499,0.990856,0.996047,0.990588,0.992265,0.992265,0.963901,0.963901,0.978806,0.995401,0.995401,0.987223,0.994176,0.987278,0.986342,0.994211,0.994211,0.994211,0.995827,0.992072,0.992072,0.992072,0.992809,0.903541,0.993748,0.993748,0.993748,0.988529,0.997185,0.997185,0.997185,0.994998,0.993845,0.988032,0.988032,0.985404,0.986857,0.988344,0.988344,0.992652,0.992652,0.991919,0.987413,0.99474,0.99276,0.99276,0.991219,0.991219,0.991917,0.97925,0.97925,0.979871,0.988088,0.988088,0.991342,0.980467,0.980467,0.990562,0.991278,0.981597,0.978177,0.98576,0.995966,0.995966,0.987692,0.993588,0.991554,0.985418,0.988932,0.986922,0.992539,0.992539,0.99419,0.99419,0.99419,0.980667,0.996747,0.989366,0.993389,0.995673,0.976442,0.976442,0.987703,0.987703,0.993946,0.991576,0.982975,0.995418,0.99638,0.99638", "train/gae_lambda": "0.79844,0.968795,0.945777,0.945777,0.975905,0.975905,0.817108,0.817108,0.817108,0.984894,0.984894,0.979411,0.979411,0.979411,0.956781,0.991473,0.991473,0.920061,0.920061,0.980788,0.995,0.995,0.965355,0.88248,0.88248,0.88248,0.88248,0.910288,0.987621,0.98397,0.959465,0.967032,0.989619,0.989619,0.995,0.986597,0.983242,0.991494,0.995,0.995,0.995,0.957455,0.944767,0.944767,0.978587,0.991618,0.995,0.995,0.993523,0.99131,0.981427,0.971584,0.989217,0.992522,0.992522,0.99488,0.995,0.990844,0.984305,0.984305,0.886901,0.894015,0.899525,0.976708,0.995,0.992571,0.995,0.588566,0.897526,0.98617,0.955795,0.888798,0.888798,0.888798,0.757724,0.943407,0.990827,0.922012,0.922012,0.922012,0.922012,0.987893,0.956347,0.925187,0.925187,0.962524,0.98669,0.952019,0.93885,0.93885,0.987061,0.983905,0.960029,0.98464,0.982637,0.982637,0.994139,0.852709,0.949364,0.995,0.99484,0.97999,0.97999,0.977793,0.979723,0.957147,0.957147,0.928811,0.928811,0.928811,0.971983,0.971983,0.951563,0.851662,0.851662,0.856064,0.856064,0.995,0.879517,0.879517,0.704651,0.704651,0.986441,0.877455,0.901124,0.901124,0.974606,0.928602,0.928602,0.987234,0.920988,0.957567,0.987989,0.987989,0.99214,0.99214,0.965997,0.956569,0.956569,0.995,0.751209,0.983051,0.992958,0.916556,0.916556,0.916556,0.898644,0.831,0.831,0.831,0.990098,0.977615,0.993808,0.993808,0.993808,0.9874,0.833674,0.833674,0.833674,0.753625,0.947045,0.995,0.995,0.993431,0.981206,0.962978,0.962978,0.99317,0.99317,0.993578,0.929151,0.986865,0.993956,0.993956,0.879425,0.879425,0.940807,0.969179,0.969179,0.984348,0.982615,0.982615,0.970024,0.965809,0.965809,0.959396,0.962573,0.951276,0.995,0.96572,0.857517,0.857517,0.979432,0.96177,0.951838,0.995,0.991587,0.994626,0.963337,0.963337,0.868663,0.868663,0.868663,0.980063,0.995,0.991592,0.984654,0.8938,0.995,0.995,0.995,0.995,0.983727,0.989,0.962297,0.926173,0.960778,0.960778", "train/replay_ratio": "4,3.67583,2.81921,2.81921,3.57989,3.57989,3.47414,3.47414,3.47414,1.84505,1.84505,3.08072,3.08072,3.08072,2.60332,0.492761,0.492761,3.90758,3.90758,1.65735,1.09787,1.09787,2.4011,4,4,4,4,4,1.80842,1.5412,2.20981,3.3967,0.971653,0.971653,1.66364,2.55967,2.12068,0.44396,0.25,0.25,0.25,1.96782,4,4,2.27446,0.25,2.02359,2.02359,2.06027,1.17448,0.740626,0.860229,1.07068,2.25315,2.25315,1.84962,1.58922,2.14375,0.85743,0.85743,3.20974,4,3.37678,1.51679,2.01873,2.45891,0.495806,3.09157,2.12355,2.32117,2.87719,3.16225,3.16225,3.16225,4,2.43505,0.483936,4,4,4,4,1.20143,2.25368,2.39614,2.39614,3.57211,0.45866,1.57985,0.278578,0.278578,2.41723,4,4,2.08983,3.27142,3.27142,0.328171,3.97348,3.15822,0.25,2.21225,2.99523,2.99523,1.10297,1.96102,2.5673,2.5673,2.40992,2.40992,2.40992,1.71374,1.71374,2.09049,3.09108,3.09108,4,4,1.85818,1.82389,1.82389,3.36114,3.36114,1.76162,3.24774,4,4,1.70839,3.29937,3.29937,1.17069,3.60222,4,2.31499,2.31499,0.25,0.25,0.25,4,4,0.420693,3.84355,1.11754,2.13905,3.46068,3.46068,3.46068,3.69669,3.6254,3.6254,3.6254,1.71857,2.56268,1.43867,1.43867,1.43867,0.318115,4,4,4,4,1.34282,0.35188,0.35188,0.25,2.13717,1.50419,1.50419,2.43077,2.43077,0.569321,3.49159,1.53764,1.17914,1.17914,2.20876,2.20876,1.74591,0.25,0.25,2.03409,0.25,0.25,2.79696,0.992027,0.992027,3.15105,2.5827,3.52253,0.25,2.22387,4,4,2.4235,2.97826,0.25,1.78984,0.756312,0.944672,4,4,3.79286,3.79286,3.79286,1.6907,1.44124,0.917289,2.85524,4,0.449703,0.449703,2.73283,2.73283,3.3978,2.08222,2.08772,2.8173,3.06043,3.06043", "train/clip_coef": "0.115955,0.113036,0.0659551,0.0659551,0.110156,0.110156,0.110342,0.110342,0.110342,0.0913582,0.0913582,0.0807597,0.0807597,0.0807597,0.100997,0.155533,0.155533,0.182219,0.182219,0.0738076,0.104969,0.104969,0.151623,0.151816,0.151816,0.151816,0.151816,0.0495946,0.108741,0.0743633,0.107654,0.170607,0.139071,0.139071,0.10802,0.0752567,0.142562,0.229226,0.130186,0.130186,0.130186,0.128235,0.102556,0.102556,0.186034,0.190827,0.141851,0.141851,0.164799,0.135718,0.193316,0.203928,0.208836,0.128482,0.128482,0.204604,0.0973439,0.0827458,0.13573,0.13573,0.175972,0.116441,0.0702661,0.098278,0.145183,0.0804577,0.0903368,0.150202,0.160732,0.0947723,0.0878069,0.0655905,0.0655905,0.0655905,0.122177,0.0609057,0.228969,0.0685316,0.0685316,0.0685316,0.0685316,0.122381,0.118856,0.115126,0.115126,0.0961186,0.167513,0.138403,0.302024,0.302024,0.15428,0.101102,0.0976397,0.029472,0.0719925,0.0719925,0.20199,0.148646,0.146845,0.234647,0.141859,0.0706651,0.0706651,0.100528,0.145239,0.0867969,0.0867969,0.0272664,0.0272664,0.0272664,0.123469,0.123469,0.147277,0.154952,0.154952,0.165275,0.165275,0.0529553,0.187786,0.187786,0.0972056,0.0972056,0.0724892,0.0472011,0.12857,0.12857,0.150267,0.143392,0.143392,0.215942,0.0566064,0.166421,0.108907,0.108907,0.245885,0.245885,0.200757,0.0856184,0.0856184,0.190855,0.160409,0.0657429,0.127863,0.0860369,0.0860369,0.0860369,0.103853,0.0868233,0.0868233,0.0868233,0.118003,0.706956,0.118378,0.118378,0.118378,0.194958,0.106459,0.106459,0.106459,0.113451,0.126632,0.149358,0.149358,0.155342,0.263137,0.131369,0.131369,0.158708,0.158708,0.131906,0.101514,0.105993,0.0703775,0.0703775,0.0890456,0.0890456,0.124814,0.236374,0.236374,0.250714,0.107174,0.107174,0.10665,0.121045,0.121045,0.0863014,0.107625,0.15809,0.129929,0.198847,0.102782,0.102782,0.112093,0.16255,0.1832,0.135608,0.146202,0.0745222,0.0569664,0.0569664,0.145659,0.145659,0.145659,0.145033,0.216634,0.232591,0.142887,0.0638507,0.21683,0.21683,0.0835696,0.0835696,0.0890787,0.151339,0.0524695,0.070615,0.01,0.01", "train/vf_coef": "5,2.99827,4.79853,4.79853,2.95319,2.95319,5,5,5,4.65044,4.65044,3.96556,3.96556,3.96556,2.99664,3.73468,3.73468,3.26347,3.26347,4.31704,3.01963,3.01963,4.58766,4.49412,4.49412,4.49412,4.49412,3.68136,1.94315,3.89077,2.88571,3.65303,2.68727,2.68727,4.99015,4.6962,3.71232,3.52006,3.09324,3.09324,3.09324,4.48339,2.79509,2.79509,5,4.30377,4.86033,4.86033,1.16105,5,2.91479,2.39204,1.9461,5,5,1.72044,5,4.36382,3.70742,3.70742,4.12124,4.22986,2.7628,5,5,5,5,4.99248,3.37843,5,5,3.37964,3.37964,3.37964,5,1.83383,3.40044,4.43966,4.43966,4.43966,4.43966,4.98635,3.70178,3.8099,3.8099,4.28959,2.87703,4.67951,3.21444,3.21444,2.69866,4.13879,3.4638,0.931774,4.24067,4.24067,0.771108,5,3.81278,2.5512,5,2.02521,2.02521,3.27614,2.45502,3.1797,3.1797,2.84214,2.84214,2.84214,2.98507,2.98507,1.79071,2.5991,2.5991,4.54177,4.54177,5,3.19361,3.19361,4.83481,4.83481,3.63448,4.16277,2.27698,2.27698,2.39144,4.19717,4.19717,1.01757,3.24161,4.11847,4.82251,4.82251,4.67533,4.67533,1.24584,4.28118,4.28118,2.13387,4.03221,0.736337,2.42296,2.97026,2.97026,2.97026,3.29981,4.0104,4.0104,4.0104,2.70197,3.5958,5,5,5,2.22062,5,5,5,4.72482,3.00691,0.873568,0.873568,4.13117,4.78825,3.50718,3.50718,4.19333,4.19333,3.69843,3.17947,4.37527,5,5,3.34033,3.34033,3.84848,3.48005,3.48005,2.88013,3.34139,3.34139,2.81338,3.41667,3.41667,4.98841,2.6765,3.93291,3.40284,2.90761,4.62799,4.62799,4.99645,1.97553,2.59934,4.05945,5,0.875706,3.75298,3.75298,5,5,5,3.3977,1.98596,1.97553,5,4.66469,1.19153,1.19153,4.73873,4.73873,4.40995,3.82342,3.55868,3.12366,4.3177,4.3177", "train/vf_clip_coef": "2.19279,1.07711,0.01,0.01,1.20727,1.20727,0.511153,0.511153,0.511153,0.742136,0.742136,0.791903,0.791903,0.791903,2.35359,0.264834,0.264834,3.65205,3.65205,0.853018,0.01,0.01,1.32996,1.73714,1.73714,1.73714,1.73714,0.484618,2.15457,0.656606,0.966206,1.64746,0.01,0.01,1.14012,1.54269,1.40989,1.22714,0.993145,0.993145,0.993145,0.01,0.17065,0.17065,1.88103,0.747608,0.308656,0.308656,0.01,0.108334,1.84169,2.07549,1.81479,1.09012,1.09012,1.09944,0.01,0.01,0.0585864,0.0585864,0.584784,0.758875,2.54779,0.129947,0.01,1.2113,0.01,2.14592,0.780535,1.039,0.01,0.199907,0.199907,0.199907,1.72471,1.42983,0.01,3.16507,3.16507,3.16507,3.16507,1.5521,1.92643,1.2273,1.2273,1.85192,1.46413,0.599319,1.7964,1.7964,2.07286,0.279691,1.35219,1.04431,0.681363,0.681363,2.70188,2.7792,2.23607,2.44402,2.38031,1.72151,1.72151,0.501529,2.24444,1.92075,1.92075,0.489915,0.489915,0.489915,1.31739,1.31739,1.93086,1.2019,1.2019,1.54763,1.54763,0.01,1.17321,1.17321,0.01,0.01,2.14132,0.832811,3.98213,3.98213,3.40116,0.01,0.01,0.01,0.01,1.77028,0.759973,0.759973,0.01,0.01,0.631472,1.35511,1.35511,2.32684,2.93381,0.764203,1.28329,2.23429,2.23429,2.23429,3.19261,2.52655,2.52655,2.52655,1.21504,3.522,0.01,0.01,0.01,1.23527,2.08519,2.08519,2.08519,1.81713,0.448837,3.19366,3.19366,1.50498,0.226165,0.522257,0.522257,0.01,0.01,0.01,1.84044,1.93882,0.624533,0.624533,1.55416,1.55416,0.121053,1.10067,1.10067,1.76398,0.71881,0.71881,1.08243,2.67031,2.67031,3.10504,0.901007,2.58358,0.533981,1.64458,0.617214,0.617214,1.77049,1.74079,1.35201,0.01,0.746731,1.31434,0.490934,0.490934,2.78729,2.78729,2.78729,2.12554,0.932159,3.083,0.0465092,1.07302,0.973396,0.973396,0.876263,0.876263,1.47614,0.780629,2.52103,0.606735,0.704369,0.704369", "train/max_grad_norm": "1.74373,2.01841,0.86923,0.86923,0.116631,0.116631,0.479972,0.479972,0.479972,0.1,0.1,0.207446,0.207446,0.207446,1.18844,1.41866,1.41866,0.1,0.1,2.08383,1.78071,1.78071,0.1,0.159575,0.159575,0.159575,0.159575,2.15389,1.10329,1.13754,1.39487,1.86873,0.1,0.1,0.996554,0.1,1.29442,0.458801,0.1,0.1,0.1,1.21964,1.14233,1.14233,0.1,0.1,0.1,0.1,0.803563,0.503879,1.80795,1.20731,0.788798,0.142805,0.142805,0.159564,0.503872,0.562951,0.1,0.1,1.01823,0.137427,0.957962,1.4224,0.1,1.17309,0.94223,0.1,0.870109,0.1,0.1,0.1,0.1,0.1,0.619132,1.98794,0.132062,0.812483,0.812483,0.812483,0.812483,0.845281,1.01102,0.322939,0.322939,0.285225,0.368529,0.145529,0.1,0.1,1.54322,3.36472,1.17759,0.356053,0.785458,0.785458,0.1,1.4909,0.22983,0.1,0.945554,0.1,0.1,0.953199,0.1,0.277641,0.277641,0.1,0.1,0.1,0.595946,0.595946,0.829011,1.33097,1.33097,1.49991,1.49991,0.895075,1.05609,1.05609,0.539847,0.539847,0.850922,0.1,0.372191,0.372191,0.1,0.1,0.1,0.1,0.1,2.33,0.545363,0.545363,0.921544,0.921544,0.1,2.94011,2.94011,0.115409,0.378353,0.708294,1.19299,0.273938,0.273938,0.273938,0.197899,0.216321,0.216321,0.216321,0.1,3.68671,0.573784,0.573784,0.573784,0.677707,0.1,0.1,0.1,1.84242,0.1,0.1,0.1,0.252669,0.252144,0.1,0.1,0.1,0.1,0.746724,0.1,1.17398,0.1,0.1,0.514049,0.514049,1.2623,0.740106,0.740106,1.46728,0.312682,0.312682,1.73012,1.19099,1.19099,0.1,1.46686,0.869704,0.248758,1.06213,0.1,0.1,0.1,0.776609,0.1,0.1,0.188408,1.45172,2.85973,2.85973,0.105946,0.105946,0.105946,0.1,0.1,0.1,0.1,0.493968,0.63753,0.63753,0.1,0.1,0.20902,1.95379,0.1,0.1,0.1,0.1", "train/ent_coef": "0.0141832,0.00303018,0.0331497,0.0331497,0.00740963,0.00740963,0.00101249,0.00101249,0.00101249,0.00326911,0.00326911,0.00484717,0.00484717,0.00484717,0.00168527,0.00153944,0.00153944,0.00381859,0.00381859,0.00117095,0.00912803,0.00912803,0.00047289,0.0288001,0.0288001,0.0288001,0.0288001,0.00494195,0.0243511,0.00156944,0.00150271,0.0224614,0.00738602,0.00738602,0.0110869,0.000616757,0.000177207,0.00885732,0.000773695,0.000773695,0.000773695,0.00616347,0.00715138,0.00715138,0.00263139,0.000550145,0.00250157,0.00250157,0.00439016,0.00076902,0.00202531,0.00224486,0.00246537,0.00346754,0.00346754,0.00531955,0.000360065,0.000700822,0.00731185,0.00731185,0.0269019,0.00811083,0.00132222,0.0010314,0.000208282,0.00344242,0.00207505,0.0338361,0.000927463,0.00213817,0.000458863,0.00112086,0.00112086,0.00112086,0.0236265,0.00356034,0.0929583,0.0113892,0.0113892,0.0113892,0.0113892,0.00458385,0.000655383,0.00755066,0.00755066,0.00290018,0.00577378,0.00475142,0.0112542,0.0112542,0.00273301,0.00277239,0.00418548,0.00142966,0.00125879,0.00125879,0.00232539,0.00502126,0.0136088,0.00568106,0.000810229,0.00332631,0.00332631,0.0562686,0.00978421,0.00228313,0.00228313,0.0117725,0.0117725,0.0117725,0.00167685,0.00167685,0.000252125,0.00452825,0.00452825,0.0327102,0.0327102,0.00321512,0.0251214,0.0251214,0.0764511,0.0764511,0.000239234,0.00565858,0.00359289,0.00359289,0.00486723,0.00662174,0.00662174,0.00152878,0.00556073,0.00205138,0.00367083,0.00367083,0.0102028,0.0102028,0.00159642,0.0264299,0.0264299,0.00560098,0.00456178,0.00141449,0.00156062,0.0285833,0.0285833,0.0285833,0.028686,0.00546849,0.00546849,0.00546849,0.0084506,2.14445e-05,0.00471917,0.00471917,0.00471917,0.00726336,0.0115262,0.0115262,0.0115262,0.00248634,0.000525476,0.00300853,0.00300853,0.020144,0.00194076,0.00182086,0.00182086,0.00160017,0.00160017,0.0118679,0.000415676,0.000667553,0.00118767,0.00118767,0.00106388,0.00106388,0.000831334,0.0022028,0.0022028,0.000640068,0.00408768,0.00408768,0.0132328,0.00220686,0.00220686,0.0103508,0.0182899,0.00207623,0.000976569,0.00112426,0.00204938,0.00204938,0.00194179,0.00240586,0.00690376,0.0111599,0.000581902,0.00119245,0.00168942,0.00168942,0.00402245,0.00402245,0.00402245,0.000236851,0.00744953,0.00065897,0.00113432,0.0880986,0.00121756,0.00121756,0.0217203,0.0217203,0.00154046,0.000546579,0.00709463,0.0229169,0.00657669,0.00657669", "train/beta1": "0.987569,0.98967,0.988793,0.988793,0.994075,0.994075,0.982416,0.982416,0.982416,0.969789,0.969789,0.991969,0.991969,0.991969,0.984139,0.967588,0.967588,0.979337,0.979337,0.985398,0.95113,0.95113,0.947848,0.987948,0.987948,0.987948,0.987948,0.992208,0.95405,0.986167,0.988539,0.986062,0.981208,0.981208,0.972903,0.984384,0.932991,0.962293,0.962288,0.962288,0.962288,0.981137,0.972914,0.972914,0.977255,0.969052,0.987699,0.987699,0.986764,0.978648,0.956987,0.957302,0.947211,0.956655,0.956655,0.984149,0.984932,0.979561,0.959008,0.959008,0.987991,0.951426,0.949138,0.97117,0.955287,0.977731,0.952755,0.985809,0.963464,0.988497,0.984765,0.986389,0.986389,0.986389,0.988943,0.993012,0.952145,0.984488,0.984488,0.984488,0.984488,0.981428,0.966081,0.987195,0.987195,0.986413,0.976923,0.987817,0.939935,0.939935,0.972801,0.9357,0.976432,0.982996,0.979202,0.979202,0.941513,0.991499,0.986721,0.929267,0.984899,0.987514,0.987514,0.980911,0.969562,0.967725,0.967725,0.979451,0.979451,0.979451,0.973038,0.973038,0.979535,0.99181,0.99181,0.983001,0.983001,0.967376,0.957331,0.957331,0.989154,0.989154,0.980693,0.987795,0.983865,0.983865,0.994506,0.988343,0.988343,0.969406,0.99696,0.984644,0.971087,0.971087,0.956059,0.956059,0.96021,0.98502,0.98502,0.964304,0.977509,0.984448,0.974082,0.985866,0.985866,0.985866,0.99354,0.976473,0.976473,0.976473,0.963805,0.980717,0.986255,0.986255,0.986255,0.939135,0.985129,0.985129,0.985129,0.977983,0.96914,0.929978,0.929978,0.984173,0.967587,0.985986,0.985986,0.98971,0.98971,0.987515,0.975297,0.991286,0.982252,0.982252,0.963443,0.963443,0.972891,0.862557,0.862557,0.952805,0.933764,0.933764,0.983899,0.991069,0.991069,0.991318,0.981309,0.986587,0.963373,0.960356,0.984308,0.984308,0.964621,0.983771,0.964916,0.956647,0.98601,0.993884,0.96876,0.96876,0.98801,0.98801,0.98801,0.966898,0.957453,0.97333,0.981078,0.990132,0.955031,0.955031,0.972988,0.972988,0.986672,0.977773,0.995347,0.989698,0.968616,0.968616", "train/beta2": "0.997223,0.999833,0.999902,0.999902,0.99999,0.99999,0.999978,0.999978,0.999978,0.99999,0.99999,0.999977,0.999977,0.999977,0.99999,0.99999,0.99999,0.999987,0.999987,0.999702,0.999986,0.999986,0.99999,0.999112,0.999112,0.999112,0.999112,0.999312,0.996779,0.999882,0.999961,0.996039,0.999978,0.999978,0.999914,0.99562,0.999924,0.99999,0.999829,0.999829,0.999829,0.99999,0.99904,0.99904,0.99999,0.999969,0.998925,0.998925,0.998716,0.998849,0.999765,0.999955,0.99999,0.999732,0.999732,0.999309,0.998114,0.99944,0.999752,0.999752,0.999331,0.999973,0.99999,0.999973,0.999481,0.99346,0.996811,0.999746,0.999951,0.997551,0.994993,0.999987,0.999987,0.999987,0.999582,0.999985,0.99999,0.999987,0.999987,0.999987,0.999987,0.999845,0.999984,0.99999,0.99999,0.99986,0.999986,0.999976,0.99999,0.99999,0.99999,0.995873,0.999979,0.999962,0.999628,0.999628,0.99993,0.999951,0.999942,0.999967,0.997488,0.999965,0.999965,0.999902,0.999981,0.999944,0.999944,0.999915,0.999915,0.999915,0.99999,0.99999,0.999967,0.995474,0.995474,0.999955,0.999955,0.996687,0.99999,0.99999,0.99999,0.99999,0.999956,0.999961,0.998999,0.998999,0.999922,0.999913,0.999913,0.999978,0.999784,0.982793,0.997996,0.997996,0.999988,0.999988,0.99999,0.959885,0.959885,0.999818,0.998736,0.999987,0.999976,0.999847,0.999847,0.999847,0.9999,0.999292,0.999292,0.999292,0.999857,0.972275,0.999897,0.999897,0.999897,0.999971,0.998804,0.998804,0.998804,0.999339,0.999988,0.999988,0.999988,0.999687,0.999557,0.999954,0.999954,0.999652,0.999652,0.99999,0.999958,0.999979,0.999264,0.999264,0.99999,0.99999,0.999836,0.99999,0.99999,0.999944,0.999962,0.999962,0.99999,0.999756,0.999756,0.999978,0.99999,0.99999,0.999983,0.999959,0.999971,0.999971,0.997724,0.99999,0.99999,0.99934,0.999505,0.999881,0.953696,0.953696,0.999941,0.999941,0.999941,0.99999,0.999837,0.99999,0.997104,0.999924,0.99999,0.99999,0.99999,0.99999,0.99999,0.99999,0.99999,0.999977,0.999932,0.999932", "train/eps": "4.11682e-14,2.0538e-08,2.237e-09,2.237e-09,4.56896e-10,4.56896e-10,1.39508e-10,1.39508e-10,1.39508e-10,1e-14,1e-14,2.32479e-09,2.32479e-09,2.32479e-09,1.05353e-11,2.75999e-13,2.75999e-13,2.51423e-14,2.51423e-14,5.02163e-10,6.4577e-14,6.4577e-14,1.06911e-13,1.71616e-11,1.71616e-11,1.71616e-11,1.71616e-11,1.34326e-10,1e-14,1.29847e-12,3.20924e-13,4.24243e-08,7.54818e-13,7.54818e-13,7.82466e-13,2.35618e-08,1e-14,1.35683e-12,1e-14,1e-14,1e-14,2.58597e-10,2.91113e-08,2.91113e-08,1.47662e-14,1.03715e-13,3.57312e-09,3.57312e-09,1e-14,1.17736e-11,1.2113e-13,1.67777e-12,1e-14,9.90802e-12,9.90802e-12,1e-14,4.93141e-07,3.02696e-09,4.17249e-12,4.17249e-12,9.41958e-14,1.44397e-12,2.22636e-09,6.47639e-14,7.21173e-12,1.72916e-09,1.66782e-08,3.3174e-14,1.38908e-13,2.11033e-10,1.57165e-13,1.20357e-14,1.20357e-14,1.20357e-14,3.47191e-12,4.12144e-13,1.53636e-11,1e-14,1e-14,1e-14,1e-14,5.48716e-14,1.52384e-14,2.3453e-13,2.3453e-13,1.00014e-10,2.65939e-13,1.6559e-11,1.59859e-12,1.59859e-12,1e-14,1.53954e-12,1.13657e-10,1e-14,4.31498e-12,4.31498e-12,8.26652e-14,1.39907e-13,1e-14,1.83512e-13,2.69633e-14,1.15937e-13,1.15937e-13,2.29381e-11,3.15544e-14,1.82834e-13,1.82834e-13,1.83882e-10,1.83882e-10,1.83882e-10,1.02914e-12,1.02914e-12,5.92952e-10,1.57641e-13,1.57641e-13,2.18572e-12,2.18572e-12,2.07867e-11,5.60908e-11,5.60908e-11,1.73679e-13,1.73679e-13,1.12574e-12,9.86236e-11,1e-14,1e-14,1e-14,7.50568e-09,7.50568e-09,6.6007e-14,1.54387e-12,1.38339e-10,2.98493e-10,2.98493e-10,2.32459e-13,2.32459e-13,3.17427e-12,1.53828e-10,1.53828e-10,5.19044e-14,7.88421e-13,1e-14,1e-14,4.0878e-13,4.0878e-13,4.0878e-13,6.0801e-14,7.86519e-13,7.86519e-13,7.86519e-13,1e-14,3.57879e-07,7.03885e-11,7.03885e-11,7.03885e-11,1e-14,6.06971e-14,6.06971e-14,6.06971e-14,1.8703e-10,1e-14,1e-14,1e-14,6.23465e-14,8.81581e-10,1e-14,1e-14,4.74692e-09,4.74692e-09,9.41316e-13,1.48595e-09,1e-14,6.12727e-11,6.12727e-11,2.67577e-11,2.67577e-11,1.87443e-11,6.61934e-14,6.61934e-14,1e-14,1e-14,1e-14,1e-14,1e-14,1e-14,1.1102e-06,1e-14,7.54474e-09,2.2613e-10,1.04859e-12,1.38992e-08,1.38992e-08,8.28081e-12,9.60398e-11,3.22348e-13,1.18722e-11,1.68415e-12,1e-14,1.59868e-10,1.59868e-10,7.09741e-10,7.09741e-10,7.09741e-10,5.69249e-13,1.71536e-13,1e-14,2.20904e-11,2.18084e-12,1.97962e-13,1.97962e-13,1e-14,1e-14,4.23694e-10,2.32513e-13,1e-14,1.04389e-10,1e-14,1e-14", "train/minibatch_size": "8192,8192,4096,4096,8192,8192,4096,4096,4096,8192,8192,8192,8192,8192,4096,8192,8192,8192,8192,4096,8192,8192,8192,4096,4096,4096,4096,8192,8192,4096,4096,8192,8192,8192,16384,8192,4096,4096,4096,4096,4096,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,4096,8192,8192,8192,8192,4096,8192,8192,8192,8192,8192,8192,4096,4096,4096,4096,4096,8192,4096,8192,8192,8192,8192,8192,4096,8192,8192,8192,8192,8192,8192,4096,4096,8192,8192,8192,4096,8192,8192,4096,8192,4096,8192,8192,4096,4096,8192,4096,4096,4096,8192,8192,8192,4096,4096,8192,8192,8192,8192,8192,8192,4096,4096,8192,8192,8192,4096,8192,8192,8192,8192,8192,8192,8192,8192,4096,4096,8192,8192,4096,16384,16384,8192,8192,8192,8192,8192,8192,8192,8192,4096,4096,4096,8192,65536,8192,8192,8192,8192,4096,4096,4096,8192,8192,4096,4096,8192,8192,8192,8192,4096,4096,8192,4096,8192,8192,8192,4096,4096,4096,4096,4096,8192,8192,8192,4096,8192,8192,4096,8192,8192,8192,8192,4096,4096,8192,8192,8192,4096,8192,4096,8192,8192,4096,4096,4096,4096,4096,8192,4096,8192,8192,8192,8192,8192,8192,4096,8192,8192,8192,8192", "train/horizon": "256,128,64,64,128,128,128,128,128,32,32,128,128,128,32,64,64,1024,1024,32,32,32,64,128,128,128,128,256,32,16,128,256,64,64,32,32,64,32,32,32,32,32,256,256,32,32,32,32,64,32,64,128,128,32,32,64,16,16,32,32,256,128,128,16,16,16,64,256,64,16,32,128,128,128,128,64,16,256,256,256,256,16,64,128,128,128,128,64,64,64,64,256,128,128,64,64,64,128,128,128,32,64,64,32,64,128,128,32,32,32,128,128,64,256,256,128,128,32,64,64,64,64,64,64,256,256,256,64,64,32,256,256,32,32,32,32,256,256,256,128,256,64,128,256,256,256,512,128,128,128,64,256,32,32,32,64,64,64,64,256,32,64,64,64,32,64,64,32,32,32,64,64,32,32,32,32,64,128,128,128,64,64,32,32,32,128,64,512,32,256,256,256,16,128,64,32,64,64,512,512,128,128,128,64,64,128,32,128,64,64,32,32,64,64,32,128,32,32", "train/vtrace_rho_clip": "1.69539,3.59205,2.00076,2.00076,2.34499,2.34499,2.23478,2.23478,2.23478,1.84242,1.84242,2.54785,2.54785,2.54785,2.62561,1.60424,1.60424,2.48685,2.48685,1.99947,1.89245,1.89245,2.41259,1.86955,1.86955,1.86955,1.86955,2.2851,1.8913,1.25723,2.9185,2.68917,1.44025,1.44025,1.70899,1.12327,1.81421,2.28494,1.67645,1.67645,1.67645,0.786599,2.66943,2.66943,2.84202,2.54131,2.11113,2.11113,1.52416,2.01927,3.23215,2.32005,3.81882,1.46024,1.46024,1.21441,1.51066,1.94239,1.9,1.9,2.42539,2.67108,3.32833,2.07536,2.6925,1.5524,2.53227,2.21879,1.30391,1.15712,0.736897,2.99204,2.99204,2.99204,2.25019,3.60713,2.51522,2.75766,2.75766,2.75766,2.75766,2.1654,1.69261,1.27685,1.27685,2.00177,1.22237,1.72219,2.2082,2.2082,1.74254,3.13087,2.49373,2.97669,2.64337,2.64337,1.29872,1.87042,1.42591,1.83169,1.7843,2.61659,2.61659,2.01385,1.47822,0.636661,0.636661,2.43938,2.43938,2.43938,1.39394,1.39394,2.63797,1.90052,1.90052,2.11561,2.11561,1.61129,0.452262,0.452262,2.63013,2.63013,1.99236,1.95238,3.81997,3.81997,2.68591,2.43259,2.43259,2.70503,2.00282,2.22221,1.57047,1.57047,2.70374,2.70374,1.62126,3.46862,3.46862,2.05507,2.62197,2.67289,3.04209,2.69204,2.69204,2.69204,3.43323,2.67747,2.67747,2.67747,0.801611,4.32166,1.44904,1.44904,1.44904,2.12295,2.96896,2.96896,2.96896,3.23911,3.0871,1.46129,1.46129,1.88891,1.28542,2.49482,2.49482,1.13644,1.13644,2.29349,2.5299,3.04534,1.57808,1.57808,1.7301,1.7301,1.8664,2.29685,2.29685,1.86124,1.59336,1.59336,1.47028,2.07391,2.07391,1.67994,2.84963,2.21442,1.50679,1.2614,2.35836,2.35836,2.23002,2.97715,2.27679,2.79559,2.65436,0.659045,2.0899,2.0899,1.37594,1.37594,1.37594,1.756,0.849481,3.41784,1.3635,1.25515,2.43799,2.43799,2.60558,2.60558,2.13234,2.30678,2.78384,2.01096,2.07787,2.07787", "train/vtrace_c_clip": "1.93007,1.83662,2.50935,2.50935,1.29436,1.29436,3.26629,3.26629,3.26629,1.60727,1.60727,1.82133,1.82133,1.82133,1.66371,1.26115,1.26115,0.963039,0.963039,1.67753,1.72805,1.72805,2.75449,2.60516,2.60516,2.60516,2.60516,1.1933,2.60868,1.73684,1.12655,2.14015,2.55998,2.55998,2.18536,2.49305,2.04096,3.04698,4.34589,4.34589,4.34589,2.59932,2.01668,2.01668,1.68498,3.20473,2.43962,2.43962,1.95556,2.38047,2.37711,2.60174,1.96093,4.56948,4.56948,1.85164,2.27564,2.00118,2.45185,2.45185,2.23578,2.45396,2.07117,2.28925,2.0547,2.7538,1.9769,2.20656,2.48534,3.51567,3.36985,1.33727,1.33727,1.33727,1.82212,1.78503,2.1846,2.24132,2.24132,2.24132,2.24132,1.31931,3.83144,2.69439,2.69439,2.17705,1.83585,2.837,1.43415,1.43415,2.6904,1.49612,1.84862,1.47083,0.7454,0.7454,1.88533,1.51567,1.75745,2.17325,2.68375,1.21624,1.21624,2.32845,1.24976,2.40381,2.40381,2.1173,2.1173,2.1173,3.00116,3.00116,1.97375,2.22541,2.22541,1.27016,1.27016,2.0936,2.91479,2.91479,3.25817,3.25817,1.84903,1.49367,1.86953,1.86953,2.12995,2.0948,2.0948,1.29583,1.74333,2.28014,1.63754,1.63754,1.34365,1.34365,1.6847,2.07529,2.07529,2.23021,1.54534,2.67112,2.7492,2.70208,2.70208,2.70208,1.90453,0.69916,0.69916,0.69916,2.21636,1.65749,1.37195,1.37195,1.37195,2.22979,1.01631,1.01631,1.01631,2.17679,1.19742,1.5059,1.5059,1.401,2.30766,2.35374,2.35374,2.23741,2.23741,1.16782,1.99684,1.98651,1.01997,1.01997,1.14473,1.14473,2.66896,2.28741,2.28741,1.91503,2.18842,2.18842,2.5152,2.32562,2.32562,1.65919,2.45123,2.06494,1.77713,1.9345,2.2074,2.2074,3.50115,1.70317,1.14392,1.1749,0.966032,1.48719,1.61998,1.61998,0.981572,0.981572,0.981572,1.4771,2.21736,2.41036,2.29725,3.01938,1.7878,1.7878,1.54225,1.54225,2.00542,1.93116,2.3435,2.33624,3.06955,3.06955", "train/prio_alpha": "0.320443,0,0.31869,0.31869,0.0736595,0.0736595,0.00345533,0.00345533,0.00345533,0.607469,0.607469,0,0,0,0.179051,0.45794,0.45794,0.451174,0.451174,0.336297,0.340268,0.340268,0.66202,0.383448,0.383448,0.383448,0.383448,0.471093,0.522551,0.743736,0.497888,0.118873,0.336055,0.336055,0.471358,0.294202,0.780712,0.705543,0.45103,0.45103,0.45103,0.572097,0.0689085,0.0689085,0.232072,0.69637,0.346006,0.346006,0.444201,0.303572,0.73125,0.529484,0.571027,0.391254,0.391254,0.60619,0.258593,0.342361,0.322606,0.322606,0.381526,0.319849,0.272769,0.581758,0.400901,0.297619,0.298622,0.670915,0.0334407,0.430633,0.247885,0,0,0,0.520713,0.259698,0.428883,0.291633,0.291633,0.291633,0.291633,0.260353,0.00988354,0.105924,0.105924,0.105935,0.531522,0.190166,0.275675,0.275675,0.342771,0.2716,0.092571,0.432376,0.400653,0.400653,0.590191,0.549901,0.214018,0.737719,0.474007,0.402369,0.402369,0.306267,0.294859,0.114472,0.114472,0,0,0,0.137858,0.137858,0.110185,0.0458187,0.0458187,0.637131,0.637131,0.467636,0.099341,0.099341,0,0,0.537686,0.119454,0.0367871,0.0367871,0.332043,0,0,0.593857,0.0616996,0.0212399,0.502114,0.502114,0.663862,0.663862,0.522548,0.0667521,0.0667521,0.402903,0.4178,0.581344,0.878636,0.113558,0.113558,0.113558,0.259498,0.506904,0.506904,0.506904,0.386622,0.142795,0.605285,0.605285,0.605285,0.663361,0.356433,0.356433,0.356433,0.409249,0.598545,0.681857,0.681857,0.625678,0.301123,0.284524,0.284524,0.4001,0.4001,0.457209,0.33919,0.614308,0.322746,0.322746,0.714559,0.714559,0.347956,0.587303,0.587303,0.562061,0.67369,0.67369,0.485817,0.561516,0.561516,0.0626866,0.788163,0.544571,0.586392,0.478709,0.132022,0.132022,0.544741,0.282024,0.441919,0.0729439,0.508501,0.68856,0.157181,0.157181,0.499725,0.499725,0.499725,0.498705,0.781706,0.654764,0.455162,0.647717,0.350209,0.350209,0.556586,0.556586,0.119308,0.392597,0.550138,0.153108,0.183533,0.183533", "train/prio_beta0": "0,0,0,0,0.257851,0.257851,0,0,0,0,0,0,0,0,0,0.0406067,0.0406067,0,0,0,0.0249186,0.0249186,0.0396529,0.0707812,0.0707812,0.0707812,0.0707812,0,0,0,0,0.0805016,0,0,0.336801,0,0,0,0,0,0,0,0,0,0.0728714,0,0.135997,0.135997,0.141785,0.19688,0,0.100746,0.00458932,0.163151,0.163151,0,0.0438866,0.260814,0,0,0.145679,0.0789925,0.0537914,0,0,0,0,0,0.0397797,0,0,0,0,0,0,0,0,0,0,0,0,0.0447977,0,0,0,0.257375,0,0,0,0,0.0185667,0,0,0,0,0,0.265651,0,0,0.0999013,0.0410669,0,0,0,0,0,0,0.135085,0.135085,0.135085,0,0,0.0512573,0,0,0,0,0,0,0,0,0,0,0,0,0,0.154906,0,0,0.107223,0,0,0.144486,0.144486,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.456982,0.0394276,0.0394276,0.0394276,0,0,0,0,0,0.0800328,0.194612,0.194612,0.057645,0,0,0,0.119181,0.119181,0.0188773,0,0,0.00952127,0.00952127,0,0,0,0,0,0.120401,0,0,0,0,0,0.0879792,0.231863,0,0,0,0,0,0.189603,0,0,0,0.113474,0.111991,0,0,0,0,0,0,0,0,0,0.0587043,0,0,0.148277,0.148277,0,0.0216516,0.0018541,0,0,0", "train/use_rnn": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "no_model_upload": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "tsne1": "5.54824,12.3862,13.7376,13.7376,11.795,11.795,12.9758,12.9758,12.9758,7.36906,7.36894,11.2916,11.2915,11.2915,5.93935,8.17035,8.17039,2.98127,2.98127,15.7195,8.66704,8.66649,6.89331,7.97937,7.97921,7.97913,7.97904,10.6534,3.63342,14.9818,6.06011,11.7205,8.86432,8.86432,13.2138,14.8678,5.68135,6.08187,5.65057,5.65052,5.65065,15.1887,11.9687,11.9687,11.5436,6.60283,14.4988,14.499,2.78384,12.8721,4.50185,4.31575,3.93054,17.6124,17.6124,2.88699,14.4445,15.3162,9.53875,9.53876,7.97994,8.154,6.56627,15.0061,13.5343,16.1687,11.9477,5.38544,10.6658,16.7026,16.8566,9.31901,9.31901,9.31901,6.36746,6.02475,9.86756,3.81243,3.81243,3.81243,3.81236,11.7106,11.3555,10.6111,10.6108,11.0532,2.76435,13.0083,6.90623,6.90623,7.42215,10.9417,10.035,2.45327,8.07244,8.07244,0.891635,5.71029,9.12025,2.60391,17.3633,5.30177,5.30176,9.78208,3.94165,9.37861,9.37861,13.7525,13.7525,13.7525,10.4596,10.4595,6.15761,12.8805,12.8807,6.21618,6.21626,14.2408,11.6024,11.6024,11.5669,11.5669,6.13265,10.8763,2.16855,2.16855,3.21543,11.797,11.7963,2.73045,10.1908,11.6656,15.3028,15.3028,8.89706,8.89711,1.7348,11.2126,11.2126,4.28813,5.18275,2.11193,4.43855,3.04433,3.04444,3.04444,3.06166,5.42001,5.42001,5.42044,3.40774,50.4242,13.9095,13.9095,13.9095,4.76276,5.85016,5.85016,5.85016,6.86536,3.63141,0.867079,0.867079,6.48179,13.9962,9.21768,9.21768,15.3486,15.3489,9.39562,6.58379,6.24131,12.8133,12.8133,5.33842,5.33842,10.5255,5.47093,5.47096,6.70425,6.01883,6.01867,7.39167,5.25847,5.26087,10.2947,4.43514,8.13878,7.29507,3.01938,11.5812,11.5812,17.3439,6.21967,5.54491,13.8278,11.6271,1.86811,11.4075,11.4075,6.9713,6.9713,6.9713,5.83191,2.52571,3.57553,16.2001,6.88816,2.07626,2.07626,8.16433,8.16381,10.8237,6.5375,7.18113,10.8036,11.3992,11.3992", "tsne2": "-19.3034,-19.5665,-15.9771,-15.9771,-15.086,-15.086,-17.5372,-17.5372,-17.5372,-6.60547,-6.60538,-16.3013,-16.3013,-16.3013,-12.7641,-2.25676,-2.25682,-20.2463,-20.2463,-1.06323,-3.11693,-3.11531,-7.36299,-18.728,-18.7268,-18.7263,-18.7281,-21.5343,-5.52363,-0.725831,-10.3259,-20.6105,-4.25357,-4.25357,-1.0286,-4.63238,-6.8534,-0.423701,0.82857,0.828582,0.828606,-1.62299,-20.3595,-20.3595,-5.56601,0.0453203,-3.30037,-3.30058,-6.13969,-2.42047,-3.42293,-3.09639,-3.47484,-2.58713,-2.58713,-5.60471,-3.66246,-3.91634,-3.91799,-3.91795,-17.5177,-17.517,-13.8381,-0.576689,-3.2732,-2.12212,-2.79015,-18.3787,-9.57387,-2.58937,-3.76574,-14.2059,-14.2059,-14.2059,-19.0225,-11.2641,-2.77884,-19.5021,-19.5021,-19.5021,-19.5022,-5.07083,-9.72291,-9.9367,-9.93662,-19.1136,-2.67714,-4.4632,-3.51556,-3.51556,-9.2106,-22.0571,-16.4234,-8.45293,-15.9598,-15.9598,-3.40311,-19.0108,-11.3921,-2.85469,-1.52153,-11.2429,-11.2429,-3.47144,-10.4183,-10.8057,-10.8057,-12.6397,-12.6397,-12.6397,-8.86985,-8.87014,-12.8976,-21.6663,-21.6664,-18.5838,-18.5837,-2.15333,-8.50091,-8.50114,-13.149,-13.149,-8.34149,-16.3991,-18.1994,-18.1994,-10.4355,-16.5476,-16.5478,0.0777692,-15.373,-21.9792,-2.83016,-2.82997,-0.979329,-0.978869,-2.01692,-23.0382,-23.0382,-2.74589,-19.9526,-1.23292,-7.60799,-17.3892,-17.3892,-17.3892,-18.7728,-21.0098,-21.0098,-21.0096,-5.98554,36.4492,-1.82244,-1.82244,-1.82244,-2.41156,-16.807,-16.8072,-16.8072,-19.8892,0.149052,-3.45863,-3.45863,-1.75726,-4.70909,-5.81759,-5.81759,-4.1017,-4.10153,-2.34406,-13.7916,-7.07762,-3.0738,-3.0738,-9.08391,-9.08391,-6.91679,-0.903714,-0.903654,-8.71074,-1.58168,-1.58161,-9.89071,-3.58913,-3.58881,-17.958,-7.67121,-20.176,-1.17232,-9.27052,-17.8203,-17.8203,-1.90586,-13.0533,-2.25386,-11.5189,-1.6605,-5.71635,-22.367,-22.3669,-21.2336,-21.2336,-21.2336,-8.84775,-5.45819,-3.55343,-3.24133,-18.9682,-1.38977,-1.38977,-7.4998,-7.49955,-17.0001,-9.8762,-7.66482,-15.6772,-11.3513,-11.3513"}, "terraform": {"SPS": "1.13088e+06,3.05614e+06,601175,589466,616041,94096.6,372034,372504,1.01947e+06,1.02125e+06,1.34785e+06,1.33983e+06,1.34492e+06,174176,836873,853257,852967,827591,1.51849e+06,507748,502942,1.45263e+06,416028,414866,2.31704e+06,2.4047e+06,2.36164e+06,2.32191e+06,1.46434e+06,442002,1.57129e+06,1.57125e+06,1.57076e+06,1.56966e+06,1.04659e+06,1.04108e+06,658339,758905,756964,1.47793e+06,1.42549e+06,1.46206e+06,604645,615536,622809,620780,922458,139950,1.54545e+06,1.5224e+06,1.61398e+06,1.60999e+06,1.72385e+06,1.67497e+06,1.80476e+06,198937,129438,129221,129323,319237,319698,320074,320081,320558,503272,1.78281e+06,136205,136199,135826,135890,751793,749645,1.02194e+06,1.02254e+06,1.02186e+06,1.01925e+06,1.14654e+06,1.14164e+06,188182,188331,188177,188210,3.14386e+06,402119,60212.3,60195.1,191182,1.90571e+06,1.89442e+06,1.38359e+06,1.3735e+06,1.92387e+06,1.80445e+06,1.1218e+06,1.1128e+06,455398,455028,1.0397e+06,1.89713e+06,1.52331e+06,1.51422e+06,1.67655e+06,1.37404e+06,1.36376e+06,1.36507e+06,523950,478729,224402,639231,638032,411045,409695,409460,409246,406716,801522,1.32123e+06,166597,166173,158393,158351,158119,157488,804538,802012,802421,803324,962091,940003,940594,941064,948279,1.99051e+06,450595,1.69775e+06,270418,1.99188e+06,1.26647e+06,2.35742e+06,1.91489e+06,1.88561e+06,159479,721730,500860,501438,499490,231736,231214,132541,2.14757e+06,918069,890004,268695,610069,467247,464972,1.25885e+06,406124,1.23082e+06,811866,808477,471667,533684,181676,185178,146000,1.02807e+06,1.03485e+06,1.0338e+06,1.03772e+06,711363,681126,796428,216928,216992,217009,504821,501684,312214,1.10365e+06,452400,433635,1.55333e+06,1.54799e+06", "agent_steps": "25.2969,27.263,75.4975,125.305,175.112,191.889,385.876,440.402,42.4673,124.41,32.2437,92.3786,152.568,44.8266,110.625,184.025,257.425,293.601,26.2144,28.3373,82.4281,26.2144,25.559,75.1043,25.9364,30.6708,88.0804,204.451,92.5368,42.4673,27.7873,82.3132,136.839,191.355,26.3455,75.4975,75.3634,398.197,454.558,26.2144,75.765,125.829,75.4975,125.305,175.112,199.754,25.6901,5.76717,26.2144,76.0218,28.7017,76.0218,123.665,177.195,199.754,247.464,136.577,190.841,217.58,25.559,75.1043,125.043,174.981,199.754,37.4866,26.0079,138.019,229.9,321.782,367.526,75.4975,125.305,101.188,167.772,234.873,267.387,45.6131,134.218,102.236,169.345,236.454,269.484,27.7873,370.672,29.6223,87.5561,36.1759,26.8698,76.6771,52.4288,154.665,26.7387,76.2839,26.2144,76.0218,89.9154,149.684,25.6901,31.1951,29.3601,197.122,26.2144,26.1419,75.7596,175.893,25.6901,119.8,463.471,173.539,242.745,26.0833,75.1043,125.043,174.981,199.754,25.6901,187.171,25.6901,199.754,95.4204,158.335,221.25,251.658,75.4975,125.305,175.112,199.754,51.5113,133.169,221.774,310.372,353.37,7.86432,25.6901,25.6901,113.246,25.9523,47.1859,26.7387,26.8698,76.6771,7.34003,75.4975,98.0419,163.054,227.541,43.3848,300.155,75.1043,25.0879,7.34003,75.487,6.29146,25.6901,26.3455,75.4975,7.86432,300.417,76.0218,25.6901,75.4975,25.6901,25.6901,6.29146,51.1181,102.236,31.0641,90.0465,149.422,208.794,26.2144,75.4975,77.8568,222.298,310.903,354.419,343.933,481.296,115.081,75.4975,25.428,385.352,26.2144,76.0218", "uptime": "22.3876,9.04539,121.576,205.283,288.797,2040.5,1035.55,1182.25,41.4361,122.185,23.8657,68.7163,113.575,257.393,137.795,223.884,309.945,352.387,16.9393,55.7712,162.792,17.8143,61.501,180.846,11.026,12.6791,36.9057,86.7768,63.1083,96.1521,17.7095,52.4031,87.1043,121.837,25.1363,72.2075,115.282,521.414,595.777,17.6678,52.1087,86.6001,125.255,207.322,287.438,327.01,27.8078,41.2309,16.8457,49.4887,17.3887,47.2581,75.9149,106.923,120.416,1241.79,1054.81,1474.47,1681.37,80.1333,235.176,391.351,547.362,624.747,74.4569,14.4642,1012.49,1687.07,2362.56,2699.38,99.7743,166.251,98.7532,163.897,229.532,261.353,39.7411,117.248,543.043,899.552,1255.95,1431.52,8.86484,921.579,491.916,1454.34,189.178,14.1157,40.3689,37.7326,112.075,13.5862,40.601,23.3413,68.0335,197.096,328.378,24.6193,16.4044,19.2625,130.043,15.6256,18.9118,55.2574,128.64,48.9969,249.125,2057.3,270.308,378.726,63.4463,182.924,304.874,426.892,487.41,32.1119,140.829,154.079,1200.53,600.688,998.059,1395.53,1587.94,93.8526,155.901,217.978,248.693,53.4208,141.208,235.43,329.636,375.319,3.98851,57.1499,15.1909,417.071,13.0841,37.1562,11.4591,13.8283,40.2671,46.0284,103.843,195.264,325.034,453.757,187.15,1296.4,566.314,11.8358,8.0588,84.8518,23.4576,42.0923,56.321,161.836,6.21676,741.814,61.4864,31.5381,93.1466,54.1477,48.256,33.9683,275.31,699.981,30.1408,87.4405,144.818,202.164,36.7087,107.36,97.2172,1027.67,1435.99,1636.53,668.076,941.416,368.044,68.4138,56.3409,888.619,16.9519,49.0985", "epoch": "96.5,26,144,239,334,183,368,420,162,474.585,123,352.397,582,85.5,105.5,175.5,245.5,280,100,108.098,314.438,50,97.5,286.5,98.9394,117,336,779.919,353,162,106,314,522,729.962,100.5,288,1149.95,759.5,867,50,144.51,240,144,239,334,381,98,5.5,50,145,54.7442,145,235.872,337.972,381,944,260.5,364,415,97.5,286.5,477,667.5,762,71.5,49.6061,526.5,877,1227.5,1402,144,239,193,320,447.984,510,87,256,97.5,161.5,225.5,257,106,353.5,56.5,167,138,102.5,292.5,100,295,51,145.5,50,145,171.5,285.5,24.5,119,112,751.962,100,99.7234,289,670.979,49,457,442,165.5,231.5,99.5,286.5,477,667.5,762,49,357,49,381,45.5,75.5,105.5,120,144,239,334,381,196.5,254,423,591.988,674,30,49,196,108,99,90,51,102.5,292.5,7,576,93.5,155.5,217,165.5,1145,573,95.7027,7,143.98,6,49,201,576,7.5,573,145,49,144,49,49,3,97.5,97.5,118.5,343.5,570,796.487,50,144,148.5,212,296.5,338,328,459,219.5,72,97,735,50,145", "perf/rollout": "0.203324,0.335272,0.285449,0.301031,0.262794,0.541457,0.344155,0.339829,0.333037,0.329325,0.223262,0.226759,0.224797,0.249271,0.266157,0.240528,0.24133,0.278605,0.398548,0.265624,0.274703,0.426352,0.0660643,0.0674182,0.27203,0.428835,0.440395,0.446234,0.211926,0.124949,0.215551,0.21529,0.21542,0.213773,0.312848,0.317069,0.19701,0.129545,0.133356,0.28008,0.291369,0.28746,0.216795,0.200235,0.189401,0.192169,0.303172,0.645963,0.276258,0.286393,0.395287,0.378461,0.411713,0.450159,0.153123,0.160946,0.316922,0.320613,0.316795,0.0745307,0.0726514,0.0714824,0.071366,0.0700476,0.242363,0.590726,0.196544,0.196256,0.201546,0.200522,0.38161,0.383651,0.245156,0.244612,0.242973,0.123758,0.196784,0.200375,0.415413,0.413911,0.419941,0.419102,0.326371,0.334972,0.392601,0.394078,0.157497,0.18836,0.192492,0.286104,0.29171,0.626645,0.678321,0.226531,0.233961,0.122228,0.122982,0.423193,0.289815,0.226141,0.227542,0.213466,0.276959,0.286261,0.284236,0.141324,0.247371,0.475326,0.200523,0.203449,0.0595717,0.0614713,0.0617418,0.0620361,0.0657222,0.148395,0.245731,0.273682,0.281512,1.18251,1.17605,1.19001,1.24135,0.104522,0.106377,0.106145,0.105455,0.178434,0.31298,0.312491,0.310256,0.151624,0.226817,0.141272,0.225846,0.341933,0.239995,0.22299,0.274807,0.498502,0.508281,0.548793,0.209489,0.327246,0.324882,0.333005,0.140985,0.143054,0.0571824,0.241615,0.45755,0.427179,0.454652,0.211079,0.11497,0.118107,0.485193,0.163461,0.224322,0.251126,0.25374,0.223697,0.106365,1.41015,0.378081,0.270695,0.147558,0.142463,0.143263,0.139465,0.242208,0.277954,0.224535,0.373692,0.371267,0.371262,0.717603,0.731901,0.240333,0.154741,0.150286,0.162654,0.183862,0.185434", "perf/eval_gpu": "0.0626678,0.0689919,0.0770761,0.0787352,0.0775779,0.375974,0.143915,0.144271,0.0591945,0.058865,0.0538037,0.0532538,0.0526878,0.171792,0.0523699,0.0535265,0.0533446,0.0535795,0.0737021,0.0868569,0.0866109,0.0736749,0.0283434,0.0281881,0.0794646,0.0914925,0.0914027,0.0898327,0.0658005,0.0484021,0.0740255,0.072139,0.0721618,0.071405,0.0517921,0.0518281,0.0462303,0.0391324,0.039672,0.0535793,0.0596459,0.0541838,0.0410473,0.0412309,0.0411214,0.0431797,0.131025,0.358435,0.0572802,0.0573222,0.0522584,0.0496126,0.0617382,0.0646725,0.0254767,0.101286,0.127716,0.134038,0.140842,0.0283063,0.0282558,0.0283761,0.0284623,0.0285777,0.0643513,0.131135,0.114307,0.114409,0.114527,0.114173,0.0406868,0.0405334,0.0745314,0.0741164,0.0735932,0.0392286,0.0641959,0.0647494,0.232294,0.233562,0.230866,0.232909,0.0561277,0.0973732,0.279782,0.27827,0.100835,0.0505213,0.0505151,0.061173,0.0599052,0.0945894,0.0957707,0.0550725,0.0551022,0.0318933,0.03209,0.125485,0.0749481,0.053905,0.0528914,0.0470753,0.053722,0.0551976,0.0546842,0.0347665,0.0475003,0.215503,0.0524726,0.053884,0.0181219,0.0184503,0.0186568,0.0187989,0.0214611,0.0341696,0.06923,0.161488,0.161592,0.481668,0.472678,0.452997,0.464424,0.0357458,0.0356821,0.0355264,0.0351502,0.0499466,0.0853161,0.0847203,0.0846597,0.0412254,0.0627411,0.036059,0.0652217,0.0963268,0.0628876,0.0566103,0.0429988,0.0736752,0.0738735,0.341944,0.0361312,0.0857718,0.0859853,0.0889581,0.0843932,0.0843606,0.0289087,0.0694067,0.168104,0.0921882,0.151444,0.0421936,0.0324915,0.0328769,0.0640245,0.0480789,0.0453461,0.0898833,0.0902432,0.0447422,0.0330912,0.722407,0.176976,0.134067,0.0373846,0.0365684,0.0367147,0.0351516,0.0640249,0.064114,0.0417306,0.185636,0.178325,0.17996,0.0996237,0.0972981,0.0629785,0.0480038,0.0549538,0.0483015,0.06737,0.0670499", "perf/eval_env": "0.113349,0.256952,0.205308,0.219507,0.182456,0.134335,0.185419,0.186511,0.265207,0.263672,0.16052,0.164472,0.163852,0.0631481,0.190711,0.176205,0.176732,0.18728,0.317543,0.175862,0.185174,0.340159,0.0319172,0.0332641,0.121827,0.324204,0.336782,0.338571,0.125976,0.0661926,0.121974,0.124047,0.124333,0.123544,0.254304,0.259588,0.146864,0.0861131,0.0885722,0.21881,0.222589,0.225119,0.143134,0.137872,0.134331,0.134036,0.156899,0.274496,0.209894,0.220063,0.287605,0.278399,0.323184,0.342867,0.125022,0.0540229,0.18009,0.177389,0.171995,0.0395,0.0404753,0.0393534,0.03918,0.0378912,0.175177,0.43815,0.0773981,0.0770016,0.0819341,0.0811898,0.313831,0.31582,0.162803,0.162762,0.16176,0.0806443,0.123484,0.126591,0.166428,0.165799,0.167506,0.165824,0.198381,0.228004,0.103699,0.105686,0.0519082,0.126781,0.130805,0.21681,0.223159,0.518471,0.56915,0.161759,0.167207,0.0864196,0.0868083,0.288129,0.194979,0.163337,0.165837,0.155967,0.21559,0.223025,0.221733,0.0991481,0.191728,0.241403,0.139332,0.140563,0.0393453,0.0406957,0.0408074,0.040811,0.0410889,0.106354,0.16762,0.102438,0.109768,0.683817,0.683823,0.715209,0.754662,0.06468,0.0665359,0.0664758,0.0662476,0.121313,0.219494,0.219816,0.217443,0.106966,0.151854,0.0729998,0.142336,0.237946,0.152691,0.158305,0.202287,0.415476,0.425113,0.19297,0.169147,0.234133,0.231339,0.234961,0.0514655,0.0534584,0.0269441,0.135555,0.279372,0.326035,0.295984,0.161835,0.0791512,0.0810315,0.415723,0.111832,0.170421,0.156459,0.158713,0.166348,0.0627769,0.67732,0.198211,0.117148,0.100568,0.0977792,0.098023,0.0972095,0.175382,0.210828,0.176687,0.1753,0.176858,0.175415,0.587843,0.602705,0.170937,0.0951297,0.0760212,0.110881,0.105367,0.107346", "perf/train_misc": "0.0774635,0.0210174,0.0198627,0.0198896,0.0198736,0.18627,0.0427562,0.0426117,0.0151759,0.0151254,0.0194809,0.0194018,0.0194855,0.0283552,0.0298888,0.0298866,0.0299162,0.029866,0.0115375,0.0179527,0.017954,0.014017,0.0140161,0.0140436,0.0288391,0.011991,0.0119861,0.0118273,0.0263397,0.0319336,0.0201171,0.0191294,0.0191276,0.0189431,0.031173,0.0311855,0.00888377,0.0120741,0.0120617,0.033904,0.0332662,0.0339111,0.0199104,0.0199065,0.0199268,0.0200211,0.0114331,0.258362,0.0235089,0.0235076,0.0162599,0.0153549,0.0191107,0.0198232,0.00769024,0.00833081,0.0494512,0.0494537,0.0499067,0.0157039,0.0157149,0.015717,0.0157193,0.015923,0.0325071,0.0160567,0.0254444,0.0254483,0.0254594,0.0254803,0.0115236,0.0115229,0.0173739,0.0173641,0.0172417,0.00872243,0.0197171,0.0197257,0.0593408,0.0593942,0.0593588,0.0596767,0.050424,0.0552529,0.101449,0.101342,0.0129045,0.0285696,0.0285197,0.0218345,0.0218253,0.0176835,0.0176651,0.0260518,0.0260711,0.0341594,0.034168,0.0552926,0.0320064,0.0194147,0.0192107,0.0230338,0.0271162,0.0272753,0.0271251,0.0516364,0.0230426,0.0454615,0.0493594,0.0493698,0.0170163,0.0170046,0.0170072,0.0170213,0.0171438,0.0381946,0.0151292,0.0528207,0.0528013,0.318658,0.318322,0.318596,0.317796,0.0121062,0.0121129,0.0121007,0.0121285,0.0135755,0.0216288,0.0216325,0.0214858,0.0107837,0.0154451,0.0514593,0.0235067,0.104291,0.0712884,0.0205616,0.0369374,0.0217783,0.0217744,0.0887509,0.0282565,0.052276,0.0522416,0.052236,0.00894155,0.00896666,0.00774817,0.0447157,0.0619269,0.0238561,0.106828,0.0345727,0.0231296,0.0231368,0.0178423,0.0303559,0.034917,0.0149469,0.0149417,0.0396091,0.0531656,0.599218,0.0282497,0.191297,0.0310697,0.0310632,0.0310674,0.0309544,0.020335,0.0203753,0.0141528,0.0409585,0.0409747,0.0411556,0.0332716,0.0333255,0.0509867,0.028568,0.0511577,0.028425,0.0157355,0.0157547", "perf/train_forward": "0.436101,0.329282,0.568727,0.568789,0.568724,10.4126,2.43157,2.43294,0.423103,0.421725,0.534592,0.532234,0.534697,2.73217,0.958709,0.958097,0.957977,0.957352,0.281734,0.73945,0.747318,0.282626,0.549498,0.549908,0.38481,0.212988,0.213029,0.210004,0.477355,1.02856,0.454804,0.43251,0.432583,0.428501,0.406835,0.406392,0.480559,0.549652,0.547891,0.395146,0.387609,0.3953,0.631986,0.632064,0.632006,0.632046,0.537479,13.2968,0.378383,0.378352,0.274244,0.259084,0.322007,0.334089,0.129311,1.14883,3.68351,3.6868,3.68614,0.730528,0.731264,0.73141,0.731626,0.731513,0.766342,0.277213,1.70222,1.70273,1.70261,1.70208,0.305479,0.305507,0.763016,0.763013,0.757442,0.382019,0.697523,0.697832,5.09716,5.0942,5.09322,5.09084,0.28967,2.21075,8.21169,8.21225,1.20057,0.469929,0.46999,0.449615,0.449552,0.175608,0.175196,0.681738,0.681597,0.994182,0.994567,0.656492,0.383396,0.442136,0.438704,0.388757,0.452252,0.45469,0.45199,0.807066,0.824167,4.16015,1.38991,1.39001,0.560701,0.560941,0.561058,0.561153,0.561005,0.46695,0.532316,2.81998,2.8191,11.7376,11.7474,11.7537,11.7464,0.534783,0.534964,0.534811,0.534446,0.625034,0.780596,0.780426,0.775562,0.389726,0.415425,0.970013,0.378665,3.43012,0.364242,0.58399,0.354003,0.164675,0.164537,5.93693,0.487788,1.71385,1.71369,1.71368,0.994583,0.996333,0.923709,0.368318,1.17548,0.677638,3.32924,0.61321,0.702756,0.703696,0.333647,1.09677,0.592042,0.379491,0.379543,0.847878,0.822094,29.884,2.42598,6.71933,0.585688,0.585792,0.585707,0.583362,0.474351,0.474364,0.419785,4.41979,4.4208,4.42221,1.32694,1.32681,1.38738,0.766311,0.956793,1.01559,0.474866,0.4757", "perf/train": "0.513564,0.3503,0.58859,0.588678,0.588598,10.5989,2.47432,2.47555,0.438279,0.43685,0.554073,0.551636,0.554183,2.76053,0.988598,0.987984,0.987893,0.987218,0.293272,0.757403,0.765272,0.296643,0.563514,0.563951,0.413649,0.224979,0.225015,0.221832,0.503694,1.0605,0.474921,0.45164,0.451711,0.447444,0.438008,0.437577,0.489442,0.561726,0.559953,0.42905,0.420875,0.429211,0.651896,0.65197,0.651933,0.652067,0.548912,13.5551,0.401892,0.40186,0.290504,0.274439,0.341118,0.353912,0.137001,1.15716,3.73296,3.73626,3.73605,0.746232,0.746979,0.747127,0.747345,0.747436,0.798849,0.29327,1.72767,1.72818,1.72807,1.72756,0.317003,0.31703,0.78039,0.780377,0.774683,0.390741,0.71724,0.717558,5.1565,5.1536,5.15258,5.15051,0.340094,2.26601,8.31314,8.3136,1.21347,0.498499,0.49851,0.471449,0.471377,0.193291,0.192861,0.70779,0.707668,1.02834,1.02874,0.711785,0.415402,0.46155,0.457915,0.411791,0.479368,0.481965,0.479115,0.858702,0.847209,4.20562,1.43927,1.43938,0.577718,0.577946,0.578065,0.578174,0.578148,0.505144,0.547445,2.8728,2.8719,12.0563,12.0658,12.0723,12.0642,0.546889,0.547077,0.546912,0.546575,0.63861,0.802225,0.802059,0.797047,0.40051,0.43087,1.02147,0.402172,3.53441,0.43553,0.604552,0.390941,0.186453,0.186312,6.02568,0.516044,1.76612,1.76593,1.76591,1.00352,1.0053,0.931458,0.413034,1.23741,0.701494,3.43607,0.647782,0.725885,0.726832,0.35149,1.12712,0.626959,0.394438,0.394485,0.887487,0.87526,30.4833,2.45423,6.91063,0.616758,0.616855,0.616775,0.614317,0.494687,0.494739,0.433938,4.46075,4.46177,4.46337,1.36021,1.36013,1.43837,0.794879,1.00795,1.04402,0.490602,0.491455", "util/gpu_percent": "92.2031,82.5217,79.7263,77.6632,81.5053,100,100,100,68.7476,66.934,88,87.2931,87.7193,100,94.3714,93,95,100,54.1702,83.7451,80.619,50.7447,99.4628,99.4211,96.1818,62.6667,58.027,60.4324,95.2931,99.4241,94.5,98.2308,96.9808,97.7885,66.2097,76.3175,81.5455,95.625,100,72.1064,73.6735,73.2128,88.2632,90.7158,90.4,100,85.1587,100,72.4681,73.6042,62.5116,51.2766,63.9231,51.2778,25,99.9926,100,100,100,98.8883,99.1895,99.089,99.1947,100,81.0882,49.3636,100,100,100,100,58.4211,60.7474,93.3333,93.4688,91,93,96,96.1294,100,100,100,100,87.875,100,100,100,100,95.7895,95.7368,75.866,78.5102,48.0968,38.375,90.0426,89.2708,97.7895,98.0965,55.5833,83.9149,86.0566,85.7736,84.8723,77.6383,78.25,77.3191,95,83.3158,100,100,100,98.5652,98.1579,98.1518,98.1263,100,91.5474,87.58,100,100,100,100,100,100,98.4316,98.5895,98.6526,100,91.2619,87.8929,86.3765,86.1905,90,91.6667,97.7474,88.5833,100,92.4359,90.9195,91.6129,43.8684,43.9474,100,77.2947,100,100,100,97.9475,97.9297,99.1732,93.2432,78.2308,75.34,100,85.4211,93.7236,94.3465,49.25,99.6933,88.9167,77.7053,78.9053,85.7158,98.1474,100,100,100,93.027,92.7763,92.0933,92.4605,82.7527,77.9789,78.8571,100,100,100,100,100,100,99,98.0211,100,98.0213,96.5", "util/gpu_mem": "17.8592,13.5607,9.31063,9.31063,9.31063,23.8929,16.2802,16.2802,8.51271,8.51271,9.11522,9.11522,9.11522,21.6539,15.5311,15.5311,15.5311,15.5311,8.08933,20.8577,20.859,20.8473,10.2714,10.2714,8.57785,8.2196,8.2196,8.2196,8.83025,9.60374,9.47347,9.47347,9.47347,9.47347,6.11896,6.11896,7.49496,26.0321,26.0908,21.2626,21.1332,21.2626,10.5156,10.5156,10.5156,10.5156,12.0219,18.0633,9.38391,9.38391,9.36762,9.36762,9.36762,9.36762,9.36762,17.8353,11.0937,11.0937,11.0937,10.4749,10.4749,10.4749,10.4749,10.4749,8.38244,11.1833,11.9405,11.9405,11.9405,11.9405,9.60374,9.60374,13.8946,13.8946,13.8946,13.8946,13.1699,13.1699,23.7382,23.7382,23.7382,23.7382,7.39726,31.4242,14.033,14.033,12.6326,7.60081,7.60081,9.97827,9.97827,20.1064,20.1064,11.0937,11.0937,10.6052,10.6052,12.5756,7.13671,7.77993,7.77993,7.02273,6.72147,6.72147,6.72147,8.88724,8.10561,22.9485,15.7347,15.7347,7.97534,7.97534,7.97534,7.97534,7.97534,8.65927,12.7384,13.5933,13.5933,22.1668,22.1668,22.1668,22.1668,14.3424,14.3424,14.3424,14.3424,10.825,12.315,12.315,12.315,12.315,10.5319,10.882,6.12711,14.4401,17.3056,11.566,9.87243,5.9317,5.9317,16.8908,5.48389,15.8649,15.8649,15.8649,15.6125,15.6125,8.85468,7.42168,13.7236,9.73401,13.0885,8.35801,6.44464,6.44464,11.2159,23.925,9.80729,9.49789,9.49789,8.529,10.4749,32.6207,13.2514,19.9441,7.69037,7.69037,7.69037,7.69037,8.38244,8.38244,10.7436,22.8508,22.8508,22.8508,15.8242,15.8242,22.6549,30.9271,8.50457,10.8088,12.3964,12.3964", "util/vram_used_gb": "3.823,2.79187,1.77234,1.77234,1.77234,5.27039,3.44421,3.44421,1.58093,1.58093,1.72546,1.72546,1.72546,4.73328,3.26453,3.26453,3.26453,3.26453,1.47937,4.54228,4.5426,4.53979,2.00281,2.00281,1.59656,1.51062,1.51062,1.51062,1.6571,1.84265,1.8114,1.8114,1.8114,1.8114,1.00671,1.00671,1.33679,5.78353,5.79761,4.6394,4.60837,4.6394,2.0614,2.0614,2.0614,2.0614,2.42273,3.87195,1.78992,1.78992,1.78601,1.78601,1.78601,1.78601,1.78601,3.81726,2.20007,2.20007,2.20007,2.05164,2.05164,2.05164,2.05164,2.05164,1.54968,2.22156,2.4032,2.4032,2.4032,2.4032,1.84265,1.84265,2.87195,2.87195,2.87195,2.87195,2.69812,2.69812,5.23328,5.23328,5.23328,5.23328,1.31335,7.07701,2.90515,2.90515,2.56921,1.36218,1.36218,1.9325,1.9325,4.36206,4.36206,2.20007,2.20007,2.08289,2.08289,2.55554,1.25085,1.40515,1.40515,1.22351,1.15125,1.15125,1.15125,1.67078,1.48328,5.04382,3.31335,3.31335,1.45203,1.45203,1.45203,1.45203,1.45203,1.61609,2.5946,2.79968,2.79968,4.85632,4.85632,4.85632,4.85632,2.97937,2.97937,2.97937,2.97937,2.13562,2.49304,2.49304,2.49304,2.49304,2.06531,2.14929,1.00867,3.00281,3.69019,2.31335,1.9071,0.961792,0.961792,3.5907,0.85437,3.3446,3.3446,3.3446,3.28406,3.28406,1.66296,1.31921,2.83093,1.8739,2.67859,1.54382,1.08484,1.08484,2.22937,5.27808,1.89148,1.81726,1.81726,1.58484,2.05164,7.36401,2.71765,4.32312,1.38367,1.38367,1.38367,1.38367,1.54968,1.54968,2.11609,5.02039,5.02039,5.02039,3.33484,3.33484,4.97339,6.95776,1.57898,2.13171,2.51257,2.51257", "util/vram_total_gb": "23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272", "util/cpu_mem_gb": "1.18692,1.47804,1.2144,1.21479,1.21479,2.01577,1.45469,1.45505,1.21924,1.21924,1.26157,1.26157,1.26157,1.57126,1.4469,1.4469,1.4469,1.4469,1.20426,1.11903,1.11903,1.16775,1.31589,1.31589,1.28565,1.23027,1.23027,1.23027,1.27173,1.29316,1.29269,1.29269,1.29282,1.29318,1.20673,1.20673,1.19091,1.26057,1.26057,1.17354,1.17354,1.17354,1.36835,1.36864,1.36864,1.36864,1.27384,1.42165,1.26756,1.26756,1.3572,1.3572,1.3572,1.3572,1.3572,1.26562,1.25928,1.25959,1.25959,1.2927,1.2927,1.29273,1.29319,1.29319,1.2172,1.23967,1.1624,1.16293,1.16343,1.16343,1.34431,1.34431,1.33801,1.33801,1.33801,1.33801,1.35741,1.35756,1.48905,1.48931,1.48954,1.48954,1.26809,1.34284,1.49725,1.49725,1.26572,1.29922,1.29922,1.28141,1.28141,1.16282,1.16282,1.34219,1.34219,1.32248,1.32248,1.21255,1.23983,1.25956,1.25956,1.26018,1.24057,1.24057,1.24057,1.32431,1.21515,1.41071,1.56373,1.564,1.25878,1.25889,1.25931,1.25976,1.25976,1.3008,1.32343,1.37585,1.37585,1.45689,1.45689,1.45689,1.45689,1.37942,1.37942,1.37942,1.37942,1.25156,1.28958,1.28958,1.28958,1.28958,1.30067,1.56049,1.18393,1.42315,1.1576,1.3054,1.35301,1.20596,1.20645,1.46038,1.19603,1.39445,1.39511,1.39543,1.24606,1.24778,1.21002,1.26201,1.23143,1.24698,1.28868,1.27484,1.20632,1.20635,1.37678,1.22181,1.30711,1.18242,1.18242,1.29248,1.50481,1.24778,1.218,1.93829,1.26897,1.26937,1.26945,1.26945,1.21752,1.21752,1.23774,1.47042,1.47042,1.47042,1.38641,1.38685,1.1755,1.62244,1.35846,1.30317,1.41315,1.41315", "env/perf": "0.0932126,0.0504205,0.567144,0.628197,0.650367,0.673575,0.689199,0.691334,0.48359,0.615719,0.407982,0.581343,0.611963,0.517945,0.616234,0.654145,0.672613,0.675732,0.259446,0.481843,0.600005,0.241335,0.337735,0.554059,0.0240486,0.293488,0.534104,0.596337,0.578449,0.508179,0.372537,0.569014,0.605758,0.623488,0.420591,0.564695,0.540774,0.681357,0.681489,0.335068,0.559599,0.582556,0.598498,0.640113,0.659718,0.66267,0.316876,0.00781006,0.297524,0.539094,0.355854,0.538987,0.582197,0.613338,0.621737,0.672409,0.652323,0.671451,0.675206,0.420509,0.614453,0.646379,0.665538,0.669028,0.506641,0.235597,0.665027,0.69174,0.701419,0.702434,0.570302,0.620438,0.608577,0.646751,0.665401,0.668026,0.434979,0.609722,0.637506,0.665528,0.680046,0.683536,0.0254036,0.683609,0.485497,0.615675,0.514651,0.305784,0.50346,0.443584,0.612596,0.219958,0.479926,0.382639,0.57079,0.62163,0.647726,0.157874,0.354807,0.395543,0.629083,0.330656,0.371683,0.563441,0.617686,0.13479,0.627633,0.69635,0.647195,0.665947,0.407331,0.608591,0.647624,0.664529,0.6664,0.0958657,0.628033,0.425196,0.666158,0.622151,0.664472,0.680901,0.681689,0.588262,0.633041,0.653523,0.656285,0.495229,0.630526,0.65903,0.676248,0.679898,0.0147768,0.206745,0.0252636,0.624863,0.0281373,0.423673,0.164813,0.328342,0.494846,0.0139107,0.550076,0.619866,0.653404,0.666023,0.509566,0.681139,0.527119,0.0247169,0.0227255,0.515165,0.00834061,0.122509,0.417262,0.554671,0.023968,0.679098,0.576998,0.327317,0.523035,0.148457,0.12744,0.0121533,0.524933,0.627206,0.421443,0.607706,0.63622,0.651077,0.414483,0.544141,0.592179,0.669663,0.686481,0.689834,0.677453,0.689551,0.630686,0.551714,0.143703,0.680727,0.333376,0.532859", "env/score": "0.0932126,0.0504205,0.567144,0.628197,0.650367,0.673575,0.689199,0.691334,0.48359,0.615719,0.407982,0.581343,0.611963,0.517945,0.616234,0.654145,0.672613,0.675732,0.259446,0.481843,0.600005,0.241335,0.337735,0.554059,0.0240486,0.293488,0.534104,0.596337,0.578449,0.508179,0.372537,0.569014,0.605758,0.623488,0.420591,0.564695,0.540774,0.681357,0.681489,0.335068,0.559599,0.582556,0.598498,0.640113,0.659718,0.66267,0.316876,0.00781006,0.297524,0.539094,0.355854,0.538987,0.582197,0.613338,0.621737,0.672409,0.652323,0.671451,0.675206,0.420509,0.614453,0.646379,0.665538,0.669028,0.506641,0.235597,0.665027,0.69174,0.701419,0.702434,0.570302,0.620438,0.608577,0.646751,0.665401,0.668026,0.434979,0.609722,0.637506,0.665528,0.680046,0.683536,0.0254036,0.683609,0.485497,0.615675,0.514651,0.305784,0.50346,0.443584,0.612596,0.219958,0.479926,0.382639,0.57079,0.62163,0.647726,0.157874,0.354807,0.395543,0.629083,0.330656,0.371683,0.563441,0.617686,0.13479,0.627633,0.69635,0.647195,0.665947,0.407331,0.608591,0.647624,0.664529,0.6664,0.0958657,0.628033,0.425196,0.666158,0.622151,0.664472,0.680901,0.681689,0.588262,0.633041,0.653523,0.656285,0.495229,0.630526,0.65903,0.676248,0.679898,0.0147768,0.206745,0.0252636,0.624863,0.0281373,0.423673,0.164813,0.328342,0.494846,0.0139107,0.550076,0.619866,0.653404,0.666023,0.509566,0.681139,0.527119,0.0247169,0.0227255,0.515165,0.00834061,0.122509,0.417262,0.554671,0.023968,0.679098,0.576998,0.327317,0.523035,0.148457,0.12744,0.0121533,0.524933,0.627206,0.421443,0.607706,0.63622,0.651077,0.414483,0.544141,0.592179,0.669663,0.686481,0.689834,0.677453,0.689551,0.630686,0.551714,0.143703,0.680727,0.333376,0.532859", "env/episode_return": "21.262,-15.7782,177.116,196.542,203.447,210.929,216.067,216.708,148.147,193.026,122.268,181.871,191.691,158.954,192.934,205.032,210.911,211.895,73.1885,146.676,187.597,67.3139,101.026,172.121,3.70284,86.3092,166.928,186.742,181.011,157.178,109.57,177.412,189.258,194.794,128.25,176.474,169.012,213.324,213.221,96.2967,175.139,182.538,187.199,200.319,206.568,207.521,94.0363,-72.2439,81.586,168.283,105.846,168.336,182.235,192.231,194.92,210.377,204.212,210.275,211.517,124.804,192.341,202.373,208.391,209.526,156.566,60.7071,208.831,217.324,220.428,220.765,178.247,194.163,190.575,202.692,208.611,209.409,130.792,190.576,199.787,208.746,213.389,214.492,2.91004,214.46,148.009,192.09,156.543,86.0012,156.712,134.615,192.089,54.0022,149.812,114.324,178.47,194.914,203.264,39.364,106.09,119.785,197.175,97.2236,105.352,176.307,193.425,16.1448,196.638,218.524,202.761,208.655,120.566,190.185,202.621,207.986,208.499,13.8831,196.404,124.969,208.819,194.915,208.339,213.633,213.915,183.878,197.997,204.525,205.381,152.597,197.515,206.583,211.997,213.128,-69.7922,56.4189,2.99826,195.738,-15.3111,126.116,41.6571,97.2616,154.385,-79.2948,171.593,194.122,204.799,208.795,154.418,213.056,164.331,0.939716,-33.3812,160.552,-170.791,27.9883,127.106,172.959,-57.2883,212.514,180.565,97.1264,162.874,39.4825,31.0153,-110.453,161.394,195.894,126.517,190.314,199.253,203.914,126.124,169.504,185.034,210.128,215.477,216.537,212.266,216.072,197.61,172.566,38.2505,213.348,99.1061,166.392", "env/episode_length": "1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024", "env/quadrant_progress": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "env/n": "760,4096,2048,2048,2048,1024,4096,12288,2048,2048,2048,2048,2048,1024,4096,4096,4096,12288,2048,2048,2048,2048,1024,1024,1489.45,2048,2048,2048,1024,1024,1024,1024,1024,1024,2048,2048,2048,2048,10240,2048,2048,2048,4096,4096,4096,12288,1024,1024,2048,2048,4096,4096,4096,4096,12288,1024,2048,2048,10240,1024,1024,1024,1024,10240,2048,1489.45,512,512,512,10240,4096,4096,2048,2048,2048,10240,2048,2048,2048,2048,2048,10240,2048,2048,1024,1024,1024,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,1024,1263.66,2048,2048,2048,2048,2048,2048,1024,2048,10240,2048,2048,2048,2048,2048,2048,10240,1024,2048,1024,10240,2048,2048,2048,10240,2048,2048,2048,10240,2048,2048,2048,2048,10240,2048,1024,1024,2048,1260.31,2048,2048,2048,2048,2048,2048,2048,2048,2048,1024,1024,2048,1328.43,1024,2048,2048,1024,2048,2048,4096,2048,2048,1024,1024,1024,1024,2048,2048,1024,2048,2048,2048,2048,2048,2048,2048,4096,4096,12288,4096,4096,1024,2048,512,10240,2048,2048", "wandb": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "slowly": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "save_frames": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "fps": "15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15", "rank": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "world_size": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "gpu_id": "0,5,5,5,5,3,3,3,2,2,4,4,4,4,5,5,5,5,3,0,0,0,1,1,5,2,2,2,4,3,1,1,1,1,5,5,5,0,0,0,0,0,1,1,1,1,4,3,1,1,3,3,3,3,3,5,1,1,1,2,2,2,2,2,3,5,1,1,1,1,3,3,3,3,3,3,3,3,1,1,1,1,1,0,3,3,2,1,1,5,5,0,0,2,2,5,5,5,4,5,5,2,4,4,4,1,5,5,3,3,5,5,5,5,5,2,2,1,1,2,2,2,2,3,3,3,3,1,1,1,1,1,2,2,5,5,0,5,4,2,2,3,1,5,5,5,3,3,3,5,2,3,3,4,2,2,2,0,2,5,5,3,2,0,5,1,2,2,2,2,5,5,4,4,4,4,3,3,0,0,4,2,1,1", "profile": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "checkpoint_interval": "200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200", "eval_episodes": "10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000", "cudagraphs": "10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10", "seed": "73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73", "reset_state": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "vec/total_agents": "512,4096,2048,2048,2048,1024,4096,4096,2048,2048,2048,2048,2048,1024,4096,4096,4096,4096,2048,2048,2048,2048,1024,1024,1024,2048,2048,2048,1024,1024,1024,1024,1024,1024,2048,2048,2048,2048,2048,2048,2048,2048,4096,4096,4096,4096,1024,1024,2048,2048,4096,4096,4096,4096,4096,1024,2048,2048,2048,1024,1024,1024,1024,1024,2048,1024,512,512,512,512,4096,4096,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,1024,1024,1024,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,1024,1024,2048,2048,2048,2048,2048,2048,1024,2048,2048,2048,2048,2048,2048,2048,2048,2048,1024,2048,1024,1024,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,2048,1024,1024,2048,1024,2048,2048,2048,2048,2048,2048,2048,2048,2048,1024,1024,2048,1024,1024,2048,2048,1024,2048,2048,4096,2048,2048,1024,1024,1024,1024,2048,2048,1024,2048,2048,2048,2048,2048,2048,2048,4096,4096,4096,4096,4096,1024,2048,512,2048,2048,2048", "vec/num_buffers": "4.53755,5.85288,1,1,1,5.49952,4.38406,4.38406,2.22214,2.22214,4.50249,4.50249,4.50249,5.64524,4.07941,4.07941,4.07941,4.07941,2.85467,1.82419,1.82419,2.24925,5.62359,5.62359,8,3.2774,3.2774,3.2774,5.53891,5.72103,5.39979,5.39979,5.39979,5.39979,2.40352,2.40352,2.91996,4.18023,4.18023,3.04153,3.04153,3.04153,3.60767,3.60767,3.60767,3.60767,3.08825,2.48593,3.70776,3.70776,3.5485,3.5485,3.5485,3.5485,3.5485,3.45906,2.59248,2.59248,2.59248,4.69516,4.69516,4.69516,4.69516,4.69516,1.06714,2.22915,1.96647,1.96647,1.96647,1.96647,2.37049,2.37049,4.40297,4.40297,4.40297,4.40297,5.52492,5.52492,4.04134,4.04134,4.04134,4.04134,8,3.5593,3.48111,3.48111,3.9445,6.37295,6.37295,3.03282,3.03282,2.85864,2.85864,4.71245,4.71245,4.23712,4.23712,1.94712,4.0558,4.68507,4.68507,4.75178,3.34427,3.34427,3.34427,3.67471,2.26818,3.70169,5.61088,5.61088,4.25112,4.25112,4.25112,4.25112,4.25112,3.2365,4.48412,3.14587,3.14587,2.67625,2.67625,2.67625,2.67625,5.77512,5.77512,5.77512,5.77512,4.69297,3.41267,3.41267,3.41267,3.41267,5.26934,5.45971,4.98907,3.01841,5.39754,4.01127,8,2.70758,2.70758,3.06106,2.92855,3.68318,3.68318,3.68318,3.51493,3.51493,3.25614,6.47801,1,2.11841,2.61993,2.42154,3.44436,3.44436,2.40227,3.19512,4.95137,1.10111,1.10111,2.92966,5.08774,1,1.92136,5.72332,5.39321,5.39321,5.39321,5.39321,1.95762,1.95762,2.32963,4.15535,4.15535,4.15535,2.52766,2.52766,2.94612,7.00434,4.10567,3.66587,6.36392,6.36392", "vec/num_threads": "2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2", "env/num_envs": "1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024", "env/num_agents": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "env/size": "64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64", "env/reset_frequency": "1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024", "env/reward_scale": "0.264765,0.164058,0.0947074,0.0947074,0.0947074,0.0986708,0.104204,0.104204,0.0617968,0.0617968,0.138282,0.138282,0.138282,0.116712,0.0520562,0.0520562,0.0520562,0.0520562,0.139901,0.0808588,0.0808588,0.12713,0.106469,0.106469,0.0670878,0.134554,0.134554,0.134554,0.065025,0.167735,0.0733323,0.0733323,0.0733323,0.0733323,0.0636093,0.0636093,0.0801451,0.0548363,0.0548363,0.0974064,0.0974064,0.0974064,0.0628914,0.0628914,0.0628914,0.0628914,0.0514406,0.406899,0.081864,0.081864,0.14947,0.14947,0.14947,0.14947,0.14947,0.0347483,0.0395171,0.0395171,0.0395171,0.0323059,0.0323059,0.0323059,0.0323059,0.0323059,0.103825,0.199659,0.119664,0.119664,0.119664,0.119664,0.0806135,0.0806135,0.0907157,0.0907157,0.0907157,0.0907157,0.106922,0.106922,0.121454,0.121454,0.121454,0.121454,0.0399401,0.0305496,0.0898518,0.0898518,0.0562788,0.20341,0.20341,0.0593002,0.0593002,0.148159,0.148159,0.116531,0.116531,0.0699513,0.0699513,0.386943,0.190519,0.121739,0.121739,0.166391,0.124066,0.124066,0.124066,0.138932,0.0774123,0.0577084,0.0692999,0.0692999,0.0578179,0.0578179,0.0578179,0.0578179,0.0578179,0.0511178,0.0413705,0.15854,0.15854,0.0455641,0.0455641,0.0455641,0.0455641,0.0666641,0.0666641,0.0666641,0.0666641,0.163731,0.0840573,0.0840573,0.0840573,0.0840573,0.0516812,0.0876824,0.305418,0.123954,0.154418,0.100453,0.0208503,0.0833223,0.0833223,0.152887,0.06484,0.0409845,0.0409845,0.0409845,0.0812131,0.0812131,0.0590756,0.134972,0.0808271,0.239621,0.181496,0.030505,0.0468422,0.0468422,0.166997,0.0602604,0.149413,0.142284,0.142284,0.49772,0.497223,0.507355,0.0853519,0.0825406,0.068665,0.068665,0.068665,0.068665,0.144292,0.144292,0.0802345,0.0701473,0.0701473,0.0701473,0.0494423,0.0494423,0.108464,0.24456,0.590184,0.156378,0.140778,0.140778", "policy/hidden_size": "64,256,512,512,512,1024,1024,1024,256,256,256,256,256,1024,512,512,512,512,512,512,512,256,512,512,128,256,256,256,256,512,256,256,256,256,256,256,512,512,512,256,256,256,512,512,512,512,512,1024,256,256,256,256,256,256,256,1024,1024,1024,1024,512,512,512,512,512,256,256,1024,1024,1024,1024,512,512,512,512,512,512,512,512,1024,1024,1024,1024,128,512,1024,1024,1024,128,128,256,256,128,128,256,256,512,512,256,128,256,256,128,128,128,128,64,512,1024,256,256,512,512,512,512,512,64,512,1024,1024,1024,1024,1024,1024,512,512,512,512,512,512,512,512,512,128,64,128,512,64,512,256,128,128,1024,256,512,512,512,1024,1024,1024,64,512,512,1024,64,512,512,256,512,256,512,512,64,64,1024,1024,512,256,256,256,256,256,256,512,1024,1024,1024,512,512,512,256,128,512,512,512", "policy/num_layers": "1.91927,4.36565,4.97329,4.97329,4.97329,6.44769,4.41942,4.41942,5.30006,5.30006,5.03084,5.03084,5.03084,5.05273,4.23627,4.23627,4.23627,4.23627,2.46345,5.03735,5.03735,4.655,5.02466,5.02466,1,4.04163,4.04163,4.04163,3.83829,4.66104,4.46975,4.46975,4.46975,4.46975,3.52747,3.52747,5.37914,5.20681,5.20681,2.29376,2.29376,2.29376,5.1062,5.1062,5.1062,5.1062,5.29163,5.57939,3.31431,3.31431,4.38804,4.38804,4.38804,4.38804,4.38804,5.45151,5.18691,5.18691,5.18691,6.00827,6.00827,6.00827,6.00827,6.00827,5.11763,3.05226,5.48279,5.48279,5.48279,5.48279,4.76252,4.76252,5.46436,5.46436,5.46436,5.46436,4.44262,4.44262,5.37067,5.37067,5.37067,5.37067,1,5.46027,7.4652,7.4652,5.02406,5.73391,5.73391,4.13073,4.13073,3.76494,3.76494,5.22387,5.22387,4.14345,4.14345,2.26138,3.82036,5.33972,5.33972,5.32993,5.09564,5.09564,5.09564,4.52635,4.60511,5.18456,5.20142,5.20142,5.92759,5.92759,5.92759,5.92759,5.92759,3.78456,4.8665,4.54796,4.54796,4.66427,4.66427,4.66427,4.66427,5.10006,5.10006,5.10006,5.10006,4.92229,4.27564,4.27564,4.27564,4.27564,7.07574,5.3599,4.75785,5.53247,1,3.30017,1.61716,2.58751,2.58751,7.38458,4.04137,4.52126,4.52126,4.52126,4.30495,4.30495,5.48079,1,3.21222,4.73885,2.20375,5.89011,4.42913,4.42913,4.26143,5.48232,3.40922,4.11886,4.11886,6.84858,4.46567,5.36748,5.171,6.66755,4.97998,4.97998,4.97998,4.97998,5.20352,5.20352,3.90938,5.3063,5.3063,5.3063,5.52915,5.52915,4.54002,5.94636,4.78705,5.9198,3.68983,3.68983", "policy/expansion_factor": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "rnn/input_size": "256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256", "rnn/hidden_size": "256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256,256", "legacy/torch_deterministic": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "legacy/cpu_offload": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "legacy/compile": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "legacy/compile_fullgraph": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "train/gpus": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "train/seed": "42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42", "train/total_timesteps": "200,200,200,200,200,306.16,440.483,440.483,330.053,330.053,242.702,242.702,242.702,354.462,293.674,293.674,293.674,293.674,200,219.09,219.09,200,200,200,202.989,232.012,232.012,232.012,244.911,332.705,217.644,217.644,217.644,217.644,200,200,200,454.715,454.715,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,282.752,217.748,217.748,217.748,200,200,200,200,200,291.889,200,367.665,367.665,367.665,367.665,200,200,267.768,267.768,267.768,267.768,356.851,356.851,269.948,269.948,269.948,269.948,200,423.192,232.869,232.869,285.405,200,200,410.567,410.567,200,200,200,200,239.194,239.194,200,242.132,223.963,223.963,200,200,200,200,200,318.043,464.121,277.856,277.856,200,200,200,200,200,200,212.981,200,200,253.694,253.694,253.694,253.694,200,200,200,200,399.828,353.408,353.408,353.408,353.408,239.2,201.067,200,300.818,200,367.761,200,200,200,233.377,200,259.574,259.574,259.574,342.892,342.892,200,200,200,200,200,200,200,200,200,342.899,200.84,200,200,200,200,200,400.302,270.401,238.177,238.177,238.177,238.177,200,200,206.607,354.974,354.974,354.974,549.93,549.93,305.953,200,200,385.607,200,200", "train/learning_rate": "0.00245323,0.0105272,0.0135035,0.0135035,0.0135035,0.0139164,0.00747599,0.00747599,0.00463284,0.00463284,0.00676115,0.00676115,0.00676115,0.00572409,0.00907492,0.00907492,0.00907492,0.00907492,0.0198324,0.00854159,0.00854159,0.00672009,0.00418122,0.00418122,0.0156677,0.00996798,0.00996798,0.00996798,0.00368577,0.00821418,0.00802749,0.00802749,0.00802749,0.00802749,0.00707955,0.00707955,0.00816603,0.00659001,0.00659001,0.00373182,0.00373182,0.00373182,0.00756089,0.00756089,0.00756089,0.00756089,0.00582229,0.0964716,0.0054597,0.0054597,0.0173818,0.0173818,0.0173818,0.0173818,0.0173818,0.00738587,0.00776602,0.00776602,0.00776602,0.00813861,0.00813861,0.00813861,0.00813861,0.00813861,0.0058701,0.0203585,0.00388554,0.00388554,0.00388554,0.00388554,0.00832763,0.00832763,0.00551772,0.00551772,0.00551772,0.00551772,0.00917997,0.00917997,0.00496821,0.00496821,0.00496821,0.00496821,0.00210187,0.00641836,0.0151083,0.0151083,0.00971446,0.0254085,0.0254085,0.00336925,0.00336925,0.01146,0.01146,0.00441574,0.00441574,0.00695656,0.00695656,0.1,0.00601837,0.0192644,0.0192644,0.0119983,0.00507026,0.00507026,0.00507026,0.000781618,0.00789247,0.00437277,0.00882125,0.00882125,0.0118505,0.0118505,0.0118505,0.0118505,0.0118505,0.00115979,0.00665964,0.0051784,0.0051784,0.00813175,0.00813175,0.00813175,0.00813175,0.00512243,0.00512243,0.00512243,0.00512243,0.00564033,0.00399243,0.00399243,0.00399243,0.00399243,0.0276047,0.00159251,0.00668136,0.00980738,0.00310396,0.00777188,0.0154848,0.0149857,0.0149857,0.1,0.007537,0.00745196,0.00745196,0.00745196,0.00596336,0.00596336,0.0056642,0.0018302,0.0139434,0.0337414,0.1,0.00253346,0.0132456,0.0132456,0.0471223,0.0182455,0.00705155,0.00738366,0.00738366,0.00169772,0.00107516,0.0312022,0.00626872,0.00954259,0.00857292,0.00857292,0.00857292,0.00857292,0.00752179,0.00752179,0.00638983,0.00610656,0.00610656,0.00610656,0.0083491,0.0083491,0.00470609,0.00535597,0.00113635,0.0192576,0.0119968,0.0119968", "train/anneal_lr": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "train/min_lr_ratio": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "train/gamma": "0.8,0.8,0.8,0.8,0.8,0.919386,0.860609,0.860609,0.933799,0.933799,0.94189,0.94189,0.94189,0.8,0.859789,0.859789,0.859789,0.859789,0.978993,0.90035,0.90035,0.956237,0.987795,0.987795,0.983638,0.874524,0.874524,0.874524,0.882137,0.966854,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.905571,0.905571,0.905571,0.8,0.8,0.8,0.8,0.863148,0.8,0.8,0.8,0.916267,0.916267,0.916267,0.916267,0.916267,0.8,0.839247,0.839247,0.839247,0.845294,0.845294,0.845294,0.845294,0.845294,0.958943,0.995857,0.874657,0.874657,0.874657,0.874657,0.8,0.8,0.89571,0.89571,0.89571,0.89571,0.806196,0.806196,0.918765,0.918765,0.918765,0.918765,0.93829,0.871134,0.822588,0.822588,0.887287,0.8,0.8,0.915996,0.915996,0.984597,0.984597,0.949673,0.949673,0.926986,0.926986,0.998622,0.980512,0.913445,0.913445,0.8,0.864396,0.864396,0.864396,0.960035,0.885399,0.905129,0.866949,0.866949,0.8,0.8,0.8,0.8,0.8,0.94775,0.8,0.928851,0.928851,0.887093,0.887093,0.887093,0.887093,0.8,0.8,0.8,0.8,0.899313,0.866159,0.866159,0.866159,0.866159,0.928738,0.910829,0.98012,0.935659,0.965532,0.829411,0.957276,0.956849,0.956849,0.984728,0.8,0.86884,0.86884,0.86884,0.8,0.8,0.8,0.8,0.997927,0.995527,0.989902,0.829311,0.907769,0.907769,0.966616,0.8,0.898603,0.8,0.8,0.817572,0.861732,0.998657,0.8,0.8,0.837591,0.837591,0.837591,0.837591,0.8,0.8,0.8,0.885598,0.885598,0.885598,0.818807,0.818807,0.949957,0.956104,0.878287,0.884881,0.927958,0.927958", "train/gae_lambda": "0.989255,0.762019,0.921439,0.921439,0.921439,0.2,0.489559,0.489559,0.259602,0.259602,0.610214,0.610214,0.610214,0.706224,0.332427,0.332427,0.332427,0.332427,0.748718,0.396829,0.396829,0.224954,0.740208,0.740208,0.995,0.523261,0.523261,0.523261,0.655458,0.338009,0.778632,0.778632,0.778632,0.778632,0.736139,0.736139,0.2,0.83127,0.83127,0.2,0.2,0.2,0.4674,0.4674,0.4674,0.4674,0.249558,0.978824,0.2,0.2,0.2,0.2,0.2,0.2,0.2,0.758261,0.732922,0.732922,0.732922,0.762137,0.762137,0.762137,0.762137,0.762137,0.79578,0.2,0.386879,0.386879,0.386879,0.386879,0.755537,0.755537,0.2,0.2,0.2,0.2,0.697343,0.697343,0.2,0.2,0.2,0.2,0.995,0.2,0.2,0.2,0.462301,0.2,0.2,0.2,0.2,0.2,0.2,0.504979,0.504979,0.2,0.2,0.203409,0.2,0.2,0.2,0.51293,0.398717,0.398717,0.398717,0.986509,0.2,0.810265,0.73438,0.73438,0.771486,0.771486,0.771486,0.771486,0.771486,0.995,0.810805,0.2,0.2,0.220741,0.220741,0.220741,0.220741,0.644231,0.644231,0.644231,0.644231,0.439875,0.626936,0.626936,0.626936,0.626936,0.964039,0.957007,0.2,0.2,0.994344,0.469168,0.995,0.2,0.2,0.872399,0.660469,0.391734,0.391734,0.391734,0.548515,0.548515,0.2,0.992157,0.2,0.849676,0.923965,0.946376,0.2,0.2,0.2,0.779873,0.653224,0.2,0.2,0.995,0.987726,0.892887,0.571301,0.586816,0.473256,0.473256,0.473256,0.473256,0.2,0.2,0.495259,0.610828,0.610828,0.610828,0.654492,0.654492,0.532278,0.309834,0.995,0.294198,0.294072,0.294072", "train/replay_ratio": "4,0.84161,2.28345,2.28345,2.28345,3.76159,1.99064,1.99064,3.09268,3.09268,2.95192,2.95192,2.95192,4,2.77635,2.77635,2.77635,2.77635,1.64087,3.05948,3.05948,1.42095,3.57334,3.57334,3.88843,0.987604,0.987604,0.987604,3.11289,4,2.20219,2.20219,2.20219,2.20219,1.85284,1.85284,2.54587,2.5752,2.5752,3.57985,3.57985,3.57985,2.63115,2.63115,2.63115,2.63115,1.74317,2.53465,2.46991,2.46991,1.72913,1.72913,1.72913,1.72913,1.72913,3.84933,2.92856,2.92856,2.92856,4,4,4,4,4,3.74799,1.22966,3.93793,3.93793,3.93793,3.93793,1.46978,1.46978,1.78841,1.78841,1.78841,1.78841,2.00875,2.00875,4,4,4,4,4,3.70331,3.85979,3.85979,3.1795,1.8554,1.8554,2.25757,2.25757,0.607965,0.607965,2.78147,2.78147,4,4,3.48681,1.51822,1.62325,1.62325,1.87661,2.19121,2.19121,2.19121,4,4,3.0185,3.34072,3.34072,3.04155,3.04155,3.04155,3.04155,3.04155,2.92994,1.54653,4,4,3.17204,3.17204,3.17204,3.17204,2.50494,2.50494,2.50494,2.50494,2.80601,2.26954,2.26954,2.26954,2.26954,3.07261,3.84742,2.2119,3.72131,3.66272,2.19855,2.68647,1.41352,1.41352,1.56354,3.42201,3.523,3.523,3.523,4,4,3.39493,4,1.30264,1.38461,3.75269,2.60279,3.552,3.552,0.807166,3.46254,3.82915,1.08743,1.08743,2.94419,4,1.85958,3.21645,4,3.42734,3.42734,3.42734,3.42734,2.3573,2.3573,3.08125,3.69338,3.69338,3.69338,3.04465,3.04465,3.85535,1.85702,4,3.20338,1.6233,1.6233", "train/clip_coef": "1,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.160727,0.0195384,0.0195384,0.0195384,0.0195384,0.01,0.01,0.01,0.129703,0.0760472,0.0760472,0.95222,0.01,0.01,0.01,0.01,0.0934374,0.01,0.01,0.01,0.01,0.122669,0.122669,0.0371378,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.0497799,0.01,0.01,0.01,0.0760946,0.0760946,0.0760946,0.0760946,0.0760946,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.237704,0.0922248,0.01,0.01,0.01,0.01,0.0858162,0.0858162,0.01,0.01,0.01,0.01,0.020568,0.020568,0.0389039,0.0389039,0.0389039,0.0389039,0.878867,0.01,0.0758188,0.0758188,0.01,0.011226,0.011226,0.025751,0.025751,0.01,0.01,0.0598456,0.0598456,0.0395194,0.0395194,0.140463,0.101907,0.0323405,0.0323405,0.148508,0.01,0.01,0.01,1,0.01,0.0310136,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.638563,0.01,0.01,0.01,0.047155,0.047155,0.047155,0.047155,0.0538519,0.0538519,0.0538519,0.0538519,0.0340972,0.01,0.01,0.01,0.01,0.448926,0.71928,0.151704,0.01,0.90295,0.01,0.660663,0.128416,0.128416,0.01,0.01,0.0901317,0.0901317,0.0901317,0.01,0.01,0.097008,0.868897,0.01,0.161139,0.217639,0.812209,0.01,0.01,0.0599156,0.0153598,0.0375942,0.118268,0.118268,0.667408,1,0.0647028,0.114322,0.01,0.01,0.01,0.01,0.01,0.238814,0.238814,0.01,0.01,0.01,0.01,0.0705161,0.0705161,0.0228187,0.0500345,0.930355,0.0166303,0.193838,0.193838", "train/vf_coef": "3.66195,4.67779,4.32179,4.32179,4.32179,4.46379,5,5,5,5,5,5,5,4.33406,5,5,5,5,5,5,5,4.81248,5,5,4.71957,4.83406,4.83406,4.83406,4.82182,5,5,5,5,5,5,5,5,5,5,4.91415,4.91415,4.91415,5,5,5,5,4.50183,4.17266,5,5,5,5,5,5,5,5,4.49578,4.49578,4.49578,5,5,5,5,5,5,5,4.44392,4.44392,4.44392,4.44392,4.83439,4.83439,5,5,5,5,5,5,4.98916,4.98916,4.98916,4.98916,4.55998,3.53705,5,5,5,4.86866,4.86866,4.28071,4.28071,5,5,4.64701,4.64701,5,5,5,4.46182,5,5,5,5,5,5,3.5646,4.27159,5,5,5,4.15752,4.15752,4.15752,4.15752,4.15752,3.93952,4.48537,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,4.76911,5,4.68141,5,4.14084,5,4.43639,5,5,5,5,5,5,5,5,5,5,3.84991,5,4.50644,3.74477,2.95783,5,5,5,5,5,5,5,4.37941,2.8983,5,4.30487,5,5,5,5,5,4.25957,4.25957,4.85583,5,5,5,3.95328,3.95328,4.48458,5,4.71177,5,5,5", "train/vf_clip_coef": "0.01,2.72664,2.60584,2.60584,2.60584,2.2423,0.846705,0.846705,1.76407,1.76407,1.86543,1.86543,1.86543,1.87016,1.67406,1.67406,1.67406,1.67406,2.16959,3.07756,3.07756,1.92047,1.81663,1.81663,0.964492,1.57934,1.57934,1.57934,1.76149,2.59519,1.95898,1.95898,1.95898,1.95898,2.5701,2.5701,2.39884,2.36277,2.36277,2.81724,2.81724,2.81724,2.12884,2.12884,2.12884,2.12884,2.14756,3.77639,1.34637,1.34637,2.40284,2.40284,2.40284,2.40284,2.40284,2.84914,2.81642,2.81642,2.81642,3.01337,3.01337,3.01337,3.01337,3.01337,2.60774,2.13999,3.36601,3.36601,3.36601,3.36601,2.72986,2.72986,1.19287,1.19287,1.19287,1.19287,2.09848,2.09848,3.02317,3.02317,3.02317,3.02317,0.01,1.83205,3.18614,3.18614,3.20736,2.75938,2.75938,1.60225,1.60225,2.17569,2.17569,3.20237,3.20237,2.08443,2.08443,2.87578,1.97156,2.37613,2.37613,2.57601,2.55741,2.55741,2.55741,0.01,1.78759,2.60353,2.66379,2.66379,1.75303,1.75303,1.75303,1.75303,1.75303,1.39991,0.96666,2.23001,2.23001,2.84943,2.84943,2.84943,2.84943,1.99066,1.99066,1.99066,1.99066,1.72703,1.67435,1.67435,1.67435,1.67435,4.57132,2.81492,2.34023,3.70818,1.22109,1.47653,0.01,1.64299,1.64299,2.55139,2.00154,2.78327,2.78327,2.78327,2.49414,2.49414,2.75444,0.01,1.68485,2.50351,3.17514,0.01,2.27604,2.27604,1.98441,2.31681,1.86533,3.41165,3.41165,0.940968,1.67872,1.66181,2.32282,3.18457,0.764673,0.764673,0.764673,0.764673,2.78096,2.78096,2.63493,2.909,2.909,2.909,2.55633,2.55633,4.30841,2.68547,0.21404,2.21185,2.64087,2.64087", "train/max_grad_norm": "1.46255,0.1,1.36206,1.36206,1.36206,0.429518,2.11528,2.11528,3.80679,3.80679,1.96735,1.96735,1.96735,1.16454,2.76314,2.76314,2.76314,2.76314,1.72159,2.25186,2.25186,1.41114,0.1,0.1,0.1,0.111448,0.111448,0.111448,2.97358,0.1,4.07692,4.07692,4.07692,4.07692,3.01686,3.01686,1.07366,4.18596,4.18596,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,2.42933,3.47066,3.47066,0.474288,0.474288,0.474288,0.474288,0.474288,4.33758,0.810988,0.810988,0.810988,2.45314,2.45314,2.45314,2.45314,2.45314,3.46716,2.0798,3.24959,3.24959,3.24959,3.24959,3.35466,3.35466,2.21317,2.21317,2.21317,2.21317,3.33709,3.33709,0.481756,0.481756,0.481756,0.481756,0.212528,4.81494,2.83788,2.83788,2.01407,0.1,0.1,3.49934,3.49934,0.914628,0.914628,4.56914,4.56914,1.64044,1.64044,0.1,1.34315,0.438278,0.438278,1.01485,1.15251,1.15251,1.15251,1.65062,2.95002,3.80478,5,5,1.21695,1.21695,1.21695,1.21695,1.21695,0.409348,5,0.1,0.1,0.587729,0.587729,0.587729,0.587729,4.29657,4.29657,4.29657,4.29657,3.04584,2.4943,2.4943,2.4943,2.4943,1.23697,0.1,1.40564,0.132961,0.114064,2.00115,0.1,2.96286,2.96286,0.1,0.867616,0.1,0.1,0.1,4.39361,4.39361,0.943789,0.838778,0.862792,0.187179,0.1,0.44487,0.1,0.1,1.96532,2.44085,2.65785,4.27608,4.27608,0.549335,0.503932,0.1,3.05211,1.03346,2.36649,2.36649,2.36649,2.36649,2.74426,2.74426,0.1,3.94569,3.94569,3.94569,4.53721,4.53721,2.62972,3.57615,1.20932,3.92827,0.1,0.1", "train/ent_coef": "0.2,0.0638806,0.00147635,0.00147635,0.00147635,0.00137729,0.00229346,0.00229346,0.00449388,0.00449388,0.0250883,0.0250883,0.0250883,0.000410767,7.37083e-05,7.37083e-05,7.37083e-05,7.37083e-05,0.0534721,0.000206325,0.000206325,0.2,0.013016,0.013016,0.2,0.0131066,0.0131066,0.0131066,0.000120986,0.000305068,0.000789749,0.000789749,0.000789749,0.000789749,0.0131717,0.0131717,0.0199218,9.54343e-05,9.54343e-05,0.00501609,0.00501609,0.00501609,0.000459804,0.000459804,0.000459804,0.000459804,0.0087958,0.2,0.00422283,0.00422283,0.0825449,0.0825449,0.0825449,0.0825449,0.0825449,0.0161071,0.00532054,0.00532054,0.00532054,0.00218659,0.00218659,0.00218659,0.00218659,0.00218659,0.00843381,0.2,0.000320162,0.000320162,0.000320162,0.000320162,0.00998642,0.00998642,0.0079761,0.0079761,0.0079761,0.0079761,0.00014518,0.00014518,0.00200034,0.00200034,0.00200034,0.00200034,0.2,0.000519136,0.000194338,0.000194338,0.000178022,0.000651056,0.000651056,0.0368478,0.0368478,0.0116532,0.0116532,0.00180999,0.00180999,0.000591397,0.000591397,0.0325307,0.0419752,0.0242029,0.0242029,0.2,0.0111138,0.0111138,0.0111138,0.2,0.00187696,0.0172335,0.000323863,0.000323863,0.000494848,0.000494848,0.000494848,0.000494848,0.000494848,0.163714,0.000179612,0.00916099,0.00916099,0.000896862,0.000896862,0.000896862,0.000896862,0.000269774,0.000269774,0.000269774,0.000269774,0.00122492,0.00969576,0.00969576,0.00969576,0.00969576,0.0006129,0.2,0.00448188,0.00167678,0.18303,0.00196145,0.2,0.072224,0.072224,0.102226,0.00232542,0.000252994,0.000252994,0.000252994,0.00136287,0.00136287,9.49747e-05,0.2,0.0237891,0.0360685,0.2,0.193459,0.00398614,0.00398614,0.0749195,0.00199083,0.000261902,0.00139436,0.00139436,0.2,0.2,0.0121005,0.000684558,0.000358147,0.00294118,0.00294118,0.00294118,0.00294118,0.00426708,0.00426708,0.0170973,0.00158666,0.00158666,0.00158666,5.78581e-05,5.78581e-05,0.00328621,0.000271882,0.2,0.00225282,0.0914973,0.0914973", "train/beta1": "0.98135,0.713059,0.846495,0.846495,0.846495,0.917455,0.956806,0.956806,0.968373,0.968373,0.938006,0.938006,0.938006,0.946958,0.948124,0.948124,0.948124,0.948124,0.946236,0.960227,0.960227,0.874983,0.885736,0.885736,0.998187,0.920885,0.920885,0.920885,0.968473,0.862174,0.964207,0.964207,0.964207,0.964207,0.898517,0.898517,0.735961,0.91831,0.91831,0.990702,0.990702,0.990702,0.942926,0.942926,0.942926,0.942926,0.92853,0.883419,0.961874,0.961874,0.891519,0.891519,0.891519,0.891519,0.891519,0.950697,0.702449,0.702449,0.702449,0.793349,0.793349,0.793349,0.793349,0.793349,0.916147,0.949905,0.835975,0.835975,0.835975,0.835975,0.948584,0.948584,0.965804,0.965804,0.965804,0.965804,0.942637,0.942637,0.953184,0.953184,0.953184,0.953184,0.987481,0.965515,0.597921,0.597921,0.911148,0.5,0.5,0.97999,0.97999,0.947441,0.947441,0.988728,0.988728,0.912029,0.912029,0.731795,0.965566,0.714743,0.714743,0.893549,0.915486,0.915486,0.915486,0.995614,0.793158,0.932219,0.924289,0.924289,0.729513,0.729513,0.729513,0.729513,0.729513,0.990721,0.957555,0.944766,0.944766,0.933839,0.933839,0.933839,0.933839,0.96445,0.96445,0.96445,0.96445,0.940083,0.976056,0.976056,0.976056,0.976056,0.994911,0.976324,0.959209,0.792371,0.994464,0.943316,0.987263,0.863597,0.863597,0.5,0.77694,0.885948,0.885948,0.885948,0.945683,0.945683,0.730782,0.996848,0.995857,0.5,0.975006,0.746395,0.86348,0.86348,0.989998,0.777985,0.919638,0.953354,0.953354,0.926977,0.994024,0.982243,0.93655,0.852478,0.796111,0.796111,0.796111,0.796111,0.957325,0.957325,0.982332,0.948551,0.948551,0.948551,0.897772,0.897772,0.912506,0.952415,0.997369,0.618029,0.840647,0.840647", "train/beta2": "0.998755,0.999966,0.99998,0.99998,0.99998,0.999939,0.999825,0.999825,0.999977,0.999977,0.999955,0.999955,0.999955,0.99999,0.99999,0.99999,0.99999,0.99999,0.999986,0.99999,0.99999,0.99999,0.99999,0.99999,0.999943,0.99999,0.99999,0.99999,0.99999,0.999988,0.999976,0.999976,0.999976,0.999976,0.99999,0.99999,0.99999,0.99999,0.99999,0.99999,0.99999,0.99999,0.999982,0.999982,0.999982,0.999982,0.99998,0.99999,0.999957,0.999957,0.999975,0.999975,0.999975,0.999975,0.999975,0.999963,0.99999,0.99999,0.99999,0.99999,0.99999,0.99999,0.99999,0.99999,0.999978,0.99999,0.99999,0.99999,0.99999,0.99999,0.99999,0.99999,0.999389,0.999389,0.999389,0.999389,0.99999,0.99999,0.99999,0.99999,0.99999,0.99999,0.99987,0.999917,0.999964,0.999964,0.999985,0.999988,0.999988,0.999985,0.999985,0.999989,0.999989,0.999974,0.999974,0.999981,0.999981,0.999756,0.999933,0.99999,0.99999,0.999978,0.999941,0.999941,0.999941,0.963024,0.999836,0.99999,0.999973,0.999973,0.99999,0.99999,0.99999,0.99999,0.99999,0.984682,0.99998,0.99999,0.99999,0.999982,0.999982,0.999982,0.999982,0.999953,0.999953,0.999953,0.999953,0.999902,0.999886,0.999886,0.999886,0.999886,0.999931,0.995701,0.99999,0.99999,0.999392,0.99984,0.998482,0.999944,0.999944,0.99999,0.999963,0.99999,0.99999,0.99999,0.999983,0.999983,0.99999,0.9998,0.999985,0.999962,0.999973,0.9,0.99999,0.99999,0.999982,0.999911,0.999874,0.99999,0.99999,0.9,0.999113,0.999974,0.99999,0.999939,0.999936,0.999936,0.999936,0.999936,0.99999,0.99999,0.99999,0.99999,0.99999,0.99999,0.999971,0.999971,0.99999,0.99999,0.999911,0.99999,0.99999,0.99999", "train/eps": "6.3722e-05,3.81751e-06,1.14788e-07,1.14788e-07,1.14788e-07,3.26944e-07,0.0001,0.0001,0.0001,0.0001,6.08529e-06,6.08529e-06,6.08529e-06,3.76331e-09,0.0001,0.0001,0.0001,0.0001,0.0001,1.48553e-06,1.48553e-06,0.0001,1.3404e-10,1.3404e-10,8.91907e-08,0.0001,0.0001,0.0001,4.77362e-07,1.99144e-10,0.0001,0.0001,0.0001,0.0001,2.21723e-05,2.21723e-05,0.0001,1.62384e-05,1.62384e-05,3.02405e-08,3.02405e-08,3.02405e-08,5.89305e-06,5.89305e-06,5.89305e-06,5.89305e-06,0.0001,0.0001,6.9477e-07,6.9477e-07,0.0001,0.0001,0.0001,0.0001,0.0001,0.0001,8.60465e-07,8.60465e-07,8.60465e-07,1.08842e-08,1.08842e-08,1.08842e-08,1.08842e-08,1.08842e-08,0.0001,1.07893e-06,3.7422e-07,3.7422e-07,3.7422e-07,3.7422e-07,3.93039e-05,3.93039e-05,0.0001,0.0001,0.0001,0.0001,0.0001,0.0001,1.8497e-08,1.8497e-08,1.8497e-08,1.8497e-08,5.0238e-09,1.35554e-08,6.65618e-08,6.65618e-08,3.74847e-08,5.08082e-05,5.08082e-05,0.0001,0.0001,8.68904e-06,8.68904e-06,3.26973e-07,3.26973e-07,3.14175e-10,3.14175e-10,0.0001,4.55041e-07,0.0001,0.0001,6.2448e-06,6.26001e-05,6.26001e-05,6.26001e-05,1.91085e-08,3.58174e-05,1.08387e-06,4.88954e-06,4.88954e-06,0.0001,0.0001,0.0001,0.0001,0.0001,3.02739e-07,6.23349e-07,2.75367e-10,2.75367e-10,2.56378e-09,2.56378e-09,2.56378e-09,2.56378e-09,1.24689e-05,1.24689e-05,1.24689e-05,1.24689e-05,0.0001,0.0001,0.0001,0.0001,0.0001,2.86589e-08,1.45112e-10,7.57855e-09,6.23185e-08,3.2479e-06,0.0001,1.17581e-09,0.0001,0.0001,3.22048e-07,1.23282e-07,1.22485e-09,1.22485e-09,1.22485e-09,2.50027e-08,2.50027e-08,9.26871e-07,1.16969e-07,1.34866e-06,1.15597e-06,1.63427e-06,1.99787e-05,1.45834e-07,1.45834e-07,0.0001,3.38577e-06,1.44823e-05,5.76552e-06,5.76552e-06,3.17756e-07,5.38272e-06,1.08284e-06,1.95206e-09,4.22344e-09,3.66791e-05,3.66791e-05,3.66791e-05,3.66791e-05,1.23097e-06,1.23097e-06,1.59072e-08,1.06734e-07,1.06734e-07,1.06734e-07,1.65589e-07,1.65589e-07,4.98485e-07,0.0001,1.95781e-07,1.09483e-05,2.07579e-06,2.07579e-06", "train/minibatch_size": "8192,16384,8192,8192,8192,8192,8192,8192,16384,16384,16384,16384,16384,16384,16384,16384,16384,16384,16384,8192,8192,16384,8192,8192,32768,16384,16384,16384,16384,8192,16384,16384,16384,16384,4096,4096,8192,16384,16384,16384,16384,16384,8192,8192,8192,8192,16384,8192,16384,16384,16384,16384,16384,16384,16384,16384,4096,4096,4096,8192,8192,8192,8192,8192,8192,32768,8192,8192,8192,8192,8192,8192,16384,16384,16384,16384,16384,16384,16384,16384,16384,16384,16384,16384,4096,4096,8192,8192,8192,16384,16384,8192,8192,16384,16384,8192,8192,32768,8192,8192,8192,8192,8192,8192,8192,8192,8192,16384,16384,16384,4096,4096,4096,4096,4096,8192,16384,8192,8192,8192,8192,8192,8192,16384,16384,16384,16384,16384,16384,16384,16384,16384,32768,8192,8192,8192,8192,16384,16384,8192,8192,4096,4096,16384,16384,16384,16384,16384,4096,16384,16384,8192,8192,8192,4096,4096,8192,8192,16384,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,16384,16384,16384,16384,16384,16384,8192,16384,8192,8192,16384,16384", "train/horizon": "512,256,256,256,256,1024,256,256,128,128,128,128,128,512,256,256,256,256,128,128,128,256,256,256,256,128,128,128,256,256,256,256,256,256,128,128,32,256,256,256,256,256,128,128,128,128,256,1024,256,256,128,128,128,128,128,256,256,256,256,256,256,256,256,256,256,512,512,512,512,512,128,128,256,256,256,256,256,256,512,512,512,512,128,512,512,512,256,128,128,256,256,256,256,256,256,256,256,1024,256,128,128,128,128,128,128,512,128,512,512,512,128,128,128,128,128,512,256,512,512,1024,1024,1024,1024,256,256,256,256,128,256,256,256,256,128,512,128,512,256,256,256,128,128,512,64,512,512,512,256,256,64,256,1024,256,512,512,64,64,256,256,256,512,512,512,512,1024,256,1024,128,128,128,128,256,256,256,256,256,256,256,256,512,512,512,256,256,256", "train/vtrace_rho_clip": "1.41872,2.4635,0.683282,0.683282,0.683282,1.89093,2.89909,2.89909,2.11487,2.11487,4.18248,4.18248,4.18248,1.40276,2.72538,2.72538,2.72538,2.72538,1.31498,2.34615,2.34615,1.88493,1.40587,1.40587,2.53386,1.10838,1.10838,1.10838,3.08992,1.30777,3.75625,3.75625,3.75625,3.75625,2.46735,2.46735,2.42811,2.23362,2.23362,2.45637,2.45637,2.45637,0.705457,0.705457,0.705457,0.705457,2.47781,1.45864,3.24713,3.24713,0.684991,0.684991,0.684991,0.684991,0.684991,1.30035,1.66106,1.66106,1.66106,1.60707,1.60707,1.60707,1.60707,1.60707,1.34934,1.36401,1.21174,1.21174,1.21174,1.21174,1.68864,1.68864,4.24942,4.24942,4.24942,4.24942,3.28024,3.28024,2.0182,2.0182,2.0182,2.0182,2.0104,2.27819,1.76848,1.76848,1.23196,1.5122,1.5122,4.43932,4.43932,1.49577,1.49577,4.97989,4.97989,1.05488,1.05488,0.1,2.37096,2.03401,2.03401,2.33118,4.45088,4.45088,4.45088,2.27256,2.22599,0.370387,2.58904,2.58904,0.678,0.678,0.678,0.678,0.678,1.94401,3.75403,1.55122,1.55122,2.05111,2.05111,2.05111,2.05111,4.68658,4.68658,4.68658,4.68658,2.4382,3.65263,3.65263,3.65263,3.65263,1.19804,2.35369,1.95524,1.71571,2.15569,2.78531,3.00714,0.593619,0.593619,0.1,0.1,1.03467,1.03467,1.03467,1.30316,1.30316,0.1,2.02318,1.52602,0.62184,0.191903,2.76139,0.1,0.1,0.1,0.764635,4.42772,2.63371,2.63371,2.61176,1.47153,0.1,0.754958,2.18539,5,5,5,5,1.40089,1.40089,1.40541,1.49811,1.49811,1.49811,2.87579,2.87579,2.03312,2.18934,2.04064,2.24416,1.62617,1.62617", "train/vtrace_c_clip": "1.51381,0.1,2.66224,2.66224,2.66224,1.43292,3.55611,3.55611,2.3105,2.3105,2.00981,2.00981,2.00981,2.76124,1.64765,1.64765,1.64765,1.64765,1.42154,0.1,0.1,1.91895,1.41001,1.41001,0.337322,0.594928,0.594928,0.594928,1.40484,0.764401,1.92939,1.92939,1.92939,1.92939,2.42969,2.42969,2.45208,3.73403,3.73403,1.90779,1.90779,1.90779,4.76048,4.76048,4.76048,4.76048,1.86768,0.733854,1.88496,1.88496,1.03026,1.03026,1.03026,1.03026,1.03026,3.40922,4.15545,4.15545,4.15545,1.1682,1.1682,1.1682,1.1682,1.1682,0.325168,0.320435,2.29454,2.29454,2.29454,2.29454,2.67268,2.67268,2.12831,2.12831,2.12831,2.12831,2.80812,2.80812,1.89726,1.89726,1.89726,1.89726,0.579177,3.10587,2.86466,2.86466,1.17973,3.11411,3.11411,3.27245,3.27245,0.207974,0.207974,2.44986,2.44986,2.97633,2.97633,1.29278,0.1,0.918926,0.918926,1.48602,1.99538,1.99538,1.99538,2.3134,2.63941,2.20787,4.51222,4.51222,4.29879,4.29879,4.29879,4.29879,4.29879,1.88174,1.59713,2.59568,2.59568,1.8457,1.8457,1.8457,1.8457,2.03057,2.03057,2.03057,2.03057,2.04047,2.64812,2.64812,2.64812,2.64812,1.7181,1.705,0.1,2.98848,1.78739,1.68574,1.17494,0.1,0.1,1.84465,4.89774,1.06281,1.06281,1.06281,2.00886,2.00886,4.39419,0.464105,1.20926,0.1,1.29712,2.5821,3.86213,3.86213,0.751459,1.13267,2.92835,1.3029,1.3029,0.688734,1.36935,1.12742,1.0377,2.27027,2.9552,2.9552,2.9552,2.9552,1.59631,1.59631,1.15863,1.32928,1.32928,1.32928,4.11645,4.11645,0.405514,2.6231,1.78131,1.63798,1.73828,1.73828", "train/prio_alpha": "0,0.854451,0.88957,0.88957,0.88957,0.524766,0.776055,0.776055,1,1,0.480981,0.480981,0.480981,1,0.712793,0.712793,0.712793,0.712793,1,0.679695,0.679695,0.775811,0.860013,0.860013,0,0.693949,0.693949,0.693949,1,0.909146,1,1,1,1,0.858227,0.858227,0.677894,0.868014,0.868014,0.788274,0.788274,0.788274,0.83549,0.83549,0.83549,0.83549,0.634551,1,0.692701,0.692701,1,1,1,1,1,0.214945,0.785876,0.785876,0.785876,1,1,1,1,1,0.996836,0.80975,0.418731,0.418731,0.418731,0.418731,0.725697,0.725697,0.451327,0.451327,0.451327,0.451327,0.949764,0.949764,0.758375,0.758375,0.758375,0.758375,0,0.69203,0.511672,0.511672,0.773623,0.478265,0.478265,0.888316,0.888316,0.579865,0.579865,0.976742,0.976742,0.590367,0.590367,0.554087,0.791612,0.609468,0.609468,0.635866,0.429913,0.429913,0.429913,0.109713,0.539568,0.448041,1,1,0.58749,0.58749,0.58749,0.58749,0.58749,0,0.816303,0.864476,0.864476,0.813976,0.813976,0.813976,0.813976,0.80544,0.80544,0.80544,0.80544,0.866011,0.646051,0.646051,0.646051,0.646051,0.658189,0.0531408,0.702417,0.769485,0.43649,0.773201,0.311648,1,1,0.694369,0.866284,0.633459,0.633459,0.633459,0.646772,0.646772,1,0.218332,0.89487,0.955491,0.932433,0.201052,1,1,0.858251,0.687854,0.584188,1,1,0,0,0.897415,0.882243,0.942139,0.522265,0.522265,0.522265,0.522265,1,1,0.806372,0.64519,0.64519,0.64519,0.930354,0.930354,0.599336,1,0,0.845597,0.812644,0.812644", "train/prio_beta0": "0.329888,0.219228,0.928197,0.928197,0.928197,0.934153,0.765727,0.765727,1,1,0.971698,0.971698,0.971698,0.949655,0.794562,0.794562,0.794562,0.794562,0.688431,1,1,0.481273,0.560534,0.560534,0.470939,0.105367,0.105367,0.105367,1,1,0.949811,0.949811,0.949811,0.949811,0.567786,0.567786,0.48333,0.894992,0.894992,0.888504,0.888504,0.888504,0.703232,0.703232,0.703232,0.703232,0.22688,0.895056,0.918366,0.918366,0.260439,0.260439,0.260439,0.260439,0.260439,0.785287,1,1,1,1,1,1,1,1,0.696276,0.881787,0.674999,0.674999,0.674999,0.674999,0.719559,0.719559,0.676252,0.676252,0.676252,0.676252,0.729729,0.729729,0.776021,0.776021,0.776021,0.776021,0.883031,0.996876,0.751823,0.751823,0.917735,0,0,0.844071,0.844071,0.331905,0.331905,0.748986,0.748986,0.558781,0.558781,0.534779,0.359301,0.316476,0.316476,0.232886,0.999733,0.999733,0.999733,0.625707,1,0.893083,0.824483,0.824483,0.744487,0.744487,0.744487,0.744487,0.744487,0.562596,0.71934,0.576437,0.576437,0.79011,0.79011,0.79011,0.79011,1,1,1,1,0.592322,0.747119,0.747119,0.747119,0.747119,0.139913,0.653231,0.240379,0.904188,0.459084,0.872328,0.818191,0.717679,0.717679,0.497106,0.928904,0.661025,0.661025,0.661025,0.430048,0.430048,0.982736,0.491609,0.818043,0.675832,0.681655,0.918174,1,1,0.813875,0.981922,0.912224,0.661096,0.661096,0.237741,0.317449,0.377191,0.865559,0.608353,1,1,1,1,0.570601,0.570601,0.744361,0.877644,0.877644,0.877644,1,1,0.439893,0.95077,0.153732,0.945918,0.41234,0.41234", "train/adam_beta1": "0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231,0.879231", "train/adam_beta2": "0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046,0.998046", "train/adam_eps": "6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06,6.00018e-06", "train/use_rnn": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "no_model_upload": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "tsne1": "20.4029,34.6335,39.413,39.4129,39.4127,32.7739,33.819,33.819,29.116,29.116,31.3555,31.3566,31.3561,37.79,32.4954,32.4956,32.4956,32.4962,10.5998,33.4078,33.408,31.6079,18.865,18.865,19.3868,33.8982,33.8982,33.8982,35.4757,34.7687,36.188,36.188,36.188,36.1879,38.7364,38.7364,34.5121,37.9163,37.9163,33.3969,33.3969,33.3969,40.7475,40.7486,40.7475,40.7475,33.8115,38.7845,30.6403,30.6403,32.2132,32.2132,32.2132,32.2132,32.2132,35.9257,40.9679,40.9679,40.9679,37.2559,37.2558,37.2558,37.2559,37.2559,11.3489,30.3982,33.5355,33.5356,33.5355,33.5355,38.3614,38.3614,29.8554,29.8554,29.8554,29.8554,37.0145,37.0155,33.1027,33.1024,33.1027,33.1024,19.4067,30.7094,32.0105,32.0105,34.8215,36.4853,36.4853,28.8124,28.8124,30.8957,30.8957,27.4612,27.4615,31.604,31.6054,32.1968,30.6828,33.2302,33.2303,34.8669,31.1104,31.1104,31.1109,19.5208,31.1229,35.1235,38.9282,38.9282,41.6576,41.6576,41.6576,41.6576,41.6576,19.2842,36.7689,32.117,32.1161,33.4358,33.4358,33.4358,33.4358,36.0528,36.0528,36.0528,36.0528,32.598,33.0469,33.0469,33.0469,33.0469,17.5445,19.1265,30.6176,33.9888,19.3375,33.0991,19.3273,29.9191,29.9191,-22.5902,40.8476,34.9469,34.9469,34.9469,36.3871,36.3871,39.0924,20.5493,30.5001,-22.6081,18.4199,21.2453,38.0679,38.0679,30.1875,38.1403,32.7258,28.7017,28.7017,21.2643,20.0966,18.4319,37.1616,37.2691,32.8326,32.8326,32.8326,32.8326,29.1119,29.1122,36.0168,35.0466,35.0466,35.0466,38.3043,38.3043,33.7895,28.8764,20.0663,31.3006,32.3928,32.3928", "tsne2": "-21.8129,38.5123,52.8542,52.8545,52.8532,48.4145,58.6379,58.6379,56.3204,56.3204,60.8644,60.8642,60.8644,51.7624,56.9293,56.9286,56.9286,56.9287,30.0393,54.3212,54.3212,41.0377,53.7687,53.7687,-23.4033,38.9057,38.9057,38.9057,58.9998,47.8498,59.9929,59.993,59.9929,59.9929,57.1001,57.1001,41.3583,60.0066,60.0066,46.3686,46.3686,46.3686,50.1678,50.1679,50.1678,50.1678,40.5651,54.2203,56.869,56.869,40.1909,40.1909,40.1909,40.1909,40.1909,55.855,52.6768,52.6768,52.6768,52.8794,52.8795,52.8794,52.8796,52.8794,31.3445,41.7833,52.231,52.2307,52.231,52.231,57.2884,57.2885,58.8108,58.8108,58.8108,58.8108,59.7014,59.7048,47.4002,47.3998,47.4002,47.3998,-23.4654,55.6184,51.5184,51.5184,52.9982,41.0701,41.0701,58.0108,58.0108,39.6546,39.6546,60.6786,60.6783,48.1932,48.1945,42.5016,39.5225,40.7881,40.7882,38.8123,62.1394,62.1394,62.1391,-22.4245,54.9721,54.9709,60.5584,60.5583,51.6372,51.6373,51.6373,51.6373,51.6373,-22.4565,61.1328,47.3416,47.3411,48.286,48.286,48.286,48.286,60.9079,60.9079,60.9079,60.9079,57.7428,59.4618,59.4622,59.4622,59.4618,37.2991,-22.4431,39.2274,47.2076,-22.597,58.3579,-23.741,40.7173,40.7173,-47.3873,51.2678,49.2649,49.2649,49.2649,55.3531,55.3531,48.4309,-21.8806,41.8927,-47.4098,54.4487,-20.4015,47.597,47.597,40.9126,53.3577,61.0106,53.7663,53.7663,-20.663,-21.9815,54.4686,53.7277,51.5412,62.1044,62.1043,62.1044,62.1043,53.083,53.0837,50.0316,54.6066,54.6066,54.6066,60.6254,60.6254,52.9704,56.3789,-21.9638,54.7859,41.1934,41.1934"}, "tetris": {"SPS": "2.53278e+06,1.64067e+06,5.32491e+06,5.23638e+06,5.2382e+06,5.23599e+06,5.23829e+06,5.22962e+06,4.55741e+06,7.64936e+06,6.58708e+06,4.919e+06,7.48858e+06,7.17176e+06,6.87572e+06,6.86653e+06,5.28488e+06,5.27786e+06,1.20306e+06,4.53642e+06,421371,6.33726e+06,1.89627e+06,4.96934e+06,6.07062e+06,4.43742e+06,4.28857e+06,4.29113e+06,4.37491e+06,3.31338e+06,3.08012e+06,3.0752e+06,3.0725e+06,3.07385e+06,3.07089e+06,3.08917e+06,8.84082e+06,8.74459e+06,3.05452e+06,3.04384e+06,3.03827e+06,3.02688e+06,3.06334e+06,3.10668e+06,3.14027e+06,3.14319e+06,4.57612e+06,4.38522e+06,3.55741e+06,3.586e+06,1.37331e+06,3.42228e+06,1.80805e+06,1.82336e+06,1.78267e+06,1.85787e+06,1.80923e+06,1.86338e+06,8.05465e+06,8.04787e+06,5.08424e+06,5.00182e+06,4.98143e+06,4.99121e+06,4.98054e+06,4.99539e+06,5.01467e+06,6.18471e+06,2.43568e+06,2.39387e+06,2.41489e+06,5.62436e+06,928428,1.08705e+06,4.54922e+06,3.55713e+06,5.78135e+06,1.36063e+06,1.358e+06,1.35765e+06,1.35627e+06,1.35448e+06,1.35635e+06,1.3562e+06,1.34729e+06,4.87275e+06,3.87323e+06,3.72486e+06,3.61872e+06,3.59181e+06,3.73654e+06,3.86119e+06,4.61147e+06,4.62384e+06,4.3886e+06,4.45766e+06,4.47808e+06,3.07708e+06,3.44966e+06,7.23632e+06,7.23271e+06,7.23721e+06,7.24892e+06,7.2574e+06,3.872e+06,3.86239e+06,3.84403e+06,3.85085e+06,3.84122e+06,3.83503e+06,3.8564e+06,3.68168e+06,4.32538e+06,2.31026e+06,2.2494e+06,2.3111e+06,2.31417e+06,2.2809e+06,3.17012e+06,6.78759e+06,6.77574e+06,5.34345e+06,4.79993e+06,4.73639e+06,4.7551e+06,4.89041e+06,4.87827e+06,4.83772e+06,4.81848e+06,1.07065e+06,2.77115e+06,9.18593e+06,4.88664e+06,4.88723e+06,7.20406e+06,7.16249e+06,7.15971e+06,7.16052e+06,7.29216e+06,5.77211e+06,2.71186e+06,2.69823e+06,5.41533e+06,5.84936e+06,1.34451e+06,1.34531e+06,1.34533e+06,1.34561e+06,2.13876e+06,2.1123e+06,2.10751e+06,2.20673e+06,2.19731e+06,2.17531e+06,2.09696e+06,2.09498e+06,2.09092e+06,3.74832e+06,3.9155e+06,3.75938e+06,3.8442e+06,3.45925e+06,3.46471e+06,3.67314e+06,3.94852e+06,3.94051e+06,3.95575e+06,7.23581e+06,3.46069e+06,4.17656e+06,5.0318e+06,5.42136e+06,5.41001e+06,5.40342e+06,5.39875e+06,5.47932e+06,5.31658e+06,5.33193e+06,5.51721e+06,5.37041e+06,5.36211e+06,5.90469e+06,5.96473e+06,2.22294e+06,2.12806e+06,2.15103e+06,3.21891e+06,6.14273e+06,2.7329e+06,2.72452e+06,2.72546e+06,2.72179e+06,2.67701e+06,2.62496e+06,5.03715e+06,5.03766e+06,5.19974e+06,5.14197e+06,5.14393e+06,5.13986e+06,2.49825e+06,2.54528e+06,2.54382e+06,2.47571e+06,6.61424e+06,6.40512e+06,1.24009e+06,4.63672e+06,5.61938e+06,5.35956e+06,5.18334e+06,2.06015e+06,7.66163e+06,7.43381e+06,7.3757e+06,7.38739e+06,7.36436e+06,7.36612e+06,5.28862e+06,4.55257e+06,4.99381e+06,3.16706e+06,4.45272e+06,2.00661e+06,1.99977e+06,5.12105e+06,5.11938e+06,2.72845e+06,4.14857e+06,799243,798222,797764,796520,799485,6.91995e+06,6.63788e+06,6.63846e+06,6.64717e+06,5.76893e+06,1.60419e+06,1.26356e+06,1.30934e+06,6.45022e+06,1.54602e+06,5.8702e+06", "agent_steps": "1327.5,383.779,115.737,181.797,214.827,247.857,280.887,297.271,74.4489,19.7919,6.29146,32.768,24.9037,26.6076,397.345,450.298,367.395,434.11,27.1319,19.2676,4.45645,3.14573,366.477,13.697,279.708,6.02931,339.739,384.958,407.503,2.62144,109.314,133.562,157.811,182.059,206.176,218.104,27.0008,80.6093,519.045,666.894,814.744,1110.44,1257.24,261.751,301.99,342.098,14.8111,46.3995,1371.54,1639.97,6.35699,41.0583,501.219,834.666,2168.46,2501.9,2834.3,2998.93,63.3733,105.513,62.1281,86.9007,111.739,136.577,161.35,490.34,565.707,18.7433,2167.93,2501.38,2834.3,7.73325,5.24288,5.50502,20.9715,503.316,560.988,515.899,717.226,918.553,1119.88,1321.21,1522.53,1723.86,1820.33,10.6168,140.444,171.639,202.834,234.029,265.224,280.756,548.405,767.558,986.71,1204.81,1643.12,503.316,21.6269,96.2068,134.611,173.015,211.419,249.823,7.73325,53.6084,68.9439,84.2138,99.4836,114.819,130.089,68.5507,18.3501,637.534,818.938,1181.75,1363.15,1633.68,28.3116,168.821,206.307,581.698,59.8344,83.6895,107.61,131.531,155.386,179.241,203.096,5.50502,46.3995,14.1558,394.658,455.344,454.296,536.871,619.446,701.891,742.916,34.3409,404.75,633.34,72.745,14.4179,838.861,2504,2835.35,2994.73,385.352,641.729,898.105,1154.74,1411.38,1667.76,1924.14,2180.51,2308.44,1.04858,2.62144,4.1943,5.76717,421.396,497.943,12.6484,626,764.412,902.824,23.1997,30.2121,501.219,6.48806,494.928,692.584,890.241,1087.9,1285.55,1483.21,1680.87,10.6168,115.737,136.774,152.175,369.361,13.5332,40.534,67.5021,16.384,11.6654,452.985,549.454,650.117,750.78,847.249,889.192,52.4288,87.1629,83.1652,359.858,415.171,470.483,215.876,255.066,294.257,333.447,40.2391,120.586,5.76717,31.5884,5.11181,7.99539,86.1143,308.281,60.9485,101.319,141.82,182.321,222.822,263.324,396.689,43.1882,28.9669,7.99539,79.233,391.643,652.214,579.6,668.729,19.5297,18.3173,836.764,2170.55,2504,2835.35,2998.93,240.386,284.033,327.68,371.327,392.954,1.80224,1.83501,5.24288,19.8574,500.695,60.7519", "uptime": "521.487,232.146,21.4914,34.0715,40.3801,46.6882,52.9964,56.1248,16.1408,2.62567,0.96832,6.69574,3.37027,3.76098,57.2771,65.081,68.8784,81.5129,22.5227,4.2956,10.6043,0.500835,195.367,2.78015,46.2498,1.39252,82.8272,93.3697,98.6261,0.80042,35.3019,43.1823,51.0737,58.9632,66.8115,70.6967,3.06889,9.19748,171.844,220.209,268.922,366.188,414.349,84.0406,96.9732,109.74,3.32425,10.5596,383.146,458.494,4.75168,11.9663,276.733,458.908,1184.82,1367.84,1549.09,1640.27,7.94577,13.219,12.0815,17.0151,21.9937,26.9821,31.9563,98.0079,113.092,3.05229,889.867,1027.22,1164.96,1.38851,5.66879,5.11841,4.65433,140.179,97.0029,378.507,526.616,674.837,823.269,971.8,1120.35,1268.78,1339.92,2.21512,35.7368,43.9796,52.5687,61.2189,69.7839,73.9062,120.939,168.462,217.062,266.75,362.921,161.275,6.31368,13.3456,18.6636,23.9809,29.2878,34.588,2.02763,13.8755,17.8648,21.8421,25.8236,29.8327,33.8684,18.5435,4.25192,282.678,361.89,523.465,601.878,719.074,9.05821,24.7021,30.2346,106.537,12.4382,17.4432,22.5118,27.46,32.3472,37.2652,42.2506,5.35713,16.6898,1.56709,80.4481,92.8775,62.0543,73.5806,85.1166,96.6367,102.366,5.97724,152.275,237.288,13.1914,2.47914,628.691,1867.26,2113.59,2232.06,178.271,299.406,420.853,540.27,657.488,774.118,894.702,1017.09,1078.15,0.284375,0.688072,1.10056,1.5147,121.631,143.745,3.51231,158.765,193.88,228.919,3.76276,8.88749,118.661,1.51046,90.6322,127.154,163.746,200.369,236.806,273.517,310.682,1.97893,21.0728,25.0013,25.6014,62.493,6.11752,18.5943,31.6238,5.1268,1.91291,166.168,201.558,238.54,275.532,311.104,326.916,10.4242,17.3234,15.815,69.4928,80.2503,91.0085,84.8503,100.466,115.864,131.489,6.08592,18.4555,4.8316,6.80163,1.06736,1.50895,16.1613,148.219,7.9211,13.2922,18.7719,24.2647,29.7618,35.2615,79.113,9.51127,5.80179,2.64832,17.7424,192.992,322.978,111.581,128.99,7.18624,4.45365,1045.35,2715.62,3133.43,3549.24,3754.51,35.6707,42.1508,48.7459,55.329,58.593,1.18601,1.52054,4.13055,3.14541,322.715,10.3918", "epoch": "633,366,441.5,693.5,819.5,945.5,1071.5,1134,568,151,6,250,47.5,203,3031.5,3435.5,1401.5,1656,207,73.5,8.5,3,349.5,104.5,533.5,23,2592,2937,3109,2.5,417,509.5,602,694.5,786.5,832,103,307.5,247.5,318,388.5,529.5,599.5,998.5,1152,1305,56.5,177,327,391,48.5,626.5,239,398,1034,1193,1351.5,1430,483.5,805,474,663,852.5,1042,1231,3741,4316,71.5,2067.5,2385.5,2703,59,40,10.5,160,120,1070,61.5,85.5,109.5,133.5,157.5,181.5,205.5,217,81,1071.5,1309.5,1547.5,1785.5,2023.5,2142,261.5,366,470.5,574.5,783.5,120,165,367,513.5,660,806.5,953,59,409,526,642.5,759,876,992.5,261.5,70,304,390.5,563.5,650,779,108,644,787,1109.5,456.5,638.5,821,1003.5,1185.5,1367.5,1549.5,10.5,177,54,1505.5,1737,1733,2048,2363,2677.5,2834,131,193,302,277.5,55,100,298.5,338,357,735,1224,1713,2202.5,2692,3181,3670,4159,4403,2,5,8,11,1607.5,1899.5,96.5,298.5,364.5,430.5,177,230.5,239,49.5,944,1321,1698,2075,2452,2829,3206,81,883,1043.5,580.5,1409,206.5,618.5,1030,62.5,44.5,54,65.5,77.5,89.5,101,106,200,332.5,634.5,2745.5,3167.5,3589.5,1647,1946,2245,2544,307,920,11,241,39,30.5,328.5,588,232.5,386.5,541,695.5,850,1004.5,3026.5,329.5,110.5,122,604.5,373.5,622,1105.5,1275.5,74.5,279.5,199.5,517.5,597,676,715,917,1083.5,1250,1416.5,1499,27.5,7,20,303,477.5,463.5", "env/perf": "0.776302,0.29033,0.13107,0.168851,0.178531,0.18486,0.188245,0.188895,0.0814403,0.00394675,0.000577588,0.0139851,0.00486862,0.00526585,0.190724,0.193203,0.189411,0.196251,0.015442,0.00621888,0.000630296,0.000351565,0.224895,0.00352523,0.179712,0.000591539,0.196382,0.199907,0.200898,0.000350733,0.151226,0.164142,0.173258,0.180515,0.183995,0.184575,0.00845757,0.0668126,0.295113,0.427418,0.534462,0.657924,0.68181,0.192067,0.198607,0.201905,0.00355448,0.0439355,0.701001,0.743765,0.000729714,0.0410406,0.412284,0.600762,1.06259,1.12447,1.15825,1.16647,0.0370626,0.0775858,0.0683477,0.114567,0.135521,0.148943,0.160028,0.202351,0.206534,0.00463303,1.01137,1.08374,1.11569,0.00103716,0.00103557,0.000696649,0.00906718,0.22557,0.201651,0.442537,0.621939,0.75359,0.864761,0.96153,1.04667,1.10529,1.11624,0.00284353,0.159886,0.173247,0.183754,0.188783,0.19144,0.191653,0.216124,0.336904,0.448779,0.54221,0.662069,0.284348,0.0110079,0.0955977,0.131952,0.149629,0.160786,0.169132,0.00176103,0.0796803,0.112794,0.131081,0.141196,0.148117,0.150959,0.0846251,0.00471982,0.457915,0.586761,0.806801,0.883332,0.928196,0.0185257,0.147618,0.15849,0.203756,0.0564846,0.121305,0.144209,0.157005,0.16628,0.173683,0.177619,0.000755615,0.0496841,0.00214628,0.193586,0.19709,0.195075,0.201341,0.206094,0.207728,0.208167,0.0131252,0.229256,0.402361,0.0743699,0.00335684,0.68566,1.15622,1.19233,1.19746,0.363269,0.576744,0.723622,0.83376,0.922785,0.995092,1.04589,1.07005,1.07393,0.000323194,0.000383693,0.000524615,0.000608608,0.206311,0.212023,0.00383323,0.292779,0.37928,0.441232,0.0101491,0.021675,0.209654,0.00152399,0.196837,0.287669,0.389339,0.477165,0.554573,0.613684,0.639002,0.00220648,0.135664,0.14743,0.147706,0.18968,0.00438793,0.0481192,0.104444,0.00468816,0.00292779,0.283281,0.392416,0.501779,0.583558,0.628119,0.640306,0.0491622,0.120757,0.0833162,0.191461,0.196078,0.199132,0.184256,0.193328,0.197934,0.201073,0.035305,0.126218,0.000768108,0.0262915,0.000434076,0.00211068,0.0852806,0.202718,0.0361725,0.11061,0.139715,0.157033,0.165979,0.172053,0.192106,0.0435374,0.0123393,0.00277001,0.0913102,0.364785,0.582931,0.22356,0.239835,0.00894017,0.0059115,0.633654,1.11944,1.18457,1.21195,1.21651,0.169507,0.180195,0.188314,0.190608,0.191556,0.000351007,0.000554915,0.000662634,0.00467154,0.404017,0.0461379", "env/score": "52703.1,19710.5,8898.36,11463.3,12120.4,12550.1,12780,12824,5528.99,267.945,39.2124,949.449,330.531,357.499,12948.3,13116.5,12859.1,13323.5,1048.36,422.2,42.7908,23.8679,15268.1,239.328,12200.6,40.1596,13332.4,13571.7,13639,23.8112,10266.7,11143.6,11762.5,12255.2,12491.4,12530.8,574.185,4535.91,20035.2,29017.4,36284.6,44666.5,46288.1,13039.5,13483.4,13707.3,241.314,2982.78,47591,50494,49.5402,2786.24,27990,40785.7,72139.5,76340.4,78633.3,79191.6,2516.18,5267.3,4640.12,7777.98,9200.49,10111.8,10864.3,13737.6,14021.6,314.536,68661.6,73575,75744.5,70.4129,70.305,47.2955,615.571,15313.9,13690.1,30043.9,42223.5,51161.2,58708.6,65278.3,71058.5,75038.1,75781.5,193.047,10854.7,11761.7,12475.1,12816.5,12996.8,13011.3,14672.7,22872.4,30467.6,36810.6,44947.8,19304.4,747.324,6490.13,8958.24,10158.3,10915.7,11482.4,119.557,5409.5,7657.56,8899.11,9585.79,10055.7,10248.6,5745.2,320.429,31087.9,39835.2,54773.7,59969.4,63015.2,1257.71,10021.8,10759.9,13833,3834.74,8235.37,9790.36,10659,11288.7,11791.3,12058.5,51.2987,3373.05,145.711,13142.5,13380.5,13243.6,13669,13991.7,14102.7,14132.5,891.069,15564.2,27316.3,5048.97,227.896,46549.4,78496,80947.4,81295.9,24662.3,39155.1,49126.7,56604,62647.9,67556.8,71005.2,72645.8,72909.2,21.9416,26.0489,35.6161,41.3184,14006.5,14394.2,260.238,19876.8,25749.3,29955.2,689.021,1471.52,14233.4,103.463,13363.3,19529.8,26432.3,32394.8,37650,41663,43381.8,149.798,9210.21,10009,10027.7,12877.4,297.897,3266.81,7090.71,318.279,198.767,19231.9,26641.1,34065.7,39617.8,42643,43470.4,3337.62,8198.22,5656.34,12998.3,13311.7,13519.1,12509.1,13125.1,13437.7,13650.9,2396.85,8568.97,52.1469,1784.93,29.4694,143.294,5789.7,13762.5,2455.75,7509.3,9485.28,10660.9,11268.3,11680.7,13042.1,2955.75,837.716,188.056,6199.05,24765.3,39575.2,15177.5,16282.4,606.948,401.331,43018.8,75999.1,80420.3,82279.1,82589.1,11507.8,12233.4,12784.6,12940.4,13004.8,23.8298,37.6732,44.9862,317.151,27428.7,3132.3", "env/episode_return": "296.966,114.929,42.4314,50.9061,53.1765,54.7423,55.5414,55.5608,30.73,7.19184,3.20466,10.9165,8.50214,8.70071,60.346,60.9667,52.4011,54.5605,12.2823,8.57715,3.69214,1.4873,75.9675,7.85605,56.6327,3.54304,59.8783,60.7314,60.992,1.72548,51.0363,54.5443,56.9115,58.6039,59.4512,59.6254,9.11255,28.0588,111.797,157.065,194.088,238.168,246.895,61.7371,63.4417,64.3551,7.67406,20.4293,220.268,234.795,4.05059,19.6503,154.637,219.836,389.523,413.411,426.989,430.574,18.6876,28.9345,27.9934,41.171,46.7404,50.5064,53.6296,61.8908,63.2274,8.09783,381.417,410.192,423.476,5.30192,4.56121,4.04514,9.34565,83.7396,63.6384,159.597,223.74,273.232,316.605,354.725,388.428,411.285,416.216,7.26615,53.004,56.365,59.0303,60.3707,61.0312,61.0113,85.1106,124.5,161.289,191.409,230.568,106.965,10.6217,34.9179,44.5349,48.5914,51.117,53.5746,6.35603,31.6057,40.6168,45.5053,48.164,49.9292,50.7236,34.1179,8.44333,166.019,211.322,290.455,318.834,335.894,12.7936,45.1513,48.1708,62.6801,24.2893,41.4067,47.0298,50.168,52.3253,54.1193,55.2335,4.0174,22.7398,6.57999,60.0168,61.0545,59.1595,60.8117,61.9383,62.5089,62.5314,11.4484,89.2329,151.467,29.141,7.7831,249.12,443.787,458.132,460.664,132.307,208.883,265.057,308.72,345.4,375.212,395.136,405.288,406.959,1.48478,2.0083,2.75649,3.28503,65.5692,67.0707,7.45054,115.215,146.814,169.637,9.45434,13.4168,78.8432,6.24537,73.7778,104.034,138.966,169.62,197.14,218.171,227.138,6.72856,43.5155,46.5485,46.6632,57.6213,8.36146,21.374,37.2095,8.29358,6.56017,100.115,135.728,172.228,199.986,215.478,219.703,21.6445,41.3017,30.8627,58.7493,60.1359,61.1999,54.2608,56.8871,58.3996,59.4164,17.0607,39.6426,4.63689,15.6227,2.72046,6.59659,34.6176,75.6096,17.9964,36.6629,43.2893,47.5945,49.9099,51.584,60.6047,20.1299,11.2776,6.88643,35.2506,136.246,218.352,86.422,91.6457,10.5757,8.59697,204.481,388.382,413.676,424.858,427.178,50.7343,53.6469,55.8053,56.701,56.9083,1.53321,3.38724,6.7703,8.54616,147.722,21.4188", "env/episode_length": "3872.88,1603.45,723.397,827.677,857.637,879.3,890.784,891.331,632.81,248.025,102.704,265.178,323.573,317.636,979.449,988.501,898.48,926.557,429.038,283.662,75.1298,54.8303,1300.02,319.499,916.718,119.88,980.033,991.843,996.222,42.06,862.284,911.307,945.427,966.233,977.165,978.054,281.425,561.579,1668.61,2282.73,2787.26,3377.58,3494.99,1012.88,1035.45,1048.16,281.843,529.407,3528.12,3740.68,290.874,526.7,2215.87,3086.79,5328.6,5645.76,5822.3,5870.54,519.829,577.341,557.084,705.711,769.972,811.96,852.661,1018.6,1037.01,286.184,5000.52,5355.93,5517.13,211.003,123.973,128.007,307.633,1279.6,1038.55,2281.22,3116.08,3744.89,4290.68,4769.92,5195.15,5482.41,5538.47,266.055,860.951,909.854,950.826,973.781,982.53,982.568,1288.07,1839.99,2372.47,2804.12,3376.96,1568.08,402.99,625.805,746.773,808.725,850.259,886.041,270.804,662.991,727.691,751.889,784.997,811.956,823.696,678.09,331.309,2399.65,3000.76,4066,4448.55,4670.94,382.904,797.707,838.533,1026.91,532.168,712.629,787.937,829.894,858.78,886.059,902.518,153.56,552.46,254.41,987.533,1002.52,963.562,992.268,1010.12,1020.31,1021.45,352.11,1309.2,2105.22,606.321,316.106,3419.05,5714,5885.85,5910.57,1883.04,2865.01,3554.46,4079.55,4511.62,4863.67,5106.73,5224.78,5243.91,38.3521,48.9112,83.4041,119.267,1061.06,1085.16,241.931,1594.08,1988.99,2281.85,262.035,364.394,1229.24,256.749,1113.9,1535.84,1999.39,2401.11,2753.29,3018.52,3123.76,249.776,756.423,790.861,813.709,964.059,334.046,519.623,717.467,324.739,188.975,1591.63,2094.59,2607.05,2991.52,3203.46,3260.57,480.54,725.496,594.371,972.838,993.397,1007.78,918.63,950.862,968.071,981.027,436.744,719.78,99.9312,487.462,204.098,257.635,712.529,1166.09,545.124,647.686,712.062,765.16,792.333,820.215,989.809,481.559,379.204,234.451,638.845,1883.13,2875.19,1244.76,1322.54,451.958,328.872,3227.8,5526.61,5847.75,5986.17,6013.48,863.052,900.285,926.714,937.065,939.514,49.625,182.217,475.492,359.665,2111.78,531.009", "env/lines_deleted": "415.781,154.552,54.4359,69.3982,73.4039,76.0502,77.413,77.4764,38.5111,1.84046,0.0158323,7.07776,2.37827,2.61018,86.0289,87.0375,76.3754,80.2941,7.78671,3.12172,0.0440658,0,119.215,1.65054,78.5317,0.0110103,86.052,87.5646,88.0528,0.000166476,68.4611,74.8217,79.0525,82.3336,83.8566,84.1179,4.18757,32.4435,157.506,227.856,285.404,352.809,365.994,89.5923,92.646,94.2165,1.64462,19.7476,373.23,397.814,0.129133,19.3545,220.584,320.949,574.687,609.808,629.48,634.716,17.8727,36.6371,31.3363,52.0239,61.3855,67.8493,73.0998,91.8975,94.046,2.26374,542.756,582.818,601.233,0.255996,0.222396,0.0442358,4.49718,117.139,92.9804,232.666,328.139,399.292,460.612,514.603,562.789,595.821,602.664,1.27126,72.7524,79.0618,83.9229,86.3911,87.5862,87.6038,117.079,181.637,241.65,290.937,355.896,150.695,5.60745,45.0787,61.0567,68.5394,73.5736,77.785,0.652957,36.6442,51.1873,59.4005,63.8092,66.8768,68.0174,41.3785,2.31932,242.166,311.222,431.597,474.44,499.85,9.09588,64.7901,69.9404,91.6798,25.9453,53.5822,63.4082,69.1569,73.0468,76.1359,78.0176,0.0386799,24.046,0.880921,88.6464,90.4911,85.1285,88.3079,90.346,91.3613,91.4767,6.51086,118.852,209.342,34.059,1.55828,363.194,624.311,644.975,648.292,190.417,303.762,382.726,442.65,491.511,531.353,559.119,572.981,575.291,0,0.000137823,0.00205247,0.011807,95.6422,98.5157,1.84863,153.373,199.327,232.673,5.12525,10.7824,110.72,0.527221,101.794,148.701,201.794,248.386,289.62,321.309,334.57,0.901934,57.8668,63.198,64.0994,84.3326,2.13658,23.5346,50.6532,2.26198,1.31102,150.512,207.727,265.884,310.312,335.018,341.765,22.9203,54.6492,38.3126,87.489,89.8609,91.397,77.6392,82.0301,84.694,86.3139,16.7894,56.7713,0.0516685,12.5488,0,0.845969,39.786,104.818,16.5762,46.0535,56.7663,63.7925,67.8311,70.8741,86.9307,19.748,6.20293,1.22909,42.1021,190.465,305.882,114.973,123.153,4.43401,3.11705,338.671,602.89,640.29,656.681,659.831,71.487,76.5396,80.0735,81.4333,81.71,0,0.0208721,0.101522,2.28698,214.17,22.1284", "env/avg_combo": "1.27886,1.28368,1.76013,1.79957,1.80221,1.80488,1.80823,1.81549,1.57111,1.06799,1.00007,1.19776,1.08298,1.08242,1.62911,1.63187,1.88211,1.84877,1.19725,1.08931,1.0003,1,1.28637,1.06248,1.67129,1.00012,1.66351,1.66636,1.6643,1,1.61316,1.60124,1.59812,1.6007,1.60303,1.60238,1.12595,1.45404,1.27916,1.28583,1.2839,1.27613,1.27423,1.57445,1.57505,1.57463,1.05773,1.3069,1.28835,1.27959,1.00102,1.36323,1.27699,1.28365,1.25953,1.25455,1.25065,1.24834,1.43904,1.56905,1.52812,1.59854,1.61353,1.60924,1.60785,1.61358,1.60994,1.06784,1.27372,1.26955,1.26567,1.00268,1.00135,1.00053,1.17079,1.32545,1.58641,1.31166,1.30561,1.29741,1.28735,1.27823,1.26937,1.26434,1.26127,1.03233,1.60896,1.60808,1.6071,1.60345,1.60468,1.6068,1.2456,1.26013,1.26518,1.27316,1.27035,1.29239,1.14905,1.52534,1.58094,1.60516,1.6102,1.6025,1.00764,1.57201,1.62467,1.63284,1.64171,1.64486,1.64931,1.43884,1.06946,1.30087,1.29696,1.28119,1.27347,1.26816,1.19394,1.66891,1.66303,1.6255,1.47149,1.65157,1.67036,1.67096,1.67808,1.68561,1.68481,1.00037,1.28952,1.01529,1.60785,1.60571,1.67481,1.66632,1.667,1.66183,1.66345,1.17939,1.33226,1.33206,1.5189,1.04179,1.29689,1.26012,1.25664,1.25518,1.31291,1.30707,1.29953,1.29195,1.28542,1.28047,1.27816,1.27517,1.27441,1,1,1,1.00017,1.58253,1.58076,1.03399,1.31606,1.31214,1.30699,1.14077,1.22158,1.2947,1.01097,1.32986,1.3344,1.33285,1.3271,1.32226,1.31749,1.31783,1.02541,1.71274,1.70673,1.68206,1.65014,1.05988,1.36879,1.47075,1.0852,1.02546,1.28629,1.29628,1.29655,1.28974,1.2839,1.28262,1.41268,1.62118,1.54074,1.6052,1.6001,1.59645,1.76993,1.75688,1.73619,1.73061,1.30245,1.64231,1.0004,1.28208,1,1.01924,1.54769,1.3371,1.40143,1.7489,1.81095,1.81955,1.81547,1.79478,1.62,1.35878,1.17946,1.01437,1.55663,1.31645,1.31001,1.34696,1.35049,1.12585,1.0613,1.27786,1.2633,1.25661,1.25239,1.25059,1.74484,1.73202,1.72975,1.72273,1.72461,1,1.00019,1.00042,1.07597,1.29361,1.43672", "env/atn_frac_soft_drop": "0.000142886,0.00344007,5.32994e-06,8.28553e-07,6.78078e-07,3.60126e-07,2.9397e-07,0,0.00335453,0.00876239,0.0546832,0.00129726,0.00434002,0.00160111,5.49902e-07,6.88854e-07,0.0030484,0.00378491,0.00277615,0.00322241,0.0227221,0.130998,8.97194e-05,0.00237367,1.08045e-06,0.0404477,1.01431e-06,1.02124e-06,5.01719e-07,0.112097,0.00102583,0.000380399,0.000271018,0.000270604,0.000188405,0.000186399,0.00546104,0.0073911,2.39424e-05,4.53517e-06,1.46413e-06,4.33832e-07,3.94285e-07,0.000285625,0.000188524,0.000241194,0.00285418,0.00218085,0.000182148,7.3206e-05,0.00481394,0.000593626,2.10817e-05,1.42838e-06,6.58052e-08,3.43716e-08,4.33107e-08,5.10595e-08,8.19785e-06,1.15605e-06,0.0143257,0.0166692,0.0167183,0.012816,0.0107716,2.69108e-08,0,0.00472514,1.74259e-07,1.12471e-07,8.07648e-08,0.00797047,0.00609126,0.0114734,0.00173586,0.001559,6.32368e-07,0.000874919,0.000652688,0.000484716,0.000541494,0.000382553,0.000279931,0.000108573,6.54544e-05,0.00272472,2.72029e-07,1.99435e-07,3.83968e-08,8.94999e-08,8.08418e-08,0,0.0029858,0.0016685,0.00106065,0.000820536,0.000377975,0.00165489,0.00606382,3.44965e-07,7.71627e-07,2.12179e-07,7.69171e-08,1.31854e-07,0.00444066,0.00255585,0.00131528,3.84607e-05,3.45675e-05,2.78859e-05,3.11318e-05,0.000383661,0.00270486,2.17304e-06,1.0828e-06,1.35948e-07,1.05028e-07,1.59125e-07,0.00124386,1.49857e-07,4.9378e-08,8.3778e-09,3.90031e-05,3.56785e-05,1.94205e-05,9.81376e-06,8.03238e-06,3.11459e-06,3.36337e-06,0.000171833,0.00772784,0.00391548,0.000232633,8.79068e-05,7.91235e-08,7.78335e-08,4.74816e-08,3.68467e-08,9.44802e-08,0.00574515,0.00265235,0.00116234,0.00063446,0.00722087,0.000152546,9.04798e-05,3.16497e-05,1.54079e-05,0.000365164,0.000118735,9.37815e-05,6.83378e-05,4.48875e-05,3.53763e-05,1.74743e-05,8.54984e-06,9.85459e-06,0.13757,0.0855853,0.0690797,0.0501878,5.65221e-05,1.92439e-05,0.0109756,5.82684e-05,2.78863e-05,1.77843e-05,0.00719265,0.0108733,0.00206076,0.00714193,0.00289596,0.00238919,0.00189009,0.00150118,0.000947112,0.000424549,0.000304823,0.00395266,3.48309e-07,2.21046e-07,2.28087e-05,0.000118322,0.00177813,0.000309696,0.00163056,0.00887046,0.0104463,0.00257593,0.00183628,0.00134616,0.000892326,0.000617203,0.000545385,0.00294317,0.00314308,0.00825343,0.00597533,0.00553589,0.00534673,2.86082e-07,7.55036e-08,0,0,0.00157214,0.000287602,0.00018959,0.00120661,5.41609e-06,0.0146463,9.57191e-06,2.05839e-06,0.0162272,0.0317692,0.0240131,0.0198934,0.0157299,0.0147338,9.84854e-07,0.000530682,0.00307307,0.00648005,0.00182345,0.000888589,0.000339469,7.02794e-08,3.48649e-08,0.00754384,0.00336697,1.16763e-05,9.61988e-05,3.01917e-05,2.22681e-05,1.84138e-05,0.00353671,0.00353329,0.00307142,0.00308353,0.00302969,0.132761,0.0180215,0.000498913,0.00221778,4.61839e-07,0.000414641", "env/atn_frac_hard_drop": "0.250431,0.23404,0.216403,0.233359,0.236961,0.238227,0.238967,0.23902,0.184232,0.144728,0.190715,0.189323,0.119613,0.124688,0.238967,0.239146,0.233285,0.236422,0.114324,0.147099,0.34262,0.174633,0.231656,0.114946,0.234993,0.193431,0.23587,0.236588,0.236724,0.258216,0.220456,0.225223,0.227713,0.231217,0.23233,0.232881,0.153685,0.183381,0.231053,0.237935,0.241268,0.244526,0.244858,0.237144,0.238955,0.239603,0.139803,0.132161,0.247271,0.248215,0.0706551,0.131379,0.236655,0.2436,0.249698,0.249679,0.249687,0.249615,0.131461,0.197747,0.177539,0.21053,0.221245,0.22994,0.234206,0.241196,0.241642,0.128217,0.251331,0.251411,0.251506,0.144792,0.215801,0.207348,0.121015,0.230915,0.239907,0.243904,0.247714,0.249198,0.249939,0.25055,0.251058,0.25156,0.25183,0.125086,0.233487,0.23731,0.238833,0.239209,0.239853,0.239797,0.227749,0.239165,0.242422,0.244738,0.246814,0.235682,0.109542,0.213942,0.232748,0.238025,0.240486,0.242229,0.123348,0.165725,0.201095,0.223252,0.227037,0.228811,0.228624,0.181938,0.110099,0.237631,0.24252,0.246413,0.247208,0.247765,0.136287,0.230091,0.233505,0.238754,0.166788,0.220081,0.228944,0.234242,0.237393,0.238308,0.238821,0.161584,0.142292,0.132665,0.242233,0.242861,0.238969,0.239666,0.240246,0.240039,0.240067,0.127635,0.227233,0.237478,0.172824,0.10985,0.249111,0.252416,0.252957,0.253194,0.246383,0.250744,0.252185,0.252873,0.253052,0.253179,0.253368,0.253599,0.253654,0.246637,0.252901,0.197172,0.158174,0.24035,0.24097,0.153337,0.237626,0.242753,0.244417,0.172114,0.147988,0.226699,0.115702,0.239418,0.241382,0.244555,0.247088,0.249195,0.251035,0.252294,0.13468,0.220168,0.227165,0.22045,0.237097,0.104209,0.160315,0.205463,0.110167,0.172475,0.233386,0.238221,0.24149,0.243971,0.245322,0.245713,0.166238,0.217191,0.194714,0.240906,0.241315,0.241322,0.229356,0.232958,0.235816,0.236756,0.154487,0.226249,0.247657,0.116033,0.100668,0.129561,0.166011,0.234551,0.118337,0.202473,0.222519,0.23032,0.235469,0.236185,0.237335,0.143638,0.120374,0.154965,0.198871,0.244629,0.249942,0.238485,0.238243,0.0928376,0.108403,0.245901,0.251352,0.251897,0.252233,0.252264,0.22738,0.231691,0.234408,0.235266,0.235407,0.205585,0.136534,0.0385514,0.108905,0.242713,0.14646", "env/atn_frac_rotate": "0.0909578,0.103194,0.162628,0.122197,0.112897,0.111723,0.110078,0.110229,0.235435,0.351215,0.153432,0.250858,0.508452,0.500637,0.117769,0.117758,0.113657,0.109231,0.498116,0.386694,0.0953282,0.175711,0.122466,0.509564,0.129424,0.0372753,0.116407,0.11539,0.114989,0.161021,0.148348,0.139773,0.136532,0.129291,0.12721,0.126386,0.333603,0.190455,0.130618,0.116331,0.110005,0.104588,0.104138,0.116547,0.11351,0.112916,0.451074,0.430931,0.0927667,0.0929813,0.0832195,0.455323,0.120224,0.107878,0.0959217,0.0966452,0.0967442,0.097054,0.443177,0.234752,0.186735,0.128898,0.112612,0.106218,0.10287,0.111164,0.110485,0.501724,0.0879296,0.0881401,0.0885839,0.382653,0.118018,0.16053,0.507595,0.121144,0.112842,0.095382,0.0926479,0.0911064,0.0908163,0.0908772,0.0910163,0.091411,0.0916804,0.490982,0.123921,0.114996,0.112455,0.111343,0.110368,0.110306,0.11726,0.103625,0.101101,0.0985297,0.097616,0.10708,0.481386,0.200419,0.141204,0.123835,0.118435,0.112893,0.415528,0.281054,0.200426,0.155911,0.149906,0.143445,0.145607,0.287793,0.518208,0.105092,0.100319,0.0953463,0.0942448,0.0940288,0.462126,0.132617,0.124188,0.121969,0.318608,0.149811,0.127984,0.117906,0.111856,0.110276,0.109457,0.0119026,0.376116,0.421928,0.112312,0.111789,0.119214,0.116457,0.115345,0.116172,0.115872,0.428498,0.117775,0.106622,0.278987,0.515879,0.0930604,0.0895554,0.0895027,0.0897469,0.0980994,0.0902247,0.0878726,0.0868271,0.0865324,0.0864961,0.0866056,0.0865028,0.0865349,0.174336,0.174851,0.180178,0.186049,0.119002,0.119435,0.35007,0.118823,0.109501,0.10589,0.334673,0.277934,0.117414,0.478338,0.107833,0.103841,0.0989553,0.094979,0.0923775,0.0904871,0.0895158,0.449161,0.167977,0.146669,0.162654,0.122608,0.544763,0.334655,0.187399,0.487592,0.343489,0.102593,0.09928,0.0984643,0.097313,0.0969735,0.0971727,0.251522,0.131039,0.178559,0.0944892,0.0943128,0.0946522,0.143055,0.137253,0.129386,0.126764,0.390737,0.154153,0.143083,0.494607,2.31296e-05,0.431364,0.336524,0.138814,0.326761,0.120496,0.101228,0.0975242,0.094651,0.0937172,0.124273,0.38144,0.499419,0.41794,0.180198,0.0966699,0.0880073,0.124594,0.124253,0.526617,0.524636,0.0966341,0.0903056,0.0903123,0.0903677,0.0905887,0.125693,0.118669,0.115353,0.114054,0.113716,0.153073,0.154729,0.642614,0.516992,0.107012,0.365522", "env/atn_frac_hold": "0.0379633,0.052301,0.0415463,0.0372707,0.0374777,0.0370663,0.0370466,0.0368784,0.0430545,0.0511346,0.0882428,0.0543809,0.0341209,0.0323057,0.0377109,0.037277,0.0427095,0.0407459,0.0416158,0.036496,0.0354657,0.144751,0.0439242,0.0294606,0.0394879,0.0388402,0.0381477,0.0379833,0.0379061,0.102089,0.0434674,0.0423788,0.0414994,0.0399196,0.0393142,0.0390014,0.0504672,0.0734348,0.04502,0.0442015,0.0430955,0.041875,0.0414708,0.0387947,0.0375844,0.0366037,0.0327804,0.0419577,0.0386488,0.0370607,0.00191232,0.0328015,0.0458306,0.0425054,0.0397218,0.0392328,0.0392535,0.039192,0.0318887,0.0355466,0.0599936,0.050469,0.0469987,0.0452546,0.0425762,0.0381796,0.0373564,0.0313362,0.0376656,0.0378336,0.0373208,0.0190777,0.0607793,0.0337658,0.010005,0.0445297,0.0381443,0.0419654,0.0391179,0.0386391,0.038641,0.0384158,0.0385051,0.0383109,0.0377141,0.0301481,0.0411176,0.0395511,0.0386026,0.0385431,0.0380444,0.037961,0.0510723,0.0465136,0.0443864,0.0424094,0.0399143,0.0469721,0.0447407,0.0417853,0.0423928,0.042187,0.0402615,0.0403819,0.0338243,0.0431561,0.0416297,0.0411212,0.0381724,0.0370896,0.0366751,0.047011,0.0291462,0.0440992,0.0419296,0.0411085,0.0408443,0.0395558,0.0366221,0.0365569,0.0363489,0.039559,0.0436186,0.0461417,0.0430421,0.0412405,0.0400138,0.0385451,0.037856,0.000214887,0.0466337,0.0303338,0.0399408,0.0397143,0.0382594,0.0384987,0.0381299,0.0382248,0.0383608,0.0434437,0.0511556,0.0463164,0.044677,0.0429443,0.0377328,0.0367256,0.036056,0.0353973,0.041944,0.0382284,0.0370504,0.0362488,0.0360322,0.0358665,0.0355003,0.0349925,0.0347685,0.130785,0.0898604,0.0659335,0.0589882,0.0412434,0.0407501,0.04917,0.0434364,0.0413825,0.0416611,0.0399611,0.0690993,0.05184,0.030279,0.0475136,0.0459996,0.0435339,0.0419996,0.0400038,0.0384108,0.0366919,0.0307543,0.0428501,0.0427744,0.0400302,0.038645,0.0323233,0.0474808,0.0504462,0.0444732,0.0346167,0.0497911,0.0464118,0.0437928,0.0415626,0.0407305,0.0402049,0.0524717,0.0504903,0.0492677,0.0403393,0.0396338,0.0395333,0.0379517,0.0383334,0.0381434,0.0381621,0.0396672,0.040795,0.00133862,0.0388063,3.86376e-05,0.0508381,0.0426101,0.0453597,0.0593589,0.0598406,0.0499306,0.0459325,0.0438789,0.0431263,0.0390478,0.0398482,0.0331776,0.0384364,0.0511891,0.0409022,0.0363491,0.0481671,0.0470022,0.0424568,0.0290798,0.0405769,0.0354487,0.0348602,0.0344066,0.0341277,0.0353893,0.0361191,0.0356225,0.0354421,0.0353507,0.127761,0.0283436,0.0407026,0.0300822,0.0408738,0.0392051", "env/game_level": "42.1293,16.0082,5.99632,7.49345,7.8949,8.15996,8.29612,8.30161,4.40223,1.00399,1,1.32887,1.00232,1.00582,9.1546,9.25568,8.18995,8.58269,1.43124,1.04437,1,1,12.4732,1.00026,8.40484,1,9.16444,9.31816,9.36857,1,7.39804,8.04051,8.45809,8.78239,8.93725,8.95917,1.14283,3.79566,16.303,23.3379,29.0924,35.8316,37.1544,9.51692,9.82323,9.98019,1.00079,2.63172,37.875,40.3341,1,2.59184,22.6083,32.6458,58.0195,61.5304,63.4996,64.0183,2.33655,4.21507,3.68631,5.75462,6.68468,7.33837,7.85904,9.74848,9.96638,1.00386,54.8267,58.8333,60.6741,1,1,1,1.15384,12.2652,9.8535,23.8157,33.364,40.4791,46.6106,52.0097,56.8301,60.132,60.8174,1.00001,7.82708,8.46167,8.94727,9.19769,9.31818,9.31724,12.2593,18.7149,24.7164,29.6454,36.1401,15.6204,1.23157,5.06433,6.65829,7.40634,7.90806,8.33079,1,4.21566,5.66892,6.4879,6.93756,7.24395,7.35421,4.68981,1.01134,24.7679,31.6725,43.7114,47.9938,50.5373,1.59718,7.03227,7.54851,9.72348,3.14153,5.91268,6.89404,7.46812,7.85723,8.16767,8.35594,1,3.03803,1,9.41702,9.60434,9.06748,9.38703,9.59022,9.69059,9.70332,1.33893,12.4369,21.4876,3.9579,1.00056,36.8714,62.9816,65.05,65.3785,19.5923,30.9273,38.8236,44.8165,49.7048,53.6849,56.4624,57.8483,58.089,1,1,1,1,10.1204,10.4097,1.00304,15.8885,20.4861,23.8185,1.20536,1.72975,11.6243,1,10.73,15.4213,20.731,25.3897,29.5125,32.6829,34.0077,1,6.33843,6.8739,6.96292,8.9891,1.01056,2.90368,5.61658,1.0058,1.00016,15.6029,21.3221,27.1382,31.5853,34.0527,34.7234,2.85512,6.01774,4.38115,9.30285,9.53664,9.68679,8.31593,8.75635,9.02568,9.189,2.3005,6.23017,1,1.9165,1,1,4.53034,11.0329,2.21667,5.1593,6.22924,6.92555,7.33017,7.64145,9.2477,2.63189,1.27294,1.00004,4.76346,19.5986,31.1422,12.0497,12.864,1.18632,1.01189,34.4211,60.8423,64.5822,66.2203,66.5386,7.69864,8.20436,8.55949,8.69411,8.72268,1,1,1,1.0096,21.9699,2.76663", "env/ticks_per_line": "10.3078,11.774,16.3209,13.3144,12.9215,12.6839,12.5934,12.6008,23.3868,158.847,102.658,62.7771,161.555,154.501,11.5153,11.4725,12.3655,12.0215,115.991,120.552,74.8943,54.8303,12.1261,201.354,11.9698,119.849,15.2454,15.1969,15.1949,42.06,14.1418,13.4527,13.1696,12.8901,12.764,12.679,107.565,25.0559,11.7334,10.9848,10.6987,10.4913,10.4839,12.8682,12.7423,12.6946,175.131,118.828,10.3696,10.3675,288.641,125.67,10.6244,9.86981,9.2842,9.2656,9.25377,9.25235,53.562,19.7422,29.614,15.952,13.7085,12.5648,12.0078,13.1041,13.0351,154.995,10.4171,10.4707,10.4947,202.71,121.129,127.741,129.684,12.1021,12.2395,10.1642,9.65235,9.45501,9.35122,9.28412,9.23898,9.2059,9.1937,194.155,13.4836,13.0493,12.8197,12.747,12.6925,12.7307,12.399,11.1308,10.7195,10.519,10.3777,11.5673,128.833,17.3153,13.7973,12.9813,12.6267,12.4276,236.707,27.6881,17.4861,14.024,13.208,12.8089,12.7115,24.6771,180.502,11.047,10.6657,10.4809,10.4879,10.4855,120.908,14.0118,13.5194,11.3142,38.0482,15.1883,13.5314,12.7609,12.3525,12.165,12.0445,153.368,100.092,207.302,11.4811,11.4071,11.494,11.361,11.2762,11.2473,11.2465,121.992,12.493,11.118,35.5896,208.737,9.70894,9.4973,9.47693,9.46617,10.8167,10.2733,10.1891,10.2077,10.2679,10.3184,10.3457,10.3717,10.3727,38.3521,48.9112,83.4041,119.227,11.4447,11.3713,138.698,11.4954,10.9128,10.7014,82.6741,89.9159,12.7642,233.106,11.5318,11.0381,10.643,10.407,10.2759,10.1749,10.139,202.569,14.9795,14.0376,13.863,11.844,199.704,43.4975,16.9873,178.472,135.628,11.5365,10.9862,10.6607,10.51,10.4219,10.3512,48.2051,15.7166,24.041,12.6035,12.5491,12.5149,13.0293,12.6922,12.4841,12.417,72.1961,14.2297,99.7631,123.654,204.098,207.978,26.2744,11.8019,80.5228,17.9689,14.2432,13.0488,12.2984,12.0507,11.532,99.6831,113.69,164.889,20.7327,12.2302,12.3095,11.2858,11.1989,194.119,142.03,10.4562,10.4948,10.5303,10.5357,10.5489,12.9092,12.3773,12.0654,11.9421,11.8983,49.625,182.128,473.4,191.392,10.9273,50.4568", "env/n": "539.087,670.049,360.968,315.937,305.437,297.444,294.857,10255,207.013,696.907,11253.3,579.437,2155.94,522.464,133.757,132.639,291.217,282.6,360.857,1183.39,13880.6,16883.4,808.276,566.784,571.39,2733.56,133.713,132.203,10009,24453.8,303.806,286.891,277.194,270.967,268.272,10212,1227.74,468.716,1216.99,893.732,739,613.171,599.443,258.461,253.078,250.209,1324.38,619.096,1179.51,10095,454.531,149.105,954.038,677.371,392.069,370.553,359.709,10001,251.435,226.607,237.317,185.323,169.979,161.413,153.413,128.579,126.423,1096.78,209.192,195.569,190.132,1041.5,1303.06,6248.8,541.567,3297.54,505.063,3575.92,2636.12,2200.71,1919.58,1726.83,1590.17,1521.46,10676,599.988,152.231,143.79,137.811,134.466,133.395,10131,1603.65,1125.54,873.019,739.75,617.644,2669.84,412.505,418.578,349.973,323.415,307.774,295.673,731.624,194.402,180.171,173.474,166.65,160.915,159.345,388.322,971.662,867.471,692.535,511.093,469.31,10347,813.563,328.231,312.168,510.39,245.819,182.687,165.65,157.544,152.137,147.582,145.445,3418.83,574.547,1566.65,265.349,261.511,271.873,264.13,259.479,256.92,10004,899.276,1585.16,983.6,439.478,1040.28,2414.18,1460.97,1422.23,11328,285.74,183.233,147.297,128.057,115.98,107.511,102.626,100.27,10075,12841,10575,6047.67,4217,246.839,241.414,676.771,1284.2,1035.21,908.758,679.654,443.337,1710.82,650.959,471.602,342.08,262.231,218.069,189.883,173.528,167.743,804.46,173.093,165.65,321.367,271.673,221.563,129.206,91.3698,913.806,1590.84,5047,3851,3117.67,2751.67,2591.73,10450,566.549,360.083,225.415,134.652,131.998,129.972,142.635,137.843,135.274,133.612,393.907,182.013,5488.71,330.983,635.48,1395.43,365.567,450.706,478.201,403.812,367.31,342.162,330.6,319.396,132.376,327.453,821.414,388.449,204.727,579.851,364.386,420.024,395.882,753.345,245.269,1295.46,755.388,714.633,701.127,10490,302.719,290.795,282.353,279.464,10075,1375.61,2185.08,542.385,261.309,501.358,246.656", "perf/rollout": "0.156584,0.10875,0.0160971,0.0173141,0.0172928,0.0173098,0.0172677,0.01738,0.0114585,0.00939592,0.0849982,0.0111753,0.0331897,0.00928013,0.00994413,0.0100648,0.0209754,0.0210383,0.0165792,0.0199392,0.145298,0.134469,0.0719615,0.00878824,0.0367153,0.0229031,0.0155057,0.0154886,0.0149219,0.0800686,0.026495,0.0265427,0.0266118,0.0265798,0.026655,0.026052,0.0157478,0.016097,0.115133,0.117705,0.118924,0.121732,0.113402,0.021608,0.0209332,0.0208528,0.022972,0.0191676,0.25066,0.240362,0.0238032,0.00862649,0.18583,0.176336,0.201856,0.153301,0.184564,0.150004,0.00857027,0.00856449,0.0101397,0.0105584,0.0106686,0.010615,0.0106637,0.0120949,0.0119936,0.0155356,0.0925659,0.0999312,0.096099,0.00936694,0.0242644,0.0567447,0.0116328,0.260852,0.0364769,0.574268,0.58714,0.589353,0.595374,0.603768,0.595171,0.596199,0.637038,0.0114536,0.0105267,0.0120033,0.0131049,0.0133678,0.0120033,0.010824,0.114987,0.113458,0.138512,0.131214,0.12853,0.304677,0.0117316,0.0165976,0.0166075,0.0165795,0.0165065,0.016463,0.00913571,0.00905665,0.00921251,0.00913984,0.0092294,0.00928907,0.00879672,0.0172095,0.017279,0.128017,0.152828,0.127359,0.126431,0.139516,0.0225577,0.019546,0.0196048,0.0367576,0.00901924,0.00938264,0.00927507,0.00851536,0.00858732,0.00880848,0.00882631,0.0590902,0.020248,0.0175211,0.0174752,0.0174697,0.0196065,0.0198886,0.0199035,0.0198978,0.0192301,0.0158208,0.147456,0.151146,0.0196673,0.0165501,0.707222,0.717541,0.716742,0.714661,0.0462145,0.049279,0.0495757,0.0386055,0.0392608,0.0419962,0.0510517,0.0512894,0.0517213,0.0368716,0.0317284,0.0374405,0.0337437,0.0167072,0.0165803,0.0111354,0.109469,0.110578,0.108456,0.0110588,0.01751,0.122227,0.00998441,0.0359025,0.0360937,0.0362165,0.0362962,0.0348031,0.0376744,0.0374051,0.0114624,0.0119049,0.0119406,0.0177694,0.0174572,0.00961087,0.0112661,0.0105411,0.0173634,0.0172615,0.471092,0.47996,0.478467,0.482267,0.534485,0.595729,0.0169155,0.0168923,0.00958333,0.00980864,0.00980002,0.00981649,0.0124074,0.0114998,0.0115766,0.0129803,0.010465,0.0110678,0.0706588,0.00958018,0.0161136,0.0179647,0.0196326,0.0416733,0.0164216,0.0174524,0.0177336,0.017674,0.0177819,0.0177724,0.0101471,0.011653,0.0167821,0.0100864,0.00988222,0.0852603,0.0869364,0.038196,0.0382204,0.0179898,0.00493576,0.671953,0.676377,0.679385,0.688038,0.668361,0.016266,0.0181192,0.0181201,0.0180613,0.023972,0.015089,0.0383311,0.028932,0.00491198,0.0994154,0.00821136", "perf/eval_gpu": "0.0533107,0.0453769,0.00742561,0.00691601,0.00688345,0.00687492,0.00679275,0.00685304,0.00389734,0.0036752,0.0303609,0.00453107,0.0142218,0.00381624,0.00375746,0.00369606,0.00695228,0.0069549,0.00957066,0.00713871,0.102313,0.0536577,0.0273258,0.00408997,0.0140382,0.0100268,0.0064423,0.0064212,0.00624461,0.0448867,0.0109396,0.0108238,0.0108382,0.0107499,0.0107971,0.0103172,0.00699319,0.00667818,0.0488421,0.0488858,0.0486905,0.0488317,0.046985,0.00918764,0.00937248,0.00929505,0.00930903,0.00800479,0.0872539,0.0880445,0.0133202,0.00448654,0.0584367,0.0583691,0.0594898,0.0562182,0.0570425,0.0544374,0.00407923,0.0037545,0.00413854,0.0041726,0.00422088,0.0041336,0.00413408,0.00428773,0.00414882,0.00695593,0.0352908,0.0359783,0.0357621,0.00502826,0.0127986,0.0323082,0.00457331,0.081582,0.0134067,0.210711,0.217642,0.219729,0.220958,0.225907,0.220521,0.223603,0.245534,0.00446526,0.00464535,0.00483886,0.00483733,0.00485132,0.00468583,0.00489074,0.0544364,0.0509609,0.049171,0.049541,0.0453963,0.0934427,0.00468943,0.00841699,0.00826435,0.0082088,0.00810277,0.00804546,0.00472915,0.00426309,0.00414808,0.00391605,0.00394708,0.00442582,0.0043829,0.00657687,0.00859994,0.0493211,0.053339,0.0486288,0.0484035,0.0514749,0.00957995,0.00808021,0.00807812,0.0140505,0.00408637,0.00398745,0.00433967,0.00455227,0.00457326,0.00443814,0.00450673,0.0341736,0.00881149,0.0106114,0.00974167,0.00972829,0.00719843,0.00728302,0.00728874,0.00727446,0.00675763,0.00726399,0.0569585,0.0562285,0.00847214,0.00967307,0.291161,0.2886,0.288122,0.289528,0.0183286,0.0182962,0.0190081,0.0174082,0.0180742,0.0177526,0.018223,0.0182487,0.0190458,0.0177299,0.0179812,0.0239138,0.0211836,0.00914612,0.009046,0.00449294,0.0565355,0.0571919,0.0552558,0.00475599,0.0090631,0.0433892,0.00506991,0.0126833,0.0125971,0.0125326,0.0125077,0.01542,0.0155604,0.014802,0.00430928,0.00390669,0.00391371,0.00791986,0.00940116,0.00423528,0.00548171,0.00426085,0.00728659,0.00837519,0.227914,0.236633,0.232936,0.237317,0.216376,0.23734,0.00954396,0.00902788,0.00438961,0.00435976,0.00435498,0.00435976,0.00532671,0.00553158,0.0055143,0.00529417,0.00370293,0.00371355,0.0411418,0.00395447,0.00848099,0.0110429,0.00994589,0.0136416,0.00651092,0.00638516,0.00647817,0.00633445,0.00640463,0.00637174,0.0037486,0.00427347,0.00748818,0.00447144,0.00407813,0.0320917,0.0333492,0.0135085,0.0135216,0.00750414,0.00245512,0.432356,0.433898,0.430042,0.425792,0.434248,0.00616885,0.00691172,0.0069473,0.00685032,0.0128885,0.0094245,0.0226449,0.0171074,0.00203175,0.0378549,0.00430881", "perf/eval_env": "0.0804784,0.059463,0.00703299,0.00767391,0.00769022,0.00770164,0.0077186,0.00781911,0.00480239,0.00458976,0.0523406,0.00598735,0.0167464,0.00435248,0.00514701,0.00528948,0.0131872,0.0132478,0.005716,0.00977877,0.0308187,0.0782413,0.0365552,0.00363154,0.0205183,0.0114577,0.00417527,0.00416907,0.00414175,0.0264584,0.0137001,0.0139563,0.014013,0.0140627,0.0140886,0.0140313,0.00721594,0.00807814,0.0605608,0.0613992,0.0619459,0.0627372,0.0615155,0.00912942,0.00914175,0.00913799,0.0122371,0.00915096,0.149516,0.146095,0.00445506,0.0031153,0.0987536,0.095426,0.104859,0.0928523,0.0994488,0.0913364,0.00367538,0.00400989,0.00494279,0.00532537,0.00538631,0.00543031,0.00547396,0.00424309,0.0044055,0.00716084,0.0438776,0.0417165,0.0423482,0.00283162,0.00936413,0.0195567,0.00428223,0.174436,0.0161504,0.354353,0.358124,0.360112,0.364757,0.368005,0.364939,0.360368,0.380298,0.00589279,0.00437902,0.00472942,0.00509034,0.00501421,0.00489467,0.00460578,0.0575469,0.0593658,0.0648403,0.0634743,0.0645398,0.157449,0.00445002,0.00679706,0.00695667,0.0069871,0.00700705,0.00703057,0.0029577,0.00328765,0.00343455,0.00352182,0.00355336,0.00333823,0.00293457,0.00770789,0.00623961,0.0723923,0.077625,0.0738751,0.0736067,0.0744309,0.00634222,0.00876706,0.00881547,0.0207421,0.00329632,0.00353829,0.00328881,0.00309401,0.00311008,0.00320194,0.00312283,0.0167589,0.00930559,0.00470982,0.00622274,0.00622972,0.0104517,0.0106706,0.0106762,0.0106892,0.0105899,0.00719539,0.0756808,0.0768187,0.00744239,0.00550386,0.407845,0.420345,0.419998,0.41687,0.0215259,0.0238546,0.0242505,0.0186036,0.0187132,0.0194653,0.0209894,0.021035,0.0211894,0.0141044,0.0106841,0.00980694,0.00927672,0.006126,0.00611584,0.00491118,0.0499403,0.0503444,0.0502583,0.00453041,0.0061422,0.0720821,0.0037536,0.0169966,0.0171687,0.0173218,0.0174089,0.0144582,0.0145447,0.0151056,0.00433704,0.00480424,0.00484608,0.00706056,0.00627814,0.00445481,0.00484999,0.0053458,0.00724418,0.00672361,0.232725,0.232809,0.235038,0.234676,0.253827,0.269978,0.00604776,0.00654316,0.00393885,0.00420811,0.00420563,0.00421066,0.00412451,0.00384001,0.00387809,0.00444084,0.00608288,0.00671224,0.0167004,0.00455907,0.00703658,0.00529378,0.00626834,0.0206226,0.00875648,0.00991699,0.0100973,0.0101903,0.0102294,0.0102502,0.00536346,0.00435972,0.00601096,0.00381878,0.00428924,0.0387552,0.0364935,0.0225368,0.0225367,0.00872259,0.0013024,0.227785,0.231063,0.238324,0.240618,0.222938,0.00767935,0.00847891,0.00835429,0.00837344,0.00841457,0.00248559,0.0100086,0.00772786,0.00222891,0.0410099,0.00308847", "perf/train_misc": "0.018156,0.0190107,0.0041514,0.00415139,0.00415218,0.0041515,0.00414972,0.0041513,0.00173271,0.000651246,0.0284836,0.00102011,0.00414609,0.000946169,0.00091629,0.000916631,0.00352321,0.00352239,0.00180402,0.00281638,0.0420705,0.0220495,0.0195038,0.00221636,0.0047357,0.00154888,0.00108847,0.00109287,0.00110397,0.0369768,0.00367749,0.00368532,0.00368405,0.00367955,0.0036736,0.00365773,0.00198498,0.00188443,0.0216928,0.021685,0.0216847,0.0216805,0.0216898,0.00386788,0.00387184,0.00388781,0.00378922,0.00430309,0.0877329,0.0872376,0.0008566,0.00047235,0.0268142,0.0267943,0.0267995,0.0268084,0.026804,0.0269299,0.00147834,0.00147862,0.00148502,0.00147445,0.00147588,0.00147291,0.00148261,0.00105262,0.00104852,0.00368944,0.00788821,0.0078942,0.00788819,0.00136275,0.00169056,0.0128097,0.00180575,0.0841537,0.00533258,0.315932,0.316281,0.316288,0.316217,0.316064,0.316045,0.315788,0.316457,0.00167855,0.0012618,0.00126909,0.00126665,0.00126223,0.00126306,0.00125542,0.0289223,0.0289581,0.0289498,0.0289334,0.0289414,0.105807,0.00145461,0.00191,0.00190335,0.00190494,0.00191576,0.00190617,0.00165856,0.0015062,0.00150736,0.00152159,0.00150801,0.00150872,0.00150799,0.00360369,0.005791,0.022997,0.0229769,0.0229685,0.0229892,0.0229548,0.00392655,0.00223622,0.00223781,0.00336917,0.00219208,0.00219038,0.00220763,0.00219708,0.00218825,0.00218911,0.0022042,0.00677684,0.00449015,0.00199025,0.001701,0.00170105,0.00142806,0.00142367,0.00142357,0.00142337,0.00142134,0.00386411,0.0304911,0.0305153,0.00263251,0.00398862,0.312928,0.312344,0.312489,0.311389,0.0037514,0.00374924,0.00379894,0.00374617,0.00375966,0.00375722,0.00374916,0.00374857,0.00377171,0.0161602,0.00336731,0.00336653,0.00337582,0.0039945,0.00397957,0.00140732,0.0354965,0.0354979,0.0354986,0.00109316,0.00119339,0.0321894,0.0023004,0.00294855,0.00295239,0.00294961,0.0029519,0.00294939,0.00295389,0.00295891,0.00139068,0.00129143,0.00129056,0.00336379,0.00337177,0.00080613,0.00102424,0.000785014,0.00466269,0.00372937,0.312157,0.312033,0.312209,0.312078,0.312777,0.311203,0.00317529,0.0031788,0.000903733,0.000902942,0.000903542,0.000903361,0.00202755,0.0020188,0.00201998,0.00201904,0.0012088,0.00118735,0.00600252,0.00179009,0.000683418,0.00468806,0.00392033,0.00517127,0.00229714,0.00229579,0.00229627,0.00229596,0.00229553,0.00229538,0.0013965,0.00175322,0.00454054,0.000503886,0.00193655,0.0147123,0.0147121,0.0029967,0.0029966,0.00541127,0.000505911,0.062646,0.0626585,0.062689,0.0627169,0.0633764,0.00274737,0.00275285,0.00275714,0.00276492,0.00273507,0.000359691,0.00378708,0.00206788,0.000481563,0.0127371,0.00127335", "perf/train_forward": "0.652521,0.511077,0.0282674,0.028275,0.0282609,0.0282741,0.0282717,0.0283146,0.015248,0.00721949,0.118083,0.0145813,0.0368055,0.00839921,0.00790146,0.00789456,0.0247077,0.0247139,0.092886,0.0376452,1.79304,0.0704721,0.460779,0.0160752,0.0446302,0.0433288,0.0137644,0.0137537,0.0137308,0.833556,0.0546871,0.0547038,0.0547217,0.0547202,0.0547659,0.0570972,0.0123584,0.0117316,0.548777,0.548633,0.548555,0.548824,0.548778,0.0583691,0.0584162,0.0583825,0.0337497,0.037258,0.840856,0.84253,0.0707762,0.0099971,0.947466,0.947404,0.947855,0.948108,0.948123,0.947982,0.00603766,0.00603212,0.0139375,0.0139483,0.0139847,0.013937,0.0139449,0.0128618,0.0128626,0.0249734,0.330202,0.330108,0.330153,0.0141899,0.131263,0.643942,0.0158573,0.83294,0.0485802,5.27548,5.27305,5.26994,5.27161,5.27176,5.27152,5.26894,5.27591,0.0146798,0.0216389,0.0216337,0.0216392,0.0216401,0.0216393,0.0215654,0.310139,0.310133,0.310017,0.310101,0.310203,0.964482,0.0255185,0.0174728,0.0174562,0.017459,0.0174612,0.0174598,0.0252439,0.0231112,0.0231121,0.0231086,0.0231136,0.023124,0.0231231,0.0499719,0.0405972,0.756525,0.756368,0.756414,0.756438,0.756004,0.0593017,0.0166035,0.01659,0.0576838,0.0158444,0.0158498,0.0158444,0.0158433,0.0158673,0.0158515,0.0158425,0.422609,0.0718545,0.0099724,0.0342233,0.034212,0.0150525,0.0150546,0.0150606,0.015059,0.0150405,0.0267307,0.602906,0.595724,0.0258538,0.0267919,5.2168,5.2034,5.20326,5.20985,0.194874,0.194853,0.195604,0.194909,0.19585,0.194907,0.194907,0.194912,0.195063,0.455981,0.0984631,0.0987148,0.099044,0.0547522,0.0547834,0.0243249,0.385555,0.385534,0.385396,0.0067624,0.0195592,0.34709,0.0162615,0.0576254,0.0576405,0.0576291,0.0576405,0.057645,0.0576315,0.0576385,0.0117378,0.0109877,0.0109869,0.022819,0.0228572,0.0194388,0.0189826,0.0189432,0.0648921,0.0246776,2.28394,2.28472,2.28694,2.28603,2.28532,2.27856,0.0316739,0.0316671,0.0145128,0.0145565,0.0145596,0.0145596,0.0377188,0.0376913,0.0376695,0.0376949,0.00808027,0.00793187,0.346248,0.0171251,0.00630522,0.0316668,0.0268103,0.20714,0.0152694,0.0152682,0.0152616,0.0152558,0.0152607,0.0153182,0.0129907,0.015494,0.0326241,0.0105779,0.0173848,0.422273,0.422319,0.0608885,0.0609031,0.078245,0.0104048,4.5134,4.51469,4.51502,4.51424,4.51781,0.0183026,0.0183035,0.0183108,0.0183093,0.0182682,0.0314971,0.310055,0.169466,0.00470303,0.565836,0.0126017", "perf/train": "0.670677,0.530088,0.0324188,0.0324264,0.032413,0.0324256,0.0324214,0.0324659,0.0169808,0.00787073,0.146567,0.0156015,0.0409516,0.00934538,0.00881776,0.00881119,0.0282309,0.0282363,0.0946901,0.0404616,1.83511,0.0925216,0.480283,0.0182916,0.0493659,0.0448777,0.0148529,0.0148465,0.0148348,0.870533,0.0583646,0.0583891,0.0584058,0.0583997,0.0584395,0.0607549,0.0143434,0.013616,0.57047,0.570318,0.57024,0.570505,0.570468,0.0622369,0.062288,0.0622703,0.0375389,0.0415611,0.928589,0.929767,0.0716328,0.0104695,0.97428,0.974198,0.974654,0.974917,0.974927,0.974912,0.007516,0.00751074,0.0154225,0.0154228,0.0154606,0.01541,0.0154276,0.0139144,0.0139111,0.0286628,0.33809,0.338002,0.338041,0.0155527,0.132954,0.656752,0.0176631,0.917094,0.0539128,5.59141,5.58933,5.58622,5.58783,5.58783,5.58756,5.58473,5.59237,0.0163584,0.0229007,0.0229027,0.0229059,0.0229023,0.0229023,0.0228209,0.339061,0.339091,0.338966,0.339035,0.339144,1.07029,0.0269731,0.0193828,0.0193595,0.019364,0.0193769,0.0193659,0.0269025,0.0246174,0.0246195,0.0246302,0.0246216,0.0246327,0.0246311,0.0535756,0.0463882,0.779522,0.779344,0.779382,0.779427,0.778959,0.0632282,0.0188397,0.0188278,0.061053,0.0180365,0.0180401,0.018052,0.0180404,0.0180556,0.0180406,0.0180467,0.429386,0.0763446,0.0119626,0.0359243,0.0359131,0.0164805,0.0164783,0.0164842,0.0164824,0.0164619,0.0305949,0.633397,0.626239,0.0284863,0.0307805,5.52973,5.51575,5.51575,5.52124,0.198626,0.198603,0.199403,0.198655,0.19961,0.198664,0.198656,0.19866,0.198834,0.472141,0.10183,0.102081,0.10242,0.0587468,0.058763,0.0257323,0.421051,0.421032,0.420895,0.00785556,0.0207526,0.37928,0.0185619,0.060574,0.0605928,0.0605787,0.0605924,0.0605944,0.0605853,0.0605974,0.0131284,0.0122791,0.0122775,0.0261828,0.0262289,0.0202449,0.0200069,0.0197282,0.0695548,0.0284069,2.5961,2.59675,2.59915,2.59811,2.5981,2.58976,0.0348492,0.0348459,0.0154165,0.0154594,0.0154631,0.0154629,0.0397463,0.0397101,0.0396895,0.039714,0.00928907,0.00911922,0.35225,0.0189152,0.00698864,0.0363548,0.0307306,0.212311,0.0175665,0.017564,0.0175579,0.0175518,0.0175562,0.0176136,0.0143872,0.0172472,0.0371646,0.0110818,0.0193214,0.436986,0.437031,0.0638852,0.0638997,0.0836563,0.0109107,4.57605,4.57735,4.57771,4.57696,4.58119,0.02105,0.0210563,0.0210679,0.0210742,0.0210032,0.0318568,0.313842,0.171534,0.00518459,0.578573,0.0138751", "util/gpu_percent": "98.6348,97.9136,98.754,97.1032,97.373,97.0397,96.9603,97,95.304,84.0997,97.2727,90.3587,98.8936,88.2963,94.2228,92.1559,91.3937,91.4902,96.7215,92.9247,100,34.4,98.7672,86.6298,98.4268,97.4,96.5507,96.5043,97,94,94.2366,94.1196,93.6129,93.4565,94.0652,96,88.8537,98.1618,99.6714,99.3944,99.2,99.1429,99.7286,96.8247,99,99.0784,90.7768,96.6601,99.7209,100,99,91.754,96.7862,97.6226,96.2516,99.3711,97.4304,98,97.1894,97,97,96.7407,96.4,96.2011,96,95.8522,96.0539,94.7394,98.0094,96.544,97.2808,97.2735,93.1899,99.7,92.1755,98.7089,95.2168,100,100,100,100,100,100,100,100,86.4783,97.042,95.4496,94.2059,93.5252,95.8277,96,99.8077,99.7143,95.9423,97.4038,96.8846,98.0886,96.8875,98.4898,98.8151,98.2517,98.3288,98.3673,89.7436,98,98,98,97.7521,98.0342,98.7069,98.1954,94.5396,99.5402,98.3372,99.6279,99.7931,100,95.3674,97.8182,97.7483,97.2195,97.4011,95.7637,96.3607,98.2637,98.2033,97.1044,97.5824,100,98.8895,85.3271,99.1552,99.0346,94.1778,95.9143,95.7397,95.9873,95,96.5517,99.4364,99.1455,95.1413,92.9817,100,100,100,100,98.3497,97.4438,97.7914,99.4816,99.5317,98.863,97.1697,94.4213,100,100,100,100,100,99.5205,99.589,97.974,99.8485,99.803,99.7879,82.5637,93.0283,98.7925,81.949,97.4615,97.3422,97.2865,97.3316,97.3024,94.8196,95.7215,81.9379,94.1925,93.4188,97,98.5939,83.8131,87.7451,85.1144,98.7823,92.0682,100,100,100,100,100,100,99,99.1439,98.4076,98,98,98,93.0067,96.9732,98.6054,97.3813,87.1077,87.1077,99.4286,94.4324,65,99.2833,95.7333,97.243,98.0649,96.9481,96.3613,96.0065,95.8194,95.9935,96.2247,91.6474,98.55,79.1152,98,98.4516,98.249,96.2412,96.4235,97.0676,94.0287,100,100,100,100,100,95.491,94.7349,94.1916,94.5602,94,89.6296,100,100,88.8347,98.4088,98.1104", "util/gpu_mem": "23.3963,13.6096,5.91541,5.91541,5.91541,5.91541,5.91541,5.91541,6.05383,20.774,9.64445,6.20038,7.68223,5.29662,5.29662,5.29662,6.46907,6.46907,7.66594,7.12043,12.4453,8.69184,13.9678,5.25591,7.68223,22.6467,7.153,7.153,7.153,14.261,6.83546,6.83546,6.83546,6.83546,6.83546,6.83546,5.86656,5.86656,23.095,23.095,23.095,23.095,23.095,7.29141,7.29141,7.29141,6.09454,5.97241,25.8552,25.8552,15.9871,5.92356,22.6798,22.6798,22.6798,22.6798,22.6798,22.6798,4.89767,4.89767,5.29662,5.29662,5.29662,5.29662,5.29662,6.92502,6.92502,20.6519,18.91,18.91,18.91,6.00498,10.0597,12.4616,6.05383,25.6353,7.87764,47.5047,47.5047,47.5047,47.5047,47.5047,47.5047,47.5047,47.5047,5.24777,6.55863,6.55863,6.55863,6.55863,6.55863,6.55863,17.5666,17.5666,17.5666,17.5666,17.5666,40.5803,21.344,21.3928,21.3928,21.3928,21.3928,21.3928,6.97387,6.97387,6.97387,6.97387,6.97387,6.97387,6.97387,22.264,5.96427,23.038,23.038,23.038,23.038,23.038,7.75551,6.61563,6.61563,9.41647,5.31291,5.31291,5.31291,5.31291,5.31291,5.31291,5.31291,18.2587,7.06344,6.03754,8.78954,8.78954,6.65634,6.65634,6.65634,6.65634,6.65634,5.86656,33.076,33.048,6.60748,5.91541,46.9348,46.9348,46.9348,46.9348,31.1714,31.1714,31.1164,31.1714,31.1132,31.1714,31.1714,31.1714,31.1714,12.6081,12.6081,12.6081,12.6081,7.47868,7.47868,6.55863,17.6725,17.6725,17.6725,19.0106,6.32251,17.4608,5.31291,11.4357,11.4357,11.4357,11.4357,11.4357,11.4357,11.4357,6.05383,6.05383,6.05383,5.96427,5.96427,20.5216,20.0725,20.5216,7.29955,5.91541,43.1325,43.1325,43.1325,43.1325,43.1325,43.1325,6.60748,6.60748,6.55863,6.55863,6.55863,6.55863,6.7459,6.7459,6.7459,6.7459,5.20706,5.20706,18.7879,5.29662,4.97909,5.96427,5.96427,16.3372,5.82585,5.82585,5.82585,5.82585,5.82585,5.82585,5.29662,5.88285,20.7985,5.92356,20.3751,14.6925,14.6925,11.11,11.11,6.94131,21.287,40.2991,40.2991,40.2991,40.2991,40.2991,6.55049,6.55049,6.55049,6.55049,6.55049,18.5355,16.5082,16.5082,4.94652,18.91,5.98055", "util/vram_used_gb": "5.15125,2.80359,0.957886,0.957886,0.957886,0.957886,0.957886,0.957886,0.991089,4.52222,1.85242,1.02625,1.38171,0.809448,0.809448,0.809448,1.0907,1.0907,1.37781,1.24695,2.52429,1.6239,2.88953,0.799683,1.38171,4.97144,1.25476,1.25476,1.25476,2.95984,1.17859,1.17859,1.17859,1.17859,1.17859,1.17859,0.946167,0.946167,5.07898,5.07898,5.07898,5.07898,5.07898,1.28796,1.28796,1.28796,1.00085,0.971558,5.74109,5.74109,3.3739,0.959839,4.97937,4.97937,4.97937,4.97937,4.97937,4.97937,0.713745,0.713745,0.809448,0.809448,0.809448,0.809448,0.809448,1.20007,1.20007,4.49292,4.07507,4.07507,4.07507,0.97937,1.95203,2.5282,0.991089,5.68835,1.42859,10.9344,10.9344,10.9344,10.9344,10.9344,10.9344,10.9344,10.9344,0.797729,1.11218,1.11218,1.11218,1.11218,1.11218,1.11218,3.75281,3.75281,3.75281,3.75281,3.75281,9.2734,4.65894,4.67065,4.67065,4.67065,4.67065,4.67065,1.21179,1.21179,1.21179,1.21179,1.21179,1.21179,1.21179,4.87964,0.969604,5.06531,5.06531,5.06531,5.06531,5.06531,1.39929,1.12585,1.12585,1.79773,0.813354,0.813354,0.813354,0.813354,0.813354,0.813354,0.813354,3.91882,1.23328,0.987183,1.64734,1.64734,1.13562,1.13562,1.13562,1.13562,1.13562,0.946167,7.47323,7.46654,1.1239,0.957886,10.7977,10.7977,10.7977,10.7977,7.01636,7.01636,7.00317,7.01636,7.0024,7.01636,7.01636,7.01636,7.01636,2.56335,2.56335,2.56335,2.56335,1.33289,1.33289,1.11218,3.7782,3.7782,3.7782,4.09919,1.05554,3.72742,0.813354,2.2821,2.2821,2.2821,2.2821,2.2821,2.2821,2.2821,0.991089,0.991089,0.991089,0.969604,0.969604,4.46167,4.35393,4.46167,1.28992,0.957886,9.88562,9.88562,9.88562,9.88562,9.88562,9.88562,1.1239,1.1239,1.11218,1.11218,1.11218,1.11218,1.1571,1.1571,1.1571,1.1571,0.787964,0.787964,4.04578,0.809448,0.733276,0.969604,0.969604,3.45789,0.936401,0.936401,0.936401,0.936401,0.936401,0.936401,0.809448,0.950073,4.52808,0.959839,4.42651,3.06335,3.06335,2.20398,2.20398,1.20398,4.64526,9.20593,9.20593,9.20593,9.20593,9.20593,1.11023,1.11023,1.11023,1.11023,1.11023,3.98523,3.4989,3.4989,0.725464,4.07507,0.973511", "util/vram_total_gb": "23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272", "util/cpu_mem_gb": "1.25522,1.17161,1.11536,1.11537,1.11585,1.11607,1.11634,1.11634,1.11682,1.0226,1.12034,1.09917,1.12622,1.10016,1.10626,1.10728,1.10176,1.10237,1.12162,1.11946,1.27499,1.11526,1.16677,1.09988,1.11924,1.01956,1.14992,1.15055,1.15097,1.29386,1.11551,1.11554,1.116,1.116,1.1161,1.11649,1.10936,1.10971,1.19569,1.19594,1.19594,1.19594,1.19594,1.13895,1.13929,1.13976,1.10537,1.11664,1.22763,1.22763,1.15942,1.09852,1.20255,1.20255,1.20352,1.20352,1.20352,1.20352,1.10019,1.10066,1.09826,1.09861,1.09887,1.09909,1.09948,1.12536,1.12695,1.03431,1.223,1.22376,1.22398,1.10962,1.09606,1.16005,1.11571,1.20631,1.14583,1.3161,1.3161,1.3161,1.3161,1.3161,1.3161,1.3161,1.3161,1.09524,1.11226,1.11226,1.11244,1.11275,1.11323,1.11323,1.1852,1.1852,1.1852,1.18547,1.18569,1.1483,1.03161,1.03879,1.03916,1.03994,1.04013,1.04013,1.11331,1.1138,1.1138,1.1138,1.11401,1.11428,1.11428,1.04522,1.11943,1.22842,1.22881,1.22881,1.22881,1.22881,1.15677,1.13822,1.13834,1.13675,1.10938,1.10986,1.10996,1.11035,1.11053,1.11084,1.11111,1.23781,1.12292,1.13241,1.13079,1.13125,1.11881,1.11959,1.12023,1.12091,1.12105,1.10912,1.14949,1.14997,1.11312,1.11864,1.27039,1.27039,1.27039,1.27039,1.07938,1.07977,1.08023,1.08036,1.08039,1.08111,1.08223,1.08314,1.08329,1.2234,1.2234,1.2234,1.2234,1.12998,1.13041,1.11319,1.19486,1.19486,1.19506,1.01972,1.11701,1.17496,1.10882,1.17348,1.17392,1.17468,1.17499,1.17571,1.17644,1.17694,1.11945,1.12075,1.12092,1.12175,1.12321,1.01218,1.0131,1.01349,1.12001,1.12127,1.3849,1.3849,1.3849,1.3849,1.3849,1.3849,1.11879,1.11906,1.11493,1.11815,1.11886,1.11953,1.11904,1.11974,1.12042,1.12137,1.09482,1.09572,1.28873,1.1025,1.09309,1.12432,1.12432,1.13644,1.10651,1.10672,1.10719,1.1076,1.1077,1.10781,1.1077,1.1074,1.0487,1.0992,1.02719,1.24712,1.24739,1.1404,1.14057,1.11024,1.02608,1.25439,1.25439,1.25439,1.25487,1.25488,1.11248,1.11256,1.11296,1.11305,1.11305,1.14858,1.15887,1.15887,1.0914,1.22144,1.10507", "wandb": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "rank": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "world_size": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "gpu_id": "1,1,1,1,1,1,1,1,1,0,1,3,5,3,3,3,3,3,3,1,2,5,5,2,3,0,1,1,1,5,4,4,4,4,4,4,2,2,1,1,1,1,1,5,5,5,4,2,1,1,3,3,5,5,5,5,5,5,3,3,2,2,2,2,2,4,4,0,3,3,3,2,3,4,4,1,3,5,5,5,5,5,5,5,5,1,3,3,3,3,3,3,4,4,4,4,4,0,0,0,0,0,0,0,4,4,4,4,4,4,4,0,4,1,1,1,1,1,2,3,3,1,2,2,2,2,2,2,2,2,1,4,2,2,4,4,4,4,4,2,0,0,2,5,4,4,4,4,0,0,0,0,0,0,0,0,0,3,3,3,3,4,4,3,5,5,5,0,5,4,5,5,5,5,5,5,5,5,2,2,2,3,3,0,0,0,1,4,3,3,3,3,3,3,4,4,1,1,1,1,3,3,3,3,2,2,3,4,5,4,4,4,4,4,4,4,4,4,1,1,0,5,0,4,4,1,1,5,0,4,4,4,4,4,5,5,5,5,5,3,3,3,2,5,5", "profile": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "checkpoint_interval": "200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200", "eval_episodes": "10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000", "cudagraphs": "10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10", "seed": "73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73", "vec/total_agents": "8192,4096,4096,4096,4096,4096,4096,4096,2048,2048,16384,4096,4096,2048,2048,2048,8192,8192,2048,4096,1024,16384,8192,4096,4096,4096,1024,1024,1024,4096,2048,2048,2048,2048,2048,2048,4096,4096,16384,16384,16384,16384,16384,2048,2048,2048,4096,2048,16384,16384,512,1024,8192,8192,8192,8192,8192,8192,4096,4096,2048,2048,2048,2048,2048,2048,2048,4096,4096,4096,4096,4096,1024,2048,2048,16384,4096,16384,16384,16384,16384,16384,16384,16384,16384,2048,2048,2048,2048,2048,2048,2048,16384,16384,16384,16384,16384,16384,2048,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,8192,8192,8192,8192,8192,2048,2048,2048,4096,4096,4096,4096,4096,4096,4096,4096,1024,2048,4096,4096,4096,2048,2048,2048,2048,2048,4096,8192,8192,4096,4096,16384,16384,16384,16384,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,2048,16384,16384,16384,4096,1024,16384,4096,4096,4096,4096,4096,4096,4096,4096,2048,2048,2048,4096,4096,1024,1024,1024,4096,4096,16384,16384,16384,16384,16384,16384,4096,4096,2048,2048,2048,2048,2048,2048,2048,2048,4096,4096,1024,2048,4096,4096,4096,8192,4096,4096,4096,4096,4096,4096,2048,2048,4096,1024,2048,4096,4096,4096,4096,4096,2048,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,512,1024,1024,2048,4096,4096", "vec/num_buffers": "6.05953,3.80308,6.61725,6.61725,6.61725,6.61725,6.61725,6.61725,6.95524,4.86456,3.27627,3.93901,4.25141,4.29023,4.29023,4.29023,3.48628,3.48628,3.69412,5.2851,3.02196,1.53133,5.14808,5.02918,4.29106,3.97938,6.74725,6.74725,6.74725,7.55707,3.26066,3.26066,3.26066,3.26066,3.26066,3.26066,5.36352,5.36352,6.10132,6.10132,6.10132,6.10132,6.10132,5.40112,5.40112,5.40112,3.96027,4.57758,5.51699,5.51699,4.47798,3.25039,4.50462,4.50462,4.50462,4.50462,4.50462,4.50462,5.87498,5.87498,4.05754,4.05754,4.05754,4.05754,4.05754,7.82518,7.82518,5.38976,5.82707,5.82707,5.82707,7.34892,2.85823,4.53014,6.29371,4.83076,6.16673,4.65398,4.65398,4.65398,4.65398,4.65398,4.65398,4.65398,4.65398,3.60584,5.63663,5.63663,5.63663,5.63663,5.63663,5.63663,6.95965,6.95965,6.95965,6.95965,6.95965,5.30595,5.79537,6.56312,6.56312,6.56312,6.56312,6.56312,8,8,8,8,8,8,8,7.67018,7.16404,5.63506,5.63506,5.63506,5.63506,5.63506,7.94706,5.27678,5.27678,4.67644,7.92139,7.92139,7.92139,7.92139,7.92139,7.92139,7.92139,4.29689,4.36531,8,7.36166,7.36166,4.46054,4.46054,4.46054,4.46054,4.46054,5.69654,5.12612,5.12612,6.56147,6.97005,3.76814,3.76814,3.76814,3.76814,5.20054,5.20054,5.20054,5.20054,5.20054,5.20054,5.20054,5.20054,5.20054,8,8,8,8,7.3439,7.3439,5.75766,7.11031,7.11031,7.11031,5.79443,3.3744,5.10537,7.86595,7.1395,7.1395,7.1395,7.1395,7.1395,7.1395,7.1395,6.89812,6.89812,6.89812,7.81567,7.81567,2.81241,2.81241,2.81241,6.19256,6.45841,6.4977,6.4977,6.4977,6.4977,6.4977,6.4977,6.2926,6.2926,5.69584,5.69584,5.69584,5.69584,6.8056,6.8056,6.8056,6.8056,3.70999,3.70999,5.78595,4.24698,1.11632,7.93898,7.93898,5.64782,4.17578,4.17578,4.17578,4.17578,4.17578,4.17578,4.10524,5.31493,8,3.75079,5.69773,6.89689,6.89689,4.33425,4.33425,4.81621,7.00977,3.62537,3.62537,3.62537,3.62537,3.62537,6.97207,6.97207,6.97207,6.97207,6.97207,5.41672,4.59845,4.59845,4.54882,5.76825,6.44648", "vec/num_threads": "2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2", "env/n_rows": "20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20", "env/n_cols": "10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10", "env/use_deck_obs": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "env/n_init_garbage": "4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4", "env/n_noise_obs": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "policy/hidden_size": "512,512,256,256,256,256,256,256,256,256,256,512,256,256,256,256,256,256,1024,512,1024,64,512,256,256,512,256,256,256,256,512,512,512,512,512,512,256,256,512,512,512,512,512,512,512,512,512,256,256,256,1024,512,512,512,512,512,512,512,128,128,256,256,256,256,256,256,256,256,512,512,512,256,1024,1024,256,256,256,512,512,512,512,512,512,512,512,256,512,512,512,512,512,512,256,256,256,256,256,256,512,256,256,256,256,256,512,512,512,512,512,512,512,512,256,512,512,512,512,512,512,256,256,512,256,256,256,256,256,256,256,1024,512,128,512,512,256,256,256,256,256,256,512,512,256,256,512,512,512,512,512,512,512,512,512,512,512,512,512,256,256,256,256,512,512,512,256,256,256,256,512,256,256,256,256,256,256,256,256,256,256,256,256,256,256,512,512,512,512,256,256,256,256,256,256,256,256,256,512,512,512,512,512,512,512,512,256,256,1024,256,32,256,256,512,256,256,256,256,256,256,256,256,256,512,256,512,512,256,256,512,512,1024,1024,1024,1024,1024,256,256,256,256,256,512,1024,1024,256,512,256", "policy/num_layers": "2.23979,2.16218,1,1,1,1,1,1,1.15551,1,1,1,1,1,1,1,1,1,1.32328,1,2.43137,4.61079,2.19441,1,1,1,1,1,1,4.38545,1,1,1,1,1,1,1,1,2.12674,2.12674,2.12674,2.12674,2.12674,1,1,1,1,1,2.35727,2.35727,1,1,2.21381,2.21381,2.21381,2.21381,2.21381,2.21381,1,1,1,1,1,1,1,1,1,1,2.12117,2.12117,2.12117,1,1.78275,1,1,2.09064,1,2.21232,2.21232,2.21232,2.21232,2.21232,2.21232,2.21232,2.21232,1,1,1,1,1,1,1,2.23832,2.23832,2.23832,2.23832,2.23832,2.22614,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2.17206,2.17206,2.17206,2.17206,2.17206,1,1.17438,1.17438,1.58524,1.28857,1.28857,1.28857,1.28857,1.28857,1.28857,1.28857,1,1,1,1.23687,1.23687,1,1,1,1,1,1,2.15849,2.15849,1,1,2.21442,2.21442,2.21442,2.21442,2.20258,2.20258,2.20258,2.20258,2.20258,2.20258,2.20258,2.20258,2.20258,5.60493,5.60493,5.60493,5.60493,1,1,1,2.21667,2.21667,2.21667,1,1,2.19204,1,2.16848,2.16848,2.16848,2.16848,2.16848,2.16848,2.16848,1.65572,1.65572,1.65572,1,1,1,1,1,1,1.3883,2.30251,2.30251,2.30251,2.30251,2.30251,2.30251,1,1,1,1,1,1,1,1,1,1,1.02779,1.02779,1,1,7.27372,1,1,2.21102,1,1,1,1,1,1,1,1,1,1,1,2.22229,2.22229,2.14581,2.14581,1,1,2.1326,2.1326,2.1326,2.1326,2.1326,1,1,1,1,1,3.95037,1.02328,1.02328,1,2.20855,1", "policy/expansion_factor": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "legacy/torch_deterministic": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "legacy/cpu_offload": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "legacy/compile": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "legacy/compile_fullgraph": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "train/gpus": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "train/seed": "42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42", "train/total_timesteps": "2169.74,2296.11,297.363,297.363,297.363,297.363,297.363,297.363,267.714,354.102,97.4236,588.177,441.846,476.747,476.747,476.747,600.89,600.89,487.008,344.156,73.7217,41.4562,2193.75,245.332,387.201,105.837,407.597,407.597,407.597,38.1418,218.215,218.215,218.215,218.215,218.215,218.215,481.575,481.575,1330.29,1330.29,1330.29,1330.29,1330.29,362.167,362.167,362.167,263.726,831.288,1643.62,1643.62,37.236,738.032,3000,3000,3000,3000,3000,3000,379.496,379.496,223.284,223.284,223.284,223.284,223.284,678.705,678.705,334.886,3000,3000,3000,137.344,92.4628,94.063,376.005,3000,672.883,1825.44,1825.44,1825.44,1825.44,1825.44,1825.44,1825.44,1825.44,189.435,280.826,280.826,280.826,280.826,280.826,280.826,1970.53,1970.53,1970.53,1970.53,1970.53,3000,387.591,345.705,345.705,345.705,345.705,345.705,137.673,137.673,137.673,137.673,137.673,137.673,137.673,410.712,327.094,1633.94,1633.94,1633.94,1633.94,1633.94,507.268,337.274,337.274,1162.67,215.083,215.083,215.083,215.083,215.083,215.083,215.083,30,831.188,250.803,546.068,546.068,743.041,743.041,743.041,743.041,743.041,613.722,1035.31,1035.31,435.204,255.937,3000,3000,3000,3000,2308.55,2308.55,2308.55,2308.55,2308.55,2308.55,2308.55,2308.55,2308.55,36.3839,36.3839,36.3839,36.3839,689.21,689.21,226.274,1249.51,1249.51,1249.51,415.83,542.09,3000,114.809,1779.58,1779.58,1779.58,1779.58,1779.58,1779.58,1779.58,189.194,189.194,189.194,391.006,391.006,242.761,242.761,242.761,290.931,206.187,893.502,893.502,893.502,893.502,893.502,893.502,312.981,312.981,498.098,498.098,498.098,498.098,353.046,353.046,353.046,353.046,722.795,722.795,32.1379,566.999,30.0392,140.731,140.731,1847.47,364.188,364.188,364.188,364.188,364.188,364.188,420.085,776.33,518.618,143.343,203.483,2344.9,2344.9,802.112,802.112,347.767,329.039,3000,3000,3000,3000,3000,393.052,393.052,393.052,393.052,393.052,31.7007,30,30,356.867,3000,363.527", "train/learning_rate": "0.00467993,0.00373997,0.00515121,0.00515121,0.00515121,0.00515121,0.00515121,0.00515121,0.00681373,0.00934608,0.007732,0.0131205,0.00949795,0.0080998,0.0080998,0.0080998,0.0071572,0.0071572,0.00655695,0.0151597,0.0533148,2.86623e-05,0.00324316,0.00544442,0.00936907,0.1,0.0093392,0.0093392,0.0093392,0.0302149,0.0075752,0.0075752,0.0075752,0.0075752,0.0075752,0.0075752,0.00997693,0.00997693,0.0033918,0.0033918,0.0033918,0.0033918,0.0033918,0.00540627,0.00540627,0.00540627,0.00632637,0.00505372,0.00829838,0.00829838,0.0443741,0.00933566,0.00370426,0.00370426,0.00370426,0.00370426,0.00370426,0.00370426,0.0074539,0.0074539,0.0101339,0.0101339,0.0101339,0.0101339,0.0101339,0.00655227,0.00655227,0.00716637,0.00701308,0.00701308,0.00701308,0.00469123,0.0639365,0.00685697,0.00491711,0.00515865,0.0102373,0.00681365,0.00681365,0.00681365,0.00681365,0.00681365,0.00681365,0.00681365,0.00681365,0.00788253,0.00569381,0.00569381,0.00569381,0.00569381,0.00569381,0.00569381,0.00502032,0.00502032,0.00502032,0.00502032,0.00502032,0.00494263,0.00418678,0.00456513,0.00456513,0.00456513,0.00456513,0.00456513,0.00836587,0.00836587,0.00836587,0.00836587,0.00836587,0.00836587,0.00836587,0.00759676,0.00479604,0.00619154,0.00619154,0.00619154,0.00619154,0.00619154,0.00752108,0.00572761,0.00572761,0.00747873,0.00502689,0.00502689,0.00502689,0.00502689,0.00502689,0.00502689,0.00502689,0.00906968,0.00400968,0.0079126,0.00617844,0.00617844,0.0113089,0.0113089,0.0113089,0.0113089,0.0113089,0.0104181,0.00425499,0.00425499,0.0118458,0.010678,0.0020538,0.0020538,0.0020538,0.0020538,0.0031086,0.0031086,0.0031086,0.0031086,0.0031086,0.0031086,0.0031086,0.0031086,0.0031086,0.050151,0.050151,0.050151,0.050151,0.00403957,0.00403957,0.00814338,0.00391823,0.00391823,0.00391823,0.00930457,0.0060809,0.00639452,0.00554654,0.00534001,0.00534001,0.00534001,0.00534001,0.00534001,0.00534001,0.00534001,0.00575391,0.00575391,0.00575391,0.00732689,0.00732689,0.00622901,0.00622901,0.00622901,0.00624444,0.00670372,0.00813525,0.00813525,0.00813525,0.00813525,0.00813525,0.00813525,0.00596235,0.00596235,0.0107172,0.0107172,0.0107172,0.0107172,0.00635784,0.00635784,0.00635784,0.00635784,0.00964969,0.00964969,0.0220224,0.00681216,0.0142636,0.00622966,0.00622966,0.00396251,0.00921402,0.00921402,0.00921402,0.00921402,0.00921402,0.00921402,0.00934444,0.011987,0.00615085,0.00653319,0.00762563,0.00382699,0.00382699,0.00621165,0.00621165,0.00689886,0.00437418,0.00433127,0.00433127,0.00433127,0.00433127,0.00433127,0.00810899,0.00810899,0.00810899,0.00810899,0.00810899,0.000394136,0.0160785,0.0160785,0.00554884,0.00494828,0.00965244", "train/anneal_lr": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "train/min_lr_ratio": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "train/gamma": "0.995016,0.995279,0.996978,0.996978,0.996978,0.996978,0.996978,0.996978,0.996559,0.995494,0.998816,0.997819,0.995379,0.994896,0.994896,0.994896,0.997608,0.997608,0.994958,0.995957,0.992031,0.884992,0.992122,0.99634,0.995937,0.996563,0.995161,0.995161,0.995161,0.991471,0.995074,0.995074,0.995074,0.995074,0.995074,0.995074,0.996915,0.996915,0.996107,0.996107,0.996107,0.996107,0.996107,0.992514,0.992514,0.992514,0.996029,0.99624,0.993617,0.993617,0.998206,0.996555,0.996351,0.996351,0.996351,0.996351,0.996351,0.996351,0.994668,0.994668,0.994659,0.994659,0.994659,0.994659,0.994659,0.993866,0.993866,0.990633,0.995318,0.995318,0.995318,0.996627,0.987202,0.997144,0.994585,0.993104,0.994032,0.994344,0.994344,0.994344,0.994344,0.994344,0.994344,0.994344,0.994344,0.993117,0.994083,0.994083,0.994083,0.994083,0.994083,0.994083,0.995785,0.995785,0.995785,0.995785,0.995785,0.996323,0.995767,0.994047,0.994047,0.994047,0.994047,0.994047,0.996549,0.996549,0.996549,0.996549,0.996549,0.996549,0.996549,0.995318,0.994739,0.996817,0.996817,0.996817,0.996817,0.996817,0.992783,0.993309,0.993309,0.995178,0.994406,0.994406,0.994406,0.994406,0.994406,0.994406,0.994406,0.999284,0.995953,0.99468,0.993804,0.993804,0.99605,0.99605,0.99605,0.99605,0.99605,0.99342,0.99659,0.99659,0.994146,0.995501,0.992917,0.992917,0.992917,0.992917,0.992822,0.992822,0.992822,0.992822,0.992822,0.992822,0.992822,0.992822,0.992822,0.992959,0.992959,0.992959,0.992959,0.995073,0.995073,0.996413,0.994473,0.994473,0.994473,0.992658,0.994645,0.996149,0.994775,0.990837,0.990837,0.990837,0.990837,0.990837,0.990837,0.990837,0.994818,0.994818,0.994818,0.993728,0.993728,0.993843,0.993843,0.993843,0.993922,0.986807,0.994564,0.994564,0.994564,0.994564,0.994564,0.994564,0.994995,0.994995,0.994096,0.994096,0.994096,0.994096,0.995668,0.995668,0.995668,0.995668,0.993358,0.993358,0.997716,0.996427,0.996847,0.997009,0.997009,0.994851,0.997118,0.997118,0.997118,0.997118,0.997118,0.997118,0.994239,0.995254,0.993979,0.995996,0.993317,0.992433,0.992433,0.997485,0.997485,0.997056,0.993517,0.992154,0.992154,0.992154,0.992154,0.992154,0.995286,0.995286,0.995286,0.995286,0.995286,0.923929,0.999327,0.999327,0.997044,0.993932,0.995943", "train/gae_lambda": "0.630631,0.620416,0.62976,0.62976,0.62976,0.62976,0.62976,0.62976,0.744543,0.870582,0.783465,0.884067,0.893688,0.829147,0.829147,0.829147,0.707167,0.707167,0.879335,0.788773,0.40608,0.974703,0.702458,0.811281,0.879129,0.2,0.796001,0.796001,0.796001,0.565139,0.864064,0.864064,0.864064,0.864064,0.864064,0.864064,0.825249,0.825249,0.730275,0.730275,0.730275,0.730275,0.730275,0.818757,0.818757,0.818757,0.805358,0.84357,0.646124,0.646124,0.69408,0.810493,0.526873,0.526873,0.526873,0.526873,0.526873,0.526873,0.793342,0.793342,0.792214,0.792214,0.792214,0.792214,0.792214,0.81317,0.81317,0.913511,0.732649,0.732649,0.732649,0.792892,0.2,0.653234,0.774816,0.836918,0.864589,0.629619,0.629619,0.629619,0.629619,0.629619,0.629619,0.629619,0.629619,0.864441,0.589374,0.589374,0.589374,0.589374,0.589374,0.589374,0.436316,0.436316,0.436316,0.436316,0.436316,0.596442,0.904077,0.769471,0.769471,0.769471,0.769471,0.769471,0.724945,0.724945,0.724945,0.724945,0.724945,0.724945,0.724945,0.839365,0.752627,0.687682,0.687682,0.687682,0.687682,0.687682,0.876856,0.752903,0.752903,0.767346,0.736298,0.736298,0.736298,0.736298,0.736298,0.736298,0.736298,0.584658,0.811868,0.845916,0.851246,0.851246,0.840714,0.840714,0.840714,0.840714,0.840714,0.7754,0.869456,0.869456,0.83455,0.865335,0.669233,0.669233,0.669233,0.669233,0.703161,0.703161,0.703161,0.703161,0.703161,0.703161,0.703161,0.703161,0.703161,0.702767,0.702767,0.702767,0.702767,0.833924,0.833924,0.751488,0.665831,0.665831,0.665831,0.828533,0.805163,0.628198,0.880065,0.871283,0.871283,0.871283,0.871283,0.871283,0.871283,0.871283,0.716916,0.716916,0.716916,0.819282,0.819282,0.858874,0.858874,0.858874,0.843268,0.863935,0.708666,0.708666,0.708666,0.708666,0.708666,0.708666,0.703427,0.703427,0.802849,0.802849,0.802849,0.802849,0.838457,0.838457,0.838457,0.838457,0.865599,0.865599,0.7342,0.794374,0.993481,0.795614,0.795614,0.747115,0.807607,0.807607,0.807607,0.807607,0.807607,0.807607,0.817997,0.763673,0.819374,0.820541,0.723741,0.757809,0.757809,0.709704,0.709704,0.785312,0.818203,0.670324,0.670324,0.670324,0.670324,0.670324,0.832628,0.832628,0.832628,0.832628,0.832628,0.280076,0.921799,0.921799,0.803122,0.534212,0.778729", "train/replay_ratio": "2.01799,3.44048,2.48062,2.48062,2.48062,2.48062,2.48062,2.48062,2.7287,1.62304,1.61529,1.31601,1.64106,1.49094,1.49094,1.49094,2.82147,2.82147,2.7029,1.54054,4,0.351167,3.06568,2.9347,2.25188,1.81259,2.87597,2.87597,2.87597,1.7169,2.35289,2.35289,2.35289,2.35289,2.35289,2.35289,1.04351,1.04351,1.84539,1.84539,1.84539,1.84539,1.84539,2.44055,2.44055,2.44055,1.11521,2.81372,3.43218,3.43218,2.94519,1.81875,3.22782,3.22782,3.22782,3.22782,3.22782,3.22782,2.07412,2.07412,2.47981,2.47981,2.47981,2.47981,2.47981,2.86156,2.86156,2.0005,2.25664,2.25664,2.25664,2.86446,3.90695,3.60452,2.63175,3.39663,2.49301,4,4,4,4,4,4,4,4,2.37582,1.99921,1.99921,1.99921,1.99921,1.99921,1.99921,2.56183,2.56183,2.56183,2.56183,2.56183,3.91656,2.18915,1.91637,1.91637,1.91637,1.91637,1.91637,2.10134,2.10134,2.10134,2.10134,2.10134,2.10134,2.10134,2.21497,3.2699,2.59565,2.59565,2.59565,2.59565,2.59565,2.39943,1.34684,1.34684,1.3798,3.0166,3.0166,3.0166,3.0166,3.0166,3.0166,3.0166,3.72415,3.02979,1.84045,1.74985,1.74985,1.56697,1.56697,1.56697,1.56697,1.56697,2.21816,2.00599,2.00599,2.85309,2.06557,4,4,4,4,2.74669,2.74669,2.74669,2.74669,2.74669,2.74669,2.74669,2.74669,2.74669,1.48041,1.48041,1.48041,1.48041,2.37578,2.37578,2.04562,3.15054,3.15054,3.15054,1.28722,1.72878,2.861,2.87112,1.9815,1.9815,1.9815,1.9815,1.9815,1.9815,1.9815,1.94946,1.94946,1.94946,2.02413,2.02413,3.42539,3.42539,3.42539,2.56987,1.8803,4,4,4,4,4,4,3.37669,3.37669,1.32903,1.32903,1.32903,1.32903,3.25179,3.25179,3.25179,3.25179,1.60952,1.60952,3.1208,2.98047,0.832749,2.37101,2.37101,2.92543,1.34659,1.34659,1.34659,1.34659,1.34659,1.34659,2.33089,2.71221,2.72774,1.90304,3.00813,2.55258,2.55258,2.07017,2.07017,3.14438,1.91718,2.57092,2.57092,2.57092,2.57092,2.57092,2.05874,2.05874,2.05874,2.05874,2.05874,2.44614,3.14084,3.14084,1.81949,3.86063,2.78261", "train/clip_coef": "0.0167542,0.0264245,0.392939,0.392939,0.392939,0.392939,0.392939,0.392939,0.566322,0.0724073,0.43014,0.270669,0.466411,0.209885,0.209885,0.209885,0.274583,0.274583,0.403768,0.627995,0.534006,0.454747,0.163196,0.348838,0.512097,0.01,0.299016,0.299016,0.299016,0.156334,0.28163,0.28163,0.28163,0.28163,0.28163,0.28163,0.213198,0.213198,0.01,0.01,0.01,0.01,0.01,0.390024,0.390024,0.390024,0.440793,0.276225,0.295651,0.295651,0.858327,0.864354,0.01,0.01,0.01,0.01,0.01,0.01,0.343916,0.343916,0.383502,0.383502,0.383502,0.383502,0.383502,0.523865,0.523865,0.273037,0.102168,0.102168,0.102168,0.191072,0.346946,0.583541,0.544183,0.318219,0.538925,0.159575,0.159575,0.159575,0.159575,0.159575,0.159575,0.159575,0.159575,0.704571,0.361611,0.361611,0.361611,0.361611,0.361611,0.361611,0.01,0.01,0.01,0.01,0.01,0.112027,0.146616,0.398212,0.398212,0.398212,0.398212,0.398212,0.406201,0.406201,0.406201,0.406201,0.406201,0.406201,0.406201,0.396586,0.413443,0.106505,0.106505,0.106505,0.106505,0.106505,0.517043,0.413445,0.413445,0.63347,0.331832,0.331832,0.331832,0.331832,0.331832,0.331832,0.331832,0.7159,0.380829,0.23456,0.576743,0.576743,0.293344,0.293344,0.293344,0.293344,0.293344,0.135562,0.126518,0.126518,0.646931,0.229066,0.110706,0.110706,0.110706,0.110706,0.0220916,0.0220916,0.0220916,0.0220916,0.0220916,0.0220916,0.0220916,0.0220916,0.0220916,0.112713,0.112713,0.112713,0.112713,0.406137,0.406137,0.106908,0.01,0.01,0.01,0.0742602,0.175395,0.138258,0.301941,0.0378503,0.0378503,0.0378503,0.0378503,0.0378503,0.0378503,0.0378503,0.604558,0.604558,0.604558,0.435947,0.435947,0.378554,0.378554,0.378554,0.369557,0.21944,0.46717,0.46717,0.46717,0.46717,0.46717,0.46717,0.36977,0.36977,0.345404,0.345404,0.345404,0.345404,0.50198,0.50198,0.50198,0.50198,0.175614,0.175614,0.791653,0.261068,0.723699,0.252942,0.252942,0.0630778,0.316651,0.316651,0.316651,0.316651,0.316651,0.316651,0.369575,0.498898,0.310922,0.077295,0.334724,0.01,0.01,0.0884527,0.0884527,0.232271,0.409155,0.483407,0.483407,0.483407,0.483407,0.483407,0.394834,0.394834,0.394834,0.394834,0.394834,0.400663,0.913192,0.913192,0.0913113,0.01,0.565711", "train/vf_coef": "1.74801,3.16128,3.24932,3.24932,3.24932,3.24932,3.24932,3.24932,3.71604,4.493,4.43322,2.98696,4.93883,3.15656,3.15656,3.15656,3.82693,3.82693,2.52937,3.96166,3.05842,3.67376,1.88264,3.71804,2.63964,4.26725,2.15731,2.15731,2.15731,0.675809,3.25266,3.25266,3.25266,3.25266,3.25266,3.25266,2.78248,2.78248,2.906,2.906,2.906,2.906,2.906,2.59884,2.59884,2.59884,2.65098,2.24106,3.0543,3.0543,2.88541,3.19108,2.81815,2.81815,2.81815,2.81815,2.81815,2.81815,2.66224,2.66224,1.46694,1.46694,1.46694,1.46694,1.46694,3.81179,3.81179,3.07471,1.87328,1.87328,1.87328,3.43727,2.18392,2.34781,3.8698,2.23099,4.52768,3.20609,3.20609,3.20609,3.20609,3.20609,3.20609,3.20609,3.20609,3.74857,3.39828,3.39828,3.39828,3.39828,3.39828,3.39828,2.92849,2.92849,2.92849,2.92849,2.92849,2.30918,2.90433,4.72131,4.72131,4.72131,4.72131,4.72131,4.56984,4.56984,4.56984,4.56984,4.56984,4.56984,4.56984,3.13705,2.89355,2.01177,2.01177,2.01177,2.01177,2.01177,4.47132,4.41179,4.41179,2.89285,3.5397,3.5397,3.5397,3.5397,3.5397,3.5397,3.5397,1.5177,2.1872,3.28957,4.42917,4.42917,3.74083,3.74083,3.74083,3.74083,3.74083,3.46242,1.3815,1.3815,1.41375,3.9457,2.68485,2.68485,2.68485,2.68485,2.6876,2.6876,2.6876,2.6876,2.6876,2.6876,2.6876,2.6876,2.6876,1.08385,1.08385,1.08385,1.08385,4.3877,4.3877,4.11491,3.77985,3.77985,3.77985,5,3.46171,2.82828,4.65121,0.681552,0.681552,0.681552,0.681552,0.681552,0.681552,0.681552,5,5,5,3.79963,3.79963,1.57816,1.57816,1.57816,3.83596,2.66162,2.86927,2.86927,2.86927,2.86927,2.86927,2.86927,2.82201,2.82201,3.67267,3.67267,3.67267,3.67267,3.59191,3.59191,3.59191,3.59191,2.46399,2.46399,2.10248,3.42749,0.143731,4.35086,4.35086,2.39639,4.40189,4.40189,4.40189,4.40189,4.40189,4.40189,2.83123,1.82427,2.68057,3.76899,2.38032,2.06427,2.06427,1.83087,1.83087,2.60274,4.45888,2.36592,2.36592,2.36592,2.36592,2.36592,3.71188,3.71188,3.71188,3.71188,3.71188,4.83041,1.20191,1.20191,3.29032,2.61227,4.58758", "train/vf_clip_coef": "1.34605,1.97878,0.428344,0.428344,0.428344,0.428344,0.428344,0.428344,1.28109,1.53064,0.01,0.01,0.927309,0.01,0.01,0.01,1.73376,1.73376,0.833338,0.897207,1.53543,1.72854,1.18927,0.01,1.41667,0.01,0.859986,0.859986,0.859986,1.19298,1.30123,1.30123,1.30123,1.30123,1.30123,1.30123,0.637438,0.637438,1.87937,1.87937,1.87937,1.87937,1.87937,0.864468,0.864468,0.864468,0.101096,1.0106,1.93525,1.93525,4.83826,1.15482,2.31983,2.31983,2.31983,2.31983,2.31983,2.31983,0.537412,0.537412,0.564594,0.564594,0.564594,0.564594,0.564594,0.882841,0.882841,1.10318,3.23804,3.23804,3.23804,0.01,2.16154,2.73428,0.905141,2.63974,0.01,1.19331,1.19331,1.19331,1.19331,1.19331,1.19331,1.19331,1.19331,0.197227,1.05039,1.05039,1.05039,1.05039,1.05039,1.05039,1.16145,1.16145,1.16145,1.16145,1.16145,2.69451,0.923424,0.911038,0.911038,0.911038,0.911038,0.911038,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,1.15021,2.16726,2.16726,2.16726,2.16726,2.16726,1.21064,1.11665,1.11665,1.65125,1.08173,1.08173,1.08173,1.08173,1.08173,1.08173,1.08173,3.82974,0.781549,0.310367,0.920494,0.920494,0.515043,0.515043,0.515043,0.515043,0.515043,0.01,2.77028,2.77028,2.61956,1.34517,2.32395,2.32395,2.32395,2.32395,1.63454,1.63454,1.63454,1.63454,1.63454,1.63454,1.63454,1.63454,1.63454,1.4709,1.4709,1.4709,1.4709,0.919405,0.919405,0.934138,0.0558171,0.0558171,0.0558171,1.16907,0.01,2.74941,1.35998,2.57025,2.57025,2.57025,2.57025,2.57025,2.57025,2.57025,0.126997,0.126997,0.126997,1.14241,1.14241,0.456055,0.456055,0.456055,0.396092,0.01,0.819935,0.819935,0.819935,0.819935,0.819935,0.819935,1.0036,1.0036,0.734301,0.734301,0.734301,0.734301,0.477348,0.477348,0.477348,0.477348,0.984082,0.984082,3.70512,0.497334,3.60271,0.01,0.01,0.788019,0.43895,0.43895,0.43895,0.43895,0.43895,0.43895,0.527377,2.12999,1.77804,0.01,0.591725,1.70017,1.70017,2.04299,2.04299,1.14816,0.694223,0.787057,0.787057,0.787057,0.787057,0.787057,0.01,0.01,0.01,0.01,0.01,2.07006,3.56163,3.56163,0.01,1.20671,0.01", "train/max_grad_norm": "4.24829,5,2.86789,2.86789,2.86789,2.86789,2.86789,2.86789,2.76822,2.42985,5,1.71415,4.2907,3.7226,3.7226,3.7226,4.06629,4.06629,5,5,3.26565,0.705346,5,3.12325,4.01936,4.6309,2.57473,2.57473,2.57473,2.71734,2.00003,2.00003,2.00003,2.00003,2.00003,2.00003,3.65803,3.65803,3.34956,3.34956,3.34956,3.34956,3.34956,2.15554,2.15554,2.15554,3.3557,3.7176,3.68247,3.68247,4.0459,5,4.93894,4.93894,4.93894,4.93894,4.93894,4.93894,4.0233,4.0233,3.89062,3.89062,3.89062,3.89062,3.89062,1.41853,1.41853,3.03232,1.62994,1.62994,1.62994,3.41705,3.00623,3.30292,1.72664,2.47272,4.3534,4.31581,4.31581,4.31581,4.31581,4.31581,4.31581,4.31581,4.31581,5,4.05973,4.05973,4.05973,4.05973,4.05973,4.05973,3.17648,3.17648,3.17648,3.17648,3.17648,4.76895,4.38678,4.22462,4.22462,4.22462,4.22462,4.22462,4.75077,4.75077,4.75077,4.75077,4.75077,4.75077,4.75077,2.09129,2.43639,2.3416,2.3416,2.3416,2.3416,2.3416,3.13838,3.55573,3.55573,4.84649,2.6111,2.6111,2.6111,2.6111,2.6111,2.6111,2.6111,3.38285,4.21125,4.71393,1.69148,1.69148,3.1787,3.1787,3.1787,3.1787,3.1787,3.04818,0.676711,0.676711,4.72129,2.41749,5,5,5,5,3.15904,3.15904,3.15904,3.15904,3.15904,3.15904,3.15904,3.15904,3.15904,1.7193,1.7193,1.7193,1.7193,3.47989,3.47989,4.35141,2.60384,2.60384,2.60384,3.51611,3.51907,1.59277,1.78161,3.66229,3.66229,3.66229,3.66229,3.66229,3.66229,3.66229,4.46555,4.46555,4.46555,3.15704,3.15704,3.96728,3.96728,3.96728,3.83964,4.02722,3.88808,3.88808,3.88808,3.88808,3.88808,3.88808,3.55105,3.55105,4.80758,4.80758,4.80758,4.80758,1.81552,1.81552,1.81552,1.81552,3.0212,3.0212,4.6575,3.58016,0.218026,3.78337,3.78337,2.82527,2.55221,2.55221,2.55221,2.55221,2.55221,2.55221,5,4.31705,2.50581,3.66819,5,3.67519,3.67519,0.648258,0.648258,4.30745,2.89112,3.01769,3.01769,3.01769,3.01769,3.01769,3.97218,3.97218,3.97218,3.97218,3.97218,4.98374,3.90876,3.90876,2.78627,5,3.02852", "train/ent_coef": "0.0191561,0.0442933,0.0122816,0.0122816,0.0122816,0.0122816,0.0122816,0.0122816,0.0317243,0.0318082,0.107151,0.0109324,0.0218391,0.00737024,0.00737024,0.00737024,0.0216783,0.0216783,0.0144156,0.0299599,0.000156999,5.51496e-05,0.00757678,0.00487738,0.010421,0.000996469,0.00723158,0.00723158,0.00723158,0.000124713,0.0154669,0.0154669,0.0154669,0.0154669,0.0154669,0.0154669,0.034034,0.034034,0.00401469,0.00401469,0.00401469,0.00401469,0.00401469,0.0101135,0.0101135,0.0101135,0.00254678,0.0111593,0.00595867,0.00595867,6.925e-05,0.0104177,0.00408564,0.00408564,0.00408564,0.00408564,0.00408564,0.00408564,0.00778005,0.00778005,0.0410794,0.0410794,0.0410794,0.0410794,0.0410794,0.0128525,0.0128525,0.000715728,0.000661254,0.000661254,0.000661254,0.00699154,0.000165064,0.00134915,0.00620292,0.0141125,0.0161312,0.0218435,0.0218435,0.0218435,0.0218435,0.0218435,0.0218435,0.0218435,0.0218435,0.00911549,0.00699521,0.00699521,0.00699521,0.00699521,0.00699521,0.00699521,0.0223622,0.0223622,0.0223622,0.0223622,0.0223622,0.0261415,0.0248052,0.00936208,0.00936208,0.00936208,0.00936208,0.00936208,0.0263296,0.0263296,0.0263296,0.0263296,0.0263296,0.0263296,0.0263296,0.00274137,0.00195811,0.00248563,0.00248563,0.00248563,0.00248563,0.00248563,0.0018498,0.010042,0.010042,0.00606643,0.0104559,0.0104559,0.0104559,0.0104559,0.0104559,0.0104559,0.0104559,0.00325257,0.0292041,0.0102407,0.0296693,0.0296693,0.00392498,0.00392498,0.00392498,0.00392498,0.00392498,0.0101327,0.0154867,0.0154867,0.0199551,0.00207074,0.00880244,0.00880244,0.00880244,0.00880244,0.0184801,0.0184801,0.0184801,0.0184801,0.0184801,0.0184801,0.0184801,0.0184801,0.0184801,2.64351e-05,2.64351e-05,2.64351e-05,2.64351e-05,0.00538068,0.00538068,0.0231728,0.00462001,0.00462001,0.00462001,0.0206597,0.0591673,0.0194147,0.00836935,0.0420171,0.0420171,0.0420171,0.0420171,0.0420171,0.0420171,0.0420171,0.00907011,0.00907011,0.00907011,0.0210142,0.0210142,0.014592,0.014592,0.014592,0.0241536,0.00567621,0.0697316,0.0697316,0.0697316,0.0697316,0.0697316,0.0697316,0.0377998,0.0377998,0.044918,0.044918,0.044918,0.044918,0.00429502,0.00429502,0.00429502,0.00429502,0.00871481,0.00871481,0.000474924,0.00819717,1.6703e-05,0.00351393,0.00351393,0.00199607,0.0424448,0.0424448,0.0424448,0.0424448,0.0424448,0.0424448,0.00568365,0.00300812,0.00176231,0.00399925,0.0265165,0.0219868,0.0219868,0.0023327,0.0023327,0.00299286,0.0275486,0.0083638,0.0083638,0.0083638,0.0083638,0.0083638,0.0341307,0.0341307,0.0341307,0.0341307,0.0341307,0.0132135,0.00458782,0.00458782,0.00961985,0.00134946,0.0257846", "train/beta1": "0.927378,0.916433,0.876586,0.876586,0.876586,0.876586,0.876586,0.876586,0.909473,0.934153,0.954639,0.931816,0.911263,0.923917,0.923917,0.923917,0.915765,0.915765,0.848161,0.908024,0.5,0.994118,0.97911,0.906484,0.823622,0.931331,0.85507,0.85507,0.85507,0.998199,0.868088,0.868088,0.868088,0.868088,0.868088,0.868088,0.934741,0.934741,0.952056,0.952056,0.952056,0.952056,0.952056,0.902828,0.902828,0.902828,0.942474,0.888604,0.942829,0.942829,0.966065,0.859315,0.946061,0.946061,0.946061,0.946061,0.946061,0.946061,0.889682,0.889682,0.914932,0.914932,0.914932,0.914932,0.914932,0.920464,0.920464,0.88209,0.940114,0.940114,0.940114,0.935976,0.698839,0.524586,0.965744,0.934678,0.911928,0.940864,0.940864,0.940864,0.940864,0.940864,0.940864,0.940864,0.940864,0.837588,0.955774,0.955774,0.955774,0.955774,0.955774,0.955774,0.938816,0.938816,0.938816,0.938816,0.938816,0.940764,0.91598,0.973487,0.973487,0.973487,0.973487,0.973487,0.939065,0.939065,0.939065,0.939065,0.939065,0.939065,0.939065,0.908428,0.935,0.942706,0.942706,0.942706,0.942706,0.942706,0.944719,0.952286,0.952286,0.945338,0.919385,0.919385,0.919385,0.919385,0.919385,0.919385,0.919385,0.918789,0.95138,0.959633,0.891139,0.891139,0.920855,0.920855,0.920855,0.920855,0.920855,0.972577,0.94773,0.94773,0.842785,0.853747,0.979584,0.979584,0.979584,0.979584,0.97197,0.97197,0.97197,0.97197,0.97197,0.97197,0.97197,0.97197,0.97197,0.998558,0.998558,0.998558,0.998558,0.897915,0.897915,0.92371,0.954455,0.954455,0.954455,0.941807,0.962468,0.928447,0.855817,0.975379,0.975379,0.975379,0.975379,0.975379,0.975379,0.975379,0.93224,0.93224,0.93224,0.816148,0.816148,0.852875,0.852875,0.852875,0.950188,0.947403,0.89872,0.89872,0.89872,0.89872,0.89872,0.89872,0.92771,0.92771,0.958672,0.958672,0.958672,0.958672,0.932414,0.932414,0.932414,0.932414,0.921983,0.921983,0.882991,0.934632,0.99555,0.954971,0.954971,0.966342,0.913276,0.913276,0.913276,0.913276,0.913276,0.913276,0.835856,0.868158,0.951583,0.932797,0.898583,0.916734,0.916734,0.927581,0.927581,0.919318,0.935639,0.886107,0.886107,0.886107,0.886107,0.886107,0.928738,0.928738,0.928738,0.928738,0.928738,0.95699,0.831777,0.831777,0.955585,0.934197,0.896784", "train/beta2": "0.99999,0.999901,0.928273,0.928273,0.928273,0.928273,0.928273,0.928273,0.969853,0.999025,0.999105,0.990269,0.999385,0.9877,0.9877,0.9877,0.998705,0.998705,0.999821,0.980602,0.999913,0.995267,0.999982,0.990591,0.999802,0.998721,0.992895,0.992895,0.992895,0.999356,0.999802,0.999802,0.999802,0.999802,0.999802,0.999802,0.996328,0.996328,0.99998,0.99998,0.99998,0.99998,0.99998,0.991584,0.991584,0.991584,0.971653,0.999928,0.99999,0.99999,0.99999,0.999899,0.999986,0.999986,0.999986,0.999986,0.999986,0.999986,0.991812,0.991812,0.999912,0.999912,0.999912,0.999912,0.999912,0.994926,0.994926,0.999587,0.99999,0.99999,0.99999,0.985367,0.99992,0.999987,0.9,0.999988,0.9,0.99999,0.99999,0.99999,0.99999,0.99999,0.99999,0.99999,0.99999,0.999532,0.989012,0.989012,0.989012,0.989012,0.989012,0.989012,0.99999,0.99999,0.99999,0.99999,0.99999,0.999972,0.985724,0.910186,0.910186,0.910186,0.910186,0.910186,0.990525,0.990525,0.990525,0.990525,0.990525,0.990525,0.990525,0.979306,0.930435,0.99999,0.99999,0.99999,0.99999,0.99999,0.9273,0.999186,0.999186,0.999984,0.987493,0.987493,0.987493,0.987493,0.987493,0.987493,0.987493,0.999929,0.999963,0.99606,0.9,0.9,0.998073,0.998073,0.998073,0.998073,0.998073,0.993881,0.999912,0.999912,0.999937,0.9,0.999987,0.999987,0.999987,0.999987,0.999989,0.999989,0.999989,0.999989,0.999989,0.999989,0.999989,0.999989,0.999989,0.999807,0.999807,0.999807,0.999807,0.952012,0.952012,0.996478,0.999982,0.999982,0.999982,0.995691,0.968522,0.99999,0.998701,0.99999,0.99999,0.99999,0.99999,0.99999,0.99999,0.99999,0.926859,0.926859,0.926859,0.975422,0.975422,0.99999,0.99999,0.99999,0.966479,0.99273,0.999931,0.999931,0.999931,0.999931,0.999931,0.999931,0.999981,0.999981,0.999957,0.999957,0.999957,0.999957,0.982486,0.982486,0.982486,0.982486,0.918285,0.918285,0.99998,0.997772,0.906848,0.980928,0.980928,0.99999,0.999376,0.999376,0.999376,0.999376,0.999376,0.999376,0.999964,0.99976,0.971018,0.927841,0.999315,0.99999,0.99999,0.99999,0.99999,0.999983,0.90019,0.999941,0.999941,0.999941,0.999941,0.999941,0.970474,0.970474,0.970474,0.970474,0.970474,0.999671,0.999967,0.999967,0.977532,0.999988,0.993648", "train/eps": "2.05889e-10,0.0001,2.01651e-06,2.01651e-06,2.01651e-06,2.01651e-06,2.01651e-06,2.01651e-06,1.30489e-06,1.2101e-08,1.51858e-14,1.51745e-06,4.7451e-09,5.54687e-09,5.54687e-09,5.54687e-09,5.66593e-11,5.66593e-11,2.63098e-13,9.17614e-07,2.77222e-10,2.70758e-06,0.0001,1.90284e-09,5.71145e-12,1.54355e-12,4.17588e-06,4.17588e-06,4.17588e-06,1.78882e-08,1.05254e-10,1.05254e-10,1.05254e-10,1.05254e-10,1.05254e-10,1.05254e-10,1.52271e-09,1.52271e-09,5.19966e-10,5.19966e-10,5.19966e-10,5.19966e-10,5.19966e-10,2.3237e-06,2.3237e-06,2.3237e-06,6.19628e-10,1.81241e-10,2.26518e-07,2.26518e-07,3.58712e-12,1.39846e-12,1.31418e-05,1.31418e-05,1.31418e-05,1.31418e-05,1.31418e-05,1.31418e-05,7.14993e-07,7.14993e-07,1.82762e-10,1.82762e-10,1.82762e-10,1.82762e-10,1.82762e-10,3.23256e-05,3.23256e-05,7.83056e-11,5.84559e-11,5.84559e-11,5.84559e-11,7.81419e-05,1.53502e-13,2.2264e-12,1.85597e-05,1.66752e-05,1.79692e-06,1.14048e-05,1.14048e-05,1.14048e-05,1.14048e-05,1.14048e-05,1.14048e-05,1.14048e-05,1.14048e-05,8.48907e-12,5.07109e-09,5.07109e-09,5.07109e-09,5.07109e-09,5.07109e-09,5.07109e-09,1.26002e-11,1.26002e-11,1.26002e-11,1.26002e-11,1.26002e-11,4.03966e-05,1.36835e-09,4.55868e-06,4.55868e-06,4.55868e-06,4.55868e-06,4.55868e-06,1.80819e-06,1.80819e-06,1.80819e-06,1.80819e-06,1.80819e-06,1.80819e-06,1.80819e-06,1.56426e-07,2.03536e-06,2.32755e-09,2.32755e-09,2.32755e-09,2.32755e-09,2.32755e-09,1.79525e-07,3.82572e-12,3.82572e-12,3.80741e-11,2.29146e-07,2.29146e-07,2.29146e-07,2.29146e-07,2.29146e-07,2.29146e-07,2.29146e-07,1.1384e-14,1.34396e-11,8.53495e-05,0.0001,0.0001,9.44015e-10,9.44015e-10,9.44015e-10,9.44015e-10,9.44015e-10,8.0716e-10,3.17747e-14,3.17747e-14,5.15593e-10,6.58983e-05,2.32556e-07,2.32556e-07,2.32556e-07,2.32556e-07,6.21415e-08,6.21415e-08,6.21415e-08,6.21415e-08,6.21415e-08,6.21415e-08,6.21415e-08,6.21415e-08,6.21415e-08,3.28257e-08,3.28257e-08,3.28257e-08,3.28257e-08,3.40279e-05,3.40279e-05,5.92494e-08,4.28348e-13,4.28348e-13,4.28348e-13,1.27071e-08,2.20117e-10,6.27328e-07,1.4421e-06,1.19282e-10,1.19282e-10,1.19282e-10,1.19282e-10,1.19282e-10,1.19282e-10,1.19282e-10,7.24929e-06,7.24929e-06,7.24929e-06,1.607e-08,1.607e-08,1.00934e-09,1.00934e-09,1.00934e-09,6.42646e-07,8.47422e-05,7.10385e-09,7.10385e-09,7.10385e-09,7.10385e-09,7.10385e-09,7.10385e-09,3.87244e-08,3.87244e-08,2.55028e-11,2.55028e-11,2.55028e-11,2.55028e-11,7.11416e-07,7.11416e-07,7.11416e-07,7.11416e-07,5.86651e-09,5.86651e-09,1.25764e-14,6.25319e-09,4.67537e-09,2.27058e-06,2.27058e-06,1.30914e-08,1.08874e-09,1.08874e-09,1.08874e-09,1.08874e-09,1.08874e-09,1.08874e-09,8.62477e-11,1.23205e-11,1.5885e-06,3.13757e-10,2.23394e-13,8.25154e-06,8.25154e-06,8.70771e-12,8.70771e-12,1.61897e-11,9.52102e-08,1.23823e-10,1.23823e-10,1.23823e-10,1.23823e-10,1.23823e-10,3.0282e-05,3.0282e-05,3.0282e-05,3.0282e-05,3.0282e-05,6.69248e-10,3.27706e-13,3.27706e-13,1.91526e-09,1.8449e-06,2.49448e-06", "train/minibatch_size": "65536,32768,16384,16384,16384,16384,16384,16384,16384,32768,32768,16384,32768,16384,16384,16384,32768,32768,16384,16384,16384,16384,32768,16384,32768,65536,32768,32768,32768,32768,16384,16384,16384,16384,16384,16384,16384,16384,65536,65536,65536,65536,65536,16384,16384,16384,8192,16384,65536,65536,65536,16384,65536,65536,65536,65536,65536,65536,16384,16384,16384,16384,16384,16384,16384,32768,32768,16384,65536,65536,65536,32768,32768,32768,16384,65536,32768,65536,65536,65536,65536,65536,65536,65536,65536,16384,16384,16384,16384,16384,16384,16384,65536,65536,65536,65536,65536,65536,16384,32768,32768,32768,32768,32768,16384,16384,16384,16384,16384,16384,16384,16384,16384,65536,65536,65536,65536,65536,16384,16384,16384,32768,16384,16384,16384,16384,16384,16384,16384,65536,16384,32768,32768,32768,32768,32768,32768,32768,32768,16384,32768,32768,32768,16384,65536,65536,65536,65536,65536,65536,65536,65536,65536,65536,65536,65536,65536,32768,32768,32768,32768,16384,16384,16384,65536,65536,65536,16384,16384,65536,16384,65536,65536,65536,65536,65536,65536,65536,16384,16384,16384,16384,16384,16384,16384,16384,16384,16384,65536,65536,65536,65536,65536,65536,32768,32768,16384,16384,16384,16384,16384,16384,16384,16384,16384,16384,65536,16384,16384,16384,16384,65536,16384,16384,16384,16384,16384,16384,16384,16384,16384,16384,16384,32768,32768,65536,65536,16384,16384,65536,65536,65536,65536,65536,32768,32768,32768,32768,32768,65536,65536,65536,16384,65536,32768", "train/horizon": "256,256,64,64,64,64,64,64,64,64,64,32,128,64,64,64,32,32,64,64,512,64,128,32,128,64,128,128,128,256,128,128,128,128,128,128,64,64,128,128,128,128,128,128,128,128,64,128,256,256,256,64,256,256,256,256,256,256,32,32,64,64,64,64,64,64,64,64,256,256,256,32,128,256,64,256,128,512,512,512,512,512,512,512,512,64,64,64,64,64,64,64,128,128,128,128,128,256,64,64,64,64,64,64,32,32,32,32,32,32,32,64,64,256,256,256,256,256,128,128,128,128,32,32,32,32,32,32,32,512,128,64,64,64,128,128,128,128,128,64,256,256,64,64,512,512,512,512,128,128,128,128,128,128,128,128,128,128,128,128,128,64,64,64,128,128,128,32,128,128,32,128,128,128,128,128,128,128,64,64,64,64,64,64,64,64,64,64,512,512,512,512,512,512,64,64,64,64,64,64,64,64,64,64,32,32,512,64,32,64,64,64,64,64,64,64,64,64,64,64,64,64,64,256,256,128,128,64,32,512,512,512,512,512,32,32,32,32,32,128,256,256,32,256,32", "train/vtrace_rho_clip": "2.13453,2.31468,1.84047,1.84047,1.84047,1.84047,1.84047,1.84047,2.09216,2.67091,1.71623,2.7441,2.29329,2.14732,2.14732,2.14732,1.50056,1.50056,1.76469,2.25533,3.39562,1.32963,2.28001,1.59061,1.20766,1.36019,1.89384,1.89384,1.89384,0.682236,2.37881,2.37881,2.37881,2.37881,2.37881,2.37881,1.97089,1.97089,2.10071,2.10071,2.10071,2.10071,2.10071,3.0521,3.0521,3.0521,3.07746,1.31279,0.923974,0.923974,5,1.80075,1.88438,1.88438,1.88438,1.88438,1.88438,1.88438,2.22366,2.22366,2.14584,2.14584,2.14584,2.14584,2.14584,1.86097,1.86097,1.81434,3.02354,3.02354,3.02354,2.53242,4.85008,4.42403,1.07548,1.14761,2.3816,1.27239,1.27239,1.27239,1.27239,1.27239,1.27239,1.27239,1.27239,1.31594,1.4622,1.4622,1.4622,1.4622,1.4622,1.4622,2.36762,2.36762,2.36762,2.36762,2.36762,2.15381,1.60135,1.1542,1.1542,1.1542,1.1542,1.1542,2.19374,2.19374,2.19374,2.19374,2.19374,2.19374,2.19374,2.12786,1.35058,1.87572,1.87572,1.87572,1.87572,1.87572,2.52694,1.39013,1.39013,1.82998,0.844329,0.844329,0.844329,0.844329,0.844329,0.844329,0.844329,3.56728,1.32746,0.650306,1.98422,1.98422,1.67254,1.67254,1.67254,1.67254,1.67254,1.75756,1.48001,1.48001,1.91293,0.763247,1.04403,1.04403,1.04403,1.04403,2.65161,2.65161,2.65161,2.65161,2.65161,2.65161,2.65161,2.65161,2.65161,0.45557,0.45557,0.45557,0.45557,0.39265,0.39265,2.36863,3.47422,3.47422,3.47422,2.43321,2.63574,1.48727,1.60291,1.90614,1.90614,1.90614,1.90614,1.90614,1.90614,1.90614,1.15521,1.15521,1.15521,2.12227,2.12227,1.64655,1.64655,1.64655,2.04203,1.47776,1.56342,1.56342,1.56342,1.56342,1.56342,1.56342,1.21816,1.21816,0.848423,0.848423,0.848423,0.848423,1.56228,1.56228,1.56228,1.56228,2.2617,2.2617,4.97697,2.51842,2.99416,1.64035,1.64035,3.08484,1.72898,1.72898,1.72898,1.72898,1.72898,1.72898,2.16708,1.63986,2.31674,1.92863,1.61869,2.88126,2.88126,1.92293,1.92293,2.32309,2.74619,1.32025,1.32025,1.32025,1.32025,1.32025,1.85442,1.85442,1.85442,1.85442,1.85442,0.198884,4.51468,4.51468,2.18106,2.35674,1.96561", "train/vtrace_c_clip": "2.09038,0.473888,1.78864,1.78864,1.78864,1.78864,1.78864,1.78864,1.66704,1.393,3.49855,1.43281,1.9875,1.57029,1.57029,1.57029,1.24429,1.24429,2.02172,1.59293,1.78044,2.81954,0.941906,1.08943,0.963687,1.53727,1.62379,1.62379,1.62379,4.97682,1.28862,1.28862,1.28862,1.28862,1.28862,1.28862,1.14957,1.14957,0.791248,0.791248,0.791248,0.791248,0.791248,1.77134,1.77134,1.77134,1.7302,1.71498,2.90173,2.90173,0.546423,1.43742,1.47606,1.47606,1.47606,1.47606,1.47606,1.47606,1.54413,1.54413,1.19701,1.19701,1.19701,1.19701,1.19701,0.962959,0.962959,2.11689,1.26059,1.26059,1.26059,1.57569,1.62161,1.59004,1.5311,3.67118,1.40721,2.11104,2.11104,2.11104,2.11104,2.11104,2.11104,2.11104,2.11104,1.45888,1.53984,1.53984,1.53984,1.53984,1.53984,1.53984,1.75251,1.75251,1.75251,1.75251,1.75251,1.71579,1.4018,1.28811,1.28811,1.28811,1.28811,1.28811,1.24941,1.24941,1.24941,1.24941,1.24941,1.24941,1.24941,1.80295,1.06381,1.83448,1.83448,1.83448,1.83448,1.83448,1.87865,2.00364,2.00364,2.05641,1.03343,1.03343,1.03343,1.03343,1.03343,1.03343,1.03343,1.18661,1.49854,1.15787,0.870569,0.870569,1.23242,1.23242,1.23242,1.23242,1.23242,1.69349,1.50013,1.50013,0.99357,2.05762,2.85385,2.85385,2.85385,2.85385,2.23837,2.23837,2.23837,2.23837,2.23837,2.23837,2.23837,2.23837,2.23837,4.28131,4.28131,4.28131,4.28131,1.10846,1.10846,1.86967,1.40992,1.40992,1.40992,1.41825,1.59369,2.88097,1.47437,3.2198,3.2198,3.2198,3.2198,3.2198,3.2198,3.2198,1.29305,1.29305,1.29305,1.98186,1.98186,1.94794,1.94794,1.94794,1.3755,1.70458,3.45487,3.45487,3.45487,3.45487,3.45487,3.45487,0.906684,0.906684,1.67001,1.67001,1.67001,1.67001,0.998243,0.998243,0.998243,0.998243,1.56376,1.56376,0.660777,1.52347,0.939816,1.87547,1.87547,2.44242,1.36859,1.36859,1.36859,1.36859,1.36859,1.36859,2.25478,0.961417,1.53326,1.83344,1.07856,1.81884,1.81884,2.16646,2.16646,1.87342,1.24535,3.08113,3.08113,3.08113,3.08113,3.08113,1.30618,1.30618,1.30618,1.30618,1.30618,4.48427,1.56013,1.56013,1.45373,1.76778,0.913169", "train/prio_alpha": "0.480182,0.837005,1,1,1,1,1,1,0.875535,0.825252,0.970187,1,0.85246,1,1,1,0.763669,0.763669,0.98766,0.887591,0.0796182,0.83944,0.733191,1,1,0.818773,1,1,1,0.372238,0.832685,0.832685,0.832685,0.832685,0.832685,0.832685,1,1,0.547094,0.547094,0.547094,0.547094,0.547094,1,1,1,0.805035,0.891853,1,1,0.212372,0.953451,0.792718,0.792718,0.792718,0.792718,0.792718,0.792718,1,1,0.958869,0.958869,0.958869,0.958869,0.958869,0.8403,0.8403,1,0.558239,0.558239,0.558239,1,0.0121165,0,0.94818,0.84011,0.856421,0.927118,0.927118,0.927118,0.927118,0.927118,0.927118,0.927118,0.927118,0.908946,0.991274,0.991274,0.991274,0.991274,0.991274,0.991274,0.705027,0.705027,0.705027,0.705027,0.705027,0.637431,1,1,1,1,1,1,1,1,1,1,1,1,1,0.783863,0.932338,0.60416,0.60416,0.60416,0.60416,0.60416,1,0.944998,0.944998,0.959654,1,1,1,1,1,1,1,0.0694924,0.804176,0.965734,1,1,1,1,1,1,1,0.880218,0.599883,0.599883,1,1,0.81274,0.81274,0.81274,0.81274,0.354858,0.354858,0.354858,0.354858,0.354858,0.354858,0.354858,0.354858,0.354858,0.354587,0.354587,0.354587,0.354587,0.996355,0.996355,0.791819,0.686267,0.686267,0.686267,0.806991,0.990482,0.663418,0.777998,0.654927,0.654927,0.654927,0.654927,0.654927,0.654927,0.654927,1,1,1,1,1,0.986354,0.986354,0.986354,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0.169289,0.901305,0.549805,1,1,0.442567,0.99645,0.99645,0.99645,0.99645,0.99645,0.99645,0.565947,0.951585,0.975912,0.903082,0.844519,0.155235,0.155235,0.69764,0.69764,0.871279,1,0.951924,0.951924,0.951924,0.951924,0.951924,1,1,1,1,1,0.416326,0.357986,0.357986,1,0.767404,1", "train/prio_beta0": "0.72886,0.895588,0.776875,0.776875,0.776875,0.776875,0.776875,0.776875,0.940867,1,1,0.787704,1,0.814882,0.814882,0.814882,1,1,0.886076,0.546053,1,0.474547,1,0.826867,0.990537,0.912251,1,1,1,0.244989,0.742509,0.742509,0.742509,0.742509,0.742509,0.742509,0.968174,0.968174,1,1,1,1,1,0.626477,0.626477,0.626477,0.876192,0.952143,0.897165,0.897165,1,1,1,1,1,1,1,1,0.615622,0.615622,0.952332,0.952332,0.952332,0.952332,0.952332,0.778394,0.778394,1,1,1,1,0.733933,1,1,0.591853,1,0.675882,1,1,1,1,1,1,1,1,0.527486,0.948656,0.948656,0.948656,0.948656,0.948656,0.948656,0.811159,0.811159,0.811159,0.811159,0.811159,1,0.721449,0.895711,0.895711,0.895711,0.895711,0.895711,0.638109,0.638109,0.638109,0.638109,0.638109,0.638109,0.638109,1,0.862658,0.988532,0.988532,0.988532,0.988532,0.988532,0.683079,0.968329,0.968329,0.67977,0.805587,0.805587,0.805587,0.805587,0.805587,0.805587,0.805587,0.908525,0.792312,0.942905,0.583101,0.583101,0.953421,0.953421,0.953421,0.953421,0.953421,1,0.627926,0.627926,1,0.774629,0.812252,0.812252,0.812252,0.812252,0.950642,0.950642,0.950642,0.950642,0.950642,0.950642,0.950642,0.950642,0.950642,0.333936,0.333936,0.333936,0.333936,0.951987,0.951987,0.800861,0.664403,0.664403,0.664403,0.858574,0.932892,1,0.72444,0.525195,0.525195,0.525195,0.525195,0.525195,0.525195,0.525195,1,1,1,0.699656,0.699656,0.773911,0.773911,0.773911,0.662456,0.855649,1,1,1,1,1,1,0.874747,0.874747,0.727416,0.727416,0.727416,0.727416,0.917541,0.917541,0.917541,0.917541,0.771341,0.771341,0.903614,0.68156,0.740075,0.698416,0.698416,1,1,1,1,1,1,1,0.954939,0.868673,0.770031,0.750669,0.823053,0.920776,0.920776,0.758448,0.758448,0.628718,0.773596,0.812752,0.812752,0.812752,0.812752,0.812752,0.758306,0.758306,0.758306,0.758306,0.758306,0.174225,0.99265,0.99265,0.946616,0.82411,0.64578", "train/use_rnn": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "no_model_upload": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "tsne1": "-23.2816,-26.4359,4.41389,4.41389,4.41333,4.41389,4.41333,4.41389,7.06366,5.13456,-6.60139,4.77093,2.23251,3.56214,3.56218,3.56214,-4.58843,-4.58843,-2.84996,10.0465,-24.2008,-10.4977,-26.4071,7.76811,-2.9094,-19.4954,3.85989,3.85984,3.85989,-32.7226,2.14927,2.14951,2.14857,2.14883,2.14946,2.14885,3.9903,3.9903,-22.3383,-22.3383,-22.3383,-22.3383,-22.3383,4.51509,4.51583,4.51625,4.48716,-2.16253,-22.0557,-22.0557,-24.1055,-2.73632,-25.4418,-25.4406,-25.4418,-25.4406,-25.4406,-25.4406,7.20606,7.20747,-1.77245,-1.77252,-1.77245,-1.77313,-1.77263,8.4343,8.43469,1.68195,-24.1621,-24.1664,-24.1621,9.57528,-24.1987,-24.2039,5.42963,-21.9535,3.33132,-23.5152,-23.2906,-23.2906,-23.2906,-23.5152,-23.5152,-23.2906,-23.2906,-2.16254,0.884207,0.884247,0.884247,0.884124,0.884228,0.884721,-20.0153,-20.0151,-20.015,-20.0152,-20.0153,-25.3401,1.87429,3.96188,3.96188,3.96188,3.96188,3.96188,9.94137,10.137,9.86382,10.1477,9.85041,9.81213,10.1371,5.92328,5.03743,-23.9381,-23.9381,-23.9381,-23.9381,-23.9381,3.8564,0.883999,0.884329,-2.05481,8.10901,8.10705,8.10751,8.10252,8.10707,8.10707,8.10321,-24.1899,-2.40856,8.5686,5.92256,5.92256,2.18282,2.18281,2.183,2.18281,2.1825,3.09859,-24.724,-24.724,-3.17038,4.97877,-24.1517,-24.1507,-24.1507,-24.1507,-25.2194,-25.2194,-24.6933,-25.2194,-24.7648,-24.7648,-25.1196,-24.7648,-24.6933,-32.7049,-32.7049,-32.7049,-32.7049,6.87376,6.87376,2.46046,-18.2021,-18.2021,-18.2022,5.14842,2.96855,-22.8774,9.38129,-29.1908,-29.1908,-29.186,-29.186,-29.186,-29.186,-29.1918,4.86212,4.86212,4.86212,5.97311,5.97311,-1.26639,-1.26661,-1.26639,9.26513,8.28184,-21.0962,-21.0495,-21.0495,-21.0495,-21.0495,-21.0495,6.75984,6.75993,-0.954689,-0.954495,-0.954451,-0.954701,6.94765,6.94742,6.94766,6.94767,2.4718,2.47176,-24.1585,3.88457,-0.712664,8.67212,8.67206,-25.1967,3.85245,3.85266,3.85295,3.85268,3.85259,3.85218,-3.4517,-2.84778,6.43573,1.48246,-2.91059,-25.8237,-25.8237,-24.9749,-24.9749,-2.52824,3.67299,-18.5767,-18.5771,-18.5771,-18.5767,-18.5767,10.3896,10.3896,10.3896,10.3898,10.3896,18.8788,-24.2076,-24.2076,3.40812,-25.3041,10.7264", "tsne2": "46.0829,52.9546,35.825,35.825,35.8262,35.825,35.8262,35.825,30.5705,21.5852,32.8281,28.3327,21.0352,24.6858,24.6858,24.6858,30.1758,30.1758,27.4852,22.5453,34.3536,14.9252,52.5977,28.3165,24.751,43.7161,31.2074,31.2074,31.2073,33.8714,28.726,28.7253,28.7255,28.7255,28.7254,28.725,23.4091,23.4091,44.969,44.9691,44.9691,44.9689,44.9689,29.3318,29.3314,29.3324,25.0976,26.5766,53.0565,53.0565,32.2563,23.0396,53.0082,53.0069,53.0082,53.0069,53.0069,53.0069,25.3571,25.3558,26.0152,26.0152,26.0152,26.0193,26.0152,31.4821,31.4822,23.3517,42.9403,42.9396,42.9403,26.1986,34.3475,34.1792,36.756,52.0376,38.0668,53.435,53.8727,53.8727,53.8727,53.435,53.435,53.8727,53.8727,22.7392,24.8487,24.8474,24.8474,24.8497,24.8491,24.8503,44.8176,44.8172,44.8177,44.8175,44.8176,53.9761,25.7532,38.5092,38.5092,38.5092,38.5092,38.5092,23.4944,23.5336,23.4616,23.5349,23.4526,23.4328,23.5335,30.7045,35.1707,44.3085,44.3085,44.3085,44.3085,44.3085,36.7184,21.412,21.4116,21.9723,29.3364,29.3374,29.337,29.3326,29.3373,29.3374,29.3327,32.6716,27.2106,26.1127,37.3745,37.3745,22.4286,22.4285,22.4283,22.4294,22.429,23.7891,40.6209,40.6209,24.9456,36.9709,54.8447,54.8461,54.8461,54.8461,46.3065,46.3065,46.2391,46.3065,46.6235,46.6235,46.1572,46.6235,46.2391,33.8782,33.8782,33.8782,33.8782,35.0224,35.0224,25.8442,45.2176,45.2176,45.2162,21.7962,25.1537,48.3031,30.102,41.6918,41.6918,41.7877,41.7877,41.7877,41.7877,41.6841,39.0924,39.0924,39.0924,26.4222,26.4222,27.6088,27.6104,27.6088,24.4266,25.8414,54.3285,54.167,54.167,54.167,54.167,54.167,28.2212,28.2212,22.4985,22.498,22.498,22.4984,31.327,31.3266,31.327,31.3269,35.8354,35.8354,32.4876,26.7916,11.4282,25.0088,25.0087,45.4222,21.7217,21.7231,21.7248,21.7234,21.7231,21.7202,26.584,25.2858,29.639,36.0823,26.8377,47.2877,47.2877,41.7284,41.7284,28.1585,37.0366,53.1134,53.1126,53.1126,53.1134,53.1134,25.7336,25.7336,25.7336,25.7337,25.7336,34.9531,32.4985,32.4985,24.2752,52.2045,26.7812"}, "tower_climb": {"SPS": "5.94531e+06,1.81802e+06,1.77432e+06,1.77643e+06,1.789e+06,6.50909e+06,1.46715e+06,1.47312e+06,5.97031e+06,3.35014e+06,3.26106e+06,3.7434e+06,3.32735e+06,2.11697e+06,2.0762e+06,2.08881e+06,2.082e+06,2.0792e+06,9.30378e+06,2.92621e+06,2.84147e+06,2.81698e+06,2.58266e+06,2.47108e+06,3.366e+06,3.3602e+06,388775,5.113e+06,3.10552e+06,3.42974e+06,3.27533e+06,2.76322e+06,2.64595e+06,2.56848e+06,2.56539e+06,6.52092e+06,1.49117e+06,3.23904e+06,2.09709e+06,2.59744e+06,4.45947e+06,2.89776e+06,2.85169e+06,2.50348e+06,2.49529e+06,2.42367e+06,5.17388e+06,4.66641e+06,4.57426e+06,3.40827e+06,8.15301e+06,8.14478e+06,7.9747e+06,7.87713e+06,4.46088e+06,4.32664e+06,6.31061e+06,6.04627e+06,4.09773e+06,3.88097e+06,1.20138e+06,4.1319e+06,2.34173e+06,6.55458e+06,6.68391e+06,3.27221e+06,3.22896e+06,5.52354e+06,5.53305e+06,1.52687e+06,582337,575409,573271,637044,635108,634046,4.78844e+06,2.00393e+06,4.41194e+06,4.97934e+06,6.02064e+06,2.42351e+06,2.39987e+06,2.38897e+06,4.5965e+06,776508,773023,770592,3.26073e+06,4.66416e+06,4.59174e+06,7.13267e+06,2.74481e+06,5.3662e+06,6.13507e+06,5.75615e+06,5.39957e+06,5.25588e+06,5.70951e+06,5.50093e+06,6.22906e+06,1.53341e+06,1.53437e+06,1.37036e+06,3.34652e+06,435067,2.63121e+06,1.21324e+06,6.16905e+06,3.39227e+06,891384,5.45709e+06,5.35293e+06,1.65756e+06,2.17835e+06,865682,856452,853878,852355,853443,4.82495e+06,4.84516e+06,4.72009e+06,1.51687e+06,954768,2.65792e+06,4.36156e+06,1.251e+06,1.24246e+06,1.23563e+06,1.23128e+06,4.21905e+06,4.04692e+06,3.87004e+06,3.86023e+06,6.85109e+06,2.8309e+06,1.81646e+06,1.78679e+06,5.88499e+06,622353,610694,531928,1.88636e+06,1.87091e+06,5.28702e+06,4.87635e+06,4.7878e+06,3.7407e+06,4.65289e+06,4.50949e+06,2.86721e+06,834513,3.37596e+06,3.90473e+06,3.78927e+06,482082,485125,486451,3.01755e+06,2.93294e+06,660669,660126,4.05888e+06,2.94067e+06,1.40526e+06,1.40189e+06,1.3923e+06", "agent_steps": "14.6801,152.044,252.707,353.348,401.605,14.6801,13.1072,38.273,14.3992,13.6315,38.7973,13.7983,13.6315,29.3601,85.9832,142.606,199.229,226.492,17.1966,13.7626,39.0314,63.8321,89.5468,99.8769,13.6315,38.7973,18.6122,65.7981,13.6315,13.6315,38.7973,13.6315,38.7973,88.0804,98.5661,14.6801,9.43718,13.6315,12.8249,38.7973,39.3216,13.6315,38.7973,13.3693,13.3693,38.5352,39.7066,14.1558,39.3216,38.7973,15.3092,41.4188,67.6332,92.9038,14.1558,39.3216,14.6801,39.8459,36.7002,246.377,631.243,13.9198,13.3693,14.6801,14.6801,13.6315,38.7973,14.1558,39.8459,38.273,278.659,464.257,649.855,12.7795,37.9453,62.9146,14.1558,38.5352,14.1558,14.1558,15.1295,13.3693,38.5352,63.701,14.1558,192.938,269.484,306.184,13.8785,14.1558,39.3216,14.6801,13.2121,173.876,15.3541,41.3064,40.3702,65.8356,14.6801,39.8459,14.4554,13.1072,38.273,236.978,30.8862,4.98074,13.4922,189.268,15.4665,13.6315,6.29146,14.1558,39.8459,38.273,12.9376,29.3601,84.9347,139.461,193.987,220.201,14.1558,14.1558,39.3216,22.0201,38.273,13.6315,14.1558,38.273,63.4388,88.0804,99.6147,14.1558,39.3216,89.5222,99.6147,14.6801,30.4087,13.3693,38.4369,14.6801,63.9631,88.0804,98.5661,38.7973,63.9631,15.1388,40.5012,64.8479,39.3216,14.1558,39.3216,13.6315,38.273,38.7973,14.4775,39.3216,38.7973,63.9631,88.0804,13.6315,38.7973,12.8451,38.0109,13.9198,13.6315,202.375,282.067,320.864", "uptime": "2.47203,82.4171,138.82,195.548,222.765,2.28845,9.01942,26.076,2.46248,4.06565,11.6744,3.64596,4.10465,13.7535,40.8954,68.0753,95.2349,108.335,1.84166,4.68401,13.4579,22.2387,31.6515,35.8487,4.08753,11.5316,47.6892,12.4884,4.40693,3.95478,11.4716,4.88328,14.2454,33.2149,37.3018,2.27317,6.29805,4.24383,6.15101,14.8747,8.81292,4.67915,13.4612,5.32444,5.32158,15.5831,7.5719,3.03582,8.46904,11.2733,1.89138,5.07352,8.33684,11.5316,3.17976,8.91561,2.31935,6.41216,8.88607,61.7684,519.984,3.41598,5.68567,2.28063,2.21443,4.17064,11.91,2.59009,7.20363,24.8229,477.272,797.417,1121.39,20.0311,59.6245,98.9711,2.91116,18.8444,3.22569,2.83941,2.58391,5.54218,15.9524,26.4747,3.07571,247.599,346.369,393.878,4.25922,3.03104,8.4712,2.0608,5.15587,31.4261,2.49687,6.86615,7.30668,12.0931,2.58661,7.06035,2.41177,8.57805,24.9541,166.943,9.11721,11.4679,5.16579,153.264,2.43571,4.03793,7.05482,2.59818,7.34338,22.6128,6.07816,33.7552,98.4416,162.229,226.146,256.909,2.95697,2.92539,8.18236,14.4326,39.5143,5.09641,3.1874,30.3376,50.5328,70.4262,79.7678,3.32154,9.4566,22.194,24.8057,2.16908,10.6771,7.31278,21.2767,2.49085,100.915,139.848,157.316,20.2755,33.6845,2.82699,7.86879,12.9214,10.1913,3.06499,8.53592,4.73605,45.4541,11.3325,3.69354,10.1639,79.1969,131.14,180.814,4.48812,12.9798,19.4215,57.5392,3.40329,4.60561,139.873,196.683,224.356", "epoch": "56,145,241,336.979,383,7,25,73,109.857,26,74,210.545,26,14,41,68,95,108,65.6,105,297.786,487,683.188,762,26,74,35.5,251,13,26,74,6.5,18.5,42,47,7,4.5,13,12.2308,37,37.5,26,74,25.5,25.5,73.5,605.875,27,75,37,29.2,79,129,177.2,13.5,37.5,14,38,70,469.926,301,106.2,25.5,14,14,13,37,27,76,36.5,531.5,885.5,1239.5,195,579,960,13.5,73.5,54,13.5,28.8571,25.5,73.5,121.5,13.5,92,128.5,146,211.769,27,75,14,50.4,663.286,58.5714,157.571,77,125.571,14,38,220.571,50,146,226,117.821,304,102.938,180.5,118,26,12,27,76,36.5,49.3529,14,40.5,66.5,92.5,105,13.5,27,75,42,36.5,6.5,13.5,36.5,60.5,84,95,13.5,37.5,85.375,95,14,58,25.5,73.3125,28,30.5,42,47,18.5,30.5,57.75,154.5,247.375,75,13.5,37.5,13,36.5,18.5,110.455,300,18.5,30.5,42,13,37,49,145,106.2,13,96.5,134.5,153", "env/perf": "0.271812,0.914309,0.952221,0.964804,0.968392,0.000465664,0.547164,0.747329,0.08719,0.413738,0.684868,0.279925,0.000360867,0.606673,0.882689,0.920112,0.936882,0.939847,0.0752159,0.580344,0.828695,0.861196,0.879707,0.884567,0.355037,0.666878,0.625488,0.757822,0.116191,0.383636,0.716876,0.236123,0.730958,0.848001,0.854648,8.7267e-05,0.000687398,0.190264,0.34592,0.681822,0.570287,0.483037,0.702358,0.336302,0.496516,0.812161,0.64606,0.376045,0.691414,0.695982,0.336221,0.636788,0.701082,0.731685,0.29362,0.633727,0.230895,0.597667,0.665466,0.926589,0.982627,9.12967e-05,0.10215,0.0021316,0.14665,0.426816,0.698513,0.277526,0.566426,0.668035,0.978412,0.990271,0.993741,0.594164,0.804482,0.863134,0.0443921,0.70591,0.210207,0.232851,0.279311,0.472334,0.762528,0.813061,0.167077,0.959135,0.977627,0.982736,0.443262,0.355929,0.579208,0.00780419,0.1001,0.890948,0.371259,0.677866,0.629126,0.717275,0.218914,0.610817,0.199179,0.500998,0.638183,0.949188,0.65448,0.000470316,0.51859,0.949075,0.336992,0.0577868,0.000161998,0.390928,0.633847,0.729629,0.416188,0.651062,0.894696,0.936198,0.959035,0.964891,0.00074053,0.292966,0.614736,0.609833,0.733205,0.0342867,0.16721,0.797502,0.869289,0.906938,0.917237,0.19367,0.676476,0.81979,0.83112,0.0023755,0.676612,0.514385,0.705882,0.297541,0.869149,0.915806,0.929377,0.771176,0.841029,0.423295,0.682141,0.729856,0.641821,0.20588,0.54929,0.248113,0.637218,0.671075,0.556729,0.75638,0.825982,0.910444,0.930872,0.380924,0.653024,0.579726,0.731001,0.343918,0.113197,0.940631,0.962393,0.966409", "env/score": "3.03678,5.30586,5.39187,5.41858,5.42237,0.598731,4.19546,4.87139,2.23393,3.70092,4.63814,3.22932,0.58701,4.31484,5.21521,5.30491,5.34641,5.35599,2.16137,4.19469,5.02594,5.1073,5.15603,5.18926,3.36837,4.61114,4.41037,4.85396,2.19649,3.54375,4.65967,2.93291,4.89596,5.16953,5.18559,0.450971,0.607365,2.7109,3.38779,4.7242,4.25779,3.94315,4.74977,3.33584,3.86435,4.94768,4.57219,3.5519,4.73284,4.78051,3.35999,4.57076,4.74434,4.82549,3.22702,4.58025,2.9286,4.49773,4.45439,5.26569,5.4446,0.423741,2.18642,0.927293,2.54589,3.73294,4.74328,3.22039,4.43605,4.64968,5.43978,5.4722,5.48108,4.32382,4.99696,5.15997,1.78492,4.72844,2.92561,2.89079,3.18295,3.90805,4.90875,5.03941,2.697,5.36913,5.42712,5.44245,3.75754,3.46603,4.40294,1.45899,1.65514,5.13292,3.54997,4.62235,4.5927,4.8312,2.84839,4.49352,2.81852,4.0912,4.57527,5.3604,4.47088,0.392669,4.11217,5.31685,3.39059,1.82943,0.45796,3.56386,4.48815,4.71731,3.71647,4.43804,5.25213,5.35016,5.40278,5.41569,0.671252,3.20606,4.51781,4.36384,4.80566,1.70746,2.59157,4.95167,5.14715,5.25324,5.28488,2.71553,4.71955,5.08387,5.11775,0.824648,4.51871,4.06815,4.75993,3.1433,5.18705,5.30375,5.33414,4.95082,5.11265,3.76148,4.68513,4.82634,4.58147,2.93111,4.36297,3.05953,4.54799,4.61164,4.13863,4.75735,5.06137,5.23763,5.28798,3.51351,4.62094,4.27864,4.82188,3.32857,2.22416,5.35137,5.40383,5.41344", "env/episode_return": "0.888416,2.67708,2.74878,2.77331,2.77897,-0.564238,1.92585,2.3863,0.78266,1.58848,2.32898,1.65867,-0.994746,3.05483,3.82038,3.88911,3.92167,3.92648,0.843068,2.17643,2.79003,2.83667,2.87287,2.88332,0.899235,1.50857,2.66488,2.31003,0.321662,1.71261,2.33099,1.93472,3.815,4.18721,4.21181,-0.700368,11.898,0.556995,1.3802,3.18246,2.13157,2.69005,3.45732,1.17126,1.05895,1.58497,2.29254,2.63823,3.95868,4.28702,1.59465,2.46193,2.59857,2.66285,2.06638,3.27328,1.79312,3.24639,1.28047,1.68345,1.91347,-1.09232,0.42348,-0.438919,1.26555,2.01366,2.83931,1.57613,2.5694,1.8884,2.09113,2.10752,2.11242,2.3544,2.87057,3.00544,0.640003,2.15531,1.57104,1.31862,1.76094,2.27097,3.14436,3.26458,0.935068,1.73595,1.76513,1.77297,2.1079,1.97435,2.77336,0.337463,0.501804,1.8972,1.67866,2.69243,2.80722,3.02906,0.683221,1.80559,0.883245,2.53843,2.96795,2.34839,2.03231,-0.474793,3.13056,1.80918,2.13637,-0.126812,-1.28173,1.27366,1.97143,2.62679,1.43594,2.37705,3.01452,3.10054,3.14743,3.15929,-0.493397,1.75429,2.81573,2.26701,1.57717,0.492519,1.46662,1.97311,2.10653,2.17806,2.19807,1.19392,2.76756,3.11711,3.14864,-0.356853,2.27963,2.19741,2.78812,1.01658,2.60583,2.69777,2.72353,2.8998,2.99873,2.15153,3.19321,3.33963,2.5276,1.41556,2.79404,0.887196,1.72226,1.78787,1.71219,2.12243,2.35977,2.48659,2.53059,1.60498,2.40908,2.415,2.84555,1.94656,0.618082,1.99588,2.03009,2.03633", "env/episode_length": "48.8254,20.6636,18.8477,18.2577,18.1383,34.5143,37.5403,29.6387,54.4335,41.9532,28.6986,48.5432,32.1058,33.034,21.1452,18.9241,17.9739,17.7539,53.3418,36.16,22.735,19.5749,18.5391,18.249,44.7434,33.4839,33.3375,27.2493,54.5279,43.0624,23.282,47.0091,30.309,24.1571,23.6951,31.2661,56.2275,52.1341,45.2733,31.818,36.3618,38.1237,29.6947,46.387,38.8446,24.7697,33.9929,43.5029,31.9025,30.9809,45.3975,34.7648,31.536,29.9159,46.3846,34.8034,47.7848,36.3488,33.3406,20.2632,16.6965,29.5573,55.5422,43.7453,49.3888,41.5702,31.9069,47.0867,37.3773,33.1358,17.6111,16.8011,16.5848,35.3621,25.3137,22.3334,51.2451,30.7045,52.9202,47.8935,47.6127,39.1044,28.5711,25.9365,51.3275,18.0621,16.9314,16.6722,42.416,43.2006,36.4404,53.3802,56.1283,18.5235,42.1047,23.9445,34.6472,30.5378,49.0168,33.5488,49.6328,38.7321,33.3202,16.9727,31.7513,44.996,37.7498,17.9969,44.2407,55.8251,32.2584,41.4926,32.0548,18.8702,44.8291,31.4456,21.8312,19.719,18.6396,18.3914,49.8289,46.8898,34.7121,34.7182,30.1004,52.045,51.1276,26.7634,22.8187,20.6081,19.9771,47.6042,32.8699,25.9386,25.3844,40.2208,24.3624,37.9147,30.4357,45.9708,22.8926,20.5485,19.9346,28.1806,24.4609,41.9658,31.5446,29.2091,34.5433,48.5906,37.4273,49.5653,34.5735,32.9098,32.9438,17.3711,23.6177,16.9193,15.607,42.5661,33.9186,35.883,29.4474,45.6642,54.372,19.1263,18.0856,17.8985", "env/n": "75907,101730,111297,113672,57833,122744,28763.1,35409.8,67748.4,51386.2,73624.1,47486.2,65079.8,68542.7,99491.1,110946,116708,118033,108829,53994.4,77441,87107.7,81218.9,14372,47825.6,62901.8,16369.9,115658,38675.2,50556.1,92206.8,46028.8,69684.1,86899.2,88351,132200,38932.1,40074.3,44316.4,66033.5,88640.3,56514,70729.8,34766.2,42761.6,63982.1,92591.6,73405.8,98850,67811.5,114332,151132,166393,143356,68233.1,90712.9,88634,115929,82403.1,127465,125597,86597.1,28449.7,99478.8,86649.8,51885.6,65807.1,76458,98432.4,31818.5,29790.9,31207.8,31613,11634.4,15575.2,17620.9,62926.6,51724.4,53627.1,67090.8,82901.9,41881.2,55117.6,60685.5,60874.4,116255,123900,125929,47728.1,73341.9,86430.9,95197.2,31254.5,180943,94807.9,151396,106183,115260,86397.2,126163,76468.1,27290.2,31507,61875,69899.5,5929.81,43854.4,58351.1,85649.1,38082.5,31382.2,87617.9,114776,56221,33224.1,71972.8,96222.8,106444,112535,113961,66888.8,68015,90912.6,31489.9,34921.9,41128.8,62261.5,39366.7,46033.5,50914.8,52499,67542,96315.5,116208,41266,112385,98298.4,42383.4,50644.9,81368.1,91865.9,102169,105292,74861.2,85852.9,80251.6,98829.4,100976,76178.7,66295.5,84326.1,42655.8,30441.4,64071.7,80426.6,136429,90891.5,124433,134408,50264.7,61932.3,15026.4,17825,56373.6,38518.2,109733,115977,117234", "perf/rollout": "0.47944,0.314447,0.341909,0.337187,0.165837,0.393608,0.124164,0.119943,0.532302,0.251809,0.269064,0.446899,0.45005,0.278235,0.296829,0.290757,0.294027,0.295395,0.573022,0.286304,0.290902,0.2885,0.296131,0.0859504,0.288492,0.289249,0.250751,0.390576,0.566995,0.357865,0.386884,0.247021,0.280371,0.304135,0.304901,0.497216,0.542065,0.45583,0.527101,0.258368,0.391663,0.289139,0.300703,0.431247,0.247913,0.265956,0.421984,0.357487,0.371454,0.273055,0.4763,0.487396,0.501066,0.417201,0.451855,0.473395,0.412376,0.441653,0.317932,0.348225,0.792988,0.617496,0.479741,0.397276,0.396916,0.381494,0.38974,0.378988,0.386268,0.348351,0.285554,0.296134,0.299459,0.149819,0.151095,0.152439,0.400643,0.551812,0.469359,0.472167,0.538423,0.214692,0.220529,0.223265,0.497706,0.96825,0.980369,0.989735,0.472051,0.382586,0.393578,0.547232,0.391808,0.491687,0.414651,0.428736,0.445356,0.444589,0.434555,0.462719,0.36401,0.157923,0.157119,0.358354,0.445849,0.0580422,0.23498,0.43552,0.422336,0.510209,0.30827,0.378104,0.399584,0.176682,0.39422,0.558388,0.583042,0.59064,0.595144,0.592026,0.410196,0.424074,0.441342,0.222872,0.405073,0.474936,0.530363,0.183233,0.188706,0.193248,0.196069,0.441612,0.47299,0.487124,0.340102,0.372697,0.241165,0.241639,0.250265,0.405593,1.00867,1.02957,1.03431,0.298701,0.307741,0.416738,0.441836,0.429731,0.43302,0.506676,0.52799,0.322918,0.471071,0.234255,0.374468,0.387533,0.679647,0.710489,0.698421,0.320384,0.340703,0.193681,0.192301,0.498514,0.417369,0.707489,0.710812,0.720867", "perf/eval_gpu": "0.0682268,0.0672694,0.0560946,0.0499118,0.0270559,0.0216155,0.0382386,0.0318503,0.103514,0.0463314,0.0440972,0.106307,0.0364146,0.0679372,0.0651465,0.0638892,0.0630625,0.0639586,0.0625914,0.0718037,0.0663629,0.0637378,0.0911653,0.0142942,0.0702812,0.0637553,0.160606,0.080411,0.0995044,0.164852,0.160981,0.0415862,0.0411044,0.0406335,0.0399408,0.0647878,0.0525607,0.0416886,0.112902,0.0442247,0.027729,0.0427465,0.04212,0.0794313,0.0551094,0.0528108,0.0870606,0.0486124,0.0477834,0.0711757,0.0543157,0.0539655,0.053759,0.044137,0.0577096,0.0574684,0.0653564,0.0627921,0.0404165,0.039816,0.213243,0.0823155,0.134251,0.0675315,0.045924,0.0414331,0.0391714,0.04756,0.0473426,0.0904152,0.145869,0.145946,0.146304,0.107899,0.107225,0.106885,0.0551154,0.158984,0.0584771,0.0433413,0.0585753,0.0670923,0.0589631,0.0584522,0.0671691,0.405628,0.405726,0.405432,0.133199,0.0390067,0.0379448,0.0665606,0.0793742,0.0809415,0.101617,0.0925012,0.0798381,0.075365,0.077987,0.0744102,0.0998052,0.033306,0.0327016,0.0734864,0.0311435,0.0414925,0.0512618,0.143385,0.105622,0.0910713,0.114998,0.0422223,0.042115,0.0281319,0.0962779,0.19872,0.194846,0.190244,0.188472,0.1861,0.170508,0.0681063,0.0660789,0.0178201,0.139819,0.0465985,0.0512928,0.0462462,0.0457611,0.0453867,0.0455703,0.073305,0.07062,0.0676488,0.0457415,0.0431544,0.042212,0.0509236,0.0491539,0.05917,0.466269,0.466117,0.465145,0.0615061,0.0611395,0.0547388,0.0508843,0.0483322,0.0310872,0.0464015,0.0465728,0.0440203,0.238482,0.0401568,0.136737,0.131083,0.430776,0.433864,0.42546,0.0123053,0.0123249,0.13639,0.137621,0.0827265,0.21595,0.145933,0.140114,0.146795", "perf/eval_env": "0.386718,0.195117,0.211811,0.21489,0.102557,0.361263,0.0767902,0.0795156,0.391641,0.194296,0.214678,0.317007,0.404057,0.203803,0.223426,0.217846,0.220942,0.221449,0.476275,0.19646,0.207976,0.209183,0.188715,0.0672974,0.19832,0.208069,0.0884625,0.291094,0.463728,0.17721,0.207649,0.198999,0.235788,0.260158,0.262489,0.41821,0.483304,0.405991,0.410787,0.208104,0.357863,0.239656,0.252219,0.34697,0.182142,0.201304,0.304745,0.296138,0.314796,0.194692,0.395784,0.418606,0.432443,0.360846,0.376519,0.408417,0.334568,0.363931,0.268763,0.301222,0.57594,0.526002,0.342608,0.313363,0.340686,0.328757,0.342931,0.317921,0.328779,0.254895,0.138241,0.14862,0.151498,0.0315292,0.0334697,0.0348444,0.340625,0.389699,0.397281,0.385355,0.446296,0.135346,0.148482,0.153028,0.423195,0.559888,0.571907,0.581565,0.304934,0.336245,0.348282,0.461822,0.307205,0.392647,0.291159,0.314135,0.352167,0.354454,0.321962,0.348843,0.227372,0.1175,0.119194,0.283143,0.358797,0.00857935,0.152667,0.290604,0.290828,0.412984,0.187321,0.322168,0.348043,0.14335,0.293476,0.345087,0.365675,0.375705,0.382117,0.383169,0.224363,0.342877,0.361632,0.181552,0.26327,0.426058,0.469028,0.131477,0.137395,0.141648,0.143639,0.358793,0.395042,0.411044,0.288431,0.314496,0.186928,0.169214,0.183075,0.331352,0.538492,0.559559,0.565417,0.228361,0.235335,0.347058,0.378328,0.36982,0.278808,0.447003,0.47289,0.269886,0.22944,0.188101,0.206884,0.228114,0.238439,0.266176,0.260708,0.254855,0.257818,0.0510419,0.0484942,0.393342,0.192979,0.557823,0.566877,0.570327", "perf/train_misc": "0.0165193,0.0300458,0.0300536,0.029749,0.0149658,0.169551,0.0362118,0.0292235,0.00755535,0.0291701,0.0237187,0.00892265,0.0212535,0.105706,0.0747987,0.0748271,0.0748476,0.0751063,0.0135833,0.0145976,0.0132026,0.0128319,0.0122133,0.00298496,0.021707,0.0176698,0.0132873,0.0124875,0.00732267,0.0117443,0.0095034,0.0874342,0.0456632,0.0456209,0.0456509,0.0197118,0.242637,0.0434466,0.0349985,0.0289081,0.0586754,0.0328176,0.0266811,0.00604611,0.0161919,0.0131852,0.0106016,0.0401084,0.0324117,0.0235913,0.0352487,0.0291993,0.0292019,0.0239335,0.0729197,0.049933,0.0375644,0.0255992,0.0354616,0.0323035,0.0306381,0,0.00644737,0.0366951,0.0526489,0.0346122,0.0237624,0.0420353,0.0349432,0.00724491,0.00299785,0.00300023,0.0029978,0.00354025,0.00344297,0.00343563,0.0160603,0.00517281,0.0146815,0.0209758,0.0148383,0.0151069,0.0121891,0.0122006,0.0396232,0.0276496,0.027627,0.0275261,0.0084335,0.0375786,0.0305968,0.0280246,0.00764703,0.00939915,0.0170788,0.0144785,0.0200777,0.0192417,0.0369707,0.025157,0.0181673,0.0278341,0.0249801,0.00597213,0.0173936,0.00501626,0.0233665,0.0149926,0.0149567,0.00753675,0.0304431,0.0431017,0.0358324,0.018295,0.0189357,0.0691872,0.0492229,0.0492415,0.0492323,0.048984,0.0175549,0.0136599,0.0111165,0.0614028,0.00987009,0.0306244,0.039936,0.018893,0.0188622,0.0188761,0.0187926,0.0197513,0.0135577,0.0129959,0.00905514,0.0410951,0.0338541,0.0293169,0.0233594,0.0257898,0.0323674,0.0324548,0.0324637,0.0849889,0.0848597,0.019958,0.0169348,0.0160365,0.0250313,0.0276468,0.0189837,0.0620798,0.00915565,0.0412667,0.0129055,0.0120091,0.052667,0.0523844,0.0525075,0.141635,0.0964799,0.0073304,0.00657703,0.00866577,0.0154439,0.0206473,0.0206443,0.0206077", "perf/train_forward": "0.135841,0.809309,0.809637,0.800733,0.404126,0.304566,0.685624,0.562171,0.0791531,0.427994,0.349858,0.156048,0.199754,0.894055,0.637422,0.638139,0.637593,0.638257,0.0309874,0.344498,0.311212,0.302943,0.276272,0.069931,0.387954,0.316774,1.25403,0.211576,0.149675,0.299157,0.243585,0.888026,0.466169,0.465979,0.466142,0.260167,1.74205,0.235431,0.50572,0.519507,0.301834,0.500007,0.407304,0.23606,0.45255,0.369426,0.173291,0.347802,0.283172,0.318332,0.151454,0.126432,0.126488,0.103698,0.295541,0.203031,0.328278,0.225888,0.311882,0.284236,0.922469,0,0.228653,0.315807,0.281765,0.339558,0.235428,0.289996,0.241243,0.331118,0.611355,0.61167,0.611771,0.477802,0.465349,0.464988,0.357641,0.227842,0.18206,0.209916,0.115558,0.517937,0.42236,0.422593,0.231174,1.70364,1.70375,1.70043,0.131627,0.319435,0.260265,0.199776,0.269841,0.122974,0.212524,0.180633,0.213706,0.205039,0.398666,0.274175,0.22738,0.557005,0.500562,0.401138,0.177206,0.548782,0.374434,0.41433,0.178894,0.123889,1.16347,0.298904,0.249482,0.43715,0.295642,2.54738,1.81552,1.816,1.8158,1.81473,0.33405,0.262315,0.213626,0.468391,0.683541,0.570581,0.238486,0.635712,0.636076,0.636293,0.638007,0.423265,0.290439,0.278306,0.193451,0.306648,0.513619,0.735714,0.587285,0.239421,2.33145,2.33062,2.33485,0.72735,0.727585,0.210965,0.178883,0.169485,0.24262,0.217591,0.150225,0.530377,0.777166,0.344929,0.238215,0.222387,3.5504,3.54507,3.55161,0.402086,0.276925,0.660598,0.596057,0.119387,0.415666,0.764713,0.765086,0.765177", "perf/train": "0.15236,0.839355,0.83969,0.830482,0.419091,0.474117,0.721836,0.591394,0.0867084,0.457164,0.373577,0.164971,0.221008,0.999761,0.712221,0.712966,0.712441,0.713363,0.0445707,0.359096,0.324415,0.315775,0.288485,0.072916,0.409661,0.334443,1.26732,0.224063,0.156998,0.310901,0.253089,0.97546,0.511833,0.5116,0.511793,0.279879,1.98469,0.278878,0.540719,0.548415,0.36051,0.532825,0.433985,0.242106,0.468742,0.382611,0.183893,0.387911,0.315583,0.341923,0.186703,0.155631,0.15569,0.127631,0.368461,0.252963,0.365843,0.251488,0.347344,0.31654,0.953107,0,0.2351,0.352502,0.334414,0.37417,0.25919,0.332032,0.276186,0.338363,0.614353,0.61467,0.614768,0.481342,0.468792,0.468423,0.373701,0.233015,0.196742,0.230892,0.130396,0.533044,0.434549,0.434794,0.270797,1.73129,1.73138,1.72796,0.14006,0.357013,0.290862,0.2278,0.277488,0.132373,0.229603,0.195111,0.233784,0.22428,0.435636,0.299332,0.245547,0.584839,0.525542,0.40711,0.1946,0.553798,0.397801,0.429322,0.193851,0.131425,1.19391,0.342005,0.285314,0.455445,0.314578,2.61657,1.86474,1.86524,1.86503,1.86371,0.351605,0.275974,0.224742,0.529794,0.693411,0.601206,0.278422,0.654605,0.654939,0.655169,0.6568,0.443017,0.303997,0.291302,0.202506,0.347743,0.547473,0.765031,0.610644,0.265211,2.36381,2.36308,2.36731,0.812339,0.812444,0.230923,0.195817,0.185522,0.267651,0.245238,0.169209,0.592457,0.786322,0.386196,0.251121,0.234396,3.60307,3.59745,3.60411,0.543721,0.373405,0.667928,0.602634,0.128052,0.43111,0.785361,0.78573,0.785785", "util/gpu_percent": "59.1429,89.6875,87.9792,88.125,100,80,96,98.3333,53.7143,83.8333,76.6667,59.6364,42,88.2593,67.6667,64.3704,99.5185,100,46.4,89.2143,87.5714,86.4,87,84,88.0833,87.8333,99.5143,78.5714,30.6667,86.1667,83.25,87,87.1667,83.0909,56,60.5,91.375,37.3333,46.9231,84.25,57.875,76.9167,78.5,45,81.125,76.4375,75.375,77.375,72,82.25,52.8,56.2,57.2,51,61.25,49.375,83.8333,70.1667,73.4074,67.6296,100,12.5,49.875,77.8333,64.5,47.9167,70,66.1429,66.5714,69.2917,85.6554,84.8644,84.7429,98.9219,98.9531,98.6032,64.5,46.75,42.5556,38.875,48.1429,96.8125,96.3125,95.625,49.875,100,100,100,61.3077,63.625,59.125,54.2,51.8,61.2143,71.4286,76.5714,68.4286,68.1429,77.5,79,77.7143,88.4167,90.4167,22,49.9286,99.0811,89.375,70.5278,78.4286,37.8333,77.75,70.4286,64,89.25,57.4118,100,100,100,100,100,86.125,61.25,63.625,71.2195,78.625,58.6667,35.625,92.375,90.25,89.3478,50,64.875,61.75,58.875,41,72.5,87.3929,90.625,88.25,67,100,100,100,89.4167,80.9167,61.625,55.875,55.5,64.8889,33,46.375,75.5833,82.6667,83.4167,89.9091,86.9,100,100,100,65.0833,51.3333,94.5625,95.5417,47.9,83.9167,73.5263,63.1053,36", "util/gpu_mem": "6.68076,14.8146,14.8146,14.8146,14.8146,12.5267,9.22921,9.22921,8.43943,8.30102,8.30102,5.98055,7.12857,15.7347,15.7347,15.7347,15.7347,15.7347,20.1227,21.7104,21.7104,21.7104,21.017,18.5406,8.49643,8.49643,16.6466,8.08933,18.8775,10.5808,10.5808,15.3764,15.3764,15.3764,15.3764,23.5673,12.3476,9.76658,22.5881,12.7547,9.85614,9.58745,9.58745,15.3276,10.3447,10.3447,7.63338,8.30916,8.30916,11.4031,7.59267,7.59267,7.59267,7.59267,24.381,24.381,10.6541,10.6541,8.11375,8.11375,18.0388,19.2189,28.7613,10.3772,24.0797,9.93756,9.93756,7.38912,7.38912,16.956,28.2978,28.2978,28.2978,10.247,10.247,10.247,21.6376,17.3468,8.10561,10.6378,8.48829,11.8102,11.8102,11.8102,24.5194,27.0846,27.0846,27.0846,5.25591,8.0649,8.0649,10.825,13.7643,8.64298,7.51939,7.51939,8.84653,8.84653,11.0612,11.0612,5.98055,6.8436,6.8436,25.9284,21.5557,9.1315,6.09454,14.0981,6.81918,22.6304,8.8791,7.59267,7.59267,11.338,20.1813,20.1721,20.1721,20.1721,20.1721,20.1721,14.2772,25.5208,25.5208,7.64152,17.9167,21.1247,9.66887,13.9678,13.9678,13.9678,13.9678,15.5962,15.5962,15.5962,15.5962,10.5075,8.84653,9.39205,9.39205,22.1093,34.4526,34.3085,32.8677,15.7347,15.7347,8.07304,8.07304,8.07304,8.80582,9.05008,9.05008,9.86428,17.6725,14.6029,6.47721,6.47721,38.3101,38.4422,38.4422,8.7814,8.7814,11.4194,11.4194,7.63338,19.5777,21.5236,21.5236,21.5236", "util/vram_used_gb": "1.14148,3.09265,3.09265,3.09265,3.09265,2.54382,1.75281,1.75281,1.56335,1.53015,1.53015,0.973511,1.2489,3.31335,3.31335,3.31335,3.31335,3.31335,4.36597,4.74683,4.74683,4.74683,4.58049,3.98645,1.57703,1.57703,3.5321,1.47937,4.06726,2.07703,2.07703,3.22742,3.22742,3.22742,3.22742,5.19226,2.50085,1.88171,4.95738,2.59851,1.9032,1.83875,1.83875,3.2157,2.02039,2.02039,1.37,1.5321,1.5321,2.27429,1.36023,1.36023,1.36023,1.36023,5.38745,5.38745,2.0946,2.0946,1.48523,1.48523,3.86609,4.14917,6.43823,2.0282,5.31519,1.92273,1.92273,1.3114,1.3114,3.60632,6.32703,6.32703,6.32703,1.99695,1.99695,1.99695,4.72937,3.70007,1.48328,2.0907,1.57507,2.37195,2.37195,2.37195,5.42065,6.03601,6.03601,6.03601,0.799683,1.47351,1.47351,2.13562,2.8407,1.61218,1.34265,1.34265,1.66101,1.66101,2.19226,2.19226,0.973511,1.18054,1.18054,5.75867,4.70972,1.72937,1.00085,2.92078,1.17468,4.96753,1.66882,1.36023,1.36023,2.25867,4.38003,4.37781,4.37781,4.37781,4.37781,4.37781,2.96375,5.66089,5.66089,1.37195,3.83679,4.60632,1.85828,2.88953,2.88953,2.88953,2.88953,3.28015,3.28015,3.28015,3.28015,2.05945,1.66101,1.79187,1.79187,4.84253,7.80347,7.7689,7.42328,3.31335,3.31335,1.47546,1.47546,1.47546,1.65125,1.70984,1.70984,1.90515,3.7782,3.04187,1.09265,1.09265,8.72882,8.7605,8.7605,1.64539,1.64539,2.2782,2.2782,1.37,4.23523,4.70203,4.70203,4.70203", "util/vram_total_gb": "23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272", "util/cpu_mem_gb": "1.10353,1.20184,1.20184,1.20184,1.20184,1.12762,1.29659,1.29659,1.09259,1.14766,1.14766,1.07676,1.09328,1.16637,1.16637,1.16637,1.16637,1.16637,1.01406,1.03854,1.03854,1.03854,1.03854,1.03854,1.2738,1.2738,1.09011,1.11259,1.08804,1.17465,1.17465,1.19566,1.19566,1.19566,1.19566,1.15393,1.11482,1.08923,0.997406,1.17881,1.12991,1.10823,1.10823,1.07135,1.11926,1.11926,1.08721,1.12325,1.12325,1.15461,1.10781,1.10781,1.10781,1.10781,1.02437,1.02437,1.16984,1.16984,1.11447,1.11447,1.10529,0.944984,0.993847,1.15256,1.06021,1.14205,1.14209,1.1255,1.1255,1.09446,1.08125,1.08133,1.08176,1.12151,1.12151,1.12151,1.1235,1.07809,1.07119,1.15695,1.12262,1.31684,1.31684,1.31684,1.03214,1.09233,1.09249,1.09282,1.07841,1.11001,1.11001,1.14418,1.07338,1.11462,1.12336,1.12336,1.12367,1.12367,1.18383,1.18383,1.08441,1.11448,1.11448,1.0989,1.0285,1.07605,1.11213,1.08469,1.09531,1.00105,1.105,1.11798,1.11798,1.2331,0.985764,1.19479,1.19481,1.19481,1.19481,1.19481,1.16465,1.05112,1.05112,1.098,1.07711,1.11582,1.12295,1.19482,1.19482,1.19482,1.19482,1.1548,1.1548,1.1548,1.1548,1.16846,1.18279,1.18054,1.18054,1.06897,1.0494,1.0494,1.0494,1.16625,1.16625,1.09171,1.09171,1.09171,1.13645,1.12383,1.12383,1.09346,1.09317,1.21515,1.11253,1.11253,1.15235,1.15235,1.15235,1.12553,1.12553,1.11058,1.11058,1.09106,1.14172,1.13168,1.13168,1.13168", "wandb": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "slowly": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "save_frames": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "fps": "15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15", "rank": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "world_size": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "gpu_id": "3,4,4,4,4,1,3,3,1,5,5,5,4,3,3,3,3,3,0,0,0,0,0,0,2,2,5,2,4,1,1,4,4,4,4,2,5,2,0,4,1,4,4,4,2,2,4,2,2,3,3,3,3,3,0,0,3,3,1,1,2,0,0,1,0,2,2,4,4,3,3,3,3,4,4,4,4,1,1,2,3,1,1,1,0,4,4,4,2,1,1,2,4,1,1,1,1,1,5,5,2,1,1,4,0,5,3,3,5,0,2,4,4,3,0,3,3,3,3,3,2,0,0,2,5,4,3,1,1,1,1,5,5,5,5,1,3,4,4,0,0,0,0,1,1,3,3,3,5,4,4,4,2,1,5,5,0,0,0,4,4,1,1,4,5,4,4,4", "profile": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "checkpoint_interval": "200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200", "eval_episodes": "10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000", "cudagraphs": "10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10", "seed": "73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73", "reset_state": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "vec/total_agents": "4096,8192,8192,8192,8192,16384,2048,2048,2048,4096,4096,2048,4096,16384,16384,16384,16384,16384,4096,2048,2048,2048,2048,2048,2048,2048,8192,4096,8192,4096,4096,16384,16384,16384,16384,16384,4096,16384,8192,8192,16384,8192,8192,4096,4096,4096,2048,8192,8192,8192,8192,8192,8192,8192,16384,16384,8192,8192,8192,8192,8192,4096,8192,8192,16384,4096,4096,8192,8192,4096,4096,4096,4096,1024,1024,1024,16384,8192,8192,8192,4096,2048,2048,2048,16384,16384,16384,16384,1024,8192,8192,8192,4096,4096,4096,4096,8192,8192,8192,8192,2048,4096,4096,8192,4096,1024,2048,16384,4096,4096,4096,8192,8192,4096,4096,8192,8192,8192,8192,8192,8192,4096,4096,8192,8192,16384,16384,4096,4096,4096,4096,8192,8192,8192,8192,8192,4096,4096,4096,4096,8192,8192,8192,16384,16384,8192,8192,8192,8192,8192,8192,8192,4096,8192,2048,2048,8192,8192,8192,16384,16384,4096,4096,2048,16384,8192,8192,8192", "vec/num_buffers": "5.53482,8,8,8,8,5.6963,7.07762,7.07762,4.14019,5.23623,5.23623,3.93862,2.91146,6.10147,6.10147,6.10147,6.10147,6.10147,6.97357,5.58723,5.58723,5.58723,5.58723,5.58723,5.33573,5.33573,3.29609,7.70696,1.71225,6.08417,6.08417,5.89135,5.89135,5.89135,5.89135,4.40885,1.18636,2.73973,1.37111,5.52931,5.58811,4.24446,4.24446,1.6183,4.60638,4.60638,5.64055,6.00564,6.00564,6.9599,6.52196,6.52196,6.52196,6.52196,4.48631,4.48631,6.09986,6.09986,5.33216,5.33216,1.0836,1,1.65898,5.62444,5.17906,3.67181,3.67181,5.49579,5.49579,1.66455,1.63608,1.63608,1.63608,6.37499,6.37499,6.37499,4.20942,1,3.54654,4.24424,4.79938,6.46977,6.46977,6.46977,3.0709,1,1,1,3.68864,4.27927,4.27927,5.9646,1,5.0885,6.48505,6.48505,5.94693,5.94693,6.8584,6.8584,5.89651,4.222,4.222,2.49458,5.47695,7.6885,6.10224,1,6.53452,1.18641,2.24714,5.80622,5.80622,4.46181,1.24238,3.31455,3.31455,3.31455,3.31455,3.31455,6.39697,4.09639,4.09639,5.99796,1.60318,2.00202,3.22405,4.0935,4.0935,4.0935,4.0935,4.07599,4.07599,4.07599,4.07599,6.11685,7.93099,5.73438,5.73438,5.55275,2.83525,2.83525,2.83525,6.55206,6.55206,5.44068,5.44068,5.44068,6.43547,3.34665,3.34665,3.10372,1,6.10527,6.14509,6.14509,5.98709,5.98709,5.98709,6.26737,6.26737,6.55122,6.55122,3.38322,5.05112,2.26227,2.26227,2.26227", "vec/num_threads": "2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2", "env/num_envs": "1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024,1024", "env/num_maps": "50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50,50", "env/reward_climb_row": "0.227369,0.331803,0.331803,0.331803,0.331803,0.509614,0.33819,0.33819,0.459604,0.404619,0.404619,0.347074,0.370693,0.542817,0.542817,0.542817,0.542817,0.542817,0.386972,0.380307,0.380307,0.380307,0.380307,0.380307,0.183699,0.183699,0.410124,0.328646,0.143558,0.355794,0.355794,0.609054,0.609054,0.609054,0.609054,0.687806,0.678395,0.24301,0.341018,0.540051,0.379029,0.589991,0.589991,0.300264,0.168043,0.168043,0.37819,0.650752,0.650752,0.768121,0.401453,0.401453,0.401453,0.401453,0.553756,0.553756,0.59782,0.59782,0.139005,0.139005,0.173083,0.199554,0.182264,0.412574,0.584484,0.458049,0.458049,0.453099,0.453099,0.262675,0.19863,0.19863,0.19863,0.417651,0.417651,0.417651,0.484089,0.313062,0.496522,0.434785,0.525023,0.487994,0.487994,0.487994,0.417634,0.141859,0.141859,0.141859,0.484931,0.510963,0.510963,0.30934,0.335064,0.193791,0.507497,0.507497,0.46702,0.46702,0.321567,0.321567,0.36076,0.518408,0.518408,0.26315,0.309141,0.963376,0.479416,0.157433,0.5732,0.203642,0.970795,0.348159,0.348159,0.452223,0.308762,0.402459,0.402459,0.402459,0.402459,0.402459,0.0512916,0.49636,0.49636,0.391117,0.178536,0.453148,0.553343,0.244422,0.244422,0.244422,0.244422,0.44266,0.44266,0.44266,0.44266,0.466572,0.392973,0.348108,0.348108,0.303494,0.334478,0.334478,0.334478,0.361998,0.361998,0.442726,0.442726,0.442726,0.416652,0.549461,0.549461,0.29416,0.247033,0.244949,0.345139,0.345139,0.319504,0.319504,0.319504,0.383224,0.383224,0.445667,0.445667,0.504802,0.299685,0.19801,0.19801,0.19801", "env/reward_fall_row": "0,-0.0355525,-0.0355525,-0.0355525,-0.0355525,-0.0645591,0,0,-0.0334065,-0.104868,-0.104868,0,-0.515688,0,0,0,0,0,0,0,0,0,0,0,0,0,-0.0111051,0,0,0,0,0,0,0,0,-0.114834,-0.0234007,-0.0584733,0,0,0,0,0,-0.0177306,0,0,-0.0136706,0,0,-0.029044,0,0,0,0,0,0,0,0,0,0,-0.0183636,-0.196652,0,-0.179136,-0.112075,0,0,-0.0484373,-0.0484373,0,0,0,0,0,0,0,0,0,0,0,-0.0195045,0,0,0,-0.156503,0,0,0,-0.0284368,0,0,0,0,-0.0648235,-0.206193,-0.206193,0,0,-0.128062,-0.128062,-0.137614,0,0,0,0,-0.275664,0,0,0,-0.204525,-0.617596,-0.159645,-0.159645,0,-0.0241525,0,0,0,0,0,-0.0485616,0,0,0,0,-0.0207625,0,0,0,0,0,0,0,0,0,-0.0419146,0,0,0,-0.0737706,-5.783e-05,-5.783e-05,-5.783e-05,0,0,-0.0375488,-0.0375488,-0.0375488,0,-0.114816,-0.114816,-0.15385,0,0,-0.0553031,-0.0553031,-0.0405143,-0.0405143,-0.0405143,0,0,0,0,0,-0.0213026,0,0,0", "env/reward_illegal_move": "-0.00366003,-0.0036624,-0.0036624,-0.0036624,-0.0036624,-0.0024766,-0.000758991,-0.000758991,-0.00629814,-0.00634139,-0.00634139,-0.00573059,-0.00558715,-0.00165889,-0.00165889,-0.00165889,-0.00165889,-0.00165889,-0.00594609,-0.00477752,-0.00477752,-0.00477752,-0.00477752,-0.00477752,-0.00144531,-0.00144531,-0.00550559,-0.00101056,-0.00361871,-0.00372165,-0.00372165,-0.0042633,-0.0042633,-0.0042633,-0.0042633,-0.00527457,-0.00348468,-0.00306938,-0.00405261,-0.00641409,-0.00424545,-0.00669089,-0.00669089,-0.00453676,-0.00317861,-0.00317861,-0.00582583,-0.00713323,-0.00713323,-0.000837501,-0.00102867,-0.00102867,-0.00102867,-0.00102867,-0.000566888,-0.000566888,-0.0048741,-0.0048741,-0.00392475,-0.00392475,-0.00330836,-0.00427999,-0.00294842,-0.00379018,-0.0001,-0.00739763,-0.00739763,-0.0001,-0.0001,-0.00014541,-0.00314522,-0.00314522,-0.00314522,-0.00228082,-0.00228082,-0.00228082,-0.00266907,-0.00174491,-0.00263934,-0.00631587,-0.00249685,-0.00662087,-0.00662087,-0.00662087,-0.00442156,-0.00574217,-0.00574217,-0.00574217,-0.00206954,-0.00366131,-0.00366131,-0.00274394,-0.00590261,-0.00635151,-0.0067565,-0.0067565,-0.0044761,-0.0044761,-0.00429907,-0.00429907,-0.00666027,-0.00247357,-0.00247357,-0.00242313,-0.005469,-0.00130648,-0.00470515,-0.00455137,-0.00505442,-0.00472494,-0.00220363,-0.00488285,-0.00488285,-0.00451105,-0.00215324,-0.00404637,-0.00404637,-0.00404637,-0.00404637,-0.00404637,-0.00574851,-0.00366059,-0.00366059,-0.00283388,-0.00425251,-0.0019936,-0.00421887,-0.00567678,-0.00567678,-0.00567678,-0.00567678,-0.00610678,-0.00610678,-0.00610678,-0.00610678,-0.00740371,-0.0001,-0.0015424,-0.0015424,-0.00467076,-0.00487836,-0.00487836,-0.00487836,-0.00610712,-0.00610712,-0.00411341,-0.00411341,-0.00411341,-0.00405834,-0.00564733,-0.00564733,-0.00265169,-0.00643111,-0.00033205,-0.00319345,-0.00319345,-0.00160142,-0.00160142,-0.00160142,-0.00452212,-0.00452212,-0.0079814,-0.0079814,-0.00425527,-0.0001,-0.00495397,-0.00495397,-0.00495397", "env/reward_move_block": "0,0.0299792,0.0299792,0.0299792,0.0299792,0,0,0,0,0,0,0.137233,0.532481,0.0823826,0.0823826,0.0823826,0.0823826,0.0823826,0.116745,0.0626937,0.0626937,0.0626937,0.0626937,0.0626937,0.00868096,0.00868096,0.111868,0,0.0162011,0.107619,0.107619,0.0663229,0.0663229,0.0663229,0.0663229,0,0.956192,0,0,0.00380154,0,0.0336724,0.0336724,0.0192757,0,0,0,0.0878304,0.0878304,0,0,0,0,0,0.0722703,0.0722703,0,0,0.0347626,0.0347626,0,0,0.0223513,0,0,0,0,0.058598,0.058598,0.00115876,0.0346094,0.0346094,0.0346094,0,0,0,0,0.00366405,0,0,0,0,0,0,0,0.0261147,0.0261147,0.0261147,0,0,0,0.0873347,0.0259928,0.0837928,0.0148832,0.0148832,0.068741,0.068741,0,0,0.023737,0,0,0.0371063,0.073344,0.40945,0.13748,0.0542444,0,0,0.218574,0,0,0,0,0.0204384,0.0204384,0.0204384,0.0204384,0.0204384,0,0,0,0,0,0.0190427,0,0,0,0,0,0.0405768,0.0405768,0.0405768,0.0405768,0.0118181,0,0.0774434,0.0774434,0.0646931,0.0187704,0.0187704,0.0187704,0.0900872,0.0900872,0.0977952,0.0977952,0.0977952,0,0.0334582,0.0334582,0.0701466,0.00968633,0,0,0,0,0,0,0.0308113,0.0308113,0,0,0,0.0137976,0,0,0", "policy/hidden_size": "256,512,512,512,512,128,256,256,256,256,256,256,64,512,512,512,512,512,128,256,256,256,256,256,128,128,1024,512,256,512,512,256,256,256,256,256,64,512,512,256,128,256,256,512,512,512,128,256,256,512,256,256,256,256,512,512,256,256,256,256,512,256,512,256,128,256,256,128,128,512,1024,1024,1024,1024,1024,1024,256,512,512,128,128,256,256,256,256,1024,1024,1024,512,128,128,256,256,256,256,256,256,256,256,256,128,256,256,512,128,512,256,1024,256,256,512,128,128,256,512,512,512,512,512,512,512,256,256,512,1024,256,128,512,512,512,512,256,256,256,256,128,256,256,256,128,1024,1024,1024,512,512,256,256,256,128,128,128,512,1024,512,512,512,1024,1024,1024,128,128,1024,1024,128,512,512,512,512", "policy/num_layers": "3.13953,4.30823,4.30823,4.30823,4.30823,1,4.35761,4.35761,3.80881,4.90841,4.90841,5.70739,3.90996,3.79107,3.79107,3.79107,3.79107,3.79107,1.96378,6.05644,6.05644,6.05644,6.05644,6.05644,6.00738,6.00738,4.03524,3.1092,5.13551,5.58106,5.58106,7.95821,7.95821,7.95821,7.95821,5.09688,2.93897,1.74741,2.96752,6.00512,5.29778,5.69075,5.69075,2.74383,3.13671,3.13671,5.87515,4.82961,4.82961,3.9136,2.67557,2.67557,2.67557,2.67557,2.74963,2.74963,4.73472,4.73472,4.51657,4.51657,5.20462,2.27403,4.24672,4.05784,7.36216,2.83009,2.83009,6.11472,6.11472,4.80384,5.2583,5.2583,5.2583,4.48723,4.48723,4.48723,6.29065,5.17065,1.97384,6.92669,3.52646,6.50337,6.50337,6.50337,5.47415,3.05471,3.05471,3.05471,2.74626,5.48468,5.48468,3.58344,4.62101,5.23797,5.86893,5.86893,6.21071,6.21071,5.79983,5.79983,4.38329,7.7568,7.7568,4.25721,4.55431,7.62385,4.96354,2.66298,5.97418,4.78944,7.76868,5.25611,5.25611,6.65065,2.37147,6.60782,6.60782,6.60782,6.60782,6.60782,4.73324,4.1834,4.1834,2.63143,2.61857,4.01796,8,4.09834,4.09834,4.09834,4.09834,6.8154,6.8154,6.8154,6.8154,4.40204,4.66747,7.78148,7.78148,4.17676,4.84803,4.84803,4.84803,3.39214,3.39214,4.93636,4.93636,4.93636,6.24134,5.23115,5.23115,1.43598,4.77498,2.2405,3.81038,3.81038,4.82043,4.82043,4.82043,3.55602,3.55602,4.46517,4.46517,5.05883,8,4.36132,4.36132,4.36132", "policy/expansion_factor": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "train/gpus": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "train/seed": "42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42", "train/total_timesteps": "100,402.161,402.161,402.161,402.161,100,100,100,100,100,100,100,100,228.153,228.153,228.153,228.153,228.153,100,100,100,100,100,100,100,100,146.415,100,473.042,100,100,100,100,100,100,100,320.214,100,100,100,296.795,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,279.846,279.846,631.676,100,100,100,100,100,100,100,100,100,742.453,742.453,742.453,100,100,100,100,100,100,100,100,100,100,100,100,307.399,307.399,307.399,100,100,100,100,769.161,195.483,103.757,103.757,100,100,100,100,100,100,100,237.283,230.358,193.01,100,301.446,100,100,229.673,100,100,100,100,220.901,220.901,220.901,220.901,220.901,100,100,100,171.729,100,100,100,100,100,100,100,100,100,100,100,100,232.467,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,321.646,321.646,321.646", "train/learning_rate": "0.00464742,0.00448069,0.00448069,0.00448069,0.00448069,0.0192796,0.0147311,0.0147311,0.0132427,0.0119276,0.0119276,0.00929287,2.30877e-05,0.00537605,0.00537605,0.00537605,0.00537605,0.00537605,0.00919022,0.00548225,0.00548225,0.00548225,0.00548225,0.00548225,0.00819334,0.00819334,0.00398794,0.00680554,0.1,0.019268,0.019268,0.00694827,0.00694827,0.00694827,0.00694827,0.00491381,0.00223477,0.0162367,0.0166289,0.00685842,0.0134852,0.0120733,0.0120733,0.026206,0.0148548,0.0148548,0.0118292,0.0191399,0.0191399,0.0157452,0.0169034,0.0169034,0.0169034,0.0169034,0.0167548,0.0167548,0.0127115,0.0127115,0.0055733,0.0055733,0.0103182,0.07679,0.00575628,0.0103213,0.0158296,0.00881573,0.00881573,0.00881051,0.00881051,0.00814835,0.00315176,0.00315176,0.00315176,0.0158312,0.0158312,0.0158312,0.00922491,0.0141131,0.0129265,0.0164944,0.016833,0.0189976,0.0189976,0.0189976,0.00850086,0.0162637,0.0162637,0.0162637,0.0108815,0.00916646,0.00916646,0.00216742,0.1,0.00805761,0.0104805,0.0104805,0.0139782,0.0139782,0.00687839,0.00687839,0.00868604,0.0130952,0.0130952,0.0124847,0.00965824,0.0694678,0.00942362,0.00815773,0.018355,0.00743673,0.0590063,0.0202128,0.0202128,0.00850131,0.0155672,0.00588382,0.00588382,0.00588382,0.00588382,0.00588382,0.0132652,0.0136928,0.0136928,0.00808783,0.0117811,0.00263583,0.00553464,0.00564289,0.00564289,0.00564289,0.00564289,0.0117084,0.0117084,0.0117084,0.0117084,0.0120214,0.00534746,0.00791782,0.00791782,0.00760214,0.00595061,0.00595061,0.00595061,0.00512122,0.00512122,0.0127875,0.0127875,0.0127875,0.00428087,0.0155951,0.0155951,0.00481982,0.00876959,0.0250766,0.0128368,0.0128368,0.00812368,0.00812368,0.00812368,0.00471233,0.00471233,0.0141461,0.0141461,0.00855194,0.00635968,0.00636076,0.00636076,0.00636076", "train/anneal_lr": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "train/min_lr_ratio": "0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1", "train/gamma": "0.883099,0.835548,0.835548,0.835548,0.835548,0.8,0.8,0.8,0.934858,0.912944,0.912944,0.8,0.961292,0.875434,0.875434,0.875434,0.875434,0.875434,0.804192,0.908905,0.908905,0.908905,0.908905,0.908905,0.872112,0.872112,0.8,0.916838,0.973148,0.966755,0.966755,0.8,0.8,0.8,0.8,0.971296,0.809162,0.8,0.8,0.8,0.8,0.819815,0.819815,0.979158,0.978259,0.978259,0.880323,0.816995,0.816995,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.8,0.9472,0.9472,0.920793,0.991311,0.8,0.962486,0.8,0.8,0.8,0.8,0.8,0.84506,0.910183,0.910183,0.910183,0.8517,0.8517,0.8517,0.8,0.915306,0.957174,0.858209,0.8,0.8,0.8,0.8,0.8,0.924149,0.924149,0.924149,0.870286,0.8,0.8,0.874888,0.988011,0.967438,0.912244,0.912244,0.806791,0.806791,0.940584,0.940584,0.8,0.81325,0.81325,0.92154,0.947094,0.999812,0.823306,0.9612,0.8,0.950317,0.995106,0.924961,0.924961,0.924769,0.921187,0.839316,0.839316,0.839316,0.839316,0.839316,0.853837,0.8,0.8,0.848925,0.8,0.8,0.8,0.893308,0.893308,0.893308,0.893308,0.8,0.8,0.8,0.8,0.8,0.940778,0.8,0.8,0.941675,0.842485,0.842485,0.842485,0.853189,0.853189,0.8,0.8,0.8,0.8,0.826517,0.826517,0.895267,0.8,0.925058,0.948608,0.948608,0.932045,0.932045,0.932045,0.8,0.8,0.8,0.8,0.8,0.8,0.870071,0.870071,0.870071", "train/gae_lambda": "0.526473,0.76057,0.76057,0.76057,0.76057,0.77406,0.393804,0.393804,0.850949,0.95943,0.95943,0.844252,0.944949,0.388111,0.388111,0.388111,0.388111,0.388111,0.792507,0.72069,0.72069,0.72069,0.72069,0.72069,0.509121,0.509121,0.831538,0.315885,0.484249,0.643536,0.643536,0.820224,0.820224,0.820224,0.820224,0.923896,0.990953,0.910509,0.855243,0.2,0.2,0.925282,0.925282,0.651227,0.2,0.2,0.925824,0.785074,0.785074,0.509091,0.909125,0.909125,0.909125,0.909125,0.792852,0.792852,0.869665,0.869665,0.2,0.2,0.593383,0.2,0.758795,0.70909,0.2,0.774187,0.774187,0.2,0.2,0.740447,0.2,0.2,0.2,0.826792,0.826792,0.826792,0.848225,0.695095,0.760111,0.559707,0.753771,0.896122,0.896122,0.896122,0.233275,0.79467,0.79467,0.79467,0.933194,0.906453,0.906453,0.795449,0.851245,0.627811,0.750559,0.750559,0.7494,0.7494,0.7082,0.7082,0.64286,0.74496,0.74496,0.823523,0.393524,0.859229,0.87261,0.840064,0.821548,0.850613,0.857787,0.724617,0.724617,0.2,0.942213,0.517184,0.517184,0.517184,0.517184,0.517184,0.495035,0.922797,0.922797,0.2,0.701203,0.80143,0.421314,0.795877,0.795877,0.795877,0.795877,0.810063,0.810063,0.810063,0.810063,0.896807,0.2,0.638084,0.638084,0.842277,0.816884,0.816884,0.816884,0.432907,0.432907,0.840587,0.840587,0.840587,0.2,0.904213,0.904213,0.453099,0.82567,0.667177,0.706042,0.706042,0.550651,0.550651,0.550651,0.722635,0.722635,0.862163,0.862163,0.942249,0.462319,0.714027,0.714027,0.714027", "train/replay_ratio": "0.27373,1.34854,1.34854,1.34854,1.34854,1.19652,0.938602,0.938602,0.25,0.793752,0.793752,0.381719,1.98599,1.02456,1.02456,1.02456,1.02456,1.02456,0.343556,0.753438,0.753438,0.753438,0.753438,0.753438,0.25,0.25,2.25567,0.25,0.403223,0.25,0.25,0.623272,0.623272,0.623272,0.623272,0.25,3.5014,0.868646,1.14279,1.24183,1.0156,1.33031,1.33031,0.977287,1.08578,1.08578,1.16034,0.546071,0.546071,0.515875,0.25,0.25,0.25,0.25,0.25,0.25,0.25,0.25,0.686723,0.686723,1.10811,0.266553,0.452914,0.25,0.25,1.11883,1.11883,0.25,0.25,1.20257,1.17017,1.17017,1.17017,1.00912,1.00912,1.00912,0.526207,0.478136,0.856218,0.351811,0.561934,0.888365,0.888365,0.888365,0.25,1.29997,1.29997,1.29997,0.25,1.03067,1.03067,0.25,1.33261,0.25,0.25,0.25,0.25,0.25,0.25,0.25,1.1541,1.11658,1.11658,1.48219,1.12938,3.64224,0.838066,0.830986,0.266349,0.43785,0.778395,0.510411,0.510411,0.926878,0.937962,1.82528,1.82528,1.82528,1.82528,1.82528,0.25,0.674344,0.674344,1.52728,1.55373,1.37491,0.25,1.92126,1.92126,1.92126,1.92126,0.605811,0.605811,0.605811,0.605811,0.549084,1.04153,1.06994,1.06994,0.35658,1.13432,1.13432,1.13432,1.19708,1.19708,0.554258,0.554258,0.554258,0.941777,0.25,0.25,1.95852,0.825407,0.396978,0.25,0.25,1.83975,1.83975,1.83975,1.50006,1.50006,0.974878,0.974878,0.998965,0.25,1.36458,1.36458,1.36458", "train/clip_coef": "0.283906,0.381209,0.381209,0.381209,0.381209,0.01,0.41346,0.41346,0.118006,0.238912,0.238912,0.0534561,0.0339736,0.40793,0.40793,0.40793,0.40793,0.40793,0.178666,0.299896,0.299896,0.299896,0.299896,0.299896,0.327502,0.327502,0.527026,0.53626,0.783748,0.517606,0.517606,0.25708,0.25708,0.25708,0.25708,0.01,0.807944,0.486985,0.543539,0.48237,0.282358,0.387535,0.387535,0.497622,0.234329,0.234329,0.322001,0.243266,0.243266,0.249265,0.183927,0.183927,0.183927,0.183927,0.338095,0.338095,0.270295,0.270295,0.367162,0.367162,0.262529,0.818979,0.409749,0.01,0.192206,0.484355,0.484355,0.457882,0.457882,0.571711,0.285754,0.285754,0.285754,0.273372,0.273372,0.273372,0.129179,0.404711,0.374147,0.404278,0.319587,0.229734,0.229734,0.229734,0.363939,0.404362,0.404362,0.404362,0.229797,0.267327,0.267327,0.33386,0.548341,0.543248,0.374214,0.374214,0.0858492,0.0858492,0.572001,0.572001,0.01,0.38603,0.38603,0.430626,0.668928,0.636896,0.0791098,0.391454,0.01,0.41923,0.218549,0.304576,0.304576,0.446405,0.519959,0.394989,0.394989,0.394989,0.394989,0.394989,0.01,0.259616,0.259616,0.194718,0.408544,0.503737,0.486362,0.360904,0.360904,0.360904,0.360904,0.204528,0.204528,0.204528,0.204528,0.01,0.366622,0.443714,0.443714,0.226926,0.626951,0.626951,0.626951,0.415861,0.415861,0.260701,0.260701,0.260701,0.380265,0.303647,0.303647,0.443645,0.423875,0.702029,0.238541,0.238541,0.261394,0.261394,0.261394,0.382478,0.382478,0.318096,0.318096,0.164233,0.556221,0.442559,0.442559,0.442559", "train/vf_coef": "3.94056,5,5,5,5,4.50078,3.09985,3.09985,3.40086,5,5,4.90556,2.75097,5,5,5,5,5,4.57195,4.89512,4.89512,4.89512,4.89512,4.89512,3.95797,3.95797,4.00473,4.34309,5,5,5,3.8221,3.8221,3.8221,3.8221,5,4.54256,4.4449,3.90232,5,1.90662,4.2128,4.2128,4.65526,3.2713,3.2713,3.0133,3.59454,3.59454,4.33209,5,5,5,5,4.54636,4.54636,3.73118,3.73118,4.95005,4.95005,5,4.55835,4.37958,3.28573,5,2.20447,2.20447,3.91898,3.91898,3.73368,3.7045,3.7045,3.7045,3.42472,3.42472,3.42472,3.74787,4.21533,3.51824,1.42173,4.15323,4.60175,4.60175,4.60175,5,3.67102,3.67102,3.67102,5,3.74964,3.74964,3.42428,5,1.624,4.35214,4.35214,3.99452,3.99452,5,5,3.31169,4.87951,4.87951,4.74519,3.82151,1.14506,4.16135,2.92948,4.75989,4.74431,2.71899,4.21835,4.21835,5,2.54575,4.32618,4.32618,4.32618,4.32618,4.32618,4.14355,4.41735,4.41735,3.7752,4.64818,5,4.46946,3.03758,3.03758,3.03758,3.03758,3.26627,3.26627,3.26627,3.26627,3.64049,4.51399,5,5,5,3.27915,3.27915,3.27915,5,5,5,5,5,5,3.71887,3.71887,5,3.18551,5,4.9657,4.9657,4.1604,4.1604,4.1604,5,5,4.34117,4.34117,5,4.38901,4.02736,4.02736,4.02736", "train/vf_clip_coef": "3.38776,3.94798,3.94798,3.94798,3.94798,3.58489,4.30608,4.30608,4.5823,4.15737,4.15737,2.04251,0.677174,3.7855,3.7855,3.7855,3.7855,3.7855,4.70653,4.42039,4.42039,4.42039,4.42039,4.42039,4.10447,4.10447,5,3.94356,4.12444,4.21521,4.21521,3.53601,3.53601,3.53601,3.53601,5,1.39307,5,5,5,4.94477,1.97983,1.97983,4.64105,5,5,4.71396,3.1441,3.1441,3.1214,3.99186,3.99186,3.99186,3.99186,2.7047,2.7047,4.73252,4.73252,4.30904,4.30904,3.06574,5,5,4.62577,4.31175,3.45074,3.45074,4.97611,4.97611,5,4.61316,4.61316,4.61316,4.25237,4.25237,4.25237,5,5,5,2.83375,4.91802,3.33871,3.33871,3.33871,4.18646,3.75981,3.75981,3.75981,4.89142,5,5,5,3.79312,2.66175,3.86151,3.86151,4.18233,4.18233,4.40528,4.40528,3.82082,3.38339,3.38339,5,3.88276,3.99706,4.26929,3.52602,5,4.71253,2.12451,3.41254,3.41254,3.36132,4.98263,4.68679,4.68679,4.68679,4.68679,4.68679,4.31993,5,5,3.10448,5,5,5,4.83034,4.83034,4.83034,4.83034,2.92193,2.92193,2.92193,2.92193,3.96287,4.68476,5,5,5,3.79593,3.79593,3.79593,5,5,4.98266,4.98266,4.98266,5,4.00935,4.00935,5,5,4.40049,3.26224,3.26224,4.87618,4.87618,4.87618,5,5,5,5,4.89381,4.97119,5,5,5", "train/max_grad_norm": "5,4.99091,4.99091,4.99091,4.99091,5,4.37043,4.37043,5,4.84172,4.84172,5,1.12,4.87506,4.87506,4.87506,4.87506,4.87506,5,5,5,5,5,5,5,5,5,4.45464,4.78666,3.66384,3.66384,3.90803,3.90803,3.90803,3.90803,5,2.89976,5,5,4.85499,5,5,5,5,4.11905,4.11905,5,5,5,4.56791,3.70789,3.70789,3.70789,3.70789,5,5,5,5,5,5,4.86922,4.57808,5,4.99059,5,5,5,5,5,4.95823,4.93946,4.93946,4.93946,4.15844,4.15844,4.15844,5,5,5,5,5,5,5,5,5,5,5,5,5,4.97128,4.97128,4.61849,5,5,5,5,4.75013,4.75013,4.87729,4.87729,5,4.04707,4.04707,5,4.64245,3.19163,4.89811,4.43306,5,5,1.409,5,5,5,4.85071,5,5,5,5,5,4.55679,5,5,4.44922,5,4.75699,5,5,5,5,5,5,5,5,5,5,3.77597,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,4.88849,4.88849,4.88849,5,5,4.92684,4.92684,5,4.60886,5,5,5", "train/ent_coef": "0.0553572,0.0510813,0.0510813,0.0510813,0.0510813,0.166033,0.030886,0.030886,0.2,0.0272364,0.0272364,0.123482,0.000900805,0.0495231,0.0495231,0.0495231,0.0495231,0.0495231,0.0607725,0.0187467,0.0187467,0.0187467,0.0187467,0.0187467,0.0672631,0.0672631,0.126491,0.068038,0.2,0.158125,0.158125,0.0279186,0.0279186,0.0279186,0.0279186,0.2,4.75794e-05,0.2,0.2,0.2,0.0154435,0.110269,0.110269,0.2,0.103208,0.103208,0.120247,0.00694124,0.00694124,0.0345668,0.0566097,0.0566097,0.0566097,0.0566097,0.0109269,0.0109269,0.0696985,0.0696985,0.179617,0.179617,0.0655822,0.2,0.2,0.10783,0.2,0.0672002,0.0672002,0.06302,0.06302,0.0341893,0.0696053,0.0696053,0.0696053,0.088185,0.088185,0.088185,0.0490678,0.125457,0.2,0.0747006,0.0701409,0.00892198,0.00892198,0.00892198,0.0899086,0.0881685,0.0881685,0.0881685,0.0137602,0.2,0.2,0.0781833,0.0367468,0.110694,0.0511704,0.0511704,0.117228,0.117228,0.0845561,0.0845561,0.0268589,0.115346,0.115346,0.078591,0.2,0.0296704,0.0327608,0.172387,0.0601093,0.2,0.00630233,0.0734512,0.0734512,0.119465,0.0778915,0.0472758,0.0472758,0.0472758,0.0472758,0.0472758,0.181723,0.152783,0.152783,0.048662,0.0639978,0.2,0.04084,0.152088,0.152088,0.152088,0.152088,0.0468947,0.0468947,0.0468947,0.0468947,0.00527545,0.0613144,0.0333405,0.0333405,0.12344,0.0697234,0.0697234,0.0697234,0.0685141,0.0685141,0.0308358,0.0308358,0.0308358,0.0811857,0.024756,0.024756,0.2,0.2,0.0777243,0.056372,0.056372,0.0460781,0.0460781,0.0460781,0.185004,0.185004,0.0243825,0.0243825,0.0293966,0.102028,0.0811386,0.0811386,0.0811386", "train/beta1": "0.945204,0.804752,0.804752,0.804752,0.804752,0.780025,0.709304,0.709304,0.868092,0.877155,0.877155,0.77166,0.993678,0.890447,0.890447,0.890447,0.890447,0.890447,0.909578,0.945261,0.945261,0.945261,0.945261,0.945261,0.898339,0.898339,0.931369,0.95504,0.983522,0.824136,0.824136,0.932995,0.932995,0.932995,0.932995,0.911914,0.996915,0.5,0.766313,0.943354,0.750672,0.755534,0.755534,0.895098,0.900192,0.900192,0.780668,0.511407,0.511407,0.889731,0.915789,0.915789,0.915789,0.915789,0.639042,0.639042,0.737192,0.737192,0.944945,0.944945,0.817429,0.978657,0.931345,0.944056,0.911565,0.859461,0.859461,0.762073,0.762073,0.78861,0.904734,0.904734,0.904734,0.673935,0.673935,0.673935,0.938426,0.957754,0.872886,0.723461,0.834407,0.862796,0.862796,0.862796,0.954179,0.857105,0.857105,0.857105,0.921096,0.924538,0.924538,0.912346,0.95853,0.936292,0.900637,0.900637,0.951004,0.951004,0.831446,0.831446,0.894539,0.817885,0.817885,0.680693,0.94205,0.880592,0.913591,0.894651,0.960993,0.90663,0.978342,0.910695,0.910695,0.954006,0.901069,0.914734,0.914734,0.914734,0.914734,0.914734,0.943362,0.930904,0.930904,0.678261,0.878765,0.9009,0.877539,0.817715,0.817715,0.817715,0.817715,0.880949,0.880949,0.880949,0.880949,0.855366,0.946701,0.885829,0.885829,0.931668,0.930489,0.930489,0.930489,0.857067,0.857067,0.912772,0.912772,0.912772,0.856083,0.765385,0.765385,0.693391,0.733971,0.80076,0.933144,0.933144,0.869433,0.869433,0.869433,0.860803,0.860803,0.868051,0.868051,0.94384,0.978644,0.838574,0.838574,0.838574", "train/beta2": "0.998849,0.998695,0.998695,0.998695,0.998695,0.9,0.999776,0.999776,0.996792,0.993204,0.993204,0.984362,0.999916,0.998059,0.998059,0.998059,0.998059,0.998059,0.970828,0.997583,0.997583,0.997583,0.997583,0.997583,0.991163,0.991163,0.987339,0.99025,0.995723,0.998842,0.998842,0.998485,0.998485,0.998485,0.998485,0.978191,0.93784,0.96573,0.992911,0.998832,0.999703,0.974758,0.974758,0.999491,0.998337,0.998337,0.983884,0.988582,0.988582,0.980822,0.998428,0.998428,0.998428,0.998428,0.997302,0.997302,0.998596,0.998596,0.99339,0.99339,0.99527,0.999855,0.998963,0.999313,0.987613,0.999392,0.999392,0.998155,0.998155,0.998675,0.998903,0.998903,0.998903,0.992396,0.992396,0.992396,0.984026,0.998038,0.982976,0.989641,0.974086,0.998951,0.998951,0.998951,0.995057,0.999199,0.999199,0.999199,0.999743,0.99399,0.99399,0.949668,0.998802,0.988513,0.998861,0.998861,0.988662,0.988662,0.999665,0.999665,0.993982,0.99325,0.99325,0.999102,0.998024,0.996652,0.997118,0.994504,0.993038,0.994269,0.995744,0.993709,0.993709,0.995063,0.996739,0.96422,0.96422,0.96422,0.96422,0.96422,0.999581,0.99694,0.99694,0.986582,0.97485,0.998268,0.997283,0.947086,0.947086,0.947086,0.947086,0.992362,0.992362,0.992362,0.992362,0.999483,0.999345,0.990658,0.990658,0.975453,0.991263,0.991263,0.991263,0.97526,0.97526,0.999361,0.999361,0.999361,0.995367,0.995258,0.995258,0.943213,0.963733,0.999085,0.994718,0.994718,0.993146,0.993146,0.993146,0.990635,0.990635,0.996559,0.996559,0.982996,0.979035,0.9906,0.9906,0.9906", "train/eps": "4.85295e-11,1.20513e-10,1.20513e-10,1.20513e-10,1.20513e-10,1e-14,7.4544e-10,7.4544e-10,9.10985e-14,1.95087e-13,1.95087e-13,1.19914e-07,1.02818e-11,3.7819e-13,3.7819e-13,3.7819e-13,3.7819e-13,3.7819e-13,1e-14,6.06686e-10,6.06686e-10,6.06686e-10,6.06686e-10,6.06686e-10,1e-14,1e-14,1.17138e-08,4.23411e-13,3.87147e-13,1.33462e-12,1.33462e-12,5.05601e-14,5.05601e-14,5.05601e-14,5.05601e-14,4.9243e-13,1.52368e-13,3.58913e-09,8.71761e-11,1.87672e-12,7.45106e-07,2.14246e-06,2.14246e-06,2.71654e-14,1.29249e-10,1.29249e-10,6.30702e-11,4.57596e-11,4.57596e-11,5.73997e-11,5.60551e-14,5.60551e-14,5.60551e-14,5.60551e-14,3.71314e-14,3.71314e-14,3.33228e-14,3.33228e-14,2.06519e-13,2.06519e-13,3.56202e-10,5.66935e-14,5.21515e-09,4.96262e-11,1.18495e-14,4.45783e-09,4.45783e-09,3.15632e-14,3.15632e-14,5.83515e-09,1.39642e-08,1.39642e-08,1.39642e-08,5.31093e-09,5.31093e-09,5.31093e-09,1e-14,3.36207e-07,1.31957e-08,8.03094e-09,3.04582e-12,1.655e-13,1.655e-13,1.655e-13,8.72681e-12,2.75106e-08,2.75106e-08,2.75106e-08,4.49342e-12,6.40385e-10,6.40385e-10,5.45655e-14,3.08085e-10,5.04501e-09,1.59548e-12,1.59548e-12,6.66609e-13,6.66609e-13,2.30462e-14,2.30462e-14,3.41565e-10,7.3122e-12,7.3122e-12,1.31508e-10,3.71739e-11,1.02155e-08,4.32464e-13,3.42056e-09,1.08286e-11,1.75495e-09,1.13398e-12,3.44894e-12,3.44894e-12,1e-14,7.43596e-10,1.137e-07,1.137e-07,1.137e-07,1.137e-07,1.137e-07,2.0215e-14,1.22213e-12,1.22213e-12,7.69518e-11,2.02686e-12,4.05465e-09,2.63071e-12,1.65827e-11,1.65827e-11,1.65827e-11,1.65827e-11,5.45139e-07,5.45139e-07,5.45139e-07,5.45139e-07,1.26377e-11,5.24682e-14,1.83874e-14,1.83874e-14,1.75605e-12,1.14749e-07,1.14749e-07,1.14749e-07,3.00823e-11,3.00823e-11,2.66179e-10,2.66179e-10,2.66179e-10,3.26532e-13,4.08732e-11,4.08732e-11,1.25002e-09,6.92786e-10,1e-14,7.76194e-14,7.76194e-14,1.10641e-10,1.10641e-10,1.10641e-10,1.79003e-13,1.79003e-13,3.84384e-12,3.84384e-12,4.5905e-10,2.45563e-13,7.29651e-08,7.29651e-08,7.29651e-08", "train/minibatch_size": "8192,16384,16384,16384,16384,16384,4096,4096,32768,8192,8192,8192,32768,8192,8192,8192,8192,8192,32768,8192,8192,8192,8192,8192,4096,4096,16384,8192,65536,8192,8192,8192,8192,8192,8192,65536,16384,16384,16384,16384,16384,16384,16384,65536,16384,16384,32768,8192,8192,8192,8192,8192,8192,8192,4096,4096,8192,8192,8192,8192,16384,65536,32768,8192,8192,16384,16384,4096,4096,32768,32768,32768,32768,8192,8192,8192,65536,32768,32768,16384,32768,16384,16384,16384,8192,32768,32768,32768,4096,16384,16384,16384,65536,16384,8192,8192,8192,8192,8192,8192,16384,4096,4096,65536,16384,8192,4096,16384,8192,32768,4096,8192,8192,8192,8192,16384,16384,16384,16384,16384,16384,32768,32768,4096,32768,65536,8192,16384,16384,16384,16384,32768,32768,32768,32768,16384,8192,8192,8192,8192,16384,16384,16384,8192,8192,16384,16384,16384,16384,8192,8192,16384,16384,4096,4096,4096,16384,16384,16384,8192,8192,8192,8192,32768,16384,32768,32768,32768", "train/horizon": "64,128,128,128,128,128,256,256,64,128,128,32,128,128,128,128,128,128,64,64,64,64,64,64,256,256,64,64,128,128,128,128,128,128,128,128,512,64,128,128,64,64,64,128,128,128,32,64,64,128,64,64,64,64,64,64,128,128,64,64,256,32,64,128,64,256,256,64,64,256,128,128,128,64,64,64,64,64,32,128,128,256,256,256,64,128,128,128,64,64,64,128,64,64,64,64,64,64,128,128,32,64,64,128,64,16,64,64,32,128,128,64,64,256,64,256,256,256,256,256,128,128,128,64,128,128,64,256,256,256,256,128,128,128,128,128,128,128,128,128,256,256,256,128,128,32,32,32,64,128,128,128,256,256,64,64,256,256,256,64,64,64,64,64,64,256,256,256", "train/vtrace_rho_clip": "4.3266,3.69187,3.69187,3.69187,3.69187,4.0626,2.86184,2.86184,3.92659,3.88845,3.88845,5,3.78212,4.2039,4.2039,4.2039,4.2039,4.2039,4.08977,4.28505,4.28505,4.28505,4.28505,4.28505,3.64968,3.64968,3.45566,2.63163,5,3.92418,3.92418,5,5,5,5,5,2.41505,3.8924,3.79503,4.9917,4.48165,4.40465,4.40465,4.16273,4.11215,4.11215,5,4.6628,4.6628,3.57277,5,5,5,5,3.73783,3.73783,3.29809,3.29809,3.92906,3.92906,3.46533,4.43785,3.48168,3.92395,4.77488,4.31378,4.31378,3.8704,3.8704,3.71454,3.38163,3.38163,3.38163,4.4101,4.4101,4.4101,4.53057,3.8808,3.85535,4.97187,4.23427,4.3085,4.3085,4.3085,5,3.35126,3.35126,3.35126,4.25337,4.10209,4.10209,3.39889,3.78971,4.50144,3.74162,3.74162,4.39257,4.39257,2.88,2.88,4.34165,4.17816,4.17816,3.24075,5,0.465124,4.44965,4.03086,4.85974,2.99563,0.23723,4.60361,4.60361,3.85389,4.03919,5,5,5,5,5,4.57979,4.66025,4.66025,3.15126,3.00796,4.26436,3.88325,4.37011,4.37011,4.37011,4.37011,4.40546,4.40546,4.40546,4.40546,3.34186,2.66682,4.15143,4.15143,4.54764,3.20465,3.20465,3.20465,3.53075,3.53075,3.63478,3.63478,3.63478,5,3.29456,3.29456,3.51896,3.09658,4.16926,3.93888,3.93888,4.5331,4.5331,4.5331,3.65591,3.65591,4.76162,4.76162,4.10681,4.63067,4.12666,4.12666,4.12666", "train/vtrace_c_clip": "4.66073,4.67343,4.67343,4.67343,4.67343,3.89753,2.55782,2.55782,3.04853,2.42898,2.42898,2.34858,2.75581,4.54561,4.54561,4.54561,4.54561,4.54561,2.63398,3.90281,3.90281,3.90281,3.90281,3.90281,5,5,1.5429,4.63021,4.63475,4.33248,4.33248,5,5,5,5,3.93494,0.902632,3.33919,3.20503,5,4.15135,3.07036,3.07036,2.75158,5,5,4.4404,3.26763,3.26763,4.74584,3.99961,3.99961,3.99961,3.99961,4.87723,4.87723,4.23916,4.23916,3.87393,3.87393,3.03634,3.80012,3.63523,3.01156,4.40826,5,5,5,5,0.457346,1.29093,1.29093,1.29093,4.21434,4.21434,4.21434,2.9222,0.123324,2.91413,4.72651,4.04661,3.0067,3.0067,3.0067,4.57219,1.76472,1.76472,1.76472,3.41609,4.23628,4.23628,5,2.7272,5,5,5,4.52194,4.52194,3.87103,3.87103,2.88647,5,5,1.66467,5,2.42887,2.8634,0.613473,5,5,4.1702,2.78276,2.78276,4.43874,2.01144,3.07482,3.07482,3.07482,3.07482,3.07482,2.52151,4.57636,4.57636,5,2.33156,2.58119,4.79004,2.04703,2.04703,2.04703,2.04703,2.51142,2.51142,2.51142,2.51142,4.54233,5,3.77872,3.77872,4.94451,3.51804,3.51804,3.51804,3.94547,3.94547,3.14165,3.14165,3.14165,4.06446,4.30949,4.30949,2.44824,3.50192,4.23709,4.7032,4.7032,5,5,5,3.72303,3.72303,4.75684,4.75684,4.31527,4.1163,1.74126,1.74126,1.74126", "train/prio_alpha": "0.940119,0.892652,0.892652,0.892652,0.892652,0.792021,0.937759,0.937759,1,1,1,0.800047,0.708587,1,1,1,1,1,0.724375,1,1,1,1,1,0.811084,0.811084,0.790582,1,1,1,1,1,1,1,1,1,0.0547724,0.982158,0.619368,0.828975,0.928983,0.582112,0.582112,1,0.813798,0.813798,0.918736,0.729546,0.729546,1,0.828149,0.828149,0.828149,0.828149,1,1,1,1,0.888651,0.888651,0.832383,1,0.714318,0.973829,1,0.978022,0.978022,0.923819,0.923819,1,0.908031,0.908031,0.908031,0.834837,0.834837,0.834837,1,0.684701,0.99235,1,0.645089,1,1,1,0.991729,0.819915,0.819915,0.819915,1,0.77017,0.77017,1,0.933665,1,0.90788,0.90788,0.872526,0.872526,0.786125,0.786125,0.944529,1,1,0.925507,1,0.420043,1,0.869293,1,1,0.333033,0.895324,0.895324,1,0.808036,0.867579,0.867579,0.867579,0.867579,0.867579,0.933109,1,1,1,1,1,0.873707,0.6815,0.6815,0.6815,0.6815,0.619419,0.619419,0.619419,0.619419,0.817843,1,1,1,0.97138,1,1,1,0.738471,0.738471,1,1,1,0.968799,1,1,1,0.823136,1,0.972717,0.972717,1,1,1,0.870039,0.870039,0.798595,0.798595,1,1,0.737338,0.737338,0.737338", "train/prio_beta0": "0.885182,0.789035,0.789035,0.789035,0.789035,1,1,1,1,1,1,1,0.68677,0.914953,0.914953,0.914953,0.914953,0.914953,1,0.958032,0.958032,0.958032,0.958032,0.958032,0.980223,0.980223,1,1,1,1,1,0.998147,0.998147,0.998147,0.998147,1,0.480633,1,1,0.930314,0.959452,1,1,1,0.9028,0.9028,0.864593,1,1,0.974511,0.839001,0.839001,0.839001,0.839001,0.693399,0.693399,1,1,0.99178,0.99178,0.756499,1,0.890944,1,1,1,1,1,1,0.970035,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0.974347,0.991255,0.991255,0.991255,1,1,1,1,0.941099,0.968889,0.971851,0.971851,1,1,1,1,1,1,1,1,1,0.116381,1,0.997877,0.866812,1,0.996503,1,1,1,0.98298,1,1,1,1,1,1,0.961803,0.961803,1,0.981996,0.896202,0.967302,0.998887,0.998887,0.998887,0.998887,1,1,1,1,0.965523,0.766277,1,1,1,0.814897,0.814897,0.814897,0.970544,0.970544,1,1,1,0.816934,1,1,1,1,1,1,1,0.92129,0.92129,0.92129,0.767091,0.767091,1,1,1,0.935121,1,1,1", "train/adam_beta1": "0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81,0.81", "train/adam_beta2": "0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95,0.95", "train/adam_eps": "1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08,1e-08", "no_model_upload": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "vec/num_envs": "4,4,4,4,4,4,4,4,4,4", "tsne1": "-6.04633,-1.39925,-1.39922,-1.39922,-1.39922,0.628103,-2.41103,-2.41103,-4.06086,-4.7693,-4.7693,5.70868,-12.8514,-8.91796,-8.91739,-8.91735,-8.91741,-8.91741,0.318188,-4.96407,-4.96407,-4.96287,-4.96407,-4.96407,-7.36552,-7.36555,2.00234,-9.60804,-4.51774,-7.636,-7.636,-4.72258,-4.72367,-4.72258,-4.72258,-3.53467,22.1239,3.35141,1.51084,-9.82531,-10.1129,5.50409,5.50422,-3.57591,-11.0468,-11.0466,1.24784,3.19785,3.19802,-5.27036,-4.19082,-4.19149,-4.1915,-4.19082,-4.79582,-4.79613,-3.00718,-3.00733,-10.472,-10.472,-1.63073,-4.90964,0.637312,-5.08583,-9.96613,2.53693,2.53619,-10.5652,-10.5652,1.35914,1.74391,1.74391,1.74391,4.63981,4.63976,4.63981,0.173574,1.28045,-0.835738,2.6953,0.372626,-1.38262,-1.38259,-1.38271,-9.58528,0.441272,0.441272,0.441272,-4.52285,-0.0988155,-0.0988155,-5.72674,-3.20509,-6.72141,-6.32653,-6.32652,-3.76678,-3.76666,-8.19212,-8.19212,0.580795,-5.47826,-5.47826,0.345336,-6.82434,-29.8991,-4.21578,0.246942,-3.20824,-3.36896,25.6812,-5.51333,-5.51333,-10.3733,-0.507016,3.11501,3.11514,3.11477,3.11505,3.11499,-4.1176,-0.280668,-0.280668,-10.3022,1.73201,0.597591,-8.52573,3.72465,3.72481,3.72447,3.72465,4.67829,4.67829,4.67805,4.67832,-1.77524,-10.5102,-6.36547,-6.36547,-5.93355,0.759649,0.759121,0.759769,-7.81499,-7.81515,-0.737002,-0.73692,-0.737002,-9.91255,-2.3721,-2.3721,3.97664,1.78449,-8.49922,-7.07324,-7.07324,-2.2568,-2.25748,-2.25699,-6.79089,-6.79054,-2.66379,-2.66379,0.0814743,-8.04762,1.60351,1.60355,1.60351", "tsne2": "76.0166,77.5891,77.5891,77.5891,77.5891,83.9636,86.6739,86.6739,72.4882,74.2509,74.2509,79.1014,26.9715,78.4046,78.4047,78.4047,78.4047,78.4047,82.7997,75.5718,75.5718,75.572,75.5718,75.5718,76.8784,76.8785,76.0968,76.6085,70.7778,74.1041,74.1041,82.5591,82.558,82.5591,82.5591,72.06,-21.1953,83.4327,77.8972,81.3862,82.6016,78.5321,78.532,71.1911,75.4715,75.4715,81.2732,84.0892,84.0913,79.8263,81.5379,81.538,81.5379,81.5379,84.7444,84.7441,82.7777,82.7777,76.8865,76.8865,75.9977,70.5824,78.4427,73.408,80.9606,79.8818,79.8814,80.6138,80.6138,73.7067,69.3576,69.3576,69.3576,81.7437,81.7418,81.7437,82.7959,72.2548,72.194,80.1314,82.223,83.7956,83.7956,83.7944,81.0219,72.4088,72.4088,72.4088,76.793,80.7057,80.7057,77.839,71.021,72.1496,75.4422,75.4422,80.7201,80.715,74.6748,74.6755,80.5058,80.4342,80.4342,73.1853,72.3798,15.4679,78.0085,71.7404,80.6474,72.9592,-0.309878,73.8374,73.8374,77.0222,71.4689,74.9124,74.9124,74.9126,74.9129,74.9124,79.5973,81.8282,81.8282,79.1322,76.8619,77.7647,81.2529,72.745,72.745,72.7451,72.745,77.9086,77.9086,77.9083,77.9087,81.9163,76.4762,81.3961,81.3961,74.8929,75.7092,75.7093,75.7089,79.1479,79.1482,79.9166,79.9105,79.9166,81.3914,82.2463,82.2463,73.9833,77.6778,74.4224,75.2685,75.2685,74.666,74.6658,74.6661,82.498,82.4972,79.429,79.429,81.373,80.8194,73.5642,73.5644,73.5642"}, "trash_pickup": {"SPS": "1.14228e+06,1.13722e+06,819201,820501,817277,810296,2.10295e+06,1.07832e+06,3.99625e+06,3.99431e+06,4.0082e+06,3.98796e+06,3.08838e+06,911528,3.09041e+06,3.16372e+06,538749,3.06593e+06,3.16056e+06,2.50895e+06,2.54814e+06,120209,1.13307e+06,1.13486e+06,1.1169e+06,217563,3.68457e+06,1.11838e+06,916416,913022,270970,3.66572e+06,3.73093e+06,3.35402e+06,3.43617e+06,3.47109e+06,1.43907e+06,154759,1.74028e+06,3.97504e+06,3.98177e+06,1.29347e+06,3.7666e+06,2.07527e+06,2.06029e+06,1.3378e+06,1.33318e+06,1.33024e+06,2.34663e+06,154880,1.15225e+06,2.15629e+06,2.15461e+06,2.14851e+06,2.06183e+06,572709,809915,274757,274486,42352.7,3.6031e+06,3.61471e+06,3.61798e+06,3.60578e+06,1.977e+06,2.94783e+06,3.40167e+06,247068,246666,127790,2.37672e+06,2.39317e+06,482303", "agent_steps": "13.6315,22.5444,3.9977,11.2722,18.7433,26.2144,4.25984,14.1558,11.2722,18.7433,26.2144,29.8844,10.2892,4.03046,4.29261,26.2472,17.3015,4.01408,11.2722,4.01408,11.2722,19.9229,7.34003,17.3015,5.57056,15.7286,4.75136,18.8744,18.8744,26.2144,19.9229,18.0879,4.45645,6.20954,4.68582,26.2472,5.24288,15.7286,29.3601,11.2722,18.7433,8.12646,4.84966,11.4033,26.3455,11.4033,18.8744,26.3455,18.7433,24.3794,5.04627,11.305,18.7761,26.2472,11.2722,7.20896,15.7286,12.3208,20.4472,11.5343,6.29146,15.7286,26.1489,36.5691,4.01408,4.01408,4.01408,11.5343,18.8744,18.8744,4.01408,11.264,26.2144", "uptime": "12.0288,19.8478,4.92388,13.7847,22.9073,32.1138,2.07257,13.2366,3.2745,5.15738,7.0211,7.93696,3.38304,4.45331,1.44718,8.42473,32.1047,1.35948,3.67088,1.7038,4.59683,165.588,6.58501,15.3632,5.04306,72.3687,1.38312,17.0024,20.6719,28.6988,73.5704,5.07403,1.19333,1.88512,1.42713,7.65748,3.67827,101.583,16.9274,2.96581,4.84213,6.3518,1.37009,5.53966,12.798,8.61298,14.2051,19.8173,8.09211,157.461,4.43269,5.35467,8.81852,12.293,5.52715,12.6399,19.4912,44.8168,74.4117,272.141,1.84813,4.45419,7.33713,10.2226,2.07293,1.38772,1.24219,46.7747,76.5159,147.498,1.74093,4.77173,54.3995", "epoch": "26,43,30.5,86,143,200,65,27,86,143,200,228,314,61.5,65.5,400.5,33,122.5,344,122.5,344,9.5,14,33,42.5,30,72.5,72,18,25,19,69,34,189.5,71.5,400.5,160,15,56,86,143,31,37,43.5,100.5,43.5,72,100.5,143,46.5,38.5,172.5,286.5,400.5,86,55,30,47,78,11,96,240,399,558,122.5,122.5,490,11,18,18,245,687.5,25", "perf/rollout": "0.111093,0.112765,0.0366033,0.0363396,0.0369298,0.0371566,0.0148054,0.109622,0.0278282,0.0274769,0.027516,0.0276852,0.00734091,0.0175292,0.0157404,0.0152232,0.127441,0.00843579,0.00814251,0.00871706,0.00845627,0.647448,0.110861,0.110164,0.0293084,0.191623,0.0142633,0.055992,0.231045,0.235249,0.262423,0.0547036,0.0156645,0.00766094,0.0149892,0.0147698,0.0074057,0.33929,0.113247,0.028494,0.0284367,0.0534376,0.0289435,0.056407,0.0572405,0.0564674,0.0570852,0.0575012,0.0304529,0.156698,0.0282677,0.0148962,0.0149194,0.0150055,0.0307305,0.0361418,0.113533,0.0799747,0.0803482,0.668562,0.0129131,0.0128226,0.0128055,0.012867,0.00960664,0.00981017,0.00194181,0.26623,0.270077,0.341449,0.00442908,0.0043664,0.252857", "perf/eval_gpu": "0.0235387,0.0235376,0.012698,0.012671,0.0127323,0.0126853,0.00350983,0.0225133,0.0055624,0.00561546,0.00555579,0.00559352,0.00159478,0.00558055,0.00376588,0.00375741,0.0342241,0.00225266,0.0022572,0.00248011,0.00248979,0.276599,0.0221782,0.0221926,0.00682356,0.0950596,0.00308053,0.0123436,0.0530283,0.0531631,0.0825202,0.0112506,0.00739148,0.00184368,0.00355976,0.00356705,0.00172994,0.148002,0.025317,0.00577942,0.00581252,0.0103903,0.00643381,0.0117887,0.0118517,0.0125392,0.0125247,0.0125461,0.00795439,0.0573573,0.00595132,0.00375864,0.00376441,0.00376446,0.00773262,0.0132358,0.025337,0.0314109,0.0313824,0.475838,0.00189741,0.0019055,0.00191509,0.00191541,0.00337647,0.00281256,0.00037377,0.0839687,0.0841904,0.157072,0.00136915,0.00137101,0.0686113", "perf/eval_env": "0.0860593,0.0877342,0.022682,0.0224377,0.0229753,0.0232429,0.0109059,0.086019,0.0217854,0.0213821,0.0214834,0.0216157,0.00551551,0.0113025,0.0115927,0.0110831,0.0906618,0.00584998,0.00555226,0.0058928,0.00562468,0.360658,0.087596,0.0868759,0.0219982,0.0918035,0.0108738,0.0428273,0.175158,0.179251,0.17706,0.0426301,0.00745143,0.00558828,0.011115,0.0108878,0.00543991,0.181916,0.0864332,0.0222502,0.0221595,0.0423729,0.0220241,0.0437888,0.0445692,0.0430996,0.043731,0.0441278,0.0220152,0.0946248,0.0218475,0.0107438,0.0107618,0.0108476,0.0223128,0.0222072,0.0866761,0.0461994,0.0466025,0.182705,0.0106935,0.0105893,0.0105702,0.0106108,0.00588282,0.00665575,0.00142953,0.177124,0.180756,0.179317,0.00286954,0.0028061,0.179246", "perf/train_misc": "0.0464544,0.0464121,0.00630786,0.00631013,0.00631095,0.00631128,0.00185008,0.0588228,0.00135932,0.00141494,0.00139035,0.00140157,0.000570411,0.00410585,0.000837931,0.000838615,0.0761877,0.000358774,0.000351972,0.000423678,0.000423889,0.839444,0.0549548,0.055051,0.0105057,0.07513,0.00073583,0.0174391,0.0676646,0.0676662,0.201049,0.00419917,0.00109117,0.000396343,0.000688359,0.000686357,0.00156518,0.390339,0.0191659,0.00118138,0.00118278,0.031529,0.00124296,0.0121597,0.01214,0.0157279,0.0157038,0.0157283,0.0025009,0.140488,0.0103382,0.00147164,0.00146854,0.00147068,0.00498511,0.00867723,0.0561814,0.0399213,0.0399886,0.536078,0.000972671,0.000973123,0.000972954,0.000973795,0.000331935,0.000144737,8.20797e-05,0.292364,0.292212,0.299873,0.000190608,0.000190755,0.155467", "perf/train_forward": "0.300617,0.301318,0.116906,0.116885,0.116944,0.11697,0.0143354,0.316708,0.00351752,0.00362817,0.00363192,0.00362701,0.00255653,0.050022,0.00451381,0.00451382,0.768505,0.00179524,0.00174691,0.00374825,0.00374704,15.9615,0.296277,0.296085,0.0771836,2.1427,0.00266928,0.160555,0.844822,0.844726,3.40413,0.0124067,0.0182344,0.00160205,0.00328453,0.00327551,0.0136144,6.04159,0.1686,0.0031509,0.00315279,0.117215,0.00449719,0.0574939,0.0575093,0.123345,0.123399,0.12347,0.0227178,3.08772,0.0747996,0.0138613,0.0138608,0.0138576,0.0275697,0.183673,0.476705,0.83351,0.833965,23.5494,0.00418867,0.00418759,0.00418756,0.00418983,0.00651875,0.00104972,0.000277388,3.68664,3.68604,7.56243,0.00216441,0.00216443,1.76528", "perf/train": "0.347072,0.34773,0.123214,0.123195,0.123255,0.123281,0.0161855,0.37553,0.00487684,0.00504311,0.00502227,0.00502858,0.00312695,0.0541278,0.00535174,0.00535243,0.844692,0.00215401,0.00209889,0.00417193,0.00417093,16.8009,0.351232,0.351136,0.0876892,2.21783,0.00340511,0.177994,0.912486,0.912392,3.60518,0.0166058,0.0193255,0.00199839,0.00397289,0.00396186,0.0151796,6.43193,0.187766,0.00433228,0.00433557,0.148744,0.00574016,0.0696535,0.0696493,0.139073,0.139103,0.139198,0.0252187,3.2282,0.0851378,0.0153329,0.0153293,0.0153283,0.0325549,0.19235,0.532887,0.873431,0.873953,24.0854,0.00516134,0.00516071,0.00516051,0.00516362,0.00685068,0.00119446,0.000359467,3.97901,3.97826,7.8623,0.00235501,0.00235518,1.92074", "util/gpu_percent": "88,79.5882,83.4259,83.0526,83.7719,82.9825,60.6238,88.4706,32,32,32,32,42.0743,81.5185,37.7,42.7368,83.2857,31.5234,40.4192,38.1589,50.7555,100,86.3529,79.1429,82.3906,100,29.1628,81.4828,83.1429,79.4286,100,44.4889,96,32.6867,41.0455,41.4737,73.5093,100,80.2667,31.4737,31.0702,72.3469,32.6279,62.5,61.6071,87.9643,62.7241,89.3929,54.6842,100,79.0741,62.8246,64.2456,61.9825,63.193,90.9158,91.7368,96.3871,93.1613,100,50.814,45.0126,45.956,44.0377,57.8037,31.2056,28.3275,100,100,100,41.3091,52.6834,100", "util/gpu_mem": "9.09894,9.09894,6.19224,6.19224,6.19224,6.19224,4.70226,9.21292,15.281,16.5934,16.8659,16.8659,4.36029,4.88952,18.8037,18.8037,9.48975,4.67783,4.67783,5.01165,5.01165,26.8241,9.21292,9.21292,5.55717,13.0641,4.93023,6.61563,14.7251,14.7251,15.3031,6.55049,9.79915,15.2055,4.97094,4.97094,4.29516,16.3616,9.75029,17.8104,17.8104,6.53421,5.61416,6.56677,6.56677,6.66448,6.66448,6.66448,6.05383,10.2714,17.5335,4.78368,4.78368,4.78368,16.182,6.28995,9.23735,7.64966,7.64966,20.286,5.44318,5.44318,5.44318,5.44318,5.55717,5.0198,4.25445,15.1159,15.1159,16.5733,4.74297,4.74297,15.0833", "util/vram_used_gb": "1.72156,1.72156,1.02429,1.02429,1.02429,1.02429,0.66687,1.7489,3.20453,3.51934,3.58472,3.58472,0.584839,0.711792,4.04956,4.04956,1.81531,0.661011,0.661011,0.741089,0.741089,5.97351,1.7489,1.7489,0.871948,2.67273,0.721558,1.12585,3.07117,3.07117,3.20984,1.11023,1.88953,3.18643,0.731323,0.731323,0.569214,3.46375,1.87781,3.81128,3.81128,1.10632,0.88562,1.11414,1.11414,1.13757,1.13757,1.13757,0.991089,2.00281,3.74487,0.686401,0.686401,0.686401,3.42065,1.04773,1.75476,1.3739,1.3739,4.40515,0.844604,0.844604,0.844604,0.844604,0.871948,0.743042,0.559448,3.16492,3.16492,3.51453,0.676636,0.676636,3.1571", "util/vram_total_gb": "23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272", "util/cpu_mem_gb": "1.10414,1.10414,1.10706,1.10706,1.10706,1.10706,1.08785,1.10088,1.00953,1.00953,1.00953,1.00953,1.08348,1.09182,1.00749,1.00823,1.11928,1.08358,1.08381,1.08589,1.08616,1.23893,1.10404,1.10404,1.09306,1.16935,1.08975,1.0991,1.1344,1.1344,1.132,1.09245,1.10423,1.00284,1.08946,1.09001,1.08688,1.22131,1.1071,1.00924,1.00924,1.09711,1.0891,1.09378,1.09378,1.0985,1.0985,1.0985,1.08216,1.19009,1.01073,1.0905,1.0905,1.0908,1.00704,1.08633,1.10541,1.12819,1.12819,1.27114,1.09116,1.09116,1.09153,1.09171,1.0826,1.08054,1.08641,1.1568,1.1568,1.16713,1.08464,1.08554,1.1527", "env/perf": "0.973652,0.974927,0.837124,0.974135,0.974805,0.974999,0.95359,0.973787,0.967926,0.97272,0.973615,0.973859,0.954141,0.926911,0.906934,0.974196,0.974818,0.813568,0.955992,0.85226,0.966521,0.974942,0.959228,0.97434,0.958948,0.974885,0.922976,0.974742,0.974564,0.97497,0.974933,0.972177,0.231885,0.948603,0.930621,0.973793,0.955072,0.974868,0.9749,0.958344,0.971189,0.962906,0.866715,0.973186,0.974743,0.973418,0.974887,0.974933,0.973386,0.974985,0.958662,0.972859,0.974467,0.974727,0.969027,0.959158,0.974531,0.974845,0.974981,0.97464,0.931485,0.969594,0.973742,0.974673,0.838834,0.510486,0.826461,0.974224,0.974936,0.97494,0.891084,0.967104,0.974932", "env/score": "38.946,38.997,33.485,38.9654,38.9922,39,38.1436,38.9514,38.7171,38.9088,38.9446,38.9544,38.1656,37.0764,36.2773,38.9678,38.9927,32.5427,38.2397,34.0904,38.6609,38.9977,38.3691,38.9735,38.3579,38.9954,36.919,38.9897,38.9824,38.9988,38.9973,38.8871,9.27539,37.9441,37.2249,38.9517,38.2029,38.9947,38.9959,38.3338,38.8476,38.5163,34.6686,38.9275,38.9897,38.9368,38.9955,38.9973,38.9354,38.9994,38.3465,38.9143,38.9787,38.9891,38.7611,38.3663,38.9811,38.9938,38.9992,38.9856,37.2594,38.7838,38.9497,38.9869,33.5534,20.4194,33.0584,38.9689,38.9974,38.9976,35.6434,38.6842,38.9973", "env/episode_return": "39.6525,39.963,33.0915,39.8707,39.9812,39.9933,38.5546,39.8485,39.3965,39.7463,39.8364,39.8592,38.714,37.1929,36.3101,39.8769,39.9377,31.8432,38.7805,33.7459,39.3242,39.9236,39.0625,39.8755,38.9085,39.9537,37.2044,39.8546,39.8963,39.9856,39.9661,39.6589,5.12158,38.458,37.647,39.8404,38.6616,39.9119,39.9281,38.8799,39.6118,39.1957,34.58,39.7047,39.9623,39.7663,39.9527,39.9791,39.7331,39.9834,38.9452,39.682,39.8255,39.9173,39.4955,39.0338,39.8816,39.9689,39.9878,39.9242,37.7646,39.5144,39.817,39.9096,33.1111,17.2694,32.3626,39.8198,39.965,39.9625,35.4748,39.3093,39.941", "env/episode_length": "320.985,230.816,413.17,254.993,191.133,174.897,412.411,276.276,362.99,321.497,299.812,291.365,375.249,426.659,396.525,267.4,228.949,440.342,376.915,437.137,370.608,239.033,329.074,283.612,395.841,225.395,374.602,290.007,250.578,197.561,211.982,342.804,500,377.637,372.699,290.727,398.873,250.54,245.084,369.379,329.049,339.241,377.341,299.358,205.875,299.645,240.703,206.908,325.522,165.206,362.292,344.771,309.636,269.964,330.251,322.929,254.384,209.218,192.116,223.091,357.372,340.501,300.04,269.589,439.604,498.346,452.851,287.612,208.193,220.561,422.559,374.384,242.292", "env/trash_collected": "38.946,38.997,33.485,38.9654,38.9922,39,38.1436,38.9514,38.7171,38.9088,38.9446,38.9544,38.1656,37.0764,36.2773,38.9678,38.9927,32.5427,38.2397,34.0904,38.6609,38.9977,38.3691,38.9735,38.3579,38.9954,36.919,38.9897,38.9824,38.9988,38.9973,38.8871,9.27539,37.9441,37.2249,38.9517,38.2029,38.9947,38.9959,38.3338,38.8476,38.5163,34.6686,38.9275,38.9897,38.9368,38.9955,38.9973,38.9354,38.9994,38.3465,38.9143,38.9787,38.9891,38.7611,38.3663,38.9811,38.9938,38.9992,38.9856,37.2594,38.7838,38.9497,38.9869,33.5534,20.4194,33.0584,38.9689,38.9974,38.9976,35.6434,38.6842,38.9973", "env/n": "211.412,291.059,68.0741,65.6842,86.1754,93.8421,34.1782,238.294,46,51.0526,55.4561,6398,17.9788,26.9444,44.39,30.5439,291.619,48.8364,10.952,46.9159,11.1179,1113.75,245.176,237.714,69.2344,292.684,86.8023,115.276,539.143,670.714,641.286,97.3778,1024,18.2468,96.5227,28.5526,21.7509,530.667,269.333,44.9123,49.6842,78.4082,123.047,114.179,159.429,110.5,139.103,159.536,51.2281,398.222,82.6852,23.8246,26.7982,30.4211,50.5965,56.6947,268.263,158,170.806,597.857,58.1783,23.8365,27.761,30.5472,41.5935,123.477,45.2678,466.571,638.714,604.636,29.9766,5.50873,547.286", "wandb": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "rank": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "world_size": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "gpu_id": "5,5,1,1,1,1,5,3,0,0,0,0,5,3,0,0,1,4,4,4,4,3,3,3,3,5,2,2,3,3,2,4,2,0,2,2,2,4,2,0,0,5,3,4,4,2,2,2,5,4,0,3,3,3,0,3,2,1,1,5,5,5,5,5,4,2,3,3,3,5,4,4,2", "profile": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "checkpoint_interval": "200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200", "eval_episodes": "10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000", "cudagraphs": "10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10", "seed": "73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73", "vec/total_agents": "4096,4096,1024,1024,1024,1024,2048,8192,4096,4096,4096,4096,2048,1024,2048,2048,2048,1024,1024,1024,1024,2048,8192,8192,4096,1024,4096,4096,4096,4096,4096,4096,8192,2048,4096,4096,2048,1024,4096,4096,4096,8192,4096,4096,4096,4096,4096,4096,4096,1024,4096,2048,2048,2048,2048,2048,4096,1024,1024,1024,4096,4096,4096,4096,1024,1024,1024,2048,2048,2048,1024,1024,2048", "vec/num_buffers": "1,1,1.44391,1.44391,1.44391,1.44391,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1.42871,1,1,1.22222,1,7.45595,1,1,1,1,1,1.19847,1,1,1,1,1,1,1.96401,1.96401,1.96401,1,1,1,1,1,1,1,1,1.06486,1.22057,1.22057,1,2.05803,2.05803,2.05803,2.05803,1,1,2.11754,1,1,1,1,1,1", "vec/num_threads": "2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2", "env/grid_size": "20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20,20", "env/num_agents": "8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8", "env/num_trash": "40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40,40", "env/num_bins": "2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2", "env/max_steps": "500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500,500", "env/report_interval": "32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32", "env/agent_sight_range": "5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5", "policy/hidden_size": "32,32,128,128,128,128,32,64,64,64,64,64,64,128,256,256,128,128,128,256,256,512,64,64,128,512,128,32,64,64,256,32,512,128,256,256,32,512,64,128,128,32,256,64,64,64,64,64,512,128,32,32,32,32,256,512,64,256,256,1024,128,128,128,128,512,512,64,256,256,512,256,256,128", "policy/num_layers": "3.01291,3.01291,6.04681,6.04681,6.04681,6.04681,3.15017,4.14743,1,1,1,1,1,4.43285,1.47895,1.47895,4.69649,1,1,1,1,5.7975,4.34487,4.34487,4.15302,6.30385,2.95681,5.69948,6.50008,6.50008,6.07243,1,5.33024,1,2.61444,2.61444,3.39285,4.38164,4.85852,1.127,1.127,3.70813,1.325,2.03055,2.03055,4.2488,4.2488,4.2488,1,8,4.50315,5.38929,5.38929,5.38929,1,3.87321,4.54173,6.4131,6.4131,7.83862,2.92514,2.92514,2.92514,2.92514,2.06106,1.73831,1,4.85668,4.85668,6.04913,2.23706,2.23706,4.83588", "policy/expansion_factor": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "legacy/torch_deterministic": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "legacy/cpu_offload": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "legacy/compile": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "legacy/compile_fullgraph": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "train/gpus": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "train/seed": "42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42", "train/total_timesteps": "35.4241,35.4241,30,30,30,30,30,37.1012,30,30,30,30,78.1488,30,30,30,44.838,30,30,30,30,30.309,44.71,44.71,38.4224,40.6046,30,30,30,30,31.2827,47.6291,44.183,45.4881,30,30,38.495,38.8045,33.365,30,30,57.4272,30.4079,30,30,30,30,30,30,38.6166,34.1241,30,30,30,30,53.2196,40.9381,32.3021,32.3021,30,41.7691,41.7691,41.7691,41.7691,30,30,30.0399,30,30,48.0647,30,30,30.4057", "train/learning_rate": "0.033269,0.033269,0.00814126,0.00814126,0.00814126,0.00814126,0.0169594,0.00930825,0.018956,0.018956,0.018956,0.018956,0.0256754,0.0270144,0.0224685,0.0224685,0.0129062,0.0209781,0.0209781,0.0151014,0.0151014,0.0207236,0.00593058,0.00593058,0.0180598,0.0128154,0.0553076,0.00828208,0.1,0.1,0.00794202,0.00881446,0.0526532,0.039908,0.1,0.1,0.028223,0.0101452,0.0248099,0.0188674,0.0188674,0.0380086,0.0284303,0.0113987,0.0113987,0.00822405,0.00822405,0.00822405,0.00826075,0.00968047,0.0136045,0.00599262,0.00599262,0.00599262,0.00701373,0.00899904,0.00892848,0.0204897,0.0204897,0.0118032,0.0147993,0.0147993,0.0147993,0.0147993,0.0254422,0.0163401,0.0155822,0.00956244,0.00956244,0.0157904,0.0164096,0.0164096,0.0297173", "train/anneal_lr": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "train/min_lr_ratio": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "train/gamma": "0.917864,0.917864,0.8,0.8,0.8,0.8,0.8,0.8,0.93176,0.93176,0.93176,0.93176,0.949657,0.832097,0.972268,0.972268,0.879822,0.967196,0.967196,0.96771,0.96771,0.935663,0.845017,0.845017,0.913735,0.971755,0.8,0.940685,0.914569,0.914569,0.899607,0.95554,0.997371,0.969969,0.938165,0.938165,0.8,0.924368,0.8,0.97896,0.97896,0.8,0.8,0.967951,0.967951,0.8,0.8,0.8,0.981576,0.980126,0.958505,0.811137,0.811137,0.811137,0.981409,0.945651,0.852875,0.940308,0.940308,0.981684,0.930484,0.930484,0.930484,0.930484,0.973335,0.8,0.8,0.957406,0.957406,0.915223,0.978609,0.978609,0.987957", "train/gae_lambda": "0.873231,0.873231,0.902253,0.902253,0.902253,0.902253,0.825144,0.78895,0.897276,0.897276,0.897276,0.897276,0.774383,0.893897,0.770241,0.770241,0.834204,0.973289,0.973289,0.983415,0.983415,0.858565,0.796977,0.796977,0.406387,0.590901,0.86771,0.96244,0.509713,0.509713,0.2,0.78538,0.877125,0.961522,0.933107,0.933107,0.963587,0.80858,0.979382,0.884308,0.884308,0.804614,0.902893,0.832499,0.832499,0.784193,0.784193,0.784193,0.759541,0.836678,0.807025,0.921982,0.921982,0.921982,0.867966,0.478295,0.862972,0.438533,0.438533,0.445797,0.972618,0.972618,0.972618,0.972618,0.968219,0.81494,0.941106,0.77452,0.77452,0.673372,0.959795,0.959795,0.860675", "train/replay_ratio": "2.76037,2.76037,3.86793,3.86793,3.86793,3.86793,3.43879,3.20957,0.694383,0.694383,0.694383,0.694383,2.4745,4,1.16308,1.16308,3.51415,2.18945,2.18945,2.59096,2.59096,3.13657,2.99791,2.99791,3.89416,4,0.843798,2.75732,2.55741,2.55741,4,1.0861,0.32882,1.28992,0.403792,0.403792,4,2.95141,3.78165,0.977983,0.977983,3.7393,0.586814,1.88577,1.88577,2.44858,2.44858,2.44858,1.38498,3.97325,4,2.47078,2.47078,2.47078,2.00976,3.56704,3.37965,4,4,4,1.83493,1.83493,1.83493,1.83493,1.03954,0.466452,1.74773,4,4,4,1.85612,1.85612,4", "train/clip_coef": "0.129471,0.129471,0.201166,0.201166,0.201166,0.201166,0.32963,0.27468,0.224283,0.224283,0.224283,0.224283,0.144844,0.316304,0.439971,0.439971,0.215012,0.465064,0.465064,0.406512,0.406512,0.385704,0.249789,0.249789,0.155,0.117929,0.182374,0.0826611,0.243412,0.243412,0.222371,0.130945,0.932724,0.306313,0.231085,0.231085,0.191369,0.313952,0.207015,0.440049,0.440049,0.443284,0.413362,0.177022,0.177022,0.305952,0.305952,0.305952,0.125178,0.210736,0.231797,0.438567,0.438567,0.438567,0.204079,0.107194,0.254185,0.134727,0.134727,0.485947,0.0627967,0.0627967,0.0627967,0.0627967,0.510809,0.328794,0.467139,0.340689,0.340689,0.35458,0.403701,0.403701,0.112283", "train/vf_coef": "4.25437,4.25437,5,5,5,5,3.17027,4.81055,2.98953,2.98953,2.98953,2.98953,4.9714,3.56843,4.18209,4.18209,4.07028,3.61522,3.61522,2.31136,2.31136,4.14432,3.93615,3.93615,4.55613,3.65691,5,5,5,5,3.69275,4.10649,3.33097,4.60727,4.05772,4.05772,4.89598,4.09668,4.09956,2.11152,2.11152,5,3.18709,3.50891,3.50891,3.64103,3.64103,3.64103,4.0479,4.76768,5,5,5,5,4.54256,5,3.95266,4.15342,4.15342,3.71405,3.9924,3.9924,3.9924,3.9924,3.46231,4.79579,3.13174,5,5,5,2.57189,2.57189,4.2114", "train/vf_clip_coef": "1.23757,1.23757,0.0138812,0.0138812,0.0138812,0.0138812,0.572413,0.01,0.01,0.01,0.01,0.01,0.450227,0.01,0.541966,0.541966,1.15891,1.08994,1.08994,0.01,0.01,0.740586,0.01,0.01,0.300522,1.11844,0.947258,0.0298,0.01,0.01,1.00817,1.11617,2.89156,0.01,0.940932,0.940932,0.842647,1.16034,0.01,0.01,0.01,0.147344,1.16668,0.22794,0.22794,0.839359,0.839359,0.839359,0.01,0.280697,0.01,0.14454,0.14454,0.14454,0.01,1.00604,0.138851,1.48616,1.48616,0.265233,0.01,0.01,0.01,0.01,0.910801,0.01,1.14933,1.04244,1.04244,0.450384,1.16127,1.16127,0.01", "train/max_grad_norm": "0.741391,0.741391,0.596233,0.596233,0.596233,0.596233,0.1,1.02267,0.1,0.1,0.1,0.1,1.28421,0.1,1.94115,1.94115,1.29638,0.1,0.1,0.223371,0.223371,0.264194,0.1,0.1,0.1,0.966931,0.871097,0.1,1.74045,1.74045,0.1,0.606533,3.98379,0.1,1.00923,1.00923,1.04857,0.922151,0.777063,1.16224,1.16224,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.70812,0.366937,0.236108,0.421994,0.421994,0.421994,0.995593,2.40225,0.808486,0.1,0.1,1.03584,0.1,0.1,0.1,0.1,0.1,0.1,0.896592,0.656692,0.656692,2.00676,1.032,1.032,0.319118", "train/ent_coef": "0.0113798,0.0113798,0.00166285,0.00166285,0.00166285,0.00166285,0.0714718,0.00119643,0.000942568,0.000942568,0.000942568,0.000942568,0.000843173,0.00628978,0.036297,0.036297,0.0116936,9.16548e-05,9.16548e-05,0.00210937,0.00210937,0.00258877,0.0486742,0.0486742,0.0994966,0.0149869,0.00112787,0.00202782,0.0273315,0.0273315,0.00240124,0.000213291,0.000139635,0.00314245,0.00113702,0.00113702,0.000514098,0.00504538,0.000682833,0.0134288,0.0134288,0.00496128,0.00206753,0.00245052,0.00245052,0.00922737,0.00922737,0.00922737,6.276e-05,0.000505615,0.0186286,0.0191927,0.0191927,0.0191927,0.0014047,0.00157167,0.0035178,0.00498477,0.00498477,0.00244379,0.000193757,0.000193757,0.000193757,0.000193757,0.000770619,0.000508582,0.000279373,0.00639941,0.00639941,0.00279967,0.0204045,0.0204045,0.0240666", "train/beta1": "0.827088,0.827088,0.774892,0.774892,0.774892,0.774892,0.909274,0.822489,0.896589,0.896589,0.896589,0.896589,0.596426,0.749749,0.90924,0.90924,0.799755,0.884954,0.884954,0.896113,0.896113,0.5,0.889907,0.889907,0.729788,0.81991,0.842532,0.895616,0.5,0.5,0.70228,0.915143,0.996325,0.798662,0.5,0.5,0.806674,0.850612,0.5,0.921441,0.921441,0.737669,0.889323,0.916359,0.916359,0.946331,0.946331,0.946331,0.88189,0.5,0.5,0.875161,0.875161,0.875161,0.831332,0.886807,0.66132,0.581836,0.581836,0.616049,0.87893,0.87893,0.87893,0.87893,0.904684,0.720199,0.878339,0.812191,0.812191,0.530825,0.880915,0.880915,0.5", "train/beta2": "0.999934,0.999934,0.999924,0.999924,0.999924,0.999924,0.999777,0.99999,0.999841,0.999841,0.999841,0.999841,0.999985,0.999967,0.999578,0.999578,0.99999,0.999799,0.999799,0.999985,0.999985,0.999954,0.999979,0.999979,0.999896,0.999768,0.999936,0.99999,0.999972,0.999972,0.999973,0.999967,0.999526,0.999896,0.99999,0.99999,0.99999,0.999941,0.999968,0.999851,0.999851,0.999926,0.999969,0.998454,0.998454,0.999752,0.999752,0.999752,0.99999,0.999779,0.999948,0.99999,0.99999,0.99999,0.999372,0.999975,0.999982,0.99997,0.99997,0.999947,0.999989,0.999989,0.999989,0.999989,0.99999,0.999985,0.999985,0.99998,0.99998,0.999978,0.99999,0.99999,0.99999", "train/eps": "9.47913e-10,9.47913e-10,5.82808e-12,5.82808e-12,5.82808e-12,5.82808e-12,1.40718e-13,3.90218e-11,1e-14,1e-14,1e-14,1e-14,7.35631e-13,4.10193e-13,1.21219e-13,1.21219e-13,1e-14,4.82041e-12,4.82041e-12,9.10965e-12,9.10965e-12,7.29941e-14,4.80464e-10,4.80464e-10,9.47028e-11,1.0636e-14,4.39057e-14,1.99995e-10,3.78752e-14,3.78752e-14,1.42282e-14,1e-14,2.89549e-06,7.67874e-13,3.9503e-14,3.9503e-14,1.84048e-11,1.79646e-13,4.17208e-14,1.56831e-12,1.56831e-12,4.64946e-10,3.93958e-12,2.89426e-13,2.89426e-13,3.32353e-10,3.32353e-10,3.32353e-10,1.97628e-11,1e-14,8.0519e-14,2.51786e-10,2.51786e-10,2.51786e-10,6.06459e-11,8.17237e-11,7.10679e-13,1e-14,1e-14,1e-14,1e-14,1e-14,1e-14,1e-14,5.8066e-13,5.87861e-12,4.22782e-13,1e-14,1e-14,1e-14,8.68085e-11,8.68085e-11,3.67556e-09", "train/minibatch_size": "4096,4096,8192,8192,8192,8192,8192,4096,8192,8192,8192,8192,8192,4096,8192,8192,4096,16384,16384,16384,16384,4096,4096,4096,4096,8192,8192,4096,8192,8192,4096,8192,8192,8192,4096,4096,4096,4096,16384,16384,16384,4096,8192,4096,4096,4096,4096,4096,8192,4096,4096,8192,8192,8192,4096,4096,4096,4096,4096,4096,16384,16384,16384,16384,8192,8192,8192,4096,4096,4096,8192,8192,8192", "train/horizon": "128,128,128,128,128,128,32,64,32,32,32,32,16,64,32,32,256,32,32,32,32,1024,64,64,32,512,16,64,256,256,256,64,16,16,16,16,16,1024,128,32,32,32,32,64,64,64,64,64,32,512,32,32,32,32,64,64,128,256,256,1024,16,16,16,16,32,32,8,512,512,512,16,16,512", "train/vtrace_rho_clip": "3.00835,3.00835,4.04331,4.04331,4.04331,4.04331,3.31438,4.30599,2.83986,2.83986,2.83986,2.83986,3.08361,4.36481,3.05777,3.05777,4.75637,3.89758,3.89758,4.02302,4.02302,2.7742,5,5,5,2.61776,4.37488,3.58825,4.24695,4.24695,1.08783,2.50999,3.57844,1.91868,2.21614,2.21614,3.72698,5,3.61455,3.07166,3.07166,5,3.23226,3.00968,3.00968,2.57225,2.57225,2.57225,4.35472,2.52659,5,5,5,5,1.77594,3.92499,4.14836,2.73016,2.73016,1.60293,3.43692,3.43692,3.43692,3.43692,2.42584,3.89914,2.41205,3.71887,3.71887,2.81497,2.33406,2.33406,2.96105", "train/vtrace_c_clip": "2.70471,2.70471,2.53793,2.53793,2.53793,2.53793,1.63119,1.32449,2.0435,2.0435,2.0435,2.0435,1.6077,3.7925,3.20455,3.20455,1.93299,4.20733,4.20733,4.13848,4.13848,2.1375,2.40615,2.40615,2.92309,3.93155,3.37373,1.86062,2.44834,2.44834,0.856381,2.62376,1.93936,3.06178,2.18587,2.18587,3.1652,2.00907,3.46705,2.80928,2.80928,2.57694,2.9318,1.64591,1.64591,1.59953,1.59953,1.59953,2.26513,1.28636,2.24927,3.60525,3.60525,3.60525,3.30343,2.12442,2.50171,1.79252,1.79252,2.28991,3.0755,3.0755,3.0755,3.0755,3.27785,3.37946,4.20365,1.78338,1.78338,2.43722,4.47914,4.47914,2.81965", "train/prio_alpha": "1,1,1,1,1,1,0.99142,0.917603,0.718031,0.718031,0.718031,0.718031,1,0.826022,0.897746,0.897746,1,0.652412,0.652412,0.498461,0.498461,0.63368,0.867994,0.867994,0.853631,0.662308,0.986723,1,1,1,0.721861,0.580645,0.477809,0.24502,0.710273,0.710273,0.886248,0.787291,0.961453,0.616313,0.616313,1,0.944189,0.634321,0.634321,1,1,1,0.827497,1,1,0.775859,0.775859,0.775859,0.184352,0.761182,0.8544,1,1,1,0.58438,0.58438,0.58438,0.58438,0.728457,0.664229,0.664487,0.775842,0.775842,0.694507,0.679727,0.679727,0.681256", "train/prio_beta0": "0.357837,0.357837,0.120961,0.120961,0.120961,0.120961,0.263202,0.313139,0.457767,0.457767,0.457767,0.457767,0.724898,0.147515,0.766245,0.766245,0.18018,0.513923,0.513923,0.756146,0.756146,0.262901,0.514494,0.514494,0.336575,0,0.656169,0.629835,0.605091,0.605091,0,0.235975,0.799329,0.59723,0.560288,0.560288,0.564165,0,0.214318,0.822461,0.822461,0.648292,0.536451,0.43115,0.43115,0.0769049,0.0769049,0.0769049,0.5371,0.503765,0.426967,0.368811,0.368811,0.368811,0.772233,0.0264523,0.431439,0.276774,0.276774,0,0.416024,0.416024,0.416024,0.416024,0.618417,0.680998,0.55494,0.0396207,0.0396207,0.110869,0.531781,0.531781,0.69718", "train/use_rnn": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "no_model_upload": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "tsne1": "-8.73684,-8.73684,-8.46869,-8.46869,-8.46869,-8.46869,-11.2977,-9.38104,7.91702,7.91702,7.91704,7.91697,-6.90674,-8.1205,13.2187,13.2187,-6.71667,13.8541,13.8541,13.7749,13.7752,-4.00041,-9.2408,-9.2408,-8.0871,-2.17427,-12.9265,-8.51476,-6.097,-6.097,-2.63105,7.24421,27.7878,22.7351,-8.71274,-8.71274,-9.80332,-3.54357,-7.59606,12.1016,12.1016,-9.62156,-12.9704,8.56718,8.56723,-11.1187,-11.1187,-11.1187,11.6983,-4.19638,-6.70371,-10.5263,-10.5263,-10.5263,23.1211,-3.084,-8.1891,-3.44414,-3.44414,-3.12906,10.6872,10.6872,10.6873,10.6875,14.0729,-13.0457,-12.6279,-3.32695,-3.32695,-3.83473,14.6785,14.6785,-4.73717", "tsne2": "-13.3421,-13.3421,-17.1013,-17.1013,-17.1013,-17.1013,-18.2525,-16.1289,3.85082,3.85082,3.85122,3.85073,-12.5915,-16.501,11.8077,11.8077,-16.1426,8.02517,8.02517,8.91683,8.91681,-14.8954,-15.0007,-15.0007,-14.6982,-16.5471,-13.6304,-13.0579,-13.1477,-13.1477,-14.1656,1.68235,9.50358,2.94094,-6.54341,-6.54341,-16.119,-16.7641,-17.3179,10.6355,10.6355,-15.6078,-13.637,2.87913,2.87914,-17.6219,-17.6219,-17.6219,5.66016,-14.0891,-13.4615,-15.309,-15.309,-15.309,2.78841,-18.0902,-15.6675,-14.3497,-14.3497,-15.1092,5.07635,5.07635,5.07633,5.07601,10.2862,-13.4971,-14.0151,-16.5304,-16.5304,-15.0921,10.3151,10.3152,-13.5986"}, "tripletriad": {"SPS": "1.5033e+06,2.98017e+06,258077,257674,3.73418e+06,3.71437e+06,3.6664e+06,4.95087e+06,794964,7.16883e+06,7.44606e+06,3.74141e+06,3.92516e+06,3.94804e+06,2.81124e+06,317549,316958,2.75394e+06,352976,436964,6.3649e+06,6.36457e+06,4.54452e+06,1.97556e+06,3.98052e+06,1.6925e+06,4.15329e+06,5.23829e+06,5.14131e+06,3.96197e+06,3.90303e+06,3.95417e+06,6.94613e+06,4.36967e+06,1.89465e+06,1.8833e+06,1.88273e+06,1.88221e+06,6.04019e+06,2.31103e+06,3.9101e+06,447893,448556,9.70416e+06,9.76249e+06,9.72116e+06,407376,410247,6.21666e+06,3.27229e+06,3.0814e+06,3.40481e+06,403865,401116,400482,398696,2.93394e+06,6.93979e+06,377005,5.42381e+06,6.27357e+06,1.29209e+06,1.29403e+06,1.29961e+06,2.15357e+06,2.64623e+06,2.64851e+06,4.33242e+06,4.20358e+06,316788,315747,316313,316049,315369,2.93589e+06,2.95866e+06,2.48994e+06,2.17457e+06,2.13539e+06,361224,359832,357815,358715,9.64235e+06,9.54276e+06,170478,169455,7.14411e+06,7.2184e+06,9.76729e+06,3.86716e+06,3.73188e+06,2.34319e+06,1.54196e+06,1.54616e+06,6.95797e+06,7.72277e+06,4.59177e+06,369734,368870,345160,344524,7.30506e+06,7.12963e+06,2.77497e+06,2.80001e+06,376272,376364,423052,2.2497e+06,212110,212309,211993,212927,7.30978e+06,1.73337e+06,1.74325e+06,8.3645e+06,2.02534e+06,2.0253e+06,132141,4.48318e+06,4.29767e+06,3.24429e+06,3.18147e+06,1.85278e+06,8.11841e+06,8.45922e+06,8.35962e+06,5.77799e+06,5.6943e+06,2.51503e+06,5.57672e+06,5.65284e+06,5.62649e+06,4.46276e+06,4.45034e+06,4.41777e+06,294264,2.42325e+06,2.36724e+06,2.38333e+06,815564,804646,4.3498e+06,3.05833e+06,2.47663e+06,2.2691e+06,2.2153e+06,494530,496433,216463,208816,228373,2.51031e+06,417059,5.56225e+06,5.55244e+06,2.75162e+06,6.23211e+06,6.53079e+06,1.74432e+06,1.74507e+06,402739,3.64115e+06,2.30313e+06,2.90748e+06,2.8855e+06,1.39371e+07,2.72748e+06,1.81786e+06,1.33164e+06,870586,5.63769e+06,5.59034e+06,5.5104e+06,4.15839e+06,3.04005e+06,364378,348569,349094,1.35577e+06,6.35847e+06,6.35692e+06,3.68874e+06,3.68097e+06,3.68025e+06,2.11235e+06,2.75351e+06,2.75371e+06,2.63395e+06,155354,6.64178e+06,6.21027e+06,8.09309e+06,3.98394e+06,2.5108e+06,704637,164822,654439,660793,2.69988e+06,2.65676e+06,6.36294e+06,173675,174149,174358,174217,2.9356e+06,2.61516e+06,449366,183327,1.73181e+06,1.22598e+06,1.22418e+06,1.21853e+06,1.22805e+06,5.72201e+06,5.10048e+06,4.94214e+06,1.91467e+06,2.00017e+06,1.11175e+06,6.31005e+06,2.98594e+06,498370,498132,5.13716e+06,1.81865e+06,8.94754e+06,732909,732631,682785,4.49018e+06,691130,9.60604e+06,3.0052e+06,8.4901e+06,2.89488e+06,779376,698983,671969,5.60784e+06,2.46185e+06,7.4462e+06,7.18205e+06,7.34976e+06,7.22201e+06,7.22014e+06,378492,5.98777e+06,6.27242e+06,1.15187e+06,2.96028e+06,2.9603e+06,2.52757e+06,1.84039e+06,218033,268699,270425,2.17147e+06", "agent_steps": "2.34291,4.45645,9.43718,15.5976,3.80109,6.29146,8.78182,3.76832,12.0914,1.27795,3.76832,1.27795,1.27795,3.76832,3.76832,7.96262,13.2055,3.76832,31.9816,2.12992,5.30842,8.71629,1.27795,2.39206,8.97843,2.88358,1.29434,3.93216,6.42253,6.12762,14.2541,16.2529,1.27795,1.85139,3.01466,8.88013,14.7784,20.6438,1.7367,2.39206,5.24288,6.16038,10.2236,1.6384,7.79878,10.879,36.7657,41.943,1.27795,27.7217,31.5884,3.93216,2.52314,7.42195,12.3535,17.2851,23.9862,1.27795,2.52314,1.27795,3.76832,4.8169,7.96262,31.9816,4.1943,29.1308,33.2268,1.27795,3.76832,2.09715,6.09485,10.1253,14.1558,16.1219,2.39206,3.44064,23.4947,1.78586,5.21011,8.0937,13.4676,6.97958,18.5139,1.27795,3.76832,2.4576,16.6134,1.27795,3.76832,1.29434,1.86778,5.45587,1.67117,18.4156,25.7556,1.27795,3.76832,1.57286,8.35584,13.8609,10.6168,16.7772,1.67117,4.84966,1.27795,3.76832,18.0879,25.1658,28.3116,3.2768,6.97958,11.5999,16.2202,18.4812,1.50733,24.4777,27.9183,3.80109,27.2302,38.1092,1.6384,6.29146,8.78182,6.29146,8.78182,3.03104,1.27795,3.76832,6.25869,1.27795,3.76832,4.55475,1.27795,3.76832,6.25869,6.68467,9.33888,10.6168,28.4426,1.58925,4.63667,7.71686,6.42253,10.6824,1.29434,2.3593,3.86662,6.42253,28.9669,18.8088,21.4303,19.7919,27.6562,31.4573,1.31072,30.4087,4.12877,6.81574,2.09715,1.27795,3.76832,7.66771,12.714,10.879,3.76832,5.96378,6.12762,14.2213,1.37626,2.58867,4.25984,7.07789,2.42483,3.93216,6.48806,9.04397,10.2892,1.34349,7.34003,12.1897,17.0394,2.7689,3.80109,6.29146,3.93216,6.48806,9.04397,3.76832,30.2776,34.5375,1.7367,6.01293,4.78413,7.92986,1.27795,2.62144,3.53894,20.7094,5.89824,7.07789,11.7309,1.31072,3.7847,4.75136,6.09485,10.0925,14.0902,15.9908,3.76832,25.8212,15.0733,5.50502,14.549,9.43718,15.6631,21.889,24.9037,5.17734,1.96608,5.8327,1.47456,4.25984,2.47398,1.6384,4.06323,20.4145,28.5409,1.27795,2.12992,1.27795,7.92986,13.1727,18.3501,14.8111,19.3331,1.57286,3.76832,3.9977,5.89824,18.645,29.7533,14.1558,3.76832,6.29146,1.27795,3.76832,6.25869,8.74906,9.96147,17.5964,1.27795,3.76832,19.3004,10.879,15.2044,3.76832,14.0247,2.62144,17.4326,19.8574,21.3975", "uptime": "1.61385,1.50106,36.4978,60.3864,1.01557,1.68315,2.36021,0.749885,16.1315,0.214293,0.547746,0.865778,0.34267,0.969057,1.32392,25.0516,41.5769,1.33439,90.1069,4.88366,0.85507,1.39062,0.313481,1.21127,2.27411,1.71099,0.317078,0.766396,1.25825,1.54389,3.61812,4.12916,0.202026,0.43543,1.59471,4.70678,7.83935,10.9553,0.301471,1.12461,1.32225,13.7567,22.8173,0.183758,0.810801,1.12713,89.7714,102.463,0.226078,8.41207,9.59187,1.13893,6.24926,18.4407,30.7808,43.1119,8.37578,0.20195,6.71797,0.281982,0.70054,3.70635,6.13932,24.6157,1.93798,10.9892,12.5373,0.295802,0.888928,6.61489,19.2804,32.0272,44.7751,50.9965,0.843644,1.25936,9.3304,1.23468,2.83924,22.6554,38.2938,19.7328,52.3164,0.149364,0.406931,14.3951,97.7107,0.209956,0.551811,0.142892,0.486801,1.43879,0.780029,11.8638,16.6792,0.228885,0.559815,0.385283,22.5881,37.4714,30.8009,48.6149,0.238572,0.681956,0.474573,1.36242,43.8606,63.6153,72.0275,1.46631,32.8077,54.6247,76.3964,87.0721,0.219454,14.2014,16.1791,0.459306,13.4553,18.8267,12.4879,1.87475,2.44099,2.40664,3.18755,1.64519,0.185819,0.482508,0.779015,0.235249,0.670484,1.78097,0.249731,0.68953,1.13117,1.46333,2.05847,2.34607,96.7337,0.656794,1.97322,3.32674,7.87886,13.1919,0.857419,0.769654,1.77943,2.83539,13.0333,38.0299,43.3576,95.0132,134.501,152.406,0.529642,72.6146,0.771703,1.25524,0.773516,0.23264,0.6152,4.36043,7.25252,27.5266,1.07091,2.52147,2.08117,4.88052,0.106074,0.959476,2.33171,4.2027,2.88813,0.82299,1.27825,1.73504,1.9686,0.448636,21.5226,35.429,49.1232,2.04573,0.638194,1.02962,1.03738,1.73101,2.42558,1.77357,11.228,12.7766,0.686202,38.6908,0.751105,1.23854,0.17725,0.677722,1.41393,29.2664,34.9009,10.8182,17.8935,0.493614,1.42144,0.76632,34.859,57.8571,80.8011,91.7083,1.29636,9.79557,33.3372,29.9937,8.44797,7.68043,12.7668,17.8707,20.3461,0.941355,0.408804,1.16885,0.858484,2.26204,2.27966,0.266233,1.35462,40.9391,57.2856,0.302455,1.20265,0.150284,10.787,17.942,25.3377,3.29603,28.0847,0.184959,1.23837,0.478553,2.26292,23.8346,38.2048,21.0532,0.664151,1.63498,0.19336,0.535747,0.875162,1.21829,1.38538,46.7324,0.238881,0.637525,16.9849,3.6796,5.14091,1.46366,7.5587,12.3238,64.5835,73.5972,9.76856", "epoch": "71.5,68,72,119,29,48,67,57.5,184.5,19.5,57.5,19.5,19.5,57.5,57.5,121.5,201.5,57.5,61,32.5,40.5,66.5,19.5,36.5,137,88,39.5,30,49,93.5,217.5,248,19.5,56.5,46,135.5,225.5,315,26.5,36.5,80,47,78,12.5,59.5,83,280.5,320,19.5,211.5,241,60,77,226.5,377,527.5,183,39,77,19.5,57.5,73.5,121.5,244,128,444.5,507,19.5,57.5,32,93,154.5,216,246,146,52.5,358.5,54.5,159,123.5,205.5,213,565,19.5,57.5,37.5,253.5,19.5,57.5,39.5,57,166.5,25.5,140.5,196.5,19.5,57.5,24,127.5,211.5,40.5,64,25.5,74,19.5,57.5,34.5,48,54,25,106.5,177,247.5,282,23,373.5,426,29,415.5,581.5,25,48,67,48,67,92.5,19.5,57.5,95.5,19.5,57.5,69.5,19.5,57.5,95.5,102,142.5,162,217,48.5,141.5,235.5,98,163,39.5,36,59,98,221,287,327,75.5,105.5,120,40,116,31.5,52,32,19.5,57.5,117,194,41.5,57.5,45.5,93.5,217,10.5,39.5,65,108,74,60,99,138,157,41,56,93,130,84.5,29,48,30,49.5,69,57.5,462,527,26.5,183.5,36.5,60.5,19.5,40,108,158,45,54,89.5,40,115.5,72.5,46.5,77,107.5,122,57.5,98.5,57.5,21,111,72,119.5,167,190,39.5,30,89,22.5,65,75.5,25,62,311.5,435.5,19.5,32.5,19.5,60.5,100.5,140,113,295,24,57.5,30.5,90,284.5,454,108,57.5,48,19.5,57.5,95.5,133.5,152,268.5,19.5,57.5,294.5,83,116,57.5,107,80,266,303,326.5", "perf/rollout": "0.00287142,0.00457637,0.0321819,0.0323177,0.00681131,0.00700754,0.00746668,0.00570189,0.0137089,0.00490547,0.00387691,0.01807,0.00492852,0.00453214,0.00652199,0.0137469,0.013783,0.00422119,0.118677,0.0127913,0.00615986,0.00616482,0.00676577,0.00576897,0.00465551,0.0036816,0.00358041,0.00640203,0.00620591,0.00343892,0.00381262,0.00347185,0.00382531,0.00146733,0.00652033,0.00673804,0.00674606,0.00675323,0.00441472,0.0071046,0.00613868,0.0184342,0.0180333,0.00644886,0.00595277,0.00600934,0.0268744,0.026931,0.00502392,0.0117745,0.0144203,0.00403602,0.00559499,0.00571991,0.0057183,0.0057094,0.0123029,0.00304017,0.00565453,0.00643794,0.00391791,0.00690444,0.00677915,0.0149319,0.00398096,0.00642419,0.00641346,0.00755941,0.00782627,0.0166878,0.0169884,0.0169015,0.016909,0.0169022,0.00108409,0.00648992,0.00966075,0.00305292,0.00317444,0.0164809,0.0161275,0.00701922,0.00688767,0.00440394,0.0041896,0.0213093,0.0210187,0.00489778,0.00420821,0.00283143,0.00279749,0.00310581,0.00613138,0.00980667,0.00949336,0.00639675,0.00465664,0.00344004,0.0129965,0.0132837,0.0604578,0.0642416,0.00317177,0.00345664,0.00470174,0.00428327,0.100607,0.100197,0.0894065,0.014469,0.0221825,0.0222962,0.0223928,0.0219991,0.00467216,0.00398838,0.00385785,0.00723004,0.00359297,0.00359244,0.0273273,0.00953858,0.0111912,0.0105474,0.0104786,0.00243994,0.00512153,0.00422914,0.00430883,0.00458618,0.00434618,0.00728884,0.00483855,0.0043194,0.00437562,0.00677148,0.00681109,0.00693011,0.0233018,0.00336075,0.00354057,0.00358915,0.00994147,0.0100484,0.00334002,0.00577745,0.00904585,0.00928941,0.00736322,0.00921927,0.00912809,0.0536794,0.0566943,0.0488012,0.00332028,0.0368891,0.00613608,0.00617664,0.00674624,0.00508354,0.00418537,0.00787082,0.00786087,0.030893,0.00606448,0.0116457,0.00737836,0.00705078,0.00743494,0.0064404,0.00632502,0.0114863,0.00442401,0.00427032,0.00436893,0.00461728,0.00832844,0.00306885,0.0357036,0.0374343,0.037844,0.00326861,0.00546214,0.00546664,0.015724,0.015791,0.0158019,0.00678539,0.00387316,0.00387573,0.0068759,0.00928798,0.0087177,0.0103262,0.00388715,0.00365042,0.00297357,0.0188512,0.034259,0.013633,0.0136417,0.00330141,0.00347907,0.00444766,0.0461185,0.0465028,0.0459038,0.0464847,0.00450828,0.0284939,0.0603112,0.0722076,0.0115228,0.00869782,0.00849438,0.00888943,0.00836015,0.00644097,0.0046881,0.00491725,0.0083569,0.00748166,0.00385502,0.00389001,0.00488431,0.00812378,0.00810669,0.0102279,0.00738719,0.00537894,0.021548,0.0215841,0.0238881,0.0107815,0.00909567,0.00478886,0.00653805,0.00606828,0.0070727,0.00571673,0.00526333,0.0177042,0.00560941,0.0183756,0.00469719,0.00456439,0.00436332,0.00450767,0.0045042,0.0124855,0.0051755,0.00426288,0.00894775,0.00589686,0.00589681,0.00648307,0.00934994,0.00693525,0.0125142,0.0123532,0.00518589", "perf/eval_gpu": "0.00114494,0.00122568,0.0226929,0.0224534,0.00191199,0.00194575,0.00193045,0.00137537,0.00849289,0.00223374,0.00145938,0.00529248,0.00238139,0.00194903,0.00184154,0.00910334,0.0090971,0.00104308,0.0669986,0.00725427,0.00192441,0.00190019,0.00390405,0.00123681,0.00180411,0.0013498,0.00132839,0.00193064,0.00194518,0.0011698,0.00119472,0.00116574,0.00175474,0.0005196,0.00186818,0.00185171,0.00184792,0.00184866,0.00159649,0.00236705,0.00155195,0.0116109,0.0115011,0.00242907,0.00179366,0.00179547,0.0202639,0.0204464,0.00182688,0.00248234,0.00250291,0.00137699,0.00387483,0.00386055,0.00387926,0.00391046,0.00311897,0.00135907,0.00386798,0.00295654,0.001432,0.00164341,0.00158905,0.0056128,0.00151537,0.00138844,0.0013966,0.00312285,0.00307765,0.0123168,0.0123487,0.0123278,0.0123359,0.0123335,0.000415598,0.00211539,0.00482483,0.000765124,0.000766847,0.011224,0.0113176,0.00451738,0.00449935,0.00180198,0.00141137,0.0157062,0.0158097,0.00182755,0.00141347,0.0013218,0.000658872,0.000654947,0.00182673,0.0029702,0.00299899,0.00288171,0.00176735,0.000938374,0.00805045,0.00800242,0.0378357,0.0376773,0.000967594,0.000966915,0.0025503,0.00234508,0.0640053,0.0716492,0.0640617,0.00431761,0.0169505,0.0169544,0.0169777,0.0169687,0.00164815,0.0012676,0.00125128,0.00176187,0.00137782,0.00138248,0.0212577,0.0035227,0.00362478,0.00305227,0.00307892,0.000802251,0.00219196,0.00162811,0.00164442,0.00185085,0.0015464,0.00206406,0.00176688,0.00143239,0.00145267,0.00199392,0.00199329,0.00198564,0.0184051,0.00114887,0.00114202,0.00117477,0.00510472,0.00510559,0.00132353,0.00154871,0.00203462,0.0039079,0.00209293,0.00430193,0.00428923,0.0425733,0.0465513,0.0390726,0.00114898,0.0262604,0.00192642,0.00191421,0.00205713,0.00186137,0.00145038,0.00306894,0.00307264,0.0158116,0.00183747,0.00250277,0.00237825,0.00238014,0.00240669,0.00145966,0.00160811,0.00628874,0.0019589,0.00159803,0.00158862,0.00160705,0.00152006,0.00103516,0.0260131,0.0271661,0.0275593,0.000922366,0.00166323,0.00168081,0.00618827,0.0061968,0.00620053,0.00206855,0.00124268,0.00133253,0.00213705,0.00678591,0.00341763,0.00359848,0.00177444,0.00106204,0.000782306,0.00918388,0.0276738,0.00727844,0.00729537,0.00114564,0.00115194,0.00154551,0.0368876,0.0369947,0.0361246,0.0368586,0.00124904,0.0087539,0.0374568,0.0469033,0.00656762,0.00321888,0.00325853,0.00332591,0.00326112,0.00191428,0.00191601,0.0017177,0.00305763,0.0023537,0.00144023,0.0011771,0.00103666,0.00432649,0.00435041,0.00633494,0.0027752,0.00211147,0.0113696,0.0113783,0.0136114,0.00345352,0.00424902,0.00172527,0.00204601,0.00170902,0.0023801,0.00314976,0.00271904,0.00740984,0.00138081,0.013071,0.00210181,0.00159291,0.00162493,0.00161107,0.00172306,0.0074811,0.00230928,0.00169961,0.00401583,0.00178994,0.00179897,0.00183165,0.00292282,0.00545919,0.00756949,0.00750359,0.00158678", "perf/eval_env": "0.00135702,0.00304564,0.00897261,0.00935082,0.00448229,0.00457167,0.00472411,0.00402356,0.00490564,0.00133779,0.00150569,0.0114407,0.00160768,0.0017336,0.00436131,0.00434933,0.00439142,0.00288176,0.0503178,0.00520209,0.0036297,0.00365232,0.00114073,0.00417777,0.00231586,0.00212445,0.00202174,0.00381002,0.00359287,0.00186454,0.00193653,0.00185618,0.00152791,0.000660726,0.00432271,0.0045911,0.00460552,0.00461206,0.0021038,0.00441678,0.00428063,0.00591082,0.00583221,0.00293387,0.00357232,0.00362215,0.00606395,0.00597561,0.001665,0.00876944,0.0100356,0.001902,0.0014309,0.00156249,0.00150853,0.0015001,0.00868052,0.000988279,0.00148556,0.00177619,0.00150034,0.00468711,0.00465363,0.00889119,0.00223814,0.00423062,0.00421594,0.00401501,0.00437231,0.00406865,0.00433672,0.00427609,0.00427488,0.00427442,0.000366099,0.00405637,0.00446993,0.00208221,0.00220561,0.00490161,0.00448846,0.00229376,0.00218487,0.00187146,0.00221425,0.00530093,0.0049116,0.00198807,0.00191846,0.00128213,0.00193053,0.00223747,0.00398481,0.00623653,0.00597597,0.00129604,0.00130542,0.00141066,0.0045596,0.00492772,0.0219672,0.0259373,0.00188124,0.00216724,0.00157309,0.00141378,0.0315219,0.025882,0.0244628,0.00971294,0.00488933,0.00501349,0.00508791,0.00469805,0.00220021,0.00231547,0.00228774,0.0037013,0.00169968,0.00170123,0.00575657,0.00483983,0.0053491,0.00658087,0.00640134,0.00141219,0.00180364,0.00179699,0.00184624,0.00206448,0.0021576,0.00489484,0.00221043,0.0022847,0.00230423,0.00434303,0.00438221,0.00450036,0.00391757,0.00200579,0.00219588,0.00221048,0.00451651,0.00462103,0.00180004,0.00391541,0.00664826,0.00503347,0.00471296,0.00453257,0.00447033,0.00981573,0.00898866,0.00883923,0.00196762,0.00968133,0.00361478,0.00366722,0.00436133,0.00230889,0.00211602,0.00451392,0.00450041,0.0129335,0.00389947,0.00875144,0.00467111,0.00438467,0.00453023,0.0046059,0.00439054,0.00444931,0.00220311,0.00185405,0.00188842,0.00192794,0.00241311,0.00183284,0.0092713,0.0098383,0.00984657,0.00212262,0.00309629,0.00306723,0.00884113,0.00890152,0.00890842,0.00439406,0.00223609,0.00220892,0.00445106,0.00225076,0.00381376,0.00425044,0.00154962,0.00223316,0.00199622,0.00915585,0.00525709,0.00579877,0.00580492,0.0019486,0.00212553,0.00227486,0.00873226,0.00900645,0.00929258,0.00916254,0.00291635,0.0191021,0.0221981,0.0245609,0.00396049,0.00475213,0.00470815,0.00477455,0.00459989,0.00389605,0.00193022,0.00198489,0.00497105,0.00480991,0.00219733,0.00239667,0.00335107,0.00337606,0.00332704,0.00101417,0.00431228,0.00295851,0.00975792,0.00978562,0.00983458,0.00629304,0.00446653,0.00217547,0.00417081,0.00310989,0.00440304,0.00191958,0.0019252,0.00946692,0.00393197,0.00363585,0.0016165,0.00208325,0.00192735,0.00198619,0.00194499,0.00462855,0.00166973,0.00170278,0.00460339,0.00363682,0.00363604,0.00432928,0.00592131,0.000976745,0.00456545,0.00448036,0.00326521", "perf/train_misc": "0.00141636,0.00303103,0.00793372,0.00794909,0.00451154,0.004527,0.00451527,0.00149118,0.00217737,0.000867495,0.000644223,0.00174215,0.00109036,0.000837699,0.00537705,0.00450883,0.00452021,0.00515003,0.0588918,0.00738967,0.00210773,0.00210938,0.000842957,0.00739653,0.000697369,0.00198438,0.000598405,0.00274756,0.00273976,0.00134176,0.00134063,0.00135578,0.000999913,0.00107598,0.00217978,0.00217895,0.00218511,0.00218426,0.00108964,0.00567056,0.00156834,0.0147064,0.0147022,0.00208172,0.00139642,0.00139433,0.00813004,0.00810822,0.00106222,0.00627404,0.00626387,0.00116686,0.00121582,0.00122024,0.00122211,0.00122493,0.00473088,0.000242828,0.00130613,0.00118018,0.000873467,0.00734764,0.00736421,0.0151805,0.00132222,0.00183267,0.0018409,0.00106355,0.000813975,0.00220443,0.00221173,0.00221226,0.0022162,0.00223338,0.000558792,0.0023666,0.00244501,0.00211525,0.0021119,0.00450064,0.00546315,0.00207068,0.00205107,0.00048293,0.000360205,0.00452766,0.00455467,0.000859509,0.000654984,8.84101e-05,0.00118865,0.0011849,0.00681941,0.0128948,0.0129026,0.000680516,0.000521096,0.00228524,0.00418663,0.00419558,0.028781,0.0289444,0.00114395,0.00113661,0.00120568,0.000914301,0.0501662,0.0499108,0.0497048,0.011699,0.0043059,0.00431599,0.00432792,0.00435712,0.000788153,0.00420597,0.00429482,0.00167877,0.00224159,0.00224148,0.00575939,0.00139646,0.00140851,0.00238692,0.00238107,0.00125199,0.000504742,0.000383866,0.000383967,0.000936883,0.000719952,0.00509293,0.00122642,0.000933225,0.000932704,0.000819437,0.000816162,0.0008192,0.00812751,0.00180584,0.00179969,0.00180023,0.00409076,0.00409269,0.000575414,0.00233687,0.00474884,0.0129782,0.00902703,0.00454006,0.00458752,0.0318349,0.0318279,0.031655,0.00176732,0.0165712,0.00254037,0.00253936,0.00385152,0.00101448,0.000766518,0.00237821,0.00237661,0.0550958,0.00366369,0.0116386,0.00229421,0.00229372,0.000551104,0.00266261,0.00377447,0.00436025,0.00224118,0.000783179,0.000784844,0.000786634,0.000789504,0.00167029,0.006203,0.00633517,0.00628588,0.00221885,0.00281807,0.00281413,0.00213011,0.00213304,0.00213464,0.00659996,0.00199654,0.0019968,0.00369446,0.00219686,0.00108355,0.00108489,0.000766301,0.00193813,0.00179216,0.0073539,0.00970967,0.0152387,0.0152569,0.00157048,0.00157059,0.000616391,0.00733376,0.0073425,0.00736421,0.00736278,0.00280266,0.0159409,0.0141747,0.0556685,0.00208112,0.00765736,0.00765147,0.00767014,0.00766688,0.00241618,0.0010692,0.000899562,0.00579883,0.00401444,0.00125753,0.00095604,0.00382462,0.00451465,0.00451748,0.000649745,0.00418344,0.000540911,0.00785151,0.00785157,0.0079151,0.0020521,0.00236032,0.000401477,0.00347813,0.0018084,0.00231404,0.00345686,0.00347773,0.0080133,0.00120298,0.00605738,0.000638685,0.000487697,0.000486681,0.000486864,0.00049184,0.00238303,0.000825219,0.000631632,0.00378473,0.00489878,0.00489981,0.00630252,0.00754683,0.00238211,0.00466914,0.00465306,0.00192674", "perf/train_forward": "0.0171626,0.0141124,0.467707,0.468453,0.0234539,0.023494,0.0234494,0.00577549,0.0702109,0.00530067,0.0040927,0.0146677,0.0142844,0.0110356,0.0110751,0.187893,0.188105,0.0134906,1.30421,0.129452,0.0121124,0.0120988,0.00959612,0.0196416,0.010922,0.013444,0.00352486,0.0154868,0.0154771,0.011542,0.0115393,0.01152,0.00638308,0.00473578,0.025648,0.0256607,0.02565,0.0256577,0.00675719,0.0148407,0.00882983,0.259053,0.259053,0.00856702,0.00584379,0.00584679,0.284274,0.284688,0.00652521,0.0214974,0.0215122,0.0139025,0.0742241,0.0744046,0.0744351,0.0745625,0.0275251,0.00176755,0.0793721,0.00710021,0.005468,0.036122,0.036154,0.0699924,0.0096915,0.016253,0.0162304,0.00880287,0.00676228,0.187476,0.187908,0.18817,0.188289,0.187946,0.00374937,0.0130014,0.0130106,0.00964689,0.00965546,0.16808,0.169334,0.0820191,0.0823173,0.00288636,0.00212709,0.357944,0.360078,0.00522702,0.00402019,0.000287725,0.0042923,0.00426405,0.0138418,0.0611435,0.0611472,0.00417226,0.00314887,0.00846493,0.159299,0.15947,0.665294,0.667566,0.00438029,0.00435429,0.0232994,0.0179742,1.27414,1.33019,1.10117,0.0316348,0.281812,0.28218,0.282839,0.285147,0.00477819,0.0292358,0.0291707,0.0068966,0.0262636,0.0262675,0.566717,0.0180798,0.0181212,0.027156,0.0271785,0.013701,0.00390618,0.00295416,0.00295359,0.00794039,0.00611718,0.0133081,0.00795485,0.00612627,0.00612224,0.00690725,0.00690802,0.00689766,0.412438,0.00811875,0.00809523,0.00809346,0.0659655,0.0659499,0.00330407,0.013066,0.0123175,0.0129358,0.0423156,0.118004,0.117965,1.16338,1.27269,1.06404,0.00773079,0.573563,0.0146167,0.0146286,0.0129278,0.00638477,0.00487955,0.0270137,0.0270159,0.563773,0.0075381,0.0317831,0.0126814,0.0126905,0.00114961,0.0145679,0.0256212,0.0280482,0.0300893,0.0063874,0.00638306,0.00638346,0.00642048,0.00580969,0.316908,0.342904,0.341121,0.0184324,0.012064,0.0120702,0.0174611,0.0174481,0.0174465,0.0172362,0.0176975,0.0176333,0.0136469,0.198703,0.0096997,0.00971352,0.00485789,0.0106098,0.00803882,0.158119,0.779743,0.168861,0.168963,0.00702355,0.00702972,0.00504814,0.696227,0.697871,0.698354,0.696972,0.0146673,0.0553639,0.509604,1.30086,0.0620339,0.0902068,0.0901836,0.0902646,0.0903229,0.013804,0.00881199,0.00740312,0.0211016,0.0209704,0.0239593,0.00530922,0.0129338,0.118122,0.11812,0.00388272,0.0288957,0.00193282,0.149095,0.149131,0.159004,0.0161638,0.082903,0.00235762,0.0114499,0.00732648,0.0130033,0.0744362,0.074411,0.168906,0.0046388,0.0554118,0.00509376,0.00388406,0.00388673,0.00388357,0.00388915,0.15812,0.00696689,0.00536145,0.0435207,0.0331366,0.0331416,0.0127929,0.0527458,0.143926,0.225003,0.224788,0.022572", "perf/train": "0.018579,0.0171435,0.47564,0.476402,0.0279655,0.028021,0.0279647,0.00726667,0.0723883,0.00616817,0.00473692,0.0164099,0.0153748,0.0118733,0.0164522,0.192402,0.192625,0.0186407,1.36311,0.136841,0.0142201,0.0142082,0.0104391,0.0270381,0.0116193,0.0154283,0.00412327,0.0182343,0.0182168,0.0128838,0.0128799,0.0128758,0.00738299,0.00581176,0.0278277,0.0278396,0.0278351,0.027842,0.00784683,0.0205112,0.0103982,0.27376,0.273755,0.0106487,0.00724022,0.00724112,0.292404,0.292797,0.00758743,0.0277714,0.0277761,0.0150693,0.0754399,0.0756248,0.0756572,0.0757874,0.032256,0.00201038,0.0806783,0.00828038,0.00634147,0.0434696,0.0435183,0.0851729,0.0110137,0.0180856,0.0180713,0.00986642,0.00757626,0.18968,0.19012,0.190382,0.190505,0.190179,0.00430816,0.015368,0.0154556,0.0117621,0.0117674,0.172581,0.174797,0.0840897,0.0843684,0.00336929,0.0024873,0.362472,0.364632,0.00608653,0.00467517,0.000376135,0.00548095,0.00544895,0.0206612,0.0740383,0.0740498,0.00485278,0.00366996,0.0107502,0.163485,0.163665,0.694075,0.69651,0.00552424,0.0054909,0.0245051,0.0188885,1.3243,1.3801,1.15087,0.0433338,0.286118,0.286496,0.287167,0.289504,0.00556634,0.0334417,0.0334655,0.00857537,0.0285052,0.028509,0.572476,0.0194762,0.0195298,0.029543,0.0295595,0.014953,0.00441092,0.00333803,0.00333756,0.00887727,0.00683714,0.0184011,0.00918127,0.00705949,0.00705494,0.00772669,0.00772418,0.00771686,0.420565,0.00992458,0.00989492,0.0098937,0.0700563,0.0700426,0.00387948,0.0154029,0.0170663,0.025914,0.0513426,0.122545,0.122552,1.19521,1.30452,1.0957,0.00949812,0.590134,0.0171571,0.017168,0.0167793,0.00739926,0.00564607,0.0293919,0.0293925,0.618869,0.0112018,0.0434217,0.0149756,0.0149842,0.00170071,0.0172305,0.0293957,0.0324084,0.0323305,0.00717058,0.00716791,0.00717009,0.00720998,0.00747999,0.323111,0.349239,0.347407,0.0206513,0.0148821,0.0148843,0.0195912,0.0195811,0.0195811,0.0238362,0.019694,0.0196301,0.0173413,0.200899,0.0107832,0.0107984,0.00562419,0.0125479,0.00983097,0.165473,0.789453,0.184099,0.18422,0.00859403,0.00860031,0.00566454,0.703561,0.705213,0.705718,0.704335,0.01747,0.0713048,0.523778,1.35653,0.064115,0.0978641,0.097835,0.0979348,0.0979898,0.0162202,0.00988119,0.00830268,0.0269004,0.0249848,0.0252168,0.00626526,0.0167584,0.122636,0.122638,0.00453246,0.0330791,0.00247373,0.156946,0.156982,0.166919,0.0182159,0.0852634,0.0027591,0.0149281,0.00913488,0.0153174,0.0778931,0.0778887,0.176919,0.00584178,0.0614691,0.00573244,0.00437176,0.00437341,0.00437044,0.00438099,0.160503,0.00779211,0.00599308,0.0473055,0.0380354,0.0380414,0.0190955,0.0602926,0.146308,0.229672,0.229442,0.0244988", "util/gpu_percent": "77.1143,90.8,98.4894,99.1277,89.5263,93,93,75,95.4459,6,6,35.2632,88.6053,93.3684,80,97.1875,97.625,89.3947,100,96.3548,94,94.5,64,91.5588,95,75.8728,12.4342,71,96,96.3226,94.4839,95,12.2368,58.9352,80.809,87.6444,87.6444,87.9775,17.1154,85.4265,78.9811,98.7419,99.2258,0,93,93,95.275,100,1,80.05,79,92.3333,97.9866,93.82,97.8411,97.92,79,0,97.9195,13.7368,87,91.4167,91.7708,89,81.5294,86.2698,85,53,57.4474,97.8689,97.0492,97.5,97.7869,100,67.7979,89.3333,88.8431,71.5577,72.4286,97.5854,97.5854,96.844,97,0,56.5789,99.1528,99.0833,37.5263,62,22.6579,27,72.9091,94.2174,95.4464,78.7143,54.9474,58,94,96.4524,96.9762,97.1875,100,7,7,100,98.0526,99.7857,100,100,80.3617,98.7714,98.6479,98.1857,100,32,96.2547,97,1,98,98,94.8571,95,94,87.5789,86,85.7944,2,2,72.2632,16.9474,92,79.2609,35.1316,89,89.1316,73.9756,72,72,99.6721,34.7609,81.3511,81.9468,92.5538,93.4,51.4211,51.1014,74.5641,73.4615,94.4921,91.0988,95,100,99.9333,100,72.8,99.1818,54,96,70.2373,59.9211,69,86.4805,86.4156,99.6875,62.4737,84.2667,79.3871,66.9344,1,55.0921,90.0465,92.0233,73.1678,92,93.7949,94,94,19.5584,97.0811,97.1081,97.0541,84.628,73,80.5789,77.8421,69,69,85.4474,95,95,48.98,98.7623,75.25,94,37.8947,70.8182,64.9249,94.9556,99.7931,89.9143,97.3056,60.48,79.6579,42.5,98.2,100,99.1667,100,66.4286,79.6429,98.375,100,96,98.3617,98.2083,95.8936,98,87.0385,25.4915,94,89.4762,84.5814,91.1027,15,84,97.5242,97.5887,14,85.75,0,94,94.4,95.0769,85,95,1,78.2895,30,78.7458,98.614,98,95.7442,20.3947,98.2105,47.8947,70,70,85.4737,91,97.1711,3,58.0789,91.0714,97.5152,97.8485,80.9474,91.6279,99.471,98.5333,95,90.8538", "util/gpu_mem": "4.66155,4.52313,9.09894,9.09894,5.37804,5.37804,5.37804,4.22188,18.2959,4.97909,4.97909,5.15821,5.31291,5.31291,4.15674,5.88285,5.88285,4.58827,9.13965,6.36322,5.16635,5.16635,15.4711,4.31144,5.23963,4.35215,4.13232,5.16635,5.16635,5.28848,5.28848,5.28848,4.52313,4.85696,19.683,19.683,19.683,19.683,4.58827,14.1928,4.5557,6.7459,6.7459,4.97094,4.97094,4.97094,7.8125,7.8125,4.58827,4.6127,4.6127,5.60602,7.32398,7.32398,7.32398,7.32398,4.70226,4.37658,7.32398,4.89767,4.89767,4.76739,4.76739,4.75111,4.1486,4.99537,4.99537,4.38472,4.38472,8.32545,8.32545,8.32545,8.32545,8.32545,4.79996,16.098,18.136,4.31958,4.31958,20.5813,19.7085,5.85028,5.85028,4.66969,4.66969,7.45425,7.45425,4.74297,4.74297,4.13232,4.16489,4.16489,4.15674,5.03608,5.03608,5.14193,5.14193,16.3911,7.60895,7.60895,6.61563,6.61563,4.64526,4.64526,20.8962,20.8962,22.7774,22.3212,22.5063,17.5608,10.3935,10.3935,10.3935,10.3935,4.58827,4.84881,4.84881,4.88138,5.55717,5.55717,8.25217,5.39433,5.39433,5.2722,5.2722,5.05236,5.01165,5.01165,5.01165,4.66969,4.66969,4.31144,4.66969,4.66969,4.66969,4.53942,4.53942,4.53942,9.54675,4.18117,4.18117,4.18117,6.37137,6.37137,4.13232,4.5557,16.3639,16.0858,4.84881,5.23963,5.23963,22.0942,19.9282,19.5583,4.18117,8.23588,5.16635,5.16635,4.48242,19.0887,19.0887,4.83253,4.83253,7.75551,4.15674,4.44986,4.40915,4.40915,4.38472,4.83253,19.8214,19.3423,4.81625,14.9691,14.9691,14.9691,14.9691,4.05904,23.6645,23.2361,23.536,4.58013,5.12564,5.12564,4.53128,4.53128,4.53128,4.31144,5.15007,5.15007,4.12418,7.60081,5.26406,5.26406,4.52313,4.84881,4.31958,6.24924,21.9572,5.90727,5.90727,4.18117,4.18117,4.85696,11.9486,11.9486,11.9486,11.9486,5.10122,4.85696,7.75551,8.67555,6.48535,6.20853,6.20853,6.20853,6.20853,5.16635,5.01165,5.01165,17.6585,17.6585,5.55717,4.38472,4.75925,5.38619,5.38619,5.06051,15.9514,4.22188,20.8229,20.8229,20.1727,4.89767,5.88285,4.66969,4.48242,5.03608,4.40915,5.67115,5.67115,6.24924,10.1897,19.5935,5.01165,5.01165,5.01165,5.01165,5.01165,7.18557,4.99537,4.99537,5.67115,20.3669,20.3669,4.15674,5.3699,21.3101,6.0294,6.0294,5.1175", "util/vram_used_gb": "0.657104,0.623901,1.72156,1.72156,0.828979,0.828979,0.828979,0.551636,3.92774,0.733276,0.733276,0.776245,0.813354,0.813354,0.536011,0.950073,0.950073,0.639526,1.73132,1.06531,0.778198,0.778198,3.25012,0.57312,0.795776,0.582886,0.530151,0.778198,0.778198,0.807495,0.807495,0.807495,0.623901,0.703979,4.2605,4.2605,4.2605,4.2605,0.639526,2.94348,0.631714,1.1571,1.1571,0.731323,0.731323,0.731323,1.41296,1.41296,0.639526,0.645386,0.645386,0.883667,1.29578,1.29578,1.29578,1.29578,0.66687,0.588745,1.29578,0.713745,0.713745,0.682495,0.682495,0.678589,0.534058,0.737183,0.737183,0.590698,0.590698,1.53601,1.53601,1.53601,1.53601,1.53601,0.690308,3.40051,3.8894,0.575073,0.575073,4.47598,4.2666,0.942261,0.942261,0.659058,0.659058,1.32703,1.32703,0.676636,0.676636,0.530151,0.537964,0.537964,0.536011,0.746948,0.746948,0.772339,0.772339,3.47083,1.36414,1.36414,1.12585,1.12585,0.653198,0.653198,4.55151,4.55151,5.00279,4.89334,4.93774,3.7514,2.0321,2.0321,2.0321,2.0321,0.639526,0.702026,0.702026,0.709839,0.871948,0.871948,1.51843,0.832886,0.832886,0.803589,0.803589,0.750854,0.741089,0.741089,0.741089,0.659058,0.659058,0.57312,0.659058,0.659058,0.659058,0.627808,0.627808,0.627808,1.82898,0.54187,0.54187,0.54187,1.06726,1.06726,0.530151,0.631714,3.46429,3.39758,0.702026,0.795776,0.795776,4.83889,4.3193,4.23059,0.54187,1.51453,0.778198,0.778198,0.614136,4.11792,4.11792,0.69812,0.69812,1.39929,0.536011,0.606323,0.596558,0.596558,0.590698,0.69812,4.2937,4.17876,0.694214,3.1297,3.1297,3.1297,3.1297,0.512573,5.21558,5.11282,5.18475,0.637573,0.768433,0.768433,0.625854,0.625854,0.625854,0.57312,0.774292,0.774292,0.528198,1.36218,0.801636,0.801636,0.623901,0.702026,0.575073,1.03796,4.80604,0.955933,0.955933,0.54187,0.54187,0.703979,2.40515,2.40515,2.40515,2.40515,0.762573,0.703979,1.39929,1.62,1.0946,1.0282,1.0282,1.0282,1.0282,0.778198,0.741089,0.741089,3.77484,3.77484,0.871948,0.590698,0.680542,0.830933,0.830933,0.752808,3.36536,0.551636,4.53394,4.53394,4.37796,0.713745,0.950073,0.659058,0.614136,0.746948,0.596558,0.899292,0.899292,1.03796,1.98322,4.23901,0.741089,0.741089,0.741089,0.741089,0.741089,1.26257,0.737183,0.737183,0.899292,4.42456,4.42456,0.536011,0.827026,4.65081,0.985229,0.985229,0.766479", "util/vram_total_gb": "23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272,23.5272", "util/cpu_mem_gb": "1.08383,1.09186,1.096,1.096,1.10606,1.10606,1.10606,1.08993,1.0035,1.10221,1.10221,1.10823,1.10238,1.10238,1.097,1.08587,1.08587,1.09877,1.11491,1.09506,1.10283,1.10283,1.0435,1.09806,1.09104,1.08802,1.08731,1.10131,1.10131,1.09602,1.09613,1.09651,1.09424,1.09232,1.00776,1.00776,1.00776,1.00782,1.09532,1.01682,1.09143,1.09899,1.09899,1.10244,1.10244,1.10244,1.09842,1.09842,1.09599,1.10224,1.10224,1.10022,1.08698,1.08698,1.08698,1.08698,1.0949,1.09131,1.08398,1.10102,1.10102,1.09388,1.09388,1.09515,1.08701,1.09714,1.09714,1.08915,1.08915,1.08505,1.08522,1.08522,1.08522,1.08522,1.09164,1.01168,1.01217,1.08774,1.08774,1.01364,1.01364,1.08314,1.08363,1.09621,1.09621,1.08786,1.08786,1.10037,1.10037,1.08526,1.08902,1.08902,1.09557,1.09504,1.09504,1.10321,1.10363,1.01735,1.09348,1.09348,1.0965,1.0965,1.09655,1.09655,1.01399,1.01399,1.03711,1.03711,1.03711,1.0195,1.09436,1.09436,1.09436,1.09436,1.0948,1.09723,1.09727,1.09933,1.0939,1.09394,1.08714,1.11268,1.11268,1.09283,1.09283,1.08568,1.09867,1.09867,1.09867,1.09985,1.09985,1.09642,1.09754,1.09754,1.09754,1.09022,1.09067,1.09067,1.10404,1.08863,1.08863,1.08863,1.09363,1.09363,1.08411,1.09024,1.01746,1.01766,1.09989,1.0871,1.0871,1.02833,1.02833,1.02833,1.08732,1.10666,1.10092,1.10092,1.0978,1.01468,1.01468,1.08437,1.08437,1.11511,1.09603,1.09904,1.08996,1.08996,1.09922,1.10232,1.0143,1.0143,1.0829,1.01953,1.01953,1.01953,1.01953,1.08816,1.01171,1.01171,1.01171,1.08378,1.10431,1.10465,1.09242,1.09242,1.09255,1.09717,1.09624,1.09624,1.0905,1.08746,1.118,1.118,1.09284,1.09626,1.09069,1.09606,1.02325,1.09756,1.09756,1.08786,1.08786,1.09576,1.09865,1.09865,1.09865,1.09865,1.10264,1.10161,1.09482,1.11053,1.09842,1.1004,1.1004,1.1004,1.1004,1.10376,1.09767,1.09767,1.01914,1.01914,1.08429,1.09472,1.10032,1.08949,1.08949,1.10466,1.00953,1.0885,1.01436,1.01436,1.01436,1.10223,1.08747,1.09719,1.09942,1.1034,1.08995,1.09018,1.09067,1.09296,1.00835,1.02372,1.09945,1.09945,1.09945,1.09945,1.09945,1.08785,1.10317,1.10317,1.09302,1.02042,1.02042,1.09709,1.09672,1.00695,1.08508,1.08508,1.08951", "env/perf": "0.640851,0.72401,0.772168,0.789182,0.708941,0.748306,0.765446,0.659273,0.776304,0.336945,0.674252,0.395471,0.453907,0.674039,0.665584,0.771031,0.786412,0.675695,0.804914,0.648876,0.720127,0.75051,0.0761883,0.613697,0.763444,0.669027,0.50327,0.708937,0.742033,0.741156,0.779583,0.786142,0.0251561,0.565795,0.638734,0.770379,0.784165,0.791774,0.519482,0.629289,0.734614,0.755714,0.775793,0.314933,0.736867,0.75317,0.808668,0.811835,0.0553499,0.791651,0.794878,0.714544,0.658197,0.767631,0.783847,0.79195,0.788195,0.0686275,0.660901,0.46709,0.674446,0.739592,0.760875,0.805184,0.729201,0.795542,0.798535,0.392798,0.70067,0.637444,0.763016,0.780367,0.790579,0.796874,0.614843,0.6387,0.790431,0.628559,0.74045,0.769248,0.787396,0.761877,0.794078,0.322019,0.610811,0.642497,0.795335,0.368854,0.644199,0.101266,0.581733,0.734771,0.562986,0.788216,0.795102,0.43952,0.664731,0.507245,0.768574,0.787243,0.773721,0.790908,0.49466,0.704321,0.462359,0.689105,0.792057,0.80096,0.802306,0.635836,0.761419,0.785208,0.795899,0.796698,0.461368,0.792091,0.798416,0.617572,0.796222,0.804186,0.594873,0.75023,0.764192,0.746971,0.765519,0.673458,0.424007,0.688607,0.72038,0.434291,0.653974,0.730044,0.41614,0.692401,0.733247,0.755665,0.77014,0.774466,0.807034,0.549713,0.738299,0.759775,0.756522,0.774775,0.511632,0.588472,0.72223,0.749903,0.795096,0.790132,0.793019,0.797747,0.805673,0.808751,0.525314,0.802172,0.710492,0.740083,0.599109,0.472174,0.6845,0.762164,0.77853,0.777572,0.648244,0.741411,0.747597,0.776662,0.223301,0.630482,0.735722,0.757875,0.648392,0.712444,0.749755,0.763611,0.765701,0.516401,0.766184,0.784735,0.794033,0.658663,0.692727,0.732359,0.719448,0.759481,0.771822,0.695817,0.796351,0.802932,0.563101,0.753659,0.706223,0.740495,0.0430732,0.626543,0.650938,0.789419,0.754378,0.765446,0.780124,0.551233,0.711423,0.70652,0.759997,0.78059,0.792208,0.794357,0.651344,0.793411,0.784368,0.74481,0.779289,0.768163,0.787721,0.796671,0.798428,0.720997,0.561606,0.737151,0.604413,0.730505,0.655125,0.495702,0.72239,0.792744,0.801464,0.174199,0.606486,0.201606,0.759478,0.779238,0.78815,0.780349,0.78923,0.360049,0.662442,0.618488,0.742037,0.789582,0.798318,0.78127,0.649885,0.742724,0.306015,0.663057,0.726092,0.746075,0.749153,0.790794,0.418806,0.656811,0.790261,0.777141,0.788607,0.668621,0.780991,0.675769,0.793737,0.798586,0.78876", "env/score": "5.89037,6.15526,6.31172,6.37178,6.11009,6.23208,6.28871,5.94746,6.33879,5.08348,6.00296,5.15814,5.36348,5.97882,5.96336,6.30712,6.36261,6.01381,6.43191,5.91227,6.13966,6.23685,4.7512,5.82573,6.27095,5.97828,5.51188,6.10467,6.21159,6.20879,6.34265,6.3537,4.91676,5.68508,5.90604,6.30578,6.35675,6.38231,5.5466,5.85554,6.18146,6.24978,6.31491,5.06116,6.19238,6.24375,6.44571,6.44732,4.843,6.37985,6.39116,6.12106,5.96109,6.30132,6.35428,6.38216,6.37434,4.81117,5.96478,5.39026,5.96919,6.21261,6.2861,6.4092,6.16452,6.39491,6.4079,5.22733,6.08024,5.89431,6.276,6.33578,6.3714,6.38487,5.82964,5.9008,6.375,5.88111,6.21352,6.30705,6.36904,6.27697,6.40671,5.00586,5.78426,5.92295,6.39618,5.13448,5.90003,4.75529,5.72884,6.18881,5.63863,6.37115,6.39546,5.34764,5.96261,5.55636,6.30349,6.364,6.32298,6.38656,5.50351,6.09521,5.33618,6.01065,6.38602,6.41836,6.42002,5.89004,6.27635,6.35757,6.39443,6.39754,5.39954,6.38286,6.40224,5.82931,6.4001,6.42881,5.77036,6.23375,6.28598,6.23369,6.29024,5.99684,5.31162,6.04963,6.14178,5.3071,5.9274,6.17531,5.30579,6.04838,6.17608,6.25396,6.30482,6.31879,6.44,5.63789,6.20424,6.27292,6.26152,6.32151,5.51528,5.75049,6.15122,6.23702,6.39376,6.38298,6.39339,6.41044,6.44046,6.44729,5.56689,6.42059,6.11131,6.20712,5.77311,5.43033,6.01658,6.27942,6.339,6.32998,5.8821,6.21832,6.23066,6.33139,4.88338,5.86089,6.19975,6.27017,5.91059,6.11194,6.23171,6.28048,6.28582,5.52599,6.29932,6.36194,6.39389,5.96394,6.05509,6.17531,6.13761,6.27011,6.30877,6.07331,6.39634,6.41006,5.69086,6.25361,6.08984,6.20204,4.86839,5.85298,5.93967,6.38509,6.24412,6.28579,6.33368,5.63649,6.11174,6.09352,6.27429,6.34184,6.38397,6.39519,5.92831,6.39347,6.36756,6.21978,6.3464,6.31051,6.37617,6.403,6.40703,6.14341,5.69085,6.19882,5.74989,6.17624,5.94794,5.48197,6.15078,6.38734,6.41555,4.64003,5.79274,4.69329,6.28192,6.34898,6.38056,6.31884,6.38294,5.1181,5.96373,5.83726,6.21486,6.37741,6.4148,6.35364,5.92156,6.22172,5.00758,5.96632,6.1633,6.22973,6.2417,6.38813,5.28169,5.93714,6.38136,6.33123,6.37021,5.97843,6.34029,6.01045,6.39569,6.4147,6.37381", "env/episode_return": "-0.335053,0.125933,0.206055,0.234961,0.108414,0.176654,0.202461,0.0365229,0.216608,-2.02931,0.0192215,-1.63083,-1.32187,-0.0305262,-0.0114432,0.203337,0.22987,0.0481729,0.258032,-0.121155,0.117697,0.171485,-3.69757,-0.317056,0.150381,-0.101092,-0.855894,0.108425,0.165531,0.143123,0.220197,0.231243,-3.8336,-0.550555,-0.284422,0.204438,0.227969,0.240415,-0.956697,-0.256204,0.151362,0.126927,0.161888,-2.1256,0.155917,0.182964,0.263873,0.266901,-3.76527,0.24092,0.245619,0.113312,-0.195238,0.200289,0.228039,0.241544,0.233986,-3.73008,-0.17481,-1.20369,-0.105805,0.148045,0.188209,0.256639,0.136652,0.244931,0.24944,-1.66665,0.0969675,-0.30357,0.144237,0.179393,0.205057,0.215846,-0.440354,-0.35813,0.239152,-0.260977,0.140978,0.203197,0.232048,0.190488,0.24756,-2.1134,-0.232524,-0.278016,0.245768,-1.88323,-0.0239677,-3.62249,-0.458042,0.144934,-0.592031,0.23314,0.244805,-1.43056,0.0219056,-0.820422,0.200612,0.233027,0.173307,0.225519,-1.02914,0.0507068,-1.20592,-0.0872314,0.202167,0.221923,0.225387,-0.282808,0.191767,0.231438,0.247456,0.250101,-1.24979,0.240432,0.252329,-0.100166,0.245374,0.257953,-0.504642,0.175965,0.200609,0.160454,0.19619,-0.119348,-1.49577,0.0533537,0.136536,-1.36116,-0.0037415,0.133618,-1.47767,0.0792662,0.150242,0.151349,0.193278,0.202963,0.260706,-0.674992,0.144846,0.18755,0.182031,0.212952,-0.928369,-0.487515,0.119436,0.172718,0.244075,0.23557,0.238175,0.247562,0.260306,0.263693,-0.695044,0.254838,0.0992006,0.162072,-0.377689,-1.21768,0.000459362,0.192238,0.220245,0.215212,-0.148903,0.159292,0.163958,0.219978,-3.32867,-0.267408,0.141592,0.185744,-0.150222,0.102828,0.170431,0.196109,0.201911,-0.793419,0.197232,0.228618,0.243958,-0.132944,0.0397756,0.0824495,0.118679,0.187767,0.21097,0.0727753,0.248756,0.257722,-0.645634,0.17301,0.106675,0.164529,-3.79451,-0.316195,-0.146535,0.232931,0.173329,0.187142,0.218585,-0.545587,0.119021,0.106437,0.186026,0.221363,0.240162,0.239324,-0.257897,0.24189,0.224901,0.161153,0.216834,0.20072,0.233216,0.246998,0.247988,0.117219,-0.698132,0.136595,-0.391235,0.119302,-0.146734,-0.98721,0.118502,0.241093,0.255313,-3.39873,-0.429253,-3.01661,0.1808,0.217395,0.233471,0.212931,0.233583,-1.85789,-0.0172622,-0.0633098,0.157075,0.237298,0.251556,0.220652,0.021401,0.1617,-2.15949,0.0231926,0.133996,0.169182,0.177777,0.23628,-1.54753,-0.0036237,0.238452,0.216039,0.234725,-0.00836401,0.222911,-0.0921517,0.240698,0.24923,0.234139", "env/episode_length": "13.9116,11.2325,11.1108,11.0559,11.2074,11.091,11.0553,11.1939,11.059,22.2574,11.5404,20.3242,18.8636,12.0049,11.7122,11.1257,11.0651,11.2721,11.0337,12.3582,11.2661,11.1526,29.9521,13.4549,11.5169,12.4669,16.2185,11.1809,11.0905,11.2899,11.0631,11.0511,29.9972,14.7505,13.4377,11.0985,11.0501,11.0323,16.872,13.2063,11.1473,11.6329,11.555,22.6647,11.1241,11.0807,11.0211,11.0151,29.9859,11.0298,11.0202,11.2379,13.0285,11.0979,11.0514,11.0297,11.044,29.992,12.8994,18.0973,12.6411,11.2216,11.1225,11.0376,11.1983,11.0353,11.0344,20.4112,11.1986,13.649,11.5688,11.4603,11.3476,11.3032,14.2854,13.8847,11.0278,13.2536,11.2917,11.0998,11.054,11.1286,11.0273,23.0587,12.9647,13.4118,11.0249,21.9689,11.5844,29.7921,14.1978,11.2121,15.1944,11.0589,11.0383,19.4435,11.3926,16.0708,11.1151,11.0495,11.4317,11.1548,17.2754,11.6245,18.3111,12.6692,11.3824,11.3157,11.2878,13.2744,11.1078,11.0402,11.0199,11.0172,18.1821,11.0393,11.0327,11.9562,11.041,11.0239,14.6816,11.108,11.0644,11.2102,11.1068,12.616,19.435,11.3858,11.0763,18.7686,11.4983,11.2412,19.4244,11.2661,11.1382,11.4181,11.2094,11.159,11.0303,15.3959,11.2501,11.1301,11.1359,11.0849,16.8343,14.32,11.267,11.1363,11.0396,11.0513,11.0415,11.039,11.0232,11.0221,15.5765,11.0258,11.2807,11.098,13.7843,18.2314,11.8716,11.1076,11.0577,11.0925,12.6795,11.1375,11.1793,11.0398,28.9413,13.2805,11.2294,11.1088,12.6234,11.2898,11.1493,11.0869,11.0724,16.0465,11.1055,11.05,11.0263,12.5038,11.5872,11.7079,11.2512,11.1151,11.0624,11.3209,11.0234,11.0228,15.1804,11.18,11.1818,11.0955,29.9943,13.5136,12.5222,11.0622,11.1818,11.2006,11.1042,14.462,11.1301,11.1906,11.1427,11.0723,11.0413,11.0386,13.4538,11.0323,11.0678,11.1771,11.0663,11.097,11.05,11.0331,11.0324,11.2735,15.4036,11.2885,14.0718,11.3769,12.6565,17.0989,11.283,11.0379,11.0186,29.4486,14.2091,27.7765,11.1594,11.0721,11.0458,11.1187,11.0406,21.7131,11.7352,11.4955,11.182,11.0438,11.0262,11.0717,11.224,11.1398,22.9359,11.3515,11.1646,11.112,11.1001,11.0518,20.2117,11.5727,11.0372,11.082,11.0506,11.7093,11.0662,12.4406,11.0456,11.0377,11.052", "env/n": "2485.45,5835.16,11799.5,11855.4,11701.7,11819.6,11856.9,5856.68,5925.69,3367.11,5679.39,3469.13,3997.08,5467.89,5610.42,5890.89,5923.26,5821.42,47520.2,5441.11,11635,11752.5,2182.84,5318.56,5690.21,2693.34,2273.78,11726.8,11817.4,5806.65,5924.31,11849,2155.82,2483.01,5277.36,5905.33,5930.8,5940.36,4444.33,5242.78,5879.32,11271.3,11340.5,6674.38,11783.6,11828.6,11891.9,11931,2155.84,11883.4,11949,5833.36,2706.61,2953.01,2965.19,2971,11893,1090.49,2711.69,4138.21,5186.42,5842.62,5891.56,11960,2926.34,5938.52,11873,3788.79,5852.79,5131.38,5665.8,5719.13,5775.64,11643,1264.45,5202.44,5942.79,2657.44,2902.85,5904.35,5928.63,2944.93,11888,3101.63,5056.58,5276.43,5944,3386.24,5664.97,1266.53,2537.47,2922.64,4619.07,11852.6,11873.4,3861.18,5763.55,4611.2,5896.51,5931,22944.4,23492,4409.65,5645.67,3775.68,5183.76,46055.6,46346.4,46481,10597.8,5898.94,5937.79,5947.6,11810,4321.98,5936.74,11871,11072.1,5935.55,5944.98,4770.73,11801.1,11847.1,11695,11801.5,2748.72,4045.66,5777.24,5918.16,4151,5699.58,5830.85,3907.89,5817.08,5884.18,5741.8,5846.9,11710,11882.6,2439.57,2913.4,2944.16,5885.54,5912.06,2200.72,5076.03,5817.08,5885.79,11873.3,5930.7,11861,23749.2,23780,23770,2345.85,23775.7,11623.9,11811,5195.71,4160.11,5522.42,5900.3,5926.99,23641.5,5153.89,11769.4,5862.85,5936.46,5006.22,5316.57,5838.81,5899.88,2691.47,5805.82,5879.36,5911.49,11878,2356.21,11804.4,11861.5,11888,2766.09,11308.2,11191.6,11651.7,11791.6,11849.3,5790.45,5945.31,11869,4951.82,2931.12,11724.9,11812,2155.82,5246.38,2694.54,11848.8,11723,11702.9,11807.1,2514.71,2947.75,5856.5,11763.6,11839.1,11873.1,11802,5269.12,23763.8,23682.9,23469.5,11839,11812.8,11861.5,11880.2,11832,11629,4849.83,5806.42,4864.79,5762.95,2716.47,4328.38,5811.61,5937.63,5947.77,2203.66,4913.5,2228.97,11747.6,11839.5,11865.7,11755,11866,3396.81,5588.76,11414.7,5861.15,5934.09,11890,11839.1,5843.37,11767.2,3244.37,5775.5,5870.32,5897.89,11812,5930.67,3643.84,5678.79,5938.01,11828.1,11861.5,5606.87,11845.5,2775.21,5932.99,11881,5929.84", "wandb": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "rank": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "world_size": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "gpu_id": "3,5,3,3,5,5,5,4,0,5,5,4,1,1,2,2,2,5,5,4,3,3,0,4,5,3,3,5,5,4,4,4,4,5,0,0,0,0,4,0,3,3,3,4,4,4,2,2,5,2,2,3,1,1,1,1,1,5,4,3,3,5,5,4,2,1,1,1,1,3,3,3,3,3,2,0,0,3,3,0,0,5,5,1,1,2,2,3,3,4,1,1,4,2,2,5,5,0,4,4,4,4,1,1,0,0,0,0,0,0,2,2,2,2,2,4,4,3,3,3,2,3,3,3,3,4,3,3,3,1,1,4,4,4,4,2,2,2,1,3,3,3,4,4,1,4,0,0,5,2,2,0,0,0,5,1,3,3,3,0,0,5,5,1,2,5,5,5,3,3,0,0,1,0,0,0,0,3,0,0,0,3,4,4,3,3,3,4,3,3,5,5,2,2,2,5,4,2,0,5,5,2,2,1,4,4,4,4,5,5,3,1,1,5,5,5,5,3,5,5,0,0,4,2,3,2,2,1,0,3,0,0,0,3,3,4,1,4,2,3,3,5,0,0,2,2,2,2,2,3,2,2,2,0,0,1,3,0,5,5,2", "profile": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "checkpoint_interval": "200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200", "eval_episodes": "10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000,10000", "cudagraphs": "10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10", "seed": "73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73,73", "vec/total_agents": "2048,4096,8192,8192,8192,8192,8192,4096,4096,2048,2048,2048,2048,2048,8192,4096,4096,8192,16384,8192,4096,4096,1024,8192,2048,4096,2048,4096,4096,4096,4096,4096,2048,4096,4096,4096,4096,4096,2048,8192,4096,8192,8192,4096,4096,4096,8192,8192,2048,8192,8192,4096,4096,4096,4096,4096,4096,1024,4096,2048,2048,8192,8192,8192,2048,4096,4096,2048,2048,4096,4096,4096,4096,4096,2048,4096,4096,4096,4096,8192,8192,4096,4096,2048,2048,4096,4096,2048,2048,2048,4096,4096,8192,8192,8192,2048,2048,4096,8192,8192,8192,8192,4096,4096,4096,4096,16384,16384,16384,8192,8192,8192,8192,8192,2048,4096,4096,4096,4096,4096,4096,2048,2048,4096,4096,4096,2048,2048,2048,2048,2048,8192,2048,2048,2048,2048,2048,2048,8192,4096,4096,4096,8192,8192,2048,4096,8192,8192,4096,4096,4096,8192,8192,8192,4096,8192,4096,4096,8192,2048,2048,4096,4096,16384,8192,8192,4096,4096,8192,8192,8192,8192,4096,2048,2048,2048,2048,4096,8192,8192,8192,4096,4096,4096,2048,2048,2048,8192,4096,4096,4096,4096,2048,2048,2048,4096,4096,8192,4096,8192,8192,4096,4096,2048,8192,8192,8192,8192,8192,8192,8192,16384,4096,8192,8192,8192,8192,4096,2048,2048,8192,8192,4096,4096,8192,4096,4096,2048,4096,4096,8192,8192,8192,2048,4096,2048,8192,4096,4096,4096,4096,8192,4096,8192,2048,2048,2048,2048,2048,4096,2048,2048,8192,8192,8192,8192,8192,4096,4096,4096,4096", "vec/num_buffers": "3.64101,3.3924,2.02319,2.02319,4.74869,4.74869,4.74869,2.71785,1,6.28047,6.28047,7.90625,5.68269,5.68269,1,1.32411,1.32411,3.66333,2.47533,1.40911,5.40188,5.40188,5.10696,2.80659,4.04189,1,1.01952,5.50681,5.50681,5.55361,5.55361,5.55361,3.69008,6.88614,2.57793,2.57793,2.57793,2.57793,4.47514,1,2.05436,3.03437,3.03437,5.47204,5.47204,5.47204,3.37573,3.37573,4.98969,2.67782,2.67782,5.79453,3.00065,3.00065,3.00065,3.00065,2.98853,3.41322,3.67413,6.51758,6.51758,2.72597,2.72597,1.73102,1.71316,3.12626,3.12626,1,1,1.96037,1.96037,1.96037,1.96037,1.96037,6.93538,2.94804,2.94804,2.22463,2.22463,1.01177,1.01177,1.84011,1.84011,4.19754,4.19754,1,1,5.63233,5.63233,1.22438,2.31362,2.31362,1.18235,3.43571,3.43571,7.12851,7.12851,6.79012,2.75743,2.75743,1.3057,1.3057,4.11589,4.11589,6.02297,6.02297,3.72313,3.72313,3.72313,1.6746,1.44057,1.44057,1.44057,1.44057,4.89818,4.47813,4.47813,5.98,6.15965,6.15965,1,4.03164,4.03164,3.9833,3.9833,3.39654,5.16604,5.16604,5.16604,4.03287,4.03287,1,4.07896,4.07896,4.07896,2.61948,2.61948,2.61948,5.12438,1,1,1,1.5454,1.5454,1.80884,2.6417,1.18108,1.18108,4.4608,2.20584,2.20584,4.51037,4.51037,4.51037,1.35609,4.12789,5.0027,5.0027,1,4.58178,4.58178,1,1,3.71498,1.32525,2.02926,1,1,2.89481,2.18747,2.61611,2.61611,1,5.70463,5.70463,5.70463,5.70463,1,1,1,1,2.15526,6.84176,6.84176,1.25639,1.25639,1.25639,1.51732,4.5243,4.5243,1,2.41025,5.93558,5.93558,3.71012,4.49574,2.46826,2.83523,4.63101,3.60843,3.60843,1,1,4.2566,2.05381,2.05381,2.05381,2.05381,3.6693,1.89658,1,2.04993,5.92691,4.90219,4.90219,4.90219,4.90219,5.24742,5.64326,5.64326,1,1,2.35082,3.25077,3.02946,3.52166,3.52166,7.32868,1.57691,1.76635,1.98007,1.98007,1.98007,3.57049,2.26513,4.81213,1.34118,6.09815,1,5.07882,5.07882,2.26292,2.10252,5.41716,5.05922,5.05922,5.05922,5.05922,5.05922,2.62068,5.96605,5.96605,1.21739,5.58252,5.58252,1,3.07363,5.7188,2.12294,2.12294,3.6508", "vec/num_threads": "2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2", "vec/num_agents": "4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096,4096", "env/width": "990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990,990", "env/height": "690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690,690", "env/card_width": "192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192,192", "env/card_height": "224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224,224", "policy/hidden_size": "512,256,1024,1024,256,256,256,128,1024,128,128,128,256,256,128,1024,1024,256,1024,512,256,256,64,256,512,256,128,256,256,256,256,256,128,256,512,512,512,512,64,256,256,512,512,128,128,128,1024,1024,64,256,256,256,1024,1024,1024,1024,256,64,1024,64,64,512,512,512,256,256,256,256,256,1024,1024,1024,1024,1024,256,256,256,256,256,1024,1024,1024,1024,128,128,1024,1024,64,64,128,128,128,128,512,512,128,128,128,1024,1024,1024,1024,128,128,512,512,1024,1024,1024,256,1024,1024,1024,1024,64,256,256,64,512,512,1024,256,256,512,512,512,256,256,256,64,64,256,128,128,128,256,256,256,1024,256,256,256,512,512,128,256,256,256,256,1024,1024,1024,1024,1024,256,1024,256,256,256,128,128,512,512,512,128,256,256,256,128,256,512,512,512,256,256,256,256,128,1024,1024,1024,512,128,128,256,256,256,256,256,256,128,1024,128,128,128,256,256,1024,1024,512,512,256,256,256,1024,1024,1024,1024,256,256,1024,1024,1024,512,512,512,512,256,256,256,256,256,512,128,256,1024,1024,64,256,64,1024,1024,1024,256,1024,128,256,64,256,1024,1024,1024,128,256,256,256,256,256,256,1024,128,128,512,512,512,128,512,1024,1024,1024,512", "policy/num_layers": "1,1,3.8241,3.8241,2.05218,2.05218,2.05218,1.18739,1.62947,1,1,2.06111,2.53358,2.53358,1,2.3225,2.3225,1,2.59421,5.29156,1.00045,1.00045,2.16124,1.72755,1.55922,2.20776,1,1.87992,1.87992,2.12199,2.12199,2.12199,1,1,1.1368,1.1368,1.1368,1.1368,1.89706,1,1.45074,5.92372,5.92372,1,1,1,2.48805,2.48805,1,1.61588,1.61588,3.20741,2.31674,2.31674,2.31674,2.31674,1,1,2.48471,1.50845,1.50845,1.30987,1.30987,1.25407,1,2.03636,2.03636,1.3756,1.3756,3.15804,3.15804,3.15804,3.15804,3.15804,1.31498,1,1,1,1,2.06026,2.06026,2.47392,2.47392,1,1,4.33675,4.33675,1.39594,1.39594,1.54935,1.92616,1.92616,1.29713,1.20736,1.20736,1.55852,1.55852,1,2.04701,2.04701,2.59583,2.59583,1.46936,1.46936,2.1762,2.1762,2.08794,2.08794,2.08794,1,4.3406,4.3406,4.3406,4.3406,1,2.66289,2.66289,1,1,1,5.4845,2.57092,2.57092,1,1,1.79434,1.99126,1.99126,1.99126,2.98968,2.98968,1,1,1,1,1.19167,1.19167,1.19167,3.38258,1.61714,1.61714,1.61714,3.32584,3.32584,1.07596,1.63849,1.91538,1.91538,1.41196,1.13907,1.13907,3.55715,3.55715,3.55715,1,2.11516,1,1,1.18623,1.65214,1.65214,1.20092,1.20092,5.76883,1,1.62547,1.58241,1.58241,1.76618,2.5967,1.12645,1.12645,2.51803,1.53712,1.53712,1.53712,1.53712,1,3.03681,3.03681,3.03681,1.34948,1,1,1.29207,1.29207,1.29207,1,2.46396,2.46396,1.41255,4.16703,2.37476,2.37476,1.09124,1.95038,1.78869,1,4.67387,3.95258,3.95258,1,1,1.96473,5.93709,5.93709,5.93709,5.93709,2.53489,1,2.6228,3.51649,1.17532,2.76632,2.76632,2.76632,2.76632,1,1,1,2.91867,2.91867,2.39427,2.7396,1.77559,1.51871,1.51871,1,2.09845,1,1.37659,1.37659,1.37659,1.97009,1.46126,1.17682,1.73491,1,1.32146,1.45235,1.45235,1.64477,1,1.62687,1,1,1,1,1,2.62564,2.01362,2.01362,2.54122,1,1,1.65175,1,3.59856,2.71851,2.71851,1.99889", "policy/expansion_factor": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "legacy/torch_deterministic": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "legacy/cpu_offload": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "legacy/compile": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "legacy/compile_fullgraph": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "train/gpus": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "train/seed": "42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42", "train/total_timesteps": "18.3841,11.757,24.8089,24.8089,10.032,10.032,10.032,10,19.3019,10,10,10,10,10,10,21.0613,21.0613,10,36.3009,16.3591,13.826,13.826,10,18.3884,10.227,22.8387,10,10.156,10.156,16.3068,16.3068,16.3068,10,14.3329,23.5856,23.5856,23.5856,23.5856,13.659,18.2308,13.8797,16.1393,16.1393,12.3612,12.3612,12.3612,41.9453,41.9453,10,31.6096,31.6096,10.2996,19.7391,19.7391,19.7391,19.7391,24.0281,10,19.7308,10,10,12.6764,12.6764,32.023,11.1594,33.2812,33.2812,10,10,16.1337,16.1337,16.1337,16.1337,16.1337,18.9356,26.8316,26.8316,13.8283,13.8283,21.5214,21.5214,18.5144,18.5144,10,10,18.9981,18.9981,10,10,10,14.4623,14.4623,12.5734,29.4831,29.4831,10,10,11.9736,22.095,22.095,16.9967,16.9967,12.8916,12.8916,10,10,28.3818,28.3818,28.3818,25.0145,18.4879,18.4879,18.4879,18.4879,11.8169,27.926,27.926,10,43.5274,43.5274,12.8836,10,10,10,10,23.8761,10,10,10,10,10,12.0182,10,10,10,10.6485,10.6485,10.6485,32.4939,12.3405,12.3405,12.3405,17.0037,17.0037,10,18.3985,10.1747,10.1747,33.1337,21.4454,21.4454,31.6909,31.6909,31.6909,10,34.6712,10.819,10.819,15.8896,10,10,20.3042,20.3042,17.0464,10,15.6635,16.2098,16.2098,10.006,20.1583,11.2548,11.2548,19.0248,10.3071,10.3071,10.3071,10.3071,10.3099,19.4005,19.4005,19.4005,21.6821,10,10,10.2413,10.2413,10.2413,10.0152,34.556,34.556,13.2539,15.9591,12.4659,12.4659,10,20.4327,28.0147,23.6891,15.4252,18.6647,18.6647,10,10,12.6471,16.1027,16.1027,16.1027,16.1027,29.5761,29.5798,17.0646,14.0543,14.6418,24.9194,24.9194,24.9194,24.9194,13.5461,15.4942,15.4942,11.3208,11.3208,19.3041,12.4624,10.7295,32.594,32.594,10,16.724,10,20.8608,20.8608,20.8608,14.9165,19.356,12.141,10,10.5636,15.5927,29.7901,29.7901,22.482,10,10,10,10,10,10,10,20.0656,10,10,22.0659,17.371,17.371,10,22.304,20.5792,19.8633,19.8633,34.1923", "train/learning_rate": "0.00307561,0.00146972,0.000923201,0.000923201,0.00280368,0.00280368,0.00280368,0.0018763,0.00173209,0.0150271,0.0150271,0.00603439,0.00234961,0.00234961,0.00530921,0.00084312,0.00084312,0.000833989,0.000641377,0.00280062,0.00279872,0.00279872,0.00560071,0.00296307,0.0138627,0.00290081,0.00407007,0.00588419,0.00588419,0.0135171,0.0135171,0.0135171,0.00778398,0.00299421,0.00220475,0.00220475,0.00220475,0.00220475,0.00768966,0.00333196,0.00240814,0.00128832,0.00128832,0.0118425,0.0118425,0.0118425,0.00145624,0.00145624,0.00344445,0.00263596,0.00263596,0.00307345,0.0016366,0.0016366,0.0016366,0.0016366,0.00118551,0.00150136,0.00228527,0.0127652,0.0127652,0.00151809,0.00151809,0.00210254,0.00187913,0.00316988,0.00316988,0.00423362,0.00423362,0.00217866,0.00217866,0.00217866,0.00217866,0.00217866,0.00383878,0.00182993,0.00182993,0.00301224,0.00301224,0.000991995,0.000991995,0.00119968,0.00119968,0.00902691,0.00902691,0.000909416,0.000909416,0.00342288,0.00342288,0.00430264,0.00326011,0.00326011,0.0025112,0.00104624,0.00104624,0.00749299,0.00749299,0.00368557,0.000975387,0.000975387,0.00110629,0.00110629,0.00777676,0.00777676,0.00996667,0.00996667,0.00104515,0.00104515,0.00104515,0.00214773,0.000817572,0.000817572,0.000817572,0.000817572,0.00915063,0.00128014,0.00128014,0.00330941,0.00226812,0.00226812,0.00171521,0.0048061,0.0048061,0.0139488,0.0139488,0.00231713,0.0108723,0.0108723,0.0108723,0.00411619,0.00411619,0.00224418,0.0101184,0.0101184,0.0101184,0.00937804,0.00937804,0.00937804,0.00133346,0.00168416,0.00168416,0.00168416,0.00137203,0.00137203,0.00340022,0.00175645,0.00203896,0.00203896,0.00159803,0.00308835,0.00308835,0.000414244,0.000414244,0.000414244,0.00188573,0.000910158,0.00654557,0.00654557,0.00443104,0.0051279,0.0051279,0.00173059,0.00173059,0.00163492,0.00165298,0.00227458,0.0029239,0.0029239,0.00174375,0.00449173,0.00256202,0.00256202,0.00352912,0.0131003,0.0131003,0.0131003,0.0131003,0.0021658,0.00113209,0.00113209,0.00113209,0.00190615,0.00321399,0.00321399,0.00438564,0.00438564,0.00438564,0.00129649,0.0017548,0.0017548,0.00340463,0.000932697,0.00450189,0.00450189,0.00360685,0.00329998,0.00556361,0.00228454,0.00085263,0.00190406,0.00190406,0.00247499,0.00247499,0.00627721,0.000932534,0.000932534,0.000932534,0.000932534,0.00233046,0.00129995,0.00195732,0.00166222,0.00730323,0.00119211,0.00119211,0.00119211,0.00119211,0.00708921,0.0106841,0.0106841,0.00296396,0.00296396,0.0028457,0.00979373,0.00223232,0.000815687,0.000815687,0.00259225,0.0027832,0.0123706,0.00112204,0.00112204,0.00112204,0.00952648,0.00343033,0.00694719,0.00187992,0.00522337,0.00173125,0.000971779,0.000971779,0.00206967,0.00262674,0.00417854,0.0128086,0.0128086,0.0128086,0.0128086,0.0128086,0.00332127,0.00633075,0.00633075,0.00274818,0.00535429,0.00535429,0.00470289,0.00127433,0.00122045,0.00142751,0.00142751,0.00212005", "train/anneal_lr": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "train/min_lr_ratio": "0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0", "train/gamma": "0.823292,0.904349,0.976587,0.976587,0.946119,0.946119,0.946119,0.944599,0.94554,0.876921,0.876921,0.8,0.898391,0.898391,0.990309,0.966259,0.966259,0.94026,0.989583,0.980367,0.987499,0.987499,0.945371,0.92695,0.86408,0.920377,0.867926,0.948049,0.948049,0.926382,0.926382,0.926382,0.957452,0.95331,0.948147,0.948147,0.948147,0.948147,0.882726,0.980787,0.975406,0.889451,0.889451,0.947059,0.947059,0.947059,0.963084,0.963084,0.8,0.962356,0.962356,0.972545,0.970905,0.970905,0.970905,0.970905,0.96562,0.941989,0.887074,0.851736,0.851736,0.969421,0.969421,0.968521,0.954836,0.971324,0.971324,0.979066,0.979066,0.887885,0.887885,0.887885,0.887885,0.887885,0.977947,0.951573,0.951573,0.964485,0.964485,0.960257,0.960257,0.970731,0.970731,0.8,0.8,0.957864,0.957864,0.963702,0.963702,0.82354,0.939557,0.939557,0.855936,0.977478,0.977478,0.991302,0.991302,0.939775,0.968361,0.968361,0.905852,0.905852,0.90811,0.90811,0.8,0.8,0.877678,0.877678,0.877678,0.971656,0.967448,0.967448,0.967448,0.967448,0.956682,0.933061,0.933061,0.941072,0.945782,0.945782,0.966093,0.945008,0.945008,0.973807,0.973807,0.984027,0.906169,0.906169,0.906169,0.891818,0.891818,0.956519,0.939664,0.939664,0.939664,0.90144,0.90144,0.90144,0.966628,0.973504,0.973504,0.973504,0.956146,0.956146,0.895538,0.923625,0.973538,0.973538,0.960399,0.95863,0.95863,0.990144,0.990144,0.990144,0.969363,0.942291,0.923085,0.923085,0.953763,0.888055,0.888055,0.937853,0.937853,0.934545,0.8,0.963986,0.939597,0.939597,0.975641,0.954912,0.94493,0.94493,0.888335,0.990934,0.990934,0.990934,0.990934,0.882782,0.94375,0.94375,0.94375,0.977745,0.85824,0.85824,0.942441,0.942441,0.942441,0.960064,0.955398,0.955398,0.966853,0.94898,0.957696,0.957696,0.978728,0.906662,0.96828,0.983831,0.961549,0.914125,0.914125,0.981537,0.981537,0.972351,0.956795,0.956795,0.956795,0.956795,0.901443,0.957854,0.950884,0.949228,0.967328,0.980169,0.980169,0.980169,0.980169,0.962591,0.940236,0.940236,0.89791,0.89791,0.941253,0.864825,0.987248,0.990559,0.990559,0.8,0.914285,0.96059,0.985218,0.985218,0.985218,0.902016,0.926829,0.8,0.925548,0.933082,0.961494,0.978539,0.978539,0.949317,0.982484,0.943829,0.947523,0.947523,0.947523,0.947523,0.947523,0.982017,0.927389,0.927389,0.943904,0.928703,0.928703,0.989916,0.92004,0.965659,0.955838,0.955838,0.989884", "train/gae_lambda": "0.981961,0.891964,0.923845,0.923845,0.822579,0.822579,0.822579,0.944977,0.983138,0.823432,0.823432,0.71395,0.852395,0.852395,0.992519,0.97555,0.97555,0.928332,0.705065,0.988262,0.954871,0.954871,0.764988,0.978873,0.98277,0.994185,0.958787,0.88035,0.88035,0.959724,0.959724,0.959724,0.788377,0.985195,0.966135,0.966135,0.966135,0.966135,0.929105,0.987376,0.931284,0.986847,0.986847,0.889633,0.889633,0.889633,0.749103,0.749103,0.2,0.972244,0.972244,0.986365,0.906736,0.906736,0.906736,0.906736,0.947012,0.519648,0.963362,0.714848,0.714848,0.994122,0.994122,0.87905,0.953294,0.990173,0.990173,0.910048,0.910048,0.762008,0.762008,0.762008,0.762008,0.762008,0.967895,0.952961,0.952961,0.972492,0.972492,0.988303,0.988303,0.962452,0.962452,0.877239,0.877239,0.632257,0.632257,0.771902,0.771902,0.95924,0.97921,0.97921,0.9947,0.931612,0.931612,0.929016,0.929016,0.920326,0.987259,0.987259,0.70679,0.70679,0.859215,0.859215,0.933848,0.933848,0.790837,0.790837,0.790837,0.784234,0.663777,0.663777,0.663777,0.663777,0.850846,0.965898,0.965898,0.890172,0.942,0.942,0.655754,0.911637,0.911637,0.939053,0.939053,0.982362,0.914872,0.914872,0.914872,0.685362,0.685362,0.977823,0.81232,0.81232,0.81232,0.884282,0.884282,0.884282,0.781398,0.936229,0.936229,0.936229,0.987525,0.987525,0.905377,0.989082,0.928505,0.928505,0.965231,0.894531,0.894531,0.527187,0.527187,0.527187,0.978868,0.904254,0.958315,0.958315,0.905721,0.889971,0.889971,0.980717,0.980717,0.979838,0.956437,0.978926,0.995,0.995,0.981834,0.99074,0.99361,0.99361,0.970417,0.908145,0.908145,0.908145,0.908145,0.978869,0.644788,0.644788,0.644788,0.980612,0.9286,0.9286,0.816586,0.816586,0.816586,0.967395,0.98264,0.98264,0.993311,0.976041,0.955033,0.955033,0.914139,0.901697,0.992348,0.975876,0.882179,0.98935,0.98935,0.951778,0.951778,0.958807,0.812813,0.812813,0.812813,0.812813,0.976617,0.910218,0.974156,0.983749,0.986371,0.637675,0.637675,0.637675,0.637675,0.955793,0.828466,0.828466,0.995,0.995,0.995,0.987554,0.984188,0.903058,0.903058,0.692371,0.994344,0.992648,0.961722,0.961722,0.961722,0.920541,0.990251,0.951076,0.974842,0.839947,0.990738,0.896265,0.896265,0.96075,0.976501,0.954522,0.856147,0.856147,0.856147,0.856147,0.856147,0.813213,0.816359,0.816359,0.990568,0.962294,0.962294,0.991627,0.966151,0.92532,0.871838,0.871838,0.993799", "train/replay_ratio": "4,2.78538,4,4,2.25047,2.25047,2.25047,2.6603,3.30232,1.71966,1.71966,1.86635,2.00658,2.00658,2.96087,4,4,2.75964,4,3.8251,1.84739,1.84739,1.96718,4,1.69993,3.63429,3.3386,2.31054,2.31054,2.29247,2.29247,2.29247,2.00125,1.93377,3.84519,3.84519,3.84519,3.84519,2.38904,3.10749,2.79653,4,4,1.21947,1.21947,1.21947,4,4,2.22111,3.29863,3.29863,2.04648,3.87324,3.87324,3.87324,3.87324,4,1.34949,4,2.39617,2.39617,3.82866,3.82866,4,3.89924,3.20462,3.20462,2.10993,2.10993,3.66232,3.66232,3.66232,3.66232,3.66232,3.1191,4,4,4,4,4,4,3.61452,3.61452,0.971977,0.971977,3.9319,3.9319,1.85591,1.85591,0.485946,4,4,3.69291,3.48039,3.48039,1.34533,1.34533,2.134,4,4,3.63854,3.63854,2.03556,2.03556,1.60984,1.60984,3.44425,3.44425,3.44425,3.19667,4,4,4,4,1.68652,3.83455,3.83455,1.54639,3.95522,3.95522,4,1.5136,1.5136,2.02354,2.02354,4,0.919152,0.919152,0.919152,1.98806,1.98806,2.79777,2.61523,2.61523,2.61523,2.08083,2.08083,2.08083,3.95919,3.41509,3.41509,3.41509,4,4,3.20988,4,2.60533,2.60533,3.99087,4,4,4,4,4,3.20308,4,2.19738,2.19738,4,2.11562,2.11562,4,4,4,2.03755,3.11375,3.93465,3.93465,0.296359,2.75914,3.75836,3.75836,4,1.92135,1.92135,1.92135,1.92135,3.12797,3.07414,3.07414,3.07414,4,2.45296,2.45296,2.42531,2.42531,2.42531,3.60663,3.5804,3.5804,3.38238,3.65485,1.15653,1.15653,1.53486,3.2978,3.35472,3.80722,4,4,4,2.87898,2.87898,1.58111,3.56637,3.56637,3.56637,3.56637,2.75439,4,3.56721,4,1.62925,3.86138,3.86138,3.86138,3.86138,2.0925,2.24308,2.24308,4,4,4,1.71883,4,4,4,1.26152,3.25278,1.4381,4,4,4,2.21202,4,0.82941,3.56303,1.60722,4,3.06777,3.06777,4,2.21089,2.78815,1.19612,1.19612,1.19612,1.19612,1.19612,4,1.57202,1.57202,3.86805,2.53599,2.53599,3.47693,4,4,4,4,3.28561", "train/clip_coef": "0.350496,0.407632,0.429875,0.429875,0.445526,0.445526,0.445526,0.375418,0.289496,0.256478,0.256478,0.316226,0.337496,0.337496,0.609895,0.365896,0.365896,0.344567,0.433771,0.636029,0.339945,0.339945,0.41327,0.556658,0.184012,0.34963,0.609841,0.39961,0.39961,0.201543,0.201543,0.201543,0.374732,0.373111,0.282483,0.282483,0.282483,0.282483,0.348792,0.479127,0.371826,0.396338,0.396338,0.223448,0.223448,0.223448,0.584472,0.584472,0.443035,0.236022,0.236022,0.345474,0.398753,0.398753,0.398753,0.398753,0.233861,0.440653,0.326255,0.328459,0.328459,0.387155,0.387155,0.344419,0.367176,0.200548,0.200548,0.241027,0.241027,0.418055,0.418055,0.418055,0.418055,0.418055,0.353436,0.290528,0.290528,0.38723,0.38723,0.202206,0.202206,0.377574,0.377574,0.142968,0.142968,0.419657,0.419657,0.317573,0.317573,0.0236336,0.294517,0.294517,0.474534,0.410516,0.410516,0.401714,0.401714,0.551865,0.18866,0.18866,0.321247,0.321247,0.291998,0.291998,0.351486,0.351486,0.644823,0.644823,0.644823,0.534669,0.30564,0.30564,0.30564,0.30564,0.420293,0.262021,0.262021,0.28381,0.217426,0.217426,0.380661,0.211308,0.211308,0.301681,0.301681,0.38429,0.35833,0.35833,0.35833,0.272772,0.272772,0.397068,0.33785,0.33785,0.33785,0.12943,0.12943,0.12943,0.435448,0.304181,0.304181,0.304181,0.250959,0.250959,0.283577,0.422514,0.368806,0.368806,0.233,0.299728,0.299728,0.357716,0.357716,0.357716,0.453785,0.600123,0.472756,0.472756,0.453907,0.386381,0.386381,0.20798,0.20798,0.366459,0.53003,0.32808,0.376541,0.376541,0.332204,0.377637,0.265284,0.265284,0.459857,0.278653,0.278653,0.278653,0.278653,0.239664,0.241501,0.241501,0.241501,0.336955,0.308713,0.308713,0.296493,0.296493,0.296493,0.434409,0.253448,0.253448,0.346195,0.41843,0.31602,0.31602,0.255625,0.457735,0.423171,0.258239,0.513432,0.518089,0.518089,0.451036,0.451036,0.264147,0.277164,0.277164,0.277164,0.277164,0.20314,0.379562,0.311891,0.561974,0.321318,0.157361,0.157361,0.157361,0.157361,0.332602,0.301908,0.301908,0.460432,0.460432,0.36775,0.353804,0.343071,0.403453,0.403453,0.253793,0.281682,0.0543616,0.406106,0.406106,0.406106,0.259359,0.416291,0.393912,0.452222,0.237577,0.226409,0.38263,0.38263,0.266418,0.293318,0.33295,0.169509,0.169509,0.169509,0.169509,0.169509,0.378855,0.260561,0.260561,0.426234,0.302283,0.302283,0.511493,0.327591,0.380259,0.246546,0.246546,0.147921", "train/vf_coef": "2.16495,0.316243,2.48316,2.48316,1.30795,1.30795,1.30795,0.1,1.49362,0.945648,0.945648,1.04456,1.89216,1.89216,0.867042,2.86849,2.86849,0.784097,2.89279,2.76017,0.992974,0.992974,2.19085,2.54024,2.54416,0.811841,0.804629,2.5003,2.5003,1.53521,1.53521,1.53521,2.43273,0.294009,1.98294,1.98294,1.98294,1.98294,2.12405,1.965,0.722267,2.8257,2.8257,2.34986,2.34986,2.34986,1.71534,1.71534,2.01884,2.26724,2.26724,1.00481,1.65249,1.65249,1.65249,1.65249,1.92078,2.33351,2.03714,1.92557,1.92557,1.84208,1.84208,1.41903,1.97933,2.016,2.016,1.78538,1.78538,1.3066,1.3066,1.3066,1.3066,1.3066,0.508022,1.72941,1.72941,1.61625,1.61625,2.35622,2.35622,3.31751,3.31751,1.99171,1.99171,3.01253,3.01253,2.05588,2.05588,1.40794,1.28711,1.28711,1.6192,1.3744,1.3744,0.359624,0.359624,1.61381,2.42438,2.42438,2.62667,2.62667,1.18567,1.18567,1.49161,1.49161,2.57671,2.57671,2.57671,0.862845,2.65049,2.65049,2.65049,2.65049,1.98268,1.64643,1.64643,2.5261,1.59159,1.59159,2.5562,2.29076,2.29076,1.98252,1.98252,1.2649,1.78049,1.78049,1.78049,1.4723,1.4723,0.851549,2.96413,2.96413,2.96413,2.23587,2.23587,2.23587,1.68338,0.903949,0.903949,0.903949,2.23015,2.23015,0.434636,1.59428,0.68775,0.68775,2.6136,3.12603,3.12603,2.18841,2.18841,2.18841,1.03328,1.23584,1.24771,1.24771,0.40801,1.96093,1.96093,2.52416,2.52416,2.66467,1.39556,2.40239,2.30383,2.30383,1.37309,1.07176,1.6091,1.6091,0.671039,3.44802,3.44802,3.44802,3.44802,0.940706,1.85133,1.85133,1.85133,1.83645,2.93145,2.93145,1.45342,1.45342,1.45342,0.585599,2.14518,2.14518,2.04304,2.09677,2.25818,2.25818,1.53221,0.76615,0.320792,1.41249,2.7779,2.55353,2.55353,1.46678,1.46678,2.06599,3.40552,3.40552,3.40552,3.40552,1.22206,2.38977,1.68338,2.75796,1.46529,2.49083,2.49083,2.49083,2.49083,3.13096,0.769035,0.769035,1.40682,1.40682,2.30247,1.57743,0.447256,1.96895,1.96895,2.01241,1.46797,1.05617,1.8889,1.8889,1.8889,3.18848,2.92002,1.22424,0.1,1.68483,1.14057,2.54046,2.54046,3.0467,2.0644,1.7108,1.90872,1.90872,1.90872,1.90872,1.90872,1.94794,1.6616,1.6616,2.57817,1.36301,1.36301,1.57527,1.79285,1.68011,1.94085,1.94085,1.39463", "train/vf_clip_coef": "2.76046,1.2523,4.01549,4.01549,2.31033,2.31033,2.31033,2.16131,0.106594,4.58286,4.58286,0.831159,2.76904,2.76904,1.65703,2.03888,2.03888,1.31763,4.6007,0.931515,1.74362,1.74362,1.41819,1.84487,4.85382,2.4978,1.75389,2.38681,2.38681,4.09493,4.09493,4.09493,2.30579,1.0747,3.98576,3.98576,3.98576,3.98576,2.05237,0.445159,2.6407,1.49436,1.49436,1.77662,1.77662,1.77662,5,5,1.33343,4.51271,4.51271,2.39486,1.04463,1.04463,1.04463,1.04463,3.70568,2.04008,0.01,0.532581,0.532581,1.66525,1.66525,4.27123,2.64073,3.95665,3.95665,2.78285,2.78285,1.30825,1.30825,1.30825,1.30825,1.30825,4.64696,5,5,1.65361,1.65361,0.662394,0.662394,1.25455,1.25455,1.3873,1.3873,2.67095,2.67095,2.96976,2.96976,0.01,3.10608,3.10608,3.31305,5,5,2.732,2.732,0.598354,0.771593,0.771593,0.01,0.01,3.75576,3.75576,2.50465,2.50465,3.98046,3.98046,3.98046,4.97716,1.57168,1.57168,1.57168,1.57168,3.5446,4.53952,4.53952,2.02424,3.09499,3.09499,2.11127,3.79105,3.79105,1.51385,1.51385,5,1.26543,1.26543,1.26543,1.20297,1.20297,1.98248,2.16134,2.16134,2.16134,3.17122,3.17122,3.17122,5,2.6993,2.6993,2.6993,0.351245,0.351245,0.01,2.84994,2.93876,2.93876,4.89047,0.138082,0.138082,4.15099,4.15099,4.15099,1.38123,4.83215,1.68583,1.68583,2.13735,3.2563,3.2563,1.31758,1.31758,0.484349,0.302434,2.27964,3.16437,3.16437,0.01,4.43793,0.01,0.01,0.01,1.00328,1.00328,1.00328,1.00328,1.61043,1.43706,1.43706,1.43706,0.01,3.16065,3.16065,2.07376,2.07376,2.07376,1.11922,3.87724,3.87724,2.81706,1.48289,0.227566,0.227566,2.22833,3.33111,0.751302,0.236004,5,0.209253,0.209253,3.17837,3.17837,3.52153,1.46358,1.46358,1.46358,1.46358,2.76429,5,1.60904,0.01,3.36864,3.50979,3.50979,3.50979,3.50979,1.85922,1.60571,1.60571,0.624791,0.624791,0.01,2.64259,2.40068,5,5,1.60435,0.450251,0.388782,0.950914,0.950914,0.950914,4.61506,0.01,0.643335,2.56463,2.51104,3.24162,3.98673,3.98673,0.572727,0.01,1.47187,1.40252,1.40252,1.40252,1.40252,1.40252,0.01,4.08188,4.08188,0.657917,4.0041,4.0041,2.44797,0.0584505,5,0.369342,0.369342,3.29912", "train/max_grad_norm": "4.07963,0.4403,2.2212,2.2212,3.04943,3.04943,3.04943,2.86669,5,0.64082,0.64082,1.44016,1.74502,1.74502,1.45808,4.88647,4.88647,2.36312,2.4581,3.14304,2.45574,2.45574,2.49137,2.6407,2.53892,4.64629,5,2.63871,2.63871,3.39427,3.39427,3.39427,4.45924,2.3678,3.50931,3.50931,3.50931,3.50931,2.86355,4.50552,4.20004,3.19014,3.19014,1.83909,1.83909,1.83909,2.74991,2.74991,1.4803,3.81656,3.81656,3.10773,4.70864,4.70864,4.70864,4.70864,2.54155,3.00657,5,3.74883,3.74883,4.32522,4.32522,3.27303,4.92626,4.18966,4.18966,4.68708,4.68708,4.41469,4.41469,4.41469,4.41469,4.41469,4.34447,2.82212,2.82212,4.82746,4.82746,5,5,4.05811,4.05811,3.03846,3.03846,2.79026,2.79026,2.31028,2.31028,2.55455,4.03932,4.03932,3.23313,3.39137,3.39137,3.10605,3.10605,2.84848,4.3875,4.3875,5,5,3.94625,3.94625,4.73327,4.73327,2.638,2.638,2.638,4.19825,3.86183,3.86183,3.86183,3.86183,1.6058,3.82031,3.82031,1.54082,5,5,3.79511,3.39101,3.39101,3.85757,3.85757,2.66776,1.9147,1.9147,1.9147,1.90269,1.90269,1.80896,0.90564,0.90564,0.90564,3.89638,3.89638,3.89638,3.27012,0.837464,0.837464,0.837464,4.75098,4.75098,0.989983,4.49766,2.18431,2.18431,1.82987,4.01195,4.01195,2.3916,2.3916,2.3916,1.81583,3.1305,2.85447,2.85447,3.76794,2.84658,2.84658,3.9308,3.9308,2.42647,4.31479,3.74258,4.84738,4.84738,1.1818,4.41167,5,5,5,1.86036,1.86036,1.86036,1.86036,1.08618,4.72257,4.72257,4.72257,5,2.74665,2.74665,3.57583,3.57583,3.57583,4.51817,4.65825,4.65825,2.07182,3.20443,2.14107,2.14107,2.31745,2.40444,4.00946,4.42973,2.66293,5,5,1.91545,1.91545,3.76314,2.83025,2.83025,2.83025,2.83025,5,3.83721,5,4.65884,2.30884,4.11465,4.11465,4.11465,4.11465,1.19461,3.40724,3.40724,5,5,4.53816,4.05734,3.84064,2.16207,2.16207,2.25441,5,3.79519,5,5,5,3.65959,5,1.49337,0.707057,2.45458,4.32972,3.68464,3.68464,4.82595,3.43966,1.09415,2.08463,2.08463,2.08463,2.08463,2.08463,5,3.19322,3.19322,4.70007,2.67081,2.67081,0.978684,5,4.27906,4.32135,4.32135,5", "train/ent_coef": "0.000113218,8.79878e-05,0.00156942,0.00156942,0.000401719,0.000401719,0.000401719,0.000214404,0.00206875,0.000213537,0.000213537,0.00113501,0.00244866,0.00244866,9.16439e-05,0.000822332,0.000822332,6.32125e-05,0.0299117,3.04375e-05,0.040265,0.040265,0.000230002,2.99467e-05,0.00346616,0.00339509,6.01465e-05,0.000622564,0.000622564,0.00183895,0.00183895,0.00183895,0.00384892,0.00673036,0.00485634,0.00485634,0.00485634,0.00485634,0.00120447,8.38742e-05,0.00787864,0.000172426,0.000172426,0.0032663,0.0032663,0.0032663,0.00380002,0.00380002,0.00266444,0.00347336,0.00347336,0.000295297,0.00215481,0.00215481,0.00215481,0.00215481,0.00355817,0.00168705,0.00439978,0.00122814,0.00122814,0.000763412,0.000763412,0.00521027,0.000293477,0.00406482,0.00406482,0.001127,0.001127,0.00164472,0.00164472,0.00164472,0.00164472,0.00164472,0.00444308,0.00874836,0.00874836,0.000108378,0.000108378,0.000938412,0.000938412,0.00212025,0.00212025,0.0489145,0.0489145,0.0187434,0.0187434,0.0299737,0.0299737,0.000150343,0.00244114,0.00244114,0.00030138,0.0123281,0.0123281,0.00416845,0.00416845,0.000212772,0.00607279,0.00607279,0.00207805,0.00207805,0.000660922,0.000660922,0.00475335,0.00475335,0.0102401,0.0102401,0.0102401,0.00474063,0.0163025,0.0163025,0.0163025,0.0163025,4.95452e-05,0.000514467,0.000514467,0.000277348,7.25302e-05,7.25302e-05,0.00155324,0.00311024,0.00311024,0.0211913,0.0211913,0.00219162,0.000990646,0.000990646,0.000990646,0.00242838,0.00242838,9.0893e-05,0.0172864,0.0172864,0.0172864,0.000807273,0.000807273,0.000807273,0.00303901,3.90546e-05,3.90546e-05,3.90546e-05,5.54151e-05,5.54151e-05,0.0019295,0.000514173,3.7932e-05,3.7932e-05,0.00257559,0.0106722,0.0106722,0.00216803,0.00216803,0.00216803,0.000774125,0.00220882,0.00212834,0.00212834,0.000844234,0.00273055,0.00273055,0.000885444,0.000885444,0.00159661,6.9386e-05,0.00160217,0.00148636,0.00148636,3.52586e-05,0.00217997,0.000881851,0.000881851,0.000995428,0.00441458,0.00441458,0.00441458,0.00441458,0.000331408,0.0150796,0.0150796,0.0150796,0.000160191,0.0120344,0.0120344,0.0059007,0.0059007,0.0059007,0.000701581,0.000501928,0.000501928,1e-05,0.00404004,0.00112392,0.00112392,0.000789327,0.000128601,0.000599614,0.00115514,0.00381461,0.00228505,0.00228505,4.50611e-05,4.50611e-05,0.000751739,0.0017928,0.0017928,0.0017928,0.0017928,8.35619e-05,0.00216168,0.000110482,0.00310307,0.0121224,0.00571941,0.00571941,0.00571941,0.00571941,0.0211349,0.0205506,0.0205506,0.000859457,0.000859457,0.0025084,0.00139774,0.000492954,0.00162963,0.00162963,3.10116e-05,6.23325e-05,0.000631898,0.000448809,0.000448809,0.000448809,0.00317281,0.000351455,0.00299904,1e-05,0.000275126,0.0124654,0.000866538,0.000866538,0.00301772,0.000204752,0.00282527,0.00235273,0.00235273,0.00235273,0.00235273,0.00235273,0.0156897,0.000285069,0.000285069,0.000627532,0.00152207,0.00152207,0.00013132,0.00464827,0.000825652,0.00667367,0.00667367,0.00160946", "train/beta1": "0.915545,0.910917,0.942149,0.942149,0.937684,0.937684,0.937684,0.965075,0.951511,0.5,0.5,0.987953,0.970043,0.970043,0.849405,0.966488,0.966488,0.971759,0.953666,0.623469,0.938472,0.938472,0.980506,0.883438,0.771961,0.838065,0.877042,0.851591,0.851591,0.5,0.5,0.5,0.802284,0.720071,0.935363,0.935363,0.935363,0.935363,0.93574,0.855131,0.919382,0.813801,0.813801,0.850718,0.850718,0.850718,0.943809,0.943809,0.991374,0.982351,0.982351,0.860886,0.907325,0.907325,0.907325,0.907325,0.944769,0.990639,0.951995,0.857442,0.857442,0.887708,0.887708,0.863235,0.934996,0.920592,0.920592,0.848687,0.848687,0.79294,0.79294,0.79294,0.79294,0.79294,0.5,0.970745,0.970745,0.915184,0.915184,0.963096,0.963096,0.981848,0.981848,0.95119,0.95119,0.951494,0.951494,0.921036,0.921036,0.930457,0.891426,0.891426,0.878067,0.895868,0.895868,0.913896,0.913896,0.80815,0.991227,0.991227,0.947774,0.947774,0.942794,0.942794,0.874323,0.874323,0.921764,0.921764,0.921764,0.878289,0.971563,0.971563,0.971563,0.971563,0.790097,0.873334,0.873334,0.919782,0.95055,0.95055,0.979311,0.960898,0.960898,0.861881,0.861881,0.951781,0.931124,0.931124,0.931124,0.931263,0.931263,0.834977,0.567626,0.567626,0.567626,0.88882,0.88882,0.88882,0.869649,0.952302,0.952302,0.952302,0.881134,0.881134,0.938859,0.938018,0.936426,0.936426,0.919082,0.822431,0.822431,0.943279,0.943279,0.943279,0.662962,0.880865,0.875103,0.875103,0.959801,0.952896,0.952896,0.933416,0.933416,0.5,0.98903,0.847559,0.960277,0.960277,0.94355,0.958285,0.961697,0.961697,0.553965,0.878249,0.878249,0.878249,0.878249,0.901601,0.955572,0.955572,0.955572,0.930657,0.957989,0.957989,0.922295,0.922295,0.922295,0.92902,0.944088,0.944088,0.778136,0.939788,0.94075,0.94075,0.994925,0.763456,0.935858,0.882191,0.84531,0.5,0.5,0.916473,0.916473,0.850731,0.930603,0.930603,0.930603,0.930603,0.975918,0.961817,0.92116,0.639833,0.906005,0.910188,0.910188,0.910188,0.910188,0.679726,0.814494,0.814494,0.806918,0.806918,0.940862,0.5,0.824508,0.9876,0.9876,0.993544,0.972273,0.960126,0.975505,0.975505,0.975505,0.92076,0.888886,0.736109,0.973217,0.947396,0.909515,0.963237,0.963237,0.835383,0.971539,0.822271,0.625686,0.625686,0.625686,0.625686,0.625686,0.888953,0.686938,0.686938,0.875384,0.764581,0.764581,0.906732,0.909513,0.851842,0.939191,0.939191,0.909951", "train/beta2": "0.999981,0.999564,0.999423,0.999423,0.999793,0.999793,0.999793,0.99999,0.999987,0.999775,0.999775,0.99999,0.999629,0.999629,0.999971,0.998559,0.998559,0.999419,0.991917,0.999695,0.999813,0.999813,0.999444,0.999388,0.999976,0.99999,0.99999,0.99993,0.99993,0.999982,0.999982,0.999982,0.999609,0.999901,0.99994,0.99994,0.99994,0.99994,0.998182,0.999982,0.999935,0.999915,0.999915,0.999926,0.999926,0.999926,0.998465,0.998465,0.999921,0.99986,0.99986,0.999903,0.999776,0.999776,0.999776,0.999776,0.997094,0.997926,0.99972,0.999977,0.999977,0.999977,0.999977,0.999501,0.99999,0.999936,0.999936,0.9998,0.9998,0.992373,0.992373,0.992373,0.992373,0.992373,0.999973,0.999776,0.999776,0.99999,0.99999,0.999873,0.999873,0.999233,0.999233,0.99995,0.99995,0.998857,0.998857,0.99998,0.99998,0.998629,0.99999,0.99999,0.999951,0.99947,0.99947,0.999827,0.999827,0.99999,0.999655,0.999655,0.999524,0.999524,0.999966,0.999966,0.99994,0.99994,0.999839,0.999839,0.999839,0.999758,0.997273,0.997273,0.997273,0.997273,0.998449,0.999655,0.999655,0.998356,0.99961,0.99961,0.999308,0.999937,0.999937,0.99995,0.99995,0.999895,0.999475,0.999475,0.999475,0.999839,0.999839,0.99999,0.999983,0.999983,0.999983,0.999939,0.999939,0.999939,0.998762,0.99999,0.99999,0.99999,0.99997,0.99997,0.995675,0.999903,0.999917,0.999917,0.99543,0.99447,0.99447,0.999017,0.999017,0.999017,0.999938,0.996877,0.999945,0.999945,0.999919,0.999927,0.999927,0.999873,0.999873,0.999866,0.999948,0.99994,0.99999,0.99999,0.999933,0.999719,0.999909,0.999909,0.999965,0.999912,0.999912,0.999912,0.999912,0.999943,0.980119,0.980119,0.980119,0.999646,0.999687,0.999687,0.999975,0.999975,0.999975,0.999988,0.999153,0.999153,0.9999,0.999202,0.99986,0.99986,0.999808,0.999917,0.99999,0.999978,0.999347,0.992864,0.992864,0.999953,0.999953,0.999904,0.98762,0.98762,0.98762,0.98762,0.997994,0.999522,0.999801,0.984354,0.99999,0.998902,0.998902,0.998902,0.998902,0.9993,0.99981,0.99981,0.99999,0.99999,0.999942,0.999784,0.999977,0.997546,0.997546,0.999964,0.999477,0.998707,0.999415,0.999415,0.999415,0.99999,0.999435,0.999962,0.999939,0.999029,0.999983,0.999435,0.999435,0.999445,0.999787,0.99848,0.999905,0.999905,0.999905,0.999905,0.999905,0.998358,0.99999,0.99999,0.99997,0.99999,0.99999,0.999967,0.999989,0.999256,0.999232,0.999232,0.999984", "train/eps": "7.17683e-14,8.21987e-10,6.51087e-10,6.51087e-10,1.28372e-12,1.28372e-12,1.28372e-12,4.73727e-13,3.68207e-13,2.20316e-12,2.20316e-12,1.28905e-12,7.42615e-14,7.42615e-14,2.03593e-14,7.46742e-12,7.46742e-12,1.10041e-12,9.41893e-11,1.11209e-09,1e-14,1e-14,1e-14,2.5937e-10,1.20915e-11,1.69116e-12,4.38231e-10,1e-14,1e-14,2.03944e-12,2.03944e-12,2.03944e-12,1e-14,1.80383e-14,1.14356e-13,1.14356e-13,1.14356e-13,1.14356e-13,8.32841e-14,9.35245e-14,1e-14,7.06766e-09,7.06766e-09,1e-14,1e-14,1e-14,5.86856e-12,5.86856e-12,3.0945e-14,1e-14,1e-14,1.18608e-14,8.63376e-12,8.63376e-12,8.63376e-12,8.63376e-12,1e-14,2.49528e-13,1.25655e-12,1e-14,1e-14,1e-14,1e-14,7.24116e-14,5.95094e-14,1e-14,1e-14,1e-14,1e-14,1e-14,1e-14,1e-14,1e-14,1e-14,1.55827e-10,2.90463e-12,2.90463e-12,1.85016e-11,1.85016e-11,4.47907e-12,4.47907e-12,1.54883e-11,1.54883e-11,1e-14,1e-14,4.37467e-13,4.37467e-13,1e-14,1e-14,6.08056e-13,1e-14,1e-14,3e-14,3.88771e-11,3.88771e-11,1.35181e-13,1.35181e-13,2.83616e-12,2.28509e-11,2.28509e-11,1e-14,1e-14,1e-14,1e-14,6.9418e-14,6.9418e-14,1.26524e-09,1.26524e-09,1.26524e-09,4.66661e-12,9.54183e-12,9.54183e-12,9.54183e-12,9.54183e-12,4.97096e-14,1.35378e-10,1.35378e-10,2.61076e-13,7.00458e-11,7.00458e-11,7.40109e-13,1e-14,1e-14,1.87563e-12,1.87563e-12,8.81176e-10,1e-14,1e-14,1e-14,1e-14,1e-14,1.43809e-12,5.59527e-11,5.59527e-11,5.59527e-11,1e-14,1e-14,1e-14,5.32846e-13,2.75132e-11,2.75132e-11,2.75132e-11,1e-14,1e-14,6.76747e-12,2.8e-13,4.32628e-10,4.32628e-10,1e-14,1e-14,1e-14,3.76476e-10,3.76476e-10,3.76476e-10,4.26134e-14,1.0218e-13,1e-14,1e-14,5.71911e-09,1e-14,1e-14,1.08605e-10,1.08605e-10,8.1795e-10,1.26274e-11,4.57645e-11,1.89187e-14,1.89187e-14,1.17713e-11,1.23883e-14,2.89079e-13,2.89079e-13,1.42538e-14,3.14003e-12,3.14003e-12,3.14003e-12,3.14003e-12,7.45763e-11,1.73447e-12,1.73447e-12,1.73447e-12,1.87604e-12,1.96126e-12,1.96126e-12,1e-14,1e-14,1e-14,2.18842e-12,1.83574e-12,1.83574e-12,3.44346e-12,3.90273e-10,1.01145e-12,1.01145e-12,4.03429e-13,2.38594e-12,1e-14,9.06776e-14,7.13284e-13,1.10581e-13,1.10581e-13,3.39508e-14,3.39508e-14,7.06874e-13,1.02575e-11,1.02575e-11,1.02575e-11,1.02575e-11,3.67083e-11,1.4376e-13,1.99023e-10,1.12024e-12,1.07122e-11,1.38841e-09,1.38841e-09,1.38841e-09,1.38841e-09,1e-14,2.71489e-13,2.71489e-13,1e-14,1e-14,8.9047e-13,6.01301e-13,1.96709e-13,2.11039e-11,2.11039e-11,2.80928e-13,1.80047e-10,1e-14,1.68212e-11,1.68212e-11,1.68212e-11,1.08296e-10,2.87366e-13,3.27043e-14,1.40246e-10,1e-14,4.65378e-14,1.09218e-09,1.09218e-09,2.52887e-11,1e-14,1e-14,1e-14,1e-14,1e-14,1e-14,1e-14,3.84106e-11,1e-14,1e-14,2.01384e-14,2.17798e-12,2.17798e-12,2.63685e-12,7.04709e-10,1.16816e-14,2.38459e-13,2.38459e-13,2.27533e-12", "train/minibatch_size": "4096,4096,8192,8192,8192,8192,8192,8192,8192,8192,8192,4096,8192,8192,4096,4096,4096,4096,8192,4096,8192,8192,8192,4096,8192,4096,8192,8192,8192,8192,8192,8192,8192,4096,8192,8192,8192,8192,8192,4096,8192,4096,4096,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,4096,4096,4096,4096,8192,8192,8192,8192,8192,8192,8192,8192,8192,4096,8192,8192,4096,4096,8192,8192,4096,4096,8192,8192,4096,4096,8192,8192,8192,8192,8192,4096,4096,4096,8192,8192,4096,8192,8192,4096,4096,8192,8192,8192,8192,8192,8192,8192,4096,8192,8192,8192,8192,8192,4096,4096,8192,8192,8192,4096,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,4096,8192,8192,8192,8192,8192,8192,8192,4096,4096,4096,8192,8192,8192,8192,4096,4096,4096,4096,4096,4096,4096,4096,4096,8192,8192,8192,8192,8192,8192,8192,8192,4096,4096,4096,8192,8192,8192,8192,8192,8192,4096,8192,8192,8192,8192,4096,8192,8192,8192,4096,8192,8192,8192,8192,8192,4096,8192,8192,4096,4096,8192,8192,8192,8192,4096,8192,4096,4096,4096,4096,4096,8192,8192,8192,8192,8192,8192,8192,8192,4096,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,4096,4096,8192,4096,16384,8192,8192,8192,8192,8192,8192,8192,8192,8192,4096,4096,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,8192,4096,8192,4096,4096,4096,8192", "train/horizon": "16,16,16,16,16,16,16,16,16,32,32,32,32,32,8,16,16,8,32,8,32,32,64,8,32,8,16,32,32,16,16,16,32,8,16,16,16,16,32,8,16,16,16,32,32,32,16,16,32,16,16,16,8,8,8,8,32,32,8,32,32,8,8,16,16,16,16,32,32,16,16,16,16,16,8,16,16,8,8,8,8,8,8,32,32,16,16,32,32,16,8,8,8,16,16,32,32,16,8,8,32,32,16,16,16,16,32,32,32,16,8,8,8,8,32,16,16,32,16,16,16,64,64,32,32,8,32,32,32,32,32,8,32,32,32,32,32,32,16,8,8,8,8,8,16,16,8,8,32,16,16,32,32,32,8,32,32,32,8,32,32,16,16,16,8,16,16,16,16,8,8,8,8,32,32,32,32,8,16,16,16,8,32,32,64,64,64,8,16,16,16,8,64,64,32,16,8,16,32,16,16,8,8,32,16,16,16,16,8,32,32,16,32,16,16,16,16,32,32,32,8,8,8,16,8,16,16,32,16,16,16,16,16,64,16,32,8,32,16,16,16,16,16,16,32,32,32,32,32,16,32,32,8,16,16,8,16,8,16,16,16", "train/vtrace_rho_clip": "5,2.73689,2.46108,2.46108,3.80583,3.80583,3.80583,3.81549,3.97267,4.54917,4.54917,4.74302,4.85562,4.85562,4.27771,5,5,5,2.21968,4.31699,5,5,4.6331,4.16743,5,4.09355,4.30022,5,5,5,5,5,2.76539,5,2.43218,2.43218,2.43218,2.43218,3.78118,4.09983,2.92381,4.43805,4.43805,3.85804,3.85804,3.85804,2.37402,2.37402,1.94523,2.68087,2.68087,5,5,5,5,5,1.81695,3.9119,5,2.63534,2.63534,5,5,3.31269,5,3.69538,3.69538,4.72554,4.72554,4.3162,4.3162,4.3162,4.3162,4.3162,5,2.60123,2.60123,5,5,5,5,5,5,5,5,4.81119,4.81119,4.68912,4.68912,0.1,4.24154,4.24154,2.78715,2.51969,2.51969,5,5,2.51338,5,5,4.20262,4.20262,5,5,5,5,2.40319,2.40319,2.40319,4.07945,5,5,5,5,5,5,5,4.34943,4.72123,4.72123,4.4126,3.28003,3.28003,3.88328,3.88328,3.26083,5,5,5,0.754779,0.754779,3.21181,1.90329,1.90329,1.90329,3.9435,3.9435,3.9435,2.04957,3.97842,3.97842,3.97842,4.41871,4.41871,2.59302,3.74441,3.45521,3.45521,1.15424,5,5,2.00187,2.00187,2.00187,3.98829,3.42441,4.54698,4.54698,5,1.78499,1.78499,4.19938,4.19938,3.63191,5,5,3.4438,3.4438,3.23626,1.47802,5,5,5,2.66096,2.66096,2.66096,2.66096,3.43952,3.81661,3.81661,3.81661,3.62497,5,5,4.2422,4.2422,4.2422,5,4.86264,4.86264,4.01128,5,3.05128,3.05128,3.55151,4.03527,3.51351,3.82742,1.73708,5,5,3.11048,3.11048,5,4.01342,4.01342,4.01342,4.01342,5,3.54013,5,5,3.54523,1.69525,1.69525,1.69525,1.69525,4.3136,5,5,5,5,5,4.00016,3.87662,2.66728,2.66728,2.49401,3.98429,1.51375,4.00524,4.00524,4.00524,4.70146,4.5262,2.71824,4.01695,4.56751,3.76608,1.8138,1.8138,5,2.68987,5,3.93061,3.93061,3.93061,3.93061,3.93061,4.67239,4.19285,4.19285,5,4.05367,4.05367,3.38063,5,1.51629,5,5,2.63505", "train/vtrace_c_clip": "0.486393,2.06733,1.62307,1.62307,1.69074,1.69074,1.69074,1.56878,1.72116,1.65428,1.65428,1.05525,0.634985,0.634985,1.93316,1.47584,1.47584,2.35085,2.38115,0.788602,0.946534,0.946534,0.480103,2.06071,0.979145,1.86764,2.59148,1.19427,1.19427,0.982607,0.982607,0.982607,0.68674,0.742989,2.40383,2.40383,2.40383,2.40383,1.33534,2.34669,1.8454,0.648476,0.648476,1.13859,1.13859,1.13859,2.59504,2.59504,1.21338,1.39147,1.39147,1.89506,2.07056,2.07056,2.07056,2.07056,2.39435,0.457427,1.88,1.82912,1.82912,1.80144,1.80144,1.40983,1.71267,2.53608,2.53608,1.5585,1.5585,1.43529,1.43529,1.43529,1.43529,1.43529,1.82035,1.82802,1.82802,1.49168,1.49168,1.90505,1.90505,2.48849,2.48849,1.6676,1.6676,0.82382,0.82382,1.91603,1.91603,0.229141,1.97996,1.97996,1.64092,1.34715,1.34715,1.78417,1.78417,2.10796,0.952444,0.952444,1.14635,1.14635,1.62385,1.62385,1.75591,1.75591,1.72843,1.72843,1.72843,1.39736,1.6274,1.6274,1.6274,1.6274,1.15345,1.98316,1.98316,1.31492,2.25068,2.25068,1.69032,2.08663,2.08663,0.953361,0.953361,2.24198,0.969249,0.969249,0.969249,2.1795,2.1795,1.51398,2.32599,2.32599,2.32599,1.43267,1.43267,1.43267,1.41495,1.55033,1.55033,1.55033,1.6452,1.6452,2.33488,1.60374,1.15929,1.15929,1.7845,2.4975,2.4975,2.46311,2.46311,2.46311,0.964481,2.83812,1.28983,1.28983,1.13592,1.7738,1.7738,3.01087,3.01087,0.648163,1.75073,0.590516,2.03827,2.03827,2.46918,1.85548,1.00894,1.00894,2.3504,1.23635,1.23635,1.23635,1.23635,1.88744,1.67515,1.67515,1.67515,1.37977,0.969918,0.969918,1.24753,1.24753,1.24753,1.90518,1.79853,1.79853,0.929191,1.87287,1.19098,1.19098,0.1,1.46445,0.782419,1.63732,2.32225,0.638269,0.638269,0.736167,0.736167,2.20143,2.17853,2.17853,2.17853,2.17853,2.50452,2.0625,0.943264,1.16137,1.34833,1.19026,1.19026,1.19026,1.19026,1.01953,1.5065,1.5065,1.696,1.696,2.19592,1.63783,1.75596,3.04538,3.04538,1.28895,1.88412,1.14457,2.09803,2.09803,2.09803,1.61148,1.61717,1.51695,2.21985,0.722769,1.60967,2.16307,2.16307,2.19647,1.46954,1.66817,1.15785,1.15785,1.15785,1.15785,1.15785,1.62992,2.1309,2.1309,1.37107,0.951263,0.951263,1.74711,3.16852,2.39646,1.76937,1.76937,1.63241", "train/prio_alpha": "0.713443,0.911295,0.131767,0.131767,0.943197,0.943197,0.943197,0.721345,0.363711,0.703053,0.703053,1,0.986832,0.986832,1,0.444569,0.444569,1,0.252774,0.513655,1,1,0.89642,0.741005,0.604841,0.693916,0.767863,0.750909,0.750909,0.753575,0.753575,0.753575,0.542471,1,0.518531,0.518531,0.518531,0.518531,1,0.317624,0.471081,0.331403,0.331403,0.948866,0.948866,0.948866,0.327713,0.327713,0.952266,0.362726,0.362726,0.930122,0.525591,0.525591,0.525591,0.525591,0.729804,0.866799,0.077362,0.986468,0.986468,0.605933,0.605933,0.748908,0.612177,0.606788,0.606788,0.653003,0.653003,0.934216,0.934216,0.934216,0.934216,0.934216,0.629854,0.62929,0.62929,0.710107,0.710107,0.579295,0.579295,0.381012,0.381012,0.951439,0.951439,0.556016,0.556016,1,1,0.99053,0.626324,0.626324,0.561785,0.485356,0.485356,0.756086,0.756086,1,0.564206,0.564206,0.639552,0.639552,1,1,0.576242,0.576242,0.0795066,0.0795066,0.0795066,0.978248,0.73529,0.73529,0.73529,0.73529,0.91475,0.123353,0.123353,1,0.532298,0.532298,0.599238,0.69498,0.69498,0.916903,0.916903,0.630298,0.856702,0.856702,0.856702,1,1,0.844211,1,1,1,0.626654,0.626654,0.626654,0.523499,0.808205,0.808205,0.808205,0.416194,0.416194,0.671552,0.530819,0.853465,0.853465,0.544265,0.605822,0.605822,0.231959,0.231959,0.231959,0.703913,0.308914,0.876456,0.876456,0.605509,1,1,0.53664,0.53664,0.500157,1,0.349864,0.761772,0.761772,0.604427,0.575298,0.637114,0.637114,0.238442,1,1,1,1,0.939872,0.508937,0.508937,0.508937,0.123555,0.755521,0.755521,0.503711,0.503711,0.503711,0.729297,0.293554,0.293554,0.746967,0.562263,1,1,1,0.667229,0.68401,0.372887,0.681562,0.636939,0.636939,1,1,0.883149,0.753447,0.753447,0.753447,0.753447,0.3183,0.385104,0.368103,0.406893,0.711155,0.48583,0.48583,0.48583,0.48583,0.978516,0.748788,0.748788,0.493219,0.493219,0.317213,0.679332,0.674667,0.388626,0.388626,0.758344,0.0397227,1,0.753525,0.753525,0.753525,0.648297,0.818046,1,0.695625,1,0.443138,0.574581,0.574581,0.793355,0.87543,0.922417,1,1,1,1,1,0.707941,0.777021,0.777021,0.526563,0.784668,0.784668,0.979432,0.497723,0.290678,0.711536,0.711536,0.726428", "train/prio_beta0": "0.0018797,0.417688,0.138826,0.138826,0,0,0,0.207796,0.285539,0.0725575,0.0725575,0,0.339227,0.339227,0,0.0361129,0.0361129,0.300181,0.0924182,0,0.277568,0.277568,0,0.0715314,0,0.298516,0.0162647,0.17214,0.17214,0.0872839,0.0872839,0.0872839,0,0.227957,0.966782,0.966782,0.966782,0.966782,0.389086,0.0830716,0.576034,0,0,0,0,0,0.0257064,0.0257064,0,0.828751,0.828751,0.244842,0.342384,0.342384,0.342384,0.342384,0.453345,0,0.0135092,0.00167594,0.00167594,0.350433,0.350433,0.199541,0.165747,0.936112,0.936112,0,0,0.426853,0.426853,0.426853,0.426853,0.426853,0.150577,0.395767,0.395767,0.0585516,0.0585516,0.299237,0.299237,0.220255,0.220255,0.236216,0.236216,0.352151,0.352151,0,0,0.0205714,0.202984,0.202984,0,0.802184,0.802184,0.444141,0.444141,0.174892,0.14883,0.14883,0.790043,0.790043,0.136191,0.136191,0.197394,0.197394,0,0,0,0.343705,0.460919,0.460919,0.460919,0.460919,0,0.0464442,0.0464442,0.284622,0.343366,0.343366,0.561885,0.046544,0.046544,0.181941,0.181941,0.554862,0,0,0,0,0,0,0.0158888,0.0158888,0.0158888,0,0,0,0.0383099,0,0,0,0.0509685,0.0509685,0.00191128,0.0654555,0,0,0.69185,0.78348,0.78348,0,0,0,0.00893147,0,0,0,0,0.0486025,0.0486025,0.116494,0.116494,0,0,0,0.0387188,0.0387188,0.010913,0.602545,0.182293,0.182293,0.0875492,0.144176,0.144176,0.144176,0.144176,0,0.321002,0.321002,0.321002,0.431897,0.256359,0.256359,0.162481,0.162481,0.162481,0,0.17102,0.17102,0,0.0169395,0.00478832,0.00478832,0.13571,0.00344377,0.237919,0.311518,0.180916,0.351821,0.351821,0,0,0.0792346,0.21627,0.21627,0.21627,0.21627,0.239781,0.589299,0.306503,0.515947,0.0179538,0,0,0,0,0,0,0,0.121082,0.121082,0.134291,0,0.330647,0.16292,0.16292,0,0,0.107791,0.23513,0.23513,0.23513,0.0149773,0.291553,0.175831,0,0.18521,0.377243,0,0,0.523598,0,0.0717466,0.231943,0.231943,0.231943,0.231943,0.231943,0.60556,0,0,0.22189,0,0,0,0.404116,0.121906,0.572141,0.572141,0.91419", "train/use_rnn": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "no_model_upload": "1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1", "tsne1": "-29.7708,-27.815,-28.5543,-28.5543,-24.1262,-24.128,-24.1266,-24.7355,-37.0096,-26.8509,-26.8509,-18.3817,-19.7564,-19.7564,-25.4343,-38.5141,-38.5141,-25.3548,-28.879,-34.7389,-20.3996,-20.3996,-17.4056,-28.6021,-23.6481,-30.5013,-30.1737,-22.7712,-22.7714,-27.4184,-27.4184,-27.4184,-22.6858,-21.4653,-25.2956,-25.2956,-25.2956,-25.2956,-18.5463,-35.3087,-26.8915,-34.1296,-34.1296,-17.5268,-17.5268,-17.5268,-28.1808,-28.1808,-15.789,-26.0558,-26.0561,-23.2258,-37.7123,-37.7125,-37.7126,-37.7115,-27.1456,-17.1937,-37.1853,-16.8772,-16.8772,-34.136,-34.1371,-28.6658,-30.9223,-25.2442,-25.2442,-23.4837,-23.4836,-36.3025,-36.3024,-36.3026,-36.3027,-36.3025,-28.0054,-27.3935,-27.3935,-31.9008,-31.9008,-37.1591,-37.1591,-39.0517,-39.0517,-19.4535,-19.4536,-41.7518,-41.7515,-18.3959,-18.3959,-16.8517,-29.5773,-29.5777,-28.6388,-25.6642,-25.6642,-19.8779,-19.8779,-23.443,-38.2648,-38.2649,-38.7409,-38.7409,-21.3461,-21.346,-22.1669,-22.1671,-28.1678,-28.1678,-28.1678,-28.8949,-40.3469,-40.3467,-40.3467,-40.3466,-18.8678,-30.8577,-30.8577,-18.2408,-32.3074,-32.3074,-40.906,-23.7442,-23.7441,-20.6932,-20.6932,-27.0246,-19.2282,-19.2282,-19.2282,-15.675,-15.675,-25.9165,-11.4724,-11.4724,-11.4724,-23.0659,-23.0666,-23.066,-28.0949,-27.1126,-27.1126,-27.1126,-35.5487,-35.5487,-28.074,-29.7027,-26.51,-26.51,-26.5945,-39.4572,-39.4572,-29.4656,-29.4657,-29.4657,-24.6699,-27.6208,-22.0617,-22.0619,-31.9282,-16.7104,-16.7105,-39.7207,-39.7207,-35.1591,-29.5299,-33.4602,-29.2498,-29.2498,2.49859,-26.4393,-35.8434,-35.8434,-36.5548,-13.5403,-13.5402,-13.5404,-13.5404,-27.7185,-39.6489,-39.6489,-39.6474,-36.3901,-20.6993,-20.6994,-22.3834,-22.3834,-22.3834,-32.2388,-30.9935,-30.9935,-27.0722,-39.5032,-15.1193,-15.1192,-17.7367,-26.0436,-32.3733,-36.8467,-28.4856,-37.0109,-37.0109,-26.1337,-26.1337,-24.031,-41.4309,-41.4305,-41.4307,-41.4307,-31.9254,-26.6663,-35.0813,-37.261,-25.2154,-31.106,-31.106,-31.106,-31.106,-16.3596,-21.475,-21.4749,-34.4486,-34.4486,-36.9944,-26.9667,-30.4852,-28.7647,-28.7647,-17.0295,-35.7327,-15.5069,-36.4751,-36.475,-36.4753,-23.4103,-36.6578,-17.981,-27.7446,-18.2977,-28.7787,-29.929,-29.929,-38.2248,-15.7378,-22.2609,-15.3617,-15.3617,-15.3617,-15.3617,-15.3616,-38.6061,-25.1586,-25.1586,-35.446,-25.7149,-25.7149,-26.199,-38.0837,-27.7126,-38.9868,-38.9868,-24.6476", "tsne2": "5.5166,-1.01311,18.0523,18.0523,-1.31173,-1.31348,-1.3133,-1.22484,7.38723,-8.45874,-8.45874,-9.87912,-6.2785,-6.27847,0.667696,5.72438,5.72438,-0.619501,18.102,2.10914,-1.59104,-1.59101,-5.3736,1.60136,-7.84063,7.33845,4.14401,-3.06871,-3.06869,-7.03,-7.03,-7.03,-5.31416,-0.896962,12.1083,12.1083,12.1083,12.1083,-6.86759,5.43677,10.1463,2.91447,2.91447,-3.58638,-3.58636,-3.58638,17.1764,17.1764,-10.0101,11.6466,11.6473,-2.20425,8.82155,8.82145,8.82149,8.82259,12.9062,-5.4181,6.2183,-9.19099,-9.19099,7.60219,7.60211,13.0637,6.4468,11.2415,11.2415,-4.93284,-4.93288,12.7718,12.7717,12.7719,12.7733,12.7718,-6.75437,13.3349,13.3349,5.6444,5.6444,8.37861,8.37861,6.30258,6.30258,-9.72222,-9.72224,10.8218,10.8217,-2.45262,-2.45262,11.5114,7.81009,7.80802,5.79744,13.2962,13.2962,-0.549107,-0.549107,0.244931,7.78309,7.7831,13.1234,13.1234,-6.00354,-6.0036,-9.71942,-9.71914,19.2827,19.2827,19.2827,12.7051,10.267,10.2672,10.267,10.2672,-5.4113,10.1909,10.1909,-5.30646,8.92198,8.92198,11.1078,-6.23081,-6.23099,-2.6797,-2.67968,13.9123,-4.03571,-4.03571,-4.03571,-8.72222,-8.72222,0.189028,-5.20981,-5.20981,-5.20981,-6.27716,-6.27714,-6.27717,16.4282,0.298481,0.298481,0.298481,6.33095,6.33095,-1.71538,6.80161,-0.0723269,-0.0723269,12.8814,12.3875,12.3875,17.7837,17.784,17.784,0.78508,17.1669,-2.52971,-2.52989,4.99544,-7.72514,-7.72513,7.22226,7.22226,1.99805,3.26293,3.79833,7.03675,7.03675,0.554874,10.9686,7.66863,7.66856,3.51153,-1.15023,-1.15025,-1.15013,-1.15016,-1.13947,9.01692,9.01692,9.01698,5.58076,-7.71689,-7.71692,-4.45665,-4.45665,-4.45665,5.73206,9.31188,9.31188,1.20654,6.04892,-0.582798,-0.582741,-4.64052,-2.19417,6.74684,7.43679,15.8638,2.56218,2.56218,1.15154,1.15154,-5.11784,8.34947,8.34929,8.34944,8.34939,9.13812,12.0218,9.07216,2.57665,-3.81015,17.1204,17.1203,17.1202,17.1204,-2.83804,-3.53516,-3.53527,6.13452,6.13452,6.59248,-7.0781,7.73291,16.6944,16.6944,-9.85213,4.89606,0.997561,9.44448,9.44442,9.44485,-7.61163,10.4638,-10.0866,0.0760491,-5.29629,8.86029,16.3666,16.3666,10.597,0.65414,-1.5707,-3.44193,-3.44193,-3.44193,-3.44193,-3.4422,10.8397,-6.58531,-6.58531,7.09898,-3.3398,-3.3398,0.720993,9.60706,16.1833,11.5707,11.5707,11.4513"}} \ No newline at end of file diff --git a/resources/constellation/point_particle_100.fs b/resources/constellation/point_particle_100.fs new file mode 100644 index 0000000000..5227abce2c --- /dev/null +++ b/resources/constellation/point_particle_100.fs @@ -0,0 +1,27 @@ +#version 100 +precision mediump float; +varying vec4 fragColor; + +void main() +{ + vec2 uv = gl_PointCoord - vec2(0.5); + float r = length(uv); + float angle = atan(uv.y, uv.x); + + float core = exp(-120.0 * r * r); + float mid = exp(- 30.0 * r * r) * 0.5; + float corona = exp(- 8.0 * r * r) * 0.35; + + float spike_mask = pow(abs(cos(angle * 2.0)), 24.0); + float spike = spike_mask * exp(-18.0 * r * r) * exp(-r * 4.0) * 1.2; + + float brightness = core + mid + corona + spike; + + if (brightness < 0.01) discard; + + vec3 color = fragColor.rgb * brightness * 5.0; + color += vec3(0.0, 0.05, 0.15) * spike; + color += vec3(0.0, 0.02, 0.08) * corona; + + gl_FragColor = vec4(color, clamp(brightness, 0.0, 1.0)); +} diff --git a/resources/constellation/point_particle_100.vs b/resources/constellation/point_particle_100.vs new file mode 100644 index 0000000000..34e841432c --- /dev/null +++ b/resources/constellation/point_particle_100.vs @@ -0,0 +1,23 @@ +#version 100 +attribute vec3 vertexPosition; +attribute vec4 vertexColor; +uniform mat4 mvp; +uniform float currentTime; +varying vec4 fragColor; + +float twinkle(float idx, float t) { + float base_size = 10.0; + float phase = mod(idx * 137.5, 360.0); + float frequency = 1.0 + mod(idx, 3.0) * 1.0; + float amplitude = (mod(idx, 20.0) == 0.0) ? 15.0 : 3.0; + float size_variation = amplitude * sin(frequency * t + radians(phase)); + return max(10.0, base_size + size_variation); +} + +void main() { + vec2 pos = vertexPosition.xy; + float idx = vertexPosition.z; + gl_Position = mvp * vec4(pos, 0.0, 1.0); + gl_PointSize = twinkle(idx, currentTime); + fragColor = vertexColor; +} diff --git a/resources/constellation/point_particle_330.fs b/resources/constellation/point_particle_330.fs new file mode 100644 index 0000000000..44fee7eaed --- /dev/null +++ b/resources/constellation/point_particle_330.fs @@ -0,0 +1,29 @@ +#version 330 + +in vec4 fragColor; +out vec4 finalColor; + +void main() +{ + vec2 uv = gl_PointCoord - vec2(0.5); + float r = length(uv); + float angle = atan(uv.y, uv.x); + + float core = exp(-120.0 * r * r); + float mid = exp(- 30.0 * r * r) * 0.5; + float corona = exp(- 8.0 * r * r) * 0.35; + + float spike_mask = pow(abs(cos(angle * 2.0)), 24.0); + float spike = spike_mask * exp(-18.0 * r * r) * exp(-r * 4.0) * 1.2; + + float brightness = core + mid + corona + spike; + + if (brightness < 0.01) + discard; + + vec3 color = fragColor.rgb * brightness * 5.0; + color += vec3(0.0, 0.05, 0.15) * spike; + color += vec3(0.0, 0.02, 0.08) * corona; + + finalColor = vec4(color, clamp(brightness, 0.0, 1.0)); +} diff --git a/resources/constellation/point_particle_330.vs b/resources/constellation/point_particle_330.vs new file mode 100644 index 0000000000..cdf17fe5a0 --- /dev/null +++ b/resources/constellation/point_particle_330.vs @@ -0,0 +1,42 @@ +#version 330 + +// Input vertex attributes +in vec3 vertexPosition; +in vec4 vertexColor; + +// Input uniform values +uniform mat4 mvp; +uniform float currentTime; + +// Output to fragment shader +out vec4 fragColor; + +// NOTE: Add your custom variables here + +float twinkle(float idx, float t) { + float base_size = 10.0; + float phase = mod(idx * 137.5, 360.0); + float frequency = 1.0 + mod(idx, 3.0) * 1.0; + float amplitude = (mod(idx, 20.0) == 0.0) ? 15.0 : 3.0; + float size_variation = amplitude * sin(frequency * t + radians(phase)); + return max(10, base_size + size_variation); +} + +void main() +{ + // Unpack data from vertexPosition + vec2 pos = vertexPosition.xy; + float idx = vertexPosition.z; + + // Calculate final vertex position (jiggle it around a bit horizontally) + //pos += vec2(100, 0)*sin(period*currentTime); + gl_Position = mvp*vec4(pos, 0.0, 1.0); + + // Calculate the screen space size of this particle (also vary it over time) + //gl_PointSize = 10 - 5*abs(sin(0.1*idx*currentTime)); + //gl_PointSize = 10.0; + + gl_PointSize = twinkle(idx, currentTime); + + fragColor = vertexColor; +} diff --git a/resources/constellation/puffer.rgs b/resources/constellation/puffer.rgs new file mode 100644 index 0000000000..95a05b0e15 Binary files /dev/null and b/resources/constellation/puffer.rgs differ diff --git a/pufferlib/resources/convert/convert_weights.bin b/resources/convert/convert_weights.bin similarity index 100% rename from pufferlib/resources/convert/convert_weights.bin rename to resources/convert/convert_weights.bin diff --git a/pufferlib/resources/cpr/cpr_weights.bin b/resources/cpr/cpr_weights.bin similarity index 100% rename from pufferlib/resources/cpr/cpr_weights.bin rename to resources/cpr/cpr_weights.bin diff --git a/pufferlib/resources/cpr/inflated_puff.png b/resources/cpr/inflated_puff.png similarity index 100% rename from pufferlib/resources/cpr/inflated_puff.png rename to resources/cpr/inflated_puff.png diff --git a/pufferlib/resources/cpr/puffers_128.png b/resources/cpr/puffers_128.png similarity index 100% rename from pufferlib/resources/cpr/puffers_128.png rename to resources/cpr/puffers_128.png diff --git a/pufferlib/resources/drive/BlueCar.glb b/resources/drive/BlueCar.glb similarity index 100% rename from pufferlib/resources/drive/BlueCar.glb rename to resources/drive/BlueCar.glb diff --git a/pufferlib/resources/drive/GreenCar.glb b/resources/drive/GreenCar.glb similarity index 100% rename from pufferlib/resources/drive/GreenCar.glb rename to resources/drive/GreenCar.glb diff --git a/pufferlib/resources/drive/GreyCar.glb b/resources/drive/GreyCar.glb similarity index 100% rename from pufferlib/resources/drive/GreyCar.glb rename to resources/drive/GreyCar.glb diff --git a/pufferlib/resources/drive/RedCar.glb b/resources/drive/RedCar.glb similarity index 100% rename from pufferlib/resources/drive/RedCar.glb rename to resources/drive/RedCar.glb diff --git a/pufferlib/resources/drive/WhiteCar.glb b/resources/drive/WhiteCar.glb similarity index 100% rename from pufferlib/resources/drive/WhiteCar.glb rename to resources/drive/WhiteCar.glb diff --git a/pufferlib/resources/drive/YellowCar.glb b/resources/drive/YellowCar.glb similarity index 100% rename from pufferlib/resources/drive/YellowCar.glb rename to resources/drive/YellowCar.glb diff --git a/resources/drive/drive_weights.bin b/resources/drive/drive_weights.bin new file mode 100644 index 0000000000..5ee3c671a9 Binary files /dev/null and b/resources/drive/drive_weights.bin differ diff --git a/resources/drive/map_010.bin b/resources/drive/map_010.bin new file mode 100644 index 0000000000..dd27b9e05a Binary files /dev/null and b/resources/drive/map_010.bin differ diff --git a/pufferlib/resources/drive/map_942.bin b/resources/drive/map_942.bin similarity index 100% rename from pufferlib/resources/drive/map_942.bin rename to resources/drive/map_942.bin diff --git a/resources/drone/drone_weights.bin b/resources/drone/drone_weights.bin new file mode 100644 index 0000000000..df5a47c211 Binary files /dev/null and b/resources/drone/drone_weights.bin differ diff --git a/pufferlib/resources/enduro/enduro_spritesheet.png b/resources/enduro/enduro_spritesheet.png similarity index 100% rename from pufferlib/resources/enduro/enduro_spritesheet.png rename to resources/enduro/enduro_spritesheet.png diff --git a/resources/enduro/enduro_weights.bin b/resources/enduro/enduro_weights.bin new file mode 100644 index 0000000000..8f95b3f707 Binary files /dev/null and b/resources/enduro/enduro_weights.bin differ diff --git a/resources/freeway/freeway_weights.bin b/resources/freeway/freeway_weights.bin new file mode 100644 index 0000000000..5f08479c5f Binary files /dev/null and b/resources/freeway/freeway_weights.bin differ diff --git a/pufferlib/resources/freeway/tex_car_body.png b/resources/freeway/tex_car_body.png similarity index 100% rename from pufferlib/resources/freeway/tex_car_body.png rename to resources/freeway/tex_car_body.png diff --git a/pufferlib/resources/freeway/tex_car_wheels.png b/resources/freeway/tex_car_wheels.png similarity index 100% rename from pufferlib/resources/freeway/tex_car_wheels.png rename to resources/freeway/tex_car_wheels.png diff --git a/pufferlib/resources/freeway/tex_chicken0.png b/resources/freeway/tex_chicken0.png similarity index 100% rename from pufferlib/resources/freeway/tex_chicken0.png rename to resources/freeway/tex_chicken0.png diff --git a/pufferlib/resources/freeway/tex_truck_body.png b/resources/freeway/tex_truck_body.png similarity index 100% rename from pufferlib/resources/freeway/tex_truck_body.png rename to resources/freeway/tex_truck_body.png diff --git a/pufferlib/resources/freeway/tex_truck_wheels.png b/resources/freeway/tex_truck_wheels.png similarity index 100% rename from pufferlib/resources/freeway/tex_truck_wheels.png rename to resources/freeway/tex_truck_wheels.png diff --git a/pufferlib/resources/nmmo3/nmmo3_weights.bin b/resources/g2048/g2048_weights.bin similarity index 58% rename from pufferlib/resources/nmmo3/nmmo3_weights.bin rename to resources/g2048/g2048_weights.bin index 515b149623..8dd8cec885 100644 Binary files a/pufferlib/resources/nmmo3/nmmo3_weights.bin and b/resources/g2048/g2048_weights.bin differ diff --git a/resources/go/go_weights.bin b/resources/go/go_weights.bin new file mode 100644 index 0000000000..c15fde5852 Binary files /dev/null and b/resources/go/go_weights.bin differ diff --git a/pufferlib/resources/impulse_wars/create_texture.py b/resources/impulse_wars/create_texture.py similarity index 100% rename from pufferlib/resources/impulse_wars/create_texture.py rename to resources/impulse_wars/create_texture.py diff --git a/pufferlib/resources/impulse_wars/shaders/gls100/bloom.fs b/resources/impulse_wars/shaders/gls100/bloom.fs similarity index 100% rename from pufferlib/resources/impulse_wars/shaders/gls100/bloom.fs rename to resources/impulse_wars/shaders/gls100/bloom.fs diff --git a/pufferlib/resources/impulse_wars/shaders/gls100/blur.fs b/resources/impulse_wars/shaders/gls100/blur.fs similarity index 100% rename from pufferlib/resources/impulse_wars/shaders/gls100/blur.fs rename to resources/impulse_wars/shaders/gls100/blur.fs diff --git a/pufferlib/resources/impulse_wars/shaders/gls100/grid.fs b/resources/impulse_wars/shaders/gls100/grid.fs similarity index 100% rename from pufferlib/resources/impulse_wars/shaders/gls100/grid.fs rename to resources/impulse_wars/shaders/gls100/grid.fs diff --git a/pufferlib/resources/impulse_wars/shaders/gls100/shader.vs b/resources/impulse_wars/shaders/gls100/shader.vs similarity index 100% rename from pufferlib/resources/impulse_wars/shaders/gls100/shader.vs rename to resources/impulse_wars/shaders/gls100/shader.vs diff --git a/pufferlib/resources/impulse_wars/shaders/gls330/bloom.fs b/resources/impulse_wars/shaders/gls330/bloom.fs similarity index 100% rename from pufferlib/resources/impulse_wars/shaders/gls330/bloom.fs rename to resources/impulse_wars/shaders/gls330/bloom.fs diff --git a/pufferlib/resources/impulse_wars/shaders/gls330/blur.fs b/resources/impulse_wars/shaders/gls330/blur.fs similarity index 100% rename from pufferlib/resources/impulse_wars/shaders/gls330/blur.fs rename to resources/impulse_wars/shaders/gls330/blur.fs diff --git a/pufferlib/resources/impulse_wars/shaders/gls330/grid.fs b/resources/impulse_wars/shaders/gls330/grid.fs similarity index 100% rename from pufferlib/resources/impulse_wars/shaders/gls330/grid.fs rename to resources/impulse_wars/shaders/gls330/grid.fs diff --git a/pufferlib/resources/impulse_wars/shaders/gls330/shader.vs b/resources/impulse_wars/shaders/gls330/shader.vs similarity index 100% rename from pufferlib/resources/impulse_wars/shaders/gls330/shader.vs rename to resources/impulse_wars/shaders/gls330/shader.vs diff --git a/pufferlib/resources/impulse_wars/wall_texture_map.png b/resources/impulse_wars/wall_texture_map.png similarity index 100% rename from pufferlib/resources/impulse_wars/wall_texture_map.png rename to resources/impulse_wars/wall_texture_map.png diff --git a/pufferlib/resources/g2048/g2048_weights.bin b/resources/maze/maze_weights.bin similarity index 61% rename from pufferlib/resources/g2048/g2048_weights.bin rename to resources/maze/maze_weights.bin index 3ebb3e38a3..aea0865845 100644 Binary files a/pufferlib/resources/g2048/g2048_weights.bin and b/resources/maze/maze_weights.bin differ diff --git a/pufferlib/resources/moba/bloom_shader_100.fs b/resources/moba/bloom_shader_100.fs similarity index 100% rename from pufferlib/resources/moba/bloom_shader_100.fs rename to resources/moba/bloom_shader_100.fs diff --git a/pufferlib/resources/moba/bloom_shader_330.fs b/resources/moba/bloom_shader_330.fs similarity index 100% rename from pufferlib/resources/moba/bloom_shader_330.fs rename to resources/moba/bloom_shader_330.fs diff --git a/pufferlib/resources/moba/dota_map.png b/resources/moba/dota_map.png similarity index 100% rename from pufferlib/resources/moba/dota_map.png rename to resources/moba/dota_map.png diff --git a/pufferlib/resources/moba/map_shader_100.fs b/resources/moba/map_shader_100.fs similarity index 100% rename from pufferlib/resources/moba/map_shader_100.fs rename to resources/moba/map_shader_100.fs diff --git a/pufferlib/resources/moba/map_shader_330.fs b/resources/moba/map_shader_330.fs similarity index 100% rename from pufferlib/resources/moba/map_shader_330.fs rename to resources/moba/map_shader_330.fs diff --git a/pufferlib/resources/moba/moba_assets.png b/resources/moba/moba_assets.png similarity index 100% rename from pufferlib/resources/moba/moba_assets.png rename to resources/moba/moba_assets.png diff --git a/resources/moba/moba_weights.bin b/resources/moba/moba_weights.bin new file mode 100644 index 0000000000..463d5af86d Binary files /dev/null and b/resources/moba/moba_weights.bin differ diff --git a/pufferlib/resources/nmmo3/ASSETS_LICENSE.md b/resources/nmmo3/ASSETS_LICENSE.md similarity index 100% rename from pufferlib/resources/nmmo3/ASSETS_LICENSE.md rename to resources/nmmo3/ASSETS_LICENSE.md diff --git a/pufferlib/resources/nmmo3/air_0.png b/resources/nmmo3/air_0.png similarity index 100% rename from pufferlib/resources/nmmo3/air_0.png rename to resources/nmmo3/air_0.png diff --git a/pufferlib/resources/nmmo3/air_1.png b/resources/nmmo3/air_1.png similarity index 100% rename from pufferlib/resources/nmmo3/air_1.png rename to resources/nmmo3/air_1.png diff --git a/pufferlib/resources/nmmo3/air_2.png b/resources/nmmo3/air_2.png similarity index 100% rename from pufferlib/resources/nmmo3/air_2.png rename to resources/nmmo3/air_2.png diff --git a/pufferlib/resources/nmmo3/air_3.png b/resources/nmmo3/air_3.png similarity index 100% rename from pufferlib/resources/nmmo3/air_3.png rename to resources/nmmo3/air_3.png diff --git a/pufferlib/resources/nmmo3/air_4.png b/resources/nmmo3/air_4.png similarity index 100% rename from pufferlib/resources/nmmo3/air_4.png rename to resources/nmmo3/air_4.png diff --git a/pufferlib/resources/nmmo3/air_5.png b/resources/nmmo3/air_5.png similarity index 100% rename from pufferlib/resources/nmmo3/air_5.png rename to resources/nmmo3/air_5.png diff --git a/pufferlib/resources/nmmo3/air_6.png b/resources/nmmo3/air_6.png similarity index 100% rename from pufferlib/resources/nmmo3/air_6.png rename to resources/nmmo3/air_6.png diff --git a/pufferlib/resources/nmmo3/air_7.png b/resources/nmmo3/air_7.png similarity index 100% rename from pufferlib/resources/nmmo3/air_7.png rename to resources/nmmo3/air_7.png diff --git a/pufferlib/resources/nmmo3/air_8.png b/resources/nmmo3/air_8.png similarity index 100% rename from pufferlib/resources/nmmo3/air_8.png rename to resources/nmmo3/air_8.png diff --git a/pufferlib/resources/nmmo3/air_9.png b/resources/nmmo3/air_9.png similarity index 100% rename from pufferlib/resources/nmmo3/air_9.png rename to resources/nmmo3/air_9.png diff --git a/pufferlib/resources/nmmo3/earth_0.png b/resources/nmmo3/earth_0.png similarity index 100% rename from pufferlib/resources/nmmo3/earth_0.png rename to resources/nmmo3/earth_0.png diff --git a/pufferlib/resources/nmmo3/earth_1.png b/resources/nmmo3/earth_1.png similarity index 100% rename from pufferlib/resources/nmmo3/earth_1.png rename to resources/nmmo3/earth_1.png diff --git a/pufferlib/resources/nmmo3/earth_2.png b/resources/nmmo3/earth_2.png similarity index 100% rename from pufferlib/resources/nmmo3/earth_2.png rename to resources/nmmo3/earth_2.png diff --git a/pufferlib/resources/nmmo3/earth_3.png b/resources/nmmo3/earth_3.png similarity index 100% rename from pufferlib/resources/nmmo3/earth_3.png rename to resources/nmmo3/earth_3.png diff --git a/pufferlib/resources/nmmo3/earth_4.png b/resources/nmmo3/earth_4.png similarity index 100% rename from pufferlib/resources/nmmo3/earth_4.png rename to resources/nmmo3/earth_4.png diff --git a/pufferlib/resources/nmmo3/earth_5.png b/resources/nmmo3/earth_5.png similarity index 100% rename from pufferlib/resources/nmmo3/earth_5.png rename to resources/nmmo3/earth_5.png diff --git a/pufferlib/resources/nmmo3/earth_6.png b/resources/nmmo3/earth_6.png similarity index 100% rename from pufferlib/resources/nmmo3/earth_6.png rename to resources/nmmo3/earth_6.png diff --git a/pufferlib/resources/nmmo3/earth_7.png b/resources/nmmo3/earth_7.png similarity index 100% rename from pufferlib/resources/nmmo3/earth_7.png rename to resources/nmmo3/earth_7.png diff --git a/pufferlib/resources/nmmo3/earth_8.png b/resources/nmmo3/earth_8.png similarity index 100% rename from pufferlib/resources/nmmo3/earth_8.png rename to resources/nmmo3/earth_8.png diff --git a/pufferlib/resources/nmmo3/earth_9.png b/resources/nmmo3/earth_9.png similarity index 100% rename from pufferlib/resources/nmmo3/earth_9.png rename to resources/nmmo3/earth_9.png diff --git a/pufferlib/resources/nmmo3/fire_0.png b/resources/nmmo3/fire_0.png similarity index 100% rename from pufferlib/resources/nmmo3/fire_0.png rename to resources/nmmo3/fire_0.png diff --git a/pufferlib/resources/nmmo3/fire_1.png b/resources/nmmo3/fire_1.png similarity index 100% rename from pufferlib/resources/nmmo3/fire_1.png rename to resources/nmmo3/fire_1.png diff --git a/pufferlib/resources/nmmo3/fire_2.png b/resources/nmmo3/fire_2.png similarity index 100% rename from pufferlib/resources/nmmo3/fire_2.png rename to resources/nmmo3/fire_2.png diff --git a/pufferlib/resources/nmmo3/fire_3.png b/resources/nmmo3/fire_3.png similarity index 100% rename from pufferlib/resources/nmmo3/fire_3.png rename to resources/nmmo3/fire_3.png diff --git a/pufferlib/resources/nmmo3/fire_4.png b/resources/nmmo3/fire_4.png similarity index 100% rename from pufferlib/resources/nmmo3/fire_4.png rename to resources/nmmo3/fire_4.png diff --git a/pufferlib/resources/nmmo3/fire_5.png b/resources/nmmo3/fire_5.png similarity index 100% rename from pufferlib/resources/nmmo3/fire_5.png rename to resources/nmmo3/fire_5.png diff --git a/pufferlib/resources/nmmo3/fire_6.png b/resources/nmmo3/fire_6.png similarity index 100% rename from pufferlib/resources/nmmo3/fire_6.png rename to resources/nmmo3/fire_6.png diff --git a/pufferlib/resources/nmmo3/fire_7.png b/resources/nmmo3/fire_7.png similarity index 100% rename from pufferlib/resources/nmmo3/fire_7.png rename to resources/nmmo3/fire_7.png diff --git a/pufferlib/resources/nmmo3/fire_8.png b/resources/nmmo3/fire_8.png similarity index 100% rename from pufferlib/resources/nmmo3/fire_8.png rename to resources/nmmo3/fire_8.png diff --git a/pufferlib/resources/nmmo3/fire_9.png b/resources/nmmo3/fire_9.png similarity index 100% rename from pufferlib/resources/nmmo3/fire_9.png rename to resources/nmmo3/fire_9.png diff --git a/pufferlib/resources/nmmo3/inventory_64.png b/resources/nmmo3/inventory_64.png similarity index 100% rename from pufferlib/resources/nmmo3/inventory_64.png rename to resources/nmmo3/inventory_64.png diff --git a/pufferlib/resources/nmmo3/inventory_64_press.png b/resources/nmmo3/inventory_64_press.png similarity index 100% rename from pufferlib/resources/nmmo3/inventory_64_press.png rename to resources/nmmo3/inventory_64_press.png diff --git a/pufferlib/resources/nmmo3/inventory_64_selected.png b/resources/nmmo3/inventory_64_selected.png similarity index 100% rename from pufferlib/resources/nmmo3/inventory_64_selected.png rename to resources/nmmo3/inventory_64_selected.png diff --git a/pufferlib/resources/nmmo3/items_condensed.png b/resources/nmmo3/items_condensed.png similarity index 100% rename from pufferlib/resources/nmmo3/items_condensed.png rename to resources/nmmo3/items_condensed.png diff --git a/pufferlib/resources/nmmo3/map_shader_100.fs b/resources/nmmo3/map_shader_100.fs similarity index 100% rename from pufferlib/resources/nmmo3/map_shader_100.fs rename to resources/nmmo3/map_shader_100.fs diff --git a/pufferlib/resources/nmmo3/map_shader_330.fs b/resources/nmmo3/map_shader_330.fs similarity index 100% rename from pufferlib/resources/nmmo3/map_shader_330.fs rename to resources/nmmo3/map_shader_330.fs diff --git a/pufferlib/resources/nmmo3/merged_sheet.png b/resources/nmmo3/merged_sheet.png similarity index 100% rename from pufferlib/resources/nmmo3/merged_sheet.png rename to resources/nmmo3/merged_sheet.png diff --git a/pufferlib/resources/nmmo3/neutral_0.png b/resources/nmmo3/neutral_0.png similarity index 100% rename from pufferlib/resources/nmmo3/neutral_0.png rename to resources/nmmo3/neutral_0.png diff --git a/pufferlib/resources/nmmo3/neutral_1.png b/resources/nmmo3/neutral_1.png similarity index 100% rename from pufferlib/resources/nmmo3/neutral_1.png rename to resources/nmmo3/neutral_1.png diff --git a/pufferlib/resources/nmmo3/neutral_2.png b/resources/nmmo3/neutral_2.png similarity index 100% rename from pufferlib/resources/nmmo3/neutral_2.png rename to resources/nmmo3/neutral_2.png diff --git a/pufferlib/resources/nmmo3/neutral_3.png b/resources/nmmo3/neutral_3.png similarity index 100% rename from pufferlib/resources/nmmo3/neutral_3.png rename to resources/nmmo3/neutral_3.png diff --git a/pufferlib/resources/nmmo3/neutral_4.png b/resources/nmmo3/neutral_4.png similarity index 100% rename from pufferlib/resources/nmmo3/neutral_4.png rename to resources/nmmo3/neutral_4.png diff --git a/pufferlib/resources/nmmo3/neutral_5.png b/resources/nmmo3/neutral_5.png similarity index 100% rename from pufferlib/resources/nmmo3/neutral_5.png rename to resources/nmmo3/neutral_5.png diff --git a/pufferlib/resources/nmmo3/neutral_6.png b/resources/nmmo3/neutral_6.png similarity index 100% rename from pufferlib/resources/nmmo3/neutral_6.png rename to resources/nmmo3/neutral_6.png diff --git a/pufferlib/resources/nmmo3/neutral_7.png b/resources/nmmo3/neutral_7.png similarity index 100% rename from pufferlib/resources/nmmo3/neutral_7.png rename to resources/nmmo3/neutral_7.png diff --git a/pufferlib/resources/nmmo3/neutral_8.png b/resources/nmmo3/neutral_8.png similarity index 100% rename from pufferlib/resources/nmmo3/neutral_8.png rename to resources/nmmo3/neutral_8.png diff --git a/pufferlib/resources/nmmo3/neutral_9.png b/resources/nmmo3/neutral_9.png similarity index 100% rename from pufferlib/resources/nmmo3/neutral_9.png rename to resources/nmmo3/neutral_9.png diff --git a/pufferlib/resources/nmmo3/nmmo3_help.png b/resources/nmmo3/nmmo3_help.png similarity index 100% rename from pufferlib/resources/nmmo3/nmmo3_help.png rename to resources/nmmo3/nmmo3_help.png diff --git a/resources/nmmo3/nmmo3_weights.bin b/resources/nmmo3/nmmo3_weights.bin new file mode 100644 index 0000000000..4d373029cd Binary files /dev/null and b/resources/nmmo3/nmmo3_weights.bin differ diff --git a/pufferlib/resources/nmmo3/water_0.png b/resources/nmmo3/water_0.png similarity index 100% rename from pufferlib/resources/nmmo3/water_0.png rename to resources/nmmo3/water_0.png diff --git a/pufferlib/resources/nmmo3/water_1.png b/resources/nmmo3/water_1.png similarity index 100% rename from pufferlib/resources/nmmo3/water_1.png rename to resources/nmmo3/water_1.png diff --git a/pufferlib/resources/nmmo3/water_2.png b/resources/nmmo3/water_2.png similarity index 100% rename from pufferlib/resources/nmmo3/water_2.png rename to resources/nmmo3/water_2.png diff --git a/pufferlib/resources/nmmo3/water_3.png b/resources/nmmo3/water_3.png similarity index 100% rename from pufferlib/resources/nmmo3/water_3.png rename to resources/nmmo3/water_3.png diff --git a/pufferlib/resources/nmmo3/water_4.png b/resources/nmmo3/water_4.png similarity index 100% rename from pufferlib/resources/nmmo3/water_4.png rename to resources/nmmo3/water_4.png diff --git a/pufferlib/resources/nmmo3/water_5.png b/resources/nmmo3/water_5.png similarity index 100% rename from pufferlib/resources/nmmo3/water_5.png rename to resources/nmmo3/water_5.png diff --git a/pufferlib/resources/nmmo3/water_6.png b/resources/nmmo3/water_6.png similarity index 100% rename from pufferlib/resources/nmmo3/water_6.png rename to resources/nmmo3/water_6.png diff --git a/pufferlib/resources/nmmo3/water_7.png b/resources/nmmo3/water_7.png similarity index 100% rename from pufferlib/resources/nmmo3/water_7.png rename to resources/nmmo3/water_7.png diff --git a/pufferlib/resources/nmmo3/water_8.png b/resources/nmmo3/water_8.png similarity index 100% rename from pufferlib/resources/nmmo3/water_8.png rename to resources/nmmo3/water_8.png diff --git a/pufferlib/resources/nmmo3/water_9.png b/resources/nmmo3/water_9.png similarity index 100% rename from pufferlib/resources/nmmo3/water_9.png rename to resources/nmmo3/water_9.png diff --git a/pufferlib/resources/onlyfish/danadvantage.bin b/resources/onlyfish/danadvantage.bin similarity index 100% rename from pufferlib/resources/onlyfish/danadvantage.bin rename to resources/onlyfish/danadvantage.bin diff --git a/pufferlib/resources/onlyfish/lonelypuff.bin b/resources/onlyfish/lonelypuff.bin similarity index 100% rename from pufferlib/resources/onlyfish/lonelypuff.bin rename to resources/onlyfish/lonelypuff.bin diff --git a/pufferlib/resources/onlyfish/star.png b/resources/onlyfish/star.png similarity index 100% rename from pufferlib/resources/onlyfish/star.png rename to resources/onlyfish/star.png diff --git a/resources/overcooked/chefs/EAST-bluehat.png b/resources/overcooked/chefs/EAST-bluehat.png new file mode 100644 index 0000000000..aa03a1994a Binary files /dev/null and b/resources/overcooked/chefs/EAST-bluehat.png differ diff --git a/resources/overcooked/chefs/EAST-dish.png b/resources/overcooked/chefs/EAST-dish.png new file mode 100644 index 0000000000..85574475bb Binary files /dev/null and b/resources/overcooked/chefs/EAST-dish.png differ diff --git a/resources/overcooked/chefs/EAST-greenhat.png b/resources/overcooked/chefs/EAST-greenhat.png new file mode 100644 index 0000000000..38fb8f8aed Binary files /dev/null and b/resources/overcooked/chefs/EAST-greenhat.png differ diff --git a/resources/overcooked/chefs/EAST-onion.png b/resources/overcooked/chefs/EAST-onion.png new file mode 100644 index 0000000000..2c11958d34 Binary files /dev/null and b/resources/overcooked/chefs/EAST-onion.png differ diff --git a/resources/overcooked/chefs/EAST-orangehat.png b/resources/overcooked/chefs/EAST-orangehat.png new file mode 100644 index 0000000000..00d8ce4c46 Binary files /dev/null and b/resources/overcooked/chefs/EAST-orangehat.png differ diff --git a/resources/overcooked/chefs/EAST-purplehat.png b/resources/overcooked/chefs/EAST-purplehat.png new file mode 100644 index 0000000000..f508f309d9 Binary files /dev/null and b/resources/overcooked/chefs/EAST-purplehat.png differ diff --git a/resources/overcooked/chefs/EAST-redhat.png b/resources/overcooked/chefs/EAST-redhat.png new file mode 100644 index 0000000000..ac823b5a6e Binary files /dev/null and b/resources/overcooked/chefs/EAST-redhat.png differ diff --git a/resources/overcooked/chefs/EAST-soup-onion.png b/resources/overcooked/chefs/EAST-soup-onion.png new file mode 100644 index 0000000000..ba70009c9b Binary files /dev/null and b/resources/overcooked/chefs/EAST-soup-onion.png differ diff --git a/resources/overcooked/chefs/EAST-soup-tomato.png b/resources/overcooked/chefs/EAST-soup-tomato.png new file mode 100644 index 0000000000..3fe0ea6d04 Binary files /dev/null and b/resources/overcooked/chefs/EAST-soup-tomato.png differ diff --git a/resources/overcooked/chefs/EAST-tomato.png b/resources/overcooked/chefs/EAST-tomato.png new file mode 100644 index 0000000000..ba15181ea7 Binary files /dev/null and b/resources/overcooked/chefs/EAST-tomato.png differ diff --git a/resources/overcooked/chefs/EAST.png b/resources/overcooked/chefs/EAST.png new file mode 100644 index 0000000000..4b704154e7 Binary files /dev/null and b/resources/overcooked/chefs/EAST.png differ diff --git a/resources/overcooked/chefs/NORTH-bluehat.png b/resources/overcooked/chefs/NORTH-bluehat.png new file mode 100644 index 0000000000..0ba8726a5e Binary files /dev/null and b/resources/overcooked/chefs/NORTH-bluehat.png differ diff --git a/resources/overcooked/chefs/NORTH-dish.png b/resources/overcooked/chefs/NORTH-dish.png new file mode 100644 index 0000000000..515ce18c79 Binary files /dev/null and b/resources/overcooked/chefs/NORTH-dish.png differ diff --git a/resources/overcooked/chefs/NORTH-greenhat.png b/resources/overcooked/chefs/NORTH-greenhat.png new file mode 100644 index 0000000000..7ab3199a8d Binary files /dev/null and b/resources/overcooked/chefs/NORTH-greenhat.png differ diff --git a/resources/overcooked/chefs/NORTH-onion.png b/resources/overcooked/chefs/NORTH-onion.png new file mode 100644 index 0000000000..adfbcde7b9 Binary files /dev/null and b/resources/overcooked/chefs/NORTH-onion.png differ diff --git a/resources/overcooked/chefs/NORTH-orangehat.png b/resources/overcooked/chefs/NORTH-orangehat.png new file mode 100644 index 0000000000..44dfd3878b Binary files /dev/null and b/resources/overcooked/chefs/NORTH-orangehat.png differ diff --git a/resources/overcooked/chefs/NORTH-purplehat.png b/resources/overcooked/chefs/NORTH-purplehat.png new file mode 100644 index 0000000000..cb204236fe Binary files /dev/null and b/resources/overcooked/chefs/NORTH-purplehat.png differ diff --git a/resources/overcooked/chefs/NORTH-redhat.png b/resources/overcooked/chefs/NORTH-redhat.png new file mode 100644 index 0000000000..5ac895a1ab Binary files /dev/null and b/resources/overcooked/chefs/NORTH-redhat.png differ diff --git a/resources/overcooked/chefs/NORTH-soup-onion.png b/resources/overcooked/chefs/NORTH-soup-onion.png new file mode 100644 index 0000000000..74d5731c2c Binary files /dev/null and b/resources/overcooked/chefs/NORTH-soup-onion.png differ diff --git a/resources/overcooked/chefs/NORTH-soup-tomato.png b/resources/overcooked/chefs/NORTH-soup-tomato.png new file mode 100644 index 0000000000..5dfb3bee5f Binary files /dev/null and b/resources/overcooked/chefs/NORTH-soup-tomato.png differ diff --git a/resources/overcooked/chefs/NORTH-tomato.png b/resources/overcooked/chefs/NORTH-tomato.png new file mode 100644 index 0000000000..e4a56aa59a Binary files /dev/null and b/resources/overcooked/chefs/NORTH-tomato.png differ diff --git a/resources/overcooked/chefs/NORTH.png b/resources/overcooked/chefs/NORTH.png new file mode 100644 index 0000000000..2c23600063 Binary files /dev/null and b/resources/overcooked/chefs/NORTH.png differ diff --git a/resources/overcooked/chefs/SOUTH-bluehat.png b/resources/overcooked/chefs/SOUTH-bluehat.png new file mode 100644 index 0000000000..8f4e95e224 Binary files /dev/null and b/resources/overcooked/chefs/SOUTH-bluehat.png differ diff --git a/resources/overcooked/chefs/SOUTH-dish.png b/resources/overcooked/chefs/SOUTH-dish.png new file mode 100644 index 0000000000..0bda2437db Binary files /dev/null and b/resources/overcooked/chefs/SOUTH-dish.png differ diff --git a/resources/overcooked/chefs/SOUTH-greenhat.png b/resources/overcooked/chefs/SOUTH-greenhat.png new file mode 100644 index 0000000000..5bf1cf7d22 Binary files /dev/null and b/resources/overcooked/chefs/SOUTH-greenhat.png differ diff --git a/resources/overcooked/chefs/SOUTH-onion.png b/resources/overcooked/chefs/SOUTH-onion.png new file mode 100644 index 0000000000..d12a0383be Binary files /dev/null and b/resources/overcooked/chefs/SOUTH-onion.png differ diff --git a/resources/overcooked/chefs/SOUTH-orangehat.png b/resources/overcooked/chefs/SOUTH-orangehat.png new file mode 100644 index 0000000000..82ffa7a5a4 Binary files /dev/null and b/resources/overcooked/chefs/SOUTH-orangehat.png differ diff --git a/resources/overcooked/chefs/SOUTH-purplehat.png b/resources/overcooked/chefs/SOUTH-purplehat.png new file mode 100644 index 0000000000..885ebf4aef Binary files /dev/null and b/resources/overcooked/chefs/SOUTH-purplehat.png differ diff --git a/resources/overcooked/chefs/SOUTH-redhat.png b/resources/overcooked/chefs/SOUTH-redhat.png new file mode 100644 index 0000000000..f610cc20b4 Binary files /dev/null and b/resources/overcooked/chefs/SOUTH-redhat.png differ diff --git a/resources/overcooked/chefs/SOUTH-soup-onion.png b/resources/overcooked/chefs/SOUTH-soup-onion.png new file mode 100644 index 0000000000..f7beeea306 Binary files /dev/null and b/resources/overcooked/chefs/SOUTH-soup-onion.png differ diff --git a/resources/overcooked/chefs/SOUTH-soup-tomato.png b/resources/overcooked/chefs/SOUTH-soup-tomato.png new file mode 100644 index 0000000000..e524822fd3 Binary files /dev/null and b/resources/overcooked/chefs/SOUTH-soup-tomato.png differ diff --git a/resources/overcooked/chefs/SOUTH-tomato.png b/resources/overcooked/chefs/SOUTH-tomato.png new file mode 100644 index 0000000000..f4ccd62d40 Binary files /dev/null and b/resources/overcooked/chefs/SOUTH-tomato.png differ diff --git a/resources/overcooked/chefs/SOUTH.png b/resources/overcooked/chefs/SOUTH.png new file mode 100644 index 0000000000..90a5c1a5c3 Binary files /dev/null and b/resources/overcooked/chefs/SOUTH.png differ diff --git a/resources/overcooked/chefs/WEST-bluehat.png b/resources/overcooked/chefs/WEST-bluehat.png new file mode 100644 index 0000000000..0ecd023abc Binary files /dev/null and b/resources/overcooked/chefs/WEST-bluehat.png differ diff --git a/resources/overcooked/chefs/WEST-dish.png b/resources/overcooked/chefs/WEST-dish.png new file mode 100644 index 0000000000..33ea8e127c Binary files /dev/null and b/resources/overcooked/chefs/WEST-dish.png differ diff --git a/resources/overcooked/chefs/WEST-greenhat.png b/resources/overcooked/chefs/WEST-greenhat.png new file mode 100644 index 0000000000..4ac02a9c22 Binary files /dev/null and b/resources/overcooked/chefs/WEST-greenhat.png differ diff --git a/resources/overcooked/chefs/WEST-onion.png b/resources/overcooked/chefs/WEST-onion.png new file mode 100644 index 0000000000..d272416842 Binary files /dev/null and b/resources/overcooked/chefs/WEST-onion.png differ diff --git a/resources/overcooked/chefs/WEST-orangehat.png b/resources/overcooked/chefs/WEST-orangehat.png new file mode 100644 index 0000000000..c72b8677c4 Binary files /dev/null and b/resources/overcooked/chefs/WEST-orangehat.png differ diff --git a/resources/overcooked/chefs/WEST-purplehat.png b/resources/overcooked/chefs/WEST-purplehat.png new file mode 100644 index 0000000000..6486365f8a Binary files /dev/null and b/resources/overcooked/chefs/WEST-purplehat.png differ diff --git a/resources/overcooked/chefs/WEST-redhat.png b/resources/overcooked/chefs/WEST-redhat.png new file mode 100644 index 0000000000..95ba881ad2 Binary files /dev/null and b/resources/overcooked/chefs/WEST-redhat.png differ diff --git a/resources/overcooked/chefs/WEST-soup-onion.png b/resources/overcooked/chefs/WEST-soup-onion.png new file mode 100644 index 0000000000..60d6082bae Binary files /dev/null and b/resources/overcooked/chefs/WEST-soup-onion.png differ diff --git a/resources/overcooked/chefs/WEST-soup-tomato.png b/resources/overcooked/chefs/WEST-soup-tomato.png new file mode 100644 index 0000000000..43245b1208 Binary files /dev/null and b/resources/overcooked/chefs/WEST-soup-tomato.png differ diff --git a/resources/overcooked/chefs/WEST-tomato.png b/resources/overcooked/chefs/WEST-tomato.png new file mode 100644 index 0000000000..44cbfe3a6e Binary files /dev/null and b/resources/overcooked/chefs/WEST-tomato.png differ diff --git a/resources/overcooked/chefs/WEST.png b/resources/overcooked/chefs/WEST.png new file mode 100644 index 0000000000..960b953038 Binary files /dev/null and b/resources/overcooked/chefs/WEST.png differ diff --git a/resources/overcooked/individual/arrow.png b/resources/overcooked/individual/arrow.png new file mode 100644 index 0000000000..e2452c0291 Binary files /dev/null and b/resources/overcooked/individual/arrow.png differ diff --git a/resources/overcooked/individual/interact.png b/resources/overcooked/individual/interact.png new file mode 100644 index 0000000000..c94e0c9510 Binary files /dev/null and b/resources/overcooked/individual/interact.png differ diff --git a/resources/overcooked/individual/stay.png b/resources/overcooked/individual/stay.png new file mode 100644 index 0000000000..ae20d854a3 Binary files /dev/null and b/resources/overcooked/individual/stay.png differ diff --git a/resources/overcooked/objects/dish.png b/resources/overcooked/objects/dish.png new file mode 100644 index 0000000000..1f2fa2ae2f Binary files /dev/null and b/resources/overcooked/objects/dish.png differ diff --git a/resources/overcooked/objects/onion.png b/resources/overcooked/objects/onion.png new file mode 100644 index 0000000000..f637b305c1 Binary files /dev/null and b/resources/overcooked/objects/onion.png differ diff --git a/resources/overcooked/objects/pot-explosion.png b/resources/overcooked/objects/pot-explosion.png new file mode 100644 index 0000000000..a802d15e7e Binary files /dev/null and b/resources/overcooked/objects/pot-explosion.png differ diff --git a/resources/overcooked/objects/soup-onion-1-cooking.png b/resources/overcooked/objects/soup-onion-1-cooking.png new file mode 100644 index 0000000000..5e91a19126 Binary files /dev/null and b/resources/overcooked/objects/soup-onion-1-cooking.png differ diff --git a/resources/overcooked/objects/soup-onion-2-cooking.png b/resources/overcooked/objects/soup-onion-2-cooking.png new file mode 100644 index 0000000000..668d70fdd4 Binary files /dev/null and b/resources/overcooked/objects/soup-onion-2-cooking.png differ diff --git a/resources/overcooked/objects/soup-onion-3-cooking.png b/resources/overcooked/objects/soup-onion-3-cooking.png new file mode 100644 index 0000000000..3c35aeb71d Binary files /dev/null and b/resources/overcooked/objects/soup-onion-3-cooking.png differ diff --git a/resources/overcooked/objects/soup-onion-cooked.png b/resources/overcooked/objects/soup-onion-cooked.png new file mode 100644 index 0000000000..664e81ab43 Binary files /dev/null and b/resources/overcooked/objects/soup-onion-cooked.png differ diff --git a/resources/overcooked/objects/soup-onion-dish.png b/resources/overcooked/objects/soup-onion-dish.png new file mode 100644 index 0000000000..7f6e4f81c4 Binary files /dev/null and b/resources/overcooked/objects/soup-onion-dish.png differ diff --git a/resources/overcooked/objects/soup-tomato-1-cooking.png b/resources/overcooked/objects/soup-tomato-1-cooking.png new file mode 100644 index 0000000000..77bbfe4b26 Binary files /dev/null and b/resources/overcooked/objects/soup-tomato-1-cooking.png differ diff --git a/resources/overcooked/objects/soup-tomato-2-cooking.png b/resources/overcooked/objects/soup-tomato-2-cooking.png new file mode 100644 index 0000000000..81b75494ac Binary files /dev/null and b/resources/overcooked/objects/soup-tomato-2-cooking.png differ diff --git a/resources/overcooked/objects/soup-tomato-3-0.png b/resources/overcooked/objects/soup-tomato-3-0.png new file mode 100644 index 0000000000..efe89b922a Binary files /dev/null and b/resources/overcooked/objects/soup-tomato-3-0.png differ diff --git a/resources/overcooked/objects/soup-tomato-3-cooking.png b/resources/overcooked/objects/soup-tomato-3-cooking.png new file mode 100644 index 0000000000..efe89b922a Binary files /dev/null and b/resources/overcooked/objects/soup-tomato-3-cooking.png differ diff --git a/resources/overcooked/objects/soup-tomato-cooked.png b/resources/overcooked/objects/soup-tomato-cooked.png new file mode 100644 index 0000000000..a022d2df6e Binary files /dev/null and b/resources/overcooked/objects/soup-tomato-cooked.png differ diff --git a/resources/overcooked/objects/soup-tomato-dish.png b/resources/overcooked/objects/soup-tomato-dish.png new file mode 100644 index 0000000000..cce15c841f Binary files /dev/null and b/resources/overcooked/objects/soup-tomato-dish.png differ diff --git a/resources/overcooked/objects/tomato.png b/resources/overcooked/objects/tomato.png new file mode 100644 index 0000000000..69c4681c6c Binary files /dev/null and b/resources/overcooked/objects/tomato.png differ diff --git a/resources/overcooked/puffer_overcooked_weights_aa.bin b/resources/overcooked/puffer_overcooked_weights_aa.bin new file mode 100644 index 0000000000..8bf8843d6d Binary files /dev/null and b/resources/overcooked/puffer_overcooked_weights_aa.bin differ diff --git a/resources/overcooked/puffer_overcooked_weights_cc.bin b/resources/overcooked/puffer_overcooked_weights_cc.bin new file mode 100644 index 0000000000..e7b9ed6740 Binary files /dev/null and b/resources/overcooked/puffer_overcooked_weights_cc.bin differ diff --git a/resources/overcooked/puffer_overcooked_weights_cor.bin b/resources/overcooked/puffer_overcooked_weights_cor.bin new file mode 100644 index 0000000000..44d3fc0bf5 Binary files /dev/null and b/resources/overcooked/puffer_overcooked_weights_cor.bin differ diff --git a/resources/overcooked/puffer_overcooked_weights_cr.bin b/resources/overcooked/puffer_overcooked_weights_cr.bin new file mode 100644 index 0000000000..a1d25b5fa5 Binary files /dev/null and b/resources/overcooked/puffer_overcooked_weights_cr.bin differ diff --git a/resources/overcooked/puffer_overcooked_weights_fc.bin b/resources/overcooked/puffer_overcooked_weights_fc.bin new file mode 100644 index 0000000000..ffd675e302 Binary files /dev/null and b/resources/overcooked/puffer_overcooked_weights_fc.bin differ diff --git a/resources/overcooked/soups/soup_cooked_tomato_0_onion_1.png b/resources/overcooked/soups/soup_cooked_tomato_0_onion_1.png new file mode 100644 index 0000000000..a5fef1e6e0 Binary files /dev/null and b/resources/overcooked/soups/soup_cooked_tomato_0_onion_1.png differ diff --git a/resources/overcooked/soups/soup_cooked_tomato_0_onion_2.png b/resources/overcooked/soups/soup_cooked_tomato_0_onion_2.png new file mode 100644 index 0000000000..bdbbc2518d Binary files /dev/null and b/resources/overcooked/soups/soup_cooked_tomato_0_onion_2.png differ diff --git a/resources/overcooked/soups/soup_cooked_tomato_0_onion_3.png b/resources/overcooked/soups/soup_cooked_tomato_0_onion_3.png new file mode 100644 index 0000000000..1f098a222a Binary files /dev/null and b/resources/overcooked/soups/soup_cooked_tomato_0_onion_3.png differ diff --git a/resources/overcooked/soups/soup_cooked_tomato_1_onion_0.png b/resources/overcooked/soups/soup_cooked_tomato_1_onion_0.png new file mode 100644 index 0000000000..624efb6f69 Binary files /dev/null and b/resources/overcooked/soups/soup_cooked_tomato_1_onion_0.png differ diff --git a/resources/overcooked/soups/soup_cooked_tomato_1_onion_1.png b/resources/overcooked/soups/soup_cooked_tomato_1_onion_1.png new file mode 100644 index 0000000000..540f45f5b2 Binary files /dev/null and b/resources/overcooked/soups/soup_cooked_tomato_1_onion_1.png differ diff --git a/resources/overcooked/soups/soup_cooked_tomato_1_onion_2.png b/resources/overcooked/soups/soup_cooked_tomato_1_onion_2.png new file mode 100644 index 0000000000..1efb46a48f Binary files /dev/null and b/resources/overcooked/soups/soup_cooked_tomato_1_onion_2.png differ diff --git a/resources/overcooked/soups/soup_cooked_tomato_2_onion_0.png b/resources/overcooked/soups/soup_cooked_tomato_2_onion_0.png new file mode 100644 index 0000000000..eb20c2d5ba Binary files /dev/null and b/resources/overcooked/soups/soup_cooked_tomato_2_onion_0.png differ diff --git a/resources/overcooked/soups/soup_cooked_tomato_2_onion_1.png b/resources/overcooked/soups/soup_cooked_tomato_2_onion_1.png new file mode 100644 index 0000000000..2e08737ff0 Binary files /dev/null and b/resources/overcooked/soups/soup_cooked_tomato_2_onion_1.png differ diff --git a/resources/overcooked/soups/soup_cooked_tomato_3_onion_0.png b/resources/overcooked/soups/soup_cooked_tomato_3_onion_0.png new file mode 100644 index 0000000000..001a69b9bc Binary files /dev/null and b/resources/overcooked/soups/soup_cooked_tomato_3_onion_0.png differ diff --git a/resources/overcooked/soups/soup_done_tomato_0_onion_1.png b/resources/overcooked/soups/soup_done_tomato_0_onion_1.png new file mode 100644 index 0000000000..d328ae7813 Binary files /dev/null and b/resources/overcooked/soups/soup_done_tomato_0_onion_1.png differ diff --git a/resources/overcooked/soups/soup_done_tomato_0_onion_2.png b/resources/overcooked/soups/soup_done_tomato_0_onion_2.png new file mode 100644 index 0000000000..80a75afb69 Binary files /dev/null and b/resources/overcooked/soups/soup_done_tomato_0_onion_2.png differ diff --git a/resources/overcooked/soups/soup_done_tomato_0_onion_3.png b/resources/overcooked/soups/soup_done_tomato_0_onion_3.png new file mode 100644 index 0000000000..ec8a96ea8c Binary files /dev/null and b/resources/overcooked/soups/soup_done_tomato_0_onion_3.png differ diff --git a/resources/overcooked/soups/soup_done_tomato_1_onion_0.png b/resources/overcooked/soups/soup_done_tomato_1_onion_0.png new file mode 100644 index 0000000000..26e89b1a71 Binary files /dev/null and b/resources/overcooked/soups/soup_done_tomato_1_onion_0.png differ diff --git a/resources/overcooked/soups/soup_done_tomato_1_onion_1.png b/resources/overcooked/soups/soup_done_tomato_1_onion_1.png new file mode 100644 index 0000000000..bad4b3e296 Binary files /dev/null and b/resources/overcooked/soups/soup_done_tomato_1_onion_1.png differ diff --git a/resources/overcooked/soups/soup_done_tomato_1_onion_2.png b/resources/overcooked/soups/soup_done_tomato_1_onion_2.png new file mode 100644 index 0000000000..e505229f23 Binary files /dev/null and b/resources/overcooked/soups/soup_done_tomato_1_onion_2.png differ diff --git a/resources/overcooked/soups/soup_done_tomato_2_onion_0.png b/resources/overcooked/soups/soup_done_tomato_2_onion_0.png new file mode 100644 index 0000000000..1eff0838f2 Binary files /dev/null and b/resources/overcooked/soups/soup_done_tomato_2_onion_0.png differ diff --git a/resources/overcooked/soups/soup_done_tomato_2_onion_1.png b/resources/overcooked/soups/soup_done_tomato_2_onion_1.png new file mode 100644 index 0000000000..af8a48814c Binary files /dev/null and b/resources/overcooked/soups/soup_done_tomato_2_onion_1.png differ diff --git a/resources/overcooked/soups/soup_done_tomato_3_onion_0.png b/resources/overcooked/soups/soup_done_tomato_3_onion_0.png new file mode 100644 index 0000000000..84f2293d1a Binary files /dev/null and b/resources/overcooked/soups/soup_done_tomato_3_onion_0.png differ diff --git a/resources/overcooked/soups/soup_idle_tomato_0_onion_1.png b/resources/overcooked/soups/soup_idle_tomato_0_onion_1.png new file mode 100644 index 0000000000..f1d5d3c1b8 Binary files /dev/null and b/resources/overcooked/soups/soup_idle_tomato_0_onion_1.png differ diff --git a/resources/overcooked/soups/soup_idle_tomato_0_onion_2.png b/resources/overcooked/soups/soup_idle_tomato_0_onion_2.png new file mode 100644 index 0000000000..f6fb62ee40 Binary files /dev/null and b/resources/overcooked/soups/soup_idle_tomato_0_onion_2.png differ diff --git a/resources/overcooked/soups/soup_idle_tomato_0_onion_3.png b/resources/overcooked/soups/soup_idle_tomato_0_onion_3.png new file mode 100644 index 0000000000..d5f45df474 Binary files /dev/null and b/resources/overcooked/soups/soup_idle_tomato_0_onion_3.png differ diff --git a/resources/overcooked/soups/soup_idle_tomato_1_onion_0.png b/resources/overcooked/soups/soup_idle_tomato_1_onion_0.png new file mode 100644 index 0000000000..2e09293be8 Binary files /dev/null and b/resources/overcooked/soups/soup_idle_tomato_1_onion_0.png differ diff --git a/resources/overcooked/soups/soup_idle_tomato_1_onion_1.png b/resources/overcooked/soups/soup_idle_tomato_1_onion_1.png new file mode 100644 index 0000000000..4f44298c77 Binary files /dev/null and b/resources/overcooked/soups/soup_idle_tomato_1_onion_1.png differ diff --git a/resources/overcooked/soups/soup_idle_tomato_1_onion_2.png b/resources/overcooked/soups/soup_idle_tomato_1_onion_2.png new file mode 100644 index 0000000000..60b2fa84d1 Binary files /dev/null and b/resources/overcooked/soups/soup_idle_tomato_1_onion_2.png differ diff --git a/resources/overcooked/soups/soup_idle_tomato_2_onion_0.png b/resources/overcooked/soups/soup_idle_tomato_2_onion_0.png new file mode 100644 index 0000000000..091f166ea0 Binary files /dev/null and b/resources/overcooked/soups/soup_idle_tomato_2_onion_0.png differ diff --git a/resources/overcooked/soups/soup_idle_tomato_2_onion_1.png b/resources/overcooked/soups/soup_idle_tomato_2_onion_1.png new file mode 100644 index 0000000000..f0df61f835 Binary files /dev/null and b/resources/overcooked/soups/soup_idle_tomato_2_onion_1.png differ diff --git a/resources/overcooked/soups/soup_idle_tomato_3_onion_0.png b/resources/overcooked/soups/soup_idle_tomato_3_onion_0.png new file mode 100644 index 0000000000..f8179877aa Binary files /dev/null and b/resources/overcooked/soups/soup_idle_tomato_3_onion_0.png differ diff --git a/resources/overcooked/terrain/counter.png b/resources/overcooked/terrain/counter.png new file mode 100644 index 0000000000..3da65f04ee Binary files /dev/null and b/resources/overcooked/terrain/counter.png differ diff --git a/resources/overcooked/terrain/dishes.png b/resources/overcooked/terrain/dishes.png new file mode 100644 index 0000000000..908d4f5a65 Binary files /dev/null and b/resources/overcooked/terrain/dishes.png differ diff --git a/resources/overcooked/terrain/floor.png b/resources/overcooked/terrain/floor.png new file mode 100644 index 0000000000..2b40ab1b98 Binary files /dev/null and b/resources/overcooked/terrain/floor.png differ diff --git a/resources/overcooked/terrain/onions.png b/resources/overcooked/terrain/onions.png new file mode 100644 index 0000000000..8e3147ebdb Binary files /dev/null and b/resources/overcooked/terrain/onions.png differ diff --git a/resources/overcooked/terrain/pot.png b/resources/overcooked/terrain/pot.png new file mode 100644 index 0000000000..2c6caac01a Binary files /dev/null and b/resources/overcooked/terrain/pot.png differ diff --git a/resources/overcooked/terrain/serve.png b/resources/overcooked/terrain/serve.png new file mode 100644 index 0000000000..0f83fe0ba3 Binary files /dev/null and b/resources/overcooked/terrain/serve.png differ diff --git a/resources/overcooked/terrain/tomatoes.png b/resources/overcooked/terrain/tomatoes.png new file mode 100644 index 0000000000..ff2ccf4704 Binary files /dev/null and b/resources/overcooked/terrain/tomatoes.png differ diff --git a/pufferlib/resources/pacman/blinky_down.png b/resources/pacman/blinky_down.png similarity index 100% rename from pufferlib/resources/pacman/blinky_down.png rename to resources/pacman/blinky_down.png diff --git a/pufferlib/resources/pacman/blinky_left.png b/resources/pacman/blinky_left.png similarity index 100% rename from pufferlib/resources/pacman/blinky_left.png rename to resources/pacman/blinky_left.png diff --git a/pufferlib/resources/pacman/blinky_right.png b/resources/pacman/blinky_right.png similarity index 100% rename from pufferlib/resources/pacman/blinky_right.png rename to resources/pacman/blinky_right.png diff --git a/pufferlib/resources/pacman/blinky_up.png b/resources/pacman/blinky_up.png similarity index 100% rename from pufferlib/resources/pacman/blinky_up.png rename to resources/pacman/blinky_up.png diff --git a/pufferlib/resources/pacman/clyde_down.png b/resources/pacman/clyde_down.png similarity index 100% rename from pufferlib/resources/pacman/clyde_down.png rename to resources/pacman/clyde_down.png diff --git a/pufferlib/resources/pacman/clyde_left.png b/resources/pacman/clyde_left.png similarity index 100% rename from pufferlib/resources/pacman/clyde_left.png rename to resources/pacman/clyde_left.png diff --git a/pufferlib/resources/pacman/clyde_right.png b/resources/pacman/clyde_right.png similarity index 100% rename from pufferlib/resources/pacman/clyde_right.png rename to resources/pacman/clyde_right.png diff --git a/pufferlib/resources/pacman/clyde_up.png b/resources/pacman/clyde_up.png similarity index 100% rename from pufferlib/resources/pacman/clyde_up.png rename to resources/pacman/clyde_up.png diff --git a/pufferlib/resources/pacman/eyes_down.png b/resources/pacman/eyes_down.png similarity index 100% rename from pufferlib/resources/pacman/eyes_down.png rename to resources/pacman/eyes_down.png diff --git a/pufferlib/resources/pacman/eyes_left.png b/resources/pacman/eyes_left.png similarity index 100% rename from pufferlib/resources/pacman/eyes_left.png rename to resources/pacman/eyes_left.png diff --git a/pufferlib/resources/pacman/eyes_right.png b/resources/pacman/eyes_right.png similarity index 100% rename from pufferlib/resources/pacman/eyes_right.png rename to resources/pacman/eyes_right.png diff --git a/pufferlib/resources/pacman/eyes_up.png b/resources/pacman/eyes_up.png similarity index 100% rename from pufferlib/resources/pacman/eyes_up.png rename to resources/pacman/eyes_up.png diff --git a/pufferlib/resources/pacman/inky_down.png b/resources/pacman/inky_down.png similarity index 100% rename from pufferlib/resources/pacman/inky_down.png rename to resources/pacman/inky_down.png diff --git a/pufferlib/resources/pacman/inky_left.png b/resources/pacman/inky_left.png similarity index 100% rename from pufferlib/resources/pacman/inky_left.png rename to resources/pacman/inky_left.png diff --git a/pufferlib/resources/pacman/inky_right.png b/resources/pacman/inky_right.png similarity index 100% rename from pufferlib/resources/pacman/inky_right.png rename to resources/pacman/inky_right.png diff --git a/pufferlib/resources/pacman/inky_up.png b/resources/pacman/inky_up.png similarity index 100% rename from pufferlib/resources/pacman/inky_up.png rename to resources/pacman/inky_up.png diff --git a/resources/pacman/pacman_weights.bin b/resources/pacman/pacman_weights.bin new file mode 100644 index 0000000000..a518701f74 Binary files /dev/null and b/resources/pacman/pacman_weights.bin differ diff --git a/pufferlib/resources/pacman/pinky_down.png b/resources/pacman/pinky_down.png similarity index 100% rename from pufferlib/resources/pacman/pinky_down.png rename to resources/pacman/pinky_down.png diff --git a/pufferlib/resources/pacman/pinky_left.png b/resources/pacman/pinky_left.png similarity index 100% rename from pufferlib/resources/pacman/pinky_left.png rename to resources/pacman/pinky_left.png diff --git a/pufferlib/resources/pacman/pinky_right.png b/resources/pacman/pinky_right.png similarity index 100% rename from pufferlib/resources/pacman/pinky_right.png rename to resources/pacman/pinky_right.png diff --git a/pufferlib/resources/pacman/pinky_up.png b/resources/pacman/pinky_up.png similarity index 100% rename from pufferlib/resources/pacman/pinky_up.png rename to resources/pacman/pinky_up.png diff --git a/pufferlib/resources/pacman/scared.png b/resources/pacman/scared.png similarity index 100% rename from pufferlib/resources/pacman/scared.png rename to resources/pacman/scared.png diff --git a/pufferlib/resources/pacman/tileset.png b/resources/pacman/tileset.png similarity index 100% rename from pufferlib/resources/pacman/tileset.png rename to resources/pacman/tileset.png diff --git a/resources/pong/pong_weights.bin b/resources/pong/pong_weights.bin new file mode 100644 index 0000000000..ca59b38c79 Binary files /dev/null and b/resources/pong/pong_weights.bin differ diff --git a/pufferlib/resources/robocode/robocode.png b/resources/robocode/robocode.png similarity index 100% rename from pufferlib/resources/robocode/robocode.png rename to resources/robocode/robocode.png diff --git a/pufferlib/resources/rware/rware_weights.bin b/resources/rware/rware_weights.bin similarity index 100% rename from pufferlib/resources/rware/rware_weights.bin rename to resources/rware/rware_weights.bin diff --git a/resources/shared/JetBrainsMono-Bold.ttf b/resources/shared/JetBrainsMono-Bold.ttf new file mode 100644 index 0000000000..1926c804b9 Binary files /dev/null and b/resources/shared/JetBrainsMono-Bold.ttf differ diff --git a/resources/shared/JetBrainsMono-Medium.ttf b/resources/shared/JetBrainsMono-Medium.ttf new file mode 100644 index 0000000000..ad71d92bb1 Binary files /dev/null and b/resources/shared/JetBrainsMono-Medium.ttf differ diff --git a/resources/shared/JetBrainsMono-Regular.ttf b/resources/shared/JetBrainsMono-Regular.ttf new file mode 100644 index 0000000000..436c982ff3 Binary files /dev/null and b/resources/shared/JetBrainsMono-Regular.ttf differ diff --git a/resources/shared/JetBrainsMono-SemiBold.ttf b/resources/shared/JetBrainsMono-SemiBold.ttf new file mode 100644 index 0000000000..b00a648578 Binary files /dev/null and b/resources/shared/JetBrainsMono-SemiBold.ttf differ diff --git a/resources/shared/Montserrat-Regular.ttf b/resources/shared/Montserrat-Regular.ttf new file mode 100644 index 0000000000..895e220a17 Binary files /dev/null and b/resources/shared/Montserrat-Regular.ttf differ diff --git a/resources/shared/Roboto-Italic.ttf b/resources/shared/Roboto-Italic.ttf new file mode 100644 index 0000000000..c3abaefb28 Binary files /dev/null and b/resources/shared/Roboto-Italic.ttf differ diff --git a/resources/shared/Roboto-Regular.ttf b/resources/shared/Roboto-Regular.ttf new file mode 100644 index 0000000000..7e3bb2f8ce Binary files /dev/null and b/resources/shared/Roboto-Regular.ttf differ diff --git a/pufferlib/resources/shared/puffer.glb b/resources/shared/puffer.glb similarity index 100% rename from pufferlib/resources/shared/puffer.glb rename to resources/shared/puffer.glb diff --git a/pufferlib/resources/shared/puffers.png b/resources/shared/puffers.png similarity index 100% rename from pufferlib/resources/shared/puffers.png rename to resources/shared/puffers.png diff --git a/pufferlib/resources/shared/puffers_128.png b/resources/shared/puffers_128.png similarity index 100% rename from pufferlib/resources/shared/puffers_128.png rename to resources/shared/puffers_128.png diff --git a/resources/slimevolley/slimevolley_weights.bin b/resources/slimevolley/slimevolley_weights.bin new file mode 100644 index 0000000000..0b81218655 Binary files /dev/null and b/resources/slimevolley/slimevolley_weights.bin differ diff --git a/pufferlib/resources/snake/snake_weights.bin b/resources/snake/snake_weights.bin similarity index 100% rename from pufferlib/resources/snake/snake_weights.bin rename to resources/snake/snake_weights.bin diff --git a/pufferlib/resources/terraform/dozer.glb b/resources/terraform/dozer.glb similarity index 100% rename from pufferlib/resources/terraform/dozer.glb rename to resources/terraform/dozer.glb diff --git a/pufferlib/resources/terraform/perlin.jpg b/resources/terraform/perlin.jpg similarity index 100% rename from pufferlib/resources/terraform/perlin.jpg rename to resources/terraform/perlin.jpg diff --git a/pufferlib/resources/terraform/shader_100.fs b/resources/terraform/shader_100.fs similarity index 100% rename from pufferlib/resources/terraform/shader_100.fs rename to resources/terraform/shader_100.fs diff --git a/pufferlib/resources/terraform/shader_100.vs b/resources/terraform/shader_100.vs similarity index 100% rename from pufferlib/resources/terraform/shader_100.vs rename to resources/terraform/shader_100.vs diff --git a/pufferlib/resources/terraform/shader_330.fs b/resources/terraform/shader_330.fs similarity index 100% rename from pufferlib/resources/terraform/shader_330.fs rename to resources/terraform/shader_330.fs diff --git a/pufferlib/resources/terraform/shader_330.vs b/resources/terraform/shader_330.vs similarity index 100% rename from pufferlib/resources/terraform/shader_330.vs rename to resources/terraform/shader_330.vs diff --git a/pufferlib/resources/terraform/target_shader_100.fs b/resources/terraform/target_shader_100.fs similarity index 100% rename from pufferlib/resources/terraform/target_shader_100.fs rename to resources/terraform/target_shader_100.fs diff --git a/pufferlib/resources/terraform/target_shader_330.fs b/resources/terraform/target_shader_330.fs similarity index 100% rename from pufferlib/resources/terraform/target_shader_330.fs rename to resources/terraform/target_shader_330.fs diff --git a/pufferlib/resources/terraform/target_shader_330.vs b/resources/terraform/target_shader_330.vs similarity index 100% rename from pufferlib/resources/terraform/target_shader_330.vs rename to resources/terraform/target_shader_330.vs diff --git a/resources/terraform/terraform_weights.bin b/resources/terraform/terraform_weights.bin new file mode 100644 index 0000000000..284b8ee7c8 Binary files /dev/null and b/resources/terraform/terraform_weights.bin differ diff --git a/resources/tetris/tetris_weights.bin b/resources/tetris/tetris_weights.bin new file mode 100644 index 0000000000..9888a21f9f Binary files /dev/null and b/resources/tetris/tetris_weights.bin differ diff --git a/resources/tower_climb/maps.bin b/resources/tower_climb/maps.bin new file mode 100644 index 0000000000..acbf5c42e0 Binary files /dev/null and b/resources/tower_climb/maps.bin differ diff --git a/pufferlib/resources/tower_climb/shaders/gls100/lighting.fs b/resources/tower_climb/shaders/gls100/lighting.fs similarity index 100% rename from pufferlib/resources/tower_climb/shaders/gls100/lighting.fs rename to resources/tower_climb/shaders/gls100/lighting.fs diff --git a/pufferlib/resources/tower_climb/shaders/gls100/lighting.vs b/resources/tower_climb/shaders/gls100/lighting.vs similarity index 100% rename from pufferlib/resources/tower_climb/shaders/gls100/lighting.vs rename to resources/tower_climb/shaders/gls100/lighting.vs diff --git a/pufferlib/resources/tower_climb/shaders/gls330/lighting.fs b/resources/tower_climb/shaders/gls330/lighting.fs similarity index 100% rename from pufferlib/resources/tower_climb/shaders/gls330/lighting.fs rename to resources/tower_climb/shaders/gls330/lighting.fs diff --git a/pufferlib/resources/tower_climb/shaders/gls330/lighting.vs b/resources/tower_climb/shaders/gls330/lighting.vs similarity index 100% rename from pufferlib/resources/tower_climb/shaders/gls330/lighting.vs rename to resources/tower_climb/shaders/gls330/lighting.vs diff --git a/pufferlib/resources/tower_climb/small_astro.glb b/resources/tower_climb/small_astro.glb similarity index 100% rename from pufferlib/resources/tower_climb/small_astro.glb rename to resources/tower_climb/small_astro.glb diff --git a/pufferlib/resources/tower_climb/space2.jpg b/resources/tower_climb/space2.jpg similarity index 100% rename from pufferlib/resources/tower_climb/space2.jpg rename to resources/tower_climb/space2.jpg diff --git a/pufferlib/resources/tower_climb/spacerock.glb b/resources/tower_climb/spacerock.glb similarity index 100% rename from pufferlib/resources/tower_climb/spacerock.glb rename to resources/tower_climb/spacerock.glb diff --git a/resources/tower_climb/tower_climb_weights.bin b/resources/tower_climb/tower_climb_weights.bin new file mode 100644 index 0000000000..758c37c629 Binary files /dev/null and b/resources/tower_climb/tower_climb_weights.bin differ diff --git a/resources/trailer/PufferNet.png b/resources/trailer/PufferNet.png new file mode 100644 index 0000000000..2b5edc1c92 Binary files /dev/null and b/resources/trailer/PufferNet.png differ diff --git a/resources/trailer/glow_330.fs b/resources/trailer/glow_330.fs new file mode 100644 index 0000000000..ad439f55ca --- /dev/null +++ b/resources/trailer/glow_330.fs @@ -0,0 +1,41 @@ +#version 330 + +in vec2 fragTexCoord; +out vec4 finalColor; + +uniform sampler2D texture0; +uniform vec2 texelSize; // 1.0 / vec2(textureWidth, textureHeight) +uniform float glowStrength; // driven by cos in time +uniform float fadeAlpha; // 0..1 fade-in multiplier + +void main() +{ + vec2 uv = fragTexCoord; + float c = texture(texture0, uv).a; + + // Solid pixels stay fully opaque — no shader math needed + if (c > 0.5) { + vec3 color = vec3(0.6, 0.95, 0.95); + finalColor = vec4(color * fadeAlpha, fadeAlpha); + return; + } + + // Find the distance to the nearest solid pixel, then apply a smooth + // exponential falloff on that distance. This gives a proper gradient + // rather than a flat accumulated plateau. + float min_dist = 32.0; + int R = 32; + for (int dx = -R; dx <= R; dx++) { + for (int dy = -R; dy <= R; dy++) { + float s = texture(texture0, uv + texelSize * vec2(dx, dy)).a; + if (s > 0.5) { + min_dist = min(min_dist, length(vec2(dx, dy))); + } + } + } + + float glow = exp(-0.12 * min_dist); // bright at d=1, fades over ~20px + float halo = glow * (0.4 + glowStrength * 0.6) * fadeAlpha; + vec3 color = vec3(0.6, 0.95, 0.95); + finalColor = vec4(color * halo, halo); +} diff --git a/resources/trailer/glow_330.vs b/resources/trailer/glow_330.vs new file mode 100644 index 0000000000..83eca2ae69 --- /dev/null +++ b/resources/trailer/glow_330.vs @@ -0,0 +1,14 @@ +#version 330 + +in vec3 vertexPosition; +in vec2 vertexTexCoord; + +uniform mat4 mvp; + +out vec2 fragTexCoord; + +void main() +{ + fragTexCoord = vertexTexCoord; + gl_Position = mvp * vec4(vertexPosition, 1.0); +} diff --git a/resources/trailer/star_330.fs b/resources/trailer/star_330.fs new file mode 100644 index 0000000000..fb56f491af --- /dev/null +++ b/resources/trailer/star_330.fs @@ -0,0 +1,33 @@ +#version 330 + +in vec4 fragColor; +out vec4 finalColor; + +void main() +{ + vec2 uv = gl_PointCoord - vec2(0.5); + float r = length(uv); + float angle = atan(uv.y, uv.x); + + // Multi-lobe Gaussian core (tight + medium + wide) + float core = exp(-120.0 * r * r); + float mid = exp(- 30.0 * r * r) * 0.5; + float corona = exp(- 3.5 * r * r) * 0.35; + + // Diffraction spikes: 4-point cross, sharp along axes + // pow(abs(cos(angle*2)), p) peaks at 0, 90, 180, 270 degrees + float spike_mask = pow(abs(cos(angle * 2.0)), 24.0); + float spike = spike_mask * exp(-18.0 * r * r) * exp(-r * 4.0) * 1.2; + + float brightness = core + mid + corona + spike; + + if (brightness < 0.01) + discard; + + // Slight chromatic shift on spikes/corona toward cool blue + vec3 color = fragColor.rgb * brightness; + color += vec3(0.0, 0.05, 0.15) * spike; + color += vec3(0.0, 0.02, 0.08) * corona; + + finalColor = vec4(color, clamp(brightness, 0.0, 1.0)); +} diff --git a/resources/trailer/star_330.vs b/resources/trailer/star_330.vs new file mode 100644 index 0000000000..9c53d2d8e1 --- /dev/null +++ b/resources/trailer/star_330.vs @@ -0,0 +1,31 @@ +#version 330 + +in vec3 vertexPosition; +in vec4 vertexColor; + +uniform mat4 mvp; +uniform float currentTime; + +out vec4 fragColor; + +float twinkle(float seed, float t) { + // Stable per-star seed passed via vertexColor.a from CPU + float phase = mod(seed * 137.5, 360.0); + float frequency = 1.2 + mod(seed * 0.317, 3.0) * 0.9; + float amplitude = 7.0; + float base_size = 20.0; + float size_variation = amplitude * sin(frequency * t + radians(phase)); + return max(1.0, base_size + size_variation); +} + +void main() +{ + vec2 pos = vertexPosition.xy; + float size_scale = vertexPosition.z; + float seed = vertexColor.a; // stable per-star identity, not alpha + + gl_Position = mvp * vec4(pos, 0.0, 1.0); + gl_PointSize = twinkle(seed, currentTime) * size_scale; + + fragColor = vertexColor; +} diff --git a/resources/trash_pickup/trash_pickup_weights.bin b/resources/trash_pickup/trash_pickup_weights.bin new file mode 100644 index 0000000000..c957874023 Binary files /dev/null and b/resources/trash_pickup/trash_pickup_weights.bin differ diff --git a/resources/tripletriad/tripletriad_weights.bin b/resources/tripletriad/tripletriad_weights.bin new file mode 100644 index 0000000000..c1da62fcc7 Binary files /dev/null and b/resources/tripletriad/tripletriad_weights.bin differ diff --git a/pufferlib/resources/whisker_racer/puffer_whisker_racer_weights.bin b/resources/whisker_racer/puffer_whisker_racer_weights.bin similarity index 100% rename from pufferlib/resources/whisker_racer/puffer_whisker_racer_weights.bin rename to resources/whisker_racer/puffer_whisker_racer_weights.bin diff --git a/scripts/build_ocean.sh b/scripts/build_ocean.sh deleted file mode 100755 index 88909d44f3..0000000000 --- a/scripts/build_ocean.sh +++ /dev/null @@ -1,109 +0,0 @@ -#!/bin/bash - -# Usage: ./build_env.sh pong [local|fast|web] - -ENV=$1 -MODE=${2:-local} -PLATFORM="$(uname -s)" -SRC_DIR="pufferlib/ocean/$ENV" -WEB_OUTPUT_DIR="build_web/$ENV" -RAYLIB_NAME='raylib-5.5_macos' -BOX2D_NAME='box2d-macos-arm64' -if [ "$PLATFORM" = "Linux" ]; then - RAYLIB_NAME='raylib-5.5_linux_amd64' - BOX2D_NAME='box2d-linux-amd64' -fi -if [ "$MODE" = "web" ]; then - RAYLIB_NAME='raylib-5.5_webassembly' - BOX2D_NAME='box2d-web' -fi - -LINK_ARCHIVES="./$RAYLIB_NAME/lib/libraylib.a" -if [ "$ENV" = "impulse_wars" ]; then - LINK_ARCHIVES="$LINK_ARCHIVES ./$BOX2D_NAME/libbox2d.a" -fi - -# Create build output directory -mkdir -p "$WEB_OUTPUT_DIR" - -if [ "$MODE" = "web" ]; then - echo "Building $ENV for web deployment..." - emcc \ - -o "$WEB_OUTPUT_DIR/game.html" \ - "$SRC_DIR/$ENV.c" \ - -O3 \ - -Wall \ - $LINK_ARCHIVES \ - -I./$RAYLIB_NAME/include \ - -I./$BOX2D_NAME/include \ - -I./$BOX2D_NAME/src \ - -I./pufferlib/extensions \ - -I./pufferlib \ - -L. \ - -L./$RAYLIB_NAME/lib \ - -sASSERTIONS=2 \ - -gsource-map \ - -s USE_GLFW=3 \ - -s USE_WEBGL2=1 \ - -s ASYNCIFY \ - -sFILESYSTEM \ - -s FORCE_FILESYSTEM=1 \ - --shell-file ./scripts/minshell.html \ - -sINITIAL_MEMORY=512MB \ - -sALLOW_MEMORY_GROWTH \ - -sSTACK_SIZE=512KB \ - -DNDEBUG \ - -DPLATFORM_WEB \ - -DGRAPHICS_API_OPENGL_ES3 \ - --preload-file pufferlib/resources/$1@resources/$1 \ - --preload-file pufferlib/resources/shared@resources/shared - echo "Web build completed: $WEB_OUTPUT_DIR/game.html" - echo "Preloaded files:" - echo " pufferlib/resources/$1@resources$1" - echo " pufferlib/resources/shared@resources/shared" - exit 0 -fi - -FLAGS=( - -Wall - -I./$RAYLIB_NAME/include - -I./$BOX2D_NAME/include - -I./$BOX2D_NAME/src - -I./pufferlib/extensions - "$SRC_DIR/$ENV.c" -o "$ENV" - $LINK_ARCHIVES - -lm - -lpthread - -ferror-limit=3 - -DPLATFORM_DESKTOP -) - - -if [ "$PLATFORM" = "Darwin" ]; then - FLAGS+=( - -framework Cocoa - -framework IOKit - -framework CoreVideo - ) -fi - -echo ${FLAGS[@]} - -if [ "$MODE" = "local" ]; then - echo "Building $ENV for local testing..." - if [ "$PLATFORM" = "Linux" ]; then - # These important debug flags don't work on macos - FLAGS+=( - -fsanitize=address,undefined,bounds,pointer-overflow,leak - -fno-omit-frame-pointer - ) - fi - clang -g -O0 ${FLAGS[@]} -elif [ "$MODE" = "fast" ]; then - echo "Building optimized $ENV for local testing..." - clang -pg -O2 -DNDEBUG ${FLAGS[@]} - echo "Built to: $ENV" -else - echo "Invalid mode specified: local|fast|web" - exit 1 -fi diff --git a/scripts/build_simple.sh b/scripts/build_simple.sh deleted file mode 100644 index 8d07113703..0000000000 --- a/scripts/build_simple.sh +++ /dev/null @@ -1,47 +0,0 @@ -#!/bin/bash - -# Usage: ./build.sh your_file.c [debug|release] - -SOURCE=$1 -MODE=${2:-debug} -PLATFORM="$(uname -s)" - -# Extract filename without extension -FILENAME=$(basename -- "$SOURCE") -FILENAME="${FILENAME%.*}" - -FLAGS=( - -Wall - "$SOURCE" -o "$FILENAME" - -lm - -lpthread -) - -if [ "$PLATFORM" = "Darwin" ]; then - FLAGS+=( - -framework Cocoa - -framework IOKit - -framework CoreVideo - ) -fi - -echo "Compiling with: ${FLAGS[@]}" - -if [ "$MODE" = "debug" ]; then - echo "Building $SOURCE in debug mode..." - if [ "$PLATFORM" = "Linux" ]; then - # These important debug flags don't work on macos - FLAGS+=( - -fsanitize=address,undefined,bounds,pointer-overflow,leak -g - ) - fi - clang -g -O0 ${FLAGS[@]} - echo "Built to: $FILENAME (debug mode)" -elif [ "$MODE" = "release" ]; then - echo "Building optimized $SOURCE..." - clang -O2 ${FLAGS[@]} - echo "Built to: $FILENAME (release mode)" -else - echo "Invalid mode specified: debug|release" - exit 1 -fi \ No newline at end of file diff --git a/scripts/sweep_atari.sh b/scripts/sweep_atari.sh deleted file mode 100755 index 7bb90cb161..0000000000 --- a/scripts/sweep_atari.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash - -environments=( - "pong" - "breakout" - "beam_rider" - "enduro" - "qbert" - "space_invaders" - "seaquest" -) - -for env in "${environments[@]}"; do - echo "Training: $env" - python demo.py --mode sweep-carbs --vec multiprocessing --env "$env" -done diff --git a/scripts/train_atari.sh b/scripts/train_atari.sh deleted file mode 100755 index d089665c85..0000000000 --- a/scripts/train_atari.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash - -environments=( - "pong" - "breakout" - "beam_rider" - "enduro" - "qbert" - "space_invaders" - "seaquest" -) - -for env in "${environments[@]}"; do - echo "Training: $env" - python demo.py --mode train --vec multiprocessing --track --env "$env" -done diff --git a/scripts/train_ocean.sh b/scripts/train_ocean.sh deleted file mode 100755 index 797f079bca..0000000000 --- a/scripts/train_ocean.sh +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/bash - -environments=( - "puffer_breakout" - "puffer_connect4" - "puffer_pong" - "puffer_snake" - "puffer_tripletriad" - "puffer_rware" - "puffer_go" - "puffer_tactics" - "puffer_moba" - "puffer_whisker_racer" -) - -for env in "${environments[@]}"; do - echo "Training: $env" - python demo.py --mode train --vec multiprocessing --track --env "$env" -done diff --git a/scripts/train_procgen.sh b/scripts/train_procgen.sh deleted file mode 100755 index 80118b1037..0000000000 --- a/scripts/train_procgen.sh +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/bash - -environments=( - "bigfish" - "bossfight" - "caveflyer" - "chaser" - "climber" - "coinrun" - "dodgeball" - "fruitbot" - "heist" - "jumper" - "leaper" - "maze" - "miner" - "ninja" - "plunder" - "starpilot" -) - -for env in "${environments[@]}"; do - echo "Training on environment: $env" - python demo.py --mode train --vec multiprocessing --track --env "$env" -done diff --git a/scripts/train_sanity.sh b/scripts/train_sanity.sh deleted file mode 100755 index ec01a39393..0000000000 --- a/scripts/train_sanity.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash - -environments=( - "puffer_squared" - "puffer_password" - "puffer_stochastic" - "puffer_memory" - "puffer_multiagent" - "puffer_spaces" - "puffer_bandit" -) - -for env in "${environments[@]}"; do - echo "Training: $env" - python demo.py --mode train --vec multiprocessing --track --env "$env" -done diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index 57fb1d9ee1..0000000000 --- a/setup.cfg +++ /dev/null @@ -1,3 +0,0 @@ -[build_ext] -inplace=true -force=true diff --git a/setup.py b/setup.py deleted file mode 100644 index 8a8444dd61..0000000000 --- a/setup.py +++ /dev/null @@ -1,308 +0,0 @@ -# Debug command: -# DEBUG=1 python setup.py build_ext --inplace --force -# CUDA_VISIBLE_DEVICES=None LD_PRELOAD=$(gcc -print-file-name=libasan.so) python3.12 -m pufferlib.clean_pufferl eval --train.device cpu - -from setuptools import find_packages, find_namespace_packages, setup, Extension -import numpy -import os -import glob -import urllib.request -import zipfile -import tarfile -import platform -import shutil - -from setuptools.command.build_ext import build_ext -from torch.utils import cpp_extension -from torch.utils.cpp_extension import ( - CppExtension, - CUDAExtension, - BuildExtension, - CUDA_HOME, - ROCM_HOME -) - -# build cuda extension if torch can find CUDA or HIP/ROCM in the system -# may require `uv pip install --no-build-isolation` or `python setup.py build_ext --inplace` -BUID_CUDA_EXT = bool(CUDA_HOME or ROCM_HOME) - -# Build with DEBUG=1 to enable debug symbols -DEBUG = os.getenv("DEBUG", "0") == "1" -NO_OCEAN = os.getenv("NO_OCEAN", "0") == "1" -NO_TRAIN = os.getenv("NO_TRAIN", "0") == "1" - -# Build raylib for your platform -RAYLIB_URL = 'https://github.com/raysan5/raylib/releases/download/5.5/' -RAYLIB_NAME = 'raylib-5.5_macos' if platform.system() == "Darwin" else 'raylib-5.5_linux_amd64' -RLIGHTS_URL = 'https://raw.githubusercontent.com/raysan5/raylib/refs/heads/master/examples/shaders/rlights.h' - -def download_raylib(platform, ext): - if not os.path.exists(platform): - print(f'Downloading Raylib {platform}') - urllib.request.urlretrieve(RAYLIB_URL + platform + ext, platform + ext) - if ext == '.zip': - with zipfile.ZipFile(platform + ext, 'r') as zip_ref: - zip_ref.extractall() - else: - with tarfile.open(platform + ext, 'r') as tar_ref: - tar_ref.extractall() - - os.remove(platform + ext) - urllib.request.urlretrieve(RLIGHTS_URL, platform + '/include/rlights.h') - -if not NO_OCEAN: - download_raylib('raylib-5.5_webassembly', '.zip') - download_raylib(RAYLIB_NAME, '.tar.gz') - -BOX2D_URL = 'https://github.com/capnspacehook/box2d/releases/latest/download/' -BOX2D_NAME = 'box2d-macos-arm64' if platform.system() == "Darwin" else 'box2d-linux-amd64' - -def download_box2d(platform): - if not os.path.exists(platform): - ext = ".tar.gz" - - print(f'Downloading Box2D {platform}') - urllib.request.urlretrieve(BOX2D_URL + platform + ext, platform + ext) - with tarfile.open(platform + ext, 'r') as tar_ref: - tar_ref.extractall() - - os.remove(platform + ext) - -if not NO_OCEAN: - download_box2d('box2d-web') - download_box2d(BOX2D_NAME) - -# Shared compile args for all platforms -extra_compile_args = [ - '-DNPY_NO_DEPRECATED_API=NPY_1_7_API_VERSION', - '-DPLATFORM_DESKTOP', -] -extra_link_args = [ - '-fwrapv' -] -cxx_args = [ - '-fdiagnostics-color=always', -] -nvcc_args = [] - -if DEBUG: - extra_compile_args += [ - '-O0', - '-g', - '-fsanitize=address,undefined,bounds,pointer-overflow,leak', - '-fno-omit-frame-pointer', - ] - extra_link_args += [ - '-g', - '-fsanitize=address,undefined,bounds,pointer-overflow,leak', - ] - cxx_args += [ - '-O0', - '-g', - ] - nvcc_args += [ - '-O0', - '-g', - ] -else: - extra_compile_args += [ - '-O2', - '-flto', - ] - extra_link_args += [ - '-O2', - ] - cxx_args += [ - '-O3', - ] - nvcc_args += [ - '-O3', - ] - -system = platform.system() -if system == 'Linux': - extra_compile_args += [ - '-Wno-alloc-size-larger-than', - '-Wno-implicit-function-declaration', - '-fmax-errors=3', - ] - extra_link_args += [ - '-Bsymbolic-functions', - ] -elif system == 'Darwin': - extra_compile_args += [ - '-Wno-error=int-conversion', - '-Wno-error=incompatible-function-pointer-types', - '-Wno-error=implicit-function-declaration', - ] - extra_link_args += [ - '-framework', 'Cocoa', - '-framework', 'OpenGL', - '-framework', 'IOKit', - ] -else: - raise ValueError(f'Unsupported system: {system}') - -# Default Gym/Gymnasium/PettingZoo versions -# Gym: -# - 0.26 still has deprecation warnings and is the last version of the package -# - 0.25 adds a breaking API change to reset, step, and render_modes -# - 0.24 is broken -# - 0.22-0.23 triggers deprecation warnings by calling its own functions -# - 0.21 is the most stable version -# - <= 0.20 is missing dict methods for gym.spaces.Dict -# - 0.18-0.21 require setuptools<=65.5.0 - -# Extensions -class BuildExt(build_ext): - def run(self): - # Propagate any build_ext options (e.g., --inplace, --force) to subcommands - build_ext_opts = self.distribution.command_options.get('build_ext', {}) - if build_ext_opts: - # Copy flags so build_torch and build_c respect inplace/force - self.distribution.command_options['build_torch'] = build_ext_opts.copy() - self.distribution.command_options['build_c'] = build_ext_opts.copy() - - # Run the torch and C builds (which will handle copying when inplace is set) - self.run_command('build_torch') - self.run_command('build_c') - -class CBuildExt(build_ext): - def run(self, *args, **kwargs): - self.extensions = [e for e in self.extensions if e.name != "pufferlib._C"] - super().run(*args, **kwargs) - -class TorchBuildExt(cpp_extension.BuildExtension): - def run(self): - self.extensions = [e for e in self.extensions if e.name == "pufferlib._C"] - super().run() - -INCLUDE = [f'{BOX2D_NAME}/include', f'{BOX2D_NAME}/src'] -RAYLIB_A = f'{RAYLIB_NAME}/lib/libraylib.a' -extension_kwargs = dict( - include_dirs=INCLUDE, - extra_compile_args=extra_compile_args, - extra_link_args=extra_link_args, - extra_objects=[RAYLIB_A], -) - -# Find C extensions -c_extensions = [] -if not NO_OCEAN: - c_extension_paths = glob.glob('pufferlib/ocean/**/binding.c', recursive=True) - c_extensions = [ - Extension( - path.rstrip('.c').replace('/', '.'), - sources=[path], - **extension_kwargs, - ) - for path in c_extension_paths if 'matsci' not in path - ] - c_extension_paths = [os.path.join(*path.split('/')[:-1]) for path in c_extension_paths] - - for c_ext in c_extensions: - if "impulse_wars" in c_ext.name: - print(f"Adding {c_ext.name} to extra objects") - c_ext.extra_objects.append(f'{BOX2D_NAME}/libbox2d.a') - # TODO: Figure out why this is necessary for some users - impulse_include = 'pufferlib/ocean/impulse_wars/include' - if impulse_include not in c_ext.include_dirs: - c_ext.include_dirs.append(impulse_include) - - if 'matsci' in c_ext.name: - c_ext.include_dirs.append('/usr/local/include') - c_ext.extra_link_args.extend(['-L/usr/local/lib', '-llammps']) - -# Define cmdclass outside of setup to add dynamic commands -cmdclass = { - "build_ext": BuildExt, - "build_torch": TorchBuildExt, - "build_c": CBuildExt, -} - -if not NO_OCEAN: - def create_env_build_class(full_name): - class EnvBuildExt(build_ext): - def run(self): - self.extensions = [e for e in self.extensions if e.name == full_name] - super().run() - return EnvBuildExt - - # Add a build_ command for each env - for c_ext in c_extensions: - env_name = c_ext.name.split('.')[-2] - cmdclass[f"build_{env_name}"] = create_env_build_class(c_ext.name) - - -# Check if CUDA compiler is available. You need cuda dev, not just runtime. -torch_extensions = [] -if not NO_TRAIN: - torch_sources = [ - "pufferlib/extensions/pufferlib.cpp", - ] - if BUID_CUDA_EXT: - extension = CUDAExtension - torch_sources.append("pufferlib/extensions/cuda/pufferlib.cu") - else: - extension = CppExtension - - torch_extensions = [ - extension( - "pufferlib._C", - torch_sources, - extra_compile_args = { - "cxx": cxx_args, - "nvcc": nvcc_args, - } - ), - ] - -# Prevent Conda from injecting garbage compile flags -from distutils.sysconfig import get_config_vars -cfg_vars = get_config_vars() -for key in ('CC', 'CXX', 'LDSHARED'): - if cfg_vars[key]: - cfg_vars[key] = cfg_vars[key].replace('-B /root/anaconda3/compiler_compat', '') - cfg_vars[key] = cfg_vars[key].replace('-pthread', '') - cfg_vars[key] = cfg_vars[key].replace('-fno-strict-overflow', '') - -for key, value in cfg_vars.items(): - if value and '-fno-strict-overflow' in str(value): - cfg_vars[key] = value.replace('-fno-strict-overflow', '') - -install_requires = [ - 'setuptools', - 'numpy<2.0', - 'shimmy[gym-v21]', - 'gym==0.23', - 'gymnasium>=0.29.1', - 'pettingzoo>=1.24.1', -] - -if not NO_TRAIN: - install_requires += [ - 'torch', - 'psutil', - 'nvidia-ml-py', - 'rich', - 'rich_argparse', - 'imageio', - 'gpytorch', - 'scikit-learn', - 'heavyball>=2.2.0', # contains relevant fixes compared to 1.7.2 and 2.1.1 - 'neptune', - 'wandb', - ] - -setup( - version="3.0.0", - packages=find_namespace_packages() + find_packages() + c_extension_paths + ['pufferlib/extensions'], - package_data={ - "pufferlib": [RAYLIB_NAME + '/lib/libraylib.a'] - }, - include_package_data=True, - install_requires=install_requires, - ext_modules = c_extensions + torch_extensions, - cmdclass=cmdclass, - include_dirs=[numpy.get_include(), RAYLIB_NAME + '/include'], -) diff --git a/src/bindings.cu b/src/bindings.cu new file mode 100644 index 0000000000..4469cb512c --- /dev/null +++ b/src/bindings.cu @@ -0,0 +1,570 @@ +// bindings.cpp - Python bindings for pufferlib (torch-free) + +#include +#include +#include "pufferlib.cu" + +#define _PUFFER_STRINGIFY(x) #x +#define PUFFER_STRINGIFY(x) _PUFFER_STRINGIFY(x) + +namespace py = pybind11; + +// Wrapper functions for Python bindings +pybind11::dict puf_log(pybind11::object pufferl_obj) { + auto& pufferl = pufferl_obj.cast(); + pybind11::dict result; + + // Summary + int gpus = pufferl.hypers.world_size; + long global_step = pufferl.global_step; + long epoch = pufferl.epoch; + double now = wall_clock(); + double dt = now - pufferl.last_log_time; + long sps = dt > 0 ? (long)((global_step - pufferl.last_log_step) / dt) : 0; + pufferl.last_log_time = now; + pufferl.last_log_step = global_step; + + result["SPS"] = sps * gpus; + result["agent_steps"] = global_step * gpus; + result["uptime"] = now - pufferl.start_time; + result["epoch"] = epoch; + + // Environment stats + pybind11::dict env_dict; + Dict* env_out = log_environments_impl(pufferl); + for (int i = 0; i < env_out->size; i++) { + env_dict[env_out->items[i].key] = env_out->items[i].value; + } + result["env"] = env_dict; + + // Losses + pybind11::dict losses_dict; + float losses_host[NUM_LOSSES]; + cudaMemcpy(losses_host, pufferl.losses_puf.data, sizeof(losses_host), cudaMemcpyDeviceToHost); + float n = losses_host[LOSS_N]; + if (n > 0) { + float inv_n = 1.0f / n; + losses_dict["policy"] = losses_host[LOSS_PG] * inv_n; + losses_dict["value"] = losses_host[LOSS_VF] * inv_n; + losses_dict["entropy"] = losses_host[LOSS_ENT] * inv_n; + losses_dict["total"] = losses_host[LOSS_TOTAL] * inv_n; + losses_dict["old_kl"] = losses_host[LOSS_OLD_APPROX_KL] * inv_n; + losses_dict["kl"] = losses_host[LOSS_APPROX_KL] * inv_n; + losses_dict["clipfrac"] = losses_host[LOSS_CLIPFRAC] * inv_n; + } + cudaMemset(pufferl.losses_puf.data, 0, numel(pufferl.losses_puf.shape) * sizeof(float)); + result["loss"] = losses_dict; + + // Profile + pybind11::dict perf_dict; + float train_total = 0; + for (int i = 0; i < NUM_PROF; i++) { + float sec = pufferl.profile.accum[i] / 1000.0f; + perf_dict[PROF_NAMES[i]] = sec; + if (i >= PROF_TRAIN_MISC) train_total += sec; + } + perf_dict["train"] = train_total; + memset(pufferl.profile.accum, 0, sizeof(pufferl.profile.accum)); + result["perf"] = perf_dict; + + // Utilization + pybind11::dict util_dict; + nvmlUtilization_t util; + nvmlDeviceGetUtilizationRates(pufferl.nvml_device, &util); + util_dict["gpu_percent"] = (float)util.gpu; + + nvmlMemory_t mem; + nvmlDeviceGetMemoryInfo(pufferl.nvml_device, &mem); + util_dict["gpu_mem"] = 100.0f * (float)mem.used / (float)mem.total; + + size_t cuda_free, cuda_total; + cudaMemGetInfo(&cuda_free, &cuda_total); + util_dict["vram_used_gb"] = (float)(cuda_total - cuda_free) / (1024.0f * 1024.0f * 1024.0f); + util_dict["vram_total_gb"] = (float)cuda_total / (1024.0f * 1024.0f * 1024.0f); + + long rss_kb = 0; + FILE* f = fopen("/proc/self/status", "r"); + if (f) { + char line[256]; + while (fgets(line, sizeof(line), f)) { + if (sscanf(line, "VmRSS: %ld", &rss_kb) == 1) break; + } + fclose(f); + } + util_dict["cpu_mem_gb"] = (float)rss_kb / (1024.0f * 1024.0f); + result["util"] = util_dict; + + return result; +} + +pybind11::dict puf_eval_log(pybind11::object pufferl_obj) { + auto& pufferl = pufferl_obj.cast(); + pybind11::dict result; + + double now = wall_clock(); + pufferl.last_log_time = now; + pufferl.last_log_step = pufferl.global_step; + + pybind11::dict env_dict; + Dict* env_out = create_dict(32); + static_vec_eval_log(pufferl.vec, env_out); + for (int i = 0; i < env_out->size; i++) { + env_dict[env_out->items[i].key] = env_out->items[i].value; + } + result["env"] = env_dict; + + return result; +} + +void python_vec_recv(pybind11::object pufferl_obj, int buf) { + // Not used in static/OMP path +} + +void python_vec_send(pybind11::object pufferl_obj, int buf) { + // Not used in static/OMP path +} + +void render(pybind11::object pufferl_obj, int env_id) { + PuffeRL& pufferl = pufferl_obj.cast(); + static_vec_render(pufferl.vec, env_id); +} + +void rollouts(pybind11::object pufferl_obj) { + PuffeRL& pufferl = pufferl_obj.cast(); + pybind11::gil_scoped_release no_gil; + double t0 = wall_clock(); + + // Zero state buffers + if (pufferl.hypers.reset_state) { + for (int i = 0; i < pufferl.hypers.num_buffers; i++) { + puf_zero(&pufferl.buffer_states[i], pufferl.default_stream); + } + } + + static_vec_omp_step(pufferl.vec); + float sec = (float)(wall_clock() - t0); + pufferl.profile.accum[PROF_ROLLOUT] += sec * 1000.0f; // store as ms + + float eval_prof[NUM_EVAL_PROF]; + static_vec_read_profile(pufferl.vec, eval_prof); + pufferl.profile.accum[PROF_EVAL_GPU] += eval_prof[EVAL_GPU]; + pufferl.profile.accum[PROF_EVAL_ENV] += eval_prof[EVAL_ENV_STEP]; + pufferl.global_step += pufferl.hypers.horizon * pufferl.hypers.total_agents; +} + +pybind11::dict train(pybind11::object pufferl_obj) { + PuffeRL& pufferl = pufferl_obj.cast(); + { + pybind11::gil_scoped_release no_gil; + train_impl(pufferl); + } + pybind11::dict losses; + return losses; +} + +void puf_close(pybind11::object pufferl_obj) { + PuffeRL& pufferl = pufferl_obj.cast(); + close_impl(pufferl); +} + +void save_weights(pybind11::object pufferl_obj, const std::string& path) { + PuffeRL& pufferl = pufferl_obj.cast(); + int64_t nbytes = numel(pufferl.master_weights.shape) * sizeof(float); + std::vector buf(nbytes); + cudaMemcpy(buf.data(), pufferl.master_weights.data, nbytes, cudaMemcpyDeviceToHost); + FILE* f = fopen(path.c_str(), "wb"); + if (!f) throw std::runtime_error("Failed to open " + path + " for writing"); + fwrite(buf.data(), 1, nbytes, f); + fclose(f); +} + +void load_weights(pybind11::object pufferl_obj, const std::string& path) { + PuffeRL& pufferl = pufferl_obj.cast(); + int64_t nbytes = numel(pufferl.master_weights.shape) * sizeof(float); + FILE* f = fopen(path.c_str(), "rb"); + if (!f) throw std::runtime_error("Failed to open " + path + " for reading"); + // Verify file size matches + fseek(f, 0, SEEK_END); + long file_size = ftell(f); + fseek(f, 0, SEEK_SET); + if (file_size != nbytes) { + fclose(f); + throw std::runtime_error("Weight file size mismatch: expected " + + std::to_string(nbytes) + " bytes, got " + std::to_string(file_size)); + } + std::vector buf(nbytes); + size_t nread = fread(buf.data(), 1, nbytes, f); + if ((int64_t)nread != nbytes) { + fclose(f); + throw std::runtime_error("Failed to read weight file"); + } + fclose(f); + cudaMemcpy(pufferl.master_weights.data, buf.data(), nbytes, cudaMemcpyHostToDevice); + if (USE_BF16) { + int n = numel(pufferl.param_puf.shape); + cast<<>>( + pufferl.param_puf.data, pufferl.master_weights.data, n); + } +} + +void py_puff_advantage( + long long values_ptr, long long rewards_ptr, + long long dones_ptr, long long importance_ptr, + long long advantages_ptr, + int num_steps, int horizon, + float gamma, float lambda, float rho_clip, float c_clip) { + constexpr int N = 16 / sizeof(precision_t); + int blocks = grid_size(num_steps); + auto kernel = (horizon % N == 0) ? puff_advantage : puff_advantage_scalar; + kernel<<>>( + (const precision_t*)values_ptr, (const precision_t*)rewards_ptr, + (const precision_t*)dones_ptr, (const precision_t*)importance_ptr, + (precision_t*)advantages_ptr, + gamma, lambda, rho_clip, c_clip, num_steps, horizon); +} + +double get_config(py::dict& kwargs, const char* key) { + if (!kwargs.contains(key)) { + throw std::runtime_error(std::string("Missing config key: ") + key); + } + try { + return kwargs[key].cast(); + } catch (const py::cast_error& e) { + throw std::runtime_error(std::string("Failed to cast config key '") + key + "': " + e.what()); + } +} + +Dict* py_dict_to_c_dict(py::dict py_dict) { + Dict* c_dict = create_dict(py_dict.size()); + for (auto item : py_dict) { + const char* key = PyUnicode_AsUTF8(item.first.ptr()); + try { + dict_set(c_dict, key, item.second.cast()); + } catch (const py::cast_error&) { + // Skip non-numeric values + } + } + return c_dict; +} + +// ============================================================================ +// Python-facing VecEnv: wraps StaticVec for use from python_pufferl.py. +// After vec_step(), GPU buffers are current — Python wraps them zero-copy +// with torch.from_blob(ptr, shape, dtype, device='cuda'). +// ============================================================================ + +struct VecEnv { + StaticVec* vec; + int total_agents; + int obs_size; + int num_atns; + std::vector act_sizes; + std::string obs_dtype; + size_t obs_elem_size; + int gpu; +}; + +std::unique_ptr create_vec(py::dict args, int gpu) { + py::dict vec_kwargs = args["vec"].cast(); + py::dict env_kwargs = args["env"].cast(); + + int total_agents = (int)get_config(vec_kwargs, "total_agents"); + int num_buffers = (int)get_config(vec_kwargs, "num_buffers"); + + Dict* vec_dict = py_dict_to_c_dict(vec_kwargs); + Dict* env_dict = py_dict_to_c_dict(env_kwargs); + + auto ve = std::make_unique(); + ve->gpu = gpu; + { + py::gil_scoped_release no_gil; + ve->vec = create_static_vec(total_agents, num_buffers, gpu, vec_dict, env_dict); + } + ve->total_agents = total_agents; + ve->obs_size = get_obs_size(); + ve->num_atns = get_num_atns(); + { + int* raw = get_act_sizes(); + int n = get_num_act_sizes(); + ve->act_sizes = std::vector(raw, raw + n); + } + ve->obs_dtype = std::string(get_obs_dtype()); + ve->obs_elem_size = get_obs_elem_size(); + return ve; +} + +void vec_reset(VecEnv& ve) { + py::gil_scoped_release no_gil; + static_vec_reset(ve.vec); +} + +void gpu_vec_step_py(VecEnv& ve, long long actions_ptr) { + cudaMemcpy(ve.vec->gpu_actions, (void*)actions_ptr, + (size_t)ve.total_agents * ve.num_atns * sizeof(float), + cudaMemcpyDeviceToDevice); + { + py::gil_scoped_release no_gil; + gpu_vec_step(ve.vec); + } +} + +void cpu_vec_step_py(VecEnv& ve, long long actions_ptr) { + memcpy(ve.vec->actions, (void*)actions_ptr, + (size_t)ve.total_agents * ve.num_atns * sizeof(float)); + { + py::gil_scoped_release no_gil; + cpu_vec_step(ve.vec); + } +} + +py::dict vec_log(VecEnv& ve) { + Dict* out = create_dict(32); + static_vec_log(ve.vec, out); + py::dict result; + for (int i = 0; i < out->size; i++) { + result[out->items[i].key] = out->items[i].value; + } + free(out->items); + free(out); + return result; +} + +void vec_close(VecEnv& ve) { + static_vec_close(ve.vec); + ve.vec = nullptr; +} + +std::unique_ptr create_pufferl(py::dict args) { + py::dict train_kwargs = args["train"].cast(); + py::dict vec_kwargs = args["vec"].cast(); + py::dict env_kwargs = args["env"].cast(); + py::dict policy_kwargs = args["policy"].cast(); + + HypersT hypers; + // Layout (total_agents and num_buffers come from vec config) + hypers.total_agents = get_config(vec_kwargs, "total_agents"); + hypers.num_buffers = get_config(vec_kwargs, "num_buffers"); + hypers.num_threads = get_config(vec_kwargs, "num_threads"); + hypers.horizon = get_config(train_kwargs, "horizon"); + // Model architecture (num_atns computed from env in C++) + hypers.hidden_size = get_config(policy_kwargs, "hidden_size"); + hypers.num_layers = get_config(policy_kwargs, "num_layers"); + // Learning rate + hypers.lr = get_config(train_kwargs, "learning_rate"); + hypers.min_lr_ratio = get_config(train_kwargs, "min_lr_ratio"); + hypers.anneal_lr = get_config(train_kwargs, "anneal_lr"); + // Optimizer + hypers.beta1 = get_config(train_kwargs, "beta1"); + hypers.beta2 = get_config(train_kwargs, "beta2"); + hypers.eps = get_config(train_kwargs, "eps"); + // Training + hypers.minibatch_size = get_config(train_kwargs, "minibatch_size"); + hypers.replay_ratio = get_config(train_kwargs, "replay_ratio"); + hypers.total_timesteps = get_config(train_kwargs, "total_timesteps"); + hypers.max_grad_norm = get_config(train_kwargs, "max_grad_norm"); + // PPO + hypers.clip_coef = get_config(train_kwargs, "clip_coef"); + hypers.vf_clip_coef = get_config(train_kwargs, "vf_clip_coef"); + hypers.vf_coef = get_config(train_kwargs, "vf_coef"); + hypers.ent_coef = get_config(train_kwargs, "ent_coef"); + // GAE + hypers.gamma = get_config(train_kwargs, "gamma"); + hypers.gae_lambda = get_config(train_kwargs, "gae_lambda"); + // VTrace + hypers.vtrace_rho_clip = get_config(train_kwargs, "vtrace_rho_clip"); + hypers.vtrace_c_clip = get_config(train_kwargs, "vtrace_c_clip"); + // Priority + hypers.prio_alpha = get_config(train_kwargs, "prio_alpha"); + hypers.prio_beta0 = get_config(train_kwargs, "prio_beta0"); + hypers.reset_state = get_config(args, "reset_state"); + // Base-level config ([base] section becomes top-level in args) + hypers.cudagraphs = get_config(args, "cudagraphs"); + hypers.profile = get_config(args, "profile"); + // Multi-GPU / device selection + hypers.rank = get_config(args, "rank"); + hypers.world_size = get_config(args, "world_size"); + hypers.gpu_id = get_config(args, "gpu_id"); + hypers.nccl_id = args["nccl_id"].cast(); + // Seed + hypers.seed = get_config(args, "seed"); + + int device_count = 0; + cudaGetDeviceCount(&device_count); + assert(device_count > 0 && "CUDA is not available"); + + std::string env_name = args["env_name"].cast(); + Dict* vec_dict = py_dict_to_c_dict(vec_kwargs.cast()); + Dict* env_dict = py_dict_to_c_dict(env_kwargs.cast()); + + std::unique_ptr pufferl; + { + pybind11::gil_scoped_release no_gil; + pufferl = create_pufferl_impl(hypers, env_name, vec_dict, env_dict); + } + + if (!pufferl) { + throw std::runtime_error("CUDA OOM: failed to allocate training buffers"); + } + + return pufferl; +} + +PYBIND11_MODULE(_C, m) { + // Multi-GPU: generate NCCL unique ID (call on rank 0, pass bytes to all ranks) + m.def("get_nccl_id", []() { + ncclUniqueId id; + ncclGetUniqueId(&id); + return py::bytes(reinterpret_cast(&id), sizeof(id)); + }); + // Standalone utilization monitor (no PuffeRL instance needed) + m.def("get_utilization", [](int gpu_id) { + static bool nvml_inited = false; + if (!nvml_inited) { nvmlInit(); nvml_inited = true; } + + py::dict util_dict; + nvmlDevice_t device; + nvmlDeviceGetHandleByIndex(gpu_id, &device); + + nvmlUtilization_t util; + nvmlDeviceGetUtilizationRates(device, &util); + util_dict["gpu_percent"] = (float)util.gpu; + + nvmlMemory_t mem; + nvmlDeviceGetMemoryInfo(device, &mem); + util_dict["gpu_mem"] = 100.0f * (float)mem.used / (float)mem.total; + + size_t cuda_free, cuda_total; + cudaMemGetInfo(&cuda_free, &cuda_total); + util_dict["vram_used_gb"] = (float)(cuda_total - cuda_free) / (1024.0f * 1024.0f * 1024.0f); + util_dict["vram_total_gb"] = (float)cuda_total / (1024.0f * 1024.0f * 1024.0f); + + long rss_kb = 0; + FILE* f = fopen("/proc/self/status", "r"); + if (f) { + char line[256]; + while (fgets(line, sizeof(line), f)) { + if (sscanf(line, "VmRSS: %ld", &rss_kb) == 1) break; + } + fclose(f); + } + util_dict["cpu_mem_gb"] = (float)rss_kb / (1024.0f * 1024.0f); + + return util_dict; + }); + + m.attr("precision_bytes") = (int)sizeof(precision_t); + m.attr("env_name") = PUFFER_STRINGIFY(ENV_NAME); + m.attr("gpu") = 1; + + // Core functions + m.def("log", &puf_log); + m.def("eval_log", &puf_eval_log); + m.def("render", &render); + m.def("rollouts", &rollouts); + m.def("train", &train); + m.def("close", &puf_close); + m.def("save_weights", &save_weights); + m.def("load_weights", &load_weights); + m.def("python_vec_recv", &python_vec_recv); + m.def("python_vec_send", &python_vec_send); + py::class_(m, "Policy"); + py::class_(m, "Muon"); + py::class_(m, "Allocator") + .def(py::init<>()); + + py::class_(m, "HypersT") + .def_readwrite("horizon", &HypersT::horizon) + .def_readwrite("total_agents", &HypersT::total_agents) + .def_readwrite("num_buffers", &HypersT::num_buffers) + .def_readwrite("num_atns", &HypersT::num_atns) + .def_readwrite("hidden_size", &HypersT::hidden_size) + + .def_readwrite("replay_ratio", &HypersT::replay_ratio) + .def_readwrite("num_layers", &HypersT::num_layers) + .def_readwrite("lr", &HypersT::lr) + .def_readwrite("min_lr_ratio", &HypersT::min_lr_ratio) + .def_readwrite("anneal_lr", &HypersT::anneal_lr) + .def_readwrite("beta1", &HypersT::beta1) + .def_readwrite("beta2", &HypersT::beta2) + .def_readwrite("eps", &HypersT::eps) + .def_readwrite("total_timesteps", &HypersT::total_timesteps) + .def_readwrite("max_grad_norm", &HypersT::max_grad_norm) + .def_readwrite("clip_coef", &HypersT::clip_coef) + .def_readwrite("vf_clip_coef", &HypersT::vf_clip_coef) + .def_readwrite("vf_coef", &HypersT::vf_coef) + .def_readwrite("ent_coef", &HypersT::ent_coef) + .def_readwrite("gamma", &HypersT::gamma) + .def_readwrite("gae_lambda", &HypersT::gae_lambda) + .def_readwrite("vtrace_rho_clip", &HypersT::vtrace_rho_clip) + .def_readwrite("vtrace_c_clip", &HypersT::vtrace_c_clip) + .def_readwrite("prio_alpha", &HypersT::prio_alpha) + .def_readwrite("prio_beta0", &HypersT::prio_beta0) + .def_readwrite("cudagraphs", &HypersT::cudagraphs) + .def_readwrite("profile", &HypersT::profile) + .def_readwrite("rank", &HypersT::rank) + .def_readwrite("world_size", &HypersT::world_size) + .def_readwrite("gpu_id", &HypersT::gpu_id) + .def_readwrite("nccl_id", &HypersT::nccl_id); + + py::class_(m, "PrecisionTensor") + .def("__repr__", [](const PrecisionTensor& t) { return std::string(puf_repr(&t)); }) + .def("ndim", [](const PrecisionTensor& t) { return ndim(t.shape); }) + .def("numel", [](const PrecisionTensor& t) { return numel(t.shape); }); + py::class_(m, "FloatTensor") + .def("__repr__", [](const FloatTensor& t) { return std::string(puf_repr(&t)); }) + .def("ndim", [](const FloatTensor& t) { return ndim(t.shape); }) + .def("numel", [](const FloatTensor& t) { return numel(t.shape); }); + + py::class_(m, "RolloutBuf") + .def_readwrite("observations", &RolloutBuf::observations) + .def_readwrite("actions", &RolloutBuf::actions) + .def_readwrite("values", &RolloutBuf::values) + .def_readwrite("logprobs", &RolloutBuf::logprobs) + .def_readwrite("rewards", &RolloutBuf::rewards) + .def_readwrite("terminals", &RolloutBuf::terminals) + .def_readwrite("ratio", &RolloutBuf::ratio) + .def_readwrite("importance", &RolloutBuf::importance); + + m.def("uptime", [](py::object pufferl_obj) -> double { + PuffeRL& pufferl = pufferl_obj.cast(); + double now = wall_clock(); + return now - pufferl.start_time; + }); + m.def("puff_advantage", &py_puff_advantage); + m.def("create_vec", &create_vec, py::arg("args"), py::arg("gpu") = 1); + py::class_>(m, "VecEnv") + .def_readonly("total_agents", &VecEnv::total_agents) + .def_readonly("obs_size", &VecEnv::obs_size) + .def_readonly("num_atns", &VecEnv::num_atns) + .def_readonly("act_sizes", &VecEnv::act_sizes) + .def_readonly("obs_dtype", &VecEnv::obs_dtype) + .def_readonly("obs_elem_size", &VecEnv::obs_elem_size) + .def_readonly("gpu", &VecEnv::gpu) + // GPU buffer pointers — wrap with torch.from_blob(..., device='cuda') + .def_property_readonly("gpu_obs_ptr", [](VecEnv& ve) { return (long long)ve.vec->gpu_observations; }) + .def_property_readonly("gpu_rewards_ptr", [](VecEnv& ve) { return (long long)ve.vec->gpu_rewards; }) + .def_property_readonly("gpu_terminals_ptr", [](VecEnv& ve) { return (long long)ve.vec->gpu_terminals; }) + // CPU buffer pointers (same as gpu_ in CPU mode since they alias) + .def_property_readonly("obs_ptr", [](VecEnv& ve) { return (long long)ve.vec->observations; }) + .def_property_readonly("rewards_ptr", [](VecEnv& ve) { return (long long)ve.vec->rewards; }) + .def_property_readonly("terminals_ptr", [](VecEnv& ve) { return (long long)ve.vec->terminals; }) + .def("reset", &vec_reset) + .def("gpu_step", &gpu_vec_step_py) + .def("cpu_step", &cpu_vec_step_py) + .def("render", [](VecEnv& ve, int env_id) { static_vec_render(ve.vec, env_id); }) + .def("log", &vec_log) + .def("close", &vec_close); + + m.def("create_pufferl", &create_pufferl); + py::class_>(m, "PuffeRL") + .def_readwrite("policy", &PuffeRL::policy) + .def_readwrite("muon", &PuffeRL::muon) + .def_readwrite("hypers", &PuffeRL::hypers) + .def_readwrite("rollouts", &PuffeRL::rollouts) + .def_readonly("epoch", &PuffeRL::epoch) + .def_readonly("global_step", &PuffeRL::global_step) + .def_readonly("last_log_time", &PuffeRL::last_log_time) + .def("num_params", [](PuffeRL& self) -> int64_t { + return numel(self.master_weights.shape); + }); +} diff --git a/src/bindings_cpu.cpp b/src/bindings_cpu.cpp new file mode 100644 index 0000000000..5ba4dc81e5 --- /dev/null +++ b/src/bindings_cpu.cpp @@ -0,0 +1,187 @@ +// bindings_cpu.cpp - CPU-only Python bindings (no nvcc/CUDA required) + +#include +#include + +#define _PUFFER_STRINGIFY(x) #x +#define PUFFER_STRINGIFY(x) _PUFFER_STRINGIFY(x) +#include + +// vecenv.h header section gives us StaticVec, Dict, cudaStream_t typedef +#include "vecenv.h" + +namespace py = pybind11; + +// Stub out CUDA functions that the static lib references (dead code when gpu=0) +extern "C" { +typedef int cudaError_t; +typedef int cudaMemcpyKind; +cudaError_t cudaHostAlloc(void**, size_t, unsigned int) { return 0; } +cudaError_t cudaMalloc(void**, size_t) { return 0; } +cudaError_t cudaMemcpy(void*, const void*, size_t, cudaMemcpyKind) { return 0; } +cudaError_t cudaMemcpyAsync(void*, const void*, size_t, cudaMemcpyKind, cudaStream_t) { return 0; } +cudaError_t cudaMemset(void*, int, size_t) { return 0; } +cudaError_t cudaFree(void*) { return 0; } +cudaError_t cudaFreeHost(void*) { return 0; } +cudaError_t cudaSetDevice(int) { return 0; } +cudaError_t cudaDeviceSynchronize(void) { return 0; } +cudaError_t cudaStreamSynchronize(cudaStream_t) { return 0; } +cudaError_t cudaStreamCreateWithFlags(cudaStream_t*, unsigned int) { return 0; } +cudaError_t cudaStreamQuery(cudaStream_t) { return 0; } +const char* cudaGetErrorString(cudaError_t) { return "stub"; } +} + +// ============================================================================ +// CPU advantage (same as puff_advantage_row_scalar but plain C++) +// ============================================================================ + +static void py_puff_advantage_cpu( + long long values_ptr, long long rewards_ptr, + long long dones_ptr, long long importance_ptr, + long long advantages_ptr, + int num_steps, int horizon, + float gamma, float lambda, float rho_clip, float c_clip) { + const float* values = (const float*)values_ptr; + const float* rewards = (const float*)rewards_ptr; + const float* dones = (const float*)dones_ptr; + const float* importance = (const float*)importance_ptr; + float* advantages = (float*)advantages_ptr; + for (int row = 0; row < num_steps; row++) { + int off = row * horizon; + float lastpufferlam = 0; + for (int t = horizon - 2; t >= 0; t--) { + int t_next = t + 1; + float nextnonterminal = 1.0f - dones[off + t_next]; + float imp = importance[off + t]; + float rho_t = imp < rho_clip ? imp : rho_clip; + float c_t = imp < c_clip ? imp : c_clip; + float r_nxt = rewards[off + t_next]; + float v = values[off + t]; + float v_nxt = values[off + t_next]; + float delta = rho_t * r_nxt + gamma * v_nxt * nextnonterminal - v; + lastpufferlam = delta + gamma * lambda * c_t * lastpufferlam * nextnonterminal; + advantages[off + t] = lastpufferlam; + } + } +} + +// ============================================================================ +// Dict helpers (same as bindings.cu) +// ============================================================================ + +static double get_config(py::dict& kwargs, const char* key) { + if (!kwargs.contains(key)) + throw std::runtime_error(std::string("Missing config key: ") + key); + return kwargs[key].cast(); +} + +static Dict* py_dict_to_c_dict(py::dict py_dict) { + Dict* c_dict = create_dict(py_dict.size()); + for (auto item : py_dict) { + const char* key = PyUnicode_AsUTF8(item.first.ptr()); + try { dict_set(c_dict, key, item.second.cast()); } + catch (const py::cast_error&) {} + } + return c_dict; +} + +// ============================================================================ +// VecEnv wrapper +// ============================================================================ + +struct VecEnv { + StaticVec* vec; + int total_agents; + int obs_size; + int num_atns; + std::vector act_sizes; + std::string obs_dtype; + size_t obs_elem_size; +}; + +static std::unique_ptr create_vec(py::dict args, int gpu = 0) { + (void)gpu; + py::dict vec_kwargs = args["vec"].cast(); + py::dict env_kwargs = args["env"].cast(); + int total_agents = (int)get_config(vec_kwargs, "total_agents"); + int num_buffers = (int)get_config(vec_kwargs, "num_buffers"); + Dict* vec_dict = py_dict_to_c_dict(vec_kwargs); + Dict* env_dict = py_dict_to_c_dict(env_kwargs); + + auto ve = std::make_unique(); + { + py::gil_scoped_release no_gil; + ve->vec = create_static_vec(total_agents, num_buffers, 0, vec_dict, env_dict); + } + ve->total_agents = total_agents; + ve->obs_size = get_obs_size(); + ve->num_atns = get_num_atns(); + { + int* raw = get_act_sizes(); + int n = get_num_act_sizes(); + ve->act_sizes = std::vector(raw, raw + n); + } + ve->obs_dtype = std::string(get_obs_dtype()); + ve->obs_elem_size = get_obs_elem_size(); + return ve; +} + +static void vec_reset(VecEnv& ve) { + py::gil_scoped_release no_gil; + static_vec_reset(ve.vec); +} + +static void cpu_vec_step_py(VecEnv& ve, long long actions_ptr) { + memcpy(ve.vec->actions, (void*)actions_ptr, + (size_t)ve.total_agents * ve.num_atns * sizeof(float)); + { + py::gil_scoped_release no_gil; + cpu_vec_step(ve.vec); + } +} + +static py::dict vec_log(VecEnv& ve) { + Dict* out = create_dict(32); + static_vec_log(ve.vec, out); + py::dict result; + for (int i = 0; i < out->size; i++) + result[out->items[i].key] = out->items[i].value; + free(out->items); + free(out); + return result; +} + +static void vec_close(VecEnv& ve) { + static_vec_close(ve.vec); + ve.vec = nullptr; +} + +// ============================================================================ +// Module +// ============================================================================ + +PYBIND11_MODULE(_C, m) { + m.attr("precision_bytes") = 4; + m.attr("env_name") = PUFFER_STRINGIFY(ENV_NAME); + m.attr("gpu") = 0; + + m.def("puff_advantage_cpu", &py_puff_advantage_cpu); + m.def("create_vec", &create_vec, py::arg("args"), py::arg("gpu") = 0); + + py::class_>(m, "VecEnv") + .def_readonly("total_agents", &VecEnv::total_agents) + .def_readonly("obs_size", &VecEnv::obs_size) + .def_readonly("num_atns", &VecEnv::num_atns) + .def_readonly("act_sizes", &VecEnv::act_sizes) + .def_readonly("obs_dtype", &VecEnv::obs_dtype) + .def_readonly("obs_elem_size", &VecEnv::obs_elem_size) + .def_property_readonly("gpu", [](VecEnv&) { return 0; }) + .def_property_readonly("obs_ptr", [](VecEnv& ve) { return (long long)ve.vec->observations; }) + .def_property_readonly("rewards_ptr", [](VecEnv& ve) { return (long long)ve.vec->rewards; }) + .def_property_readonly("terminals_ptr", [](VecEnv& ve) { return (long long)ve.vec->terminals; }) + .def("reset", &vec_reset) + .def("cpu_step", &cpu_vec_step_py) + .def("render", [](VecEnv& ve, int env_id) { static_vec_render(ve.vec, env_id); }) + .def("log", &vec_log) + .def("close", &vec_close); +} diff --git a/src/cudnn_conv2d.cu b/src/cudnn_conv2d.cu new file mode 100644 index 0000000000..f1d86b597d --- /dev/null +++ b/src/cudnn_conv2d.cu @@ -0,0 +1,187 @@ +// cuDNN Conv2d: forward/backward with fused bias+activation. +// Included by ocean.cu (training) and tests/test_nmmo3_cuda.cu (test). + +#ifndef CUDNN_CONV2D_CU +#define CUDNN_CONV2D_CU + +#include +#include +#include + +#include "kernels.cu" + +#ifndef CHECK_CUDNN +#define CHECK_CUDNN(call) do { \ + cudnnStatus_t e = call; \ + if (e != CUDNN_STATUS_SUCCESS) { \ + fprintf(stderr, "cuDNN %s:%d: %s\n", __FILE__, __LINE__, cudnnGetErrorString(e)); exit(1); \ + } \ +} while(0) +#endif + +static inline int div_ceil(int a, int b) { return (a + b - 1) / b; } + +static cudnnHandle_t get_cudnn_handle() { + static cudnnHandle_t h = nullptr; + if (!h) CHECK_CUDNN(cudnnCreate(&h)); + return h; +} + +// ---- ConvWeights: params + batch-independent cuDNN state ---- + +struct ConvWeights { + PrecisionTensor w, b; // w: (OC, IC*K*K), b: (OC) + int IC, OC, K, S, IH, IW, OH, OW; + bool relu; + cudnnDataType_t dtype; + cudnnTensorDescriptor_t cudnn_bias; + cudnnFilterDescriptor_t cudnn_filt; + cudnnConvolutionDescriptor_t cudnn_conv; + cudnnActivationDescriptor_t cudnn_act; + bool cudnn_ready; +}; + +// ---- ConvActivations: per-batch-size buffers + descriptors ---- + +struct ConvActivations { + PrecisionTensor out, grad, saved_input; + PrecisionTensor wgrad, bgrad; + // Per-batch-size cuDNN state + cudnnTensorDescriptor_t cudnn_in, cudnn_out; + cudnnConvolutionFwdAlgo_t fwd_algo; + cudnnConvolutionBwdDataAlgo_t bwd_data_algo; + cudnnConvolutionBwdFilterAlgo_t bwd_filt_algo; + size_t fwd_ws_bytes, bwd_data_ws_bytes, bwd_filt_ws_bytes; + void* fwd_ws; void* bwd_data_ws; void* bwd_filt_ws; + bool cudnn_setup; +}; + +static void conv_init(ConvWeights* cw, int IC, int OC, int K, int S, int IH, int IW, bool relu) { + cw->IC = IC; cw->OC = OC; cw->K = K; cw->S = S; cw->IH = IH; cw->IW = IW; + cw->OH = (IH - K) / S + 1; cw->OW = (IW - K) / S + 1; + cw->relu = relu; cw->cudnn_ready = false; +} + +// Create batch-independent descriptors (once) +static void conv_setup_shared(ConvWeights* cw, cudnnDataType_t dt) { + if (cw->cudnn_ready) return; + cw->dtype = dt; + CHECK_CUDNN(cudnnCreateFilterDescriptor(&cw->cudnn_filt)); + CHECK_CUDNN(cudnnSetFilter4dDescriptor(cw->cudnn_filt, dt, CUDNN_TENSOR_NCHW, cw->OC, cw->IC, cw->K, cw->K)); + CHECK_CUDNN(cudnnCreateConvolutionDescriptor(&cw->cudnn_conv)); + CHECK_CUDNN(cudnnSetConvolution2dDescriptor(cw->cudnn_conv, 0, 0, cw->S, cw->S, 1, 1, CUDNN_CROSS_CORRELATION, CUDNN_DATA_FLOAT)); + CHECK_CUDNN(cudnnCreateTensorDescriptor(&cw->cudnn_bias)); + CHECK_CUDNN(cudnnSetTensor4dDescriptor(cw->cudnn_bias, CUDNN_TENSOR_NCHW, dt, 1, cw->OC, 1, 1)); + CHECK_CUDNN(cudnnCreateActivationDescriptor(&cw->cudnn_act)); + CHECK_CUDNN(cudnnSetActivationDescriptor(cw->cudnn_act, + cw->relu ? CUDNN_ACTIVATION_RELU : CUDNN_ACTIVATION_IDENTITY, CUDNN_NOT_PROPAGATE_NAN, 0.0)); + cw->cudnn_ready = true; +} + +// Setup per-activation-set cuDNN state: batch-dependent descriptors + algo search + workspace +static void conv_setup_activations(ConvWeights* cw, ConvActivations* ca, int B, cudnnDataType_t dt) { + conv_setup_shared(cw, dt); + cudnnHandle_t h = get_cudnn_handle(); + + CHECK_CUDNN(cudnnCreateTensorDescriptor(&ca->cudnn_in)); + CHECK_CUDNN(cudnnSetTensor4dDescriptor(ca->cudnn_in, CUDNN_TENSOR_NCHW, dt, B, cw->IC, cw->IH, cw->IW)); + CHECK_CUDNN(cudnnCreateTensorDescriptor(&ca->cudnn_out)); + CHECK_CUDNN(cudnnSetTensor4dDescriptor(ca->cudnn_out, CUDNN_TENSOR_NCHW, dt, B, cw->OC, cw->OH, cw->OW)); + + int returned; + cudnnConvolutionFwdAlgoPerf_t fp; + CHECK_CUDNN(cudnnFindConvolutionForwardAlgorithm(h, ca->cudnn_in, cw->cudnn_filt, cw->cudnn_conv, ca->cudnn_out, 1, &returned, &fp)); + ca->fwd_algo = fp.algo; + CHECK_CUDNN(cudnnGetConvolutionForwardWorkspaceSize(h, ca->cudnn_in, cw->cudnn_filt, cw->cudnn_conv, ca->cudnn_out, ca->fwd_algo, &ca->fwd_ws_bytes)); + ca->fwd_ws = NULL; if (ca->fwd_ws_bytes > 0) cudaMalloc(&ca->fwd_ws, ca->fwd_ws_bytes); + + cudnnConvolutionBwdFilterAlgoPerf_t ffp; + CHECK_CUDNN(cudnnFindConvolutionBackwardFilterAlgorithm(h, ca->cudnn_in, ca->cudnn_out, cw->cudnn_conv, cw->cudnn_filt, 1, &returned, &ffp)); + ca->bwd_filt_algo = ffp.algo; + CHECK_CUDNN(cudnnGetConvolutionBackwardFilterWorkspaceSize(h, ca->cudnn_in, ca->cudnn_out, cw->cudnn_conv, cw->cudnn_filt, ca->bwd_filt_algo, &ca->bwd_filt_ws_bytes)); + ca->bwd_filt_ws = NULL; if (ca->bwd_filt_ws_bytes > 0) cudaMalloc(&ca->bwd_filt_ws, ca->bwd_filt_ws_bytes); + + cudnnConvolutionBwdDataAlgoPerf_t dp; + CHECK_CUDNN(cudnnFindConvolutionBackwardDataAlgorithm(h, cw->cudnn_filt, ca->cudnn_out, cw->cudnn_conv, ca->cudnn_in, 1, &returned, &dp)); + ca->bwd_data_algo = dp.algo; + CHECK_CUDNN(cudnnGetConvolutionBackwardDataWorkspaceSize(h, cw->cudnn_filt, ca->cudnn_out, cw->cudnn_conv, ca->cudnn_in, ca->bwd_data_algo, &ca->bwd_data_ws_bytes)); + ca->bwd_data_ws = NULL; if (ca->bwd_data_ws_bytes > 0) cudaMalloc(&ca->bwd_data_ws, ca->bwd_data_ws_bytes); + + ca->cudnn_setup = true; +} + +// Legacy single-setup API (for tests) +static void conv_setup(ConvWeights* cw, int B, cudnnDataType_t dt) { + conv_setup_shared(cw, dt); +} + +static void conv_reg_params(ConvWeights* cw, Allocator* alloc) { + cw->w = {.shape = {cw->OC, cw->IC * cw->K * cw->K}}; + cw->b = {.shape = {cw->OC}}; + alloc_register(alloc,&cw->w); alloc_register(alloc,&cw->b); +} + +static void conv_reg_train(ConvWeights* cw, ConvActivations* ca, Allocator* acts, Allocator* grads, int B, cudnnDataType_t dt) { + ca->out = {.shape = {B * cw->OC * cw->OH * cw->OW}}; + ca->grad = {.shape = {B * cw->OC * cw->OH * cw->OW}}; + ca->saved_input = {.shape = {B * cw->IC * cw->IH * cw->IW}}; + ca->wgrad = {.shape = {cw->OC, cw->IC * cw->K * cw->K}}; + ca->bgrad = {.shape = {cw->OC}}; + alloc_register(acts,&ca->out); alloc_register(acts,&ca->grad); alloc_register(acts,&ca->saved_input); + alloc_register(grads,&ca->wgrad); alloc_register(grads,&ca->bgrad); + conv_setup_activations(cw, ca, B, dt); +} + +static void conv_reg_rollout(ConvWeights* cw, ConvActivations* ca, Allocator* alloc, int B, cudnnDataType_t dt) { + ca->out = {.shape = {B * cw->OC * cw->OH * cw->OW}}; + ca->cudnn_setup = false; + alloc_register(alloc,&ca->out); + conv_setup_activations(cw, ca, B, dt); +} + +static void conv_init_weights(ConvWeights* cw, uint64_t* seed, cudaStream_t stream) { + PrecisionTensor wt = {.data = cw->w.data, .shape = {cw->OC, cw->IC * cw->K * cw->K}}; + puf_kaiming_init(&wt, 1.0f, (*seed)++, stream); + cudaMemsetAsync(cw->b.data, 0, numel(cw->b.shape) * sizeof(precision_t), stream); +} + +// ---- Forward / Backward ---- + +// Fused conv + bias + activation. All NCHW. Saves input for backward. +static void conv_forward(ConvWeights* cw, ConvActivations* ca, void* input, int B, cudaStream_t stream) { + cudnnHandle_t h = get_cudnn_handle(); + CHECK_CUDNN(cudnnSetStream(h, stream)); + float alpha = 1.0f, beta = 0.0f; + if (ca->saved_input.data) { + cudaMemcpyAsync(ca->saved_input.data, input, + (int64_t)B * cw->IC * cw->IH * cw->IW * sizeof(precision_t), cudaMemcpyDeviceToDevice, stream); + } + CHECK_CUDNN(cudnnConvolutionBiasActivationForward(h, + &alpha, ca->cudnn_in, input, cw->cudnn_filt, cw->w.data, + cw->cudnn_conv, ca->fwd_algo, ca->fwd_ws, ca->fwd_ws_bytes, + &beta, ca->cudnn_out, ca->out.data, cw->cudnn_bias, cw->b.data, + cw->cudnn_act, ca->cudnn_out, ca->out.data)); +} + +// Backward: upstream grad in ca->grad, relu mask in ca->out. +// Caller must apply relu backward and bias grad (dtype-specific kernels). +// This does cuDNN filter grad + optional data grad. +static void conv_backward(ConvWeights* cw, ConvActivations* ca, void* input_grad, int B, cudaStream_t stream) { + cudnnHandle_t h = get_cudnn_handle(); + CHECK_CUDNN(cudnnSetStream(h, stream)); + float alpha = 1.0f, beta = 0.0f; + + CHECK_CUDNN(cudnnConvolutionBackwardFilter(h, + &alpha, ca->cudnn_in, ca->saved_input.data, ca->cudnn_out, ca->grad.data, + cw->cudnn_conv, ca->bwd_filt_algo, ca->bwd_filt_ws, ca->bwd_filt_ws_bytes, + &beta, cw->cudnn_filt, ca->wgrad.data)); + + if (input_grad) { + CHECK_CUDNN(cudnnConvolutionBackwardData(h, + &alpha, cw->cudnn_filt, cw->w.data, ca->cudnn_out, ca->grad.data, + cw->cudnn_conv, ca->bwd_data_algo, ca->bwd_data_ws, ca->bwd_data_ws_bytes, + &beta, ca->cudnn_in, input_grad)); + } +} + +#endif // CUDNN_CONV2D_CU diff --git a/src/kernels.cu b/src/kernels.cu new file mode 100644 index 0000000000..d7c74ab77b --- /dev/null +++ b/src/kernels.cu @@ -0,0 +1,443 @@ +#ifndef PUFFERLIB_KERNELS_CU +#define PUFFERLIB_KERNELS_CU + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#ifdef PRECISION_FLOAT +typedef float precision_t; +constexpr bool USE_BF16 = false; +constexpr int PRECISION_SIZE = 4; +static constexpr cudaDataType_t CUBLAS_PRECISION = CUDA_R_32F; +static constexpr cublasComputeType_t CUBLAS_COMPUTE_PRECISION = CUBLAS_COMPUTE_32F; +#define NCCL_PRECISION ncclFloat +#define to_float(x) (x) +#define from_float(x) (x) +#else +typedef __nv_bfloat16 precision_t; +constexpr bool USE_BF16 = true; +constexpr int PRECISION_SIZE = 2; +static constexpr cudaDataType_t CUBLAS_PRECISION = CUDA_R_16BF; +static constexpr cublasComputeType_t CUBLAS_COMPUTE_PRECISION = CUBLAS_COMPUTE_32F; +#define NCCL_PRECISION ncclBfloat16 +#define to_float(x) __bfloat162float(x) +#define from_float(x) __float2bfloat16(x) +#endif + +#include "tensor.h" + +__host__ __device__ inline int ndim(const int64_t* shape) { + int n = 0; while (n < PUF_MAX_DIMS && shape[n] != 0) n++; return n; +} + +__host__ __device__ inline int64_t numel(const int64_t* shape) { + int64_t n = 1; for (int i = 0; i < PUF_MAX_DIMS && shape[i] != 0; i++) n *= shape[i]; return n; +} + +inline int64_t batch_size(const int64_t* shape) { + int n = ndim(shape); + int64_t b = 1; + for (int i = 0; i < n - 2; i++) b *= shape[i]; + return b; +} + +inline const char* _puf_repr_impl(const char* name, const char* dtype, + const int64_t* shape, int nd, int64_t ne, bool empty) { + static thread_local char buf[256]; + if (empty) { snprintf(buf, sizeof(buf), "%s(empty)", name); return buf; } + int pos = snprintf(buf, sizeof(buf), "%s(%s, [", name, dtype); + for (int i = 0; i < nd && pos < (int)sizeof(buf) - 32; i++) + pos += snprintf(buf + pos, sizeof(buf) - pos, "%s%lld", i ? ", " : "", (long long)shape[i]); + snprintf(buf + pos, sizeof(buf) - pos, "], %lld elems)", (long long)ne); + return buf; +} + +inline const char* puf_repr(const PrecisionTensor* t) { + return _puf_repr_impl("PrecisionTensor", USE_BF16 ? "bf16" : "f32", + t->shape, ndim(t->shape), numel(t->shape), !t->data); +} + +inline const char* puf_repr(const FloatTensor* t) { + return _puf_repr_impl("FloatTensor", "f32", + t->shape, ndim(t->shape), numel(t->shape), !t->data); +} + +#ifndef CUDART_INF_F +#define CUDART_INF_F __int_as_float(0x7f800000) +#endif + +#define PPO_THREADS 256 +#define SELECT_COPY_THREADS 256 +#define MAX_ATN_HEADS 16 + + +#define BLOCK_SIZE 256 +inline int grid_size(int N) { + return (N + BLOCK_SIZE - 1) / BLOCK_SIZE; +} + +#define SEQ_SIZE 256 +inline int seq_size(int N) { + return (N + SEQ_SIZE - 1) / SEQ_SIZE; +} + +#define SOFTPLUS_BETA 1.0f +#define SOFTPLUS_THRESHOLD 20.0f +__device__ __forceinline__ float softplus_fwd(float x) { + float x_scaled = x * SOFTPLUS_BETA; + return (x_scaled > SOFTPLUS_THRESHOLD) ? x : log1pf(expf(x_scaled)) / SOFTPLUS_BETA; +} + +__device__ __forceinline__ float softplus_bwd(float grad_output, float x) { + float beta_x = SOFTPLUS_BETA * x; + if (beta_x > SOFTPLUS_THRESHOLD) { + return grad_output; + } + float exp_beta_x = expf(beta_x); + return grad_output * (exp_beta_x / (1.0f + exp_beta_x)); +} + +__device__ __forceinline__ float relu(float x) { + return fmaxf(0.0f, x); +} + +__device__ __forceinline__ float relu_backward(float x, float grad_output) { + return (x > 0.0f) ? grad_output : 0.0f; +} + +__device__ __forceinline__ float sigmoid(float x) { + float z = expf(-fabsf(x)); + return x >= 0.0f ? 1.0f / (1.0f + z) : z / (1.0f + z); +} + +__device__ __forceinline__ float sigmoid_backward(float x, float grad_output) { + float sig = sigmoid(x); + return grad_output * sig * (1.0f - sig); +} + +__device__ __inline__ float fast_tanh(float x) { + float v1 = fminf(fmaxf(x, -9.0f), 9.0f); + float v2 = v1 * v1; + float p = v2 * -2.76076847742355e-16f + 2.00018790482477e-13f; + p = v2 * p + -8.60467152213735e-11f; + p = v2 * p + 5.12229709037114e-08f; + p = v2 * p + 1.48572235717979e-05f; + p = v2 * p + 6.37261928875436e-04f; + p = v2 * p + 4.89352455891786e-03f; + p = v1 * p; + float q = v2 * 1.19825839466702e-06f + 1.18534705686654e-04f; + q = v2 * q + 2.26843463243900e-03f; + q = v2 * q + 4.89352518554385e-03f; + return p / q; +} + +__device__ __inline__ float fast_sigmoid(float x) { + return fminf(1.0f, fmaxf(0.0f, (fast_tanh(x * 0.5f) + 1.0f) * 0.5f)); +} + +__device__ __forceinline__ float lerp(float a, float b, float w) { + float diff = b - a; + return (fabsf(w) < 0.5f) ? a + w * diff : b - diff * (1.0f - w); +} + +__device__ __forceinline__ float logaddexp(float a, float b) { + float m = fmaxf(a, b), diff = fminf(a, b) - m; + return (diff < -88.0f) ? m : m + log1pf(__expf(diff)); +} + +__device__ __forceinline__ void copy_bytes(const char* __restrict__ src, + char* __restrict__ dst, int src_row, int dst_row, int row_bytes) { + const int* soffset = (const int*)(src + (int64_t)src_row * row_bytes); + int* doffset = (int*)(dst + (int64_t)dst_row * row_bytes); + for (int i = threadIdx.x; i < row_bytes / 4; i += blockDim.x) { + doffset[i] = soffset[i]; + } +} + +// Transpose dims 0,1: [A, B, C] -> [B, A, C]. For 2D, pass C=1. +__global__ void transpose_102(precision_t* __restrict__ dst, + const precision_t* __restrict__ src, int A, int B, int C) { + int idx = blockIdx.x * blockDim.x + threadIdx.x; + int total = A * B * C; + if (idx >= total) { + return; + } + int a = idx / (B * C), rem = idx % (B * C), b = rem / C, c = rem % C; + dst[b * A * C + a * C + c] = src[idx]; +} + +__global__ void fill_precision_kernel(precision_t* __restrict__ dst, precision_t val, int n) { + int idx = blockIdx.x * blockDim.x + threadIdx.x; + if (idx < n) { + dst[idx] = val; + } +} + +__global__ void clamp_precision_kernel(precision_t* __restrict__ dst, float lo, float hi, int n) { + int idx = blockIdx.x * blockDim.x + threadIdx.x; + if (idx < n) { + float v = to_float(dst[idx]); + dst[idx] = from_float(fminf(fmaxf(v, lo), hi)); + } +} + +__global__ void add_kernel(float* __restrict__ dst, const precision_t* __restrict__ src, int n) { + int idx = blockIdx.x * blockDim.x + threadIdx.x; + if (idx < n) { + dst[idx] += to_float(src[idx]); + } +} + +#ifndef PRECISION_FLOAT +__global__ void add_kernel(precision_t* __restrict__ dst, const precision_t* __restrict__ src, int n) { + int idx = blockIdx.x * blockDim.x + threadIdx.x; + if (idx < n) { + dst[idx] = from_float(to_float(dst[idx]) + to_float(src[idx])); + } +} +#endif + +// merge shape[dim] into shape[dim+1] --- +inline PrecisionTensor* puf_squeeze(PrecisionTensor* t, int dim) { + int n = ndim(t->shape); + t->shape[dim + 1] *= t->shape[dim]; + for (int i = dim; i < n - 1; i++) t->shape[i] = t->shape[i + 1]; + t->shape[n - 1] = 0; + return t; +} +inline FloatTensor* puf_squeeze(FloatTensor* t, int dim) { + int n = ndim(t->shape); + t->shape[dim + 1] *= t->shape[dim]; + for (int i = dim; i < n - 1; i++) t->shape[i] = t->shape[i + 1]; + t->shape[n - 1] = 0; + return t; +} + +// split shape[dim] into {d0, d1} --- +inline PrecisionTensor* puf_unsqueeze(PrecisionTensor* t, int dim, int64_t d0, int64_t d1) { + assert(d0 * d1 == t->shape[dim] && "puf_unsqueeze: d0 * d1 must equal shape[dim]"); + int n = ndim(t->shape); + for (int i = n; i > dim; i--) t->shape[i] = t->shape[i - 1]; + t->shape[dim] = d0; + t->shape[dim + 1] = d1; + return t; +} + +// Dense row-major GEMM: C(M,N) = alpha * op_a(A) @ op_b(B) + beta * C +// Strides derived from M, N, K assuming tightly packed row-major storage. +static const size_t CUBLAS_WS_BYTES = 32 * 1024 * 1024; + +static cublasHandle_t cublas_get_handle() { + static thread_local cublasHandle_t handle = nullptr; + if (!handle) { + cublasCreate(&handle); + void* ws = nullptr; + cudaMalloc(&ws, CUBLAS_WS_BYTES); + cublasSetWorkspace(handle, ws, CUBLAS_WS_BYTES); + } + return handle; +} + +static inline void cublasGemmExDense( + cublasOperation_t op_a, cublasOperation_t op_b, + int M, int N, int K, void* A, void* B, void* C, + cudaStream_t stream, float alpha = 1.0f, float beta = 0.0f) { + int lda = (op_a == CUBLAS_OP_N) ? K : M; + int ldb = (op_b == CUBLAS_OP_N) ? N : K; + + cublasHandle_t handle = cublas_get_handle(); + cublasSetStream(handle, stream); + cublasGemmEx(handle, op_b, op_a, N, M, K, &alpha, + B, CUBLAS_PRECISION, ldb, A, CUBLAS_PRECISION, lda, &beta, + C, CUBLAS_PRECISION, N, CUBLAS_COMPUTE_PRECISION, CUBLAS_GEMM_DEFAULT); +} + +// out(...,N) = a(...,K) @ b(N,K)^T — leading dims folded into M +void puf_mm(PrecisionTensor* a, PrecisionTensor* b, PrecisionTensor* out, cudaStream_t stream) { + int M = batch_size(a->shape) * a->shape[ndim(a->shape)-2]; + int K = a->shape[ndim(a->shape)-1]; + int N = b->shape[ndim(b->shape)-2]; + cublasGemmExDense(CUBLAS_OP_N, CUBLAS_OP_T, M, N, K, + a->data, b->data, out->data, stream); +} + +// out(M,N) = a(...,M)^T @ b(...,N) — leading dims folded into K +void puf_mm_tn(PrecisionTensor* a, PrecisionTensor* b, PrecisionTensor* out, cudaStream_t stream) { + int M = a->shape[ndim(a->shape)-1]; + int K = batch_size(a->shape) * a->shape[ndim(a->shape)-2]; + int N = b->shape[ndim(b->shape)-1]; + cublasGemmExDense(CUBLAS_OP_T, CUBLAS_OP_N, M, N, K, + a->data, b->data, out->data, stream); +} + +// out(...,N) = a(...,K) @ b(K,N) — leading dims folded into M +void puf_mm_nn(PrecisionTensor* a, PrecisionTensor* b, PrecisionTensor* out, cudaStream_t stream) { + int M = batch_size(a->shape) * a->shape[ndim(a->shape)-2]; + int K = a->shape[ndim(a->shape)-1]; + int N = b->shape[ndim(b->shape)-1]; + cublasGemmExDense(CUBLAS_OP_N, CUBLAS_OP_N, M, N, K, + a->data, b->data, out->data, stream); +} + +static void puf_addmm_nn(PrecisionTensor* a, PrecisionTensor* b, PrecisionTensor* out, + float alpha, float beta, cudaStream_t stream) { + int M = batch_size(a->shape) * a->shape[ndim(a->shape)-2]; + int K = a->shape[ndim(a->shape)-1]; + int N = b->shape[ndim(b->shape)-1]; + cublasGemmExDense(CUBLAS_OP_N, CUBLAS_OP_N, M, N, K, + a->data, b->data, out->data, stream, alpha, beta); +} + +__global__ void cast(precision_t* __restrict__ dst, + const float* __restrict__ src, int n) { + int idx = blockIdx.x * blockDim.x + threadIdx.x; + if (idx < n) { + dst[idx] = from_float(src[idx]); + } +} + +#ifndef PRECISION_FLOAT +__global__ void cast(float* __restrict__ dst, + const precision_t* __restrict__ src, int n) { + int idx = blockIdx.x * blockDim.x + threadIdx.x; + if (idx < n) { + dst[idx] = to_float(src[idx]); + } +} +#endif + +__global__ void cast(precision_t* __restrict__ dst, + const unsigned char* __restrict__ src, int n) { + int idx = blockIdx.x * blockDim.x + threadIdx.x; + if (idx < n) { + dst[idx] = from_float((float)src[idx]); + } +} + +__global__ void cast(unsigned char* __restrict__ dst, + const precision_t* __restrict__ src, int n) { + int idx = blockIdx.x * blockDim.x + threadIdx.x; + if (idx < n) { + dst[idx] = to_float(src[idx]); + } +} + +void puf_copy(PrecisionTensor* dst, const PrecisionTensor* src, cudaStream_t stream) { + assert(numel(dst->shape) == numel(src->shape) && "puf_copy: size mismatch"); + cudaMemcpyAsync(dst->data, src->data, numel(dst->shape) * sizeof(precision_t), cudaMemcpyDeviceToDevice, stream); +} + +void puf_zero(PrecisionTensor* dst, cudaStream_t stream) { + cudaMemsetAsync(dst->data, 0, numel(dst->shape) * sizeof(precision_t), stream); +} + +void puf_zero(FloatTensor* dst, cudaStream_t stream) { + cudaMemsetAsync(dst->data, 0, numel(dst->shape) * sizeof(float), stream); +} + +__global__ void uniform_scale_kernel(float* data, float bound, int n) { + int idx = blockIdx.x * blockDim.x + threadIdx.x; + if (idx < n) data[idx] = data[idx] * 2.0f * bound - bound; +} + +// Uniform(-1/sqrt(fan_in), 1/sqrt(fan_in)) +void puf_kaiming_init(PrecisionTensor* dst, float gain, ulong seed, cudaStream_t stream) { + assert(ndim(dst->shape) == 2); + long rows = dst->shape[0], cols = dst->shape[1]; + assert(rows > 0 && cols > 0); + long n = rows * cols; + float bound = gain / std::sqrt((float)cols); + float* buf; + cudaMalloc(&buf, n * sizeof(float)); + curandGenerator_t gen; + curandCreateGenerator(&gen, CURAND_RNG_PSEUDO_DEFAULT); + curandSetPseudoRandomGeneratorSeed(gen, seed); + curandGenerateUniform(gen, buf, n); + curandDestroyGenerator(gen); + uniform_scale_kernel<<>>(buf, bound, n); + cast<<>>(dst->data, buf, n); + cudaFree(buf); +} + +// Normal(0, std). Used for embeddings +void puf_normal_init(PrecisionTensor* dst, float std, ulong seed, cudaStream_t stream) { + long n = numel(dst->shape); + assert(n > 0); + long rand_count = (n % 2 == 0) ? n : n + 1; + float* buf; + cudaMalloc(&buf, rand_count * sizeof(float)); + curandGenerator_t gen; + curandCreateGenerator(&gen, CURAND_RNG_PSEUDO_DEFAULT); + curandSetPseudoRandomGeneratorSeed(gen, seed); + curandGenerateNormal(gen, buf, rand_count, 0.0f, std); + curandDestroyGenerator(gen); + cast<<>>(dst->data, buf, n); + cudaFree(buf); +} + +struct AllocEntry { + void** data_ptr; // address of the tensor's data field + int64_t* shape; // pointer to the tensor's shape array + int elem_size; // sizeof element type +}; + +struct Allocator { + AllocEntry* regs = nullptr; + int num_regs = 0; + void* mem = nullptr; + long total_elems = 0; + long total_bytes = 0; +}; + +static void alloc_register_impl(Allocator* alloc, void** data_ptr, int64_t* shape, int elem_size) { + alloc->regs = (AllocEntry*)realloc(alloc->regs, (alloc->num_regs + 1) * sizeof(AllocEntry)); + alloc->regs[alloc->num_regs++] = {data_ptr, shape, elem_size}; + int64_t n = numel(shape); + alloc->total_elems += n; + alloc->total_bytes = (alloc->total_bytes + 15) & ~15; + alloc->total_bytes += n * elem_size; +} +void alloc_register(Allocator* a, PrecisionTensor* t) { + alloc_register_impl(a, (void**)&t->data, t->shape, sizeof(precision_t)); +} +void alloc_register(Allocator* a, FloatTensor* t) { + alloc_register_impl(a, (void**)&t->data, t->shape, sizeof(float)); +} +void alloc_register(Allocator* a, LongTensor* t) { + alloc_register_impl(a, (void**)&t->data, t->shape, sizeof(long)); +} +void alloc_register(Allocator* a, IntTensor* t) { + alloc_register_impl(a, (void**)&t->data, t->shape, sizeof(int)); +} + +cudaError_t alloc_create(Allocator* alloc) { + if (alloc->total_bytes == 0) return cudaSuccess; + cudaError_t err = cudaMalloc(&alloc->mem, alloc->total_bytes); + if (err != cudaSuccess) return err; + cudaMemset(alloc->mem, 0, alloc->total_bytes); + long offset = 0; + for (int i = 0; i < alloc->num_regs; i++) { + offset = (offset + 15) & ~15; + *alloc->regs[i].data_ptr = (char*)alloc->mem + offset; + offset += numel(alloc->regs[i].shape) * alloc->regs[i].elem_size; + } + return cudaSuccess; +} + +void alloc_free(Allocator* alloc) { + if (alloc->mem) { cudaFree(alloc->mem); alloc->mem = nullptr; } + if (alloc->regs) { free(alloc->regs); alloc->regs = nullptr; } + alloc->num_regs = 0; + alloc->total_elems = 0; + alloc->total_bytes = 0; +} + +#endif // PUFFERLIB_KERNELS_CU diff --git a/src/models.cu b/src/models.cu new file mode 100644 index 0000000000..2ba14caa43 --- /dev/null +++ b/src/models.cu @@ -0,0 +1,853 @@ +// Removed vector dependency for MinGRU activations - now uses raw pointers + +#ifndef PUFFERLIB_MODELS_CU +#define PUFFERLIB_MODELS_CU + +#include +#include +#include + +#include "kernels.cu" + +// Signatures used by encoder and decoder. Writing custom nets in 4.0 requires a fair bit of code, +// because you are responsible for defining your own activation and gradient buffers. +// In practice, this is fairly simple. See our Encoder and Decoder for examples. +// You probably only ever need a custom Encoder +typedef void (*init_weights_fn)(void* weights, ulong* seed, cudaStream_t stream); +typedef void (*reg_params_fn)(void* weights, Allocator* alloc); +typedef void (*reg_train_fn)(void* weights, void* buf, Allocator* acts, Allocator* grads, int B_TT); +typedef void (*reg_rollout_fn)(void* weights, void* buf, Allocator* alloc, int B); +typedef void* (*create_weights_fn)(void* self); +typedef void (*free_weights_fn)(void* weights); +typedef void (*free_activations_fn)(void* activations); +typedef PrecisionTensor (*forward_fn)(void* weights, void* activations, PrecisionTensor input, cudaStream_t stream); +typedef void (*encoder_backward_fn)(void* weights, void* activations, + PrecisionTensor grad, cudaStream_t stream); +typedef PrecisionTensor (*decoder_backward_fn)(void* weights, void* activations, + FloatTensor grad_logits, FloatTensor grad_logstd, FloatTensor grad_value, cudaStream_t stream); +typedef PrecisionTensor (*network_forward_fn)(void* weights, PrecisionTensor x, + PrecisionTensor state, void* activations, cudaStream_t stream); +typedef PrecisionTensor (*network_forward_train_fn)(void* weights, PrecisionTensor x, + PrecisionTensor state, void* activations, cudaStream_t stream); +typedef PrecisionTensor (*network_backward_fn)(void* weights, + PrecisionTensor grad, void* activations, cudaStream_t stream); + +struct Encoder { + forward_fn forward; + encoder_backward_fn backward; + init_weights_fn init_weights; + reg_params_fn reg_params; + reg_train_fn reg_train; + reg_rollout_fn reg_rollout; + create_weights_fn create_weights; + free_weights_fn free_weights; + free_activations_fn free_activations; + int in_dim, out_dim; + size_t activation_size; // sizeof(EncoderActivations) or custom override +}; + +struct Decoder { + forward_fn forward; + decoder_backward_fn backward; + init_weights_fn init_weights; + reg_params_fn reg_params; + reg_train_fn reg_train; + reg_rollout_fn reg_rollout; + create_weights_fn create_weights; + free_weights_fn free_weights; + free_activations_fn free_activations; + int hidden_dim, output_dim; + bool continuous; +}; + +struct Network { + network_forward_fn forward; + network_forward_train_fn forward_train; + network_backward_fn backward; + init_weights_fn init_weights; + reg_params_fn reg_params; + reg_train_fn reg_train; + reg_rollout_fn reg_rollout; + create_weights_fn create_weights; + free_weights_fn free_weights; + free_activations_fn free_activations; + int hidden, num_layers, horizon; +}; + +struct EncoderWeights { + PrecisionTensor weight; + int in_dim, out_dim; +}; + +struct EncoderActivations { + PrecisionTensor out, saved_input, wgrad_scratch; +}; + +// The core of 4.0 is the MinGRU fused scan operation. This allows us to parallelize +// training across the sequence dimension and scale to longer sequences +__device__ __forceinline__ void log_coeffs_and_values_fwd(float gate, float hidden, + float* log_coeff_out, float* log_value_out) { + float abs_gate = fabsf(gate); + float sp_neg = log1pf(expf(-abs_gate)); + float softplus_gate = (gate >= 0.0f) ? gate + sp_neg : sp_neg; + float softplus_neg_gate = (gate >= 0.0f) ? sp_neg : -gate + sp_neg; + *log_coeff_out = -softplus_gate; + float log_tilde_h = (hidden >= 0.0f) ? logf(hidden + 0.5f) : -softplus_fwd(-hidden); + *log_value_out = -softplus_neg_gate + log_tilde_h; +} + +__device__ __forceinline__ void log_coeffs_and_values_bwd(float grad_log_coeffs, float grad_log_values, + float gate, float hidden, float* grad_gate_out, float* grad_hidden_out) { + float sig_gate = sigmoid(gate); + *grad_gate_out = -grad_log_coeffs * sig_gate + grad_log_values * (1.0f - sig_gate); + *grad_hidden_out = (hidden >= 0.0f) ? grad_log_values / (hidden + 0.5f) : grad_log_values * sigmoid(-hidden); +} + +__global__ void mingru_gate(precision_t* out, precision_t* next_state, + const precision_t* combined, const precision_t* state_in, + const precision_t* x_in, int H, int B) { + int idx = blockIdx.x * blockDim.x + threadIdx.x; + int N = B * H; + if (idx >= N) { + return; + } + + int b = idx / H; + int h = idx % H; + + // combined = linear(x_in) = (B, H) -> (B, 3*H) + int combined_base = b * 3 * H; + float hidden = to_float(combined[combined_base + h]); + float gate = to_float(combined[combined_base + H + h]); + float proj = to_float(combined[combined_base + 2*H + h]); + float state = to_float(state_in[idx]); + float x = to_float(x_in[idx]); + + // mingru_gate computation + float gate_sigmoid = sigmoid(gate); + float hidden_tilde = (hidden >= 0.0f) ? hidden + 0.5f : fast_sigmoid(hidden); + float mingru_out = lerp(state, hidden_tilde, gate_sigmoid); + + // next_state is mingru_out (for recurrence) + next_state[idx] = from_float(mingru_out); + + // Highway connection: sigmoid(proj) * mingru_out + (1 - sigmoid(proj)) * x (highway gate) + float proj_sigmoid = sigmoid(proj); + out[idx] = from_float(proj_sigmoid * mingru_out + (1.0f - proj_sigmoid) * x); +} + +// Prefix scan buffers +struct PrefixScan { + precision_t* combined_ptr = nullptr; + precision_t* state_ptr = nullptr; + precision_t* input_ptr = nullptr; // (B, T, H) original input before projection (for highway gate) + int B = 0, T = 0, H = 0; + FloatTensor a_star, s_vals, log_values_buf; + PrecisionTensor out, next_state; + PrecisionTensor grad_combined, grad_state; + PrecisionTensor grad_input; // (B, T, H) highway gate gradient w.r.t. input +}; + +// Checkpointing trades off partial recomputation for memory bandwidth. +#define CHECKPOINT_INTERVAL 4 +__global__ void mingru_scan_forward(PrefixScan scan) { + int T_seq = scan.T, H = scan.H, B = scan.B; + precision_t* __restrict__ out = scan.out.data; + precision_t* __restrict__ next_state = scan.next_state.data; + float* __restrict__ a_star_buf = scan.a_star.data; + float* __restrict__ s_buf = scan.s_vals.data; + float* __restrict__ log_values_buf = scan.log_values_buf.data; + const precision_t* __restrict__ combined = scan.combined_ptr; + const precision_t* __restrict__ state = scan.state_ptr; + const precision_t* __restrict__ input = scan.input_ptr; + + int idx = blockIdx.x * blockDim.x + threadIdx.x; + if (idx >= B * H) { + return; + } + + int b = idx / H; + int h = idx % H; + + int bH = b * H; + int H3 = 3 * H; + int H2 = 2 * H; + int bHT = bH * T_seq; + int out_base = bHT + h; + int cbase = 3 * bHT; + + float a_star = 0.0f; + float log_value = 0.0f; + + // Handle t=0 outside the loop: use log(state), coeff = 0 + float s = __logf(to_float(state[bH + h])); + log_value = s; + + int T_out = T_seq + 1; + int buf_base = b * T_out * H + h; + int buf_curr = buf_base; + a_star_buf[buf_curr] = a_star; + s_buf[buf_curr] = s; + log_values_buf[buf_curr] = log_value; + + const precision_t* combined_h_base = &combined[cbase + h]; + const precision_t* combined_g_base = &combined[cbase + H + h]; + const precision_t* combined_p_base = &combined[cbase + H2 + h]; + + // Loop t=1..T_seq with sparse checkpointing + float scan_result = 0.0f; + int out_curr = out_base; + int t_offset = 0; + + for (int t = 1; t < T_seq + 1; t++) { + float hidden_val = to_float(combined_h_base[t_offset]); + float gate_val = to_float(combined_g_base[t_offset]); + float proj_val = to_float(combined_p_base[t_offset]); + float x_val = to_float(input[out_base + (t - 1) * H]); + + float log_coeff_val; + log_coeffs_and_values_fwd(gate_val, hidden_val, &log_coeff_val, &log_value); + + // a_star[t] = sum_{i=0}^t log_coeffs[i] + a_star += log_coeff_val; + + float z = log_value - a_star; + s = logaddexp(s, z); + + scan_result = __expf(a_star + s); + float proj_sigmoid = sigmoid(proj_val); + + // out = sigmoid(proj) * scan_result + (1 - sigmoid(proj)) * x (highway gate) + out[out_curr] = from_float(proj_sigmoid * scan_result + (1.0f - proj_sigmoid) * x_val); + + buf_curr += H; + out_curr += H; + t_offset += H3; + + if (t % CHECKPOINT_INTERVAL == 0) { + a_star_buf[buf_curr] = a_star; + s_buf[buf_curr] = s; + log_values_buf[buf_curr] = log_value; + } + } + + // Write timestep T to next_state (raw scan_result, no proj, for recurrence) + next_state[bH + h] = from_float(scan_result); +} + +// Reads sparse checkpoints from forward pass, recomputes intermediate values in chunks +__global__ void mingru_scan_backward(PrefixScan scan, + const precision_t* __restrict__ grad_out, + const precision_t* __restrict__ grad_next_state) { + int T_seq = scan.T, H = scan.H, B = scan.B; + precision_t* __restrict__ grad_combined = scan.grad_combined.data; + precision_t* __restrict__ grad_state = scan.grad_state.data; + precision_t* __restrict__ grad_input = scan.grad_input.data; + const precision_t* __restrict__ combined = scan.combined_ptr; + const precision_t* __restrict__ state = scan.state_ptr; + const precision_t* __restrict__ input = scan.input_ptr; + const float* __restrict__ a_star_buf = scan.a_star.data; + const float* __restrict__ s_buf = scan.s_vals.data; + const float* __restrict__ log_values_buf = scan.log_values_buf.data; + + int idx = blockIdx.x * blockDim.x + threadIdx.x; + if (idx >= B * H) { + return; + } + + int b = idx / H; + int h = idx % H; + + int bHT = b * H * T_seq; + int cbase = 3 * bHT; + int H3 = 3 * H; + int H2 = 2 * H; + const int state_idx = b * H + h; + const int out_base = bHT + h; + + const precision_t* combined_h_base = &combined[cbase + h]; + const precision_t* combined_g_base = &combined[cbase + H + h]; + const precision_t* combined_p_base = &combined[cbase + H2 + h]; + + precision_t* grad_combined_h_base = &grad_combined[cbase + h]; + precision_t* grad_combined_g_base = &grad_combined[cbase + H + h]; + precision_t* grad_combined_p_base = &grad_combined[cbase + H2 + h]; + + int T_out = T_seq + 1; + int buf_base = b * T_out * H + h; + + float acc = 0.0; + float s_val_next = 0.0; + float carry_grad_a = 0.0; + + for (int chunk_end = T_seq; chunk_end > 0; chunk_end -= CHECKPOINT_INTERVAL) { + int chunk_start = (chunk_end > CHECKPOINT_INTERVAL) ? (chunk_end - CHECKPOINT_INTERVAL) : 0; + int chunk_len = chunk_end - chunk_start; + + // Chunk storage in registers + float chunk_a_star[CHECKPOINT_INTERVAL]; + float chunk_s[CHECKPOINT_INTERVAL]; + float chunk_log_values[CHECKPOINT_INTERVAL]; + float chunk_hidden[CHECKPOINT_INTERVAL]; + float chunk_gate[CHECKPOINT_INTERVAL]; + + // Load checkpoint from global memory + int ckpt_buf_idx = buf_base + chunk_start * H; + float recomp_a_star = a_star_buf[ckpt_buf_idx]; + float recomp_s = s_buf[ckpt_buf_idx]; + float recomp_log_value = log_values_buf[ckpt_buf_idx]; + + // Recompute and store from chunk_start to chunk_end + for (int i = 0; i < chunk_len; ++i) { + int t = chunk_start + 1 + i; + int t_offset = (t - 1) * H3; + float hv = to_float(combined_h_base[t_offset]); + float gv = to_float(combined_g_base[t_offset]); + + float lc; + log_coeffs_and_values_fwd(gv, hv, &lc, &recomp_log_value); + recomp_a_star += lc; + + float z = recomp_log_value - recomp_a_star; + recomp_s = logaddexp(recomp_s, z); + + chunk_a_star[i] = recomp_a_star; + chunk_s[i] = recomp_s; + chunk_log_values[i] = recomp_log_value; + chunk_hidden[i] = hv; + chunk_gate[i] = gv; + } + + for (int i = chunk_len - 1; i >= 0; --i) { + int t = chunk_start + 1 + i; + int t_offset = (t - 1) * H3; + + float a_star_t = chunk_a_star[i]; + float s_t = chunk_s[i]; + float log_value_t = chunk_log_values[i]; + float hidden_val = chunk_hidden[i]; + float gate_val = chunk_gate[i]; + + float proj_val = to_float(combined_p_base[t_offset]); + int input_idx = out_base + (t - 1) * H; + float x_val = to_float(input[input_idx]); + + float scan_result = __expf(a_star_t + s_t); + float z = log_value_t - a_star_t; + + float grad_out_val = to_float(grad_out[input_idx]); + float grad_scan_from_next = (t == T_seq) ? to_float(grad_next_state[state_idx]) : 0.0f; + float proj_sigmoid = sigmoid(proj_val); + + // Highway gate gradients: out = sigmoid(proj) * scan_result + (1 - sigmoid(proj)) * x + float grad_scan_result = grad_scan_from_next + grad_out_val * proj_sigmoid; + float grad_proj = grad_out_val * (scan_result - x_val) * proj_sigmoid * (1.0f - proj_sigmoid); + grad_input[input_idx] = from_float(grad_out_val * (1.0f - proj_sigmoid)); + + float grad_log_h = grad_scan_result * scan_result; + float grad_s = grad_log_h; + + if (t == T_seq) { + acc = grad_s; + } else { + acc = grad_s + acc * __expf(s_t - s_val_next); + } + float grad_z = acc * __expf(z - s_t); + s_val_next = s_t; + + float grad_a = grad_log_h + carry_grad_a - grad_z; + carry_grad_a = grad_a; + + float grad_g, grad_h; + log_coeffs_and_values_bwd(grad_a, grad_z, gate_val, hidden_val, &grad_g, &grad_h); + + grad_combined_h_base[t_offset] = from_float(grad_h); + grad_combined_g_base[t_offset] = from_float(grad_g); + grad_combined_p_base[t_offset] = from_float(grad_proj); + } + } + + int ckpt_0_idx = buf_base; + float a_star_0 = a_star_buf[ckpt_0_idx]; + float s_0 = s_buf[ckpt_0_idx]; + float log_value_0 = log_values_buf[ckpt_0_idx]; + + float scan_result_0 = __expf(a_star_0 + s_0); + float z_0 = log_value_0 - a_star_0; + + float grad_scan_result_0 = 0.0f; + float grad_log_h_0 = grad_scan_result_0 * scan_result_0; + float grad_s_0 = grad_log_h_0; + + acc = grad_s_0 + acc * __expf(s_0 - s_val_next); + float grad_z_0 = acc * __expf(z_0 - s_0); + + grad_state[state_idx] = from_float(grad_z_0 / to_float(state[state_idx])); +} + +__global__ void sum_rows_to_precision_kernel(precision_t* __restrict__ dst, + const float* __restrict__ src, int R, int C) { + int col = blockIdx.x * blockDim.x + threadIdx.x; + if (col >= C) { + return; + } + float sum = 0.0f; + for (int r = 0; r < R; r++) { + sum += src[r * C + col]; + } + dst[col] = from_float(sum); +} + +__global__ void assemble_decoder_grad( + precision_t* __restrict__ dst, const float* __restrict__ grad_logits, + const float* __restrict__ grad_value, int B_TT, int od, int od_plus_1) { + int idx = blockIdx.x * blockDim.x + threadIdx.x; + if (idx >= B_TT * od_plus_1) { + return; + } + int row = idx / od_plus_1, col = idx % od_plus_1; + dst[idx] = from_float((col < od) ? grad_logits[row * od + col] : grad_value[row]); +} + +static PrecisionTensor encoder_forward(void* w, void* activations, PrecisionTensor input, cudaStream_t stream) { + EncoderWeights* ew = (EncoderWeights*)w; + EncoderActivations* a = (EncoderActivations*)activations; + if (a->saved_input.data) puf_copy(&a->saved_input, &input, stream); + puf_mm(&input, &ew->weight, &a->out, stream); + return a->out; +} + +static void encoder_backward(void* w, void* activations, PrecisionTensor grad, cudaStream_t stream) { + EncoderActivations* a = (EncoderActivations*)activations; + puf_mm_tn(&grad, &a->saved_input, &a->wgrad_scratch, stream); +} + +static void encoder_init_weights(void* w, ulong* seed, cudaStream_t stream) { + EncoderWeights* ew = (EncoderWeights*)w; + PrecisionTensor wt = { + .data = ew->weight.data, + .shape = {ew->out_dim, ew->in_dim}, + }; + puf_kaiming_init(&wt, std::sqrt(2.0f), (*seed)++, stream); +} + +static void encoder_reg_params(void* w, Allocator* alloc) { + EncoderWeights* ew = (EncoderWeights*)w; + ew->weight = {.shape = {ew->out_dim, ew->in_dim}}; + alloc_register(alloc,&ew->weight); +} + +static void encoder_reg_train(void* w, void* activations, Allocator* acts, Allocator* grads, int B_TT) { + EncoderWeights* ew = (EncoderWeights*)w; + EncoderActivations* a = (EncoderActivations*)activations; + *a = (EncoderActivations){ + .out = {.shape = {B_TT, ew->out_dim}}, + .saved_input = {.shape = {B_TT, ew->in_dim}}, + .wgrad_scratch = {.shape = {ew->out_dim, ew->in_dim}}, + }; + alloc_register(acts,&a->out); + alloc_register(acts,&a->saved_input); + alloc_register(grads,&a->wgrad_scratch); +} + +static void encoder_reg_rollout(void* w, void* activations, Allocator* alloc, int B) { + EncoderWeights* ew = (EncoderWeights*)w; + EncoderActivations* a = (EncoderActivations*)activations; + a->out = {.shape = {B, ew->out_dim}}; + alloc_register(alloc,&a->out); +} + +static void* encoder_create_weights(void* self) { + Encoder* e = (Encoder*)self; + EncoderWeights* ew = (EncoderWeights*)calloc(1, sizeof(EncoderWeights)); + ew->in_dim = e->in_dim; ew->out_dim = e->out_dim; + return ew; +} + +static void encoder_free_weights(void* weights) { + free(weights); +} + +static void encoder_free_activations(void* activations) { + free(activations); +} + +struct DecoderWeights { + PrecisionTensor weight, logstd; + int hidden_dim, output_dim; + bool continuous; +}; + +struct DecoderActivations { + PrecisionTensor out, grad_out, saved_input, grad_input, wgrad_scratch, logstd_scratch; +}; + +static PrecisionTensor decoder_forward(void* w, void* activations, PrecisionTensor input, cudaStream_t stream) { + DecoderWeights* dw = (DecoderWeights*)w; + DecoderActivations* a = (DecoderActivations*)activations; + if (a->saved_input.data) { + puf_copy(&a->saved_input, &input, stream); + } + puf_mm(&input, &dw->weight, &a->out, stream); + return a->out; +} + +static void decoder_init_weights(void* w, ulong* seed, cudaStream_t stream) { + DecoderWeights* dw = (DecoderWeights*)w; + PrecisionTensor wt = { + .data = dw->weight.data, + .shape = {dw->output_dim + 1, dw->hidden_dim}, + }; + puf_kaiming_init(&wt, 1.0f, (*seed)++, stream); +} + +static void decoder_reg_params(void* w, Allocator* alloc) { + DecoderWeights* dw = (DecoderWeights*)w; + dw->weight = {.shape = {dw->output_dim + 1, dw->hidden_dim}}; + alloc_register(alloc,&dw->weight); + if (dw->continuous) { + dw->logstd = {.shape = {1, dw->output_dim}}; + alloc_register(alloc,&dw->logstd); + } +} + +static void decoder_reg_train(void* w, void* activations, Allocator* acts, Allocator* grads, int B_TT) { + DecoderWeights* dw = (DecoderWeights*)w; + DecoderActivations* a = (DecoderActivations*)activations; + int od1 = dw->output_dim + 1; + *a = (DecoderActivations){ + .out = {.shape = {B_TT, od1}}, + .grad_out = {.shape = {B_TT, od1}}, + .saved_input = {.shape = {B_TT, dw->hidden_dim}}, + .grad_input = {.shape = {B_TT, dw->hidden_dim}}, + .wgrad_scratch = {.shape = {od1, dw->hidden_dim}}, + .logstd_scratch = {.shape = {1, dw->output_dim}}, + }; + alloc_register(acts,&a->out); + alloc_register(acts,&a->saved_input); + alloc_register(acts,&a->grad_out); + alloc_register(acts,&a->grad_input); + alloc_register(grads,&a->wgrad_scratch); + if (dw->continuous) alloc_register(grads,&a->logstd_scratch); +} + +static void decoder_reg_rollout(void* w, void* activations, Allocator* alloc, int B) { + DecoderWeights* dw = (DecoderWeights*)w; + DecoderActivations* a = (DecoderActivations*)activations; + a->out = {.shape = {B, dw->output_dim + 1}}; + alloc_register(alloc,&a->out); +} + +static void* decoder_create_weights(void* self) { + Decoder* d = (Decoder*)self; + DecoderWeights* dw = (DecoderWeights*)calloc(1, sizeof(DecoderWeights)); + dw->hidden_dim = d->hidden_dim; dw->output_dim = d->output_dim; dw->continuous = d->continuous; + return dw; +} + +static void decoder_free_weights(void* weights) { + free(weights); +} + +static void decoder_free_activations(void* activations) { + free(activations); +} + +static PrecisionTensor decoder_backward(void* w, void* activations, + FloatTensor grad_logits, FloatTensor grad_logstd, FloatTensor grad_value, cudaStream_t stream) { + DecoderWeights* dw = (DecoderWeights*)w; + DecoderActivations* a = (DecoderActivations*)activations; + int B_TT = a->saved_input.shape[0]; + int od = dw->output_dim, od1 = od + 1; + assemble_decoder_grad<<>>( + a->grad_out.data, grad_logits.data, grad_value.data, B_TT, od, od1); + puf_mm_tn(&a->grad_out, &a->saved_input, &a->wgrad_scratch, stream); + if (dw->continuous && grad_logstd.data != nullptr) { + sum_rows_to_precision_kernel<<output_dim), BLOCK_SIZE, 0, stream>>>( + a->logstd_scratch.data, grad_logstd.data, B_TT, dw->output_dim); + } + puf_mm_nn(&a->grad_out, &dw->weight, &a->grad_input, stream); + return a->grad_input; +} + +struct MinGRUActivations { + int num_layers; + // Rollout + PrecisionTensor* combined; // (B rollout, 3*T)[num_layers] + PrecisionTensor out; // (B rollout, T) + PrecisionTensor next_state; // (B rollout, T) + // Training + PrecisionTensor* saved_inputs; // (B, TT, T)[num_layers] + PrefixScan* scan_bufs; // [num_layers] + PrecisionTensor* combined_bufs; // (B*TT, 3*T)[num_layers] + PrecisionTensor* wgrad_scratch; // (3*T, T)[num_layers] + PrecisionTensor grad_input_buf; // (B*TT, T) + PrecisionTensor grad_next_state; // (B, 1, T) +}; + +void mingru_activations_free(MinGRUActivations* a) { + free(a->combined); + free(a->saved_inputs); + free(a->scan_bufs); + free(a->combined_bufs); + free(a->wgrad_scratch); +} + +struct MinGRUWeights { + int hidden, num_layers, horizon; + PrecisionTensor* weights; // [num_layers] +}; + +static PrecisionTensor mingru_state_layer(MinGRUWeights* m, PrecisionTensor& state, int i) { + long B = state.shape[1], H = state.shape[2]; + return {.data = state.data + i * B * H, .shape = {B, H}}; +} + +static void mingru_init_weights(void* w, ulong* seed, cudaStream_t stream) { + MinGRUWeights* m = (MinGRUWeights*)w; + for (int i = 0; i < m->num_layers; i++) { + PrecisionTensor w2d = { + .data = m->weights[i].data, + .shape = {3 * m->hidden, m->hidden}, + }; + puf_kaiming_init(&w2d, 1.0f, (*seed)++, stream); + } +} + +static void mingru_reg_params(void* w, Allocator* alloc) { + MinGRUWeights* m = (MinGRUWeights*)w; + for (int i = 0; i < m->num_layers; i++) { + m->weights[i] = {.shape = {3 * m->hidden, m->hidden}}; + alloc_register(alloc,&m->weights[i]); + } +} + +static void mingru_reg_train(void* w, void* activations, Allocator* acts, Allocator* grads, int B_TT) { + MinGRUWeights* m = (MinGRUWeights*)w; + MinGRUActivations* a = (MinGRUActivations*)activations; + int H = m->hidden, TT = m->horizon, B = B_TT / TT; + a->num_layers = m->num_layers; + a->saved_inputs = (PrecisionTensor*)calloc(m->num_layers, sizeof(PrecisionTensor)); + a->scan_bufs = (PrefixScan*)calloc(m->num_layers, sizeof(PrefixScan)); + a->combined_bufs = (PrecisionTensor*)calloc(m->num_layers, sizeof(PrecisionTensor)); + a->wgrad_scratch = (PrecisionTensor*)calloc(m->num_layers, sizeof(PrecisionTensor)); + a->grad_input_buf = {.shape = {B_TT, H}}; + a->grad_next_state = {.shape = {B, 1, H}}; + alloc_register(acts,&a->grad_input_buf); + alloc_register(acts,&a->grad_next_state); + for (int i = 0; i < m->num_layers; i++) { + a->scan_bufs[i] = { + .B = B, .T = TT, .H = H, + .a_star = {.shape = {B, TT + 1, H}}, + .s_vals = {.shape = {B, TT + 1, H}}, + .log_values_buf = {.shape = {B, TT + 1, H}}, + .out = {.shape = {B, TT, H}}, + .next_state = {.shape = {B, 1, H}}, + .grad_combined = {.shape = {B, TT, 3 * H}}, + .grad_state = {.shape = {B, 1, H}}, + .grad_input = {.shape = {B, TT, H}}, + }; + a->saved_inputs[i] = {.shape = {B, TT, H}}; + a->combined_bufs[i] = {.shape = {B_TT, 3 * H}}; + a->wgrad_scratch[i] = {.shape = {3 * H, H}}; + alloc_register(acts,&a->saved_inputs[i]); + alloc_register(acts,&a->combined_bufs[i]); + alloc_register(acts,&a->scan_bufs[i].out); + alloc_register(acts,&a->scan_bufs[i].next_state); + alloc_register(acts,&a->scan_bufs[i].a_star); + alloc_register(acts,&a->scan_bufs[i].s_vals); + alloc_register(acts,&a->scan_bufs[i].log_values_buf); + alloc_register(acts,&a->scan_bufs[i].grad_combined); + alloc_register(acts,&a->scan_bufs[i].grad_state); + alloc_register(acts,&a->scan_bufs[i].grad_input); + alloc_register(grads,&a->wgrad_scratch[i]); + } +} + +static void mingru_reg_rollout(void* weights, void* activations, Allocator* alloc, int B_inf) { + MinGRUWeights* w = (MinGRUWeights*)weights; + MinGRUActivations* a = (MinGRUActivations*)activations; + int H = w->hidden; + a->num_layers = w->num_layers; + a->combined = (PrecisionTensor*)calloc(w->num_layers, sizeof(PrecisionTensor)); + for (int i = 0; i < w->num_layers; i++) { + a->combined[i] = {.shape = {B_inf, 3 * H}}; + alloc_register(alloc,&a->combined[i]); + } + a->out = {.shape = {B_inf, H}}; + a->next_state = {.shape = {B_inf, H}}; + alloc_register(alloc,&a->out); + alloc_register(alloc,&a->next_state); +} + +static void* mingru_create_weights(void* self) { + Network* n = (Network*)self; + MinGRUWeights* mw = (MinGRUWeights*)calloc(1, sizeof(MinGRUWeights)); + mw->hidden = n->hidden; mw->num_layers = n->num_layers; mw->horizon = n->horizon; + mw->weights = (PrecisionTensor*)calloc(n->num_layers, sizeof(PrecisionTensor)); + return mw; +} + +static void mingru_free_weights(void* weights) { + MinGRUWeights* mw = (MinGRUWeights*)weights; + free(mw->weights); + free(mw); +} + +static void mingru_free_activations(void* activations) { + MinGRUActivations* a = (MinGRUActivations*)activations; + mingru_activations_free(a); + free(a); +} + +static PrecisionTensor mingru_forward(void* w, PrecisionTensor x, PrecisionTensor state, + void* activations, cudaStream_t stream) { + MinGRUWeights* m = (MinGRUWeights*)w; + MinGRUActivations* a = (MinGRUActivations*)activations; + int B = state.shape[1]; + int H = state.shape[2]; + for (int i = 0; i < m->num_layers; i++) { + PrecisionTensor state_i = mingru_state_layer(m, state, i); + puf_mm(&x, &m->weights[i], &a->combined[i], stream); + mingru_gate<<>>( + a->out.data, a->next_state.data, + a->combined[i].data, state_i.data, x.data, H, B); + puf_copy(&state_i, &a->next_state, stream); + x = a->out; + } + return x; +} + +static PrecisionTensor mingru_forward_train(void* w, PrecisionTensor x, PrecisionTensor state, + void* activations, cudaStream_t stream) { + MinGRUWeights* m = (MinGRUWeights*)w; + MinGRUActivations* a = (MinGRUActivations*)activations; + int B = x.shape[0]; + for (int i = 0; i < m->num_layers; i++) { + puf_copy(&a->saved_inputs[i], &x, stream); + PrecisionTensor state_i = mingru_state_layer(m, state, i); + puf_mm(&x, &m->weights[i], &a->combined_bufs[i], stream); + a->scan_bufs[i].combined_ptr = a->combined_bufs[i].data; + a->scan_bufs[i].state_ptr = state_i.data; + a->scan_bufs[i].input_ptr = a->saved_inputs[i].data; + mingru_scan_forward<<hidden), BLOCK_SIZE, 0, stream>>>(a->scan_bufs[i]); + x = a->scan_bufs[i].out; + } + return x; +} + +static PrecisionTensor mingru_backward(void* w, PrecisionTensor grad, void* activations, cudaStream_t stream) { + MinGRUWeights* m = (MinGRUWeights*)w; + MinGRUActivations* a = (MinGRUActivations*)activations; + for (int i = m->num_layers - 1; i >= 0; i--) { + PrefixScan& scan = a->scan_bufs[i]; + mingru_scan_backward<<>>( + scan, grad.data, a->grad_next_state.data); + puf_mm_tn(&scan.grad_combined, &a->saved_inputs[i], &a->wgrad_scratch[i], stream); + puf_mm_nn(&scan.grad_combined, &m->weights[i], &a->grad_input_buf, stream); + int n = numel(scan.grad_input.shape); + add_kernel<<>>( + a->grad_input_buf.data, scan.grad_input.data, n); + grad = a->grad_input_buf; + } + return grad; +} + +struct Policy { + Encoder encoder; + Decoder decoder; + Network network; + int input_dim, hidden_dim, output_dim; + int num_atns; +}; + +struct PolicyActivations { + void* encoder; + void* decoder; + void* network; +}; + +struct PolicyWeights { + void* encoder; + void* decoder; + void* network; +}; + +static void policy_activations_free(Policy* p, PolicyActivations& a) { + p->encoder.free_activations(a.encoder); + p->decoder.free_activations(a.decoder); + p->network.free_activations(a.network); +} + +PrecisionTensor policy_forward(Policy* p, PolicyWeights& w, PolicyActivations& activations, + PrecisionTensor obs, PrecisionTensor state, cudaStream_t stream) { + PrecisionTensor enc_out = p->encoder.forward(w.encoder, activations.encoder, obs, stream); + PrecisionTensor h = p->network.forward(w.network, enc_out, state, activations.network, stream); + return p->decoder.forward(w.decoder, activations.decoder, h, stream); +} + +PrecisionTensor policy_forward_train(Policy* p, PolicyWeights& w, PolicyActivations& activations, + PrecisionTensor x, PrecisionTensor state, cudaStream_t stream) { + int B = x.shape[0], TT = x.shape[1]; + PrecisionTensor h = p->encoder.forward(w.encoder, activations.encoder, *puf_squeeze(&x, 0), stream); + h = p->network.forward_train(w.network, *puf_unsqueeze(&h, 0, B, TT), state, activations.network, stream); + PrecisionTensor dec_out = p->decoder.forward(w.decoder, activations.decoder, *puf_squeeze(&h, 0), stream); + return *puf_unsqueeze(&dec_out, 0, B, TT); +} + +void policy_backward(Policy* p, PolicyWeights& w, PolicyActivations& activations, + FloatTensor grad_logits, FloatTensor grad_logstd, FloatTensor grad_value, cudaStream_t stream) { + int B = grad_logits.shape[0], TT = grad_logits.shape[1]; + PrecisionTensor grad_h = p->decoder.backward(w.decoder, activations.decoder, + *puf_squeeze(&grad_logits, 0), grad_logstd, *puf_squeeze(&grad_value, 0), stream); + grad_h = p->network.backward(w.network, *puf_unsqueeze(&grad_h, 0, B, TT), activations.network, stream); + p->encoder.backward(w.encoder, activations.encoder, grad_h, stream); +} + +PolicyActivations policy_reg_train(Policy* p, PolicyWeights& w, + Allocator* acts, Allocator* grads, int B_TT) { + PolicyActivations a; + a.encoder = calloc(1, p->encoder.activation_size); + a.decoder = calloc(1, sizeof(DecoderActivations)); + a.network = calloc(1, sizeof(MinGRUActivations)); + p->encoder.reg_train(w.encoder, a.encoder, acts, grads, B_TT); + p->decoder.reg_train(w.decoder, a.decoder, acts, grads, B_TT); + p->network.reg_train(w.network, a.network, acts, grads, B_TT); + return a; +} + +PolicyActivations policy_reg_rollout(Policy* p, PolicyWeights& w, Allocator* acts, int B_inf) { + PolicyActivations a; + a.encoder = calloc(1, p->encoder.activation_size); + a.decoder = calloc(1, sizeof(DecoderActivations)); + a.network = calloc(1, sizeof(MinGRUActivations)); + p->encoder.reg_rollout(w.encoder, a.encoder, acts, B_inf); + p->decoder.reg_rollout(w.decoder, a.decoder, acts, B_inf); + p->network.reg_rollout(w.network, a.network, acts, B_inf); + return a; +} + +void policy_init_weights(Policy* p, PolicyWeights& w, uint64_t* seed, cudaStream_t stream) { + p->encoder.init_weights(w.encoder, seed, stream); + p->decoder.init_weights(w.decoder, seed, stream); + p->network.init_weights(w.network, seed, stream); +} + +PolicyWeights policy_weights_create(Policy* p, Allocator* params) { + PolicyWeights w; + w.encoder = p->encoder.create_weights(&p->encoder); + w.decoder = p->decoder.create_weights(&p->decoder); + w.network = p->network.create_weights(&p->network); + p->encoder.reg_params(w.encoder, params); + p->decoder.reg_params(w.decoder, params); + p->network.reg_params(w.network, params); + return w; +} + +void policy_weights_free(Policy* p, PolicyWeights* w) { + p->encoder.free_weights(w->encoder); + p->decoder.free_weights(w->decoder); + p->network.free_weights(w->network); +} + +#endif // PUFFERLIB_MODELS_CU diff --git a/src/muon.cu b/src/muon.cu new file mode 100644 index 0000000000..1665dcf1ee --- /dev/null +++ b/src/muon.cu @@ -0,0 +1,227 @@ +#include + +__global__ void muon_norm_reduce(float* __restrict__ out, const float* __restrict__ partials, int num_blocks) { + __shared__ float sdata[256]; + int tid = threadIdx.x; + sdata[tid] = (tid < num_blocks) ? partials[tid] : 0.0f; + __syncthreads(); + for (int s = blockDim.x / 2; s > 0; s >>= 1) { + if (tid < s) { + sdata[tid] += sdata[tid + s]; + } + __syncthreads(); + } + if (tid == 0) { + *out = sdata[0]; + } +} + +__global__ void muon_norm_partials(float* __restrict__ partials, const precision_t* __restrict__ src, int n) { + __shared__ float sdata[256]; + int tid = threadIdx.x; + float sum = 0.0f; + for (int i = blockIdx.x * blockDim.x + tid; i < n; i += blockDim.x * gridDim.x) { + float v = to_float(src[i]); + sum += v * v; + } + sdata[tid] = sum; + __syncthreads(); + for (int s = blockDim.x / 2; s > 0; s >>= 1) { + if (tid < s) { + sdata[tid] += sdata[tid + s]; + } + __syncthreads(); + } + if (tid == 0) { + partials[blockIdx.x] = sdata[0]; + } +} + +__global__ void muon_norm_apply(precision_t* __restrict__ dst, const float* __restrict__ norm_ptr, float eps, int n) { + float inv_norm = 1.0f / fmaxf(sqrtf(*norm_ptr), eps); + int idx = blockIdx.x * blockDim.x + threadIdx.x; + if (idx < n) { + dst[idx] = from_float(to_float(dst[idx]) * inv_norm); + } +} + +// Nesterov with f32 momentum accumulator and precision_t gradients +__global__ void muon_nesterov(float* __restrict__ mb, precision_t* __restrict__ gc, float mu, int n) { + int idx = blockIdx.x * blockDim.x + threadIdx.x; + if (idx < n) { + float m = mu * mb[idx] + to_float(gc[idx]); + mb[idx] = m; + gc[idx] = from_float(to_float(gc[idx]) + mu * m); + } +} + +// Fused weight update: wb = wb * (1 - lr*wd) - lr * scale * update +__global__ void muon_weight_update(float* __restrict__ wb, const precision_t* __restrict__ update, + const float* __restrict__ lr_ptr, float wd, float scale, int n) { + float lr = *lr_ptr; + float wd_scale = 1.0f - lr * wd; + int idx = blockIdx.x * blockDim.x + threadIdx.x; + if (idx < n) { + wb[idx] = wb[idx] * wd_scale - lr * scale * to_float(update[idx]); + } +} + +__global__ void muon_clip_norm(precision_t* __restrict__ dst, + const float* __restrict__ sum_sq_ptr, float max_norm, float eps, int n) { + float clip_coef = fminf(max_norm / (sqrtf(*sum_sq_ptr) + eps), 1.0f); + int idx = blockIdx.x * blockDim.x + threadIdx.x; + if (idx < n) { + dst[idx] = from_float(to_float(dst[idx]) * clip_coef); + } +} + +static constexpr double ns_coeffs[5][3] = { + {4.0848, -6.8946, 2.9270}, + {3.9505, -6.3029, 2.6377}, + {3.7418, -5.5913, 2.3037}, + {2.8769, -3.1427, 1.2046}, + {2.8366, -3.0525, 1.2012}, +}; + +struct Muon { + double momentum, weight_decay, eps; + float lr_val_init; + float* lr_ptr; + float* lr_derived_ptr; + float* norm_ptr; + float* grad_norm_ptr; + FloatTensor lr_puf, lr_derived_puf, ns_norm_puf, grad_norm_puf; + FloatTensor mb_puf; + PrecisionTensor gram, gram_buf, x_buf; + FloatTensor norm_partials; + long max_M, max_N; + Allocator* param_alloc; // params allocator — shapes used by muon_step + ncclComm_t nccl_comm; + int world_size; +}; + +void muon_init(Muon* m, Allocator* param_alloc, double lr_val, + double momentum, double eps, double weight_decay, + Allocator* alloc) { + m->momentum = momentum; + m->weight_decay = weight_decay; + m->eps = eps; + m->lr_val_init = (float)lr_val; + m->lr_ptr = nullptr; + m->lr_derived_ptr = nullptr; + m->param_alloc = param_alloc; + m->nccl_comm = nullptr; + m->world_size = 1; + m->max_M = 0; m->max_N = 0; + long n = param_alloc->total_elems; + m->lr_puf = {.shape = {1}}; + m->lr_derived_puf = {.shape = {2}}; + m->mb_puf = {.shape = {n}}; + m->norm_partials = {.shape = {256}}; + m->grad_norm_puf = {.shape = {1}}; + alloc_register(alloc, &m->lr_puf); + alloc_register(alloc, &m->lr_derived_puf); + alloc_register(alloc, &m->mb_puf); + alloc_register(alloc, &m->norm_partials); + alloc_register(alloc, &m->grad_norm_puf); + long max_M = 0, max_N = 0; + for (int _i = 0; _i < param_alloc->num_regs; _i++) { + AllocEntry& e = param_alloc->regs[_i]; + if (ndim(e.shape) >= 2) { + long R = e.shape[0], C = numel(e.shape) / R; + max_M = max(max_M, min(R, C)); + max_N = max(max_N, max(R, C)); + } + } + if (max_M > 0) { + m->max_M = max_M; m->max_N = max_N; + m->gram = {.shape = {max_M, max_M}}; + m->gram_buf = {.shape = {max_M, max_M}}; + m->x_buf = {.shape = {max_M, max_N}}; + m->ns_norm_puf = {.shape = {1}}; + alloc_register(alloc, &m->gram); + alloc_register(alloc, &m->gram_buf); + alloc_register(alloc, &m->x_buf); + alloc_register(alloc, &m->ns_norm_puf); + } +} + +void muon_post_create(Muon* m) { + m->lr_ptr = m->lr_puf.data; + m->lr_derived_ptr = m->lr_derived_puf.data; + m->grad_norm_ptr = m->grad_norm_puf.data; + if (m->ns_norm_puf.data) m->norm_ptr = m->ns_norm_puf.data; + cudaMemcpy(m->lr_ptr, &m->lr_val_init, sizeof(float), cudaMemcpyHostToDevice); + cudaMemset(m->lr_derived_ptr, 0, 2 * sizeof(float)); + cudaMemset(m->mb_puf.data, 0, numel(m->mb_puf.shape) * sizeof(float)); +} + +void muon_step(Muon* m, FloatTensor weights, PrecisionTensor grads, float max_grad_norm, cudaStream_t stream = 0) { + // Multi-GPU support: simple all-reduce over a contiguous grad buffer + if (m->nccl_comm != nullptr && m->world_size > 1) { + ncclAllReduce(grads.data, grads.data, numel(grads.shape), + NCCL_PRECISION, ncclAvg, m->nccl_comm, stream); + } + + // Clip gradients by norm + int clip_blocks = min((int)grid_size(numel(grads.shape)), 256); + muon_norm_partials<<>>( + m->norm_partials.data, grads.data, numel(grads.shape)); + muon_norm_reduce<<<1, 256, 0, stream>>>(m->grad_norm_ptr, m->norm_partials.data, clip_blocks); + muon_clip_norm<<>>( + grads.data, m->grad_norm_ptr, max_grad_norm, 1e-6f, numel(grads.shape)); + + // Nesterov momentum + muon_nesterov<<mb_puf.shape)), BLOCK_SIZE, 0, stream>>>( + m->mb_puf.data, grads.data, (float)m->momentum, numel(m->mb_puf.shape)); + + long offset = 0; + for (int _i = 0; _i < m->param_alloc->num_regs; _i++) { + AllocEntry& e = m->param_alloc->regs[_i]; + precision_t* gc_ptr = grads.data + offset; + float* wb_ptr = weights.data + offset; + long ne = numel(e.shape); + const precision_t* update_ptr = gc_ptr; + float scale = 1.0f; + + // Orthogonalize the update + if (ndim(e.shape) >= 2) { + long R = e.shape[0], C = ne / R; + long M = min(R, C), N = max(R, C); + bool tall = R > C; + PrecisionTensor x = {.data = gc_ptr, .shape = {R, C}}; + PrecisionTensor x_buf = {.data = m->x_buf.data, .shape = {R, C}}; + PrecisionTensor gram = {.data = m->gram.data, .shape = {M, M}}; + PrecisionTensor gram_buf = {.data = m->gram_buf.data, .shape = {M, M}}; + + int nblk = min((int)grid_size(numel(x.shape)), 256); + muon_norm_partials<<>>( + m->norm_partials.data, x.data, numel(x.shape)); + muon_norm_reduce<<<1, 256, 0, stream>>>(m->norm_ptr, m->norm_partials.data, nblk); + muon_norm_apply<<>>( + x.data, m->norm_ptr, 1e-7f, numel(x.shape)); + + cublasOperation_t gram_op_a = tall ? CUBLAS_OP_T : CUBLAS_OP_N; + cublasOperation_t gram_op_b = tall ? CUBLAS_OP_N : CUBLAS_OP_T; + for (int i = 0; i < 5; ++i) { + PrecisionTensor& src = (i % 2 == 0) ? x : x_buf; + PrecisionTensor& dst = (i % 2 == 0) ? x_buf : x; + cublasGemmExDense(gram_op_a, gram_op_b, (int)M, (int)M, (int)N, + src.data, src.data, gram.data, stream); + puf_copy(&gram_buf, &gram, stream); + puf_addmm_nn(&gram, &gram, &gram_buf, ns_coeffs[i][2], ns_coeffs[i][1], stream); + puf_copy(&dst, &src, stream); + cublasGemmExDense(CUBLAS_OP_N, CUBLAS_OP_N, (int)R, (int)C, (int)M, + tall ? src.data : gram_buf.data, tall ? gram_buf.data : src.data, dst.data, + stream, 1.0f, ns_coeffs[i][0]); + } + + update_ptr = x_buf.data; + scale = sqrtf(fmaxf(1.0f, (float)R / (float)C)); + } + + muon_weight_update<<>>( + wb_ptr, update_ptr, m->lr_ptr, (float)m->weight_decay, scale, (int)ne); + offset += ne; + } +} diff --git a/src/ocean.cu b/src/ocean.cu new file mode 100644 index 0000000000..baaa9b7be6 --- /dev/null +++ b/src/ocean.cu @@ -0,0 +1,590 @@ +// NMMO3 CUDA encoder: multihot, cuDNN conv, embedding, concat, projection +// Included by pufferlib.cu — requires precision_t, PrecisionTensor, Allocator, puf_mm, etc. + +#include "cudnn_conv2d.cu" + +// ---- NMMO3 constants ---- + +static constexpr int N3_MAP_H = 11, N3_MAP_W = 15, N3_NFEAT = 10; +static constexpr int N3_MULTIHOT = 59; +static constexpr int N3_MAP_SIZE = N3_MAP_H * N3_MAP_W * N3_NFEAT; +static constexpr int N3_PLAYER = 47, N3_REWARD = 10; +static constexpr int N3_EMBED_DIM = 32, N3_EMBED_VOCAB = 128; +static constexpr int N3_PLAYER_EMBED = N3_PLAYER * N3_EMBED_DIM; +static constexpr int N3_C1_IC = 59, N3_C1_OC = 128, N3_C1_K = 5, N3_C1_S = 3; +static constexpr int N3_C1_OH = 3, N3_C1_OW = 4; +static constexpr int N3_C2_IC = 128, N3_C2_OC = 128, N3_C2_K = 3, N3_C2_S = 1; +static constexpr int N3_C2_OH = 1, N3_C2_OW = 2; +static constexpr int N3_CONV_FLAT = N3_C2_OC * N3_C2_OH * N3_C2_OW; +static constexpr int N3_CONCAT = N3_CONV_FLAT + N3_PLAYER_EMBED + N3_PLAYER + N3_REWARD; + +__constant__ int N3_OFFSETS[10] = {0, 4, 8, 25, 30, 33, 38, 43, 48, 55}; + +static cudnnDataType_t n3_cudnn_dtype() { + return (PRECISION_SIZE == 2) ? CUDNN_DATA_BFLOAT16 : CUDNN_DATA_FLOAT; +} + +// ---- NMMO3 kernels ---- + +__global__ void n3_multihot_kernel( + precision_t* __restrict__ out, const precision_t* __restrict__ obs, int B, int obs_size) { + int idx = blockIdx.x * blockDim.x + threadIdx.x; + if (idx >= B * N3_MAP_H * N3_MAP_W) return; + int b = idx / (N3_MAP_H * N3_MAP_W), rem = idx % (N3_MAP_H * N3_MAP_W); + int h = rem / N3_MAP_W, w = rem % N3_MAP_W; + const precision_t* src = obs + b * obs_size + (h * N3_MAP_W + w) * N3_NFEAT; + precision_t* dst = out + b * N3_MULTIHOT * N3_MAP_H * N3_MAP_W; + for (int f = 0; f < N3_NFEAT; f++) + dst[(N3_OFFSETS[f] + (int)to_float(src[f])) * N3_MAP_H * N3_MAP_W + h * N3_MAP_W + w] = from_float(1.0f); +} + +__global__ void n3_embedding_kernel( + precision_t* __restrict__ out, const precision_t* __restrict__ obs, + const precision_t* __restrict__ embed_w, int B, int obs_size) { + int idx = blockIdx.x * blockDim.x + threadIdx.x; + if (idx >= B * N3_PLAYER) return; + int b = idx / N3_PLAYER, f = idx % N3_PLAYER; + int val = (int)to_float(obs[b * obs_size + N3_MAP_SIZE + f]); + const precision_t* src = embed_w + val * N3_EMBED_DIM; + precision_t* dst = out + b * N3_PLAYER_EMBED + f * N3_EMBED_DIM; + for (int d = 0; d < N3_EMBED_DIM; d++) dst[d] = src[d]; +} + +__global__ void n3_concat_kernel( + precision_t* __restrict__ out, const precision_t* __restrict__ conv_flat, + const precision_t* __restrict__ embed, const precision_t* __restrict__ obs, + int B, int obs_size) { + int idx = blockIdx.x * blockDim.x + threadIdx.x; + if (idx >= B * N3_CONCAT) return; + int b = idx / N3_CONCAT, c = idx % N3_CONCAT; + precision_t val; + if (c < N3_CONV_FLAT) { + int oc = c / (N3_C2_OH * N3_C2_OW), r = c % (N3_C2_OH * N3_C2_OW); + int oh = r / N3_C2_OW, ow = r % N3_C2_OW; + val = conv_flat[b * N3_CONV_FLAT + oc * N3_C2_OH * N3_C2_OW + oh * N3_C2_OW + ow]; + } else if (c < N3_CONV_FLAT + N3_PLAYER_EMBED) + val = embed[b * N3_PLAYER_EMBED + (c - N3_CONV_FLAT)]; + else if (c < N3_CONV_FLAT + N3_PLAYER_EMBED + N3_PLAYER) + val = obs[b * obs_size + N3_MAP_SIZE + (c - N3_CONV_FLAT - N3_PLAYER_EMBED)]; + else + val = obs[b * obs_size + obs_size - N3_REWARD + (c - N3_CONV_FLAT - N3_PLAYER_EMBED - N3_PLAYER)]; + out[idx] = val; +} + +__global__ void n3_bias_relu_kernel( + precision_t* __restrict__ data, const precision_t* __restrict__ bias, int total, int dim) { + int idx = blockIdx.x * blockDim.x + threadIdx.x; + if (idx >= total) return; + data[idx] = from_float(fmaxf(0.0f, to_float(data[idx]) + to_float(bias[idx % dim]))); +} + +__global__ void n3_relu_backward_kernel( + precision_t* __restrict__ grad, const precision_t* __restrict__ out, int total) { + int idx = blockIdx.x * blockDim.x + threadIdx.x; + if (idx >= total) return; + if (to_float(out[idx]) <= 0.0f) grad[idx] = from_float(0.0f); +} + + +__global__ void bias_grad_kernel( + precision_t* __restrict__ bgrad, const precision_t* __restrict__ grad, int N, int dim) { + int d = blockIdx.x; + if (d >= dim) return; + float sum = 0.0f; + for (int i = threadIdx.x; i < N; i += blockDim.x) + sum += to_float(grad[i * dim + d]); + for (int offset = 16; offset > 0; offset >>= 1) + sum += __shfl_down_sync(0xffffffff, sum, offset); + __shared__ float sdata[32]; + int lane = threadIdx.x % 32, warp = threadIdx.x / 32; + if (lane == 0) sdata[warp] = sum; + __syncthreads(); + if (warp == 0) { + sum = (lane < (blockDim.x + 31) / 32) ? sdata[lane] : 0.0f; + for (int offset = 16; offset > 0; offset >>= 1) + sum += __shfl_down_sync(0xffffffff, sum, offset); + if (lane == 0) bgrad[d] = from_float(sum); + } +} + +// NCHW bias grad: sum over (B, OH, OW) for each OC channel +__global__ void n3_conv_bias_grad_nchw( + precision_t* __restrict__ bgrad, const precision_t* __restrict__ grad, + int B, int OC, int spatial) { + int oc = blockIdx.x; + if (oc >= OC) return; + float sum = 0.0f; + int total = B * spatial; + for (int i = threadIdx.x; i < total; i += blockDim.x) { + int b = i / spatial, s = i % spatial; + sum += to_float(grad[b * OC * spatial + oc * spatial + s]); + } + for (int offset = 16; offset > 0; offset >>= 1) + sum += __shfl_down_sync(0xffffffff, sum, offset); + __shared__ float sdata[32]; + int lane = threadIdx.x % 32, warp = threadIdx.x / 32; + if (lane == 0) sdata[warp] = sum; + __syncthreads(); + if (warp == 0) { + sum = (lane < (blockDim.x + 31) / 32) ? sdata[lane] : 0.0f; + for (int offset = 16; offset > 0; offset >>= 1) + sum += __shfl_down_sync(0xffffffff, sum, offset); + if (lane == 0) bgrad[oc] = from_float(sum); + } +} + +__global__ void n3_concat_backward_conv_kernel( + precision_t* __restrict__ conv_grad, const precision_t* __restrict__ concat_grad, int B) { + int idx = blockIdx.x * blockDim.x + threadIdx.x; + if (idx >= B * N3_CONV_FLAT) return; + int b = idx / N3_CONV_FLAT, c = idx % N3_CONV_FLAT; + conv_grad[b * N3_CONV_FLAT + c] = concat_grad[b * N3_CONCAT + c]; +} + +// Embedding backward: scatter-add grad from concat_grad's player_embed region +// into embed_wgrad (float accumulation buffer). +// Each (b, f) looked up row obs[b, MAP_SIZE+f] from the table. +__global__ void n3_embedding_backward_kernel( + float* __restrict__ embed_wgrad_f, + const precision_t* __restrict__ concat_grad, + const precision_t* __restrict__ obs, + int B, int obs_size) { + int idx = blockIdx.x * blockDim.x + threadIdx.x; + if (idx >= B * N3_PLAYER * N3_EMBED_DIM) return; + int b = idx / (N3_PLAYER * N3_EMBED_DIM); + int rem = idx % (N3_PLAYER * N3_EMBED_DIM); + int f = rem / N3_EMBED_DIM; + int d = rem % N3_EMBED_DIM; + int val = (int)to_float(obs[b * obs_size + N3_MAP_SIZE + f]); + float g = to_float(concat_grad[b * N3_CONCAT + N3_CONV_FLAT + f * N3_EMBED_DIM + d]); + atomicAdd(&embed_wgrad_f[val * N3_EMBED_DIM + d], g); +} + +// Cast float buffer to precision_t +__global__ void n3_float_to_precision_kernel( + precision_t* __restrict__ dst, const float* __restrict__ src, int n) { + int idx = blockIdx.x * blockDim.x + threadIdx.x; + if (idx < n) dst[idx] = from_float(src[idx]); +} + +// ---- atomicAdd for precision_t ---- +#ifdef PRECISION_FLOAT +__device__ __forceinline__ void atomicAdd_precision(precision_t* addr, precision_t val) { + atomicAdd(addr, val); +} +#else +__device__ __forceinline__ void atomicAdd_precision(precision_t* addr, precision_t val) { + // bf16 atomicAdd via CAS on enclosing 32-bit word + unsigned int* addr_u32 = (unsigned int*)((size_t)addr & ~2ULL); + bool is_high = ((size_t)addr & 2) != 0; + unsigned int old_u32 = *addr_u32, assumed; + do { + assumed = old_u32; + __nv_bfloat16* pair = (__nv_bfloat16*)&old_u32; + float sum = __bfloat162float(pair[is_high]) + __bfloat162float(val); + unsigned int new_u32 = assumed; + ((__nv_bfloat16*)&new_u32)[is_high] = __float2bfloat16(sum); + old_u32 = atomicCAS(addr_u32, assumed, new_u32); + } while (old_u32 != assumed); +} +#endif + +// ---- NCHW bias kernels for im2col conv path ---- + +__global__ void conv_bias_kernel(precision_t* __restrict__ data, + const precision_t* __restrict__ bias, int B, int OC, int spatial) { + int idx = blockIdx.x * blockDim.x + threadIdx.x; + int total = B * OC * spatial; + if (idx >= total) return; + int oc = (idx / spatial) % OC; + data[idx] = from_float(to_float(data[idx]) + to_float(bias[oc])); +} + +__global__ void conv_bias_relu_kernel(precision_t* __restrict__ data, + const precision_t* __restrict__ bias, int B, int OC, int spatial) { + int idx = blockIdx.x * blockDim.x + threadIdx.x; + int total = B * OC * spatial; + if (idx >= total) return; + int oc = (idx / spatial) % OC; + data[idx] = from_float(fmaxf(0.0f, to_float(data[idx]) + to_float(bias[oc]))); +} + +// ---- im2col + cuBLAS conv (no cuDNN) ---- +// NCHW layout throughout. Weight stored as (OC, IC*K*K). +// im2col produces (B*OH*OW, IC*K*K), matmul with W^T gives (B*OH*OW, OC), +// then reshape to NCHW (B, OC, OH, OW). + +__global__ void im2col_kernel( + const precision_t* __restrict__ input, precision_t* __restrict__ col, + int B, int IC, int IH, int IW, int K, int S, int OH, int OW +) { + int idx = blockIdx.x * blockDim.x + threadIdx.x; + int total = B * OH * OW * IC * K * K; + if (idx >= total) return; + int col_w = IC * K * K; + int row = idx / col_w; + int c = idx % col_w; + int b = row / (OH * OW); + int rem = row % (OH * OW); + int oh = rem / OW, ow = rem % OW; + int ic = c / (K * K), kk = c % (K * K); + int kh = kk / K, kw = kk % K; + int ih = oh * S + kh, iw = ow * S + kw; + col[idx] = input[b * IC * IH * IW + ic * IH * IW + ih * IW + iw]; +} + +// Backward: col2im — input-centric gather to avoid atomics. +// Each thread owns one (b, ic, ih, iw) element and sums contributions from all +// (oh, ow, kh, kw) patches that map to it. +__global__ void col2im_kernel( + const precision_t* __restrict__ col, precision_t* __restrict__ grad_input, + int B, int IC, int IH, int IW, int K, int S, int OH, int OW +) { + int idx = blockIdx.x * blockDim.x + threadIdx.x; + int total = B * IC * IH * IW; + if (idx >= total) return; + int iw = idx % IW; + int ih = (idx / IW) % IH; + int ic = (idx / (IW * IH)) % IC; + int b = idx / (IW * IH * IC); + float sum = 0.0f; + for (int kh = 0; kh < K; kh++) { + int ih_off = ih - kh; + if (ih_off < 0 || ih_off % S != 0) continue; + int oh = ih_off / S; + if (oh >= OH) continue; + for (int kw = 0; kw < K; kw++) { + int iw_off = iw - kw; + if (iw_off < 0 || iw_off % S != 0) continue; + int ow = iw_off / S; + if (ow >= OW) continue; + int col_idx = (b * OH * OW + oh * OW + ow) * (IC * K * K) + ic * K * K + kh * K + kw; + sum += to_float(col[col_idx]); + } + } + grad_input[idx] = from_float(sum); +} + +// Transpose (B, OC, OH, OW) -> (B*OH*OW, OC) [NCHW to row-major spatial-first] +__global__ void nchw_to_rows_kernel( + const precision_t* __restrict__ src, precision_t* __restrict__ dst, + int B, int OC, int spatial +) { + int idx = blockIdx.x * blockDim.x + threadIdx.x; + int total = B * OC * spatial; + if (idx >= total) return; + int b = idx / (OC * spatial); + int oc = (idx / spatial) % OC; + int s = idx % spatial; + dst[(b * spatial + s) * OC + oc] = src[idx]; +} + +// Transpose (B*OH*OW, OC) -> (B, OC, OH, OW) [row-major spatial-first to NCHW] +__global__ void rows_to_nchw_kernel( + const precision_t* __restrict__ src, precision_t* __restrict__ dst, + int B, int OC, int spatial +) { + int idx = blockIdx.x * blockDim.x + threadIdx.x; + int total = B * OC * spatial; + if (idx >= total) return; + int b = idx / (OC * spatial); + int oc = (idx / spatial) % OC; + int s = idx % spatial; + dst[idx] = src[(b * spatial + s) * OC + oc]; +} + +// Forward: im2col conv + bias + optional relu. All NCHW. +// col_buf: pre-allocated (max_B * OH * OW, IC * K * K) +// mm_buf: pre-allocated (max_B * OH * OW, OC) — row-major (spatial-first) +static void gemm_conv_forward( + PrecisionTensor* weight, PrecisionTensor* bias, + precision_t* input, precision_t* output, + precision_t* col_buf, precision_t* mm_buf, + int B, int IC, int IH, int IW, int OC, int K, int S, int OH, int OW, + bool relu, cudaStream_t stream +) { + int col_rows = B * OH * OW; + int col_cols = IC * K * K; + int total_col = col_rows * col_cols; + int total_out = B * OC * OH * OW; + + // im2col: input NCHW -> col (B*OH*OW, IC*K*K) + im2col_kernel<<>>( + input, col_buf, B, IC, IH, IW, K, S, OH, OW); + + // matmul: col (B*OH*OW, IC*K*K) @ W^T (IC*K*K, OC) = mm_buf (B*OH*OW, OC) + PrecisionTensor col_t = {.data = col_buf, .shape = {col_rows, col_cols}}; + PrecisionTensor mm_t = {.data = mm_buf, .shape = {col_rows, OC}}; + puf_mm(&col_t, weight, &mm_t, stream); + + // transpose (B*OH*OW, OC) -> (B, OC, OH, OW) NCHW + bias + relu + int spatial = OH * OW; + rows_to_nchw_kernel<<>>( + mm_buf, output, B, OC, spatial); + if (relu) { + conv_bias_relu_kernel<<>>( + output, bias->data, B, OC, spatial); + } else { + conv_bias_kernel<<>>( + output, bias->data, B, OC, spatial); + } +} + +// Backward: weight grad + optional input grad via im2col/col2im + cuBLAS. +// grad_output is NCHW (B, OC, OH, OW). saved_input is NCHW. +// Caller handles relu backward and bias grad (same as cuDNN path). +static void gemm_conv_backward( + PrecisionTensor* weight, + precision_t* saved_input, precision_t* grad_output, + precision_t* wgrad, precision_t* input_grad, + precision_t* col_buf, precision_t* mm_buf, + int B, int IC, int IH, int IW, int OC, int K, int S, int OH, int OW, + cudaStream_t stream +) { + int col_rows = B * OH * OW; + int col_cols = IC * K * K; + int total_col = col_rows * col_cols; + int total_out = B * OC * OH * OW; + int spatial = OH * OW; + + // Transpose grad_output NCHW -> (B*OH*OW, OC) + nchw_to_rows_kernel<<>>( + grad_output, mm_buf, B, OC, spatial); + + // im2col of saved_input + im2col_kernel<<>>( + saved_input, col_buf, B, IC, IH, IW, K, S, OH, OW); + + // Weight grad: mm_buf^T (OC, B*OH*OW) @ col_buf (B*OH*OW, IC*K*K) = wgrad (OC, IC*K*K) + PrecisionTensor mm_t = {.data = mm_buf, .shape = {col_rows, OC}}; + PrecisionTensor col_t = {.data = col_buf, .shape = {col_rows, col_cols}}; + PrecisionTensor wg_t = {.data = wgrad, .shape = {OC, col_cols}}; + puf_mm_tn(&mm_t, &col_t, &wg_t, stream); + + // Input grad (optional): mm_buf (B*OH*OW, OC) @ weight (OC, IC*K*K) = col_grad (B*OH*OW, IC*K*K) + if (input_grad) { + puf_mm_nn(&mm_t, weight, &col_t, stream); // reuse col_buf as col_grad + col2im_kernel<<>>( + col_buf, input_grad, B, IC, IH, IW, K, S, OH, OW); + } +} + +// ---- NMMO3 encoder structs ---- + +struct NMMO3EncoderWeights { + ConvWeights conv1, conv2; + PrecisionTensor embed_w, proj_w, proj_b; + int obs_size, hidden; +}; + +struct NMMO3EncoderActivations { + ConvActivations conv1, conv2; + PrecisionTensor col1, mm1, col2, mm2; // im2col + matmul scratch buffers + PrecisionTensor multihot, embed_out, concat, out, saved_obs; + PrecisionTensor embed_wgrad, proj_wgrad, proj_bgrad; + FloatTensor embed_wgrad_f; // float accumulation buffer for scatter-add +}; + +static NMMO3EncoderWeights* nmmo3_encoder_create(int obs_size, int hidden) { + NMMO3EncoderWeights* ew = (NMMO3EncoderWeights*)calloc(1, sizeof(NMMO3EncoderWeights)); + ew->obs_size = obs_size; ew->hidden = hidden; + conv_init(&ew->conv1, N3_C1_IC, N3_C1_OC, N3_C1_K, N3_C1_S, N3_MAP_H, N3_MAP_W, true); + conv_init(&ew->conv2, N3_C2_IC, N3_C2_OC, N3_C2_K, N3_C2_S, N3_C1_OH, N3_C1_OW, false); + return ew; +} + +// ---- NMMO3 encoder interface ---- + +static PrecisionTensor nmmo3_encoder_forward(void* w, void* activations, PrecisionTensor input, cudaStream_t stream) { + NMMO3EncoderWeights* ew = (NMMO3EncoderWeights*)w; + NMMO3EncoderActivations* a = (NMMO3EncoderActivations*)activations; + int B = input.shape[0]; + + if (a->saved_obs.data) puf_copy(&a->saved_obs, &input, stream); + + cudaMemsetAsync(a->multihot.data, 0, (int64_t)B * N3_MULTIHOT * N3_MAP_H * N3_MAP_W * sizeof(precision_t), stream); + n3_multihot_kernel<<>>( + a->multihot.data, input.data, B, ew->obs_size); + + gemm_conv_forward(&ew->conv1.w, &ew->conv1.b, a->multihot.data, a->conv1.out.data, + a->col1.data, a->mm1.data, B, N3_C1_IC, N3_MAP_H, N3_MAP_W, + N3_C1_OC, N3_C1_K, N3_C1_S, N3_C1_OH, N3_C1_OW, true, stream); + if (a->conv1.saved_input.data) + cudaMemcpyAsync(a->conv1.saved_input.data, a->multihot.data, + (int64_t)B * N3_C1_IC * N3_MAP_H * N3_MAP_W * sizeof(precision_t), cudaMemcpyDeviceToDevice, stream); + gemm_conv_forward(&ew->conv2.w, &ew->conv2.b, a->conv1.out.data, a->conv2.out.data, + a->col2.data, a->mm2.data, B, N3_C2_IC, N3_C1_OH, N3_C1_OW, + N3_C2_OC, N3_C2_K, N3_C2_S, N3_C2_OH, N3_C2_OW, false, stream); + if (a->conv2.saved_input.data) + cudaMemcpyAsync(a->conv2.saved_input.data, a->conv1.out.data, + (int64_t)B * N3_C2_IC * N3_C1_OH * N3_C1_OW * sizeof(precision_t), cudaMemcpyDeviceToDevice, stream); + + n3_embedding_kernel<<>>( + a->embed_out.data, input.data, ew->embed_w.data, B, ew->obs_size); + n3_concat_kernel<<>>( + a->concat.data, a->conv2.out.data, a->embed_out.data, input.data, B, ew->obs_size); + + puf_mm(&a->concat, &ew->proj_w, &a->out, stream); + n3_bias_relu_kernel<<hidden), BLOCK_SIZE, 0, stream>>>( + a->out.data, ew->proj_b.data, B * ew->hidden, ew->hidden); + return a->out; +} + +static void nmmo3_encoder_backward(void* w, void* activations, PrecisionTensor grad, cudaStream_t stream) { + NMMO3EncoderWeights* ew = (NMMO3EncoderWeights*)w; + NMMO3EncoderActivations* a = (NMMO3EncoderActivations*)activations; + int B = grad.shape[0], H = ew->hidden; + + n3_relu_backward_kernel<<>>( + grad.data, a->out.data, B * H); + bias_grad_kernel<<>>( + a->proj_bgrad.data, grad.data, B, H); + puf_mm_tn(&grad, &a->concat, &a->proj_wgrad, stream); + + PrecisionTensor grad_concat = {.data = a->concat.data, .shape = {B, N3_CONCAT}}; + puf_mm_nn(&grad, &ew->proj_w, &grad_concat, stream); + + n3_concat_backward_conv_kernel<<>>( + a->conv2.grad.data, grad_concat.data, B); + + n3_conv_bias_grad_nchw<<conv2.OC, 256, 0, stream>>>( + a->conv2.bgrad.data, a->conv2.grad.data, + B, ew->conv2.OC, ew->conv2.OH * ew->conv2.OW); + gemm_conv_backward(&ew->conv2.w, a->conv2.saved_input.data, a->conv2.grad.data, + a->conv2.wgrad.data, a->conv1.grad.data, + a->col2.data, a->mm2.data, B, N3_C2_IC, N3_C1_OH, N3_C1_OW, + N3_C2_OC, N3_C2_K, N3_C2_S, N3_C2_OH, N3_C2_OW, stream); + + n3_relu_backward_kernel<<conv1.OC * ew->conv1.OH * ew->conv1.OW), BLOCK_SIZE, 0, stream>>>( + a->conv1.grad.data, a->conv1.out.data, + B * ew->conv1.OC * ew->conv1.OH * ew->conv1.OW); + n3_conv_bias_grad_nchw<<conv1.OC, 256, 0, stream>>>( + a->conv1.bgrad.data, a->conv1.grad.data, + B, ew->conv1.OC, ew->conv1.OH * ew->conv1.OW); + gemm_conv_backward(&ew->conv1.w, a->conv1.saved_input.data, a->conv1.grad.data, + a->conv1.wgrad.data, NULL, + a->col1.data, a->mm1.data, B, N3_C1_IC, N3_MAP_H, N3_MAP_W, + N3_C1_OC, N3_C1_K, N3_C1_S, N3_C1_OH, N3_C1_OW, stream); + + // Embedding backward: scatter-add from concat gradient into float buffer, then cast + int embed_n = N3_EMBED_VOCAB * N3_EMBED_DIM; + cudaMemsetAsync(a->embed_wgrad_f.data, 0, embed_n * sizeof(float), stream); + n3_embedding_backward_kernel<<>>( + a->embed_wgrad_f.data, grad_concat.data, a->saved_obs.data, B, ew->obs_size); + n3_float_to_precision_kernel<<>>( + a->embed_wgrad.data, a->embed_wgrad_f.data, embed_n); +} + +static void nmmo3_encoder_init_weights(void* w, uint64_t* seed, cudaStream_t stream) { + NMMO3EncoderWeights* ew = (NMMO3EncoderWeights*)w; + conv_init_weights(&ew->conv1, seed, stream); + conv_init_weights(&ew->conv2, seed, stream); + auto init2d = [&](PrecisionTensor& t, int rows, int cols, float gain) { + PrecisionTensor wt = {.data = t.data, .shape = {rows, cols}}; + puf_kaiming_init(&wt, gain, (*seed)++, stream); + }; + puf_normal_init(&ew->embed_w, 1.0f, (*seed)++, stream); + init2d(ew->proj_w, ew->hidden, N3_CONCAT, 1.0f); + cudaMemsetAsync(ew->proj_b.data, 0, numel(ew->proj_b.shape) * sizeof(precision_t), stream); +} + +static void nmmo3_encoder_reg_params(void* w, Allocator* alloc) { + NMMO3EncoderWeights* ew = (NMMO3EncoderWeights*)w; + conv_reg_params(&ew->conv1, alloc); + conv_reg_params(&ew->conv2, alloc); + ew->embed_w = {.shape = {N3_EMBED_VOCAB, N3_EMBED_DIM}}; + ew->proj_w = {.shape = {ew->hidden, N3_CONCAT}}; + ew->proj_b = {.shape = {ew->hidden}}; + alloc_register(alloc,&ew->embed_w); + alloc_register(alloc,&ew->proj_w); alloc_register(alloc,&ew->proj_b); +} + +static void nmmo3_encoder_reg_train(void* w, void* activations, Allocator* acts, Allocator* grads, int B_TT) { + NMMO3EncoderWeights* ew = (NMMO3EncoderWeights*)w; + NMMO3EncoderActivations* a = (NMMO3EncoderActivations*)activations; + *a = {}; + a->multihot = {.shape = {B_TT, N3_MULTIHOT * N3_MAP_H * N3_MAP_W}}; + alloc_register(acts,&a->multihot); + // Conv1 buffers + a->conv1.out = {.shape = {B_TT * N3_C1_OC * N3_C1_OH * N3_C1_OW}}; + a->conv1.grad = {.shape = {B_TT * N3_C1_OC * N3_C1_OH * N3_C1_OW}}; + a->conv1.saved_input = {.shape = {B_TT * N3_C1_IC * N3_MAP_H * N3_MAP_W}}; + a->conv1.wgrad = {.shape = {N3_C1_OC, N3_C1_IC * N3_C1_K * N3_C1_K}}; + a->conv1.bgrad = {.shape = {N3_C1_OC}}; + alloc_register(acts,&a->conv1.out); alloc_register(acts,&a->conv1.grad); alloc_register(acts,&a->conv1.saved_input); + alloc_register(grads,&a->conv1.wgrad); alloc_register(grads,&a->conv1.bgrad); + a->col1 = {.shape = {B_TT * N3_C1_OH * N3_C1_OW, N3_C1_IC * N3_C1_K * N3_C1_K}}; + a->mm1 = {.shape = {B_TT * N3_C1_OH * N3_C1_OW, N3_C1_OC}}; + alloc_register(acts,&a->col1); alloc_register(acts,&a->mm1); + // Conv2 buffers + a->conv2.out = {.shape = {B_TT * N3_C2_OC * N3_C2_OH * N3_C2_OW}}; + a->conv2.grad = {.shape = {B_TT * N3_C2_OC * N3_C2_OH * N3_C2_OW}}; + a->conv2.saved_input = {.shape = {B_TT * N3_C2_IC * N3_C1_OH * N3_C1_OW}}; + a->conv2.wgrad = {.shape = {N3_C2_OC, N3_C2_IC * N3_C2_K * N3_C2_K}}; + a->conv2.bgrad = {.shape = {N3_C2_OC}}; + alloc_register(acts,&a->conv2.out); alloc_register(acts,&a->conv2.grad); alloc_register(acts,&a->conv2.saved_input); + alloc_register(grads,&a->conv2.wgrad); alloc_register(grads,&a->conv2.bgrad); + a->col2 = {.shape = {B_TT * N3_C2_OH * N3_C2_OW, N3_C2_IC * N3_C2_K * N3_C2_K}}; + a->mm2 = {.shape = {B_TT * N3_C2_OH * N3_C2_OW, N3_C2_OC}}; + alloc_register(acts,&a->col2); alloc_register(acts,&a->mm2); + a->embed_out = {.shape = {B_TT, N3_PLAYER_EMBED}}; + a->concat = {.shape = {B_TT, N3_CONCAT}}; + a->out = {.shape = {B_TT, ew->hidden}}; + a->saved_obs = {.shape = {B_TT, ew->obs_size}}; + alloc_register(acts,&a->embed_out); alloc_register(acts,&a->concat); + alloc_register(acts,&a->out); alloc_register(acts,&a->saved_obs); + a->embed_wgrad = {.shape = {N3_EMBED_VOCAB, N3_EMBED_DIM}}; + a->embed_wgrad_f = {.shape = {N3_EMBED_VOCAB, N3_EMBED_DIM}}; + a->proj_wgrad = {.shape = {ew->hidden, N3_CONCAT}}; + a->proj_bgrad = {.shape = {ew->hidden}}; + alloc_register(grads,&a->embed_wgrad); + alloc_register(acts,&a->embed_wgrad_f); + alloc_register(grads,&a->proj_wgrad); alloc_register(grads,&a->proj_bgrad); +} + +static void nmmo3_encoder_reg_rollout(void* w, void* activations, Allocator* alloc, int B) { + NMMO3EncoderWeights* ew = (NMMO3EncoderWeights*)w; + NMMO3EncoderActivations* a = (NMMO3EncoderActivations*)activations; + a->multihot = {.shape = {B, N3_MULTIHOT * N3_MAP_H * N3_MAP_W}}; + alloc_register(alloc,&a->multihot); + a->conv1.out = {.shape = {B * N3_C1_OC * N3_C1_OH * N3_C1_OW}}; + alloc_register(alloc,&a->conv1.out); + a->col1 = {.shape = {B * N3_C1_OH * N3_C1_OW, N3_C1_IC * N3_C1_K * N3_C1_K}}; + a->mm1 = {.shape = {B * N3_C1_OH * N3_C1_OW, N3_C1_OC}}; + alloc_register(alloc,&a->col1); alloc_register(alloc,&a->mm1); + a->conv2.out = {.shape = {B * N3_C2_OC * N3_C2_OH * N3_C2_OW}}; + alloc_register(alloc,&a->conv2.out); + a->col2 = {.shape = {B * N3_C2_OH * N3_C2_OW, N3_C2_IC * N3_C2_K * N3_C2_K}}; + a->mm2 = {.shape = {B * N3_C2_OH * N3_C2_OW, N3_C2_OC}}; + alloc_register(alloc,&a->col2); alloc_register(alloc,&a->mm2); + a->embed_out = {.shape = {B, N3_PLAYER_EMBED}}; + a->concat = {.shape = {B, N3_CONCAT}}; + a->out = {.shape = {B, ew->hidden}}; + alloc_register(alloc,&a->embed_out); alloc_register(alloc,&a->concat); alloc_register(alloc,&a->out); +} + +static void* nmmo3_encoder_create_weights(void* self) { + Encoder* e = (Encoder*)self; + return nmmo3_encoder_create(e->in_dim, e->out_dim); +} +static void nmmo3_encoder_free_weights(void* weights) { free(weights); } +static void nmmo3_encoder_free_activations(void* activations) { free(activations); } + +// Override encoder vtable for known ocean environments. No-op for unknown envs. +static void create_custom_encoder(const std::string& env_name, Encoder* enc) { + if (env_name == "nmmo3") { + *enc = Encoder{ + .forward = nmmo3_encoder_forward, + .backward = nmmo3_encoder_backward, + .init_weights = nmmo3_encoder_init_weights, + .reg_params = nmmo3_encoder_reg_params, + .reg_train = nmmo3_encoder_reg_train, + .reg_rollout = nmmo3_encoder_reg_rollout, + .create_weights = nmmo3_encoder_create_weights, + .free_weights = nmmo3_encoder_free_weights, + .free_activations = nmmo3_encoder_free_activations, + .in_dim = enc->in_dim, .out_dim = enc->out_dim, + .activation_size = sizeof(NMMO3EncoderActivations), + }; + } +} diff --git a/src/pufferlib.cu b/src/pufferlib.cu new file mode 100644 index 0000000000..6c513c97b7 --- /dev/null +++ b/src/pufferlib.cu @@ -0,0 +1,1802 @@ +#include +#include +#include +#include +#include + +#include +#include "models.cu" +#include "ocean.cu" +#include "muon.cu" +#include "vecenv.h" + +static double wall_clock() { + struct timespec ts; + clock_gettime(CLOCK_REALTIME, &ts); + return ts.tv_sec + ts.tv_nsec * 1e-9; +} + +enum LossIdx { + LOSS_PG = 0, LOSS_VF = 1, LOSS_ENT = 2, LOSS_TOTAL = 3, + LOSS_OLD_APPROX_KL = 4, LOSS_APPROX_KL = 5, LOSS_CLIPFRAC = 6, + LOSS_N = 7, NUM_LOSSES = 8, +}; + +enum ProfileIdx { + PROF_ROLLOUT = 0, + PROF_EVAL_GPU, + PROF_EVAL_ENV, + PROF_TRAIN_MISC, + PROF_TRAIN_FORWARD, + NUM_PROF, +}; + +static const char* PROF_NAMES[NUM_PROF] = { + "rollout", + "eval_gpu", + "eval_env", + "train_misc", + "train_forward", +}; + +#define NUM_TRAIN_EVENTS 5 +typedef struct { + cudaEvent_t events[NUM_TRAIN_EVENTS]; + float accum[NUM_PROF]; +} ProfileT; + +// Data collected by parallel environment workers. Each worker handles +// a constant subset of agents +struct RolloutBuf { + PrecisionTensor observations; // (horizon, agents, input_size) + PrecisionTensor actions; // (horizon, agents, num_atns) + PrecisionTensor values; // (horizon, agents) + PrecisionTensor logprobs; // ... + PrecisionTensor rewards; + PrecisionTensor terminals; + PrecisionTensor ratio; + PrecisionTensor importance; +}; + +// Buffers are initialized as raw structs with only shape information. alloc_register +// stores the shape and data pointer. Memory is only allocated after all buffers are registered. +void register_rollout_buffers(RolloutBuf& bufs, Allocator* alloc, int T, int B, int input_size, int num_atns) { + bufs = (RolloutBuf){ + .observations = {.shape = {T, B, input_size}}, + .actions = {.shape = {T, B, num_atns}}, + .values = {.shape = {T, B}}, + .logprobs = {.shape = {T, B}}, + .rewards = {.shape = {T, B}}, + .terminals = {.shape = {T, B}}, + .ratio = {.shape = {T, B}}, + .importance = {.shape = {T, B}}, + }; + alloc_register(alloc, &bufs.observations); + alloc_register(alloc, &bufs.actions); + alloc_register(alloc, &bufs.values); + alloc_register(alloc, &bufs.logprobs); + alloc_register(alloc, &bufs.rewards); + alloc_register(alloc, &bufs.terminals); + alloc_register(alloc, &bufs.ratio); + alloc_register(alloc, &bufs.importance); +} + +// Train data layout is transposed to (B, T) from rollouts layout (T, B) +// This allows env workers to collect data with contiguous writes and +// training to perform several (though not all) ops in contiguous memory +struct TrainGraph { + PrecisionTensor mb_state; // (layers, B, hidden) + PrecisionTensor mb_obs; // (B, T, input_size) + PrecisionTensor mb_actions; // (B, T, num_atns) + PrecisionTensor mb_logprobs; // (B, T) + PrecisionTensor mb_advantages; // ... + PrecisionTensor mb_values; + PrecisionTensor mb_returns; + PrecisionTensor mb_ratio; + PrecisionTensor mb_newvalue; + PrecisionTensor mb_prio; // (B,) +}; + +void register_train_buffers(TrainGraph& bufs, Allocator* alloc, int B, int T, int input_size, + int hidden_size, int num_atns, int num_layers) { + bufs = (TrainGraph){ + .mb_state = {.shape = {num_layers, B, hidden_size}}, + .mb_obs = {.shape = {B, T, input_size}}, + .mb_actions = {.shape = {B, T, num_atns}}, + .mb_logprobs = {.shape = {B, T}}, + .mb_advantages = {.shape = {B, T}}, + .mb_values = {.shape = {B, T}}, + .mb_returns = {.shape = {B, T}}, + .mb_ratio = {.shape = {B, T}}, + .mb_newvalue = {.shape = {B, T}}, + .mb_prio = {.shape = {B}}, + }; + alloc_register(alloc, &bufs.mb_obs); + alloc_register(alloc, &bufs.mb_state); + alloc_register(alloc, &bufs.mb_actions); + alloc_register(alloc, &bufs.mb_logprobs); + alloc_register(alloc, &bufs.mb_advantages); + alloc_register(alloc, &bufs.mb_prio); + alloc_register(alloc, &bufs.mb_values); + alloc_register(alloc, &bufs.mb_returns); + alloc_register(alloc, &bufs.mb_ratio); + alloc_register(alloc, &bufs.mb_newvalue); +} + +// PPO buffers + args are quite complex. We do the entire +// forward + backwards pass for the full loss function in one kernel +struct PPOGraphArgs { + precision_t* out_ratio; + precision_t* out_newvalue; + const precision_t* actions; + const precision_t* old_logprobs; + const precision_t* advantages; + const precision_t* prio; + const precision_t* values; + const precision_t* returns; +}; + +struct PPOKernelArgs { + float* grad_logits; + float* grad_logstd; // For continuous actions + float* grad_values_pred; + const precision_t* logits; + const precision_t* logstd; // Continuous only + const precision_t* values_pred; + const float* adv_mean; + const float* adv_var; + const int* act_sizes; + int num_atns; + float clip_coef, vf_clip_coef, vf_coef, ent_coef; + int T_seq, A_total, N; + int logits_stride_n, logits_stride_t, logits_stride_a; + int values_stride_n, values_stride_t; + bool is_continuous; +}; + +struct PPOBuffersPuf { + FloatTensor loss_output, grad_loss; + FloatTensor saved_for_bwd; + FloatTensor grad_logits, grad_values, grad_logstd, adv_scratch; +}; + +void register_ppo_buffers(PPOBuffersPuf& bufs, Allocator* alloc, int N, int T, int A_total, bool is_continuous) { + long total = (long)N * T; + bufs = (PPOBuffersPuf){ + .loss_output = {.shape = {1}}, + .grad_loss = {.shape = {1}}, + .saved_for_bwd = {.shape = {total, 5}}, + .grad_logits = {.shape = {N, T, A_total}}, + .grad_values = {.shape = {N, T, 1}}, + .grad_logstd = {.shape = {N, T, A_total}}, + .adv_scratch = {.shape = {2}}, + }; + alloc_register(alloc, &bufs.loss_output); + alloc_register(alloc, &bufs.saved_for_bwd); + alloc_register(alloc, &bufs.grad_loss); + alloc_register(alloc, &bufs.grad_logits); + alloc_register(alloc, &bufs.grad_values); + if (is_continuous) { + alloc_register(alloc, &bufs.grad_logstd); + } + alloc_register(alloc, &bufs.adv_scratch); +} + +// Prioritized replay over single-epoch data. These kernels are +// the least cleaned because we will likely have a better method in 5.0 +struct PrioBuffers { + FloatTensor prio_probs, cdf, mb_prio; + IntTensor idx; +}; + +void register_prio_buffers(PrioBuffers& bufs, Allocator* alloc, int B, int minibatch_segments) { + bufs = (PrioBuffers){ + .prio_probs = {.shape = {B}}, + .cdf = {.shape = {B}}, + .mb_prio = {.shape = {minibatch_segments}}, + .idx = {.shape = {minibatch_segments}}, + }; + alloc_register(alloc, &bufs.prio_probs); + alloc_register(alloc, &bufs.cdf); + alloc_register(alloc, &bufs.idx); + alloc_register(alloc, &bufs.mb_prio); +} + +// Slice: select dim0 index t, then narrow dim0 from start for count. +// 3D (T, B, F) -> (count, F); 2D (T, B) -> (count,) +inline PrecisionTensor puf_slice(PrecisionTensor& p, int t, int start, int count) { + if (ndim(p.shape) == 3) { + long B = p.shape[1], F = p.shape[2]; + return {.data = p.data + (t*B + start)*F, .shape = {count, F}}; + } else { + long B = p.shape[1]; + return {.data = p.data + (t*B + start), .shape = {count}}; + } +} + +struct EnvBuf { + OBS_TENSOR_T obs; // (total_agents, obs_size) - type defined per-env in binding.c + FloatTensor actions; // (total_agents, num_atns) + FloatTensor rewards; // (total_agents,) + FloatTensor terminals; // (total_agents,) +}; + +StaticVec* create_environments(int num_buffers, int total_agents, + const std::string& env_name, Dict* vec_kwargs, Dict* env_kwargs, EnvBuf& env) { + StaticVec* vec = create_static_vec(total_agents, num_buffers, 1, vec_kwargs, env_kwargs); + env.obs = { + .data = (decltype(env.obs.data))vec->gpu_observations, + .shape = {total_agents, get_obs_size()}, + }; + env.actions = { .data = (float*)vec->gpu_actions, .shape = {total_agents, get_num_atns()} }; + env.rewards = { .data = (float*)vec->gpu_rewards, .shape = {total_agents} }; + env.terminals = { .data = (float*)vec->gpu_terminals, .shape = {total_agents} }; + return vec; +} + +typedef struct { + // Layout + int horizon; + int total_agents; + int num_buffers; + // Model architecture + int num_atns; + int hidden_size; + int num_layers; + // Learning rate + float lr; + float min_lr_ratio; + bool anneal_lr; + // Optimizer + float beta1; + float beta2; + float eps; + // Training + int minibatch_size; + float replay_ratio; + long total_timesteps; + float max_grad_norm; + // PPO + float clip_coef; + float vf_clip_coef; + float vf_coef; + float ent_coef; + // GAE + float gamma; + float gae_lambda; + // VTrace + float vtrace_rho_clip; + float vtrace_c_clip; + // Priority + float prio_alpha; + float prio_beta0; + // Flags + bool reset_state; + int cudagraphs; + bool profile; + // Multi-GPU + int rank; + int world_size; + int gpu_id; + std::string nccl_id; // raw bytes of ncclUniqueId (empty for single-GPU) + // Threading + int num_threads; + int seed; +} HypersT; + +typedef struct { + Policy policy; + PolicyWeights weights; // current precision_t weights (structured) + PolicyActivations train_activations; + Allocator params_alloc; + Allocator grads_alloc; + Allocator activations_alloc; + StaticVec* vec; + Muon muon; + ncclComm_t nccl_comm; // NCCL communicator for multi-GPU + HypersT hypers; + bool is_continuous; // True if all action dimensions are continuous (size==1) + PrecisionTensor* buffer_states; // Per-buffer states for contiguous access + PolicyActivations* buffer_activations; // Per-buffer inference activations + RolloutBuf rollouts; + RolloutBuf train_rollouts; // Pre-allocated transposed copy for train_impl + EnvBuf env; + TrainGraph train_buf; + PrecisionTensor advantages_puf; // Pre-allocated for train_impl (B, T) + cudaGraphExec_t* fused_rollout_cudagraphs; // [horizon][num_buffers] + cudaGraphExec_t train_cudagraph; + cudaStream_t* streams; // per-buffer raw CUDA streams + cudaStream_t default_stream; // main-thread stream (captured once at init) + IntTensor act_sizes_puf; // CUDA int32 tensor of action head sizes + FloatTensor losses_puf; // (NUM_LOSSES,) f32 accumulator + PPOBuffersPuf ppo_bufs_puf; // Pre-allocated buffers for ppo_loss_fwd_bwd + PrioBuffers prio_bufs; // Pre-allocated buffers for prio_replay + FloatTensor master_weights; // fp32 master weights (flat); same buffer as param_puf in fp32 mode + PrecisionTensor param_puf; + PrecisionTensor grad_puf; + LongTensor rng_offset_puf; // (num_buffers+1,) int64 CUDA device counters + ProfileT profile; + nvmlDevice_t nvml_device; + long epoch; + long global_step; + double start_time; + double last_log_time; + long last_log_step; + int train_warmup; + bool rollout_captured; + bool train_captured; + ulong seed; + curandStatePhilox4_32_10_t** rng_states; // per-buffer persistent RNG states [num_buffers] +} PuffeRL; + +Dict* log_environments_impl(PuffeRL& pufferl) { + Dict* out = create_dict(32); + static_vec_log(pufferl.vec, out); + return out; +} + +inline void profile_begin(const char* tag, bool enable) { + if (enable) nvtxRangePushA(tag); +} + +inline void profile_end(bool enable) { + if (enable) nvtxRangePop(); +} + +// Thread-local stream for per-buffer threads (set once by thread_init_wrapper) +static thread_local cudaStream_t tl_stream = 0; + +// Thread initialization callback - sets thread-local stream once per thread +extern "C" void thread_init_wrapper(void* ctx, int buf) { + PuffeRL* pufferl = (PuffeRL*)ctx; + tl_stream = pufferl->streams[buf]; +} + +__global__ void rng_init(curandStatePhilox4_32_10_t* states, uint64_t seed, int n) { + int idx = blockIdx.x * blockDim.x + threadIdx.x; + if (idx < n) { + curand_init(seed, idx, 0, &states[idx]); + } +} + +__device__ __forceinline__ float safe_logit(const precision_t* logits, + int logits_base, int logits_offset, int offset) { + float l = to_float(logits[logits_base + logits_offset + offset]); + if (isnan(l)) { + l = 0.0f; + } + if (isinf(l)) { + l = (l > 0) ? 3.4028e+38f : -3.4028e+38f; + } + return l; +} + +// Expects action logits and values to be in the same contiguous buffer. See default decoder +__global__ void sample_logits( + PrecisionTensor dec_out, // (B, logits_dim + 1 for values) + PrecisionTensor logstd_puf, // (1, od) - continuous actions only + IntTensor act_sizes_puf, // (num_atns,) action head sizes + precision_t* __restrict__ actions, // (B, num_atns) + precision_t* __restrict__ logprobs, // (B,) + precision_t* __restrict__ value_out, // (B,) + curandStatePhilox4_32_10_t* __restrict__ rng_states) { + int B = dec_out.shape[0]; + int fused_cols = dec_out.shape[1]; + int num_atns = numel(act_sizes_puf.shape); + const int* act_sizes = act_sizes_puf.data; + const precision_t* logits = dec_out.data; + int logits_stride = fused_cols; + int value_stride = fused_cols; + bool is_continuous = logstd_puf.data != nullptr && numel(logstd_puf.shape) > 0; + const precision_t* logstd = logstd_puf.data; + int logstd_stride = is_continuous ? 0 : 0; // 1D broadcast: stride 0 + const precision_t* value = logits + (fused_cols - 1); // last column + + int idx = blockIdx.x * blockDim.x + threadIdx.x; + if (idx >= B) { + return; + } + + // Load persistent RNG state (advanced in-place each call) + curandStatePhilox4_32_10_t state = rng_states[idx]; + + int logits_base = idx * logits_stride; + float total_log_prob = 0.0f; + + if (is_continuous) { + // Continuous action sampling from Normal(mean, exp(logstd)) + constexpr float LOG_2PI = 1.8378770664093453f; // log(2*pi) + int logstd_base = idx * logstd_stride; // separate stride for logstd (may be 0 for broadcast) + + for (int h = 0; h < num_atns; ++h) { + float mean = to_float(logits[logits_base + h]); + float log_std = to_float(logstd[logstd_base + h]); + float std = expf(log_std); + + // Sample from N(0,1) and transform: action = mean + std * noise + float noise = curand_normal(&state); + float action = mean + std * noise; + + // Log probability: -0.5 * ((action - mean) / std)^2 - 0.5 * log(2*pi) - log(std) + float normalized = (action - mean) / std; + float log_prob = -0.5f * normalized * normalized - 0.5f * LOG_2PI - log_std; + + actions[idx * num_atns + h] = from_float(action); + total_log_prob += log_prob; + } + } else { + // Discrete action sampling (original multinomial logic) + int logits_offset = 0; // offset within row for current action head + + for (int h = 0; h < num_atns; ++h) { + int A = act_sizes[h]; // size of this action head + + // Step 1: Find max and sum for numerical stability (with nan_to_num) + float max_val = -INFINITY; + float sum_exp = 0.0f; + for (int a = 0; a < A; ++a) { + float l = safe_logit(logits, logits_base, logits_offset, a); + if (l > max_val) { + sum_exp *= expf(max_val - l); + max_val = l; + } + sum_exp += expf(l - max_val); + } + float logsumexp = max_val + logf(sum_exp); + + // Step 3: Generate random value for this action head + float rand_val = curand_uniform(&state); + + // Step 4: Multinomial sampling using inverse CDF + float cumsum = 0.0f; + int sampled_action = A - 1; // default to last action + + for (int a = 0; a < A; ++a) { + float l = safe_logit(logits, logits_base, logits_offset, a); + float prob = expf(l - logsumexp); + cumsum += prob; + if (rand_val < cumsum) { + sampled_action = a; + break; + } + } + + // Step 5: Gather log probability of sampled action + float sampled_logit = safe_logit(logits, logits_base, logits_offset, sampled_action); + float log_prob = sampled_logit - logsumexp; + + // Write action for this head + actions[idx * num_atns + h] = from_float(sampled_action); + total_log_prob += log_prob; + + // Advance to next action head + logits_offset += A; + } + } + + // Write summed log probability (log of joint probability) + logprobs[idx] = from_float(total_log_prob); + + // Copy value (fused to avoid separate elementwise kernel for strided->contiguous copy) + value_out[idx] = value[idx * value_stride]; + + // Save RNG state back for next call + rng_states[idx] = state; +} + +// Single step rollout forward pass. Called by each environment worker in their +// own buffer thread. This operation is cudagraphed. +extern "C" void net_callback_wrapper(void* ctx, int buf, int t) { + PuffeRL* pufferl = (PuffeRL*)ctx; + HypersT& hypers = pufferl->hypers; + int graph = t * hypers.num_buffers + buf; + profile_begin("fused_rollout", hypers.profile); + + cudaStream_t current_stream = tl_stream; + if (pufferl->rollout_captured) { + cudaGraphLaunch(pufferl->fused_rollout_cudagraphs[graph], current_stream); + profile_end(hypers.profile); + return; + } + + bool capturing = pufferl->epoch == hypers.cudagraphs; + if (capturing) { + cudaStreamBeginCapture(current_stream, cudaStreamCaptureModeGlobal); + } + + RolloutBuf& rollouts = pufferl->rollouts; + EnvBuf& env = pufferl->env; + int block_size = pufferl->vec->total_agents / hypers.num_buffers; + int start = buf * block_size; + cudaStream_t stream = current_stream; + + // Copy observations, rewards, terminals from GPU env buffers to rollout buffer + OBS_TENSOR_T& obs_env = env.obs; + int n = block_size * obs_env.shape[1]; + PrecisionTensor obs_dst = puf_slice(rollouts.observations, t, start, block_size); + cast<<>>( + obs_dst.data, obs_env.data + (long)start*obs_env.shape[1], n); + + PrecisionTensor rew_dst = puf_slice(rollouts.rewards, t, start, block_size); + n = block_size; + cast<<>>( + rew_dst.data, env.rewards.data + start, n); + + PrecisionTensor term_dst = puf_slice(rollouts.terminals, t, start, block_size); + cast<<>>( + term_dst.data, env.terminals.data + start, n); + + // Policy forward pass for rollouts + PrecisionTensor state_puf = pufferl->buffer_states[buf]; + PrecisionTensor dec_puf = policy_forward(&pufferl->policy, pufferl->weights, pufferl->buffer_activations[buf], obs_dst, state_puf, stream); + + // Sample actions, logprobs, values into rollout buffer + PrecisionTensor act_slice = puf_slice(rollouts.actions, t, start, block_size); + PrecisionTensor lp_slice = puf_slice(rollouts.logprobs, t, start, block_size); + PrecisionTensor val_slice = puf_slice(rollouts.values, t, start, block_size); + PrecisionTensor p_logstd = {}; + DecoderWeights* dw = (DecoderWeights*)pufferl->weights.decoder; + if (dw->continuous) { + p_logstd = dw->logstd; + } + + sample_logits<<>>( + dec_puf, p_logstd, pufferl->act_sizes_puf, + act_slice.data, lp_slice.data, val_slice.data, + pufferl->rng_states[buf]); + + // Copy actions to env + long act_cols = env.actions.shape[1]; + cast<<>>( + env.actions.data + start * act_cols, act_slice.data, numel(act_slice.shape)); + + if (capturing) { + cudaGraph_t _graph; + cudaStreamEndCapture(current_stream, &_graph); + cudaGraphInstantiate(&pufferl->fused_rollout_cudagraphs[graph], _graph, 0); + cudaGraphDestroy(_graph); + cudaDeviceSynchronize(); + } + profile_end(hypers.profile); +} + + +__device__ __forceinline__ void ppo_discrete_head( + const precision_t* __restrict__ logits, int logits_base, + int logits_stride_a, int logits_offset, int A, int act, + float* out_logsumexp, float* out_entropy, float* out_logp) { + float max_logit = -INFINITY; + float sum = 0.0f; + float act_logit = 0.0f; + + for (int a = 0; a < A; ++a) { + float l = to_float(logits[logits_base + (logits_offset + a) * logits_stride_a]); + if (a == act) { + act_logit = l; + } + if (l > max_logit) { + sum *= __expf(max_logit - l); + max_logit = l; + } + sum += __expf(l - max_logit); + } + float logsumexp = max_logit + __logf(sum); + + float ent = 0.0f; + for (int a = 0; a < A; ++a) { + float l = to_float(logits[logits_base + (logits_offset + a) * logits_stride_a]); + float logp = l - logsumexp; + float p = __expf(logp); + ent -= p * logp; + } + + *out_logsumexp = logsumexp; + *out_entropy = ent; + *out_logp = act_logit - logsumexp; +} + +__device__ __forceinline__ void ppo_continuous_head( + float mean, float log_std, float action, + float* out_logp, float* out_entropy) { + constexpr float HALF_LOG_2PI = 0.9189385332046727f; + constexpr float HALF_1_PLUS_LOG_2PI = 1.4189385332046727f; + float std = __expf(log_std); + float normalized = (action - mean) / std; + *out_logp = -0.5f * normalized * normalized - HALF_LOG_2PI - log_std; + *out_entropy = HALF_1_PLUS_LOG_2PI + log_std; +} + +__global__ void ppo_loss_compute( + float* __restrict__ ppo_partials, + PPOKernelArgs a, PPOGraphArgs g) { + int idx = blockIdx.x * blockDim.x + threadIdx.x; + int tid = threadIdx.x; + int total_elements = a.N * a.T_seq; + float inv_NT = 1.0f / float(total_elements); + + __shared__ float block_losses[LOSS_N][PPO_THREADS]; + for (int c = 0; c < LOSS_N; c++) { + block_losses[c][tid] = 0.0f; + } + + if (idx >= total_elements) { + goto reduce; + } + + { + int n = idx / a.T_seq; + int t = idx % a.T_seq; + int nt = n * a.T_seq + t; + + int logits_base = n * a.logits_stride_n + t * a.logits_stride_t; + int values_idx = n * a.values_stride_n + t * a.values_stride_t; + int grad_logits_base = nt * a.A_total; + + // Shared computation (used by both forward and backward) + + float old_logp = to_float(g.old_logprobs[nt]); + float adv = to_float(g.advantages[nt]); + float w = to_float(g.prio[n]); + float val = to_float(g.values[nt]); + float ret = to_float(g.returns[nt]); + float val_pred = to_float(a.values_pred[values_idx]); + g.out_newvalue[nt] = from_float(val_pred); + + float adv_std = sqrtf(float(a.adv_var[0])); + float adv_normalized = (adv - float(a.adv_mean[0])) / (adv_std + 1e-8f); + + // grad_loss is always 1.0 (set in post_create, never changes) + float dL = inv_NT; + float d_pg_loss = dL; + float d_entropy_term = dL * (-a.ent_coef); + + // Value loss (forward) + value gradient (backward) + + float v_error = val_pred - val; + float v_clipped = val + fmaxf(-a.vf_clip_coef, fminf(a.vf_clip_coef, v_error)); + float v_loss_unclipped = (val_pred - ret) * (val_pred - ret); + float v_loss_clipped = (v_clipped - ret) * (v_clipped - ret); + float v_loss = 0.5f * fmaxf(v_loss_unclipped, v_loss_clipped); + + // Value gradient + bool use_clipped_vf = (v_loss_clipped > v_loss_unclipped); + float d_val_pred = 0.0f; + if (use_clipped_vf) { + if (v_error >= -a.vf_clip_coef && v_error <= a.vf_clip_coef) { + d_val_pred = v_clipped - ret; + } + } else { + d_val_pred = val_pred - ret; + } + a.grad_values_pred[nt] = dL * a.vf_coef * d_val_pred; + + // Policy loss + gradients + + float pg_loss, total_entropy, logratio, ratio; + float total_log_prob = 0.0f; + total_entropy = 0.0f; + + // Discrete-only: per-head arrays needed across forward + backward + float head_logsumexp[MAX_ATN_HEADS]; + float head_entropy[MAX_ATN_HEADS]; + int head_act[MAX_ATN_HEADS]; + + if (!a.is_continuous) { + int logits_offset = 0; + for (int h = 0; h < a.num_atns; ++h) { + int A = a.act_sizes[h]; + int act = static_cast(g.actions[nt * a.num_atns + h]); + head_act[h] = act; + float lse, ent, lp; + ppo_discrete_head(a.logits, logits_base, a.logits_stride_a, logits_offset, A, act, &lse, &ent, &lp); + head_logsumexp[h] = lse; + head_entropy[h] = ent; + total_log_prob += lp; + total_entropy += ent; + logits_offset += A; + } + } else { + for (int h = 0; h < a.num_atns; ++h) { + float mean = to_float(a.logits[logits_base + h * a.logits_stride_a]); + float log_std = to_float(a.logstd[h]); + float action = float(g.actions[nt * a.num_atns + h]); + float lp, ent; + ppo_continuous_head(mean, log_std, action, &lp, &ent); + total_log_prob += lp; + total_entropy += ent; + } + } + + // Shared pg loss computation + logratio = total_log_prob - old_logp; + ratio = __expf(logratio); + g.out_ratio[nt] = from_float(ratio); + float ratio_clipped = fmaxf(1.0f - a.clip_coef, fminf(1.0f + a.clip_coef, ratio)); + float wa = -w * adv_normalized; + float pg_loss1 = wa * ratio; + float pg_loss2 = wa * ratio_clipped; + pg_loss = fmaxf(pg_loss1, pg_loss2); + + float d_ratio = wa * d_pg_loss; + if (pg_loss2 > pg_loss1) { + if (ratio <= (1.0f - a.clip_coef) || ratio >= (1.0f + a.clip_coef)) { + d_ratio = 0.0f; + } + } + float d_new_logp = d_ratio * ratio; + + if (!a.is_continuous) { + int logits_offset = 0; + for (int h = 0; h < a.num_atns; ++h) { + int A = a.act_sizes[h]; + int act = head_act[h]; + float logsumexp = head_logsumexp[h]; + float ent = head_entropy[h]; + + for (int j = 0; j < A; ++j) { + float l = to_float(a.logits[logits_base + (logits_offset + j) * a.logits_stride_a]); + float logp = l - logsumexp; + float p = __expf(logp); + float d_logit = (j == act) ? d_new_logp : 0.0f; + d_logit -= p * d_new_logp; + d_logit += d_entropy_term * p * (-ent - logp); + a.grad_logits[grad_logits_base + logits_offset + j] = d_logit; + } + logits_offset += A; + } + } else { + for (int h = 0; h < a.num_atns; ++h) { + float mean = to_float(a.logits[logits_base + h * a.logits_stride_a]); + float log_std = to_float(a.logstd[h]); + float std = __expf(log_std); + float var = std * std; + float action = float(g.actions[nt * a.num_atns + h]); + float diff = action - mean; + + a.grad_logits[grad_logits_base + h] = d_new_logp * diff / var; + a.grad_logstd[nt * a.num_atns + h] = d_new_logp * (diff * diff / var - 1.0f) + d_entropy_term; + } + } + + // Forward: loss partials + float thread_loss = (pg_loss + a.vf_coef * v_loss - a.ent_coef * total_entropy) * inv_NT; + block_losses[LOSS_PG][tid] = pg_loss * inv_NT; + block_losses[LOSS_VF][tid] = v_loss * inv_NT; + block_losses[LOSS_ENT][tid] = total_entropy * inv_NT; + block_losses[LOSS_TOTAL][tid] = thread_loss; + block_losses[LOSS_OLD_APPROX_KL][tid] = (-logratio) * inv_NT; + block_losses[LOSS_APPROX_KL][tid] = ((ratio - 1.0f) - logratio) * inv_NT; + block_losses[LOSS_CLIPFRAC][tid] = (fabsf(ratio - 1.0f) > a.clip_coef ? 1.0f : 0.0f) * inv_NT; + } // end if (idx < total_elements) + +// Deterministic aggregation +reduce: + __syncthreads(); + + for (int stride = PPO_THREADS / 2; stride > 0; stride >>= 1) { + if (tid < stride) { + for (int c = 0; c < LOSS_N; c++) { + block_losses[c][tid] += block_losses[c][tid + stride]; + } + } + __syncthreads(); + } + + if (tid == 0) { + int base = blockIdx.x * (LOSS_N + 1); + ppo_partials[base] = block_losses[LOSS_TOTAL][0]; + for (int c = 0; c < LOSS_N; c++) { + ppo_partials[base + 1 + c] = block_losses[c][0]; + } + } +} + +// Deterministic reduction of per-block PPO loss partials + count increment +__global__ void ppo_loss_reduce( + float* __restrict__ loss, + float* __restrict__ losses_acc, + const float* __restrict__ partials, + int num_blocks) { + int tid = threadIdx.x; + if (tid > LOSS_N) { + return; + } + + float sum = 0.0f; + for (int b = 0; b < num_blocks; b++) { + sum += partials[b * (LOSS_N + 1) + tid]; + } + + if (tid == 0) { + *loss += sum; + } else { + losses_acc[tid - 1] += sum; + } + + // Fold add_scalar: increment epoch count + if (tid == 0) { + losses_acc[LOSS_N] += 1.0f; + } +} + +__global__ void ppo_var_mean(const precision_t* __restrict__ src, + float* __restrict__ var_out, float* __restrict__ mean_out, int n) { + __shared__ float sdata[256]; + int tid = threadIdx.x; + float sum = 0.0f; + for (int i = tid; i < n; i += blockDim.x) { + sum += to_float(src[i]); + } + sdata[tid] = sum; + __syncthreads(); + for (int s = blockDim.x / 2; s > 0; s >>= 1) { + if (tid < s) { + sdata[tid] += sdata[tid + s]; + } + __syncthreads(); + } + float mean = sdata[0] / (float)n; + if (tid == 0) { + *mean_out = mean; + } + __syncthreads(); + float ss = 0.0f; + for (int i = tid; i < n; i += blockDim.x) { + float d = to_float(src[i]) - mean; + ss += d * d; + } + sdata[tid] = ss; + __syncthreads(); + for (int s = blockDim.x / 2; s > 0; s >>= 1) { + if (tid < s) { + sdata[tid] += sdata[tid + s]; + } + __syncthreads(); + } + if (tid == 0) { + *var_out = sdata[0] / (float)(n - 1); + } +} + +// This is a huge kernel for a relatively cheap operation. But without this, +// it's death by a thousand cuts with repeated kernel launches. Even graphed, you +// blow up the memory bandwidth. +void ppo_loss_fwd_bwd( + PrecisionTensor& dec_out, // (N, T, fused_cols) — fused logits+value from decoder + PrecisionTensor& logstd, // continuous logstd or empty + TrainGraph& graph, + IntTensor& act_sizes, FloatTensor& losses_acc, + float clip_coef, float vf_clip_coef, float vf_coef, float ent_coef, + PPOBuffersPuf& bufs, bool is_continuous, + cudaStream_t stream) { + int N = dec_out.shape[0], T = dec_out.shape[1], fused_cols = dec_out.shape[2]; + int A_total = fused_cols - 1; // last column is value + int total = N * T; + + // Pointers into fused decoder output + const precision_t* logits_ptr = dec_out.data; + + float* adv_var_ptr = bufs.adv_scratch.data; + float* adv_mean_ptr = adv_var_ptr + 1; + ppo_var_mean<<<1, 256, 0, stream>>>( + graph.mb_advantages.data, adv_var_ptr, adv_mean_ptr, numel(graph.mb_advantages.shape)); + + int ppo_grid = (total + PPO_THREADS - 1) / PPO_THREADS; + + static float* ppo_partials_buf = nullptr; + static int ppo_partials_capacity = 0; + int ppo_partials_needed = ppo_grid * (LOSS_N + 1); + if (!ppo_partials_buf || ppo_partials_needed > ppo_partials_capacity) { + if (ppo_partials_buf) cudaFree(ppo_partials_buf); + ppo_partials_capacity = ppo_partials_needed; + cudaMalloc(&ppo_partials_buf, ppo_partials_capacity * sizeof(float)); + } + + cudaMemsetAsync(bufs.loss_output.data, 0, sizeof(float), stream); + + PPOGraphArgs graph_args = { + .out_ratio = graph.mb_ratio.data, + .out_newvalue = graph.mb_newvalue.data, + .actions = graph.mb_actions.data, + .old_logprobs = graph.mb_logprobs.data, + .advantages = graph.mb_advantages.data, + .prio = graph.mb_prio.data, + .values = graph.mb_values.data, + .returns = graph.mb_returns.data, + }; + + PPOKernelArgs args = { + .grad_logits = bufs.grad_logits.data, + .grad_logstd = is_continuous ? bufs.grad_logstd.data : nullptr, + .grad_values_pred = bufs.grad_values.data, + .logits = logits_ptr, + .logstd = is_continuous ? logstd.data : nullptr, + .values_pred = logits_ptr + A_total, + .adv_mean = adv_mean_ptr, + .adv_var = adv_var_ptr, + .act_sizes = act_sizes.data, + .num_atns = (int)numel(act_sizes.shape), + .clip_coef = clip_coef, .vf_clip_coef = vf_clip_coef, + .vf_coef = vf_coef, .ent_coef = ent_coef, + .T_seq = T, .A_total = A_total, .N = N, + .logits_stride_n = T * fused_cols, .logits_stride_t = fused_cols, .logits_stride_a = 1, + .values_stride_n = T * fused_cols, .values_stride_t = fused_cols, + .is_continuous = is_continuous, + }; + + ppo_loss_compute<<>>(ppo_partials_buf, args, graph_args); + + ppo_loss_reduce<<<1, LOSS_N + 1, 0, stream>>>( + bufs.loss_output.data, losses_acc.data, ppo_partials_buf, ppo_grid); +} + +#define PRIO_WARP_SIZE 32 +#define PRIO_FULL_MASK 0xffffffff +#define PRIO_BLOCK_SIZE 256 +#define PRIO_NUM_WARPS (PRIO_BLOCK_SIZE / PRIO_WARP_SIZE) +__global__ void compute_prio_adv_reduction( + const precision_t* __restrict__ advantages, + float* prio_weights, float prio_alpha, int stride) { + int row = blockIdx.x; + int tx = threadIdx.x; + int offset = row * stride; + + float local_sum = 0.0f; + for (int t = tx; t < stride; t += blockDim.x) { + local_sum += fabsf(to_float(advantages[offset + t])); + } + + for (int s = PRIO_WARP_SIZE / 2; s >= 1; s /= 2) { + local_sum += __shfl_down_sync(PRIO_FULL_MASK, local_sum, s); + } + if (tx == 0) { + float pw = __powf(local_sum, prio_alpha); + if (isnan(pw) || isinf(pw)) { + pw = 0.0f; + } + prio_weights[row] = pw; + } +} + +__global__ void compute_prio_normalize(float* prio_weights, int length) { + __shared__ float shmem[PRIO_NUM_WARPS]; + __shared__ float block_sum; + + int tx = threadIdx.x; + int lane = tx % PRIO_WARP_SIZE; + int warp_id = tx / PRIO_WARP_SIZE; + const float eps = 1e-6f; + + float local_sum = 0.0f; + for (int t = tx; t < length; t += blockDim.x) { + local_sum += prio_weights[t]; + } + for (int s = PRIO_WARP_SIZE / 2; s >= 1; s /= 2) { + local_sum += __shfl_down_sync(PRIO_FULL_MASK, local_sum, s); + } + if (lane == 0) { + shmem[warp_id] = local_sum; + } + __syncthreads(); + + if (warp_id == 0) { + float val = (lane < PRIO_NUM_WARPS) ? shmem[lane] : 0.0f; + for (int s = PRIO_NUM_WARPS / 2; s >= 1; s /= 2) { + val += __shfl_down_sync(PRIO_FULL_MASK, val, s); + } + if (tx == 0) { + block_sum = val + eps; + } + } + __syncthreads(); + + for (int t = tx; t < length; t += blockDim.x) { + prio_weights[t] = (prio_weights[t] + eps) / block_sum; + } +} + +// mb_prio[i] = pow(total_agents * prio_probs[idx[i]], -anneal_beta) +__global__ void compute_prio_imp_weights( + const int* __restrict__ indices, + const float* __restrict__ prio_probs, + float* mb_prio, int total_agents, + float anneal_beta, int minibatch_segments) { + int tx = threadIdx.x + blockIdx.x * blockDim.x; + if (tx < minibatch_segments) { + float value = prio_probs[indices[tx]] * (float)total_agents; + mb_prio[tx] = __powf(value, -anneal_beta); + } +} + +// Multinomial with replacement (uses cuRAND) +__global__ void multinomial_sample( + int* __restrict__ out_idx, const float* __restrict__ probs, + float* __restrict__ cdf, int B, int num_samples, + uint64_t seed, int64_t* __restrict__ offset_ptr) { + int tid = threadIdx.x; + if (tid == 0) { + float cum = 0.0f; + for (int i = 0; i < B; i++) { + cum += probs[i]; + cdf[i] = cum; + } + } + __syncthreads(); + if (tid < num_samples) { + uint64_t base_off = *offset_ptr; + curandStatePhilox4_32_10_t rng_state; + curand_init(seed, base_off + tid, 0, &rng_state); + float u = curand_uniform(&rng_state); + int lo = 0, hi = B - 1; + while (lo < hi) { + int mid = (lo + hi) / 2; + if (cdf[mid] < u) { + lo = mid + 1; + } else { + hi = mid; + } + } + out_idx[tid] = lo; + } + if (tid == 0) { + atomicAdd((unsigned long long*)offset_ptr, (unsigned long long)num_samples); + } +} + +// Prioritize high absolute advantage trajectories +// This is a form of implicit curriculum learning +// It is a major improvement in some complex environments +// The values of alpha and beta found by sweeps will tell you +// whether it is important for your task +void prio_replay_cuda(PrecisionTensor& advantages, float prio_alpha, + int minibatch_segments, int total_agents, float anneal_beta, + PrioBuffers& bufs, ulong seed, long* offset_ptr, cudaStream_t stream) { + int B = advantages.shape[0], T = advantages.shape[1]; + compute_prio_adv_reduction<<>>( + advantages.data, bufs.prio_probs.data, prio_alpha, T); + compute_prio_normalize<<<1, PRIO_BLOCK_SIZE, 0, stream>>>( + bufs.prio_probs.data, B); + int block = fmaxf(((minibatch_segments + 31) / 32) * 32, 32); + multinomial_sample<<<1, block, 0, stream>>>( + bufs.idx.data, bufs.prio_probs.data, + bufs.cdf.data, B, minibatch_segments, seed, offset_ptr); + int p3_blocks = (minibatch_segments + PRIO_BLOCK_SIZE - 1) / PRIO_BLOCK_SIZE; + compute_prio_imp_weights<<>>( + bufs.idx.data, bufs.prio_probs.data, + bufs.mb_prio.data, total_agents, anneal_beta, minibatch_segments); +} + +// Experience the puffer advantage! Generalized advantage estimation + V-Trace +// importance sampling correction in a single streamlined operation +__device__ void puff_advantage_row_scalar( + const precision_t* values, const precision_t* rewards, const precision_t* dones, + const precision_t* importance, precision_t* advantages, float gamma, float lambda, + float rho_clip, float c_clip, int horizon) { + float lastpufferlam = 0; + for (int t = horizon-2; t >= 0; t--) { + int t_next = t + 1; + float nextnonterminal = 1.0f - to_float(dones[t_next]); + float imp = to_float(importance[t]); + float rho_t = fminf(imp, rho_clip); + float c_t = fminf(imp, c_clip); + float r_nxt = to_float(rewards[t_next]); + float v = to_float(values[t]); + float v_nxt = to_float(values[t_next]); + float delta = rho_t*r_nxt + gamma*v_nxt*nextnonterminal - v; + lastpufferlam = delta + gamma*lambda*c_t*lastpufferlam*nextnonterminal; + advantages[t] = from_float(lastpufferlam); + } +} + +// These loading fns just optimize bandwidth for advantage since we call it on all +// the data every minibatch. This should change in 5.0 +__device__ __forceinline__ void adv_vec_load(const float* ptr, float* out) { + float4 v = *reinterpret_cast(ptr); + out[0] = v.x; out[1] = v.y; out[2] = v.z; out[3] = v.w; +} + +__device__ __forceinline__ void adv_vec_load(const __nv_bfloat16* ptr, float* out) { + uint4 raw = *reinterpret_cast(ptr); + const __nv_bfloat16* bf = reinterpret_cast(&raw); + #pragma unroll + for (int i = 0; i < 8; i++) { + out[i] = __bfloat162float(bf[i]); + } +} + +// Store N floats as precision_t via 128-bit writes (float4 for f32, uint4 for bf16) +__device__ __forceinline__ void adv_vec_store(float* ptr, const float* vals) { + *reinterpret_cast(ptr) = make_float4(vals[0], vals[1], vals[2], vals[3]); +} + +__device__ __forceinline__ void adv_vec_store(__nv_bfloat16* ptr, const float* vals) { + // N=8 for bf16: all 8 elements fit in one uint4 (128 bits) + __nv_bfloat16 tmp[8]; + #pragma unroll + for (int i = 0; i < 8; i++) tmp[i] = __float2bfloat16(vals[i]); + *reinterpret_cast(ptr) = *reinterpret_cast(tmp); +} + +__device__ __forceinline__ void puff_advantage_row_vec( + const precision_t* values, const precision_t* rewards, const precision_t* dones, + const precision_t* importance, precision_t* advantages, float gamma, float lambda, + float rho_clip, float c_clip, int horizon) { + constexpr int N = 16 / sizeof(precision_t); + + float lastpufferlam = 0.0f; + int num_chunks = horizon / N; + + float next_value = to_float(values[horizon - 1]); + float next_done = to_float(dones[horizon - 1]); + float next_reward = to_float(rewards[horizon - 1]); + + for (int chunk = num_chunks - 1; chunk >= 0; chunk--) { + int base = chunk * N; + + float v[N], r[N], d[N], imp[N]; + adv_vec_load(values + base, v); + adv_vec_load(rewards + base, r); + adv_vec_load(dones + base, d); + adv_vec_load(importance + base, imp); + + float adv[N] = {0}; + int start_idx = (chunk == num_chunks - 1) ? (N - 2) : (N - 1); + + #pragma unroll + for (int i = start_idx; i >= 0; i--) { + float nextnonterminal = 1.0f - next_done; + float rho_t = fminf(imp[i], rho_clip); + float c_t = fminf(imp[i], c_clip); + float delta = rho_t * (next_reward + gamma * next_value * nextnonterminal - v[i]); + lastpufferlam = delta + gamma * lambda * c_t * lastpufferlam * nextnonterminal; + adv[i] = lastpufferlam; + next_value = v[i]; + next_done = d[i]; + next_reward = r[i]; + } + + adv_vec_store(advantages + base, adv); + } +} + +__global__ void puff_advantage(const precision_t* values, const precision_t* rewards, + const precision_t* dones, const precision_t* importance, precision_t* advantages, float gamma, + float lambda, float rho_clip, float c_clip, int num_steps, int horizon) { + int row = blockIdx.x*blockDim.x + threadIdx.x; + if (row >= num_steps) { + return; + } + int offset = row*horizon; + puff_advantage_row_vec(values + offset, rewards + offset, dones + offset, + importance + offset, advantages + offset, gamma, lambda, rho_clip, c_clip, horizon); +} + +__global__ void puff_advantage_scalar(const precision_t* values, const precision_t* rewards, + const precision_t* dones, const precision_t* importance, precision_t* advantages, float gamma, + float lambda, float rho_clip, float c_clip, int num_steps, int horizon) { + int row = blockIdx.x*blockDim.x + threadIdx.x; + if (row >= num_steps) { + return; + } + int offset = row*horizon; + puff_advantage_row_scalar(values + offset, rewards + offset, dones + offset, + importance + offset, advantages + offset, gamma, lambda, rho_clip, c_clip, horizon); +} + +void puff_advantage_cuda(PrecisionTensor& values, PrecisionTensor& rewards, + PrecisionTensor& dones, PrecisionTensor& importance, PrecisionTensor& advantages, + float gamma, float lambda, float rho_clip, float c_clip, cudaStream_t stream) { + int num_steps = values.shape[0], horizon = values.shape[1]; + int blocks = grid_size(num_steps); + constexpr int N = 16 / sizeof(precision_t); + auto kernel = (horizon % N == 0) ? puff_advantage : puff_advantage_scalar; + kernel<<>>( + values.data, rewards.data, dones.data, importance.data, + advantages.data, gamma, lambda, rho_clip, c_clip, num_steps, horizon); +} + +// Minor copy bandwidth optimizations +__global__ void index_copy(char* __restrict__ dst, const int* __restrict__ idx, + const char* __restrict__ src, int num_idx, int row_bytes) { + int i = blockIdx.x * blockDim.x + threadIdx.x; + if (i < num_idx) { + int dst_row = idx[i]; + memcpy(dst + (int64_t)dst_row * row_bytes, src + (int64_t)i * row_bytes, row_bytes); + } +} + +__device__ __forceinline__ void copy_values_adv_returns( + const precision_t* __restrict__ src_values, precision_t* __restrict__ dst_values, + const precision_t* __restrict__ src_advantages, precision_t* __restrict__ dst_advantages, + precision_t* __restrict__ dst_returns, + int src_row, int dst_row, int horizon) { + int srh = (int64_t)src_row * horizon; + int drh = (int64_t)dst_row * horizon; + const precision_t* s_values = src_values + srh; + const precision_t* s_adv = src_advantages + srh; + precision_t* d_values = dst_values + drh; + precision_t* d_adv = dst_advantages + drh; + precision_t* d_returns = dst_returns + drh; + for (int i = threadIdx.x; i < horizon; i += blockDim.x) { + precision_t val = s_values[i]; + precision_t adv = s_adv[i]; + d_values[i] = val; + d_adv[i] = adv; + d_returns[i] = from_float(to_float(val) + to_float(adv)); + } +} + +__global__ void select_copy(RolloutBuf rollouts, TrainGraph graph, + const int* __restrict__ idx, const precision_t* __restrict__ advantages, + const float* __restrict__ mb_prio) { + int mb = blockIdx.x; + int ch = blockIdx.y; + int src_row = idx[mb]; + + // Compute row byte counts from tensor shapes + int obs_row_bytes = (numel(rollouts.observations.shape) / rollouts.observations.shape[0]) * sizeof(precision_t); + int act_row_bytes = (numel(rollouts.actions.shape) / rollouts.actions.shape[0]) * sizeof(precision_t); + int lp_row_bytes = (numel(rollouts.logprobs.shape) / rollouts.logprobs.shape[0]) * sizeof(precision_t); + int horizon = rollouts.values.shape[1]; + + switch (ch) { + case 0: + copy_bytes((const char*)rollouts.observations.data, (char*)graph.mb_obs.data, src_row, mb, obs_row_bytes); + break; + case 1: + copy_bytes((const char*)rollouts.actions.data, (char*)graph.mb_actions.data, src_row, mb, act_row_bytes); + break; + case 2: + copy_bytes((const char*)rollouts.logprobs.data, (char*)graph.mb_logprobs.data, src_row, mb, lp_row_bytes); + break; + case 3: + copy_values_adv_returns(rollouts.values.data, graph.mb_values.data, + advantages, graph.mb_advantages.data, + graph.mb_returns.data, src_row, mb, horizon); + break; + case 4: + if (threadIdx.x == 0) { + graph.mb_prio.data[mb] = from_float(mb_prio[mb]); + break; + } + } +} + +inline float cosine_annealing(float lr_base, float lr_min, long t, long T) { + if (T == 0) return lr_base; + float ratio = (double )t / (double) T; + ratio = std::max(0.0f, std::min(1.0f, ratio)); + return lr_min + 0.5f*(lr_base - lr_min)*(1.0f + std::cos(M_PI * ratio)); +} + +void train_impl(PuffeRL& pufferl) { + // Update to HypersT& p + HypersT& hypers = pufferl.hypers; + + cudaEventRecord(pufferl.profile.events[0]); // pre-loop start + cudaStream_t train_stream = pufferl.default_stream; + + // Transpose from rollout layout (T, B, ...) to train layout (B, T, ...) + RolloutBuf& src = pufferl.rollouts; + RolloutBuf& rollouts = pufferl.train_rollouts; + PrecisionTensor& advantages_puf = pufferl.advantages_puf; + + int T = src.observations.shape[0], B = src.observations.shape[1]; + int obs_size = (ndim(src.observations.shape) >= 3) ? src.observations.shape[2] : 1; + int num_atns = (ndim(src.actions.shape) >= 3) ? src.actions.shape[2] : 1; + + transpose_102<<>>( + rollouts.observations.data, src.observations.data, T, B, obs_size); + transpose_102<<>>( + rollouts.actions.data, src.actions.data, T, B, num_atns); + transpose_102<<>>( + rollouts.logprobs.data, src.logprobs.data, T, B, 1); + transpose_102<<>>( + rollouts.rewards.data, src.rewards.data, T, B, 1); + transpose_102<<>>( + rollouts.terminals.data, src.terminals.data, T, B, 1); + transpose_102<<>>( + rollouts.ratio.data, src.ratio.data, T, B, 1); + transpose_102<<>>( + rollouts.values.data, src.values.data, T, B, 1); + + // We hard-clamp rewards to -1, 1. Our envs are mostly designed to respect this range + clamp_precision_kernel<<>>( + rollouts.rewards.data, -1.0f, 1.0f, numel(rollouts.rewards.shape)); + + // Set importance weights to 1.0 + fill_precision_kernel<<>>( + rollouts.ratio.data, from_float(1.0f), numel(rollouts.ratio.shape)); + + // Inline any of these only used once + int minibatch_size = hypers.minibatch_size; + int batch_size = hypers.total_agents * hypers.horizon; + int minibatch_segments = minibatch_size / hypers.horizon; + float prio_beta0 = hypers.prio_beta0; + float prio_alpha = hypers.prio_alpha; + bool anneal_lr = hypers.anneal_lr; + int current_epoch = pufferl.epoch; + + Muon* muon = &pufferl.muon; + int total_epochs = hypers.total_timesteps / batch_size; + if (anneal_lr) { + float lr_min = hypers.min_lr_ratio * hypers.lr; + float lr = cosine_annealing(hypers.lr, lr_min, current_epoch, total_epochs); + cudaMemcpy(muon->lr_ptr, &lr, sizeof(float), cudaMemcpyHostToDevice); + } + + // Annealed priority exponent + float anneal_beta = prio_beta0 + (1.0f - prio_beta0) * prio_alpha * (float)current_epoch/(float)total_epochs; + TrainGraph& graph = pufferl.train_buf; + cudaEventRecord(pufferl.profile.events[1]); // pre-loop end + + int total_minibatches = hypers.replay_ratio * batch_size / hypers.minibatch_size; + for (int mb = 0; mb < total_minibatches; ++mb) { + cudaEventRecord(pufferl.profile.events[2]); // start of misc (overwritten each iter) + puf_zero(&advantages_puf, train_stream); + + profile_begin("compute_advantage", hypers.profile); + puff_advantage_cuda(rollouts.values, rollouts.rewards, rollouts.terminals, + rollouts.ratio, advantages_puf, hypers.gamma, hypers.gae_lambda, + hypers.vtrace_rho_clip, hypers.vtrace_c_clip, train_stream); + profile_end(hypers.profile); + + profile_begin("compute_prio", hypers.profile); + // Use the training RNG offset slot (last slot, index num_buffers) + long* train_rng_offset = pufferl.rng_offset_puf.data + hypers.num_buffers; + prio_replay_cuda(advantages_puf, prio_alpha, minibatch_segments, + hypers.total_agents, anneal_beta, + pufferl.prio_bufs, pufferl.seed, train_rng_offset, train_stream); + profile_end(hypers.profile); + + profile_begin("train_select_and_copy", hypers.profile); + if (hypers.reset_state) puf_zero(&graph.mb_state, train_stream); + { + RolloutBuf sel_src = rollouts; + sel_src.values = rollouts.values; + int mb_segs = pufferl.prio_bufs.idx.shape[0]; + select_copy<<>>( + sel_src, graph, pufferl.prio_bufs.idx.data, + advantages_puf.data, pufferl.prio_bufs.mb_prio.data); + } + profile_end(hypers.profile); + + cudaEventRecord(pufferl.profile.events[3]); // end misc / start forward + profile_begin("train_forward_backward", hypers.profile); + if (pufferl.train_captured) { + cudaGraphLaunch(pufferl.train_cudagraph, train_stream); + } else { + bool capturing = pufferl.train_warmup == hypers.cudagraphs; + if (capturing) { + cudaStreamBeginCapture(train_stream, cudaStreamCaptureModeGlobal); + } + + cudaStream_t stream = train_stream; + PrecisionTensor obs_puf = graph.mb_obs; + PrecisionTensor state_puf = graph.mb_state; + PrecisionTensor dec_puf = policy_forward_train(&pufferl.policy, pufferl.weights, pufferl.train_activations, obs_puf, state_puf, stream); + DecoderWeights* dw_train = (DecoderWeights*)pufferl.weights.decoder; + PrecisionTensor p_logstd; + if (dw_train->continuous) { + p_logstd = dw_train->logstd; + } + + ppo_loss_fwd_bwd(dec_puf, p_logstd, graph, + pufferl.act_sizes_puf, pufferl.losses_puf, + hypers.clip_coef, hypers.vf_clip_coef, hypers.vf_coef, hypers.ent_coef, + pufferl.ppo_bufs_puf, pufferl.is_continuous, stream); + + FloatTensor grad_logits_puf = pufferl.ppo_bufs_puf.grad_logits; + FloatTensor grad_logstd_puf = pufferl.is_continuous ? pufferl.ppo_bufs_puf.grad_logstd : FloatTensor(); + FloatTensor grad_values_puf = pufferl.ppo_bufs_puf.grad_values; + policy_backward(&pufferl.policy, pufferl.weights, pufferl.train_activations, + grad_logits_puf, grad_logstd_puf, grad_values_puf, stream); + + muon_step(&pufferl.muon, pufferl.master_weights, pufferl.grad_puf, hypers.max_grad_norm, stream); + if (USE_BF16) { + int n = numel(pufferl.param_puf.shape); + cast<<>>( + pufferl.param_puf.data, pufferl.master_weights.data, n); + } + if (capturing) { + cudaGraph_t _graph; + cudaStreamEndCapture(train_stream, &_graph); + cudaGraphInstantiate(&pufferl.train_cudagraph, _graph, 0); + cudaGraphDestroy(_graph); + cudaDeviceSynchronize(); + pufferl.train_captured = true; + } + pufferl.train_warmup++; + } + profile_end(hypers.profile); + + // This version is consistent with PufferLib 3.0. One of the major algorithmic + // questions remaining is how and when to update value and advantage estimates. + { + int num_idx = numel(pufferl.prio_bufs.idx.shape); + int row_bytes = (numel(graph.mb_ratio.shape) / graph.mb_ratio.shape[0]) * sizeof(precision_t); + index_copy<<>>( + (char*)rollouts.ratio.data, pufferl.prio_bufs.idx.data, + (const char*)graph.mb_ratio.data, num_idx, row_bytes); + } + { + int num_idx = numel(pufferl.prio_bufs.idx.shape); + int row_bytes = graph.mb_newvalue.shape[1] * sizeof(precision_t); + index_copy<<>>( + (char*)rollouts.values.data, pufferl.prio_bufs.idx.data, + (const char*)graph.mb_newvalue.data, num_idx, row_bytes); + } + cudaEventRecord(pufferl.profile.events[4]); // end forward + } + pufferl.epoch += 1; + + cudaStreamSynchronize(pufferl.default_stream); + + if (total_minibatches > 0) { + float ms; + // Pre-loop setup (transpose, advantage, allocs) + cudaEventElapsedTime(&ms, pufferl.profile.events[0], pufferl.profile.events[1]); + pufferl.profile.accum[PROF_TRAIN_MISC] += ms; + // In-loop misc (last iteration, representative) scaled by count + cudaEventElapsedTime(&ms, pufferl.profile.events[2], pufferl.profile.events[3]); + pufferl.profile.accum[PROF_TRAIN_MISC] += ms * total_minibatches; + // In-loop forward (last iteration, representative) scaled by count + cudaEventElapsedTime(&ms, pufferl.profile.events[3], pufferl.profile.events[4]); + pufferl.profile.accum[PROF_TRAIN_FORWARD] += ms * total_minibatches; + } + +} + +std::unique_ptr create_pufferl_impl(HypersT& hypers, + const std::string& env_name, Dict* vec_kwargs, Dict* env_kwargs) { + auto pufferl = std::make_unique(); + pufferl->hypers = hypers; + pufferl->nccl_comm = nullptr; + pufferl->default_stream = 0; + + cudaSetDevice(hypers.gpu_id); + + // Multi-GPU: initialize NCCL + if (hypers.world_size > 1) { + if (hypers.nccl_id.size() != sizeof(ncclUniqueId)) + throw std::runtime_error("nccl_id must be " + std::to_string(sizeof(ncclUniqueId)) + " bytes"); + ncclUniqueId nccl_id; + memcpy(&nccl_id, hypers.nccl_id.data(), sizeof(nccl_id)); + ncclCommInitRank(&pufferl->nccl_comm, hypers.world_size, nccl_id, hypers.rank); + printf("Rank %d/%d: NCCL initialized\n", hypers.rank, hypers.world_size); + } + + ulong seed = hypers.seed + hypers.rank; + pufferl->seed = seed; + + // Load environment first to get input_size and action info from env + // Create environments and set up action sizes + StaticVec* vec = create_environments(hypers.num_buffers, hypers.total_agents, + env_name, vec_kwargs, env_kwargs, pufferl->env); + pufferl->vec = vec; + + // Sanity check action space + int num_action_heads = pufferl->env.actions.shape[1]; + int* raw_act_sizes = get_act_sizes(); // CPU int32 pointer from env + int act_n = 0; + int num_continuous = 0; + int num_discrete = 0; + for (int i = 0; i < num_action_heads; i++) { + int val = raw_act_sizes[i]; + if (val == 1) { + num_continuous++; + } else { + num_discrete++; + } + act_n += val; + } + assert((num_continuous == 0 || num_discrete == 0) && + "Mixed continuous/discrete action spaces not supported"); + pufferl->is_continuous = (num_continuous > 0); + if (pufferl->is_continuous) { + printf("Detected continuous action space with %d dimensions\n", num_action_heads); + } else { + printf("Detected discrete action space with %d heads\n", num_action_heads); + } + + // Create profiling events + for (int i = 0; i < NUM_TRAIN_EVENTS; i++) { + cudaEventCreate(&pufferl->profile.events[i]); + } + memset(pufferl->profile.accum, 0, sizeof(pufferl->profile.accum)); + nvmlInit(); + nvmlDeviceGetHandleByIndex(hypers.gpu_id, &pufferl->nvml_device); + + // Create policy + int input_size = pufferl->env.obs.shape[1]; + int hidden_size = hypers.hidden_size; + int num_layers = hypers.num_layers; + bool is_continuous = pufferl->is_continuous; + int decoder_output_size = is_continuous ? num_action_heads : act_n; + int minibatch_segments = hypers.minibatch_size / hypers.horizon; + int inf_batch = vec->total_agents / hypers.num_buffers; + int B_TT = minibatch_segments * hypers.horizon; + int horizon = hypers.horizon; + int total_agents = vec->total_agents; + int batch = total_agents / hypers.num_buffers; + int num_buffers = hypers.num_buffers; + + Encoder encoder = { + .forward = encoder_forward, + .backward = encoder_backward, + .init_weights = encoder_init_weights, + .reg_params = encoder_reg_params, + .reg_train = encoder_reg_train, + .reg_rollout = encoder_reg_rollout, + .create_weights = encoder_create_weights, + .free_weights = encoder_free_weights, + .free_activations = encoder_free_activations, + .in_dim = input_size, .out_dim = hidden_size, + .activation_size = sizeof(EncoderActivations), + }; + create_custom_encoder(env_name, &encoder); + Decoder decoder = { + .forward = decoder_forward, + .backward = decoder_backward, + .init_weights = decoder_init_weights, + .reg_params = decoder_reg_params, + .reg_train = decoder_reg_train, + .reg_rollout = decoder_reg_rollout, + .create_weights = decoder_create_weights, + .free_weights = decoder_free_weights, + .free_activations = decoder_free_activations, + .hidden_dim = hidden_size, .output_dim = decoder_output_size, .continuous = is_continuous, + }; + Network network = { + .forward = mingru_forward, + .forward_train = mingru_forward_train, + .backward = mingru_backward, + .init_weights = mingru_init_weights, + .reg_params = mingru_reg_params, + .reg_train = mingru_reg_train, + .reg_rollout = mingru_reg_rollout, + .create_weights = mingru_create_weights, + .free_weights = mingru_free_weights, + .free_activations = mingru_free_activations, + .hidden = hidden_size, .num_layers = num_layers, .horizon = hypers.horizon, + }; + pufferl->policy = Policy{ + .encoder = encoder, .decoder = decoder, .network = network, + .input_dim = input_size, .hidden_dim = hidden_size, .output_dim = decoder_output_size, + .num_atns = act_n, + }; + + // Create and allocate params + Allocator* params = &pufferl->params_alloc; + Allocator* acts = &pufferl->activations_alloc; + Allocator* grads = &pufferl->grads_alloc; + + // Buffers for weights, grads, and activations + pufferl->weights = policy_weights_create(&pufferl->policy, params); + pufferl->train_activations = policy_reg_train(&pufferl->policy, pufferl->weights, acts, grads, B_TT); + pufferl->buffer_activations = (PolicyActivations*)calloc(num_buffers, sizeof(PolicyActivations)); + pufferl->buffer_states = (PrecisionTensor*)calloc(num_buffers, sizeof(PrecisionTensor)); + for (int i = 0; i < num_buffers; i++) { + pufferl->buffer_activations[i] = policy_reg_rollout( + &pufferl->policy, pufferl->weights, acts, inf_batch); + pufferl->buffer_states[i] = { + .shape = {num_layers, batch, hidden_size}, + }; + alloc_register(acts, &pufferl->buffer_states[i]); + } + register_rollout_buffers(pufferl->rollouts, + acts, horizon, total_agents, input_size, num_action_heads); + register_train_buffers(pufferl->train_buf, + acts, minibatch_segments, horizon, input_size, + hidden_size, num_action_heads, num_layers); + register_rollout_buffers(pufferl->train_rollouts, + acts, total_agents, horizon, input_size, num_action_heads); + register_ppo_buffers(pufferl->ppo_bufs_puf, + acts, minibatch_segments, hypers.horizon, decoder_output_size, is_continuous); + register_prio_buffers(pufferl->prio_bufs, + acts, hypers.total_agents, minibatch_segments); + + // Extra cuda buffers just reuse activ allocator + pufferl->rng_offset_puf = {.shape = {num_buffers + 1}}; + alloc_register(acts, &pufferl->rng_offset_puf); + + pufferl->act_sizes_puf = {.shape = {num_action_heads}}; + alloc_register(acts, &pufferl->act_sizes_puf); + + pufferl->losses_puf = {.shape = {NUM_LOSSES}}; + alloc_register(acts, &pufferl->losses_puf); + + pufferl->advantages_puf = {.shape = {total_agents, horizon}}; + alloc_register(acts, &pufferl->advantages_puf); + + muon_init(&pufferl->muon, params, hypers.lr, hypers.beta1, hypers.eps, 0.0, acts); + pufferl->muon.nccl_comm = pufferl->nccl_comm; + pufferl->muon.world_size = hypers.world_size; + + // All buffers allocated here + if (alloc_create(params) != cudaSuccess) { + return nullptr; + } + if (alloc_create(grads) != cudaSuccess) { + return nullptr; + } + if (alloc_create(acts) != cudaSuccess) { + return nullptr; + } + + pufferl->grad_puf = {.data = (precision_t*)grads->mem, .shape = {grads->total_elems}}; + pufferl->param_puf = {.data = (precision_t*)params->mem, .shape = {params->total_elems}}; + + ulong init_seed = hypers.seed; + policy_init_weights(&pufferl->policy, pufferl->weights, &init_seed, pufferl->default_stream); + pufferl->master_weights = {.data = (float*)pufferl->param_puf.data, .shape = {params->total_elems}}; + if (USE_BF16) { + pufferl->master_weights = {.shape = {params->total_elems}}; + cudaMalloc(&pufferl->master_weights.data, params->total_elems * sizeof(float)); + int n = numel(pufferl->param_puf.shape); + cast<<default_stream>>>( + pufferl->master_weights.data, pufferl->param_puf.data, n); + } + + // Per-buffer persistent RNG states + int agents_per_buf = total_agents / num_buffers; + pufferl->rng_states = (curandStatePhilox4_32_10_t**)calloc(num_buffers, sizeof(curandStatePhilox4_32_10_t*)); + for (int i = 0; i < num_buffers; i++) { + cudaMalloc(&pufferl->rng_states[i], agents_per_buf * sizeof(curandStatePhilox4_32_10_t)); + rng_init<<>>( + pufferl->rng_states[i], pufferl->seed + i, agents_per_buf); + } + + // Post-create initialization + cudaMemcpy(pufferl->act_sizes_puf.data, raw_act_sizes, num_action_heads * sizeof(int), cudaMemcpyHostToDevice); + cudaMemset(pufferl->losses_puf.data, 0, NUM_LOSSES * sizeof(float)); + float one = 1.0f; + cudaMemcpy(pufferl->ppo_bufs_puf.grad_loss.data, &one, sizeof(float), cudaMemcpyHostToDevice); + muon_post_create(&pufferl->muon); + + // Cudagraph rolluts and entire training step + if (hypers.cudagraphs >= 0) { + pufferl->fused_rollout_cudagraphs = (cudaGraphExec_t*)calloc(horizon*num_buffers, sizeof(cudaGraphExec_t)); + pufferl->train_warmup = 0; + + // Snapshot weights + optimizer state before init-time capture + long wb_bytes = numel(pufferl->master_weights.shape) * sizeof(float); + void* saved_weights; + cudaMalloc(&saved_weights, wb_bytes); + cudaMemcpy(saved_weights, pufferl->master_weights.data, wb_bytes, cudaMemcpyDeviceToDevice); + void* saved_momentum; + cudaMalloc(&saved_momentum, wb_bytes); + cudaMemcpy(saved_momentum, pufferl->muon.mb_puf.data, wb_bytes, cudaMemcpyDeviceToDevice); + + // Create per-buffer streams before capture so graphs are + // captured and replayed on the same streams. + pufferl->streams = (cudaStream_t*)calloc(num_buffers, sizeof(cudaStream_t)); + for (int i = 0; i < num_buffers; i++) { + cudaStreamCreate(&pufferl->streams[i]); + vec->streams[i] = pufferl->streams[i]; + } + + cudaStream_t saved_default = pufferl->default_stream; + cudaStream_t saved_tl = tl_stream; + cudaStream_t warmup_stream; + cudaStreamCreate(&warmup_stream); + pufferl->default_stream = warmup_stream; + + for (pufferl->epoch = 0; pufferl->epoch <= hypers.cudagraphs; pufferl->epoch++) { + for (int i = 0; i < num_buffers * horizon; ++i) { + int buf = i % num_buffers; + tl_stream = pufferl->streams[buf]; + net_callback_wrapper(pufferl.get(), buf, i / num_buffers); + cudaDeviceSynchronize(); + } + } + pufferl->rollout_captured = true; + + tl_stream = warmup_stream; + for (int i = 0; i <= hypers.cudagraphs; i++) { + train_impl(*pufferl); + } + + cudaStreamSynchronize(warmup_stream); + cudaDeviceSynchronize(); + pufferl->default_stream = saved_default; + tl_stream = saved_tl; + cudaStreamDestroy(warmup_stream); + + // Restore weights + optimizer state corrupted by warmup/capture + cudaMemcpy(pufferl->master_weights.data, saved_weights, wb_bytes, cudaMemcpyDeviceToDevice); + cudaFree(saved_weights); + cudaMemcpy(pufferl->muon.mb_puf.data, saved_momentum, wb_bytes, cudaMemcpyDeviceToDevice); + cudaFree(saved_momentum); + if (USE_BF16) { + int n = numel(pufferl->param_puf.shape); + cast<<default_stream>>>( + pufferl->param_puf.data, pufferl->master_weights.data, n); + } + + // Re-init RNG states corrupted by warmup + for (int i = 0; i < num_buffers; i++) { + rng_init<<>>( + pufferl->rng_states[i], pufferl->seed + i, agents_per_buf); + } + cudaDeviceSynchronize(); + + pufferl->epoch = 0; + pufferl->global_step = 0; + } + + // Create per-buffer streams if not already created by cudagraph path + if (!pufferl->streams) { + pufferl->streams = (cudaStream_t*)calloc(num_buffers, sizeof(cudaStream_t)); + for (int i = 0; i < num_buffers; i++) { + cudaStreamCreate(&pufferl->streams[i]); + vec->streams[i] = pufferl->streams[i]; + } + } + + create_static_threads(vec, hypers.num_threads, horizon, pufferl.get(), + net_callback_wrapper, thread_init_wrapper); + static_vec_reset(vec); + + if (hypers.profile) { + cudaDeviceSynchronize(); + cudaProfilerStart(); + } + + double now = wall_clock(); + pufferl->start_time = now; + pufferl->last_log_time = now; + pufferl->last_log_step = 0; + + return pufferl; +} + +void close_impl(PuffeRL& pufferl) { + cudaDeviceSynchronize(); + if (pufferl.hypers.profile) { + cudaProfilerStop(); + } + + cudaGraphExecDestroy(pufferl.train_cudagraph); + for (int i = 0; i < pufferl.hypers.horizon * pufferl.hypers.num_buffers; i++) { + cudaGraphExecDestroy(pufferl.fused_rollout_cudagraphs[i]); + } + + policy_weights_free(&pufferl.policy, &pufferl.weights); + policy_activations_free(&pufferl.policy, pufferl.train_activations); + for (int buf = 0; buf < pufferl.hypers.num_buffers; buf++) { + policy_activations_free(&pufferl.policy, pufferl.buffer_activations[buf]); + } + + for (int i = 0; i < pufferl.hypers.num_buffers; i++) { + cudaFree(pufferl.rng_states[i]); + } + free(pufferl.rng_states); + + if (USE_BF16) { + cudaFree(pufferl.master_weights.data); + } + + alloc_free(&pufferl.params_alloc); + alloc_free(&pufferl.grads_alloc); + alloc_free(&pufferl.activations_alloc); + + for (int i = 0; i < pufferl.hypers.num_buffers; i++) { + cudaStreamDestroy(pufferl.streams[i]); + } + for (int i = 0; i < NUM_TRAIN_EVENTS; i++) { + cudaEventDestroy(pufferl.profile.events[i]); + } + nvmlShutdown(); + + static_vec_close(pufferl.vec); + + free(pufferl.buffer_states); + free(pufferl.buffer_activations); + free(pufferl.fused_rollout_cudagraphs); + free(pufferl.streams); + + if (pufferl.nccl_comm != nullptr) { + ncclCommDestroy(pufferl.nccl_comm); + } +} diff --git a/pufferlib/extensions/puffernet.h b/src/puffernet.h similarity index 68% rename from pufferlib/extensions/puffernet.h rename to src/puffernet.h index 593407ab53..c9a83ccd2a 100644 --- a/pufferlib/extensions/puffernet.h +++ b/src/puffernet.h @@ -11,7 +11,7 @@ typedef struct { } Arena; Arena* make_allocator(size_t total_size) { - void* buffer = calloc(1, total_size + sizeof(Arena)); + void* buffer = (void*)calloc(1, total_size + sizeof(Arena)); Arena* allocator = (Arena*)buffer; allocator->data = (void*)((char*)buffer + sizeof(Arena)); allocator->capacity = total_size; @@ -36,25 +36,28 @@ struct Weights { int idx; }; -void _load_weights(const char* filename, float* weights, size_t num_weights) { +Weights* load_weights(const char* filename) { FILE* file = fopen(filename, "rb"); if (!file) { perror("Error opening file"); + return NULL; } fseek(file, 0, SEEK_END); + long file_size = ftell(file); rewind(file); - size_t read_size = fread(weights, sizeof(float), num_weights, file); + size_t num_weights = file_size / sizeof(float); + // +7 ensures get_weights_aligned never reads past the buffer: the native + // backend uses 16-byte alignment with bf16 params (2 bytes), so each tensor + // starts at an 8-float boundary. After the last tensor, up to 7 extra floats + // may be addressed before the next 8-aligned boundary. + Weights* weights = (Weights*)calloc(1, sizeof(Weights) + (num_weights + 7)*sizeof(float)); + weights->data = (float*)(weights + 1); + size_t read_size = fread(weights->data, sizeof(float), num_weights, file); fclose(file); if (read_size != num_weights) { perror("Error reading file"); } -} - -Weights* load_weights(const char* filename, size_t num_weights) { - Weights* weights = calloc(1, sizeof(Weights) + num_weights*sizeof(float)); - weights->data = (float*)(weights + 1); - _load_weights(filename, weights->data, num_weights); - weights->size = num_weights; + weights->size = num_weights + 7; weights->idx = 0; return weights; } @@ -66,6 +69,16 @@ float* get_weights(Weights* weights, int num_weights) { return data; } +// Advances index to next 8-float (16-byte) boundary after reading, matching +// the native backend's Allocator which aligns to 16 bytes with bf16 params. +float* get_weights_aligned(Weights* weights, int num_weights) { + float* data = &weights->data[weights->idx]; + weights->idx += num_weights; + weights->idx = (weights->idx + 7) & ~7; + assert(weights->idx <= weights->size); + return data; +} + // PufferNet implementation of PyTorch functions // These are tested against the PyTorch implementation void _relu(float* input, float* output, int size) { @@ -296,19 +309,57 @@ void _cat_dim1(float* x, float* y, float* output, int batch_size, int x_size, in } } -void _argmax_multidiscrete(float* input, int* output, int batch_size, int logit_sizes[], int num_actions) { - int in_adr = 0; +double _randn(double mean, double std) { + static int has_spare = 0; + static double spare; + + if (has_spare) { + has_spare = 0; + return mean + std * spare; + } + + has_spare = 1; + double u, v, s; + do { + u = 2.0 * rand() / RAND_MAX - 1.0; + v = 2.0 * rand() / RAND_MAX - 1.0; + s = u * u + v * v; + } while (s >= 1.0 || s == 0.0); + + s = sqrt(-2.0 * log(s) / s); + spare = v * s; + return mean + std * (u * s); +} + +void _gaussian_sample(float* input, float* log_std, float* output, int batch_size, int num_actions) { + for (int b = 0; b < batch_size; b++) { + // +1 skips the value head fused into the decoder output + int in_adr = b * (num_actions + 1); + for (int a = 0; a < num_actions; a++) { + int out_adr = b * num_actions + a; + float mean = input[in_adr + a]; + float std = expf(log_std[a]); + output[out_adr] = (float)_randn(mean, std); + } + } +} + +void _argmax_multidiscrete(float* input, float* output, int batch_size, int logit_sizes[], int num_actions) { + int atn_sum = 0; + for (int a = 0; a < num_actions; a++) atn_sum += logit_sizes[a]; for (int b = 0; b < batch_size; b++) { + // +1 skips the value head fused into the decoder output + int in_adr = b * (atn_sum + 1); for (int a = 0; a < num_actions; a++) { int out_adr = b*num_actions + a; float max_logit = input[in_adr]; - output[out_adr] = 0; + output[out_adr] = 0.0f; int num_action_types = logit_sizes[a]; for (int i = 1; i < num_action_types; i++) { float out = input[in_adr + i]; if (out > max_logit) { max_logit = out; - output[out_adr] = i; + output[out_adr] = (float)i; } } in_adr += num_action_types; @@ -316,9 +367,12 @@ void _argmax_multidiscrete(float* input, int* output, int batch_size, int logit_ } } -void _softmax_multidiscrete(float* input, int* output, int batch_size, int logit_sizes[], int num_actions) { - int in_adr = 0; +void _softmax_multidiscrete(float* input, float* output, int batch_size, int logit_sizes[], int num_actions) { + int atn_sum = 0; + for (int a = 0; a < num_actions; a++) atn_sum += logit_sizes[a]; for (int b = 0; b < batch_size; b++) { + // +1 skips the value head fused into the decoder output + int in_adr = b * (atn_sum + 1); for (int a = 0; a < num_actions; a++) { int out_adr = b*num_actions + a; float logit_exp_sum = 0; @@ -328,11 +382,11 @@ void _softmax_multidiscrete(float* input, int* output, int batch_size, int logit } float prob = rand() / (float)RAND_MAX; float logit_prob = 0; - output[out_adr] = 0; + output[out_adr] = 0.0f; for (int i = 0; i < num_action_types; i++) { logit_prob += expf(input[in_adr + i]) / logit_exp_sum; if (prob < logit_prob) { - output[out_adr] = i; + output[out_adr] = (float)i; break; } } @@ -357,8 +411,8 @@ void _max_dim1(float* input, float* output, int batch_size, int seq_len, int fea } // User API. Provided to help organize layers -typedef struct Linear Linear; -struct Linear { +typedef struct Affine Affine; +struct Affine { float* output; float* weights; float* bias; @@ -367,10 +421,10 @@ struct Linear { int output_dim; }; -Linear* make_linear(Weights* weights, int batch_size, int input_dim, int output_dim) { +Affine* make_affine(Weights* weights, int batch_size, int input_dim, int output_dim) { size_t buffer_size = batch_size*output_dim*sizeof(float); - Linear* layer = calloc(1, sizeof(Linear) + buffer_size); - *layer = (Linear){ + Affine* layer = (Affine*)calloc(1, sizeof(Affine) + buffer_size); + *layer = (Affine){ .output = (float*)(layer + 1), .weights = get_weights(weights, output_dim*input_dim), .bias = get_weights(weights, output_dim), @@ -381,16 +435,49 @@ Linear* make_linear(Weights* weights, int batch_size, int input_dim, int output_ return layer; } -void linear(Linear* layer, float* input) { +void affine(Affine* layer, float* input) { _linear(input, layer->weights, layer->bias, layer->output, layer->batch_size, layer->input_dim, layer->output_dim); } -void linear_accumulate(Linear* layer, float* input) { +void affine_accumulate(Affine* layer, float* input) { _linear_accumulate(input, layer->weights, layer->bias, layer->output, layer->batch_size, layer->input_dim, layer->output_dim); } +typedef struct Linear Linear; +struct Linear { + float* output; + float* weights; + int batch_size; + int input_dim; + int output_dim; +}; + +Linear* make_linear(Weights* weights, int batch_size, int input_dim, int output_dim) { + size_t buffer_size = batch_size*output_dim*sizeof(float); + Linear* layer = (Linear*)calloc(1, sizeof(Linear) + buffer_size); + *layer = (Linear){ + .output = (float*)(layer + 1), + .weights = get_weights_aligned(weights, output_dim*input_dim), + .batch_size = batch_size, + .input_dim = input_dim, + .output_dim = output_dim, + }; + return layer; +} + +void linear(Linear* layer, float* input) { + for (int b = 0; b < layer->batch_size; b++) { + for (int o = 0; o < layer->output_dim; o++) { + float sum = 0.0f; + for (int i = 0; i < layer->input_dim; i++) + sum += input[b*layer->input_dim + i] * layer->weights[o*layer->input_dim + i]; + layer->output[b*layer->output_dim + o] = sum; + } + } +} + typedef struct ReLU ReLU; struct ReLU { float* output; @@ -400,7 +487,7 @@ struct ReLU { ReLU* make_relu(int batch_size, int input_dim) { size_t buffer_size = batch_size*input_dim*sizeof(float); - ReLU* layer = calloc(1, sizeof(ReLU) + buffer_size); + ReLU* layer = (ReLU*)calloc(1, sizeof(ReLU) + buffer_size); *layer = (ReLU){ .output = (float*)(layer + 1), .batch_size = batch_size, @@ -422,7 +509,7 @@ struct GELU { GELU* make_gelu(int batch_size, int input_dim) { size_t buffer_size = batch_size*input_dim*sizeof(float); - GELU* layer = calloc(1, sizeof(GELU) + buffer_size); + GELU* layer = (GELU*)calloc(1, sizeof(GELU) + buffer_size); *layer = (GELU){ .output = (float*)(layer + 1), .batch_size = batch_size, @@ -445,7 +532,7 @@ struct MaxDim1 { MaxDim1* make_max_dim1(int batch_size, int seq_len, int feature_dim) { size_t buffer_size = batch_size*feature_dim*sizeof(float); - MaxDim1* layer = calloc(1, sizeof(MaxDim1) + buffer_size); + MaxDim1* layer = (MaxDim1*)calloc(1, sizeof(MaxDim1) + buffer_size); *layer = (MaxDim1){ .output = (float*)(layer + 1), .batch_size = batch_size, @@ -477,7 +564,7 @@ Conv2D* make_conv2d(Weights* weights, int batch_size, int in_width, int in_heigh int in_channels, int out_channels, int kernel_size, int stride) { size_t buffer_size = batch_size*out_channels*in_height*in_width*sizeof(float); int num_weights = out_channels*in_channels*kernel_size*kernel_size; - Conv2D* layer = calloc(1, sizeof(Conv2D) + buffer_size); + Conv2D* layer = (Conv2D*)calloc(1, sizeof(Conv2D) + buffer_size); *layer = (Conv2D){ .output = (float*)(layer + 1), .weights = get_weights(weights, num_weights), @@ -519,7 +606,7 @@ Conv3D* make_conv3d(Weights* weights, int batch_size, int in_width, int in_heigh size_t buffer_size = batch_size*out_channels*in_depth*in_height*in_width*sizeof(float); int num_weights = out_channels*in_channels*kernel_size*kernel_size*kernel_size; - Conv3D* layer = calloc(1, sizeof(Conv3D) + buffer_size); + Conv3D* layer = (Conv3D*)calloc(1, sizeof(Conv3D) + buffer_size); *layer = (Conv3D){ .output = (float*)(layer + 1), .weights = get_weights(weights, num_weights), @@ -558,7 +645,7 @@ struct LSTM { LSTM* make_lstm(Weights* weights, int batch_size, int input_size, int hidden_size) { int state_size = batch_size*hidden_size; - LSTM* layer = calloc(1, sizeof(LSTM) + 6*state_size*sizeof(float)); + LSTM* layer = (LSTM*)calloc(1, sizeof(LSTM) + 6*state_size*sizeof(float)); float* buffer = (float*)(layer + 1); *layer = (LSTM){ .state_h = buffer, @@ -619,7 +706,7 @@ struct LayerNorm { LayerNorm* make_layernorm(Weights* weights, int batch_size, int input_dim) { size_t output_size = batch_size*input_dim*sizeof(float); - LayerNorm* layer = calloc(1, sizeof(LayerNorm) + output_size); + LayerNorm* layer = (LayerNorm*)calloc(1, sizeof(LayerNorm) + output_size); *layer = (LayerNorm){ .output = (float*)(layer + 1), .weights = get_weights(weights, input_dim), @@ -645,7 +732,7 @@ struct OneHot { OneHot* make_one_hot(int batch_size, int input_size, int num_classes) { size_t buffer_size = batch_size*input_size*num_classes*sizeof(int); - OneHot* layer = calloc(1, sizeof(OneHot) + buffer_size); + OneHot* layer = (OneHot*)calloc(1, sizeof(OneHot) + buffer_size); *layer = (OneHot){ .output = (int*)(layer + 1), .batch_size = batch_size, @@ -669,7 +756,7 @@ struct CatDim1 { CatDim1* make_cat_dim1(int batch_size, int x_size, int y_size) { size_t buffer_size = batch_size*(x_size + y_size)*sizeof(float); - CatDim1* layer = calloc(1, sizeof(CatDim1) + buffer_size); + CatDim1* layer = (CatDim1*)calloc(1, sizeof(CatDim1) + buffer_size); *layer = (CatDim1){ .output = (float*)(layer + 1), .batch_size = batch_size, @@ -691,18 +778,18 @@ struct Multidiscrete { }; Multidiscrete* make_multidiscrete(int batch_size, int logit_sizes[], int num_actions) { - Multidiscrete* layer = calloc(1, sizeof(Multidiscrete)); + Multidiscrete* layer = (Multidiscrete*)calloc(1, sizeof(Multidiscrete)); layer->batch_size = batch_size; layer->num_actions = num_actions; memcpy(layer->logit_sizes, logit_sizes, num_actions*sizeof(int)); return layer; } -void argmax_multidiscrete(Multidiscrete* layer, float* input, int* output) { +void argmax_multidiscrete(Multidiscrete* layer, float* input, float* output) { _argmax_multidiscrete(input, output, layer->batch_size, layer->logit_sizes, layer->num_actions); } -void softmax_multidiscrete(Multidiscrete* layer, float* input, int* output) { +void softmax_multidiscrete(Multidiscrete* layer, float* input, float* output) { _softmax_multidiscrete(input, output, layer->batch_size, layer->logit_sizes, layer->num_actions); } @@ -712,21 +799,21 @@ typedef struct Default Default; struct Default { int num_agents; float* obs; - Linear* encoder; + Affine* encoder; ReLU* relu1; - Linear* actor; - Linear* value_fn; + Affine* actor; + Affine* value_fn; Multidiscrete* multidiscrete; }; Default* make_default(Weights* weights, int num_agents, int input_dim, int hidden_dim, int action_dim) { - Default* net = calloc(1, sizeof(Default)); + Default* net = (Default*)calloc(1, sizeof(Default)); net->num_agents = num_agents; net->obs = (float*)calloc(num_agents*input_dim, sizeof(float)); - net->encoder = make_linear(weights, num_agents, input_dim, hidden_dim); + net->encoder = make_affine(weights, num_agents, input_dim, hidden_dim); net->relu1 = make_relu(num_agents, hidden_dim); - net->actor = make_linear(weights, num_agents, hidden_dim, action_dim); - net->value_fn = make_linear(weights, num_agents, hidden_dim, 1); + net->actor = make_affine(weights, num_agents, hidden_dim, action_dim); + net->value_fn = make_affine(weights, num_agents, hidden_dim, 1); int logit_sizes[1] = {action_dim}; net->multidiscrete = make_multidiscrete(num_agents, logit_sizes, 1); return net; @@ -742,11 +829,11 @@ void free_default(Default* net) { free(net); } -void forward_default(Default* net, float* observations, int* actions) { - linear(net->encoder, observations); +void forward_default(Default* net, float* observations, float* actions) { + affine(net->encoder, observations); relu(net->relu1, net->encoder->output); - linear(net->actor, net->relu1->output); - linear(net->value_fn, net->relu1->output); + affine(net->actor, net->relu1->output); + affine(net->value_fn, net->relu1->output); softmax_multidiscrete(net->multidiscrete, net->actor->output, actions); } @@ -754,26 +841,26 @@ typedef struct LinearLSTM LinearLSTM; struct LinearLSTM { int num_agents; float* obs; - Linear* encoder; + Affine* encoder; GELU* gelu1; LSTM* lstm; - Linear* actor; - Linear* value_fn; + Affine* actor; + Affine* value_fn; Multidiscrete* multidiscrete; }; LinearLSTM* make_linearlstm(Weights* weights, int num_agents, int input_dim, int logit_sizes[], int num_actions) { - LinearLSTM* net = calloc(1, sizeof(LinearLSTM)); + LinearLSTM* net = (LinearLSTM*)calloc(1, sizeof(LinearLSTM)); net->num_agents = num_agents; - net->obs = calloc(num_agents*input_dim, sizeof(float)); - net->encoder = make_linear(weights, num_agents, input_dim, 128); + net->obs = (float*)calloc(num_agents*input_dim, sizeof(float)); + net->encoder = make_affine(weights, num_agents, input_dim, 128); net->gelu1 = make_gelu(num_agents, 128); int atn_sum = 0; for (int i = 0; i < num_actions; i++) { atn_sum += logit_sizes[i]; } - net->actor = make_linear(weights, num_agents, 128, atn_sum); - net->value_fn = make_linear(weights, num_agents, 128, 1); + net->actor = make_affine(weights, num_agents, 128, atn_sum); + net->value_fn = make_affine(weights, num_agents, 128, 1); net->lstm = make_lstm(weights, num_agents, 128, 128); net->multidiscrete = make_multidiscrete(num_agents, logit_sizes, num_actions); return net; @@ -790,12 +877,12 @@ void free_linearlstm(LinearLSTM* net) { free(net); } -void forward_linearlstm(LinearLSTM* net, float* observations, int* actions) { - linear(net->encoder, observations); +void forward_linearlstm(LinearLSTM* net, float* observations, float* actions) { + affine(net->encoder, observations); gelu(net->gelu1, net->encoder->output); lstm(net->lstm, net->gelu1->output); - linear(net->actor, net->lstm->state_h); - linear(net->value_fn, net->lstm->state_h); + affine(net->actor, net->lstm->state_h); + affine(net->value_fn, net->lstm->state_h); softmax_multidiscrete(net->multidiscrete, net->actor->output, actions); } @@ -806,26 +893,26 @@ typedef struct ConvLSTM ConvLSTM; struct ConvLSTM { ReLU* relu1; Conv2D* conv2; ReLU* relu2; - Linear* linear; + Affine* linear; LSTM* lstm; - Linear* actor; - Linear* value_fn; + Affine* actor; + Affine* value_fn; Multidiscrete* multidiscrete; }; ConvLSTM* make_convlstm(Weights* weights, int num_agents, int input_dim, int input_channels, int cnn_channels, int hidden_dim, int action_dim) { - ConvLSTM* net = calloc(1, sizeof(ConvLSTM)); + ConvLSTM* net = (ConvLSTM*)calloc(1, sizeof(ConvLSTM)); net->num_agents = num_agents; - net->obs = calloc(num_agents*input_dim*input_dim*input_channels, sizeof(float)); + net->obs = (float*)calloc(num_agents*input_dim*input_dim*input_channels, sizeof(float)); net->conv1 = make_conv2d(weights, num_agents, input_dim, input_dim, input_channels, cnn_channels, 5, 3); net->relu1 = make_relu(num_agents, hidden_dim*3*3); net->conv2 = make_conv2d(weights, num_agents, 3, 3, cnn_channels, cnn_channels, 3, 1); net->relu2 = make_relu(num_agents, hidden_dim); - net->linear = make_linear(weights, num_agents, cnn_channels, hidden_dim); - net->actor = make_linear(weights, num_agents, hidden_dim, action_dim); - net->value_fn = make_linear(weights, num_agents, hidden_dim, 1); + net->linear = make_affine(weights, num_agents, cnn_channels, hidden_dim); + net->actor = make_affine(weights, num_agents, hidden_dim, action_dim); + net->value_fn = make_affine(weights, num_agents, hidden_dim, 1); net->lstm = make_lstm(weights, num_agents, hidden_dim, hidden_dim); int logit_sizes[1] = {action_dim}; net->multidiscrete = make_multidiscrete(num_agents, logit_sizes, 1); @@ -846,14 +933,157 @@ void free_convlstm(ConvLSTM* net) { free(net); } -void forward_convlstm(ConvLSTM* net, float* observations, int* actions) { +void forward_convlstm(ConvLSTM* net, float* observations, float* actions) { conv2d(net->conv1, observations); relu(net->relu1, net->conv1->output); conv2d(net->conv2, net->relu1->output); relu(net->relu2, net->conv2->output); - linear(net->linear, net->relu2->output); + affine(net->linear, net->relu2->output); lstm(net->lstm, net->linear->output); - linear(net->actor, net->lstm->state_h); - linear(net->value_fn, net->lstm->state_h); + affine(net->actor, net->lstm->state_h); + affine(net->value_fn, net->lstm->state_h); softmax_multidiscrete(net->multidiscrete, net->actor->output, actions); } + +// MinGRU: inference-only single-step recurrent layer (no parallel scan). +// Matches the fused gate + highway connection in models.cu mingru_gate kernel. +// Each layer has a bias-free projection (hidden -> 3*hidden). +// State layout: (num_layers, batch_size, hidden_size). +typedef struct MinGRU MinGRU; +struct MinGRU { + float* state; // (num_layers, batch_size, hidden_size) - persists across steps + float* output; // (batch_size, hidden_size) + Linear** proj; // [num_layers], each projects hidden -> 3*hidden + int batch_size; + int hidden_size; + int num_layers; +}; + +MinGRU* make_mingru(Weights* weights, int batch_size, int hidden_size, int num_layers) { + MinGRU* layer = (MinGRU*)calloc(1, sizeof(MinGRU)); + layer->state = (float*)calloc(num_layers * batch_size * hidden_size, sizeof(float)); + layer->output = (float*)calloc(batch_size * hidden_size, sizeof(float)); + layer->proj = (Linear**)calloc(num_layers, sizeof(Linear*)); + layer->batch_size = batch_size; + layer->hidden_size = hidden_size; + layer->num_layers = num_layers; + for (int l = 0; l < num_layers; l++) { + layer->proj[l] = make_linear(weights, batch_size, hidden_size, 3 * hidden_size); + } + return layer; +} + +void mingru(MinGRU* layer, float* input) { + int B = layer->batch_size; + int H = layer->hidden_size; + float* x = input; + for (int l = 0; l < layer->num_layers; l++) { + float* state_l = layer->state + l * B * H; + linear(layer->proj[l], x); + float* combined = layer->proj[l]->output; + for (int b = 0; b < B; b++) { + float* cb = combined + b * 3 * H; + float* sb = state_l + b * H; + float* xb = x + b * H; + float* ob = layer->output + b * H; + for (int h = 0; h < H; h++) { + float hidden = cb[h]; + float gate = cb[H + h]; + float hw = cb[2*H + h]; + float s = sb[h]; + float gate_s = _sigmoid(gate); + float h_tilde = (hidden >= 0.0f) ? hidden + 0.5f : _sigmoid(hidden); + float mingru_out = s + gate_s * (h_tilde - s); + float hw_s = _sigmoid(hw); + ob[h] = hw_s * mingru_out + (1.0f - hw_s) * xb[h]; + sb[h] = mingru_out; + } + } + x = layer->output; + } +} + +void free_mingru(MinGRU* layer) { + for (int l = 0; l < layer->num_layers; l++) free(layer->proj[l]); + free(layer->state); + free(layer->output); + free(layer->proj); + free(layer); +} + +// PufferNet: default policy matching the native backend Policy in models.cu. +// Architecture: Linear encoder -> N x MinGRU -> Linear decoder (fused value). +// Weight file order (matches policy_weights_create reg_params call order): +// encoder weight (hidden_dim x input_dim) +// decoder weight ((atn_sum+1) x hidden_dim, last output is value) +// decoder logstd (1 x num_actions) IF continuous +// mingru weights[0..num_layers-1] (3*hidden_dim x hidden_dim each) +typedef struct PufferNet PufferNet; +struct PufferNet { + int num_agents; + float* obs; + Linear* encoder; + MinGRU* mingru; + Linear* decoder; // output_dim = atn_sum+1; last element is value + float* log_std; + int is_continuous; + int num_actions; + Multidiscrete* multidiscrete; +}; + +PufferNet* make_puffernet(Weights* weights, int num_agents, int input_dim, + int hidden_dim, int num_layers, int logit_sizes[], int num_actions) { + PufferNet* net = (PufferNet*)calloc(1, sizeof(PufferNet)); + net->num_agents = num_agents; + net->obs = (float*)calloc(num_agents * input_dim, sizeof(float)); + int atn_sum = 0; + int is_continuous = 1; + for (int i = 0; i < num_actions; i++) { + atn_sum += logit_sizes[i]; + if (logit_sizes[i] != 1) is_continuous = 0; + } + net->is_continuous = is_continuous; + net->num_actions = num_actions; + + net->encoder = make_linear(weights, num_agents, input_dim, hidden_dim); + net->decoder = make_linear(weights, num_agents, hidden_dim, atn_sum + 1); + if (net->is_continuous) { + net->log_std = get_weights_aligned(weights, num_actions); + } + net->mingru = make_mingru(weights, num_agents, hidden_dim, num_layers); + if (!net->is_continuous) { + net->multidiscrete = make_multidiscrete(num_agents, logit_sizes, num_actions); + } + return net; +} + +void _gaussian_mean(float* input, float* output, int batch_size, int num_actions) { + for (int b = 0; b < batch_size; b++) { + // +1 skips the value head fused into the decoder output + int in_adr = b * (num_actions + 1); + for (int a = 0; a < num_actions; a++) + output[b * num_actions + a] = input[in_adr + a]; + } +} + +void forward_puffernet(PufferNet* net, float* observations, float* actions) { + linear(net->encoder, observations); + mingru(net->mingru, net->encoder->output); + linear(net->decoder, net->mingru->output); + if (net->is_continuous) { + _gaussian_mean(net->decoder->output, actions, net->num_agents, net->num_actions); + } else { + softmax_multidiscrete(net->multidiscrete, net->decoder->output, actions); + } +} + +void free_puffernet(PufferNet* net) { + free(net->obs); + free(net->encoder); + free(net->decoder); + free_mingru(net->mingru); + if (net->multidiscrete) { + free(net->multidiscrete); + } + free(net); +} diff --git a/src/tensor.h b/src/tensor.h new file mode 100644 index 0000000000..8bf00d1c5f --- /dev/null +++ b/src/tensor.h @@ -0,0 +1,35 @@ +#ifndef PUFFERLIB_TENSOR_H +#define PUFFERLIB_TENSOR_H + +#include + +#define PUF_MAX_DIMS 8 + +typedef struct { + float* data; + int64_t shape[PUF_MAX_DIMS]; +} FloatTensor; + +typedef struct { + unsigned char* data; + int64_t shape[PUF_MAX_DIMS]; +} ByteTensor; + +typedef struct { + long* data; + int64_t shape[PUF_MAX_DIMS]; +} LongTensor; + +typedef struct { + int* data; + int64_t shape[PUF_MAX_DIMS]; +} IntTensor; + +#ifdef __CUDACC__ +typedef struct { + precision_t* data; + int64_t shape[PUF_MAX_DIMS]; +} PrecisionTensor; +#endif + +#endif // PUFFERLIB_TENSOR_H diff --git a/src/vecenv.h b/src/vecenv.h new file mode 100644 index 0000000000..6464de89f8 --- /dev/null +++ b/src/vecenv.h @@ -0,0 +1,664 @@ +// vecenv.h - Static env binding: types + implementation +// Types/declarations always available (for pufferlib.cu). +// Implementations compiled only when OBS_SIZE is defined (by binding.c). + +#pragma once + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#include "tensor.h" + +// Dict types +typedef struct { + const char* key; + double value; + void* ptr; +} DictItem; + +typedef struct { + DictItem* items; + int size; + int capacity; +} Dict; + +static inline Dict* create_dict(int capacity) { + Dict* dict = (Dict*)calloc(1, sizeof(Dict)); + dict->capacity = capacity; + dict->items = (DictItem*)calloc(capacity, sizeof(DictItem)); + return dict; +} + +static inline DictItem* dict_get_unsafe(Dict* dict, const char* key) { + for (int i = 0; i < dict->size; i++) { + if (strcmp(dict->items[i].key, key) == 0) { + return &dict->items[i]; + } + } + return NULL; +} + +static inline DictItem* dict_get(Dict* dict, const char* key) { + DictItem* item = dict_get_unsafe(dict, key); + if (item == NULL) printf("dict_get failed to find key: %s\n", key); + assert(item != NULL); + return item; +} + +static inline void dict_set(Dict* dict, const char* key, double value) { + assert(dict->size < dict->capacity); + DictItem* item = dict_get_unsafe(dict, key); + if (item != NULL) { + item->value = value; + return; + } + dict->items[dict->size].key = key; + dict->items[dict->size].value = value; + dict->size++; +} + +// Forward declare CUDA stream type +typedef struct CUstream_st* cudaStream_t; + +// Threading state +typedef struct StaticThreading StaticThreading; + +// Generic VecEnv - envs is void* to be type-agnostic +typedef struct StaticVec { + void* envs; + int size; + int total_agents; + int buffers; + int agents_per_buffer; + int* buffer_env_starts; + int* buffer_env_counts; + void* observations; + float* actions; + float* rewards; + float* terminals; + void* gpu_observations; + float* gpu_actions; + float* gpu_rewards; + float* gpu_terminals; + cudaStream_t* streams; + StaticThreading* threading; + int obs_size; + int num_atns; + int gpu; +} StaticVec; + +// Callback types +typedef void (*net_callback_fn)(void* ctx, int buf, int t); +typedef void (*thread_init_fn)(void* ctx, int buf); +typedef void (*step_fn)(void* env); + +enum EvalProfileIdx { + EVAL_GPU = 0, // forward + D2H (everything before env step) + EVAL_ENV_STEP, // OMP c_step (pure CPU) + NUM_EVAL_PROF, +}; + +// Functions implemented by env's static library +StaticVec* create_static_vec(int total_agents, int num_buffers, int gpu, Dict* vec_kwargs, Dict* env_kwargs); +void static_vec_reset(StaticVec* vec); +void static_vec_close(StaticVec* vec); +void static_vec_log(StaticVec* vec, Dict* out); +void static_vec_eval_log(StaticVec* vec, Dict* out); +void create_static_threads(StaticVec* vec, int num_threads, int horizon, + void* ctx, net_callback_fn net_callback, thread_init_fn thread_init); +void static_vec_omp_step(StaticVec* vec); +void static_vec_seq_step(StaticVec* vec); +void static_vec_render(StaticVec* vec, int env_id); +void static_vec_read_profile(StaticVec* vec, float out[NUM_EVAL_PROF]); + +// Env info +int get_obs_size(void); +int get_num_atns(void); +int* get_act_sizes(void); +int get_num_act_sizes(void); +const char* get_obs_dtype(void); +size_t get_obs_elem_size(void); + +// Synchronous single-step +void static_vec_step(StaticVec* vec); +void gpu_vec_step(StaticVec* vec); +void cpu_vec_step(StaticVec* vec); + +// Optional shared state functions +void* my_shared(void* env, Dict* kwargs); +void my_shared_close(void* env); +void* my_get(void* env, Dict* out); +int my_put(void* env, Dict* kwargs); + +#ifdef __cplusplus +} +#endif + +// ============================================================================ +// Implementation — only compiled when OBS_SIZE is defined (i.e. from binding.c) +// ============================================================================ + +#ifdef OBS_SIZE + +static inline size_t obs_element_size(void) { + OBS_TENSOR_T t; + return sizeof(*t.data); +} + +// Usually near the top, after any #includes +#define _STRINGIFY(x) #x +#define STRINGIFY(x) _STRINGIFY(x) +const char dtype_symbol[] = STRINGIFY(OBS_TENSOR_T); + +#include +#include +#include +#include +#include + +// Forward declare CUDA types and functions to avoid conflicts with raylib's float3 +typedef int cudaError_t; +typedef int cudaMemcpyKind; +#define cudaSuccess 0 +#define cudaMemcpyHostToDevice 1 +#define cudaMemcpyDeviceToHost 2 +#define cudaHostAllocPortable 1 +#define cudaStreamNonBlocking 1 + +extern cudaError_t cudaHostAlloc(void**, size_t, unsigned int); +extern cudaError_t cudaMalloc(void**, size_t); +extern cudaError_t cudaMemcpy(void*, const void*, size_t, cudaMemcpyKind); +extern cudaError_t cudaMemcpyAsync(void*, const void*, size_t, cudaMemcpyKind, cudaStream_t); +extern cudaError_t cudaMemset(void*, int, size_t); +extern cudaError_t cudaFree(void*); +extern cudaError_t cudaFreeHost(void*); +extern cudaError_t cudaSetDevice(int); +extern cudaError_t cudaDeviceSynchronize(void); +extern cudaError_t cudaStreamSynchronize(cudaStream_t); +extern cudaError_t cudaStreamCreateWithFlags(cudaStream_t*, unsigned int); +extern cudaError_t cudaStreamQuery(cudaStream_t); +extern const char* cudaGetErrorString(cudaError_t); + +#define OMP_WAITING 5 +#define OMP_RUNNING 6 + +// Forward declare env-provided functions (defined in binding.c after this include) +void my_init(Env* env, Dict* kwargs); +void my_log(Log* log, Dict* out); + + +struct StaticThreading { + atomic_int* buffer_states; + atomic_int shutdown; + int num_threads; + int num_buffers; + pthread_t* threads; + float* accum; // [num_buffers * NUM_EVAL_PROF] per-buffer timing in ms +}; + +typedef struct StaticOMPArg { + StaticVec* vec; + int buf; + int horizon; + void* ctx; + net_callback_fn net_callback; + thread_init_fn thread_init; +} StaticOMPArg; + +// OMP thread manager +static void* static_omp_threadmanager(void* arg) { + StaticOMPArg* worker_arg = (StaticOMPArg*)arg; + StaticVec* vec = worker_arg->vec; + StaticThreading* threading = vec->threading; + int buf = worker_arg->buf; + int horizon = worker_arg->horizon; + void* ctx = worker_arg->ctx; + net_callback_fn net_callback = worker_arg->net_callback; + thread_init_fn thread_init = worker_arg->thread_init; + + if (thread_init != NULL) { + thread_init(ctx, buf); + } + + int agents_per_buffer = vec->agents_per_buffer; + int agent_start = buf * agents_per_buffer; + int env_start = vec->buffer_env_starts[buf]; + int env_count = vec->buffer_env_counts[buf]; + atomic_int* buffer_states = threading->buffer_states; + int num_workers = threading->num_threads / vec->buffers; + if (num_workers < 1) num_workers = 1; + + Env* envs = (Env*)vec->envs; + + printf("Num workers: %d\n", num_workers); + while (true) { + while (atomic_load(&buffer_states[buf]) != OMP_RUNNING) { + if (atomic_load(&threading->shutdown)) { + return NULL; + } + } + cudaStream_t stream = vec->streams[buf]; + + float* my_accum = &threading->accum[buf * NUM_EVAL_PROF]; + struct timespec t0, t1; + + for (int t = 0; t < horizon; t++) { + clock_gettime(CLOCK_MONOTONIC, &t0); + net_callback(ctx, buf, t); + + cudaMemcpyAsync( + &vec->actions[agent_start * NUM_ATNS], + &vec->gpu_actions[agent_start * NUM_ATNS], + agents_per_buffer * NUM_ATNS * sizeof(float), + cudaMemcpyDeviceToHost, stream); + cudaStreamSynchronize(stream); + clock_gettime(CLOCK_MONOTONIC, &t1); + my_accum[EVAL_GPU] += (t1.tv_sec - t0.tv_sec) * 1000.0f + (t1.tv_nsec - t0.tv_nsec) / 1e6f; + + memset(&vec->rewards[agent_start], 0, agents_per_buffer * sizeof(float)); + memset(&vec->terminals[agent_start], 0, agents_per_buffer * sizeof(float)); + clock_gettime(CLOCK_MONOTONIC, &t0); + #pragma omp parallel for schedule(static) num_threads(num_workers) + for (int i = env_start; i < env_start + env_count; i++) { + c_step(&envs[i]); + } + clock_gettime(CLOCK_MONOTONIC, &t1); + my_accum[EVAL_ENV_STEP] += (t1.tv_sec - t0.tv_sec) * 1000.0f + (t1.tv_nsec - t0.tv_nsec) / 1e6f; + + cudaMemcpyAsync( + (char*)vec->gpu_observations + agent_start * OBS_SIZE * obs_element_size(), + (char*)vec->observations + agent_start * OBS_SIZE * obs_element_size(), + agents_per_buffer * OBS_SIZE * obs_element_size(), + cudaMemcpyHostToDevice, stream); + cudaMemcpyAsync( + &vec->gpu_rewards[agent_start], + &vec->rewards[agent_start], + agents_per_buffer * sizeof(float), + cudaMemcpyHostToDevice, stream); + cudaMemcpyAsync( + &vec->gpu_terminals[agent_start], + &vec->terminals[agent_start], + agents_per_buffer * sizeof(float), + cudaMemcpyHostToDevice, stream); + } + cudaStreamSynchronize(stream); + atomic_store(&buffer_states[buf], OMP_WAITING); + } +} + +void static_vec_omp_step(StaticVec* vec) { + StaticThreading* threading = vec->threading; + for (int buf = 0; buf < vec->buffers; buf++) { + atomic_store(&threading->buffer_states[buf], OMP_RUNNING); + } + for (int buf = 0; buf < vec->buffers; buf++) { + while (atomic_load(&threading->buffer_states[buf]) != OMP_WAITING) {} + } +} + +void static_vec_seq_step(StaticVec* vec) { + StaticThreading* threading = vec->threading; + for (int buf = 0; buf < vec->buffers; buf++) { + atomic_store(&threading->buffer_states[buf], OMP_RUNNING); + while (atomic_load(&threading->buffer_states[buf]) != OMP_WAITING) {} + } +} + +// Optional: Initialize all envs at once (for shared state, variable agents per env, etc.) +// Default implementation creates envs until total_agents is reached +#ifdef MY_VEC_INIT +Env* my_vec_init(int* num_envs_out, int* buffer_env_starts, int* buffer_env_counts, + Dict* vec_kwargs, Dict* env_kwargs); +#else +Env* my_vec_init(int* num_envs_out, int* buffer_env_starts, int* buffer_env_counts, + Dict* vec_kwargs, Dict* env_kwargs) { + + int total_agents = (int)dict_get(vec_kwargs, "total_agents")->value; + int num_buffers = (int)dict_get(vec_kwargs, "num_buffers")->value; + int agents_per_buffer = total_agents / num_buffers; + + // Allocate max possible envs (1 agent per env worst case) + Env* envs = (Env*)calloc(total_agents, sizeof(Env)); + + int num_envs = 0; + int agents_created = 0; + while (agents_created < total_agents) { + srand(num_envs); + envs[num_envs].rng = num_envs; + my_init(&envs[num_envs], env_kwargs); + agents_created += envs[num_envs].num_agents; + num_envs++; + } + + // Shrink to actual size needed + envs = (Env*)realloc(envs, num_envs * sizeof(Env)); + + // Fill buffer info by iterating through envs + int buf = 0; + int buf_agents = 0; + buffer_env_starts[0] = 0; + buffer_env_counts[0] = 0; + for (int i = 0; i < num_envs; i++) { + buf_agents += envs[i].num_agents; + buffer_env_counts[buf]++; + if (buf_agents >= agents_per_buffer && buf < num_buffers - 1) { + buf++; + buffer_env_starts[buf] = i + 1; + buffer_env_counts[buf] = 0; + buf_agents = 0; + } + } + + *num_envs_out = num_envs; + return envs; +} +#endif + +#ifdef MY_VEC_CLOSE +void my_vec_close(Env* envs); +#else +void my_vec_close(Env* envs) { + return; +} +#endif + +StaticVec* create_static_vec(int total_agents, int num_buffers, int gpu, Dict* vec_kwargs, Dict* env_kwargs) { + StaticVec* vec = (StaticVec*)calloc(1, sizeof(StaticVec)); + vec->total_agents = total_agents; + vec->buffers = num_buffers; + vec->agents_per_buffer = total_agents / num_buffers; + vec->obs_size = OBS_SIZE; + vec->num_atns = NUM_ATNS; + vec->gpu = gpu; + + vec->buffer_env_starts = (int*)calloc(num_buffers, sizeof(int)); + vec->buffer_env_counts = (int*)calloc(num_buffers, sizeof(int)); + + // Let my_vec_init allocate and initialize envs, fill buffer info + int num_envs = 0; + vec->envs = my_vec_init(&num_envs, vec->buffer_env_starts, vec->buffer_env_counts, + vec_kwargs, env_kwargs); + vec->size = num_envs; + + size_t obs_elem_size = obs_element_size(); + if (gpu) { + cudaHostAlloc((void**)&vec->observations, total_agents * OBS_SIZE * obs_elem_size, cudaHostAllocPortable); + cudaHostAlloc((void**)&vec->actions, total_agents * NUM_ATNS * sizeof(float), cudaHostAllocPortable); + cudaHostAlloc((void**)&vec->rewards, total_agents * sizeof(float), cudaHostAllocPortable); + cudaHostAlloc((void**)&vec->terminals, total_agents * sizeof(float), cudaHostAllocPortable); + + cudaMalloc((void**)&vec->gpu_observations, total_agents * OBS_SIZE * obs_elem_size); + cudaMalloc((void**)&vec->gpu_actions, total_agents * NUM_ATNS * sizeof(float)); + cudaMalloc((void**)&vec->gpu_rewards, total_agents * sizeof(float)); + cudaMalloc((void**)&vec->gpu_terminals, total_agents * sizeof(float)); + + cudaMemset(vec->gpu_observations, 0, total_agents * OBS_SIZE * obs_elem_size); + cudaMemset(vec->gpu_actions, 0, total_agents * NUM_ATNS * sizeof(float)); + cudaMemset(vec->gpu_rewards, 0, total_agents * sizeof(float)); + cudaMemset(vec->gpu_terminals, 0, total_agents * sizeof(float)); + } else { + vec->observations = calloc(total_agents * OBS_SIZE, obs_elem_size); + vec->actions = (float*)calloc(total_agents * NUM_ATNS, sizeof(float)); + vec->rewards = (float*)calloc(total_agents, sizeof(float)); + vec->terminals = (float*)calloc(total_agents, sizeof(float)); + // CPU mode: gpu pointers alias the same buffers (no copy needed) + vec->gpu_observations = vec->observations; + vec->gpu_actions = vec->actions; + vec->gpu_rewards = vec->rewards; + vec->gpu_terminals = vec->terminals; + } + + // Streams allocated here, created in create_static_threads + vec->streams = (cudaStream_t*)calloc(num_buffers, sizeof(cudaStream_t)); + + // Assign pointers to envs based on buffer layout + Env* envs = (Env*)vec->envs; + for (int buf = 0; buf < num_buffers; buf++) { + int buf_start = buf * vec->agents_per_buffer; + int buf_agent = 0; + int env_start = vec->buffer_env_starts[buf]; + int env_count = vec->buffer_env_counts[buf]; + + for (int e = 0; e < env_count; e++) { + Env* env = &envs[env_start + e]; + int slot = buf_start + buf_agent; + env->observations = (void*)((char*)vec->observations + slot * OBS_SIZE * obs_elem_size); + env->actions = vec->actions + slot * NUM_ATNS; + env->rewards = vec->rewards + slot; + env->terminals = vec->terminals + slot; + buf_agent += env->num_agents; + } + } + + return vec; +} + +void static_vec_reset(StaticVec* vec) { + Env* envs = (Env*)vec->envs; + for (int i = 0; i < vec->size; i++) { + c_reset(&envs[i]); + } + if (vec->gpu) { + cudaMemcpy(vec->gpu_observations, vec->observations, + vec->total_agents * OBS_SIZE * obs_element_size(), cudaMemcpyHostToDevice); + cudaMemset(vec->gpu_rewards, 0, vec->total_agents * sizeof(float)); + cudaMemset(vec->gpu_terminals, 0, vec->total_agents * sizeof(float)); + cudaDeviceSynchronize(); + } else { + memset(vec->rewards, 0, vec->total_agents * sizeof(float)); + memset(vec->terminals, 0, vec->total_agents * sizeof(float)); + } +} + +void create_static_threads(StaticVec* vec, int num_threads, int horizon, + void* ctx, net_callback_fn net_callback, thread_init_fn thread_init) { + vec->threading = (StaticThreading*)calloc(1, sizeof(StaticThreading)); + vec->threading->num_threads = num_threads; + vec->threading->num_buffers = vec->buffers; + vec->threading->buffer_states = (atomic_int*)calloc(vec->buffers, sizeof(atomic_int)); + vec->threading->threads = (pthread_t*)calloc(vec->buffers, sizeof(pthread_t)); + vec->threading->accum = (float*)calloc(vec->buffers * NUM_EVAL_PROF, sizeof(float)); + + // Streams are now created by pufferlib.cu (PyTorch-managed streams) + // Do NOT create streams here - they've already been set up + + StaticOMPArg* args = (StaticOMPArg*)calloc(vec->buffers, sizeof(StaticOMPArg)); + for (int i = 0; i < vec->buffers; i++) { + args[i].vec = vec; + args[i].buf = i; + args[i].horizon = horizon; + args[i].ctx = ctx; + args[i].net_callback = net_callback; + args[i].thread_init = thread_init; + pthread_create(&vec->threading->threads[i], NULL, static_omp_threadmanager, &args[i]); + } +} + +void static_vec_close(StaticVec* vec) { + Env* envs = (Env*)vec->envs; + + if (vec->threading != NULL) { + atomic_store(&vec->threading->shutdown, 1); + for (int i = 0; i < vec->buffers; i++) { + pthread_join(vec->threading->threads[i], NULL); + } + } + + for (int i = 0; i < vec->size; i++) { + Env* env = &envs[i]; + c_close(env); + } + + my_vec_close(envs); + free(vec->envs); + if (vec->threading != NULL) { + free(vec->threading->buffer_states); + free(vec->threading->threads); + free(vec->threading->accum); + free(vec->threading); + } + free(vec->buffer_env_starts); + free(vec->buffer_env_counts); + + if (vec->gpu) { + cudaDeviceSynchronize(); + cudaFree(vec->gpu_observations); + cudaFree(vec->gpu_actions); + cudaFree(vec->gpu_rewards); + cudaFree(vec->gpu_terminals); + cudaFreeHost(vec->observations); + cudaFreeHost(vec->actions); + cudaFreeHost(vec->rewards); + cudaFreeHost(vec->terminals); + } else { + free(vec->observations); + free(vec->actions); + free(vec->rewards); + free(vec->terminals); + } + + free(vec->streams); + free(vec); +} + +static inline float static_vec_aggregate_logs(StaticVec* vec, Log* out) { + Env* envs = (Env*)vec->envs; + memset(out, 0, sizeof(Log)); + int num_keys = sizeof(Log) / sizeof(float); + for (int i = 0; i < vec->size; i++) { + Env* env = &envs[i]; + if (env->log.n == 0) { + continue; + } + for (int j = 0; j < num_keys; j++) { + ((float*)out)[j] += ((float*)&env->log)[j]; + } + } + float n = out->n; + if (n == 0.0f) { + return 0; + } + for (int i = 0; i < num_keys; i++) { + ((float*)out)[i] /= n; + } + return n; +} + +void static_vec_log(StaticVec* vec, Dict* out) { + Env* envs = (Env*)vec->envs; + Log aggregate; + float n = static_vec_aggregate_logs(vec, &aggregate); + if (n == 0) { + return; + } + for (int i = 0; i < vec->size; i++) { + memset(&envs[i].log, 0, sizeof(Log)); + } + my_log(&aggregate, out); + dict_set(out, "n", n); +} + +void static_vec_eval_log(StaticVec* vec, Dict* out) { + Log aggregate; + float n = static_vec_aggregate_logs(vec, &aggregate); + if (n == 0) { + return; + } + my_log(&aggregate, out); + dict_set(out, "n", n); +} + +void static_vec_read_profile(StaticVec* vec, float out[NUM_EVAL_PROF]) { + StaticThreading* threading = vec->threading; + memset(out, 0, NUM_EVAL_PROF * sizeof(float)); + for (int buf = 0; buf < threading->num_buffers; buf++) { + float* src = &threading->accum[buf * NUM_EVAL_PROF]; + for (int i = 0; i < NUM_EVAL_PROF; i++) { + out[i] += src[i]; + } + memset(src, 0, NUM_EVAL_PROF * sizeof(float)); + } + // Average across buffers (they run in parallel) + for (int i = 0; i < NUM_EVAL_PROF; i++) { + out[i] /= threading->num_buffers; + } +} + +void static_vec_render(StaticVec* vec, int env_id) { + Env* envs = (Env*)vec->envs; + c_render(&envs[env_id]); +} + +int get_obs_size(void) { return OBS_SIZE; } +int get_num_atns(void) { return NUM_ATNS; } +static int _act_sizes[] = ACT_SIZES; +int* get_act_sizes(void) { return _act_sizes; } +int get_num_act_sizes(void) { return (int)(sizeof(_act_sizes) / sizeof(_act_sizes[0])); } +const char* get_obs_dtype(void) { return dtype_symbol; } +size_t get_obs_elem_size(void) { return obs_element_size(); } + +static inline void _static_vec_env_step(StaticVec* vec) { + memset(vec->rewards, 0, vec->total_agents * sizeof(float)); + memset(vec->terminals, 0, vec->total_agents * sizeof(float)); + Env* envs = (Env*)vec->envs; + #pragma omp parallel for schedule(static) + for (int i = 0; i < vec->size; i++) { + c_step(&envs[i]); + } +} + +void gpu_vec_step(StaticVec* vec) { + assert(vec->buffers == 1); + cudaMemcpy(vec->actions, vec->gpu_actions, + (size_t)vec->total_agents * NUM_ATNS * sizeof(float), + cudaMemcpyDeviceToHost); + _static_vec_env_step(vec); + cudaMemcpy(vec->gpu_observations, vec->observations, + (size_t)vec->total_agents * OBS_SIZE * obs_element_size(), + cudaMemcpyHostToDevice); + cudaMemcpy(vec->gpu_rewards, vec->rewards, + vec->total_agents * sizeof(float), cudaMemcpyHostToDevice); + cudaMemcpy(vec->gpu_terminals, vec->terminals, + vec->total_agents * sizeof(float), cudaMemcpyHostToDevice); +} + +void cpu_vec_step(StaticVec* vec) { + assert(vec->buffers == 1); + _static_vec_env_step(vec); +} + +void static_vec_step(StaticVec* vec) { + if (vec->gpu) gpu_vec_step(vec); + else cpu_vec_step(vec); +} + +// Optional shared state functions - default implementations +#ifndef MY_SHARED +void* my_shared(void* env, Dict* kwargs) { + return NULL; +} +#endif + +#ifndef MY_SHARED_CLOSE +void my_shared_close(void* env) {} +#endif + +#ifndef MY_GET +void* my_get(void* env, Dict* out) { + return NULL; +} +#endif + +#ifndef MY_PUT +int my_put(void* env, Dict* kwargs) { + return 0; +} +#endif + +#endif // OBS_SIZE diff --git a/tests/mem_test.py b/tests/mem_test.py deleted file mode 100644 index d0ca0c4d4e..0000000000 --- a/tests/mem_test.py +++ /dev/null @@ -1,93 +0,0 @@ -from pdb import set_trace as T -import numpy as np -import time - -import selectors -from multiprocessing import Process, Pipe, Array - -def worker_process(envs_per_worker, shared_mem, bandwidth, - delay_mean, delay_std, send_pipe, recv_pipe): - data = np.random.randn(bandwidth) - while True: - request = recv_pipe.recv() - for _ in range(envs_per_worker): - start = time.process_time() - idx = 0 - target_time = delay_mean + delay_std*np.random.randn() - while time.process_time() - start < target_time: - idx += 1 - shared_mem[:bandwidth] = data - - send_pipe.send('end') - - -def test_speed(envs_per_worker=1, bandwidth=1, delay_mean=0.01, delay_std=0.001, - num_workers=4, batch_size=4, timeout=10): - - main_send_pipes, work_recv_pipes = zip(*[Pipe() for _ in range(num_workers)]) - work_send_pipes, main_recv_pipes = zip(*[Pipe() for _ in range(num_workers)]) - - shared_mem = [Array('d', bandwidth) for _ in range(num_workers)] - processes = [Process( - target=worker_process, - args=(envs_per_worker, shared_mem, bandwidth, - delay_mean, delay_std, work_send_pipes[i], work_recv_pipes[i])) - for i in range(num_workers)] - - for p in processes: - p.start() - - send_idxs = {i for i in range(num_workers)} - - # Register all receive pipes with the selector - sel = selectors.DefaultSelector() - for pipe in main_recv_pipes: - sel.register(pipe, selectors.EVENT_READ) - - steps_collected = 0 - start = time.time() - while time.time() - start < timeout: - for idx in send_idxs: - main_send_pipes[idx].send('start') - - send_idxs = set() - - for key, _ in sel.select(timeout=None): - pipe = key.fileobj - idx = main_recv_pipes.index(pipe) - - if pipe.poll(): - assert pipe.recv() == 'end' - send_idxs.add(idx) - - if len(send_idxs) == batch_size: - break - - end = time.time() - - for p in processes: - p.terminate() - - sps = steps_collected / (end - start) - print( - f'SPS: {sps:.2f}', - f'envs_per_worker: {envs_per_worker}', - f'delay_mean: {delay_mean}', - f'delay_std: {delay_std}', - f'num_workers: {num_workers}', - f'batch_size: {batch_size}', - f'sync: {sync}', - ) - - -if __name__ == '__main__': - #timeout = 1 - #test_speed(timeout=1) - test_speed(delay_mean=0, delay_std=0, num_workers=1, batch_size=1) - test_speed(delay_mean=0, delay_std=0, num_workers=1, batch_size=1) - test_speed(delay_mean=0, delay_std=0, num_workers=6, batch_size=6) - test_speed(delay_mean=0, delay_std=0, num_workers=6, batch_size=6) - test_speed(delay_mean=0, delay_std=0, num_workers=24, batch_size=6) - test_speed(delay_mean=0, delay_std=0, num_workers=24, batch_size=24) - test_speed(delay_mean=0, delay_std=0, num_workers=24, batch_size=6) - diff --git a/tests/microbench.py b/tests/microbench.py new file mode 100644 index 0000000000..87cb22fc6e --- /dev/null +++ b/tests/microbench.py @@ -0,0 +1,364 @@ +import time +import rich + +import torch +import torch.utils.cpp_extension + +import pufferlib +try: + from pufferlib import _C +except ImportError: + raise ImportError('Failed to import C/CUDA advantage kernel. If you have non-default PyTorch, try installing with --no-build-isolation') + +BR = 4096 # Rollout batch (no T dim) +BT = 512 # Train batch (with T dim) +T = 64 +H = 128 +A = 4 +TIMEOUT = 1 + +def check_close(a, b, rtol=1e-3, atol=1e-4): + output = [] + assert len(a) == len(b) + for a, b in zip(a, b): + a = a.float() + b = b.float() + max_diff = (a - b).abs().max() + passed = torch.allclose(a, b, rtol=rtol, atol=atol) + color = 'green' if passed else 'red' + output.append(f'[{color}]{max_diff:.2e}[/{color}]') + + return ' '.join(output) + +def parse_args(args): + py_args = [] + cpp_args = [] + backward = False + for arg in args: + if isinstance(arg, torch.Tensor): + if arg.requires_grad: + backward = True + + # VERY IMPORTANT: You have to set requires_grad AFTER moving to GPU + # Otherwise torch moves grads back to CPU and crushes perf + #dtype = torch.float64 if arg.dtype == torch.float32 else arg.dtype + dtype = torch.float32 if arg.dtype == torch.float32 else arg.dtype + py_args.append(arg.clone().detach().to(dtype).cuda().requires_grad_(arg.requires_grad)) + cpp_args.append(arg.clone().detach().cuda().requires_grad_(arg.requires_grad)) + else: + py_args.append(arg) + cpp_args.append(arg) + + return py_args, cpp_args, backward + +def test_loss(outputs): + if type(outputs) == torch.Tensor: + return outputs.sum() + + return sum([o.sum() for o in outputs])/len(outputs) + +def test_kernel(py_func, cpp_func, *args, benchmark=True): + py_args, cpp_args, backward = parse_args(args) + + py_out = py_func(*py_args) + cpp_out = cpp_func(*cpp_args) + + if not isinstance(py_out, (tuple, list)): + py_out = [py_out] + if not isinstance(cpp_out, (tuple, list)): + cpp_out = [cpp_out] + + output = check_close(py_out, cpp_out) + rich.print('\tForward check:', output) + + if backward: + py_loss = test_loss(py_out) + cpp_loss = test_loss(cpp_out) + + py_loss.backward() + cpp_loss.backward() + + has_grad = lambda v: [e.grad for e in v if isinstance(e, torch.Tensor) and e.grad is not None] + py_grad = has_grad(py_args) + cpp_grad = has_grad(cpp_args) + + + output = check_close(py_grad, cpp_grad) + rich.print('\tBackward check:', output) + + if benchmark: + py_sps = time_sps(py_func, *py_args) + cpp_sps = time_sps(cpp_func, *cpp_args) + print(f'\tForward sps: {py_sps} (naive) {cpp_sps} (C++)') + + if backward: + py_sps = time_sps(py_func, *py_args, backward=True) + cpp_sps = time_sps(cpp_func, *cpp_args, backward=True) + print(f'\tBackward sps: {py_sps} (naive) {cpp_sps} (C++)') + +def time_sps(func, *args, backward=False): + assert isinstance(args[0], torch.Tensor) + N = args[0].shape[:-1].numel() + + if backward: + outputs = func(*args) + if not isinstance(outputs, (tuple, list)): + outputs = [outputs] + grad_outputs = [torch.randn_like(o) for o in outputs] + + # Warm up + for i in range(3): + if backward: + for arg in args: + if isinstance(arg, torch.Tensor) and arg.requires_grad: + arg.grad = None + torch.autograd.backward(outputs, grad_outputs, retain_graph=True) + else: + with torch.no_grad(): + func(*args) + + torch.cuda.synchronize() + start = time.time() + steps = 0 + while time.time() - start < TIMEOUT: + steps += 1 + if backward: + for arg in args: + if isinstance(arg, torch.Tensor) and arg.requires_grad: + arg.grad = None + torch.autograd.backward(outputs, grad_outputs, retain_graph=True) + else: + with torch.no_grad(): + func(*args) + + torch.cuda.synchronize() + sps = N*steps/(time.time() - start) + if sps < 1e3: + return f'{sps:.2f}' + if sps < 1e6: + return f'{sps/1e3:.2f} K' + if sps < 1e9: + return f'{sps/1e6:.2f} M' + + return f'{sps/1e9:.2f} B' + +def mingru_gate(state, gate, hidden): + hidden = torch.where(hidden >= 0, hidden + 0.5, hidden.sigmoid()) + gate = gate.sigmoid() + out = torch.lerp(state, hidden, gate) + return out + +def test_mingru_gate(): + state = torch.randn(BR, H) + gate = torch.randn(BR, H) + hidden = torch.randn(BR, H) + print('mingru_gate') + test_kernel(mingru_gate, _C.mingru_gate, state, gate, hidden) + +def log_coeffs_and_values(gate, hidden): + log_coeffs = -torch.nn.functional.softplus(gate) + log_z = -torch.nn.functional.softplus(-gate) + log_tilde_h = torch.where(hidden >= 0, + (torch.nn.functional.relu(hidden) + 0.5).log(), + -torch.nn.functional.softplus(-hidden)) + log_values = log_z + log_tilde_h + return log_coeffs, log_values + +def log_coeffs_and_values_loss(outputs): + log_coeffs, log_values = outputs + return torch.sum(log_coeffs) + torch.sum(log_values) + +def test_log_coeffs_and_values(): + gate = torch.randn(BT, T, H, requires_grad=True) + hidden = torch.randn(BT, T, H, requires_grad=True) + print('log_coeffs_and_values') + test_kernel(log_coeffs_and_values, _C.log_coeffs_and_values, gate, hidden) + +def fused_scan(log_coeffs, log_values, state): + # Fuse cat+pad+narrow into the scan (matches kernel behavior) + log_values = torch.cat([state.log(), log_values], dim=1) + log_coeffs = torch.nn.functional.pad(log_coeffs, (0, 0, 1, 0)) + a_star = log_coeffs.cumsum(1) + log_h0_plus_b_star = (log_values - a_star).logcumsumexp(1) + log_h = a_star + log_h0_plus_b_star + full_out = log_h.exp() + # Narrow to get last T timesteps (kernel returns this directly) + T = log_values.size(1) - 1 # original T before cat + out = full_out.narrow(1, 1, T) # skip first timestep + next_state = full_out.narrow(1, T, 1) # last timestep + return [out, next_state] + +def fused_scan_loss(outputs): + return torch.sum(outputs[0]) + torch.sum(outputs[1]) + +def test_fused_scan(): + # Numerically unstable function. Must be called with the distribution + # that is used in the full network. + log_coeffs = -torch.nn.functional.softplus(torch.randn(BT, T, H)).requires_grad_(True) + log_values = -torch.nn.functional.softplus(torch.randn(BT, T, H)).requires_grad_(True) + state = torch.rand(BT, 1, H).requires_grad_(True) # state must be positive for log + + print('fused_scan') + test_kernel(fused_scan, _C.fused_scan, log_coeffs, log_values, state) + +def logcumsumexp(x): + return [torch.log(torch.exp(x).cumsum(1))] + +def logcumsumexp_loss(outputs): + return torch.sum(outputs[0]) + +def test_logcumsumexp(): + x = torch.randn(BT, T, H, requires_grad=True) + print('logcumsumexp') + test_kernel(logcumsumexp, _C.logcumsumexp_cuda, x) + +def fused_ppo_loss(logits, newvalue, actions, old_logprobs, + advantages, prio, values, returns, adv_mean, adv_std, + clip_coef, vf_clip_coef, vf_coef, ent_coef): + + segments, horizon, _ = logits.shape + + flat_logits = logits.reshape(-1, logits.size(-1)); + flat_actions = actions.reshape(-1); + logprobs_new = torch.log_softmax(flat_logits, 1); + + probs_new = logprobs_new.exp(); + entropy = - (probs_new * logprobs_new).sum(1).mean(); + + newlogprob_flat = logprobs_new.gather(1, flat_actions.unsqueeze(1)).squeeze(1); + newlogprob = newlogprob_flat.reshape(segments, horizon); + logratio = newlogprob - old_logprobs; + ratio_new = logratio.exp(); + + adv_normalized = prio.unsqueeze(1) * (advantages - adv_mean) / (adv_std + 1e-8); + pg_loss1 = -adv_normalized * ratio_new; + pg_loss2 = -adv_normalized * torch.clamp(ratio_new, 1.0 - clip_coef, 1.0 + clip_coef); + pg_loss = torch.max(pg_loss1, pg_loss2).mean(); + + newvalue = newvalue.view(returns.shape) + v_clipped = values + torch.clamp(newvalue - values, -vf_clip_coef, vf_clip_coef); + v_loss_unclipped = (newvalue - returns).pow(2); + v_loss_clipped = (v_clipped - returns).pow(2); + v_loss = 0.5 * torch.max(v_loss_unclipped, v_loss_clipped).mean(); + + # Entrop is a little off (1e-6) + loss = pg_loss + vf_coef*v_loss - ent_coef*entropy + return loss + +def test_fused_ppo_loss(): + logits = torch.randn(BT, T, A, requires_grad=True) + values_pred = torch.randn(BT, T, requires_grad=True).contiguous() + actions = torch.randint(0, A, (BT, T)) + old_logprobs = torch.randn(BT, T) + advantages = torch.randn(BT, T) + prio = torch.rand(BT) + values = torch.randn(BT, T) + returns = torch.randn(BT, T) + + adv_mean = advantages.mean() + adv_std = advantages.std() + + # TODO: These should be tensors, but have to adjust the test kernel too. + # This makes it much slower... but needed for graphing? More perf checks required. + clip_coef = 0.1 + vf_clip_coef = 0.1 + vf_coef = 0.1 + ent_coef = 0.1 + + args = (fused_ppo_loss, _C.fused_ppo_loss, logits, values_pred, actions, + old_logprobs, advantages, prio, values, returns, advantages.mean(), advantages.std(), + clip_coef, vf_clip_coef, vf_coef, ent_coef) + print('fused_ppo_loss') + test_kernel(*args) + +def rmsnorm(x, weight, eps): + shape = (x.shape[-1],) + return torch.nn.functional.rms_norm(x, shape, weight, eps) + +def rmsnorm_loss(outputs): + return torch.sum(outputs[0]) + +def test_rmsnorm(): + x = torch.randn(BT, T, H, requires_grad=True) + weight = torch.randn(H, requires_grad=True) + eps = 1e-5 + + print('rmsnorm correctness') + test_kernel(rmsnorm, _C.rmsnorm, x, weight, eps) + +def sample_logits_py(logits): + """Reference implementation: nan_to_num + log_softmax + multinomial + gather.""" + # nan_to_num + clean_logits = torch.nan_to_num(logits) + # log_softmax + log_probs = torch.log_softmax(clean_logits, 1) + # multinomial sampling + probs = log_probs.exp() + actions = torch.multinomial(probs, 1).squeeze(1) + # gather logprobs + sampled_logprobs = log_probs.gather(1, actions.unsqueeze(1)).squeeze(1) + return [actions, sampled_logprobs] + +def test_sample_logits(): + """Test sample_logits kernel. + + Verifies that: + 1. Actions are valid indices + 2. Logprobs are correct for the sampled actions (match log_softmax gather) + 3. Value is correctly copied (handles strided input) + """ + logits = torch.randn(BR, A).cuda() + value = torch.randn(BR, 1).cuda() # (B, 1) like fused decoder output + seed = 42 + offset = torch.zeros(1, dtype=torch.int64, device='cuda') # Tensor for CUDA graph support + + # Pre-allocate output tensors (kernel writes directly to these) + actions = torch.empty(BR, dtype=torch.float64, device='cuda') + logprobs = torch.empty(BR, dtype=logits.dtype, device='cuda') + value_out = torch.empty(BR, dtype=logits.dtype, device='cuda') + + print('sample_logits') + + # Run kernel (writes to actions, logprobs, value_out in-place) + _C.sample_logits(logits, value, actions, logprobs, value_out, seed, offset) + + # Verify actions are valid indices (float64 but should be integer values) + valid_actions = actions.min() >= 0 and actions.max() < A + action_color = 'green' if valid_actions else 'red' + rich.print(f'\tActions valid: [{action_color}]{valid_actions}[/{action_color}]') + assert valid_actions, "Actions contain invalid values" + + # Verify logprobs match log_softmax gather + log_probs = torch.log_softmax(torch.nan_to_num(logits), 1) + # Convert float64 actions to int64 for indexing + actions_int = actions.long() + expected_logprobs = log_probs.gather(1, actions_int.unsqueeze(1)).squeeze(1) + logprob_max_diff = (expected_logprobs - logprobs.float()).abs().max() + logprob_match = torch.allclose(expected_logprobs, logprobs.float(), rtol=1e-3, atol=1e-4) + match_color = 'green' if logprob_match else 'red' + rich.print(f'\tLogprobs = log_softmax[action]: [{match_color}]{logprob_match} (max diff: {logprob_max_diff:.2e})[/{match_color}]') + + # Verify value copy + expected_value = value.flatten() + value_match = torch.allclose(expected_value, value_out, rtol=1e-5, atol=1e-6) + value_color = 'green' if value_match else 'red' + rich.print(f'\tValue copy: [{value_color}]{value_match}[/{value_color}]') + + # Benchmark + py_sps = time_sps(sample_logits_py, logits) + # Wrapper for benchmarking with in-place signature + def cpp_sample(logits): + _C.sample_logits(logits, value, actions, logprobs, value_out, seed, offset) + # Offset increment is now fused into kernel + return [actions, logprobs] + cpp_sps = time_sps(cpp_sample, logits) + print(f'\tForward sps: {py_sps} (naive) {cpp_sps} (C++)') + +if __name__ == '__main__': + #test_mingru_gate() + #test_log_coeffs_and_values() + #test_logcumsumexp() + #test_fused_scan() + #test_fused_ppo_loss() + test_sample_logits() + #test_rmsnorm() diff --git a/tests/pool/envpool_results.npy b/tests/pool/envpool_results.npy deleted file mode 100644 index 05f7d2e775..0000000000 Binary files a/tests/pool/envpool_results.npy and /dev/null differ diff --git a/tests/pool/plot_packing.py b/tests/pool/plot_packing.py deleted file mode 100644 index b7c1ca5468..0000000000 --- a/tests/pool/plot_packing.py +++ /dev/null @@ -1,39 +0,0 @@ -import plotly.graph_objects as go -import numpy as np - -# Parameters -n_bars = 24 -mu = 0.002 -std = 0.002 - -background = '#061a1a' -forground = '#f1f1f1' - -# Sampling from the normal distribution -bar_heights = mu + np.clip(np.random.normal(mu, std, n_bars), 0, np.inf) - -# Creating the bar chart -fig = go.Figure(go.Bar( - x=[i for i in range(n_bars)], - y=bar_heights, - marker_line_width=0, - marker_color=forground, -)) - -# Updating the layout -fig.update_layout({ - 'plot_bgcolor': background, - 'paper_bgcolor': background, - 'showlegend': False, - 'xaxis': {'visible': False}, - 'yaxis': {'visible': False, 'range': [0, max(bar_heights)]}, - 'margin': {'l': 0, 'r': 0, 't': 0, 'b': 0}, - 'height': 400, - 'width': 800, - 'bargap': 0.0, - 'bargroupgap': 0.0, -}) - - -fig.show() -fig.write_image('../docker/env_variance.png', scale=3) diff --git a/tests/pool/test_basic_multprocessing.py b/tests/pool/test_basic_multprocessing.py deleted file mode 100644 index 3d6e95747d..0000000000 --- a/tests/pool/test_basic_multprocessing.py +++ /dev/null @@ -1,94 +0,0 @@ -from pdb import set_trace as T -import numpy as np -import time - -import selectors -from multiprocessing import Process, Pipe - -def worker_process(envs_per_worker, delay_mean, delay_std, send_pipe, recv_pipe): - while True: - request = recv_pipe.recv() - for _ in range(envs_per_worker): - start = time.process_time() - idx = 0 - target_time = delay_mean + delay_std*np.random.randn() - while time.process_time() - start < target_time: - idx += 1 - - send_pipe.send('end') - -def test_speed(envs_per_worker=1, delay_mean=0.01, delay_std=0.001, num_workers=4, batch_size=4, sync=True, timeout=10): - main_send_pipes, work_recv_pipes = zip(*[Pipe() for _ in range(num_workers)]) - work_send_pipes, main_recv_pipes = zip(*[Pipe() for _ in range(num_workers)]) - - processes = [Process( - target=worker_process, - args=(envs_per_worker, delay_mean, delay_std, work_send_pipes[i], work_recv_pipes[i])) - for i in range(num_workers)] - - for p in processes: - p.start() - - send_idxs = {i for i in range(num_workers)} - - # Register all receive pipes with the selector - sel = selectors.DefaultSelector() - for pipe in main_recv_pipes: - sel.register(pipe, selectors.EVENT_READ) - - steps_collected = 0 - start = time.time() - while time.time() - start < timeout: - for idx in send_idxs: - main_send_pipes[idx].send('start') - - send_idxs = set() - - if sync: - for idx, pipe in enumerate(main_recv_pipes): - assert pipe.recv() == 'end' - send_idxs.add(idx) - - steps_collected += num_workers*envs_per_worker - else: - for key, _ in sel.select(timeout=None): - pipe = key.fileobj - idx = main_recv_pipes.index(pipe) - - if pipe.poll(): - assert pipe.recv() == 'end' - send_idxs.add(idx) - - if len(send_idxs) == batch_size: - break - - steps_collected += batch_size*envs_per_worker - - end = time.time() - - for p in processes: - p.terminate() - - sps = steps_collected / (end - start) - print( - f'SPS: {sps:.2f}', - f'envs_per_worker: {envs_per_worker}', - f'delay_mean: {delay_mean}', - f'delay_std: {delay_std}', - f'num_workers: {num_workers}', - f'batch_size: {batch_size}', - f'sync: {sync}', - ) - - -if __name__ == '__main__': - #timeout = 1 - #test_speed(timeout=1) - test_speed(delay_mean=0, delay_std=0, num_workers=1, batch_size=1, sync=False) - test_speed(delay_mean=0, delay_std=0, num_workers=1, batch_size=1, sync=True) - test_speed(delay_mean=0, delay_std=0, num_workers=6, batch_size=6, sync=False) - test_speed(delay_mean=0, delay_std=0, num_workers=6, batch_size=6, sync=True) - test_speed(delay_mean=0, delay_std=0, num_workers=24, batch_size=6, sync=False) - test_speed(delay_mean=0, delay_std=0, num_workers=24, batch_size=24, sync=False) - test_speed(delay_mean=0, delay_std=0, num_workers=24, batch_size=6, sync=True) - diff --git a/tests/pool/test_envpool.py b/tests/pool/test_envpool.py deleted file mode 100644 index 28b4da568b..0000000000 --- a/tests/pool/test_envpool.py +++ /dev/null @@ -1,264 +0,0 @@ -from pdb import set_trace as T -import numpy as np -import time - -import gymnasium - -import pufferlib -from pufferlib.vectorization import Serial, Multiprocessing, Ray - - -# This is about 1 second on a good CPU core. It is quite difficult to -# find good sources of a 1 second delay without using a timer that can swap -# on sleep -WORK_ITERATIONS = 150_000_000 - - -class PerformanceEnv: - def __init__(self, delay_mean, delay_std): - np.random.seed(time.time_ns() % 2**32) - - self.observation_space = gymnasium.spaces.Box( - low=-2**20, high=2**20, - shape=(1,), dtype=np.float32 - ) - self.action_space = gymnasium.spaces.Discrete(2) - self.observation = self.observation_space.sample() - - self.delay_mean = delay_mean - self.delay_std = delay_std - - - def reset(self, seed=None): - return self.observation, {} - - def step(self, action): - start = time.process_time() - idx = 0 - target_time = self.delay_mean + self.delay_std*np.random.randn() - while time.process_time() - start < target_time: - idx += 1 - - return self.observation, 0, False, False, {} - - def close(self): - pass - - -def test_performance(vectorization, workers, envs_per_worker, - delay_mean, delay_std, batch_size=None, timeout=1): - def make_env(): - return pufferlib.emulation.GymnasiumPufferEnv( - env_creator=PerformanceEnv, env_args=(delay_mean, delay_std)) - - if batch_size is None: - batch_size = workers * envs_per_worker - - actions = np.array([make_env().action_space.sample() for _ in range(batch_size)]) - - if vectorization in (Serial, Multiprocessing, 'SyncMultiprocessing', 'SyncRay', Ray): - synchronous = False - if vectorization == 'SyncMultiprocessing': - vectorization = Multiprocessing - synchronous = True - if vectorization == 'SyncRay': - vectorization = Ray - synchronous = True - - envs = vectorization( - make_env, - num_workers=workers, - envs_per_worker=envs_per_worker, - batch_size=batch_size, - synchronous=synchronous, - ) - else: - envs = vectorization([make_env for _ in range(workers)]) - - envs.reset() - num_steps = 0 - start = time.time() - while time.time() - start < timeout: - obs = envs.step(actions)[0] - num_steps += obs.shape[0] - - end = time.time() - envs.close() - - return num_steps, end - start - - -def sweep_performance_tests(): - backends = ( - gymnasium.vector.SyncVectorEnv, Serial, - gymnasium.vector.AsyncVectorEnv, 'SyncMultiprocessing', - Multiprocessing, - 'SyncRay', Ray, - ) - results = {} - delay_means = (1e-2, 1e-2, 1e-3, 1e-3, 1e-4, 1e-4) - delay_stds = (1e-3, 1e-2, 1e-4, 1e-3, 1e-5, 1e-4) - for mean, std in zip(delay_means, delay_stds): - results[(mean, std)] = {} - print('Environment delay: ', mean, std) - for workers in (1, 6, 24, 96, 192): - resul = {} - results[(mean, std)][workers] = resul - print('\t', workers) - for vec in backends: - res = {} - if type(vec) != str: - name = vec.__name__ - else: - name = vec - - resul[name] = res - print(2*'\t', name) - - for envs_per_worker in (1, 2, 4): - batch_sizes=[workers * envs_per_worker] - if vec in (Multiprocessing, Ray) and workers != 1: - batch_sizes.append(workers * envs_per_worker // 2) - batch_sizes.append(workers * envs_per_worker // 3) - - for batch in batch_sizes: - steps, duration = test_performance( - vec, workers, envs_per_worker, mean, std, batch) - - res[(envs_per_worker, batch)] = (steps, duration) - - print('SPS, envs/worker, batch size: ', - steps / duration, envs_per_worker, batch) - - #np.save('envpool_results.npy', results, allow_pickle=True) - -def plot_performance_tests(): - data = np.load('envpool_results.npy', allow_pickle=True).item() - n_envs = len(data) - - inner_data = list(data.items())[0][1] - n_cores, cores = len(inner_data), list(inner_data.keys()) - - inner_inner_data = list(inner_data.items())[0][1] - n_backends, backends = len(inner_inner_data), list(inner_inner_data.keys()) - - from matplotlib import pyplot as plt - import matplotlib.colors as mcolors - - # Create figure and axes - fig, ax = plt.subplots(figsize=(15, 5)) # Adjust size as needed - #plt.yscale('log') - - # Bar settings - bar_width = 0.15 - group_width = n_backends * bar_width * n_cores - index = np.arange(n_envs) * (group_width + bar_width * 2) # Adding more space between environments - - # Grayscale colors for backends - grayscale_colors = np.linspace(0.4, 1, n_backends) - backend_colors = [str(g) for g in grayscale_colors] - - # Hue colors for cores - hue_colors = 255*plt.cm.hsv(np.linspace(0, 0.6, n_cores))[:, :3] - bars_data = [] - - grayscale_colors = np.linspace(0.4, 1, n_cores) - hue_colors = 255*plt.cm.hsv(np.linspace(0, 0.6, n_backends))[:, :3] - - import plotly.graph_objects as go - import dash - import dash_core_components as dcc - import dash_html_components as html - - # Plotting the bars - pos = 0 - - x_labels = [f'{mean}±{std}' for mean, std in data.keys()] - tick_vals = np.linspace(0, bar_width*n_envs*n_cores*(n_backends+1), n_envs) - - # Set up layout configuration - layout = go.Layout( - title=dict( - text='Performance of Vectorization Backends on Various Workloads (24 core machine)', - y=0.9 - ), - width=2000,# 1000, - height=500, - yaxis=dict(title='Speedup over Expected Serial Performance'), - plot_bgcolor='rgba(6, 26, 26, 1)', # Dark cyan background - paper_bgcolor='rgba(6, 26, 26, 1)', - font=dict(color='rgba(241, 241, 241, 1)'), # Light text - barmode='group', - xaxis = dict( - title='Test Environment Delays (mean/std) and Process Counts', - tickmode='array', - tickvals = tick_vals, - ticktext = x_labels, - ), - legend=dict( - y=1.20, - x=0.9,#0.80 - ), - ) - - fig = go.Figure(data=bars_data, layout=layout) - x = 0 - for env_idx, (mean, std) in enumerate(data): - env = data[(mean, std)] - label = ('mean = %.1e, std = %.1e' % (mean, std)) - for workers_idx, workers in enumerate(env): - runs = env[workers] - for vec_idx, vec in enumerate(runs): - results = runs[vec].values() - best_sps = max(steps / duration for steps, duration in results) - speedup = best_sps * mean - - color = hue_colors[vec_idx] * grayscale_colors[workers_idx] - color = f'rgb{tuple(color[:3])}' # Convert to RGB string - fig.add_trace(go.Bar( - x=[x], - y=[speedup], # Y value - marker_color=color, # Color - text=label, - showlegend=False, - )) - x += bar_width - label = '' - x += bar_width - x += 3*bar_width - - # Create figure with the collected bar data and layout - for idx, vec in enumerate(backends): - if vec == 'Serial': - vec = 'Puffer Serial' - elif vec == 'SyncMultiprocessing': - vec = 'Puffer Multiproc.' - elif vec == 'Multiprocessing': - vec = 'Puffer Pool' - - color = f'rgb{tuple(hue_colors[idx])}' # Convert to RGB string - fig.add_trace(go.Bar( - x=[None], # No x value - y=[None], # No y value - name=vec, # Name for the legend entry - marker_color=color, # Transparent color - showlegend=True, # Show in legend - )) - - for idx, core in enumerate(cores): - color = f'rgb{tuple(3*[grayscale_colors[idx]])}' - fig.add_trace(go.Bar( - x=[None], # No x value - y=[None], # No y value - name=core, # Name for the legend entry - marker_color=color, # Transparent color - showlegend=True, # Show in legend - )) - - # Save the figure to a file - fig.write_image('../docker/envpool_sps.png', scale=3) - - -if __name__ == '__main__': - #sweep_performance_tests() - plot_performance_tests() diff --git a/tests/pool/test_multiprocessing.py b/tests/pool/test_multiprocessing.py deleted file mode 100644 index aefd71b850..0000000000 --- a/tests/pool/test_multiprocessing.py +++ /dev/null @@ -1,42 +0,0 @@ -from pdb import set_trace as T -import numpy as np -import time - -from pufferlib.vectorization import Multiprocessing -from pufferlib.environments import pokemon_red - -def test_envpool(num_envs, envs_per_worker, envs_per_batch, steps=1000, env_pool=True): - pool = Multiprocessing(pokemon_red.env_creator(), num_envs=num_envs, - envs_per_worker=envs_per_worker, envs_per_batch=envs_per_batch, - env_pool=True, - ) - pool.async_reset() - - a = np.array([pool.single_action_space.sample() for _ in range(envs_per_batch)]) - start = time.time() - for s in range(steps): - o, r, d, t, i, mask, env_id = pool.recv() - pool.send(a) - end = time.time() - print('Steps per second: ', envs_per_batch * steps / (end - start)) - pool.close() - - -if __name__ == '__main__': - # 225 sps - #test_envpool(num_envs=1, envs_per_worker=1, envs_per_batch=1, env_pool=False) - - # 600 sps - #test_envpool(num_envs=6, envs_per_worker=1, envs_per_batch=6, env_pool=False) - - # 645 sps - #test_envpool(num_envs=24, envs_per_worker=4, envs_per_batch=24, env_pool=False) - - # 755 sps - # test_envpool(num_envs=24, envs_per_worker=4, envs_per_batch=24) - - # 1050 sps - # test_envpool(num_envs=48, envs_per_worker=4, envs_per_batch=24) - - # 1300 sps - test_envpool(num_envs=48, envs_per_worker=4, envs_per_batch=12) diff --git a/tests/profile_kernels.cu b/tests/profile_kernels.cu new file mode 100644 index 0000000000..880eeab2ee --- /dev/null +++ b/tests/profile_kernels.cu @@ -0,0 +1,746 @@ +#include +#include +#include +#include +#include +#include + +#include "pufferlib.cu" +#include "ini.h" + +const int WARMUP_ITERS = 100; +const int TIMING_ITERS = 1000; + +const int BUF = 2; +const int BR = 4096; // Rollout batch (no T dim) +const int BT = 512; // Train batch (with T dim) +const int T_ = 64; // T_ to avoid collision with PrefixScan::T +const int H_ = 128; +const int A_ = 4; +const int INPUT_SIZE = 96; + +#ifndef ENV_NAME +#error "ENV_NAME must be defined at compile time (e.g. -DENV_NAME=breakout)" +#endif +#define STRINGIFY(x) #x +#define TOSTRING(x) STRINGIFY(x) + +typedef void (*kernel_fn)(void*); + +void print_usage(const char* prog) { + printf("Usage: %s \n", prog); + printf("\nProfiles:\n"); + printf(" kernels - All individual kernel microbenchmarks\n"); + printf(" mingrugate - MinGRU gate kernel only\n"); + printf(" logcoeffsvals - log_coeffs_and_values fwd+bwd\n"); + printf(" fusedscan - Fused scan (checkpointed) kernel only\n"); + printf(" samplelogits - Sample logits kernel only\n"); + printf(" ppoloss - PPO loss fused fwd+bwd kernel\n"); + printf(" im2col - im2col + col2im (nmmo3 conv sizes, B=1024)\n"); + printf(" envspeed - Environment step throughput\n"); + printf(" --buffers N - Number of buffers (default: %d)\n", BUF); + printf(" --threads N - Number of threads (default: 16)\n"); + printf(" --horizon N - Horizon length (default: %d)\n", T_); + printf(" all - Run all available profiles\n"); +} + +inline void print_timing(const char* name, float ms, int N) { + printf(" %-28s %8.1f us %8.2f M elem/s\n", name, ms * 1000, N / ms / 1e3); +} + +inline void warmup_gpu() { + float* dummy; + cudaMalloc(&dummy, 64 * 1024 * 1024); + for (int i = 0; i < 100; i++) cudaMemset(dummy, 0, 64 * 1024 * 1024); + cudaDeviceSynchronize(); + cudaFree(dummy); +} + +inline float rand1() { + return (float)rand() / RAND_MAX * 2.0f - 1.0f; +} + +inline void float_to_device(precision_t* dst, const float* src, int count) { + precision_t* tmp = (precision_t*)malloc(count * sizeof(precision_t)); + for (int i = 0; i < count; ++i) tmp[i] = (precision_t)src[i]; + cudaMemcpy(dst, tmp, count * sizeof(precision_t), cudaMemcpyHostToDevice); + free(tmp); +} + +inline float profile_kernel(kernel_fn fn, void* args) { + for (int i = 0; i < WARMUP_ITERS; ++i) fn(args); + cudaDeviceSynchronize(); + + cudaEvent_t start, stop; + cudaEventCreate(&start); + cudaEventCreate(&stop); + + cudaProfilerStart(); + cudaEventRecord(start); + for (int i = 0; i < TIMING_ITERS; ++i) fn(args); + cudaEventRecord(stop); + cudaEventSynchronize(stop); + cudaProfilerStop(); + + float ms = 0; + cudaEventElapsedTime(&ms, start, stop); + cudaEventDestroy(start); + cudaEventDestroy(stop); + cudaDeviceSynchronize(); + return ms / TIMING_ITERS; +} + +struct MingruGateProfile { + PrecisionTensor state, combined, x_in, out, next_state; + Allocator alloc; + int B, H; +}; + +MingruGateProfile* create_mingrugate(int B, int H) { + auto* p = (MingruGateProfile*)calloc(1, sizeof(MingruGateProfile)); + p->B = B; p->H = H; + p->state = {.shape = {B, H}}; + p->combined = {.shape = {B, 3*H}}; + p->x_in = {.shape = {B, H}}; + p->out = {.shape = {B, H}}; + p->next_state = {.shape = {B, H}}; + p->alloc = {}; + alloc_register(&p->alloc, &p->state); + alloc_register(&p->alloc, &p->combined); + alloc_register(&p->alloc, &p->x_in); + alloc_register(&p->alloc, &p->out); + alloc_register(&p->alloc, &p->next_state); + alloc_create(&p->alloc); + + int N = B * H; + float* buf = (float*)malloc((N + 3*N + N) * sizeof(float)); + for (int i = 0; i < N; ++i) buf[i] = fabsf(rand1()) + 0.1f; + float_to_device(p->state.data, buf, N); + for (int i = 0; i < 3*N; ++i) buf[i] = rand1() * 5.0f; + float_to_device(p->combined.data, buf, 3*N); + for (int i = 0; i < N; ++i) buf[i] = rand1(); + float_to_device(p->x_in.data, buf, N); + free(buf); + return p; +} + +void run_mingrugate(MingruGateProfile* p) { + mingru_gate<<B * p->H), BLOCK_SIZE>>>( + p->out.data, p->next_state.data, p->combined.data, + p->state.data, p->x_in.data, p->H, p->B); +} + +void profile_mingrugate(int B, int H) { + printf("mingru_gate (B=%d, H=%d)\n", B, H); + auto* p = create_mingrugate(B, H); + float ms = profile_kernel((kernel_fn)run_mingrugate, p); + print_timing("forward", ms, B); + printf("\n"); + alloc_free(&p->alloc); + free(p); +} + +__global__ void log_coeffs_and_values_fwd_kernel( + float* log_coeff_out, float* log_value_out, + const float* gate, const float* hidden, int N) { + int idx = blockIdx.x * blockDim.x + threadIdx.x; + if (idx >= N) return; + log_coeffs_and_values_fwd(gate[idx], hidden[idx], + &log_coeff_out[idx], &log_value_out[idx]); +} + +__global__ void log_coeffs_and_values_bwd_kernel( + float* grad_gate_out, float* grad_hidden_out, + const float* grad_log_coeffs, const float* grad_log_values, + const float* gate, const float* hidden, int N) { + int idx = blockIdx.x * blockDim.x + threadIdx.x; + if (idx >= N) return; + log_coeffs_and_values_bwd(grad_log_coeffs[idx], grad_log_values[idx], + gate[idx], hidden[idx], &grad_gate_out[idx], &grad_hidden_out[idx]); +} + +struct LogCoeffsProfile { + FloatTensor gate, hidden, log_coeff, log_value; + FloatTensor grad_log_coeffs, grad_log_values, grad_gate, grad_hidden; + Allocator alloc; + int N; +}; + +LogCoeffsProfile* create_logcoeffs(int N) { + auto* p = (LogCoeffsProfile*)calloc(1, sizeof(LogCoeffsProfile)); + p->N = N; + p->gate = {.shape = {N}}; + p->hidden = {.shape = {N}}; + p->log_coeff = {.shape = {N}}; + p->log_value = {.shape = {N}}; + p->grad_log_coeffs = {.shape = {N}}; + p->grad_log_values = {.shape = {N}}; + p->grad_gate = {.shape = {N}}; + p->grad_hidden = {.shape = {N}}; + p->alloc = {}; + alloc_register(&p->alloc, &p->gate); + alloc_register(&p->alloc, &p->hidden); + alloc_register(&p->alloc, &p->log_coeff); + alloc_register(&p->alloc, &p->log_value); + alloc_register(&p->alloc, &p->grad_log_coeffs); + alloc_register(&p->alloc, &p->grad_log_values); + alloc_register(&p->alloc, &p->grad_gate); + alloc_register(&p->alloc, &p->grad_hidden); + alloc_create(&p->alloc); + + float* buf = (float*)malloc(N * sizeof(float)); + for (int i = 0; i < N; ++i) buf[i] = rand1() * 5.0f; + cudaMemcpy(p->gate.data, buf, N * sizeof(float), cudaMemcpyHostToDevice); + for (int i = 0; i < N; ++i) buf[i] = rand1() * 5.0f; + cudaMemcpy(p->hidden.data, buf, N * sizeof(float), cudaMemcpyHostToDevice); + for (int i = 0; i < N; ++i) buf[i] = rand1(); + cudaMemcpy(p->grad_log_coeffs.data, buf, N * sizeof(float), cudaMemcpyHostToDevice); + for (int i = 0; i < N; ++i) buf[i] = rand1(); + cudaMemcpy(p->grad_log_values.data, buf, N * sizeof(float), cudaMemcpyHostToDevice); + free(buf); + return p; +} + +void run_logcoeffs_fwd(LogCoeffsProfile* p) { + log_coeffs_and_values_fwd_kernel<<N), BLOCK_SIZE>>>( + p->log_coeff.data, p->log_value.data, + p->gate.data, p->hidden.data, p->N); +} + +void run_logcoeffs_bwd(LogCoeffsProfile* p) { + log_coeffs_and_values_bwd_kernel<<N), BLOCK_SIZE>>>( + p->grad_gate.data, p->grad_hidden.data, + p->grad_log_coeffs.data, p->grad_log_values.data, + p->gate.data, p->hidden.data, p->N); +} + +void profile_logcoeffs(int B, int T, int H) { + int N = B * T * H; + printf("log_coeffs_and_values (N=%d, %dx%dx%d)\n", N, B, T, H); + auto* p = create_logcoeffs(N); + float fwd = profile_kernel((kernel_fn)run_logcoeffs_fwd, p); + print_timing("forward", fwd, N); + float bwd = profile_kernel((kernel_fn)run_logcoeffs_bwd, p); + print_timing("backward", bwd, N); + printf("\n"); + alloc_free(&p->alloc); + free(p); +} + +struct FusedScanProfile { + PrefixScan scan; + PrecisionTensor grad_out, grad_next_state; + Allocator alloc; + int B, T, H; +}; + +FusedScanProfile* create_fusedscan(int B, int T, int H) { + auto* p = (FusedScanProfile*)calloc(1, sizeof(FusedScanProfile)); + p->B = B; p->T = T; p->H = H; + + PrefixScan& s = p->scan; + s.B = B; s.T = T; s.H = H; + + // Allocator needs PrecisionTensor/FloatTensor, but PrefixScan uses raw ptrs + // for combined/state/input. Allocate those via tensors then assign. + PrecisionTensor combined_t = {.shape = {B, T, 3*H}}; + PrecisionTensor state_t = {.shape = {B, H}}; + PrecisionTensor input_t = {.shape = {B, T, H}}; + + s.out = {.shape = {B, T, H}}; + s.next_state = {.shape = {B, H}}; + s.a_star = {.shape = {B, T+1, H}}; + s.s_vals = {.shape = {B, T+1, H}}; + s.log_values_buf = {.shape = {B, T+1, H}}; + s.grad_combined = {.shape = {B, T, 3*H}}; + s.grad_state = {.shape = {B, H}}; + s.grad_input = {.shape = {B, T, H}}; + + p->grad_out = {.shape = {B, T, H}}; + p->grad_next_state = {.shape = {B, H}}; + + p->alloc = {}; + alloc_register(&p->alloc, &combined_t); + alloc_register(&p->alloc, &state_t); + alloc_register(&p->alloc, &input_t); + alloc_register(&p->alloc, &s.out); + alloc_register(&p->alloc, &s.next_state); + alloc_register(&p->alloc, &s.a_star); + alloc_register(&p->alloc, &s.s_vals); + alloc_register(&p->alloc, &s.log_values_buf); + alloc_register(&p->alloc, &s.grad_combined); + alloc_register(&p->alloc, &s.grad_state); + alloc_register(&p->alloc, &s.grad_input); + alloc_register(&p->alloc, &p->grad_out); + alloc_register(&p->alloc, &p->grad_next_state); + alloc_create(&p->alloc); + + s.combined_ptr = combined_t.data; + s.state_ptr = state_t.data; + s.input_ptr = input_t.data; + + int N_combined = B * T * 3 * H; + int N_state = B * H; + int N_out = B * T * H; + float* buf = (float*)malloc(N_combined * sizeof(float)); + for (int i = 0; i < N_combined; ++i) buf[i] = rand1() * 5.0f; + float_to_device(s.combined_ptr, buf, N_combined); + for (int i = 0; i < N_state; ++i) buf[i] = fabsf(rand1()) + 0.1f; + float_to_device(s.state_ptr, buf, N_state); + for (int i = 0; i < N_out; ++i) buf[i] = rand1(); + float_to_device(s.input_ptr, buf, N_out); + float_to_device(p->grad_out.data, buf, N_out); + for (int i = 0; i < N_state; ++i) buf[i] = rand1(); + float_to_device(p->grad_next_state.data, buf, N_state); + free(buf); + return p; +} + +void run_fusedscan_fwd(FusedScanProfile* p) { + mingru_scan_forward<<B * p->H), BLOCK_SIZE>>>(p->scan); +} + +void run_fusedscan_bwd(FusedScanProfile* p) { + mingru_scan_backward<<B * p->H), BLOCK_SIZE>>>( + p->scan, p->grad_out.data, p->grad_next_state.data); +} + +void profile_fusedscan(int B, int T, int H) { + printf("fused_scan (N=%d, %dx%dx%d)\n", B*T*H, B, T, H); + auto* p = create_fusedscan(B, T, H); + float fwd = profile_kernel((kernel_fn)run_fusedscan_fwd, p); + print_timing("forward", fwd, B*T); + float bwd = profile_kernel((kernel_fn)run_fusedscan_bwd, p); + print_timing("backward", bwd, B*T); + printf("\n"); + alloc_free(&p->alloc); + free(p); +} + +struct PPOProfile { + PPOKernelArgs ka; + PPOGraphArgs ga; + FloatTensor loss, losses_acc, ppo_partials; + FloatTensor grad_logits_t, grad_values_t, adv_mean_t, adv_var_t; + PrecisionTensor logits_t, actions_t, old_logprobs_t, advantages_t, prio_t, values_t, returns_t; + PrecisionTensor ratio_t, newvalue_t; + IntTensor act_sizes_t; + Allocator alloc; + int N, T, A, ppo_grid; +}; + +PPOProfile* create_ppoloss(int N, int T, int A) { + auto* p = (PPOProfile*)calloc(1, sizeof(PPOProfile)); + p->N = N; p->T = T; p->A = A; + + int NT = N * T; + int fused_cols = A + 1; + int ppo_grid = (NT + PPO_THREADS - 1) / PPO_THREADS; + p->ppo_grid = ppo_grid; + + p->logits_t = {.shape = {N, T, fused_cols}}; + p->actions_t = {.shape = {NT}}; + p->old_logprobs_t = {.shape = {NT}}; + p->advantages_t = {.shape = {NT}}; + p->prio_t = {.shape = {N}}; + p->values_t = {.shape = {NT}}; + p->returns_t = {.shape = {NT}}; + p->ratio_t = {.shape = {NT}}; + p->newvalue_t = {.shape = {NT}}; + p->grad_logits_t = {.shape = {N, T, A}}; + p->grad_values_t = {.shape = {NT}}; + p->adv_mean_t = {.shape = {1}}; + p->adv_var_t = {.shape = {1}}; + p->loss = {.shape = {1}}; + p->losses_acc = {.shape = {LOSS_N + 1}}; + p->ppo_partials = {.shape = {ppo_grid, LOSS_N + 1}}; + p->act_sizes_t = {.shape = {1}}; + + p->alloc = {}; + alloc_register(&p->alloc, &p->logits_t); + alloc_register(&p->alloc, &p->actions_t); + alloc_register(&p->alloc, &p->old_logprobs_t); + alloc_register(&p->alloc, &p->advantages_t); + alloc_register(&p->alloc, &p->prio_t); + alloc_register(&p->alloc, &p->values_t); + alloc_register(&p->alloc, &p->returns_t); + alloc_register(&p->alloc, &p->ratio_t); + alloc_register(&p->alloc, &p->newvalue_t); + alloc_register(&p->alloc, &p->grad_logits_t); + alloc_register(&p->alloc, &p->grad_values_t); + alloc_register(&p->alloc, &p->adv_mean_t); + alloc_register(&p->alloc, &p->adv_var_t); + alloc_register(&p->alloc, &p->loss); + alloc_register(&p->alloc, &p->losses_acc); + alloc_register(&p->alloc, &p->ppo_partials); + alloc_register(&p->alloc, &p->act_sizes_t); + alloc_create(&p->alloc); + + cudaMemcpy(p->act_sizes_t.data, &A, sizeof(int), cudaMemcpyHostToDevice); + + // Fill with random data + float* buf = (float*)malloc(NT * fused_cols * sizeof(float)); + + // Advantages (precision_t) + compute mean/var + float adv_sum = 0, adv_sq = 0; + for (int i = 0; i < NT; ++i) { + float a = rand1(); + buf[i] = a; + adv_sum += a; + adv_sq += a * a; + } + float adv_mean = adv_sum / NT; + float adv_var = adv_sq / NT - adv_mean * adv_mean; + float_to_device(p->advantages_t.data, buf, NT); + cudaMemcpy(p->adv_mean_t.data, &adv_mean, sizeof(float), cudaMemcpyHostToDevice); + cudaMemcpy(p->adv_var_t.data, &adv_var, sizeof(float), cudaMemcpyHostToDevice); + + // Fill logits (fused: A logit cols + 1 value col per row) + for (int i = 0; i < NT * fused_cols; ++i) buf[i] = rand1() * 2.0f; + float_to_device(p->logits_t.data, buf, NT * fused_cols); + // actions + for (int i = 0; i < NT; ++i) buf[i] = (float)(rand() % A); + float_to_device(p->actions_t.data, buf, NT); + // old_logprobs + for (int i = 0; i < NT; ++i) buf[i] = rand1() * 2.0f; + float_to_device(p->old_logprobs_t.data, buf, NT); + // values + returns + for (int i = 0; i < NT; ++i) buf[i] = rand1(); + float_to_device(p->values_t.data, buf, NT); + for (int i = 0; i < NT; ++i) buf[i] = rand1(); + float_to_device(p->returns_t.data, buf, NT); + // prio + for (int i = 0; i < N; ++i) buf[i] = (float)rand() / RAND_MAX; + float_to_device(p->prio_t.data, buf, N); + free(buf); + + // Wire up kernel args + p->ka = { + .grad_logits = p->grad_logits_t.data, + .grad_logstd = nullptr, + .grad_values_pred = p->grad_values_t.data, + .logits = p->logits_t.data, + .logstd = nullptr, + .values_pred = p->logits_t.data + A, // value is last col in fused layout + .adv_mean = p->adv_mean_t.data, + .adv_var = p->adv_var_t.data, + .act_sizes = p->act_sizes_t.data, + .num_atns = 1, + .clip_coef = 0.1f, .vf_clip_coef = 0.1f, .vf_coef = 0.5f, .ent_coef = 0.01f, + .T_seq = T, .A_total = A, .N = N, + .logits_stride_n = T * fused_cols, .logits_stride_t = fused_cols, .logits_stride_a = 1, + .values_stride_n = T * fused_cols, .values_stride_t = fused_cols, + .is_continuous = false, + }; + p->ga = { + .out_ratio = p->ratio_t.data, + .out_newvalue = p->newvalue_t.data, + .actions = p->actions_t.data, + .old_logprobs = p->old_logprobs_t.data, + .advantages = p->advantages_t.data, + .prio = p->prio_t.data, + .values = p->values_t.data, + .returns = p->returns_t.data, + }; + + return p; +} + +void run_ppoloss(PPOProfile* p) { + cudaMemset(p->loss.data, 0, sizeof(float)); + ppo_loss_compute<<ppo_grid, PPO_THREADS>>>( + p->ppo_partials.data, p->ka, p->ga); + ppo_loss_reduce<<<1, LOSS_N + 1>>>( + p->loss.data, p->losses_acc.data, p->ppo_partials.data, p->ppo_grid); +} + +void profile_ppoloss(int N, int T, int A) { + int NT = N * T; + printf("ppo_loss_fwd_bwd (NT=%d, %dx%d, A=%d)\n", NT, N, T, A); + auto* p = create_ppoloss(N, T, A); + float ms = profile_kernel((kernel_fn)run_ppoloss, p); + print_timing("fwd+bwd", ms, NT); + printf("\n"); + alloc_free(&p->alloc); + free(p); +} + +struct SampleLogitsProfile { + PrecisionTensor dec_out, logstd; + IntTensor act_sizes; + PrecisionTensor actions_t, logprobs_t, value_out_t; + curandStatePhilox4_32_10_t* rng_states; + Allocator alloc; + int B, A; +}; + +SampleLogitsProfile* create_samplelogits(int B, int A) { + auto* p = (SampleLogitsProfile*)calloc(1, sizeof(SampleLogitsProfile)); + p->B = B; p->A = A; + + int fused_cols = A + 1; + p->dec_out = {.shape = {B, fused_cols}}; + p->logstd = {.shape = {0}}; // empty for discrete + p->act_sizes = {.shape = {1}}; + p->actions_t = {.shape = {B}}; + p->logprobs_t = {.shape = {B}}; + p->value_out_t = {.shape = {B}}; + + p->alloc = {}; + alloc_register(&p->alloc, &p->dec_out); + alloc_register(&p->alloc, &p->act_sizes); + alloc_register(&p->alloc, &p->actions_t); + alloc_register(&p->alloc, &p->logprobs_t); + alloc_register(&p->alloc, &p->value_out_t); + alloc_create(&p->alloc); + + cudaMemcpy(p->act_sizes.data, &A, sizeof(int), cudaMemcpyHostToDevice); + + cudaMalloc(&p->rng_states, B * sizeof(curandStatePhilox4_32_10_t)); + rng_init<<>>(p->rng_states, 42, B); + cudaDeviceSynchronize(); + + float* buf = (float*)malloc(B * fused_cols * sizeof(float)); + for (int i = 0; i < B * fused_cols; ++i) buf[i] = rand1() * 5.0f; + float_to_device(p->dec_out.data, buf, B * fused_cols); + free(buf); + return p; +} + +void run_samplelogits(SampleLogitsProfile* p) { + sample_logits<<B), BLOCK_SIZE>>>( + p->dec_out, p->logstd, p->act_sizes, + p->actions_t.data, p->logprobs_t.data, p->value_out_t.data, + p->rng_states); +} + +void profile_samplelogits(int B, int A) { + printf("sample_logits (B=%d, A=%d)\n", B, A); + auto* p = create_samplelogits(B, A); + float ms = profile_kernel((kernel_fn)run_samplelogits, p); + print_timing("forward", ms, B); + printf("\n"); + cudaFree(p->rng_states); + alloc_free(&p->alloc); + free(p); +} + +struct Im2ColProfile { + PrecisionTensor input, col, grad_input; + Allocator alloc; + int B, IC, IH, IW, K, S, OH, OW; +}; + +Im2ColProfile* create_im2col(int B, int IC, int IH, int IW, int K, int S, int OH, int OW) { + auto* p = (Im2ColProfile*)calloc(1, sizeof(Im2ColProfile)); + p->B = B; p->IC = IC; p->IH = IH; p->IW = IW; + p->K = K; p->S = S; p->OH = OH; p->OW = OW; + int in_size = B * IC * IH * IW; + int col_size = B * OH * OW * IC * K * K; + p->input = {.shape = {in_size}}; + p->col = {.shape = {col_size}}; + p->grad_input = {.shape = {in_size}}; + p->alloc = {}; + alloc_register(&p->alloc, &p->input); + alloc_register(&p->alloc, &p->col); + alloc_register(&p->alloc, &p->grad_input); + alloc_create(&p->alloc); + float* buf = (float*)malloc(std::max(in_size, col_size) * sizeof(float)); + for (int i = 0; i < in_size; ++i) buf[i] = rand1(); + float_to_device(p->input.data, buf, in_size); + for (int i = 0; i < col_size; ++i) buf[i] = rand1(); + float_to_device(p->col.data, buf, col_size); + free(buf); + return p; +} + +void run_im2col(Im2ColProfile* p) { + int total = p->B * p->OH * p->OW * p->IC * p->K * p->K; + im2col_kernel<<>>( + p->input.data, p->col.data, + p->B, p->IC, p->IH, p->IW, p->K, p->S, p->OH, p->OW); +} + +void run_col2im(Im2ColProfile* p) { + int total = p->B * p->IC * p->IH * p->IW; + col2im_kernel<<>>( + p->col.data, p->grad_input.data, + p->B, p->IC, p->IH, p->IW, p->K, p->S, p->OH, p->OW); +} + +void profile_im2col(int B, int IC, int IH, int IW, int K, int S, int OH, int OW) { + int total = B * OH * OW * IC * K * K; + printf("im2col/col2im (B=%d, IC=%d, %dx%d, K=%d, S=%d -> %dx%d)\n", + B, IC, IH, IW, K, S, OH, OW); + auto* p = create_im2col(B, IC, IH, IW, K, S, OH, OW); + float fwd = profile_kernel((kernel_fn)run_im2col, p); + print_timing("im2col", fwd, total); + float bwd = profile_kernel((kernel_fn)run_col2im, p); + print_timing("col2im", bwd, total); + printf("\n"); + alloc_free(&p->alloc); + free(p); +} + +static void empty_net_callback(void* ctx, int buf, int t) { + (void)ctx; (void)buf; (void)t; +} +static void empty_thread_init(void* ctx, int buf) { + (void)ctx; (void)buf; +} + +typedef struct { + StaticVec* vec; + int num_envs, num_buffers, num_threads, horizon, obs_size, num_atns; +} EnvSpeedArgs; + +static int ini_handler_env(void* user, const char* section, + const char* name, const char* value) { + Dict* env_kwargs = (Dict*)user; + if (strcmp(section, "env") == 0) dict_set(env_kwargs, strdup(name), atof(value)); + return 1; +} + +typedef struct { int total_agents; int num_buffers; } VecDefaults; +static int ini_handler_vec(void* user, const char* section, + const char* name, const char* value) { + VecDefaults* defaults = (VecDefaults*)user; + if (strcmp(section, "vec") == 0) { + if (strcmp(name, "total_agents") == 0) defaults->total_agents = atoi(value); + else if (strcmp(name, "num_buffers") == 0) defaults->num_buffers = atoi(value); + } + return 1; +} + +EnvSpeedArgs* create_envspeed(int total_agents, int num_buffers, int num_threads, int horizon) { + char ini_path[512]; + snprintf(ini_path, sizeof(ini_path), "config/%s.ini", TOSTRING(ENV_NAME)); + + VecDefaults defaults = {0}; + ini_parse(ini_path, ini_handler_vec, &defaults); + if (total_agents == 0) total_agents = defaults.total_agents > 0 ? defaults.total_agents : 8192; + if (num_buffers == 0) num_buffers = defaults.num_buffers > 0 ? defaults.num_buffers : 2; + + Dict* env_kwargs = create_dict(64); + ini_parse(ini_path, ini_handler_env, env_kwargs); + Dict* vec_kwargs = create_dict(8); + dict_set(vec_kwargs, "total_agents", (double)total_agents); + dict_set(vec_kwargs, "num_buffers", (double)num_buffers); + + StaticVec* vec = create_static_vec(total_agents, num_buffers, 1, vec_kwargs, env_kwargs); + if (!vec) { fprintf(stderr, "Failed to create environments\n"); return nullptr; } + for (int i = 0; i < num_buffers; i++) + cudaStreamCreateWithFlags(&vec->streams[i], cudaStreamNonBlocking); + + printf("Created %d envs (%s) for %d total_agents\n", vec->size, TOSTRING(ENV_NAME), total_agents); + create_static_threads(vec, num_threads, horizon, nullptr, empty_net_callback, empty_thread_init); + static_vec_reset(vec); + cudaDeviceSynchronize(); + + EnvSpeedArgs* args = (EnvSpeedArgs*)calloc(1, sizeof(EnvSpeedArgs)); + args->vec = vec; + args->num_envs = vec->size; + args->num_buffers = num_buffers; + args->num_threads = num_threads; + args->horizon = horizon; + args->obs_size = get_obs_size(); + args->num_atns = get_num_atns(); + return args; +} + +void profile_envspeed(int total_agents, int num_buffers, int num_threads, int horizon) { + printf("env_speed_static (total_agents=%d, buffers=%d, threads=%d, horizon=%d)\n", + total_agents, num_buffers, num_threads, horizon); + EnvSpeedArgs* args = create_envspeed(total_agents, num_buffers, num_threads, horizon); + if (!args) { printf(" Failed to create env - skipping\n\n"); return; } + printf(" num_envs=%d, obs_size=%d, num_atns=%d\n", args->num_envs, args->obs_size, args->num_atns); + + // Warmup + auto t0 = std::chrono::steady_clock::now(); + for (int i = 0; i < 10; ++i) { + static_vec_omp_step(args->vec); + cudaDeviceSynchronize(); + float elapsed = std::chrono::duration(std::chrono::steady_clock::now() - t0).count(); + if (elapsed > 3.0f) break; + } + + // Timed + cudaEvent_t start, stop; + cudaEventCreate(&start); + cudaEventCreate(&stop); + t0 = std::chrono::steady_clock::now(); + cudaEventRecord(start); + float completed = 0; + for (int i = 0; i < 1000; ++i) { + static_vec_omp_step(args->vec); + completed += 1; + float elapsed = std::chrono::duration(std::chrono::steady_clock::now() - t0).count(); + if (elapsed > 3.0f) break; + } + cudaDeviceSynchronize(); + cudaEventRecord(stop); + cudaEventSynchronize(stop); + float ms = 0; + cudaEventElapsedTime(&ms, start, stop); + cudaEventDestroy(start); + cudaEventDestroy(stop); + + float rollout_ms = ms / completed; + int total_steps = total_agents * horizon; + printf(" rollout time: %.2f ms (%d steps)\n", rollout_ms, total_steps); + printf(" throughput: %.2f M steps/s\n", total_steps / rollout_ms / 1e3); + free(args); + printf("\n"); +} + +int main(int argc, char** argv) { + if (argc < 2) { print_usage(argv[0]); return 1; } + + const char* profile = argv[1]; + int buffers = BUF, threads = 16, horizon = T_; + int total_agents = BR * buffers; + for (int i = 2; i < argc - 1; i++) { + if (strcmp(argv[i], "--buffers") == 0) buffers = atoi(argv[++i]); + else if (strcmp(argv[i], "--threads") == 0) threads = atoi(argv[++i]); + else if (strcmp(argv[i], "--horizon") == 0) horizon = atoi(argv[++i]); + else if (strcmp(argv[i], "--total-agents") == 0) total_agents = atoi(argv[++i]); + } + + warmup_gpu(); + bool run_all = strcmp(profile, "all") == 0; + + if (strcmp(profile, "kernels") == 0 || strcmp(profile, "mingrugate") == 0 || run_all) + profile_mingrugate(BR, H_); + if (strcmp(profile, "kernels") == 0 || strcmp(profile, "logcoeffsvals") == 0 || run_all) + profile_logcoeffs(BT, T_, H_); + if (strcmp(profile, "kernels") == 0 || strcmp(profile, "fusedscan") == 0 || run_all) + profile_fusedscan(BT, T_, H_); + if (strcmp(profile, "kernels") == 0 || strcmp(profile, "samplelogits") == 0 || run_all) + profile_samplelogits(BR, A_); + if (strcmp(profile, "kernels") == 0 || strcmp(profile, "ppoloss") == 0 || run_all) + profile_ppoloss(BT, T_, A_); + if (strcmp(profile, "kernels") == 0 || strcmp(profile, "im2col") == 0 || run_all) { + profile_im2col(1024, N3_C1_IC, N3_MAP_H, N3_MAP_W, N3_C1_K, N3_C1_S, N3_C1_OH, N3_C1_OW); + profile_im2col(1024, N3_C2_IC, N3_C1_OH, N3_C1_OW, N3_C2_K, N3_C2_S, N3_C2_OH, N3_C2_OW); + } + + if (strcmp(profile, "envspeed") == 0 || run_all) + profile_envspeed(total_agents, buffers, threads, horizon); + + if (!run_all + && strcmp(profile, "kernels") != 0 + && strcmp(profile, "mingrugate") != 0 + && strcmp(profile, "logcoeffsvals") != 0 + && strcmp(profile, "fusedscan") != 0 + && strcmp(profile, "samplelogits") != 0 + && strcmp(profile, "ppoloss") != 0 + && strcmp(profile, "im2col") != 0 + && strcmp(profile, "envspeed") != 0 + ) { + printf("Unknown profile: %s\n\n", profile); + print_usage(argv[0]); + return 1; + } + + return 0; +} diff --git a/tests/test.py b/tests/test.py deleted file mode 100644 index 1890c3c2ef..0000000000 --- a/tests/test.py +++ /dev/null @@ -1,299 +0,0 @@ -from pdb import set_trace as T - -import numpy as np - -import pufferlib -import pufferlib.emulation -import pufferlib.utils -import pufferlib.vector -from pufferlib.environments import test - -# Deprecation warnings from gymnasium -import gymnasium -import warnings -warnings.filterwarnings("ignore") - -class RandomState: - def __init__(self, seed): - self.rng = np.random.RandomState(seed) - - def random(self): - return self.rng.random() - - def probabilistic_round(self, n): - frac, integer = np.modf(n) - if self.random() < frac: - return int(integer) + 1 - else: - return int(integer) - - def sample(self, ary, n): - n_rounded = self.probabilistic_round(n) - return self.rng.choice(ary, n_rounded, replace=False).tolist() - - def choice(self, ary): - return self.sample(ary, 1)[0] - - -# TODO: Fix this. Was in utils.py. Only used for tests -def make_zeros_like(data): - if isinstance(data, dict): - return {k: make_zeros_like(v) for k, v in data.items()} - elif isinstance(data, (list, tuple)): - return [make_zeros_like(v) for v in data] - elif isinstance(data, np.ndarray): - return np.zeros_like(data) - elif isinstance(data, (int, float)): - return 0 - else: - raise ValueError(f'Unsupported type: {type(data)}') - -def compare_arrays(array_1, array_2): - assert isinstance(array_1, np.ndarray) - assert isinstance(array_2, np.ndarray) - assert array_1.shape == array_2.shape - return np.allclose(array_1, array_2) - -def compare_dicts(dict_1, dict_2, idx): - assert isinstance(dict_1, (dict, OrderedDict)) - assert isinstance(dict_2, (dict, OrderedDict)) - - if not all(k in dict_2 for k in dict_1): - raise ValueError("Keys do not match between dictionaries.") - - for k, v in dict_1.items(): - if not compare_space_samples(v, dict_2[k], idx): - return False - - return True - -def compare_lists(list_1, list_2, idx): - assert isinstance(list_1, (list, tuple)) - assert isinstance(list_2, (list, tuple)) - - if len(list_1) != len(list_2): - raise ValueError("Lengths do not match between lists/tuples.") - - for v1, v2 in zip(list_1, list_2): - if not compare_space_samples(v1, v2, idx): - return False - - return True - -def compare_space_samples(sample_1, sample_2, sample_2_batch_idx=None): - '''Compare two samples from the same space - - Optionally, sample_2 may be a batch of samples from the same space - concatenated along the first dimension of the leaves. In this case, - sample_2_batch_idx specifies which sample to compare. - ''' - if isinstance(sample_1, (dict, OrderedDict)): - return compare_dicts(sample_1, sample_2, sample_2_batch_idx) - elif isinstance(sample_1, (list, tuple)): - return compare_lists(sample_1, sample_2, sample_2_batch_idx) - elif isinstance(sample_1, np.ndarray): - assert isinstance(sample_2, np.ndarray) - if sample_2_batch_idx is not None: - sample_2 = sample_2[sample_2_batch_idx] - return compare_arrays(sample_1, sample_2) - elif isinstance(sample_1, (int, float)): - if sample_2_batch_idx is not None: - sample_2 = sample_2[sample_2_batch_idx] - if isinstance(sample_2, np.ndarray): - assert sample_2.size == 1, "Cannot compare scalar to non-scalar." - sample_2 = sample_2[0] - return sample_1 == sample_2 - else: - raise ValueError(f"Unsupported type: {type(sample_1)}") - - - -def test_gymnasium_emulation(env_cls, steps=100): - raw_env = env_cls() - puf_env = pufferlib.emulation.GymnasiumPufferEnv(env_creator=env_cls) - - raw_done = puf_done = True - raw_truncated = puf_truncated = False - - for i in range(steps): - assert puf_done == raw_done - assert puf_truncated == raw_truncated - - if raw_done: - puf_ob, _ = puf_env.reset() - raw_ob, _ = raw_env.reset() - - # Reconstruct original obs format from puffer env and compare to raw - if puf_env.is_obs_emulated: - puf_ob = pufferlib.emulation.nativize( - puf_ob, puf_env.env.observation_space, puf_env.obs_dtype) - - pufferlib.utils.compare_space_samples(raw_ob, puf_ob) - - action = raw_env.action_space.sample() - raw_ob, raw_reward, raw_done, raw_truncated, _ = raw_env.step(action) - - # Convert raw actions to puffer format - if puf_env.is_atn_emulated: - action = pufferlib.emulation.emulate_copy( - action, puf_env.action_space.dtype, puf_env.atn_dtype) - - puf_ob, puf_reward, puf_done, puf_truncated, _ = puf_env.step(action) - assert puf_reward == raw_reward - -def test_pettingzoo_emulation(env_cls, steps=100): - raw_env = env_cls() - puf_env = pufferlib.emulation.PettingZooPufferEnv(env_creator=env_cls) - - for i in range(steps): - raw_done = len(raw_env.agents) == 0 - puf_done = len(puf_env.agents) == 0 - - assert puf_done == raw_done - - if raw_done: - puf_obs, _ = puf_env.reset() - raw_obs, _ = raw_env.reset() - - for agent in puf_env.possible_agents: - if agent not in raw_obs: - assert np.sum(puf_obs[agent] != 0) == 0 - continue - - raw_ob = raw_obs[agent] - puf_ob = puf_obs[agent] - - # Reconstruct original obs format from puffer env and compare to raw - if puf_env.is_obs_emulated: - puf_ob = pufferlib.emulation.nativize( - puf_ob, puf_env.env.single_observation_space, puf_env.obs_dtype) - - assert pufferlib.utils.compare_space_samples(raw_ob, puf_ob) - - raw_actions = {a: raw_env.action_space(a).sample() - for a in raw_env.agents} - puf_actions = raw_actions - - raw_obs, raw_rewards, raw_dones, raw_truncateds, _ = raw_env.step(raw_actions) - - # Convert raw actions to puffer format - dummy_action = raw_actions[list(raw_actions.keys())[0]] - if puf_env.is_atn_emulated: - for agent in puf_env.possible_agents: - if agent not in raw_actions: - puf_actions[agent] = dummy_action - continue - - puf_actions[agent] = pufferlib.emulation.emulate_copy( - raw_actions[agent], puf_env.single_action_space.dtype, puf_env.atn_dtype) - - puf_obs, puf_rewards, puf_dones, puf_truncateds, _ = puf_env.step(puf_actions) - - for agent in raw_rewards: - assert puf_rewards[agent] == raw_rewards[agent] - - for agent in raw_dones: - assert puf_dones[agent] == raw_dones[agent] - -def test_puffer_vectorization(env_cls, puffer_cls, steps=100, num_envs=1, **kwargs): - raw_envs = [puffer_cls(env_creator=env_cls) for _ in range(num_envs)] - vec_envs = pufferlib.vector.make(puffer_cls, - env_kwargs={'env_creator': env_cls}, num_envs=num_envs, **kwargs) - - num_agents = sum(env.num_agents for env in raw_envs) - assert num_agents == vec_envs.num_agents - - raw_obs = [env.reset()[0] for i, env in enumerate(raw_envs)] - vec_obs, _ = vec_envs.reset() - - for _ in range(steps): - # PettingZoo dict observations - if isinstance(raw_obs[0], dict): - raw_obs = [v for d in raw_obs for v in d.values()] - - raw_obs = np.stack(raw_obs, axis=0) - assert raw_obs.shape == vec_obs.shape - assert np.all(raw_obs == vec_obs) - - actions = vec_envs.action_space.sample() - raw_actions = np.split(actions, num_envs) - - # Copy reset behavior of VecEnv - raw_obs, raw_rewards, raw_terminals, raw_truncations = [], [], [], [] - for idx, r_env in enumerate(raw_envs): - if r_env.done: - raw_obs.append(r_env.reset()[0]) - raw_rewards.extend([0] * r_env.num_agents) - raw_terminals.extend([False] * r_env.num_agents) - raw_truncations.extend([False] * r_env.num_agents) - else: - r_ob, r_rew, r_term, r_trunc, _ = r_env.step(raw_actions[idx]) - raw_obs.append(r_ob) - raw_rewards.append(r_rew) - raw_terminals.append(r_term) - raw_truncations.append(r_trunc) - - vec_obs, vec_rewards, vec_terminals, vec_truncations, _ = vec_envs.step(actions) - - rew = raw_rewards - if isinstance(raw_rewards[0], dict): - raw_rewards = [v for d in raw_rewards for v in d.values()] - raw_terminals = [v for d in raw_terminals for v in d.values()] - raw_truncations = [v for d in raw_truncations for v in d.values()] - - raw_rewards = np.asarray(raw_rewards, dtype=np.float32) - raw_terminals = np.asarray(raw_terminals) - raw_truncations = np.asarray(raw_truncations) - - assert np.all(raw_rewards == vec_rewards) - assert np.all(raw_terminals == vec_terminals) - assert np.all(raw_truncations == vec_truncations) - - vec_envs.close() - for raw_env in raw_envs: - raw_env.close() - -def test_emulation(): - for env_cls in test.MOCK_SINGLE_AGENT_ENVIRONMENTS: - test_gymnasium_emulation(env_cls) - - print('Gymnasium emulation tests passed') - - for env_cls in test.MOCK_MULTI_AGENT_ENVIRONMENTS: - test_pettingzoo_emulation(env_cls) - - print('PettingZoo emulation tests passed') - -def test_vectorization(): - for vectorization in [ - pufferlib.vector.Serial, - pufferlib.vector.Multiprocessing, - pufferlib.vector.Ray]: - for env_cls in test.MOCK_SINGLE_AGENT_ENVIRONMENTS: - test_puffer_vectorization( - env_cls, - pufferlib.emulation.GymnasiumPufferEnv, - steps=10, - num_envs=4, - num_workers=4, - backend=vectorization, - ) - - print(f'Gymnasium {vectorization.__name__} vectorization tests passed') - - for env_cls in test.MOCK_MULTI_AGENT_ENVIRONMENTS: - test_puffer_vectorization( - env_cls, - pufferlib.emulation.PettingZooPufferEnv, - steps=10, - num_envs=4, - num_workers=4, - backend=vectorization, - ) - - print(f'PettingZoo {vectorization.__name__} vectorization tests passed') - -if __name__ == '__main__': - test_emulation() - test_vectorization() - exit(0) # For Ray diff --git a/tests/test_atari_reset.py b/tests/test_atari_reset.py deleted file mode 100644 index a82635d248..0000000000 --- a/tests/test_atari_reset.py +++ /dev/null @@ -1,29 +0,0 @@ -from pdb import set_trace as T -from pufferlib.environments import atari - - -def test_atari_reset(): - '''Common way to bug the wrappers can be detected - by checking that the environment properly resets - after hitting 0 lives''' - env = atari.env_creator('BreakoutNoFrameskip-v4')(4) - - obs, info = env.reset() - prev_lives = 5 - - lives = [] - for i in range(1000): - action = env.action_space.sample() - obs, reward, terminal, truncated, info = env.step(action) - - if info['lives'] != prev_lives: - lives.append(i) - prev_lives = info['lives'] - - if terminal or truncated: - obs = env.reset() - - assert len(lives) > 10 - -if __name__ == '__main__': - test_atari_reset() diff --git a/tests/test_carbs.py b/tests/test_carbs.py deleted file mode 100644 index 0feb117000..0000000000 --- a/tests/test_carbs.py +++ /dev/null @@ -1,138 +0,0 @@ -import numpy as np - -from carbs import CARBS -from carbs import CARBSParams -from carbs import LinearSpace -from carbs import LogSpace -from carbs import LogitSpace -from carbs import ObservationInParam -from carbs import ParamDictType -from carbs import Param - -import wandb - - -class SyntheticExperiment: - def __init__(self, n_params, noise=0.1): - self.n_params = n_params - self.noise = noise - - self.param_optima = np.random.randn(n_params) - - def optimize(self, params): - dist = (params-self.param_optima)**2 - reward = 2**(-dist) - noise = 1 + self.noise*np.random.randn() - return noise * np.prod(reward) - -class CARBSSearch: - def __init__(self, experiment): - self.experiment = experiment - self.best_reward = None - self.best_params = None - - param_spaces = [ - Param(name=str(i), - space=LinearSpace(min=-10, max=10, is_integer=False), - search_center=0.0) - for i in range(self.experiment.n_params) - ] - carbs_params = CARBSParams( - better_direction_sign=1, - is_wandb_logging_enabled=False, - resample_frequency=0, - ) - self.carbs = CARBS(carbs_params, param_spaces) - - def sample(self): - suggestion = self.carbs.suggest().suggestion - params = np.array([suggestion[str(i)] for i in range(self.experiment.n_params)]) - reward = self.experiment.optimize(params) - if self.best_reward is None or reward > self.best_reward: - self.best_reward = reward - self.best_params = params - - obs_out = self.carbs.observe( - ObservationInParam( - input=suggestion, - output=reward, - cost=1,#uptime, - ) - ) - return params, reward - -class GeneticAlgorithm: - def __init__(self, experiment, mutation_rate=0.1): - self.experiment = experiment - self.mutation_rate = mutation_rate - self.best_reward = None - self.best_params = np.random.randn(self.experiment.n_params) - - def sample(self): - mutation = self.mutation_rate*np.random.randn(self.experiment.n_params) - params = self.best_params + mutation - reward = self.experiment.optimize(params) - if self.best_reward is None or reward > self.best_reward: - self.best_reward = reward - self.best_params = params - - return params, reward - -class WandbSearch: - def __init__(self, experiment, method='bayes', strategy=None): - self.experiment = experiment - self.strategy = strategy - - self.parameters = {f'param_{i}': - {'distribution': 'normal', 'mu': 0, 'sigma': 1} - for i in range(10)} - - name = strategy.__class__.__name__ if strategy is not None else method - self.sweep_id = wandb.sweep( - sweep=dict( - method=method, - name=f'sweep-{name}', - metric=dict( - goal='maximize', - name='reward', - ), - parameters=self.parameters, - ), - project="sweeping", - ) - self.idx = 0 - - def run(self): - def main(): - self.idx += 1 - wandb.init(name=f'experiment-{self.idx}') - wandb.config.__dict__['_locked'] = {} - if self.strategy is not None: - params, reward = self.strategy.sample() - else: - params = np.array([float(wandb.config[k]) for k in self.parameters]) - reward = self.experiment.optimize(params) - - param_dict = dict(zip(self.parameters.keys(), params)) - wandb.config.update(param_dict, allow_val_change=True) - wandb.log({'reward': reward}) - - wandb.agent(self.sweep_id, main, count=100) - - -if __name__ == '__main__': - experiment = SyntheticExperiment(10) - - strategy = CARBSSearch(experiment) - wandb_search = WandbSearch(experiment, strategy=strategy) - wandb_search.run() - - wandb_search = WandbSearch(experiment, method='random') - wandb_search.run() - - wandb_search = WandbSearch(experiment, method='bayes') - wandb_search.run() - - strategy = GeneticAlgorithm(experiment) - wandb_search = WandbSearch(experiment, strategy=strategy) - wandb_search.run() diff --git a/tests/test_cleanrl_utils.py b/tests/test_cleanrl_utils.py deleted file mode 100644 index 08dc939b59..0000000000 --- a/tests/test_cleanrl_utils.py +++ /dev/null @@ -1,87 +0,0 @@ -from pdb import set_trace as T -import numpy as np - -import torch -from torch.distributions import Categorical - -import gym - -import pufferlib -import pufferlib.models -import pufferlib.cleanrl -import pufferlib.environments.classic_control -import pufferlib.vectorization - - -def test_cleanrl_utils(): - envs = pufferlib.vectorization.Serial( - env_creator=pufferlib.environments.classic_control.env_creator('cartpole'), - num_envs=4, envs_per_worker=2 - ) - - obs, info, _, _ = envs.reset() - - policy = pufferlib.models.Default(envs.driver_env) - policy = pufferlib.models.LSTMWrapper(envs.driver_env, policy) - policy = pufferlib.cleanrl.RecurrentPolicy(policy) - - obs = torch.tensor(obs).unsqueeze(1).float() - actions = policy.get_action_and_value(obs) - -def shape_check(a1, l1, e1, a2, l2, e2): - assert a1.shape == a2.shape - assert l1.shape == l2.shape - assert e1.shape == e2.shape - -def test_sample_logits(): - batch = 8 - - d = gym.spaces.Discrete(5) - d_logits = torch.randn(batch, 5) - d_action = torch.tensor([d.sample() for _ in range(batch)]) - - nvec = [3, 7, 4] - md = gym.spaces.MultiDiscrete(nvec) - md_logits = [torch.rand(batch, n) for n in nvec] - md_action = torch.tensor(np.array([md.sample() for _ in range(batch)])) - - a1, l1, e1 = pufferlib.cleanrl.sample_logits(d_logits) - a2, l2, e2 = correct_sample_logits(d_logits) - shape_check(a1, l1, e1, a2, l2, e2) - - a1, l1, e1 = pufferlib.cleanrl.sample_logits(d_logits, action=d_action) - a2, l2, e2 = correct_sample_logits(d_logits, d_action) - shape_check(a1, l1, e1, a2, l2, e2) - - a1, l1, e1 = pufferlib.cleanrl.sample_logits(md_logits) - a2, l2, e2 = pufferlib.cleanrl.sample_logits(md_logits, action=md_action) - shape_check(a1, l1, e1, a2, l2, e2) - -def correct_sample_logits(logits, action=None): - '''A bad but known correct implementation''' - if isinstance(logits, torch.Tensor): - categorical = Categorical(logits=logits) - if action is None: - action = categorical.sample() - else: - action = action.view(-1) - - logprob = categorical.log_prob(action) - entropy = categorical.entropy() - return action, logprob, entropy - - multi_categorical = [Categorical(logits=l) for l in logits] - - if action is None: - action = torch.stack([c.sample() for c in multi_categorical]) - else: - action = action.view(-1, action.shape[-1]).T - - logprob = torch.stack([c.log_prob(a) for c, a in zip(multi_categorical, action)]).T.sum(1) - entropy = torch.stack([c.entropy() for c in multi_categorical]).T.sum(1) - return action, logprob, entropy - - -if __name__ == '__main__': - test_cleanrl_utils() - #test_sample_logits() diff --git a/tests/test_custom_sweep.py b/tests/test_custom_sweep.py deleted file mode 100644 index a53e157def..0000000000 --- a/tests/test_custom_sweep.py +++ /dev/null @@ -1,128 +0,0 @@ -import copy -import time -import random -import pickle - -import numpy as np -import torch - -import pufferlib.pufferl as pufferl -from pufferlib.sweep import Protein - - -def sweep(env_name, args): - start_time = time.time() - - timestamp = time.strftime("%Y%m%d_%H%M%S") - obs_file = f"sweep_observations_{env_name}_{timestamp}.pkl" - print(f"Sweep observations will be saved to: {obs_file}") - - sweep_manager = Protein(args["sweep"], **args["sweep_extra"]) - points_per_run = args["sweep"]["downsample"] - target_key = f"environment/{args['sweep']['metric']}" - - orig_arg = copy.deepcopy(args) - suggest_history = [] - - for i in range(args["max_runs"]): - print(f"\n--- Starting sweep run {i + 1}/{args['max_runs']} ---") - - # Set a new random seed for each run - seed = time.time_ns() & 0xFFFFFFFF - random.seed(seed) - np.random.seed(seed) - torch.manual_seed(seed) - - # Suggest new hyperparameters and update the arguments - suggest_start_time = time.time() - run_args, info = sweep_manager.suggest(args) - suggest_time = time.time() - suggest_start_time - print(f"sweep_manager.suggest() took {suggest_time:.4f} seconds") - suggest_history.append( - { - "run_args": copy.deepcopy(run_args), - "info": info, - "suggest_time": suggest_time, - "run_index": i, - } - ) - - # Run training with the suggested hyperparameters - all_logs = pufferl.train(env_name, args=run_args, should_stop_early=pufferl.stop_if_loss_nan) - - # Process the logs to get scores and costs for the sweep observation - all_logs = [e for e in all_logs if target_key in e] - if not all_logs: - print( - f"Warning: Target key '{target_key}' not found in logs for this run. Skipping observation." - ) - continue - - scores = pufferl.downsample( - [log[target_key] for log in all_logs], points_per_run - ) - costs = pufferl.downsample([log["uptime"] for log in all_logs], points_per_run) - timesteps = pufferl.downsample( - [log["agent_steps"] for log in all_logs], points_per_run - ) - - # Observe the results of the run - for score, cost, timestep in zip(scores, costs, timesteps): - # Temporarily set total_timesteps to the observed value for accurate logging - run_args["train"]["total_timesteps"] = timestep - sweep_manager.observe(run_args, score, cost) - - # Save observations to a fixed file every 10 runs and at the end - if (i + 1) % 10 == 0 or (i + 1) >= args["max_runs"]: - print(f"\n--- Saving sweep observations to {obs_file} (run {i + 1}) ---") - with open(obs_file, "wb") as f: - pickle.dump( - { - "success": sweep_manager.success_observations, - "failure": sweep_manager.failure_observations, - "suggest_history": suggest_history, - "total_sweep_time": time.time() - start_time, - "args": orig_arg, - }, - f, - ) - - total_sweep_time = time.time() - start_time - print(f"\n--- Total sweep time: {total_sweep_time:.2f} seconds ---") - total_suggest_time = sum(h["suggest_time"] for h in suggest_history) - print(f"--- Total suggest time: {total_suggest_time:.2f} seconds ---") - - -if __name__ == "__main__": - import sys - - env_name = sys.argv.pop(1) if len(sys.argv) > 1 else "puffer_pong" - - # parser = None - parser = pufferl.make_parser() - parser.add_argument('--gp-iter', type=int, default=None) - parser.add_argument('--gp-lr', type=float, default=None) - # parser.add_argument('--use-gpu', action="store_true") - # parser.add_argument('--prune-pareto', action="store_true") - # parser.add_argument('--ucb-beta', type=float, default=None) - args = pufferl.load_config(env_name, parser) - - # Use wandb - args["wandb"] = True - args["no_model_upload"] = True - # args["train"]["optimizer"] = "adam" - - # Custom sweep args - args["sweep_extra"] = {} - if args["gp_iter"] is not None: - args["sweep_extra"]["gp_training_iter"] = args["gp_iter"] - if args["gp_lr"] is not None: - args["sweep_extra"]["gp_learning_rate"] = args["gp_lr"] - # if args["use_gpu"]: - # args["sweep"]["use_gpu"] = True - # if args["prune_pareto"]: - # args["sweep_extra"]["prune_pareto"] = args["prune_pareto"] - # if args["ucb_beta"] is not None: - # args["sweep_extra"]["ucb_beta"] = args["ucb_beta"] - - sweep(env_name, args) diff --git a/tests/test_env_binding.py b/tests/test_env_binding.py deleted file mode 100644 index cefcef857d..0000000000 --- a/tests/test_env_binding.py +++ /dev/null @@ -1,116 +0,0 @@ -from pufferlib.ocean.breakout import breakout - -kwargs = dict( - frameskip=1, - width=576, - height=330, - paddle_width=62, - paddle_height=8, - ball_width=32, - ball_height=32, - brick_width=32, - brick_height=12, - brick_rows=6, - brick_cols=18, - continuous=False, -) - -def test_env_binding(): - reference = breakout.Breakout() - - # Correct usage - c_env = breakout.binding.env_init( - reference.observations, - reference.actions, - reference.rewards, - reference.terminals, - reference.truncations, - 0, - **kwargs - ) - c_envs = breakout.binding.vectorize(c_env) - breakout.binding.vec_reset(c_envs, 0) - breakout.binding.vec_step(c_envs) - breakout.binding.vec_close(c_envs) - - # Correct vec usage - c_envs = breakout.binding.vec_init( - reference.observations, - reference.actions, - reference.rewards, - reference.terminals, - reference.truncations, - reference.num_agents, - 0, - **kwargs - ) - - # Correct vec usage - c_envs = breakout.binding.vec_init( - reference.observations, - reference.actions, - reference.rewards, - reference.terminals, - reference.truncations, - reference.num_agents, - 0, - **kwargs - ) - breakout.binding.vec_reset(c_envs, 0) - breakout.binding.vec_step(c_envs) - breakout.binding.vec_close(c_envs) - - try: - c_env = breakout.binding.env_init() - raise Exception('init missing args. Should have thrown TypeError') - except TypeError: - pass - - try: - c_env = breakout.binding.env_init( - reference.observations, - reference.actions, - reference.rewards, - reference.terminals, - reference.truncations, - reference.num_agents, - 0, - ) - raise Exception('init missing kwarg. Should have thrown TypeError') - except TypeError: - pass - - try: - c_envs = breakout.binding.vec_init() - raise Exception('vec_init missing args. Should have thrown TypeError') - except TypeError: - pass - - try: - c_envs = breakout.binding.vec_init( - reference.observations, - reference.actions, - reference.rewards, - reference.terminals, - reference.truncations, - reference.num_agents, - 0, - ) - raise Exception('vec_init missing kwarg. Should have thrown TypeError') - except TypeError: - pass - - try: - breakout.binding.vec_reset() - raise Exception('vec_reset missing arg. Should have thrown TypeError') - except TypeError: - pass - - try: - breakout.binding.vec_step() - raise Exception('vec_step missing arg. Should have thrown TypeError') - except TypeError: - pass - -if __name__ == '__main__': - test_env_binding() diff --git a/tests/test_extensions.py b/tests/test_extensions.py deleted file mode 100644 index bef142266b..0000000000 --- a/tests/test_extensions.py +++ /dev/null @@ -1,95 +0,0 @@ -from pdb import set_trace as T - -import numpy as np -import timeit -import gym - -from pufferlib.emulation import flatten_structure, flatten_space, flatten, unflatten, concatenate, split -import pufferlib.utils - -def test_pack_unpack(): - for space in nested_spaces: - sample = space.sample() - flat_space = flatten_space(space) - flat_sample = flatten(sample) - pack_sample = concatenate(flat_sample) - - sz = [int(np.prod(subspace.shape)) for subspace in flat_space.values()] - unpack_sample = split(pack_sample, flat_space, sz, batched=False) - unflat_sample = unflatten(unpack_sample, space) - assert pufferlib.utils.compare_space_samples(sample, unflat_sample), "Unflatten failed." - -test_cases = [ - # Nested Dict with Box and Discrete spaces - gym.spaces.Dict({ - "a": gym.spaces.Box(low=0, high=1, shape=(3,)), - "b": gym.spaces.MultiDiscrete([3, 10]), - "c": gym.spaces.Dict({ - "d": gym.spaces.Box(low=-10, high=10, shape=(100,)), - "e": gym.spaces.Discrete(1000) - }) - }), - - # Nested Tuple with Box spaces of different shapes - gym.spaces.Tuple(( - gym.spaces.Box(low=0, high=1, shape=(1,)), - gym.spaces.Box(low=-5, high=5, shape=(10,)), - gym.spaces.Tuple(( - gym.spaces.Box(low=-100, high=100, shape=(1000,)), - gym.spaces.Box(low=-1000, high=1000, shape=(10000,)) - )) - )), - - # Nested Dict with Tuple, Box, and Discrete spaces - gym.spaces.Dict({ - "f": gym.spaces.Tuple((gym.spaces.Discrete(2), gym.spaces.Discrete(3))), - "g": gym.spaces.Box(low=-10, high=10, shape=(50,)), - "h": gym.spaces.Tuple(( - gym.spaces.Box(low=0, high=1, shape=(500,)), - gym.spaces.Dict({ - "i": gym.spaces.Discrete(5000), - "j": gym.spaces.Box(low=-100, high=100, shape=(10000,)) - }) - )) - }), - - # Flat spaces for control - gym.spaces.Box(low=0, high=1, shape=(10,)), - gym.spaces.Discrete(100) -] - - -def test_flatten_unflatten(iterations=10_000): - flatten_times = [] - concatenate_times = [] - split_times = [] - unflatten_times = [] - for space in test_cases: - data = space.sample() - flat = flatten(data) - structure = flatten_structure(data) - flat_space = flatten_space(space) - merged = concatenate(flat) - sz = [int(np.prod(subspace.shape)) for subspace in flat_space.values()] - unmerged = split(merged, flat_space, sz, batched=False) - unflat = unflatten(unmerged, structure) - assert pufferlib.utils.compare_space_samples(data, unflat), "Unflatten failed." - - flatten_times.append(timeit.timeit( - lambda: flatten(data), number=iterations)) - concatenate_times.append(timeit.timeit( - lambda: concatenate(flat), number=iterations)) - split_times.append(timeit.timeit( - lambda: split(merged, flat_space, sz, batched=False), number=iterations)) - unflatten_times.append(timeit.timeit( - lambda: unflatten(unmerged, structure), number=iterations)) - - print(f'{np.mean(flatten_times)/iterations:.8f}: Flatten time') - print(f'{np.mean(concatenate_times)/iterations:.8f}: Concatenate time') - print(f'{np.mean(split_times)/iterations:.8f}: Split time') - print(f'{np.mean(unflatten_times)/iterations:.8f}: Unflatten time') - - -if __name__ == '__main__': - iterations = 10_000 - test_flatten_unflatten(iterations=iterations) diff --git a/tests/test_flatten.py b/tests/test_flatten.py deleted file mode 100644 index c2b7de346a..0000000000 --- a/tests/test_flatten.py +++ /dev/null @@ -1,84 +0,0 @@ -import pufferlib.extensions as c -from pufferlib.emulation import flatten_structure -import timeit - - -samples = [ - [1, {'foo': (1, 2, 3)}], - {'foo': 1, 'bar': {'baz': 2, 'qux': 3}}, - 1, - {'a': [1, 2, {'b': (3, 4)}]}, - {'x': {'y': {'z': [1, 2, 3]}}}, - (1, 2, [3, 4], {'a': 5}), - {'nested': {'more': {'and_more': (1, 2, [3, {'deep': 4}])}}}, - [[1, 2], [3, 4], [5, 6]], - {'a': 1, 'b': 2, 'c': {'d': 3, 'e': [4, 5]}}, - (1, {'a': 2, 'b': {'c': 3, 'd': [4, 5]}}), - {'a': {'b': {'c': {'d': 1}}}}, - [1, 2, 3, [4, 5, {'a': 6}]], - {'single': 1}, - (1,), - {'a': {'b': [1, 2, (3, 4, {'e': 5})]}}, - [[1, 2], 3, {'a': (4, 5)}], - (1, [2, {'a': 3}], {'b': 4}, [5, 6]), - {'mixed': (1, [2, 3], {'a': 4, 'b': (5, [6, 7])})} -] - - -def compare_data(data, unflat): - if isinstance(data, (list, tuple)) and isinstance(unflat, (list, tuple)): - if len(data) != len(unflat): - return False - return all(compare_data(d, f) for d, f in zip(data, unflat)) - elif isinstance(data, dict) and isinstance(unflat, dict): - if len(data) != len(unflat): - return False - return all(compare_data(data[key], unflat[key]) for key in sorted(data)) - else: - return data == unflat - -def test_flatten_unflatten(): - for sample in samples: - structure = flatten_structure(sample) - flat = c.flatten(sample) - unflat = c.unflatten(flat, structure) - if not compare_data(sample, unflat): - print(f"Sample: {sample}") - print(f"Flattened: {flat}") - print(f"Unflattened: {unflat}") - breakpoint() - assert compare_data(sample, unflat) - -def test_flatten_performance(n=100_000): - print("\nFlatten Performance Testing:") - total_calls_per_second = 0 - num_samples = len(samples) - for sample in samples: - wrapped = lambda: c.flatten(sample) - time_per_call = timeit.timeit(wrapped, number=n) / n - calls_per_second_in_k = int(1 / time_per_call / 1000) - print(f"Sample {str(sample)[:10]}... - Average flatten calls per second: {calls_per_second_in_k} K") - total_calls_per_second += calls_per_second_in_k - avg_calls_per_second_in_k = total_calls_per_second // num_samples - print(f"Average flatten calls per second across all samples: {avg_calls_per_second_in_k} K") - -def test_unflatten_performance(n=100_000): - print("\nUnflatten Performance Testing:") - total_calls_per_second = 0 - num_samples = len(samples) - for sample in samples: - flat = c.flatten(sample) - structure = flatten_structure(sample) - wrapped = lambda: c.unflatten(flat, structure) - time_per_call = timeit.timeit(wrapped, number=n) / n - calls_per_second_in_k = int(1 / time_per_call / 1000) - print(f"Sample {str(sample)[:10]}... - Average unflatten calls per second: {calls_per_second_in_k} K") - total_calls_per_second += calls_per_second_in_k - avg_calls_per_second_in_k = total_calls_per_second // num_samples - print(f"Average unflatten calls per second across all samples: {avg_calls_per_second_in_k} K") - - -if __name__ == "__main__": - test_flatten_unflatten() - test_flatten_performance() - test_unflatten_performance() diff --git a/tests/test_muon.py b/tests/test_muon.py new file mode 100644 index 0000000000..fdd37f30f1 --- /dev/null +++ b/tests/test_muon.py @@ -0,0 +1,115 @@ + +import torch +import torch.utils.cpp_extension +import torch.nn as nn +import warnings +from typing import List + +# Suppress heavyball warnings +warnings.filterwarnings(action='ignore', category=UserWarning, module=r'heavyball.*') + +# Try importing torch.optim.Muon (from muon-optim package) +from pufferlib.muon import Muon as TorchMuon + +# Import heavyball's ForeachMuon +import heavyball +from heavyball import ForeachMuon + +# Set compile mode to default +heavyball.utils.compile_mode = "default" + +# Reproducibility +torch.manual_seed(42) +torch.set_num_threads(1) + +# Config +config = { + 'learning_rate': 1e-3, + 'adam_beta1': 0.9, + 'adam_beta2': 0.999, + 'adam_eps': 1e-8, +} + +# Model: Linear -> ReLU -> Linear (no biases) +class Net(nn.Module): + def __init__(self): + super().__init__() + self.l1 = nn.Linear(10, 20, bias=True) + self.act = nn.ReLU() + self.l2 = nn.Linear(20, 1, bias=True) + + def forward(self, x): + return self.l2(self.act(self.l1(x))) + +# Initialize model and data +model1 = Net() +model2 = Net() + +# Copy weights +for p1, p2 in zip(model1.parameters(), model2.parameters()): + p2.data.copy_(p1.data) + +# Dummy data +x = torch.randn(16, 10) +y = torch.randn(16, 1) + +# Optimizers +heavy_optimizer = ForeachMuon( + model1.parameters(), + lr=config['learning_rate'], + betas=(config['adam_beta1'], config['adam_beta2']), + eps=config['adam_eps'], + heavyball_momentum=True, + compile_step=False +) + +torch_optimizer = TorchMuon( + model2.parameters(), + lr=config['learning_rate'], + momentum=config['adam_beta1'], + eps=config['adam_eps'], + weight_decay=0.0, +) + +# Loss function +loss_fn = nn.MSELoss() + +# Training loop +n_epochs = 5 +print(f"{'Epoch':<6} {'AllClose':<10} {'Max Abs Diff':<15}") +print("-" * 35) + +for epoch in range(n_epochs): + # Zero grads + heavy_optimizer.zero_grad() + torch_optimizer.zero_grad() + + # Forward + loss1 = loss_fn(model1(x), y) + loss2 = loss_fn(model2(x), y) + + # Backward + loss1.backward() + loss2.backward() + + # Step + heavy_optimizer.step() + torch_optimizer.step() + + # Compare parameters + all_close = True + max_diff = 0.0 + for p1, p2 in zip(model1.parameters(), model2.parameters()): + diff = (p1.data - p2.data).abs() + max_diff = max(max_diff, diff.max().item()) + if not torch.allclose(p1.data, p2.data, atol=1e-6, rtol=1e-5): + all_close = False + + print(f"{epoch+1:<6} {str(all_close):<10} {max_diff:<15.3e}") + + # Optional: break early if divergence + if not all_close and max_diff > 1e-4: + print("❗ Significant divergence detected.") + break + +print("\n✅ Test complete.") diff --git a/tests/test_namespace.py b/tests/test_namespace.py deleted file mode 100644 index 08095017c2..0000000000 --- a/tests/test_namespace.py +++ /dev/null @@ -1,29 +0,0 @@ -from pufferlib import namespace, dataclass - -def test_namespace_as_function(): - ns = namespace(x=1, y=2, z=3) - - assert ns.x == 1 - assert ns.y == 2 - assert ns.z == 3 - assert list(ns.keys()) == ['x', 'y', 'z'] - assert list(ns.values()) == [1, 2, 3] - assert list(ns.items()) == [('x', 1), ('y', 2), ('z', 3)] - -@dataclass -class TestClass: - a: int - b = 1 - -def test_namespace_as_decorator(): - obj = TestClass(a=4, b=5) - - assert obj.a == 4 - assert obj.b == 5 - assert list(obj.keys()) == ['a', 'b'] - assert list(obj.values()) == [4, 5] - assert list(obj.items()) == [('a', 4), ('b', 5)] - -if __name__ == '__main__': - test_namespace_as_function() - test_namespace_as_decorator() diff --git a/tests/test_nested.py b/tests/test_nested.py deleted file mode 100644 index dcef1cc49e..0000000000 --- a/tests/test_nested.py +++ /dev/null @@ -1,143 +0,0 @@ -from pdb import set_trace as T -import numpy as np - -import pufferlib.spaces -from pufferlib.emulation import flatten - -def dtype_from_space(space): - if isinstance(space, pufferlib.spaces.Tuple): - dtype = [] - num_bytes = 0 - for i, elem in enumerate(space): - dtype_ext, bytes_ext = dtype_from_space(elem) - dtype.append((f'f{i}', dtype_ext)) - #dtype.append((dtype_ext,)) - num_bytes += bytes_ext - elif isinstance(space, pufferlib.spaces.Dict): - dtype = [] - num_bytes = 0 - for k, value in space.items(): - dtype_ext, bytes_ext = dtype_from_space(value) - dtype.append((k, dtype_ext)) - num_bytes += bytes_ext - else: - dtype = (space.dtype, space.shape) - num_bytes = space.dtype.itemsize * np.prod(space.shape) - - return dtype, num_bytes - - -def flat_dtype_from_space(space, name=None): - dtype = [] - _flat_dtype_from_space(space, dtype, name) - return dtype - -def _flat_dtype_from_space(space, dtype, name=None): - if isinstance(space, pufferlib.spaces.Tuple): - for i, elem in enumerate(space): - _flat_dtype_from_space(elem, dtype, name=f'f{i}') - #_flat_dtype_from_space(elem, dtype, name=None) - elif isinstance(space, pufferlib.spaces.Dict): - for k, value in space.items(): - _flat_dtype_from_space(value, dtype, name=k) - else: - if name is not None: - dtype.append((name, space.dtype, space.shape)) - else: - dtype.append((space.dtype, space.shape)) - - return dtype - -def fill_with_sample(arr, sample): - if isinstance(sample, dict): - for k, v in sample.items(): - fill_with_sample(arr[k], v) - elif isinstance(sample, tuple): - for i, v in enumerate(sample): - fill_with_sample(arr[f'f{i}'], v) - else: - arr[()] = sample - - -from gymnasium.spaces import Tuple, Dict, Box - -test_space = Tuple([ - Dict({ - 'a': Box(0, 1, shape=(2,)), - 'b': Box(0, 1, shape=(3,)) - }), - Dict({ - 'c': Box(0, 1, shape=(4,)), - }) -]) - -# Some notes: -# The flat version may be faster. It allows you to fill in a single -# numpy call, but you still have the precomputation step, although -# that one is with no copies. The main limit there is that you need -# unique dict keys everywhere to do it, since they are no longer -# unique when flat, even if they are in the structured version -# In either case, tuples need keys assigned for each element, which is -# the main limitation. - -dtype, num_bytes = dtype_from_space(test_space) -dtype = np.dtype(dtype) -elem = np.zeros(1, dtype=dtype) -#flat_dtype = flat_dtype_from_space(test_space) -sample = test_space.sample() -fill_with_sample(elem, sample) -breakpoint() -#flat_sample = flatten(sample) -rec_array = np.rec.array(flat_sample, dtype=flat_dtype) -rec_array = rec_array.view(dtype) - -''' -test_space = Dict({ - 'a': Box(0, 1, shape=(3,)), - 'b': Dict({ - 'c': Box(0, 1, shape=(4,)), - 'd': Box(0, 1, shape=(3,)) - }), - 'e': Box(0, 1, shape=(3,)) -}) -''' - -breakpoint() -exit() - -def mkdt(d): - ll = [] - sz_bytes = 0 - for k,v in d.items(): - if isinstance(v,np.ndarray): - ll.append((k,v.dtype)) - sz_bytes += v.nbytes - else: - l_ext, sz_ext = mkdt(v) - ll.append((k,l_ext)) - sz_bytes += sz_ext - return ll, sz_bytes - -def mkdt_flat(d): - dtype = [] - return _mkdt_flat(d, dtype) - -def _mkdt_flat(d, dtype): - for k,v in d.items(): - if isinstance(v,np.ndarray): - dtype.append((k,v.dtype)) - else: - _mkdt_flat(v, dtype) - return dtype - - -arr1=np.arange(10).astype(np.float32) -arr2=np.arange(100.,110.).astype(np.uint8) -arr3=np.arange(200,210).astype(np.int32) -d={'a':arr1, 'b':{'b1':arr2, 'b2':{'c':arr3}}} -dt, sz_bytes = mkdt(d) - -#A = np.zeros(sz_bytes, dtype=np.uint8) -flat = flatten(d) -flat_dtype = mkdt_flat(d) -rec_array = np.rec.array(flat, dtype=flat_dtype).view(dt) diff --git a/tests/test_newbind.py b/tests/test_newbind.py deleted file mode 100644 index b07b1792d6..0000000000 --- a/tests/test_newbind.py +++ /dev/null @@ -1,170 +0,0 @@ -import time -import numpy as np - -from pufferlib.ocean.squared import binding as squared_bind - -N = 2048 -TIME = 1.0 - -# Create NumPy arrays with varying dtypes and sizes -obs = np.zeros((N, 11, 11), dtype=np.uint8) -atn = np.zeros((N), dtype=np.int32) -rew = np.zeros((N), dtype=np.float32) -term = np.zeros((N), dtype=np.uint8) -trunc = np.zeros((N), dtype=np.uint8) - -def make_envs(): - env_ptrs = [] - for i in range(N): - ptr = squared_bind.env_init(obs[i].ravel(), atn[i:i+1], rew[i:i+1], term[i:i+1], trunc[i:i+1], size=11) - env_ptrs.append(ptr) - - return env_ptrs - -def time_loop(): - env_ptrs = make_envs() - for ptr in env_ptrs: - squared_bind.env_reset(ptr) - - start = time.time() - atn[:] = np.random.randint(0, 5, (N)) - steps = 0 - while time.time() - start < TIME: - steps += N - for i in range(N): - squared_bind.env_step(env_ptrs[i]) - - print("Loop SPS:", steps / (time.time() - start)) - -def time_vec(): - env_ptrs = make_envs() - vec_ptr = squared_bind.init_vec(obs, atn, rew, term, trunc, N, size=11) - squared_bind.vec_reset(vec_ptr) - start = time.time() - atn[:] = np.random.randint(0, 5, (N)) - - steps = 0 - while time.time() - start < TIME: - squared_bind.vec_step(vec_ptr) - steps += N - - print("Vec SPS:", steps / (time.time() - start)) - - for ptr in env_ptrs: - squared_bind.env_close(ptr) - -def test_loop(): - env_ptrs = make_envs() - for ptr in env_ptrs: - squared_bind.env_reset(ptr) - - while True: - atn[:] = np.random.randint(0, 5, (N)) - for i in range(N): - squared_bind.env_step(env_ptrs[i]) - - squared_bind.env_render(env_ptrs[0]) - - for ptr in env_ptrs: - squared_bind.env_close(ptr) - -def test_vec(): - vec_ptr = squared_bind.init_vec(obs, atn, rew, term, trunc, N, size=11) - squared_bind.vec_reset(vec_ptr) - while True: - atn[:] = np.random.randint(0, 5, (N)) - squared_bind.vec_step(vec_ptr) - squared_bind.vec_render(vec_ptr, 0) - - squared_bind.vec_close(vec_ptr) - -def test_env_binding(): - ptr = squared_bind.env_init(obs[0], atn[0:1], rew[0:1], term[0:1], trunc[0:1], size=11) - squared_bind.env_reset(ptr) - squared_bind.env_step(ptr) - squared_bind.env_close(ptr) - -def test_vectorize_binding(): - ptr = squared_bind.env_init(obs[0], atn[0:1], rew[0:1], term[0:1], trunc[0:1], size=11) - vec_ptr = squared_bind.vectorize(ptr) - squared_bind.vec_reset(vec_ptr) - squared_bind.vec_step(vec_ptr) - squared_bind.vec_close(vec_ptr) - -def test_vec_binding(): - vec_ptr = squared_bind.init_vec(obs, atn, rew, term, trunc, N, size=11) - squared_bind.vec_reset(vec_ptr) - squared_bind.vec_step(vec_ptr) - squared_bind.vec_close(vec_ptr) - -def test_log(): - vec_ptr = squared_bind.init_vec(obs, atn, rew, term, trunc, N, size=11) - squared_bind.vec_reset(vec_ptr) - for i in range(1000): - squared_bind.vec_step(vec_ptr) - - logs = squared_bind.vec_log(vec_ptr) - print(logs) - squared_bind.vec_close(vec_ptr) - -def test_pong(): - from pufferlib.ocean.pong import binding as pong_bind - N = 2048 - - obs = np.zeros((N, 8), dtype=np.float32) - atn = np.zeros((N), dtype=np.int32) - rew = np.zeros((N), dtype=np.float32) - term = np.zeros((N), dtype=np.uint8) - trunc = np.zeros((N), dtype=np.uint8) - - ptr = pong_bind.init_vec(obs, atn, rew, term, trunc, N, - width=500, height=640, paddle_width=20, paddle_height=70, - ball_width=32, ball_height=32, paddle_speed=8, - ball_initial_speed_x=10, ball_initial_speed_y=1, - ball_speed_y_increment=3, ball_max_speed_y=13, - max_score=21, frameskip=1, continuous=False - ) - - pong_bind.vec_reset(ptr) - while True: - pong_bind.vec_step(ptr) - pong_bind.vec_render(ptr, 0) - - pong_bind.vec_close(ptr) - -def test_pong_single(): - from pufferlib.ocean.pong import binding as pong_bind - obs = np.zeros((8), dtype=np.float32) - atn = np.zeros((1,), dtype=np.int32) - rew = np.zeros((1,), dtype=np.float32) - term = np.zeros((1,), dtype=np.uint8) - trunc = np.zeros((1,), dtype=np.uint8) - - ptr = pong_bind.env_init(obs, atn, rew, term, trunc, - width=500, height=640, paddle_width=20, paddle_height=70, - ball_width=32, ball_height=32, paddle_speed=8, - ball_initial_speed_x=10, ball_initial_speed_y=1, - ball_speed_y_increment=3, ball_max_speed_y=13, - max_score=21, frameskip=1, continuous=False - ) - - pong_bind.env_reset(ptr) - while True: - pong_bind.env_step(ptr) - pong_bind.env_render(ptr) - - pong_bind.env_close(ptr) - - -if __name__ == '__main__': - #test_loop() - #test_vec() - #time_loop() - #time_vec() - test_log() - - #test_pong_single() - #test_env_binding() - #test_vectorize_binding() - #test_vec_binding() - diff --git a/tests/test_nmmo3_compile.py b/tests/test_nmmo3_compile.py deleted file mode 100644 index 4f92f90cb1..0000000000 --- a/tests/test_nmmo3_compile.py +++ /dev/null @@ -1,64 +0,0 @@ -from pdb import set_trace as T -import time -import torch -import numpy as np - - -@torch.compile(fullgraph=True, mode='reduce-overhead') -def fast_decode_map(codes, obs, factors, add, div): - codes = codes.view(codes.shape[0], 1, -1) - dec = add + (codes//div) % factors - obs.scatter_(1, dec, 1) - return obs - -#@torch.compile(fullgraph=True, mode='reduce-overhead') -def decode_map(codes): - codes = codes.unsqueeze(1).long() - factors = [4, 4, 16, 5, 3, 5, 5, 6, 7, 4] - n_channels = sum(factors) - obs = torch.zeros(codes.shape[0], n_channels, 11, 15, device='cuda') - - add, div = 0, 1 - # TODO: check item/tier order - for mod in factors: - obs.scatter_(1, add+(codes//div)%mod, 1) - add += mod - div *= mod - - return obs - - -def test_perf(n=100, agents=1024): - factors = np.array([4, 4, 16, 5, 3, 5, 5, 6, 7, 4]) - n_channels = sum(factors) - add = np.array([0, *np.cumsum(factors).tolist()[:-1]])[None, :, None] - div = np.array([1, *np.cumprod(factors).tolist()[:-1]])[None, :, None] - - factors = torch.tensor(factors)[None, :, None].cuda() - add = torch.tensor(add).cuda() - div = torch.tensor(div).cuda() - - codes = torch.randint(0, 4*4*16*5*3*5*5*6*7*4, (agents, 11, 15)).cuda() - obs = torch.zeros(agents, n_channels, 11*15, device='cuda') - obs_view = obs.view(agents, n_channels, 11, 15) - - # Warm up - decode_map(codes) - fast_decode_map(codes, obs, factors, add, div) - torch.cuda.synchronize() - - start = time.time() - for _ in range(n): - fast_decode_map(codes, obs, factors, add, div) - #obs2 = decode_map(codes) - #print(torch.all(obs_view == obs2)) - - - torch.cuda.synchronize() - end = time.time() - sps = n / (end - start) - print(f'SPS: {sps:.2f}') - -if __name__ == '__main__': - test_perf() - diff --git a/tests/test_nmmo3_cuda.cu b/tests/test_nmmo3_cuda.cu new file mode 100644 index 0000000000..0c65d6310f --- /dev/null +++ b/tests/test_nmmo3_cuda.cu @@ -0,0 +1,97 @@ +// Test harness for NMMO3 encoder — thin wrapper around ocean.cu's real implementation. +// Build: nvcc -shared -o ocean_test.so tests/test_nmmo3_cuda.cu -I pufferlib/src -lcublas -lcudnn -lcurand -Xcompiler -fPIC -O2 + +#define PRECISION_FLOAT +#include "../pufferlib/src/models.cu" + +extern "C" { + +static Encoder g_enc; +static NMMO3EncoderWeights* g_w = nullptr; +static NMMO3EncoderActivations* g_a = nullptr; +static Allocator g_param_alloc = {}, g_act_alloc = {}, g_grad_alloc = {}; + +void nmmo3_test_init(int B) { + if (g_w) { + alloc_free(&g_param_alloc); + alloc_free(&g_act_alloc); + alloc_free(&g_grad_alloc); + free(g_w); + free(g_a); + } + g_enc = {}; + g_enc.in_dim = 1707; + g_enc.out_dim = 512; + create_custom_encoder("puffer_nmmo3", &g_enc); + + g_w = (NMMO3EncoderWeights*)g_enc.create_weights(&g_enc); + g_param_alloc = {}; + g_enc.reg_params(g_w, &g_param_alloc); + alloc_create(&g_param_alloc); + + g_a = (NMMO3EncoderActivations*)calloc(1, sizeof(NMMO3EncoderActivations)); + g_act_alloc = {}; + g_grad_alloc = {}; + g_enc.reg_train(g_w, g_a, &g_act_alloc, &g_grad_alloc, B); + alloc_create(&g_act_alloc); + alloc_create(&g_grad_alloc); +} + +// Copy weights from device pointers (PyTorch CUDA tensors) +void nmmo3_test_set_weights(void* c1w, void* c1b, void* c2w, void* c2b, + void* ew, void* pw, void* pb) { + cudaMemcpy(g_w->conv1.w.data, c1w, numel(g_w->conv1.w.shape) * sizeof(float), cudaMemcpyDeviceToDevice); + cudaMemcpy(g_w->conv1.b.data, c1b, numel(g_w->conv1.b.shape) * sizeof(float), cudaMemcpyDeviceToDevice); + cudaMemcpy(g_w->conv2.w.data, c2w, numel(g_w->conv2.w.shape) * sizeof(float), cudaMemcpyDeviceToDevice); + cudaMemcpy(g_w->conv2.b.data, c2b, numel(g_w->conv2.b.shape) * sizeof(float), cudaMemcpyDeviceToDevice); + cudaMemcpy(g_w->embed_w.data, ew, numel(g_w->embed_w.shape) * sizeof(float), cudaMemcpyDeviceToDevice); + cudaMemcpy(g_w->proj_w.data, pw, numel(g_w->proj_w.shape) * sizeof(float), cudaMemcpyDeviceToDevice); + cudaMemcpy(g_w->proj_b.data, pb, numel(g_w->proj_b.shape) * sizeof(float), cudaMemcpyDeviceToDevice); +} + +// Forward: obs and output are device float ptrs +void nmmo3_test_forward(void* output, void* obs, int B) { + PrecisionTensor input = {.data = (precision_t*)obs, .shape = {B, 1707}}; + PrecisionTensor result = g_enc.forward(g_w, g_a, input, 0); + cudaMemcpy(output, result.data, B * 512 * sizeof(float), cudaMemcpyDeviceToDevice); + cudaDeviceSynchronize(); +} + +// Backward: grad is device float ptr (B, 512), modified in-place by relu backward +void nmmo3_test_backward(void* grad, int B) { + PrecisionTensor g = {.data = (precision_t*)grad, .shape = {B, 512}}; + g_enc.backward(g_w, g_a, g, 0); + cudaDeviceSynchronize(); +} + +// Extract weight gradients (device-to-device copy) +void nmmo3_test_get_conv1_wgrad(void* dst) { + cudaMemcpy(dst, g_a->conv1.wgrad.data, numel(g_a->conv1.wgrad.shape) * sizeof(float), cudaMemcpyDeviceToDevice); +} +void nmmo3_test_get_conv1_bgrad(void* dst) { + cudaMemcpy(dst, g_a->conv1.bgrad.data, numel(g_a->conv1.bgrad.shape) * sizeof(float), cudaMemcpyDeviceToDevice); +} +void nmmo3_test_get_conv2_wgrad(void* dst) { + cudaMemcpy(dst, g_a->conv2.wgrad.data, numel(g_a->conv2.wgrad.shape) * sizeof(float), cudaMemcpyDeviceToDevice); +} +void nmmo3_test_get_conv2_bgrad(void* dst) { + cudaMemcpy(dst, g_a->conv2.bgrad.data, numel(g_a->conv2.bgrad.shape) * sizeof(float), cudaMemcpyDeviceToDevice); +} +void nmmo3_test_get_proj_wgrad(void* dst) { + cudaMemcpy(dst, g_a->proj_wgrad.data, numel(g_a->proj_wgrad.shape) * sizeof(float), cudaMemcpyDeviceToDevice); +} +void nmmo3_test_get_proj_bgrad(void* dst) { + cudaMemcpy(dst, g_a->proj_bgrad.data, numel(g_a->proj_bgrad.shape) * sizeof(float), cudaMemcpyDeviceToDevice); +} + +// Embedding weight gradient +void nmmo3_test_get_embed_wgrad(void* dst) { + cudaMemcpy(dst, g_a->embed_wgrad.data, numel(g_a->embed_wgrad.shape) * sizeof(float), cudaMemcpyDeviceToDevice); +} + +// Intermediate activations for relu mask comparison +void nmmo3_test_get_conv1_out(void* dst, int B) { + cudaMemcpy(dst, g_a->conv1.out.data, (int64_t)B * 128 * 3 * 4 * sizeof(float), cudaMemcpyDeviceToDevice); +} + +} // extern "C" diff --git a/tests/test_nmmo3_encoder.py b/tests/test_nmmo3_encoder.py new file mode 100644 index 0000000000..50c7036386 --- /dev/null +++ b/tests/test_nmmo3_encoder.py @@ -0,0 +1,297 @@ +"""Test NMMO3 CUDA encoder forward and backward against PyTorch reference. + +Builds a shared library from test_nmmo3_cuda.cu (thin wrapper around ocean.cu), +then compares numerics for forward output and all weight gradients. +""" + +import subprocess +import ctypes +import os +import sys +import numpy as np +import torch +import torch.nn as nn +import torch.nn.functional as F + +SRC = os.path.join(os.path.dirname(__file__), "test_nmmo3_cuda.cu") +SO = os.path.join(os.path.dirname(__file__), "ocean_test.so") + + +def build(): + cmd = [ + "nvcc", "-shared", "-o", SO, SRC, + "-I", os.path.join(os.path.dirname(__file__), "..", "pufferlib", "src"), + "-lcublas", "-lcudnn", "-lcurand", + "--compiler-options", "-fPIC", "-Xcompiler", "-O2", + ] + print(f"Building: {' '.join(cmd)}") + subprocess.check_call(cmd) + + +# ============================================================================ +# PyTorch reference +# ============================================================================ + +FACTORS = [4, 4, 17, 5, 3, 5, 5, 5, 7, 4] +OFFSETS_NP = [0] + list(np.cumsum(FACTORS)[:-1]) + + +class NMMO3EncoderRef(nn.Module): + def __init__(self): + super().__init__() + offsets = torch.tensor(OFFSETS_NP).view(1, -1, 1, 1) + self.register_buffer("offsets", offsets) + self.conv1 = nn.Conv2d(59, 128, 5, stride=3) + self.conv2 = nn.Conv2d(128, 128, 3, stride=1) + self.embed = nn.Embedding(128, 32) + self.proj = nn.Linear(1817, 512) + + def forward(self, observations): + B = observations.shape[0] + ob_map = observations[:, :1650].view(B, 11, 15, 10) + mh = torch.zeros(B, 59, 11, 15, dtype=torch.float32, device=observations.device) + codes = ob_map.long().permute(0, 3, 1, 2) + self.offsets + mh.scatter_(1, codes, 1) + x = F.relu(self.conv1(mh)) + x = self.conv2(x).flatten(1) + ob_player = observations[:, 1650:-10] + player_embed = self.embed(ob_player.int()).flatten(1) + ob_reward = observations[:, -10:] + cat = torch.cat([x, player_embed, ob_player.float(), ob_reward.float()], dim=1) + return F.relu(self.proj(cat)) + + +# ============================================================================ +# ctypes wrapper +# ============================================================================ + +def load_lib(): + lib = ctypes.CDLL(SO) + VP = ctypes.c_void_p + lib.nmmo3_test_init.argtypes = [ctypes.c_int] + lib.nmmo3_test_set_weights.argtypes = [VP] * 7 + lib.nmmo3_test_forward.argtypes = [VP, VP, ctypes.c_int] + lib.nmmo3_test_backward.argtypes = [VP, ctypes.c_int] + for name in ["conv1_wgrad", "conv1_bgrad", "conv2_wgrad", "conv2_bgrad", + "proj_wgrad", "proj_bgrad", "embed_wgrad"]: + getattr(lib, f"nmmo3_test_get_{name}").argtypes = [VP] + lib.nmmo3_test_get_conv1_out.argtypes = [VP, ctypes.c_int] + return lib + + +def ptr(t): + return ctypes.c_void_p(t.data_ptr()) + + +def extract_weights(model): + return [t.data.contiguous() for t in [ + model.conv1.weight, model.conv1.bias, + model.conv2.weight, model.conv2.bias, + model.embed.weight, model.proj.weight, model.proj.bias, + ]] + + +def generate_valid_obs(B, device): + obs = torch.zeros(B, 1707, dtype=torch.float32, device=device) + for h in range(11): + for w in range(15): + for f in range(10): + idx = (h * 15 + w) * 10 + f + obs[:, idx] = torch.randint(0, FACTORS[f], (B,)).float() + obs[:, 1650:1697] = torch.randint(0, 128, (B, 47)).float() + obs[:, 1697:1707] = torch.randint(0, 256, (B, 10)).float() + return obs + + +def check_match(name, got, ref, atol=1e-4, rtol=1e-4): + max_diff = (got - ref).abs().max().item() + mean_diff = (got - ref).abs().mean().item() + ref_norm = ref.abs().mean().item() + print(f" [{name}] max={max_diff:.6e} mean={mean_diff:.6e} " + f"rel={mean_diff / (ref_norm + 1e-8):.6e}") + ok = torch.allclose(got, ref, atol=atol, rtol=rtol) + if not ok: + diff = (got - ref).abs() + idx = np.unravel_index(diff.argmax().item(), got.shape) + print(f" Worst at {idx}: got={got[idx].item():.6f}, ref={ref[idx].item():.6f}") + assert ok, f"{name} FAILED" + + +# ============================================================================ +# Tests +# ============================================================================ + +def test_forward(lib, B): + """Compare CUDA encoder forward against PyTorch reference.""" + print(f"\n--- Forward B={B} ---") + device = torch.device("cuda") + torch.manual_seed(42) + model = NMMO3EncoderRef().to(device).float().eval() + obs = generate_valid_obs(B, device) + + lib.nmmo3_test_init(B) + lib.nmmo3_test_set_weights(*[ptr(w) for w in extract_weights(model)]) + + cuda_out = torch.zeros(B, 512, device=device) + lib.nmmo3_test_forward(ptr(cuda_out), ptr(obs), B) + torch.cuda.synchronize() + + with torch.no_grad(): + ref_out = model(obs) + + check_match("forward", cuda_out, ref_out) + print(" PASSED") + + +def test_backward(lib, B): + """Compare CUDA encoder backward (all weight grads) against PyTorch autograd. + + Uses CUDA forward relu masks on the PyTorch path so both sides agree on + which activations are zeroed — avoids cuDNN fused-relu edge cases near zero. + """ + print(f"\n--- Backward B={B} ---") + device = torch.device("cuda") + torch.manual_seed(42) + model = NMMO3EncoderRef().to(device).float() + obs = generate_valid_obs(B, device) + + lib.nmmo3_test_init(B) + weights = extract_weights(model) + lib.nmmo3_test_set_weights(*[ptr(w) for w in weights]) + + # ---- CUDA forward ---- + cuda_out = torch.zeros(B, 512, device=device) + lib.nmmo3_test_forward(ptr(cuda_out), ptr(obs), B) + + conv1_out_cuda = torch.zeros(B, 128, 3, 4, device=device) + lib.nmmo3_test_get_conv1_out(ptr(conv1_out_cuda), B) + torch.cuda.synchronize() + + # ---- PyTorch forward with CUDA relu masks ---- + c1w, c1b, c2w, c2b, ew, pw, pb = [w.detach().requires_grad_(True) for w in weights] + + # Multihot (discrete, no grad) + ob_map = obs[:, :1650].view(B, 11, 15, 10) + mh = torch.zeros(B, 59, 11, 15, device=device) + offsets = torch.tensor(OFFSETS_NP).view(1, -1, 1, 1).to(device) + codes = ob_map.long().permute(0, 3, 1, 2) + offsets + mh.scatter_(1, codes, 1) + + # Conv1: raw conv, apply CUDA's relu mask + conv1_raw = F.conv2d(mh, c1w, c1b, stride=3) + conv1_masked = conv1_raw * (conv1_out_cuda > 0).float() + + # Conv2: no relu + conv2_out = F.conv2d(conv1_masked, c2w, c2b, stride=1) + + # Player/reward branches + ob_player = obs[:, 1650:-10] + player_embed = F.embedding(ob_player.int(), ew).flatten(1) + ob_reward = obs[:, -10:] + + # Concat + projection with CUDA's relu mask + cat = torch.cat([conv2_out.flatten(1), player_embed, + ob_player.detach().float(), ob_reward.detach().float()], dim=1) + proj_raw = F.linear(cat, pw, pb) + proj_masked = proj_raw * (cuda_out > 0).float() + + # ---- Backward ---- + grad_output = torch.randn(B, 512, device=device) + proj_masked.backward(grad_output) + + grad_cuda = grad_output.clone() + lib.nmmo3_test_backward(ptr(grad_cuda), B) + torch.cuda.synchronize() + + # ---- Compare all weight grads ---- + tol = dict(atol=1e-2, rtol=1e-2) + + cuda_proj_wgrad = torch.zeros(512, 1817, device=device) + lib.nmmo3_test_get_proj_wgrad(ptr(cuda_proj_wgrad)) + check_match("proj_wgrad", cuda_proj_wgrad, pw.grad, **tol) + + cuda_proj_bgrad = torch.zeros(512, device=device) + lib.nmmo3_test_get_proj_bgrad(ptr(cuda_proj_bgrad)) + check_match("proj_bgrad", cuda_proj_bgrad, pb.grad, **tol) + + cuda_c2_wgrad = torch.zeros(128, 128 * 3 * 3, device=device) + lib.nmmo3_test_get_conv2_wgrad(ptr(cuda_c2_wgrad)) + check_match("conv2_wgrad", cuda_c2_wgrad, c2w.grad.view(128, -1), **tol) + + cuda_c2_bgrad = torch.zeros(128, device=device) + lib.nmmo3_test_get_conv2_bgrad(ptr(cuda_c2_bgrad)) + check_match("conv2_bgrad", cuda_c2_bgrad, c2b.grad, **tol) + + cuda_c1_wgrad = torch.zeros(128, 59 * 5 * 5, device=device) + lib.nmmo3_test_get_conv1_wgrad(ptr(cuda_c1_wgrad)) + check_match("conv1_wgrad", cuda_c1_wgrad, c1w.grad.view(128, -1), **tol) + + cuda_c1_bgrad = torch.zeros(128, device=device) + lib.nmmo3_test_get_conv1_bgrad(ptr(cuda_c1_bgrad)) + check_match("conv1_bgrad", cuda_c1_bgrad, c1b.grad, **tol) + + cuda_embed_wgrad = torch.zeros(128, 32, device=device) + lib.nmmo3_test_get_embed_wgrad(ptr(cuda_embed_wgrad)) + check_match("embed_wgrad", cuda_embed_wgrad, ew.grad, **tol) + + print(" PASSED") + + +# ============================================================================ +# Benchmarks +# ============================================================================ + +def bench_encoder(lib, B, warmup=10, iters=100): + print(f"\n--- Benchmark B={B} ({iters} iters) ---") + device = torch.device("cuda") + torch.manual_seed(42) + model = NMMO3EncoderRef().to(device).float().eval() + obs = generate_valid_obs(B, device) + + lib.nmmo3_test_init(B) + lib.nmmo3_test_set_weights(*[ptr(w) for w in extract_weights(model)]) + + output = torch.zeros(B, 512, device=device) + + def run_cuda(): + lib.nmmo3_test_forward(ptr(output), ptr(obs), B) + + def run_torch(): + with torch.no_grad(): + model(obs) + + for fn in [run_cuda, run_torch]: + for _ in range(warmup): + fn() + torch.cuda.synchronize() + + start = torch.cuda.Event(enable_timing=True) + end = torch.cuda.Event(enable_timing=True) + times = {} + for name, fn in [("cuda", run_cuda), ("torch", run_torch)]: + start.record() + for _ in range(iters): + fn() + end.record() + torch.cuda.synchronize() + times[name] = start.elapsed_time(end) / iters + + for name, ms in times.items(): + print(f" {name:8s} {ms:.3f} ms") + print(f" cuda vs torch: {times['torch'] / times['cuda']:.2f}x") + + +if __name__ == "__main__": + build() + lib = load_lib() + mode = sys.argv[1] if len(sys.argv) > 1 else "all" + + if mode in ("test", "all"): + for B in [1, 8, 64]: + test_forward(lib, B) + test_backward(lib, B) + print("\nAll tests passed!") + + if mode in ("bench", "all"): + for B in [1, 8, 64, 256]: + bench_encoder(lib, B) diff --git a/tests/test_performance.py b/tests/test_performance.py deleted file mode 100644 index ae6e385d66..0000000000 --- a/tests/test_performance.py +++ /dev/null @@ -1,328 +0,0 @@ -from pdb import set_trace as T -import time -from tqdm import tqdm -import importlib -import random -import sys - -import pufferlib -import pufferlib.utils -import pufferlib.exceptions -import pufferlib.emulation -import pufferlib.environments - -import numpy as np - -import pufferlib -from pufferlib.environments import ocean -from pufferlib.vector import Multiprocessing, Serial, Ray, make, autotune - -import time -import psutil -import gymnasium - -DEFAULT_TIMEOUT = 10 - -import time -from functools import wraps - -class TimedEnv: - def __init__(self, env): - self._env = env - self.reset_times = [] - self.step_times = [] - - def __getattr__(self, name): - return getattr(self._env, name) - - def step(self, *args, **kwargs): - start = time.time() - result = self._env.step(*args, **kwargs) - end = time.time() - elapsed = end - start - self.step_times.append(elapsed) - return result - - def reset(self, *args, **kwargs): - start = time.time() - result = self._env.reset(*args, **kwargs) - end = time.time() - elapsed = end - start - self.reset_times.append(elapsed) - return result - -def profile_emulation(env_creator, timeout=DEFAULT_TIMEOUT, seed=42): - reset_times = [] - step_times = [] - agent_step_count = 0 - terminal = False - truncated = False - reset = True - - random.seed(seed) - np.random.seed(seed) - - env = env_creator() - env.env = TimedEnv(env.env) - multiagent = callable(env.action_space) - - start = time.time() - while time.time() - start < timeout: - if reset: - s = time.time() - ob, info = env.reset(seed=seed) - reset_times.append(time.time() - s) - - if multiagent: - action = {agent: env.action_space(agent).sample() for agent in ob} - agent_step_count += len(env.agents) - else: - action = env.action_space.sample() - agent_step_count += 1 - - s = time.time() - ob, reward, terminal, truncated, info = env.step(action) - step_times.append(time.time() - s) - - reset = (multiagent and len(env.agents) == 0) or terminal or truncated - - env.close() - - puf_total_reset = sum(reset_times) - puf_total_step = sum(step_times) - puf_reset_mean = np.mean(reset_times) - puf_step_mean = np.mean(step_times) - puf_step_std = np.std(step_times) - - raw_total_reset = sum(env.env.reset_times) - raw_total_step = sum(env.env.step_times) - raw_reset_mean = np.mean(env.env.reset_times) - raw_step_mean = np.mean(env.env.step_times) - raw_step_std = np.std(env.env.step_times) - - env_sps = agent_step_count / (puf_total_step + puf_total_reset) - env_percent_reset = 100 * puf_total_reset / (puf_total_reset + puf_total_step) - env_percent_step_std = 100 * puf_step_std / puf_step_mean - env_overhead = 100 * (puf_total_step - raw_total_step + puf_total_reset - raw_total_reset) / (puf_total_step + puf_total_reset) - - - print(f' SPS : {env_sps:.1f}') - print(f' Overhead : {env_overhead:.2g}%') - print(f' Reset : {env_percent_reset:.3g}%') - print(f' Step STD : {env_percent_step_std:.3g}%') - -def profile_puffer(env_creator, timeout=DEFAULT_TIMEOUT, **kwargs): - vecenv = make(env_creator, **kwargs) - actions = [vecenv.action_space.sample() for _ in range(1000)] - - agent_steps = 0 - vecenv.reset() - start = time.time() - while time.time() - start < timeout: - vecenv.send(actions[agent_steps%1000]) - o, r, d, t, i, env_id, mask = vecenv.recv() - agent_steps += sum(mask) - - sps = agent_steps / (time.time() - start) - vecenv.close() - - backend = kwargs.get('backend', Serial) - if backend == Multiprocessing and 'batch_size' in kwargs: - print(f' Puffer : {(sps):.1f} - Pool') - else: - print(f' Puffer : {(sps):.1f} - {backend.__name__}') - return sps - -def profile_gymnasium_vec(env_creator, num_envs, timeout=DEFAULT_TIMEOUT): - vecenv = gymnasium.vector.AsyncVectorEnv([env_creator] * num_envs) - actions = [vecenv.action_space.sample() for _ in range(1000)] - - steps = 0 - vecenv.reset() - start = time.time() - while time.time() - start < timeout: - vecenv.step(actions[steps%1000]) - steps += 1 - - sps = steps * vecenv.num_envs / (time.time() - start) - vecenv.close() - - print(f' Gymnasium : {(sps):.1f}') - return sps - -def profile_sb3_vec(env_creator, num_envs, timeout=DEFAULT_TIMEOUT): - with pufferlib.utils.Suppress(): - from stable_baselines3.common.vec_env import SubprocVecEnv - vecenv = SubprocVecEnv([env_creator] * num_envs) - actions = [[vecenv.action_space.sample() for _ in range(num_envs)] - for _ in range(1000)] - - steps = 0 - vecenv.reset() - start = time.time() - while time.time() - start < timeout: - vecenv.step(actions[steps%1000]) - steps += 1 - - sps = steps * vecenv.num_envs / (time.time() - start) - vecenv.close() - - print(f' SB3 : {(sps):.1f}') - return sps - -def profile_all(name, env_creator, num_envs, num_workers=24, - env_batch_size=None, zero_copy=True, timeout=DEFAULT_TIMEOUT): - if env_batch_size is None: - env_batch_size = num_envs - - print(name) - profile_emulation(env_creator, timeout=timeout) - profile_puffer(env_creator, num_envs=env_batch_size, - backend=Multiprocessing, timeout=timeout, - num_workers=min(num_workers, env_batch_size), - ) - if env_batch_size is not None and env_batch_size != num_envs: - profile_puffer(env_creator, num_envs=num_envs, - backend=Multiprocessing, timeout=timeout, num_workers=num_workers, - batch_size=env_batch_size, zero_copy=zero_copy - ) - profile_gymnasium_vec(env_creator, num_envs=env_batch_size, timeout=timeout) - profile_sb3_vec(env_creator, num_envs=env_batch_size, timeout=timeout) - print() - -if __name__ == '__main__': - from pufferlib.environments import nocturne - env_creator = nocturne.env_creator() - profile_emulation(env_creator) - #profile_puffer(env_creator, num_envs=8, backend=Multiprocessing) - exit(0) - - from pufferlib.environments import vizdoom - env_creator = vizdoom.env_creator() - #profile_emulation(env_creator) - profile_puffer(env_creator, num_envs=24, - batch_size=8, backend=Multiprocessing, zero_copy=False) - - from pufferlib.environments import ocean - env_creator = ocean.env_creator('grid') - #profile_emulation(env_creator) - - import cProfile - cProfile.run('profile_emulation(env_creator)', 'stats.profile') - import pstats - from pstats import SortKey - p = pstats.Stats('stats.profile') - p.sort_stats(SortKey.TIME).print_stats(10) - - exit(0) - - from pufferlib.environments import nmmo - print('Neural MMO') - env_creator = nmmo.env_creator() - profile_emulation(env_creator) - #profile_puffer(env_creator, num_envs=8, backend=Multiprocessing) - profile_puffer(env_creator, num_envs=96, - batch_size=48, backend=Multiprocessing, zero_copy=False) - print() - - from pufferlib.environments import nethack - profile_all('NetHack', nethack.env_creator(), num_envs=48) - - from pufferlib.environments import minihack - profile_all('MiniHack', minihack.env_creator(), num_envs=48) - - from pufferlib.environments import pokemon_red - profile_all('Pokemon Red', pokemon_red.env_creator(), - num_envs=144, env_batch_size=48, zero_copy=False) - - from pufferlib.environments import procgen - profile_all('ProcGen', procgen.env_creator('bigfish'), - num_envs=144, env_batch_size=48, num_workers=24, zero_copy=False) - - from pufferlib.environments import classic_control - profile_all('Classic Control', classic_control.env_creator(), - num_envs=1152, env_batch_size=48) - - from pufferlib.environments import ocean - profile_all('Ocean Squared', ocean.env_creator('squared'), - num_envs=1152, env_batch_size=48) - - from pufferlib.environments import atari - profile_all('Atari Breakout', atari.env_creator('BreakoutNoFrameskip-v4'), - num_envs=144, env_batch_size=48, zero_copy=False) - - from pufferlib.environments import crafter - profile_all('Crafter', crafter.env_creator(), - num_envs=24, env_batch_size=8, zero_copy=False) - - from pufferlib.environments import minigrid - profile_all('MiniGrid', minigrid.env_creator(), - num_envs=192, env_batch_size=48, zero_copy=False) - - exit(0) - - ''' - # Small scale version for laptop - from pufferlib.environments import nmmo - print('Neural MMO') - env_creator = nmmo.env_creator() - profile_emulation(env_creator) - profile_puffer(env_creator, num_envs=4, num_workers=4, backend=Multiprocessing) - profile_puffer(env_creator, num_envs=12, num_workers=6, - batch_size=4, backend=Multiprocessing) - print() - - from pufferlib.environments import nethack - profile_all('NetHack', nethack.env_creator(), num_envs=12, num_workers=6) - - from pufferlib.environments import minihack - profile_all('MiniHack', minihack.env_creator(), num_envs=12, num_workers=6) - - from pufferlib.environments import pokemon_red - profile_all('Pokemon Red', pokemon_red.env_creator(), - num_envs=36, num_workers=6, env_batch_size=12, zero_copy=False) - - from pufferlib.environments import classic_control - profile_all('Classic Control', classic_control.env_creator(), - num_envs=36, num_workers=6, env_batch_size=12, zero_copy=False) - - from pufferlib.environments import ocean - profile_all('Ocean Squared', ocean.env_creator('squared'), - num_envs=36, num_workers=6, env_batch_size=12, zero_copy=False) - - from pufferlib.environments import atari - profile_all('Atari Breakout', atari.env_creator('BreakoutNoFrameskip-v4'), - num_envs=36, num_workers=6, env_batch_size=12, zero_copy=False) - - from pufferlib.environments import crafter - profile_all('Crafter', crafter.env_creator(), - num_envs=12, num_workers=6, env_batch_size=4, zero_copy=False) - - from pufferlib.environments import minigrid - profile_all('MiniGrid', minigrid.env_creator(), - num_envs=36, num_workers=6, env_batch_size=12, zero_copy=False) - - exit(0) - ''' - - #from functools import partial - #counts = [1e5, 1e6, 1e7, 1e8] - #delays = [0, 0.1, 0.25, 0.5, 1] - #bandwidth = [1, 1e4, 1e5, 1e6] - - - #synthetic_creators = {} - #for count in counts: - # name = f'test_delay_{count}' - - #env_creators.test = partial( - # ocean.env_creator('performance_empiric'), - # count_n=270_000, bandwidth=150_000 - #) - - #timeout = 60 - #cores = psutil.cpu_count(logical=False) - #for key, creator in env_creators.items(): - # prof = profile_emulation(creator, timeout) - # profile_vec(creator, cores, timeout, prof.puf.sps) - # print() diff --git a/tests/test_pokemon_red.py b/tests/test_pokemon_red.py deleted file mode 100644 index 12ea02f703..0000000000 --- a/tests/test_pokemon_red.py +++ /dev/null @@ -1,9 +0,0 @@ -from pufferlib.environments.pokemon_red import env_creator - -env = env_creator()() -ob, info = env.reset() -for i in range(100): - ob, reward, terminal, truncated, info = env.step(env.action_space.sample()) - print(f'Step: {i}, Info: {info}') - -env.close() diff --git a/tests/test_policy_pool.py b/tests/test_policy_pool.py deleted file mode 100644 index 9f7a3689b0..0000000000 --- a/tests/test_policy_pool.py +++ /dev/null @@ -1,129 +0,0 @@ -import unittest - -import numpy as np -import torch - -import pufferlib.policy_pool as pp - -NUM_AGENTS = 4 -NUM_ENVS = 2 -POOL_AGENTS = NUM_AGENTS * NUM_ENVS # batch size -OBS_DIM = 3 -ACTION_DIM = 5 - -# TODO: add test for recurrent policy forward -BPTT_HORIZON = 16 -LSTM_INPUT_DIM = POOL_AGENTS * BPTT_HORIZON -LSTM_HIDDEN_DIM = 32 - - -class MockPolicy: - def __call__(self, obs): - batch_size = obs.shape[0] - actions = torch.arange(batch_size * ACTION_DIM).view(batch_size, ACTION_DIM) - logprobs = torch.arange(batch_size, dtype=torch.float32) - values = torch.arange(batch_size, dtype=torch.float32) + 10 # add to make the values different - return actions, logprobs, None, values - -class MockPolicyStore: - def __init__(self, num_policies): - self._policies = {f'Policy{i+1}': MockPolicy() for i in range(num_policies)} - self.path = 'mock_policy_store' - - def policy_names(self): - return list(self._policies.keys()) - - def get_policy(self, name): - return self._policies[name] - -class TestPolicyPool(unittest.TestCase): - def setUp(self): - self.mock_nonrecurrent_policy = MockPolicy() - self.mock_nonrecurrent_policy.name = 'BasePolicy1' - self.nonrecurrent_policy_pool = pp.PolicyPool( - policy=self.mock_nonrecurrent_policy, - total_agents=POOL_AGENTS, - atn_shape=(ACTION_DIM,), - device='cpu', - policy_store=MockPolicyStore(3), - kernel = [0, 1, 0, 2], - skip_ranker=True, - ) - - def test_init_with_kernel(self): - test_policy_pool = self.nonrecurrent_policy_pool - kernel = [0, 1, 0, 2] - policy_ids, sample_idxs, kernel = test_policy_pool._init_sample_idx_from_kernel(kernel) - - self.assertTrue(np.array_equal(policy_ids, np.array([0, 1, 2]))) - self.assertEqual(sample_idxs, {0: [0, 2, 4, 6], 1: [1, 5], 2: [3, 7]}) # map policy id to agent list - self.assertEqual(kernel, [0, 1, 0, 2, 0, 1, 0, 2]) # tiled into POOL_AGENTS - - def test_update_policies(self): - policy_pool = self.nonrecurrent_policy_pool - - # Test with no policies in the policy store - # All policies should be the learner policy - policy_store = MockPolicyStore(0) - policy_pool.update_policies(policy_ids=np.array([0, 1, 2]), store=policy_store) - for pol in policy_pool.current_policies.values(): - self.assertEqual(pol['name'], 'learner') - self.assertEqual(pol['policy'], policy_pool.learner_policy) - - # Sample 2 policies when there is only one policy in the policy store - # Both policies should be Policy1 - policy_store = MockPolicyStore(1) - policy_pool.update_policies(policy_ids=np.array([0, 1, 2]), store=policy_store) - for pol in policy_pool.current_policies.values(): - self.assertEqual(pol['name'], 'Policy1') - self.assertEqual(pol['policy'], policy_store.get_policy('Policy1')) - - # Sample 3 policies when there are 10 policies in the policy store - # All sampled policies should be different - policy_store = MockPolicyStore(10) - policy_pool.update_policies(policy_ids=np.array([0, 1, 2, 3]), store=policy_store) - self.assertEqual(len(set(p['name'] for p in policy_pool.current_policies.values())), 3) - - # Use all_selector - policy_store = MockPolicyStore(5) - policy_pool.update_policies(policy_ids=np.array([0, 1, 2, 3, 4, 5]), store=policy_store, - policy_selector=pp.AllPolicySelector(seed=0)) - self.assertEqual(len(set(p['name'] for p in policy_pool.current_policies.values())), 5) - - def test_nonrecurrent_forward(self): - policy_pool = self.nonrecurrent_policy_pool - - obs = torch.arange(POOL_AGENTS * OBS_DIM).view(POOL_AGENTS, OBS_DIM) - atn, lgprob, val, _ = policy_pool.forwards(obs) - - for policy_id in policy_pool.policy_ids: - samp = policy_pool.sample_idxs[policy_id] - policy = policy_pool.learner_policy if policy_id == 0 \ - else policy_pool.current_policies[policy_id]['policy'] - atn1, lgprob1, _, val1 = policy(obs[samp]) - - self.assertTrue(torch.equal(atn[samp], atn1)) - self.assertTrue(torch.equal(lgprob[samp], lgprob1)) - self.assertTrue(torch.equal(val[samp], val1)) - - def test_update_scores(self): - policy_pool = self.nonrecurrent_policy_pool - # With the kernel [0, 1, 0, 2], agents 1 and 3 are learner, and agents 2 and 4 are different - - infos = [{1: {'return': 1}, 2: {'return': 2}, 3: {'return': 3}, 4: {'return': 4}}, - {1: {'return': 10}, 2: {'return': 20}, 4: {'return': 40}}] - pol1_name = policy_pool._get_policy_name(2) - pol2_name = policy_pool._get_policy_name(4) - - policy_infos = policy_pool.update_scores(infos, 'return') - self.assertEqual(policy_infos['learner'], [{'return': 1}, {'return': 3}, {'return': 10}]) - self.assertEqual(policy_infos[pol1_name], [{'return': 2}, {'return': 20}]) - self.assertEqual(policy_infos[pol2_name], [{'return': 4}, {'return': 40}]) - - # policy_pool.scores only keep the last game's results - self.assertEqual(policy_pool.scores['learner'], 10) - self.assertEqual(policy_pool.scores[pol1_name], 20) - self.assertEqual(policy_pool.scores[pol2_name], 40) - -if __name__ == '__main__': - unittest.main() diff --git a/tests/test_puffernet_linearlstm.py b/tests/test_puffernet_linearlstm.py deleted file mode 100644 index 2b89c0c7e6..0000000000 --- a/tests/test_puffernet_linearlstm.py +++ /dev/null @@ -1,102 +0,0 @@ -import torch -import numpy as np - -from pufferlib.ocean import env_creator -from pufferlib.models import Default, LSTMWrapper - -import pyximport -pyximport.install( - setup_args={"include_dirs": [ - np.get_include(), - 'pufferlib/extensions', - ]}, -) - -from pufferlib.extensions import puffernet - - -def make_dummy_data(*shape, seed=42): - np.random.seed(seed) - ary = np.random.rand(*shape).astype(np.float32) - 0.5 - return np.ascontiguousarray(ary) - -def assert_near(a, b, tolerance=1e-4): - assert a.shape == b.shape, f"Shape mismatch: {a.shape} vs {b.shape}" - assert np.all(np.abs(a - b) < tolerance), f"Value mismatch exceeds tolerance {tolerance}" - -def test_tetris_puffernet(model_path='puffer_tetris_weights.bin'): - # Load the environment to get parameters - env = env_creator('puffer_tetris')() - - ### Instantiate the pytorch model - policy = Default(env) - policy = LSTMWrapper(env, policy) - - # Load and assign weights to the pytorch model - with open(model_path, 'rb') as f: - weights_blob = np.fromfile(f, dtype=np.float32) - - current_pos = 0 - layer_weights = [] - for name, param in policy.named_parameters(): - print(name, param.shape) - num_params = param.numel() - weights = weights_blob[current_pos:current_pos+num_params] - param.data = torch.from_numpy(weights).view_as(param) - layer_weights.append(weights) - current_pos += num_params - - ### Prepare dummy input data - batch_size = 1 - obs_shape = env.single_observation_space.shape - atn_dim = env.single_action_space.n - dummy_obs_np = make_dummy_data(batch_size, *obs_shape) - dummy_obs_torch = torch.from_numpy(dummy_obs_np) - - dummy_h_np = make_dummy_data(batch_size, policy.hidden_size, seed=43) - dummy_h_torch = torch.from_numpy(dummy_h_np) - dummy_c_np = make_dummy_data(batch_size, policy.hidden_size, seed=44) - dummy_c_torch = torch.from_numpy(dummy_c_np) - - ### PyTorch Forward Pass - policy.eval() - with torch.no_grad(): - hidden_torch = policy.policy.encode_observations(dummy_obs_torch) - logits_torch, values_torch = policy.forward_eval(dummy_obs_torch, {'lstm_h': dummy_h_torch, 'lstm_c': dummy_c_torch}) - hidden_np = hidden_torch.detach().numpy() - logits_np = logits_torch.detach().numpy() - values_np = values_torch.detach().numpy() - - ### PufferNet Forward Pass and compare - hidden_puffer = np.zeros((batch_size, policy.hidden_size), dtype=np.float32) - puffernet.puf_linear_layer(dummy_obs_np, layer_weights[0], layer_weights[1], hidden_puffer, - batch_size, obs_shape[0], policy.hidden_size) - puffernet.puf_gelu(hidden_puffer, hidden_puffer, hidden_puffer.size) - - assert_near(hidden_np, hidden_puffer) - print("encoder output matches!") - - # LSTM -> decoder, value - lstm_buffer = np.zeros((batch_size * policy.hidden_size * 4), dtype=np.float32) - puffernet.puf_lstm(hidden_puffer, dummy_h_np, dummy_c_np, - layer_weights[6], layer_weights[7], layer_weights[8], layer_weights[9], - lstm_buffer, batch_size, policy.hidden_size, policy.hidden_size) - new_hidden = dummy_h_np - - # actor - logits_puffer = np.zeros((batch_size, atn_dim), dtype=np.float32) - puffernet.puf_linear_layer(new_hidden, layer_weights[2], layer_weights[3], logits_puffer, - batch_size, policy.hidden_size, atn_dim) - assert_near(logits_np, logits_puffer) - print("decoder output matches!") - - # value_fn - values_puffer = np.zeros((batch_size, 1), dtype=np.float32) - puffernet.puf_linear_layer(new_hidden, layer_weights[4], layer_weights[5], values_puffer, - batch_size, policy.hidden_size, 1) - assert_near(values_np, values_puffer) - print("value_fn output matches!") - -if __name__ == '__main__': - test_tetris_puffernet() - print("All tests passed!") diff --git a/tests/test_pytorch.py b/tests/test_pytorch.py deleted file mode 100644 index 9b72f195e7..0000000000 --- a/tests/test_pytorch.py +++ /dev/null @@ -1,211 +0,0 @@ -from typing import Any, Dict, List, Tuple - -import gymnasium as gym -import numpy as np -import torch -import pytest - -import pufferlib -import pufferlib.emulation -from pufferlib.pytorch import NativeDType, nativize_dtype, nativize_tensor - - -# TODO: align=True for dtype -@pytest.mark.parametrize( - "observation_dtype,emulated_dtype,expected", - [ - ( - np.dtype((np.uint8, (4,)), align=True), - np.dtype( - [ - ("x", np.uint8, (4,)), - ], - align=True, - ), - {"x": (torch.uint8, (4,), 0, 4)}, - ), - ( - np.dtype((np.uint8, (4, 5)), align=True), - np.dtype( - [ - ("x", np.uint8, (4, 5)), - ], - align=True, - ), - {"x": (torch.uint8, (4, 5), 0, 20)}, - ), - ( - np.dtype((np.uint8, (4,)), align=True), - np.dtype([("x", np.uint32, (1,))], align=True), - {"x": (torch.uint32, (1,), 0, 4)}, - ), - ( - np.dtype((np.uint8, (12,)), align=True), - np.dtype([("foo", np.int32, (1,)), ("bar", np.int32, (2,))], align=True), - {"foo": (torch.int32, (1,), 0, 4), "bar": (torch.int32, (2,), 4, 8)}, - ), - ( - np.dtype((np.uint8, (16,)), align=True), - np.dtype( - [ - ("foo", np.int32, (1,)), - ("bar", [("a", np.int32, (2,)), ("b", np.int32, (1,))]), - ], - align=True, - ), - { - "foo": (torch.int32, (1,), 0, 4), - "bar": { - "a": (torch.int32, (2,), 4, 8), - "b": (torch.int32, (1,), 12, 4), - }, - }, - ), - ( - np.dtype((np.float32, (4,)), align=True), - np.dtype( - [ - ("foo", np.float32, (1,)), - ("bar", [("a", np.float32, (2,)), ("b", np.float32, (1,))]), - ], - align=True, - ), - { - "foo": (torch.float32, (1,), 0, 1), - "bar": { - "a": (torch.float32, (2,), 1, 2), - "b": (torch.float32, (1,), 3, 1), - }, - }, - ), - ( - np.dtype((np.int32, (4,)), align=True), - np.dtype( - [ - ("foo", np.int32, (1,)), - ( - "bar", - [ - ("a", [("y", np.int32, (1,)), ("z", np.int32, (1,))]), - ("b", np.int32, (1,)), - ], - ), - ], - align=True, - ), - { - "foo": (torch.int32, (1,), 0, 1), - "bar": { - "a": { - "y": (torch.int32, (1,), 1, 1), - "z": (torch.int32, (1,), 2, 1), - }, - "b": (torch.int32, (1,), 3, 1), - }, - }, - ), - ( - np.dtype((np.uint8, (84,)), align=True), - np.dtype( - [ - ("xx", np.float32, (1, 2)), - ("yy", [("aa", np.uint8, (7, 7)), ("bb", np.int32, (2, 3))],), - ], - align=True, - ), - { - "xx": (torch.float32, (1, 2), 0, 8), - "yy": { - "aa": (torch.uint8, (7, 7), 8, 49), - "bb": (torch.int32, (2, 3), 60, 24), - }, - }, - ), - ], -) -def test_nativize_dtype( - observation_dtype: np.array, emulated_dtype: np.array, expected: NativeDType -): - assert expected == nativize_dtype( - pufferlib.namespace( - observation_dtype=observation_dtype, - emulated_observation_dtype=emulated_dtype, - ) - ) - - -@pytest.mark.parametrize( - "space,sample_dtype", - [ - ( - gym.spaces.Dict( - { - "x": gym.spaces.Box(-1.0, 1.0, (1, 2), dtype=np.float32), - "y": gym.spaces.Dict( - { - "a": gym.spaces.Box(0, 255, (7, 7), dtype=np.uint8), - "b": gym.spaces.Box(-1024, 1024, (2, 3), dtype=np.int32), - } - ), - } - ), - np.dtype(np.uint8), - ), - ( - gym.spaces.Dict( - { - "xx": gym.spaces.Box(-1.0, 1.0, (1, 2), dtype=np.float32), - "yy": gym.spaces.Box(-1.0, 1.0, (4, 5), dtype=np.float32), - } - ), - np.dtype(np.float32), - ), - ( - gym.spaces.Dict( - { - "screen": gym.spaces.Box(0, 255, (18, 20), dtype=np.uint8), - } - ), - np.dtype(np.uint8), - ), - ], -) -def test_nativize_tensor(space: gym.spaces.Space, sample_dtype: np.dtype): - emulated_dtype = pufferlib.emulation.dtype_from_space(space) - observation_space, observation_dtype = ( - pufferlib.emulation.emulate_observation_space(space) - ) - native_dtype = nativize_dtype( - pufferlib.namespace( - observation_dtype=sample_dtype, - emulated_observation_dtype=emulated_dtype, - ) - ) - flat = np.zeros(observation_space.shape, dtype=observation_space.dtype).view( - observation_dtype - ) - structured = space.sample() - pufferlib.emulation.emulate(flat, structured) - - def flatten(inp: Any | Dict[str, Any]) -> List[Any | Tuple[str, Any]]: - result = [] - - for k, v in inp.items(): - if isinstance(v, dict): - result.extend(flatten(v)) - elif isinstance(v, np.ndarray): - result.append((k, v)) - elif isinstance(v, torch.Tensor): - result.append((k, v.numpy())) - else: - raise - return result - - observation = torch.tensor(flat.view(observation_space.dtype)).unsqueeze(0) - nativized_tensor = nativize_tensor(observation, native_dtype) - assert all( - nx == ny and np.all(vx == vy) - for (nx, vx), (ny, vy) in zip(flatten(nativized_tensor), flatten(structured)) - ) - explain_out = torch._dynamo.explain(nativize_tensor)(observation, native_dtype) - assert len(explain_out.break_reasons) == 0 diff --git a/tests/test_record_array.py b/tests/test_record_array.py deleted file mode 100644 index 094ebb54a6..0000000000 --- a/tests/test_record_array.py +++ /dev/null @@ -1,65 +0,0 @@ -import gymnasium as gym -import numpy as np - -# Create a custom Gym space using Dict, Tuple, and Box -space = gym.spaces.Dict({ - "position": gym.spaces.Box(low=-1.0, high=1.0, shape=(2,), dtype=np.float32), - "velocity": gym.spaces.Box(low=-1.0, high=1.0, shape=(2,), dtype=np.float32), - "description": gym.spaces.Tuple(( - #gym.spaces.Discrete(10), - gym.spaces.Box(low=0, high=100, shape=(), dtype=np.int32), - gym.spaces.Box(low=0, high=100, shape=(), dtype=np.int32) - )) -}) - -space = gym.spaces.Dict({ - "position": gym.spaces.Box(low=-1.0, high=1.0, shape=(2,), dtype=np.float32), -}) - - -# Define a function to create a dtype from the Gym space -def create_dtype_from_space(space): - if isinstance(space, gym.spaces.Dict): - dtype_fields = [(name, create_dtype_from_space(subspace)) for name, subspace in space.spaces.items()] - return np.dtype(dtype_fields) - elif isinstance(space, gym.spaces.Tuple): - dtype_fields = [('field' + str(i), create_dtype_from_space(subspace)) for i, subspace in enumerate(space.spaces)] - return np.dtype(dtype_fields) - elif isinstance(space, gym.spaces.Box): - return (space.dtype, space.shape) - elif isinstance(space, gym.spaces.Discrete): - return np.int64 # Assuming np.int64 for Discrete spaces - -# Compute the dtype from the space -space_dtype = create_dtype_from_space(space) - -sample = dict(space.sample()) -breakpoint() -np.rec.array(sample, dtype=space_dtype) - -# Function to sample from the space and convert to a structured numpy array -def sample_and_convert(space, dtype): - sample = space.sample() - flat_sample = {} - def flatten(sample, name_prefix=""): - for key, item in sample.items(): - full_key = name_prefix + key if name_prefix == "" else name_prefix + "_" + key - if isinstance(item, dict): - flatten(item, full_key) - else: - flat_sample[full_key] = item - flatten(sample) - return np.array(tuple(flat_sample.values()), dtype=dtype) - -num_samples = 3 -samples = [sample_and_convert(space, space_dtype) for _ in range(num_samples)] -print("Samples:", samples) - -record_array = np.rec.array(samples) -print("Record Array:", record_array) - -bytes_array = record_array.tobytes() -print("Bytes Array:", bytes_array) - -record_array = np.rec.array(bytes_array, dtype=space_dtype) -print("Record Array from Bytes:", record_array) diff --git a/tests/test_record_emulation.py b/tests/test_record_emulation.py deleted file mode 100644 index 38a1cf23f0..0000000000 --- a/tests/test_record_emulation.py +++ /dev/null @@ -1,8 +0,0 @@ -import pufferlib.emulation - -from pufferlib.environments.ocean import env_creator - -env = env_creator('spaces')() -env.reset() -env.step([1,0]) -breakpoint() diff --git a/tests/test_registry.sh b/tests/test_registry.sh deleted file mode 100644 index 6bf2c91643..0000000000 --- a/tests/test_registry.sh +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/bash - -# Loop through all folders in the `registry` directory -for folder in pufferlib/registry/*; do - if [ -d "$folder" ]; then - # Extract folder name - folder_name=$(basename $folder) - - if [[ $folder_name == __* ]]; then - continue - fi - - # Install package with extras - pip install -e .[$folder_name] > /dev/null 2>&1 - - # Run tests - python tests/test_registry.py $folder_name - fi -done diff --git a/tests/test_render.py b/tests/test_render.py deleted file mode 100644 index f8bb38309f..0000000000 --- a/tests/test_render.py +++ /dev/null @@ -1,53 +0,0 @@ -from pdb import set_trace as T - -import argparse -import importlib -import time - -import cv2 - - -# Tested human: classic_control, atari, minigrid -# Tested rbg_array: atari, pokemon_red, crafter -# Tested ansii: minihack, nethack, squared -if __name__ == '__main__': - parser = argparse.ArgumentParser() - parser.add_argument('--env', type=str, default='atari') - parser.add_argument('--render-mode', type=str, default='rgb_array') - args = parser.parse_args() - - env_module = importlib.import_module(f'pufferlib.environments.{args.env}') - - if args.render_mode == 'human': - env = env_module.env_creator()(render_mode='human') - else: - env = env_module.env_creator()() - - terminal = True - while True: - start = time.time() - if terminal or truncated: - ob, _ = env.reset() - - if args.render_mode == 'rgb_array': - frame = env.render() - frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR) - #if ob.shape[0] in (1, 3, 4): - # ob = ob.transpose(1, 2, 0) - cv2.imshow('frame', frame) - - #cv2.imshow('ob', ob) - cv2.waitKey(1) - elif args.render_mode == 'ansi': - chars = env.render() - print("\033c", end="") - print(chars) - - ob = ob.reshape(1, *ob.shape) - action = env.action_space.sample() - ob, reward, terminal, truncated, info = env.step(action) - env.render() - start = time.time() - if time.time() - start < 1/60: - time.sleep(1/60 - (time.time() - start)) - diff --git a/tests/test_rich.py b/tests/test_rich.py deleted file mode 100644 index e54c5663da..0000000000 --- a/tests/test_rich.py +++ /dev/null @@ -1,291 +0,0 @@ -import psutil -import GPUtil -import time -import sys - -import rich -from rich.console import Console -from rich.layout import Layout -from rich.live import Live -from rich.table import Table -from rich.panel import Panel -from rich.progress import Progress, BarColumn, TextColumn, MofNCompleteColumn - -#import pufferlib - -ROUND_OPEN = rich.box.Box( - "╭──╮\n" - "│ │\n" - "│ │\n" - "│ │\n" - "│ │\n" - "│ │\n" - "│ │\n" - "╰──╯\n" -) - -c1 = '[bright_cyan]' -c2 = '[white]' -c3 = '[cyan]' -b1 = '[bright_cyan]' -b2 = '[bright_white]' - -def abbreviate(num): - if num < 1e3: - return f"{num:.0f}" - elif num < 1e6: - return f"{num/1e3:.1f}k" - elif num < 1e9: - return f"{num/1e6:.1f}m" - elif num < 1e12: - return f"{num/1e9:.1f}b" - else: - return f"{num/1e12:.1f}t" - -def duration(seconds): - h = seconds // 3600 - m = (seconds % 3600) // 60 - s = seconds % 60 - return f"{h}h {m}m {s}s" if h else f"{m}m {s}s" if m else f"{s}s" - -def print_dashboard(performance_data, loss_data, user_data, min_interval=0.25, last_print=[0]): - console = Console() - - util = Table(box=None, expand=True, show_header=False) - cpu_percent = psutil.cpu_percent() - dram_percent = psutil.virtual_memory().percent - gpus = GPUtil.getGPUs() - gpu_percent = gpus[0].load * 100 if gpus else 0 - vram_percent = gpus[0].memoryUtil * 100 if gpus else 0 - util.add_column(justify="left") - util.add_column(justify="center") - util.add_column(justify="center") - util.add_column(justify="center") - util.add_column(justify="right") - util.add_row( - f':blowfish: {c1}PufferLib {b2}1.0.0', - f'{c1}CPU: {c3}{cpu_percent:.1f}%', - f'{c1}GPU: {c3}{gpu_percent:.1f}%', - f'{c1}DRAM: {c3}{dram_percent:.1f}%', - f'{c1}VRAM: {c3}{vram_percent:.1f}%', - ) - - summary= Table(box=None, expand=True) - summary.add_column(f"{c1}Summary", justify='left', vertical='top') - summary.add_column(f"{c1}Value", justify='right', vertical='top') - summary.add_row(f'{c2}Epoch', f'{b2}{performance.epoch}') - summary.add_row(f'{c2}Uptime', f'{b2}{duration(performance.uptime)}') - estimated_time = performance.total_steps / performance.sps - summary.add_row(f'{c2}Estim', f'{b2}{duration(estimated_time)}') - summary.add_row(f'{c2}Agent Steps', f'{b2}{abbreviate(performance.agent_steps)}') - summary.add_row(f'{c2}Steps/sec', f'{b2}{abbreviate(performance.sps)}') - summary.add_row(f'{c2}sec/Batch', f'{b2}{performance.epoch_time:.2f}') - - perf = Table(box=None, expand=True) - perf.add_column(f"{c1}Performance", justify="left", ratio=1.0) - perf.add_column(f"{c1}Time", justify="right", ratio=0.5) - perf.add_row(f'{c2}Training', f'{b2}{performance.epoch_train_time:.2f}') - perf.add_row(f'{c2}Evaluation', f'{b2}{performance.epoch_eval_time:.2f}') - perf.add_row(f'{c2}Environment', f'{b2}{performance.epoch_env_time:.2f}') - perf.add_row(f'{c2}Forward', f'{b2}{performance.epoch_forward_time:.2f}') - perf.add_row(f'{c2}Misc', f'{b2}{performance.epoch_misc_time:.2f}') - perf.add_row(f'{c2}Allocation', f'{b2}{performance.epoch_alloc_time:.2f}') - perf.add_row(f'{c2}Backward', f'{b2}{performance.epoch_backward_time:.2f}') - - losses = Table(box=None, expand=True) - losses.add_column(f'{c1}Losses', justify="left", ratio=1.0) - losses.add_column(f'{c1}Value', justify="right", ratio=0.5) - for metric, value in loss_data.items(): - losses.add_row(f'{c2}{metric}', f'{b2}{value}') - - monitor = Table(box=None, expand=True, pad_edge=False) - monitor.add_row(summary, perf, losses) - - user = Table(box=None, expand=True, pad_edge=False) - user1 = Table(box=None, expand=True) - user2 = Table(box=None, expand=True) - user.add_row(user1, user2) - user1.add_column(f"{c1}User Stats", justify="left", ratio=1.0) - user1.add_column(f"{c1}Value", justify="right",ratio=1.0) - user2.add_column(f"{c1}User Stats", justify="left", ratio=1.0) - user2.add_column(f"{c1}Value", justify="right",ratio=1.0) - i = 0 - for metric, value in user_data.items(): - u = user1 if i % 2 == 0 else user2 - u.add_row(f'{c2}{metric}', f'{b2}{value}') - i += 1 - - table = Table(box=ROUND_OPEN, expand=True, show_header=False, width=80, border_style='bright_cyan') - table.add_row(util) - table.add_row(monitor) - table.add_row(user) - console.print(table) - - -class Dashboard: - def __init__(self): - self.console = Console() - self.rich = rich - - layout = Layout() - layout.split( - Layout(name="utilization", size=5), - Layout(name="monitoring"), - ) - - self.layout = layout - ''' - layout.split( - Layout(name="utilization", size=5), - Layout(name="puffer", size=2), - Layout(name="monitor", size=12), - Layout(name="user") - ) - layout["monitor"].split_row( - Layout(name="performance"), - Layout(name="losses") - ) - layout["user"].split_row( - Layout(name="user_stats") - ) - ''' - - utilization = Progress( - BarColumn(bar_width=None, style="bar.back", complete_style="bar.complete"), - TextColumn("[progress.description]{task.description}"), - MofNCompleteColumn(), - expand=True - ) - self.cpu_task = utilization.add_task("[cyan]CPU", total=100) - self.gpu_task = utilization.add_task("[red]GPU", total=100) - self.dram_task = utilization.add_task("[blue]DRAM", total=100) - self.vram_task = utilization.add_task("[magenta]VRAM", total=100) - self.layout["utilization"].update(utilization) - self.utilization = utilization - - #self.live = Live(self.layout, console=self.console)#, auto_refresh=4) - #self.live.start() - - def _update_utilization(self): - self.utilization.update(self.cpu_task, completed=psutil.cpu_percent()) - self.utilization.update(self.dram_task, completed=psutil.virtual_memory().percent) - gpus = GPUtil.getGPUs() - if gpus: - self.utilization.update(self.gpu_task, completed=gpus[0].load * 100) - self.utilization.update(self.vram_task, completed=gpus[0].memoryUtil * 100) - else: - self.utilization.update(self.gpu_task, completed=0) - self.utilization.update(self.vram_task, completed=0) - - #self.layout['puffer'].update(f':blowfish: PufferLib {pufferlib.__version__}') - #self.layout['puffer'].update(f':blowfish: PufferLib 1.0.0') - - def update(self, total_uptime, estimated_time, total_steps, steps_per_second, performance_data, loss_data, user_data): - topline = self.update_topline(total_uptime, estimated_time, total_steps, steps_per_second) - performance = self.update_performance(performance_data) - losses = self.update_losses(loss_data) - user = self.update_user_stats(user_data) - - megatable = Table(box=ROUND_OPEN, expand=True, show_header=False) - megatable.add_row(topline) - megatable.add_row('') - perf = Table(box=None, expand=True) - perf.add_column(performance, ratio=1.0) - perf.add_column(losses, ratio=1.0) - #megatable.add_row(performance) - #megatable.add_row(losses) - megatable.add_row(perf) - megatable.add_row('') - megatable.add_row(user) - self.layout["monitoring"].update(megatable) - self.console.clear() - self.console.print(self.layout) - - - def update_topline(self, total_uptime, estimated_time, total_steps, steps_per_second): - table = Table(box=None, expand=True) - table.add_column(justify="left") - table.add_column(justify="center") - table.add_column(justify="right") - table.add_row( - f':blowfish: PufferLib 1.0.0', - f'[bold magenta]Uptime: [cyan]{total_uptime}/{estimated_time}(est)', - f'[bold magenta]Agent Steps: [cyan]{total_steps} ({steps_per_second}/s)' - ) - return table - - def update_performance(self, data): - table = Table(box=None, expand=True) - #self.layout["performance"].update(table) - table.add_column("[bold magenta]Performance", justify="right", ratio=1.0) - table.add_column("Latency", justify="left", style="cyan", ratio=1.0) - for metric, value in data.items(): - table.add_row(metric, str(value)) - - return table - self.console.clear() - self.console.print(self.layout) - - def update_losses(self, data): - table = Table(box=None, expand=True) - #self.layout["losses"].update(table) - table.add_column("[bold magenta]Losses", justify="right", ratio=1.0) - table.add_column("Value", justify="left", style="bright_cyan", ratio=1.0) - for metric, value in data.items(): - table.add_row(metric, str(value)) - - table.add_row("") - - return table - self.console.clear() - self.console.print(self.layout) - - def update_user_stats(self, data): - table = Table(box=None, expand=True) - table.add_column("[bold magenta]User Stats", justify="right", style="bold yellow", ratio=1.0) - table.add_column("Value", justify="left",ratio=1.0) - #self.layout["user_stats"].update(table) - for metric, value in data.items(): - table.add_row(metric, str(value)) - - return table - self.console.clear() - self.console.print(self.layout) - - -#dashboard = Dashboard() - -# Update loop -try: - while True: - #dashboard._update_utilization() - topline = (5000, 100000, 102332, 1038, 1.3) - performance = { - 'training': 0.7, - 'evaluation': 0.6, - 'environment': 0.2, - 'forward': 0.3, - 'misc': 0.1, - 'allocation': 0.2, - 'backward': 0.3, - } - losses = { - 'policy': 0.4, - 'value': 0.2, - 'entropy': 0.1, - 'old_approx_kl': 0.1, - 'approx_kl': 0.2, - 'clip_fraction': 0.1, - 'explained_variance': 0.3, - } - user_stats = { - 'time_alive': 128, - 'exploration': 0.1, - 'experience': 1000, - } - #dashboard.update(*topline, performance, losses, user_stats) - print_dashboard(*topline, performance, losses, user_stats) - time.sleep(1) -except KeyboardInterrupt: - dashboard.stop() - diff --git a/tests/test_utils.py b/tests/test_utils.py deleted file mode 100644 index e193d0aaf5..0000000000 --- a/tests/test_utils.py +++ /dev/null @@ -1,14 +0,0 @@ -import sys -import gym - -import pufferlib -import pufferlib.utils - -def test_suppress(): - with pufferlib.utils.Suppress(): - gym.make('Breakout-v4') - print('stdout (you should not see this)', file=sys.stdout) - print('stderr (you should not see this)', file=sys.stderr) - -if __name__ == '__main__': - test_suppress() \ No newline at end of file diff --git a/tests/time_alloc.py b/tests/time_alloc.py deleted file mode 100644 index fd938d4ca6..0000000000 --- a/tests/time_alloc.py +++ /dev/null @@ -1,15 +0,0 @@ -import numpy as np -import timeit - -# Time np.zeros(2, 5) for 100000 iterations -time_zeros = timeit.timeit('np.zeros((2, 5))', setup='import numpy as np', number=100000) - -# Pre-allocate the array -preallocated_array = np.zeros((2, 5)) - -# Time setting the pre-allocated array to zero for 100000 iterations -time_preallocated = timeit.timeit('preallocated_array[:] = 0', setup='import numpy as np; preallocated_array = np.zeros((2, 5))', number=100000) - -print(f"Time for np.zeros(2, 5) over 100000 iterations: {time_zeros} seconds") -print(f"Time for preallocated *= 0 over 100000 iterations: {time_preallocated} seconds") - diff --git a/trailer/trailer.c b/trailer/trailer.c new file mode 100644 index 0000000000..c97f6e9cae --- /dev/null +++ b/trailer/trailer.c @@ -0,0 +1,723 @@ +#include +#include +#include +#include +#include +#include + +#include "raylib.h" + +#if defined(__APPLE__) + #define GL_SILENCE_DEPRECATION + #include + #include +#else + #include "glad.h" +#endif +#include "rlgl.h" +#include "raymath.h" + +#define GLSL_VERSION 330 + +#define SCREEN_W 1920 +#define SCREEN_H 1080 + +#define FONT_TITLE 72 +#define FONT_LABEL 42 + +static const Color BG = {4, 8, 20, 255}; +static const Color C_WHITE = {220, 230, 255, 255}; +static const Color C_CYAN = {0, 187, 187, 255}; + +// ─── Vertex layout (x, y, size_scale, r, g, b, a) ─────────────────────────── +typedef struct { + float x, y, size_scale; + float r, g, b, a; +} StarVertex; + +// ─── GL draw ────────────────────────────────────────────────────────────────── +static void draw_stars(StarVertex *verts, int n, Shader *sh) { + GLuint vao = 0, vbo = 0; + glGenVertexArrays(1, &vao); + glBindVertexArray(vao); + glGenBuffers(1, &vbo); + glBindBuffer(GL_ARRAY_BUFFER, vbo); + glBufferData(GL_ARRAY_BUFFER, n * sizeof(StarVertex), verts, GL_STREAM_DRAW); + glVertexAttribPointer(sh->locs[SHADER_LOC_VERTEX_POSITION], + 3, GL_FLOAT, GL_FALSE, sizeof(StarVertex), (void*)0); + glEnableVertexAttribArray(sh->locs[SHADER_LOC_VERTEX_POSITION]); + glVertexAttribPointer(sh->locs[SHADER_LOC_VERTEX_COLOR], + 4, GL_FLOAT, GL_FALSE, sizeof(StarVertex), (void*)(3 * sizeof(float))); + glEnableVertexAttribArray(sh->locs[SHADER_LOC_VERTEX_COLOR]); + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindVertexArray(0); + + rlDrawRenderBatchActive(); + rlSetBlendMode(RL_BLEND_ADDITIVE); + int timeLoc = GetShaderLocation(*sh, "currentTime"); + glUseProgram(sh->id); + glUniform1f(timeLoc, (float)GetTime()); + Matrix mvp = MatrixMultiply(rlGetMatrixModelview(), rlGetMatrixProjection()); + glUniformMatrix4fv(sh->locs[SHADER_LOC_MATRIX_MVP], 1, GL_FALSE, MatrixToFloat(mvp)); + glBindVertexArray(vao); + glDrawArrays(GL_POINTS, 0, n); + glBindVertexArray(0); + glUseProgram(0); + rlSetBlendMode(RL_BLEND_ALPHA); + glDeleteBuffers(1, &vbo); + glDeleteVertexArrays(1, &vao); +} + +// ─── Shared background star field ───────────────────────────────────────────── +#define NUM_BG_STARS 32768 +#define NUM_VISIBLE_STARS 16384 // stars with normal distribution; rest start at center +#define BG_DENSE_R 1200.0f // full density inside this radius +#define BG_FADE_R 2400.0f // density lerps to BG_SPARSE_FRAC by here +#define BG_SPARSE_FRAC 0.02f // density fraction beyond BG_FADE_R +#define BG_MAX_R 4000.0f + +typedef struct { float r, angle, vr, brightness, size_scale; } BgStar; +static BgStar bg_stars[NUM_BG_STARS]; +static StarVertex bg_verts[NUM_BG_STARS]; + +// Text layout anchors +#define HAIKU_Y 60.0f // top of first haiku line +#define FOOTER_Y 860.0f // top of "PufferLib 4.0" line + +// Spiral/nova epicenter — midpoint between bottom of haiku line 3 and top of footer +// line3_bottom = HAIKU_Y + (FONT_TITLE+16)*2 + FONT_TITLE = 60+176+72 = 308 +// footer_top = FOOTER_Y = 860 → mid = (308+860)/2 = 584 +#define SPIRAL_CX (SCREEN_W * 0.5f) +#define SPIRAL_CY 584.0f + +#define SPIRAL_GM 16000000.0f // gravitational constant — tune for feel +#define SPIRAL_OMEGA 0.1f // base angular velocity (rad/s) +#define SPIRAL_OMEGA_R 1000.0f // differential rotation scale (inner faster) + +// Area of annulus [r0, r1] proportional to r1^2 - r0^2 +// We split visible stars across three zones by desired density weight: +// dense: uniform area in [0, BG_DENSE_R] weight = 1.0 +// fade: uniform area in [BG_DENSE_R, BG_FADE_R] weight = avg ~0.5*(1+SPARSE_FRAC) +// outer: uniform area in [BG_FADE_R, BG_MAX_R] weight = BG_SPARSE_FRAC +// Stars per zone proportional to area * weight +static void init_bg_stars(void) { + float a_dense = BG_DENSE_R * BG_DENSE_R; + float a_fade = BG_FADE_R * BG_FADE_R - a_dense; + float a_outer = BG_MAX_R * BG_MAX_R - BG_FADE_R * BG_FADE_R; + float w_dense = 1.0f; + float w_fade = 0.5f * (1.0f + BG_SPARSE_FRAC); + float w_outer = BG_SPARSE_FRAC; + float total = a_dense * w_dense + a_fade * w_fade + a_outer * w_outer; + int n_dense = (int)(NUM_VISIBLE_STARS * a_dense * w_dense / total); + int n_fade = (int)(NUM_VISIBLE_STARS * a_fade * w_fade / total); + // remainder goes to outer + + for (int i = 0; i < NUM_BG_STARS; i++) { + float r; + if (i >= NUM_VISIBLE_STARS) { + // Hidden nova stars + r = 0.5f + ((float)rand() / (float)RAND_MAX) * 4.5f; + } else if (i < n_dense) { + float rnd = (float)rand() / (float)RAND_MAX; + r = BG_DENSE_R * sqrtf(rnd); + } else if (i < n_dense + n_fade) { + float rnd = (float)rand() / (float)RAND_MAX; + r = sqrtf(BG_DENSE_R*BG_DENSE_R + rnd * (BG_FADE_R*BG_FADE_R - BG_DENSE_R*BG_DENSE_R)); + } else { + float rnd = (float)rand() / (float)RAND_MAX; + r = sqrtf(BG_FADE_R*BG_FADE_R + rnd * (BG_MAX_R*BG_MAX_R - BG_FADE_R*BG_FADE_R)); + } + bg_stars[i].r = r; + bg_stars[i].angle = ((float)rand() / (float)RAND_MAX) * 2.0f * 3.14159265f; + bg_stars[i].vr = 0.0f; + bg_stars[i].brightness = 0.2f + (float)(rand() % 80) / 100.0f; + float s = (float)rand() / (float)RAND_MAX; + bg_stars[i].size_scale = (s < 0.85f) + ? (0.2f + s * 0.4f) * 0.7f + : (0.8f + (s - 0.85f) * 6.0f) * 0.7f; + } +} + +#define NOVA_GM 5000000.0f // outward repulsion strength for nova + +// Integrate one timestep of gravitational attraction toward center +static void update_bg_spiral(float dt) { + for (int i = 0; i < NUM_BG_STARS; i++) { + float r = bg_stars[i].r; + bg_stars[i].vr -= SPIRAL_GM / (r * r) * dt; + bg_stars[i].r += bg_stars[i].vr * dt; + bg_stars[i].angle += SPIRAL_OMEGA * SPIRAL_OMEGA_R / (r + SPIRAL_OMEGA_R) * dt; + if (bg_stars[i].r < 1.0f) bg_stars[i].r = 1.0f; + } +} + +// Integrate one timestep of outward nova explosion (1/r^2 repulsion) +static void update_bg_nova(float dt) { + for (int i = 0; i < NUM_BG_STARS; i++) { + float r = fmaxf(bg_stars[i].r, 1.0f); + bg_stars[i].vr += NOVA_GM / (r * r) * dt; + bg_stars[i].r += bg_stars[i].vr * dt; + // No angular update — stars fly straight outward + } +} + +static int bg_draw_count; + +static void build_bg_verts_spiral(float alpha, int nova) { + float cx = SPIRAL_CX, cy = SPIRAL_CY; + int n = nova ? NUM_BG_STARS : NUM_VISIBLE_STARS; + for (int i = 0; i < n; i++) { + float br = bg_stars[i].brightness * alpha; + bg_verts[i] = (StarVertex){ + .x = cx + bg_stars[i].r * cosf(bg_stars[i].angle), + .y = cy + bg_stars[i].r * sinf(bg_stars[i].angle), + .size_scale = bg_stars[i].size_scale, + .r = C_WHITE.r / 255.0f * br, + .g = C_WHITE.g / 255.0f * br, + .b = C_WHITE.b / 255.0f * br, + .a = (float)i, + }; + } + bg_draw_count = n; +} + +static void build_bg_verts(void) { + bg_draw_count = NUM_VISIBLE_STARS; + for (int i = 0; i < NUM_VISIBLE_STARS; i++) { + float br = bg_stars[i].brightness; + float cx = SPIRAL_CX, cy = SPIRAL_CY; + bg_verts[i] = (StarVertex){ + .x = cx + bg_stars[i].r * cosf(bg_stars[i].angle), + .y = cy + bg_stars[i].r * sinf(bg_stars[i].angle), + .size_scale = bg_stars[i].size_scale, + .r = C_WHITE.r / 255.0f * br, + .g = C_WHITE.g / 255.0f * br, + .b = C_WHITE.b / 255.0f * br, + .a = (float)i, // stable seed for twinkle + }; + } +} + +/* ============================================================ + ANIMATION 1: Speed Comparison (0–3s) + Four rows, each a star bouncing at a rate proportional to + the environment's simulation throughput (20M/4M/1M/30k sps). + The 20M ball completes one full traverse in 1/1.333 s. + ============================================================ */ + +#define NUM_BALLS 4 +#define LANE_H 195 // 780px / 4 lanes +#define A1_MARGIN_L 280 +#define A1_MARGIN_R 160 +#define TRACK_W (SCREEN_W - A1_MARGIN_L - A1_MARGIN_R) +#define TRACK_Y0 298 // 200 top + 780/8 = first lane center + +#define SPEED_20M (2.0f * TRACK_W / 0.75f) +static const float SPEEDS[NUM_BALLS] = { + SPEED_20M, + SPEED_20M * (4.0f / 20.0f), + SPEED_20M * (1.0f / 20.0f), + SPEED_20M * (0.03f / 20.0f), +}; +static const char *BALL_LABELS[NUM_BALLS] = {"20M", "4M", "1M", "30k"}; +static const char *BALL_VERSIONS[NUM_BALLS] = {"v4", "v3", "v2", "v1"}; + +#define BALL_STAR_SCALE 5.28f + +static float ball_x[NUM_BALLS]; +static float ball_dir[NUM_BALLS]; +static StarVertex ball_verts[NUM_BALLS]; + +static void init_anim1(void) { + for (int i = 0; i < NUM_BALLS; i++) { + ball_x[i] = A1_MARGIN_L; + ball_dir[i] = 1.0f; + } +} + +static void update_anim1(float dt, Font roboto, Shader *sh) { + for (int i = 0; i < NUM_BALLS; i++) { + ball_x[i] += SPEEDS[i] * ball_dir[i] * dt; + if (ball_x[i] >= A1_MARGIN_L + TRACK_W) { + ball_x[i] = A1_MARGIN_L + TRACK_W; ball_dir[i] = -1.0f; + } else if (ball_x[i] <= A1_MARGIN_L) { + ball_x[i] = A1_MARGIN_L; ball_dir[i] = 1.0f; + } + float lane_y = TRACK_Y0 + i * LANE_H; + ball_verts[i] = (StarVertex){ + .x = ball_x[i], .y = lane_y, + .size_scale = BALL_STAR_SCALE, + .r = C_CYAN.r / 255.0f, .g = C_CYAN.g / 255.0f, + .b = C_CYAN.b / 255.0f, .a = (float)(NUM_BG_STARS + i), // stable seed + }; + } + + build_bg_verts(); + draw_stars(bg_verts, bg_draw_count, sh); + draw_stars(ball_verts, NUM_BALLS, sh); + + for (int i = 0; i < NUM_BALLS; i++) { + int lane_y = TRACK_Y0 + i * LANE_H; + DrawLine(A1_MARGIN_L, lane_y, A1_MARGIN_L + TRACK_W, lane_y, + (Color){0, 187, 187, 20}); + DrawTextEx(roboto, BALL_VERSIONS[i], (Vector2){40, lane_y - FONT_LABEL/2}, FONT_LABEL, 1, C_CYAN); + DrawTextEx(roboto, BALL_LABELS[i], (Vector2){140, lane_y - FONT_LABEL/2}, FONT_LABEL, 1, C_WHITE); + } + const char *title = "Steps Per Second"; + const char *subtitle = "(1/1,000,000 scale)"; + Vector2 tsz = MeasureTextEx(roboto, title, FONT_TITLE, 1); + Vector2 ssz = MeasureTextEx(roboto, subtitle, FONT_LABEL, 1); + DrawTextEx(roboto, title, + (Vector2){SCREEN_W/2 - tsz.x/2, 100}, FONT_TITLE, 1, C_WHITE); + DrawTextEx(roboto, subtitle, + (Vector2){SCREEN_W/2 - ssz.x/2, 100 + FONT_TITLE + 4}, FONT_LABEL, 1, C_WHITE); +} + +/* ============================================================ + ANIMATION 2: Horizontal Bar Chart – Solve Times (3–6s) + Bars are starry regions. Each bar lerps from a large start + width down to a smaller end width (showing speedup). + Stars are pre-scattered across the start width; the right + edge shrinks by culling stars beyond the current width. + Phase: 0–1s static at start widths + 1–2s lerp start → end + 2–3s static at end widths + ============================================================ */ + +#define NUM_ENVS 5 +#define CHART_LEFT 440 +#define CHART_MAX_W (SCREEN_W/2 - CHART_LEFT - 40) +#define CHART_TOP 238 // 200 top + 156/2 - BAR_H/2; first bar center at 278 +#define BAR_H 80 +#define BAR_GAP 76 // 780px / 5 bars = 156 per slot; 156 - 80 = 76 + +#define BAR_STAR_SCALE 0.20f +#define STAR_DENSITY 0.075f // stars per square pixel +#define MAX_BAR_STARS 30000 // upper bound for static allocation + +typedef struct { + const char *name; + float start_val; + float end_val; + float start_px; // set by init + float end_ratio; // end_val / start_val, set by init + int star_off; // offset into flat arrays, set by init + int star_count; // set by init +} EnvBar; + +static EnvBar envs[NUM_ENVS] = { + {"Environment A", 27.0f, 3.0f, 0, 0, 0, 0}, + {"Environment B", 3.0f, 0.24f, 0, 0, 0, 0}, + {"Environment C", 1.0f, 0.14f, 0, 0, 0, 0}, + {"Environment D", 0.5f, 0.08f, 0, 0, 0, 0}, + {"Environment E", 0.2f, 0.04f, 0, 0, 0, 0}, +}; + +static float bar_nx[MAX_BAR_STARS]; +static float bar_sy[MAX_BAR_STARS]; +static StarVertex bar_verts[MAX_BAR_STARS]; + +static void init_anim2(void) { + float max_val = 0.0f; + for (int e = 0; e < NUM_ENVS; e++) + if (envs[e].start_val > max_val) max_val = envs[e].start_val; + + int offset = 0; + for (int e = 0; e < NUM_ENVS; e++) { + envs[e].start_px = (envs[e].start_val / max_val) * CHART_MAX_W; + envs[e].end_ratio = envs[e].end_val / envs[e].start_val; + envs[e].star_count = (int)(STAR_DENSITY * envs[e].start_px * BAR_H); + envs[e].star_off = offset; + float cy = CHART_TOP + e * (BAR_H + BAR_GAP) + BAR_H * 0.5f; + for (int i = 0; i < envs[e].star_count; i++) { + bar_nx[offset + i] = (float)rand() / (float)RAND_MAX; + float fy = ((float)rand() / (float)RAND_MAX) * BAR_H - BAR_H * 0.5f; + bar_sy[offset + i] = cy + fy; + } + offset += envs[e].star_count; + } +} + +static void draw_anim2(float anim_t, Font roboto, Shader *sh) { + float lerp_t; + if (anim_t < 1.0f) lerp_t = 0.0f; + else if (anim_t < 2.0f) lerp_t = anim_t - 1.0f; + else lerp_t = 1.0f; + + int n = 0; + for (int e = 0; e < NUM_ENVS; e++) { + float cull = 1.0f - lerp_t * (1.0f - envs[e].end_ratio); + int off = envs[e].star_off; + for (int i = 0; i < envs[e].star_count; i++) { + if (bar_nx[off + i] > cull) continue; + bar_verts[n++] = (StarVertex){ + .x = CHART_LEFT + bar_nx[off + i] * envs[e].start_px, + .y = bar_sy[off + i], + .size_scale = BAR_STAR_SCALE, + .r = C_CYAN.r / 255.0f, .g = C_CYAN.g / 255.0f, + .b = C_CYAN.b / 255.0f, .a = (float)(off + i), // stable seed + }; + } + } + + build_bg_verts(); + draw_stars(bg_verts, bg_draw_count, sh); + draw_stars(bar_verts, n, sh); + + for (int e = 0; e < NUM_ENVS; e++) { + float cy = CHART_TOP + e * (BAR_H + BAR_GAP) + BAR_H * 0.5f; + DrawTextEx(roboto, envs[e].name, (Vector2){100, cy - FONT_LABEL/2}, FONT_LABEL, 1, C_WHITE); + } + // Anim2 title: centered in left half + Vector2 t2sz = MeasureTextEx(roboto, "Solve Time", FONT_TITLE, 1); + DrawTextEx(roboto, "Solve Time", + (Vector2){SCREEN_W/4 - t2sz.x/2, 100}, FONT_TITLE, 1, C_WHITE); +} + +/* ============================================================ + ANIMATION 3: PufferNet logo with pulsing glow (6–9s) + Image is wide black outlines on transparent BG. A Sobel + edge + blurred halo is driven by cos(time) for the pulse. + ============================================================ */ + +static void draw_anim3(float anim_t, Shader *glow_sh, Texture2D tex, Shader *star_sh, Font roboto) { + float glow = 0.65f + 0.15f * cosf(anim_t * 2.5f); // 0..1 drives the oscillating portion + + float fade = fminf(anim_t / 0.5f, 1.0f); + + int glow_loc = GetShaderLocation(*glow_sh, "glowStrength"); + int texel_loc = GetShaderLocation(*glow_sh, "texelSize"); + int fade_loc = GetShaderLocation(*glow_sh, "fadeAlpha"); + float texel[2] = {1.0f / tex.width, 1.0f / tex.height}; + + SetShaderValue(*glow_sh, glow_loc, &glow, SHADER_UNIFORM_FLOAT); + SetShaderValue(*glow_sh, texel_loc, texel, SHADER_UNIFORM_VEC2); + SetShaderValue(*glow_sh, fade_loc, &fade, SHADER_UNIFORM_FLOAT); + + // Center image in the right half of the screen + float x = SCREEN_W/2 + (SCREEN_W/2 - tex.width) * 0.5f; + float y = (SCREEN_H - tex.height) * 0.5f + 70; + + BeginShaderMode(*glow_sh); + DrawTexture(tex, (int)x, (int)y, WHITE); + EndShaderMode(); + + // Title centered in right half, same y=100 as anim2 title + Color title_col = (Color){C_WHITE.r, C_WHITE.g, C_WHITE.b, (unsigned char)(fade * 255)}; + Vector2 t3sz = MeasureTextEx(roboto, "PufferNet", FONT_TITLE, 1); + DrawTextEx(roboto, "PufferNet", + (Vector2){SCREEN_W*3/4 - t3sz.x/2, 100}, FONT_TITLE, 1, title_col); +} + +/* ============================================================ + ANIMATION 4: Spiral in (9–12s) + Anim2+3 fade out over 0.5s. Stars spiral in. + ============================================================ */ + +static void draw_anim4(float anim_t, Font roboto, Shader *star_sh, + Shader *glow_sh, Texture2D tex) { + float fade_out = 1.0f - fminf(anim_t / 0.5f, 1.0f); + + if (fade_out > 0.0f) { + draw_anim3(5.5f, glow_sh, tex, star_sh, roboto); + DrawRectangle(0, 0, SCREEN_W, SCREEN_H, + (Color){BG.r, BG.g, BG.b, (unsigned char)((1.0f - fade_out) * 255)}); + } + + build_bg_verts_spiral(1.0f, 0); + draw_stars(bg_verts, bg_draw_count, star_sh); +} + +// ─── Text overlay helpers ───────────────────────────────────────────────────── + +// Returns 0..1 alpha: starts fading in at `start`, fully opaque after `fade` seconds +static float fade_in(float t, float start, float fade) { + return fmaxf(0.0f, fminf((t - start) / fade, 1.0f)); +} + +// Draw centered text at (SCREEN_W/2, y) with given color and 0..1 alpha +static void draw_centered(Font f, const char *text, float y, Color col, float alpha) { + if (alpha <= 0.0f) return; + col.a = (unsigned char)(alpha * 255); + Vector2 sz = MeasureTextEx(f, text, FONT_TITLE, 1); + DrawTextEx(f, text, (Vector2){SCREEN_W * 0.5f - sz.x * 0.5f, y}, FONT_TITLE, 1, col); +} + +// Draw two strings side-by-side, centered together, at y +static void draw_centered2(Font f, + const char *s1, Color c1, + const char *s2, Color c2, + float y, float alpha) { + if (alpha <= 0.0f) return; + c1.a = c2.a = (unsigned char)(alpha * 255); + Vector2 sz1 = MeasureTextEx(f, s1, FONT_TITLE, 1); + Vector2 sz2 = MeasureTextEx(f, s2, FONT_TITLE, 1); + float x = SCREEN_W * 0.5f - (sz1.x + sz2.x) * 0.5f; + DrawTextEx(f, s1, (Vector2){x, y}, FONT_TITLE, 1, c1); + DrawTextEx(f, s2, (Vector2){x + sz1.x, y}, FONT_TITLE, 1, c2); +} + +// ─── Haiku + title overlay (called every frame from anim5 onward) ───────────── +#define T_NOVA 31.5f + +static void draw_haiku_overlay(float t, Font roboto) { + float lh = FONT_TITLE + 16; // line height + draw_centered(roboto, "Each thought is a star", HAIKU_Y, C_WHITE, fade_in(t, 26.5f, 0.5f)); + draw_centered(roboto, "Few form a constellation", HAIKU_Y + lh, C_WHITE, fade_in(t, 28.5f, 0.5f)); + draw_centered(roboto, "But they shine brightest", HAIKU_Y + lh*2, C_WHITE, fade_in(t, T_NOVA, 0.5f)); + draw_centered2(roboto, "PufferLib ", C_WHITE, "4.0", C_CYAN, + FOOTER_Y, fade_in(t, T_NOVA + 2.0f, 0.5f)); + draw_centered2(roboto, "Download now at ", C_WHITE, "puffer.ai", C_CYAN, + FOOTER_Y + lh, fade_in(t, T_NOVA + 4.0f, 0.5f)); +} + +/* ============================================================ + ANIMATION 5: Thumbnails fade in, then spiral in (22–end) + Each thumbnail placed at a fixed position around the screen. + After .25s stagger fade-in, positions included in spiral. + ============================================================ */ + +#define NUM_THUMBS 32 + +static const char *thumb_paths[NUM_THUMBS] = { + "../puffer.ai/docs/assets/2048_thumbnail.png", + "../puffer.ai/docs/assets/blastar_thumbnail.png", + "../puffer.ai/docs/assets/breakout_thumbnail.png", + "../puffer.ai/docs/assets/cartpole_thumbnail.png", + "../puffer.ai/docs/assets/connect4_thumbnail.png", + "../puffer.ai/docs/assets/convert_thumbnail.png", + "../puffer.ai/docs/assets/cpr_thumbnail.png", + "../puffer.ai/docs/assets/drone_thumbnail.png", + "../puffer.ai/docs/assets/enduro_thumbnail.png", + "../puffer.ai/docs/assets/freeway_thumbnail.png", + "../puffer.ai/docs/assets/go_thumbnail.png", + "../puffer.ai/docs/assets/gpudrive_thumbnail.png", + "../puffer.ai/docs/assets/impulse_wars_thumbnail.png", + "../puffer.ai/docs/assets/moba_thumbnail.png", + "../puffer.ai/docs/assets/nmmo3_thumbnail.png", + "../puffer.ai/docs/assets/pacman_thumbnail.png", + "../puffer.ai/docs/assets/pong_thumbnail.png", + "../puffer.ai/docs/assets/robocode_thumbnail.png", + "../puffer.ai/docs/assets/rware_thumbnail.png", + "../puffer.ai/docs/assets/slimevolley_thumbnail.png", + "../puffer.ai/docs/assets/snake_thumbnail.png", + "../puffer.ai/docs/assets/squared_thumbnail.png", + "../puffer.ai/docs/assets/tactical_thumbnail.png", + "../puffer.ai/docs/assets/target_thumbnail.png", + "../puffer.ai/docs/assets/tcg_thumbnail.png", + "../puffer.ai/docs/assets/template_thumbnail.png", + "../puffer.ai/docs/assets/terraform_thumbnail.png", + "../puffer.ai/docs/assets/tetris_thumbnail.png", + "../puffer.ai/docs/assets/tower_climb_thumbnail.png", + "../puffer.ai/docs/assets/trash_pickup_thumbnail.png", + "../puffer.ai/docs/assets/tripletriad_thumbnail.png", + "../puffer.ai/docs/assets/whisker_racer_thumbnail.png", +}; + +static Texture2D thumbs[NUM_THUMBS]; +static float thumb_r[NUM_THUMBS]; +static float thumb_angle[NUM_THUMBS]; +static float thumb_vr[NUM_THUMBS]; + +static void init_anim5(void) { + for (int i = 0; i < NUM_THUMBS; i++) + thumbs[i] = LoadTexture(thumb_paths[i]); + + // Spawn in a slight outward spiral: radius grows by THUMB_SPIRAL_DR per step + float cx = SPIRAL_CX, cy = SPIRAL_CY; + float ring_r = 400.0f; + float spiral_dr = 12.0f; // px added to radius per thumbnail + for (int i = 0; i < NUM_THUMBS; i++) { + thumb_r[i] = ring_r + i * spiral_dr; + thumb_angle[i] = (float)i / (float)NUM_THUMBS * 2.0f * 3.14159265f; + thumb_vr[i] = 0.0f; + } + (void)cx; (void)cy; +} + +static void unload_anim5(void) { + for (int i = 0; i < NUM_THUMBS; i++) + UnloadTexture(thumbs[i]); +} + +static void draw_anim5(float anim_t, float dt, Shader *star_sh) { + float cx = SPIRAL_CX, cy = SPIRAL_CY; + + // Stars already integrated via update_bg_spiral each frame + build_bg_verts_spiral(1.0f, 0); + draw_stars(bg_verts, bg_draw_count, star_sh); + + for (int i = 0; i < NUM_THUMBS; i++) { + // Stagger in reverse angular order: highest angle appears first, + // so each new thumbnail materialises behind the already-spiraling ones + int rev = NUM_THUMBS - 1 - i; + float fade_start = rev * 0.07f; + float alpha = fmaxf(0.0f, fminf((anim_t - fade_start) / 0.25f, 1.0f)); + + // Only integrate once visible — invisible ones stay at their start position + if (alpha > 0.0f) { + thumb_vr[i] -= SPIRAL_GM / (thumb_r[i] * thumb_r[i]) * dt; + thumb_r[i] += thumb_vr[i] * dt; + thumb_angle[i] += SPIRAL_OMEGA * SPIRAL_OMEGA_R / (thumb_r[i] + SPIRAL_OMEGA_R) * dt; + if (thumb_r[i] < 1.0f) thumb_r[i] = 1.0f; + } + + if (alpha <= 0.0f) continue; + + float r = thumb_r[i]; + float ang = thumb_angle[i]; + float px = cx + r * cosf(ang); + float py = cy + r * sinf(ang); + + // Scale proportional to r so size reaches 1px at center + float tw = thumbs[i].width, th = thumbs[i].height; + float base_scale = fminf(300.0f / tw, 300.0f / th); + float r_frac = thumb_r[i] / (400.0f + (NUM_THUMBS - 1) * 12.0f); + float size_scale = fmaxf(1.0f / fmaxf(tw, th), base_scale * r_frac); + float dw = tw * size_scale, dh = th * size_scale; + + Rectangle src = {0, 0, tw, th}; + Rectangle dest = {px - dw*0.5f, py - dh*0.5f, dw, dh}; + Color tint = {255, 255, 255, (unsigned char)(alpha * 255)}; + DrawTexturePro(thumbs[i], src, dest, (Vector2){0,0}, 0.0f, tint); + } +} + +// ─── Video recording ────────────────────────────────────────────────────────── +#define RECORD_FPS 30 + +typedef struct { int pipefd[2]; pid_t pid; } VideoRecorder; + +static bool OpenVideo(VideoRecorder *rec, const char *filename, int w, int h) { + if (pipe(rec->pipefd) == -1) { fprintf(stderr, "pipe failed\n"); return false; } + rec->pid = fork(); + if (rec->pid == -1) { fprintf(stderr, "fork failed\n"); return false; } + if (rec->pid == 0) { + close(rec->pipefd[1]); + dup2(rec->pipefd[0], STDIN_FILENO); + close(rec->pipefd[0]); + for (int fd = 3; fd < 256; fd++) close(fd); + char sz[32]; snprintf(sz, sizeof(sz), "%dx%d", w, h); + char fps[8]; snprintf(fps, sizeof(fps), "%d", RECORD_FPS); + execlp("ffmpeg", "ffmpeg", "-y", + "-f", "rawvideo", "-pix_fmt", "rgba", + "-s", sz, "-r", fps, "-i", "-", + "-c:v", "libx264", "-pix_fmt", "yuv420p", + "-preset", "medium", "-crf", "23", + "-loglevel", "error", + filename, NULL); + fprintf(stderr, "exec ffmpeg failed\n"); + _exit(1); + } + close(rec->pipefd[0]); + return true; +} + +static void WriteFrame(VideoRecorder *rec, int w, int h) { + rlDrawRenderBatchActive(); // flush pending RayLib draws before reading pixels + unsigned char *data = rlReadScreenPixels(w, h); + write(rec->pipefd[1], data, w * h * 4); + RL_FREE(data); +} + +static void CloseVideo(VideoRecorder *rec) { + close(rec->pipefd[1]); + waitpid(rec->pid, NULL, 0); +} + +// ─── Main ───────────────────────────────────────────────────────────────────── +int main(void) { + SetConfigFlags(FLAG_MSAA_4X_HINT | FLAG_VSYNC_HINT); + InitWindow(SCREEN_W, SCREEN_H, "PufferLib Trailer"); + SetTargetFPS(60); + glEnable(GL_PROGRAM_POINT_SIZE); + + Shader star_shader = LoadShader( + TextFormat("resources/trailer/star_%i.vs", GLSL_VERSION), + TextFormat("resources/trailer/star_%i.fs", GLSL_VERSION) + ); + Shader glow_shader = LoadShader( + TextFormat("resources/trailer/glow_%i.vs", GLSL_VERSION), + TextFormat("resources/trailer/glow_%i.fs", GLSL_VERSION) + ); + Texture2D puffernet = LoadTexture("resources/trailer/PufferNet.png"); + + Font roboto = LoadFontEx("resources/shared/Roboto-Regular.ttf", FONT_TITLE, NULL, 0); + SetTextureFilter(roboto.texture, TEXTURE_FILTER_BILINEAR); + + init_bg_stars(); + init_anim1(); + init_anim2(); + init_anim5(); + + VideoRecorder recorder; + int phase = 0; + float phase_time = 0; + bool recording = OpenVideo(&recorder, "trailer/v1.mp4", SCREEN_W, SCREEN_H); + if (!recording) fprintf(stderr, "Warning: video recording disabled\n"); + + while (!WindowShouldClose()) { + float dt = GetFrameTime(); + phase_time += dt; + + if (phase == 0 && phase_time > 10.0f) { + if (recording) CloseVideo(&recorder); + phase = 1; + phase_time = 0; + recording = OpenVideo(&recorder, "trailer/v2.mp4", SCREEN_W, SCREEN_H); + init_bg_stars(); // Reset stars for the second video + } + + if (phase == 1 && phase_time > 42.5f) break; + + BeginDrawing(); + ClearBackground(BG); + + if (phase == 0) { + update_anim1(dt, roboto, &star_shader); + } else { + float t = phase_time; + if (t < 5.0f) { + build_bg_verts(); + draw_stars(bg_verts, bg_draw_count, &star_shader); + } + else if (t < 10.5f) { + build_bg_verts(); + draw_stars(bg_verts, bg_draw_count, &star_shader); + draw_anim3(t - 5.0f, &glow_shader, puffernet, &star_shader, roboto); + } + else if (t < 12.5f) { + update_bg_spiral(dt); + draw_anim4(t - 10.5f, roboto, &star_shader, &glow_shader, puffernet); + } + else if (t < 22.5f) { + draw_anim4(2.0f, roboto, &star_shader, &glow_shader, puffernet); + } + else if (t < 31.5f) { + update_bg_spiral(dt); + draw_anim5(t - 22.5f, dt, &star_shader); + draw_haiku_overlay(t, roboto); + } + else { + update_bg_nova(dt); + build_bg_verts_spiral(1.0f, 1); + draw_stars(bg_verts, bg_draw_count, &star_shader); + draw_haiku_overlay(t, roboto); + } + } + + static int frame_counter = 0; + if (recording && (frame_counter++ % 2 == 0)) + WriteFrame(&recorder, SCREEN_W, SCREEN_H); + EndDrawing(); + } + + if (recording) CloseVideo(&recorder); + unload_anim5(); + UnloadFont(roboto); + UnloadShader(star_shader); + UnloadShader(glow_shader); + UnloadTexture(puffernet); + CloseWindow(); + return 0; +} diff --git a/vendor/KHR/khrplatform.h b/vendor/KHR/khrplatform.h new file mode 100644 index 0000000000..01646449ca --- /dev/null +++ b/vendor/KHR/khrplatform.h @@ -0,0 +1,311 @@ +#ifndef __khrplatform_h_ +#define __khrplatform_h_ + +/* +** Copyright (c) 2008-2018 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be included +** in all copies or substantial portions of the Materials. +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ + +/* Khronos platform-specific types and definitions. + * + * The master copy of khrplatform.h is maintained in the Khronos EGL + * Registry repository at https://github.com/KhronosGroup/EGL-Registry + * The last semantic modification to khrplatform.h was at commit ID: + * 67a3e0864c2d75ea5287b9f3d2eb74a745936692 + * + * Adopters may modify this file to suit their platform. Adopters are + * encouraged to submit platform specific modifications to the Khronos + * group so that they can be included in future versions of this file. + * Please submit changes by filing pull requests or issues on + * the EGL Registry repository linked above. + * + * + * See the Implementer's Guidelines for information about where this file + * should be located on your system and for more details of its use: + * http://www.khronos.org/registry/implementers_guide.pdf + * + * This file should be included as + * #include + * by Khronos client API header files that use its types and defines. + * + * The types in khrplatform.h should only be used to define API-specific types. + * + * Types defined in khrplatform.h: + * khronos_int8_t signed 8 bit + * khronos_uint8_t unsigned 8 bit + * khronos_int16_t signed 16 bit + * khronos_uint16_t unsigned 16 bit + * khronos_int32_t signed 32 bit + * khronos_uint32_t unsigned 32 bit + * khronos_int64_t signed 64 bit + * khronos_uint64_t unsigned 64 bit + * khronos_intptr_t signed same number of bits as a pointer + * khronos_uintptr_t unsigned same number of bits as a pointer + * khronos_ssize_t signed size + * khronos_usize_t unsigned size + * khronos_float_t signed 32 bit floating point + * khronos_time_ns_t unsigned 64 bit time in nanoseconds + * khronos_utime_nanoseconds_t unsigned time interval or absolute time in + * nanoseconds + * khronos_stime_nanoseconds_t signed time interval in nanoseconds + * khronos_boolean_enum_t enumerated boolean type. This should + * only be used as a base type when a client API's boolean type is + * an enum. Client APIs which use an integer or other type for + * booleans cannot use this as the base type for their boolean. + * + * Tokens defined in khrplatform.h: + * + * KHRONOS_FALSE, KHRONOS_TRUE Enumerated boolean false/true values. + * + * KHRONOS_SUPPORT_INT64 is 1 if 64 bit integers are supported; otherwise 0. + * KHRONOS_SUPPORT_FLOAT is 1 if floats are supported; otherwise 0. + * + * Calling convention macros defined in this file: + * KHRONOS_APICALL + * KHRONOS_APIENTRY + * KHRONOS_APIATTRIBUTES + * + * These may be used in function prototypes as: + * + * KHRONOS_APICALL void KHRONOS_APIENTRY funcname( + * int arg1, + * int arg2) KHRONOS_APIATTRIBUTES; + */ + +#if defined(__SCITECH_SNAP__) && !defined(KHRONOS_STATIC) +# define KHRONOS_STATIC 1 +#endif + +/*------------------------------------------------------------------------- + * Definition of KHRONOS_APICALL + *------------------------------------------------------------------------- + * This precedes the return type of the function in the function prototype. + */ +#if defined(KHRONOS_STATIC) + /* If the preprocessor constant KHRONOS_STATIC is defined, make the + * header compatible with static linking. */ +# define KHRONOS_APICALL +#elif defined(_WIN32) +# define KHRONOS_APICALL __declspec(dllimport) +#elif defined (__SYMBIAN32__) +# define KHRONOS_APICALL IMPORT_C +#elif defined(__ANDROID__) +# define KHRONOS_APICALL __attribute__((visibility("default"))) +#else +# define KHRONOS_APICALL +#endif + +/*------------------------------------------------------------------------- + * Definition of KHRONOS_APIENTRY + *------------------------------------------------------------------------- + * This follows the return type of the function and precedes the function + * name in the function prototype. + */ +#if defined(_WIN32) && !defined(_WIN32_WCE) && !defined(__SCITECH_SNAP__) + /* Win32 but not WinCE */ +# define KHRONOS_APIENTRY __stdcall +#else +# define KHRONOS_APIENTRY +#endif + +/*------------------------------------------------------------------------- + * Definition of KHRONOS_APIATTRIBUTES + *------------------------------------------------------------------------- + * This follows the closing parenthesis of the function prototype arguments. + */ +#if defined (__ARMCC_2__) +#define KHRONOS_APIATTRIBUTES __softfp +#else +#define KHRONOS_APIATTRIBUTES +#endif + +/*------------------------------------------------------------------------- + * basic type definitions + *-----------------------------------------------------------------------*/ +#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__GNUC__) || defined(__SCO__) || defined(__USLC__) + + +/* + * Using + */ +#include +typedef int32_t khronos_int32_t; +typedef uint32_t khronos_uint32_t; +typedef int64_t khronos_int64_t; +typedef uint64_t khronos_uint64_t; +#define KHRONOS_SUPPORT_INT64 1 +#define KHRONOS_SUPPORT_FLOAT 1 +/* + * To support platform where unsigned long cannot be used interchangeably with + * inptr_t (e.g. CHERI-extended ISAs), we can use the stdint.h intptr_t. + * Ideally, we could just use (u)intptr_t everywhere, but this could result in + * ABI breakage if khronos_uintptr_t is changed from unsigned long to + * unsigned long long or similar (this results in different C++ name mangling). + * To avoid changes for existing platforms, we restrict usage of intptr_t to + * platforms where the size of a pointer is larger than the size of long. + */ +#if defined(__SIZEOF_LONG__) && defined(__SIZEOF_POINTER__) +#if __SIZEOF_POINTER__ > __SIZEOF_LONG__ +#define KHRONOS_USE_INTPTR_T +#endif +#endif + +#elif defined(__VMS ) || defined(__sgi) + +/* + * Using + */ +#include +typedef int32_t khronos_int32_t; +typedef uint32_t khronos_uint32_t; +typedef int64_t khronos_int64_t; +typedef uint64_t khronos_uint64_t; +#define KHRONOS_SUPPORT_INT64 1 +#define KHRONOS_SUPPORT_FLOAT 1 + +#elif defined(_WIN32) && !defined(__SCITECH_SNAP__) + +/* + * Win32 + */ +typedef __int32 khronos_int32_t; +typedef unsigned __int32 khronos_uint32_t; +typedef __int64 khronos_int64_t; +typedef unsigned __int64 khronos_uint64_t; +#define KHRONOS_SUPPORT_INT64 1 +#define KHRONOS_SUPPORT_FLOAT 1 + +#elif defined(__sun__) || defined(__digital__) + +/* + * Sun or Digital + */ +typedef int khronos_int32_t; +typedef unsigned int khronos_uint32_t; +#if defined(__arch64__) || defined(_LP64) +typedef long int khronos_int64_t; +typedef unsigned long int khronos_uint64_t; +#else +typedef long long int khronos_int64_t; +typedef unsigned long long int khronos_uint64_t; +#endif /* __arch64__ */ +#define KHRONOS_SUPPORT_INT64 1 +#define KHRONOS_SUPPORT_FLOAT 1 + +#elif 0 + +/* + * Hypothetical platform with no float or int64 support + */ +typedef int khronos_int32_t; +typedef unsigned int khronos_uint32_t; +#define KHRONOS_SUPPORT_INT64 0 +#define KHRONOS_SUPPORT_FLOAT 0 + +#else + +/* + * Generic fallback + */ +#include +typedef int32_t khronos_int32_t; +typedef uint32_t khronos_uint32_t; +typedef int64_t khronos_int64_t; +typedef uint64_t khronos_uint64_t; +#define KHRONOS_SUPPORT_INT64 1 +#define KHRONOS_SUPPORT_FLOAT 1 + +#endif + + +/* + * Types that are (so far) the same on all platforms + */ +typedef signed char khronos_int8_t; +typedef unsigned char khronos_uint8_t; +typedef signed short int khronos_int16_t; +typedef unsigned short int khronos_uint16_t; + +/* + * Types that differ between LLP64 and LP64 architectures - in LLP64, + * pointers are 64 bits, but 'long' is still 32 bits. Win64 appears + * to be the only LLP64 architecture in current use. + */ +#ifdef KHRONOS_USE_INTPTR_T +typedef intptr_t khronos_intptr_t; +typedef uintptr_t khronos_uintptr_t; +#elif defined(_WIN64) +typedef signed long long int khronos_intptr_t; +typedef unsigned long long int khronos_uintptr_t; +#else +typedef signed long int khronos_intptr_t; +typedef unsigned long int khronos_uintptr_t; +#endif + +#if defined(_WIN64) +typedef signed long long int khronos_ssize_t; +typedef unsigned long long int khronos_usize_t; +#else +typedef signed long int khronos_ssize_t; +typedef unsigned long int khronos_usize_t; +#endif + +#if KHRONOS_SUPPORT_FLOAT +/* + * Float type + */ +typedef float khronos_float_t; +#endif + +#if KHRONOS_SUPPORT_INT64 +/* Time types + * + * These types can be used to represent a time interval in nanoseconds or + * an absolute Unadjusted System Time. Unadjusted System Time is the number + * of nanoseconds since some arbitrary system event (e.g. since the last + * time the system booted). The Unadjusted System Time is an unsigned + * 64 bit value that wraps back to 0 every 584 years. Time intervals + * may be either signed or unsigned. + */ +typedef khronos_uint64_t khronos_utime_nanoseconds_t; +typedef khronos_int64_t khronos_stime_nanoseconds_t; +#endif + +/* + * Dummy value used to pad enum types to 32 bits. + */ +#ifndef KHRONOS_MAX_ENUM +#define KHRONOS_MAX_ENUM 0x7FFFFFFF +#endif + +/* + * Enumerated boolean type + * + * Values other than zero should be considered to be true. Therefore + * comparisons should not be made against KHRONOS_TRUE. + */ +typedef enum { + KHRONOS_FALSE = 0, + KHRONOS_TRUE = 1, + KHRONOS_BOOLEAN_ENUM_FORCE_SIZE = KHRONOS_MAX_ENUM +} khronos_boolean_enum_t; + +#endif /* __khrplatform_h_ */ diff --git a/vendor/cJSON.c b/vendor/cJSON.c new file mode 100644 index 0000000000..6e4fb0dd36 --- /dev/null +++ b/vendor/cJSON.c @@ -0,0 +1,3191 @@ +/* + Copyright (c) 2009-2017 Dave Gamble and cJSON contributors + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +/* cJSON */ +/* JSON parser in C. */ + +/* disable warnings about old C89 functions in MSVC */ +#if !defined(_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER) +#define _CRT_SECURE_NO_DEPRECATE +#endif + +#ifdef __GNUC__ +#pragma GCC visibility push(default) +#endif +#if defined(_MSC_VER) +#pragma warning (push) +/* disable warning about single line comments in system headers */ +#pragma warning (disable : 4001) +#endif + +#include +#include +#include +#include +#include +#include +#include + +#ifdef ENABLE_LOCALES +#include +#endif + +#if defined(_MSC_VER) +#pragma warning (pop) +#endif +#ifdef __GNUC__ +#pragma GCC visibility pop +#endif + +#include "cJSON.h" + +/* define our own boolean type */ +#ifdef true +#undef true +#endif +#define true ((cJSON_bool)1) + +#ifdef false +#undef false +#endif +#define false ((cJSON_bool)0) + +/* define isnan and isinf for ANSI C, if in C99 or above, isnan and isinf has been defined in math.h */ +#ifndef isinf +#define isinf(d) (isnan((d - d)) && !isnan(d)) +#endif +#ifndef isnan +#define isnan(d) (d != d) +#endif + +#ifndef NAN +#ifdef _WIN32 +#define NAN sqrt(-1.0) +#else +#define NAN 0.0/0.0 +#endif +#endif + +typedef struct { + const unsigned char *json; + size_t position; +} error; +static error global_error = { NULL, 0 }; + +CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void) +{ + return (const char*) (global_error.json + global_error.position); +} + +CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item) +{ + if (!cJSON_IsString(item)) + { + return NULL; + } + + return item->valuestring; +} + +CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON * const item) +{ + if (!cJSON_IsNumber(item)) + { + return (double) NAN; + } + + return item->valuedouble; +} + +/* This is a safeguard to prevent copy-pasters from using incompatible C and header files */ +#if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 7) || (CJSON_VERSION_PATCH != 19) + #error cJSON.h and cJSON.c have different versions. Make sure that both have the same. +#endif + +CJSON_PUBLIC(const char*) cJSON_Version(void) +{ + static char version[15]; + sprintf(version, "%i.%i.%i", CJSON_VERSION_MAJOR, CJSON_VERSION_MINOR, CJSON_VERSION_PATCH); + + return version; +} + +/* Case insensitive string comparison, doesn't consider two NULL pointers equal though */ +static int case_insensitive_strcmp(const unsigned char *string1, const unsigned char *string2) +{ + if ((string1 == NULL) || (string2 == NULL)) + { + return 1; + } + + if (string1 == string2) + { + return 0; + } + + for(; tolower(*string1) == tolower(*string2); (void)string1++, string2++) + { + if (*string1 == '\0') + { + return 0; + } + } + + return tolower(*string1) - tolower(*string2); +} + +typedef struct internal_hooks +{ + void *(CJSON_CDECL *allocate)(size_t size); + void (CJSON_CDECL *deallocate)(void *pointer); + void *(CJSON_CDECL *reallocate)(void *pointer, size_t size); +} internal_hooks; + +#if defined(_MSC_VER) +/* work around MSVC error C2322: '...' address of dllimport '...' is not static */ +static void * CJSON_CDECL internal_malloc(size_t size) +{ + return malloc(size); +} +static void CJSON_CDECL internal_free(void *pointer) +{ + free(pointer); +} +static void * CJSON_CDECL internal_realloc(void *pointer, size_t size) +{ + return realloc(pointer, size); +} +#else +#define internal_malloc malloc +#define internal_free free +#define internal_realloc realloc +#endif + +/* strlen of character literals resolved at compile time */ +#define static_strlen(string_literal) (sizeof(string_literal) - sizeof("")) + +static internal_hooks global_hooks = { internal_malloc, internal_free, internal_realloc }; + +static unsigned char* cJSON_strdup(const unsigned char* string, const internal_hooks * const hooks) +{ + size_t length = 0; + unsigned char *copy = NULL; + + if (string == NULL) + { + return NULL; + } + + length = strlen((const char*)string) + sizeof(""); + copy = (unsigned char*)hooks->allocate(length); + if (copy == NULL) + { + return NULL; + } + memcpy(copy, string, length); + + return copy; +} + +CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks) +{ + if (hooks == NULL) + { + /* Reset hooks */ + global_hooks.allocate = malloc; + global_hooks.deallocate = free; + global_hooks.reallocate = realloc; + return; + } + + global_hooks.allocate = malloc; + if (hooks->malloc_fn != NULL) + { + global_hooks.allocate = hooks->malloc_fn; + } + + global_hooks.deallocate = free; + if (hooks->free_fn != NULL) + { + global_hooks.deallocate = hooks->free_fn; + } + + /* use realloc only if both free and malloc are used */ + global_hooks.reallocate = NULL; + if ((global_hooks.allocate == malloc) && (global_hooks.deallocate == free)) + { + global_hooks.reallocate = realloc; + } +} + +/* Internal constructor. */ +static cJSON *cJSON_New_Item(const internal_hooks * const hooks) +{ + cJSON* node = (cJSON*)hooks->allocate(sizeof(cJSON)); + if (node) + { + memset(node, '\0', sizeof(cJSON)); + } + + return node; +} + +/* Delete a cJSON structure. */ +CJSON_PUBLIC(void) cJSON_Delete(cJSON *item) +{ + cJSON *next = NULL; + while (item != NULL) + { + next = item->next; + if (!(item->type & cJSON_IsReference) && (item->child != NULL)) + { + cJSON_Delete(item->child); + } + if (!(item->type & cJSON_IsReference) && (item->valuestring != NULL)) + { + global_hooks.deallocate(item->valuestring); + item->valuestring = NULL; + } + if (!(item->type & cJSON_StringIsConst) && (item->string != NULL)) + { + global_hooks.deallocate(item->string); + item->string = NULL; + } + global_hooks.deallocate(item); + item = next; + } +} + +/* get the decimal point character of the current locale */ +static unsigned char get_decimal_point(void) +{ +#ifdef ENABLE_LOCALES + struct lconv *lconv = localeconv(); + return (unsigned char) lconv->decimal_point[0]; +#else + return '.'; +#endif +} + +typedef struct +{ + const unsigned char *content; + size_t length; + size_t offset; + size_t depth; /* How deeply nested (in arrays/objects) is the input at the current offset. */ + internal_hooks hooks; +} parse_buffer; + +/* check if the given size is left to read in a given parse buffer (starting with 1) */ +#define can_read(buffer, size) ((buffer != NULL) && (((buffer)->offset + size) <= (buffer)->length)) +/* check if the buffer can be accessed at the given index (starting with 0) */ +#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length)) +#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index)) +/* get a pointer to the buffer at the position */ +#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset) + +/* Parse the input text to generate a number, and populate the result into item. */ +static cJSON_bool parse_number(cJSON * const item, parse_buffer * const input_buffer) +{ + double number = 0; + unsigned char *after_end = NULL; + unsigned char *number_c_string; + unsigned char decimal_point = get_decimal_point(); + size_t i = 0; + size_t number_string_length = 0; + cJSON_bool has_decimal_point = false; + + if ((input_buffer == NULL) || (input_buffer->content == NULL)) + { + return false; + } + + /* copy the number into a temporary buffer and replace '.' with the decimal point + * of the current locale (for strtod) + * This also takes care of '\0' not necessarily being available for marking the end of the input */ + for (i = 0; can_access_at_index(input_buffer, i); i++) + { + switch (buffer_at_offset(input_buffer)[i]) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case '+': + case '-': + case 'e': + case 'E': + number_string_length++; + break; + + case '.': + number_string_length++; + has_decimal_point = true; + break; + + default: + goto loop_end; + } + } +loop_end: + /* malloc for temporary buffer, add 1 for '\0' */ + number_c_string = (unsigned char *) input_buffer->hooks.allocate(number_string_length + 1); + if (number_c_string == NULL) + { + return false; /* allocation failure */ + } + + memcpy(number_c_string, buffer_at_offset(input_buffer), number_string_length); + number_c_string[number_string_length] = '\0'; + + if (has_decimal_point) + { + for (i = 0; i < number_string_length; i++) + { + if (number_c_string[i] == '.') + { + /* replace '.' with the decimal point of the current locale (for strtod) */ + number_c_string[i] = decimal_point; + } + } + } + + number = strtod((const char*)number_c_string, (char**)&after_end); + if (number_c_string == after_end) + { + /* free the temporary buffer */ + input_buffer->hooks.deallocate(number_c_string); + return false; /* parse_error */ + } + + item->valuedouble = number; + + /* use saturation in case of overflow */ + if (number >= INT_MAX) + { + item->valueint = INT_MAX; + } + else if (number <= (double)INT_MIN) + { + item->valueint = INT_MIN; + } + else + { + item->valueint = (int)number; + } + + item->type = cJSON_Number; + + input_buffer->offset += (size_t)(after_end - number_c_string); + /* free the temporary buffer */ + input_buffer->hooks.deallocate(number_c_string); + return true; +} + +/* don't ask me, but the original cJSON_SetNumberValue returns an integer or double */ +CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number) +{ + if (number >= INT_MAX) + { + object->valueint = INT_MAX; + } + else if (number <= (double)INT_MIN) + { + object->valueint = INT_MIN; + } + else + { + object->valueint = (int)number; + } + + return object->valuedouble = number; +} + +/* Note: when passing a NULL valuestring, cJSON_SetValuestring treats this as an error and return NULL */ +CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring) +{ + char *copy = NULL; + size_t v1_len; + size_t v2_len; + /* if object's type is not cJSON_String or is cJSON_IsReference, it should not set valuestring */ + if ((object == NULL) || !(object->type & cJSON_String) || (object->type & cJSON_IsReference)) + { + return NULL; + } + /* return NULL if the object is corrupted or valuestring is NULL */ + if (object->valuestring == NULL || valuestring == NULL) + { + return NULL; + } + + v1_len = strlen(valuestring); + v2_len = strlen(object->valuestring); + + if (v1_len <= v2_len) + { + /* strcpy does not handle overlapping string: [X1, X2] [Y1, Y2] => X2 < Y1 or Y2 < X1 */ + if (!( valuestring + v1_len < object->valuestring || object->valuestring + v2_len < valuestring )) + { + return NULL; + } + strcpy(object->valuestring, valuestring); + return object->valuestring; + } + copy = (char*) cJSON_strdup((const unsigned char*)valuestring, &global_hooks); + if (copy == NULL) + { + return NULL; + } + if (object->valuestring != NULL) + { + cJSON_free(object->valuestring); + } + object->valuestring = copy; + + return copy; +} + +typedef struct +{ + unsigned char *buffer; + size_t length; + size_t offset; + size_t depth; /* current nesting depth (for formatted printing) */ + cJSON_bool noalloc; + cJSON_bool format; /* is this print a formatted print */ + internal_hooks hooks; +} printbuffer; + +/* realloc printbuffer if necessary to have at least "needed" bytes more */ +static unsigned char* ensure(printbuffer * const p, size_t needed) +{ + unsigned char *newbuffer = NULL; + size_t newsize = 0; + + if ((p == NULL) || (p->buffer == NULL)) + { + return NULL; + } + + if ((p->length > 0) && (p->offset >= p->length)) + { + /* make sure that offset is valid */ + return NULL; + } + + if (needed > INT_MAX) + { + /* sizes bigger than INT_MAX are currently not supported */ + return NULL; + } + + needed += p->offset + 1; + if (needed <= p->length) + { + return p->buffer + p->offset; + } + + if (p->noalloc) { + return NULL; + } + + /* calculate new buffer size */ + if (needed > (INT_MAX / 2)) + { + /* overflow of int, use INT_MAX if possible */ + if (needed <= INT_MAX) + { + newsize = INT_MAX; + } + else + { + return NULL; + } + } + else + { + newsize = needed * 2; + } + + if (p->hooks.reallocate != NULL) + { + /* reallocate with realloc if available */ + newbuffer = (unsigned char*)p->hooks.reallocate(p->buffer, newsize); + if (newbuffer == NULL) + { + p->hooks.deallocate(p->buffer); + p->length = 0; + p->buffer = NULL; + + return NULL; + } + } + else + { + /* otherwise reallocate manually */ + newbuffer = (unsigned char*)p->hooks.allocate(newsize); + if (!newbuffer) + { + p->hooks.deallocate(p->buffer); + p->length = 0; + p->buffer = NULL; + + return NULL; + } + + memcpy(newbuffer, p->buffer, p->offset + 1); + p->hooks.deallocate(p->buffer); + } + p->length = newsize; + p->buffer = newbuffer; + + return newbuffer + p->offset; +} + +/* calculate the new length of the string in a printbuffer and update the offset */ +static void update_offset(printbuffer * const buffer) +{ + const unsigned char *buffer_pointer = NULL; + if ((buffer == NULL) || (buffer->buffer == NULL)) + { + return; + } + buffer_pointer = buffer->buffer + buffer->offset; + + buffer->offset += strlen((const char*)buffer_pointer); +} + +/* securely comparison of floating-point variables */ +static cJSON_bool compare_double(double a, double b) +{ + double maxVal = fabs(a) > fabs(b) ? fabs(a) : fabs(b); + return (fabs(a - b) <= maxVal * DBL_EPSILON); +} + +/* Render the number nicely from the given item into a string. */ +static cJSON_bool print_number(const cJSON * const item, printbuffer * const output_buffer) +{ + unsigned char *output_pointer = NULL; + double d = item->valuedouble; + int length = 0; + size_t i = 0; + unsigned char number_buffer[26] = {0}; /* temporary buffer to print the number into */ + unsigned char decimal_point = get_decimal_point(); + double test = 0.0; + + if (output_buffer == NULL) + { + return false; + } + + /* This checks for NaN and Infinity */ + if (isnan(d) || isinf(d)) + { + length = sprintf((char*)number_buffer, "null"); + } + else if(d == (double)item->valueint) + { + length = sprintf((char*)number_buffer, "%d", item->valueint); + } + else + { + /* Try 15 decimal places of precision to avoid nonsignificant nonzero digits */ + length = sprintf((char*)number_buffer, "%1.15g", d); + + /* Check whether the original double can be recovered */ + if ((sscanf((char*)number_buffer, "%lg", &test) != 1) || !compare_double((double)test, d)) + { + /* If not, print with 17 decimal places of precision */ + length = sprintf((char*)number_buffer, "%1.17g", d); + } + } + + /* sprintf failed or buffer overrun occurred */ + if ((length < 0) || (length > (int)(sizeof(number_buffer) - 1))) + { + return false; + } + + /* reserve appropriate space in the output */ + output_pointer = ensure(output_buffer, (size_t)length + sizeof("")); + if (output_pointer == NULL) + { + return false; + } + + /* copy the printed number to the output and replace locale + * dependent decimal point with '.' */ + for (i = 0; i < ((size_t)length); i++) + { + if (number_buffer[i] == decimal_point) + { + output_pointer[i] = '.'; + continue; + } + + output_pointer[i] = number_buffer[i]; + } + output_pointer[i] = '\0'; + + output_buffer->offset += (size_t)length; + + return true; +} + +/* parse 4 digit hexadecimal number */ +static unsigned parse_hex4(const unsigned char * const input) +{ + unsigned int h = 0; + size_t i = 0; + + for (i = 0; i < 4; i++) + { + /* parse digit */ + if ((input[i] >= '0') && (input[i] <= '9')) + { + h += (unsigned int) input[i] - '0'; + } + else if ((input[i] >= 'A') && (input[i] <= 'F')) + { + h += (unsigned int) 10 + input[i] - 'A'; + } + else if ((input[i] >= 'a') && (input[i] <= 'f')) + { + h += (unsigned int) 10 + input[i] - 'a'; + } + else /* invalid */ + { + return 0; + } + + if (i < 3) + { + /* shift left to make place for the next nibble */ + h = h << 4; + } + } + + return h; +} + +/* converts a UTF-16 literal to UTF-8 + * A literal can be one or two sequences of the form \uXXXX */ +static unsigned char utf16_literal_to_utf8(const unsigned char * const input_pointer, const unsigned char * const input_end, unsigned char **output_pointer) +{ + long unsigned int codepoint = 0; + unsigned int first_code = 0; + const unsigned char *first_sequence = input_pointer; + unsigned char utf8_length = 0; + unsigned char utf8_position = 0; + unsigned char sequence_length = 0; + unsigned char first_byte_mark = 0; + + if ((input_end - first_sequence) < 6) + { + /* input ends unexpectedly */ + goto fail; + } + + /* get the first utf16 sequence */ + first_code = parse_hex4(first_sequence + 2); + + /* check that the code is valid */ + if (((first_code >= 0xDC00) && (first_code <= 0xDFFF))) + { + goto fail; + } + + /* UTF16 surrogate pair */ + if ((first_code >= 0xD800) && (first_code <= 0xDBFF)) + { + const unsigned char *second_sequence = first_sequence + 6; + unsigned int second_code = 0; + sequence_length = 12; /* \uXXXX\uXXXX */ + + if ((input_end - second_sequence) < 6) + { + /* input ends unexpectedly */ + goto fail; + } + + if ((second_sequence[0] != '\\') || (second_sequence[1] != 'u')) + { + /* missing second half of the surrogate pair */ + goto fail; + } + + /* get the second utf16 sequence */ + second_code = parse_hex4(second_sequence + 2); + /* check that the code is valid */ + if ((second_code < 0xDC00) || (second_code > 0xDFFF)) + { + /* invalid second half of the surrogate pair */ + goto fail; + } + + + /* calculate the unicode codepoint from the surrogate pair */ + codepoint = 0x10000 + (((first_code & 0x3FF) << 10) | (second_code & 0x3FF)); + } + else + { + sequence_length = 6; /* \uXXXX */ + codepoint = first_code; + } + + /* encode as UTF-8 + * takes at maximum 4 bytes to encode: + * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */ + if (codepoint < 0x80) + { + /* normal ascii, encoding 0xxxxxxx */ + utf8_length = 1; + } + else if (codepoint < 0x800) + { + /* two bytes, encoding 110xxxxx 10xxxxxx */ + utf8_length = 2; + first_byte_mark = 0xC0; /* 11000000 */ + } + else if (codepoint < 0x10000) + { + /* three bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx */ + utf8_length = 3; + first_byte_mark = 0xE0; /* 11100000 */ + } + else if (codepoint <= 0x10FFFF) + { + /* four bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx 10xxxxxx */ + utf8_length = 4; + first_byte_mark = 0xF0; /* 11110000 */ + } + else + { + /* invalid unicode codepoint */ + goto fail; + } + + /* encode as utf8 */ + for (utf8_position = (unsigned char)(utf8_length - 1); utf8_position > 0; utf8_position--) + { + /* 10xxxxxx */ + (*output_pointer)[utf8_position] = (unsigned char)((codepoint | 0x80) & 0xBF); + codepoint >>= 6; + } + /* encode first byte */ + if (utf8_length > 1) + { + (*output_pointer)[0] = (unsigned char)((codepoint | first_byte_mark) & 0xFF); + } + else + { + (*output_pointer)[0] = (unsigned char)(codepoint & 0x7F); + } + + *output_pointer += utf8_length; + + return sequence_length; + +fail: + return 0; +} + +/* Parse the input text into an unescaped cinput, and populate item. */ +static cJSON_bool parse_string(cJSON * const item, parse_buffer * const input_buffer) +{ + const unsigned char *input_pointer = buffer_at_offset(input_buffer) + 1; + const unsigned char *input_end = buffer_at_offset(input_buffer) + 1; + unsigned char *output_pointer = NULL; + unsigned char *output = NULL; + + /* not a string */ + if (buffer_at_offset(input_buffer)[0] != '\"') + { + goto fail; + } + + { + /* calculate approximate size of the output (overestimate) */ + size_t allocation_length = 0; + size_t skipped_bytes = 0; + while (((size_t)(input_end - input_buffer->content) < input_buffer->length) && (*input_end != '\"')) + { + /* is escape sequence */ + if (input_end[0] == '\\') + { + if ((size_t)(input_end + 1 - input_buffer->content) >= input_buffer->length) + { + /* prevent buffer overflow when last input character is a backslash */ + goto fail; + } + skipped_bytes++; + input_end++; + } + input_end++; + } + if (((size_t)(input_end - input_buffer->content) >= input_buffer->length) || (*input_end != '\"')) + { + goto fail; /* string ended unexpectedly */ + } + + /* This is at most how much we need for the output */ + allocation_length = (size_t) (input_end - buffer_at_offset(input_buffer)) - skipped_bytes; + output = (unsigned char*)input_buffer->hooks.allocate(allocation_length + sizeof("")); + if (output == NULL) + { + goto fail; /* allocation failure */ + } + } + + output_pointer = output; + /* loop through the string literal */ + while (input_pointer < input_end) + { + if (*input_pointer != '\\') + { + *output_pointer++ = *input_pointer++; + } + /* escape sequence */ + else + { + unsigned char sequence_length = 2; + if ((input_end - input_pointer) < 1) + { + goto fail; + } + + switch (input_pointer[1]) + { + case 'b': + *output_pointer++ = '\b'; + break; + case 'f': + *output_pointer++ = '\f'; + break; + case 'n': + *output_pointer++ = '\n'; + break; + case 'r': + *output_pointer++ = '\r'; + break; + case 't': + *output_pointer++ = '\t'; + break; + case '\"': + case '\\': + case '/': + *output_pointer++ = input_pointer[1]; + break; + + /* UTF-16 literal */ + case 'u': + sequence_length = utf16_literal_to_utf8(input_pointer, input_end, &output_pointer); + if (sequence_length == 0) + { + /* failed to convert UTF16-literal to UTF-8 */ + goto fail; + } + break; + + default: + goto fail; + } + input_pointer += sequence_length; + } + } + + /* zero terminate the output */ + *output_pointer = '\0'; + + item->type = cJSON_String; + item->valuestring = (char*)output; + + input_buffer->offset = (size_t) (input_end - input_buffer->content); + input_buffer->offset++; + + return true; + +fail: + if (output != NULL) + { + input_buffer->hooks.deallocate(output); + output = NULL; + } + + if (input_pointer != NULL) + { + input_buffer->offset = (size_t)(input_pointer - input_buffer->content); + } + + return false; +} + +/* Render the cstring provided to an escaped version that can be printed. */ +static cJSON_bool print_string_ptr(const unsigned char * const input, printbuffer * const output_buffer) +{ + const unsigned char *input_pointer = NULL; + unsigned char *output = NULL; + unsigned char *output_pointer = NULL; + size_t output_length = 0; + /* numbers of additional characters needed for escaping */ + size_t escape_characters = 0; + + if (output_buffer == NULL) + { + return false; + } + + /* empty string */ + if (input == NULL) + { + output = ensure(output_buffer, sizeof("\"\"")); + if (output == NULL) + { + return false; + } + strcpy((char*)output, "\"\""); + + return true; + } + + /* set "flag" to 1 if something needs to be escaped */ + for (input_pointer = input; *input_pointer; input_pointer++) + { + switch (*input_pointer) + { + case '\"': + case '\\': + case '\b': + case '\f': + case '\n': + case '\r': + case '\t': + /* one character escape sequence */ + escape_characters++; + break; + default: + if (*input_pointer < 32) + { + /* UTF-16 escape sequence uXXXX */ + escape_characters += 5; + } + break; + } + } + output_length = (size_t)(input_pointer - input) + escape_characters; + + output = ensure(output_buffer, output_length + sizeof("\"\"")); + if (output == NULL) + { + return false; + } + + /* no characters have to be escaped */ + if (escape_characters == 0) + { + output[0] = '\"'; + memcpy(output + 1, input, output_length); + output[output_length + 1] = '\"'; + output[output_length + 2] = '\0'; + + return true; + } + + output[0] = '\"'; + output_pointer = output + 1; + /* copy the string */ + for (input_pointer = input; *input_pointer != '\0'; (void)input_pointer++, output_pointer++) + { + if ((*input_pointer > 31) && (*input_pointer != '\"') && (*input_pointer != '\\')) + { + /* normal character, copy */ + *output_pointer = *input_pointer; + } + else + { + /* character needs to be escaped */ + *output_pointer++ = '\\'; + switch (*input_pointer) + { + case '\\': + *output_pointer = '\\'; + break; + case '\"': + *output_pointer = '\"'; + break; + case '\b': + *output_pointer = 'b'; + break; + case '\f': + *output_pointer = 'f'; + break; + case '\n': + *output_pointer = 'n'; + break; + case '\r': + *output_pointer = 'r'; + break; + case '\t': + *output_pointer = 't'; + break; + default: + /* escape and print as unicode codepoint */ + sprintf((char*)output_pointer, "u%04x", *input_pointer); + output_pointer += 4; + break; + } + } + } + output[output_length + 1] = '\"'; + output[output_length + 2] = '\0'; + + return true; +} + +/* Invoke print_string_ptr (which is useful) on an item. */ +static cJSON_bool print_string(const cJSON * const item, printbuffer * const p) +{ + return print_string_ptr((unsigned char*)item->valuestring, p); +} + +/* Predeclare these prototypes. */ +static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer); +static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer); +static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer); +static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer); +static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer); +static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer); + +/* Utility to jump whitespace and cr/lf */ +static parse_buffer *buffer_skip_whitespace(parse_buffer * const buffer) +{ + if ((buffer == NULL) || (buffer->content == NULL)) + { + return NULL; + } + + if (cannot_access_at_index(buffer, 0)) + { + return buffer; + } + + while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32)) + { + buffer->offset++; + } + + if (buffer->offset == buffer->length) + { + buffer->offset--; + } + + return buffer; +} + +/* skip the UTF-8 BOM (byte order mark) if it is at the beginning of a buffer */ +static parse_buffer *skip_utf8_bom(parse_buffer * const buffer) +{ + if ((buffer == NULL) || (buffer->content == NULL) || (buffer->offset != 0)) + { + return NULL; + } + + if (can_access_at_index(buffer, 4) && (strncmp((const char*)buffer_at_offset(buffer), "\xEF\xBB\xBF", 3) == 0)) + { + buffer->offset += 3; + } + + return buffer; +} + +CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated) +{ + size_t buffer_length; + + if (NULL == value) + { + return NULL; + } + + /* Adding null character size due to require_null_terminated. */ + buffer_length = strlen(value) + sizeof(""); + + return cJSON_ParseWithLengthOpts(value, buffer_length, return_parse_end, require_null_terminated); +} + +/* Parse an object - create a new root, and populate. */ +CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, cJSON_bool require_null_terminated) +{ + parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } }; + cJSON *item = NULL; + + /* reset error position */ + global_error.json = NULL; + global_error.position = 0; + + if (value == NULL || 0 == buffer_length) + { + goto fail; + } + + buffer.content = (const unsigned char*)value; + buffer.length = buffer_length; + buffer.offset = 0; + buffer.hooks = global_hooks; + + item = cJSON_New_Item(&global_hooks); + if (item == NULL) /* memory fail */ + { + goto fail; + } + + if (!parse_value(item, buffer_skip_whitespace(skip_utf8_bom(&buffer)))) + { + /* parse failure. ep is set. */ + goto fail; + } + + /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */ + if (require_null_terminated) + { + buffer_skip_whitespace(&buffer); + if ((buffer.offset >= buffer.length) || buffer_at_offset(&buffer)[0] != '\0') + { + goto fail; + } + } + if (return_parse_end) + { + *return_parse_end = (const char*)buffer_at_offset(&buffer); + } + + return item; + +fail: + if (item != NULL) + { + cJSON_Delete(item); + } + + if (value != NULL) + { + error local_error; + local_error.json = (const unsigned char*)value; + local_error.position = 0; + + if (buffer.offset < buffer.length) + { + local_error.position = buffer.offset; + } + else if (buffer.length > 0) + { + local_error.position = buffer.length - 1; + } + + if (return_parse_end != NULL) + { + *return_parse_end = (const char*)local_error.json + local_error.position; + } + + global_error = local_error; + } + + return NULL; +} + +/* Default options for cJSON_Parse */ +CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value) +{ + return cJSON_ParseWithOpts(value, 0, 0); +} + +CJSON_PUBLIC(cJSON *) cJSON_ParseWithLength(const char *value, size_t buffer_length) +{ + return cJSON_ParseWithLengthOpts(value, buffer_length, 0, 0); +} + +#define cjson_min(a, b) (((a) < (b)) ? (a) : (b)) + +static unsigned char *print(const cJSON * const item, cJSON_bool format, const internal_hooks * const hooks) +{ + static const size_t default_buffer_size = 256; + printbuffer buffer[1]; + unsigned char *printed = NULL; + + memset(buffer, 0, sizeof(buffer)); + + /* create buffer */ + buffer->buffer = (unsigned char*) hooks->allocate(default_buffer_size); + buffer->length = default_buffer_size; + buffer->format = format; + buffer->hooks = *hooks; + if (buffer->buffer == NULL) + { + goto fail; + } + + /* print the value */ + if (!print_value(item, buffer)) + { + goto fail; + } + update_offset(buffer); + + /* check if reallocate is available */ + if (hooks->reallocate != NULL) + { + printed = (unsigned char*) hooks->reallocate(buffer->buffer, buffer->offset + 1); + if (printed == NULL) { + goto fail; + } + buffer->buffer = NULL; + } + else /* otherwise copy the JSON over to a new buffer */ + { + printed = (unsigned char*) hooks->allocate(buffer->offset + 1); + if (printed == NULL) + { + goto fail; + } + memcpy(printed, buffer->buffer, cjson_min(buffer->length, buffer->offset + 1)); + printed[buffer->offset] = '\0'; /* just to be sure */ + + /* free the buffer */ + hooks->deallocate(buffer->buffer); + buffer->buffer = NULL; + } + + return printed; + +fail: + if (buffer->buffer != NULL) + { + hooks->deallocate(buffer->buffer); + buffer->buffer = NULL; + } + + if (printed != NULL) + { + hooks->deallocate(printed); + printed = NULL; + } + + return NULL; +} + +/* Render a cJSON item/entity/structure to text. */ +CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item) +{ + return (char*)print(item, true, &global_hooks); +} + +CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item) +{ + return (char*)print(item, false, &global_hooks); +} + +CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt) +{ + printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } }; + + if (prebuffer < 0) + { + return NULL; + } + + p.buffer = (unsigned char*)global_hooks.allocate((size_t)prebuffer); + if (!p.buffer) + { + return NULL; + } + + p.length = (size_t)prebuffer; + p.offset = 0; + p.noalloc = false; + p.format = fmt; + p.hooks = global_hooks; + + if (!print_value(item, &p)) + { + global_hooks.deallocate(p.buffer); + p.buffer = NULL; + return NULL; + } + + return (char*)p.buffer; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format) +{ + printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } }; + + if ((length < 0) || (buffer == NULL)) + { + return false; + } + + p.buffer = (unsigned char*)buffer; + p.length = (size_t)length; + p.offset = 0; + p.noalloc = true; + p.format = format; + p.hooks = global_hooks; + + return print_value(item, &p); +} + +/* Parser core - when encountering text, process appropriately. */ +static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer) +{ + if ((input_buffer == NULL) || (input_buffer->content == NULL)) + { + return false; /* no input */ + } + + /* parse the different types of values */ + /* null */ + if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "null", 4) == 0)) + { + item->type = cJSON_NULL; + input_buffer->offset += 4; + return true; + } + /* false */ + if (can_read(input_buffer, 5) && (strncmp((const char*)buffer_at_offset(input_buffer), "false", 5) == 0)) + { + item->type = cJSON_False; + input_buffer->offset += 5; + return true; + } + /* true */ + if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "true", 4) == 0)) + { + item->type = cJSON_True; + item->valueint = 1; + input_buffer->offset += 4; + return true; + } + /* string */ + if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '\"')) + { + return parse_string(item, input_buffer); + } + /* number */ + if (can_access_at_index(input_buffer, 0) && ((buffer_at_offset(input_buffer)[0] == '-') || ((buffer_at_offset(input_buffer)[0] >= '0') && (buffer_at_offset(input_buffer)[0] <= '9')))) + { + return parse_number(item, input_buffer); + } + /* array */ + if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '[')) + { + return parse_array(item, input_buffer); + } + /* object */ + if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '{')) + { + return parse_object(item, input_buffer); + } + + return false; +} + +/* Render a value to text. */ +static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer) +{ + unsigned char *output = NULL; + + if ((item == NULL) || (output_buffer == NULL)) + { + return false; + } + + switch ((item->type) & 0xFF) + { + case cJSON_NULL: + output = ensure(output_buffer, 5); + if (output == NULL) + { + return false; + } + strcpy((char*)output, "null"); + return true; + + case cJSON_False: + output = ensure(output_buffer, 6); + if (output == NULL) + { + return false; + } + strcpy((char*)output, "false"); + return true; + + case cJSON_True: + output = ensure(output_buffer, 5); + if (output == NULL) + { + return false; + } + strcpy((char*)output, "true"); + return true; + + case cJSON_Number: + return print_number(item, output_buffer); + + case cJSON_Raw: + { + size_t raw_length = 0; + if (item->valuestring == NULL) + { + return false; + } + + raw_length = strlen(item->valuestring) + sizeof(""); + output = ensure(output_buffer, raw_length); + if (output == NULL) + { + return false; + } + memcpy(output, item->valuestring, raw_length); + return true; + } + + case cJSON_String: + return print_string(item, output_buffer); + + case cJSON_Array: + return print_array(item, output_buffer); + + case cJSON_Object: + return print_object(item, output_buffer); + + default: + return false; + } +} + +/* Build an array from input text. */ +static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer) +{ + cJSON *head = NULL; /* head of the linked list */ + cJSON *current_item = NULL; + + if (input_buffer->depth >= CJSON_NESTING_LIMIT) + { + return false; /* to deeply nested */ + } + input_buffer->depth++; + + if (buffer_at_offset(input_buffer)[0] != '[') + { + /* not an array */ + goto fail; + } + + input_buffer->offset++; + buffer_skip_whitespace(input_buffer); + if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ']')) + { + /* empty array */ + goto success; + } + + /* check if we skipped to the end of the buffer */ + if (cannot_access_at_index(input_buffer, 0)) + { + input_buffer->offset--; + goto fail; + } + + /* step back to character in front of the first element */ + input_buffer->offset--; + /* loop through the comma separated array elements */ + do + { + /* allocate next item */ + cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks)); + if (new_item == NULL) + { + goto fail; /* allocation failure */ + } + + /* attach next item to list */ + if (head == NULL) + { + /* start the linked list */ + current_item = head = new_item; + } + else + { + /* add to the end and advance */ + current_item->next = new_item; + new_item->prev = current_item; + current_item = new_item; + } + + /* parse next value */ + input_buffer->offset++; + buffer_skip_whitespace(input_buffer); + if (!parse_value(current_item, input_buffer)) + { + goto fail; /* failed to parse value */ + } + buffer_skip_whitespace(input_buffer); + } + while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ',')); + + if (cannot_access_at_index(input_buffer, 0) || buffer_at_offset(input_buffer)[0] != ']') + { + goto fail; /* expected end of array */ + } + +success: + input_buffer->depth--; + + if (head != NULL) { + head->prev = current_item; + } + + item->type = cJSON_Array; + item->child = head; + + input_buffer->offset++; + + return true; + +fail: + if (head != NULL) + { + cJSON_Delete(head); + } + + return false; +} + +/* Render an array to text */ +static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer) +{ + unsigned char *output_pointer = NULL; + size_t length = 0; + cJSON *current_element = item->child; + + if (output_buffer == NULL) + { + return false; + } + + /* Compose the output array. */ + /* opening square bracket */ + output_pointer = ensure(output_buffer, 1); + if (output_pointer == NULL) + { + return false; + } + + *output_pointer = '['; + output_buffer->offset++; + output_buffer->depth++; + + while (current_element != NULL) + { + if (!print_value(current_element, output_buffer)) + { + return false; + } + update_offset(output_buffer); + if (current_element->next) + { + length = (size_t) (output_buffer->format ? 2 : 1); + output_pointer = ensure(output_buffer, length + 1); + if (output_pointer == NULL) + { + return false; + } + *output_pointer++ = ','; + if(output_buffer->format) + { + *output_pointer++ = ' '; + } + *output_pointer = '\0'; + output_buffer->offset += length; + } + current_element = current_element->next; + } + + output_pointer = ensure(output_buffer, 2); + if (output_pointer == NULL) + { + return false; + } + *output_pointer++ = ']'; + *output_pointer = '\0'; + output_buffer->depth--; + + return true; +} + +/* Build an object from the text. */ +static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer) +{ + cJSON *head = NULL; /* linked list head */ + cJSON *current_item = NULL; + + if (input_buffer->depth >= CJSON_NESTING_LIMIT) + { + return false; /* to deeply nested */ + } + input_buffer->depth++; + + if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '{')) + { + goto fail; /* not an object */ + } + + input_buffer->offset++; + buffer_skip_whitespace(input_buffer); + if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '}')) + { + goto success; /* empty object */ + } + + /* check if we skipped to the end of the buffer */ + if (cannot_access_at_index(input_buffer, 0)) + { + input_buffer->offset--; + goto fail; + } + + /* step back to character in front of the first element */ + input_buffer->offset--; + /* loop through the comma separated array elements */ + do + { + /* allocate next item */ + cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks)); + if (new_item == NULL) + { + goto fail; /* allocation failure */ + } + + /* attach next item to list */ + if (head == NULL) + { + /* start the linked list */ + current_item = head = new_item; + } + else + { + /* add to the end and advance */ + current_item->next = new_item; + new_item->prev = current_item; + current_item = new_item; + } + + if (cannot_access_at_index(input_buffer, 1)) + { + goto fail; /* nothing comes after the comma */ + } + + /* parse the name of the child */ + input_buffer->offset++; + buffer_skip_whitespace(input_buffer); + if (!parse_string(current_item, input_buffer)) + { + goto fail; /* failed to parse name */ + } + buffer_skip_whitespace(input_buffer); + + /* swap valuestring and string, because we parsed the name */ + current_item->string = current_item->valuestring; + current_item->valuestring = NULL; + + if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != ':')) + { + goto fail; /* invalid object */ + } + + /* parse the value */ + input_buffer->offset++; + buffer_skip_whitespace(input_buffer); + if (!parse_value(current_item, input_buffer)) + { + goto fail; /* failed to parse value */ + } + buffer_skip_whitespace(input_buffer); + } + while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ',')); + + if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '}')) + { + goto fail; /* expected end of object */ + } + +success: + input_buffer->depth--; + + if (head != NULL) { + head->prev = current_item; + } + + item->type = cJSON_Object; + item->child = head; + + input_buffer->offset++; + return true; + +fail: + if (head != NULL) + { + cJSON_Delete(head); + } + + return false; +} + +/* Render an object to text. */ +static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer) +{ + unsigned char *output_pointer = NULL; + size_t length = 0; + cJSON *current_item = item->child; + + if (output_buffer == NULL) + { + return false; + } + + /* Compose the output: */ + length = (size_t) (output_buffer->format ? 2 : 1); /* fmt: {\n */ + output_pointer = ensure(output_buffer, length + 1); + if (output_pointer == NULL) + { + return false; + } + + *output_pointer++ = '{'; + output_buffer->depth++; + if (output_buffer->format) + { + *output_pointer++ = '\n'; + } + output_buffer->offset += length; + + while (current_item) + { + if (output_buffer->format) + { + size_t i; + output_pointer = ensure(output_buffer, output_buffer->depth); + if (output_pointer == NULL) + { + return false; + } + for (i = 0; i < output_buffer->depth; i++) + { + *output_pointer++ = '\t'; + } + output_buffer->offset += output_buffer->depth; + } + + /* print key */ + if (!print_string_ptr((unsigned char*)current_item->string, output_buffer)) + { + return false; + } + update_offset(output_buffer); + + length = (size_t) (output_buffer->format ? 2 : 1); + output_pointer = ensure(output_buffer, length); + if (output_pointer == NULL) + { + return false; + } + *output_pointer++ = ':'; + if (output_buffer->format) + { + *output_pointer++ = '\t'; + } + output_buffer->offset += length; + + /* print value */ + if (!print_value(current_item, output_buffer)) + { + return false; + } + update_offset(output_buffer); + + /* print comma if not last */ + length = ((size_t)(output_buffer->format ? 1 : 0) + (size_t)(current_item->next ? 1 : 0)); + output_pointer = ensure(output_buffer, length + 1); + if (output_pointer == NULL) + { + return false; + } + if (current_item->next) + { + *output_pointer++ = ','; + } + + if (output_buffer->format) + { + *output_pointer++ = '\n'; + } + *output_pointer = '\0'; + output_buffer->offset += length; + + current_item = current_item->next; + } + + output_pointer = ensure(output_buffer, output_buffer->format ? (output_buffer->depth + 1) : 2); + if (output_pointer == NULL) + { + return false; + } + if (output_buffer->format) + { + size_t i; + for (i = 0; i < (output_buffer->depth - 1); i++) + { + *output_pointer++ = '\t'; + } + } + *output_pointer++ = '}'; + *output_pointer = '\0'; + output_buffer->depth--; + + return true; +} + +/* Get Array size/item / object item. */ +CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array) +{ + cJSON *child = NULL; + size_t size = 0; + + if (array == NULL) + { + return 0; + } + + child = array->child; + + while(child != NULL) + { + size++; + child = child->next; + } + + /* FIXME: Can overflow here. Cannot be fixed without breaking the API */ + + return (int)size; +} + +static cJSON* get_array_item(const cJSON *array, size_t index) +{ + cJSON *current_child = NULL; + + if (array == NULL) + { + return NULL; + } + + current_child = array->child; + while ((current_child != NULL) && (index > 0)) + { + index--; + current_child = current_child->next; + } + + return current_child; +} + +CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index) +{ + if (index < 0) + { + return NULL; + } + + return get_array_item(array, (size_t)index); +} + +static cJSON *get_object_item(const cJSON * const object, const char * const name, const cJSON_bool case_sensitive) +{ + cJSON *current_element = NULL; + + if ((object == NULL) || (name == NULL)) + { + return NULL; + } + + current_element = object->child; + if (case_sensitive) + { + while ((current_element != NULL) && (current_element->string != NULL) && (strcmp(name, current_element->string) != 0)) + { + current_element = current_element->next; + } + } + else + { + while ((current_element != NULL) && (case_insensitive_strcmp((const unsigned char*)name, (const unsigned char*)(current_element->string)) != 0)) + { + current_element = current_element->next; + } + } + + if ((current_element == NULL) || (current_element->string == NULL)) { + return NULL; + } + + return current_element; +} + +CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string) +{ + return get_object_item(object, string, false); +} + +CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string) +{ + return get_object_item(object, string, true); +} + +CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string) +{ + return cJSON_GetObjectItem(object, string) ? 1 : 0; +} + +/* Utility for array list handling. */ +static void suffix_object(cJSON *prev, cJSON *item) +{ + prev->next = item; + item->prev = prev; +} + +/* Utility for handling references. */ +static cJSON *create_reference(const cJSON *item, const internal_hooks * const hooks) +{ + cJSON *reference = NULL; + if (item == NULL) + { + return NULL; + } + + reference = cJSON_New_Item(hooks); + if (reference == NULL) + { + return NULL; + } + + memcpy(reference, item, sizeof(cJSON)); + reference->string = NULL; + reference->type |= cJSON_IsReference; + reference->next = reference->prev = NULL; + return reference; +} + +static cJSON_bool add_item_to_array(cJSON *array, cJSON *item) +{ + cJSON *child = NULL; + + if ((item == NULL) || (array == NULL) || (array == item)) + { + return false; + } + + child = array->child; + /* + * To find the last item in array quickly, we use prev in array + */ + if (child == NULL) + { + /* list is empty, start new one */ + array->child = item; + item->prev = item; + item->next = NULL; + } + else + { + /* append to the end */ + if (child->prev) + { + suffix_object(child->prev, item); + array->child->prev = item; + } + } + + return true; +} + +/* Add item to array/object. */ +CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item) +{ + return add_item_to_array(array, item); +} + +#if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5)))) + #pragma GCC diagnostic push +#endif +#ifdef __GNUC__ +#pragma GCC diagnostic ignored "-Wcast-qual" +#endif +/* helper function to cast away const */ +static void* cast_away_const(const void* string) +{ + return (void*)string; +} +#if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5)))) + #pragma GCC diagnostic pop +#endif + + +static cJSON_bool add_item_to_object(cJSON * const object, const char * const string, cJSON * const item, const internal_hooks * const hooks, const cJSON_bool constant_key) +{ + char *new_key = NULL; + int new_type = cJSON_Invalid; + + if ((object == NULL) || (string == NULL) || (item == NULL) || (object == item)) + { + return false; + } + + if (constant_key) + { + new_key = (char*)cast_away_const(string); + new_type = item->type | cJSON_StringIsConst; + } + else + { + new_key = (char*)cJSON_strdup((const unsigned char*)string, hooks); + if (new_key == NULL) + { + return false; + } + + new_type = item->type & ~cJSON_StringIsConst; + } + + if (!(item->type & cJSON_StringIsConst) && (item->string != NULL)) + { + hooks->deallocate(item->string); + } + + item->string = new_key; + item->type = new_type; + + return add_item_to_array(object, item); +} + +CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item) +{ + return add_item_to_object(object, string, item, &global_hooks, false); +} + +/* Add an item to an object with constant string as key */ +CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item) +{ + return add_item_to_object(object, string, item, &global_hooks, true); +} + +CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item) +{ + if (array == NULL) + { + return false; + } + + return add_item_to_array(array, create_reference(item, &global_hooks)); +} + +CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item) +{ + if ((object == NULL) || (string == NULL)) + { + return false; + } + + return add_item_to_object(object, string, create_reference(item, &global_hooks), &global_hooks, false); +} + +CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name) +{ + cJSON *null = cJSON_CreateNull(); + if (add_item_to_object(object, name, null, &global_hooks, false)) + { + return null; + } + + cJSON_Delete(null); + return NULL; +} + +CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name) +{ + cJSON *true_item = cJSON_CreateTrue(); + if (add_item_to_object(object, name, true_item, &global_hooks, false)) + { + return true_item; + } + + cJSON_Delete(true_item); + return NULL; +} + +CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name) +{ + cJSON *false_item = cJSON_CreateFalse(); + if (add_item_to_object(object, name, false_item, &global_hooks, false)) + { + return false_item; + } + + cJSON_Delete(false_item); + return NULL; +} + +CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean) +{ + cJSON *bool_item = cJSON_CreateBool(boolean); + if (add_item_to_object(object, name, bool_item, &global_hooks, false)) + { + return bool_item; + } + + cJSON_Delete(bool_item); + return NULL; +} + +CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number) +{ + cJSON *number_item = cJSON_CreateNumber(number); + if (add_item_to_object(object, name, number_item, &global_hooks, false)) + { + return number_item; + } + + cJSON_Delete(number_item); + return NULL; +} + +CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string) +{ + cJSON *string_item = cJSON_CreateString(string); + if (add_item_to_object(object, name, string_item, &global_hooks, false)) + { + return string_item; + } + + cJSON_Delete(string_item); + return NULL; +} + +CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw) +{ + cJSON *raw_item = cJSON_CreateRaw(raw); + if (add_item_to_object(object, name, raw_item, &global_hooks, false)) + { + return raw_item; + } + + cJSON_Delete(raw_item); + return NULL; +} + +CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name) +{ + cJSON *object_item = cJSON_CreateObject(); + if (add_item_to_object(object, name, object_item, &global_hooks, false)) + { + return object_item; + } + + cJSON_Delete(object_item); + return NULL; +} + +CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name) +{ + cJSON *array = cJSON_CreateArray(); + if (add_item_to_object(object, name, array, &global_hooks, false)) + { + return array; + } + + cJSON_Delete(array); + return NULL; +} + +CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item) +{ + if ((parent == NULL) || (item == NULL) || (item != parent->child && item->prev == NULL)) + { + return NULL; + } + + if (item != parent->child) + { + /* not the first element */ + item->prev->next = item->next; + } + if (item->next != NULL) + { + /* not the last element */ + item->next->prev = item->prev; + } + + if (item == parent->child) + { + /* first element */ + parent->child = item->next; + } + else if (item->next == NULL) + { + /* last element */ + parent->child->prev = item->prev; + } + + /* make sure the detached item doesn't point anywhere anymore */ + item->prev = NULL; + item->next = NULL; + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which) +{ + if (which < 0) + { + return NULL; + } + + return cJSON_DetachItemViaPointer(array, get_array_item(array, (size_t)which)); +} + +CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which) +{ + cJSON_Delete(cJSON_DetachItemFromArray(array, which)); +} + +CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string) +{ + cJSON *to_detach = cJSON_GetObjectItem(object, string); + + return cJSON_DetachItemViaPointer(object, to_detach); +} + +CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string) +{ + cJSON *to_detach = cJSON_GetObjectItemCaseSensitive(object, string); + + return cJSON_DetachItemViaPointer(object, to_detach); +} + +CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string) +{ + cJSON_Delete(cJSON_DetachItemFromObject(object, string)); +} + +CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string) +{ + cJSON_Delete(cJSON_DetachItemFromObjectCaseSensitive(object, string)); +} + +/* Replace array/object items with new ones. */ +CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem) +{ + cJSON *after_inserted = NULL; + + if (which < 0 || newitem == NULL) + { + return false; + } + + after_inserted = get_array_item(array, (size_t)which); + if (after_inserted == NULL) + { + return add_item_to_array(array, newitem); + } + + if (after_inserted != array->child && after_inserted->prev == NULL) { + /* return false if after_inserted is a corrupted array item */ + return false; + } + + newitem->next = after_inserted; + newitem->prev = after_inserted->prev; + after_inserted->prev = newitem; + if (after_inserted == array->child) + { + array->child = newitem; + } + else + { + newitem->prev->next = newitem; + } + return true; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement) +{ + if ((parent == NULL) || (parent->child == NULL) || (replacement == NULL) || (item == NULL)) + { + return false; + } + + if (replacement == item) + { + return true; + } + + replacement->next = item->next; + replacement->prev = item->prev; + + if (replacement->next != NULL) + { + replacement->next->prev = replacement; + } + if (parent->child == item) + { + if (parent->child->prev == parent->child) + { + replacement->prev = replacement; + } + parent->child = replacement; + } + else + { /* + * To find the last item in array quickly, we use prev in array. + * We can't modify the last item's next pointer where this item was the parent's child + */ + if (replacement->prev != NULL) + { + replacement->prev->next = replacement; + } + if (replacement->next == NULL) + { + parent->child->prev = replacement; + } + } + + item->next = NULL; + item->prev = NULL; + cJSON_Delete(item); + + return true; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem) +{ + if (which < 0) + { + return false; + } + + return cJSON_ReplaceItemViaPointer(array, get_array_item(array, (size_t)which), newitem); +} + +static cJSON_bool replace_item_in_object(cJSON *object, const char *string, cJSON *replacement, cJSON_bool case_sensitive) +{ + if ((replacement == NULL) || (string == NULL)) + { + return false; + } + + /* replace the name in the replacement */ + if (!(replacement->type & cJSON_StringIsConst) && (replacement->string != NULL)) + { + cJSON_free(replacement->string); + } + replacement->string = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks); + if (replacement->string == NULL) + { + return false; + } + + replacement->type &= ~cJSON_StringIsConst; + + return cJSON_ReplaceItemViaPointer(object, get_object_item(object, string, case_sensitive), replacement); +} + +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem) +{ + return replace_item_in_object(object, string, newitem, false); +} + +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object, const char *string, cJSON *newitem) +{ + return replace_item_in_object(object, string, newitem, true); +} + +/* Create basic types: */ +CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if(item) + { + item->type = cJSON_NULL; + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if(item) + { + item->type = cJSON_True; + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if(item) + { + item->type = cJSON_False; + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if(item) + { + item->type = boolean ? cJSON_True : cJSON_False; + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if(item) + { + item->type = cJSON_Number; + item->valuedouble = num; + + /* use saturation in case of overflow */ + if (num >= INT_MAX) + { + item->valueint = INT_MAX; + } + else if (num <= (double)INT_MIN) + { + item->valueint = INT_MIN; + } + else + { + item->valueint = (int)num; + } + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if(item) + { + item->type = cJSON_String; + item->valuestring = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks); + if(!item->valuestring) + { + cJSON_Delete(item); + return NULL; + } + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if (item != NULL) + { + item->type = cJSON_String | cJSON_IsReference; + item->valuestring = (char*)cast_away_const(string); + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if (item != NULL) { + item->type = cJSON_Object | cJSON_IsReference; + item->child = (cJSON*)cast_away_const(child); + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child) { + cJSON *item = cJSON_New_Item(&global_hooks); + if (item != NULL) { + item->type = cJSON_Array | cJSON_IsReference; + item->child = (cJSON*)cast_away_const(child); + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if(item) + { + item->type = cJSON_Raw; + item->valuestring = (char*)cJSON_strdup((const unsigned char*)raw, &global_hooks); + if(!item->valuestring) + { + cJSON_Delete(item); + return NULL; + } + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if(item) + { + item->type=cJSON_Array; + } + + return item; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void) +{ + cJSON *item = cJSON_New_Item(&global_hooks); + if (item) + { + item->type = cJSON_Object; + } + + return item; +} + +/* Create Arrays: */ +CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count) +{ + size_t i = 0; + cJSON *n = NULL; + cJSON *p = NULL; + cJSON *a = NULL; + + if ((count < 0) || (numbers == NULL)) + { + return NULL; + } + + a = cJSON_CreateArray(); + + for(i = 0; a && (i < (size_t)count); i++) + { + n = cJSON_CreateNumber(numbers[i]); + if (!n) + { + cJSON_Delete(a); + return NULL; + } + if(!i) + { + a->child = n; + } + else + { + suffix_object(p, n); + } + p = n; + } + + if (a && a->child) { + a->child->prev = n; + } + + return a; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count) +{ + size_t i = 0; + cJSON *n = NULL; + cJSON *p = NULL; + cJSON *a = NULL; + + if ((count < 0) || (numbers == NULL)) + { + return NULL; + } + + a = cJSON_CreateArray(); + + for(i = 0; a && (i < (size_t)count); i++) + { + n = cJSON_CreateNumber((double)numbers[i]); + if(!n) + { + cJSON_Delete(a); + return NULL; + } + if(!i) + { + a->child = n; + } + else + { + suffix_object(p, n); + } + p = n; + } + + if (a && a->child) { + a->child->prev = n; + } + + return a; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count) +{ + size_t i = 0; + cJSON *n = NULL; + cJSON *p = NULL; + cJSON *a = NULL; + + if ((count < 0) || (numbers == NULL)) + { + return NULL; + } + + a = cJSON_CreateArray(); + + for(i = 0; a && (i < (size_t)count); i++) + { + n = cJSON_CreateNumber(numbers[i]); + if(!n) + { + cJSON_Delete(a); + return NULL; + } + if(!i) + { + a->child = n; + } + else + { + suffix_object(p, n); + } + p = n; + } + + if (a && a->child) { + a->child->prev = n; + } + + return a; +} + +CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int count) +{ + size_t i = 0; + cJSON *n = NULL; + cJSON *p = NULL; + cJSON *a = NULL; + + if ((count < 0) || (strings == NULL)) + { + return NULL; + } + + a = cJSON_CreateArray(); + + for (i = 0; a && (i < (size_t)count); i++) + { + n = cJSON_CreateString(strings[i]); + if(!n) + { + cJSON_Delete(a); + return NULL; + } + if(!i) + { + a->child = n; + } + else + { + suffix_object(p,n); + } + p = n; + } + + if (a && a->child) { + a->child->prev = n; + } + + return a; +} + +/* Duplication */ +cJSON * cJSON_Duplicate_rec(const cJSON *item, size_t depth, cJSON_bool recurse); + +CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse) +{ + return cJSON_Duplicate_rec(item, 0, recurse ); +} + +cJSON * cJSON_Duplicate_rec(const cJSON *item, size_t depth, cJSON_bool recurse) +{ + cJSON *newitem = NULL; + cJSON *child = NULL; + cJSON *next = NULL; + cJSON *newchild = NULL; + + /* Bail on bad ptr */ + if (!item) + { + goto fail; + } + /* Create new item */ + newitem = cJSON_New_Item(&global_hooks); + if (!newitem) + { + goto fail; + } + /* Copy over all vars */ + newitem->type = item->type & (~cJSON_IsReference); + newitem->valueint = item->valueint; + newitem->valuedouble = item->valuedouble; + if (item->valuestring) + { + newitem->valuestring = (char*)cJSON_strdup((unsigned char*)item->valuestring, &global_hooks); + if (!newitem->valuestring) + { + goto fail; + } + } + if (item->string) + { + newitem->string = (item->type&cJSON_StringIsConst) ? item->string : (char*)cJSON_strdup((unsigned char*)item->string, &global_hooks); + if (!newitem->string) + { + goto fail; + } + } + /* If non-recursive, then we're done! */ + if (!recurse) + { + return newitem; + } + /* Walk the ->next chain for the child. */ + child = item->child; + while (child != NULL) + { + if(depth >= CJSON_CIRCULAR_LIMIT) { + goto fail; + } + newchild = cJSON_Duplicate_rec(child, depth + 1, true); /* Duplicate (with recurse) each item in the ->next chain */ + if (!newchild) + { + goto fail; + } + if (next != NULL) + { + /* If newitem->child already set, then crosswire ->prev and ->next and move on */ + next->next = newchild; + newchild->prev = next; + next = newchild; + } + else + { + /* Set newitem->child and move to it */ + newitem->child = newchild; + next = newchild; + } + child = child->next; + } + if (newitem && newitem->child) + { + newitem->child->prev = newchild; + } + + return newitem; + +fail: + if (newitem != NULL) + { + cJSON_Delete(newitem); + } + + return NULL; +} + +static void skip_oneline_comment(char **input) +{ + *input += static_strlen("//"); + + for (; (*input)[0] != '\0'; ++(*input)) + { + if ((*input)[0] == '\n') { + *input += static_strlen("\n"); + return; + } + } +} + +static void skip_multiline_comment(char **input) +{ + *input += static_strlen("/*"); + + for (; (*input)[0] != '\0'; ++(*input)) + { + if (((*input)[0] == '*') && ((*input)[1] == '/')) + { + *input += static_strlen("*/"); + return; + } + } +} + +static void minify_string(char **input, char **output) { + (*output)[0] = (*input)[0]; + *input += static_strlen("\""); + *output += static_strlen("\""); + + + for (; (*input)[0] != '\0'; (void)++(*input), ++(*output)) { + (*output)[0] = (*input)[0]; + + if ((*input)[0] == '\"') { + (*output)[0] = '\"'; + *input += static_strlen("\""); + *output += static_strlen("\""); + return; + } else if (((*input)[0] == '\\') && ((*input)[1] == '\"')) { + (*output)[1] = (*input)[1]; + *input += static_strlen("\""); + *output += static_strlen("\""); + } + } +} + +CJSON_PUBLIC(void) cJSON_Minify(char *json) +{ + char *into = json; + + if (json == NULL) + { + return; + } + + while (json[0] != '\0') + { + switch (json[0]) + { + case ' ': + case '\t': + case '\r': + case '\n': + json++; + break; + + case '/': + if (json[1] == '/') + { + skip_oneline_comment(&json); + } + else if (json[1] == '*') + { + skip_multiline_comment(&json); + } else { + json++; + } + break; + + case '\"': + minify_string(&json, (char**)&into); + break; + + default: + into[0] = json[0]; + json++; + into++; + } + } + + /* and null-terminate. */ + *into = '\0'; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & 0xFF) == cJSON_Invalid; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & 0xFF) == cJSON_False; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & 0xff) == cJSON_True; +} + + +CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & (cJSON_True | cJSON_False)) != 0; +} +CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & 0xFF) == cJSON_NULL; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & 0xFF) == cJSON_Number; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & 0xFF) == cJSON_String; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & 0xFF) == cJSON_Array; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & 0xFF) == cJSON_Object; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item) +{ + if (item == NULL) + { + return false; + } + + return (item->type & 0xFF) == cJSON_Raw; +} + +CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive) +{ + if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF))) + { + return false; + } + + /* check if type is valid */ + switch (a->type & 0xFF) + { + case cJSON_False: + case cJSON_True: + case cJSON_NULL: + case cJSON_Number: + case cJSON_String: + case cJSON_Raw: + case cJSON_Array: + case cJSON_Object: + break; + + default: + return false; + } + + /* identical objects are equal */ + if (a == b) + { + return true; + } + + switch (a->type & 0xFF) + { + /* in these cases and equal type is enough */ + case cJSON_False: + case cJSON_True: + case cJSON_NULL: + return true; + + case cJSON_Number: + if (compare_double(a->valuedouble, b->valuedouble)) + { + return true; + } + return false; + + case cJSON_String: + case cJSON_Raw: + if ((a->valuestring == NULL) || (b->valuestring == NULL)) + { + return false; + } + if (strcmp(a->valuestring, b->valuestring) == 0) + { + return true; + } + + return false; + + case cJSON_Array: + { + cJSON *a_element = a->child; + cJSON *b_element = b->child; + + for (; (a_element != NULL) && (b_element != NULL);) + { + if (!cJSON_Compare(a_element, b_element, case_sensitive)) + { + return false; + } + + a_element = a_element->next; + b_element = b_element->next; + } + + /* one of the arrays is longer than the other */ + if (a_element != b_element) { + return false; + } + + return true; + } + + case cJSON_Object: + { + cJSON *a_element = NULL; + cJSON *b_element = NULL; + cJSON_ArrayForEach(a_element, a) + { + /* TODO This has O(n^2) runtime, which is horrible! */ + b_element = get_object_item(b, a_element->string, case_sensitive); + if (b_element == NULL) + { + return false; + } + + if (!cJSON_Compare(a_element, b_element, case_sensitive)) + { + return false; + } + } + + /* doing this twice, once on a and b to prevent true comparison if a subset of b + * TODO: Do this the proper way, this is just a fix for now */ + cJSON_ArrayForEach(b_element, b) + { + a_element = get_object_item(a, b_element->string, case_sensitive); + if (a_element == NULL) + { + return false; + } + + if (!cJSON_Compare(b_element, a_element, case_sensitive)) + { + return false; + } + } + + return true; + } + + default: + return false; + } +} + +CJSON_PUBLIC(void *) cJSON_malloc(size_t size) +{ + return global_hooks.allocate(size); +} + +CJSON_PUBLIC(void) cJSON_free(void *object) +{ + global_hooks.deallocate(object); + object = NULL; +} diff --git a/vendor/cJSON.h b/vendor/cJSON.h new file mode 100644 index 0000000000..cab5feb427 --- /dev/null +++ b/vendor/cJSON.h @@ -0,0 +1,306 @@ +/* + Copyright (c) 2009-2017 Dave Gamble and cJSON contributors + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +#ifndef cJSON__h +#define cJSON__h + +#ifdef __cplusplus +extern "C" +{ +#endif + +#if !defined(__WINDOWS__) && (defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32)) +#define __WINDOWS__ +#endif + +#ifdef __WINDOWS__ + +/* When compiling for windows, we specify a specific calling convention to avoid issues where we are being called from a project with a different default calling convention. For windows you have 3 define options: + +CJSON_HIDE_SYMBOLS - Define this in the case where you don't want to ever dllexport symbols +CJSON_EXPORT_SYMBOLS - Define this on library build when you want to dllexport symbols (default) +CJSON_IMPORT_SYMBOLS - Define this if you want to dllimport symbol + +For *nix builds that support visibility attribute, you can define similar behavior by + +setting default visibility to hidden by adding +-fvisibility=hidden (for gcc) +or +-xldscope=hidden (for sun cc) +to CFLAGS + +then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJSON_EXPORT_SYMBOLS does + +*/ + +#define CJSON_CDECL __cdecl +#define CJSON_STDCALL __stdcall + +/* export symbols by default, this is necessary for copy pasting the C and header file */ +#if !defined(CJSON_HIDE_SYMBOLS) && !defined(CJSON_IMPORT_SYMBOLS) && !defined(CJSON_EXPORT_SYMBOLS) +#define CJSON_EXPORT_SYMBOLS +#endif + +#if defined(CJSON_HIDE_SYMBOLS) +#define CJSON_PUBLIC(type) type CJSON_STDCALL +#elif defined(CJSON_EXPORT_SYMBOLS) +#define CJSON_PUBLIC(type) __declspec(dllexport) type CJSON_STDCALL +#elif defined(CJSON_IMPORT_SYMBOLS) +#define CJSON_PUBLIC(type) __declspec(dllimport) type CJSON_STDCALL +#endif +#else /* !__WINDOWS__ */ +#define CJSON_CDECL +#define CJSON_STDCALL + +#if (defined(__GNUC__) || defined(__SUNPRO_CC) || defined (__SUNPRO_C)) && defined(CJSON_API_VISIBILITY) +#define CJSON_PUBLIC(type) __attribute__((visibility("default"))) type +#else +#define CJSON_PUBLIC(type) type +#endif +#endif + +/* project version */ +#define CJSON_VERSION_MAJOR 1 +#define CJSON_VERSION_MINOR 7 +#define CJSON_VERSION_PATCH 19 + +#include + +/* cJSON Types: */ +#define cJSON_Invalid (0) +#define cJSON_False (1 << 0) +#define cJSON_True (1 << 1) +#define cJSON_NULL (1 << 2) +#define cJSON_Number (1 << 3) +#define cJSON_String (1 << 4) +#define cJSON_Array (1 << 5) +#define cJSON_Object (1 << 6) +#define cJSON_Raw (1 << 7) /* raw json */ + +#define cJSON_IsReference 256 +#define cJSON_StringIsConst 512 + +/* The cJSON structure: */ +typedef struct cJSON +{ + /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */ + struct cJSON *next; + struct cJSON *prev; + /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */ + struct cJSON *child; + + /* The type of the item, as above. */ + int type; + + /* The item's string, if type==cJSON_String and type == cJSON_Raw */ + char *valuestring; + /* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */ + int valueint; + /* The item's number, if type==cJSON_Number */ + double valuedouble; + + /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */ + char *string; +} cJSON; + +typedef struct cJSON_Hooks +{ + /* malloc/free are CDECL on Windows regardless of the default calling convention of the compiler, so ensure the hooks allow passing those functions directly. */ + void *(CJSON_CDECL *malloc_fn)(size_t sz); + void (CJSON_CDECL *free_fn)(void *ptr); +} cJSON_Hooks; + +typedef int cJSON_bool; + +/* Limits how deeply nested arrays/objects can be before cJSON rejects to parse them. + * This is to prevent stack overflows. */ +#ifndef CJSON_NESTING_LIMIT +#define CJSON_NESTING_LIMIT 1000 +#endif + +/* Limits the length of circular references can be before cJSON rejects to parse them. + * This is to prevent stack overflows. */ +#ifndef CJSON_CIRCULAR_LIMIT +#define CJSON_CIRCULAR_LIMIT 10000 +#endif + +/* returns the version of cJSON as a string */ +CJSON_PUBLIC(const char*) cJSON_Version(void); + +/* Supply malloc, realloc and free functions to cJSON */ +CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks); + +/* Memory Management: the caller is always responsible to free the results from all variants of cJSON_Parse (with cJSON_Delete) and cJSON_Print (with stdlib free, cJSON_Hooks.free_fn, or cJSON_free as appropriate). The exception is cJSON_PrintPreallocated, where the caller has full responsibility of the buffer. */ +/* Supply a block of JSON, and this returns a cJSON object you can interrogate. */ +CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value); +CJSON_PUBLIC(cJSON *) cJSON_ParseWithLength(const char *value, size_t buffer_length); +/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */ +/* If you supply a ptr in return_parse_end and parsing fails, then return_parse_end will contain a pointer to the error so will match cJSON_GetErrorPtr(). */ +CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated); +CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, cJSON_bool require_null_terminated); + +/* Render a cJSON entity to text for transfer/storage. */ +CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item); +/* Render a cJSON entity to text for transfer/storage without any formatting. */ +CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item); +/* Render a cJSON entity to text using a buffered strategy. prebuffer is a guess at the final size. guessing well reduces reallocation. fmt=0 gives unformatted, =1 gives formatted */ +CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt); +/* Render a cJSON entity to text using a buffer already allocated in memory with given length. Returns 1 on success and 0 on failure. */ +/* NOTE: cJSON is not always 100% accurate in estimating how much memory it will use, so to be safe allocate 5 bytes more than you actually need */ +CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format); +/* Delete a cJSON entity and all subentities. */ +CJSON_PUBLIC(void) cJSON_Delete(cJSON *item); + +/* Returns the number of items in an array (or object). */ +CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array); +/* Retrieve item number "index" from array "array". Returns NULL if unsuccessful. */ +CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index); +/* Get item "string" from object. Case insensitive. */ +CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string); +CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string); +CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string); +/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */ +CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void); + +/* Check item type and return its value */ +CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item); +CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON * const item); + +/* These functions check the type of an item */ +CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item); +CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item); + +/* These calls create a cJSON item of the appropriate type. */ +CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void); +CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void); +CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void); +CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean); +CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num); +CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string); +/* raw json */ +CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw); +CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void); +CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void); + +/* Create a string where valuestring references a string so + * it will not be freed by cJSON_Delete */ +CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string); +/* Create an object/array that only references it's elements so + * they will not be freed by cJSON_Delete */ +CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child); +CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child); + +/* These utilities create an Array of count items. + * The parameter count cannot be greater than the number of elements in the number array, otherwise array access will be out of bounds.*/ +CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count); +CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count); +CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count); +CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int count); + +/* Append item to the specified array/object. */ +CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item); +CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item); +/* Use this when string is definitely const (i.e. a literal, or as good as), and will definitely survive the cJSON object. + * WARNING: When this function was used, make sure to always check that (item->type & cJSON_StringIsConst) is zero before + * writing to `item->string` */ +CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item); +/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */ +CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item); +CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item); + +/* Remove/Detach items from Arrays/Objects. */ +CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item); +CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which); +CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which); +CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string); +CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string); +CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string); +CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string); + +/* Update array items. */ +CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem); /* Shifts pre-existing items to the right. */ +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement); +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem); +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem); +CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object,const char *string,cJSON *newitem); + +/* Duplicate a cJSON item */ +CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse); +/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will + * need to be released. With recurse!=0, it will duplicate any children connected to the item. + * The item->next and ->prev pointers are always zero on return from Duplicate. */ +/* Recursively compare two cJSON items for equality. If either a or b is NULL or invalid, they will be considered unequal. + * case_sensitive determines if object keys are treated case sensitive (1) or case insensitive (0) */ +CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive); + +/* Minify a strings, remove blank characters(such as ' ', '\t', '\r', '\n') from strings. + * The input pointer json cannot point to a read-only address area, such as a string constant, + * but should point to a readable and writable address area. */ +CJSON_PUBLIC(void) cJSON_Minify(char *json); + +/* Helper functions for creating and adding items to an object at the same time. + * They return the added item or NULL on failure. */ +CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name); +CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name); +CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name); +CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean); +CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number); +CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string); +CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw); +CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name); +CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name); + +/* When assigning an integer value, it needs to be propagated to valuedouble too. */ +#define cJSON_SetIntValue(object, number) ((object) ? (object)->valueint = (object)->valuedouble = (number) : (number)) +/* helper for the cJSON_SetNumberValue macro */ +CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number); +#define cJSON_SetNumberValue(object, number) ((object != NULL) ? cJSON_SetNumberHelper(object, (double)number) : (number)) +/* Change the valuestring of a cJSON_String object, only takes effect when type of object is cJSON_String */ +CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring); + +/* If the object is not a boolean type this does nothing and returns cJSON_Invalid else it returns the new type*/ +#define cJSON_SetBoolValue(object, boolValue) ( \ + (object != NULL && ((object)->type & (cJSON_False|cJSON_True))) ? \ + (object)->type=((object)->type &(~(cJSON_False|cJSON_True)))|((boolValue)?cJSON_True:cJSON_False) : \ + cJSON_Invalid\ +) + +/* Macro for iterating over an array or object */ +#define cJSON_ArrayForEach(element, array) for(element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next) + +/* malloc/free objects using the malloc/free functions that have been set with cJSON_InitHooks */ +CJSON_PUBLIC(void *) cJSON_malloc(size_t size); +CJSON_PUBLIC(void) cJSON_free(void *object); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/vendor/glad.h b/vendor/glad.h new file mode 100644 index 0000000000..ea21c9c2aa --- /dev/null +++ b/vendor/glad.h @@ -0,0 +1,2129 @@ +/* + + OpenGL loader generated by glad 0.1.36 on Tue Oct 14 18:01:52 2025. + + Language/Generator: C/C++ + Specification: gl + APIs: gl=3.3 + Profile: core + Extensions: + + Loader: True + Local files: False + Omit khrplatform: False + Reproducible: False + + Commandline: + --profile="core" --api="gl=3.3" --generator="c" --spec="gl" --extensions="" + Online: + https://glad.dav1d.de/#profile=core&language=c&specification=gl&loader=on&api=gl%3D3.3 +*/ + + +#ifndef __glad_h_ +#define __glad_h_ + +#ifdef __gl_h_ +#error OpenGL header already included, remove this include, glad already provides it +#endif +#define __gl_h_ + +#if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__) +#define APIENTRY __stdcall +#endif + +#ifndef APIENTRY +#define APIENTRY +#endif +#ifndef APIENTRYP +#define APIENTRYP APIENTRY * +#endif + +#ifndef GLAPIENTRY +#define GLAPIENTRY APIENTRY +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +struct gladGLversionStruct { + int major; + int minor; +}; + +typedef void* (* GLADloadproc)(const char *name); + +#ifndef GLAPI +# if defined(GLAD_GLAPI_EXPORT) +# if defined(_WIN32) || defined(__CYGWIN__) +# if defined(GLAD_GLAPI_EXPORT_BUILD) +# if defined(__GNUC__) +# define GLAPI __attribute__ ((dllexport)) extern +# else +# define GLAPI __declspec(dllexport) extern +# endif +# else +# if defined(__GNUC__) +# define GLAPI __attribute__ ((dllimport)) extern +# else +# define GLAPI __declspec(dllimport) extern +# endif +# endif +# elif defined(__GNUC__) && defined(GLAD_GLAPI_EXPORT_BUILD) +# define GLAPI __attribute__ ((visibility ("default"))) extern +# else +# define GLAPI extern +# endif +# else +# define GLAPI extern +# endif +#endif + +GLAPI struct gladGLversionStruct GLVersion; + +GLAPI int gladLoadGL(void); + +GLAPI int gladLoadGLLoader(GLADloadproc); + +#include "KHR/khrplatform.h" +typedef unsigned int GLenum; +typedef unsigned char GLboolean; +typedef unsigned int GLbitfield; +typedef void GLvoid; +typedef khronos_int8_t GLbyte; +typedef khronos_uint8_t GLubyte; +typedef khronos_int16_t GLshort; +typedef khronos_uint16_t GLushort; +typedef int GLint; +typedef unsigned int GLuint; +typedef khronos_int32_t GLclampx; +typedef int GLsizei; +typedef khronos_float_t GLfloat; +typedef khronos_float_t GLclampf; +typedef double GLdouble; +typedef double GLclampd; +typedef void *GLeglClientBufferEXT; +typedef void *GLeglImageOES; +typedef char GLchar; +typedef char GLcharARB; +#ifdef __APPLE__ +typedef void *GLhandleARB; +#else +typedef unsigned int GLhandleARB; +#endif +typedef khronos_uint16_t GLhalf; +typedef khronos_uint16_t GLhalfARB; +typedef khronos_int32_t GLfixed; +typedef khronos_intptr_t GLintptr; +typedef khronos_intptr_t GLintptrARB; +typedef khronos_ssize_t GLsizeiptr; +typedef khronos_ssize_t GLsizeiptrARB; +typedef khronos_int64_t GLint64; +typedef khronos_int64_t GLint64EXT; +typedef khronos_uint64_t GLuint64; +typedef khronos_uint64_t GLuint64EXT; +typedef struct __GLsync *GLsync; +struct _cl_context; +struct _cl_event; +typedef void (APIENTRY *GLDEBUGPROC)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam); +typedef void (APIENTRY *GLDEBUGPROCARB)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam); +typedef void (APIENTRY *GLDEBUGPROCKHR)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam); +typedef void (APIENTRY *GLDEBUGPROCAMD)(GLuint id,GLenum category,GLenum severity,GLsizei length,const GLchar *message,void *userParam); +typedef unsigned short GLhalfNV; +typedef GLintptr GLvdpauSurfaceNV; +typedef void (APIENTRY *GLVULKANPROCNV)(void); +#define GL_DEPTH_BUFFER_BIT 0x00000100 +#define GL_STENCIL_BUFFER_BIT 0x00000400 +#define GL_COLOR_BUFFER_BIT 0x00004000 +#define GL_FALSE 0 +#define GL_TRUE 1 +#define GL_POINTS 0x0000 +#define GL_LINES 0x0001 +#define GL_LINE_LOOP 0x0002 +#define GL_LINE_STRIP 0x0003 +#define GL_TRIANGLES 0x0004 +#define GL_TRIANGLE_STRIP 0x0005 +#define GL_TRIANGLE_FAN 0x0006 +#define GL_NEVER 0x0200 +#define GL_LESS 0x0201 +#define GL_EQUAL 0x0202 +#define GL_LEQUAL 0x0203 +#define GL_GREATER 0x0204 +#define GL_NOTEQUAL 0x0205 +#define GL_GEQUAL 0x0206 +#define GL_ALWAYS 0x0207 +#define GL_ZERO 0 +#define GL_ONE 1 +#define GL_SRC_COLOR 0x0300 +#define GL_ONE_MINUS_SRC_COLOR 0x0301 +#define GL_SRC_ALPHA 0x0302 +#define GL_ONE_MINUS_SRC_ALPHA 0x0303 +#define GL_DST_ALPHA 0x0304 +#define GL_ONE_MINUS_DST_ALPHA 0x0305 +#define GL_DST_COLOR 0x0306 +#define GL_ONE_MINUS_DST_COLOR 0x0307 +#define GL_SRC_ALPHA_SATURATE 0x0308 +#define GL_NONE 0 +#define GL_FRONT_LEFT 0x0400 +#define GL_FRONT_RIGHT 0x0401 +#define GL_BACK_LEFT 0x0402 +#define GL_BACK_RIGHT 0x0403 +#define GL_FRONT 0x0404 +#define GL_BACK 0x0405 +#define GL_LEFT 0x0406 +#define GL_RIGHT 0x0407 +#define GL_FRONT_AND_BACK 0x0408 +#define GL_NO_ERROR 0 +#define GL_INVALID_ENUM 0x0500 +#define GL_INVALID_VALUE 0x0501 +#define GL_INVALID_OPERATION 0x0502 +#define GL_OUT_OF_MEMORY 0x0505 +#define GL_CW 0x0900 +#define GL_CCW 0x0901 +#define GL_POINT_SIZE 0x0B11 +#define GL_POINT_SIZE_RANGE 0x0B12 +#define GL_POINT_SIZE_GRANULARITY 0x0B13 +#define GL_LINE_SMOOTH 0x0B20 +#define GL_LINE_WIDTH 0x0B21 +#define GL_LINE_WIDTH_RANGE 0x0B22 +#define GL_LINE_WIDTH_GRANULARITY 0x0B23 +#define GL_POLYGON_MODE 0x0B40 +#define GL_POLYGON_SMOOTH 0x0B41 +#define GL_CULL_FACE 0x0B44 +#define GL_CULL_FACE_MODE 0x0B45 +#define GL_FRONT_FACE 0x0B46 +#define GL_DEPTH_RANGE 0x0B70 +#define GL_DEPTH_TEST 0x0B71 +#define GL_DEPTH_WRITEMASK 0x0B72 +#define GL_DEPTH_CLEAR_VALUE 0x0B73 +#define GL_DEPTH_FUNC 0x0B74 +#define GL_STENCIL_TEST 0x0B90 +#define GL_STENCIL_CLEAR_VALUE 0x0B91 +#define GL_STENCIL_FUNC 0x0B92 +#define GL_STENCIL_VALUE_MASK 0x0B93 +#define GL_STENCIL_FAIL 0x0B94 +#define GL_STENCIL_PASS_DEPTH_FAIL 0x0B95 +#define GL_STENCIL_PASS_DEPTH_PASS 0x0B96 +#define GL_STENCIL_REF 0x0B97 +#define GL_STENCIL_WRITEMASK 0x0B98 +#define GL_VIEWPORT 0x0BA2 +#define GL_DITHER 0x0BD0 +#define GL_BLEND_DST 0x0BE0 +#define GL_BLEND_SRC 0x0BE1 +#define GL_BLEND 0x0BE2 +#define GL_LOGIC_OP_MODE 0x0BF0 +#define GL_DRAW_BUFFER 0x0C01 +#define GL_READ_BUFFER 0x0C02 +#define GL_SCISSOR_BOX 0x0C10 +#define GL_SCISSOR_TEST 0x0C11 +#define GL_COLOR_CLEAR_VALUE 0x0C22 +#define GL_COLOR_WRITEMASK 0x0C23 +#define GL_DOUBLEBUFFER 0x0C32 +#define GL_STEREO 0x0C33 +#define GL_LINE_SMOOTH_HINT 0x0C52 +#define GL_POLYGON_SMOOTH_HINT 0x0C53 +#define GL_UNPACK_SWAP_BYTES 0x0CF0 +#define GL_UNPACK_LSB_FIRST 0x0CF1 +#define GL_UNPACK_ROW_LENGTH 0x0CF2 +#define GL_UNPACK_SKIP_ROWS 0x0CF3 +#define GL_UNPACK_SKIP_PIXELS 0x0CF4 +#define GL_UNPACK_ALIGNMENT 0x0CF5 +#define GL_PACK_SWAP_BYTES 0x0D00 +#define GL_PACK_LSB_FIRST 0x0D01 +#define GL_PACK_ROW_LENGTH 0x0D02 +#define GL_PACK_SKIP_ROWS 0x0D03 +#define GL_PACK_SKIP_PIXELS 0x0D04 +#define GL_PACK_ALIGNMENT 0x0D05 +#define GL_MAX_TEXTURE_SIZE 0x0D33 +#define GL_MAX_VIEWPORT_DIMS 0x0D3A +#define GL_SUBPIXEL_BITS 0x0D50 +#define GL_TEXTURE_1D 0x0DE0 +#define GL_TEXTURE_2D 0x0DE1 +#define GL_TEXTURE_WIDTH 0x1000 +#define GL_TEXTURE_HEIGHT 0x1001 +#define GL_TEXTURE_BORDER_COLOR 0x1004 +#define GL_DONT_CARE 0x1100 +#define GL_FASTEST 0x1101 +#define GL_NICEST 0x1102 +#define GL_BYTE 0x1400 +#define GL_UNSIGNED_BYTE 0x1401 +#define GL_SHORT 0x1402 +#define GL_UNSIGNED_SHORT 0x1403 +#define GL_INT 0x1404 +#define GL_UNSIGNED_INT 0x1405 +#define GL_FLOAT 0x1406 +#define GL_CLEAR 0x1500 +#define GL_AND 0x1501 +#define GL_AND_REVERSE 0x1502 +#define GL_COPY 0x1503 +#define GL_AND_INVERTED 0x1504 +#define GL_NOOP 0x1505 +#define GL_XOR 0x1506 +#define GL_OR 0x1507 +#define GL_NOR 0x1508 +#define GL_EQUIV 0x1509 +#define GL_INVERT 0x150A +#define GL_OR_REVERSE 0x150B +#define GL_COPY_INVERTED 0x150C +#define GL_OR_INVERTED 0x150D +#define GL_NAND 0x150E +#define GL_SET 0x150F +#define GL_TEXTURE 0x1702 +#define GL_COLOR 0x1800 +#define GL_DEPTH 0x1801 +#define GL_STENCIL 0x1802 +#define GL_STENCIL_INDEX 0x1901 +#define GL_DEPTH_COMPONENT 0x1902 +#define GL_RED 0x1903 +#define GL_GREEN 0x1904 +#define GL_BLUE 0x1905 +#define GL_ALPHA 0x1906 +#define GL_RGB 0x1907 +#define GL_RGBA 0x1908 +#define GL_POINT 0x1B00 +#define GL_LINE 0x1B01 +#define GL_FILL 0x1B02 +#define GL_KEEP 0x1E00 +#define GL_REPLACE 0x1E01 +#define GL_INCR 0x1E02 +#define GL_DECR 0x1E03 +#define GL_VENDOR 0x1F00 +#define GL_RENDERER 0x1F01 +#define GL_VERSION 0x1F02 +#define GL_EXTENSIONS 0x1F03 +#define GL_NEAREST 0x2600 +#define GL_LINEAR 0x2601 +#define GL_NEAREST_MIPMAP_NEAREST 0x2700 +#define GL_LINEAR_MIPMAP_NEAREST 0x2701 +#define GL_NEAREST_MIPMAP_LINEAR 0x2702 +#define GL_LINEAR_MIPMAP_LINEAR 0x2703 +#define GL_TEXTURE_MAG_FILTER 0x2800 +#define GL_TEXTURE_MIN_FILTER 0x2801 +#define GL_TEXTURE_WRAP_S 0x2802 +#define GL_TEXTURE_WRAP_T 0x2803 +#define GL_REPEAT 0x2901 +#define GL_COLOR_LOGIC_OP 0x0BF2 +#define GL_POLYGON_OFFSET_UNITS 0x2A00 +#define GL_POLYGON_OFFSET_POINT 0x2A01 +#define GL_POLYGON_OFFSET_LINE 0x2A02 +#define GL_POLYGON_OFFSET_FILL 0x8037 +#define GL_POLYGON_OFFSET_FACTOR 0x8038 +#define GL_TEXTURE_BINDING_1D 0x8068 +#define GL_TEXTURE_BINDING_2D 0x8069 +#define GL_TEXTURE_INTERNAL_FORMAT 0x1003 +#define GL_TEXTURE_RED_SIZE 0x805C +#define GL_TEXTURE_GREEN_SIZE 0x805D +#define GL_TEXTURE_BLUE_SIZE 0x805E +#define GL_TEXTURE_ALPHA_SIZE 0x805F +#define GL_DOUBLE 0x140A +#define GL_PROXY_TEXTURE_1D 0x8063 +#define GL_PROXY_TEXTURE_2D 0x8064 +#define GL_R3_G3_B2 0x2A10 +#define GL_RGB4 0x804F +#define GL_RGB5 0x8050 +#define GL_RGB8 0x8051 +#define GL_RGB10 0x8052 +#define GL_RGB12 0x8053 +#define GL_RGB16 0x8054 +#define GL_RGBA2 0x8055 +#define GL_RGBA4 0x8056 +#define GL_RGB5_A1 0x8057 +#define GL_RGBA8 0x8058 +#define GL_RGB10_A2 0x8059 +#define GL_RGBA12 0x805A +#define GL_RGBA16 0x805B +#define GL_UNSIGNED_BYTE_3_3_2 0x8032 +#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033 +#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034 +#define GL_UNSIGNED_INT_8_8_8_8 0x8035 +#define GL_UNSIGNED_INT_10_10_10_2 0x8036 +#define GL_TEXTURE_BINDING_3D 0x806A +#define GL_PACK_SKIP_IMAGES 0x806B +#define GL_PACK_IMAGE_HEIGHT 0x806C +#define GL_UNPACK_SKIP_IMAGES 0x806D +#define GL_UNPACK_IMAGE_HEIGHT 0x806E +#define GL_TEXTURE_3D 0x806F +#define GL_PROXY_TEXTURE_3D 0x8070 +#define GL_TEXTURE_DEPTH 0x8071 +#define GL_TEXTURE_WRAP_R 0x8072 +#define GL_MAX_3D_TEXTURE_SIZE 0x8073 +#define GL_UNSIGNED_BYTE_2_3_3_REV 0x8362 +#define GL_UNSIGNED_SHORT_5_6_5 0x8363 +#define GL_UNSIGNED_SHORT_5_6_5_REV 0x8364 +#define GL_UNSIGNED_SHORT_4_4_4_4_REV 0x8365 +#define GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366 +#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367 +#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368 +#define GL_BGR 0x80E0 +#define GL_BGRA 0x80E1 +#define GL_MAX_ELEMENTS_VERTICES 0x80E8 +#define GL_MAX_ELEMENTS_INDICES 0x80E9 +#define GL_CLAMP_TO_EDGE 0x812F +#define GL_TEXTURE_MIN_LOD 0x813A +#define GL_TEXTURE_MAX_LOD 0x813B +#define GL_TEXTURE_BASE_LEVEL 0x813C +#define GL_TEXTURE_MAX_LEVEL 0x813D +#define GL_SMOOTH_POINT_SIZE_RANGE 0x0B12 +#define GL_SMOOTH_POINT_SIZE_GRANULARITY 0x0B13 +#define GL_SMOOTH_LINE_WIDTH_RANGE 0x0B22 +#define GL_SMOOTH_LINE_WIDTH_GRANULARITY 0x0B23 +#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E +#define GL_TEXTURE0 0x84C0 +#define GL_TEXTURE1 0x84C1 +#define GL_TEXTURE2 0x84C2 +#define GL_TEXTURE3 0x84C3 +#define GL_TEXTURE4 0x84C4 +#define GL_TEXTURE5 0x84C5 +#define GL_TEXTURE6 0x84C6 +#define GL_TEXTURE7 0x84C7 +#define GL_TEXTURE8 0x84C8 +#define GL_TEXTURE9 0x84C9 +#define GL_TEXTURE10 0x84CA +#define GL_TEXTURE11 0x84CB +#define GL_TEXTURE12 0x84CC +#define GL_TEXTURE13 0x84CD +#define GL_TEXTURE14 0x84CE +#define GL_TEXTURE15 0x84CF +#define GL_TEXTURE16 0x84D0 +#define GL_TEXTURE17 0x84D1 +#define GL_TEXTURE18 0x84D2 +#define GL_TEXTURE19 0x84D3 +#define GL_TEXTURE20 0x84D4 +#define GL_TEXTURE21 0x84D5 +#define GL_TEXTURE22 0x84D6 +#define GL_TEXTURE23 0x84D7 +#define GL_TEXTURE24 0x84D8 +#define GL_TEXTURE25 0x84D9 +#define GL_TEXTURE26 0x84DA +#define GL_TEXTURE27 0x84DB +#define GL_TEXTURE28 0x84DC +#define GL_TEXTURE29 0x84DD +#define GL_TEXTURE30 0x84DE +#define GL_TEXTURE31 0x84DF +#define GL_ACTIVE_TEXTURE 0x84E0 +#define GL_MULTISAMPLE 0x809D +#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E +#define GL_SAMPLE_ALPHA_TO_ONE 0x809F +#define GL_SAMPLE_COVERAGE 0x80A0 +#define GL_SAMPLE_BUFFERS 0x80A8 +#define GL_SAMPLES 0x80A9 +#define GL_SAMPLE_COVERAGE_VALUE 0x80AA +#define GL_SAMPLE_COVERAGE_INVERT 0x80AB +#define GL_TEXTURE_CUBE_MAP 0x8513 +#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A +#define GL_PROXY_TEXTURE_CUBE_MAP 0x851B +#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C +#define GL_COMPRESSED_RGB 0x84ED +#define GL_COMPRESSED_RGBA 0x84EE +#define GL_TEXTURE_COMPRESSION_HINT 0x84EF +#define GL_TEXTURE_COMPRESSED_IMAGE_SIZE 0x86A0 +#define GL_TEXTURE_COMPRESSED 0x86A1 +#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2 +#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3 +#define GL_CLAMP_TO_BORDER 0x812D +#define GL_BLEND_DST_RGB 0x80C8 +#define GL_BLEND_SRC_RGB 0x80C9 +#define GL_BLEND_DST_ALPHA 0x80CA +#define GL_BLEND_SRC_ALPHA 0x80CB +#define GL_POINT_FADE_THRESHOLD_SIZE 0x8128 +#define GL_DEPTH_COMPONENT16 0x81A5 +#define GL_DEPTH_COMPONENT24 0x81A6 +#define GL_DEPTH_COMPONENT32 0x81A7 +#define GL_MIRRORED_REPEAT 0x8370 +#define GL_MAX_TEXTURE_LOD_BIAS 0x84FD +#define GL_TEXTURE_LOD_BIAS 0x8501 +#define GL_INCR_WRAP 0x8507 +#define GL_DECR_WRAP 0x8508 +#define GL_TEXTURE_DEPTH_SIZE 0x884A +#define GL_TEXTURE_COMPARE_MODE 0x884C +#define GL_TEXTURE_COMPARE_FUNC 0x884D +#define GL_BLEND_COLOR 0x8005 +#define GL_BLEND_EQUATION 0x8009 +#define GL_CONSTANT_COLOR 0x8001 +#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002 +#define GL_CONSTANT_ALPHA 0x8003 +#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004 +#define GL_FUNC_ADD 0x8006 +#define GL_FUNC_REVERSE_SUBTRACT 0x800B +#define GL_FUNC_SUBTRACT 0x800A +#define GL_MIN 0x8007 +#define GL_MAX 0x8008 +#define GL_BUFFER_SIZE 0x8764 +#define GL_BUFFER_USAGE 0x8765 +#define GL_QUERY_COUNTER_BITS 0x8864 +#define GL_CURRENT_QUERY 0x8865 +#define GL_QUERY_RESULT 0x8866 +#define GL_QUERY_RESULT_AVAILABLE 0x8867 +#define GL_ARRAY_BUFFER 0x8892 +#define GL_ELEMENT_ARRAY_BUFFER 0x8893 +#define GL_ARRAY_BUFFER_BINDING 0x8894 +#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895 +#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F +#define GL_READ_ONLY 0x88B8 +#define GL_WRITE_ONLY 0x88B9 +#define GL_READ_WRITE 0x88BA +#define GL_BUFFER_ACCESS 0x88BB +#define GL_BUFFER_MAPPED 0x88BC +#define GL_BUFFER_MAP_POINTER 0x88BD +#define GL_STREAM_DRAW 0x88E0 +#define GL_STREAM_READ 0x88E1 +#define GL_STREAM_COPY 0x88E2 +#define GL_STATIC_DRAW 0x88E4 +#define GL_STATIC_READ 0x88E5 +#define GL_STATIC_COPY 0x88E6 +#define GL_DYNAMIC_DRAW 0x88E8 +#define GL_DYNAMIC_READ 0x88E9 +#define GL_DYNAMIC_COPY 0x88EA +#define GL_SAMPLES_PASSED 0x8914 +#define GL_SRC1_ALPHA 0x8589 +#define GL_BLEND_EQUATION_RGB 0x8009 +#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622 +#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623 +#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624 +#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625 +#define GL_CURRENT_VERTEX_ATTRIB 0x8626 +#define GL_VERTEX_PROGRAM_POINT_SIZE 0x8642 +#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645 +#define GL_STENCIL_BACK_FUNC 0x8800 +#define GL_STENCIL_BACK_FAIL 0x8801 +#define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802 +#define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803 +#define GL_MAX_DRAW_BUFFERS 0x8824 +#define GL_DRAW_BUFFER0 0x8825 +#define GL_DRAW_BUFFER1 0x8826 +#define GL_DRAW_BUFFER2 0x8827 +#define GL_DRAW_BUFFER3 0x8828 +#define GL_DRAW_BUFFER4 0x8829 +#define GL_DRAW_BUFFER5 0x882A +#define GL_DRAW_BUFFER6 0x882B +#define GL_DRAW_BUFFER7 0x882C +#define GL_DRAW_BUFFER8 0x882D +#define GL_DRAW_BUFFER9 0x882E +#define GL_DRAW_BUFFER10 0x882F +#define GL_DRAW_BUFFER11 0x8830 +#define GL_DRAW_BUFFER12 0x8831 +#define GL_DRAW_BUFFER13 0x8832 +#define GL_DRAW_BUFFER14 0x8833 +#define GL_DRAW_BUFFER15 0x8834 +#define GL_BLEND_EQUATION_ALPHA 0x883D +#define GL_MAX_VERTEX_ATTRIBS 0x8869 +#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A +#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872 +#define GL_FRAGMENT_SHADER 0x8B30 +#define GL_VERTEX_SHADER 0x8B31 +#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS 0x8B49 +#define GL_MAX_VERTEX_UNIFORM_COMPONENTS 0x8B4A +#define GL_MAX_VARYING_FLOATS 0x8B4B +#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C +#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D +#define GL_SHADER_TYPE 0x8B4F +#define GL_FLOAT_VEC2 0x8B50 +#define GL_FLOAT_VEC3 0x8B51 +#define GL_FLOAT_VEC4 0x8B52 +#define GL_INT_VEC2 0x8B53 +#define GL_INT_VEC3 0x8B54 +#define GL_INT_VEC4 0x8B55 +#define GL_BOOL 0x8B56 +#define GL_BOOL_VEC2 0x8B57 +#define GL_BOOL_VEC3 0x8B58 +#define GL_BOOL_VEC4 0x8B59 +#define GL_FLOAT_MAT2 0x8B5A +#define GL_FLOAT_MAT3 0x8B5B +#define GL_FLOAT_MAT4 0x8B5C +#define GL_SAMPLER_1D 0x8B5D +#define GL_SAMPLER_2D 0x8B5E +#define GL_SAMPLER_3D 0x8B5F +#define GL_SAMPLER_CUBE 0x8B60 +#define GL_SAMPLER_1D_SHADOW 0x8B61 +#define GL_SAMPLER_2D_SHADOW 0x8B62 +#define GL_DELETE_STATUS 0x8B80 +#define GL_COMPILE_STATUS 0x8B81 +#define GL_LINK_STATUS 0x8B82 +#define GL_VALIDATE_STATUS 0x8B83 +#define GL_INFO_LOG_LENGTH 0x8B84 +#define GL_ATTACHED_SHADERS 0x8B85 +#define GL_ACTIVE_UNIFORMS 0x8B86 +#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87 +#define GL_SHADER_SOURCE_LENGTH 0x8B88 +#define GL_ACTIVE_ATTRIBUTES 0x8B89 +#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A +#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT 0x8B8B +#define GL_SHADING_LANGUAGE_VERSION 0x8B8C +#define GL_CURRENT_PROGRAM 0x8B8D +#define GL_POINT_SPRITE_COORD_ORIGIN 0x8CA0 +#define GL_LOWER_LEFT 0x8CA1 +#define GL_UPPER_LEFT 0x8CA2 +#define GL_STENCIL_BACK_REF 0x8CA3 +#define GL_STENCIL_BACK_VALUE_MASK 0x8CA4 +#define GL_STENCIL_BACK_WRITEMASK 0x8CA5 +#define GL_PIXEL_PACK_BUFFER 0x88EB +#define GL_PIXEL_UNPACK_BUFFER 0x88EC +#define GL_PIXEL_PACK_BUFFER_BINDING 0x88ED +#define GL_PIXEL_UNPACK_BUFFER_BINDING 0x88EF +#define GL_FLOAT_MAT2x3 0x8B65 +#define GL_FLOAT_MAT2x4 0x8B66 +#define GL_FLOAT_MAT3x2 0x8B67 +#define GL_FLOAT_MAT3x4 0x8B68 +#define GL_FLOAT_MAT4x2 0x8B69 +#define GL_FLOAT_MAT4x3 0x8B6A +#define GL_SRGB 0x8C40 +#define GL_SRGB8 0x8C41 +#define GL_SRGB_ALPHA 0x8C42 +#define GL_SRGB8_ALPHA8 0x8C43 +#define GL_COMPRESSED_SRGB 0x8C48 +#define GL_COMPRESSED_SRGB_ALPHA 0x8C49 +#define GL_COMPARE_REF_TO_TEXTURE 0x884E +#define GL_CLIP_DISTANCE0 0x3000 +#define GL_CLIP_DISTANCE1 0x3001 +#define GL_CLIP_DISTANCE2 0x3002 +#define GL_CLIP_DISTANCE3 0x3003 +#define GL_CLIP_DISTANCE4 0x3004 +#define GL_CLIP_DISTANCE5 0x3005 +#define GL_CLIP_DISTANCE6 0x3006 +#define GL_CLIP_DISTANCE7 0x3007 +#define GL_MAX_CLIP_DISTANCES 0x0D32 +#define GL_MAJOR_VERSION 0x821B +#define GL_MINOR_VERSION 0x821C +#define GL_NUM_EXTENSIONS 0x821D +#define GL_CONTEXT_FLAGS 0x821E +#define GL_COMPRESSED_RED 0x8225 +#define GL_COMPRESSED_RG 0x8226 +#define GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT 0x00000001 +#define GL_RGBA32F 0x8814 +#define GL_RGB32F 0x8815 +#define GL_RGBA16F 0x881A +#define GL_RGB16F 0x881B +#define GL_VERTEX_ATTRIB_ARRAY_INTEGER 0x88FD +#define GL_MAX_ARRAY_TEXTURE_LAYERS 0x88FF +#define GL_MIN_PROGRAM_TEXEL_OFFSET 0x8904 +#define GL_MAX_PROGRAM_TEXEL_OFFSET 0x8905 +#define GL_CLAMP_READ_COLOR 0x891C +#define GL_FIXED_ONLY 0x891D +#define GL_MAX_VARYING_COMPONENTS 0x8B4B +#define GL_TEXTURE_1D_ARRAY 0x8C18 +#define GL_PROXY_TEXTURE_1D_ARRAY 0x8C19 +#define GL_TEXTURE_2D_ARRAY 0x8C1A +#define GL_PROXY_TEXTURE_2D_ARRAY 0x8C1B +#define GL_TEXTURE_BINDING_1D_ARRAY 0x8C1C +#define GL_TEXTURE_BINDING_2D_ARRAY 0x8C1D +#define GL_R11F_G11F_B10F 0x8C3A +#define GL_UNSIGNED_INT_10F_11F_11F_REV 0x8C3B +#define GL_RGB9_E5 0x8C3D +#define GL_UNSIGNED_INT_5_9_9_9_REV 0x8C3E +#define GL_TEXTURE_SHARED_SIZE 0x8C3F +#define GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH 0x8C76 +#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE 0x8C7F +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS 0x8C80 +#define GL_TRANSFORM_FEEDBACK_VARYINGS 0x8C83 +#define GL_TRANSFORM_FEEDBACK_BUFFER_START 0x8C84 +#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE 0x8C85 +#define GL_PRIMITIVES_GENERATED 0x8C87 +#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN 0x8C88 +#define GL_RASTERIZER_DISCARD 0x8C89 +#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS 0x8C8A +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS 0x8C8B +#define GL_INTERLEAVED_ATTRIBS 0x8C8C +#define GL_SEPARATE_ATTRIBS 0x8C8D +#define GL_TRANSFORM_FEEDBACK_BUFFER 0x8C8E +#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING 0x8C8F +#define GL_RGBA32UI 0x8D70 +#define GL_RGB32UI 0x8D71 +#define GL_RGBA16UI 0x8D76 +#define GL_RGB16UI 0x8D77 +#define GL_RGBA8UI 0x8D7C +#define GL_RGB8UI 0x8D7D +#define GL_RGBA32I 0x8D82 +#define GL_RGB32I 0x8D83 +#define GL_RGBA16I 0x8D88 +#define GL_RGB16I 0x8D89 +#define GL_RGBA8I 0x8D8E +#define GL_RGB8I 0x8D8F +#define GL_RED_INTEGER 0x8D94 +#define GL_GREEN_INTEGER 0x8D95 +#define GL_BLUE_INTEGER 0x8D96 +#define GL_RGB_INTEGER 0x8D98 +#define GL_RGBA_INTEGER 0x8D99 +#define GL_BGR_INTEGER 0x8D9A +#define GL_BGRA_INTEGER 0x8D9B +#define GL_SAMPLER_1D_ARRAY 0x8DC0 +#define GL_SAMPLER_2D_ARRAY 0x8DC1 +#define GL_SAMPLER_1D_ARRAY_SHADOW 0x8DC3 +#define GL_SAMPLER_2D_ARRAY_SHADOW 0x8DC4 +#define GL_SAMPLER_CUBE_SHADOW 0x8DC5 +#define GL_UNSIGNED_INT_VEC2 0x8DC6 +#define GL_UNSIGNED_INT_VEC3 0x8DC7 +#define GL_UNSIGNED_INT_VEC4 0x8DC8 +#define GL_INT_SAMPLER_1D 0x8DC9 +#define GL_INT_SAMPLER_2D 0x8DCA +#define GL_INT_SAMPLER_3D 0x8DCB +#define GL_INT_SAMPLER_CUBE 0x8DCC +#define GL_INT_SAMPLER_1D_ARRAY 0x8DCE +#define GL_INT_SAMPLER_2D_ARRAY 0x8DCF +#define GL_UNSIGNED_INT_SAMPLER_1D 0x8DD1 +#define GL_UNSIGNED_INT_SAMPLER_2D 0x8DD2 +#define GL_UNSIGNED_INT_SAMPLER_3D 0x8DD3 +#define GL_UNSIGNED_INT_SAMPLER_CUBE 0x8DD4 +#define GL_UNSIGNED_INT_SAMPLER_1D_ARRAY 0x8DD6 +#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY 0x8DD7 +#define GL_QUERY_WAIT 0x8E13 +#define GL_QUERY_NO_WAIT 0x8E14 +#define GL_QUERY_BY_REGION_WAIT 0x8E15 +#define GL_QUERY_BY_REGION_NO_WAIT 0x8E16 +#define GL_BUFFER_ACCESS_FLAGS 0x911F +#define GL_BUFFER_MAP_LENGTH 0x9120 +#define GL_BUFFER_MAP_OFFSET 0x9121 +#define GL_DEPTH_COMPONENT32F 0x8CAC +#define GL_DEPTH32F_STENCIL8 0x8CAD +#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV 0x8DAD +#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506 +#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING 0x8210 +#define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE 0x8211 +#define GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE 0x8212 +#define GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE 0x8213 +#define GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE 0x8214 +#define GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE 0x8215 +#define GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE 0x8216 +#define GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE 0x8217 +#define GL_FRAMEBUFFER_DEFAULT 0x8218 +#define GL_FRAMEBUFFER_UNDEFINED 0x8219 +#define GL_DEPTH_STENCIL_ATTACHMENT 0x821A +#define GL_MAX_RENDERBUFFER_SIZE 0x84E8 +#define GL_DEPTH_STENCIL 0x84F9 +#define GL_UNSIGNED_INT_24_8 0x84FA +#define GL_DEPTH24_STENCIL8 0x88F0 +#define GL_TEXTURE_STENCIL_SIZE 0x88F1 +#define GL_TEXTURE_RED_TYPE 0x8C10 +#define GL_TEXTURE_GREEN_TYPE 0x8C11 +#define GL_TEXTURE_BLUE_TYPE 0x8C12 +#define GL_TEXTURE_ALPHA_TYPE 0x8C13 +#define GL_TEXTURE_DEPTH_TYPE 0x8C16 +#define GL_UNSIGNED_NORMALIZED 0x8C17 +#define GL_FRAMEBUFFER_BINDING 0x8CA6 +#define GL_DRAW_FRAMEBUFFER_BINDING 0x8CA6 +#define GL_RENDERBUFFER_BINDING 0x8CA7 +#define GL_READ_FRAMEBUFFER 0x8CA8 +#define GL_DRAW_FRAMEBUFFER 0x8CA9 +#define GL_READ_FRAMEBUFFER_BINDING 0x8CAA +#define GL_RENDERBUFFER_SAMPLES 0x8CAB +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0 +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER 0x8CD4 +#define GL_FRAMEBUFFER_COMPLETE 0x8CD5 +#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6 +#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7 +#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER 0x8CDB +#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER 0x8CDC +#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD +#define GL_MAX_COLOR_ATTACHMENTS 0x8CDF +#define GL_COLOR_ATTACHMENT0 0x8CE0 +#define GL_COLOR_ATTACHMENT1 0x8CE1 +#define GL_COLOR_ATTACHMENT2 0x8CE2 +#define GL_COLOR_ATTACHMENT3 0x8CE3 +#define GL_COLOR_ATTACHMENT4 0x8CE4 +#define GL_COLOR_ATTACHMENT5 0x8CE5 +#define GL_COLOR_ATTACHMENT6 0x8CE6 +#define GL_COLOR_ATTACHMENT7 0x8CE7 +#define GL_COLOR_ATTACHMENT8 0x8CE8 +#define GL_COLOR_ATTACHMENT9 0x8CE9 +#define GL_COLOR_ATTACHMENT10 0x8CEA +#define GL_COLOR_ATTACHMENT11 0x8CEB +#define GL_COLOR_ATTACHMENT12 0x8CEC +#define GL_COLOR_ATTACHMENT13 0x8CED +#define GL_COLOR_ATTACHMENT14 0x8CEE +#define GL_COLOR_ATTACHMENT15 0x8CEF +#define GL_COLOR_ATTACHMENT16 0x8CF0 +#define GL_COLOR_ATTACHMENT17 0x8CF1 +#define GL_COLOR_ATTACHMENT18 0x8CF2 +#define GL_COLOR_ATTACHMENT19 0x8CF3 +#define GL_COLOR_ATTACHMENT20 0x8CF4 +#define GL_COLOR_ATTACHMENT21 0x8CF5 +#define GL_COLOR_ATTACHMENT22 0x8CF6 +#define GL_COLOR_ATTACHMENT23 0x8CF7 +#define GL_COLOR_ATTACHMENT24 0x8CF8 +#define GL_COLOR_ATTACHMENT25 0x8CF9 +#define GL_COLOR_ATTACHMENT26 0x8CFA +#define GL_COLOR_ATTACHMENT27 0x8CFB +#define GL_COLOR_ATTACHMENT28 0x8CFC +#define GL_COLOR_ATTACHMENT29 0x8CFD +#define GL_COLOR_ATTACHMENT30 0x8CFE +#define GL_COLOR_ATTACHMENT31 0x8CFF +#define GL_DEPTH_ATTACHMENT 0x8D00 +#define GL_STENCIL_ATTACHMENT 0x8D20 +#define GL_FRAMEBUFFER 0x8D40 +#define GL_RENDERBUFFER 0x8D41 +#define GL_RENDERBUFFER_WIDTH 0x8D42 +#define GL_RENDERBUFFER_HEIGHT 0x8D43 +#define GL_RENDERBUFFER_INTERNAL_FORMAT 0x8D44 +#define GL_STENCIL_INDEX1 0x8D46 +#define GL_STENCIL_INDEX4 0x8D47 +#define GL_STENCIL_INDEX8 0x8D48 +#define GL_STENCIL_INDEX16 0x8D49 +#define GL_RENDERBUFFER_RED_SIZE 0x8D50 +#define GL_RENDERBUFFER_GREEN_SIZE 0x8D51 +#define GL_RENDERBUFFER_BLUE_SIZE 0x8D52 +#define GL_RENDERBUFFER_ALPHA_SIZE 0x8D53 +#define GL_RENDERBUFFER_DEPTH_SIZE 0x8D54 +#define GL_RENDERBUFFER_STENCIL_SIZE 0x8D55 +#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 0x8D56 +#define GL_MAX_SAMPLES 0x8D57 +#define GL_FRAMEBUFFER_SRGB 0x8DB9 +#define GL_HALF_FLOAT 0x140B +#define GL_MAP_READ_BIT 0x0001 +#define GL_MAP_WRITE_BIT 0x0002 +#define GL_MAP_INVALIDATE_RANGE_BIT 0x0004 +#define GL_MAP_INVALIDATE_BUFFER_BIT 0x0008 +#define GL_MAP_FLUSH_EXPLICIT_BIT 0x0010 +#define GL_MAP_UNSYNCHRONIZED_BIT 0x0020 +#define GL_COMPRESSED_RED_RGTC1 0x8DBB +#define GL_COMPRESSED_SIGNED_RED_RGTC1 0x8DBC +#define GL_COMPRESSED_RG_RGTC2 0x8DBD +#define GL_COMPRESSED_SIGNED_RG_RGTC2 0x8DBE +#define GL_RG 0x8227 +#define GL_RG_INTEGER 0x8228 +#define GL_R8 0x8229 +#define GL_R16 0x822A +#define GL_RG8 0x822B +#define GL_RG16 0x822C +#define GL_R16F 0x822D +#define GL_R32F 0x822E +#define GL_RG16F 0x822F +#define GL_RG32F 0x8230 +#define GL_R8I 0x8231 +#define GL_R8UI 0x8232 +#define GL_R16I 0x8233 +#define GL_R16UI 0x8234 +#define GL_R32I 0x8235 +#define GL_R32UI 0x8236 +#define GL_RG8I 0x8237 +#define GL_RG8UI 0x8238 +#define GL_RG16I 0x8239 +#define GL_RG16UI 0x823A +#define GL_RG32I 0x823B +#define GL_RG32UI 0x823C +#define GL_VERTEX_ARRAY_BINDING 0x85B5 +#define GL_SAMPLER_2D_RECT 0x8B63 +#define GL_SAMPLER_2D_RECT_SHADOW 0x8B64 +#define GL_SAMPLER_BUFFER 0x8DC2 +#define GL_INT_SAMPLER_2D_RECT 0x8DCD +#define GL_INT_SAMPLER_BUFFER 0x8DD0 +#define GL_UNSIGNED_INT_SAMPLER_2D_RECT 0x8DD5 +#define GL_UNSIGNED_INT_SAMPLER_BUFFER 0x8DD8 +#define GL_TEXTURE_BUFFER 0x8C2A +#define GL_MAX_TEXTURE_BUFFER_SIZE 0x8C2B +#define GL_TEXTURE_BINDING_BUFFER 0x8C2C +#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING 0x8C2D +#define GL_TEXTURE_RECTANGLE 0x84F5 +#define GL_TEXTURE_BINDING_RECTANGLE 0x84F6 +#define GL_PROXY_TEXTURE_RECTANGLE 0x84F7 +#define GL_MAX_RECTANGLE_TEXTURE_SIZE 0x84F8 +#define GL_R8_SNORM 0x8F94 +#define GL_RG8_SNORM 0x8F95 +#define GL_RGB8_SNORM 0x8F96 +#define GL_RGBA8_SNORM 0x8F97 +#define GL_R16_SNORM 0x8F98 +#define GL_RG16_SNORM 0x8F99 +#define GL_RGB16_SNORM 0x8F9A +#define GL_RGBA16_SNORM 0x8F9B +#define GL_SIGNED_NORMALIZED 0x8F9C +#define GL_PRIMITIVE_RESTART 0x8F9D +#define GL_PRIMITIVE_RESTART_INDEX 0x8F9E +#define GL_COPY_READ_BUFFER 0x8F36 +#define GL_COPY_WRITE_BUFFER 0x8F37 +#define GL_UNIFORM_BUFFER 0x8A11 +#define GL_UNIFORM_BUFFER_BINDING 0x8A28 +#define GL_UNIFORM_BUFFER_START 0x8A29 +#define GL_UNIFORM_BUFFER_SIZE 0x8A2A +#define GL_MAX_VERTEX_UNIFORM_BLOCKS 0x8A2B +#define GL_MAX_GEOMETRY_UNIFORM_BLOCKS 0x8A2C +#define GL_MAX_FRAGMENT_UNIFORM_BLOCKS 0x8A2D +#define GL_MAX_COMBINED_UNIFORM_BLOCKS 0x8A2E +#define GL_MAX_UNIFORM_BUFFER_BINDINGS 0x8A2F +#define GL_MAX_UNIFORM_BLOCK_SIZE 0x8A30 +#define GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS 0x8A31 +#define GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS 0x8A32 +#define GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS 0x8A33 +#define GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT 0x8A34 +#define GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH 0x8A35 +#define GL_ACTIVE_UNIFORM_BLOCKS 0x8A36 +#define GL_UNIFORM_TYPE 0x8A37 +#define GL_UNIFORM_SIZE 0x8A38 +#define GL_UNIFORM_NAME_LENGTH 0x8A39 +#define GL_UNIFORM_BLOCK_INDEX 0x8A3A +#define GL_UNIFORM_OFFSET 0x8A3B +#define GL_UNIFORM_ARRAY_STRIDE 0x8A3C +#define GL_UNIFORM_MATRIX_STRIDE 0x8A3D +#define GL_UNIFORM_IS_ROW_MAJOR 0x8A3E +#define GL_UNIFORM_BLOCK_BINDING 0x8A3F +#define GL_UNIFORM_BLOCK_DATA_SIZE 0x8A40 +#define GL_UNIFORM_BLOCK_NAME_LENGTH 0x8A41 +#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS 0x8A42 +#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES 0x8A43 +#define GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER 0x8A44 +#define GL_UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER 0x8A45 +#define GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER 0x8A46 +#define GL_INVALID_INDEX 0xFFFFFFFF +#define GL_CONTEXT_CORE_PROFILE_BIT 0x00000001 +#define GL_CONTEXT_COMPATIBILITY_PROFILE_BIT 0x00000002 +#define GL_LINES_ADJACENCY 0x000A +#define GL_LINE_STRIP_ADJACENCY 0x000B +#define GL_TRIANGLES_ADJACENCY 0x000C +#define GL_TRIANGLE_STRIP_ADJACENCY 0x000D +#define GL_PROGRAM_POINT_SIZE 0x8642 +#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS 0x8C29 +#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED 0x8DA7 +#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS 0x8DA8 +#define GL_GEOMETRY_SHADER 0x8DD9 +#define GL_GEOMETRY_VERTICES_OUT 0x8916 +#define GL_GEOMETRY_INPUT_TYPE 0x8917 +#define GL_GEOMETRY_OUTPUT_TYPE 0x8918 +#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS 0x8DDF +#define GL_MAX_GEOMETRY_OUTPUT_VERTICES 0x8DE0 +#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS 0x8DE1 +#define GL_MAX_VERTEX_OUTPUT_COMPONENTS 0x9122 +#define GL_MAX_GEOMETRY_INPUT_COMPONENTS 0x9123 +#define GL_MAX_GEOMETRY_OUTPUT_COMPONENTS 0x9124 +#define GL_MAX_FRAGMENT_INPUT_COMPONENTS 0x9125 +#define GL_CONTEXT_PROFILE_MASK 0x9126 +#define GL_DEPTH_CLAMP 0x864F +#define GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION 0x8E4C +#define GL_FIRST_VERTEX_CONVENTION 0x8E4D +#define GL_LAST_VERTEX_CONVENTION 0x8E4E +#define GL_PROVOKING_VERTEX 0x8E4F +#define GL_TEXTURE_CUBE_MAP_SEAMLESS 0x884F +#define GL_MAX_SERVER_WAIT_TIMEOUT 0x9111 +#define GL_OBJECT_TYPE 0x9112 +#define GL_SYNC_CONDITION 0x9113 +#define GL_SYNC_STATUS 0x9114 +#define GL_SYNC_FLAGS 0x9115 +#define GL_SYNC_FENCE 0x9116 +#define GL_SYNC_GPU_COMMANDS_COMPLETE 0x9117 +#define GL_UNSIGNALED 0x9118 +#define GL_SIGNALED 0x9119 +#define GL_ALREADY_SIGNALED 0x911A +#define GL_TIMEOUT_EXPIRED 0x911B +#define GL_CONDITION_SATISFIED 0x911C +#define GL_WAIT_FAILED 0x911D +#define GL_TIMEOUT_IGNORED 0xFFFFFFFFFFFFFFFF +#define GL_SYNC_FLUSH_COMMANDS_BIT 0x00000001 +#define GL_SAMPLE_POSITION 0x8E50 +#define GL_SAMPLE_MASK 0x8E51 +#define GL_SAMPLE_MASK_VALUE 0x8E52 +#define GL_MAX_SAMPLE_MASK_WORDS 0x8E59 +#define GL_TEXTURE_2D_MULTISAMPLE 0x9100 +#define GL_PROXY_TEXTURE_2D_MULTISAMPLE 0x9101 +#define GL_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9102 +#define GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9103 +#define GL_TEXTURE_BINDING_2D_MULTISAMPLE 0x9104 +#define GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY 0x9105 +#define GL_TEXTURE_SAMPLES 0x9106 +#define GL_TEXTURE_FIXED_SAMPLE_LOCATIONS 0x9107 +#define GL_SAMPLER_2D_MULTISAMPLE 0x9108 +#define GL_INT_SAMPLER_2D_MULTISAMPLE 0x9109 +#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE 0x910A +#define GL_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910B +#define GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910C +#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910D +#define GL_MAX_COLOR_TEXTURE_SAMPLES 0x910E +#define GL_MAX_DEPTH_TEXTURE_SAMPLES 0x910F +#define GL_MAX_INTEGER_SAMPLES 0x9110 +#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR 0x88FE +#define GL_SRC1_COLOR 0x88F9 +#define GL_ONE_MINUS_SRC1_COLOR 0x88FA +#define GL_ONE_MINUS_SRC1_ALPHA 0x88FB +#define GL_MAX_DUAL_SOURCE_DRAW_BUFFERS 0x88FC +#define GL_ANY_SAMPLES_PASSED 0x8C2F +#define GL_SAMPLER_BINDING 0x8919 +#define GL_RGB10_A2UI 0x906F +#define GL_TEXTURE_SWIZZLE_R 0x8E42 +#define GL_TEXTURE_SWIZZLE_G 0x8E43 +#define GL_TEXTURE_SWIZZLE_B 0x8E44 +#define GL_TEXTURE_SWIZZLE_A 0x8E45 +#define GL_TEXTURE_SWIZZLE_RGBA 0x8E46 +#define GL_TIME_ELAPSED 0x88BF +#define GL_TIMESTAMP 0x8E28 +#define GL_INT_2_10_10_10_REV 0x8D9F +#ifndef GL_VERSION_1_0 +#define GL_VERSION_1_0 1 +GLAPI int GLAD_GL_VERSION_1_0; +typedef void (APIENTRYP PFNGLCULLFACEPROC)(GLenum mode); +GLAPI PFNGLCULLFACEPROC glad_glCullFace; +#define glCullFace glad_glCullFace +typedef void (APIENTRYP PFNGLFRONTFACEPROC)(GLenum mode); +GLAPI PFNGLFRONTFACEPROC glad_glFrontFace; +#define glFrontFace glad_glFrontFace +typedef void (APIENTRYP PFNGLHINTPROC)(GLenum target, GLenum mode); +GLAPI PFNGLHINTPROC glad_glHint; +#define glHint glad_glHint +typedef void (APIENTRYP PFNGLLINEWIDTHPROC)(GLfloat width); +GLAPI PFNGLLINEWIDTHPROC glad_glLineWidth; +#define glLineWidth glad_glLineWidth +typedef void (APIENTRYP PFNGLPOINTSIZEPROC)(GLfloat size); +GLAPI PFNGLPOINTSIZEPROC glad_glPointSize; +#define glPointSize glad_glPointSize +typedef void (APIENTRYP PFNGLPOLYGONMODEPROC)(GLenum face, GLenum mode); +GLAPI PFNGLPOLYGONMODEPROC glad_glPolygonMode; +#define glPolygonMode glad_glPolygonMode +typedef void (APIENTRYP PFNGLSCISSORPROC)(GLint x, GLint y, GLsizei width, GLsizei height); +GLAPI PFNGLSCISSORPROC glad_glScissor; +#define glScissor glad_glScissor +typedef void (APIENTRYP PFNGLTEXPARAMETERFPROC)(GLenum target, GLenum pname, GLfloat param); +GLAPI PFNGLTEXPARAMETERFPROC glad_glTexParameterf; +#define glTexParameterf glad_glTexParameterf +typedef void (APIENTRYP PFNGLTEXPARAMETERFVPROC)(GLenum target, GLenum pname, const GLfloat *params); +GLAPI PFNGLTEXPARAMETERFVPROC glad_glTexParameterfv; +#define glTexParameterfv glad_glTexParameterfv +typedef void (APIENTRYP PFNGLTEXPARAMETERIPROC)(GLenum target, GLenum pname, GLint param); +GLAPI PFNGLTEXPARAMETERIPROC glad_glTexParameteri; +#define glTexParameteri glad_glTexParameteri +typedef void (APIENTRYP PFNGLTEXPARAMETERIVPROC)(GLenum target, GLenum pname, const GLint *params); +GLAPI PFNGLTEXPARAMETERIVPROC glad_glTexParameteriv; +#define glTexParameteriv glad_glTexParameteriv +typedef void (APIENTRYP PFNGLTEXIMAGE1DPROC)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const void *pixels); +GLAPI PFNGLTEXIMAGE1DPROC glad_glTexImage1D; +#define glTexImage1D glad_glTexImage1D +typedef void (APIENTRYP PFNGLTEXIMAGE2DPROC)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels); +GLAPI PFNGLTEXIMAGE2DPROC glad_glTexImage2D; +#define glTexImage2D glad_glTexImage2D +typedef void (APIENTRYP PFNGLDRAWBUFFERPROC)(GLenum buf); +GLAPI PFNGLDRAWBUFFERPROC glad_glDrawBuffer; +#define glDrawBuffer glad_glDrawBuffer +typedef void (APIENTRYP PFNGLCLEARPROC)(GLbitfield mask); +GLAPI PFNGLCLEARPROC glad_glClear; +#define glClear glad_glClear +typedef void (APIENTRYP PFNGLCLEARCOLORPROC)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); +GLAPI PFNGLCLEARCOLORPROC glad_glClearColor; +#define glClearColor glad_glClearColor +typedef void (APIENTRYP PFNGLCLEARSTENCILPROC)(GLint s); +GLAPI PFNGLCLEARSTENCILPROC glad_glClearStencil; +#define glClearStencil glad_glClearStencil +typedef void (APIENTRYP PFNGLCLEARDEPTHPROC)(GLdouble depth); +GLAPI PFNGLCLEARDEPTHPROC glad_glClearDepth; +#define glClearDepth glad_glClearDepth +typedef void (APIENTRYP PFNGLSTENCILMASKPROC)(GLuint mask); +GLAPI PFNGLSTENCILMASKPROC glad_glStencilMask; +#define glStencilMask glad_glStencilMask +typedef void (APIENTRYP PFNGLCOLORMASKPROC)(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); +GLAPI PFNGLCOLORMASKPROC glad_glColorMask; +#define glColorMask glad_glColorMask +typedef void (APIENTRYP PFNGLDEPTHMASKPROC)(GLboolean flag); +GLAPI PFNGLDEPTHMASKPROC glad_glDepthMask; +#define glDepthMask glad_glDepthMask +typedef void (APIENTRYP PFNGLDISABLEPROC)(GLenum cap); +GLAPI PFNGLDISABLEPROC glad_glDisable; +#define glDisable glad_glDisable +typedef void (APIENTRYP PFNGLENABLEPROC)(GLenum cap); +GLAPI PFNGLENABLEPROC glad_glEnable; +#define glEnable glad_glEnable +typedef void (APIENTRYP PFNGLFINISHPROC)(void); +GLAPI PFNGLFINISHPROC glad_glFinish; +#define glFinish glad_glFinish +typedef void (APIENTRYP PFNGLFLUSHPROC)(void); +GLAPI PFNGLFLUSHPROC glad_glFlush; +#define glFlush glad_glFlush +typedef void (APIENTRYP PFNGLBLENDFUNCPROC)(GLenum sfactor, GLenum dfactor); +GLAPI PFNGLBLENDFUNCPROC glad_glBlendFunc; +#define glBlendFunc glad_glBlendFunc +typedef void (APIENTRYP PFNGLLOGICOPPROC)(GLenum opcode); +GLAPI PFNGLLOGICOPPROC glad_glLogicOp; +#define glLogicOp glad_glLogicOp +typedef void (APIENTRYP PFNGLSTENCILFUNCPROC)(GLenum func, GLint ref, GLuint mask); +GLAPI PFNGLSTENCILFUNCPROC glad_glStencilFunc; +#define glStencilFunc glad_glStencilFunc +typedef void (APIENTRYP PFNGLSTENCILOPPROC)(GLenum fail, GLenum zfail, GLenum zpass); +GLAPI PFNGLSTENCILOPPROC glad_glStencilOp; +#define glStencilOp glad_glStencilOp +typedef void (APIENTRYP PFNGLDEPTHFUNCPROC)(GLenum func); +GLAPI PFNGLDEPTHFUNCPROC glad_glDepthFunc; +#define glDepthFunc glad_glDepthFunc +typedef void (APIENTRYP PFNGLPIXELSTOREFPROC)(GLenum pname, GLfloat param); +GLAPI PFNGLPIXELSTOREFPROC glad_glPixelStoref; +#define glPixelStoref glad_glPixelStoref +typedef void (APIENTRYP PFNGLPIXELSTOREIPROC)(GLenum pname, GLint param); +GLAPI PFNGLPIXELSTOREIPROC glad_glPixelStorei; +#define glPixelStorei glad_glPixelStorei +typedef void (APIENTRYP PFNGLREADBUFFERPROC)(GLenum src); +GLAPI PFNGLREADBUFFERPROC glad_glReadBuffer; +#define glReadBuffer glad_glReadBuffer +typedef void (APIENTRYP PFNGLREADPIXELSPROC)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels); +GLAPI PFNGLREADPIXELSPROC glad_glReadPixels; +#define glReadPixels glad_glReadPixels +typedef void (APIENTRYP PFNGLGETBOOLEANVPROC)(GLenum pname, GLboolean *data); +GLAPI PFNGLGETBOOLEANVPROC glad_glGetBooleanv; +#define glGetBooleanv glad_glGetBooleanv +typedef void (APIENTRYP PFNGLGETDOUBLEVPROC)(GLenum pname, GLdouble *data); +GLAPI PFNGLGETDOUBLEVPROC glad_glGetDoublev; +#define glGetDoublev glad_glGetDoublev +typedef GLenum (APIENTRYP PFNGLGETERRORPROC)(void); +GLAPI PFNGLGETERRORPROC glad_glGetError; +#define glGetError glad_glGetError +typedef void (APIENTRYP PFNGLGETFLOATVPROC)(GLenum pname, GLfloat *data); +GLAPI PFNGLGETFLOATVPROC glad_glGetFloatv; +#define glGetFloatv glad_glGetFloatv +typedef void (APIENTRYP PFNGLGETINTEGERVPROC)(GLenum pname, GLint *data); +GLAPI PFNGLGETINTEGERVPROC glad_glGetIntegerv; +#define glGetIntegerv glad_glGetIntegerv +typedef const GLubyte * (APIENTRYP PFNGLGETSTRINGPROC)(GLenum name); +GLAPI PFNGLGETSTRINGPROC glad_glGetString; +#define glGetString glad_glGetString +typedef void (APIENTRYP PFNGLGETTEXIMAGEPROC)(GLenum target, GLint level, GLenum format, GLenum type, void *pixels); +GLAPI PFNGLGETTEXIMAGEPROC glad_glGetTexImage; +#define glGetTexImage glad_glGetTexImage +typedef void (APIENTRYP PFNGLGETTEXPARAMETERFVPROC)(GLenum target, GLenum pname, GLfloat *params); +GLAPI PFNGLGETTEXPARAMETERFVPROC glad_glGetTexParameterfv; +#define glGetTexParameterfv glad_glGetTexParameterfv +typedef void (APIENTRYP PFNGLGETTEXPARAMETERIVPROC)(GLenum target, GLenum pname, GLint *params); +GLAPI PFNGLGETTEXPARAMETERIVPROC glad_glGetTexParameteriv; +#define glGetTexParameteriv glad_glGetTexParameteriv +typedef void (APIENTRYP PFNGLGETTEXLEVELPARAMETERFVPROC)(GLenum target, GLint level, GLenum pname, GLfloat *params); +GLAPI PFNGLGETTEXLEVELPARAMETERFVPROC glad_glGetTexLevelParameterfv; +#define glGetTexLevelParameterfv glad_glGetTexLevelParameterfv +typedef void (APIENTRYP PFNGLGETTEXLEVELPARAMETERIVPROC)(GLenum target, GLint level, GLenum pname, GLint *params); +GLAPI PFNGLGETTEXLEVELPARAMETERIVPROC glad_glGetTexLevelParameteriv; +#define glGetTexLevelParameteriv glad_glGetTexLevelParameteriv +typedef GLboolean (APIENTRYP PFNGLISENABLEDPROC)(GLenum cap); +GLAPI PFNGLISENABLEDPROC glad_glIsEnabled; +#define glIsEnabled glad_glIsEnabled +typedef void (APIENTRYP PFNGLDEPTHRANGEPROC)(GLdouble n, GLdouble f); +GLAPI PFNGLDEPTHRANGEPROC glad_glDepthRange; +#define glDepthRange glad_glDepthRange +typedef void (APIENTRYP PFNGLVIEWPORTPROC)(GLint x, GLint y, GLsizei width, GLsizei height); +GLAPI PFNGLVIEWPORTPROC glad_glViewport; +#define glViewport glad_glViewport +#endif +#ifndef GL_VERSION_1_1 +#define GL_VERSION_1_1 1 +GLAPI int GLAD_GL_VERSION_1_1; +typedef void (APIENTRYP PFNGLDRAWARRAYSPROC)(GLenum mode, GLint first, GLsizei count); +GLAPI PFNGLDRAWARRAYSPROC glad_glDrawArrays; +#define glDrawArrays glad_glDrawArrays +typedef void (APIENTRYP PFNGLDRAWELEMENTSPROC)(GLenum mode, GLsizei count, GLenum type, const void *indices); +GLAPI PFNGLDRAWELEMENTSPROC glad_glDrawElements; +#define glDrawElements glad_glDrawElements +typedef void (APIENTRYP PFNGLPOLYGONOFFSETPROC)(GLfloat factor, GLfloat units); +GLAPI PFNGLPOLYGONOFFSETPROC glad_glPolygonOffset; +#define glPolygonOffset glad_glPolygonOffset +typedef void (APIENTRYP PFNGLCOPYTEXIMAGE1DPROC)(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border); +GLAPI PFNGLCOPYTEXIMAGE1DPROC glad_glCopyTexImage1D; +#define glCopyTexImage1D glad_glCopyTexImage1D +typedef void (APIENTRYP PFNGLCOPYTEXIMAGE2DPROC)(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); +GLAPI PFNGLCOPYTEXIMAGE2DPROC glad_glCopyTexImage2D; +#define glCopyTexImage2D glad_glCopyTexImage2D +typedef void (APIENTRYP PFNGLCOPYTEXSUBIMAGE1DPROC)(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); +GLAPI PFNGLCOPYTEXSUBIMAGE1DPROC glad_glCopyTexSubImage1D; +#define glCopyTexSubImage1D glad_glCopyTexSubImage1D +typedef void (APIENTRYP PFNGLCOPYTEXSUBIMAGE2DPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); +GLAPI PFNGLCOPYTEXSUBIMAGE2DPROC glad_glCopyTexSubImage2D; +#define glCopyTexSubImage2D glad_glCopyTexSubImage2D +typedef void (APIENTRYP PFNGLTEXSUBIMAGE1DPROC)(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void *pixels); +GLAPI PFNGLTEXSUBIMAGE1DPROC glad_glTexSubImage1D; +#define glTexSubImage1D glad_glTexSubImage1D +typedef void (APIENTRYP PFNGLTEXSUBIMAGE2DPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels); +GLAPI PFNGLTEXSUBIMAGE2DPROC glad_glTexSubImage2D; +#define glTexSubImage2D glad_glTexSubImage2D +typedef void (APIENTRYP PFNGLBINDTEXTUREPROC)(GLenum target, GLuint texture); +GLAPI PFNGLBINDTEXTUREPROC glad_glBindTexture; +#define glBindTexture glad_glBindTexture +typedef void (APIENTRYP PFNGLDELETETEXTURESPROC)(GLsizei n, const GLuint *textures); +GLAPI PFNGLDELETETEXTURESPROC glad_glDeleteTextures; +#define glDeleteTextures glad_glDeleteTextures +typedef void (APIENTRYP PFNGLGENTEXTURESPROC)(GLsizei n, GLuint *textures); +GLAPI PFNGLGENTEXTURESPROC glad_glGenTextures; +#define glGenTextures glad_glGenTextures +typedef GLboolean (APIENTRYP PFNGLISTEXTUREPROC)(GLuint texture); +GLAPI PFNGLISTEXTUREPROC glad_glIsTexture; +#define glIsTexture glad_glIsTexture +#endif +#ifndef GL_VERSION_1_2 +#define GL_VERSION_1_2 1 +GLAPI int GLAD_GL_VERSION_1_2; +typedef void (APIENTRYP PFNGLDRAWRANGEELEMENTSPROC)(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices); +GLAPI PFNGLDRAWRANGEELEMENTSPROC glad_glDrawRangeElements; +#define glDrawRangeElements glad_glDrawRangeElements +typedef void (APIENTRYP PFNGLTEXIMAGE3DPROC)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels); +GLAPI PFNGLTEXIMAGE3DPROC glad_glTexImage3D; +#define glTexImage3D glad_glTexImage3D +typedef void (APIENTRYP PFNGLTEXSUBIMAGE3DPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels); +GLAPI PFNGLTEXSUBIMAGE3DPROC glad_glTexSubImage3D; +#define glTexSubImage3D glad_glTexSubImage3D +typedef void (APIENTRYP PFNGLCOPYTEXSUBIMAGE3DPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); +GLAPI PFNGLCOPYTEXSUBIMAGE3DPROC glad_glCopyTexSubImage3D; +#define glCopyTexSubImage3D glad_glCopyTexSubImage3D +#endif +#ifndef GL_VERSION_1_3 +#define GL_VERSION_1_3 1 +GLAPI int GLAD_GL_VERSION_1_3; +typedef void (APIENTRYP PFNGLACTIVETEXTUREPROC)(GLenum texture); +GLAPI PFNGLACTIVETEXTUREPROC glad_glActiveTexture; +#define glActiveTexture glad_glActiveTexture +typedef void (APIENTRYP PFNGLSAMPLECOVERAGEPROC)(GLfloat value, GLboolean invert); +GLAPI PFNGLSAMPLECOVERAGEPROC glad_glSampleCoverage; +#define glSampleCoverage glad_glSampleCoverage +typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE3DPROC)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data); +GLAPI PFNGLCOMPRESSEDTEXIMAGE3DPROC glad_glCompressedTexImage3D; +#define glCompressedTexImage3D glad_glCompressedTexImage3D +typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE2DPROC)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data); +GLAPI PFNGLCOMPRESSEDTEXIMAGE2DPROC glad_glCompressedTexImage2D; +#define glCompressedTexImage2D glad_glCompressedTexImage2D +typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE1DPROC)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void *data); +GLAPI PFNGLCOMPRESSEDTEXIMAGE1DPROC glad_glCompressedTexImage1D; +#define glCompressedTexImage1D glad_glCompressedTexImage1D +typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data); +GLAPI PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC glad_glCompressedTexSubImage3D; +#define glCompressedTexSubImage3D glad_glCompressedTexSubImage3D +typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data); +GLAPI PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC glad_glCompressedTexSubImage2D; +#define glCompressedTexSubImage2D glad_glCompressedTexSubImage2D +typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC)(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void *data); +GLAPI PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC glad_glCompressedTexSubImage1D; +#define glCompressedTexSubImage1D glad_glCompressedTexSubImage1D +typedef void (APIENTRYP PFNGLGETCOMPRESSEDTEXIMAGEPROC)(GLenum target, GLint level, void *img); +GLAPI PFNGLGETCOMPRESSEDTEXIMAGEPROC glad_glGetCompressedTexImage; +#define glGetCompressedTexImage glad_glGetCompressedTexImage +#endif +#ifndef GL_VERSION_1_4 +#define GL_VERSION_1_4 1 +GLAPI int GLAD_GL_VERSION_1_4; +typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEPROC)(GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); +GLAPI PFNGLBLENDFUNCSEPARATEPROC glad_glBlendFuncSeparate; +#define glBlendFuncSeparate glad_glBlendFuncSeparate +typedef void (APIENTRYP PFNGLMULTIDRAWARRAYSPROC)(GLenum mode, const GLint *first, const GLsizei *count, GLsizei drawcount); +GLAPI PFNGLMULTIDRAWARRAYSPROC glad_glMultiDrawArrays; +#define glMultiDrawArrays glad_glMultiDrawArrays +typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSPROC)(GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei drawcount); +GLAPI PFNGLMULTIDRAWELEMENTSPROC glad_glMultiDrawElements; +#define glMultiDrawElements glad_glMultiDrawElements +typedef void (APIENTRYP PFNGLPOINTPARAMETERFPROC)(GLenum pname, GLfloat param); +GLAPI PFNGLPOINTPARAMETERFPROC glad_glPointParameterf; +#define glPointParameterf glad_glPointParameterf +typedef void (APIENTRYP PFNGLPOINTPARAMETERFVPROC)(GLenum pname, const GLfloat *params); +GLAPI PFNGLPOINTPARAMETERFVPROC glad_glPointParameterfv; +#define glPointParameterfv glad_glPointParameterfv +typedef void (APIENTRYP PFNGLPOINTPARAMETERIPROC)(GLenum pname, GLint param); +GLAPI PFNGLPOINTPARAMETERIPROC glad_glPointParameteri; +#define glPointParameteri glad_glPointParameteri +typedef void (APIENTRYP PFNGLPOINTPARAMETERIVPROC)(GLenum pname, const GLint *params); +GLAPI PFNGLPOINTPARAMETERIVPROC glad_glPointParameteriv; +#define glPointParameteriv glad_glPointParameteriv +typedef void (APIENTRYP PFNGLBLENDCOLORPROC)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); +GLAPI PFNGLBLENDCOLORPROC glad_glBlendColor; +#define glBlendColor glad_glBlendColor +typedef void (APIENTRYP PFNGLBLENDEQUATIONPROC)(GLenum mode); +GLAPI PFNGLBLENDEQUATIONPROC glad_glBlendEquation; +#define glBlendEquation glad_glBlendEquation +#endif +#ifndef GL_VERSION_1_5 +#define GL_VERSION_1_5 1 +GLAPI int GLAD_GL_VERSION_1_5; +typedef void (APIENTRYP PFNGLGENQUERIESPROC)(GLsizei n, GLuint *ids); +GLAPI PFNGLGENQUERIESPROC glad_glGenQueries; +#define glGenQueries glad_glGenQueries +typedef void (APIENTRYP PFNGLDELETEQUERIESPROC)(GLsizei n, const GLuint *ids); +GLAPI PFNGLDELETEQUERIESPROC glad_glDeleteQueries; +#define glDeleteQueries glad_glDeleteQueries +typedef GLboolean (APIENTRYP PFNGLISQUERYPROC)(GLuint id); +GLAPI PFNGLISQUERYPROC glad_glIsQuery; +#define glIsQuery glad_glIsQuery +typedef void (APIENTRYP PFNGLBEGINQUERYPROC)(GLenum target, GLuint id); +GLAPI PFNGLBEGINQUERYPROC glad_glBeginQuery; +#define glBeginQuery glad_glBeginQuery +typedef void (APIENTRYP PFNGLENDQUERYPROC)(GLenum target); +GLAPI PFNGLENDQUERYPROC glad_glEndQuery; +#define glEndQuery glad_glEndQuery +typedef void (APIENTRYP PFNGLGETQUERYIVPROC)(GLenum target, GLenum pname, GLint *params); +GLAPI PFNGLGETQUERYIVPROC glad_glGetQueryiv; +#define glGetQueryiv glad_glGetQueryiv +typedef void (APIENTRYP PFNGLGETQUERYOBJECTIVPROC)(GLuint id, GLenum pname, GLint *params); +GLAPI PFNGLGETQUERYOBJECTIVPROC glad_glGetQueryObjectiv; +#define glGetQueryObjectiv glad_glGetQueryObjectiv +typedef void (APIENTRYP PFNGLGETQUERYOBJECTUIVPROC)(GLuint id, GLenum pname, GLuint *params); +GLAPI PFNGLGETQUERYOBJECTUIVPROC glad_glGetQueryObjectuiv; +#define glGetQueryObjectuiv glad_glGetQueryObjectuiv +typedef void (APIENTRYP PFNGLBINDBUFFERPROC)(GLenum target, GLuint buffer); +GLAPI PFNGLBINDBUFFERPROC glad_glBindBuffer; +#define glBindBuffer glad_glBindBuffer +typedef void (APIENTRYP PFNGLDELETEBUFFERSPROC)(GLsizei n, const GLuint *buffers); +GLAPI PFNGLDELETEBUFFERSPROC glad_glDeleteBuffers; +#define glDeleteBuffers glad_glDeleteBuffers +typedef void (APIENTRYP PFNGLGENBUFFERSPROC)(GLsizei n, GLuint *buffers); +GLAPI PFNGLGENBUFFERSPROC glad_glGenBuffers; +#define glGenBuffers glad_glGenBuffers +typedef GLboolean (APIENTRYP PFNGLISBUFFERPROC)(GLuint buffer); +GLAPI PFNGLISBUFFERPROC glad_glIsBuffer; +#define glIsBuffer glad_glIsBuffer +typedef void (APIENTRYP PFNGLBUFFERDATAPROC)(GLenum target, GLsizeiptr size, const void *data, GLenum usage); +GLAPI PFNGLBUFFERDATAPROC glad_glBufferData; +#define glBufferData glad_glBufferData +typedef void (APIENTRYP PFNGLBUFFERSUBDATAPROC)(GLenum target, GLintptr offset, GLsizeiptr size, const void *data); +GLAPI PFNGLBUFFERSUBDATAPROC glad_glBufferSubData; +#define glBufferSubData glad_glBufferSubData +typedef void (APIENTRYP PFNGLGETBUFFERSUBDATAPROC)(GLenum target, GLintptr offset, GLsizeiptr size, void *data); +GLAPI PFNGLGETBUFFERSUBDATAPROC glad_glGetBufferSubData; +#define glGetBufferSubData glad_glGetBufferSubData +typedef void * (APIENTRYP PFNGLMAPBUFFERPROC)(GLenum target, GLenum access); +GLAPI PFNGLMAPBUFFERPROC glad_glMapBuffer; +#define glMapBuffer glad_glMapBuffer +typedef GLboolean (APIENTRYP PFNGLUNMAPBUFFERPROC)(GLenum target); +GLAPI PFNGLUNMAPBUFFERPROC glad_glUnmapBuffer; +#define glUnmapBuffer glad_glUnmapBuffer +typedef void (APIENTRYP PFNGLGETBUFFERPARAMETERIVPROC)(GLenum target, GLenum pname, GLint *params); +GLAPI PFNGLGETBUFFERPARAMETERIVPROC glad_glGetBufferParameteriv; +#define glGetBufferParameteriv glad_glGetBufferParameteriv +typedef void (APIENTRYP PFNGLGETBUFFERPOINTERVPROC)(GLenum target, GLenum pname, void **params); +GLAPI PFNGLGETBUFFERPOINTERVPROC glad_glGetBufferPointerv; +#define glGetBufferPointerv glad_glGetBufferPointerv +#endif +#ifndef GL_VERSION_2_0 +#define GL_VERSION_2_0 1 +GLAPI int GLAD_GL_VERSION_2_0; +typedef void (APIENTRYP PFNGLBLENDEQUATIONSEPARATEPROC)(GLenum modeRGB, GLenum modeAlpha); +GLAPI PFNGLBLENDEQUATIONSEPARATEPROC glad_glBlendEquationSeparate; +#define glBlendEquationSeparate glad_glBlendEquationSeparate +typedef void (APIENTRYP PFNGLDRAWBUFFERSPROC)(GLsizei n, const GLenum *bufs); +GLAPI PFNGLDRAWBUFFERSPROC glad_glDrawBuffers; +#define glDrawBuffers glad_glDrawBuffers +typedef void (APIENTRYP PFNGLSTENCILOPSEPARATEPROC)(GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass); +GLAPI PFNGLSTENCILOPSEPARATEPROC glad_glStencilOpSeparate; +#define glStencilOpSeparate glad_glStencilOpSeparate +typedef void (APIENTRYP PFNGLSTENCILFUNCSEPARATEPROC)(GLenum face, GLenum func, GLint ref, GLuint mask); +GLAPI PFNGLSTENCILFUNCSEPARATEPROC glad_glStencilFuncSeparate; +#define glStencilFuncSeparate glad_glStencilFuncSeparate +typedef void (APIENTRYP PFNGLSTENCILMASKSEPARATEPROC)(GLenum face, GLuint mask); +GLAPI PFNGLSTENCILMASKSEPARATEPROC glad_glStencilMaskSeparate; +#define glStencilMaskSeparate glad_glStencilMaskSeparate +typedef void (APIENTRYP PFNGLATTACHSHADERPROC)(GLuint program, GLuint shader); +GLAPI PFNGLATTACHSHADERPROC glad_glAttachShader; +#define glAttachShader glad_glAttachShader +typedef void (APIENTRYP PFNGLBINDATTRIBLOCATIONPROC)(GLuint program, GLuint index, const GLchar *name); +GLAPI PFNGLBINDATTRIBLOCATIONPROC glad_glBindAttribLocation; +#define glBindAttribLocation glad_glBindAttribLocation +typedef void (APIENTRYP PFNGLCOMPILESHADERPROC)(GLuint shader); +GLAPI PFNGLCOMPILESHADERPROC glad_glCompileShader; +#define glCompileShader glad_glCompileShader +typedef GLuint (APIENTRYP PFNGLCREATEPROGRAMPROC)(void); +GLAPI PFNGLCREATEPROGRAMPROC glad_glCreateProgram; +#define glCreateProgram glad_glCreateProgram +typedef GLuint (APIENTRYP PFNGLCREATESHADERPROC)(GLenum type); +GLAPI PFNGLCREATESHADERPROC glad_glCreateShader; +#define glCreateShader glad_glCreateShader +typedef void (APIENTRYP PFNGLDELETEPROGRAMPROC)(GLuint program); +GLAPI PFNGLDELETEPROGRAMPROC glad_glDeleteProgram; +#define glDeleteProgram glad_glDeleteProgram +typedef void (APIENTRYP PFNGLDELETESHADERPROC)(GLuint shader); +GLAPI PFNGLDELETESHADERPROC glad_glDeleteShader; +#define glDeleteShader glad_glDeleteShader +typedef void (APIENTRYP PFNGLDETACHSHADERPROC)(GLuint program, GLuint shader); +GLAPI PFNGLDETACHSHADERPROC glad_glDetachShader; +#define glDetachShader glad_glDetachShader +typedef void (APIENTRYP PFNGLDISABLEVERTEXATTRIBARRAYPROC)(GLuint index); +GLAPI PFNGLDISABLEVERTEXATTRIBARRAYPROC glad_glDisableVertexAttribArray; +#define glDisableVertexAttribArray glad_glDisableVertexAttribArray +typedef void (APIENTRYP PFNGLENABLEVERTEXATTRIBARRAYPROC)(GLuint index); +GLAPI PFNGLENABLEVERTEXATTRIBARRAYPROC glad_glEnableVertexAttribArray; +#define glEnableVertexAttribArray glad_glEnableVertexAttribArray +typedef void (APIENTRYP PFNGLGETACTIVEATTRIBPROC)(GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name); +GLAPI PFNGLGETACTIVEATTRIBPROC glad_glGetActiveAttrib; +#define glGetActiveAttrib glad_glGetActiveAttrib +typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMPROC)(GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name); +GLAPI PFNGLGETACTIVEUNIFORMPROC glad_glGetActiveUniform; +#define glGetActiveUniform glad_glGetActiveUniform +typedef void (APIENTRYP PFNGLGETATTACHEDSHADERSPROC)(GLuint program, GLsizei maxCount, GLsizei *count, GLuint *shaders); +GLAPI PFNGLGETATTACHEDSHADERSPROC glad_glGetAttachedShaders; +#define glGetAttachedShaders glad_glGetAttachedShaders +typedef GLint (APIENTRYP PFNGLGETATTRIBLOCATIONPROC)(GLuint program, const GLchar *name); +GLAPI PFNGLGETATTRIBLOCATIONPROC glad_glGetAttribLocation; +#define glGetAttribLocation glad_glGetAttribLocation +typedef void (APIENTRYP PFNGLGETPROGRAMIVPROC)(GLuint program, GLenum pname, GLint *params); +GLAPI PFNGLGETPROGRAMIVPROC glad_glGetProgramiv; +#define glGetProgramiv glad_glGetProgramiv +typedef void (APIENTRYP PFNGLGETPROGRAMINFOLOGPROC)(GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog); +GLAPI PFNGLGETPROGRAMINFOLOGPROC glad_glGetProgramInfoLog; +#define glGetProgramInfoLog glad_glGetProgramInfoLog +typedef void (APIENTRYP PFNGLGETSHADERIVPROC)(GLuint shader, GLenum pname, GLint *params); +GLAPI PFNGLGETSHADERIVPROC glad_glGetShaderiv; +#define glGetShaderiv glad_glGetShaderiv +typedef void (APIENTRYP PFNGLGETSHADERINFOLOGPROC)(GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog); +GLAPI PFNGLGETSHADERINFOLOGPROC glad_glGetShaderInfoLog; +#define glGetShaderInfoLog glad_glGetShaderInfoLog +typedef void (APIENTRYP PFNGLGETSHADERSOURCEPROC)(GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source); +GLAPI PFNGLGETSHADERSOURCEPROC glad_glGetShaderSource; +#define glGetShaderSource glad_glGetShaderSource +typedef GLint (APIENTRYP PFNGLGETUNIFORMLOCATIONPROC)(GLuint program, const GLchar *name); +GLAPI PFNGLGETUNIFORMLOCATIONPROC glad_glGetUniformLocation; +#define glGetUniformLocation glad_glGetUniformLocation +typedef void (APIENTRYP PFNGLGETUNIFORMFVPROC)(GLuint program, GLint location, GLfloat *params); +GLAPI PFNGLGETUNIFORMFVPROC glad_glGetUniformfv; +#define glGetUniformfv glad_glGetUniformfv +typedef void (APIENTRYP PFNGLGETUNIFORMIVPROC)(GLuint program, GLint location, GLint *params); +GLAPI PFNGLGETUNIFORMIVPROC glad_glGetUniformiv; +#define glGetUniformiv glad_glGetUniformiv +typedef void (APIENTRYP PFNGLGETVERTEXATTRIBDVPROC)(GLuint index, GLenum pname, GLdouble *params); +GLAPI PFNGLGETVERTEXATTRIBDVPROC glad_glGetVertexAttribdv; +#define glGetVertexAttribdv glad_glGetVertexAttribdv +typedef void (APIENTRYP PFNGLGETVERTEXATTRIBFVPROC)(GLuint index, GLenum pname, GLfloat *params); +GLAPI PFNGLGETVERTEXATTRIBFVPROC glad_glGetVertexAttribfv; +#define glGetVertexAttribfv glad_glGetVertexAttribfv +typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIVPROC)(GLuint index, GLenum pname, GLint *params); +GLAPI PFNGLGETVERTEXATTRIBIVPROC glad_glGetVertexAttribiv; +#define glGetVertexAttribiv glad_glGetVertexAttribiv +typedef void (APIENTRYP PFNGLGETVERTEXATTRIBPOINTERVPROC)(GLuint index, GLenum pname, void **pointer); +GLAPI PFNGLGETVERTEXATTRIBPOINTERVPROC glad_glGetVertexAttribPointerv; +#define glGetVertexAttribPointerv glad_glGetVertexAttribPointerv +typedef GLboolean (APIENTRYP PFNGLISPROGRAMPROC)(GLuint program); +GLAPI PFNGLISPROGRAMPROC glad_glIsProgram; +#define glIsProgram glad_glIsProgram +typedef GLboolean (APIENTRYP PFNGLISSHADERPROC)(GLuint shader); +GLAPI PFNGLISSHADERPROC glad_glIsShader; +#define glIsShader glad_glIsShader +typedef void (APIENTRYP PFNGLLINKPROGRAMPROC)(GLuint program); +GLAPI PFNGLLINKPROGRAMPROC glad_glLinkProgram; +#define glLinkProgram glad_glLinkProgram +typedef void (APIENTRYP PFNGLSHADERSOURCEPROC)(GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length); +GLAPI PFNGLSHADERSOURCEPROC glad_glShaderSource; +#define glShaderSource glad_glShaderSource +typedef void (APIENTRYP PFNGLUSEPROGRAMPROC)(GLuint program); +GLAPI PFNGLUSEPROGRAMPROC glad_glUseProgram; +#define glUseProgram glad_glUseProgram +typedef void (APIENTRYP PFNGLUNIFORM1FPROC)(GLint location, GLfloat v0); +GLAPI PFNGLUNIFORM1FPROC glad_glUniform1f; +#define glUniform1f glad_glUniform1f +typedef void (APIENTRYP PFNGLUNIFORM2FPROC)(GLint location, GLfloat v0, GLfloat v1); +GLAPI PFNGLUNIFORM2FPROC glad_glUniform2f; +#define glUniform2f glad_glUniform2f +typedef void (APIENTRYP PFNGLUNIFORM3FPROC)(GLint location, GLfloat v0, GLfloat v1, GLfloat v2); +GLAPI PFNGLUNIFORM3FPROC glad_glUniform3f; +#define glUniform3f glad_glUniform3f +typedef void (APIENTRYP PFNGLUNIFORM4FPROC)(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); +GLAPI PFNGLUNIFORM4FPROC glad_glUniform4f; +#define glUniform4f glad_glUniform4f +typedef void (APIENTRYP PFNGLUNIFORM1IPROC)(GLint location, GLint v0); +GLAPI PFNGLUNIFORM1IPROC glad_glUniform1i; +#define glUniform1i glad_glUniform1i +typedef void (APIENTRYP PFNGLUNIFORM2IPROC)(GLint location, GLint v0, GLint v1); +GLAPI PFNGLUNIFORM2IPROC glad_glUniform2i; +#define glUniform2i glad_glUniform2i +typedef void (APIENTRYP PFNGLUNIFORM3IPROC)(GLint location, GLint v0, GLint v1, GLint v2); +GLAPI PFNGLUNIFORM3IPROC glad_glUniform3i; +#define glUniform3i glad_glUniform3i +typedef void (APIENTRYP PFNGLUNIFORM4IPROC)(GLint location, GLint v0, GLint v1, GLint v2, GLint v3); +GLAPI PFNGLUNIFORM4IPROC glad_glUniform4i; +#define glUniform4i glad_glUniform4i +typedef void (APIENTRYP PFNGLUNIFORM1FVPROC)(GLint location, GLsizei count, const GLfloat *value); +GLAPI PFNGLUNIFORM1FVPROC glad_glUniform1fv; +#define glUniform1fv glad_glUniform1fv +typedef void (APIENTRYP PFNGLUNIFORM2FVPROC)(GLint location, GLsizei count, const GLfloat *value); +GLAPI PFNGLUNIFORM2FVPROC glad_glUniform2fv; +#define glUniform2fv glad_glUniform2fv +typedef void (APIENTRYP PFNGLUNIFORM3FVPROC)(GLint location, GLsizei count, const GLfloat *value); +GLAPI PFNGLUNIFORM3FVPROC glad_glUniform3fv; +#define glUniform3fv glad_glUniform3fv +typedef void (APIENTRYP PFNGLUNIFORM4FVPROC)(GLint location, GLsizei count, const GLfloat *value); +GLAPI PFNGLUNIFORM4FVPROC glad_glUniform4fv; +#define glUniform4fv glad_glUniform4fv +typedef void (APIENTRYP PFNGLUNIFORM1IVPROC)(GLint location, GLsizei count, const GLint *value); +GLAPI PFNGLUNIFORM1IVPROC glad_glUniform1iv; +#define glUniform1iv glad_glUniform1iv +typedef void (APIENTRYP PFNGLUNIFORM2IVPROC)(GLint location, GLsizei count, const GLint *value); +GLAPI PFNGLUNIFORM2IVPROC glad_glUniform2iv; +#define glUniform2iv glad_glUniform2iv +typedef void (APIENTRYP PFNGLUNIFORM3IVPROC)(GLint location, GLsizei count, const GLint *value); +GLAPI PFNGLUNIFORM3IVPROC glad_glUniform3iv; +#define glUniform3iv glad_glUniform3iv +typedef void (APIENTRYP PFNGLUNIFORM4IVPROC)(GLint location, GLsizei count, const GLint *value); +GLAPI PFNGLUNIFORM4IVPROC glad_glUniform4iv; +#define glUniform4iv glad_glUniform4iv +typedef void (APIENTRYP PFNGLUNIFORMMATRIX2FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GLAPI PFNGLUNIFORMMATRIX2FVPROC glad_glUniformMatrix2fv; +#define glUniformMatrix2fv glad_glUniformMatrix2fv +typedef void (APIENTRYP PFNGLUNIFORMMATRIX3FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GLAPI PFNGLUNIFORMMATRIX3FVPROC glad_glUniformMatrix3fv; +#define glUniformMatrix3fv glad_glUniformMatrix3fv +typedef void (APIENTRYP PFNGLUNIFORMMATRIX4FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GLAPI PFNGLUNIFORMMATRIX4FVPROC glad_glUniformMatrix4fv; +#define glUniformMatrix4fv glad_glUniformMatrix4fv +typedef void (APIENTRYP PFNGLVALIDATEPROGRAMPROC)(GLuint program); +GLAPI PFNGLVALIDATEPROGRAMPROC glad_glValidateProgram; +#define glValidateProgram glad_glValidateProgram +typedef void (APIENTRYP PFNGLVERTEXATTRIB1DPROC)(GLuint index, GLdouble x); +GLAPI PFNGLVERTEXATTRIB1DPROC glad_glVertexAttrib1d; +#define glVertexAttrib1d glad_glVertexAttrib1d +typedef void (APIENTRYP PFNGLVERTEXATTRIB1DVPROC)(GLuint index, const GLdouble *v); +GLAPI PFNGLVERTEXATTRIB1DVPROC glad_glVertexAttrib1dv; +#define glVertexAttrib1dv glad_glVertexAttrib1dv +typedef void (APIENTRYP PFNGLVERTEXATTRIB1FPROC)(GLuint index, GLfloat x); +GLAPI PFNGLVERTEXATTRIB1FPROC glad_glVertexAttrib1f; +#define glVertexAttrib1f glad_glVertexAttrib1f +typedef void (APIENTRYP PFNGLVERTEXATTRIB1FVPROC)(GLuint index, const GLfloat *v); +GLAPI PFNGLVERTEXATTRIB1FVPROC glad_glVertexAttrib1fv; +#define glVertexAttrib1fv glad_glVertexAttrib1fv +typedef void (APIENTRYP PFNGLVERTEXATTRIB1SPROC)(GLuint index, GLshort x); +GLAPI PFNGLVERTEXATTRIB1SPROC glad_glVertexAttrib1s; +#define glVertexAttrib1s glad_glVertexAttrib1s +typedef void (APIENTRYP PFNGLVERTEXATTRIB1SVPROC)(GLuint index, const GLshort *v); +GLAPI PFNGLVERTEXATTRIB1SVPROC glad_glVertexAttrib1sv; +#define glVertexAttrib1sv glad_glVertexAttrib1sv +typedef void (APIENTRYP PFNGLVERTEXATTRIB2DPROC)(GLuint index, GLdouble x, GLdouble y); +GLAPI PFNGLVERTEXATTRIB2DPROC glad_glVertexAttrib2d; +#define glVertexAttrib2d glad_glVertexAttrib2d +typedef void (APIENTRYP PFNGLVERTEXATTRIB2DVPROC)(GLuint index, const GLdouble *v); +GLAPI PFNGLVERTEXATTRIB2DVPROC glad_glVertexAttrib2dv; +#define glVertexAttrib2dv glad_glVertexAttrib2dv +typedef void (APIENTRYP PFNGLVERTEXATTRIB2FPROC)(GLuint index, GLfloat x, GLfloat y); +GLAPI PFNGLVERTEXATTRIB2FPROC glad_glVertexAttrib2f; +#define glVertexAttrib2f glad_glVertexAttrib2f +typedef void (APIENTRYP PFNGLVERTEXATTRIB2FVPROC)(GLuint index, const GLfloat *v); +GLAPI PFNGLVERTEXATTRIB2FVPROC glad_glVertexAttrib2fv; +#define glVertexAttrib2fv glad_glVertexAttrib2fv +typedef void (APIENTRYP PFNGLVERTEXATTRIB2SPROC)(GLuint index, GLshort x, GLshort y); +GLAPI PFNGLVERTEXATTRIB2SPROC glad_glVertexAttrib2s; +#define glVertexAttrib2s glad_glVertexAttrib2s +typedef void (APIENTRYP PFNGLVERTEXATTRIB2SVPROC)(GLuint index, const GLshort *v); +GLAPI PFNGLVERTEXATTRIB2SVPROC glad_glVertexAttrib2sv; +#define glVertexAttrib2sv glad_glVertexAttrib2sv +typedef void (APIENTRYP PFNGLVERTEXATTRIB3DPROC)(GLuint index, GLdouble x, GLdouble y, GLdouble z); +GLAPI PFNGLVERTEXATTRIB3DPROC glad_glVertexAttrib3d; +#define glVertexAttrib3d glad_glVertexAttrib3d +typedef void (APIENTRYP PFNGLVERTEXATTRIB3DVPROC)(GLuint index, const GLdouble *v); +GLAPI PFNGLVERTEXATTRIB3DVPROC glad_glVertexAttrib3dv; +#define glVertexAttrib3dv glad_glVertexAttrib3dv +typedef void (APIENTRYP PFNGLVERTEXATTRIB3FPROC)(GLuint index, GLfloat x, GLfloat y, GLfloat z); +GLAPI PFNGLVERTEXATTRIB3FPROC glad_glVertexAttrib3f; +#define glVertexAttrib3f glad_glVertexAttrib3f +typedef void (APIENTRYP PFNGLVERTEXATTRIB3FVPROC)(GLuint index, const GLfloat *v); +GLAPI PFNGLVERTEXATTRIB3FVPROC glad_glVertexAttrib3fv; +#define glVertexAttrib3fv glad_glVertexAttrib3fv +typedef void (APIENTRYP PFNGLVERTEXATTRIB3SPROC)(GLuint index, GLshort x, GLshort y, GLshort z); +GLAPI PFNGLVERTEXATTRIB3SPROC glad_glVertexAttrib3s; +#define glVertexAttrib3s glad_glVertexAttrib3s +typedef void (APIENTRYP PFNGLVERTEXATTRIB3SVPROC)(GLuint index, const GLshort *v); +GLAPI PFNGLVERTEXATTRIB3SVPROC glad_glVertexAttrib3sv; +#define glVertexAttrib3sv glad_glVertexAttrib3sv +typedef void (APIENTRYP PFNGLVERTEXATTRIB4NBVPROC)(GLuint index, const GLbyte *v); +GLAPI PFNGLVERTEXATTRIB4NBVPROC glad_glVertexAttrib4Nbv; +#define glVertexAttrib4Nbv glad_glVertexAttrib4Nbv +typedef void (APIENTRYP PFNGLVERTEXATTRIB4NIVPROC)(GLuint index, const GLint *v); +GLAPI PFNGLVERTEXATTRIB4NIVPROC glad_glVertexAttrib4Niv; +#define glVertexAttrib4Niv glad_glVertexAttrib4Niv +typedef void (APIENTRYP PFNGLVERTEXATTRIB4NSVPROC)(GLuint index, const GLshort *v); +GLAPI PFNGLVERTEXATTRIB4NSVPROC glad_glVertexAttrib4Nsv; +#define glVertexAttrib4Nsv glad_glVertexAttrib4Nsv +typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUBPROC)(GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w); +GLAPI PFNGLVERTEXATTRIB4NUBPROC glad_glVertexAttrib4Nub; +#define glVertexAttrib4Nub glad_glVertexAttrib4Nub +typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUBVPROC)(GLuint index, const GLubyte *v); +GLAPI PFNGLVERTEXATTRIB4NUBVPROC glad_glVertexAttrib4Nubv; +#define glVertexAttrib4Nubv glad_glVertexAttrib4Nubv +typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUIVPROC)(GLuint index, const GLuint *v); +GLAPI PFNGLVERTEXATTRIB4NUIVPROC glad_glVertexAttrib4Nuiv; +#define glVertexAttrib4Nuiv glad_glVertexAttrib4Nuiv +typedef void (APIENTRYP PFNGLVERTEXATTRIB4NUSVPROC)(GLuint index, const GLushort *v); +GLAPI PFNGLVERTEXATTRIB4NUSVPROC glad_glVertexAttrib4Nusv; +#define glVertexAttrib4Nusv glad_glVertexAttrib4Nusv +typedef void (APIENTRYP PFNGLVERTEXATTRIB4BVPROC)(GLuint index, const GLbyte *v); +GLAPI PFNGLVERTEXATTRIB4BVPROC glad_glVertexAttrib4bv; +#define glVertexAttrib4bv glad_glVertexAttrib4bv +typedef void (APIENTRYP PFNGLVERTEXATTRIB4DPROC)(GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +GLAPI PFNGLVERTEXATTRIB4DPROC glad_glVertexAttrib4d; +#define glVertexAttrib4d glad_glVertexAttrib4d +typedef void (APIENTRYP PFNGLVERTEXATTRIB4DVPROC)(GLuint index, const GLdouble *v); +GLAPI PFNGLVERTEXATTRIB4DVPROC glad_glVertexAttrib4dv; +#define glVertexAttrib4dv glad_glVertexAttrib4dv +typedef void (APIENTRYP PFNGLVERTEXATTRIB4FPROC)(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +GLAPI PFNGLVERTEXATTRIB4FPROC glad_glVertexAttrib4f; +#define glVertexAttrib4f glad_glVertexAttrib4f +typedef void (APIENTRYP PFNGLVERTEXATTRIB4FVPROC)(GLuint index, const GLfloat *v); +GLAPI PFNGLVERTEXATTRIB4FVPROC glad_glVertexAttrib4fv; +#define glVertexAttrib4fv glad_glVertexAttrib4fv +typedef void (APIENTRYP PFNGLVERTEXATTRIB4IVPROC)(GLuint index, const GLint *v); +GLAPI PFNGLVERTEXATTRIB4IVPROC glad_glVertexAttrib4iv; +#define glVertexAttrib4iv glad_glVertexAttrib4iv +typedef void (APIENTRYP PFNGLVERTEXATTRIB4SPROC)(GLuint index, GLshort x, GLshort y, GLshort z, GLshort w); +GLAPI PFNGLVERTEXATTRIB4SPROC glad_glVertexAttrib4s; +#define glVertexAttrib4s glad_glVertexAttrib4s +typedef void (APIENTRYP PFNGLVERTEXATTRIB4SVPROC)(GLuint index, const GLshort *v); +GLAPI PFNGLVERTEXATTRIB4SVPROC glad_glVertexAttrib4sv; +#define glVertexAttrib4sv glad_glVertexAttrib4sv +typedef void (APIENTRYP PFNGLVERTEXATTRIB4UBVPROC)(GLuint index, const GLubyte *v); +GLAPI PFNGLVERTEXATTRIB4UBVPROC glad_glVertexAttrib4ubv; +#define glVertexAttrib4ubv glad_glVertexAttrib4ubv +typedef void (APIENTRYP PFNGLVERTEXATTRIB4UIVPROC)(GLuint index, const GLuint *v); +GLAPI PFNGLVERTEXATTRIB4UIVPROC glad_glVertexAttrib4uiv; +#define glVertexAttrib4uiv glad_glVertexAttrib4uiv +typedef void (APIENTRYP PFNGLVERTEXATTRIB4USVPROC)(GLuint index, const GLushort *v); +GLAPI PFNGLVERTEXATTRIB4USVPROC glad_glVertexAttrib4usv; +#define glVertexAttrib4usv glad_glVertexAttrib4usv +typedef void (APIENTRYP PFNGLVERTEXATTRIBPOINTERPROC)(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer); +GLAPI PFNGLVERTEXATTRIBPOINTERPROC glad_glVertexAttribPointer; +#define glVertexAttribPointer glad_glVertexAttribPointer +#endif +#ifndef GL_VERSION_2_1 +#define GL_VERSION_2_1 1 +GLAPI int GLAD_GL_VERSION_2_1; +typedef void (APIENTRYP PFNGLUNIFORMMATRIX2X3FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GLAPI PFNGLUNIFORMMATRIX2X3FVPROC glad_glUniformMatrix2x3fv; +#define glUniformMatrix2x3fv glad_glUniformMatrix2x3fv +typedef void (APIENTRYP PFNGLUNIFORMMATRIX3X2FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GLAPI PFNGLUNIFORMMATRIX3X2FVPROC glad_glUniformMatrix3x2fv; +#define glUniformMatrix3x2fv glad_glUniformMatrix3x2fv +typedef void (APIENTRYP PFNGLUNIFORMMATRIX2X4FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GLAPI PFNGLUNIFORMMATRIX2X4FVPROC glad_glUniformMatrix2x4fv; +#define glUniformMatrix2x4fv glad_glUniformMatrix2x4fv +typedef void (APIENTRYP PFNGLUNIFORMMATRIX4X2FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GLAPI PFNGLUNIFORMMATRIX4X2FVPROC glad_glUniformMatrix4x2fv; +#define glUniformMatrix4x2fv glad_glUniformMatrix4x2fv +typedef void (APIENTRYP PFNGLUNIFORMMATRIX3X4FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GLAPI PFNGLUNIFORMMATRIX3X4FVPROC glad_glUniformMatrix3x4fv; +#define glUniformMatrix3x4fv glad_glUniformMatrix3x4fv +typedef void (APIENTRYP PFNGLUNIFORMMATRIX4X3FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GLAPI PFNGLUNIFORMMATRIX4X3FVPROC glad_glUniformMatrix4x3fv; +#define glUniformMatrix4x3fv glad_glUniformMatrix4x3fv +#endif +#ifndef GL_VERSION_3_0 +#define GL_VERSION_3_0 1 +GLAPI int GLAD_GL_VERSION_3_0; +typedef void (APIENTRYP PFNGLCOLORMASKIPROC)(GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a); +GLAPI PFNGLCOLORMASKIPROC glad_glColorMaski; +#define glColorMaski glad_glColorMaski +typedef void (APIENTRYP PFNGLGETBOOLEANI_VPROC)(GLenum target, GLuint index, GLboolean *data); +GLAPI PFNGLGETBOOLEANI_VPROC glad_glGetBooleani_v; +#define glGetBooleani_v glad_glGetBooleani_v +typedef void (APIENTRYP PFNGLGETINTEGERI_VPROC)(GLenum target, GLuint index, GLint *data); +GLAPI PFNGLGETINTEGERI_VPROC glad_glGetIntegeri_v; +#define glGetIntegeri_v glad_glGetIntegeri_v +typedef void (APIENTRYP PFNGLENABLEIPROC)(GLenum target, GLuint index); +GLAPI PFNGLENABLEIPROC glad_glEnablei; +#define glEnablei glad_glEnablei +typedef void (APIENTRYP PFNGLDISABLEIPROC)(GLenum target, GLuint index); +GLAPI PFNGLDISABLEIPROC glad_glDisablei; +#define glDisablei glad_glDisablei +typedef GLboolean (APIENTRYP PFNGLISENABLEDIPROC)(GLenum target, GLuint index); +GLAPI PFNGLISENABLEDIPROC glad_glIsEnabledi; +#define glIsEnabledi glad_glIsEnabledi +typedef void (APIENTRYP PFNGLBEGINTRANSFORMFEEDBACKPROC)(GLenum primitiveMode); +GLAPI PFNGLBEGINTRANSFORMFEEDBACKPROC glad_glBeginTransformFeedback; +#define glBeginTransformFeedback glad_glBeginTransformFeedback +typedef void (APIENTRYP PFNGLENDTRANSFORMFEEDBACKPROC)(void); +GLAPI PFNGLENDTRANSFORMFEEDBACKPROC glad_glEndTransformFeedback; +#define glEndTransformFeedback glad_glEndTransformFeedback +typedef void (APIENTRYP PFNGLBINDBUFFERRANGEPROC)(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size); +GLAPI PFNGLBINDBUFFERRANGEPROC glad_glBindBufferRange; +#define glBindBufferRange glad_glBindBufferRange +typedef void (APIENTRYP PFNGLBINDBUFFERBASEPROC)(GLenum target, GLuint index, GLuint buffer); +GLAPI PFNGLBINDBUFFERBASEPROC glad_glBindBufferBase; +#define glBindBufferBase glad_glBindBufferBase +typedef void (APIENTRYP PFNGLTRANSFORMFEEDBACKVARYINGSPROC)(GLuint program, GLsizei count, const GLchar *const*varyings, GLenum bufferMode); +GLAPI PFNGLTRANSFORMFEEDBACKVARYINGSPROC glad_glTransformFeedbackVaryings; +#define glTransformFeedbackVaryings glad_glTransformFeedbackVaryings +typedef void (APIENTRYP PFNGLGETTRANSFORMFEEDBACKVARYINGPROC)(GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name); +GLAPI PFNGLGETTRANSFORMFEEDBACKVARYINGPROC glad_glGetTransformFeedbackVarying; +#define glGetTransformFeedbackVarying glad_glGetTransformFeedbackVarying +typedef void (APIENTRYP PFNGLCLAMPCOLORPROC)(GLenum target, GLenum clamp); +GLAPI PFNGLCLAMPCOLORPROC glad_glClampColor; +#define glClampColor glad_glClampColor +typedef void (APIENTRYP PFNGLBEGINCONDITIONALRENDERPROC)(GLuint id, GLenum mode); +GLAPI PFNGLBEGINCONDITIONALRENDERPROC glad_glBeginConditionalRender; +#define glBeginConditionalRender glad_glBeginConditionalRender +typedef void (APIENTRYP PFNGLENDCONDITIONALRENDERPROC)(void); +GLAPI PFNGLENDCONDITIONALRENDERPROC glad_glEndConditionalRender; +#define glEndConditionalRender glad_glEndConditionalRender +typedef void (APIENTRYP PFNGLVERTEXATTRIBIPOINTERPROC)(GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer); +GLAPI PFNGLVERTEXATTRIBIPOINTERPROC glad_glVertexAttribIPointer; +#define glVertexAttribIPointer glad_glVertexAttribIPointer +typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIIVPROC)(GLuint index, GLenum pname, GLint *params); +GLAPI PFNGLGETVERTEXATTRIBIIVPROC glad_glGetVertexAttribIiv; +#define glGetVertexAttribIiv glad_glGetVertexAttribIiv +typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIUIVPROC)(GLuint index, GLenum pname, GLuint *params); +GLAPI PFNGLGETVERTEXATTRIBIUIVPROC glad_glGetVertexAttribIuiv; +#define glGetVertexAttribIuiv glad_glGetVertexAttribIuiv +typedef void (APIENTRYP PFNGLVERTEXATTRIBI1IPROC)(GLuint index, GLint x); +GLAPI PFNGLVERTEXATTRIBI1IPROC glad_glVertexAttribI1i; +#define glVertexAttribI1i glad_glVertexAttribI1i +typedef void (APIENTRYP PFNGLVERTEXATTRIBI2IPROC)(GLuint index, GLint x, GLint y); +GLAPI PFNGLVERTEXATTRIBI2IPROC glad_glVertexAttribI2i; +#define glVertexAttribI2i glad_glVertexAttribI2i +typedef void (APIENTRYP PFNGLVERTEXATTRIBI3IPROC)(GLuint index, GLint x, GLint y, GLint z); +GLAPI PFNGLVERTEXATTRIBI3IPROC glad_glVertexAttribI3i; +#define glVertexAttribI3i glad_glVertexAttribI3i +typedef void (APIENTRYP PFNGLVERTEXATTRIBI4IPROC)(GLuint index, GLint x, GLint y, GLint z, GLint w); +GLAPI PFNGLVERTEXATTRIBI4IPROC glad_glVertexAttribI4i; +#define glVertexAttribI4i glad_glVertexAttribI4i +typedef void (APIENTRYP PFNGLVERTEXATTRIBI1UIPROC)(GLuint index, GLuint x); +GLAPI PFNGLVERTEXATTRIBI1UIPROC glad_glVertexAttribI1ui; +#define glVertexAttribI1ui glad_glVertexAttribI1ui +typedef void (APIENTRYP PFNGLVERTEXATTRIBI2UIPROC)(GLuint index, GLuint x, GLuint y); +GLAPI PFNGLVERTEXATTRIBI2UIPROC glad_glVertexAttribI2ui; +#define glVertexAttribI2ui glad_glVertexAttribI2ui +typedef void (APIENTRYP PFNGLVERTEXATTRIBI3UIPROC)(GLuint index, GLuint x, GLuint y, GLuint z); +GLAPI PFNGLVERTEXATTRIBI3UIPROC glad_glVertexAttribI3ui; +#define glVertexAttribI3ui glad_glVertexAttribI3ui +typedef void (APIENTRYP PFNGLVERTEXATTRIBI4UIPROC)(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); +GLAPI PFNGLVERTEXATTRIBI4UIPROC glad_glVertexAttribI4ui; +#define glVertexAttribI4ui glad_glVertexAttribI4ui +typedef void (APIENTRYP PFNGLVERTEXATTRIBI1IVPROC)(GLuint index, const GLint *v); +GLAPI PFNGLVERTEXATTRIBI1IVPROC glad_glVertexAttribI1iv; +#define glVertexAttribI1iv glad_glVertexAttribI1iv +typedef void (APIENTRYP PFNGLVERTEXATTRIBI2IVPROC)(GLuint index, const GLint *v); +GLAPI PFNGLVERTEXATTRIBI2IVPROC glad_glVertexAttribI2iv; +#define glVertexAttribI2iv glad_glVertexAttribI2iv +typedef void (APIENTRYP PFNGLVERTEXATTRIBI3IVPROC)(GLuint index, const GLint *v); +GLAPI PFNGLVERTEXATTRIBI3IVPROC glad_glVertexAttribI3iv; +#define glVertexAttribI3iv glad_glVertexAttribI3iv +typedef void (APIENTRYP PFNGLVERTEXATTRIBI4IVPROC)(GLuint index, const GLint *v); +GLAPI PFNGLVERTEXATTRIBI4IVPROC glad_glVertexAttribI4iv; +#define glVertexAttribI4iv glad_glVertexAttribI4iv +typedef void (APIENTRYP PFNGLVERTEXATTRIBI1UIVPROC)(GLuint index, const GLuint *v); +GLAPI PFNGLVERTEXATTRIBI1UIVPROC glad_glVertexAttribI1uiv; +#define glVertexAttribI1uiv glad_glVertexAttribI1uiv +typedef void (APIENTRYP PFNGLVERTEXATTRIBI2UIVPROC)(GLuint index, const GLuint *v); +GLAPI PFNGLVERTEXATTRIBI2UIVPROC glad_glVertexAttribI2uiv; +#define glVertexAttribI2uiv glad_glVertexAttribI2uiv +typedef void (APIENTRYP PFNGLVERTEXATTRIBI3UIVPROC)(GLuint index, const GLuint *v); +GLAPI PFNGLVERTEXATTRIBI3UIVPROC glad_glVertexAttribI3uiv; +#define glVertexAttribI3uiv glad_glVertexAttribI3uiv +typedef void (APIENTRYP PFNGLVERTEXATTRIBI4UIVPROC)(GLuint index, const GLuint *v); +GLAPI PFNGLVERTEXATTRIBI4UIVPROC glad_glVertexAttribI4uiv; +#define glVertexAttribI4uiv glad_glVertexAttribI4uiv +typedef void (APIENTRYP PFNGLVERTEXATTRIBI4BVPROC)(GLuint index, const GLbyte *v); +GLAPI PFNGLVERTEXATTRIBI4BVPROC glad_glVertexAttribI4bv; +#define glVertexAttribI4bv glad_glVertexAttribI4bv +typedef void (APIENTRYP PFNGLVERTEXATTRIBI4SVPROC)(GLuint index, const GLshort *v); +GLAPI PFNGLVERTEXATTRIBI4SVPROC glad_glVertexAttribI4sv; +#define glVertexAttribI4sv glad_glVertexAttribI4sv +typedef void (APIENTRYP PFNGLVERTEXATTRIBI4UBVPROC)(GLuint index, const GLubyte *v); +GLAPI PFNGLVERTEXATTRIBI4UBVPROC glad_glVertexAttribI4ubv; +#define glVertexAttribI4ubv glad_glVertexAttribI4ubv +typedef void (APIENTRYP PFNGLVERTEXATTRIBI4USVPROC)(GLuint index, const GLushort *v); +GLAPI PFNGLVERTEXATTRIBI4USVPROC glad_glVertexAttribI4usv; +#define glVertexAttribI4usv glad_glVertexAttribI4usv +typedef void (APIENTRYP PFNGLGETUNIFORMUIVPROC)(GLuint program, GLint location, GLuint *params); +GLAPI PFNGLGETUNIFORMUIVPROC glad_glGetUniformuiv; +#define glGetUniformuiv glad_glGetUniformuiv +typedef void (APIENTRYP PFNGLBINDFRAGDATALOCATIONPROC)(GLuint program, GLuint color, const GLchar *name); +GLAPI PFNGLBINDFRAGDATALOCATIONPROC glad_glBindFragDataLocation; +#define glBindFragDataLocation glad_glBindFragDataLocation +typedef GLint (APIENTRYP PFNGLGETFRAGDATALOCATIONPROC)(GLuint program, const GLchar *name); +GLAPI PFNGLGETFRAGDATALOCATIONPROC glad_glGetFragDataLocation; +#define glGetFragDataLocation glad_glGetFragDataLocation +typedef void (APIENTRYP PFNGLUNIFORM1UIPROC)(GLint location, GLuint v0); +GLAPI PFNGLUNIFORM1UIPROC glad_glUniform1ui; +#define glUniform1ui glad_glUniform1ui +typedef void (APIENTRYP PFNGLUNIFORM2UIPROC)(GLint location, GLuint v0, GLuint v1); +GLAPI PFNGLUNIFORM2UIPROC glad_glUniform2ui; +#define glUniform2ui glad_glUniform2ui +typedef void (APIENTRYP PFNGLUNIFORM3UIPROC)(GLint location, GLuint v0, GLuint v1, GLuint v2); +GLAPI PFNGLUNIFORM3UIPROC glad_glUniform3ui; +#define glUniform3ui glad_glUniform3ui +typedef void (APIENTRYP PFNGLUNIFORM4UIPROC)(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); +GLAPI PFNGLUNIFORM4UIPROC glad_glUniform4ui; +#define glUniform4ui glad_glUniform4ui +typedef void (APIENTRYP PFNGLUNIFORM1UIVPROC)(GLint location, GLsizei count, const GLuint *value); +GLAPI PFNGLUNIFORM1UIVPROC glad_glUniform1uiv; +#define glUniform1uiv glad_glUniform1uiv +typedef void (APIENTRYP PFNGLUNIFORM2UIVPROC)(GLint location, GLsizei count, const GLuint *value); +GLAPI PFNGLUNIFORM2UIVPROC glad_glUniform2uiv; +#define glUniform2uiv glad_glUniform2uiv +typedef void (APIENTRYP PFNGLUNIFORM3UIVPROC)(GLint location, GLsizei count, const GLuint *value); +GLAPI PFNGLUNIFORM3UIVPROC glad_glUniform3uiv; +#define glUniform3uiv glad_glUniform3uiv +typedef void (APIENTRYP PFNGLUNIFORM4UIVPROC)(GLint location, GLsizei count, const GLuint *value); +GLAPI PFNGLUNIFORM4UIVPROC glad_glUniform4uiv; +#define glUniform4uiv glad_glUniform4uiv +typedef void (APIENTRYP PFNGLTEXPARAMETERIIVPROC)(GLenum target, GLenum pname, const GLint *params); +GLAPI PFNGLTEXPARAMETERIIVPROC glad_glTexParameterIiv; +#define glTexParameterIiv glad_glTexParameterIiv +typedef void (APIENTRYP PFNGLTEXPARAMETERIUIVPROC)(GLenum target, GLenum pname, const GLuint *params); +GLAPI PFNGLTEXPARAMETERIUIVPROC glad_glTexParameterIuiv; +#define glTexParameterIuiv glad_glTexParameterIuiv +typedef void (APIENTRYP PFNGLGETTEXPARAMETERIIVPROC)(GLenum target, GLenum pname, GLint *params); +GLAPI PFNGLGETTEXPARAMETERIIVPROC glad_glGetTexParameterIiv; +#define glGetTexParameterIiv glad_glGetTexParameterIiv +typedef void (APIENTRYP PFNGLGETTEXPARAMETERIUIVPROC)(GLenum target, GLenum pname, GLuint *params); +GLAPI PFNGLGETTEXPARAMETERIUIVPROC glad_glGetTexParameterIuiv; +#define glGetTexParameterIuiv glad_glGetTexParameterIuiv +typedef void (APIENTRYP PFNGLCLEARBUFFERIVPROC)(GLenum buffer, GLint drawbuffer, const GLint *value); +GLAPI PFNGLCLEARBUFFERIVPROC glad_glClearBufferiv; +#define glClearBufferiv glad_glClearBufferiv +typedef void (APIENTRYP PFNGLCLEARBUFFERUIVPROC)(GLenum buffer, GLint drawbuffer, const GLuint *value); +GLAPI PFNGLCLEARBUFFERUIVPROC glad_glClearBufferuiv; +#define glClearBufferuiv glad_glClearBufferuiv +typedef void (APIENTRYP PFNGLCLEARBUFFERFVPROC)(GLenum buffer, GLint drawbuffer, const GLfloat *value); +GLAPI PFNGLCLEARBUFFERFVPROC glad_glClearBufferfv; +#define glClearBufferfv glad_glClearBufferfv +typedef void (APIENTRYP PFNGLCLEARBUFFERFIPROC)(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil); +GLAPI PFNGLCLEARBUFFERFIPROC glad_glClearBufferfi; +#define glClearBufferfi glad_glClearBufferfi +typedef const GLubyte * (APIENTRYP PFNGLGETSTRINGIPROC)(GLenum name, GLuint index); +GLAPI PFNGLGETSTRINGIPROC glad_glGetStringi; +#define glGetStringi glad_glGetStringi +typedef GLboolean (APIENTRYP PFNGLISRENDERBUFFERPROC)(GLuint renderbuffer); +GLAPI PFNGLISRENDERBUFFERPROC glad_glIsRenderbuffer; +#define glIsRenderbuffer glad_glIsRenderbuffer +typedef void (APIENTRYP PFNGLBINDRENDERBUFFERPROC)(GLenum target, GLuint renderbuffer); +GLAPI PFNGLBINDRENDERBUFFERPROC glad_glBindRenderbuffer; +#define glBindRenderbuffer glad_glBindRenderbuffer +typedef void (APIENTRYP PFNGLDELETERENDERBUFFERSPROC)(GLsizei n, const GLuint *renderbuffers); +GLAPI PFNGLDELETERENDERBUFFERSPROC glad_glDeleteRenderbuffers; +#define glDeleteRenderbuffers glad_glDeleteRenderbuffers +typedef void (APIENTRYP PFNGLGENRENDERBUFFERSPROC)(GLsizei n, GLuint *renderbuffers); +GLAPI PFNGLGENRENDERBUFFERSPROC glad_glGenRenderbuffers; +#define glGenRenderbuffers glad_glGenRenderbuffers +typedef void (APIENTRYP PFNGLRENDERBUFFERSTORAGEPROC)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height); +GLAPI PFNGLRENDERBUFFERSTORAGEPROC glad_glRenderbufferStorage; +#define glRenderbufferStorage glad_glRenderbufferStorage +typedef void (APIENTRYP PFNGLGETRENDERBUFFERPARAMETERIVPROC)(GLenum target, GLenum pname, GLint *params); +GLAPI PFNGLGETRENDERBUFFERPARAMETERIVPROC glad_glGetRenderbufferParameteriv; +#define glGetRenderbufferParameteriv glad_glGetRenderbufferParameteriv +typedef GLboolean (APIENTRYP PFNGLISFRAMEBUFFERPROC)(GLuint framebuffer); +GLAPI PFNGLISFRAMEBUFFERPROC glad_glIsFramebuffer; +#define glIsFramebuffer glad_glIsFramebuffer +typedef void (APIENTRYP PFNGLBINDFRAMEBUFFERPROC)(GLenum target, GLuint framebuffer); +GLAPI PFNGLBINDFRAMEBUFFERPROC glad_glBindFramebuffer; +#define glBindFramebuffer glad_glBindFramebuffer +typedef void (APIENTRYP PFNGLDELETEFRAMEBUFFERSPROC)(GLsizei n, const GLuint *framebuffers); +GLAPI PFNGLDELETEFRAMEBUFFERSPROC glad_glDeleteFramebuffers; +#define glDeleteFramebuffers glad_glDeleteFramebuffers +typedef void (APIENTRYP PFNGLGENFRAMEBUFFERSPROC)(GLsizei n, GLuint *framebuffers); +GLAPI PFNGLGENFRAMEBUFFERSPROC glad_glGenFramebuffers; +#define glGenFramebuffers glad_glGenFramebuffers +typedef GLenum (APIENTRYP PFNGLCHECKFRAMEBUFFERSTATUSPROC)(GLenum target); +GLAPI PFNGLCHECKFRAMEBUFFERSTATUSPROC glad_glCheckFramebufferStatus; +#define glCheckFramebufferStatus glad_glCheckFramebufferStatus +typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE1DPROC)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +GLAPI PFNGLFRAMEBUFFERTEXTURE1DPROC glad_glFramebufferTexture1D; +#define glFramebufferTexture1D glad_glFramebufferTexture1D +typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DPROC)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +GLAPI PFNGLFRAMEBUFFERTEXTURE2DPROC glad_glFramebufferTexture2D; +#define glFramebufferTexture2D glad_glFramebufferTexture2D +typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE3DPROC)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset); +GLAPI PFNGLFRAMEBUFFERTEXTURE3DPROC glad_glFramebufferTexture3D; +#define glFramebufferTexture3D glad_glFramebufferTexture3D +typedef void (APIENTRYP PFNGLFRAMEBUFFERRENDERBUFFERPROC)(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); +GLAPI PFNGLFRAMEBUFFERRENDERBUFFERPROC glad_glFramebufferRenderbuffer; +#define glFramebufferRenderbuffer glad_glFramebufferRenderbuffer +typedef void (APIENTRYP PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC)(GLenum target, GLenum attachment, GLenum pname, GLint *params); +GLAPI PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC glad_glGetFramebufferAttachmentParameteriv; +#define glGetFramebufferAttachmentParameteriv glad_glGetFramebufferAttachmentParameteriv +typedef void (APIENTRYP PFNGLGENERATEMIPMAPPROC)(GLenum target); +GLAPI PFNGLGENERATEMIPMAPPROC glad_glGenerateMipmap; +#define glGenerateMipmap glad_glGenerateMipmap +typedef void (APIENTRYP PFNGLBLITFRAMEBUFFERPROC)(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); +GLAPI PFNGLBLITFRAMEBUFFERPROC glad_glBlitFramebuffer; +#define glBlitFramebuffer glad_glBlitFramebuffer +typedef void (APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); +GLAPI PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC glad_glRenderbufferStorageMultisample; +#define glRenderbufferStorageMultisample glad_glRenderbufferStorageMultisample +typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURELAYERPROC)(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer); +GLAPI PFNGLFRAMEBUFFERTEXTURELAYERPROC glad_glFramebufferTextureLayer; +#define glFramebufferTextureLayer glad_glFramebufferTextureLayer +typedef void * (APIENTRYP PFNGLMAPBUFFERRANGEPROC)(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access); +GLAPI PFNGLMAPBUFFERRANGEPROC glad_glMapBufferRange; +#define glMapBufferRange glad_glMapBufferRange +typedef void (APIENTRYP PFNGLFLUSHMAPPEDBUFFERRANGEPROC)(GLenum target, GLintptr offset, GLsizeiptr length); +GLAPI PFNGLFLUSHMAPPEDBUFFERRANGEPROC glad_glFlushMappedBufferRange; +#define glFlushMappedBufferRange glad_glFlushMappedBufferRange +typedef void (APIENTRYP PFNGLBINDVERTEXARRAYPROC)(GLuint array); +GLAPI PFNGLBINDVERTEXARRAYPROC glad_glBindVertexArray; +#define glBindVertexArray glad_glBindVertexArray +typedef void (APIENTRYP PFNGLDELETEVERTEXARRAYSPROC)(GLsizei n, const GLuint *arrays); +GLAPI PFNGLDELETEVERTEXARRAYSPROC glad_glDeleteVertexArrays; +#define glDeleteVertexArrays glad_glDeleteVertexArrays +typedef void (APIENTRYP PFNGLGENVERTEXARRAYSPROC)(GLsizei n, GLuint *arrays); +GLAPI PFNGLGENVERTEXARRAYSPROC glad_glGenVertexArrays; +#define glGenVertexArrays glad_glGenVertexArrays +typedef GLboolean (APIENTRYP PFNGLISVERTEXARRAYPROC)(GLuint array); +GLAPI PFNGLISVERTEXARRAYPROC glad_glIsVertexArray; +#define glIsVertexArray glad_glIsVertexArray +#endif +#ifndef GL_VERSION_3_1 +#define GL_VERSION_3_1 1 +GLAPI int GLAD_GL_VERSION_3_1; +typedef void (APIENTRYP PFNGLDRAWARRAYSINSTANCEDPROC)(GLenum mode, GLint first, GLsizei count, GLsizei instancecount); +GLAPI PFNGLDRAWARRAYSINSTANCEDPROC glad_glDrawArraysInstanced; +#define glDrawArraysInstanced glad_glDrawArraysInstanced +typedef void (APIENTRYP PFNGLDRAWELEMENTSINSTANCEDPROC)(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount); +GLAPI PFNGLDRAWELEMENTSINSTANCEDPROC glad_glDrawElementsInstanced; +#define glDrawElementsInstanced glad_glDrawElementsInstanced +typedef void (APIENTRYP PFNGLTEXBUFFERPROC)(GLenum target, GLenum internalformat, GLuint buffer); +GLAPI PFNGLTEXBUFFERPROC glad_glTexBuffer; +#define glTexBuffer glad_glTexBuffer +typedef void (APIENTRYP PFNGLPRIMITIVERESTARTINDEXPROC)(GLuint index); +GLAPI PFNGLPRIMITIVERESTARTINDEXPROC glad_glPrimitiveRestartIndex; +#define glPrimitiveRestartIndex glad_glPrimitiveRestartIndex +typedef void (APIENTRYP PFNGLCOPYBUFFERSUBDATAPROC)(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size); +GLAPI PFNGLCOPYBUFFERSUBDATAPROC glad_glCopyBufferSubData; +#define glCopyBufferSubData glad_glCopyBufferSubData +typedef void (APIENTRYP PFNGLGETUNIFORMINDICESPROC)(GLuint program, GLsizei uniformCount, const GLchar *const*uniformNames, GLuint *uniformIndices); +GLAPI PFNGLGETUNIFORMINDICESPROC glad_glGetUniformIndices; +#define glGetUniformIndices glad_glGetUniformIndices +typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMSIVPROC)(GLuint program, GLsizei uniformCount, const GLuint *uniformIndices, GLenum pname, GLint *params); +GLAPI PFNGLGETACTIVEUNIFORMSIVPROC glad_glGetActiveUniformsiv; +#define glGetActiveUniformsiv glad_glGetActiveUniformsiv +typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMNAMEPROC)(GLuint program, GLuint uniformIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformName); +GLAPI PFNGLGETACTIVEUNIFORMNAMEPROC glad_glGetActiveUniformName; +#define glGetActiveUniformName glad_glGetActiveUniformName +typedef GLuint (APIENTRYP PFNGLGETUNIFORMBLOCKINDEXPROC)(GLuint program, const GLchar *uniformBlockName); +GLAPI PFNGLGETUNIFORMBLOCKINDEXPROC glad_glGetUniformBlockIndex; +#define glGetUniformBlockIndex glad_glGetUniformBlockIndex +typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMBLOCKIVPROC)(GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint *params); +GLAPI PFNGLGETACTIVEUNIFORMBLOCKIVPROC glad_glGetActiveUniformBlockiv; +#define glGetActiveUniformBlockiv glad_glGetActiveUniformBlockiv +typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC)(GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName); +GLAPI PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC glad_glGetActiveUniformBlockName; +#define glGetActiveUniformBlockName glad_glGetActiveUniformBlockName +typedef void (APIENTRYP PFNGLUNIFORMBLOCKBINDINGPROC)(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding); +GLAPI PFNGLUNIFORMBLOCKBINDINGPROC glad_glUniformBlockBinding; +#define glUniformBlockBinding glad_glUniformBlockBinding +#endif +#ifndef GL_VERSION_3_2 +#define GL_VERSION_3_2 1 +GLAPI int GLAD_GL_VERSION_3_2; +typedef void (APIENTRYP PFNGLDRAWELEMENTSBASEVERTEXPROC)(GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex); +GLAPI PFNGLDRAWELEMENTSBASEVERTEXPROC glad_glDrawElementsBaseVertex; +#define glDrawElementsBaseVertex glad_glDrawElementsBaseVertex +typedef void (APIENTRYP PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC)(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices, GLint basevertex); +GLAPI PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC glad_glDrawRangeElementsBaseVertex; +#define glDrawRangeElementsBaseVertex glad_glDrawRangeElementsBaseVertex +typedef void (APIENTRYP PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC)(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex); +GLAPI PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC glad_glDrawElementsInstancedBaseVertex; +#define glDrawElementsInstancedBaseVertex glad_glDrawElementsInstancedBaseVertex +typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC)(GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei drawcount, const GLint *basevertex); +GLAPI PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC glad_glMultiDrawElementsBaseVertex; +#define glMultiDrawElementsBaseVertex glad_glMultiDrawElementsBaseVertex +typedef void (APIENTRYP PFNGLPROVOKINGVERTEXPROC)(GLenum mode); +GLAPI PFNGLPROVOKINGVERTEXPROC glad_glProvokingVertex; +#define glProvokingVertex glad_glProvokingVertex +typedef GLsync (APIENTRYP PFNGLFENCESYNCPROC)(GLenum condition, GLbitfield flags); +GLAPI PFNGLFENCESYNCPROC glad_glFenceSync; +#define glFenceSync glad_glFenceSync +typedef GLboolean (APIENTRYP PFNGLISSYNCPROC)(GLsync sync); +GLAPI PFNGLISSYNCPROC glad_glIsSync; +#define glIsSync glad_glIsSync +typedef void (APIENTRYP PFNGLDELETESYNCPROC)(GLsync sync); +GLAPI PFNGLDELETESYNCPROC glad_glDeleteSync; +#define glDeleteSync glad_glDeleteSync +typedef GLenum (APIENTRYP PFNGLCLIENTWAITSYNCPROC)(GLsync sync, GLbitfield flags, GLuint64 timeout); +GLAPI PFNGLCLIENTWAITSYNCPROC glad_glClientWaitSync; +#define glClientWaitSync glad_glClientWaitSync +typedef void (APIENTRYP PFNGLWAITSYNCPROC)(GLsync sync, GLbitfield flags, GLuint64 timeout); +GLAPI PFNGLWAITSYNCPROC glad_glWaitSync; +#define glWaitSync glad_glWaitSync +typedef void (APIENTRYP PFNGLGETINTEGER64VPROC)(GLenum pname, GLint64 *data); +GLAPI PFNGLGETINTEGER64VPROC glad_glGetInteger64v; +#define glGetInteger64v glad_glGetInteger64v +typedef void (APIENTRYP PFNGLGETSYNCIVPROC)(GLsync sync, GLenum pname, GLsizei count, GLsizei *length, GLint *values); +GLAPI PFNGLGETSYNCIVPROC glad_glGetSynciv; +#define glGetSynciv glad_glGetSynciv +typedef void (APIENTRYP PFNGLGETINTEGER64I_VPROC)(GLenum target, GLuint index, GLint64 *data); +GLAPI PFNGLGETINTEGER64I_VPROC glad_glGetInteger64i_v; +#define glGetInteger64i_v glad_glGetInteger64i_v +typedef void (APIENTRYP PFNGLGETBUFFERPARAMETERI64VPROC)(GLenum target, GLenum pname, GLint64 *params); +GLAPI PFNGLGETBUFFERPARAMETERI64VPROC glad_glGetBufferParameteri64v; +#define glGetBufferParameteri64v glad_glGetBufferParameteri64v +typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTUREPROC)(GLenum target, GLenum attachment, GLuint texture, GLint level); +GLAPI PFNGLFRAMEBUFFERTEXTUREPROC glad_glFramebufferTexture; +#define glFramebufferTexture glad_glFramebufferTexture +typedef void (APIENTRYP PFNGLTEXIMAGE2DMULTISAMPLEPROC)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations); +GLAPI PFNGLTEXIMAGE2DMULTISAMPLEPROC glad_glTexImage2DMultisample; +#define glTexImage2DMultisample glad_glTexImage2DMultisample +typedef void (APIENTRYP PFNGLTEXIMAGE3DMULTISAMPLEPROC)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations); +GLAPI PFNGLTEXIMAGE3DMULTISAMPLEPROC glad_glTexImage3DMultisample; +#define glTexImage3DMultisample glad_glTexImage3DMultisample +typedef void (APIENTRYP PFNGLGETMULTISAMPLEFVPROC)(GLenum pname, GLuint index, GLfloat *val); +GLAPI PFNGLGETMULTISAMPLEFVPROC glad_glGetMultisamplefv; +#define glGetMultisamplefv glad_glGetMultisamplefv +typedef void (APIENTRYP PFNGLSAMPLEMASKIPROC)(GLuint maskNumber, GLbitfield mask); +GLAPI PFNGLSAMPLEMASKIPROC glad_glSampleMaski; +#define glSampleMaski glad_glSampleMaski +#endif +#ifndef GL_VERSION_3_3 +#define GL_VERSION_3_3 1 +GLAPI int GLAD_GL_VERSION_3_3; +typedef void (APIENTRYP PFNGLBINDFRAGDATALOCATIONINDEXEDPROC)(GLuint program, GLuint colorNumber, GLuint index, const GLchar *name); +GLAPI PFNGLBINDFRAGDATALOCATIONINDEXEDPROC glad_glBindFragDataLocationIndexed; +#define glBindFragDataLocationIndexed glad_glBindFragDataLocationIndexed +typedef GLint (APIENTRYP PFNGLGETFRAGDATAINDEXPROC)(GLuint program, const GLchar *name); +GLAPI PFNGLGETFRAGDATAINDEXPROC glad_glGetFragDataIndex; +#define glGetFragDataIndex glad_glGetFragDataIndex +typedef void (APIENTRYP PFNGLGENSAMPLERSPROC)(GLsizei count, GLuint *samplers); +GLAPI PFNGLGENSAMPLERSPROC glad_glGenSamplers; +#define glGenSamplers glad_glGenSamplers +typedef void (APIENTRYP PFNGLDELETESAMPLERSPROC)(GLsizei count, const GLuint *samplers); +GLAPI PFNGLDELETESAMPLERSPROC glad_glDeleteSamplers; +#define glDeleteSamplers glad_glDeleteSamplers +typedef GLboolean (APIENTRYP PFNGLISSAMPLERPROC)(GLuint sampler); +GLAPI PFNGLISSAMPLERPROC glad_glIsSampler; +#define glIsSampler glad_glIsSampler +typedef void (APIENTRYP PFNGLBINDSAMPLERPROC)(GLuint unit, GLuint sampler); +GLAPI PFNGLBINDSAMPLERPROC glad_glBindSampler; +#define glBindSampler glad_glBindSampler +typedef void (APIENTRYP PFNGLSAMPLERPARAMETERIPROC)(GLuint sampler, GLenum pname, GLint param); +GLAPI PFNGLSAMPLERPARAMETERIPROC glad_glSamplerParameteri; +#define glSamplerParameteri glad_glSamplerParameteri +typedef void (APIENTRYP PFNGLSAMPLERPARAMETERIVPROC)(GLuint sampler, GLenum pname, const GLint *param); +GLAPI PFNGLSAMPLERPARAMETERIVPROC glad_glSamplerParameteriv; +#define glSamplerParameteriv glad_glSamplerParameteriv +typedef void (APIENTRYP PFNGLSAMPLERPARAMETERFPROC)(GLuint sampler, GLenum pname, GLfloat param); +GLAPI PFNGLSAMPLERPARAMETERFPROC glad_glSamplerParameterf; +#define glSamplerParameterf glad_glSamplerParameterf +typedef void (APIENTRYP PFNGLSAMPLERPARAMETERFVPROC)(GLuint sampler, GLenum pname, const GLfloat *param); +GLAPI PFNGLSAMPLERPARAMETERFVPROC glad_glSamplerParameterfv; +#define glSamplerParameterfv glad_glSamplerParameterfv +typedef void (APIENTRYP PFNGLSAMPLERPARAMETERIIVPROC)(GLuint sampler, GLenum pname, const GLint *param); +GLAPI PFNGLSAMPLERPARAMETERIIVPROC glad_glSamplerParameterIiv; +#define glSamplerParameterIiv glad_glSamplerParameterIiv +typedef void (APIENTRYP PFNGLSAMPLERPARAMETERIUIVPROC)(GLuint sampler, GLenum pname, const GLuint *param); +GLAPI PFNGLSAMPLERPARAMETERIUIVPROC glad_glSamplerParameterIuiv; +#define glSamplerParameterIuiv glad_glSamplerParameterIuiv +typedef void (APIENTRYP PFNGLGETSAMPLERPARAMETERIVPROC)(GLuint sampler, GLenum pname, GLint *params); +GLAPI PFNGLGETSAMPLERPARAMETERIVPROC glad_glGetSamplerParameteriv; +#define glGetSamplerParameteriv glad_glGetSamplerParameteriv +typedef void (APIENTRYP PFNGLGETSAMPLERPARAMETERIIVPROC)(GLuint sampler, GLenum pname, GLint *params); +GLAPI PFNGLGETSAMPLERPARAMETERIIVPROC glad_glGetSamplerParameterIiv; +#define glGetSamplerParameterIiv glad_glGetSamplerParameterIiv +typedef void (APIENTRYP PFNGLGETSAMPLERPARAMETERFVPROC)(GLuint sampler, GLenum pname, GLfloat *params); +GLAPI PFNGLGETSAMPLERPARAMETERFVPROC glad_glGetSamplerParameterfv; +#define glGetSamplerParameterfv glad_glGetSamplerParameterfv +typedef void (APIENTRYP PFNGLGETSAMPLERPARAMETERIUIVPROC)(GLuint sampler, GLenum pname, GLuint *params); +GLAPI PFNGLGETSAMPLERPARAMETERIUIVPROC glad_glGetSamplerParameterIuiv; +#define glGetSamplerParameterIuiv glad_glGetSamplerParameterIuiv +typedef void (APIENTRYP PFNGLQUERYCOUNTERPROC)(GLuint id, GLenum target); +GLAPI PFNGLQUERYCOUNTERPROC glad_glQueryCounter; +#define glQueryCounter glad_glQueryCounter +typedef void (APIENTRYP PFNGLGETQUERYOBJECTI64VPROC)(GLuint id, GLenum pname, GLint64 *params); +GLAPI PFNGLGETQUERYOBJECTI64VPROC glad_glGetQueryObjecti64v; +#define glGetQueryObjecti64v glad_glGetQueryObjecti64v +typedef void (APIENTRYP PFNGLGETQUERYOBJECTUI64VPROC)(GLuint id, GLenum pname, GLuint64 *params); +GLAPI PFNGLGETQUERYOBJECTUI64VPROC glad_glGetQueryObjectui64v; +#define glGetQueryObjectui64v glad_glGetQueryObjectui64v +typedef void (APIENTRYP PFNGLVERTEXATTRIBDIVISORPROC)(GLuint index, GLuint divisor); +GLAPI PFNGLVERTEXATTRIBDIVISORPROC glad_glVertexAttribDivisor; +#define glVertexAttribDivisor glad_glVertexAttribDivisor +typedef void (APIENTRYP PFNGLVERTEXATTRIBP1UIPROC)(GLuint index, GLenum type, GLboolean normalized, GLuint value); +GLAPI PFNGLVERTEXATTRIBP1UIPROC glad_glVertexAttribP1ui; +#define glVertexAttribP1ui glad_glVertexAttribP1ui +typedef void (APIENTRYP PFNGLVERTEXATTRIBP1UIVPROC)(GLuint index, GLenum type, GLboolean normalized, const GLuint *value); +GLAPI PFNGLVERTEXATTRIBP1UIVPROC glad_glVertexAttribP1uiv; +#define glVertexAttribP1uiv glad_glVertexAttribP1uiv +typedef void (APIENTRYP PFNGLVERTEXATTRIBP2UIPROC)(GLuint index, GLenum type, GLboolean normalized, GLuint value); +GLAPI PFNGLVERTEXATTRIBP2UIPROC glad_glVertexAttribP2ui; +#define glVertexAttribP2ui glad_glVertexAttribP2ui +typedef void (APIENTRYP PFNGLVERTEXATTRIBP2UIVPROC)(GLuint index, GLenum type, GLboolean normalized, const GLuint *value); +GLAPI PFNGLVERTEXATTRIBP2UIVPROC glad_glVertexAttribP2uiv; +#define glVertexAttribP2uiv glad_glVertexAttribP2uiv +typedef void (APIENTRYP PFNGLVERTEXATTRIBP3UIPROC)(GLuint index, GLenum type, GLboolean normalized, GLuint value); +GLAPI PFNGLVERTEXATTRIBP3UIPROC glad_glVertexAttribP3ui; +#define glVertexAttribP3ui glad_glVertexAttribP3ui +typedef void (APIENTRYP PFNGLVERTEXATTRIBP3UIVPROC)(GLuint index, GLenum type, GLboolean normalized, const GLuint *value); +GLAPI PFNGLVERTEXATTRIBP3UIVPROC glad_glVertexAttribP3uiv; +#define glVertexAttribP3uiv glad_glVertexAttribP3uiv +typedef void (APIENTRYP PFNGLVERTEXATTRIBP4UIPROC)(GLuint index, GLenum type, GLboolean normalized, GLuint value); +GLAPI PFNGLVERTEXATTRIBP4UIPROC glad_glVertexAttribP4ui; +#define glVertexAttribP4ui glad_glVertexAttribP4ui +typedef void (APIENTRYP PFNGLVERTEXATTRIBP4UIVPROC)(GLuint index, GLenum type, GLboolean normalized, const GLuint *value); +GLAPI PFNGLVERTEXATTRIBP4UIVPROC glad_glVertexAttribP4uiv; +#define glVertexAttribP4uiv glad_glVertexAttribP4uiv +typedef void (APIENTRYP PFNGLVERTEXP2UIPROC)(GLenum type, GLuint value); +GLAPI PFNGLVERTEXP2UIPROC glad_glVertexP2ui; +#define glVertexP2ui glad_glVertexP2ui +typedef void (APIENTRYP PFNGLVERTEXP2UIVPROC)(GLenum type, const GLuint *value); +GLAPI PFNGLVERTEXP2UIVPROC glad_glVertexP2uiv; +#define glVertexP2uiv glad_glVertexP2uiv +typedef void (APIENTRYP PFNGLVERTEXP3UIPROC)(GLenum type, GLuint value); +GLAPI PFNGLVERTEXP3UIPROC glad_glVertexP3ui; +#define glVertexP3ui glad_glVertexP3ui +typedef void (APIENTRYP PFNGLVERTEXP3UIVPROC)(GLenum type, const GLuint *value); +GLAPI PFNGLVERTEXP3UIVPROC glad_glVertexP3uiv; +#define glVertexP3uiv glad_glVertexP3uiv +typedef void (APIENTRYP PFNGLVERTEXP4UIPROC)(GLenum type, GLuint value); +GLAPI PFNGLVERTEXP4UIPROC glad_glVertexP4ui; +#define glVertexP4ui glad_glVertexP4ui +typedef void (APIENTRYP PFNGLVERTEXP4UIVPROC)(GLenum type, const GLuint *value); +GLAPI PFNGLVERTEXP4UIVPROC glad_glVertexP4uiv; +#define glVertexP4uiv glad_glVertexP4uiv +typedef void (APIENTRYP PFNGLTEXCOORDP1UIPROC)(GLenum type, GLuint coords); +GLAPI PFNGLTEXCOORDP1UIPROC glad_glTexCoordP1ui; +#define glTexCoordP1ui glad_glTexCoordP1ui +typedef void (APIENTRYP PFNGLTEXCOORDP1UIVPROC)(GLenum type, const GLuint *coords); +GLAPI PFNGLTEXCOORDP1UIVPROC glad_glTexCoordP1uiv; +#define glTexCoordP1uiv glad_glTexCoordP1uiv +typedef void (APIENTRYP PFNGLTEXCOORDP2UIPROC)(GLenum type, GLuint coords); +GLAPI PFNGLTEXCOORDP2UIPROC glad_glTexCoordP2ui; +#define glTexCoordP2ui glad_glTexCoordP2ui +typedef void (APIENTRYP PFNGLTEXCOORDP2UIVPROC)(GLenum type, const GLuint *coords); +GLAPI PFNGLTEXCOORDP2UIVPROC glad_glTexCoordP2uiv; +#define glTexCoordP2uiv glad_glTexCoordP2uiv +typedef void (APIENTRYP PFNGLTEXCOORDP3UIPROC)(GLenum type, GLuint coords); +GLAPI PFNGLTEXCOORDP3UIPROC glad_glTexCoordP3ui; +#define glTexCoordP3ui glad_glTexCoordP3ui +typedef void (APIENTRYP PFNGLTEXCOORDP3UIVPROC)(GLenum type, const GLuint *coords); +GLAPI PFNGLTEXCOORDP3UIVPROC glad_glTexCoordP3uiv; +#define glTexCoordP3uiv glad_glTexCoordP3uiv +typedef void (APIENTRYP PFNGLTEXCOORDP4UIPROC)(GLenum type, GLuint coords); +GLAPI PFNGLTEXCOORDP4UIPROC glad_glTexCoordP4ui; +#define glTexCoordP4ui glad_glTexCoordP4ui +typedef void (APIENTRYP PFNGLTEXCOORDP4UIVPROC)(GLenum type, const GLuint *coords); +GLAPI PFNGLTEXCOORDP4UIVPROC glad_glTexCoordP4uiv; +#define glTexCoordP4uiv glad_glTexCoordP4uiv +typedef void (APIENTRYP PFNGLMULTITEXCOORDP1UIPROC)(GLenum texture, GLenum type, GLuint coords); +GLAPI PFNGLMULTITEXCOORDP1UIPROC glad_glMultiTexCoordP1ui; +#define glMultiTexCoordP1ui glad_glMultiTexCoordP1ui +typedef void (APIENTRYP PFNGLMULTITEXCOORDP1UIVPROC)(GLenum texture, GLenum type, const GLuint *coords); +GLAPI PFNGLMULTITEXCOORDP1UIVPROC glad_glMultiTexCoordP1uiv; +#define glMultiTexCoordP1uiv glad_glMultiTexCoordP1uiv +typedef void (APIENTRYP PFNGLMULTITEXCOORDP2UIPROC)(GLenum texture, GLenum type, GLuint coords); +GLAPI PFNGLMULTITEXCOORDP2UIPROC glad_glMultiTexCoordP2ui; +#define glMultiTexCoordP2ui glad_glMultiTexCoordP2ui +typedef void (APIENTRYP PFNGLMULTITEXCOORDP2UIVPROC)(GLenum texture, GLenum type, const GLuint *coords); +GLAPI PFNGLMULTITEXCOORDP2UIVPROC glad_glMultiTexCoordP2uiv; +#define glMultiTexCoordP2uiv glad_glMultiTexCoordP2uiv +typedef void (APIENTRYP PFNGLMULTITEXCOORDP3UIPROC)(GLenum texture, GLenum type, GLuint coords); +GLAPI PFNGLMULTITEXCOORDP3UIPROC glad_glMultiTexCoordP3ui; +#define glMultiTexCoordP3ui glad_glMultiTexCoordP3ui +typedef void (APIENTRYP PFNGLMULTITEXCOORDP3UIVPROC)(GLenum texture, GLenum type, const GLuint *coords); +GLAPI PFNGLMULTITEXCOORDP3UIVPROC glad_glMultiTexCoordP3uiv; +#define glMultiTexCoordP3uiv glad_glMultiTexCoordP3uiv +typedef void (APIENTRYP PFNGLMULTITEXCOORDP4UIPROC)(GLenum texture, GLenum type, GLuint coords); +GLAPI PFNGLMULTITEXCOORDP4UIPROC glad_glMultiTexCoordP4ui; +#define glMultiTexCoordP4ui glad_glMultiTexCoordP4ui +typedef void (APIENTRYP PFNGLMULTITEXCOORDP4UIVPROC)(GLenum texture, GLenum type, const GLuint *coords); +GLAPI PFNGLMULTITEXCOORDP4UIVPROC glad_glMultiTexCoordP4uiv; +#define glMultiTexCoordP4uiv glad_glMultiTexCoordP4uiv +typedef void (APIENTRYP PFNGLNORMALP3UIPROC)(GLenum type, GLuint coords); +GLAPI PFNGLNORMALP3UIPROC glad_glNormalP3ui; +#define glNormalP3ui glad_glNormalP3ui +typedef void (APIENTRYP PFNGLNORMALP3UIVPROC)(GLenum type, const GLuint *coords); +GLAPI PFNGLNORMALP3UIVPROC glad_glNormalP3uiv; +#define glNormalP3uiv glad_glNormalP3uiv +typedef void (APIENTRYP PFNGLCOLORP3UIPROC)(GLenum type, GLuint color); +GLAPI PFNGLCOLORP3UIPROC glad_glColorP3ui; +#define glColorP3ui glad_glColorP3ui +typedef void (APIENTRYP PFNGLCOLORP3UIVPROC)(GLenum type, const GLuint *color); +GLAPI PFNGLCOLORP3UIVPROC glad_glColorP3uiv; +#define glColorP3uiv glad_glColorP3uiv +typedef void (APIENTRYP PFNGLCOLORP4UIPROC)(GLenum type, GLuint color); +GLAPI PFNGLCOLORP4UIPROC glad_glColorP4ui; +#define glColorP4ui glad_glColorP4ui +typedef void (APIENTRYP PFNGLCOLORP4UIVPROC)(GLenum type, const GLuint *color); +GLAPI PFNGLCOLORP4UIVPROC glad_glColorP4uiv; +#define glColorP4uiv glad_glColorP4uiv +typedef void (APIENTRYP PFNGLSECONDARYCOLORP3UIPROC)(GLenum type, GLuint color); +GLAPI PFNGLSECONDARYCOLORP3UIPROC glad_glSecondaryColorP3ui; +#define glSecondaryColorP3ui glad_glSecondaryColorP3ui +typedef void (APIENTRYP PFNGLSECONDARYCOLORP3UIVPROC)(GLenum type, const GLuint *color); +GLAPI PFNGLSECONDARYCOLORP3UIVPROC glad_glSecondaryColorP3uiv; +#define glSecondaryColorP3uiv glad_glSecondaryColorP3uiv +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/vendor/ini.c b/vendor/ini.c new file mode 100644 index 0000000000..6f0919d8e9 --- /dev/null +++ b/vendor/ini.c @@ -0,0 +1,333 @@ +/* inih -- simple .INI file parser + +SPDX-License-Identifier: BSD-3-Clause + +Copyright (C) 2009-2025, Ben Hoyt + +inih is released under the New BSD license (see LICENSE.txt). Go to the project +home page for more info: + +https://github.com/benhoyt/inih + +*/ + +#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS) +#define _CRT_SECURE_NO_WARNINGS +#endif + +#include +#include +#include +#include + +#include "ini.h" + +#if !INI_USE_STACK +#if INI_CUSTOM_ALLOCATOR +#include +void* ini_malloc(size_t size); +void ini_free(void* ptr); +void* ini_realloc(void* ptr, size_t size); +#else +#include +#define ini_malloc malloc +#define ini_free free +#define ini_realloc realloc +#endif +#endif + +#define MAX_SECTION 50 +#define MAX_NAME 50 + +/* Used by ini_parse_string() to keep track of string parsing state. */ +typedef struct { + const char* ptr; + size_t num_left; +} ini_parse_string_ctx; + +/* Strip whitespace chars off end of given string, in place. end must be a + pointer to the NUL terminator at the end of the string. Return s. */ +static char* ini_rstrip(char* s, char* end) +{ + while (end > s && isspace((unsigned char)(*--end))) + *end = '\0'; + return s; +} + +/* Return pointer to first non-whitespace char in given string. */ +static char* ini_lskip(const char* s) +{ + while (*s && isspace((unsigned char)(*s))) + s++; + return (char*)s; +} + +/* Return pointer to first char (of chars) or inline comment in given string, + or pointer to NUL at end of string if neither found. Inline comment must + be prefixed by a whitespace character to register as a comment. */ +static char* ini_find_chars_or_comment(const char* s, const char* chars) +{ +#if INI_ALLOW_INLINE_COMMENTS + int was_space = 0; + while (*s && (!chars || !strchr(chars, *s)) && + !(was_space && strchr(INI_INLINE_COMMENT_PREFIXES, *s))) { + was_space = isspace((unsigned char)(*s)); + s++; + } +#else + while (*s && (!chars || !strchr(chars, *s))) { + s++; + } +#endif + return (char*)s; +} + +/* Similar to strncpy, but ensures dest (size bytes) is + NUL-terminated, and doesn't pad with NULs. */ +static char* ini_strncpy0(char* dest, const char* src, size_t size) +{ + /* Could use strncpy internally, but it causes gcc warnings (see issue #91) */ + size_t i; + for (i = 0; i < size - 1 && src[i]; i++) + dest[i] = src[i]; + dest[i] = '\0'; + return dest; +} + +/* See documentation in header file. */ +int ini_parse_stream(ini_reader reader, void* stream, ini_handler handler, + void* user) +{ + /* Uses a fair bit of stack (use heap instead if you need to) */ +#if INI_USE_STACK + char line[INI_MAX_LINE]; + size_t max_line = INI_MAX_LINE; +#else + char* line; + size_t max_line = INI_INITIAL_ALLOC; +#endif +#if INI_ALLOW_REALLOC && !INI_USE_STACK + char* new_line; +#endif + char section[MAX_SECTION] = ""; +#if INI_ALLOW_MULTILINE + char prev_name[MAX_NAME] = ""; +#endif + + size_t offset; + char* start; + char* end; + char* name; + char* value; + int lineno = 0; + int error = 0; + char abyss[16]; /* Used to consume input when a line is too long. */ + size_t abyss_len; + + assert(reader != NULL); + assert(stream != NULL); + assert(handler != NULL); + +#if !INI_USE_STACK + line = (char*)ini_malloc(INI_INITIAL_ALLOC); + if (!line) { + return -2; + } +#endif + +#if INI_HANDLER_LINENO +#define HANDLER(u, s, n, v) handler(u, s, n, v, lineno) +#else +#define HANDLER(u, s, n, v) handler(u, s, n, v) +#endif + + /* Scan through stream line by line */ + while (reader(line, (int)max_line, stream) != NULL) { + offset = strlen(line); + +#if INI_ALLOW_REALLOC && !INI_USE_STACK + while (max_line < INI_MAX_LINE && + offset == max_line - 1 && line[offset - 1] != '\n') { + max_line *= 2; + if (max_line > INI_MAX_LINE) + max_line = INI_MAX_LINE; + new_line = ini_realloc(line, max_line); + if (!new_line) { + ini_free(line); + return -2; + } + line = new_line; + if (reader(line + offset, (int)(max_line - offset), stream) == NULL) + break; + offset += strlen(line + offset); + } +#endif + + lineno++; + + /* If line exceeded INI_MAX_LINE bytes, discard till end of line. */ + if (offset == max_line - 1 && line[offset - 1] != '\n') { + while (reader(abyss, sizeof(abyss), stream) != NULL) { + if (!error) + error = lineno; + abyss_len = strlen(abyss); + if (abyss_len > 0 && abyss[abyss_len - 1] == '\n') + break; + } + } + + start = line; +#if INI_ALLOW_BOM + if (lineno == 1 && (unsigned char)start[0] == 0xEF && + (unsigned char)start[1] == 0xBB && + (unsigned char)start[2] == 0xBF) { + start += 3; + } +#endif + start = ini_rstrip(ini_lskip(start), line + offset); + + if (strchr(INI_START_COMMENT_PREFIXES, *start)) { + /* Start-of-line comment */ + } +#if INI_ALLOW_MULTILINE + else if (*prev_name && *start && start > line) { +#if INI_ALLOW_INLINE_COMMENTS + end = ini_find_chars_or_comment(start, NULL); + *end = '\0'; + ini_rstrip(start, end); +#endif + /* Non-blank line with leading whitespace, treat as continuation + of previous name's value (as per Python configparser). */ + if (!HANDLER(user, section, prev_name, start) && !error) + error = lineno; + } +#endif + else if (*start == '[') { + /* A "[section]" line */ + end = ini_find_chars_or_comment(start + 1, "]"); + if (*end == ']') { + *end = '\0'; + ini_strncpy0(section, start + 1, sizeof(section)); +#if INI_ALLOW_MULTILINE + *prev_name = '\0'; +#endif +#if INI_CALL_HANDLER_ON_NEW_SECTION + if (!HANDLER(user, section, NULL, NULL) && !error) + error = lineno; +#endif + } + else if (!error) { + /* No ']' found on section line */ + error = lineno; + } + } + else if (*start) { + /* Not a comment, must be a name[=:]value pair */ + end = ini_find_chars_or_comment(start, "=:"); + if (*end == '=' || *end == ':') { + *end = '\0'; + name = ini_rstrip(start, end); + value = end + 1; +#if INI_ALLOW_INLINE_COMMENTS + end = ini_find_chars_or_comment(value, NULL); + *end = '\0'; +#endif + value = ini_lskip(value); + ini_rstrip(value, end); + +#if INI_ALLOW_MULTILINE + ini_strncpy0(prev_name, name, sizeof(prev_name)); +#endif + /* Valid name[=:]value pair found, call handler */ + if (!HANDLER(user, section, name, value) && !error) + error = lineno; + } + else { + /* No '=' or ':' found on name[=:]value line */ +#if INI_ALLOW_NO_VALUE + *end = '\0'; + name = ini_rstrip(start, end); + if (!HANDLER(user, section, name, NULL) && !error) + error = lineno; +#else + if (!error) + error = lineno; +#endif + } + } + +#if INI_STOP_ON_FIRST_ERROR + if (error) + break; +#endif + } + +#if !INI_USE_STACK + ini_free(line); +#endif + + return error; +} + +/* See documentation in header file. */ +int ini_parse_file(FILE* file, ini_handler handler, void* user) +{ + return ini_parse_stream((ini_reader)fgets, file, handler, user); +} + +/* See documentation in header file. */ +int ini_parse(const char* filename, ini_handler handler, void* user) +{ + FILE* file; + int error; + + file = fopen(filename, "r"); + if (!file) + return -1; + error = ini_parse_file(file, handler, user); + fclose(file); + return error; +} + +/* An ini_reader function to read the next line from a string buffer. This + is the fgets() equivalent used by ini_parse_string(). */ +static char* ini_reader_string(char* str, int num, void* stream) { + ini_parse_string_ctx* ctx = (ini_parse_string_ctx*)stream; + const char* ctx_ptr = ctx->ptr; + size_t ctx_num_left = ctx->num_left; + char* strp = str; + char c; + + if (ctx_num_left == 0 || num < 2) + return NULL; + + while (num > 1 && ctx_num_left != 0) { + c = *ctx_ptr++; + ctx_num_left--; + *strp++ = c; + if (c == '\n') + break; + num--; + } + + *strp = '\0'; + ctx->ptr = ctx_ptr; + ctx->num_left = ctx_num_left; + return str; +} + +/* See documentation in header file. */ +int ini_parse_string(const char* string, ini_handler handler, void* user) { + return ini_parse_string_length(string, strlen(string), handler, user); +} + +/* See documentation in header file. */ +int ini_parse_string_length(const char* string, size_t length, + ini_handler handler, void* user) { + ini_parse_string_ctx ctx; + + ctx.ptr = string; + ctx.num_left = length; + return ini_parse_stream((ini_reader)ini_reader_string, &ctx, handler, + user); +} diff --git a/vendor/ini.h b/vendor/ini.h new file mode 100644 index 0000000000..07aa7f48f0 --- /dev/null +++ b/vendor/ini.h @@ -0,0 +1,189 @@ +/* inih -- simple .INI file parser + +SPDX-License-Identifier: BSD-3-Clause + +Copyright (C) 2009-2025, Ben Hoyt + +inih is released under the New BSD license (see LICENSE.txt). Go to the project +home page for more info: + +https://github.com/benhoyt/inih + +*/ + +#ifndef INI_H +#define INI_H + +/* Make this header file easier to include in C++ code */ +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/* Nonzero if ini_handler callback should accept lineno parameter. */ +#ifndef INI_HANDLER_LINENO +#define INI_HANDLER_LINENO 0 +#endif + +/* Visibility symbols, required for Windows DLLs */ +#ifndef INI_API +#if defined _WIN32 || defined __CYGWIN__ +# ifdef INI_SHARED_LIB +# ifdef INI_SHARED_LIB_BUILDING +# define INI_API __declspec(dllexport) +# else +# define INI_API __declspec(dllimport) +# endif +# else +# define INI_API +# endif +#else +# if defined(__GNUC__) && __GNUC__ >= 4 +# define INI_API __attribute__ ((visibility ("default"))) +# else +# define INI_API +# endif +#endif +#endif + +/* Typedef for prototype of handler function. + + Note that even though the value parameter has type "const char*", the user + may cast to "char*" and modify its content, as the value is not used again + after the call to ini_handler. This is not true of section and name -- + those must not be modified. +*/ +#if INI_HANDLER_LINENO +typedef int (*ini_handler)(void* user, const char* section, + const char* name, const char* value, + int lineno); +#else +typedef int (*ini_handler)(void* user, const char* section, + const char* name, const char* value); +#endif + +/* Typedef for prototype of fgets-style reader function. */ +typedef char* (*ini_reader)(char* str, int num, void* stream); + +/* Parse given INI-style file. May have [section]s, name=value pairs + (whitespace stripped), and comments starting with ';' (semicolon). Section + is "" if name=value pair parsed before any section heading. name:value + pairs are also supported as a concession to Python's configparser. + + For each name=value pair parsed, call handler function with given user + pointer as well as section, name, and value (data only valid for duration + of handler call). Handler should return nonzero on success, zero on error. + + Returns 0 on success, line number of first error on parse error (doesn't + stop on first error), -1 on file open error, or -2 on memory allocation + error (only when INI_USE_STACK is zero). +*/ +INI_API int ini_parse(const char* filename, ini_handler handler, void* user); + +/* Same as ini_parse(), but takes a FILE* instead of filename. This doesn't + close the file when it's finished -- the caller must do that. */ +INI_API int ini_parse_file(FILE* file, ini_handler handler, void* user); + +/* Same as ini_parse(), but takes an ini_reader function pointer instead of + filename. Used for implementing custom or string-based I/O (see also + ini_parse_string). */ +INI_API int ini_parse_stream(ini_reader reader, void* stream, ini_handler handler, + void* user); + +/* Same as ini_parse(), but takes a zero-terminated string with the INI data + instead of a file. Useful for parsing INI data from a network socket or + which is already in memory. */ +INI_API int ini_parse_string(const char* string, ini_handler handler, void* user); + +/* Same as ini_parse_string(), but takes a string and its length, avoiding + strlen(). Useful for parsing INI data from a network socket or which is + already in memory, or interfacing with C++ std::string_view. */ +INI_API int ini_parse_string_length(const char* string, size_t length, ini_handler handler, void* user); + +/* Nonzero to allow multi-line value parsing, in the style of Python's + configparser. If allowed, ini_parse() will call the handler with the same + name for each subsequent line parsed. */ +#ifndef INI_ALLOW_MULTILINE +#define INI_ALLOW_MULTILINE 1 +#endif + +/* Nonzero to allow a UTF-8 BOM sequence (0xEF 0xBB 0xBF) at the start of + the file. See https://github.com/benhoyt/inih/issues/21 */ +#ifndef INI_ALLOW_BOM +#define INI_ALLOW_BOM 1 +#endif + +/* Chars that begin a start-of-line comment. Per Python configparser, allow + both ; and # comments at the start of a line by default. */ +#ifndef INI_START_COMMENT_PREFIXES +#define INI_START_COMMENT_PREFIXES ";#" +#endif + +/* Nonzero to allow inline comments (with valid inline comment characters + specified by INI_INLINE_COMMENT_PREFIXES). Set to 0 to turn off and match + Python 3.2+ configparser behaviour. */ +#ifndef INI_ALLOW_INLINE_COMMENTS +#define INI_ALLOW_INLINE_COMMENTS 1 +#endif +#ifndef INI_INLINE_COMMENT_PREFIXES +#define INI_INLINE_COMMENT_PREFIXES ";" +#endif + +/* Nonzero to use stack for line buffer, zero to use heap (malloc/free). */ +#ifndef INI_USE_STACK +#define INI_USE_STACK 1 +#endif + +/* Maximum line length for any line in INI file (stack or heap). Note that + this must be 3 more than the longest line (due to '\r', '\n', and '\0'). */ +#ifndef INI_MAX_LINE +#define INI_MAX_LINE 200 +#endif + +/* Nonzero to allow heap line buffer to grow via realloc(), zero for a + fixed-size buffer of INI_MAX_LINE bytes. Only applies if INI_USE_STACK is + zero. */ +#ifndef INI_ALLOW_REALLOC +#define INI_ALLOW_REALLOC 0 +#endif + +/* Initial size in bytes for heap line buffer. Only applies if INI_USE_STACK + is zero. */ +#ifndef INI_INITIAL_ALLOC +#define INI_INITIAL_ALLOC 200 +#endif + +/* Stop parsing on first error (default is to keep parsing). */ +#ifndef INI_STOP_ON_FIRST_ERROR +#define INI_STOP_ON_FIRST_ERROR 0 +#endif + +/* Nonzero to call the handler at the start of each new section (with + name and value NULL). Default is to only call the handler on + each name=value pair. */ +#ifndef INI_CALL_HANDLER_ON_NEW_SECTION +#define INI_CALL_HANDLER_ON_NEW_SECTION 0 +#endif + +/* Nonzero to allow a name without a value (no '=' or ':' on the line) and + call the handler with value NULL in this case. Default is to treat + no-value lines as an error. */ +#ifndef INI_ALLOW_NO_VALUE +#define INI_ALLOW_NO_VALUE 0 +#endif + +/* Nonzero to use custom ini_malloc, ini_free, and ini_realloc memory + allocation functions (INI_USE_STACK must also be 0). These functions must + have the same signatures as malloc/free/realloc and behave in a similar + way. ini_realloc is only needed if INI_ALLOW_REALLOC is set. */ +#ifndef INI_CUSTOM_ALLOCATOR +#define INI_CUSTOM_ALLOCATOR 0 +#endif + + +#ifdef __cplusplus +} +#endif + +#endif /* INI_H */ diff --git a/scripts/minshell.html b/vendor/minshell.html similarity index 92% rename from scripts/minshell.html rename to vendor/minshell.html index 4068ca36c7..6e2f137eb1 100644 --- a/scripts/minshell.html +++ b/vendor/minshell.html @@ -34,12 +34,8 @@ diff --git a/vendor/raygui.h b/vendor/raygui.h new file mode 100644 index 0000000000..8188e0e32b --- /dev/null +++ b/vendor/raygui.h @@ -0,0 +1,5980 @@ +/******************************************************************************************* +* +* raygui v4.5-dev - A simple and easy-to-use immediate-mode gui library +* +* DESCRIPTION: +* raygui is a tools-dev-focused immediate-mode-gui library based on raylib but also +* available as a standalone library, as long as input and drawing functions are provided +* +* FEATURES: +* - Immediate-mode gui, minimal retained data +* - +25 controls provided (basic and advanced) +* - Styling system for colors, font and metrics +* - Icons supported, embedded as a 1-bit icons pack +* - Standalone mode option (custom input/graphics backend) +* - Multiple support tools provided for raygui development +* +* POSSIBLE IMPROVEMENTS: +* - Better standalone mode API for easy plug of custom backends +* - Externalize required inputs, allow user easier customization +* +* LIMITATIONS: +* - No editable multi-line word-wraped text box supported +* - No auto-layout mechanism, up to the user to define controls position and size +* - Standalone mode requires library modification and some user work to plug another backend +* +* NOTES: +* - WARNING: GuiLoadStyle() and GuiLoadStyle{Custom}() functions, allocate memory for +* font atlas recs and glyphs, freeing that memory is (usually) up to the user, +* no unload function is explicitly provided... but note that GuiLoadStyleDefault() unloads +* by default any previously loaded font (texture, recs, glyphs) +* - Global UI alpha (guiAlpha) is applied inside GuiDrawRectangle() and GuiDrawText() functions +* +* CONTROLS PROVIDED: +* # Container/separators Controls +* - WindowBox --> StatusBar, Panel +* - GroupBox --> Line +* - Line +* - Panel --> StatusBar +* - ScrollPanel --> StatusBar +* - TabBar --> Button +* +* # Basic Controls +* - Label +* - LabelButton --> Label +* - Button +* - Toggle +* - ToggleGroup --> Toggle +* - ToggleSlider +* - CheckBox +* - ComboBox +* - DropdownBox +* - TextBox +* - ValueBox --> TextBox +* - Spinner --> Button, ValueBox +* - Slider +* - SliderBar --> Slider +* - ProgressBar +* - StatusBar +* - DummyRec +* - Grid +* +* # Advance Controls +* - ListView +* - ColorPicker --> ColorPanel, ColorBarHue +* - MessageBox --> Window, Label, Button +* - TextInputBox --> Window, Label, TextBox, Button +* +* It also provides a set of functions for styling the controls based on its properties (size, color) +* +* +* RAYGUI STYLE (guiStyle): +* raygui uses a global data array for all gui style properties (allocated on data segment by default), +* when a new style is loaded, it is loaded over the global style... but a default gui style could always be +* recovered with GuiLoadStyleDefault() function, that overwrites the current style to the default one +* +* The global style array size is fixed and depends on the number of controls and properties: +* +* static unsigned int guiStyle[RAYGUI_MAX_CONTROLS*(RAYGUI_MAX_PROPS_BASE + RAYGUI_MAX_PROPS_EXTENDED)]; +* +* guiStyle size is by default: 16*(16 + 8) = 384*4 = 1536 bytes = 1.5 KB +* +* Note that the first set of BASE properties (by default guiStyle[0..15]) belong to the generic style +* used for all controls, when any of those base values is set, it is automatically populated to all +* controls, so, specific control values overwriting generic style should be set after base values +* +* After the first BASE set we have the EXTENDED properties (by default guiStyle[16..23]), those +* properties are actually common to all controls and can not be overwritten individually (like BASE ones) +* Some of those properties are: TEXT_SIZE, TEXT_SPACING, LINE_COLOR, BACKGROUND_COLOR +* +* Custom control properties can be defined using the EXTENDED properties for each independent control. +* +* TOOL: rGuiStyler is a visual tool to customize raygui style: github.com/raysan5/rguistyler +* +* +* RAYGUI ICONS (guiIcons): +* raygui could use a global array containing icons data (allocated on data segment by default), +* a custom icons set could be loaded over this array using GuiLoadIcons(), but loaded icons set +* must be same RAYGUI_ICON_SIZE and no more than RAYGUI_ICON_MAX_ICONS will be loaded +* +* Every icon is codified in binary form, using 1 bit per pixel, so, every 16x16 icon +* requires 8 integers (16*16/32) to be stored in memory. +* +* When the icon is draw, actually one quad per pixel is drawn if the bit for that pixel is set +* +* The global icons array size is fixed and depends on the number of icons and size: +* +* static unsigned int guiIcons[RAYGUI_ICON_MAX_ICONS*RAYGUI_ICON_DATA_ELEMENTS]; +* +* guiIcons size is by default: 256*(16*16/32) = 2048*4 = 8192 bytes = 8 KB +* +* TOOL: rGuiIcons is a visual tool to customize/create raygui icons: github.com/raysan5/rguiicons +* +* RAYGUI LAYOUT: +* raygui currently does not provide an auto-layout mechanism like other libraries, +* layouts must be defined manually on controls drawing, providing the right bounds Rectangle for it +* +* TOOL: rGuiLayout is a visual tool to create raygui layouts: github.com/raysan5/rguilayout +* +* CONFIGURATION: +* #define RAYGUI_IMPLEMENTATION +* Generates the implementation of the library into the included file +* If not defined, the library is in header only mode and can be included in other headers +* or source files without problems. But only ONE file should hold the implementation +* +* #define RAYGUI_STANDALONE +* Avoid raylib.h header inclusion in this file. Data types defined on raylib are defined +* internally in the library and input management and drawing functions must be provided by +* the user (check library implementation for further details) +* +* #define RAYGUI_NO_ICONS +* Avoid including embedded ricons data (256 icons, 16x16 pixels, 1-bit per pixel, 2KB) +* +* #define RAYGUI_CUSTOM_ICONS +* Includes custom ricons.h header defining a set of custom icons, +* this file can be generated using rGuiIcons tool +* +* #define RAYGUI_DEBUG_RECS_BOUNDS +* Draw control bounds rectangles for debug +* +* #define RAYGUI_DEBUG_TEXT_BOUNDS +* Draw text bounds rectangles for debug +* +* VERSIONS HISTORY: +* 5.0-dev (2025) Current dev version... +* ADDED: guiControlExclusiveMode and guiControlExclusiveRec for exclusive modes +* ADDED: GuiValueBoxFloat() +* ADDED: GuiDropdonwBox() properties: DROPDOWN_ARROW_HIDDEN, DROPDOWN_ROLL_UP +* ADDED: GuiListView() property: LIST_ITEMS_BORDER_WIDTH +* ADDED: GuiLoadIconsFromMemory() +* ADDED: Multiple new icons +* REMOVED: GuiSpinner() from controls list, using BUTTON + VALUEBOX properties +* REMOVED: GuiSliderPro(), functionality was redundant +* REVIEWED: Controls using text labels to use LABEL properties +* REVIEWED: Replaced sprintf() by snprintf() for more safety +* REVIEWED: GuiTabBar(), close tab with mouse middle button +* REVIEWED: GuiScrollPanel(), scroll speed proportional to content +* REVIEWED: GuiDropdownBox(), support roll up and hidden arrow +* REVIEWED: GuiTextBox(), cursor position initialization +* REVIEWED: GuiSliderPro(), control value change check +* REVIEWED: GuiGrid(), simplified implementation +* REVIEWED: GuiIconText(), increase buffer size and reviewed padding +* REVIEWED: GuiDrawText(), improved wrap mode drawing +* REVIEWED: GuiScrollBar(), minor tweaks +* REVIEWED: GuiProgressBar(), improved borders computing +* REVIEWED: GuiTextBox(), multiple improvements: autocursor and more +* REVIEWED: Functions descriptions, removed wrong return value reference +* REDESIGNED: GuiColorPanel(), improved HSV <-> RGBA convertion +* +* 4.0 (12-Sep-2023) ADDED: GuiToggleSlider() +* ADDED: GuiColorPickerHSV() and GuiColorPanelHSV() +* ADDED: Multiple new icons, mostly compiler related +* ADDED: New DEFAULT properties: TEXT_LINE_SPACING, TEXT_ALIGNMENT_VERTICAL, TEXT_WRAP_MODE +* ADDED: New enum values: GuiTextAlignment, GuiTextAlignmentVertical, GuiTextWrapMode +* ADDED: Support loading styles with custom font charset from external file +* REDESIGNED: GuiTextBox(), support mouse cursor positioning +* REDESIGNED: GuiDrawText(), support multiline and word-wrap modes (read only) +* REDESIGNED: GuiProgressBar() to be more visual, progress affects border color +* REDESIGNED: Global alpha consideration moved to GuiDrawRectangle() and GuiDrawText() +* REDESIGNED: GuiScrollPanel(), get parameters by reference and return result value +* REDESIGNED: GuiToggleGroup(), get parameters by reference and return result value +* REDESIGNED: GuiComboBox(), get parameters by reference and return result value +* REDESIGNED: GuiCheckBox(), get parameters by reference and return result value +* REDESIGNED: GuiSlider(), get parameters by reference and return result value +* REDESIGNED: GuiSliderBar(), get parameters by reference and return result value +* REDESIGNED: GuiProgressBar(), get parameters by reference and return result value +* REDESIGNED: GuiListView(), get parameters by reference and return result value +* REDESIGNED: GuiColorPicker(), get parameters by reference and return result value +* REDESIGNED: GuiColorPanel(), get parameters by reference and return result value +* REDESIGNED: GuiColorBarAlpha(), get parameters by reference and return result value +* REDESIGNED: GuiColorBarHue(), get parameters by reference and return result value +* REDESIGNED: GuiGrid(), get parameters by reference and return result value +* REDESIGNED: GuiGrid(), added extra parameter +* REDESIGNED: GuiListViewEx(), change parameters order +* REDESIGNED: All controls return result as int value +* REVIEWED: GuiScrollPanel() to avoid smallish scroll-bars +* REVIEWED: All examples and specially controls_test_suite +* RENAMED: gui_file_dialog module to gui_window_file_dialog +* UPDATED: All styles to include ISO-8859-15 charset (as much as possible) +* +* 3.6 (10-May-2023) ADDED: New icon: SAND_TIMER +* ADDED: GuiLoadStyleFromMemory() (binary only) +* REVIEWED: GuiScrollBar() horizontal movement key +* REVIEWED: GuiTextBox() crash on cursor movement +* REVIEWED: GuiTextBox(), additional inputs support +* REVIEWED: GuiLabelButton(), avoid text cut +* REVIEWED: GuiTextInputBox(), password input +* REVIEWED: Local GetCodepointNext(), aligned with raylib +* REDESIGNED: GuiSlider*()/GuiScrollBar() to support out-of-bounds +* +* 3.5 (20-Apr-2023) ADDED: GuiTabBar(), based on GuiToggle() +* ADDED: Helper functions to split text in separate lines +* ADDED: Multiple new icons, useful for code editing tools +* REMOVED: Unneeded icon editing functions +* REMOVED: GuiTextBoxMulti(), very limited and broken +* REMOVED: MeasureTextEx() dependency, logic directly implemented +* REMOVED: DrawTextEx() dependency, logic directly implemented +* REVIEWED: GuiScrollBar(), improve mouse-click behaviour +* REVIEWED: Library header info, more info, better organized +* REDESIGNED: GuiTextBox() to support cursor movement +* REDESIGNED: GuiDrawText() to divide drawing by lines +* +* 3.2 (22-May-2022) RENAMED: Some enum values, for unification, avoiding prefixes +* REMOVED: GuiScrollBar(), only internal +* REDESIGNED: GuiPanel() to support text parameter +* REDESIGNED: GuiScrollPanel() to support text parameter +* REDESIGNED: GuiColorPicker() to support text parameter +* REDESIGNED: GuiColorPanel() to support text parameter +* REDESIGNED: GuiColorBarAlpha() to support text parameter +* REDESIGNED: GuiColorBarHue() to support text parameter +* REDESIGNED: GuiTextInputBox() to support password +* +* 3.1 (12-Jan-2022) REVIEWED: Default style for consistency (aligned with rGuiLayout v2.5 tool) +* REVIEWED: GuiLoadStyle() to support compressed font atlas image data and unload previous textures +* REVIEWED: External icons usage logic +* REVIEWED: GuiLine() for centered alignment when including text +* RENAMED: Multiple controls properties definitions to prepend RAYGUI_ +* RENAMED: RICON_ references to RAYGUI_ICON_ for library consistency +* Projects updated and multiple tweaks +* +* 3.0 (04-Nov-2021) Integrated ricons data to avoid external file +* REDESIGNED: GuiTextBoxMulti() +* REMOVED: GuiImageButton*() +* Multiple minor tweaks and bugs corrected +* +* 2.9 (17-Mar-2021) REMOVED: Tooltip API +* 2.8 (03-May-2020) Centralized rectangles drawing to GuiDrawRectangle() +* 2.7 (20-Feb-2020) ADDED: Possible tooltips API +* 2.6 (09-Sep-2019) ADDED: GuiTextInputBox() +* REDESIGNED: GuiListView*(), GuiDropdownBox(), GuiSlider*(), GuiProgressBar(), GuiMessageBox() +* REVIEWED: GuiTextBox(), GuiSpinner(), GuiValueBox(), GuiLoadStyle() +* Replaced property INNER_PADDING by TEXT_PADDING, renamed some properties +* ADDED: 8 new custom styles ready to use +* Multiple minor tweaks and bugs corrected +* +* 2.5 (28-May-2019) Implemented extended GuiTextBox(), GuiValueBox(), GuiSpinner() +* 2.3 (29-Apr-2019) ADDED: rIcons auxiliar library and support for it, multiple controls reviewed +* Refactor all controls drawing mechanism to use control state +* 2.2 (05-Feb-2019) ADDED: GuiScrollBar(), GuiScrollPanel(), reviewed GuiListView(), removed Gui*Ex() controls +* 2.1 (26-Dec-2018) REDESIGNED: GuiCheckBox(), GuiComboBox(), GuiDropdownBox(), GuiToggleGroup() > Use combined text string +* REDESIGNED: Style system (breaking change) +* 2.0 (08-Nov-2018) ADDED: Support controls guiLock and custom fonts +* REVIEWED: GuiComboBox(), GuiListView()... +* 1.9 (09-Oct-2018) REVIEWED: GuiGrid(), GuiTextBox(), GuiTextBoxMulti(), GuiValueBox()... +* 1.8 (01-May-2018) Lot of rework and redesign to align with rGuiStyler and rGuiLayout +* 1.5 (21-Jun-2017) Working in an improved styles system +* 1.4 (15-Jun-2017) Rewritten all GUI functions (removed useless ones) +* 1.3 (12-Jun-2017) Complete redesign of style system +* 1.1 (01-Jun-2017) Complete review of the library +* 1.0 (07-Jun-2016) Converted to header-only by Ramon Santamaria +* 0.9 (07-Mar-2016) Reviewed and tested by Albert Martos, Ian Eito, Sergio Martinez and Ramon Santamaria +* 0.8 (27-Aug-2015) Initial release. Implemented by Kevin Gato, Daniel Nicolás and Ramon Santamaria +* +* DEPENDENCIES: +* raylib 5.0 - Inputs reading (keyboard/mouse), shapes drawing, font loading and text drawing +* +* STANDALONE MODE: +* By default raygui depends on raylib mostly for the inputs and the drawing functionality but that dependency can be disabled +* with the config flag RAYGUI_STANDALONE. In that case is up to the user to provide another backend to cover library needs +* +* The following functions should be redefined for a custom backend: +* +* - Vector2 GetMousePosition(void); +* - float GetMouseWheelMove(void); +* - bool IsMouseButtonDown(int button); +* - bool IsMouseButtonPressed(int button); +* - bool IsMouseButtonReleased(int button); +* - bool IsKeyDown(int key); +* - bool IsKeyPressed(int key); +* - int GetCharPressed(void); // -- GuiTextBox(), GuiValueBox() +* +* - void DrawRectangle(int x, int y, int width, int height, Color color); // -- GuiDrawRectangle() +* - void DrawRectangleGradientEx(Rectangle rec, Color col1, Color col2, Color col3, Color col4); // -- GuiColorPicker() +* +* - Font GetFontDefault(void); // -- GuiLoadStyleDefault() +* - Font LoadFontEx(const char *fileName, int fontSize, int *codepoints, int codepointCount); // -- GuiLoadStyle() +* - Texture2D LoadTextureFromImage(Image image); // -- GuiLoadStyle(), required to load texture from embedded font atlas image +* - void SetShapesTexture(Texture2D tex, Rectangle rec); // -- GuiLoadStyle(), required to set shapes rec to font white rec (optimization) +* - char *LoadFileText(const char *fileName); // -- GuiLoadStyle(), required to load charset data +* - void UnloadFileText(char *text); // -- GuiLoadStyle(), required to unload charset data +* - const char *GetDirectoryPath(const char *filePath); // -- GuiLoadStyle(), required to find charset/font file from text .rgs +* - int *LoadCodepoints(const char *text, int *count); // -- GuiLoadStyle(), required to load required font codepoints list +* - void UnloadCodepoints(int *codepoints); // -- GuiLoadStyle(), required to unload codepoints list +* - unsigned char *DecompressData(const unsigned char *compData, int compDataSize, int *dataSize); // -- GuiLoadStyle() +* +* CONTRIBUTORS: +* Ramon Santamaria: Supervision, review, redesign, update and maintenance +* Vlad Adrian: Complete rewrite of GuiTextBox() to support extended features (2019) +* Sergio Martinez: Review, testing (2015) and redesign of multiple controls (2018) +* Adria Arranz: Testing and implementation of additional controls (2018) +* Jordi Jorba: Testing and implementation of additional controls (2018) +* Albert Martos: Review and testing of the library (2015) +* Ian Eito: Review and testing of the library (2015) +* Kevin Gato: Initial implementation of basic components (2014) +* Daniel Nicolas: Initial implementation of basic components (2014) +* +* +* LICENSE: zlib/libpng +* +* Copyright (c) 2014-2025 Ramon Santamaria (@raysan5) +* +* This software is provided "as-is", without any express or implied warranty. In no event +* will the authors be held liable for any damages arising from the use of this software. +* +* Permission is granted to anyone to use this software for any purpose, including commercial +* applications, and to alter it and redistribute it freely, subject to the following restrictions: +* +* 1. The origin of this software must not be misrepresented; you must not claim that you +* wrote the original software. If you use this software in a product, an acknowledgment +* in the product documentation would be appreciated but is not required. +* +* 2. Altered source versions must be plainly marked as such, and must not be misrepresented +* as being the original software. +* +* 3. This notice may not be removed or altered from any source distribution. +* +**********************************************************************************************/ + +#ifndef RAYGUI_H +#define RAYGUI_H + +#define RAYGUI_VERSION_MAJOR 4 +#define RAYGUI_VERSION_MINOR 5 +#define RAYGUI_VERSION_PATCH 0 +#define RAYGUI_VERSION "5.0-dev" + +#if !defined(RAYGUI_STANDALONE) + #include "raylib.h" +#endif + +// Function specifiers in case library is build/used as a shared library (Windows) +// NOTE: Microsoft specifiers to tell compiler that symbols are imported/exported from a .dll +#if defined(_WIN32) + #if defined(BUILD_LIBTYPE_SHARED) + #define RAYGUIAPI __declspec(dllexport) // We are building the library as a Win32 shared library (.dll) + #elif defined(USE_LIBTYPE_SHARED) + #define RAYGUIAPI __declspec(dllimport) // We are using the library as a Win32 shared library (.dll) + #endif +#endif + +// Function specifiers definition +#ifndef RAYGUIAPI + #define RAYGUIAPI // Functions defined as 'extern' by default (implicit specifiers) +#endif + +//---------------------------------------------------------------------------------- +// Defines and Macros +//---------------------------------------------------------------------------------- +// Simple log system to avoid printf() calls if required +// NOTE: Avoiding those calls, also avoids const strings memory usage +#define RAYGUI_SUPPORT_LOG_INFO +#if defined(RAYGUI_SUPPORT_LOG_INFO) + #define RAYGUI_LOG(...) printf(__VA_ARGS__) +#else + #define RAYGUI_LOG(...) +#endif + +//---------------------------------------------------------------------------------- +// Types and Structures Definition +// NOTE: Some types are required for RAYGUI_STANDALONE usage +//---------------------------------------------------------------------------------- +#if defined(RAYGUI_STANDALONE) + #ifndef __cplusplus + // Boolean type + #ifndef true + typedef enum { false, true } bool; + #endif + #endif + + // Vector2 type + typedef struct Vector2 { + float x; + float y; + } Vector2; + + // Vector3 type // -- ConvertHSVtoRGB(), ConvertRGBtoHSV() + typedef struct Vector3 { + float x; + float y; + float z; + } Vector3; + + // Color type, RGBA (32bit) + typedef struct Color { + unsigned char r; + unsigned char g; + unsigned char b; + unsigned char a; + } Color; + + // Rectangle type + typedef struct Rectangle { + float x; + float y; + float width; + float height; + } Rectangle; + + // TODO: Texture2D type is very coupled to raylib, required by Font type + // It should be redesigned to be provided by user + typedef struct Texture { + unsigned int id; // OpenGL texture id + int width; // Texture base width + int height; // Texture base height + int mipmaps; // Mipmap levels, 1 by default + int format; // Data format (PixelFormat type) + } Texture; + + // Texture2D, same as Texture + typedef Texture Texture2D; + + // Image, pixel data stored in CPU memory (RAM) + typedef struct Image { + void *data; // Image raw data + int width; // Image base width + int height; // Image base height + int mipmaps; // Mipmap levels, 1 by default + int format; // Data format (PixelFormat type) + } Image; + + // GlyphInfo, font characters glyphs info + typedef struct GlyphInfo { + int value; // Character value (Unicode) + int offsetX; // Character offset X when drawing + int offsetY; // Character offset Y when drawing + int advanceX; // Character advance position X + Image image; // Character image data + } GlyphInfo; + + // TODO: Font type is very coupled to raylib, mostly required by GuiLoadStyle() + // It should be redesigned to be provided by user + typedef struct Font { + int baseSize; // Base size (default chars height) + int glyphCount; // Number of glyph characters + int glyphPadding; // Padding around the glyph characters + Texture2D texture; // Texture atlas containing the glyphs + Rectangle *recs; // Rectangles in texture for the glyphs + GlyphInfo *glyphs; // Glyphs info data + } Font; +#endif + +// Style property +// NOTE: Used when exporting style as code for convenience +typedef struct GuiStyleProp { + unsigned short controlId; // Control identifier + unsigned short propertyId; // Property identifier + int propertyValue; // Property value +} GuiStyleProp; + +/* +// Controls text style -NOT USED- +// NOTE: Text style is defined by control +typedef struct GuiTextStyle { + unsigned int size; + int charSpacing; + int lineSpacing; + int alignmentH; + int alignmentV; + int padding; +} GuiTextStyle; +*/ + +// Gui control state +typedef enum { + STATE_NORMAL = 0, + STATE_FOCUSED, + STATE_PRESSED, + STATE_DISABLED +} GuiState; + +// Gui control text alignment +typedef enum { + TEXT_ALIGN_LEFT = 0, + TEXT_ALIGN_CENTER, + TEXT_ALIGN_RIGHT +} GuiTextAlignment; + +// Gui control text alignment vertical +// NOTE: Text vertical position inside the text bounds +typedef enum { + TEXT_ALIGN_TOP = 0, + TEXT_ALIGN_MIDDLE, + TEXT_ALIGN_BOTTOM +} GuiTextAlignmentVertical; + +// Gui control text wrap mode +// NOTE: Useful for multiline text +typedef enum { + TEXT_WRAP_NONE = 0, + TEXT_WRAP_CHAR, + TEXT_WRAP_WORD +} GuiTextWrapMode; + +// Gui controls +typedef enum { + // Default -> populates to all controls when set + DEFAULT = 0, + + // Basic controls + LABEL, // Used also for: LABELBUTTON + BUTTON, + TOGGLE, // Used also for: TOGGLEGROUP + SLIDER, // Used also for: SLIDERBAR, TOGGLESLIDER + PROGRESSBAR, + CHECKBOX, + COMBOBOX, + DROPDOWNBOX, + TEXTBOX, // Used also for: TEXTBOXMULTI + VALUEBOX, + CONTROL11, + LISTVIEW, + COLORPICKER, + SCROLLBAR, + STATUSBAR +} GuiControl; + +// Gui base properties for every control +// NOTE: RAYGUI_MAX_PROPS_BASE properties (by default 16 properties) +typedef enum { + BORDER_COLOR_NORMAL = 0, // Control border color in STATE_NORMAL + BASE_COLOR_NORMAL, // Control base color in STATE_NORMAL + TEXT_COLOR_NORMAL, // Control text color in STATE_NORMAL + BORDER_COLOR_FOCUSED, // Control border color in STATE_FOCUSED + BASE_COLOR_FOCUSED, // Control base color in STATE_FOCUSED + TEXT_COLOR_FOCUSED, // Control text color in STATE_FOCUSED + BORDER_COLOR_PRESSED, // Control border color in STATE_PRESSED + BASE_COLOR_PRESSED, // Control base color in STATE_PRESSED + TEXT_COLOR_PRESSED, // Control text color in STATE_PRESSED + BORDER_COLOR_DISABLED, // Control border color in STATE_DISABLED + BASE_COLOR_DISABLED, // Control base color in STATE_DISABLED + TEXT_COLOR_DISABLED, // Control text color in STATE_DISABLED + BORDER_WIDTH = 12, // Control border size, 0 for no border + //TEXT_SIZE, // Control text size (glyphs max height) -> GLOBAL for all controls + //TEXT_SPACING, // Control text spacing between glyphs -> GLOBAL for all controls + //TEXT_LINE_SPACING, // Control text spacing between lines -> GLOBAL for all controls + TEXT_PADDING = 13, // Control text padding, not considering border + TEXT_ALIGNMENT = 14, // Control text horizontal alignment inside control text bound (after border and padding) + //TEXT_WRAP_MODE // Control text wrap-mode inside text bounds -> GLOBAL for all controls +} GuiControlProperty; + +// TODO: Which text styling properties should be global or per-control? +// At this moment TEXT_PADDING and TEXT_ALIGNMENT is configured and saved per control while +// TEXT_SIZE, TEXT_SPACING, TEXT_LINE_SPACING, TEXT_ALIGNMENT_VERTICAL, TEXT_WRAP_MODE are global and +// should be configured by user as needed while defining the UI layout + +// Gui extended properties depend on control +// NOTE: RAYGUI_MAX_PROPS_EXTENDED properties (by default, max 8 properties) +//---------------------------------------------------------------------------------- +// DEFAULT extended properties +// NOTE: Those properties are common to all controls or global +// WARNING: We only have 8 slots for those properties by default!!! -> New global control: TEXT? +typedef enum { + TEXT_SIZE = 16, // Text size (glyphs max height) + TEXT_SPACING, // Text spacing between glyphs + LINE_COLOR, // Line control color + BACKGROUND_COLOR, // Background color + TEXT_LINE_SPACING, // Text spacing between lines + TEXT_ALIGNMENT_VERTICAL, // Text vertical alignment inside text bounds (after border and padding) + TEXT_WRAP_MODE // Text wrap-mode inside text bounds + //TEXT_DECORATION // Text decoration: 0-None, 1-Underline, 2-Line-through, 3-Overline + //TEXT_DECORATION_THICK // Text decoration line thickness +} GuiDefaultProperty; + +// Other possible text properties: +// TEXT_WEIGHT // Normal, Italic, Bold -> Requires specific font change +// TEXT_INDENT // Text indentation -> Now using TEXT_PADDING... + +// Label +//typedef enum { } GuiLabelProperty; + +// Button/Spinner +//typedef enum { } GuiButtonProperty; + +// Toggle/ToggleGroup +typedef enum { + GROUP_PADDING = 16, // ToggleGroup separation between toggles +} GuiToggleProperty; + +// Slider/SliderBar +typedef enum { + SLIDER_WIDTH = 16, // Slider size of internal bar + SLIDER_PADDING // Slider/SliderBar internal bar padding +} GuiSliderProperty; + +// ProgressBar +typedef enum { + PROGRESS_PADDING = 16, // ProgressBar internal padding +} GuiProgressBarProperty; + +// ScrollBar +typedef enum { + ARROWS_SIZE = 16, // ScrollBar arrows size + ARROWS_VISIBLE, // ScrollBar arrows visible + SCROLL_SLIDER_PADDING, // ScrollBar slider internal padding + SCROLL_SLIDER_SIZE, // ScrollBar slider size + SCROLL_PADDING, // ScrollBar scroll padding from arrows + SCROLL_SPEED, // ScrollBar scrolling speed +} GuiScrollBarProperty; + +// CheckBox +typedef enum { + CHECK_PADDING = 16 // CheckBox internal check padding +} GuiCheckBoxProperty; + +// ComboBox +typedef enum { + COMBO_BUTTON_WIDTH = 16, // ComboBox right button width + COMBO_BUTTON_SPACING // ComboBox button separation +} GuiComboBoxProperty; + +// DropdownBox +typedef enum { + ARROW_PADDING = 16, // DropdownBox arrow separation from border and items + DROPDOWN_ITEMS_SPACING, // DropdownBox items separation + DROPDOWN_ARROW_HIDDEN, // DropdownBox arrow hidden + DROPDOWN_ROLL_UP // DropdownBox roll up flag (default rolls down) +} GuiDropdownBoxProperty; + +// TextBox/TextBoxMulti/ValueBox/Spinner +typedef enum { + TEXT_READONLY = 16, // TextBox in read-only mode: 0-text editable, 1-text no-editable +} GuiTextBoxProperty; + +// ValueBox/Spinner +typedef enum { + SPINNER_BUTTON_WIDTH = 16, // Spinner left/right buttons width + SPINNER_BUTTON_SPACING, // Spinner buttons separation +} GuiValueBoxProperty; + +// Control11 +//typedef enum { } GuiControl11Property; + +// ListView +typedef enum { + LIST_ITEMS_HEIGHT = 16, // ListView items height + LIST_ITEMS_SPACING, // ListView items separation + SCROLLBAR_WIDTH, // ListView scrollbar size (usually width) + SCROLLBAR_SIDE, // ListView scrollbar side (0-SCROLLBAR_LEFT_SIDE, 1-SCROLLBAR_RIGHT_SIDE) + LIST_ITEMS_BORDER_NORMAL, // ListView items border enabled in normal state + LIST_ITEMS_BORDER_WIDTH // ListView items border width +} GuiListViewProperty; + +// ColorPicker +typedef enum { + COLOR_SELECTOR_SIZE = 16, + HUEBAR_WIDTH, // ColorPicker right hue bar width + HUEBAR_PADDING, // ColorPicker right hue bar separation from panel + HUEBAR_SELECTOR_HEIGHT, // ColorPicker right hue bar selector height + HUEBAR_SELECTOR_OVERFLOW // ColorPicker right hue bar selector overflow +} GuiColorPickerProperty; + +#define SCROLLBAR_LEFT_SIDE 0 +#define SCROLLBAR_RIGHT_SIDE 1 + +//---------------------------------------------------------------------------------- +// Global Variables Definition +//---------------------------------------------------------------------------------- +// ... + +//---------------------------------------------------------------------------------- +// Module Functions Declaration +//---------------------------------------------------------------------------------- + +#if defined(__cplusplus) +extern "C" { // Prevents name mangling of functions +#endif + +// Global gui state control functions +RAYGUIAPI void GuiEnable(void); // Enable gui controls (global state) +RAYGUIAPI void GuiDisable(void); // Disable gui controls (global state) +RAYGUIAPI void GuiLock(void); // Lock gui controls (global state) +RAYGUIAPI void GuiUnlock(void); // Unlock gui controls (global state) +RAYGUIAPI bool GuiIsLocked(void); // Check if gui is locked (global state) +RAYGUIAPI void GuiSetAlpha(float alpha); // Set gui controls alpha (global state), alpha goes from 0.0f to 1.0f +RAYGUIAPI void GuiSetState(int state); // Set gui state (global state) +RAYGUIAPI int GuiGetState(void); // Get gui state (global state) + +// Font set/get functions +RAYGUIAPI void GuiSetFont(Font font); // Set gui custom font (global state) +RAYGUIAPI Font GuiGetFont(void); // Get gui custom font (global state) + +// Style set/get functions +RAYGUIAPI void GuiSetStyle(int control, int property, int value); // Set one style property +RAYGUIAPI int GuiGetStyle(int control, int property); // Get one style property + +// Styles loading functions +RAYGUIAPI void GuiLoadStyle(const char *fileName); // Load style file over global style variable (.rgs) +RAYGUIAPI void GuiLoadStyleDefault(void); // Load style default over global style + +// Tooltips management functions +RAYGUIAPI void GuiEnableTooltip(void); // Enable gui tooltips (global state) +RAYGUIAPI void GuiDisableTooltip(void); // Disable gui tooltips (global state) +RAYGUIAPI void GuiSetTooltip(const char *tooltip); // Set tooltip string + +// Icons functionality +RAYGUIAPI const char *GuiIconText(int iconId, const char *text); // Get text with icon id prepended (if supported) +#if !defined(RAYGUI_NO_ICONS) +RAYGUIAPI void GuiSetIconScale(int scale); // Set default icon drawing size +RAYGUIAPI unsigned int *GuiGetIcons(void); // Get raygui icons data pointer +RAYGUIAPI char **GuiLoadIcons(const char *fileName, bool loadIconsName); // Load raygui icons file (.rgi) into internal icons data +RAYGUIAPI void GuiDrawIcon(int iconId, int posX, int posY, int pixelSize, Color color); // Draw icon using pixel size at specified position +#endif + +// Utility functions +RAYGUIAPI int GuiGetTextWidth(const char *text); // Get text width considering gui style and icon size (if required) + +// Controls +//---------------------------------------------------------------------------------------------------------- +// Container/separator controls, useful for controls organization +RAYGUIAPI int GuiWindowBox(Rectangle bounds, const char *title); // Window Box control, shows a window that can be closed +RAYGUIAPI int GuiGroupBox(Rectangle bounds, const char *text); // Group Box control with text name +RAYGUIAPI int GuiLine(Rectangle bounds, const char *text); // Line separator control, could contain text +RAYGUIAPI int GuiPanel(Rectangle bounds, const char *text); // Panel control, useful to group controls +RAYGUIAPI int GuiTabBar(Rectangle bounds, const char **text, int count, int *active); // Tab Bar control, returns TAB to be closed or -1 +RAYGUIAPI int GuiScrollPanel(Rectangle bounds, const char *text, Rectangle content, Vector2 *scroll, Rectangle *view); // Scroll Panel control + +// Basic controls set +RAYGUIAPI int GuiLabel(Rectangle bounds, const char *text); // Label control +RAYGUIAPI int GuiButton(Rectangle bounds, const char *text); // Button control, returns true when clicked +RAYGUIAPI int GuiLabelButton(Rectangle bounds, const char *text); // Label button control, returns true when clicked +RAYGUIAPI int GuiToggle(Rectangle bounds, const char *text, bool *active); // Toggle Button control +RAYGUIAPI int GuiToggleGroup(Rectangle bounds, const char *text, int *active); // Toggle Group control +RAYGUIAPI int GuiToggleSlider(Rectangle bounds, const char *text, int *active); // Toggle Slider control +RAYGUIAPI int GuiCheckBox(Rectangle bounds, const char *text, bool *checked); // Check Box control, returns true when active +RAYGUIAPI int GuiComboBox(Rectangle bounds, const char *text, int *active); // Combo Box control + +RAYGUIAPI int GuiDropdownBox(Rectangle bounds, const char *text, int *active, bool editMode); // Dropdown Box control +RAYGUIAPI int GuiSpinner(Rectangle bounds, const char *text, int *value, int minValue, int maxValue, bool editMode); // Spinner control +RAYGUIAPI int GuiValueBox(Rectangle bounds, const char *text, int *value, int minValue, int maxValue, bool editMode); // Value Box control, updates input text with numbers +RAYGUIAPI int GuiValueBoxFloat(Rectangle bounds, const char *text, char *textValue, float *value, bool editMode); // Value box control for float values +RAYGUIAPI int GuiTextBox(Rectangle bounds, char *text, int textSize, bool editMode); // Text Box control, updates input text + +RAYGUIAPI int GuiSlider(Rectangle bounds, const char *textLeft, const char *textRight, float *value, float minValue, float maxValue); // Slider control +RAYGUIAPI int GuiSliderBar(Rectangle bounds, const char *textLeft, const char *textRight, float *value, float minValue, float maxValue); // Slider Bar control +RAYGUIAPI int GuiProgressBar(Rectangle bounds, const char *textLeft, const char *textRight, float *value, float minValue, float maxValue); // Progress Bar control +RAYGUIAPI int GuiStatusBar(Rectangle bounds, const char *text); // Status Bar control, shows info text +RAYGUIAPI int GuiDummyRec(Rectangle bounds, const char *text); // Dummy control for placeholders +RAYGUIAPI int GuiGrid(Rectangle bounds, const char *text, float spacing, int subdivs, Vector2 *mouseCell); // Grid control + +// Advance controls set +RAYGUIAPI int GuiListView(Rectangle bounds, const char *text, int *scrollIndex, int *active); // List View control +RAYGUIAPI int GuiListViewEx(Rectangle bounds, const char **text, int count, int *scrollIndex, int *active, int *focus); // List View with extended parameters +RAYGUIAPI int GuiMessageBox(Rectangle bounds, const char *title, const char *message, const char *buttons); // Message Box control, displays a message +RAYGUIAPI int GuiTextInputBox(Rectangle bounds, const char *title, const char *message, const char *buttons, char *text, int textMaxSize, bool *secretViewActive); // Text Input Box control, ask for text, supports secret +RAYGUIAPI int GuiColorPicker(Rectangle bounds, const char *text, Color *color); // Color Picker control (multiple color controls) +RAYGUIAPI int GuiColorPanel(Rectangle bounds, const char *text, Color *color); // Color Panel control +RAYGUIAPI int GuiColorBarAlpha(Rectangle bounds, const char *text, float *alpha); // Color Bar Alpha control +RAYGUIAPI int GuiColorBarHue(Rectangle bounds, const char *text, float *value); // Color Bar Hue control +RAYGUIAPI int GuiColorPickerHSV(Rectangle bounds, const char *text, Vector3 *colorHsv); // Color Picker control that avoids conversion to RGB on each call (multiple color controls) +RAYGUIAPI int GuiColorPanelHSV(Rectangle bounds, const char *text, Vector3 *colorHsv); // Color Panel control that updates Hue-Saturation-Value color value, used by GuiColorPickerHSV() +//---------------------------------------------------------------------------------------------------------- + +#if !defined(RAYGUI_NO_ICONS) + +#if !defined(RAYGUI_CUSTOM_ICONS) +//---------------------------------------------------------------------------------- +// Icons enumeration +//---------------------------------------------------------------------------------- +typedef enum { + ICON_NONE = 0, + ICON_FOLDER_FILE_OPEN = 1, + ICON_FILE_SAVE_CLASSIC = 2, + ICON_FOLDER_OPEN = 3, + ICON_FOLDER_SAVE = 4, + ICON_FILE_OPEN = 5, + ICON_FILE_SAVE = 6, + ICON_FILE_EXPORT = 7, + ICON_FILE_ADD = 8, + ICON_FILE_DELETE = 9, + ICON_FILETYPE_TEXT = 10, + ICON_FILETYPE_AUDIO = 11, + ICON_FILETYPE_IMAGE = 12, + ICON_FILETYPE_PLAY = 13, + ICON_FILETYPE_VIDEO = 14, + ICON_FILETYPE_INFO = 15, + ICON_FILE_COPY = 16, + ICON_FILE_CUT = 17, + ICON_FILE_PASTE = 18, + ICON_CURSOR_HAND = 19, + ICON_CURSOR_POINTER = 20, + ICON_CURSOR_CLASSIC = 21, + ICON_PENCIL = 22, + ICON_PENCIL_BIG = 23, + ICON_BRUSH_CLASSIC = 24, + ICON_BRUSH_PAINTER = 25, + ICON_WATER_DROP = 26, + ICON_COLOR_PICKER = 27, + ICON_RUBBER = 28, + ICON_COLOR_BUCKET = 29, + ICON_TEXT_T = 30, + ICON_TEXT_A = 31, + ICON_SCALE = 32, + ICON_RESIZE = 33, + ICON_FILTER_POINT = 34, + ICON_FILTER_BILINEAR = 35, + ICON_CROP = 36, + ICON_CROP_ALPHA = 37, + ICON_SQUARE_TOGGLE = 38, + ICON_SYMMETRY = 39, + ICON_SYMMETRY_HORIZONTAL = 40, + ICON_SYMMETRY_VERTICAL = 41, + ICON_LENS = 42, + ICON_LENS_BIG = 43, + ICON_EYE_ON = 44, + ICON_EYE_OFF = 45, + ICON_FILTER_TOP = 46, + ICON_FILTER = 47, + ICON_TARGET_POINT = 48, + ICON_TARGET_SMALL = 49, + ICON_TARGET_BIG = 50, + ICON_TARGET_MOVE = 51, + ICON_CURSOR_MOVE = 52, + ICON_CURSOR_SCALE = 53, + ICON_CURSOR_SCALE_RIGHT = 54, + ICON_CURSOR_SCALE_LEFT = 55, + ICON_UNDO = 56, + ICON_REDO = 57, + ICON_REREDO = 58, + ICON_MUTATE = 59, + ICON_ROTATE = 60, + ICON_REPEAT = 61, + ICON_SHUFFLE = 62, + ICON_EMPTYBOX = 63, + ICON_TARGET = 64, + ICON_TARGET_SMALL_FILL = 65, + ICON_TARGET_BIG_FILL = 66, + ICON_TARGET_MOVE_FILL = 67, + ICON_CURSOR_MOVE_FILL = 68, + ICON_CURSOR_SCALE_FILL = 69, + ICON_CURSOR_SCALE_RIGHT_FILL = 70, + ICON_CURSOR_SCALE_LEFT_FILL = 71, + ICON_UNDO_FILL = 72, + ICON_REDO_FILL = 73, + ICON_REREDO_FILL = 74, + ICON_MUTATE_FILL = 75, + ICON_ROTATE_FILL = 76, + ICON_REPEAT_FILL = 77, + ICON_SHUFFLE_FILL = 78, + ICON_EMPTYBOX_SMALL = 79, + ICON_BOX = 80, + ICON_BOX_TOP = 81, + ICON_BOX_TOP_RIGHT = 82, + ICON_BOX_RIGHT = 83, + ICON_BOX_BOTTOM_RIGHT = 84, + ICON_BOX_BOTTOM = 85, + ICON_BOX_BOTTOM_LEFT = 86, + ICON_BOX_LEFT = 87, + ICON_BOX_TOP_LEFT = 88, + ICON_BOX_CENTER = 89, + ICON_BOX_CIRCLE_MASK = 90, + ICON_POT = 91, + ICON_ALPHA_MULTIPLY = 92, + ICON_ALPHA_CLEAR = 93, + ICON_DITHERING = 94, + ICON_MIPMAPS = 95, + ICON_BOX_GRID = 96, + ICON_GRID = 97, + ICON_BOX_CORNERS_SMALL = 98, + ICON_BOX_CORNERS_BIG = 99, + ICON_FOUR_BOXES = 100, + ICON_GRID_FILL = 101, + ICON_BOX_MULTISIZE = 102, + ICON_ZOOM_SMALL = 103, + ICON_ZOOM_MEDIUM = 104, + ICON_ZOOM_BIG = 105, + ICON_ZOOM_ALL = 106, + ICON_ZOOM_CENTER = 107, + ICON_BOX_DOTS_SMALL = 108, + ICON_BOX_DOTS_BIG = 109, + ICON_BOX_CONCENTRIC = 110, + ICON_BOX_GRID_BIG = 111, + ICON_OK_TICK = 112, + ICON_CROSS = 113, + ICON_ARROW_LEFT = 114, + ICON_ARROW_RIGHT = 115, + ICON_ARROW_DOWN = 116, + ICON_ARROW_UP = 117, + ICON_ARROW_LEFT_FILL = 118, + ICON_ARROW_RIGHT_FILL = 119, + ICON_ARROW_DOWN_FILL = 120, + ICON_ARROW_UP_FILL = 121, + ICON_AUDIO = 122, + ICON_FX = 123, + ICON_WAVE = 124, + ICON_WAVE_SINUS = 125, + ICON_WAVE_SQUARE = 126, + ICON_WAVE_TRIANGULAR = 127, + ICON_CROSS_SMALL = 128, + ICON_PLAYER_PREVIOUS = 129, + ICON_PLAYER_PLAY_BACK = 130, + ICON_PLAYER_PLAY = 131, + ICON_PLAYER_PAUSE = 132, + ICON_PLAYER_STOP = 133, + ICON_PLAYER_NEXT = 134, + ICON_PLAYER_RECORD = 135, + ICON_MAGNET = 136, + ICON_LOCK_CLOSE = 137, + ICON_LOCK_OPEN = 138, + ICON_CLOCK = 139, + ICON_TOOLS = 140, + ICON_GEAR = 141, + ICON_GEAR_BIG = 142, + ICON_BIN = 143, + ICON_HAND_POINTER = 144, + ICON_LASER = 145, + ICON_COIN = 146, + ICON_EXPLOSION = 147, + ICON_1UP = 148, + ICON_PLAYER = 149, + ICON_PLAYER_JUMP = 150, + ICON_KEY = 151, + ICON_DEMON = 152, + ICON_TEXT_POPUP = 153, + ICON_GEAR_EX = 154, + ICON_CRACK = 155, + ICON_CRACK_POINTS = 156, + ICON_STAR = 157, + ICON_DOOR = 158, + ICON_EXIT = 159, + ICON_MODE_2D = 160, + ICON_MODE_3D = 161, + ICON_CUBE = 162, + ICON_CUBE_FACE_TOP = 163, + ICON_CUBE_FACE_LEFT = 164, + ICON_CUBE_FACE_FRONT = 165, + ICON_CUBE_FACE_BOTTOM = 166, + ICON_CUBE_FACE_RIGHT = 167, + ICON_CUBE_FACE_BACK = 168, + ICON_CAMERA = 169, + ICON_SPECIAL = 170, + ICON_LINK_NET = 171, + ICON_LINK_BOXES = 172, + ICON_LINK_MULTI = 173, + ICON_LINK = 174, + ICON_LINK_BROKE = 175, + ICON_TEXT_NOTES = 176, + ICON_NOTEBOOK = 177, + ICON_SUITCASE = 178, + ICON_SUITCASE_ZIP = 179, + ICON_MAILBOX = 180, + ICON_MONITOR = 181, + ICON_PRINTER = 182, + ICON_PHOTO_CAMERA = 183, + ICON_PHOTO_CAMERA_FLASH = 184, + ICON_HOUSE = 185, + ICON_HEART = 186, + ICON_CORNER = 187, + ICON_VERTICAL_BARS = 188, + ICON_VERTICAL_BARS_FILL = 189, + ICON_LIFE_BARS = 190, + ICON_INFO = 191, + ICON_CROSSLINE = 192, + ICON_HELP = 193, + ICON_FILETYPE_ALPHA = 194, + ICON_FILETYPE_HOME = 195, + ICON_LAYERS_VISIBLE = 196, + ICON_LAYERS = 197, + ICON_WINDOW = 198, + ICON_HIDPI = 199, + ICON_FILETYPE_BINARY = 200, + ICON_HEX = 201, + ICON_SHIELD = 202, + ICON_FILE_NEW = 203, + ICON_FOLDER_ADD = 204, + ICON_ALARM = 205, + ICON_CPU = 206, + ICON_ROM = 207, + ICON_STEP_OVER = 208, + ICON_STEP_INTO = 209, + ICON_STEP_OUT = 210, + ICON_RESTART = 211, + ICON_BREAKPOINT_ON = 212, + ICON_BREAKPOINT_OFF = 213, + ICON_BURGER_MENU = 214, + ICON_CASE_SENSITIVE = 215, + ICON_REG_EXP = 216, + ICON_FOLDER = 217, + ICON_FILE = 218, + ICON_SAND_TIMER = 219, + ICON_WARNING = 220, + ICON_HELP_BOX = 221, + ICON_INFO_BOX = 222, + ICON_PRIORITY = 223, + ICON_LAYERS_ISO = 224, + ICON_LAYERS2 = 225, + ICON_MLAYERS = 226, + ICON_MAPS = 227, + ICON_HOT = 228, + ICON_LABEL = 229, + ICON_NAME_ID = 230, + ICON_SLICING = 231, + ICON_MANUAL_CONTROL = 232, + ICON_COLLISION = 233, + ICON_234 = 234, + ICON_235 = 235, + ICON_236 = 236, + ICON_237 = 237, + ICON_238 = 238, + ICON_239 = 239, + ICON_240 = 240, + ICON_241 = 241, + ICON_242 = 242, + ICON_243 = 243, + ICON_244 = 244, + ICON_245 = 245, + ICON_246 = 246, + ICON_247 = 247, + ICON_248 = 248, + ICON_249 = 249, + ICON_250 = 250, + ICON_251 = 251, + ICON_252 = 252, + ICON_253 = 253, + ICON_254 = 254, + ICON_255 = 255, +} GuiIconName; +#endif + +#endif + +#if defined(__cplusplus) +} // Prevents name mangling of functions +#endif + +#endif // RAYGUI_H + +/*********************************************************************************** +* +* RAYGUI IMPLEMENTATION +* +************************************************************************************/ + +#if defined(RAYGUI_IMPLEMENTATION) + +#include // required for: isspace() [GuiTextBox()] +#include // Required for: FILE, fopen(), fclose(), fprintf(), feof(), fscanf(), snprintf(), vsprintf() [GuiLoadStyle(), GuiLoadIcons()] +#include // Required for: strlen() [GuiTextBox(), GuiValueBox()], memset(), memcpy() +#include // Required for: va_list, va_start(), vfprintf(), va_end() [TextFormat()] +#include // Required for: roundf() [GuiColorPicker()] + +// Allow custom memory allocators +#if defined(RAYGUI_MALLOC) || defined(RAYGUI_CALLOC) || defined(RAYGUI_FREE) + #if !defined(RAYGUI_MALLOC) || !defined(RAYGUI_CALLOC) || !defined(RAYGUI_FREE) + #error "RAYGUI: if RAYGUI_MALLOC, RAYGUI_CALLOC, or RAYGUI_FREE is customized, all three must be customized" + #endif +#else + #include // Required for: malloc(), calloc(), free() [GuiLoadStyle(), GuiLoadIcons()] + + #define RAYGUI_MALLOC(sz) malloc(sz) + #define RAYGUI_CALLOC(n,sz) calloc(n,sz) + #define RAYGUI_FREE(p) free(p) +#endif + +#ifdef __cplusplus + #define RAYGUI_CLITERAL(name) name +#else + #define RAYGUI_CLITERAL(name) (name) +#endif + +// Check if two rectangles are equal, used to validate a slider bounds as an id +#ifndef CHECK_BOUNDS_ID + #define CHECK_BOUNDS_ID(src, dst) ((src.x == dst.x) && (src.y == dst.y) && (src.width == dst.width) && (src.height == dst.height)) +#endif + +#if !defined(RAYGUI_NO_ICONS) && !defined(RAYGUI_CUSTOM_ICONS) + +// Embedded icons, no external file provided +#define RAYGUI_ICON_SIZE 16 // Size of icons in pixels (squared) +#define RAYGUI_ICON_MAX_ICONS 256 // Maximum number of icons +#define RAYGUI_ICON_MAX_NAME_LENGTH 32 // Maximum length of icon name id + +// Icons data is defined by bit array (every bit represents one pixel) +// Those arrays are stored as unsigned int data arrays, so, +// every array element defines 32 pixels (bits) of information +// One icon is defined by 8 int, (8 int * 32 bit = 256 bit = 16*16 pixels) +// NOTE: Number of elemens depend on RAYGUI_ICON_SIZE (by default 16x16 pixels) +#define RAYGUI_ICON_DATA_ELEMENTS (RAYGUI_ICON_SIZE*RAYGUI_ICON_SIZE/32) + +//---------------------------------------------------------------------------------- +// Icons data for all gui possible icons (allocated on data segment by default) +// +// NOTE 1: Every icon is codified in binary form, using 1 bit per pixel, so, +// every 16x16 icon requires 8 integers (16*16/32) to be stored +// +// NOTE 2: A different icon set could be loaded over this array using GuiLoadIcons(), +// but loaded icons set must be same RAYGUI_ICON_SIZE and no more than RAYGUI_ICON_MAX_ICONS +// +// guiIcons size is by default: 256*(16*16/32) = 2048*4 = 8192 bytes = 8 KB +//---------------------------------------------------------------------------------- +static unsigned int guiIcons[RAYGUI_ICON_MAX_ICONS*RAYGUI_ICON_DATA_ELEMENTS] = { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_NONE + 0x3ff80000, 0x2f082008, 0x2042207e, 0x40027fc2, 0x40024002, 0x40024002, 0x40024002, 0x00007ffe, // ICON_FOLDER_FILE_OPEN + 0x3ffe0000, 0x44226422, 0x400247e2, 0x5ffa4002, 0x57ea500a, 0x500a500a, 0x40025ffa, 0x00007ffe, // ICON_FILE_SAVE_CLASSIC + 0x00000000, 0x0042007e, 0x40027fc2, 0x40024002, 0x41024002, 0x44424282, 0x793e4102, 0x00000100, // ICON_FOLDER_OPEN + 0x00000000, 0x0042007e, 0x40027fc2, 0x40024002, 0x41024102, 0x44424102, 0x793e4282, 0x00000000, // ICON_FOLDER_SAVE + 0x3ff00000, 0x201c2010, 0x20042004, 0x21042004, 0x24442284, 0x21042104, 0x20042104, 0x00003ffc, // ICON_FILE_OPEN + 0x3ff00000, 0x201c2010, 0x20042004, 0x21042004, 0x21042104, 0x22842444, 0x20042104, 0x00003ffc, // ICON_FILE_SAVE + 0x3ff00000, 0x201c2010, 0x00042004, 0x20041004, 0x20844784, 0x00841384, 0x20042784, 0x00003ffc, // ICON_FILE_EXPORT + 0x3ff00000, 0x201c2010, 0x20042004, 0x20042004, 0x22042204, 0x22042f84, 0x20042204, 0x00003ffc, // ICON_FILE_ADD + 0x3ff00000, 0x201c2010, 0x20042004, 0x20042004, 0x25042884, 0x25042204, 0x20042884, 0x00003ffc, // ICON_FILE_DELETE + 0x3ff00000, 0x201c2010, 0x20042004, 0x20042ff4, 0x20042ff4, 0x20042ff4, 0x20042004, 0x00003ffc, // ICON_FILETYPE_TEXT + 0x3ff00000, 0x201c2010, 0x27042004, 0x244424c4, 0x26442444, 0x20642664, 0x20042004, 0x00003ffc, // ICON_FILETYPE_AUDIO + 0x3ff00000, 0x201c2010, 0x26042604, 0x20042004, 0x35442884, 0x2414222c, 0x20042004, 0x00003ffc, // ICON_FILETYPE_IMAGE + 0x3ff00000, 0x201c2010, 0x20c42004, 0x22442144, 0x22442444, 0x20c42144, 0x20042004, 0x00003ffc, // ICON_FILETYPE_PLAY + 0x3ff00000, 0x3ffc2ff0, 0x3f3c2ff4, 0x3dbc2eb4, 0x3dbc2bb4, 0x3f3c2eb4, 0x3ffc2ff4, 0x00002ff4, // ICON_FILETYPE_VIDEO + 0x3ff00000, 0x201c2010, 0x21842184, 0x21842004, 0x21842184, 0x21842184, 0x20042184, 0x00003ffc, // ICON_FILETYPE_INFO + 0x0ff00000, 0x381c0810, 0x28042804, 0x28042804, 0x28042804, 0x28042804, 0x20102ffc, 0x00003ff0, // ICON_FILE_COPY + 0x00000000, 0x701c0000, 0x079c1e14, 0x55a000f0, 0x079c00f0, 0x701c1e14, 0x00000000, 0x00000000, // ICON_FILE_CUT + 0x01c00000, 0x13e41bec, 0x3f841004, 0x204420c4, 0x20442044, 0x20442044, 0x207c2044, 0x00003fc0, // ICON_FILE_PASTE + 0x00000000, 0x3aa00fe0, 0x2abc2aa0, 0x2aa42aa4, 0x20042aa4, 0x20042004, 0x3ffc2004, 0x00000000, // ICON_CURSOR_HAND + 0x00000000, 0x003c000c, 0x030800c8, 0x30100c10, 0x10202020, 0x04400840, 0x01800280, 0x00000000, // ICON_CURSOR_POINTER + 0x00000000, 0x00180000, 0x01f00078, 0x03e007f0, 0x07c003e0, 0x04000e40, 0x00000000, 0x00000000, // ICON_CURSOR_CLASSIC + 0x00000000, 0x04000000, 0x11000a00, 0x04400a80, 0x01100220, 0x00580088, 0x00000038, 0x00000000, // ICON_PENCIL + 0x04000000, 0x15000a00, 0x50402880, 0x14102820, 0x05040a08, 0x015c028c, 0x007c00bc, 0x00000000, // ICON_PENCIL_BIG + 0x01c00000, 0x01400140, 0x01400140, 0x0ff80140, 0x0ff80808, 0x0aa80808, 0x0aa80aa8, 0x00000ff8, // ICON_BRUSH_CLASSIC + 0x1ffc0000, 0x5ffc7ffe, 0x40004000, 0x00807f80, 0x01c001c0, 0x01c001c0, 0x01c001c0, 0x00000080, // ICON_BRUSH_PAINTER + 0x00000000, 0x00800000, 0x01c00080, 0x03e001c0, 0x07f003e0, 0x036006f0, 0x000001c0, 0x00000000, // ICON_WATER_DROP + 0x00000000, 0x3e003800, 0x1f803f80, 0x0c201e40, 0x02080c10, 0x00840104, 0x00380044, 0x00000000, // ICON_COLOR_PICKER + 0x00000000, 0x07800300, 0x1fe00fc0, 0x3f883fd0, 0x0e021f04, 0x02040402, 0x00f00108, 0x00000000, // ICON_RUBBER + 0x00c00000, 0x02800140, 0x08200440, 0x20081010, 0x2ffe3004, 0x03f807fc, 0x00e001f0, 0x00000040, // ICON_COLOR_BUCKET + 0x00000000, 0x21843ffc, 0x01800180, 0x01800180, 0x01800180, 0x01800180, 0x03c00180, 0x00000000, // ICON_TEXT_T + 0x00800000, 0x01400180, 0x06200340, 0x0c100620, 0x1ff80c10, 0x380c1808, 0x70067004, 0x0000f80f, // ICON_TEXT_A + 0x78000000, 0x50004000, 0x00004800, 0x03c003c0, 0x03c003c0, 0x00100000, 0x0002000a, 0x0000000e, // ICON_SCALE + 0x75560000, 0x5e004002, 0x54001002, 0x41001202, 0x408200fe, 0x40820082, 0x40820082, 0x00006afe, // ICON_RESIZE + 0x00000000, 0x3f003f00, 0x3f003f00, 0x3f003f00, 0x00400080, 0x001c0020, 0x001c001c, 0x00000000, // ICON_FILTER_POINT + 0x6d800000, 0x00004080, 0x40804080, 0x40800000, 0x00406d80, 0x001c0020, 0x001c001c, 0x00000000, // ICON_FILTER_BILINEAR + 0x40080000, 0x1ffe2008, 0x14081008, 0x11081208, 0x10481088, 0x10081028, 0x10047ff8, 0x00001002, // ICON_CROP + 0x00100000, 0x3ffc0010, 0x2ab03550, 0x22b02550, 0x20b02150, 0x20302050, 0x2000fff0, 0x00002000, // ICON_CROP_ALPHA + 0x40000000, 0x1ff82000, 0x04082808, 0x01082208, 0x00482088, 0x00182028, 0x35542008, 0x00000002, // ICON_SQUARE_TOGGLE + 0x00000000, 0x02800280, 0x06c006c0, 0x0ea00ee0, 0x1e901eb0, 0x3e883e98, 0x7efc7e8c, 0x00000000, // ICON_SYMMETRY + 0x01000000, 0x05600100, 0x1d480d50, 0x7d423d44, 0x3d447d42, 0x0d501d48, 0x01000560, 0x00000100, // ICON_SYMMETRY_HORIZONTAL + 0x01800000, 0x04200240, 0x10080810, 0x00001ff8, 0x00007ffe, 0x0ff01ff8, 0x03c007e0, 0x00000180, // ICON_SYMMETRY_VERTICAL + 0x00000000, 0x010800f0, 0x02040204, 0x02040204, 0x07f00308, 0x1c000e00, 0x30003800, 0x00000000, // ICON_LENS + 0x00000000, 0x061803f0, 0x08240c0c, 0x08040814, 0x0c0c0804, 0x23f01618, 0x18002400, 0x00000000, // ICON_LENS_BIG + 0x00000000, 0x00000000, 0x1c7007c0, 0x638e3398, 0x1c703398, 0x000007c0, 0x00000000, 0x00000000, // ICON_EYE_ON + 0x00000000, 0x10002000, 0x04700fc0, 0x610e3218, 0x1c703098, 0x001007a0, 0x00000008, 0x00000000, // ICON_EYE_OFF + 0x00000000, 0x00007ffc, 0x40047ffc, 0x10102008, 0x04400820, 0x02800280, 0x02800280, 0x00000100, // ICON_FILTER_TOP + 0x00000000, 0x40027ffe, 0x10082004, 0x04200810, 0x02400240, 0x02400240, 0x01400240, 0x000000c0, // ICON_FILTER + 0x00800000, 0x00800080, 0x00000080, 0x3c9e0000, 0x00000000, 0x00800080, 0x00800080, 0x00000000, // ICON_TARGET_POINT + 0x00800000, 0x00800080, 0x00800080, 0x3f7e01c0, 0x008001c0, 0x00800080, 0x00800080, 0x00000000, // ICON_TARGET_SMALL + 0x00800000, 0x00800080, 0x03e00080, 0x3e3e0220, 0x03e00220, 0x00800080, 0x00800080, 0x00000000, // ICON_TARGET_BIG + 0x01000000, 0x04400280, 0x01000100, 0x43842008, 0x43849ab2, 0x01002008, 0x04400100, 0x01000280, // ICON_TARGET_MOVE + 0x01000000, 0x04400280, 0x01000100, 0x41042108, 0x41049ff2, 0x01002108, 0x04400100, 0x01000280, // ICON_CURSOR_MOVE + 0x781e0000, 0x500a4002, 0x04204812, 0x00000240, 0x02400000, 0x48120420, 0x4002500a, 0x0000781e, // ICON_CURSOR_SCALE + 0x00000000, 0x20003c00, 0x24002800, 0x01000200, 0x00400080, 0x00140024, 0x003c0004, 0x00000000, // ICON_CURSOR_SCALE_RIGHT + 0x00000000, 0x0004003c, 0x00240014, 0x00800040, 0x02000100, 0x28002400, 0x3c002000, 0x00000000, // ICON_CURSOR_SCALE_LEFT + 0x00000000, 0x00100020, 0x10101fc8, 0x10001020, 0x10001000, 0x10001000, 0x00001fc0, 0x00000000, // ICON_UNDO + 0x00000000, 0x08000400, 0x080813f8, 0x00080408, 0x00080008, 0x00080008, 0x000003f8, 0x00000000, // ICON_REDO + 0x00000000, 0x3ffc0000, 0x20042004, 0x20002000, 0x20402000, 0x3f902020, 0x00400020, 0x00000000, // ICON_REREDO + 0x00000000, 0x3ffc0000, 0x20042004, 0x27fc2004, 0x20202000, 0x3fc82010, 0x00200010, 0x00000000, // ICON_MUTATE + 0x00000000, 0x0ff00000, 0x10081818, 0x11801008, 0x10001180, 0x18101020, 0x00100fc8, 0x00000020, // ICON_ROTATE + 0x00000000, 0x04000200, 0x240429fc, 0x20042204, 0x20442004, 0x3f942024, 0x00400020, 0x00000000, // ICON_REPEAT + 0x00000000, 0x20001000, 0x22104c0e, 0x00801120, 0x11200040, 0x4c0e2210, 0x10002000, 0x00000000, // ICON_SHUFFLE + 0x7ffe0000, 0x50024002, 0x44024802, 0x41024202, 0x40424082, 0x40124022, 0x4002400a, 0x00007ffe, // ICON_EMPTYBOX + 0x00800000, 0x03e00080, 0x08080490, 0x3c9e0808, 0x08080808, 0x03e00490, 0x00800080, 0x00000000, // ICON_TARGET + 0x00800000, 0x00800080, 0x00800080, 0x3ffe01c0, 0x008001c0, 0x00800080, 0x00800080, 0x00000000, // ICON_TARGET_SMALL_FILL + 0x00800000, 0x00800080, 0x03e00080, 0x3ffe03e0, 0x03e003e0, 0x00800080, 0x00800080, 0x00000000, // ICON_TARGET_BIG_FILL + 0x01000000, 0x07c00380, 0x01000100, 0x638c2008, 0x638cfbbe, 0x01002008, 0x07c00100, 0x01000380, // ICON_TARGET_MOVE_FILL + 0x01000000, 0x07c00380, 0x01000100, 0x610c2108, 0x610cfffe, 0x01002108, 0x07c00100, 0x01000380, // ICON_CURSOR_MOVE_FILL + 0x781e0000, 0x6006700e, 0x04204812, 0x00000240, 0x02400000, 0x48120420, 0x700e6006, 0x0000781e, // ICON_CURSOR_SCALE_FILL + 0x00000000, 0x38003c00, 0x24003000, 0x01000200, 0x00400080, 0x000c0024, 0x003c001c, 0x00000000, // ICON_CURSOR_SCALE_RIGHT_FILL + 0x00000000, 0x001c003c, 0x0024000c, 0x00800040, 0x02000100, 0x30002400, 0x3c003800, 0x00000000, // ICON_CURSOR_SCALE_LEFT_FILL + 0x00000000, 0x00300020, 0x10301ff8, 0x10001020, 0x10001000, 0x10001000, 0x00001fc0, 0x00000000, // ICON_UNDO_FILL + 0x00000000, 0x0c000400, 0x0c081ff8, 0x00080408, 0x00080008, 0x00080008, 0x000003f8, 0x00000000, // ICON_REDO_FILL + 0x00000000, 0x3ffc0000, 0x20042004, 0x20002000, 0x20402000, 0x3ff02060, 0x00400060, 0x00000000, // ICON_REREDO_FILL + 0x00000000, 0x3ffc0000, 0x20042004, 0x27fc2004, 0x20202000, 0x3ff82030, 0x00200030, 0x00000000, // ICON_MUTATE_FILL + 0x00000000, 0x0ff00000, 0x10081818, 0x11801008, 0x10001180, 0x18301020, 0x00300ff8, 0x00000020, // ICON_ROTATE_FILL + 0x00000000, 0x06000200, 0x26042ffc, 0x20042204, 0x20442004, 0x3ff42064, 0x00400060, 0x00000000, // ICON_REPEAT_FILL + 0x00000000, 0x30001000, 0x32107c0e, 0x00801120, 0x11200040, 0x7c0e3210, 0x10003000, 0x00000000, // ICON_SHUFFLE_FILL + 0x00000000, 0x30043ffc, 0x24042804, 0x21042204, 0x20442084, 0x20142024, 0x3ffc200c, 0x00000000, // ICON_EMPTYBOX_SMALL + 0x00000000, 0x20043ffc, 0x20042004, 0x20042004, 0x20042004, 0x20042004, 0x3ffc2004, 0x00000000, // ICON_BOX + 0x00000000, 0x23c43ffc, 0x23c423c4, 0x200423c4, 0x20042004, 0x20042004, 0x3ffc2004, 0x00000000, // ICON_BOX_TOP + 0x00000000, 0x3e043ffc, 0x3e043e04, 0x20043e04, 0x20042004, 0x20042004, 0x3ffc2004, 0x00000000, // ICON_BOX_TOP_RIGHT + 0x00000000, 0x20043ffc, 0x20042004, 0x3e043e04, 0x3e043e04, 0x20042004, 0x3ffc2004, 0x00000000, // ICON_BOX_RIGHT + 0x00000000, 0x20043ffc, 0x20042004, 0x20042004, 0x3e042004, 0x3e043e04, 0x3ffc3e04, 0x00000000, // ICON_BOX_BOTTOM_RIGHT + 0x00000000, 0x20043ffc, 0x20042004, 0x20042004, 0x23c42004, 0x23c423c4, 0x3ffc23c4, 0x00000000, // ICON_BOX_BOTTOM + 0x00000000, 0x20043ffc, 0x20042004, 0x20042004, 0x207c2004, 0x207c207c, 0x3ffc207c, 0x00000000, // ICON_BOX_BOTTOM_LEFT + 0x00000000, 0x20043ffc, 0x20042004, 0x207c207c, 0x207c207c, 0x20042004, 0x3ffc2004, 0x00000000, // ICON_BOX_LEFT + 0x00000000, 0x207c3ffc, 0x207c207c, 0x2004207c, 0x20042004, 0x20042004, 0x3ffc2004, 0x00000000, // ICON_BOX_TOP_LEFT + 0x00000000, 0x20043ffc, 0x20042004, 0x23c423c4, 0x23c423c4, 0x20042004, 0x3ffc2004, 0x00000000, // ICON_BOX_CENTER + 0x7ffe0000, 0x40024002, 0x47e24182, 0x4ff247e2, 0x47e24ff2, 0x418247e2, 0x40024002, 0x00007ffe, // ICON_BOX_CIRCLE_MASK + 0x7fff0000, 0x40014001, 0x40014001, 0x49555ddd, 0x4945495d, 0x400149c5, 0x40014001, 0x00007fff, // ICON_POT + 0x7ffe0000, 0x53327332, 0x44ce4cce, 0x41324332, 0x404e40ce, 0x48125432, 0x4006540e, 0x00007ffe, // ICON_ALPHA_MULTIPLY + 0x7ffe0000, 0x53327332, 0x44ce4cce, 0x41324332, 0x5c4e40ce, 0x44124432, 0x40065c0e, 0x00007ffe, // ICON_ALPHA_CLEAR + 0x7ffe0000, 0x42fe417e, 0x42fe417e, 0x42fe417e, 0x42fe417e, 0x42fe417e, 0x42fe417e, 0x00007ffe, // ICON_DITHERING + 0x07fe0000, 0x1ffa0002, 0x7fea000a, 0x402a402a, 0x5b2a512a, 0x5128552a, 0x40205128, 0x00007fe0, // ICON_MIPMAPS + 0x00000000, 0x1ff80000, 0x12481248, 0x12481ff8, 0x1ff81248, 0x12481248, 0x00001ff8, 0x00000000, // ICON_BOX_GRID + 0x12480000, 0x7ffe1248, 0x12481248, 0x12487ffe, 0x7ffe1248, 0x12481248, 0x12487ffe, 0x00001248, // ICON_GRID + 0x00000000, 0x1c380000, 0x1c3817e8, 0x08100810, 0x08100810, 0x17e81c38, 0x00001c38, 0x00000000, // ICON_BOX_CORNERS_SMALL + 0x700e0000, 0x700e5ffa, 0x20042004, 0x20042004, 0x20042004, 0x20042004, 0x5ffa700e, 0x0000700e, // ICON_BOX_CORNERS_BIG + 0x3f7e0000, 0x21422142, 0x21422142, 0x00003f7e, 0x21423f7e, 0x21422142, 0x3f7e2142, 0x00000000, // ICON_FOUR_BOXES + 0x00000000, 0x3bb80000, 0x3bb83bb8, 0x3bb80000, 0x3bb83bb8, 0x3bb80000, 0x3bb83bb8, 0x00000000, // ICON_GRID_FILL + 0x7ffe0000, 0x7ffe7ffe, 0x77fe7000, 0x77fe77fe, 0x777e7700, 0x777e777e, 0x777e777e, 0x0000777e, // ICON_BOX_MULTISIZE + 0x781e0000, 0x40024002, 0x00004002, 0x01800000, 0x00000180, 0x40020000, 0x40024002, 0x0000781e, // ICON_ZOOM_SMALL + 0x781e0000, 0x40024002, 0x00004002, 0x03c003c0, 0x03c003c0, 0x40020000, 0x40024002, 0x0000781e, // ICON_ZOOM_MEDIUM + 0x781e0000, 0x40024002, 0x07e04002, 0x07e007e0, 0x07e007e0, 0x400207e0, 0x40024002, 0x0000781e, // ICON_ZOOM_BIG + 0x781e0000, 0x5ffa4002, 0x1ff85ffa, 0x1ff81ff8, 0x1ff81ff8, 0x5ffa1ff8, 0x40025ffa, 0x0000781e, // ICON_ZOOM_ALL + 0x00000000, 0x2004381c, 0x00002004, 0x00000000, 0x00000000, 0x20040000, 0x381c2004, 0x00000000, // ICON_ZOOM_CENTER + 0x00000000, 0x1db80000, 0x10081008, 0x10080000, 0x00001008, 0x10081008, 0x00001db8, 0x00000000, // ICON_BOX_DOTS_SMALL + 0x35560000, 0x00002002, 0x00002002, 0x00002002, 0x00002002, 0x00002002, 0x35562002, 0x00000000, // ICON_BOX_DOTS_BIG + 0x7ffe0000, 0x40024002, 0x48124ff2, 0x49924812, 0x48124992, 0x4ff24812, 0x40024002, 0x00007ffe, // ICON_BOX_CONCENTRIC + 0x00000000, 0x10841ffc, 0x10841084, 0x1ffc1084, 0x10841084, 0x10841084, 0x00001ffc, 0x00000000, // ICON_BOX_GRID_BIG + 0x00000000, 0x00000000, 0x10000000, 0x04000800, 0x01040200, 0x00500088, 0x00000020, 0x00000000, // ICON_OK_TICK + 0x00000000, 0x10080000, 0x04200810, 0x01800240, 0x02400180, 0x08100420, 0x00001008, 0x00000000, // ICON_CROSS + 0x00000000, 0x02000000, 0x00800100, 0x00200040, 0x00200010, 0x00800040, 0x02000100, 0x00000000, // ICON_ARROW_LEFT + 0x00000000, 0x00400000, 0x01000080, 0x04000200, 0x04000800, 0x01000200, 0x00400080, 0x00000000, // ICON_ARROW_RIGHT + 0x00000000, 0x00000000, 0x00000000, 0x08081004, 0x02200410, 0x00800140, 0x00000000, 0x00000000, // ICON_ARROW_DOWN + 0x00000000, 0x00000000, 0x01400080, 0x04100220, 0x10040808, 0x00000000, 0x00000000, 0x00000000, // ICON_ARROW_UP + 0x00000000, 0x02000000, 0x03800300, 0x03e003c0, 0x03e003f0, 0x038003c0, 0x02000300, 0x00000000, // ICON_ARROW_LEFT_FILL + 0x00000000, 0x00400000, 0x01c000c0, 0x07c003c0, 0x07c00fc0, 0x01c003c0, 0x004000c0, 0x00000000, // ICON_ARROW_RIGHT_FILL + 0x00000000, 0x00000000, 0x00000000, 0x0ff81ffc, 0x03e007f0, 0x008001c0, 0x00000000, 0x00000000, // ICON_ARROW_DOWN_FILL + 0x00000000, 0x00000000, 0x01c00080, 0x07f003e0, 0x1ffc0ff8, 0x00000000, 0x00000000, 0x00000000, // ICON_ARROW_UP_FILL + 0x00000000, 0x18a008c0, 0x32881290, 0x24822686, 0x26862482, 0x12903288, 0x08c018a0, 0x00000000, // ICON_AUDIO + 0x00000000, 0x04800780, 0x004000c0, 0x662000f0, 0x08103c30, 0x130a0e18, 0x0000318e, 0x00000000, // ICON_FX + 0x00000000, 0x00800000, 0x08880888, 0x2aaa0a8a, 0x0a8a2aaa, 0x08880888, 0x00000080, 0x00000000, // ICON_WAVE + 0x00000000, 0x00600000, 0x01080090, 0x02040108, 0x42044204, 0x24022402, 0x00001800, 0x00000000, // ICON_WAVE_SINUS + 0x00000000, 0x07f80000, 0x04080408, 0x04080408, 0x04080408, 0x7c0e0408, 0x00000000, 0x00000000, // ICON_WAVE_SQUARE + 0x00000000, 0x00000000, 0x00a00040, 0x22084110, 0x08021404, 0x00000000, 0x00000000, 0x00000000, // ICON_WAVE_TRIANGULAR + 0x00000000, 0x00000000, 0x04200000, 0x01800240, 0x02400180, 0x00000420, 0x00000000, 0x00000000, // ICON_CROSS_SMALL + 0x00000000, 0x18380000, 0x12281428, 0x10a81128, 0x112810a8, 0x14281228, 0x00001838, 0x00000000, // ICON_PLAYER_PREVIOUS + 0x00000000, 0x18000000, 0x11801600, 0x10181060, 0x10601018, 0x16001180, 0x00001800, 0x00000000, // ICON_PLAYER_PLAY_BACK + 0x00000000, 0x00180000, 0x01880068, 0x18080608, 0x06081808, 0x00680188, 0x00000018, 0x00000000, // ICON_PLAYER_PLAY + 0x00000000, 0x1e780000, 0x12481248, 0x12481248, 0x12481248, 0x12481248, 0x00001e78, 0x00000000, // ICON_PLAYER_PAUSE + 0x00000000, 0x1ff80000, 0x10081008, 0x10081008, 0x10081008, 0x10081008, 0x00001ff8, 0x00000000, // ICON_PLAYER_STOP + 0x00000000, 0x1c180000, 0x14481428, 0x15081488, 0x14881508, 0x14281448, 0x00001c18, 0x00000000, // ICON_PLAYER_NEXT + 0x00000000, 0x03c00000, 0x08100420, 0x10081008, 0x10081008, 0x04200810, 0x000003c0, 0x00000000, // ICON_PLAYER_RECORD + 0x00000000, 0x0c3007e0, 0x13c81818, 0x14281668, 0x14281428, 0x1c381c38, 0x08102244, 0x00000000, // ICON_MAGNET + 0x07c00000, 0x08200820, 0x3ff80820, 0x23882008, 0x21082388, 0x20082108, 0x1ff02008, 0x00000000, // ICON_LOCK_CLOSE + 0x07c00000, 0x08000800, 0x3ff80800, 0x23882008, 0x21082388, 0x20082108, 0x1ff02008, 0x00000000, // ICON_LOCK_OPEN + 0x01c00000, 0x0c180770, 0x3086188c, 0x60832082, 0x60034781, 0x30062002, 0x0c18180c, 0x01c00770, // ICON_CLOCK + 0x0a200000, 0x1b201b20, 0x04200e20, 0x04200420, 0x04700420, 0x0e700e70, 0x0e700e70, 0x04200e70, // ICON_TOOLS + 0x01800000, 0x3bdc318c, 0x0ff01ff8, 0x7c3e1e78, 0x1e787c3e, 0x1ff80ff0, 0x318c3bdc, 0x00000180, // ICON_GEAR + 0x01800000, 0x3ffc318c, 0x1c381ff8, 0x781e1818, 0x1818781e, 0x1ff81c38, 0x318c3ffc, 0x00000180, // ICON_GEAR_BIG + 0x00000000, 0x08080ff8, 0x08081ffc, 0x0aa80aa8, 0x0aa80aa8, 0x0aa80aa8, 0x08080aa8, 0x00000ff8, // ICON_BIN + 0x00000000, 0x00000000, 0x20043ffc, 0x08043f84, 0x04040f84, 0x04040784, 0x000007fc, 0x00000000, // ICON_HAND_POINTER + 0x00000000, 0x24400400, 0x00001480, 0x6efe0e00, 0x00000e00, 0x24401480, 0x00000400, 0x00000000, // ICON_LASER + 0x00000000, 0x03c00000, 0x08300460, 0x11181118, 0x11181118, 0x04600830, 0x000003c0, 0x00000000, // ICON_COIN + 0x00000000, 0x10880080, 0x06c00810, 0x366c07e0, 0x07e00240, 0x00001768, 0x04200240, 0x00000000, // ICON_EXPLOSION + 0x00000000, 0x3d280000, 0x2528252c, 0x3d282528, 0x05280528, 0x05e80528, 0x00000000, 0x00000000, // ICON_1UP + 0x01800000, 0x03c003c0, 0x018003c0, 0x0ff007e0, 0x0bd00bd0, 0x0a500bd0, 0x02400240, 0x02400240, // ICON_PLAYER + 0x01800000, 0x03c003c0, 0x118013c0, 0x03c81ff8, 0x07c003c8, 0x04400440, 0x0c080478, 0x00000000, // ICON_PLAYER_JUMP + 0x3ff80000, 0x30183ff8, 0x30183018, 0x3ff83ff8, 0x03000300, 0x03c003c0, 0x03e00300, 0x000003e0, // ICON_KEY + 0x3ff80000, 0x3ff83ff8, 0x33983ff8, 0x3ff83398, 0x3ff83ff8, 0x00000540, 0x0fe00aa0, 0x00000fe0, // ICON_DEMON + 0x00000000, 0x0ff00000, 0x20041008, 0x25442004, 0x10082004, 0x06000bf0, 0x00000300, 0x00000000, // ICON_TEXT_POPUP + 0x00000000, 0x11440000, 0x07f00be8, 0x1c1c0e38, 0x1c1c0c18, 0x07f00e38, 0x11440be8, 0x00000000, // ICON_GEAR_EX + 0x00000000, 0x20080000, 0x0c601010, 0x07c00fe0, 0x07c007c0, 0x0c600fe0, 0x20081010, 0x00000000, // ICON_CRACK + 0x00000000, 0x20080000, 0x0c601010, 0x04400fe0, 0x04405554, 0x0c600fe0, 0x20081010, 0x00000000, // ICON_CRACK_POINTS + 0x00000000, 0x00800080, 0x01c001c0, 0x1ffc3ffe, 0x03e007f0, 0x07f003e0, 0x0c180770, 0x00000808, // ICON_STAR + 0x0ff00000, 0x08180810, 0x08100818, 0x0a100810, 0x08180810, 0x08100818, 0x08100810, 0x00001ff8, // ICON_DOOR + 0x0ff00000, 0x08100810, 0x08100810, 0x10100010, 0x4f902010, 0x10102010, 0x08100010, 0x00000ff0, // ICON_EXIT + 0x00040000, 0x001f000e, 0x0ef40004, 0x12f41284, 0x0ef41214, 0x10040004, 0x7ffc3004, 0x10003000, // ICON_MODE_2D + 0x78040000, 0x501f600e, 0x0ef44004, 0x12f41284, 0x0ef41284, 0x10140004, 0x7ffc300c, 0x10003000, // ICON_MODE_3D + 0x7fe00000, 0x50286030, 0x47fe4804, 0x44224402, 0x44224422, 0x241275e2, 0x0c06140a, 0x000007fe, // ICON_CUBE + 0x7fe00000, 0x5ff87ff0, 0x47fe4ffc, 0x44224402, 0x44224422, 0x241275e2, 0x0c06140a, 0x000007fe, // ICON_CUBE_FACE_TOP + 0x7fe00000, 0x50386030, 0x47c2483c, 0x443e443e, 0x443e443e, 0x241e75fe, 0x0c06140e, 0x000007fe, // ICON_CUBE_FACE_LEFT + 0x7fe00000, 0x50286030, 0x47fe4804, 0x47fe47fe, 0x47fe47fe, 0x27fe77fe, 0x0ffe17fe, 0x000007fe, // ICON_CUBE_FACE_FRONT + 0x7fe00000, 0x50286030, 0x47fe4804, 0x44224402, 0x44224422, 0x3bf27be2, 0x0bfe1bfa, 0x000007fe, // ICON_CUBE_FACE_BOTTOM + 0x7fe00000, 0x70286030, 0x7ffe7804, 0x7c227c02, 0x7c227c22, 0x3c127de2, 0x0c061c0a, 0x000007fe, // ICON_CUBE_FACE_RIGHT + 0x7fe00000, 0x6fe85ff0, 0x781e77e4, 0x7be27be2, 0x7be27be2, 0x24127be2, 0x0c06140a, 0x000007fe, // ICON_CUBE_FACE_BACK + 0x00000000, 0x2a0233fe, 0x22022602, 0x22022202, 0x2a022602, 0x00a033fe, 0x02080110, 0x00000000, // ICON_CAMERA + 0x00000000, 0x200c3ffc, 0x000c000c, 0x3ffc000c, 0x30003000, 0x30003000, 0x3ffc3004, 0x00000000, // ICON_SPECIAL + 0x00000000, 0x0022003e, 0x012201e2, 0x0100013e, 0x01000100, 0x79000100, 0x4f004900, 0x00007800, // ICON_LINK_NET + 0x00000000, 0x44007c00, 0x45004600, 0x00627cbe, 0x00620022, 0x45007cbe, 0x44004600, 0x00007c00, // ICON_LINK_BOXES + 0x00000000, 0x0044007c, 0x0010007c, 0x3f100010, 0x3f1021f0, 0x3f100010, 0x3f0021f0, 0x00000000, // ICON_LINK_MULTI + 0x00000000, 0x0044007c, 0x00440044, 0x0010007c, 0x00100010, 0x44107c10, 0x440047f0, 0x00007c00, // ICON_LINK + 0x00000000, 0x0044007c, 0x00440044, 0x0000007c, 0x00000010, 0x44007c10, 0x44004550, 0x00007c00, // ICON_LINK_BROKE + 0x02a00000, 0x22a43ffc, 0x20042004, 0x20042ff4, 0x20042ff4, 0x20042ff4, 0x20042004, 0x00003ffc, // ICON_TEXT_NOTES + 0x3ffc0000, 0x20042004, 0x245e27c4, 0x27c42444, 0x2004201e, 0x201e2004, 0x20042004, 0x00003ffc, // ICON_NOTEBOOK + 0x00000000, 0x07e00000, 0x04200420, 0x24243ffc, 0x24242424, 0x24242424, 0x3ffc2424, 0x00000000, // ICON_SUITCASE + 0x00000000, 0x0fe00000, 0x08200820, 0x40047ffc, 0x7ffc5554, 0x40045554, 0x7ffc4004, 0x00000000, // ICON_SUITCASE_ZIP + 0x00000000, 0x20043ffc, 0x3ffc2004, 0x13c81008, 0x100813c8, 0x10081008, 0x1ff81008, 0x00000000, // ICON_MAILBOX + 0x00000000, 0x40027ffe, 0x5ffa5ffa, 0x5ffa5ffa, 0x40025ffa, 0x03c07ffe, 0x1ff81ff8, 0x00000000, // ICON_MONITOR + 0x0ff00000, 0x6bfe7ffe, 0x7ffe7ffe, 0x68167ffe, 0x08106816, 0x08100810, 0x0ff00810, 0x00000000, // ICON_PRINTER + 0x3ff80000, 0xfffe2008, 0x870a8002, 0x904a888a, 0x904a904a, 0x870a888a, 0xfffe8002, 0x00000000, // ICON_PHOTO_CAMERA + 0x0fc00000, 0xfcfe0cd8, 0x8002fffe, 0x84428382, 0x84428442, 0x80028382, 0xfffe8002, 0x00000000, // ICON_PHOTO_CAMERA_FLASH + 0x00000000, 0x02400180, 0x08100420, 0x20041008, 0x23c42004, 0x22442244, 0x3ffc2244, 0x00000000, // ICON_HOUSE + 0x00000000, 0x1c700000, 0x3ff83ef8, 0x3ff83ff8, 0x0fe01ff0, 0x038007c0, 0x00000100, 0x00000000, // ICON_HEART + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x80000000, 0xe000c000, // ICON_CORNER + 0x00000000, 0x14001c00, 0x15c01400, 0x15401540, 0x155c1540, 0x15541554, 0x1ddc1554, 0x00000000, // ICON_VERTICAL_BARS + 0x00000000, 0x03000300, 0x1b001b00, 0x1b601b60, 0x1b6c1b60, 0x1b6c1b6c, 0x1b6c1b6c, 0x00000000, // ICON_VERTICAL_BARS_FILL + 0x00000000, 0x00000000, 0x403e7ffe, 0x7ffe403e, 0x7ffe0000, 0x43fe43fe, 0x00007ffe, 0x00000000, // ICON_LIFE_BARS + 0x7ffc0000, 0x43844004, 0x43844284, 0x43844004, 0x42844284, 0x42844284, 0x40044384, 0x00007ffc, // ICON_INFO + 0x40008000, 0x10002000, 0x04000800, 0x01000200, 0x00400080, 0x00100020, 0x00040008, 0x00010002, // ICON_CROSSLINE + 0x00000000, 0x1ff01ff0, 0x18301830, 0x1f001830, 0x03001f00, 0x00000300, 0x03000300, 0x00000000, // ICON_HELP + 0x3ff00000, 0x2abc3550, 0x2aac3554, 0x2aac3554, 0x2aac3554, 0x2aac3554, 0x2aac3554, 0x00003ffc, // ICON_FILETYPE_ALPHA + 0x3ff00000, 0x201c2010, 0x22442184, 0x28142424, 0x29942814, 0x2ff42994, 0x20042004, 0x00003ffc, // ICON_FILETYPE_HOME + 0x07fe0000, 0x04020402, 0x7fe20402, 0x44224422, 0x44224422, 0x402047fe, 0x40204020, 0x00007fe0, // ICON_LAYERS_VISIBLE + 0x07fe0000, 0x04020402, 0x7c020402, 0x44024402, 0x44024402, 0x402047fe, 0x40204020, 0x00007fe0, // ICON_LAYERS + 0x00000000, 0x40027ffe, 0x7ffe4002, 0x40024002, 0x40024002, 0x40024002, 0x7ffe4002, 0x00000000, // ICON_WINDOW + 0x09100000, 0x09f00910, 0x09100910, 0x00000910, 0x24a2779e, 0x27a224a2, 0x709e20a2, 0x00000000, // ICON_HIDPI + 0x3ff00000, 0x201c2010, 0x2a842e84, 0x2e842a84, 0x2ba42004, 0x2aa42aa4, 0x20042ba4, 0x00003ffc, // ICON_FILETYPE_BINARY + 0x00000000, 0x00000000, 0x00120012, 0x4a5e4bd2, 0x485233d2, 0x00004bd2, 0x00000000, 0x00000000, // ICON_HEX + 0x01800000, 0x381c0660, 0x23c42004, 0x23c42044, 0x13c82204, 0x08101008, 0x02400420, 0x00000180, // ICON_SHIELD + 0x007e0000, 0x20023fc2, 0x40227fe2, 0x400a403a, 0x400a400a, 0x400a400a, 0x4008400e, 0x00007ff8, // ICON_FILE_NEW + 0x00000000, 0x0042007e, 0x40027fc2, 0x44024002, 0x5f024402, 0x44024402, 0x7ffe4002, 0x00000000, // ICON_FOLDER_ADD + 0x44220000, 0x12482244, 0xf3cf0000, 0x14280420, 0x48122424, 0x08100810, 0x1ff81008, 0x03c00420, // ICON_ALARM + 0x0aa00000, 0x1ff80aa0, 0x1068700e, 0x1008706e, 0x1008700e, 0x1008700e, 0x0aa01ff8, 0x00000aa0, // ICON_CPU + 0x07e00000, 0x04201db8, 0x04a01c38, 0x04a01d38, 0x04a01d38, 0x04a01d38, 0x04201d38, 0x000007e0, // ICON_ROM + 0x00000000, 0x03c00000, 0x3c382ff0, 0x3c04380c, 0x01800000, 0x03c003c0, 0x00000180, 0x00000000, // ICON_STEP_OVER + 0x01800000, 0x01800180, 0x01800180, 0x03c007e0, 0x00000180, 0x01800000, 0x03c003c0, 0x00000180, // ICON_STEP_INTO + 0x01800000, 0x07e003c0, 0x01800180, 0x01800180, 0x00000180, 0x01800000, 0x03c003c0, 0x00000180, // ICON_STEP_OUT + 0x00000000, 0x0ff003c0, 0x181c1c34, 0x303c301c, 0x30003000, 0x1c301800, 0x03c00ff0, 0x00000000, // ICON_RESTART + 0x00000000, 0x00000000, 0x07e003c0, 0x0ff00ff0, 0x0ff00ff0, 0x03c007e0, 0x00000000, 0x00000000, // ICON_BREAKPOINT_ON + 0x00000000, 0x00000000, 0x042003c0, 0x08100810, 0x08100810, 0x03c00420, 0x00000000, 0x00000000, // ICON_BREAKPOINT_OFF + 0x00000000, 0x00000000, 0x1ff81ff8, 0x1ff80000, 0x00001ff8, 0x1ff81ff8, 0x00000000, 0x00000000, // ICON_BURGER_MENU + 0x00000000, 0x00000000, 0x00880070, 0x0c880088, 0x1e8810f8, 0x3e881288, 0x00000000, 0x00000000, // ICON_CASE_SENSITIVE + 0x00000000, 0x02000000, 0x07000a80, 0x07001fc0, 0x02000a80, 0x00300030, 0x00000000, 0x00000000, // ICON_REG_EXP + 0x00000000, 0x0042007e, 0x40027fc2, 0x40024002, 0x40024002, 0x40024002, 0x7ffe4002, 0x00000000, // ICON_FOLDER + 0x3ff00000, 0x201c2010, 0x20042004, 0x20042004, 0x20042004, 0x20042004, 0x20042004, 0x00003ffc, // ICON_FILE + 0x1ff00000, 0x20082008, 0x17d02fe8, 0x05400ba0, 0x09200540, 0x23881010, 0x2fe827c8, 0x00001ff0, // ICON_SAND_TIMER + 0x01800000, 0x02400240, 0x05a00420, 0x09900990, 0x11881188, 0x21842004, 0x40024182, 0x00003ffc, // ICON_WARNING + 0x7ffe0000, 0x4ff24002, 0x4c324ff2, 0x4f824c02, 0x41824f82, 0x41824002, 0x40024182, 0x00007ffe, // ICON_HELP_BOX + 0x7ffe0000, 0x41824002, 0x40024182, 0x41824182, 0x41824182, 0x41824182, 0x40024182, 0x00007ffe, // ICON_INFO_BOX + 0x01800000, 0x04200240, 0x10080810, 0x7bde2004, 0x0a500a50, 0x08500bd0, 0x08100850, 0x00000ff0, // ICON_PRIORITY + 0x01800000, 0x18180660, 0x80016006, 0x98196006, 0x99996666, 0x19986666, 0x01800660, 0x00000000, // ICON_LAYERS_ISO + 0x07fe0000, 0x1c020402, 0x74021402, 0x54025402, 0x54025402, 0x500857fe, 0x40205ff8, 0x00007fe0, // ICON_LAYERS2 + 0x0ffe0000, 0x3ffa0802, 0x7fea200a, 0x402a402a, 0x422a422a, 0x422e422a, 0x40384e28, 0x00007fe0, // ICON_MLAYERS + 0x0ffe0000, 0x3ffa0802, 0x7fea200a, 0x402a402a, 0x5b2a512a, 0x512e552a, 0x40385128, 0x00007fe0, // ICON_MAPS + 0x04200000, 0x1cf00c60, 0x11f019f0, 0x0f3807b8, 0x1e3c0f3c, 0x1c1c1e1c, 0x1e3c1c1c, 0x00000f70, // ICON_HOT + 0x00000000, 0x20803f00, 0x2a202e40, 0x20082e10, 0x08021004, 0x02040402, 0x00900108, 0x00000060, // ICON_LABEL + 0x00000000, 0x042007e0, 0x47e27c3e, 0x4ffa4002, 0x47fa4002, 0x4ffa4002, 0x7ffe4002, 0x00000000, // ICON_NAME_ID + 0x7fe00000, 0x402e4020, 0x43ce5e0a, 0x40504078, 0x438e4078, 0x402e5e0a, 0x7fe04020, 0x00000000, // ICON_SLICING + 0x00000000, 0x40027ffe, 0x47c24002, 0x55425d42, 0x55725542, 0x50125552, 0x10105016, 0x00001ff0, // ICON_MANUAL_CONTROL + 0x7ffe0000, 0x43c24002, 0x48124422, 0x500a500a, 0x500a500a, 0x44224812, 0x400243c2, 0x00007ffe, // ICON_COLLISION + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_234 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_235 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_236 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_237 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_238 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_239 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_240 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_241 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_242 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_243 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_244 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_245 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_246 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_247 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_248 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_249 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_250 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_251 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_252 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_253 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_254 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // ICON_255 +}; + +// NOTE: A pointer to current icons array should be defined +static unsigned int *guiIconsPtr = guiIcons; + +#endif // !RAYGUI_NO_ICONS && !RAYGUI_CUSTOM_ICONS + +#ifndef RAYGUI_ICON_SIZE + #define RAYGUI_ICON_SIZE 0 +#endif + +// WARNING: Those values define the total size of the style data array, +// if changed, previous saved styles could become incompatible +#define RAYGUI_MAX_CONTROLS 16 // Maximum number of controls +#define RAYGUI_MAX_PROPS_BASE 16 // Maximum number of base properties +#define RAYGUI_MAX_PROPS_EXTENDED 8 // Maximum number of extended properties + +//---------------------------------------------------------------------------------- +// Module Types and Structures Definition +//---------------------------------------------------------------------------------- +// Gui control property style color element +typedef enum { BORDER = 0, BASE, TEXT, OTHER } GuiPropertyElement; + +//---------------------------------------------------------------------------------- +// Global Variables Definition +//---------------------------------------------------------------------------------- +static GuiState guiState = STATE_NORMAL; // Gui global state, if !STATE_NORMAL, forces defined state + +static Font guiFont = { 0 }; // Gui current font (WARNING: highly coupled to raylib) +static bool guiLocked = false; // Gui lock state (no inputs processed) +static float guiAlpha = 1.0f; // Gui controls transparency + +static unsigned int guiIconScale = 1; // Gui icon default scale (if icons enabled) + +static bool guiTooltip = false; // Tooltip enabled/disabled +static const char *guiTooltipPtr = NULL; // Tooltip string pointer (string provided by user) + +static bool guiControlExclusiveMode = false; // Gui control exclusive mode (no inputs processed except current control) +static Rectangle guiControlExclusiveRec = { 0 }; // Gui control exclusive bounds rectangle, used as an unique identifier + +static int textBoxCursorIndex = 0; // Cursor index, shared by all GuiTextBox*() +//static int blinkCursorFrameCounter = 0; // Frame counter for cursor blinking +static int autoCursorCounter = 0; // Frame counter for automatic repeated cursor movement on key-down (cooldown and delay) + +//---------------------------------------------------------------------------------- +// Style data array for all gui style properties (allocated on data segment by default) +// +// NOTE 1: First set of BASE properties are generic to all controls but could be individually +// overwritten per control, first set of EXTENDED properties are generic to all controls and +// can not be overwritten individually but custom EXTENDED properties can be used by control +// +// NOTE 2: A new style set could be loaded over this array using GuiLoadStyle(), +// but default gui style could always be recovered with GuiLoadStyleDefault() +// +// guiStyle size is by default: 16*(16 + 8) = 384*4 = 1536 bytes = 1.5 KB +//---------------------------------------------------------------------------------- +static unsigned int guiStyle[RAYGUI_MAX_CONTROLS*(RAYGUI_MAX_PROPS_BASE + RAYGUI_MAX_PROPS_EXTENDED)] = { 0 }; + +static bool guiStyleLoaded = false; // Style loaded flag for lazy style initialization + +//---------------------------------------------------------------------------------- +// Standalone Mode Functions Declaration +// +// NOTE: raygui depend on some raylib input and drawing functions +// To use raygui as standalone library, below functions must be defined by the user +//---------------------------------------------------------------------------------- +#if defined(RAYGUI_STANDALONE) + +#define KEY_RIGHT 262 +#define KEY_LEFT 263 +#define KEY_DOWN 264 +#define KEY_UP 265 +#define KEY_BACKSPACE 259 +#define KEY_ENTER 257 + +#define MOUSE_LEFT_BUTTON 0 + +// Input required functions +//------------------------------------------------------------------------------- +static Vector2 GetMousePosition(void); +static float GetMouseWheelMove(void); +static bool IsMouseButtonDown(int button); +static bool IsMouseButtonPressed(int button); +static bool IsMouseButtonReleased(int button); + +static bool IsKeyDown(int key); +static bool IsKeyPressed(int key); +static int GetCharPressed(void); // -- GuiTextBox(), GuiValueBox() +//------------------------------------------------------------------------------- + +// Drawing required functions +//------------------------------------------------------------------------------- +static void DrawRectangle(int x, int y, int width, int height, Color color); // -- GuiDrawRectangle() +static void DrawRectangleGradientEx(Rectangle rec, Color col1, Color col2, Color col3, Color col4); // -- GuiColorPicker() +//------------------------------------------------------------------------------- + +// Text required functions +//------------------------------------------------------------------------------- +static Font GetFontDefault(void); // -- GuiLoadStyleDefault() +static Font LoadFontEx(const char *fileName, int fontSize, int *codepoints, int codepointCount); // -- GuiLoadStyle(), load font + +static Texture2D LoadTextureFromImage(Image image); // -- GuiLoadStyle(), required to load texture from embedded font atlas image +static void SetShapesTexture(Texture2D tex, Rectangle rec); // -- GuiLoadStyle(), required to set shapes rec to font white rec (optimization) + +static char *LoadFileText(const char *fileName); // -- GuiLoadStyle(), required to load charset data +static void UnloadFileText(char *text); // -- GuiLoadStyle(), required to unload charset data + +static const char *GetDirectoryPath(const char *filePath); // -- GuiLoadStyle(), required to find charset/font file from text .rgs + +static int *LoadCodepoints(const char *text, int *count); // -- GuiLoadStyle(), required to load required font codepoints list +static void UnloadCodepoints(int *codepoints); // -- GuiLoadStyle(), required to unload codepoints list + +static unsigned char *DecompressData(const unsigned char *compData, int compDataSize, int *dataSize); // -- GuiLoadStyle() +//------------------------------------------------------------------------------- + +// raylib functions already implemented in raygui +//------------------------------------------------------------------------------- +static Color GetColor(int hexValue); // Returns a Color struct from hexadecimal value +static int ColorToInt(Color color); // Returns hexadecimal value for a Color +static bool CheckCollisionPointRec(Vector2 point, Rectangle rec); // Check if point is inside rectangle +static const char *TextFormat(const char *text, ...); // Formatting of text with variables to 'embed' +static const char **TextSplit(const char *text, char delimiter, int *count); // Split text into multiple strings +static int TextToInteger(const char *text); // Get integer value from text +static float TextToFloat(const char *text); // Get float value from text + +static int GetCodepointNext(const char *text, int *codepointSize); // Get next codepoint in a UTF-8 encoded text +static const char *CodepointToUTF8(int codepoint, int *byteSize); // Encode codepoint into UTF-8 text (char array size returned as parameter) + +static void DrawRectangleGradientV(int posX, int posY, int width, int height, Color color1, Color color2); // Draw rectangle vertical gradient +//------------------------------------------------------------------------------- + +#endif // RAYGUI_STANDALONE + +//---------------------------------------------------------------------------------- +// Module Internal Functions Declaration +//---------------------------------------------------------------------------------- +static void GuiLoadStyleFromMemory(const unsigned char *fileData, int dataSize); // Load style from memory (binary only) + +static Rectangle GetTextBounds(int control, Rectangle bounds); // Get text bounds considering control bounds +static const char *GetTextIcon(const char *text, int *iconId); // Get text icon if provided and move text cursor + +static void GuiDrawText(const char *text, Rectangle textBounds, int alignment, Color tint); // Gui draw text using default font +static void GuiDrawRectangle(Rectangle rec, int borderWidth, Color borderColor, Color color); // Gui draw rectangle using default raygui style + +static const char **GuiTextSplit(const char *text, char delimiter, int *count, int *textRow); // Split controls text into multiple strings +static Vector3 ConvertHSVtoRGB(Vector3 hsv); // Convert color data from HSV to RGB +static Vector3 ConvertRGBtoHSV(Vector3 rgb); // Convert color data from RGB to HSV + +static int GuiScrollBar(Rectangle bounds, int value, int minValue, int maxValue); // Scroll bar control, used by GuiScrollPanel() +static void GuiTooltip(Rectangle controlRec); // Draw tooltip using control rec position + +static Color GuiFade(Color color, float alpha); // Fade color by an alpha factor + +//---------------------------------------------------------------------------------- +// Gui Setup Functions Definition +//---------------------------------------------------------------------------------- +// Enable gui global state +// NOTE: We check for STATE_DISABLED to avoid messing custom global state setups +void GuiEnable(void) { if (guiState == STATE_DISABLED) guiState = STATE_NORMAL; } + +// Disable gui global state +// NOTE: We check for STATE_NORMAL to avoid messing custom global state setups +void GuiDisable(void) { if (guiState == STATE_NORMAL) guiState = STATE_DISABLED; } + +// Lock gui global state +void GuiLock(void) { guiLocked = true; } + +// Unlock gui global state +void GuiUnlock(void) { guiLocked = false; } + +// Check if gui is locked (global state) +bool GuiIsLocked(void) { return guiLocked; } + +// Set gui controls alpha global state +void GuiSetAlpha(float alpha) +{ + if (alpha < 0.0f) alpha = 0.0f; + else if (alpha > 1.0f) alpha = 1.0f; + + guiAlpha = alpha; +} + +// Set gui state (global state) +void GuiSetState(int state) { guiState = (GuiState)state; } + +// Get gui state (global state) +int GuiGetState(void) { return guiState; } + +// Set custom gui font +// NOTE: Font loading/unloading is external to raygui +void GuiSetFont(Font font) +{ + if (font.texture.id > 0) + { + // NOTE: If we try to setup a font but default style has not been + // lazily loaded before, it will be overwritten, so we need to force + // default style loading first + if (!guiStyleLoaded) GuiLoadStyleDefault(); + + guiFont = font; + } +} + +// Get custom gui font +Font GuiGetFont(void) +{ + return guiFont; +} + +// Set control style property value +void GuiSetStyle(int control, int property, int value) +{ + if (!guiStyleLoaded) GuiLoadStyleDefault(); + guiStyle[control*(RAYGUI_MAX_PROPS_BASE + RAYGUI_MAX_PROPS_EXTENDED) + property] = value; + + // Default properties are propagated to all controls + if ((control == 0) && (property < RAYGUI_MAX_PROPS_BASE)) + { + for (int i = 1; i < RAYGUI_MAX_CONTROLS; i++) guiStyle[i*(RAYGUI_MAX_PROPS_BASE + RAYGUI_MAX_PROPS_EXTENDED) + property] = value; + } +} + +// Get control style property value +int GuiGetStyle(int control, int property) +{ + if (!guiStyleLoaded) GuiLoadStyleDefault(); + return guiStyle[control*(RAYGUI_MAX_PROPS_BASE + RAYGUI_MAX_PROPS_EXTENDED) + property]; +} + +//---------------------------------------------------------------------------------- +// Gui Controls Functions Definition +//---------------------------------------------------------------------------------- + +// Window Box control +int GuiWindowBox(Rectangle bounds, const char *title) +{ + // Window title bar height (including borders) + // NOTE: This define is also used by GuiMessageBox() and GuiTextInputBox() + #if !defined(RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT) + #define RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT 24 + #endif + + #if !defined(RAYGUI_WINDOWBOX_CLOSEBUTTON_HEIGHT) + #define RAYGUI_WINDOWBOX_CLOSEBUTTON_HEIGHT 18 + #endif + + int result = 0; + //GuiState state = guiState; + + int statusBarHeight = RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT; + + Rectangle statusBar = { bounds.x, bounds.y, bounds.width, (float)statusBarHeight }; + if (bounds.height < statusBarHeight*2.0f) bounds.height = statusBarHeight*2.0f; + + const float vPadding = statusBarHeight/2.0f - RAYGUI_WINDOWBOX_CLOSEBUTTON_HEIGHT/2.0f; + Rectangle windowPanel = { bounds.x, bounds.y + (float)statusBarHeight - 1, bounds.width, bounds.height - (float)statusBarHeight + 1 }; + Rectangle closeButtonRec = { statusBar.x + statusBar.width - GuiGetStyle(STATUSBAR, BORDER_WIDTH) - RAYGUI_WINDOWBOX_CLOSEBUTTON_HEIGHT - vPadding, + statusBar.y + vPadding, RAYGUI_WINDOWBOX_CLOSEBUTTON_HEIGHT, RAYGUI_WINDOWBOX_CLOSEBUTTON_HEIGHT }; + + // Update control + //-------------------------------------------------------------------- + // NOTE: Logic is directly managed by button + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + GuiStatusBar(statusBar, title); // Draw window header as status bar + GuiPanel(windowPanel, NULL); // Draw window base + + // Draw window close button + int tempBorderWidth = GuiGetStyle(BUTTON, BORDER_WIDTH); + int tempTextAlignment = GuiGetStyle(BUTTON, TEXT_ALIGNMENT); + GuiSetStyle(BUTTON, BORDER_WIDTH, 1); + GuiSetStyle(BUTTON, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER); +#if defined(RAYGUI_NO_ICONS) + result = GuiButton(closeButtonRec, "x"); +#else + result = GuiButton(closeButtonRec, GuiIconText(ICON_CROSS_SMALL, NULL)); +#endif + GuiSetStyle(BUTTON, BORDER_WIDTH, tempBorderWidth); + GuiSetStyle(BUTTON, TEXT_ALIGNMENT, tempTextAlignment); + //-------------------------------------------------------------------- + + return result; // Window close button clicked: result = 1 +} + +// Group Box control with text name +int GuiGroupBox(Rectangle bounds, const char *text) +{ + #if !defined(RAYGUI_GROUPBOX_LINE_THICK) + #define RAYGUI_GROUPBOX_LINE_THICK 1 + #endif + + int result = 0; + GuiState state = guiState; + + // Draw control + //-------------------------------------------------------------------- + GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y, RAYGUI_GROUPBOX_LINE_THICK, bounds.height }, 0, BLANK, GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? (int)BORDER_COLOR_DISABLED : (int)LINE_COLOR))); + GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y + bounds.height - 1, bounds.width, RAYGUI_GROUPBOX_LINE_THICK }, 0, BLANK, GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? (int)BORDER_COLOR_DISABLED : (int)LINE_COLOR))); + GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x + bounds.width - 1, bounds.y, RAYGUI_GROUPBOX_LINE_THICK, bounds.height }, 0, BLANK, GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? (int)BORDER_COLOR_DISABLED : (int)LINE_COLOR))); + + GuiLine(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y - GuiGetStyle(DEFAULT, TEXT_SIZE)/2, bounds.width, (float)GuiGetStyle(DEFAULT, TEXT_SIZE) }, text); + //-------------------------------------------------------------------- + + return result; +} + +// Line control +int GuiLine(Rectangle bounds, const char *text) +{ + #if !defined(RAYGUI_LINE_MARGIN_TEXT) + #define RAYGUI_LINE_MARGIN_TEXT 12 + #endif + #if !defined(RAYGUI_LINE_TEXT_PADDING) + #define RAYGUI_LINE_TEXT_PADDING 4 + #endif + + int result = 0; + GuiState state = guiState; + + Color color = GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? (int)BORDER_COLOR_DISABLED : (int)LINE_COLOR)); + + // Draw control + //-------------------------------------------------------------------- + if (text == NULL) GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y + bounds.height/2, bounds.width, 1 }, 0, BLANK, color); + else + { + Rectangle textBounds = { 0 }; + textBounds.width = (float)GuiGetTextWidth(text) + 2; + textBounds.height = bounds.height; + textBounds.x = bounds.x + RAYGUI_LINE_MARGIN_TEXT; + textBounds.y = bounds.y; + + // Draw line with embedded text label: "--- text --------------" + GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y + bounds.height/2, RAYGUI_LINE_MARGIN_TEXT - RAYGUI_LINE_TEXT_PADDING, 1 }, 0, BLANK, color); + GuiDrawText(text, textBounds, TEXT_ALIGN_LEFT, color); + GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x + 12 + textBounds.width + 4, bounds.y + bounds.height/2, bounds.width - textBounds.width - RAYGUI_LINE_MARGIN_TEXT - RAYGUI_LINE_TEXT_PADDING, 1 }, 0, BLANK, color); + } + //-------------------------------------------------------------------- + + return result; +} + +// Panel control +int GuiPanel(Rectangle bounds, const char *text) +{ + #if !defined(RAYGUI_PANEL_BORDER_WIDTH) + #define RAYGUI_PANEL_BORDER_WIDTH 1 + #endif + + int result = 0; + GuiState state = guiState; + + // Text will be drawn as a header bar (if provided) + Rectangle statusBar = { bounds.x, bounds.y, bounds.width, (float)RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT }; + if ((text != NULL) && (bounds.height < RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT*2.0f)) bounds.height = RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT*2.0f; + + if (text != NULL) + { + // Move panel bounds after the header bar + bounds.y += (float)RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT - 1; + bounds.height -= (float)RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT - 1; + } + + // Draw control + //-------------------------------------------------------------------- + if (text != NULL) GuiStatusBar(statusBar, text); // Draw panel header as status bar + + GuiDrawRectangle(bounds, RAYGUI_PANEL_BORDER_WIDTH, GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? (int)BORDER_COLOR_DISABLED : (int)LINE_COLOR)), + GetColor(GuiGetStyle(DEFAULT, (state == STATE_DISABLED)? (int)BASE_COLOR_DISABLED : (int)BACKGROUND_COLOR))); + //-------------------------------------------------------------------- + + return result; +} + +// Tab Bar control +// NOTE: Using GuiToggle() for the TABS +int GuiTabBar(Rectangle bounds, const char **text, int count, int *active) +{ + #define RAYGUI_TABBAR_ITEM_WIDTH 160 + + int result = -1; + //GuiState state = guiState; + + Rectangle tabBounds = { bounds.x, bounds.y, RAYGUI_TABBAR_ITEM_WIDTH, bounds.height }; + + if (*active < 0) *active = 0; + else if (*active > count - 1) *active = count - 1; + + int offsetX = 0; // Required in case tabs go out of screen + offsetX = (*active + 2)*RAYGUI_TABBAR_ITEM_WIDTH - GetScreenWidth(); + if (offsetX < 0) offsetX = 0; + + bool toggle = false; // Required for individual toggles + + // Draw control + //-------------------------------------------------------------------- + for (int i = 0; i < count; i++) + { + tabBounds.x = bounds.x + (RAYGUI_TABBAR_ITEM_WIDTH + 4)*i - offsetX; + + if (tabBounds.x < GetScreenWidth()) + { + // Draw tabs as toggle controls + int textAlignment = GuiGetStyle(TOGGLE, TEXT_ALIGNMENT); + int textPadding = GuiGetStyle(TOGGLE, TEXT_PADDING); + GuiSetStyle(TOGGLE, TEXT_ALIGNMENT, TEXT_ALIGN_LEFT); + GuiSetStyle(TOGGLE, TEXT_PADDING, 8); + + if (i == (*active)) + { + toggle = true; + GuiToggle(tabBounds, GuiIconText(12, text[i]), &toggle); + } + else + { + toggle = false; + GuiToggle(tabBounds, GuiIconText(12, text[i]), &toggle); + if (toggle) *active = i; + } + + // Close tab with middle mouse button pressed + if (CheckCollisionPointRec(GetMousePosition(), tabBounds) && IsMouseButtonPressed(MOUSE_MIDDLE_BUTTON)) result = i; + + GuiSetStyle(TOGGLE, TEXT_PADDING, textPadding); + GuiSetStyle(TOGGLE, TEXT_ALIGNMENT, textAlignment); + + // Draw tab close button + // NOTE: Only draw close button for current tab: if (CheckCollisionPointRec(mousePosition, tabBounds)) + int tempBorderWidth = GuiGetStyle(BUTTON, BORDER_WIDTH); + int tempTextAlignment = GuiGetStyle(BUTTON, TEXT_ALIGNMENT); + GuiSetStyle(BUTTON, BORDER_WIDTH, 1); + GuiSetStyle(BUTTON, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER); +#if defined(RAYGUI_NO_ICONS) + if (GuiButton(RAYGUI_CLITERAL(Rectangle){ tabBounds.x + tabBounds.width - 14 - 5, tabBounds.y + 5, 14, 14 }, "x")) result = i; +#else + if (GuiButton(RAYGUI_CLITERAL(Rectangle){ tabBounds.x + tabBounds.width - 14 - 5, tabBounds.y + 5, 14, 14 }, GuiIconText(ICON_CROSS_SMALL, NULL))) result = i; +#endif + GuiSetStyle(BUTTON, BORDER_WIDTH, tempBorderWidth); + GuiSetStyle(BUTTON, TEXT_ALIGNMENT, tempTextAlignment); + } + } + + // Draw tab-bar bottom line + GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y + bounds.height - 1, bounds.width, 1 }, 0, BLANK, GetColor(GuiGetStyle(TOGGLE, BORDER_COLOR_NORMAL))); + //-------------------------------------------------------------------- + + return result; // Return as result the current TAB closing requested +} + +// Scroll Panel control +int GuiScrollPanel(Rectangle bounds, const char *text, Rectangle content, Vector2 *scroll, Rectangle *view) +{ + #define RAYGUI_MIN_SCROLLBAR_WIDTH 40 + #define RAYGUI_MIN_SCROLLBAR_HEIGHT 40 + #define RAYGUI_MIN_MOUSE_WHEEL_SPEED 20 + + int result = 0; + GuiState state = guiState; + + Rectangle temp = { 0 }; + if (view == NULL) view = &temp; + + Vector2 scrollPos = { 0.0f, 0.0f }; + if (scroll != NULL) scrollPos = *scroll; + + // Text will be drawn as a header bar (if provided) + Rectangle statusBar = { bounds.x, bounds.y, bounds.width, (float)RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT }; + if (bounds.height < RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT*2.0f) bounds.height = RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT*2.0f; + + if (text != NULL) + { + // Move panel bounds after the header bar + bounds.y += (float)RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT - 1; + bounds.height -= (float)RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT + 1; + } + + bool hasHorizontalScrollBar = (content.width > bounds.width - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH))? true : false; + bool hasVerticalScrollBar = (content.height > bounds.height - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH))? true : false; + + // Recheck to account for the other scrollbar being visible + if (!hasHorizontalScrollBar) hasHorizontalScrollBar = (hasVerticalScrollBar && (content.width > (bounds.width - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH))))? true : false; + if (!hasVerticalScrollBar) hasVerticalScrollBar = (hasHorizontalScrollBar && (content.height > (bounds.height - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH))))? true : false; + + int horizontalScrollBarWidth = hasHorizontalScrollBar? GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH) : 0; + int verticalScrollBarWidth = hasVerticalScrollBar? GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH) : 0; + Rectangle horizontalScrollBar = { + (float)((GuiGetStyle(LISTVIEW, SCROLLBAR_SIDE) == SCROLLBAR_LEFT_SIDE)? (float)bounds.x + verticalScrollBarWidth : (float)bounds.x) + GuiGetStyle(DEFAULT, BORDER_WIDTH), + (float)bounds.y + bounds.height - horizontalScrollBarWidth - GuiGetStyle(DEFAULT, BORDER_WIDTH), + (float)bounds.width - verticalScrollBarWidth - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH), + (float)horizontalScrollBarWidth + }; + Rectangle verticalScrollBar = { + (float)((GuiGetStyle(LISTVIEW, SCROLLBAR_SIDE) == SCROLLBAR_LEFT_SIDE)? (float)bounds.x + GuiGetStyle(DEFAULT, BORDER_WIDTH) : (float)bounds.x + bounds.width - verticalScrollBarWidth - GuiGetStyle(DEFAULT, BORDER_WIDTH)), + (float)bounds.y + GuiGetStyle(DEFAULT, BORDER_WIDTH), + (float)verticalScrollBarWidth, + (float)bounds.height - horizontalScrollBarWidth - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) + }; + + // Make sure scroll bars have a minimum width/height + if (horizontalScrollBar.width < RAYGUI_MIN_SCROLLBAR_WIDTH) horizontalScrollBar.width = RAYGUI_MIN_SCROLLBAR_WIDTH; + if (verticalScrollBar.height < RAYGUI_MIN_SCROLLBAR_HEIGHT) verticalScrollBar.height = RAYGUI_MIN_SCROLLBAR_HEIGHT; + + // Calculate view area (area without the scrollbars) + *view = (GuiGetStyle(LISTVIEW, SCROLLBAR_SIDE) == SCROLLBAR_LEFT_SIDE)? + RAYGUI_CLITERAL(Rectangle){ bounds.x + verticalScrollBarWidth + GuiGetStyle(DEFAULT, BORDER_WIDTH), bounds.y + GuiGetStyle(DEFAULT, BORDER_WIDTH), bounds.width - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - verticalScrollBarWidth, bounds.height - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - horizontalScrollBarWidth } : + RAYGUI_CLITERAL(Rectangle){ bounds.x + GuiGetStyle(DEFAULT, BORDER_WIDTH), bounds.y + GuiGetStyle(DEFAULT, BORDER_WIDTH), bounds.width - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - verticalScrollBarWidth, bounds.height - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - horizontalScrollBarWidth }; + + // Clip view area to the actual content size + if (view->width > content.width) view->width = content.width; + if (view->height > content.height) view->height = content.height; + + float horizontalMin = hasHorizontalScrollBar? ((GuiGetStyle(LISTVIEW, SCROLLBAR_SIDE) == SCROLLBAR_LEFT_SIDE)? (float)-verticalScrollBarWidth : 0) - (float)GuiGetStyle(DEFAULT, BORDER_WIDTH) : (((float)GuiGetStyle(LISTVIEW, SCROLLBAR_SIDE) == SCROLLBAR_LEFT_SIDE)? (float)-verticalScrollBarWidth : 0) - (float)GuiGetStyle(DEFAULT, BORDER_WIDTH); + float horizontalMax = hasHorizontalScrollBar? content.width - bounds.width + (float)verticalScrollBarWidth + GuiGetStyle(DEFAULT, BORDER_WIDTH) - (((float)GuiGetStyle(LISTVIEW, SCROLLBAR_SIDE) == SCROLLBAR_LEFT_SIDE)? (float)verticalScrollBarWidth : 0) : (float)-GuiGetStyle(DEFAULT, BORDER_WIDTH); + float verticalMin = hasVerticalScrollBar? 0.0f : -1.0f; + float verticalMax = hasVerticalScrollBar? content.height - bounds.height + (float)horizontalScrollBarWidth + (float)GuiGetStyle(DEFAULT, BORDER_WIDTH) : (float)-GuiGetStyle(DEFAULT, BORDER_WIDTH); + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked) + { + Vector2 mousePoint = GetMousePosition(); + + // Check button state + if (CheckCollisionPointRec(mousePoint, bounds)) + { + if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) state = STATE_PRESSED; + else state = STATE_FOCUSED; + +#if defined(SUPPORT_SCROLLBAR_KEY_INPUT) + if (hasHorizontalScrollBar) + { + if (IsKeyDown(KEY_RIGHT)) scrollPos.x -= GuiGetStyle(SCROLLBAR, SCROLL_SPEED); + if (IsKeyDown(KEY_LEFT)) scrollPos.x += GuiGetStyle(SCROLLBAR, SCROLL_SPEED); + } + + if (hasVerticalScrollBar) + { + if (IsKeyDown(KEY_DOWN)) scrollPos.y -= GuiGetStyle(SCROLLBAR, SCROLL_SPEED); + if (IsKeyDown(KEY_UP)) scrollPos.y += GuiGetStyle(SCROLLBAR, SCROLL_SPEED); + } +#endif + float wheelMove = GetMouseWheelMove(); + + // Set scrolling speed with mouse wheel based on ratio between bounds and content + Vector2 mouseWheelSpeed = { content.width/bounds.width, content.height/bounds.height }; + if (mouseWheelSpeed.x < RAYGUI_MIN_MOUSE_WHEEL_SPEED) mouseWheelSpeed.x = RAYGUI_MIN_MOUSE_WHEEL_SPEED; + if (mouseWheelSpeed.y < RAYGUI_MIN_MOUSE_WHEEL_SPEED) mouseWheelSpeed.y = RAYGUI_MIN_MOUSE_WHEEL_SPEED; + + // Horizontal and vertical scrolling with mouse wheel + if (hasHorizontalScrollBar && (IsKeyDown(KEY_LEFT_CONTROL) || IsKeyDown(KEY_LEFT_SHIFT))) scrollPos.x += wheelMove*mouseWheelSpeed.x; + else scrollPos.y += wheelMove*mouseWheelSpeed.y; // Vertical scroll + } + } + + // Normalize scroll values + if (scrollPos.x > -horizontalMin) scrollPos.x = -horizontalMin; + if (scrollPos.x < -horizontalMax) scrollPos.x = -horizontalMax; + if (scrollPos.y > -verticalMin) scrollPos.y = -verticalMin; + if (scrollPos.y < -verticalMax) scrollPos.y = -verticalMax; + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + if (text != NULL) GuiStatusBar(statusBar, text); // Draw panel header as status bar + + GuiDrawRectangle(bounds, 0, BLANK, GetColor(GuiGetStyle(DEFAULT, BACKGROUND_COLOR))); // Draw background + + // Save size of the scrollbar slider + const int slider = GuiGetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE); + + // Draw horizontal scrollbar if visible + if (hasHorizontalScrollBar) + { + // Change scrollbar slider size to show the diff in size between the content width and the widget width + GuiSetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE, (int)(((bounds.width - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - verticalScrollBarWidth)/(int)content.width)*((int)bounds.width - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - verticalScrollBarWidth))); + scrollPos.x = (float)-GuiScrollBar(horizontalScrollBar, (int)-scrollPos.x, (int)horizontalMin, (int)horizontalMax); + } + else scrollPos.x = 0.0f; + + // Draw vertical scrollbar if visible + if (hasVerticalScrollBar) + { + // Change scrollbar slider size to show the diff in size between the content height and the widget height + GuiSetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE, (int)(((bounds.height - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - horizontalScrollBarWidth)/(int)content.height)*((int)bounds.height - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) - horizontalScrollBarWidth))); + scrollPos.y = (float)-GuiScrollBar(verticalScrollBar, (int)-scrollPos.y, (int)verticalMin, (int)verticalMax); + } + else scrollPos.y = 0.0f; + + // Draw detail corner rectangle if both scroll bars are visible + if (hasHorizontalScrollBar && hasVerticalScrollBar) + { + Rectangle corner = { (GuiGetStyle(LISTVIEW, SCROLLBAR_SIDE) == SCROLLBAR_LEFT_SIDE)? (bounds.x + GuiGetStyle(DEFAULT, BORDER_WIDTH) + 2) : (horizontalScrollBar.x + horizontalScrollBar.width + 2), verticalScrollBar.y + verticalScrollBar.height + 2, (float)horizontalScrollBarWidth - 4, (float)verticalScrollBarWidth - 4 }; + GuiDrawRectangle(corner, 0, BLANK, GetColor(GuiGetStyle(LISTVIEW, TEXT + (state*3)))); + } + + // Draw scrollbar lines depending on current state + GuiDrawRectangle(bounds, GuiGetStyle(LISTVIEW, BORDER_WIDTH), GetColor(GuiGetStyle(LISTVIEW, BORDER + (state*3))), BLANK); + + // Set scrollbar slider size back to the way it was before + GuiSetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE, slider); + //-------------------------------------------------------------------- + + if (scroll != NULL) *scroll = scrollPos; + + return result; +} + +// Label control +int GuiLabel(Rectangle bounds, const char *text) +{ + int result = 0; + GuiState state = guiState; + + // Update control + //-------------------------------------------------------------------- + //... + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + GuiDrawText(text, GetTextBounds(LABEL, bounds), GuiGetStyle(LABEL, TEXT_ALIGNMENT), GetColor(GuiGetStyle(LABEL, TEXT + (state*3)))); + //-------------------------------------------------------------------- + + return result; +} + +// Button control, returns true when clicked +int GuiButton(Rectangle bounds, const char *text) +{ + int result = 0; + GuiState state = guiState; + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode) + { + Vector2 mousePoint = GetMousePosition(); + + // Check button state + if (CheckCollisionPointRec(mousePoint, bounds)) + { + if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) state = STATE_PRESSED; + else state = STATE_FOCUSED; + + if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) result = 1; + } + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + GuiDrawRectangle(bounds, GuiGetStyle(BUTTON, BORDER_WIDTH), GetColor(GuiGetStyle(BUTTON, BORDER + (state*3))), GetColor(GuiGetStyle(BUTTON, BASE + (state*3)))); + GuiDrawText(text, GetTextBounds(BUTTON, bounds), GuiGetStyle(BUTTON, TEXT_ALIGNMENT), GetColor(GuiGetStyle(BUTTON, TEXT + (state*3)))); + + if (state == STATE_FOCUSED) GuiTooltip(bounds); + //------------------------------------------------------------------ + + return result; // Button pressed: result = 1 +} + +// Label button control +int GuiLabelButton(Rectangle bounds, const char *text) +{ + GuiState state = guiState; + bool pressed = false; + + // NOTE: We force bounds.width to be all text + float textWidth = (float)GuiGetTextWidth(text); + if ((bounds.width - 2*GuiGetStyle(LABEL, BORDER_WIDTH) - 2*GuiGetStyle(LABEL, TEXT_PADDING)) < textWidth) bounds.width = textWidth + 2*GuiGetStyle(LABEL, BORDER_WIDTH) + 2*GuiGetStyle(LABEL, TEXT_PADDING) + 2; + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode) + { + Vector2 mousePoint = GetMousePosition(); + + // Check checkbox state + if (CheckCollisionPointRec(mousePoint, bounds)) + { + if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) state = STATE_PRESSED; + else state = STATE_FOCUSED; + + if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) pressed = true; + } + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + GuiDrawText(text, GetTextBounds(LABEL, bounds), GuiGetStyle(LABEL, TEXT_ALIGNMENT), GetColor(GuiGetStyle(LABEL, TEXT + (state*3)))); + //-------------------------------------------------------------------- + + return pressed; +} + +// Toggle Button control +int GuiToggle(Rectangle bounds, const char *text, bool *active) +{ + int result = 0; + GuiState state = guiState; + + bool temp = false; + if (active == NULL) active = &temp; + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode) + { + Vector2 mousePoint = GetMousePosition(); + + // Check toggle button state + if (CheckCollisionPointRec(mousePoint, bounds)) + { + if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) state = STATE_PRESSED; + else if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) + { + state = STATE_NORMAL; + *active = !(*active); + } + else state = STATE_FOCUSED; + } + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + if (state == STATE_NORMAL) + { + GuiDrawRectangle(bounds, GuiGetStyle(TOGGLE, BORDER_WIDTH), GetColor(GuiGetStyle(TOGGLE, ((*active)? BORDER_COLOR_PRESSED : (BORDER + state*3)))), GetColor(GuiGetStyle(TOGGLE, ((*active)? BASE_COLOR_PRESSED : (BASE + state*3))))); + GuiDrawText(text, GetTextBounds(TOGGLE, bounds), GuiGetStyle(TOGGLE, TEXT_ALIGNMENT), GetColor(GuiGetStyle(TOGGLE, ((*active)? TEXT_COLOR_PRESSED : (TEXT + state*3))))); + } + else + { + GuiDrawRectangle(bounds, GuiGetStyle(TOGGLE, BORDER_WIDTH), GetColor(GuiGetStyle(TOGGLE, BORDER + state*3)), GetColor(GuiGetStyle(TOGGLE, BASE + state*3))); + GuiDrawText(text, GetTextBounds(TOGGLE, bounds), GuiGetStyle(TOGGLE, TEXT_ALIGNMENT), GetColor(GuiGetStyle(TOGGLE, TEXT + state*3))); + } + + if (state == STATE_FOCUSED) GuiTooltip(bounds); + //-------------------------------------------------------------------- + + return result; +} + +// Toggle Group control +int GuiToggleGroup(Rectangle bounds, const char *text, int *active) +{ + #if !defined(RAYGUI_TOGGLEGROUP_MAX_ITEMS) + #define RAYGUI_TOGGLEGROUP_MAX_ITEMS 32 + #endif + + int result = 0; + float initBoundsX = bounds.x; + + int temp = 0; + if (active == NULL) active = &temp; + + bool toggle = false; // Required for individual toggles + + // Get substrings items from text (items pointers) + int rows[RAYGUI_TOGGLEGROUP_MAX_ITEMS] = { 0 }; + int itemCount = 0; + const char **items = GuiTextSplit(text, ';', &itemCount, rows); + + int prevRow = rows[0]; + + for (int i = 0; i < itemCount; i++) + { + if (prevRow != rows[i]) + { + bounds.x = initBoundsX; + bounds.y += (bounds.height + GuiGetStyle(TOGGLE, GROUP_PADDING)); + prevRow = rows[i]; + } + + if (i == (*active)) + { + toggle = true; + GuiToggle(bounds, items[i], &toggle); + } + else + { + toggle = false; + GuiToggle(bounds, items[i], &toggle); + if (toggle) *active = i; + } + + bounds.x += (bounds.width + GuiGetStyle(TOGGLE, GROUP_PADDING)); + } + + return result; +} + +// Toggle Slider control extended +int GuiToggleSlider(Rectangle bounds, const char *text, int *active) +{ + int result = 0; + GuiState state = guiState; + + int temp = 0; + if (active == NULL) active = &temp; + + //bool toggle = false; // Required for individual toggles + + // Get substrings items from text (items pointers) + int itemCount = 0; + const char **items = NULL; + + if (text != NULL) items = GuiTextSplit(text, ';', &itemCount, NULL); + + Rectangle slider = { + 0, // Calculated later depending on the active toggle + bounds.y + GuiGetStyle(SLIDER, BORDER_WIDTH) + GuiGetStyle(SLIDER, SLIDER_PADDING), + (bounds.width - 2*GuiGetStyle(SLIDER, BORDER_WIDTH) - (itemCount + 1)*GuiGetStyle(SLIDER, SLIDER_PADDING))/itemCount, + bounds.height - 2*GuiGetStyle(SLIDER, BORDER_WIDTH) - 2*GuiGetStyle(SLIDER, SLIDER_PADDING) }; + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked) + { + Vector2 mousePoint = GetMousePosition(); + + if (CheckCollisionPointRec(mousePoint, bounds)) + { + if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) state = STATE_PRESSED; + else if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) + { + state = STATE_PRESSED; + (*active)++; + result = 1; + } + else state = STATE_FOCUSED; + } + + if ((*active) && (state != STATE_FOCUSED)) state = STATE_PRESSED; + } + + if (*active >= itemCount) *active = 0; + slider.x = bounds.x + GuiGetStyle(SLIDER, BORDER_WIDTH) + (*active + 1)*GuiGetStyle(SLIDER, SLIDER_PADDING) + (*active)*slider.width; + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + GuiDrawRectangle(bounds, GuiGetStyle(SLIDER, BORDER_WIDTH), GetColor(GuiGetStyle(TOGGLE, BORDER + (state*3))), + GetColor(GuiGetStyle(TOGGLE, BASE_COLOR_NORMAL))); + + // Draw internal slider + if (state == STATE_NORMAL) GuiDrawRectangle(slider, 0, BLANK, GetColor(GuiGetStyle(SLIDER, BASE_COLOR_PRESSED))); + else if (state == STATE_FOCUSED) GuiDrawRectangle(slider, 0, BLANK, GetColor(GuiGetStyle(SLIDER, BASE_COLOR_FOCUSED))); + else if (state == STATE_PRESSED) GuiDrawRectangle(slider, 0, BLANK, GetColor(GuiGetStyle(SLIDER, BASE_COLOR_PRESSED))); + + // Draw text in slider + if (text != NULL) + { + Rectangle textBounds = { 0 }; + textBounds.width = (float)GuiGetTextWidth(text); + textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE); + textBounds.x = slider.x + slider.width/2 - textBounds.width/2; + textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2; + + GuiDrawText(items[*active], textBounds, GuiGetStyle(TOGGLE, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(TOGGLE, TEXT + (state*3))), guiAlpha)); + } + //-------------------------------------------------------------------- + + return result; +} + +// Check Box control, returns 1 when state changed +int GuiCheckBox(Rectangle bounds, const char *text, bool *checked) +{ + int result = 0; + GuiState state = guiState; + + bool temp = false; + if (checked == NULL) checked = &temp; + + Rectangle textBounds = { 0 }; + + if (text != NULL) + { + textBounds.width = (float)GuiGetTextWidth(text) + 2; + textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE); + textBounds.x = bounds.x + bounds.width + GuiGetStyle(CHECKBOX, TEXT_PADDING); + textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2; + if (GuiGetStyle(CHECKBOX, TEXT_ALIGNMENT) == TEXT_ALIGN_LEFT) textBounds.x = bounds.x - textBounds.width - GuiGetStyle(CHECKBOX, TEXT_PADDING); + } + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode) + { + Vector2 mousePoint = GetMousePosition(); + + Rectangle totalBounds = { + (GuiGetStyle(CHECKBOX, TEXT_ALIGNMENT) == TEXT_ALIGN_LEFT)? textBounds.x : bounds.x, + bounds.y, + bounds.width + textBounds.width + GuiGetStyle(CHECKBOX, TEXT_PADDING), + bounds.height, + }; + + // Check checkbox state + if (CheckCollisionPointRec(mousePoint, totalBounds)) + { + if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) state = STATE_PRESSED; + else state = STATE_FOCUSED; + + if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) + { + *checked = !(*checked); + result = 1; + } + } + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + GuiDrawRectangle(bounds, GuiGetStyle(CHECKBOX, BORDER_WIDTH), GetColor(GuiGetStyle(CHECKBOX, BORDER + (state*3))), BLANK); + + if (*checked) + { + Rectangle check = { bounds.x + GuiGetStyle(CHECKBOX, BORDER_WIDTH) + GuiGetStyle(CHECKBOX, CHECK_PADDING), + bounds.y + GuiGetStyle(CHECKBOX, BORDER_WIDTH) + GuiGetStyle(CHECKBOX, CHECK_PADDING), + bounds.width - 2*(GuiGetStyle(CHECKBOX, BORDER_WIDTH) + GuiGetStyle(CHECKBOX, CHECK_PADDING)), + bounds.height - 2*(GuiGetStyle(CHECKBOX, BORDER_WIDTH) + GuiGetStyle(CHECKBOX, CHECK_PADDING)) }; + GuiDrawRectangle(check, 0, BLANK, GetColor(GuiGetStyle(CHECKBOX, TEXT + state*3))); + } + + GuiDrawText(text, textBounds, (GuiGetStyle(CHECKBOX, TEXT_ALIGNMENT) == TEXT_ALIGN_RIGHT)? TEXT_ALIGN_LEFT : TEXT_ALIGN_RIGHT, GetColor(GuiGetStyle(LABEL, TEXT + (state*3)))); + //-------------------------------------------------------------------- + + return result; +} + +// Combo Box control +int GuiComboBox(Rectangle bounds, const char *text, int *active) +{ + int result = 0; + GuiState state = guiState; + + int temp = 0; + if (active == NULL) active = &temp; + + bounds.width -= (GuiGetStyle(COMBOBOX, COMBO_BUTTON_WIDTH) + GuiGetStyle(COMBOBOX, COMBO_BUTTON_SPACING)); + + Rectangle selector = { (float)bounds.x + bounds.width + GuiGetStyle(COMBOBOX, COMBO_BUTTON_SPACING), + (float)bounds.y, (float)GuiGetStyle(COMBOBOX, COMBO_BUTTON_WIDTH), (float)bounds.height }; + + // Get substrings items from text (items pointers, lengths and count) + int itemCount = 0; + const char **items = GuiTextSplit(text, ';', &itemCount, NULL); + + if (*active < 0) *active = 0; + else if (*active > (itemCount - 1)) *active = itemCount - 1; + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked && (itemCount > 1) && !guiControlExclusiveMode) + { + Vector2 mousePoint = GetMousePosition(); + + if (CheckCollisionPointRec(mousePoint, bounds) || + CheckCollisionPointRec(mousePoint, selector)) + { + if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) + { + *active += 1; + if (*active >= itemCount) *active = 0; // Cyclic combobox + } + + if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) state = STATE_PRESSED; + else state = STATE_FOCUSED; + } + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + // Draw combo box main + GuiDrawRectangle(bounds, GuiGetStyle(COMBOBOX, BORDER_WIDTH), GetColor(GuiGetStyle(COMBOBOX, BORDER + (state*3))), GetColor(GuiGetStyle(COMBOBOX, BASE + (state*3)))); + GuiDrawText(items[*active], GetTextBounds(COMBOBOX, bounds), GuiGetStyle(COMBOBOX, TEXT_ALIGNMENT), GetColor(GuiGetStyle(COMBOBOX, TEXT + (state*3)))); + + // Draw selector using a custom button + // NOTE: BORDER_WIDTH and TEXT_ALIGNMENT forced values + int tempBorderWidth = GuiGetStyle(BUTTON, BORDER_WIDTH); + int tempTextAlign = GuiGetStyle(BUTTON, TEXT_ALIGNMENT); + GuiSetStyle(BUTTON, BORDER_WIDTH, 1); + GuiSetStyle(BUTTON, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER); + + GuiButton(selector, TextFormat("%i/%i", *active + 1, itemCount)); + + GuiSetStyle(BUTTON, TEXT_ALIGNMENT, tempTextAlign); + GuiSetStyle(BUTTON, BORDER_WIDTH, tempBorderWidth); + //-------------------------------------------------------------------- + + return result; +} + +// Dropdown Box control +// NOTE: Returns mouse click +int GuiDropdownBox(Rectangle bounds, const char *text, int *active, bool editMode) +{ + int result = 0; + GuiState state = guiState; + + int temp = 0; + if (active == NULL) active = &temp; + + int itemSelected = *active; + int itemFocused = -1; + + int direction = 0; // Dropdown box open direction: down (default) + if (GuiGetStyle(DROPDOWNBOX, DROPDOWN_ROLL_UP) == 1) direction = 1; // Up + + // Get substrings items from text (items pointers, lengths and count) + int itemCount = 0; + const char **items = GuiTextSplit(text, ';', &itemCount, NULL); + + Rectangle boundsOpen = bounds; + boundsOpen.height = (itemCount + 1)*(bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING)); + if (direction == 1) boundsOpen.y -= itemCount*(bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING)) + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING); + + Rectangle itemBounds = bounds; + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && (editMode || !guiLocked) && (itemCount > 1) && !guiControlExclusiveMode) + { + Vector2 mousePoint = GetMousePosition(); + + if (editMode) + { + state = STATE_PRESSED; + + // Check if mouse has been pressed or released outside limits + if (!CheckCollisionPointRec(mousePoint, boundsOpen)) + { + if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON) || IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) result = 1; + } + + // Check if already selected item has been pressed again + if (CheckCollisionPointRec(mousePoint, bounds) && IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) result = 1; + + // Check focused and selected item + for (int i = 0; i < itemCount; i++) + { + // Update item rectangle y position for next item + if (direction == 0) itemBounds.y += (bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING)); + else itemBounds.y -= (bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING)); + + if (CheckCollisionPointRec(mousePoint, itemBounds)) + { + itemFocused = i; + if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) + { + itemSelected = i; + result = 1; // Item selected + } + break; + } + } + + itemBounds = bounds; + } + else + { + if (CheckCollisionPointRec(mousePoint, bounds)) + { + if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) + { + result = 1; + state = STATE_PRESSED; + } + else state = STATE_FOCUSED; + } + } + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + if (editMode) GuiPanel(boundsOpen, NULL); + + GuiDrawRectangle(bounds, GuiGetStyle(DROPDOWNBOX, BORDER_WIDTH), GetColor(GuiGetStyle(DROPDOWNBOX, BORDER + state*3)), GetColor(GuiGetStyle(DROPDOWNBOX, BASE + state*3))); + GuiDrawText(items[itemSelected], GetTextBounds(DROPDOWNBOX, bounds), GuiGetStyle(DROPDOWNBOX, TEXT_ALIGNMENT), GetColor(GuiGetStyle(DROPDOWNBOX, TEXT + state*3))); + + if (editMode) + { + // Draw visible items + for (int i = 0; i < itemCount; i++) + { + // Update item rectangle y position for next item + if (direction == 0) itemBounds.y += (bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING)); + else itemBounds.y -= (bounds.height + GuiGetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING)); + + if (i == itemSelected) + { + GuiDrawRectangle(itemBounds, GuiGetStyle(DROPDOWNBOX, BORDER_WIDTH), GetColor(GuiGetStyle(DROPDOWNBOX, BORDER_COLOR_PRESSED)), GetColor(GuiGetStyle(DROPDOWNBOX, BASE_COLOR_PRESSED))); + GuiDrawText(items[i], GetTextBounds(DROPDOWNBOX, itemBounds), GuiGetStyle(DROPDOWNBOX, TEXT_ALIGNMENT), GetColor(GuiGetStyle(DROPDOWNBOX, TEXT_COLOR_PRESSED))); + } + else if (i == itemFocused) + { + GuiDrawRectangle(itemBounds, GuiGetStyle(DROPDOWNBOX, BORDER_WIDTH), GetColor(GuiGetStyle(DROPDOWNBOX, BORDER_COLOR_FOCUSED)), GetColor(GuiGetStyle(DROPDOWNBOX, BASE_COLOR_FOCUSED))); + GuiDrawText(items[i], GetTextBounds(DROPDOWNBOX, itemBounds), GuiGetStyle(DROPDOWNBOX, TEXT_ALIGNMENT), GetColor(GuiGetStyle(DROPDOWNBOX, TEXT_COLOR_FOCUSED))); + } + else GuiDrawText(items[i], GetTextBounds(DROPDOWNBOX, itemBounds), GuiGetStyle(DROPDOWNBOX, TEXT_ALIGNMENT), GetColor(GuiGetStyle(DROPDOWNBOX, TEXT_COLOR_NORMAL))); + } + } + + if (!GuiGetStyle(DROPDOWNBOX, DROPDOWN_ARROW_HIDDEN)) + { + // Draw arrows (using icon if available) +#if defined(RAYGUI_NO_ICONS) + GuiDrawText("v", RAYGUI_CLITERAL(Rectangle){ bounds.x + bounds.width - GuiGetStyle(DROPDOWNBOX, ARROW_PADDING), bounds.y + bounds.height/2 - 2, 10, 10 }, + TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(DROPDOWNBOX, TEXT + (state*3)))); +#else + GuiDrawText(direction? "#121#" : "#120#", RAYGUI_CLITERAL(Rectangle){ bounds.x + bounds.width - GuiGetStyle(DROPDOWNBOX, ARROW_PADDING), bounds.y + bounds.height/2 - 6, 10, 10 }, + TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(DROPDOWNBOX, TEXT + (state*3)))); // ICON_ARROW_DOWN_FILL +#endif + } + //-------------------------------------------------------------------- + + *active = itemSelected; + + // TODO: Use result to return more internal states: mouse-press out-of-bounds, mouse-press over selected-item... + return result; // Mouse click: result = 1 +} + +// Text Box control +// NOTE: Returns true on ENTER pressed (useful for data validation) +int GuiTextBox(Rectangle bounds, char *text, int textSize, bool editMode) +{ + #if !defined(RAYGUI_TEXTBOX_AUTO_CURSOR_COOLDOWN) + #define RAYGUI_TEXTBOX_AUTO_CURSOR_COOLDOWN 30 // Frames to wait for autocursor movement + #endif + #if !defined(RAYGUI_TEXTBOX_AUTO_CURSOR_DELAY) + #define RAYGUI_TEXTBOX_AUTO_CURSOR_DELAY 2 // Frames delay for autocursor movement + #endif + + int result = 0; + GuiState state = guiState; + + bool multiline = false; // TODO: Consider multiline text input + int wrapMode = GuiGetStyle(DEFAULT, TEXT_WRAP_MODE); + + Rectangle textBounds = GetTextBounds(TEXTBOX, bounds); + int textLength = (text != NULL)? (int)strlen(text) : 0; // Get current text length + int thisCursorIndex = textBoxCursorIndex; + if (thisCursorIndex > textLength) thisCursorIndex = textLength; + int textWidth = GuiGetTextWidth(text) - GuiGetTextWidth(text + thisCursorIndex); + int textIndexOffset = 0; // Text index offset to start drawing in the box + + // Cursor rectangle + // NOTE: Position X value should be updated + Rectangle cursor = { + textBounds.x + textWidth + GuiGetStyle(DEFAULT, TEXT_SPACING), + textBounds.y + textBounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE), + 2, + (float)GuiGetStyle(DEFAULT, TEXT_SIZE)*2 + }; + + if (cursor.height >= bounds.height) cursor.height = bounds.height - GuiGetStyle(TEXTBOX, BORDER_WIDTH)*2; + if (cursor.y < (bounds.y + GuiGetStyle(TEXTBOX, BORDER_WIDTH))) cursor.y = bounds.y + GuiGetStyle(TEXTBOX, BORDER_WIDTH); + + // Mouse cursor rectangle + // NOTE: Initialized outside of screen + Rectangle mouseCursor = cursor; + mouseCursor.x = -1; + mouseCursor.width = 1; + + // Blink-cursor frame counter + //if (!autoCursorMode) blinkCursorFrameCounter++; + //else blinkCursorFrameCounter = 0; + + // Update control + //-------------------------------------------------------------------- + // WARNING: Text editing is only supported under certain conditions: + if ((state != STATE_DISABLED) && // Control not disabled + !GuiGetStyle(TEXTBOX, TEXT_READONLY) && // TextBox not on read-only mode + !guiLocked && // Gui not locked + !guiControlExclusiveMode && // No gui slider on dragging + (wrapMode == TEXT_WRAP_NONE)) // No wrap mode + { + Vector2 mousePosition = GetMousePosition(); + + if (editMode) + { + // GLOBAL: Auto-cursor movement logic + // NOTE: Keystrokes are handled repeatedly when button is held down for some time + if (IsKeyDown(KEY_LEFT) || IsKeyDown(KEY_RIGHT) || IsKeyDown(KEY_UP) || IsKeyDown(KEY_DOWN) || IsKeyDown(KEY_BACKSPACE) || IsKeyDown(KEY_DELETE)) autoCursorCounter++; + else autoCursorCounter = 0; + + bool autoCursorShouldTrigger = (autoCursorCounter > RAYGUI_TEXTBOX_AUTO_CURSOR_COOLDOWN) && ((autoCursorCounter % RAYGUI_TEXTBOX_AUTO_CURSOR_DELAY) == 0); + + state = STATE_PRESSED; + + if (textBoxCursorIndex > textLength) textBoxCursorIndex = textLength; + + // If text does not fit in the textbox and current cursor position is out of bounds, + // we add an index offset to text for drawing only what requires depending on cursor + while (textWidth >= textBounds.width) + { + int nextCodepointSize = 0; + GetCodepointNext(text + textIndexOffset, &nextCodepointSize); + + textIndexOffset += nextCodepointSize; + + textWidth = GuiGetTextWidth(text + textIndexOffset) - GuiGetTextWidth(text + textBoxCursorIndex); + } + + int codepoint = GetCharPressed(); // Get Unicode codepoint + if (multiline && IsKeyPressed(KEY_ENTER)) codepoint = (int)'\n'; + + // Encode codepoint as UTF-8 + int codepointSize = 0; + const char *charEncoded = CodepointToUTF8(codepoint, &codepointSize); + + // Handle Paste action + if (IsKeyPressed(KEY_V) && (IsKeyDown(KEY_LEFT_CONTROL) || IsKeyDown(KEY_RIGHT_CONTROL))) + { + const char *pasteText = GetClipboardText(); + if (pasteText != NULL) + { + int pasteLength = 0; + int pasteCodepoint; + int pasteCodepointSize; + // count how many codepoints to copy, stopping at the first unwanted control character + while (true) + { + pasteCodepoint = GetCodepointNext(pasteText + pasteLength, &pasteCodepointSize); + if (textLength + pasteLength + pasteCodepointSize >= textSize) break; + if (!(multiline && (pasteCodepoint == (int)'\n')) && !(pasteCodepoint >= 32)) break; + pasteLength += pasteCodepointSize; + } + if (pasteLength > 0) + { + // Move forward data from cursor position + for (int i = textLength + pasteLength; i > textBoxCursorIndex; i--) text[i] = text[i - pasteLength]; + + // Paste data in at cursor + for (int i = 0; i < pasteLength; i++) text[textBoxCursorIndex + i] = pasteText[i]; + + textBoxCursorIndex += pasteLength; + textLength += pasteLength; + text[textLength] = '\0'; + } + } + } + // Add codepoint to text, at current cursor position + // NOTE: Make sure we do not overflow buffer size + else if (((multiline && (codepoint == (int)'\n')) || (codepoint >= 32)) && ((textLength + codepointSize) < textSize)) + { + // Move forward data from cursor position + for (int i = (textLength + codepointSize); i > textBoxCursorIndex; i--) text[i] = text[i - codepointSize]; + + // Add new codepoint in current cursor position + for (int i = 0; i < codepointSize; i++) text[textBoxCursorIndex + i] = charEncoded[i]; + + textBoxCursorIndex += codepointSize; + textLength += codepointSize; + + // Make sure text last character is EOL + text[textLength] = '\0'; + } + + // Move cursor to start + if ((textLength > 0) && IsKeyPressed(KEY_HOME)) textBoxCursorIndex = 0; + + // Move cursor to end + if ((textLength > textBoxCursorIndex) && IsKeyPressed(KEY_END)) textBoxCursorIndex = textLength; + + // Delete related codepoints from text, after current cursor position + if ((textLength > textBoxCursorIndex) && IsKeyPressed(KEY_DELETE) && (IsKeyDown(KEY_LEFT_CONTROL) || IsKeyDown(KEY_RIGHT_CONTROL))) + { + int offset = textBoxCursorIndex; + int accCodepointSize = 0; + int nextCodepointSize; + int nextCodepoint; + // Check characters of the same type to delete (either ASCII punctuation or anything non-whitespace) + // Not using isalnum() since it only works on ASCII characters + nextCodepoint = GetCodepointNext(text + offset, &nextCodepointSize); + bool puctuation = ispunct(nextCodepoint & 0xff); + while (offset < textLength) + { + if ((puctuation && !ispunct(nextCodepoint & 0xff)) || (!puctuation && (isspace(nextCodepoint & 0xff) || ispunct(nextCodepoint & 0xff)))) + break; + offset += nextCodepointSize; + accCodepointSize += nextCodepointSize; + nextCodepoint = GetCodepointNext(text + offset, &nextCodepointSize); + } + // Check whitespace to delete (ASCII only) + while (offset < textLength) + { + if (!isspace(nextCodepoint & 0xff)) + break; + offset += nextCodepointSize; + accCodepointSize += nextCodepointSize; + nextCodepoint = GetCodepointNext(text + offset, &nextCodepointSize); + } + + // Move text after cursor forward (including final null terminator) + for (int i = offset; i <= textLength; i++) text[i - accCodepointSize] = text[i]; + + textLength -= accCodepointSize; + } + // Delete single codepoint from text, after current cursor position + else if ((textLength > textBoxCursorIndex) && (IsKeyPressed(KEY_DELETE) || (IsKeyDown(KEY_DELETE) && autoCursorShouldTrigger))) + { + int nextCodepointSize = 0; + GetCodepointNext(text + textBoxCursorIndex, &nextCodepointSize); + + // Move text after cursor forward (including final null terminator) + for (int i = textBoxCursorIndex + nextCodepointSize; i <= textLength; i++) text[i - nextCodepointSize] = text[i]; + + textLength -= nextCodepointSize; + } + + // Delete related codepoints from text, before current cursor position + if ((textBoxCursorIndex > 0) && IsKeyPressed(KEY_BACKSPACE) && (IsKeyDown(KEY_LEFT_CONTROL) || IsKeyDown(KEY_RIGHT_CONTROL))) + { + int offset = textBoxCursorIndex; + int accCodepointSize = 0; + int prevCodepointSize; + int prevCodepoint; + + // Check whitespace to delete (ASCII only) + while (offset > 0) + { + prevCodepoint = GetCodepointPrevious(text + offset, &prevCodepointSize); + if (!isspace(prevCodepoint & 0xff)) break; + + offset -= prevCodepointSize; + accCodepointSize += prevCodepointSize; + } + // Check characters of the same type to delete (either ASCII punctuation or anything non-whitespace) + // Not using isalnum() since it only works on ASCII characters + bool puctuation = ispunct(prevCodepoint & 0xff); + while (offset > 0) + { + prevCodepoint = GetCodepointPrevious(text + offset, &prevCodepointSize); + if ((puctuation && !ispunct(prevCodepoint & 0xff)) || (!puctuation && (isspace(prevCodepoint & 0xff) || ispunct(prevCodepoint & 0xff)))) break; + + offset -= prevCodepointSize; + accCodepointSize += prevCodepointSize; + } + + // Move text after cursor forward (including final null terminator) + for (int i = textBoxCursorIndex; i <= textLength; i++) text[i - accCodepointSize] = text[i]; + + textLength -= accCodepointSize; + textBoxCursorIndex -= accCodepointSize; + } + // Delete single codepoint from text, before current cursor position + else if ((textBoxCursorIndex > 0) && (IsKeyPressed(KEY_BACKSPACE) || (IsKeyDown(KEY_BACKSPACE) && autoCursorShouldTrigger))) + { + int prevCodepointSize = 0; + + GetCodepointPrevious(text + textBoxCursorIndex, &prevCodepointSize); + + // Move text after cursor forward (including final null terminator) + for (int i = textBoxCursorIndex; i <= textLength; i++) text[i - prevCodepointSize] = text[i]; + + textLength -= prevCodepointSize; + textBoxCursorIndex -= prevCodepointSize; + } + + // Move cursor position with keys + if ((textBoxCursorIndex > 0) && IsKeyPressed(KEY_LEFT) && (IsKeyDown(KEY_LEFT_CONTROL) || IsKeyDown(KEY_RIGHT_CONTROL))) + { + int offset = textBoxCursorIndex; + int prevCodepointSize; + int prevCodepoint; + + // Check whitespace to skip (ASCII only) + while (offset > 0) + { + prevCodepoint = GetCodepointPrevious(text + offset, &prevCodepointSize); + if (!isspace(prevCodepoint & 0xff)) break; + + offset -= prevCodepointSize; + } + + // Check characters of the same type to skip (either ASCII punctuation or anything non-whitespace) + // Not using isalnum() since it only works on ASCII characters + bool puctuation = ispunct(prevCodepoint & 0xff); + while (offset > 0) + { + prevCodepoint = GetCodepointPrevious(text + offset, &prevCodepointSize); + if ((puctuation && !ispunct(prevCodepoint & 0xff)) || (!puctuation && (isspace(prevCodepoint & 0xff) || ispunct(prevCodepoint & 0xff)))) break; + + offset -= prevCodepointSize; + } + + textBoxCursorIndex = offset; + } + else if ((textBoxCursorIndex > 0) && (IsKeyPressed(KEY_LEFT) || (IsKeyDown(KEY_LEFT) && autoCursorShouldTrigger))) + { + int prevCodepointSize = 0; + GetCodepointPrevious(text + textBoxCursorIndex, &prevCodepointSize); + + textBoxCursorIndex -= prevCodepointSize; + } + else if ((textLength > textBoxCursorIndex) && IsKeyPressed(KEY_RIGHT) && (IsKeyDown(KEY_LEFT_CONTROL) || IsKeyDown(KEY_RIGHT_CONTROL))) + { + int offset = textBoxCursorIndex; + int nextCodepointSize; + int nextCodepoint; + + // Check characters of the same type to skip (either ASCII punctuation or anything non-whitespace) + // Not using isalnum() since it only works on ASCII characters + nextCodepoint = GetCodepointNext(text + offset, &nextCodepointSize); + bool puctuation = ispunct(nextCodepoint & 0xff); + while (offset < textLength) + { + if ((puctuation && !ispunct(nextCodepoint & 0xff)) || (!puctuation && (isspace(nextCodepoint & 0xff) || ispunct(nextCodepoint & 0xff)))) break; + + offset += nextCodepointSize; + nextCodepoint = GetCodepointNext(text + offset, &nextCodepointSize); + } + + // Check whitespace to skip (ASCII only) + while (offset < textLength) + { + if (!isspace(nextCodepoint & 0xff)) break; + + offset += nextCodepointSize; + nextCodepoint = GetCodepointNext(text + offset, &nextCodepointSize); + } + + textBoxCursorIndex = offset; + } + else if ((textLength > textBoxCursorIndex) && (IsKeyPressed(KEY_RIGHT) || (IsKeyDown(KEY_RIGHT) && autoCursorShouldTrigger))) + { + int nextCodepointSize = 0; + GetCodepointNext(text + textBoxCursorIndex, &nextCodepointSize); + + textBoxCursorIndex += nextCodepointSize; + } + + // Move cursor position with mouse + if (CheckCollisionPointRec(mousePosition, textBounds)) // Mouse hover text + { + float scaleFactor = (float)GuiGetStyle(DEFAULT, TEXT_SIZE)/(float)guiFont.baseSize; + int codepointIndex = 0; + float glyphWidth = 0.0f; + float widthToMouseX = 0; + int mouseCursorIndex = 0; + + for (int i = textIndexOffset; i < textLength; i += codepointSize) + { + codepoint = GetCodepointNext(&text[i], &codepointSize); + codepointIndex = GetGlyphIndex(guiFont, codepoint); + + if (guiFont.glyphs[codepointIndex].advanceX == 0) glyphWidth = ((float)guiFont.recs[codepointIndex].width*scaleFactor); + else glyphWidth = ((float)guiFont.glyphs[codepointIndex].advanceX*scaleFactor); + + if (mousePosition.x <= (textBounds.x + (widthToMouseX + glyphWidth/2))) + { + mouseCursor.x = textBounds.x + widthToMouseX; + mouseCursorIndex = i; + break; + } + + widthToMouseX += (glyphWidth + (float)GuiGetStyle(DEFAULT, TEXT_SPACING)); + } + + // Check if mouse cursor is at the last position + int textEndWidth = GuiGetTextWidth(text + textIndexOffset); + if (GetMousePosition().x >= (textBounds.x + textEndWidth - glyphWidth/2)) + { + mouseCursor.x = textBounds.x + textEndWidth; + mouseCursorIndex = textLength; + } + + // Place cursor at required index on mouse click + if ((mouseCursor.x >= 0) && IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) + { + cursor.x = mouseCursor.x; + textBoxCursorIndex = mouseCursorIndex; + } + } + else mouseCursor.x = -1; + + // Recalculate cursor position.y depending on textBoxCursorIndex + cursor.x = bounds.x + GuiGetStyle(TEXTBOX, TEXT_PADDING) + GuiGetTextWidth(text + textIndexOffset) - GuiGetTextWidth(text + textBoxCursorIndex) + GuiGetStyle(DEFAULT, TEXT_SPACING); + //if (multiline) cursor.y = GetTextLines() + + // Finish text editing on ENTER or mouse click outside bounds + if ((!multiline && IsKeyPressed(KEY_ENTER)) || + (!CheckCollisionPointRec(mousePosition, bounds) && IsMouseButtonPressed(MOUSE_LEFT_BUTTON))) + { + textBoxCursorIndex = 0; // GLOBAL: Reset the shared cursor index + autoCursorCounter = 0; // GLOBAL: Reset counter for repeated keystrokes + result = 1; + } + } + else + { + if (CheckCollisionPointRec(mousePosition, bounds)) + { + state = STATE_FOCUSED; + + if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) + { + textBoxCursorIndex = textLength; // GLOBAL: Place cursor index to the end of current text + autoCursorCounter = 0; // GLOBAL: Reset counter for repeated keystrokes + result = 1; + } + } + } + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + if (state == STATE_PRESSED) + { + GuiDrawRectangle(bounds, GuiGetStyle(TEXTBOX, BORDER_WIDTH), GetColor(GuiGetStyle(TEXTBOX, BORDER + (state*3))), GetColor(GuiGetStyle(TEXTBOX, BASE_COLOR_PRESSED))); + } + else if (state == STATE_DISABLED) + { + GuiDrawRectangle(bounds, GuiGetStyle(TEXTBOX, BORDER_WIDTH), GetColor(GuiGetStyle(TEXTBOX, BORDER + (state*3))), GetColor(GuiGetStyle(TEXTBOX, BASE_COLOR_DISABLED))); + } + else GuiDrawRectangle(bounds, GuiGetStyle(TEXTBOX, BORDER_WIDTH), GetColor(GuiGetStyle(TEXTBOX, BORDER + (state*3))), BLANK); + + // Draw text considering index offset if required + // NOTE: Text index offset depends on cursor position + GuiDrawText(text + textIndexOffset, textBounds, GuiGetStyle(TEXTBOX, TEXT_ALIGNMENT), GetColor(GuiGetStyle(TEXTBOX, TEXT + (state*3)))); + + // Draw cursor + if (editMode && !GuiGetStyle(TEXTBOX, TEXT_READONLY)) + { + //if (autoCursorMode || ((blinkCursorFrameCounter/40)%2 == 0)) + GuiDrawRectangle(cursor, 0, BLANK, GetColor(GuiGetStyle(TEXTBOX, BORDER_COLOR_PRESSED))); + + // Draw mouse position cursor (if required) + if (mouseCursor.x >= 0) GuiDrawRectangle(mouseCursor, 0, BLANK, GetColor(GuiGetStyle(TEXTBOX, BORDER_COLOR_PRESSED))); + } + else if (state == STATE_FOCUSED) GuiTooltip(bounds); + //-------------------------------------------------------------------- + + return result; // Mouse button pressed: result = 1 +} + +/* +// Text Box control with multiple lines and word-wrap +// NOTE: This text-box is readonly, no editing supported by default +bool GuiTextBoxMulti(Rectangle bounds, char *text, int textSize, bool editMode) +{ + bool pressed = false; + + GuiSetStyle(TEXTBOX, TEXT_READONLY, 1); + GuiSetStyle(DEFAULT, TEXT_WRAP_MODE, TEXT_WRAP_WORD); // WARNING: If wrap mode enabled, text editing is not supported + GuiSetStyle(DEFAULT, TEXT_ALIGNMENT_VERTICAL, TEXT_ALIGN_TOP); + + // TODO: Implement methods to calculate cursor position properly + pressed = GuiTextBox(bounds, text, textSize, editMode); + + GuiSetStyle(DEFAULT, TEXT_ALIGNMENT_VERTICAL, TEXT_ALIGN_MIDDLE); + GuiSetStyle(DEFAULT, TEXT_WRAP_MODE, TEXT_WRAP_NONE); + GuiSetStyle(TEXTBOX, TEXT_READONLY, 0); + + return pressed; +} +*/ + +// Spinner control, returns selected value +int GuiSpinner(Rectangle bounds, const char *text, int *value, int minValue, int maxValue, bool editMode) +{ + int result = 1; + GuiState state = guiState; + + int tempValue = *value; + + Rectangle valueBoxBounds = { + bounds.x + GuiGetStyle(VALUEBOX, SPINNER_BUTTON_WIDTH) + GuiGetStyle(VALUEBOX, SPINNER_BUTTON_SPACING), + bounds.y, + bounds.width - 2*(GuiGetStyle(VALUEBOX, SPINNER_BUTTON_WIDTH) + GuiGetStyle(VALUEBOX, SPINNER_BUTTON_SPACING)), bounds.height }; + Rectangle leftButtonBound = { (float)bounds.x, (float)bounds.y, (float)GuiGetStyle(VALUEBOX, SPINNER_BUTTON_WIDTH), (float)bounds.height }; + Rectangle rightButtonBound = { (float)bounds.x + bounds.width - GuiGetStyle(VALUEBOX, SPINNER_BUTTON_WIDTH), (float)bounds.y, + (float)GuiGetStyle(VALUEBOX, SPINNER_BUTTON_WIDTH), (float)bounds.height }; + + Rectangle textBounds = { 0 }; + if (text != NULL) + { + textBounds.width = (float)GuiGetTextWidth(text) + 2; + textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE); + textBounds.x = bounds.x + bounds.width + GuiGetStyle(VALUEBOX, TEXT_PADDING); + textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2; + if (GuiGetStyle(VALUEBOX, TEXT_ALIGNMENT) == TEXT_ALIGN_LEFT) textBounds.x = bounds.x - textBounds.width - GuiGetStyle(VALUEBOX, TEXT_PADDING); + } + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode) + { + Vector2 mousePoint = GetMousePosition(); + + // Check spinner state + if (CheckCollisionPointRec(mousePoint, bounds)) + { + if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) state = STATE_PRESSED; + else state = STATE_FOCUSED; + } + } + +#if defined(RAYGUI_NO_ICONS) + if (GuiButton(leftButtonBound, "<")) tempValue--; + if (GuiButton(rightButtonBound, ">")) tempValue++; +#else + if (GuiButton(leftButtonBound, GuiIconText(ICON_ARROW_LEFT_FILL, NULL))) tempValue--; + if (GuiButton(rightButtonBound, GuiIconText(ICON_ARROW_RIGHT_FILL, NULL))) tempValue++; +#endif + + if (!editMode) + { + if (tempValue < minValue) tempValue = minValue; + if (tempValue > maxValue) tempValue = maxValue; + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + result = GuiValueBox(valueBoxBounds, NULL, &tempValue, minValue, maxValue, editMode); + + // Draw value selector custom buttons + // NOTE: BORDER_WIDTH and TEXT_ALIGNMENT forced values + int tempBorderWidth = GuiGetStyle(BUTTON, BORDER_WIDTH); + int tempTextAlign = GuiGetStyle(BUTTON, TEXT_ALIGNMENT); + GuiSetStyle(BUTTON, BORDER_WIDTH, GuiGetStyle(VALUEBOX, BORDER_WIDTH)); + GuiSetStyle(BUTTON, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER); + + GuiSetStyle(BUTTON, TEXT_ALIGNMENT, tempTextAlign); + GuiSetStyle(BUTTON, BORDER_WIDTH, tempBorderWidth); + + // Draw text label if provided + GuiDrawText(text, textBounds, (GuiGetStyle(VALUEBOX, TEXT_ALIGNMENT) == TEXT_ALIGN_RIGHT)? TEXT_ALIGN_LEFT : TEXT_ALIGN_RIGHT, GetColor(GuiGetStyle(LABEL, TEXT + (state*3)))); + //-------------------------------------------------------------------- + + *value = tempValue; + return result; +} + +// Value Box control, updates input text with numbers +// NOTE: Requires static variables: frameCounter +int GuiValueBox(Rectangle bounds, const char *text, int *value, int minValue, int maxValue, bool editMode) +{ + #if !defined(RAYGUI_VALUEBOX_MAX_CHARS) + #define RAYGUI_VALUEBOX_MAX_CHARS 32 + #endif + + int result = 0; + GuiState state = guiState; + + char textValue[RAYGUI_VALUEBOX_MAX_CHARS + 1] = "\0"; + snprintf(textValue, RAYGUI_VALUEBOX_MAX_CHARS + 1, "%i", *value); + + Rectangle textBounds = { 0 }; + if (text != NULL) + { + textBounds.width = (float)GuiGetTextWidth(text) + 2; + textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE); + textBounds.x = bounds.x + bounds.width + GuiGetStyle(VALUEBOX, TEXT_PADDING); + textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2; + if (GuiGetStyle(VALUEBOX, TEXT_ALIGNMENT) == TEXT_ALIGN_LEFT) textBounds.x = bounds.x - textBounds.width - GuiGetStyle(VALUEBOX, TEXT_PADDING); + } + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode) + { + Vector2 mousePoint = GetMousePosition(); + + bool valueHasChanged = false; + + if (editMode) + { + state = STATE_PRESSED; + + int keyCount = (int)strlen(textValue); + + // Add or remove minus symbol + if (IsKeyPressed(KEY_MINUS)) + { + if (textValue[0] == '-') + { + for (int i = 0 ; i < keyCount; i++) + { + textValue[i] = textValue[i + 1]; + } + keyCount--; + valueHasChanged = true; + } + else if (keyCount < RAYGUI_VALUEBOX_MAX_CHARS -1) + { + if (keyCount == 0) + { + textValue[0] = '0'; + textValue[1] = '\0'; + keyCount++; + } + + for (int i = keyCount ; i > -1; i--) textValue[i + 1] = textValue[i]; + + textValue[0] = '-'; + keyCount++; + valueHasChanged = true; + } + } + + // Only allow keys in range [48..57] + if (keyCount < RAYGUI_VALUEBOX_MAX_CHARS) + { + if (GuiGetTextWidth(textValue) < bounds.width) + { + int key = GetCharPressed(); + if ((key >= 48) && (key <= 57)) + { + textValue[keyCount] = (char)key; + keyCount++; + valueHasChanged = true; + } + } + } + + // Delete text + if (keyCount > 0) + { + if (IsKeyPressed(KEY_BACKSPACE)) + { + keyCount--; + textValue[keyCount] = '\0'; + valueHasChanged = true; + } + } + + if (valueHasChanged) *value = TextToInteger(textValue); + + // NOTE: We are not clamp values until user input finishes + //if (*value > maxValue) *value = maxValue; + //else if (*value < minValue) *value = minValue; + + if ((IsKeyPressed(KEY_ENTER) || IsKeyPressed(KEY_KP_ENTER)) || (!CheckCollisionPointRec(mousePoint, bounds) && IsMouseButtonPressed(MOUSE_LEFT_BUTTON))) + { + if (*value > maxValue) *value = maxValue; + else if (*value < minValue) *value = minValue; + + result = 1; + } + } + else + { + if (*value > maxValue) *value = maxValue; + else if (*value < minValue) *value = minValue; + + if (CheckCollisionPointRec(mousePoint, bounds)) + { + state = STATE_FOCUSED; + if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) result = 1; + } + } + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + Color baseColor = BLANK; + if (state == STATE_PRESSED) baseColor = GetColor(GuiGetStyle(VALUEBOX, BASE_COLOR_PRESSED)); + else if (state == STATE_DISABLED) baseColor = GetColor(GuiGetStyle(VALUEBOX, BASE_COLOR_DISABLED)); + + GuiDrawRectangle(bounds, GuiGetStyle(VALUEBOX, BORDER_WIDTH), GetColor(GuiGetStyle(VALUEBOX, BORDER + (state*3))), baseColor); + GuiDrawText(textValue, GetTextBounds(VALUEBOX, bounds), TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(VALUEBOX, TEXT + (state*3)))); + + // Draw cursor rectangle + if (editMode) + { + // NOTE: ValueBox internal text is always centered + Rectangle cursor = { bounds.x + GuiGetTextWidth(textValue)/2 + bounds.width/2 + 1, + bounds.y + GuiGetStyle(TEXTBOX, BORDER_WIDTH) + 2, + 2, bounds.height - GuiGetStyle(TEXTBOX, BORDER_WIDTH)*2 - 4 }; + if (cursor.height > bounds.height) cursor.height = bounds.height - GuiGetStyle(TEXTBOX, BORDER_WIDTH)*2; + GuiDrawRectangle(cursor, 0, BLANK, GetColor(GuiGetStyle(VALUEBOX, BORDER_COLOR_PRESSED))); + } + + // Draw text label if provided + GuiDrawText(text, textBounds, (GuiGetStyle(VALUEBOX, TEXT_ALIGNMENT) == TEXT_ALIGN_RIGHT)? TEXT_ALIGN_LEFT : TEXT_ALIGN_RIGHT, GetColor(GuiGetStyle(LABEL, TEXT + (state*3)))); + //-------------------------------------------------------------------- + + return result; +} + +// Floating point Value Box control, updates input val_str with numbers +// NOTE: Requires static variables: frameCounter +int GuiValueBoxFloat(Rectangle bounds, const char *text, char *textValue, float *value, bool editMode) +{ + #if !defined(RAYGUI_VALUEBOX_MAX_CHARS) + #define RAYGUI_VALUEBOX_MAX_CHARS 32 + #endif + + int result = 0; + GuiState state = guiState; + + //char textValue[RAYGUI_VALUEBOX_MAX_CHARS + 1] = "\0"; + //snprintf(textValue, sizeof(textValue), "%2.2f", *value); + + Rectangle textBounds = { 0 }; + if (text != NULL) + { + textBounds.width = (float)GuiGetTextWidth(text) + 2; + textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE); + textBounds.x = bounds.x + bounds.width + GuiGetStyle(VALUEBOX, TEXT_PADDING); + textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2; + if (GuiGetStyle(VALUEBOX, TEXT_ALIGNMENT) == TEXT_ALIGN_LEFT) textBounds.x = bounds.x - textBounds.width - GuiGetStyle(VALUEBOX, TEXT_PADDING); + } + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode) + { + Vector2 mousePoint = GetMousePosition(); + + bool valueHasChanged = false; + + if (editMode) + { + state = STATE_PRESSED; + + int keyCount = (int)strlen(textValue); + + // Add or remove minus symbol + if (IsKeyPressed(KEY_MINUS)) + { + if (textValue[0] == '-') + { + for (int i = 0; i < keyCount; i++) + { + textValue[i] = textValue[i + 1]; + } + keyCount--; + valueHasChanged = true; + } + else if (keyCount < RAYGUI_VALUEBOX_MAX_CHARS - 1) { + if (keyCount == 0) { + textValue[0] = '0'; + textValue[1] = '\0'; + keyCount++; + } + for (int i = keyCount; i > -1; i--) + { + textValue[i + 1] = textValue[i]; + } + textValue[0] = '-'; + keyCount++; + valueHasChanged = true; + } + } + + // Only allow keys in range [48..57] + if (keyCount < RAYGUI_VALUEBOX_MAX_CHARS) + { + if (GuiGetTextWidth(textValue) < bounds.width) + { + int key = GetCharPressed(); + if (((key >= 48) && (key <= 57)) || + (key == '.') || + ((keyCount == 0) && (key == '+')) || // NOTE: Sign can only be in first position + ((keyCount == 0) && (key == '-'))) + { + textValue[keyCount] = (char)key; + keyCount++; + + valueHasChanged = true; + } + } + } + + // Pressed backspace + if (IsKeyPressed(KEY_BACKSPACE)) + { + if (keyCount > 0) + { + keyCount--; + textValue[keyCount] = '\0'; + valueHasChanged = true; + } + } + + if (valueHasChanged) *value = TextToFloat(textValue); + + if ((IsKeyPressed(KEY_ENTER) || IsKeyPressed(KEY_KP_ENTER)) || (!CheckCollisionPointRec(mousePoint, bounds) && IsMouseButtonPressed(MOUSE_LEFT_BUTTON))) result = 1; + } + else + { + if (CheckCollisionPointRec(mousePoint, bounds)) + { + state = STATE_FOCUSED; + if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) result = 1; + } + } + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + Color baseColor = BLANK; + if (state == STATE_PRESSED) baseColor = GetColor(GuiGetStyle(VALUEBOX, BASE_COLOR_PRESSED)); + else if (state == STATE_DISABLED) baseColor = GetColor(GuiGetStyle(VALUEBOX, BASE_COLOR_DISABLED)); + + GuiDrawRectangle(bounds, GuiGetStyle(VALUEBOX, BORDER_WIDTH), GetColor(GuiGetStyle(VALUEBOX, BORDER + (state*3))), baseColor); + GuiDrawText(textValue, GetTextBounds(VALUEBOX, bounds), TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(VALUEBOX, TEXT + (state*3)))); + + // Draw cursor + if (editMode) + { + // NOTE: ValueBox internal text is always centered + Rectangle cursor = {bounds.x + GuiGetTextWidth(textValue)/2 + bounds.width/2 + 1, + bounds.y + 2*GuiGetStyle(VALUEBOX, BORDER_WIDTH), 4, + bounds.height - 4*GuiGetStyle(VALUEBOX, BORDER_WIDTH)}; + GuiDrawRectangle(cursor, 0, BLANK, GetColor(GuiGetStyle(VALUEBOX, BORDER_COLOR_PRESSED))); + } + + // Draw text label if provided + GuiDrawText(text, textBounds, + (GuiGetStyle(VALUEBOX, TEXT_ALIGNMENT) == TEXT_ALIGN_RIGHT)? TEXT_ALIGN_LEFT : TEXT_ALIGN_RIGHT, + GetColor(GuiGetStyle(LABEL, TEXT + (state*3)))); + //-------------------------------------------------------------------- + + return result; +} + +// Slider control with pro parameters +// NOTE: Other GuiSlider*() controls use this one +int GuiSlider(Rectangle bounds, const char *textLeft, const char *textRight, float *value, float minValue, float maxValue) +{ + int result = 0; + GuiState state = guiState; + + float temp = (maxValue - minValue)/2.0f; + if (value == NULL) value = &temp; + float oldValue = *value; + + int sliderWidth = GuiGetStyle(SLIDER, SLIDER_WIDTH); + + Rectangle slider = { bounds.x, bounds.y + GuiGetStyle(SLIDER, BORDER_WIDTH) + GuiGetStyle(SLIDER, SLIDER_PADDING), + 0, bounds.height - 2*GuiGetStyle(SLIDER, BORDER_WIDTH) - 2*GuiGetStyle(SLIDER, SLIDER_PADDING) }; + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked) + { + Vector2 mousePoint = GetMousePosition(); + + if (guiControlExclusiveMode) // Allows to keep dragging outside of bounds + { + if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) + { + if (CHECK_BOUNDS_ID(bounds, guiControlExclusiveRec)) + { + state = STATE_PRESSED; + // Get equivalent value and slider position from mousePosition.x + *value = (maxValue - minValue)*((mousePoint.x - bounds.x - sliderWidth/2)/(bounds.width - sliderWidth)) + minValue; + } + } + else + { + guiControlExclusiveMode = false; + guiControlExclusiveRec = RAYGUI_CLITERAL(Rectangle){ 0, 0, 0, 0 }; + } + } + else if (CheckCollisionPointRec(mousePoint, bounds)) + { + if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) + { + state = STATE_PRESSED; + guiControlExclusiveMode = true; + guiControlExclusiveRec = bounds; // Store bounds as an identifier when dragging starts + + if (!CheckCollisionPointRec(mousePoint, slider)) + { + // Get equivalent value and slider position from mousePosition.x + *value = (maxValue - minValue)*((mousePoint.x - bounds.x - sliderWidth/2)/(bounds.width - sliderWidth)) + minValue; + } + } + else state = STATE_FOCUSED; + } + + if (*value > maxValue) *value = maxValue; + else if (*value < minValue) *value = minValue; + } + + // Control value change check + if (oldValue == *value) result = 0; + else result = 1; + + // Slider bar limits check + float sliderValue = (((*value - minValue)/(maxValue - minValue))*(bounds.width - sliderWidth - 2*GuiGetStyle(SLIDER, BORDER_WIDTH))); + if (sliderWidth > 0) // Slider + { + slider.x += sliderValue; + slider.width = (float)sliderWidth; + if (slider.x <= (bounds.x + GuiGetStyle(SLIDER, BORDER_WIDTH))) slider.x = bounds.x + GuiGetStyle(SLIDER, BORDER_WIDTH); + else if ((slider.x + slider.width) >= (bounds.x + bounds.width)) slider.x = bounds.x + bounds.width - slider.width - GuiGetStyle(SLIDER, BORDER_WIDTH); + } + else if (sliderWidth == 0) // SliderBar + { + slider.x += GuiGetStyle(SLIDER, BORDER_WIDTH); + slider.width = sliderValue; + if (slider.width > bounds.width) slider.width = bounds.width - 2*GuiGetStyle(SLIDER, BORDER_WIDTH); + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + GuiDrawRectangle(bounds, GuiGetStyle(SLIDER, BORDER_WIDTH), GetColor(GuiGetStyle(SLIDER, BORDER + (state*3))), GetColor(GuiGetStyle(SLIDER, (state != STATE_DISABLED)? BASE_COLOR_NORMAL : BASE_COLOR_DISABLED))); + + // Draw slider internal bar (depends on state) + if (state == STATE_NORMAL) GuiDrawRectangle(slider, 0, BLANK, GetColor(GuiGetStyle(SLIDER, BASE_COLOR_PRESSED))); + else if (state == STATE_FOCUSED) GuiDrawRectangle(slider, 0, BLANK, GetColor(GuiGetStyle(SLIDER, TEXT_COLOR_FOCUSED))); + else if (state == STATE_PRESSED) GuiDrawRectangle(slider, 0, BLANK, GetColor(GuiGetStyle(SLIDER, TEXT_COLOR_PRESSED))); + else if (state == STATE_DISABLED) GuiDrawRectangle(slider, 0, BLANK, GetColor(GuiGetStyle(SLIDER, TEXT_COLOR_DISABLED))); + + // Draw left/right text if provided + if (textLeft != NULL) + { + Rectangle textBounds = { 0 }; + textBounds.width = (float)GuiGetTextWidth(textLeft); + textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE); + textBounds.x = bounds.x - textBounds.width - GuiGetStyle(SLIDER, TEXT_PADDING); + textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2; + + GuiDrawText(textLeft, textBounds, TEXT_ALIGN_RIGHT, GetColor(GuiGetStyle(LABEL, TEXT + (state*3)))); + } + + if (textRight != NULL) + { + Rectangle textBounds = { 0 }; + textBounds.width = (float)GuiGetTextWidth(textRight); + textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE); + textBounds.x = bounds.x + bounds.width + GuiGetStyle(SLIDER, TEXT_PADDING); + textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2; + + GuiDrawText(textRight, textBounds, TEXT_ALIGN_LEFT, GetColor(GuiGetStyle(LABEL, TEXT + (state*3)))); + } + //-------------------------------------------------------------------- + + return result; +} + +// Slider Bar control extended, returns selected value +int GuiSliderBar(Rectangle bounds, const char *textLeft, const char *textRight, float *value, float minValue, float maxValue) +{ + int result = 0; + int preSliderWidth = GuiGetStyle(SLIDER, SLIDER_WIDTH); + GuiSetStyle(SLIDER, SLIDER_WIDTH, 0); + result = GuiSlider(bounds, textLeft, textRight, value, minValue, maxValue); + GuiSetStyle(SLIDER, SLIDER_WIDTH, preSliderWidth); + + return result; +} + +// Progress Bar control extended, shows current progress value +int GuiProgressBar(Rectangle bounds, const char *textLeft, const char *textRight, float *value, float minValue, float maxValue) +{ + int result = 0; + GuiState state = guiState; + + float temp = (maxValue - minValue)/2.0f; + if (value == NULL) value = &temp; + + // Progress bar + Rectangle progress = { bounds.x + GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), + bounds.y + GuiGetStyle(PROGRESSBAR, BORDER_WIDTH) + GuiGetStyle(PROGRESSBAR, PROGRESS_PADDING), 0, + bounds.height - GuiGetStyle(PROGRESSBAR, BORDER_WIDTH) - 2*GuiGetStyle(PROGRESSBAR, PROGRESS_PADDING) -1 }; + + // Update control + //-------------------------------------------------------------------- + if (*value > maxValue) *value = maxValue; + + // WARNING: Working with floats could lead to rounding issues + if ((state != STATE_DISABLED)) progress.width = ((float)*value/(maxValue - minValue))*(bounds.width - 2*GuiGetStyle(PROGRESSBAR, BORDER_WIDTH)); + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + if (state == STATE_DISABLED) + { + GuiDrawRectangle(bounds, GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), GetColor(GuiGetStyle(PROGRESSBAR, BORDER + (state*3))), BLANK); + } + else + { + if (*value > minValue) + { + // Draw progress bar with colored border, more visual + GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y, (int)progress.width + (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH) }, 0, BLANK, GetColor(GuiGetStyle(PROGRESSBAR, BORDER_COLOR_FOCUSED))); + GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y + 1, (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), bounds.height - 2 }, 0, BLANK, GetColor(GuiGetStyle(PROGRESSBAR, BORDER_COLOR_FOCUSED))); + GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y + bounds.height - 1, (int)progress.width + (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH) }, 0, BLANK, GetColor(GuiGetStyle(PROGRESSBAR, BORDER_COLOR_FOCUSED))); + } + else GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x, bounds.y, (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), bounds.height+GuiGetStyle(PROGRESSBAR, BORDER_WIDTH)-1 }, 0, BLANK, GetColor(GuiGetStyle(PROGRESSBAR, BORDER_COLOR_NORMAL))); + + if (*value >= maxValue) GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x + progress.width + (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), bounds.y, (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), bounds.height+GuiGetStyle(PROGRESSBAR, BORDER_WIDTH)-1}, 0, BLANK, GetColor(GuiGetStyle(PROGRESSBAR, BORDER_COLOR_FOCUSED))); + else + { + // Draw borders not yet reached by value + GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x + (int)progress.width + (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), bounds.y, bounds.width - (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH) - (int)progress.width - 1, (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH) }, 0, BLANK, GetColor(GuiGetStyle(PROGRESSBAR, BORDER_COLOR_NORMAL))); + GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x + (int)progress.width + (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), bounds.y + bounds.height - 1, bounds.width - (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH) - (int)progress.width - 1, (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH) }, 0, BLANK, GetColor(GuiGetStyle(PROGRESSBAR, BORDER_COLOR_NORMAL))); + GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ bounds.x + bounds.width - (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), bounds.y, (float)GuiGetStyle(PROGRESSBAR, BORDER_WIDTH), bounds.height+GuiGetStyle(PROGRESSBAR, BORDER_WIDTH)-1 }, 0, BLANK, GetColor(GuiGetStyle(PROGRESSBAR, BORDER_COLOR_NORMAL))); + } + + // Draw slider internal progress bar (depends on state) + GuiDrawRectangle(progress, 0, BLANK, GetColor(GuiGetStyle(PROGRESSBAR, BASE_COLOR_PRESSED))); + } + + // Draw left/right text if provided + if (textLeft != NULL) + { + Rectangle textBounds = { 0 }; + textBounds.width = (float)GuiGetTextWidth(textLeft); + textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE); + textBounds.x = bounds.x - textBounds.width - GuiGetStyle(PROGRESSBAR, TEXT_PADDING); + textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2; + + GuiDrawText(textLeft, textBounds, TEXT_ALIGN_RIGHT, GetColor(GuiGetStyle(LABEL, TEXT + (state*3)))); + } + + if (textRight != NULL) + { + Rectangle textBounds = { 0 }; + textBounds.width = (float)GuiGetTextWidth(textRight); + textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE); + textBounds.x = bounds.x + bounds.width + GuiGetStyle(PROGRESSBAR, TEXT_PADDING); + textBounds.y = bounds.y + bounds.height/2 - GuiGetStyle(DEFAULT, TEXT_SIZE)/2; + + GuiDrawText(textRight, textBounds, TEXT_ALIGN_LEFT, GetColor(GuiGetStyle(LABEL, TEXT + (state*3)))); + } + //-------------------------------------------------------------------- + + return result; +} + +// Status Bar control +int GuiStatusBar(Rectangle bounds, const char *text) +{ + int result = 0; + GuiState state = guiState; + + // Draw control + //-------------------------------------------------------------------- + GuiDrawRectangle(bounds, GuiGetStyle(STATUSBAR, BORDER_WIDTH), GetColor(GuiGetStyle(STATUSBAR, BORDER + (state*3))), GetColor(GuiGetStyle(STATUSBAR, BASE + (state*3)))); + GuiDrawText(text, GetTextBounds(STATUSBAR, bounds), GuiGetStyle(STATUSBAR, TEXT_ALIGNMENT), GetColor(GuiGetStyle(STATUSBAR, TEXT + (state*3)))); + //-------------------------------------------------------------------- + + return result; +} + +// Dummy rectangle control, intended for placeholding +int GuiDummyRec(Rectangle bounds, const char *text) +{ + int result = 0; + GuiState state = guiState; + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode) + { + Vector2 mousePoint = GetMousePosition(); + + // Check button state + if (CheckCollisionPointRec(mousePoint, bounds)) + { + if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) state = STATE_PRESSED; + else state = STATE_FOCUSED; + } + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + GuiDrawRectangle(bounds, 0, BLANK, GetColor(GuiGetStyle(DEFAULT, (state != STATE_DISABLED)? BASE_COLOR_NORMAL : BASE_COLOR_DISABLED))); + GuiDrawText(text, GetTextBounds(DEFAULT, bounds), TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(BUTTON, (state != STATE_DISABLED)? TEXT_COLOR_NORMAL : TEXT_COLOR_DISABLED))); + //------------------------------------------------------------------ + + return result; +} + +// List View control +int GuiListView(Rectangle bounds, const char *text, int *scrollIndex, int *active) +{ + int result = 0; + int itemCount = 0; + const char **items = NULL; + + if (text != NULL) items = GuiTextSplit(text, ';', &itemCount, NULL); + + result = GuiListViewEx(bounds, items, itemCount, scrollIndex, active, NULL); + + return result; +} + +// List View control with extended parameters +int GuiListViewEx(Rectangle bounds, const char **text, int count, int *scrollIndex, int *active, int *focus) +{ + int result = 0; + GuiState state = guiState; + + int itemFocused = (focus == NULL)? -1 : *focus; + int itemSelected = (active == NULL)? -1 : *active; + + // Check if we need a scroll bar + bool useScrollBar = false; + if ((GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) + GuiGetStyle(LISTVIEW, LIST_ITEMS_SPACING))*count > bounds.height) useScrollBar = true; + + // Define base item rectangle [0] + Rectangle itemBounds = { 0 }; + itemBounds.x = bounds.x + GuiGetStyle(LISTVIEW, LIST_ITEMS_SPACING); + itemBounds.y = bounds.y + GuiGetStyle(LISTVIEW, LIST_ITEMS_SPACING) + GuiGetStyle(DEFAULT, BORDER_WIDTH); + itemBounds.width = bounds.width - 2*GuiGetStyle(LISTVIEW, LIST_ITEMS_SPACING) - GuiGetStyle(DEFAULT, BORDER_WIDTH); + itemBounds.height = (float)GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT); + if (useScrollBar) itemBounds.width -= GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH); + + // Get items on the list + int visibleItems = (int)bounds.height/(GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) + GuiGetStyle(LISTVIEW, LIST_ITEMS_SPACING)); + if (visibleItems > count) visibleItems = count; + + int startIndex = (scrollIndex == NULL)? 0 : *scrollIndex; + if ((startIndex < 0) || (startIndex > (count - visibleItems))) startIndex = 0; + int endIndex = startIndex + visibleItems; + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode) + { + Vector2 mousePoint = GetMousePosition(); + + // Check mouse inside list view + if (CheckCollisionPointRec(mousePoint, bounds)) + { + state = STATE_FOCUSED; + + // Check focused and selected item + for (int i = 0; i < visibleItems; i++) + { + if (CheckCollisionPointRec(mousePoint, itemBounds)) + { + itemFocused = startIndex + i; + if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) + { + if (itemSelected == (startIndex + i)) itemSelected = -1; + else itemSelected = startIndex + i; + } + break; + } + + // Update item rectangle y position for next item + itemBounds.y += (GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) + GuiGetStyle(LISTVIEW, LIST_ITEMS_SPACING)); + } + + if (useScrollBar) + { + int wheelMove = (int)GetMouseWheelMove(); + startIndex -= wheelMove; + + if (startIndex < 0) startIndex = 0; + else if (startIndex > (count - visibleItems)) startIndex = count - visibleItems; + + endIndex = startIndex + visibleItems; + if (endIndex > count) endIndex = count; + } + } + else itemFocused = -1; + + // Reset item rectangle y to [0] + itemBounds.y = bounds.y + GuiGetStyle(LISTVIEW, LIST_ITEMS_SPACING) + GuiGetStyle(DEFAULT, BORDER_WIDTH); + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + GuiDrawRectangle(bounds, GuiGetStyle(LISTVIEW, BORDER_WIDTH), GetColor(GuiGetStyle(LISTVIEW, BORDER + state*3)), GetColor(GuiGetStyle(DEFAULT, BACKGROUND_COLOR))); // Draw background + + // Draw visible items + for (int i = 0; ((i < visibleItems) && (text != NULL)); i++) + { + if (GuiGetStyle(LISTVIEW, LIST_ITEMS_BORDER_NORMAL)) GuiDrawRectangle(itemBounds, GuiGetStyle(LISTVIEW, LIST_ITEMS_BORDER_WIDTH), GetColor(GuiGetStyle(LISTVIEW, BORDER_COLOR_NORMAL)), BLANK); + + if (state == STATE_DISABLED) + { + if ((startIndex + i) == itemSelected) GuiDrawRectangle(itemBounds, GuiGetStyle(LISTVIEW, LIST_ITEMS_BORDER_WIDTH), GetColor(GuiGetStyle(LISTVIEW, BORDER_COLOR_DISABLED)), GetColor(GuiGetStyle(LISTVIEW, BASE_COLOR_DISABLED))); + + GuiDrawText(text[startIndex + i], GetTextBounds(DEFAULT, itemBounds), GuiGetStyle(LISTVIEW, TEXT_ALIGNMENT), GetColor(GuiGetStyle(LISTVIEW, TEXT_COLOR_DISABLED))); + } + else + { + if (((startIndex + i) == itemSelected) && (active != NULL)) + { + // Draw item selected + GuiDrawRectangle(itemBounds, GuiGetStyle(LISTVIEW, LIST_ITEMS_BORDER_WIDTH), GetColor(GuiGetStyle(LISTVIEW, BORDER_COLOR_PRESSED)), GetColor(GuiGetStyle(LISTVIEW, BASE_COLOR_PRESSED))); + GuiDrawText(text[startIndex + i], GetTextBounds(DEFAULT, itemBounds), GuiGetStyle(LISTVIEW, TEXT_ALIGNMENT), GetColor(GuiGetStyle(LISTVIEW, TEXT_COLOR_PRESSED))); + } + else if (((startIndex + i) == itemFocused)) // && (focus != NULL)) // NOTE: We want items focused, despite not returned! + { + // Draw item focused + GuiDrawRectangle(itemBounds, GuiGetStyle(LISTVIEW, LIST_ITEMS_BORDER_WIDTH), GetColor(GuiGetStyle(LISTVIEW, BORDER_COLOR_FOCUSED)), GetColor(GuiGetStyle(LISTVIEW, BASE_COLOR_FOCUSED))); + GuiDrawText(text[startIndex + i], GetTextBounds(DEFAULT, itemBounds), GuiGetStyle(LISTVIEW, TEXT_ALIGNMENT), GetColor(GuiGetStyle(LISTVIEW, TEXT_COLOR_FOCUSED))); + } + else + { + // Draw item normal (no rectangle) + GuiDrawText(text[startIndex + i], GetTextBounds(DEFAULT, itemBounds), GuiGetStyle(LISTVIEW, TEXT_ALIGNMENT), GetColor(GuiGetStyle(LISTVIEW, TEXT_COLOR_NORMAL))); + } + } + + // Update item rectangle y position for next item + itemBounds.y += (GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) + GuiGetStyle(LISTVIEW, LIST_ITEMS_SPACING)); + } + + if (useScrollBar) + { + Rectangle scrollBarBounds = { + bounds.x + bounds.width - GuiGetStyle(LISTVIEW, BORDER_WIDTH) - GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH), + bounds.y + GuiGetStyle(LISTVIEW, BORDER_WIDTH), (float)GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH), + bounds.height - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) + }; + + // Calculate percentage of visible items and apply same percentage to scrollbar + float percentVisible = (float)(endIndex - startIndex)/count; + float sliderSize = bounds.height*percentVisible; + + int prevSliderSize = GuiGetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE); // Save default slider size + int prevScrollSpeed = GuiGetStyle(SCROLLBAR, SCROLL_SPEED); // Save default scroll speed + GuiSetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE, (int)sliderSize); // Change slider size + GuiSetStyle(SCROLLBAR, SCROLL_SPEED, count - visibleItems); // Change scroll speed + + startIndex = GuiScrollBar(scrollBarBounds, startIndex, 0, count - visibleItems); + + GuiSetStyle(SCROLLBAR, SCROLL_SPEED, prevScrollSpeed); // Reset scroll speed to default + GuiSetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE, prevSliderSize); // Reset slider size to default + } + //-------------------------------------------------------------------- + + if (active != NULL) *active = itemSelected; + if (focus != NULL) *focus = itemFocused; + if (scrollIndex != NULL) *scrollIndex = startIndex; + + return result; +} + +// Color Panel control - Color (RGBA) variant +int GuiColorPanel(Rectangle bounds, const char *text, Color *color) +{ + int result = 0; + + Vector3 vcolor = { (float)color->r/255.0f, (float)color->g/255.0f, (float)color->b/255.0f }; + Vector3 hsv = ConvertRGBtoHSV(vcolor); + Vector3 prevHsv = hsv; // workaround to see if GuiColorPanelHSV modifies the hsv + + GuiColorPanelHSV(bounds, text, &hsv); + + // Check if the hsv was changed, only then change the color + // This is required, because the Color->HSV->Color conversion has precision errors + // Thus the assignment from HSV to Color should only be made, if the HSV has a new user-entered value + // Otherwise GuiColorPanel would often modify it's color without user input + // TODO: GuiColorPanelHSV could return 1 if the slider was dragged, to simplify this check + if (hsv.x != prevHsv.x || hsv.y != prevHsv.y || hsv.z != prevHsv.z) + { + Vector3 rgb = ConvertHSVtoRGB(hsv); + + // NOTE: Vector3ToColor() only available on raylib 1.8.1 + *color = RAYGUI_CLITERAL(Color){ (unsigned char)(255.0f*rgb.x), + (unsigned char)(255.0f*rgb.y), + (unsigned char)(255.0f*rgb.z), + color->a }; + } + return result; +} + +// Color Bar Alpha control +// NOTE: Returns alpha value normalized [0..1] +int GuiColorBarAlpha(Rectangle bounds, const char *text, float *alpha) +{ + #if !defined(RAYGUI_COLORBARALPHA_CHECKED_SIZE) + #define RAYGUI_COLORBARALPHA_CHECKED_SIZE 10 + #endif + + int result = 0; + GuiState state = guiState; + Rectangle selector = { (float)bounds.x + (*alpha)*bounds.width - GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_HEIGHT)/2, + (float)bounds.y - GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_OVERFLOW), + (float)GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_HEIGHT), + (float)bounds.height + GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_OVERFLOW)*2 }; + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked) + { + Vector2 mousePoint = GetMousePosition(); + + if (guiControlExclusiveMode) // Allows to keep dragging outside of bounds + { + if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) + { + if (CHECK_BOUNDS_ID(bounds, guiControlExclusiveRec)) + { + state = STATE_PRESSED; + + *alpha = (mousePoint.x - bounds.x)/bounds.width; + if (*alpha <= 0.0f) *alpha = 0.0f; + if (*alpha >= 1.0f) *alpha = 1.0f; + } + } + else + { + guiControlExclusiveMode = false; + guiControlExclusiveRec = RAYGUI_CLITERAL(Rectangle){ 0, 0, 0, 0 }; + } + } + else if (CheckCollisionPointRec(mousePoint, bounds) || CheckCollisionPointRec(mousePoint, selector)) + { + if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) + { + state = STATE_PRESSED; + guiControlExclusiveMode = true; + guiControlExclusiveRec = bounds; // Store bounds as an identifier when dragging starts + + *alpha = (mousePoint.x - bounds.x)/bounds.width; + if (*alpha <= 0.0f) *alpha = 0.0f; + if (*alpha >= 1.0f) *alpha = 1.0f; + //selector.x = bounds.x + (int)(((alpha - 0)/(100 - 0))*(bounds.width - 2*GuiGetStyle(SLIDER, BORDER_WIDTH))) - selector.width/2; + } + else state = STATE_FOCUSED; + } + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + // Draw alpha bar: checked background + if (state != STATE_DISABLED) + { + int checksX = (int)bounds.width/RAYGUI_COLORBARALPHA_CHECKED_SIZE; + int checksY = (int)bounds.height/RAYGUI_COLORBARALPHA_CHECKED_SIZE; + + for (int x = 0; x < checksX; x++) + { + for (int y = 0; y < checksY; y++) + { + Rectangle check = { bounds.x + x*RAYGUI_COLORBARALPHA_CHECKED_SIZE, bounds.y + y*RAYGUI_COLORBARALPHA_CHECKED_SIZE, RAYGUI_COLORBARALPHA_CHECKED_SIZE, RAYGUI_COLORBARALPHA_CHECKED_SIZE }; + GuiDrawRectangle(check, 0, BLANK, ((x + y)%2)? Fade(GetColor(GuiGetStyle(COLORPICKER, BORDER_COLOR_DISABLED)), 0.4f) : Fade(GetColor(GuiGetStyle(COLORPICKER, BASE_COLOR_DISABLED)), 0.4f)); + } + } + + DrawRectangleGradientEx(bounds, RAYGUI_CLITERAL(Color){ 255, 255, 255, 0 }, RAYGUI_CLITERAL(Color){ 255, 255, 255, 0 }, Fade(RAYGUI_CLITERAL(Color){ 0, 0, 0, 255 }, guiAlpha), Fade(RAYGUI_CLITERAL(Color){ 0, 0, 0, 255 }, guiAlpha)); + } + else DrawRectangleGradientEx(bounds, Fade(GetColor(GuiGetStyle(COLORPICKER, BASE_COLOR_DISABLED)), 0.1f), Fade(GetColor(GuiGetStyle(COLORPICKER, BASE_COLOR_DISABLED)), 0.1f), Fade(GetColor(GuiGetStyle(COLORPICKER, BORDER_COLOR_DISABLED)), guiAlpha), Fade(GetColor(GuiGetStyle(COLORPICKER, BORDER_COLOR_DISABLED)), guiAlpha)); + + GuiDrawRectangle(bounds, GuiGetStyle(COLORPICKER, BORDER_WIDTH), GetColor(GuiGetStyle(COLORPICKER, BORDER + state*3)), BLANK); + + // Draw alpha bar: selector + GuiDrawRectangle(selector, 0, BLANK, GetColor(GuiGetStyle(COLORPICKER, BORDER + state*3))); + //-------------------------------------------------------------------- + + return result; +} + +// Color Bar Hue control +// Returns hue value normalized [0..1] +// NOTE: Other similar bars (for reference): +// Color GuiColorBarSat() [WHITE->color] +// Color GuiColorBarValue() [BLACK->color], HSV/HSL +// float GuiColorBarLuminance() [BLACK->WHITE] +int GuiColorBarHue(Rectangle bounds, const char *text, float *hue) +{ + int result = 0; + GuiState state = guiState; + Rectangle selector = { (float)bounds.x - GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_OVERFLOW), (float)bounds.y + (*hue)/360.0f*bounds.height - GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_HEIGHT)/2, (float)bounds.width + GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_OVERFLOW)*2, (float)GuiGetStyle(COLORPICKER, HUEBAR_SELECTOR_HEIGHT) }; + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked) + { + Vector2 mousePoint = GetMousePosition(); + + if (guiControlExclusiveMode) // Allows to keep dragging outside of bounds + { + if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) + { + if (CHECK_BOUNDS_ID(bounds, guiControlExclusiveRec)) + { + state = STATE_PRESSED; + + *hue = (mousePoint.y - bounds.y)*360/bounds.height; + if (*hue <= 0.0f) *hue = 0.0f; + if (*hue >= 359.0f) *hue = 359.0f; + } + } + else + { + guiControlExclusiveMode = false; + guiControlExclusiveRec = RAYGUI_CLITERAL(Rectangle){ 0, 0, 0, 0 }; + } + } + else if (CheckCollisionPointRec(mousePoint, bounds) || CheckCollisionPointRec(mousePoint, selector)) + { + if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) + { + state = STATE_PRESSED; + guiControlExclusiveMode = true; + guiControlExclusiveRec = bounds; // Store bounds as an identifier when dragging starts + + *hue = (mousePoint.y - bounds.y)*360/bounds.height; + if (*hue <= 0.0f) *hue = 0.0f; + if (*hue >= 359.0f) *hue = 359.0f; + + } + else state = STATE_FOCUSED; + + /*if (IsKeyDown(KEY_UP)) + { + hue -= 2.0f; + if (hue <= 0.0f) hue = 0.0f; + } + else if (IsKeyDown(KEY_DOWN)) + { + hue += 2.0f; + if (hue >= 360.0f) hue = 360.0f; + }*/ + } + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + if (state != STATE_DISABLED) + { + // Draw hue bar:color bars + // TODO: Use directly DrawRectangleGradientEx(bounds, color1, color2, color2, color1); + DrawRectangleGradientV((int)bounds.x, (int)(bounds.y), (int)bounds.width, (int)ceilf(bounds.height/6), Fade(RAYGUI_CLITERAL(Color){ 255, 0, 0, 255 }, guiAlpha), Fade(RAYGUI_CLITERAL(Color){ 255, 255, 0, 255 }, guiAlpha)); + DrawRectangleGradientV((int)bounds.x, (int)(bounds.y + bounds.height/6), (int)bounds.width, (int)ceilf(bounds.height/6), Fade(RAYGUI_CLITERAL(Color){ 255, 255, 0, 255 }, guiAlpha), Fade(RAYGUI_CLITERAL(Color){ 0, 255, 0, 255 }, guiAlpha)); + DrawRectangleGradientV((int)bounds.x, (int)(bounds.y + 2*(bounds.height/6)), (int)bounds.width, (int)ceilf(bounds.height/6), Fade(RAYGUI_CLITERAL(Color){ 0, 255, 0, 255 }, guiAlpha), Fade(RAYGUI_CLITERAL(Color){ 0, 255, 255, 255 }, guiAlpha)); + DrawRectangleGradientV((int)bounds.x, (int)(bounds.y + 3*(bounds.height/6)), (int)bounds.width, (int)ceilf(bounds.height/6), Fade(RAYGUI_CLITERAL(Color){ 0, 255, 255, 255 }, guiAlpha), Fade(RAYGUI_CLITERAL(Color){ 0, 0, 255, 255 }, guiAlpha)); + DrawRectangleGradientV((int)bounds.x, (int)(bounds.y + 4*(bounds.height/6)), (int)bounds.width, (int)ceilf(bounds.height/6), Fade(RAYGUI_CLITERAL(Color){ 0, 0, 255, 255 }, guiAlpha), Fade(RAYGUI_CLITERAL(Color){ 255, 0, 255, 255 }, guiAlpha)); + DrawRectangleGradientV((int)bounds.x, (int)(bounds.y + 5*(bounds.height/6)), (int)bounds.width, (int)(bounds.height/6), Fade(RAYGUI_CLITERAL(Color){ 255, 0, 255, 255 }, guiAlpha), Fade(RAYGUI_CLITERAL(Color){ 255, 0, 0, 255 }, guiAlpha)); + } + else DrawRectangleGradientV((int)bounds.x, (int)bounds.y, (int)bounds.width, (int)bounds.height, Fade(Fade(GetColor(GuiGetStyle(COLORPICKER, BASE_COLOR_DISABLED)), 0.1f), guiAlpha), Fade(GetColor(GuiGetStyle(COLORPICKER, BORDER_COLOR_DISABLED)), guiAlpha)); + + GuiDrawRectangle(bounds, GuiGetStyle(COLORPICKER, BORDER_WIDTH), GetColor(GuiGetStyle(COLORPICKER, BORDER + state*3)), BLANK); + + // Draw hue bar: selector + GuiDrawRectangle(selector, 0, BLANK, GetColor(GuiGetStyle(COLORPICKER, BORDER + state*3))); + //-------------------------------------------------------------------- + + return result; +} + +// Color Picker control +// NOTE: It's divided in multiple controls: +// Color GuiColorPanel(Rectangle bounds, Color color) +// float GuiColorBarAlpha(Rectangle bounds, float alpha) +// float GuiColorBarHue(Rectangle bounds, float value) +// NOTE: bounds define GuiColorPanel() size +// NOTE: this picker converts RGB to HSV, which can cause the Hue control to jump. If you have this problem, consider using the HSV variant instead +int GuiColorPicker(Rectangle bounds, const char *text, Color *color) +{ + int result = 0; + + Color temp = { 200, 0, 0, 255 }; + if (color == NULL) color = &temp; + + GuiColorPanel(bounds, NULL, color); + + Rectangle boundsHue = { (float)bounds.x + bounds.width + GuiGetStyle(COLORPICKER, HUEBAR_PADDING), (float)bounds.y, (float)GuiGetStyle(COLORPICKER, HUEBAR_WIDTH), (float)bounds.height }; + //Rectangle boundsAlpha = { bounds.x, bounds.y + bounds.height + GuiGetStyle(COLORPICKER, BARS_PADDING), bounds.width, GuiGetStyle(COLORPICKER, BARS_THICK) }; + + // NOTE: this conversion can cause low hue-resolution, if the r, g and b value are very similar, which causes the hue bar to shift around when only the GuiColorPanel is used + Vector3 hsv = ConvertRGBtoHSV(RAYGUI_CLITERAL(Vector3){ (*color).r/255.0f, (*color).g/255.0f, (*color).b/255.0f }); + + GuiColorBarHue(boundsHue, NULL, &hsv.x); + + //color.a = (unsigned char)(GuiColorBarAlpha(boundsAlpha, (float)color.a/255.0f)*255.0f); + Vector3 rgb = ConvertHSVtoRGB(hsv); + + *color = RAYGUI_CLITERAL(Color){ (unsigned char)roundf(rgb.x*255.0f), (unsigned char)roundf(rgb.y*255.0f), (unsigned char)roundf(rgb.z*255.0f), (*color).a }; + + return result; +} + +// Color Picker control that avoids conversion to RGB and back to HSV on each call, thus avoiding jittering +// The user can call ConvertHSVtoRGB() to convert *colorHsv value to RGB +// NOTE: It's divided in multiple controls: +// int GuiColorPanelHSV(Rectangle bounds, const char *text, Vector3 *colorHsv) +// int GuiColorBarAlpha(Rectangle bounds, const char *text, float *alpha) +// float GuiColorBarHue(Rectangle bounds, float value) +// NOTE: bounds define GuiColorPanelHSV() size +int GuiColorPickerHSV(Rectangle bounds, const char *text, Vector3 *colorHsv) +{ + int result = 0; + + Vector3 tempHsv = { 0 }; + + if (colorHsv == NULL) + { + const Vector3 tempColor = { 200.0f/255.0f, 0.0f, 0.0f }; + tempHsv = ConvertRGBtoHSV(tempColor); + colorHsv = &tempHsv; + } + + GuiColorPanelHSV(bounds, NULL, colorHsv); + + const Rectangle boundsHue = { (float)bounds.x + bounds.width + GuiGetStyle(COLORPICKER, HUEBAR_PADDING), (float)bounds.y, (float)GuiGetStyle(COLORPICKER, HUEBAR_WIDTH), (float)bounds.height }; + + GuiColorBarHue(boundsHue, NULL, &colorHsv->x); + + return result; +} + +// Color Panel control - HSV variant +int GuiColorPanelHSV(Rectangle bounds, const char *text, Vector3 *colorHsv) +{ + int result = 0; + GuiState state = guiState; + Vector2 pickerSelector = { 0 }; + + const Color colWhite = { 255, 255, 255, 255 }; + const Color colBlack = { 0, 0, 0, 255 }; + + pickerSelector.x = bounds.x + (float)colorHsv->y*bounds.width; // HSV: Saturation + pickerSelector.y = bounds.y + (1.0f - (float)colorHsv->z)*bounds.height; // HSV: Value + + Vector3 maxHue = { colorHsv->x, 1.0f, 1.0f }; + Vector3 rgbHue = ConvertHSVtoRGB(maxHue); + Color maxHueCol = { (unsigned char)(255.0f*rgbHue.x), + (unsigned char)(255.0f*rgbHue.y), + (unsigned char)(255.0f*rgbHue.z), 255 }; + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked) + { + Vector2 mousePoint = GetMousePosition(); + + if (guiControlExclusiveMode) // Allows to keep dragging outside of bounds + { + if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) + { + if (CHECK_BOUNDS_ID(bounds, guiControlExclusiveRec)) + { + pickerSelector = mousePoint; + + if (pickerSelector.x < bounds.x) pickerSelector.x = bounds.x; + if (pickerSelector.x > bounds.x + bounds.width) pickerSelector.x = bounds.x + bounds.width; + if (pickerSelector.y < bounds.y) pickerSelector.y = bounds.y; + if (pickerSelector.y > bounds.y + bounds.height) pickerSelector.y = bounds.y + bounds.height; + + // Calculate color from picker + Vector2 colorPick = { pickerSelector.x - bounds.x, pickerSelector.y - bounds.y }; + + colorPick.x /= (float)bounds.width; // Get normalized value on x + colorPick.y /= (float)bounds.height; // Get normalized value on y + + colorHsv->y = colorPick.x; + colorHsv->z = 1.0f - colorPick.y; + + } + } + else + { + guiControlExclusiveMode = false; + guiControlExclusiveRec = RAYGUI_CLITERAL(Rectangle){ 0, 0, 0, 0 }; + } + } + else if (CheckCollisionPointRec(mousePoint, bounds)) + { + if (IsMouseButtonDown(MOUSE_LEFT_BUTTON)) + { + state = STATE_PRESSED; + guiControlExclusiveMode = true; + guiControlExclusiveRec = bounds; + pickerSelector = mousePoint; + + // Calculate color from picker + Vector2 colorPick = { pickerSelector.x - bounds.x, pickerSelector.y - bounds.y }; + + colorPick.x /= (float)bounds.width; // Get normalized value on x + colorPick.y /= (float)bounds.height; // Get normalized value on y + + colorHsv->y = colorPick.x; + colorHsv->z = 1.0f - colorPick.y; + } + else state = STATE_FOCUSED; + } + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + if (state != STATE_DISABLED) + { + DrawRectangleGradientEx(bounds, Fade(colWhite, guiAlpha), Fade(colWhite, guiAlpha), Fade(maxHueCol, guiAlpha), Fade(maxHueCol, guiAlpha)); + DrawRectangleGradientEx(bounds, Fade(colBlack, 0), Fade(colBlack, guiAlpha), Fade(colBlack, guiAlpha), Fade(colBlack, 0)); + + // Draw color picker: selector + Rectangle selector = { pickerSelector.x - GuiGetStyle(COLORPICKER, COLOR_SELECTOR_SIZE)/2, pickerSelector.y - GuiGetStyle(COLORPICKER, COLOR_SELECTOR_SIZE)/2, (float)GuiGetStyle(COLORPICKER, COLOR_SELECTOR_SIZE), (float)GuiGetStyle(COLORPICKER, COLOR_SELECTOR_SIZE) }; + GuiDrawRectangle(selector, 0, BLANK, colWhite); + } + else + { + DrawRectangleGradientEx(bounds, Fade(Fade(GetColor(GuiGetStyle(COLORPICKER, BASE_COLOR_DISABLED)), 0.1f), guiAlpha), Fade(Fade(colBlack, 0.6f), guiAlpha), Fade(Fade(colBlack, 0.6f), guiAlpha), Fade(Fade(GetColor(GuiGetStyle(COLORPICKER, BORDER_COLOR_DISABLED)), 0.6f), guiAlpha)); + } + + GuiDrawRectangle(bounds, GuiGetStyle(COLORPICKER, BORDER_WIDTH), GetColor(GuiGetStyle(COLORPICKER, BORDER + state*3)), BLANK); + //-------------------------------------------------------------------- + + return result; +} + +// Message Box control +int GuiMessageBox(Rectangle bounds, const char *title, const char *message, const char *buttons) +{ + #if !defined(RAYGUI_MESSAGEBOX_BUTTON_HEIGHT) + #define RAYGUI_MESSAGEBOX_BUTTON_HEIGHT 24 + #endif + #if !defined(RAYGUI_MESSAGEBOX_BUTTON_PADDING) + #define RAYGUI_MESSAGEBOX_BUTTON_PADDING 12 + #endif + + int result = -1; // Returns clicked button from buttons list, 0 refers to closed window button + + int buttonCount = 0; + const char **buttonsText = GuiTextSplit(buttons, ';', &buttonCount, NULL); + Rectangle buttonBounds = { 0 }; + buttonBounds.x = bounds.x + RAYGUI_MESSAGEBOX_BUTTON_PADDING; + buttonBounds.y = bounds.y + bounds.height - RAYGUI_MESSAGEBOX_BUTTON_HEIGHT - RAYGUI_MESSAGEBOX_BUTTON_PADDING; + buttonBounds.width = (bounds.width - RAYGUI_MESSAGEBOX_BUTTON_PADDING*(buttonCount + 1))/buttonCount; + buttonBounds.height = RAYGUI_MESSAGEBOX_BUTTON_HEIGHT; + + //int textWidth = GuiGetTextWidth(message) + 2; + + Rectangle textBounds = { 0 }; + textBounds.x = bounds.x + RAYGUI_MESSAGEBOX_BUTTON_PADDING; + textBounds.y = bounds.y + RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT + RAYGUI_MESSAGEBOX_BUTTON_PADDING; + textBounds.width = bounds.width - RAYGUI_MESSAGEBOX_BUTTON_PADDING*2; + textBounds.height = bounds.height - RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT - 3*RAYGUI_MESSAGEBOX_BUTTON_PADDING - RAYGUI_MESSAGEBOX_BUTTON_HEIGHT; + + // Draw control + //-------------------------------------------------------------------- + if (GuiWindowBox(bounds, title)) result = 0; + + int prevTextAlignment = GuiGetStyle(LABEL, TEXT_ALIGNMENT); + GuiSetStyle(LABEL, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER); + GuiLabel(textBounds, message); + GuiSetStyle(LABEL, TEXT_ALIGNMENT, prevTextAlignment); + + prevTextAlignment = GuiGetStyle(BUTTON, TEXT_ALIGNMENT); + GuiSetStyle(BUTTON, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER); + + for (int i = 0; i < buttonCount; i++) + { + if (GuiButton(buttonBounds, buttonsText[i])) result = i + 1; + buttonBounds.x += (buttonBounds.width + RAYGUI_MESSAGEBOX_BUTTON_PADDING); + } + + GuiSetStyle(BUTTON, TEXT_ALIGNMENT, prevTextAlignment); + //-------------------------------------------------------------------- + + return result; +} + +// Text Input Box control, ask for text +int GuiTextInputBox(Rectangle bounds, const char *title, const char *message, const char *buttons, char *text, int textMaxSize, bool *secretViewActive) +{ + #if !defined(RAYGUI_TEXTINPUTBOX_BUTTON_HEIGHT) + #define RAYGUI_TEXTINPUTBOX_BUTTON_HEIGHT 24 + #endif + #if !defined(RAYGUI_TEXTINPUTBOX_BUTTON_PADDING) + #define RAYGUI_TEXTINPUTBOX_BUTTON_PADDING 12 + #endif + #if !defined(RAYGUI_TEXTINPUTBOX_HEIGHT) + #define RAYGUI_TEXTINPUTBOX_HEIGHT 26 + #endif + + // Used to enable text edit mode + // WARNING: No more than one GuiTextInputBox() should be open at the same time + static bool textEditMode = false; + + int result = -1; + + int buttonCount = 0; + const char **buttonsText = GuiTextSplit(buttons, ';', &buttonCount, NULL); + Rectangle buttonBounds = { 0 }; + buttonBounds.x = bounds.x + RAYGUI_TEXTINPUTBOX_BUTTON_PADDING; + buttonBounds.y = bounds.y + bounds.height - RAYGUI_TEXTINPUTBOX_BUTTON_HEIGHT - RAYGUI_TEXTINPUTBOX_BUTTON_PADDING; + buttonBounds.width = (bounds.width - RAYGUI_TEXTINPUTBOX_BUTTON_PADDING*(buttonCount + 1))/buttonCount; + buttonBounds.height = RAYGUI_TEXTINPUTBOX_BUTTON_HEIGHT; + + int messageInputHeight = (int)bounds.height - RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT - GuiGetStyle(STATUSBAR, BORDER_WIDTH) - RAYGUI_TEXTINPUTBOX_BUTTON_HEIGHT - 2*RAYGUI_TEXTINPUTBOX_BUTTON_PADDING; + + Rectangle textBounds = { 0 }; + if (message != NULL) + { + int textSize = GuiGetTextWidth(message) + 2; + + textBounds.x = bounds.x + bounds.width/2 - textSize/2; + textBounds.y = bounds.y + RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT + messageInputHeight/4 - (float)GuiGetStyle(DEFAULT, TEXT_SIZE)/2; + textBounds.width = (float)textSize; + textBounds.height = (float)GuiGetStyle(DEFAULT, TEXT_SIZE); + } + + Rectangle textBoxBounds = { 0 }; + textBoxBounds.x = bounds.x + RAYGUI_TEXTINPUTBOX_BUTTON_PADDING; + textBoxBounds.y = bounds.y + RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT - RAYGUI_TEXTINPUTBOX_HEIGHT/2; + if (message == NULL) textBoxBounds.y = bounds.y + 24 + RAYGUI_TEXTINPUTBOX_BUTTON_PADDING; + else textBoxBounds.y += (messageInputHeight/2 + messageInputHeight/4); + textBoxBounds.width = bounds.width - RAYGUI_TEXTINPUTBOX_BUTTON_PADDING*2; + textBoxBounds.height = RAYGUI_TEXTINPUTBOX_HEIGHT; + + // Draw control + //-------------------------------------------------------------------- + if (GuiWindowBox(bounds, title)) result = 0; + + // Draw message if available + if (message != NULL) + { + int prevTextAlignment = GuiGetStyle(LABEL, TEXT_ALIGNMENT); + GuiSetStyle(LABEL, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER); + GuiLabel(textBounds, message); + GuiSetStyle(LABEL, TEXT_ALIGNMENT, prevTextAlignment); + } + + if (secretViewActive != NULL) + { + static char stars[] = "****************"; + if (GuiTextBox(RAYGUI_CLITERAL(Rectangle){ textBoxBounds.x, textBoxBounds.y, textBoxBounds.width - 4 - RAYGUI_TEXTINPUTBOX_HEIGHT, textBoxBounds.height }, + ((*secretViewActive == 1) || textEditMode)? text : stars, textMaxSize, textEditMode)) textEditMode = !textEditMode; + + GuiToggle(RAYGUI_CLITERAL(Rectangle){ textBoxBounds.x + textBoxBounds.width - RAYGUI_TEXTINPUTBOX_HEIGHT, textBoxBounds.y, RAYGUI_TEXTINPUTBOX_HEIGHT, RAYGUI_TEXTINPUTBOX_HEIGHT }, (*secretViewActive == 1)? "#44#" : "#45#", secretViewActive); + } + else + { + if (GuiTextBox(textBoxBounds, text, textMaxSize, textEditMode)) textEditMode = !textEditMode; + } + + int prevBtnTextAlignment = GuiGetStyle(BUTTON, TEXT_ALIGNMENT); + GuiSetStyle(BUTTON, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER); + + for (int i = 0; i < buttonCount; i++) + { + if (GuiButton(buttonBounds, buttonsText[i])) result = i + 1; + buttonBounds.x += (buttonBounds.width + RAYGUI_MESSAGEBOX_BUTTON_PADDING); + } + + if (result >= 0) textEditMode = false; + + GuiSetStyle(BUTTON, TEXT_ALIGNMENT, prevBtnTextAlignment); + //-------------------------------------------------------------------- + + return result; // Result is the pressed button index +} + +// Grid control +// NOTE: Returns grid mouse-hover selected cell +// About drawing lines at subpixel spacing, simple put, not easy solution: +// https://stackoverflow.com/questions/4435450/2d-opengl-drawing-lines-that-dont-exactly-fit-pixel-raster +int GuiGrid(Rectangle bounds, const char *text, float spacing, int subdivs, Vector2 *mouseCell) +{ + // Grid lines alpha amount + #if !defined(RAYGUI_GRID_ALPHA) + #define RAYGUI_GRID_ALPHA 0.15f + #endif + + int result = 0; + GuiState state = guiState; + + Vector2 mousePoint = GetMousePosition(); + Vector2 currentMouseCell = { -1, -1 }; + + float spaceWidth = spacing/(float)subdivs; + int linesV = (int)(bounds.width/spaceWidth) + 1; + int linesH = (int)(bounds.height/spaceWidth) + 1; + + int color = GuiGetStyle(DEFAULT, LINE_COLOR); + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked && !guiControlExclusiveMode) + { + if (CheckCollisionPointRec(mousePoint, bounds)) + { + // NOTE: Cell values must be the upper left of the cell the mouse is in + currentMouseCell.x = floorf((mousePoint.x - bounds.x)/spacing); + currentMouseCell.y = floorf((mousePoint.y - bounds.y)/spacing); + } + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + if (state == STATE_DISABLED) color = GuiGetStyle(DEFAULT, BORDER_COLOR_DISABLED); + + if (subdivs > 0) + { + // Draw vertical grid lines + for (int i = 0; i < linesV; i++) + { + Rectangle lineV = { bounds.x + spacing*i/subdivs, bounds.y, 1, bounds.height + 1 }; + GuiDrawRectangle(lineV, 0, BLANK, ((i%subdivs) == 0)? GuiFade(GetColor(color), RAYGUI_GRID_ALPHA*4) : GuiFade(GetColor(color), RAYGUI_GRID_ALPHA)); + } + + // Draw horizontal grid lines + for (int i = 0; i < linesH; i++) + { + Rectangle lineH = { bounds.x, bounds.y + spacing*i/subdivs, bounds.width + 1, 1 }; + GuiDrawRectangle(lineH, 0, BLANK, ((i%subdivs) == 0)? GuiFade(GetColor(color), RAYGUI_GRID_ALPHA*4) : GuiFade(GetColor(color), RAYGUI_GRID_ALPHA)); + } + } + + if (mouseCell != NULL) *mouseCell = currentMouseCell; + return result; +} + +//---------------------------------------------------------------------------------- +// Tooltip management functions +// NOTE: Tooltips requires some global variables: tooltipPtr +//---------------------------------------------------------------------------------- +// Enable gui tooltips (global state) +void GuiEnableTooltip(void) { guiTooltip = true; } + +// Disable gui tooltips (global state) +void GuiDisableTooltip(void) { guiTooltip = false; } + +// Set tooltip string +void GuiSetTooltip(const char *tooltip) { guiTooltipPtr = tooltip; } + +//---------------------------------------------------------------------------------- +// Styles loading functions +//---------------------------------------------------------------------------------- + +// Load raygui style file (.rgs) +// NOTE: By default a binary file is expected, that file could contain a custom font, +// in that case, custom font image atlas is GRAY+ALPHA and pixel data can be compressed (DEFLATE) +void GuiLoadStyle(const char *fileName) +{ + #define MAX_LINE_BUFFER_SIZE 256 + + bool tryBinary = false; + if (!guiStyleLoaded) GuiLoadStyleDefault(); + + // Try reading the files as text file first + FILE *rgsFile = fopen(fileName, "rt"); + + if (rgsFile != NULL) + { + char buffer[MAX_LINE_BUFFER_SIZE] = { 0 }; + fgets(buffer, MAX_LINE_BUFFER_SIZE, rgsFile); + + if (buffer[0] == '#') + { + int controlId = 0; + int propertyId = 0; + unsigned int propertyValue = 0; + + while (!feof(rgsFile)) + { + switch (buffer[0]) + { + case 'p': + { + // Style property: p + + sscanf(buffer, "p %d %d 0x%x", &controlId, &propertyId, &propertyValue); + GuiSetStyle(controlId, propertyId, (int)propertyValue); + + } break; + case 'f': + { + // Style font: f + + int fontSize = 0; + char charmapFileName[256] = { 0 }; + char fontFileName[256] = { 0 }; + sscanf(buffer, "f %d %s %[^\r\n]s", &fontSize, charmapFileName, fontFileName); + + Font font = { 0 }; + int *codepoints = NULL; + int codepointCount = 0; + + if (charmapFileName[0] != '0') + { + // Load text data from file + // NOTE: Expected an UTF-8 array of codepoints, no separation + char *textData = LoadFileText(TextFormat("%s/%s", GetDirectoryPath(fileName), charmapFileName)); + codepoints = LoadCodepoints(textData, &codepointCount); + UnloadFileText(textData); + } + + if (fontFileName[0] != '\0') + { + // In case a font is already loaded and it is not default internal font, unload it + if (font.texture.id != GetFontDefault().texture.id) UnloadTexture(font.texture); + + if (codepointCount > 0) font = LoadFontEx(TextFormat("%s/%s", GetDirectoryPath(fileName), fontFileName), fontSize, codepoints, codepointCount); + else font = LoadFontEx(TextFormat("%s/%s", GetDirectoryPath(fileName), fontFileName), fontSize, NULL, 0); // Default to 95 standard codepoints + } + + // If font texture not properly loaded, revert to default font and size/spacing + if (font.texture.id == 0) + { + font = GetFontDefault(); + GuiSetStyle(DEFAULT, TEXT_SIZE, 10); + GuiSetStyle(DEFAULT, TEXT_SPACING, 1); + } + + UnloadCodepoints(codepoints); + + if ((font.texture.id > 0) && (font.glyphCount > 0)) GuiSetFont(font); + + } break; + default: break; + } + + fgets(buffer, MAX_LINE_BUFFER_SIZE, rgsFile); + } + } + else tryBinary = true; + + fclose(rgsFile); + } + + if (tryBinary) + { + rgsFile = fopen(fileName, "rb"); + + if (rgsFile != NULL) + { + fseek(rgsFile, 0, SEEK_END); + int fileDataSize = ftell(rgsFile); + fseek(rgsFile, 0, SEEK_SET); + + if (fileDataSize > 0) + { + unsigned char *fileData = (unsigned char *)RAYGUI_CALLOC(fileDataSize, sizeof(unsigned char)); + fread(fileData, sizeof(unsigned char), fileDataSize, rgsFile); + + GuiLoadStyleFromMemory(fileData, fileDataSize); + + RAYGUI_FREE(fileData); + } + + fclose(rgsFile); + } + } +} + +// Load style default over global style +void GuiLoadStyleDefault(void) +{ + // We set this variable first to avoid cyclic function calls + // when calling GuiSetStyle() and GuiGetStyle() + guiStyleLoaded = true; + + // Initialize default LIGHT style property values + // WARNING: Default value are applied to all controls on set but + // they can be overwritten later on for every custom control + GuiSetStyle(DEFAULT, BORDER_COLOR_NORMAL, 0x838383ff); + GuiSetStyle(DEFAULT, BASE_COLOR_NORMAL, 0xc9c9c9ff); + GuiSetStyle(DEFAULT, TEXT_COLOR_NORMAL, 0x686868ff); + GuiSetStyle(DEFAULT, BORDER_COLOR_FOCUSED, 0x5bb2d9ff); + GuiSetStyle(DEFAULT, BASE_COLOR_FOCUSED, 0xc9effeff); + GuiSetStyle(DEFAULT, TEXT_COLOR_FOCUSED, 0x6c9bbcff); + GuiSetStyle(DEFAULT, BORDER_COLOR_PRESSED, 0x0492c7ff); + GuiSetStyle(DEFAULT, BASE_COLOR_PRESSED, 0x97e8ffff); + GuiSetStyle(DEFAULT, TEXT_COLOR_PRESSED, 0x368bafff); + GuiSetStyle(DEFAULT, BORDER_COLOR_DISABLED, 0xb5c1c2ff); + GuiSetStyle(DEFAULT, BASE_COLOR_DISABLED, 0xe6e9e9ff); + GuiSetStyle(DEFAULT, TEXT_COLOR_DISABLED, 0xaeb7b8ff); + GuiSetStyle(DEFAULT, BORDER_WIDTH, 1); + GuiSetStyle(DEFAULT, TEXT_PADDING, 0); + GuiSetStyle(DEFAULT, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER); + + // Initialize default extended property values + // NOTE: By default, extended property values are initialized to 0 + GuiSetStyle(DEFAULT, TEXT_SIZE, 10); // DEFAULT, shared by all controls + GuiSetStyle(DEFAULT, TEXT_SPACING, 1); // DEFAULT, shared by all controls + GuiSetStyle(DEFAULT, LINE_COLOR, 0x90abb5ff); // DEFAULT specific property + GuiSetStyle(DEFAULT, BACKGROUND_COLOR, 0xf5f5f5ff); // DEFAULT specific property + GuiSetStyle(DEFAULT, TEXT_LINE_SPACING, 15); // DEFAULT, 15 pixels between lines + GuiSetStyle(DEFAULT, TEXT_ALIGNMENT_VERTICAL, TEXT_ALIGN_MIDDLE); // DEFAULT, text aligned vertically to middle of text-bounds + + // Initialize control-specific property values + // NOTE: Those properties are in default list but require specific values by control type + GuiSetStyle(LABEL, TEXT_ALIGNMENT, TEXT_ALIGN_LEFT); + GuiSetStyle(BUTTON, BORDER_WIDTH, 2); + GuiSetStyle(SLIDER, TEXT_PADDING, 4); + GuiSetStyle(PROGRESSBAR, TEXT_PADDING, 4); + GuiSetStyle(CHECKBOX, TEXT_PADDING, 4); + GuiSetStyle(CHECKBOX, TEXT_ALIGNMENT, TEXT_ALIGN_RIGHT); + GuiSetStyle(DROPDOWNBOX, TEXT_PADDING, 0); + GuiSetStyle(DROPDOWNBOX, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER); + GuiSetStyle(TEXTBOX, TEXT_PADDING, 4); + GuiSetStyle(TEXTBOX, TEXT_ALIGNMENT, TEXT_ALIGN_LEFT); + GuiSetStyle(VALUEBOX, TEXT_PADDING, 0); + GuiSetStyle(VALUEBOX, TEXT_ALIGNMENT, TEXT_ALIGN_LEFT); + GuiSetStyle(STATUSBAR, TEXT_PADDING, 8); + GuiSetStyle(STATUSBAR, TEXT_ALIGNMENT, TEXT_ALIGN_LEFT); + + // Initialize extended property values + // NOTE: By default, extended property values are initialized to 0 + GuiSetStyle(TOGGLE, GROUP_PADDING, 2); + GuiSetStyle(SLIDER, SLIDER_WIDTH, 16); + GuiSetStyle(SLIDER, SLIDER_PADDING, 1); + GuiSetStyle(PROGRESSBAR, PROGRESS_PADDING, 1); + GuiSetStyle(CHECKBOX, CHECK_PADDING, 1); + GuiSetStyle(COMBOBOX, COMBO_BUTTON_WIDTH, 32); + GuiSetStyle(COMBOBOX, COMBO_BUTTON_SPACING, 2); + GuiSetStyle(DROPDOWNBOX, ARROW_PADDING, 16); + GuiSetStyle(DROPDOWNBOX, DROPDOWN_ITEMS_SPACING, 2); + GuiSetStyle(VALUEBOX, SPINNER_BUTTON_WIDTH, 24); + GuiSetStyle(VALUEBOX, SPINNER_BUTTON_SPACING, 2); + GuiSetStyle(SCROLLBAR, BORDER_WIDTH, 0); + GuiSetStyle(SCROLLBAR, ARROWS_VISIBLE, 0); + GuiSetStyle(SCROLLBAR, ARROWS_SIZE, 6); + GuiSetStyle(SCROLLBAR, SCROLL_SLIDER_PADDING, 0); + GuiSetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE, 16); + GuiSetStyle(SCROLLBAR, SCROLL_PADDING, 0); + GuiSetStyle(SCROLLBAR, SCROLL_SPEED, 12); + GuiSetStyle(LISTVIEW, LIST_ITEMS_HEIGHT, 28); + GuiSetStyle(LISTVIEW, LIST_ITEMS_SPACING, 2); + GuiSetStyle(LISTVIEW, LIST_ITEMS_BORDER_WIDTH, 1); + GuiSetStyle(LISTVIEW, SCROLLBAR_WIDTH, 12); + GuiSetStyle(LISTVIEW, SCROLLBAR_SIDE, SCROLLBAR_RIGHT_SIDE); + GuiSetStyle(COLORPICKER, COLOR_SELECTOR_SIZE, 8); + GuiSetStyle(COLORPICKER, HUEBAR_WIDTH, 16); + GuiSetStyle(COLORPICKER, HUEBAR_PADDING, 8); + GuiSetStyle(COLORPICKER, HUEBAR_SELECTOR_HEIGHT, 8); + GuiSetStyle(COLORPICKER, HUEBAR_SELECTOR_OVERFLOW, 2); + + if (guiFont.texture.id != GetFontDefault().texture.id) + { + // Unload previous font texture + UnloadTexture(guiFont.texture); + RAYGUI_FREE(guiFont.recs); + RAYGUI_FREE(guiFont.glyphs); + guiFont.recs = NULL; + guiFont.glyphs = NULL; + + // Setup default raylib font + guiFont = GetFontDefault(); + + // NOTE: Default raylib font character 95 is a white square + Rectangle whiteChar = guiFont.recs[95]; + + // NOTE: We set up a 1px padding on char rectangle to avoid pixel bleeding on MSAA filtering + SetShapesTexture(guiFont.texture, RAYGUI_CLITERAL(Rectangle){ whiteChar.x + 1, whiteChar.y + 1, whiteChar.width - 2, whiteChar.height - 2 }); + } +} + +// Get text with icon id prepended +// NOTE: Useful to add icons by name id (enum) instead of +// a number that can change between ricon versions +const char *GuiIconText(int iconId, const char *text) +{ +#if defined(RAYGUI_NO_ICONS) + return NULL; +#else + static char buffer[1024] = { 0 }; + static char iconBuffer[16] = { 0 }; + + if (text != NULL) + { + memset(buffer, 0, 1024); + snprintf(buffer, 1024, "#%03i#", iconId); + + for (int i = 5; i < 1024; i++) + { + buffer[i] = text[i - 5]; + if (text[i - 5] == '\0') break; + } + + return buffer; + } + else + { + snprintf(iconBuffer, 16, "#%03i#", iconId); + + return iconBuffer; + } +#endif +} + +#if !defined(RAYGUI_NO_ICONS) +// Get full icons data pointer +unsigned int *GuiGetIcons(void) { return guiIconsPtr; } + +// Load raygui icons file (.rgi) +// NOTE: In case nameIds are required, they can be requested with loadIconsName, +// they are returned as a guiIconsName[iconCount][RAYGUI_ICON_MAX_NAME_LENGTH], +// WARNING: guiIconsName[]][] memory should be manually freed! +char **GuiLoadIcons(const char *fileName, bool loadIconsName) +{ + // Style File Structure (.rgi) + // ------------------------------------------------------ + // Offset | Size | Type | Description + // ------------------------------------------------------ + // 0 | 4 | char | Signature: "rGI " + // 4 | 2 | short | Version: 100 + // 6 | 2 | short | reserved + + // 8 | 2 | short | Num icons (N) + // 10 | 2 | short | Icons size (Options: 16, 32, 64) (S) + + // Icons name id (32 bytes per name id) + // foreach (icon) + // { + // 12+32*i | 32 | char | Icon NameId + // } + + // Icons data: One bit per pixel, stored as unsigned int array (depends on icon size) + // S*S pixels/32bit per unsigned int = K unsigned int per icon + // foreach (icon) + // { + // ... | K | unsigned int | Icon Data + // } + + FILE *rgiFile = fopen(fileName, "rb"); + + char **guiIconsName = NULL; + + if (rgiFile != NULL) + { + char signature[5] = { 0 }; + short version = 0; + short reserved = 0; + short iconCount = 0; + short iconSize = 0; + + fread(signature, 1, 4, rgiFile); + fread(&version, sizeof(short), 1, rgiFile); + fread(&reserved, sizeof(short), 1, rgiFile); + fread(&iconCount, sizeof(short), 1, rgiFile); + fread(&iconSize, sizeof(short), 1, rgiFile); + + if ((signature[0] == 'r') && + (signature[1] == 'G') && + (signature[2] == 'I') && + (signature[3] == ' ')) + { + if (loadIconsName) + { + guiIconsName = (char **)RAYGUI_CALLOC(iconCount, sizeof(char *)); + for (int i = 0; i < iconCount; i++) + { + guiIconsName[i] = (char *)RAYGUI_CALLOC(RAYGUI_ICON_MAX_NAME_LENGTH, sizeof(char)); + fread(guiIconsName[i], 1, RAYGUI_ICON_MAX_NAME_LENGTH, rgiFile); + } + } + else fseek(rgiFile, iconCount*RAYGUI_ICON_MAX_NAME_LENGTH, SEEK_CUR); + + // Read icons data directly over internal icons array + fread(guiIconsPtr, sizeof(unsigned int), (int)iconCount*((int)iconSize*(int)iconSize/32), rgiFile); + } + + fclose(rgiFile); + } + + return guiIconsName; +} + +// Load icons from memory +// WARNING: Binary files only +char **GuiLoadIconsFromMemory(const unsigned char *fileData, int dataSize, bool loadIconsName) +{ + unsigned char *fileDataPtr = (unsigned char *)fileData; + char **guiIconsName = NULL; + + char signature[5] = { 0 }; + short version = 0; + short reserved = 0; + short iconCount = 0; + short iconSize = 0; + + memcpy(signature, fileDataPtr, 4); + memcpy(&version, fileDataPtr + 4, sizeof(short)); + memcpy(&reserved, fileDataPtr + 4 + 2, sizeof(short)); + memcpy(&iconCount, fileDataPtr + 4 + 2 + 2, sizeof(short)); + memcpy(&iconSize, fileDataPtr + 4 + 2 + 2 + 2, sizeof(short)); + fileDataPtr += 12; + + if ((signature[0] == 'r') && + (signature[1] == 'G') && + (signature[2] == 'I') && + (signature[3] == ' ')) + { + if (loadIconsName) + { + guiIconsName = (char **)RAYGUI_CALLOC(iconCount, sizeof(char *)); + for (int i = 0; i < iconCount; i++) + { + guiIconsName[i] = (char *)RAYGUI_CALLOC(RAYGUI_ICON_MAX_NAME_LENGTH, sizeof(char)); + memcpy(guiIconsName[i], fileDataPtr, RAYGUI_ICON_MAX_NAME_LENGTH); + fileDataPtr += RAYGUI_ICON_MAX_NAME_LENGTH; + } + } + else + { + // Skip icon name data if not required + fileDataPtr += iconCount*RAYGUI_ICON_MAX_NAME_LENGTH; + } + + int iconDataSize = iconCount*((int)iconSize*(int)iconSize/32)*(int)sizeof(unsigned int); + guiIconsPtr = (unsigned int *)RAYGUI_CALLOC(iconDataSize, 1); + + memcpy(guiIconsPtr, fileDataPtr, iconDataSize); + } + + return guiIconsName; +} + +// Draw selected icon using rectangles pixel-by-pixel +void GuiDrawIcon(int iconId, int posX, int posY, int pixelSize, Color color) +{ + #define BIT_CHECK(a,b) ((a) & (1u<<(b))) + + for (int i = 0, y = 0; i < RAYGUI_ICON_SIZE*RAYGUI_ICON_SIZE/32; i++) + { + for (int k = 0; k < 32; k++) + { + if (BIT_CHECK(guiIconsPtr[iconId*RAYGUI_ICON_DATA_ELEMENTS + i], k)) + { + #if !defined(RAYGUI_STANDALONE) + GuiDrawRectangle(RAYGUI_CLITERAL(Rectangle){ (float)posX + (k%RAYGUI_ICON_SIZE)*pixelSize, (float)posY + y*pixelSize, (float)pixelSize, (float)pixelSize }, 0, BLANK, color); + #endif + } + + if ((k == 15) || (k == 31)) y++; + } + } +} + +// Set icon drawing size +void GuiSetIconScale(int scale) +{ + if (scale >= 1) guiIconScale = scale; +} + +// Get text width considering gui style and icon size (if required) +int GuiGetTextWidth(const char *text) +{ + #if !defined(ICON_TEXT_PADDING) + #define ICON_TEXT_PADDING 4 + #endif + + Vector2 textSize = { 0 }; + int textIconOffset = 0; + + if ((text != NULL) && (text[0] != '\0')) + { + if (text[0] == '#') + { + for (int i = 1; (i < 5) && (text[i] != '\0'); i++) + { + if (text[i] == '#') + { + textIconOffset = i; + break; + } + } + } + + text += textIconOffset; + + // Make sure guiFont is set, GuiGetStyle() initializes it lazynessly + float fontSize = (float)GuiGetStyle(DEFAULT, TEXT_SIZE); + + // Custom MeasureText() implementation + if ((guiFont.texture.id > 0) && (text != NULL)) + { + // Get size in bytes of text, considering end of line and line break + int size = 0; + for (int i = 0; i < MAX_LINE_BUFFER_SIZE; i++) + { + if ((text[i] != '\0') && (text[i] != '\n')) size++; + else break; + } + + float scaleFactor = fontSize/(float)guiFont.baseSize; + textSize.y = (float)guiFont.baseSize*scaleFactor; + float glyphWidth = 0.0f; + + for (int i = 0, codepointSize = 0; i < size; i += codepointSize) + { + int codepoint = GetCodepointNext(&text[i], &codepointSize); + int codepointIndex = GetGlyphIndex(guiFont, codepoint); + + if (guiFont.glyphs[codepointIndex].advanceX == 0) glyphWidth = ((float)guiFont.recs[codepointIndex].width*scaleFactor); + else glyphWidth = ((float)guiFont.glyphs[codepointIndex].advanceX*scaleFactor); + + textSize.x += (glyphWidth + (float)GuiGetStyle(DEFAULT, TEXT_SPACING)); + } + } + + if (textIconOffset > 0) textSize.x += (RAYGUI_ICON_SIZE + ICON_TEXT_PADDING); + } + + return (int)textSize.x; +} + +#endif // !RAYGUI_NO_ICONS + +//---------------------------------------------------------------------------------- +// Module Internal Functions Definition +//---------------------------------------------------------------------------------- +// Load style from memory +// WARNING: Binary files only +static void GuiLoadStyleFromMemory(const unsigned char *fileData, int dataSize) +{ + unsigned char *fileDataPtr = (unsigned char *)fileData; + + char signature[5] = { 0 }; + short version = 0; + short reserved = 0; + int propertyCount = 0; + + memcpy(signature, fileDataPtr, 4); + memcpy(&version, fileDataPtr + 4, sizeof(short)); + memcpy(&reserved, fileDataPtr + 4 + 2, sizeof(short)); + memcpy(&propertyCount, fileDataPtr + 4 + 2 + 2, sizeof(int)); + fileDataPtr += 12; + + if ((signature[0] == 'r') && + (signature[1] == 'G') && + (signature[2] == 'S') && + (signature[3] == ' ')) + { + short controlId = 0; + short propertyId = 0; + unsigned int propertyValue = 0; + + for (int i = 0; i < propertyCount; i++) + { + memcpy(&controlId, fileDataPtr, sizeof(short)); + memcpy(&propertyId, fileDataPtr + 2, sizeof(short)); + memcpy(&propertyValue, fileDataPtr + 2 + 2, sizeof(unsigned int)); + fileDataPtr += 8; + + if (controlId == 0) // DEFAULT control + { + // If a DEFAULT property is loaded, it is propagated to all controls + // NOTE: All DEFAULT properties should be defined first in the file + GuiSetStyle(0, (int)propertyId, propertyValue); + + if (propertyId < RAYGUI_MAX_PROPS_BASE) for (int j = 1; j < RAYGUI_MAX_CONTROLS; j++) GuiSetStyle(j, (int)propertyId, propertyValue); + } + else GuiSetStyle((int)controlId, (int)propertyId, propertyValue); + } + + // Font loading is highly dependant on raylib API to load font data and image + +#if !defined(RAYGUI_STANDALONE) + // Load custom font if available + int fontDataSize = 0; + memcpy(&fontDataSize, fileDataPtr, sizeof(int)); + fileDataPtr += 4; + + if (fontDataSize > 0) + { + Font font = { 0 }; + int fontType = 0; // 0-Normal, 1-SDF + + memcpy(&font.baseSize, fileDataPtr, sizeof(int)); + memcpy(&font.glyphCount, fileDataPtr + 4, sizeof(int)); + memcpy(&fontType, fileDataPtr + 4 + 4, sizeof(int)); + fileDataPtr += 12; + + // Load font white rectangle + Rectangle fontWhiteRec = { 0 }; + memcpy(&fontWhiteRec, fileDataPtr, sizeof(Rectangle)); + fileDataPtr += 16; + + // Load font image parameters + int fontImageUncompSize = 0; + int fontImageCompSize = 0; + memcpy(&fontImageUncompSize, fileDataPtr, sizeof(int)); + memcpy(&fontImageCompSize, fileDataPtr + 4, sizeof(int)); + fileDataPtr += 8; + + Image imFont = { 0 }; + imFont.mipmaps = 1; + memcpy(&imFont.width, fileDataPtr, sizeof(int)); + memcpy(&imFont.height, fileDataPtr + 4, sizeof(int)); + memcpy(&imFont.format, fileDataPtr + 4 + 4, sizeof(int)); + fileDataPtr += 12; + + if ((fontImageCompSize > 0) && (fontImageCompSize != fontImageUncompSize)) + { + // Compressed font atlas image data (DEFLATE), it requires DecompressData() + int dataUncompSize = 0; + unsigned char *compData = (unsigned char *)RAYGUI_CALLOC(fontImageCompSize, sizeof(unsigned char)); + memcpy(compData, fileDataPtr, fontImageCompSize); + fileDataPtr += fontImageCompSize; + + imFont.data = DecompressData(compData, fontImageCompSize, &dataUncompSize); + + // Security check, dataUncompSize must match the provided fontImageUncompSize + if (dataUncompSize != fontImageUncompSize) RAYGUI_LOG("WARNING: Uncompressed font atlas image data could be corrupted"); + + RAYGUI_FREE(compData); + } + else + { + // Font atlas image data is not compressed + imFont.data = (unsigned char *)RAYGUI_CALLOC(fontImageUncompSize, sizeof(unsigned char)); + memcpy(imFont.data, fileDataPtr, fontImageUncompSize); + fileDataPtr += fontImageUncompSize; + } + + if (font.texture.id != GetFontDefault().texture.id) UnloadTexture(font.texture); + font.texture = LoadTextureFromImage(imFont); + + RAYGUI_FREE(imFont.data); + + // Validate font atlas texture was loaded correctly + if (font.texture.id != 0) + { + // Load font recs data + int recsDataSize = font.glyphCount*sizeof(Rectangle); + int recsDataCompressedSize = 0; + + // WARNING: Version 400 adds the compression size parameter + if (version >= 400) + { + // RGS files version 400 support compressed recs data + memcpy(&recsDataCompressedSize, fileDataPtr, sizeof(int)); + fileDataPtr += sizeof(int); + } + + if ((recsDataCompressedSize > 0) && (recsDataCompressedSize != recsDataSize)) + { + // Recs data is compressed, uncompress it + unsigned char *recsDataCompressed = (unsigned char *)RAYGUI_CALLOC(recsDataCompressedSize, sizeof(unsigned char)); + + memcpy(recsDataCompressed, fileDataPtr, recsDataCompressedSize); + fileDataPtr += recsDataCompressedSize; + + int recsDataUncompSize = 0; + font.recs = (Rectangle *)DecompressData(recsDataCompressed, recsDataCompressedSize, &recsDataUncompSize); + + // Security check, data uncompressed size must match the expected original data size + if (recsDataUncompSize != recsDataSize) RAYGUI_LOG("WARNING: Uncompressed font recs data could be corrupted"); + + RAYGUI_FREE(recsDataCompressed); + } + else + { + // Recs data is uncompressed + font.recs = (Rectangle *)RAYGUI_CALLOC(font.glyphCount, sizeof(Rectangle)); + for (int i = 0; i < font.glyphCount; i++) + { + memcpy(&font.recs[i], fileDataPtr, sizeof(Rectangle)); + fileDataPtr += sizeof(Rectangle); + } + } + + // Load font glyphs info data + int glyphsDataSize = font.glyphCount*16; // 16 bytes data per glyph + int glyphsDataCompressedSize = 0; + + // WARNING: Version 400 adds the compression size parameter + if (version >= 400) + { + // RGS files version 400 support compressed glyphs data + memcpy(&glyphsDataCompressedSize, fileDataPtr, sizeof(int)); + fileDataPtr += sizeof(int); + } + + // Allocate required glyphs space to fill with data + font.glyphs = (GlyphInfo *)RAYGUI_CALLOC(font.glyphCount, sizeof(GlyphInfo)); + + if ((glyphsDataCompressedSize > 0) && (glyphsDataCompressedSize != glyphsDataSize)) + { + // Glyphs data is compressed, uncompress it + unsigned char *glypsDataCompressed = (unsigned char *)RAYGUI_CALLOC(glyphsDataCompressedSize, sizeof(unsigned char)); + + memcpy(glypsDataCompressed, fileDataPtr, glyphsDataCompressedSize); + fileDataPtr += glyphsDataCompressedSize; + + int glyphsDataUncompSize = 0; + unsigned char *glyphsDataUncomp = DecompressData(glypsDataCompressed, glyphsDataCompressedSize, &glyphsDataUncompSize); + + // Security check, data uncompressed size must match the expected original data size + if (glyphsDataUncompSize != glyphsDataSize) RAYGUI_LOG("WARNING: Uncompressed font glyphs data could be corrupted"); + + unsigned char *glyphsDataUncompPtr = glyphsDataUncomp; + + for (int i = 0; i < font.glyphCount; i++) + { + memcpy(&font.glyphs[i].value, glyphsDataUncompPtr, sizeof(int)); + memcpy(&font.glyphs[i].offsetX, glyphsDataUncompPtr + 4, sizeof(int)); + memcpy(&font.glyphs[i].offsetY, glyphsDataUncompPtr + 8, sizeof(int)); + memcpy(&font.glyphs[i].advanceX, glyphsDataUncompPtr + 12, sizeof(int)); + glyphsDataUncompPtr += 16; + } + + RAYGUI_FREE(glypsDataCompressed); + RAYGUI_FREE(glyphsDataUncomp); + } + else + { + // Glyphs data is uncompressed + for (int i = 0; i < font.glyphCount; i++) + { + memcpy(&font.glyphs[i].value, fileDataPtr, sizeof(int)); + memcpy(&font.glyphs[i].offsetX, fileDataPtr + 4, sizeof(int)); + memcpy(&font.glyphs[i].offsetY, fileDataPtr + 8, sizeof(int)); + memcpy(&font.glyphs[i].advanceX, fileDataPtr + 12, sizeof(int)); + fileDataPtr += 16; + } + } + } + else font = GetFontDefault(); // Fallback in case of errors loading font atlas texture + + GuiSetFont(font); + + // Set font texture source rectangle to be used as white texture to draw shapes + // NOTE: It makes possible to draw shapes and text (full UI) in a single draw call + if ((fontWhiteRec.x > 0) && + (fontWhiteRec.y > 0) && + (fontWhiteRec.width > 0) && + (fontWhiteRec.height > 0)) SetShapesTexture(font.texture, fontWhiteRec); + } +#endif + } +} + +// Get text bounds considering control bounds +static Rectangle GetTextBounds(int control, Rectangle bounds) +{ + Rectangle textBounds = bounds; + + textBounds.x = bounds.x + GuiGetStyle(control, BORDER_WIDTH); + textBounds.y = bounds.y + GuiGetStyle(control, BORDER_WIDTH) + GuiGetStyle(control, TEXT_PADDING); + textBounds.width = bounds.width - 2*GuiGetStyle(control, BORDER_WIDTH) - 2*GuiGetStyle(control, TEXT_PADDING); + textBounds.height = bounds.height - 2*GuiGetStyle(control, BORDER_WIDTH) - 2*GuiGetStyle(control, TEXT_PADDING); // NOTE: Text is processed line per line! + + // Depending on control, TEXT_PADDING and TEXT_ALIGNMENT properties could affect the text-bounds + switch (control) + { + case COMBOBOX: + case DROPDOWNBOX: + case LISTVIEW: + // TODO: Special cases (no label): COMBOBOX, DROPDOWNBOX, LISTVIEW + case SLIDER: + case CHECKBOX: + case VALUEBOX: + case CONTROL11: + // TODO: More special cases (label on side): SLIDER, CHECKBOX, VALUEBOX, SPINNER + default: + { + // TODO: WARNING: TEXT_ALIGNMENT is already considered in GuiDrawText() + if (GuiGetStyle(control, TEXT_ALIGNMENT) == TEXT_ALIGN_RIGHT) textBounds.x -= GuiGetStyle(control, TEXT_PADDING); + else textBounds.x += GuiGetStyle(control, TEXT_PADDING); + } + break; + } + + return textBounds; +} + +// Get text icon if provided and move text cursor +// NOTE: We support up to 999 values for iconId +static const char *GetTextIcon(const char *text, int *iconId) +{ +#if !defined(RAYGUI_NO_ICONS) + *iconId = -1; + if (text[0] == '#') // Maybe we have an icon! + { + char iconValue[4] = { 0 }; // Maximum length for icon value: 3 digits + '\0' + + int pos = 1; + while ((pos < 4) && (text[pos] >= '0') && (text[pos] <= '9')) + { + iconValue[pos - 1] = text[pos]; + pos++; + } + + if (text[pos] == '#') + { + *iconId = TextToInteger(iconValue); + + // Move text pointer after icon + // WARNING: If only icon provided, it could point to EOL character: '\0' + if (*iconId >= 0) text += (pos + 1); + } + } +#endif + + return text; +} + +// Get text divided into lines (by line-breaks '\n') +// WARNING: It returns pointers to new lines but it does not add NULL ('\0') terminator! +static const char **GetTextLines(const char *text, int *count) +{ + #define RAYGUI_MAX_TEXT_LINES 128 + + static const char *lines[RAYGUI_MAX_TEXT_LINES] = { 0 }; + for (int i = 0; i < RAYGUI_MAX_TEXT_LINES; i++) lines[i] = NULL; // Init NULL pointers to substrings + + int textSize = (int)strlen(text); + + lines[0] = text; + *count = 1; + + for (int i = 0, k = 0; (i < textSize) && (*count < RAYGUI_MAX_TEXT_LINES); i++) + { + if (text[i] == '\n') + { + k++; + lines[k] = &text[i + 1]; // WARNING: next value is valid? + *count += 1; + } + } + + return lines; +} + +// Get text width to next space for provided string +static float GetNextSpaceWidth(const char *text, int *nextSpaceIndex) +{ + float width = 0; + int codepointByteCount = 0; + int codepoint = 0; + int index = 0; + float glyphWidth = 0; + float scaleFactor = (float)GuiGetStyle(DEFAULT, TEXT_SIZE)/guiFont.baseSize; + + for (int i = 0; text[i] != '\0'; i++) + { + if (text[i] != ' ') + { + codepoint = GetCodepoint(&text[i], &codepointByteCount); + index = GetGlyphIndex(guiFont, codepoint); + glyphWidth = (guiFont.glyphs[index].advanceX == 0)? guiFont.recs[index].width*scaleFactor : guiFont.glyphs[index].advanceX*scaleFactor; + width += (glyphWidth + (float)GuiGetStyle(DEFAULT, TEXT_SPACING)); + } + else + { + *nextSpaceIndex = i; + break; + } + } + + return width; +} + +// Gui draw text using default font +static void GuiDrawText(const char *text, Rectangle textBounds, int alignment, Color tint) +{ + #define TEXT_VALIGN_PIXEL_OFFSET(h) ((int)h%2) // Vertical alignment for pixel perfect + + #if !defined(ICON_TEXT_PADDING) + #define ICON_TEXT_PADDING 4 + #endif + + if ((text == NULL) || (text[0] == '\0')) return; // Security check + + // PROCEDURE: + // - Text is processed line per line + // - For every line, horizontal alignment is defined + // - For all text, vertical alignment is defined (multiline text only) + // - For every line, wordwrap mode is checked (useful for GuitextBox(), read-only) + + // Get text lines (using '\n' as delimiter) to be processed individually + // WARNING: We can't use GuiTextSplit() function because it can be already used + // before the GuiDrawText() call and its buffer is static, it would be overriden :( + int lineCount = 0; + const char **lines = GetTextLines(text, &lineCount); + + // Text style variables + //int alignment = GuiGetStyle(DEFAULT, TEXT_ALIGNMENT); + int alignmentVertical = GuiGetStyle(DEFAULT, TEXT_ALIGNMENT_VERTICAL); + int wrapMode = GuiGetStyle(DEFAULT, TEXT_WRAP_MODE); // Wrap-mode only available in read-only mode, no for text editing + + // TODO: WARNING: This totalHeight is not valid for vertical alignment in case of word-wrap + float totalHeight = (float)(lineCount*GuiGetStyle(DEFAULT, TEXT_SIZE) + (lineCount - 1)*GuiGetStyle(DEFAULT, TEXT_SIZE)/2); + float posOffsetY = 0.0f; + + for (int i = 0; i < lineCount; i++) + { + int iconId = 0; + lines[i] = GetTextIcon(lines[i], &iconId); // Check text for icon and move cursor + + // Get text position depending on alignment and iconId + //--------------------------------------------------------------------------------- + Vector2 textBoundsPosition = { textBounds.x, textBounds.y }; + float textBoundsWidthOffset = 0.0f; + + // NOTE: We get text size after icon has been processed + // WARNING: GuiGetTextWidth() also processes text icon to get width! -> Really needed? + int textSizeX = GuiGetTextWidth(lines[i]); + + // If text requires an icon, add size to measure + if (iconId >= 0) + { + textSizeX += RAYGUI_ICON_SIZE*guiIconScale; + + // WARNING: If only icon provided, text could be pointing to EOF character: '\0' +#if !defined(RAYGUI_NO_ICONS) + if ((lines[i] != NULL) && (lines[i][0] != '\0')) textSizeX += ICON_TEXT_PADDING; +#endif + } + + // Check guiTextAlign global variables + switch (alignment) + { + case TEXT_ALIGN_LEFT: textBoundsPosition.x = textBounds.x; break; + case TEXT_ALIGN_CENTER: textBoundsPosition.x = textBounds.x + textBounds.width/2 - textSizeX/2; break; + case TEXT_ALIGN_RIGHT: textBoundsPosition.x = textBounds.x + textBounds.width - textSizeX; break; + default: break; + } + + if (textSizeX > textBounds.width && (lines[i] != NULL) && (lines[i][0] != '\0')) textBoundsPosition.x = textBounds.x; + + switch (alignmentVertical) + { + // Only valid in case of wordWrap = 0; + case TEXT_ALIGN_TOP: textBoundsPosition.y = textBounds.y + posOffsetY; break; + case TEXT_ALIGN_MIDDLE: textBoundsPosition.y = textBounds.y + posOffsetY + textBounds.height/2 - totalHeight/2 + TEXT_VALIGN_PIXEL_OFFSET(textBounds.height); break; + case TEXT_ALIGN_BOTTOM: textBoundsPosition.y = textBounds.y + posOffsetY + textBounds.height - totalHeight + TEXT_VALIGN_PIXEL_OFFSET(textBounds.height); break; + default: break; + } + + // NOTE: Make sure we get pixel-perfect coordinates, + // In case of decimals we got weird text positioning + textBoundsPosition.x = (float)((int)textBoundsPosition.x); + textBoundsPosition.y = (float)((int)textBoundsPosition.y); + //--------------------------------------------------------------------------------- + + // Draw text (with icon if available) + //--------------------------------------------------------------------------------- +#if !defined(RAYGUI_NO_ICONS) + if (iconId >= 0) + { + // NOTE: We consider icon height, probably different than text size + GuiDrawIcon(iconId, (int)textBoundsPosition.x, (int)(textBounds.y + textBounds.height/2 - RAYGUI_ICON_SIZE*guiIconScale/2 + TEXT_VALIGN_PIXEL_OFFSET(textBounds.height)), guiIconScale, tint); + textBoundsPosition.x += (float)(RAYGUI_ICON_SIZE*guiIconScale + ICON_TEXT_PADDING); + textBoundsWidthOffset = (float)(RAYGUI_ICON_SIZE*guiIconScale + ICON_TEXT_PADDING); + } +#endif + // Get size in bytes of text, + // considering end of line and line break + int lineSize = 0; + for (int c = 0; (lines[i][c] != '\0') && (lines[i][c] != '\n') && (lines[i][c] != '\r'); c++, lineSize++){ } + float scaleFactor = (float)GuiGetStyle(DEFAULT, TEXT_SIZE)/guiFont.baseSize; + + int lastSpaceIndex = 0; + bool tempWrapCharMode = false; + + int textOffsetY = 0; + float textOffsetX = 0.0f; + float glyphWidth = 0; + + int ellipsisWidth = GuiGetTextWidth("..."); + bool textOverflow = false; + for (int c = 0, codepointSize = 0; c < lineSize; c += codepointSize) + { + int codepoint = GetCodepointNext(&lines[i][c], &codepointSize); + int index = GetGlyphIndex(guiFont, codepoint); + + // NOTE: Normally we exit the decoding sequence as soon as a bad byte is found (and return 0x3f) + // but we need to draw all of the bad bytes using the '?' symbol moving one byte + if (codepoint == 0x3f) codepointSize = 1; // TODO: Review not recognized codepoints size + + // Get glyph width to check if it goes out of bounds + if (guiFont.glyphs[index].advanceX == 0) glyphWidth = ((float)guiFont.recs[index].width*scaleFactor); + else glyphWidth = (float)guiFont.glyphs[index].advanceX*scaleFactor; + + // Wrap mode text measuring, to validate if + // it can be drawn or a new line is required + if (wrapMode == TEXT_WRAP_CHAR) + { + // Jump to next line if current character reach end of the box limits + if ((textOffsetX + glyphWidth) > textBounds.width - textBoundsWidthOffset) + { + textOffsetX = 0.0f; + textOffsetY += GuiGetStyle(DEFAULT, TEXT_LINE_SPACING); + + if (tempWrapCharMode) // Wrap at char level when too long words + { + wrapMode = TEXT_WRAP_WORD; + tempWrapCharMode = false; + } + } + } + else if (wrapMode == TEXT_WRAP_WORD) + { + if (codepoint == 32) lastSpaceIndex = c; + + // Get width to next space in line + int nextSpaceIndex = 0; + float nextSpaceWidth = GetNextSpaceWidth(lines[i] + c, &nextSpaceIndex); + + int nextSpaceIndex2 = 0; + float nextWordSize = GetNextSpaceWidth(lines[i] + lastSpaceIndex + 1, &nextSpaceIndex2); + + if (nextWordSize > textBounds.width - textBoundsWidthOffset) + { + // Considering the case the next word is longer than bounds + tempWrapCharMode = true; + wrapMode = TEXT_WRAP_CHAR; + } + else if ((textOffsetX + nextSpaceWidth) > textBounds.width - textBoundsWidthOffset) + { + textOffsetX = 0.0f; + textOffsetY += GuiGetStyle(DEFAULT, TEXT_LINE_SPACING); + } + } + + if (codepoint == '\n') break; // WARNING: Lines are already processed manually, no need to keep drawing after this codepoint + else + { + // TODO: There are multiple types of spaces in Unicode, + // maybe it's a good idea to add support for more: http://jkorpela.fi/chars/spaces.html + if ((codepoint != ' ') && (codepoint != '\t')) // Do not draw codepoints with no glyph + { + if (wrapMode == TEXT_WRAP_NONE) + { + // Draw only required text glyphs fitting the textBounds.width + if (textSizeX > textBounds.width) + { + if (textOffsetX <= (textBounds.width - glyphWidth - textBoundsWidthOffset - ellipsisWidth)) + { + DrawTextCodepoint(guiFont, codepoint, RAYGUI_CLITERAL(Vector2){ textBoundsPosition.x + textOffsetX, textBoundsPosition.y + textOffsetY }, (float)GuiGetStyle(DEFAULT, TEXT_SIZE), GuiFade(tint, guiAlpha)); + } + else if (!textOverflow) + { + textOverflow = true; + + for (int j = 0; j < ellipsisWidth; j += ellipsisWidth/3) + { + DrawTextCodepoint(guiFont, '.', RAYGUI_CLITERAL(Vector2){ textBoundsPosition.x + textOffsetX + j, textBoundsPosition.y + textOffsetY }, (float)GuiGetStyle(DEFAULT, TEXT_SIZE), GuiFade(tint, guiAlpha)); + } + } + } + else + { + DrawTextCodepoint(guiFont, codepoint, RAYGUI_CLITERAL(Vector2){ textBoundsPosition.x + textOffsetX, textBoundsPosition.y + textOffsetY }, (float)GuiGetStyle(DEFAULT, TEXT_SIZE), GuiFade(tint, guiAlpha)); + } + } + else if ((wrapMode == TEXT_WRAP_CHAR) || (wrapMode == TEXT_WRAP_WORD)) + { + // Draw only glyphs inside the bounds + if ((textBoundsPosition.y + textOffsetY) <= (textBounds.y + textBounds.height - GuiGetStyle(DEFAULT, TEXT_SIZE))) + { + DrawTextCodepoint(guiFont, codepoint, RAYGUI_CLITERAL(Vector2){ textBoundsPosition.x + textOffsetX, textBoundsPosition.y + textOffsetY }, (float)GuiGetStyle(DEFAULT, TEXT_SIZE), GuiFade(tint, guiAlpha)); + } + } + } + + if (guiFont.glyphs[index].advanceX == 0) textOffsetX += ((float)guiFont.recs[index].width*scaleFactor + (float)GuiGetStyle(DEFAULT, TEXT_SPACING)); + else textOffsetX += ((float)guiFont.glyphs[index].advanceX*scaleFactor + (float)GuiGetStyle(DEFAULT, TEXT_SPACING)); + } + } + + if (wrapMode == TEXT_WRAP_NONE) posOffsetY += (float)GuiGetStyle(DEFAULT, TEXT_LINE_SPACING); + else if ((wrapMode == TEXT_WRAP_CHAR) || (wrapMode == TEXT_WRAP_WORD)) posOffsetY += (textOffsetY + (float)GuiGetStyle(DEFAULT, TEXT_LINE_SPACING)); + //--------------------------------------------------------------------------------- + } + +#if defined(RAYGUI_DEBUG_TEXT_BOUNDS) + GuiDrawRectangle(textBounds, 0, WHITE, Fade(BLUE, 0.4f)); +#endif +} + +// Gui draw rectangle using default raygui plain style with borders +static void GuiDrawRectangle(Rectangle rec, int borderWidth, Color borderColor, Color color) +{ + if (color.a > 0) + { + // Draw rectangle filled with color + DrawRectangle((int)rec.x, (int)rec.y, (int)rec.width, (int)rec.height, GuiFade(color, guiAlpha)); + } + + if (borderWidth > 0) + { + // Draw rectangle border lines with color + DrawRectangle((int)rec.x, (int)rec.y, (int)rec.width, borderWidth, GuiFade(borderColor, guiAlpha)); + DrawRectangle((int)rec.x, (int)rec.y + borderWidth, borderWidth, (int)rec.height - 2*borderWidth, GuiFade(borderColor, guiAlpha)); + DrawRectangle((int)rec.x + (int)rec.width - borderWidth, (int)rec.y + borderWidth, borderWidth, (int)rec.height - 2*borderWidth, GuiFade(borderColor, guiAlpha)); + DrawRectangle((int)rec.x, (int)rec.y + (int)rec.height - borderWidth, (int)rec.width, borderWidth, GuiFade(borderColor, guiAlpha)); + } + +#if defined(RAYGUI_DEBUG_RECS_BOUNDS) + DrawRectangle((int)rec.x, (int)rec.y, (int)rec.width, (int)rec.height, Fade(RED, 0.4f)); +#endif +} + +// Draw tooltip using control bounds +static void GuiTooltip(Rectangle controlRec) +{ + if (!guiLocked && guiTooltip && (guiTooltipPtr != NULL) && !guiControlExclusiveMode) + { + Vector2 textSize = MeasureTextEx(GuiGetFont(), guiTooltipPtr, (float)GuiGetStyle(DEFAULT, TEXT_SIZE), (float)GuiGetStyle(DEFAULT, TEXT_SPACING)); + + if ((controlRec.x + textSize.x + 16) > GetScreenWidth()) controlRec.x -= (textSize.x + 16 - controlRec.width); + + GuiPanel(RAYGUI_CLITERAL(Rectangle){ controlRec.x, controlRec.y + controlRec.height + 4, textSize.x + 16, GuiGetStyle(DEFAULT, TEXT_SIZE) + 8.0f }, NULL); + + int textPadding = GuiGetStyle(LABEL, TEXT_PADDING); + int textAlignment = GuiGetStyle(LABEL, TEXT_ALIGNMENT); + GuiSetStyle(LABEL, TEXT_PADDING, 0); + GuiSetStyle(LABEL, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER); + GuiLabel(RAYGUI_CLITERAL(Rectangle){ controlRec.x, controlRec.y + controlRec.height + 4, textSize.x + 16, GuiGetStyle(DEFAULT, TEXT_SIZE) + 8.0f }, guiTooltipPtr); + GuiSetStyle(LABEL, TEXT_ALIGNMENT, textAlignment); + GuiSetStyle(LABEL, TEXT_PADDING, textPadding); + } +} + +// Split controls text into multiple strings +// Also check for multiple columns (required by GuiToggleGroup()) +static const char **GuiTextSplit(const char *text, char delimiter, int *count, int *textRow) +{ + // NOTE: Current implementation returns a copy of the provided string with '\0' (string end delimiter) + // inserted between strings defined by "delimiter" parameter. No memory is dynamically allocated, + // all used memory is static... it has some limitations: + // 1. Maximum number of possible split strings is set by RAYGUI_TEXTSPLIT_MAX_ITEMS + // 2. Maximum size of text to split is RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE + // NOTE: Those definitions could be externally provided if required + + // TODO: HACK: GuiTextSplit() - Review how textRows are returned to user + // textRow is an externally provided array of integers that stores row number for every splitted string + + #if !defined(RAYGUI_TEXTSPLIT_MAX_ITEMS) + #define RAYGUI_TEXTSPLIT_MAX_ITEMS 128 + #endif + #if !defined(RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE) + #define RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE 1024 + #endif + + static const char *result[RAYGUI_TEXTSPLIT_MAX_ITEMS] = { NULL }; // String pointers array (points to buffer data) + static char buffer[RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE] = { 0 }; // Buffer data (text input copy with '\0' added) + memset(buffer, 0, RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE); + + result[0] = buffer; + int counter = 1; + + if (textRow != NULL) textRow[0] = 0; + + // Count how many substrings we have on text and point to every one + for (int i = 0; i < RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE; i++) + { + buffer[i] = text[i]; + if (buffer[i] == '\0') break; + else if ((buffer[i] == delimiter) || (buffer[i] == '\n')) + { + result[counter] = buffer + i + 1; + + if (textRow != NULL) + { + if (buffer[i] == '\n') textRow[counter] = textRow[counter - 1] + 1; + else textRow[counter] = textRow[counter - 1]; + } + + buffer[i] = '\0'; // Set an end of string at this point + + counter++; + if (counter >= RAYGUI_TEXTSPLIT_MAX_ITEMS) break; + } + } + + *count = counter; + + return result; +} + +// Convert color data from RGB to HSV +// NOTE: Color data should be passed normalized +static Vector3 ConvertRGBtoHSV(Vector3 rgb) +{ + Vector3 hsv = { 0 }; + float min = 0.0f; + float max = 0.0f; + float delta = 0.0f; + + min = (rgb.x < rgb.y)? rgb.x : rgb.y; + min = (min < rgb.z)? min : rgb.z; + + max = (rgb.x > rgb.y)? rgb.x : rgb.y; + max = (max > rgb.z)? max : rgb.z; + + hsv.z = max; // Value + delta = max - min; + + if (delta < 0.00001f) + { + hsv.y = 0.0f; + hsv.x = 0.0f; // Undefined, maybe NAN? + return hsv; + } + + if (max > 0.0f) + { + // NOTE: If max is 0, this divide would cause a crash + hsv.y = (delta/max); // Saturation + } + else + { + // NOTE: If max is 0, then r = g = b = 0, s = 0, h is undefined + hsv.y = 0.0f; + hsv.x = 0.0f; // Undefined, maybe NAN? + return hsv; + } + + // NOTE: Comparing float values could not work properly + if (rgb.x >= max) hsv.x = (rgb.y - rgb.z)/delta; // Between yellow & magenta + else + { + if (rgb.y >= max) hsv.x = 2.0f + (rgb.z - rgb.x)/delta; // Between cyan & yellow + else hsv.x = 4.0f + (rgb.x - rgb.y)/delta; // Between magenta & cyan + } + + hsv.x *= 60.0f; // Convert to degrees + + if (hsv.x < 0.0f) hsv.x += 360.0f; + + return hsv; +} + +// Convert color data from HSV to RGB +// NOTE: Color data should be passed normalized +static Vector3 ConvertHSVtoRGB(Vector3 hsv) +{ + Vector3 rgb = { 0 }; + float hh = 0.0f, p = 0.0f, q = 0.0f, t = 0.0f, ff = 0.0f; + long i = 0; + + // NOTE: Comparing float values could not work properly + if (hsv.y <= 0.0f) + { + rgb.x = hsv.z; + rgb.y = hsv.z; + rgb.z = hsv.z; + return rgb; + } + + hh = hsv.x; + if (hh >= 360.0f) hh = 0.0f; + hh /= 60.0f; + + i = (long)hh; + ff = hh - i; + p = hsv.z*(1.0f - hsv.y); + q = hsv.z*(1.0f - (hsv.y*ff)); + t = hsv.z*(1.0f - (hsv.y*(1.0f - ff))); + + switch (i) + { + case 0: + { + rgb.x = hsv.z; + rgb.y = t; + rgb.z = p; + } break; + case 1: + { + rgb.x = q; + rgb.y = hsv.z; + rgb.z = p; + } break; + case 2: + { + rgb.x = p; + rgb.y = hsv.z; + rgb.z = t; + } break; + case 3: + { + rgb.x = p; + rgb.y = q; + rgb.z = hsv.z; + } break; + case 4: + { + rgb.x = t; + rgb.y = p; + rgb.z = hsv.z; + } break; + case 5: + default: + { + rgb.x = hsv.z; + rgb.y = p; + rgb.z = q; + } break; + } + + return rgb; +} + +// Scroll bar control (used by GuiScrollPanel()) +static int GuiScrollBar(Rectangle bounds, int value, int minValue, int maxValue) +{ + GuiState state = guiState; + + // Is the scrollbar horizontal or vertical? + bool isVertical = (bounds.width > bounds.height)? false : true; + + // The size (width or height depending on scrollbar type) of the spinner buttons + const int spinnerSize = GuiGetStyle(SCROLLBAR, ARROWS_VISIBLE)? + (isVertical? (int)bounds.width - 2*GuiGetStyle(SCROLLBAR, BORDER_WIDTH) : + (int)bounds.height - 2*GuiGetStyle(SCROLLBAR, BORDER_WIDTH)) : 0; + + // Arrow buttons [<] [>] [∧] [∨] + Rectangle arrowUpLeft = { 0 }; + Rectangle arrowDownRight = { 0 }; + + // Actual area of the scrollbar excluding the arrow buttons + Rectangle scrollbar = { 0 }; + + // Slider bar that moves --[///]----- + Rectangle slider = { 0 }; + + // Normalize value + if (value > maxValue) value = maxValue; + if (value < minValue) value = minValue; + + int valueRange = maxValue - minValue; + if (valueRange <= 0) valueRange = 1; + + int sliderSize = GuiGetStyle(SCROLLBAR, SCROLL_SLIDER_SIZE); + if (sliderSize < 1) sliderSize = 1; // TODO: Consider a minimum slider size + + // Calculate rectangles for all of the components + arrowUpLeft = RAYGUI_CLITERAL(Rectangle){ + (float)bounds.x + GuiGetStyle(SCROLLBAR, BORDER_WIDTH), + (float)bounds.y + GuiGetStyle(SCROLLBAR, BORDER_WIDTH), + (float)spinnerSize, (float)spinnerSize }; + + if (isVertical) + { + arrowDownRight = RAYGUI_CLITERAL(Rectangle){ (float)bounds.x + GuiGetStyle(SCROLLBAR, BORDER_WIDTH), (float)bounds.y + bounds.height - spinnerSize - GuiGetStyle(SCROLLBAR, BORDER_WIDTH), (float)spinnerSize, (float)spinnerSize }; + scrollbar = RAYGUI_CLITERAL(Rectangle){ bounds.x + GuiGetStyle(SCROLLBAR, BORDER_WIDTH) + GuiGetStyle(SCROLLBAR, SCROLL_PADDING), arrowUpLeft.y + arrowUpLeft.height, bounds.width - 2*(GuiGetStyle(SCROLLBAR, BORDER_WIDTH) + GuiGetStyle(SCROLLBAR, SCROLL_PADDING)), bounds.height - arrowUpLeft.height - arrowDownRight.height - 2*GuiGetStyle(SCROLLBAR, BORDER_WIDTH) }; + + // Make sure the slider won't get outside of the scrollbar + sliderSize = (sliderSize >= scrollbar.height)? ((int)scrollbar.height - 2) : sliderSize; + slider = RAYGUI_CLITERAL(Rectangle){ + bounds.x + GuiGetStyle(SCROLLBAR, BORDER_WIDTH) + GuiGetStyle(SCROLLBAR, SCROLL_SLIDER_PADDING), + scrollbar.y + (int)(((float)(value - minValue)/valueRange)*(scrollbar.height - sliderSize)), + bounds.width - 2*(GuiGetStyle(SCROLLBAR, BORDER_WIDTH) + GuiGetStyle(SCROLLBAR, SCROLL_SLIDER_PADDING)), + (float)sliderSize }; + } + else // horizontal + { + arrowDownRight = RAYGUI_CLITERAL(Rectangle){ (float)bounds.x + bounds.width - spinnerSize - GuiGetStyle(SCROLLBAR, BORDER_WIDTH), (float)bounds.y + GuiGetStyle(SCROLLBAR, BORDER_WIDTH), (float)spinnerSize, (float)spinnerSize }; + scrollbar = RAYGUI_CLITERAL(Rectangle){ arrowUpLeft.x + arrowUpLeft.width, bounds.y + GuiGetStyle(SCROLLBAR, BORDER_WIDTH) + GuiGetStyle(SCROLLBAR, SCROLL_PADDING), bounds.width - arrowUpLeft.width - arrowDownRight.width - 2*GuiGetStyle(SCROLLBAR, BORDER_WIDTH), bounds.height - 2*(GuiGetStyle(SCROLLBAR, BORDER_WIDTH) + GuiGetStyle(SCROLLBAR, SCROLL_PADDING)) }; + + // Make sure the slider won't get outside of the scrollbar + sliderSize = (sliderSize >= scrollbar.width)? ((int)scrollbar.width - 2) : sliderSize; + slider = RAYGUI_CLITERAL(Rectangle){ + scrollbar.x + (int)(((float)(value - minValue)/valueRange)*(scrollbar.width - sliderSize)), + bounds.y + GuiGetStyle(SCROLLBAR, BORDER_WIDTH) + GuiGetStyle(SCROLLBAR, SCROLL_SLIDER_PADDING), + (float)sliderSize, + bounds.height - 2*(GuiGetStyle(SCROLLBAR, BORDER_WIDTH) + GuiGetStyle(SCROLLBAR, SCROLL_SLIDER_PADDING)) }; + } + + // Update control + //-------------------------------------------------------------------- + if ((state != STATE_DISABLED) && !guiLocked) + { + Vector2 mousePoint = GetMousePosition(); + + if (guiControlExclusiveMode) // Allows to keep dragging outside of bounds + { + if (IsMouseButtonDown(MOUSE_LEFT_BUTTON) && + !CheckCollisionPointRec(mousePoint, arrowUpLeft) && + !CheckCollisionPointRec(mousePoint, arrowDownRight)) + { + if (CHECK_BOUNDS_ID(bounds, guiControlExclusiveRec)) + { + state = STATE_PRESSED; + + if (isVertical) value = (int)(((float)(mousePoint.y - scrollbar.y - slider.height/2)*valueRange)/(scrollbar.height - slider.height) + minValue); + else value = (int)(((float)(mousePoint.x - scrollbar.x - slider.width/2)*valueRange)/(scrollbar.width - slider.width) + minValue); + } + } + else + { + guiControlExclusiveMode = false; + guiControlExclusiveRec = RAYGUI_CLITERAL(Rectangle){ 0, 0, 0, 0 }; + } + } + else if (CheckCollisionPointRec(mousePoint, bounds)) + { + state = STATE_FOCUSED; + + // Handle mouse wheel + int wheel = (int)GetMouseWheelMove(); + if (wheel != 0) value += wheel; + + // Handle mouse button down + if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) + { + guiControlExclusiveMode = true; + guiControlExclusiveRec = bounds; // Store bounds as an identifier when dragging starts + + // Check arrows click + if (CheckCollisionPointRec(mousePoint, arrowUpLeft)) value -= valueRange/GuiGetStyle(SCROLLBAR, SCROLL_SPEED); + else if (CheckCollisionPointRec(mousePoint, arrowDownRight)) value += valueRange/GuiGetStyle(SCROLLBAR, SCROLL_SPEED); + else if (!CheckCollisionPointRec(mousePoint, slider)) + { + // If click on scrollbar position but not on slider, place slider directly on that position + if (isVertical) value = (int)(((float)(mousePoint.y - scrollbar.y - slider.height/2)*valueRange)/(scrollbar.height - slider.height) + minValue); + else value = (int)(((float)(mousePoint.x - scrollbar.x - slider.width/2)*valueRange)/(scrollbar.width - slider.width) + minValue); + } + + state = STATE_PRESSED; + } + + // Keyboard control on mouse hover scrollbar + /* + if (isVertical) + { + if (IsKeyDown(KEY_DOWN)) value += 5; + else if (IsKeyDown(KEY_UP)) value -= 5; + } + else + { + if (IsKeyDown(KEY_RIGHT)) value += 5; + else if (IsKeyDown(KEY_LEFT)) value -= 5; + } + */ + } + + // Normalize value + if (value > maxValue) value = maxValue; + if (value < minValue) value = minValue; + } + //-------------------------------------------------------------------- + + // Draw control + //-------------------------------------------------------------------- + GuiDrawRectangle(bounds, GuiGetStyle(SCROLLBAR, BORDER_WIDTH), GetColor(GuiGetStyle(LISTVIEW, BORDER + state*3)), GetColor(GuiGetStyle(DEFAULT, BORDER_COLOR_DISABLED))); // Draw the background + + GuiDrawRectangle(scrollbar, 0, BLANK, GetColor(GuiGetStyle(BUTTON, BASE_COLOR_NORMAL))); // Draw the scrollbar active area background + GuiDrawRectangle(slider, 0, BLANK, GetColor(GuiGetStyle(SLIDER, BORDER + state*3))); // Draw the slider bar + + // Draw arrows (using icon if available) + if (GuiGetStyle(SCROLLBAR, ARROWS_VISIBLE)) + { +#if defined(RAYGUI_NO_ICONS) + GuiDrawText(isVertical? "^" : "<", + RAYGUI_CLITERAL(Rectangle){ arrowUpLeft.x, arrowUpLeft.y, isVertical? bounds.width : bounds.height, isVertical? bounds.width : bounds.height }, + TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(DROPDOWNBOX, TEXT + (state*3)))); + GuiDrawText(isVertical? "v" : ">", + RAYGUI_CLITERAL(Rectangle){ arrowDownRight.x, arrowDownRight.y, isVertical? bounds.width : bounds.height, isVertical? bounds.width : bounds.height }, + TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(DROPDOWNBOX, TEXT + (state*3)))); +#else + GuiDrawText(isVertical? "#121#" : "#118#", + RAYGUI_CLITERAL(Rectangle){ arrowUpLeft.x, arrowUpLeft.y, isVertical? bounds.width : bounds.height, isVertical? bounds.width : bounds.height }, + TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(SCROLLBAR, TEXT + state*3))); // ICON_ARROW_UP_FILL / ICON_ARROW_LEFT_FILL + GuiDrawText(isVertical? "#120#" : "#119#", + RAYGUI_CLITERAL(Rectangle){ arrowDownRight.x, arrowDownRight.y, isVertical? bounds.width : bounds.height, isVertical? bounds.width : bounds.height }, + TEXT_ALIGN_CENTER, GetColor(GuiGetStyle(SCROLLBAR, TEXT + state*3))); // ICON_ARROW_DOWN_FILL / ICON_ARROW_RIGHT_FILL +#endif + } + //-------------------------------------------------------------------- + + return value; +} + +// Color fade-in or fade-out, alpha goes from 0.0f to 1.0f +// WARNING: It multiplies current alpha by alpha scale factor +static Color GuiFade(Color color, float alpha) +{ + if (alpha < 0.0f) alpha = 0.0f; + else if (alpha > 1.0f) alpha = 1.0f; + + Color result = { color.r, color.g, color.b, (unsigned char)(color.a*alpha) }; + + return result; +} + +#if defined(RAYGUI_STANDALONE) +// Returns a Color struct from hexadecimal value +static Color GetColor(int hexValue) +{ + Color color; + + color.r = (unsigned char)(hexValue >> 24) & 0xff; + color.g = (unsigned char)(hexValue >> 16) & 0xff; + color.b = (unsigned char)(hexValue >> 8) & 0xff; + color.a = (unsigned char)hexValue & 0xff; + + return color; +} + +// Returns hexadecimal value for a Color +static int ColorToInt(Color color) +{ + return (((int)color.r << 24) | ((int)color.g << 16) | ((int)color.b << 8) | (int)color.a); +} + +// Check if point is inside rectangle +static bool CheckCollisionPointRec(Vector2 point, Rectangle rec) +{ + bool collision = false; + + if ((point.x >= rec.x) && (point.x <= (rec.x + rec.width)) && + (point.y >= rec.y) && (point.y <= (rec.y + rec.height))) collision = true; + + return collision; +} + +// Formatting of text with variables to 'embed' +static const char *TextFormat(const char *text, ...) +{ + #if !defined(RAYGUI_TEXTFORMAT_MAX_SIZE) + #define RAYGUI_TEXTFORMAT_MAX_SIZE 256 + #endif + + static char buffer[RAYGUI_TEXTFORMAT_MAX_SIZE]; + + va_list args; + va_start(args, text); + vsnprintf(buffer, RAYGUI_TEXTFORMAT_MAX_SIZE, text, args); + va_end(args); + + return buffer; +} + +// Draw rectangle with vertical gradient fill color +// NOTE: This function is only used by GuiColorPicker() +static void DrawRectangleGradientV(int posX, int posY, int width, int height, Color color1, Color color2) +{ + Rectangle bounds = { (float)posX, (float)posY, (float)width, (float)height }; + DrawRectangleGradientEx(bounds, color1, color2, color2, color1); +} + +// Split string into multiple strings +const char **TextSplit(const char *text, char delimiter, int *count) +{ + // NOTE: Current implementation returns a copy of the provided string with '\0' (string end delimiter) + // inserted between strings defined by "delimiter" parameter. No memory is dynamically allocated, + // all used memory is static... it has some limitations: + // 1. Maximum number of possible split strings is set by RAYGUI_TEXTSPLIT_MAX_ITEMS + // 2. Maximum size of text to split is RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE + + #if !defined(RAYGUI_TEXTSPLIT_MAX_ITEMS) + #define RAYGUI_TEXTSPLIT_MAX_ITEMS 128 + #endif + #if !defined(RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE) + #define RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE 1024 + #endif + + static const char *result[RAYGUI_TEXTSPLIT_MAX_ITEMS] = { NULL }; + static char buffer[RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE] = { 0 }; + memset(buffer, 0, RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE); + + result[0] = buffer; + int counter = 0; + + if (text != NULL) + { + counter = 1; + + // Count how many substrings we have on text and point to every one + for (int i = 0; i < RAYGUI_TEXTSPLIT_MAX_TEXT_SIZE; i++) + { + buffer[i] = text[i]; + if (buffer[i] == '\0') break; + else if (buffer[i] == delimiter) + { + buffer[i] = '\0'; // Set an end of string at this point + result[counter] = buffer + i + 1; + counter++; + + if (counter == RAYGUI_TEXTSPLIT_MAX_ITEMS) break; + } + } + } + + *count = counter; + return result; +} + +// Get integer value from text +// NOTE: This function replaces atoi() [stdlib.h] +static int TextToInteger(const char *text) +{ + int value = 0; + int sign = 1; + + if ((text[0] == '+') || (text[0] == '-')) + { + if (text[0] == '-') sign = -1; + text++; + } + + for (int i = 0; ((text[i] >= '0') && (text[i] <= '9')); ++i) value = value*10 + (int)(text[i] - '0'); + + return value*sign; +} + +// Get float value from text +// NOTE: This function replaces atof() [stdlib.h] +// WARNING: Only '.' character is understood as decimal point +static float TextToFloat(const char *text) +{ + float value = 0.0f; + float sign = 1.0f; + + if ((text[0] == '+') || (text[0] == '-')) + { + if (text[0] == '-') sign = -1.0f; + text++; + } + + int i = 0; + for (; ((text[i] >= '0') && (text[i] <= '9')); i++) value = value*10.0f + (float)(text[i] - '0'); + + if (text[i++] != '.') value *= sign; + else + { + float divisor = 10.0f; + for (; ((text[i] >= '0') && (text[i] <= '9')); i++) + { + value += ((float)(text[i] - '0'))/divisor; + divisor = divisor*10.0f; + } + } + + return value; +} + +// Encode codepoint into UTF-8 text (char array size returned as parameter) +static const char *CodepointToUTF8(int codepoint, int *byteSize) +{ + static char utf8[6] = { 0 }; + int size = 0; + + if (codepoint <= 0x7f) + { + utf8[0] = (char)codepoint; + size = 1; + } + else if (codepoint <= 0x7ff) + { + utf8[0] = (char)(((codepoint >> 6) & 0x1f) | 0xc0); + utf8[1] = (char)((codepoint & 0x3f) | 0x80); + size = 2; + } + else if (codepoint <= 0xffff) + { + utf8[0] = (char)(((codepoint >> 12) & 0x0f) | 0xe0); + utf8[1] = (char)(((codepoint >> 6) & 0x3f) | 0x80); + utf8[2] = (char)((codepoint & 0x3f) | 0x80); + size = 3; + } + else if (codepoint <= 0x10ffff) + { + utf8[0] = (char)(((codepoint >> 18) & 0x07) | 0xf0); + utf8[1] = (char)(((codepoint >> 12) & 0x3f) | 0x80); + utf8[2] = (char)(((codepoint >> 6) & 0x3f) | 0x80); + utf8[3] = (char)((codepoint & 0x3f) | 0x80); + size = 4; + } + + *byteSize = size; + + return utf8; +} + +// Get next codepoint in a UTF-8 encoded text, scanning until '\0' is found +// When a invalid UTF-8 byte is encountered we exit as soon as possible and a '?'(0x3f) codepoint is returned +// Total number of bytes processed are returned as a parameter +// NOTE: the standard says U+FFFD should be returned in case of errors +// but that character is not supported by the default font in raylib +static int GetCodepointNext(const char *text, int *codepointSize) +{ + const char *ptr = text; + int codepoint = 0x3f; // Codepoint (defaults to '?') + *codepointSize = 1; + + // Get current codepoint and bytes processed + if (0xf0 == (0xf8 & ptr[0])) + { + // 4 byte UTF-8 codepoint + if (((ptr[1] & 0xC0) ^ 0x80) || ((ptr[2] & 0xC0) ^ 0x80) || ((ptr[3] & 0xC0) ^ 0x80)) { return codepoint; } //10xxxxxx checks + codepoint = ((0x07 & ptr[0]) << 18) | ((0x3f & ptr[1]) << 12) | ((0x3f & ptr[2]) << 6) | (0x3f & ptr[3]); + *codepointSize = 4; + } + else if (0xe0 == (0xf0 & ptr[0])) + { + // 3 byte UTF-8 codepoint + if (((ptr[1] & 0xC0) ^ 0x80) || ((ptr[2] & 0xC0) ^ 0x80)) { return codepoint; } //10xxxxxx checks + codepoint = ((0x0f & ptr[0]) << 12) | ((0x3f & ptr[1]) << 6) | (0x3f & ptr[2]); + *codepointSize = 3; + } + else if (0xc0 == (0xe0 & ptr[0])) + { + // 2 byte UTF-8 codepoint + if ((ptr[1] & 0xC0) ^ 0x80) { return codepoint; } //10xxxxxx checks + codepoint = ((0x1f & ptr[0]) << 6) | (0x3f & ptr[1]); + *codepointSize = 2; + } + else if (0x00 == (0x80 & ptr[0])) + { + // 1 byte UTF-8 codepoint + codepoint = ptr[0]; + *codepointSize = 1; + } + + return codepoint; +} +#endif // RAYGUI_STANDALONE + +#endif // RAYGUI_IMPLEMENTATION diff --git a/vendor/rcamera.h b/vendor/rcamera.h new file mode 100644 index 0000000000..3e9f830958 --- /dev/null +++ b/vendor/rcamera.h @@ -0,0 +1,555 @@ +/******************************************************************************************* +* +* rcamera - Basic camera system with support for multiple camera modes +* +* CONFIGURATION: +* #define RCAMERA_IMPLEMENTATION +* Generates the implementation of the library into the included file. +* If not defined, the library is in header only mode and can be included in other headers +* or source files without problems. But only ONE file should hold the implementation. +* +* #define RCAMERA_STANDALONE +* If defined, the library can be used as standalone as a camera system but some +* functions must be redefined to manage inputs accordingly. +* +* CONTRIBUTORS: +* Ramon Santamaria: Supervision, review, update and maintenance +* Christoph Wagner: Complete redesign, using raymath (2022) +* Marc Palau: Initial implementation (2014) +* +* +* LICENSE: zlib/libpng +* +* Copyright (c) 2022-2025 Christoph Wagner (@Crydsch) & Ramon Santamaria (@raysan5) +* +* This software is provided "as-is", without any express or implied warranty. In no event +* will the authors be held liable for any damages arising from the use of this software. +* +* Permission is granted to anyone to use this software for any purpose, including commercial +* applications, and to alter it and redistribute it freely, subject to the following restrictions: +* +* 1. The origin of this software must not be misrepresented; you must not claim that you +* wrote the original software. If you use this software in a product, an acknowledgment +* in the product documentation would be appreciated but is not required. +* +* 2. Altered source versions must be plainly marked as such, and must not be misrepresented +* as being the original software. +* +* 3. This notice may not be removed or altered from any source distribution. +* +**********************************************************************************************/ + +#ifndef RCAMERA_H +#define RCAMERA_H + +//---------------------------------------------------------------------------------- +// Defines and Macros +//---------------------------------------------------------------------------------- +// Function specifiers definition + +// Function specifiers in case library is build/used as a shared library (Windows) +// NOTE: Microsoft specifiers to tell compiler that symbols are imported/exported from a .dll +#if defined(_WIN32) +#if defined(BUILD_LIBTYPE_SHARED) +#if defined(__TINYC__) +#define __declspec(x) __attribute__((x)) +#endif +#define RLAPI __declspec(dllexport) // We are building the library as a Win32 shared library (.dll) +#elif defined(USE_LIBTYPE_SHARED) +#define RLAPI __declspec(dllimport) // We are using the library as a Win32 shared library (.dll) +#endif +#endif + +#ifndef RLAPI + #define RLAPI // Functions defined as 'extern' by default (implicit specifiers) +#endif + +#if defined(RCAMERA_STANDALONE) + #define CAMERA_CULL_DISTANCE_NEAR 0.05 + #define CAMERA_CULL_DISTANCE_FAR 4000.0 +#else + #define CAMERA_CULL_DISTANCE_NEAR RL_CULL_DISTANCE_NEAR + #define CAMERA_CULL_DISTANCE_FAR RL_CULL_DISTANCE_FAR +#endif + +//---------------------------------------------------------------------------------- +// Types and Structures Definition +// NOTE: Below types are required for standalone usage +//---------------------------------------------------------------------------------- +#if defined(RCAMERA_STANDALONE) + // Vector2, 2 components + typedef struct Vector2 { + float x; // Vector x component + float y; // Vector y component + } Vector2; + + // Vector3, 3 components + typedef struct Vector3 { + float x; // Vector x component + float y; // Vector y component + float z; // Vector z component + } Vector3; + + // Matrix, 4x4 components, column major, OpenGL style, right-handed + typedef struct Matrix { + float m0, m4, m8, m12; // Matrix first row (4 components) + float m1, m5, m9, m13; // Matrix second row (4 components) + float m2, m6, m10, m14; // Matrix third row (4 components) + float m3, m7, m11, m15; // Matrix fourth row (4 components) + } Matrix; + + // Camera type, defines a camera position/orientation in 3d space + typedef struct Camera3D { + Vector3 position; // Camera position + Vector3 target; // Camera target it looks-at + Vector3 up; // Camera up vector (rotation over its axis) + float fovy; // Camera field-of-view apperture in Y (degrees) in perspective, used as near plane width in orthographic + int projection; // Camera projection type: CAMERA_PERSPECTIVE or CAMERA_ORTHOGRAPHIC + } Camera3D; + + typedef Camera3D Camera; // Camera type fallback, defaults to Camera3D + + // Camera projection + typedef enum { + CAMERA_PERSPECTIVE = 0, // Perspective projection + CAMERA_ORTHOGRAPHIC // Orthographic projection + } CameraProjection; + + // Camera system modes + typedef enum { + CAMERA_CUSTOM = 0, // Camera custom, controlled by user (UpdateCamera() does nothing) + CAMERA_FREE, // Camera free mode + CAMERA_ORBITAL, // Camera orbital, around target, zoom supported + CAMERA_FIRST_PERSON, // Camera first person + CAMERA_THIRD_PERSON // Camera third person + } CameraMode; +#endif + +//---------------------------------------------------------------------------------- +// Global Variables Definition +//---------------------------------------------------------------------------------- +//... + +//---------------------------------------------------------------------------------- +// Module Functions Declaration +//---------------------------------------------------------------------------------- + +#if defined(__cplusplus) +extern "C" { // Prevents name mangling of functions +#endif + +RLAPI Vector3 GetCameraForward(Camera *camera); +RLAPI Vector3 GetCameraUp(Camera *camera); +RLAPI Vector3 GetCameraRight(Camera *camera); + +// Camera movement +RLAPI void CameraMoveForward(Camera *camera, float distance, bool moveInWorldPlane); +RLAPI void CameraMoveUp(Camera *camera, float distance); +RLAPI void CameraMoveRight(Camera *camera, float distance, bool moveInWorldPlane); +RLAPI void CameraMoveToTarget(Camera *camera, float delta); + +// Camera rotation +RLAPI void CameraYaw(Camera *camera, float angle, bool rotateAroundTarget); +RLAPI void CameraPitch(Camera *camera, float angle, bool lockView, bool rotateAroundTarget, bool rotateUp); +RLAPI void CameraRoll(Camera *camera, float angle); + +RLAPI Matrix GetCameraViewMatrix(Camera *camera); +RLAPI Matrix GetCameraProjectionMatrix(Camera *camera, float aspect); + +#if defined(__cplusplus) +} +#endif + +#endif // RCAMERA_H + +/*********************************************************************************** +* +* CAMERA IMPLEMENTATION +* +************************************************************************************/ + +#if defined(RCAMERA_IMPLEMENTATION) + +#include "raymath.h" // Required for vector maths: + // Vector3Add() + // Vector3Subtract() + // Vector3Scale() + // Vector3Normalize() + // Vector3Distance() + // Vector3CrossProduct() + // Vector3RotateByAxisAngle() + // Vector3Angle() + // Vector3Negate() + // MatrixLookAt() + // MatrixPerspective() + // MatrixOrtho() + // MatrixIdentity() + +// raylib required functionality: + // GetMouseDelta() + // GetMouseWheelMove() + // IsKeyDown() + // IsKeyPressed() + // GetFrameTime() + +//---------------------------------------------------------------------------------- +// Defines and Macros +//---------------------------------------------------------------------------------- +#define CAMERA_MOVE_SPEED 5.4f // Units per second +#define CAMERA_ROTATION_SPEED 0.03f +#define CAMERA_PAN_SPEED 0.2f + +// Camera mouse movement sensitivity +#define CAMERA_MOUSE_MOVE_SENSITIVITY 0.003f + +// Camera orbital speed in CAMERA_ORBITAL mode +#define CAMERA_ORBITAL_SPEED 0.5f // Radians per second + +//---------------------------------------------------------------------------------- +// Types and Structures Definition +//---------------------------------------------------------------------------------- +//... + +//---------------------------------------------------------------------------------- +// Global Variables Definition +//---------------------------------------------------------------------------------- +//... + +//---------------------------------------------------------------------------------- +// Module Internal Functions Declaration +//---------------------------------------------------------------------------------- +//... + +//---------------------------------------------------------------------------------- +// Module Functions Definition +//---------------------------------------------------------------------------------- +// Returns the cameras forward vector (normalized) +Vector3 GetCameraForward(Camera *camera) +{ + return Vector3Normalize(Vector3Subtract(camera->target, camera->position)); +} + +// Returns the cameras up vector (normalized) +// Note: The up vector might not be perpendicular to the forward vector +Vector3 GetCameraUp(Camera *camera) +{ + return Vector3Normalize(camera->up); +} + +// Returns the cameras right vector (normalized) +Vector3 GetCameraRight(Camera *camera) +{ + Vector3 forward = GetCameraForward(camera); + Vector3 up = GetCameraUp(camera); + + return Vector3Normalize(Vector3CrossProduct(forward, up)); +} + +// Moves the camera in its forward direction +void CameraMoveForward(Camera *camera, float distance, bool moveInWorldPlane) +{ + Vector3 forward = GetCameraForward(camera); + + if (moveInWorldPlane) + { + // Project vector onto world plane + forward.y = 0; + forward = Vector3Normalize(forward); + } + + // Scale by distance + forward = Vector3Scale(forward, distance); + + // Move position and target + camera->position = Vector3Add(camera->position, forward); + camera->target = Vector3Add(camera->target, forward); +} + +// Moves the camera in its up direction +void CameraMoveUp(Camera *camera, float distance) +{ + Vector3 up = GetCameraUp(camera); + + // Scale by distance + up = Vector3Scale(up, distance); + + // Move position and target + camera->position = Vector3Add(camera->position, up); + camera->target = Vector3Add(camera->target, up); +} + +// Moves the camera target in its current right direction +void CameraMoveRight(Camera *camera, float distance, bool moveInWorldPlane) +{ + Vector3 right = GetCameraRight(camera); + + if (moveInWorldPlane) + { + // Project vector onto world plane + right.y = 0; + right = Vector3Normalize(right); + } + + // Scale by distance + right = Vector3Scale(right, distance); + + // Move position and target + camera->position = Vector3Add(camera->position, right); + camera->target = Vector3Add(camera->target, right); +} + +// Moves the camera position closer/farther to/from the camera target +void CameraMoveToTarget(Camera *camera, float delta) +{ + float distance = Vector3Distance(camera->position, camera->target); + + // Apply delta + distance += delta; + + // Distance must be greater than 0 + if (distance <= 0) distance = 0.001f; + + // Set new distance by moving the position along the forward vector + Vector3 forward = GetCameraForward(camera); + camera->position = Vector3Add(camera->target, Vector3Scale(forward, -distance)); +} + +// Rotates the camera around its up vector +// Yaw is "looking left and right" +// If rotateAroundTarget is false, the camera rotates around its position +// Note: angle must be provided in radians +void CameraYaw(Camera *camera, float angle, bool rotateAroundTarget) +{ + // Rotation axis + Vector3 up = GetCameraUp(camera); + + // View vector + Vector3 targetPosition = Vector3Subtract(camera->target, camera->position); + + // Rotate view vector around up axis + targetPosition = Vector3RotateByAxisAngle(targetPosition, up, angle); + + if (rotateAroundTarget) + { + // Move position relative to target + camera->position = Vector3Subtract(camera->target, targetPosition); + } + else // rotate around camera.position + { + // Move target relative to position + camera->target = Vector3Add(camera->position, targetPosition); + } +} + +// Rotates the camera around its right vector, pitch is "looking up and down" +// - lockView prevents camera overrotation (aka "somersaults") +// - rotateAroundTarget defines if rotation is around target or around its position +// - rotateUp rotates the up direction as well (typically only usefull in CAMERA_FREE) +// NOTE: angle must be provided in radians +void CameraPitch(Camera *camera, float angle, bool lockView, bool rotateAroundTarget, bool rotateUp) +{ + // Up direction + Vector3 up = GetCameraUp(camera); + + // View vector + Vector3 targetPosition = Vector3Subtract(camera->target, camera->position); + + if (lockView) + { + // In these camera modes we clamp the Pitch angle + // to allow only viewing straight up or down. + + // Clamp view up + float maxAngleUp = Vector3Angle(up, targetPosition); + maxAngleUp -= 0.001f; // avoid numerical errors + if (angle > maxAngleUp) angle = maxAngleUp; + + // Clamp view down + float maxAngleDown = Vector3Angle(Vector3Negate(up), targetPosition); + maxAngleDown *= -1.0f; // downwards angle is negative + maxAngleDown += 0.001f; // avoid numerical errors + if (angle < maxAngleDown) angle = maxAngleDown; + } + + // Rotation axis + Vector3 right = GetCameraRight(camera); + + // Rotate view vector around right axis + targetPosition = Vector3RotateByAxisAngle(targetPosition, right, angle); + + if (rotateAroundTarget) + { + // Move position relative to target + camera->position = Vector3Subtract(camera->target, targetPosition); + } + else // rotate around camera.position + { + // Move target relative to position + camera->target = Vector3Add(camera->position, targetPosition); + } + + if (rotateUp) + { + // Rotate up direction around right axis + camera->up = Vector3RotateByAxisAngle(camera->up, right, angle); + } +} + +// Rotates the camera around its forward vector +// Roll is "turning your head sideways to the left or right" +// Note: angle must be provided in radians +void CameraRoll(Camera *camera, float angle) +{ + // Rotation axis + Vector3 forward = GetCameraForward(camera); + + // Rotate up direction around forward axis + camera->up = Vector3RotateByAxisAngle(camera->up, forward, angle); +} + +// Returns the camera view matrix +Matrix GetCameraViewMatrix(Camera *camera) +{ + return MatrixLookAt(camera->position, camera->target, camera->up); +} + +// Returns the camera projection matrix +Matrix GetCameraProjectionMatrix(Camera *camera, float aspect) +{ + if (camera->projection == CAMERA_PERSPECTIVE) + { + return MatrixPerspective(camera->fovy*DEG2RAD, aspect, CAMERA_CULL_DISTANCE_NEAR, CAMERA_CULL_DISTANCE_FAR); + } + else if (camera->projection == CAMERA_ORTHOGRAPHIC) + { + double top = camera->fovy/2.0; + double right = top*aspect; + + return MatrixOrtho(-right, right, -top, top, CAMERA_CULL_DISTANCE_NEAR, CAMERA_CULL_DISTANCE_FAR); + } + + return MatrixIdentity(); +} + +#if !defined(RCAMERA_STANDALONE) +// Update camera position for selected mode +// Camera mode: CAMERA_FREE, CAMERA_FIRST_PERSON, CAMERA_THIRD_PERSON, CAMERA_ORBITAL or CUSTOM +void UpdateCamera(Camera *camera, int mode) +{ + Vector2 mousePositionDelta = GetMouseDelta(); + + bool moveInWorldPlane = ((mode == CAMERA_FIRST_PERSON) || (mode == CAMERA_THIRD_PERSON)); + bool rotateAroundTarget = ((mode == CAMERA_THIRD_PERSON) || (mode == CAMERA_ORBITAL)); + bool lockView = ((mode == CAMERA_FREE) || (mode == CAMERA_FIRST_PERSON) || (mode == CAMERA_THIRD_PERSON) || (mode == CAMERA_ORBITAL)); + bool rotateUp = false; + + // Camera speeds based on frame time + float cameraMoveSpeed = CAMERA_MOVE_SPEED*GetFrameTime(); + float cameraRotationSpeed = CAMERA_ROTATION_SPEED*GetFrameTime(); + float cameraPanSpeed = CAMERA_PAN_SPEED*GetFrameTime(); + float cameraOrbitalSpeed = CAMERA_ORBITAL_SPEED*GetFrameTime(); + + if (mode == CAMERA_CUSTOM) {} + else if (mode == CAMERA_ORBITAL) + { + // Orbital can just orbit + Matrix rotation = MatrixRotate(GetCameraUp(camera), cameraOrbitalSpeed); + Vector3 view = Vector3Subtract(camera->position, camera->target); + view = Vector3Transform(view, rotation); + camera->position = Vector3Add(camera->target, view); + } + else + { + // Camera rotation + if (IsKeyDown(KEY_DOWN)) CameraPitch(camera, -cameraRotationSpeed, lockView, rotateAroundTarget, rotateUp); + if (IsKeyDown(KEY_UP)) CameraPitch(camera, cameraRotationSpeed, lockView, rotateAroundTarget, rotateUp); + if (IsKeyDown(KEY_RIGHT)) CameraYaw(camera, -cameraRotationSpeed, rotateAroundTarget); + if (IsKeyDown(KEY_LEFT)) CameraYaw(camera, cameraRotationSpeed, rotateAroundTarget); + if (IsKeyDown(KEY_Q)) CameraRoll(camera, -cameraRotationSpeed); + if (IsKeyDown(KEY_E)) CameraRoll(camera, cameraRotationSpeed); + + // Camera movement + // Camera pan (for CAMERA_FREE) + if ((mode == CAMERA_FREE) && (IsMouseButtonDown(MOUSE_BUTTON_MIDDLE))) + { + const Vector2 mouseDelta = GetMouseDelta(); + if (mouseDelta.x > 0.0f) CameraMoveRight(camera, cameraPanSpeed, moveInWorldPlane); + if (mouseDelta.x < 0.0f) CameraMoveRight(camera, -cameraPanSpeed, moveInWorldPlane); + if (mouseDelta.y > 0.0f) CameraMoveUp(camera, -cameraPanSpeed); + if (mouseDelta.y < 0.0f) CameraMoveUp(camera, cameraPanSpeed); + } + else + { + // Mouse support + CameraYaw(camera, -mousePositionDelta.x*CAMERA_MOUSE_MOVE_SENSITIVITY, rotateAroundTarget); + CameraPitch(camera, -mousePositionDelta.y*CAMERA_MOUSE_MOVE_SENSITIVITY, lockView, rotateAroundTarget, rotateUp); + } + + // Keyboard support + if (IsKeyDown(KEY_W)) CameraMoveForward(camera, cameraMoveSpeed, moveInWorldPlane); + if (IsKeyDown(KEY_A)) CameraMoveRight(camera, -cameraMoveSpeed, moveInWorldPlane); + if (IsKeyDown(KEY_S)) CameraMoveForward(camera, -cameraMoveSpeed, moveInWorldPlane); + if (IsKeyDown(KEY_D)) CameraMoveRight(camera, cameraMoveSpeed, moveInWorldPlane); + + // Gamepad movement + if (IsGamepadAvailable(0)) + { + // Gamepad controller support + CameraYaw(camera, -(GetGamepadAxisMovement(0, GAMEPAD_AXIS_RIGHT_X)*2)*CAMERA_MOUSE_MOVE_SENSITIVITY, rotateAroundTarget); + CameraPitch(camera, -(GetGamepadAxisMovement(0, GAMEPAD_AXIS_RIGHT_Y)*2)*CAMERA_MOUSE_MOVE_SENSITIVITY, lockView, rotateAroundTarget, rotateUp); + + if (GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_Y) <= -0.25f) CameraMoveForward(camera, cameraMoveSpeed, moveInWorldPlane); + if (GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_X) <= -0.25f) CameraMoveRight(camera, -cameraMoveSpeed, moveInWorldPlane); + if (GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_Y) >= 0.25f) CameraMoveForward(camera, -cameraMoveSpeed, moveInWorldPlane); + if (GetGamepadAxisMovement(0, GAMEPAD_AXIS_LEFT_X) >= 0.25f) CameraMoveRight(camera, cameraMoveSpeed, moveInWorldPlane); + } + + if (mode == CAMERA_FREE) + { + if (IsKeyDown(KEY_SPACE)) CameraMoveUp(camera, cameraMoveSpeed); + if (IsKeyDown(KEY_LEFT_CONTROL)) CameraMoveUp(camera, -cameraMoveSpeed); + } + } + + if ((mode == CAMERA_THIRD_PERSON) || (mode == CAMERA_ORBITAL) || (mode == CAMERA_FREE)) + { + // Zoom target distance + CameraMoveToTarget(camera, -GetMouseWheelMove()); + if (IsKeyPressed(KEY_KP_SUBTRACT)) CameraMoveToTarget(camera, 2.0f); + if (IsKeyPressed(KEY_KP_ADD)) CameraMoveToTarget(camera, -2.0f); + } +} +#endif // !RCAMERA_STANDALONE + +// Update camera movement, movement/rotation values should be provided by user +void UpdateCameraPro(Camera *camera, Vector3 movement, Vector3 rotation, float zoom) +{ + // Required values + // movement.x - Move forward/backward + // movement.y - Move right/left + // movement.z - Move up/down + // rotation.x - yaw + // rotation.y - pitch + // rotation.z - roll + // zoom - Move towards target + + bool lockView = true; + bool rotateAroundTarget = false; + bool rotateUp = false; + bool moveInWorldPlane = true; + + // Camera rotation + CameraPitch(camera, -rotation.y*DEG2RAD, lockView, rotateAroundTarget, rotateUp); + CameraYaw(camera, -rotation.x*DEG2RAD, rotateAroundTarget); + CameraRoll(camera, rotation.z*DEG2RAD); + + // Camera movement + CameraMoveForward(camera, movement.x, moveInWorldPlane); + CameraMoveRight(camera, movement.y, moveInWorldPlane); + CameraMoveUp(camera, movement.z); + + // Zoom target distance + CameraMoveToTarget(camera, zoom); +} + +#endif // RCAMERA_IMPLEMENTATION diff --git a/pufferlib/ocean/impulse_wars/include/rlights.h b/vendor/rlights.h similarity index 97% rename from pufferlib/ocean/impulse_wars/include/rlights.h rename to vendor/rlights.h index e84009bf65..aba907b5fb 100644 --- a/pufferlib/ocean/impulse_wars/include/rlights.h +++ b/vendor/rlights.h @@ -36,7 +36,7 @@ //---------------------------------------------------------------------------------- // Defines and Macros //---------------------------------------------------------------------------------- -#define MAX_LIGHTS 64 // Max dynamic lights supported by shader +#define MAX_LIGHTS 4 // Max dynamic lights supported by shader //---------------------------------------------------------------------------------- // Types and Structures Definition @@ -109,7 +109,7 @@ void UpdateLightValues(Shader shader, Light light); // Send light proper static int lightsCount = 0; // Current amount of created lights //---------------------------------------------------------------------------------- -// Module specific Functions Declaration +// Module Internal Functions Declaration //---------------------------------------------------------------------------------- // ... @@ -167,4 +167,4 @@ void UpdateLightValues(Shader shader, Light light) SetShaderValue(shader, light.colorLoc, color, SHADER_UNIFORM_VEC4); } -#endif // RLIGHTS_IMPLEMENTATION +#endif // RLIGHTS_IMPLEMENTATION \ No newline at end of file