commit
2007fb7edc
200 files changed
+27710
No files matched your search
Executable
+84
@@ -0,0 +1,84 @@
|
||||
#!/usr/bin/env bash
|
||||
# Checks the simulation is deterministic across builds and platforms, which desktop/web crossplay depends on.
|
||||
#
|
||||
# Fails if any source calls the maths library's transcendentals (src/dmath.h replaces them), then builds the game
|
||||
# several ways and plays the same seeded bot matches in each (--balance with RPG_SEED), comparing the determinism hash
|
||||
# they print:
|
||||
# gcc GCC, optimised (the usual build)
|
||||
# gcc-fma GCC for this CPU (with FMA if it has it, standing in for arm64's fused multiply-adds)
|
||||
# clang-O0 Clang, unoptimised
|
||||
# wasm Emscripten, run under node (needs EMSDK, or emsdk_env.sh sourced)
|
||||
#
|
||||
# Usage: tools/determinism_check.sh [matches per seed, default 20] [seeds, default "1 2 3"]
|
||||
set -euo pipefail
|
||||
|
||||
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
||||
OUT="$ROOT/build-check"
|
||||
MATCHES="${1:-20}"
|
||||
SEEDS="${2:-1 2 3}"
|
||||
|
||||
banned=$(grep -nE "std::(sin|cos|tan|atan2|atan|asin|acos|exp|exp2|expm1|log|log2|log10|log1p|pow|hypot|cbrt|sinh|cosh|tanh|lerp)\(|\b(sinf|cosf|tanf|atan2f|powf|expf|logf|log2f)\(|SDL_(sin|cos|tan|atan2|atan|pow|exp|log)f?\(" \
|
||||
"$ROOT"/src/*.cpp "$ROOT"/src/*.h | grep -v "src/dmath.h" || true)
|
||||
if [ -n "$banned" ]; then
|
||||
echo "Maths library transcendentals in the source (use math_sin and friends from src/dmath.h):"
|
||||
echo "$banned"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
configure() # name, cmake arguments...
|
||||
{
|
||||
local name="$1"
|
||||
shift
|
||||
if [ ! -f "$OUT/$name/build.ninja" ]; then
|
||||
cmake -S "$ROOT" -B "$OUT/$name" -G Ninja "$@" > "$OUT/$name.log" 2>&1
|
||||
fi
|
||||
cmake --build "$OUT/$name" >> "$OUT/$name.log" 2>&1 || {
|
||||
echo "$name failed to build, see $OUT/$name.log"
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
|
||||
mkdir -p "$OUT"
|
||||
names=(gcc gcc-fma clang-O0)
|
||||
configure gcc -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++
|
||||
configure gcc-fma -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ \
|
||||
-DCMAKE_CXX_FLAGS=-march=native -DCMAKE_C_FLAGS=-march=native
|
||||
configure clang-O0 -DCMAKE_BUILD_TYPE=Debug -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++
|
||||
if [ -n "${EMSDK:-}" ] || command -v emcmake > /dev/null; then
|
||||
[ -n "${EMSDK:-}" ] && source "$EMSDK/emsdk_env.sh" > /dev/null 2>&1
|
||||
if [ ! -f "$OUT/wasm/build.ninja" ]; then
|
||||
emcmake cmake -S "$ROOT" -B "$OUT/wasm" -G Ninja -DCMAKE_BUILD_TYPE=Release -DRPG_NODE=ON > "$OUT/wasm.log" 2>&1
|
||||
fi
|
||||
cmake --build "$OUT/wasm" >> "$OUT/wasm.log" 2>&1 || {
|
||||
echo "wasm failed to build, see $OUT/wasm.log"
|
||||
exit 1
|
||||
}
|
||||
names+=(wasm)
|
||||
else
|
||||
echo "Emscripten not found (set EMSDK): skipping the wasm build."
|
||||
fi
|
||||
|
||||
hash_get() # name, seed
|
||||
{
|
||||
local run=("$OUT/$1/smack-a-brother")
|
||||
[ "$1" = wasm ] && run=(node "$OUT/wasm/smack-a-brother.js")
|
||||
(cd "$OUT/$1" && RPG_SEED="$2" "${run[@]}" --balance "$MATCHES" 2>&1 | grep -oE "hash: [0-9a-f]+" | cut -d' ' -f2)
|
||||
}
|
||||
|
||||
failed=0
|
||||
for seed in $SEEDS; do
|
||||
line="seed $seed:"
|
||||
first=""
|
||||
for name in "${names[@]}"; do
|
||||
hash=$(hash_get "$name" "$seed")
|
||||
line+=" $name $hash"
|
||||
[ -z "$first" ] && first="$hash"
|
||||
[ "$hash" != "$first" ] && failed=1
|
||||
done
|
||||
echo "$line"
|
||||
done
|
||||
if [ "$failed" = 1 ]; then
|
||||
echo "DESYNC: the builds disagree."
|
||||
exit 1
|
||||
fi
|
||||
echo "Deterministic: every build agrees."
|
||||
Reference in new issue
Block a user