mirror of
https://github.com/nolen777/eagle0.git
synced 2026-07-29 04:05:44 +00:00
Compare commits
238
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c541085956 | ||
|
|
c97c141155 | ||
|
|
72ea2de25c | ||
|
|
4b559c2278 | ||
|
|
327ecf1aed | ||
|
|
8fc893ce08 | ||
|
|
0ec0e10c0f | ||
|
|
38c7a01743 | ||
|
|
a481b5ce60 | ||
|
|
7786db1040 | ||
|
|
200aa0d319 | ||
|
|
c8bb543907 | ||
|
|
de7ecf45d1 | ||
|
|
f25298ed9e | ||
|
|
d4ea2fbd93 | ||
|
|
79c51fb21a | ||
|
|
c57c9b5f18 | ||
|
|
823cd73d33 | ||
|
|
54db4b6e34 | ||
|
|
112399d67c | ||
|
|
01b80d8798 | ||
|
|
f6a3f36a13 | ||
|
|
d674e23987 | ||
|
|
51aebf5e40 | ||
|
|
2ec6d2f1d7 | ||
|
|
9f94917a2d | ||
|
|
06f2104750 | ||
|
|
b1e1e36236 | ||
|
|
9eb2056ac6 | ||
|
|
0c3cb22e83 | ||
|
|
92f27ba273 | ||
|
|
47d682e7c1 | ||
|
|
75d84b67ff | ||
|
|
be8f5ca5da | ||
|
|
c7910a6183 | ||
|
|
98afc28762 | ||
|
|
4cd1349a5a | ||
|
|
cebac64264 | ||
|
|
172125e03b | ||
|
|
15006091b4 | ||
|
|
2175f1d957 | ||
|
|
d445cbfe25 | ||
|
|
5fc56c342d | ||
|
|
e5350d03a8 | ||
|
|
097daf3dc1 | ||
|
|
3c3dc85187 | ||
|
|
a775a667f6 | ||
|
|
a1a7a69aeb | ||
|
|
ff549ab337 | ||
|
|
464651503e | ||
|
|
2f93250c8e | ||
|
|
22ce7ba750 | ||
|
|
acbb09f6a1 | ||
|
|
900dd23ae7 | ||
|
|
0f391776aa | ||
|
|
817fb613ab | ||
|
|
2f57ea0160 | ||
|
|
f5d5aedf9d | ||
|
|
c5114e9bf1 | ||
|
|
7514aed437 | ||
|
|
f4d381c9d4 | ||
|
|
8698036f7c | ||
|
|
21f04cfd46 | ||
|
|
074cf62cc9 | ||
|
|
a66f833c90 | ||
|
|
d704d23d39 | ||
|
|
e2570aec4a | ||
|
|
6b97fde9ab | ||
|
|
30adf1bcbf | ||
|
|
f205b49a54 | ||
|
|
5c7e18696e | ||
|
|
c78b00b0fc | ||
|
|
b05d6e1e1b | ||
|
|
da0bce655c | ||
|
|
d4dcbcc9d5 | ||
|
|
f132e5b87b | ||
|
|
872475e82b | ||
|
|
66d062bfda | ||
|
|
a514ceb62f | ||
|
|
b0d8a5bc41 | ||
|
|
8f4bb5130e | ||
|
|
9386589558 | ||
|
|
5945289a81 | ||
|
|
53346cc85b | ||
|
|
a6fad3ac4e | ||
|
|
cb7e2b5d5c | ||
|
|
0f764416a3 | ||
|
|
c9e0012bf7 | ||
|
|
457f2a677a | ||
|
|
ced56ee41f | ||
|
|
4e910f1f22 | ||
|
|
34bceebace | ||
|
|
b4f802ba77 | ||
|
|
3d9d464870 | ||
|
|
a7e21427f9 | ||
|
|
bdbf10294b | ||
|
|
8588430cf0 | ||
|
|
d920bb5c17 | ||
|
|
64fe9bf59d | ||
|
|
101b0bf41f | ||
|
|
019865b5ee | ||
|
|
799d34a1f1 | ||
|
|
951d533ed3 | ||
|
|
459eb0ef7b | ||
|
|
f710105bd9 | ||
|
|
4998e3ce40 | ||
|
|
d739b374a4 | ||
|
|
bd61ebcbb6 | ||
|
|
3963275092 | ||
|
|
a796e0fe67 | ||
|
|
52ac61fa1d | ||
|
|
29ca7665b1 | ||
|
|
d9bdb814f4 | ||
|
|
3dfb094a08 | ||
|
|
7ce1818a7f | ||
|
|
6e6eff7991 | ||
|
|
aa9c98f081 | ||
|
|
cdf0ad45f0 | ||
|
|
1b97b6673f | ||
|
|
721d432bc6 | ||
|
|
e513a784eb | ||
|
|
ff8da78992 | ||
|
|
84a69ce982 | ||
|
|
7d743f8678 | ||
|
|
3f24e15392 | ||
|
|
0f86bb6874 | ||
|
|
05ee7a2ab2 | ||
|
|
b9321433d0 | ||
|
|
62791401e9 | ||
|
|
4d28bba9cc | ||
|
|
1f3660e1f3 | ||
|
|
95ff44e205 | ||
|
|
987a164092 | ||
|
|
1b5b11fd5b | ||
|
|
ddcde52e27 | ||
|
|
ea2da84535 | ||
|
|
abed8ee574 | ||
|
|
556c59a9c7 | ||
|
|
ad2d085b24 | ||
|
|
d7209102b8 | ||
|
|
14e1ba6795 | ||
|
|
65b56081ce | ||
|
|
eafb51cbfa | ||
|
|
3444ae296e | ||
|
|
4f2fff5da6 | ||
|
|
144483a45d | ||
|
|
53345b2bb0 | ||
|
|
5d6bc429b0 | ||
|
|
a4faf61613 | ||
|
|
fdd516598d | ||
|
|
70da6990c4 | ||
|
|
e8b18d0805 | ||
|
|
1ca9e8678c | ||
|
|
94670149fe | ||
|
|
8e253c2972 | ||
|
|
6e15c6d9cb | ||
|
|
ca00e90ad6 | ||
|
|
b1d76ea661 | ||
|
|
059d428cfa | ||
|
|
a4b50eb357 | ||
|
|
0dfd5aa11d | ||
|
|
2b63ccd145 | ||
|
|
97cec5ec38 | ||
|
|
31fb5a3616 | ||
|
|
7b7130d67d | ||
|
|
6707ad55ff | ||
|
|
89aa73b63a | ||
|
|
bb7453a002 | ||
|
|
8cea29dcb0 | ||
|
|
d5d74ec8d6 | ||
|
|
9b000b94ac | ||
|
|
82ed9fcc83 | ||
|
|
cd53283935 | ||
|
|
3faddf76f8 | ||
|
|
6e24ae2f4f | ||
|
|
66912580c8 | ||
|
|
219dd830e1 | ||
|
|
3d5cdcc78e | ||
|
|
ab1d43fae3 | ||
|
|
2d51f3c23d | ||
|
|
f9447cf7aa | ||
|
|
c6ed0bfc7d | ||
|
|
2d4621b1a6 | ||
|
|
3bf929b4a5 | ||
|
|
ebed01ba86 | ||
|
|
880d005347 | ||
|
|
e8ef216de8 | ||
|
|
baa453594a | ||
|
|
9c767d5c49 | ||
|
|
e0892bd2fa | ||
|
|
315be7c465 | ||
|
|
9d34dc0954 | ||
|
|
bdedd43e3c | ||
|
|
97e779675e | ||
|
|
2ef4216886 | ||
|
|
8c9764a57e | ||
|
|
eb94eb1a6d | ||
|
|
12e3fb99eb | ||
|
|
2bd90a26a8 | ||
|
|
24db3a4cb1 | ||
|
|
0d05ea1730 | ||
|
|
9c13b3c1bf | ||
|
|
492d9d16eb | ||
|
|
c4cd0eb683 | ||
|
|
287f7b9818 | ||
|
|
15b5a3e0c1 | ||
|
|
cf93c43ef2 | ||
|
|
380c24537b | ||
|
|
6200bc7e02 | ||
|
|
e92465c894 | ||
|
|
6f432d221a | ||
|
|
b8ddca4e76 | ||
|
|
f343ee9f7f | ||
|
|
9a8c4c6fdd | ||
|
|
96f2dc0454 | ||
|
|
e0988ef186 | ||
|
|
a154174fa1 | ||
|
|
042861f065 | ||
|
|
0f776af050 | ||
|
|
166e50924f | ||
|
|
efb34ede56 | ||
|
|
22b55eb223 | ||
|
|
f5d9027206 | ||
|
|
9dcbeff21a | ||
|
|
0cc7c4d0a2 | ||
|
|
b0ca65b720 | ||
|
|
e3eb3eb7bf | ||
|
|
b8b2c92227 | ||
|
|
424dde5da6 | ||
|
|
ce7e636987 | ||
|
|
c51f61ba56 | ||
|
|
91623bcf7a | ||
|
|
34e14a3521 | ||
|
|
6c1a79b342 | ||
|
|
6af5014866 | ||
|
|
16f53dc1b1 | ||
|
|
df09fe0684 | ||
|
|
e765764cea |
@@ -177,10 +177,12 @@ jobs:
|
||||
env:
|
||||
DO_CDN_PAT: ${{ secrets.DO_CDN_PAT }}
|
||||
run: |
|
||||
UNITY_VERSION=$(grep "m_EditorVersion:" src/main/csharp/net/eagle0/clients/unity/eagle0/ProjectSettings/ProjectVersion.txt | head -1 | sed 's/m_EditorVersion: //')
|
||||
UNITY_MAJOR_MINOR=$(echo "$UNITY_VERSION" | sed -E 's/^([0-9]+)\.([0-9]+).*/\1.\2/')
|
||||
curl -s -X DELETE "https://api.digitalocean.com/v2/cdn/endpoints/8c98df29-6f0c-4704-8e82-ca40a2b81aa8/cache" \
|
||||
-H "Authorization: Bearer $DO_CDN_PAT" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"files": ["addressables/iOS/*"]}' \
|
||||
-d "{\"files\": [\"addressables/iOS/$UNITY_MAJOR_MINOR/*\"]}" \
|
||||
--fail || echo "Warning: CDN purge failed (non-fatal)"
|
||||
|
||||
- name: Archive Build Log
|
||||
|
||||
@@ -50,11 +50,9 @@ on:
|
||||
- "scripts/notarize_wait.sh"
|
||||
- "ci/github_actions/build_mac.sh"
|
||||
- "ci/github_actions/build_unity_mac.sh"
|
||||
- "ci/github_actions/ensure_unity_installed.sh"
|
||||
- "ci/github_actions/ensure_bazel_installed.sh"
|
||||
- ".github/actions/setup-bazel/**"
|
||||
- "ci/github_actions/detect_addressables_changes.sh"
|
||||
- "src/main/csharp/net/eagle0/clients/unity/eagle0/ProjectSettings/ProjectVersion.txt"
|
||||
- "src/main/csharp/net/eagle0/clients/unity/eagle0/ProjectSettings/ProjectSettings.asset"
|
||||
- ".bazelrc"
|
||||
- "ci/mac/**"
|
||||
@@ -125,25 +123,11 @@ jobs:
|
||||
- name: Clean stale files
|
||||
run: |
|
||||
git clean -ffd
|
||||
LIBRARY_DIR="src/main/csharp/net/eagle0/clients/unity/eagle0/Library"
|
||||
VERSION_CACHE="$LIBRARY_DIR/.last_unity_version"
|
||||
PROJECT_VERSION_FILE="src/main/csharp/net/eagle0/clients/unity/eagle0/ProjectSettings/ProjectVersion.txt"
|
||||
CURRENT_VERSION=$(grep "m_EditorVersion:" "$PROJECT_VERSION_FILE" | head -1 | sed 's/m_EditorVersion: //')
|
||||
|
||||
# Nuke Library/ when Unity version changes to avoid import loops
|
||||
if [ -f "$VERSION_CACHE" ]; then
|
||||
CACHED_VERSION=$(cat "$VERSION_CACHE")
|
||||
if [ "$CACHED_VERSION" != "$CURRENT_VERSION" ]; then
|
||||
echo "Unity version changed ($CACHED_VERSION -> $CURRENT_VERSION) -- clearing Library/"
|
||||
rm -rf "$LIBRARY_DIR"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Only clear Bee/ when C# files were added/deleted/renamed (structural
|
||||
# changes that stale the DAG). Content-only modifications are handled by
|
||||
# Bee's incremental compilation. See persist_library.sh for background.
|
||||
BEE_DIR="$LIBRARY_DIR/Bee"
|
||||
SHA_FILE="$LIBRARY_DIR/.last_built_sha"
|
||||
BEE_DIR="src/main/csharp/net/eagle0/clients/unity/eagle0/Library/Bee"
|
||||
SHA_FILE="src/main/csharp/net/eagle0/clients/unity/eagle0/Library/.last_built_sha"
|
||||
if [ -f "$SHA_FILE" ] && [ -d "$BEE_DIR" ]; then
|
||||
LAST_SHA=$(cat "$SHA_FILE")
|
||||
if git diff --diff-filter=ADR --name-only "$LAST_SHA" HEAD -- '*.cs' '*.csproj' '*.asmdef' 2>/dev/null | grep -q .; then
|
||||
@@ -200,12 +184,6 @@ jobs:
|
||||
mkdir -p src/main/csharp/net/eagle0/clients/unity/eagle0/Library
|
||||
git rev-parse HEAD > src/main/csharp/net/eagle0/clients/unity/eagle0/Library/.last_built_sha
|
||||
|
||||
- name: Save Unity version for Library/ cache invalidation
|
||||
if: success()
|
||||
run: |
|
||||
mkdir -p src/main/csharp/net/eagle0/clients/unity/eagle0/Library
|
||||
grep "m_EditorVersion:" src/main/csharp/net/eagle0/clients/unity/eagle0/ProjectSettings/ProjectVersion.txt | head -1 | sed 's/m_EditorVersion: //' > src/main/csharp/net/eagle0/clients/unity/eagle0/Library/.last_unity_version
|
||||
|
||||
- name: Check if should deploy
|
||||
id: check-deploy
|
||||
run: |
|
||||
@@ -267,6 +245,7 @@ jobs:
|
||||
runs-on: [self-hosted, macOS, notarize]
|
||||
outputs:
|
||||
deployed_version: ${{ steps.deploy-mac.outputs.deployed_version }}
|
||||
deployed_unity_major_minor: ${{ steps.deploy-mac.outputs.deployed_unity_major_minor }}
|
||||
concurrency:
|
||||
group: mac-deploy-${{ github.ref }}
|
||||
cancel-in-progress: false
|
||||
@@ -495,6 +474,9 @@ jobs:
|
||||
rm "$SPARKLE_PRIVATE_KEY_PATH"
|
||||
|
||||
echo "deployed_version=$VERSION" >> $GITHUB_OUTPUT
|
||||
UNITY_VERSION=$(grep "m_EditorVersion:" src/main/csharp/net/eagle0/clients/unity/eagle0/ProjectSettings/ProjectVersion.txt | head -1 | sed 's/m_EditorVersion: //')
|
||||
UNITY_MAJOR_MINOR=$(echo "$UNITY_VERSION" | sed -E 's/^([0-9]+)\.([0-9]+).*/\1.\2/')
|
||||
echo "deployed_unity_major_minor=$UNITY_MAJOR_MINOR" >> $GITHUB_OUTPUT
|
||||
|
||||
# Artifact cleanup is handled by the cleanup job on ubuntu-latest
|
||||
- name: Cleanup build directory
|
||||
@@ -515,7 +497,7 @@ jobs:
|
||||
curl -s -X DELETE "https://api.digitalocean.com/v2/cdn/endpoints/8c98df29-6f0c-4704-8e82-ca40a2b81aa8/cache" \
|
||||
-H "Authorization: Bearer $DO_CDN_PAT" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"files": ["mac/*", "addressables/StandaloneOSX/*"]}' \
|
||||
-d '{"files": ["mac/*", "addressables/StandaloneOSX/${{ needs.deploy-mac.outputs.deployed_unity_major_minor }}/*"]}' \
|
||||
--fail || echo "Warning: CDN purge failed (non-fatal)"
|
||||
|
||||
curl -X POST "https://admin.eagle0.net/notify-update?platform=mac&version=${{ needs.deploy-mac.outputs.deployed_version }}&required=false" \
|
||||
|
||||
@@ -20,6 +20,7 @@ on:
|
||||
- 'ci/github_actions/ensure_bazel_installed.sh'
|
||||
- 'scripts/build_eagle_ci.sh'
|
||||
- 'scripts/build_shardok_ci.sh'
|
||||
- 'scripts/build_shardok_linux_arm64_ci.sh'
|
||||
- '.github/actions/setup-bazel/**'
|
||||
- '.github/workflows/server_build.yml'
|
||||
|
||||
@@ -83,6 +84,7 @@ jobs:
|
||||
'src/main/cpp/',
|
||||
'src/main/protobuf/net/eagle0/shardok/',
|
||||
'scripts/build_shardok_ci.sh',
|
||||
'scripts/build_shardok_linux_arm64_ci.sh',
|
||||
];
|
||||
|
||||
const shared = matches(sharedPatterns);
|
||||
@@ -106,6 +108,10 @@ jobs:
|
||||
name: 'Shardok server',
|
||||
command: './scripts/build_shardok_ci.sh',
|
||||
});
|
||||
include.push({
|
||||
name: 'Shardok Linux ARM64 server',
|
||||
command: './scripts/build_shardok_linux_arm64_ci.sh',
|
||||
});
|
||||
}
|
||||
core.setOutput('build_matrix', JSON.stringify({include}));
|
||||
|
||||
|
||||
@@ -294,7 +294,7 @@ to be used for different players or game situations within the same server proce
|
||||
**C# (Unity Client):**
|
||||
|
||||
- Located in `/src/main/csharp/net/eagle0/clients/unity/eagle0/`
|
||||
- Uses Unity 6.5 (6000.5.0f1) with comprehensive protobuf integration (100+ .proto files)
|
||||
- Uses Unity 6 (6000.4.10f1) with comprehensive protobuf integration (100+ .proto files)
|
||||
- Key components: `EagleConnection.cs` (gRPC client), `EagleGameController.cs` (main game logic)
|
||||
- Real-time bidirectional streaming with server via `PersistentClientConnection.cs`
|
||||
- Strategic map UI in `Assets/Eagle/`, tactical battle UI in `Assets/Shardok/`
|
||||
|
||||
+1
-1
@@ -282,7 +282,7 @@ oci.pull(
|
||||
# Base image for Admin Server (Alpine for lightweight Go binary)
|
||||
oci.pull(
|
||||
name = "alpine_linux",
|
||||
digest = "sha256:a2d49ea686c2adfe3c992e47dc3b5e7fa6e6b5055609400dc2acaeb241c829f4",
|
||||
digest = "sha256:28bd5fe8b56d1bd048e5babf5b10710ebe0bae67db86916198a6eec434943f8b",
|
||||
image = "docker.io/library/alpine",
|
||||
platforms = ["linux/amd64"],
|
||||
tag = "3.24",
|
||||
|
||||
Generated
+8
-8
@@ -904,7 +904,7 @@
|
||||
"@@rules_oci+//oci:extensions.bzl%oci": {
|
||||
"general": {
|
||||
"bzlTransitiveDigest": "H23W9dvwCQM6h+Wt8PjIahx08EkAU5eSbUxAyx9Mopc=",
|
||||
"usagesDigest": "tbQ7wHHObzzrBzSRv652104GY3xxiaQDK5OUp2YeEbg=",
|
||||
"usagesDigest": "k6DBHAkb5br/tpwCPUMJgqwb+7U4DXyCmBZQBgLnHJ8=",
|
||||
"recordedInputs": [
|
||||
"REPO_MAPPING:aspect_bazel_lib+,bazel_tools bazel_tools",
|
||||
"REPO_MAPPING:bazel_features+,bazel_tools bazel_tools",
|
||||
@@ -922,7 +922,7 @@
|
||||
"scheme": "https",
|
||||
"registry": "index.docker.io",
|
||||
"repository": "library/eclipse-temurin",
|
||||
"identifier": "sha256:db3011b348ad87ced055afe5145238d87a3d8f0e8f23eb4d0cd8cecb4659b085",
|
||||
"identifier": "sha256:0beb258e10ad28d2bae0f74349a170bdfa67da0ef87c028cbf3d95c3e1170120",
|
||||
"platform": "linux/amd64",
|
||||
"target_name": "eclipse_temurin_25_jre_linux_amd64",
|
||||
"bazel_tags": []
|
||||
@@ -936,7 +936,7 @@
|
||||
"scheme": "https",
|
||||
"registry": "index.docker.io",
|
||||
"repository": "library/eclipse-temurin",
|
||||
"identifier": "sha256:db3011b348ad87ced055afe5145238d87a3d8f0e8f23eb4d0cd8cecb4659b085",
|
||||
"identifier": "sha256:0beb258e10ad28d2bae0f74349a170bdfa67da0ef87c028cbf3d95c3e1170120",
|
||||
"platforms": {
|
||||
"@@platforms//cpu:x86_64": "@eclipse_temurin_25_jre_linux_amd64"
|
||||
},
|
||||
@@ -980,7 +980,7 @@
|
||||
"scheme": "https",
|
||||
"registry": "index.docker.io",
|
||||
"repository": "library/ubuntu",
|
||||
"identifier": "24.04",
|
||||
"identifier": "26.04",
|
||||
"platform": "linux/amd64",
|
||||
"target_name": "ubuntu_24_04_linux_amd64",
|
||||
"bazel_tags": []
|
||||
@@ -993,7 +993,7 @@
|
||||
"scheme": "https",
|
||||
"registry": "index.docker.io",
|
||||
"repository": "library/ubuntu",
|
||||
"identifier": "24.04",
|
||||
"identifier": "26.04",
|
||||
"platform": "linux/arm64/v8",
|
||||
"target_name": "ubuntu_24_04_linux_arm64_v8",
|
||||
"bazel_tags": []
|
||||
@@ -1007,7 +1007,7 @@
|
||||
"scheme": "https",
|
||||
"registry": "index.docker.io",
|
||||
"repository": "library/ubuntu",
|
||||
"identifier": "24.04",
|
||||
"identifier": "26.04",
|
||||
"platforms": {
|
||||
"@@platforms//cpu:x86_64": "@ubuntu_24_04_linux_amd64",
|
||||
"@@platforms//cpu:arm64": "@ubuntu_24_04_linux_arm64_v8"
|
||||
@@ -1023,7 +1023,7 @@
|
||||
"scheme": "https",
|
||||
"registry": "index.docker.io",
|
||||
"repository": "library/alpine",
|
||||
"identifier": "sha256:a2d49ea686c2adfe3c992e47dc3b5e7fa6e6b5055609400dc2acaeb241c829f4",
|
||||
"identifier": "sha256:28bd5fe8b56d1bd048e5babf5b10710ebe0bae67db86916198a6eec434943f8b",
|
||||
"platform": "linux/amd64",
|
||||
"target_name": "alpine_linux_linux_amd64",
|
||||
"bazel_tags": []
|
||||
@@ -1037,7 +1037,7 @@
|
||||
"scheme": "https",
|
||||
"registry": "index.docker.io",
|
||||
"repository": "library/alpine",
|
||||
"identifier": "sha256:a2d49ea686c2adfe3c992e47dc3b5e7fa6e6b5055609400dc2acaeb241c829f4",
|
||||
"identifier": "sha256:28bd5fe8b56d1bd048e5babf5b10710ebe0bae67db86916198a6eec434943f8b",
|
||||
"platforms": {
|
||||
"@@platforms//cpu:x86_64": "@alpine_linux_linux_amd64"
|
||||
},
|
||||
|
||||
@@ -5,8 +5,7 @@ set -x
|
||||
|
||||
COMMAND_LOG="$(bazel info command_log)"
|
||||
bazel build \
|
||||
//src/main/cpp/net/eagle0/shardok:shardok-server \
|
||||
//src/main/cpp/net/eagle0/shardok:shardok-inspector
|
||||
//src/main/cpp/net/eagle0/shardok:shardok-server
|
||||
STATUS="$?"
|
||||
|
||||
if [ $STATUS -eq 0 ]
|
||||
@@ -26,7 +25,6 @@ echo "Setting up Shardok files..."
|
||||
/bin/cp -R ./bazel-bin/src/main/cpp/net/eagle0/shardok/shardok-server ./shardok/
|
||||
/bin/mkdir -p ./shardok/shardok-server.runfiles/net_eagle0/src/main/
|
||||
/bin/cp -R ./bazel-bin/src/main/cpp/net/eagle0/shardok/shardok-server.runfiles/net_eagle0/src/main/resources ./shardok/shardok-server.runfiles/net_eagle0/src/main/
|
||||
/bin/cp -R ./bazel-bin/src/main/cpp/net/eagle0/shardok/shardok-inspector ./shardok/
|
||||
|
||||
echo "tar & zip shardok files..."
|
||||
/bin/tar cfh - shardok | /usr/bin/pigz > ./deploy/shardok.tar.gz
|
||||
|
||||
@@ -49,7 +49,7 @@ check_modules_installed() {
|
||||
fi
|
||||
;;
|
||||
mac)
|
||||
if ! has_mac_il2cpp_support "$unity_path" "$unity_app_contents_path"; then
|
||||
if ! has_il2cpp_variation "${unity_app_contents_path}/PlaybackEngines/MacStandaloneSupport/Variations"; then
|
||||
echo "✗ Mac IL2CPP module not installed for Unity ${UNITY_VERSION}"
|
||||
return 1
|
||||
fi
|
||||
@@ -67,7 +67,7 @@ check_modules_installed() {
|
||||
echo "✗ iOS module missing"
|
||||
missing=1
|
||||
fi
|
||||
if ! has_mac_il2cpp_support "$unity_path" "$unity_app_contents_path"; then
|
||||
if ! has_il2cpp_variation "${unity_app_contents_path}/PlaybackEngines/MacStandaloneSupport/Variations"; then
|
||||
echo "✗ Mac IL2CPP module missing"
|
||||
missing=1
|
||||
fi
|
||||
@@ -84,14 +84,6 @@ check_modules_installed() {
|
||||
return 0
|
||||
}
|
||||
|
||||
has_mac_il2cpp_support() {
|
||||
local unity_path="$1"
|
||||
local unity_app_contents_path="$2"
|
||||
|
||||
has_il2cpp_variation "${unity_app_contents_path}/PlaybackEngines/MacStandaloneSupport/Variations" ||
|
||||
has_il2cpp_variation "${unity_path}/PlaybackEngines/MacStandaloneSupport/Variations"
|
||||
}
|
||||
|
||||
has_il2cpp_variation() {
|
||||
local variations_path="$1"
|
||||
local variation
|
||||
|
||||
@@ -13,7 +13,10 @@ set -euxo pipefail
|
||||
BUILD_TARGET=$1
|
||||
WORKSPACE=$(pwd)
|
||||
UNITY_PROJECT="$WORKSPACE/src/main/csharp/net/eagle0/clients/unity/eagle0"
|
||||
SERVER_DATA="$UNITY_PROJECT/ServerData/$BUILD_TARGET"
|
||||
UNITY_VERSION=$(grep "m_EditorVersion:" "$UNITY_PROJECT/ProjectSettings/ProjectVersion.txt" | head -1 | sed 's/m_EditorVersion: //')
|
||||
UNITY_MAJOR_MINOR=$(echo "$UNITY_VERSION" | sed -E 's/^([0-9]+)\.([0-9]+).*/\1.\2/')
|
||||
ADDRESSABLES_PREFIX="addressables/$BUILD_TARGET/$UNITY_MAJOR_MINOR"
|
||||
SERVER_DATA="$UNITY_PROJECT/ServerData/$BUILD_TARGET/$UNITY_MAJOR_MINOR"
|
||||
|
||||
# DigitalOcean Spaces configuration (same region as other eagle0 buckets)
|
||||
DO_ENDPOINT="https://sfo3.digitaloceanspaces.com"
|
||||
@@ -75,7 +78,7 @@ summarize_pending_uploads() {
|
||||
sorted_uploads_file=$(mktemp)
|
||||
trap 'rm -f "$sync_args_file" "$uploads_file" "$sorted_uploads_file"' RETURN
|
||||
|
||||
aws s3 sync "$SERVER_DATA" "s3://$DO_BUCKET/addressables/$BUILD_TARGET/" \
|
||||
aws s3 sync "$SERVER_DATA" "s3://$DO_BUCKET/$ADDRESSABLES_PREFIX/" \
|
||||
--endpoint-url "$DO_ENDPOINT" \
|
||||
--acl public-read \
|
||||
--size-only \
|
||||
@@ -178,7 +181,7 @@ if [ ! -d "$SERVER_DATA" ]; then
|
||||
fi
|
||||
|
||||
echo "Uploading Addressables bundles from $SERVER_DATA"
|
||||
echo "Target: s3://$DO_BUCKET/addressables/$BUILD_TARGET/"
|
||||
echo "Target: s3://$DO_BUCKET/$ADDRESSABLES_PREFIX/"
|
||||
|
||||
# Configure AWS CLI for DigitalOcean Spaces
|
||||
export AWS_ACCESS_KEY_ID="$ACCESS_KEY_ID"
|
||||
@@ -193,13 +196,13 @@ summarize_pending_uploads
|
||||
#
|
||||
# --delete removes files in destination that don't exist in source.
|
||||
# --acl public-read makes files publicly accessible.
|
||||
aws s3 sync "$SERVER_DATA" "s3://$DO_BUCKET/addressables/$BUILD_TARGET/" \
|
||||
aws s3 sync "$SERVER_DATA" "s3://$DO_BUCKET/$ADDRESSABLES_PREFIX/" \
|
||||
--endpoint-url "$DO_ENDPOINT" \
|
||||
--acl public-read \
|
||||
--size-only \
|
||||
--delete
|
||||
|
||||
aws s3 sync "$SERVER_DATA" "s3://$DO_BUCKET/addressables/$BUILD_TARGET/" \
|
||||
aws s3 sync "$SERVER_DATA" "s3://$DO_BUCKET/$ADDRESSABLES_PREFIX/" \
|
||||
--endpoint-url "$DO_ENDPOINT" \
|
||||
--acl public-read \
|
||||
--exclude "*" \
|
||||
@@ -208,4 +211,4 @@ aws s3 sync "$SERVER_DATA" "s3://$DO_BUCKET/addressables/$BUILD_TARGET/" \
|
||||
--include "*.json"
|
||||
|
||||
echo "Addressables upload complete"
|
||||
echo "Files available at: https://assets.eagle0.net/addressables/$BUILD_TARGET/"
|
||||
echo "Files available at: https://assets.eagle0.net/$ADDRESSABLES_PREFIX/"
|
||||
|
||||
Executable
+17
@@ -0,0 +1,17 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
bazel_cmd=(bazel)
|
||||
if [ -n "${BAZEL_OUTPUT_USER_ROOT:-}" ]; then
|
||||
bazel_cmd+=("--output_user_root=${BAZEL_OUTPUT_USER_ROOT}")
|
||||
fi
|
||||
if [ -n "${BAZEL_OUTPUT_BASE:-}" ]; then
|
||||
bazel_cmd+=("--output_base=${BAZEL_OUTPUT_BASE}")
|
||||
fi
|
||||
|
||||
"${bazel_cmd[@]}" build \
|
||||
--platforms=//:linux_arm64 \
|
||||
--extra_toolchains=@llvm_toolchain_linux_arm64//:cc-toolchain-aarch64-linux \
|
||||
"$@" \
|
||||
//src/main/cpp/net/eagle0/shardok:shardok-server
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <cstdio>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <mutex>
|
||||
|
||||
#include "tools/cpp/runfiles/runfiles.h"
|
||||
@@ -37,7 +38,7 @@ auto rloc(const string& execPath) -> string {
|
||||
const std::unique_ptr<Runfiles> runfiles(Runfiles::Create(execPath, &error));
|
||||
|
||||
if (runfiles == nullptr) {
|
||||
fprintf(stderr, "Error! %s\n", error.c_str());
|
||||
std::cerr << "Error! " << error << '\n';
|
||||
abort();
|
||||
// error handling
|
||||
}
|
||||
@@ -78,9 +79,9 @@ auto FilesystemUtils::MapFilesDirectory() -> string {
|
||||
|
||||
void FilesystemUtils::MakeDirectoryIfNecessary(const string& directoryPath) {
|
||||
if (fs::create_directories(directoryPath))
|
||||
fprintf(stderr, "Directory %s created\n", directoryPath.c_str());
|
||||
std::cerr << "Directory " << directoryPath << " created\n";
|
||||
else
|
||||
fprintf(stderr, "No new directory created for %s\n", directoryPath.c_str());
|
||||
std::cerr << "No new directory created for " << directoryPath << '\n';
|
||||
}
|
||||
|
||||
auto FilesystemUtils::SaveFilesDirectory() -> string {
|
||||
@@ -140,11 +141,11 @@ auto FilesystemUtils::AtomicallySaveToPath(const string& path, const byte_vector
|
||||
if (ostr.good()) {
|
||||
const int err = rename(tempPath.c_str(), path.c_str());
|
||||
if (err == -1) {
|
||||
fprintf(stderr, "Failed to move file to %s! Errno %d\n", path.c_str(), errno);
|
||||
std::cerr << "Failed to move file to " << path << "! Errno " << errno << '\n';
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "Failed writing to %s!\n", tempPath.c_str());
|
||||
std::cerr << "Failed writing to " << tempPath << "!\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -80,7 +80,7 @@ void EmitShardokLatencyTrace(
|
||||
out << "}";
|
||||
|
||||
std::scoped_lock lock(LogMutex());
|
||||
std::cerr << out.str() << std::endl;
|
||||
std::cerr << out.str() << '\n';
|
||||
}
|
||||
|
||||
ScopedShardokLatencyTrace::ScopedShardokLatencyTrace(
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <condition_variable>
|
||||
#include <functional>
|
||||
#include <future>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <queue>
|
||||
@@ -171,7 +172,7 @@ public:
|
||||
// Get detailed queue information for debugging
|
||||
void debug_queue_state() const {
|
||||
std::unique_lock<std::mutex> lock(const_cast<std::mutex&>(queue_mutex));
|
||||
printf("ThreadPool: Queue size: %zu\n", tasks.size());
|
||||
std::cout << "ThreadPool: Queue size: " << tasks.size() << '\n';
|
||||
if (!tasks.empty()) {
|
||||
// Create a copy to inspect priorities without modifying queue
|
||||
auto queue_copy = tasks;
|
||||
@@ -180,9 +181,9 @@ public:
|
||||
priorities.push_back(queue_copy.top().priority);
|
||||
queue_copy.pop();
|
||||
}
|
||||
printf("ThreadPool: Priorities in queue: ");
|
||||
for (int p : priorities) { printf("%d ", p); }
|
||||
printf("\n");
|
||||
std::cout << "ThreadPool: Priorities in queue: ";
|
||||
for (int p : priorities) { std::cout << p << ' '; }
|
||||
std::cout << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -197,4 +198,4 @@ public:
|
||||
|
||||
} // namespace eagle0::common
|
||||
|
||||
#endif // EAGLE0_THREADPOOL_HPP
|
||||
#endif // EAGLE0_THREADPOOL_HPP
|
||||
|
||||
@@ -9,9 +9,11 @@
|
||||
#include <fstream>
|
||||
#include <future>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
#include <mutex>
|
||||
#include <random>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <thread>
|
||||
|
||||
@@ -862,12 +864,12 @@ auto AbstractMCTSAI::LogSearchResults(
|
||||
// Log selected command
|
||||
const std::string selectedDesc =
|
||||
bestChild->action ? bestChild->action->getDescription() : "Unknown";
|
||||
printf("MCTS: Selected %s (visit:%d, reward:%.2f, lookahead:%.2f) from %zu options\n",
|
||||
selectedDesc.c_str(),
|
||||
bestChild->visitCount,
|
||||
bestChild->averageReward,
|
||||
bestChild->lookaheadScore,
|
||||
rootNode->children.size());
|
||||
std::ostringstream selectedLine;
|
||||
selectedLine << std::fixed << std::setprecision(2) << "MCTS: Selected " << selectedDesc
|
||||
<< " (visit:" << bestChild->visitCount << ", reward:" << bestChild->averageReward
|
||||
<< ", lookahead:" << bestChild->lookaheadScore << ") from "
|
||||
<< rootNode->children.size() << " options";
|
||||
std::cout << selectedLine.str() << '\n';
|
||||
|
||||
// Log top 3 actions by visits
|
||||
std::vector<const MCTSNode*> sortedChildren;
|
||||
@@ -879,20 +881,17 @@ auto AbstractMCTSAI::LogSearchResults(
|
||||
|
||||
// Show all actions if there are <= 10, otherwise top 5
|
||||
const size_t numToShow = sortedChildren.size() <= 10 ? sortedChildren.size() : 5;
|
||||
printf("MCTS: Top %zu actions by visits (out of %zu total):\n",
|
||||
numToShow,
|
||||
sortedChildren.size());
|
||||
std::cout << "MCTS: Top " << numToShow << " actions by visits (out of " << sortedChildren.size()
|
||||
<< " total):\n";
|
||||
for (size_t i = 0; i < numToShow; ++i) {
|
||||
const auto* child = sortedChildren[i];
|
||||
printf(" [%zu] visits:%d avgReward:%.2f immediate:%.2f lookahead:%.2f",
|
||||
i,
|
||||
child->visitCount,
|
||||
child->averageReward,
|
||||
child->immediateScore,
|
||||
child->lookaheadScore);
|
||||
std::ostringstream line;
|
||||
line << std::fixed << std::setprecision(2) << " [" << i << "] visits:" << child->visitCount
|
||||
<< " avgReward:" << child->averageReward << " immediate:" << child->immediateScore
|
||||
<< " lookahead:" << child->lookaheadScore;
|
||||
|
||||
// Show the action's own description
|
||||
if (child->action) { printf(" %s", child->action->getDescription().c_str()); }
|
||||
if (child->action) { line << ' ' << child->action->getDescription(); }
|
||||
|
||||
// Show sequence preview
|
||||
if (!child->children.empty()) {
|
||||
@@ -905,16 +904,15 @@ auto AbstractMCTSAI::LogSearchResults(
|
||||
}
|
||||
}
|
||||
if (bestNext && bestNext->action) {
|
||||
printf(" -> %s", bestNext->action->getDescription().c_str());
|
||||
line << " -> " << bestNext->action->getDescription();
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
std::cout << line.str() << '\n';
|
||||
}
|
||||
|
||||
printf("MCTS: Tree stats - max depth:%d, total nodes:%d, root visits:%d\n",
|
||||
result.searchDepth,
|
||||
result.nodesEvaluated,
|
||||
rootNode->visitCount);
|
||||
std::cout << "MCTS: Tree stats - max depth:" << result.searchDepth
|
||||
<< ", total nodes:" << result.nodesEvaluated
|
||||
<< ", root visits:" << rootNode->visitCount << '\n';
|
||||
|
||||
// Log best sequence from chosen action (following most-visited path)
|
||||
std::vector<const MCTSNode*> bestSequence;
|
||||
@@ -940,7 +938,10 @@ auto AbstractMCTSAI::LogSearchResults(
|
||||
}
|
||||
|
||||
if (!bestSequence.empty()) {
|
||||
printf("MCTS: Best sequence from chosen action (final: %.2f):\n", sequenceScore);
|
||||
std::ostringstream sequenceLine;
|
||||
sequenceLine << std::fixed << std::setprecision(2)
|
||||
<< "MCTS: Best sequence from chosen action (final: " << sequenceScore << "):";
|
||||
std::cout << sequenceLine.str() << '\n';
|
||||
int displayedStep = 0;
|
||||
for (size_t i = 0; i < bestSequence.size(); ++i) {
|
||||
const auto* node = bestSequence[i];
|
||||
@@ -949,29 +950,31 @@ auto AbstractMCTSAI::LogSearchResults(
|
||||
if (i > 0 && node->parent && node->parent->IsChanceNode()) { continue; }
|
||||
|
||||
displayedStep++;
|
||||
printf(" %d.", displayedStep);
|
||||
if (node->action) { printf(" %s", node->action->getDescription().c_str()); }
|
||||
std::ostringstream line;
|
||||
line << " " << displayedStep << ".";
|
||||
if (node->action) { line << ' ' << node->action->getDescription(); }
|
||||
|
||||
// If this is a chance node, display outcome probabilities and scores
|
||||
if (node->IsChanceNode() && !node->outcomeProbabilities.empty()) {
|
||||
printf(" [");
|
||||
line << " [";
|
||||
for (size_t j = 0; j < node->outcomeProbabilities.size(); ++j) {
|
||||
if (j > 0) printf(", ");
|
||||
if (j > 0) { line << ", "; }
|
||||
const double prob = node->outcomeProbabilities[j] * 100;
|
||||
// Show lookahead score for each outcome if child exists
|
||||
if (j < node->children.size() && node->children[j]->visitCount > 0) {
|
||||
printf("%.0f%%->%.1f", prob, node->children[j]->lookaheadScore);
|
||||
line << std::fixed << std::setprecision(0) << prob << "%->"
|
||||
<< std::setprecision(1) << node->children[j]->lookaheadScore;
|
||||
} else {
|
||||
printf("%.0f%%->?", prob);
|
||||
line << std::fixed << std::setprecision(0) << prob << "%->?";
|
||||
}
|
||||
}
|
||||
printf("]");
|
||||
line << "]";
|
||||
}
|
||||
|
||||
printf(" (visits:%d, immediate:%.2f, lookahead:%.2f)\n",
|
||||
node->visitCount,
|
||||
node->immediateScore,
|
||||
node->lookaheadScore);
|
||||
line << std::fixed << std::setprecision(2) << " (visits:" << node->visitCount
|
||||
<< ", immediate:" << node->immediateScore << ", lookahead:" << node->lookaheadScore
|
||||
<< ")";
|
||||
std::cout << line.str() << '\n';
|
||||
|
||||
// For non-root nodes in the sequence, show what the top alternatives were
|
||||
// Skip showing alternatives for chance nodes (they have outcome children, not action
|
||||
@@ -991,17 +994,17 @@ auto AbstractMCTSAI::LogSearchResults(
|
||||
});
|
||||
|
||||
// Show top 3 alternatives at this decision point
|
||||
printf(" Alternatives at this node (%zu total):\n", siblings.size());
|
||||
std::cout << " Alternatives at this node (" << siblings.size() << " total):\n";
|
||||
const size_t topN = std::min(siblings.size(), size_t(3));
|
||||
for (size_t j = 0; j < topN; ++j) {
|
||||
const auto* alt = siblings[j];
|
||||
printf(" [%zu] visits:%d immediate:%.2f lookahead:%.2f",
|
||||
j,
|
||||
alt->visitCount,
|
||||
alt->immediateScore,
|
||||
alt->lookaheadScore);
|
||||
if (alt->action) { printf(" %s", alt->action->getDescription().c_str()); }
|
||||
printf("\n");
|
||||
std::ostringstream altLine;
|
||||
altLine << std::fixed << std::setprecision(2) << " [" << j
|
||||
<< "] visits:" << alt->visitCount
|
||||
<< " immediate:" << alt->immediateScore
|
||||
<< " lookahead:" << alt->lookaheadScore;
|
||||
if (alt->action) { altLine << ' ' << alt->action->getDescription(); }
|
||||
std::cout << altLine.str() << '\n';
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1013,7 +1016,7 @@ auto AbstractMCTSAI::DumpTreeToFile(const MCTSNode* root, const std::string& fil
|
||||
|
||||
std::ofstream out(filepath);
|
||||
if (!out) {
|
||||
fprintf(stderr, "Failed to open dump file: %s\n", filepath.c_str());
|
||||
std::cerr << "Failed to open dump file: " << filepath << '\n';
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1042,7 +1045,7 @@ auto AbstractMCTSAI::DumpTreeToFile(const MCTSNode* root, const std::string& fil
|
||||
out << "\n=== End of Tree Dump ===\n";
|
||||
out.close();
|
||||
|
||||
printf("MCTS: Tree dumped to %s\n", filepath.c_str());
|
||||
std::cout << "MCTS: Tree dumped to " << filepath << '\n';
|
||||
}
|
||||
|
||||
auto AbstractMCTSAI::DumpNodeRecursive(
|
||||
|
||||
@@ -6,8 +6,11 @@
|
||||
#define EAGLE0_ABSTRACT_MCTSNODE_HPP
|
||||
|
||||
#include <cmath>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
|
||||
#include "MCTSAction.hpp"
|
||||
@@ -205,13 +208,13 @@ struct MCTSNode {
|
||||
isMaximizingPlayer ? child->lookaheadScore : -child->lookaheadScore;
|
||||
const double explorationValue =
|
||||
explorationConstant * std::sqrt(std::log(visitCount) / child->visitCount);
|
||||
printf(" UCB: %s lookahead=%.2f expl=%.2f (+%.2f) = %.2f [%s]\n",
|
||||
isMaximizingPlayer ? "MAX" : "MIN",
|
||||
child->lookaheadScore,
|
||||
exploitationValue,
|
||||
explorationValue,
|
||||
value,
|
||||
child->action ? child->action->getDescription().c_str() : "root");
|
||||
std::ostringstream line;
|
||||
line << std::fixed << std::setprecision(2)
|
||||
<< " UCB: " << (isMaximizingPlayer ? "MAX" : "MIN")
|
||||
<< " lookahead=" << child->lookaheadScore << " expl=" << exploitationValue
|
||||
<< " (+" << explorationValue << ") = " << value << " ["
|
||||
<< (child->action ? child->action->getDescription() : "root") << "]";
|
||||
std::cout << line.str() << '\n';
|
||||
}
|
||||
|
||||
if (value > bestValue) {
|
||||
|
||||
@@ -28,36 +28,6 @@ cc_binary(
|
||||
deps = [":shardok-server-lib"],
|
||||
)
|
||||
|
||||
cc_binary(
|
||||
name = "shardok-inspector",
|
||||
srcs = ["shardok_inspector.cpp"],
|
||||
copts = COPTS,
|
||||
data = [
|
||||
"//src/main/resources/net/eagle0/shardok:battalion_types",
|
||||
"//src/main/resources/net/eagle0/shardok:settings",
|
||||
"//src/main/resources/net/eagle0/shardok/maps",
|
||||
],
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//src/main/cpp/net/eagle0/common:byte_vector",
|
||||
"//src/main/cpp/net/eagle0/common:filesystem_utils",
|
||||
"//src/main/cpp/net/eagle0/common:tsv_parser",
|
||||
"//src/main/cpp/net/eagle0/shardok/library:engine",
|
||||
],
|
||||
)
|
||||
|
||||
cc_binary(
|
||||
name = "corrupt-game-checker",
|
||||
srcs = ["CorruptGameChecker.cpp"],
|
||||
copts = COPTS,
|
||||
deps = [
|
||||
"//src/main/cpp/net/eagle0/common:byte_vector",
|
||||
"//src/main/cpp/net/eagle0/common:filesystem_utils",
|
||||
"//src/main/cpp/net/eagle0/shardok/library:game_state_w",
|
||||
"//src/main/protobuf/net/eagle0/common:shardok_internal_interface_cc_grpc",
|
||||
],
|
||||
)
|
||||
|
||||
cc_binary(
|
||||
name = "hex-map-migrator",
|
||||
srcs = ["HexMapMigrator.cpp"],
|
||||
@@ -69,6 +39,25 @@ cc_binary(
|
||||
],
|
||||
)
|
||||
|
||||
cc_binary(
|
||||
name = "random_battle_runner",
|
||||
srcs = ["RandomBattleRunner.cpp"],
|
||||
copts = COPTS,
|
||||
data = [
|
||||
"//src/main/resources/net/eagle0/shardok:battalion_types",
|
||||
"//src/main/resources/net/eagle0/shardok:settings",
|
||||
"//src/main/resources/net/eagle0/shardok/maps",
|
||||
],
|
||||
deps = [
|
||||
"//src/main/cpp/net/eagle0/common:byte_vector",
|
||||
"//src/main/cpp/net/eagle0/common:filesystem_utils",
|
||||
"//src/main/cpp/net/eagle0/common:unit_conversions",
|
||||
"//src/main/cpp/net/eagle0/shardok/library:shardok_c_types",
|
||||
"//src/main/cpp/net/eagle0/shardok/server:games_manager",
|
||||
"//src/main/protobuf/net/eagle0/common:random_units_cc_proto",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "map_info_calculator",
|
||||
srcs = ["MapInfoCalculator.cpp"],
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
//
|
||||
// Created by Dan Crosby on 1/9/22.
|
||||
//
|
||||
|
||||
#include "src/main/cpp/net/eagle0/common/byte_vector.hpp"
|
||||
#include "src/main/cpp/net/eagle0/shardok/library/GameStateW.hpp"
|
||||
#include "src/main/protobuf/net/eagle0/common/shardok_internal_interface.pb.h"
|
||||
#include "src/main/protobuf/net/eagle0/shardok/storage/game.pb.h"
|
||||
|
||||
auto main(int argc, char** argv) -> int {
|
||||
char* path = argv[1];
|
||||
|
||||
printf("Checking file %s\n", path);
|
||||
|
||||
auto bytes = byte_vector::FromPath(path);
|
||||
|
||||
net::eagle0::shardok::storage::Game game;
|
||||
game.ParseFromArray(bytes.data(), bytes.size());
|
||||
|
||||
printf("The game ID is %s\n", game.game_id().c_str());
|
||||
printf("The size is %lu\n", bytes.size());
|
||||
|
||||
const int arCount = game.action_result_size();
|
||||
printf("There are %d results\n", arCount);
|
||||
|
||||
for (int arIndex = 0; arIndex < arCount; arIndex++) {
|
||||
shardok::GameStateW gameState =
|
||||
shardok::GameStateW::FromByteString(game.action_result(arIndex).state_after_fb());
|
||||
const auto* hexMap = gameState->hex_map();
|
||||
|
||||
for (int terrainIndex = 0; terrainIndex < hexMap->terrain()->size(); terrainIndex++) {
|
||||
const auto* terrain = hexMap->terrain()->Get(terrainIndex);
|
||||
if (terrain->type() == net::eagle0::shardok::storage::fb::Terrain_::Type_STILL_WATER)
|
||||
continue;
|
||||
if (terrain->type() == net::eagle0::shardok::storage::fb::Terrain_::Type_RIVER)
|
||||
continue;
|
||||
|
||||
if (terrain->modifier().bridge().present()) {
|
||||
printf("Caught one! arIndex %d, terrainIndex %d\n", arIndex, terrainIndex);
|
||||
printf("Action result was %s\n",
|
||||
game.action_result(arIndex).action_result().DebugString().c_str());
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
// Created by Dan Crosby on 3/19/20.
|
||||
//
|
||||
|
||||
#include <cstdio>
|
||||
#include <iostream>
|
||||
|
||||
#include "src/main/cpp/net/eagle0/common/FilesystemUtils.hpp"
|
||||
#include "src/main/cpp/net/eagle0/common/byte_vector.hpp"
|
||||
@@ -14,7 +14,7 @@ void ModifyMap(HexMapProto& map);
|
||||
|
||||
int main(const int argc, char** argv) {
|
||||
if (argc < 3) {
|
||||
printf("Usage: %s input_path output_path\n", argv[0]);
|
||||
std::cerr << "Usage: " << argv[0] << " input_path output_path\n";
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -22,18 +22,22 @@ int main(const int argc, char** argv) {
|
||||
const std::string outputPath = argv[2];
|
||||
const byte_vector mapProtoBytes = byte_vector::FromPath(inputPath);
|
||||
net::eagle0::shardok::common::HexMap mapProto;
|
||||
mapProto.ParseFromArray(mapProtoBytes.data(), static_cast<int>(mapProtoBytes.size()));
|
||||
if (!mapProto.ParseFromArray(mapProtoBytes.data(), static_cast<int>(mapProtoBytes.size()))) {
|
||||
std::cerr << "Failed to parse hex map from " << inputPath << '\n';
|
||||
return -1;
|
||||
}
|
||||
|
||||
ModifyMap(mapProto);
|
||||
const std::string outputString = mapProto.SerializeAsString();
|
||||
if (FilesystemUtils::AtomicallySaveToPath(outputPath, byte_vector(outputString))) return 0;
|
||||
|
||||
printf("Failed to save.\n");
|
||||
std::cerr << "Failed to save.\n";
|
||||
return -1;
|
||||
}
|
||||
|
||||
void ModifyMap(HexMapProto& map) {
|
||||
for (int i = 0; i < map.terrain_size(); i++) {
|
||||
const int terrainCount = map.terrain_size();
|
||||
for (int i = 0; i < terrainCount; i++) {
|
||||
const auto existingTerrainType = map.terrain(i).type();
|
||||
const auto newTerrain =
|
||||
static_cast<net::eagle0::shardok::common::Terrain_Type>(existingTerrainType + 2);
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include "MapInfoCalculator.hpp"
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
|
||||
@@ -12,44 +13,42 @@
|
||||
#include "src/main/cpp/net/eagle0/shardok/library/util/HexMapUtils.hpp"
|
||||
#include "src/main/cpp/net/eagle0/shardok/util/MapLoader.hpp"
|
||||
|
||||
using namespace shardok;
|
||||
|
||||
auto LoadMapFb(const string& mapName) -> Wrapper<HexMap> {
|
||||
auto LoadMapFb(const std::string& mapName) -> shardok::Wrapper<shardok::HexMap> {
|
||||
const HexMapProto mapProto = LoadMap(mapName);
|
||||
|
||||
flatbuffers::FlatBufferBuilder fbb{};
|
||||
const auto hexMapOffset = fb::ConvertHexMapProto(fbb, mapProto);
|
||||
const auto hexMapOffset = shardok::fb::ConvertHexMapProto(fbb, mapProto);
|
||||
fbb.Finish(hexMapOffset);
|
||||
return Wrapper<HexMap>(fbb);
|
||||
return shardok::Wrapper<shardok::HexMap>(fbb);
|
||||
}
|
||||
|
||||
auto CalculateMap(
|
||||
const string& mapName,
|
||||
const std::shared_ptr<ActionPointDistancesCache>& apdCache,
|
||||
const BattalionTypeSPtr& battalionType) -> OneMapInfo {
|
||||
const std::string& mapName,
|
||||
const std::shared_ptr<shardok::ActionPointDistancesCache>& apdCache,
|
||||
const shardok::BattalionTypeSPtr& battalionType) -> OneMapInfo {
|
||||
auto hexMap = LoadMapFb(mapName);
|
||||
|
||||
const auto mapId = ActionPointDistancesCache::GetMapId(hexMap);
|
||||
const auto mapId = shardok::ActionPointDistancesCache::GetMapId(hexMap);
|
||||
|
||||
const CoordsSet criticalTileLocations = GetCriticalTileLocations(hexMap);
|
||||
const shardok::CoordsSet criticalTileLocations = shardok::GetCriticalTileLocations(hexMap);
|
||||
|
||||
OneMapInfo info{
|
||||
.castleCount = criticalTileLocations.size(),
|
||||
.name = mapName,
|
||||
.positionsRequiringCrossing = {}};
|
||||
|
||||
for (unsigned int i = 0; i < hexMap->attacker_starting_positions()->size(); i++) {
|
||||
for (std::size_t i = 0; i < hexMap->attacker_starting_positions()->size(); i++) {
|
||||
const auto* positionList = hexMap->attacker_starting_positions()->Get(i);
|
||||
if (positionList->positions()->size() < 1) continue;
|
||||
if (positionList->positions()->empty()) continue;
|
||||
if (positionList->positions()->size() != 10) {
|
||||
std::cerr << "Should have 10 starting positions!" << '\n';
|
||||
abort();
|
||||
std::abort();
|
||||
}
|
||||
|
||||
int positionsRequiringCrossing = 0;
|
||||
for (const auto* startingPosition : *positionList->positions()) {
|
||||
for (const Coords& castlePosition : criticalTileLocations) {
|
||||
if (!CanReach(
|
||||
for (const shardok::Coords& castlePosition : criticalTileLocations) {
|
||||
if (!shardok::CanReach(
|
||||
*startingPosition,
|
||||
castlePosition,
|
||||
hexMap,
|
||||
@@ -61,7 +60,7 @@ auto CalculateMap(
|
||||
};
|
||||
}
|
||||
}
|
||||
info.positionsRequiringCrossing[i] = positionsRequiringCrossing;
|
||||
info.positionsRequiringCrossing[static_cast<int>(i)] = positionsRequiringCrossing;
|
||||
}
|
||||
|
||||
return info;
|
||||
|
||||
@@ -12,19 +12,15 @@
|
||||
|
||||
#include "src/main/cpp/net/eagle0/shardok/library/action_point_distances/ActionPointDistancesCache.hpp"
|
||||
|
||||
using namespace shardok;
|
||||
using std::map;
|
||||
using std::string;
|
||||
|
||||
struct alignas(64) OneMapInfo {
|
||||
uint32_t castleCount;
|
||||
string name;
|
||||
map<int, int> positionsRequiringCrossing;
|
||||
std::string name;
|
||||
std::map<int, int> positionsRequiringCrossing;
|
||||
};
|
||||
|
||||
auto CalculateMap(
|
||||
const string& mapName,
|
||||
const std::shared_ptr<ActionPointDistancesCache>& apdCache,
|
||||
const BattalionTypeSPtr& battalionType) -> OneMapInfo;
|
||||
const std::string& mapName,
|
||||
const std::shared_ptr<shardok::ActionPointDistancesCache>& apdCache,
|
||||
const shardok::BattalionTypeSPtr& battalionType) -> OneMapInfo;
|
||||
|
||||
#endif // EAGLE0_MAPINFOCALCULATOR_HPP
|
||||
|
||||
@@ -5,36 +5,37 @@
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "MapInfoCalculator.hpp"
|
||||
#include "src/main/cpp/net/eagle0/common/FilesystemUtils.hpp"
|
||||
#include "src/main/cpp/net/eagle0/shardok/library/settings/GameSettings.hpp"
|
||||
#include "src/main/cpp/net/eagle0/shardok/util/BattalionTypeRegistrar.hpp"
|
||||
#include "src/main/cpp/net/eagle0/shardok/util/MapLoader.hpp"
|
||||
|
||||
using namespace shardok;
|
||||
|
||||
auto main(const int argc, char** argv) -> int {
|
||||
FilesystemUtils::SetExecPath(argv[0]);
|
||||
|
||||
std::ostream* outputStreamPtr = &std::cout;
|
||||
std::ofstream outputFile{};
|
||||
if (argc > 1) {
|
||||
const string outputPath = argv[1];
|
||||
const std::string outputPath = argv[1];
|
||||
outputFile.open(outputPath);
|
||||
outputStreamPtr = &outputFile;
|
||||
}
|
||||
std::ostream& outputStream = *outputStreamPtr;
|
||||
|
||||
const auto gameSettings = std::make_shared<GameSettings>();
|
||||
const auto gameSettings = std::make_shared<shardok::GameSettings>();
|
||||
auto setter = gameSettings->GetSetter();
|
||||
BattalionTypeRegistrar::RegisterBattalionTypes(setter);
|
||||
const BattalionTypeSPtr& battalionType = gameSettings->GetGetter().GetBattalionType(
|
||||
shardok::BattalionTypeRegistrar::RegisterBattalionTypes(setter);
|
||||
const shardok::BattalionTypeSPtr& battalionType = gameSettings->GetGetter().GetBattalionType(
|
||||
net::eagle0::shardok::storage::fb::BattalionTypeId_LIGHT_INFANTRY);
|
||||
|
||||
vector<OneMapInfo> mapInfos{};
|
||||
for (const string& mapName : GetMapNames()) {
|
||||
std::shared_ptr<ActionPointDistancesCache> apdCache =
|
||||
std::make_shared<ActionPointDistancesCache>();
|
||||
std::vector<OneMapInfo> mapInfos{};
|
||||
for (const std::string& mapName : GetMapNames()) {
|
||||
std::shared_ptr<shardok::ActionPointDistancesCache> apdCache =
|
||||
std::make_shared<shardok::ActionPointDistancesCache>();
|
||||
|
||||
mapInfos.push_back(CalculateMap(mapName, apdCache, battalionType));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,162 @@
|
||||
//
|
||||
// Created by Dan Crosby on 3/29/21.
|
||||
//
|
||||
|
||||
#include <algorithm>
|
||||
#include <climits>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <random>
|
||||
#include <stdexcept>
|
||||
#include <thread>
|
||||
|
||||
#include "src/main/cpp/net/eagle0/common/FilesystemUtils.hpp"
|
||||
#include "src/main/cpp/net/eagle0/common/UnitConversions.hpp"
|
||||
#include "src/main/cpp/net/eagle0/shardok/library/ShardokCTypes.h"
|
||||
#include "src/main/cpp/net/eagle0/shardok/server/ShardokGamesManager.hpp"
|
||||
#include "src/main/protobuf/net/eagle0/common/random_units.pb.h"
|
||||
|
||||
using net::eagle0::common::RandomUnits;
|
||||
|
||||
constexpr int THREAD_COUNT = 16;
|
||||
|
||||
#define FIXED_SEED true
|
||||
|
||||
#if FIXED_SEED
|
||||
std::mt19937 g;
|
||||
#else
|
||||
std::random_device rd;
|
||||
std::mt19937 g(rd());
|
||||
#endif
|
||||
|
||||
std::mutex randomMutex;
|
||||
std::vector<std::string> fileNames{};
|
||||
|
||||
std::unique_ptr<shardok::ShardokGamesManager> manager;
|
||||
|
||||
auto randInt(const int lowInc, const int hiInc) {
|
||||
std::lock_guard<std::mutex> lock(randomMutex);
|
||||
return std::uniform_int_distribution(lowInc, hiInc)(g);
|
||||
}
|
||||
|
||||
void runBattle(const std::vector<shardok::Unit>& units) {
|
||||
if (fileNames.empty()) { throw std::runtime_error("No map files found"); }
|
||||
if (units.size() < 2) { throw std::runtime_error("Need at least two units to run a battle"); }
|
||||
|
||||
auto mapName = fileNames[randInt(0, (int)fileNames.size() - 1)];
|
||||
auto month = randInt(1, 12);
|
||||
|
||||
const auto maxP1UnitCount = std::min<size_t>(20, units.size() - 1);
|
||||
auto p1UnitCount = randInt(1, static_cast<int>(maxP1UnitCount));
|
||||
std::vector<shardok::Unit> p1Units{};
|
||||
for (int i = 0; i < p1UnitCount; i++) {
|
||||
auto unit = units[i];
|
||||
unit.mutate_player_id(0);
|
||||
p1Units.push_back(unit);
|
||||
}
|
||||
|
||||
const auto maxP2UnitCount = std::min<size_t>(20, units.size() - p1UnitCount);
|
||||
auto p2UnitCount = randInt(1, static_cast<int>(maxP2UnitCount));
|
||||
std::vector<shardok::Unit> p2Units{};
|
||||
for (int i = p1UnitCount; i < p1UnitCount + p2UnitCount; i++) {
|
||||
auto unit = units[i];
|
||||
unit.mutate_player_id(1);
|
||||
p2Units.push_back(unit);
|
||||
}
|
||||
|
||||
std::cout << "map name is " << mapName << ", " << p1UnitCount << " attacking " << p2UnitCount
|
||||
<< '\n';
|
||||
|
||||
std::vector<VictoryConditionProto> attVictoryConditions{
|
||||
VictoryConditionProto::VICTORY_CONDITION_HOLDS_CRITICAL_TILES,
|
||||
VictoryConditionProto::VICTORY_CONDITION_LAST_PLAYER_STANDING};
|
||||
std::vector<VictoryConditionProto> defVictoryConditions{
|
||||
VictoryConditionProto::VICTORY_CONDITION_LAST_PLAYER_STANDING,
|
||||
VictoryConditionProto::VICTORY_CONDITION_WIN_AFTER_MAX_ROUNDS};
|
||||
|
||||
auto p1 = shardok::PlayerInfoWithUnits(
|
||||
0,
|
||||
true,
|
||||
5,
|
||||
false,
|
||||
10000,
|
||||
attVictoryConditions,
|
||||
{},
|
||||
p1Units,
|
||||
false);
|
||||
auto p2 = shardok::PlayerInfoWithUnits(
|
||||
1,
|
||||
true,
|
||||
7,
|
||||
true,
|
||||
10000,
|
||||
defVictoryConditions,
|
||||
{},
|
||||
p2Units,
|
||||
false);
|
||||
|
||||
std::string gameId = std::to_string(randInt(INT_MIN, INT_MAX));
|
||||
|
||||
manager->UnlockedCreateSpecifiedGame(
|
||||
gameId,
|
||||
{p1, p2},
|
||||
mapName,
|
||||
"",
|
||||
month,
|
||||
TutorialBattleConfigProto{},
|
||||
"");
|
||||
}
|
||||
|
||||
auto LoadUnits() -> std::vector<shardok::Unit> {
|
||||
const auto bytes = byte_vector::FromPath("/tmp/random_heroes.bin");
|
||||
|
||||
RandomUnits commonUnits;
|
||||
if (!commonUnits.ParseFromArray(bytes.data(), static_cast<int>(bytes.size()))) {
|
||||
throw std::runtime_error("Failed to parse /tmp/random_heroes.bin");
|
||||
}
|
||||
std::cout << "Loaded " << commonUnits.units_size() << " units\n";
|
||||
|
||||
std::vector<shardok::Unit> units{};
|
||||
units.reserve(commonUnits.units_size());
|
||||
|
||||
for (const auto& commonUnit : commonUnits.units()) {
|
||||
// FIXME: assumes 2 players
|
||||
units.push_back(shardok::ConvertUnit(commonUnit, 0, {0, 1}));
|
||||
}
|
||||
std::shuffle(units.begin(), units.end(), g);
|
||||
|
||||
return units;
|
||||
}
|
||||
|
||||
[[noreturn]] void runBattlesThread(const std::vector<shardok::Unit>& units) {
|
||||
while (true) { runBattle(units); }
|
||||
}
|
||||
|
||||
auto main(int /*argc*/, char** argv) -> int {
|
||||
#if FIXED_SEED
|
||||
std::srand(4564564);
|
||||
g.seed(378473);
|
||||
#else
|
||||
std::srand(std::time(nullptr));
|
||||
#endif
|
||||
|
||||
FilesystemUtils::SetExecPath(argv[0]);
|
||||
|
||||
auto randomUnits = LoadUnits();
|
||||
|
||||
std::cout << "Map file directory is " << FilesystemUtils::MapFilesDirectory() << '\n';
|
||||
fileNames = FilesystemUtils::FilesInDirectory(FilesystemUtils::MapFilesDirectory(), ".e0m");
|
||||
|
||||
for (auto& fileName : fileNames) { fileName.resize(fileName.size() - 4); }
|
||||
|
||||
manager = std::make_unique<shardok::ShardokGamesManager>(std::vector<std::string>());
|
||||
|
||||
std::thread threads[THREAD_COUNT];
|
||||
|
||||
for (int i = 0; i < THREAD_COUNT; i++) {
|
||||
threads[i] = std::thread(runBattlesThread, randomUnits);
|
||||
}
|
||||
|
||||
for (auto& thread : threads) { thread.join(); }
|
||||
}
|
||||
@@ -16,9 +16,6 @@ namespace shardok {
|
||||
constexpr double kOverpowerRatio = 2.0;
|
||||
constexpr double kBraveWaterCostMultiplier = 1.2;
|
||||
|
||||
using std::pair;
|
||||
using std::shared_ptr;
|
||||
|
||||
DIST_T NormalizedCostWhenBraving(const DIST_T cost) {
|
||||
if (cost >= static_cast<double>(ActionPointDistances::IMPOSSIBLE) / kBraveWaterCostMultiplier)
|
||||
return ActionPointDistances::IMPOSSIBLE;
|
||||
@@ -235,4 +232,4 @@ auto GenerateTargetPriorities(
|
||||
return allTargetsUnitsAndDistances;
|
||||
}
|
||||
|
||||
} // namespace shardok
|
||||
} // namespace shardok
|
||||
|
||||
@@ -20,7 +20,6 @@ namespace shardok {
|
||||
using GameState = net::eagle0::shardok::storage::fb::GameState;
|
||||
using Unit = net::eagle0::shardok::storage::fb::Unit;
|
||||
using net::eagle0::shardok::storage::fb::PlayerInfo;
|
||||
using std::vector;
|
||||
|
||||
using BattalionTypeGetter = std::function<BattalionTypeSPtr(BattalionTypeId)>;
|
||||
|
||||
@@ -33,9 +32,9 @@ struct TargetAndAttackLocations {
|
||||
|
||||
struct TargetPriorityList {
|
||||
UnitId attackingUnitId;
|
||||
vector<TargetAndAttackLocations> priorityOrder;
|
||||
std::vector<TargetAndAttackLocations> priorityOrder;
|
||||
|
||||
TargetPriorityList(const UnitId uid, const vector<TargetAndAttackLocations>& po)
|
||||
TargetPriorityList(const UnitId uid, const std::vector<TargetAndAttackLocations>& po)
|
||||
: attackingUnitId(uid),
|
||||
priorityOrder(po) {}
|
||||
};
|
||||
@@ -64,16 +63,16 @@ auto EffectiveDistance(
|
||||
|
||||
// Chooses a list of targets in priority order for each unit.
|
||||
auto GenerateTargetPriorities(
|
||||
const vector<const Unit*>& occupants,
|
||||
const std::vector<const Unit*>& occupants,
|
||||
const HexMap* map,
|
||||
const CoordsSet& targets,
|
||||
PlayerId attackerId,
|
||||
const vector<const Unit*>& remainingUnits,
|
||||
const std::vector<const Unit*>& remainingUnits,
|
||||
const APDCache& apdCache,
|
||||
const ALCache& alCache,
|
||||
const BattalionTypeGetter& battalionTypeGetter,
|
||||
ActionPoints braveWaterCost,
|
||||
bool isLateGame = false) -> vector<TargetPriorityList>;
|
||||
bool isLateGame = false) -> std::vector<TargetPriorityList>;
|
||||
|
||||
} // namespace shardok
|
||||
|
||||
|
||||
@@ -17,8 +17,6 @@
|
||||
namespace shardok {
|
||||
|
||||
using Unit = net::eagle0::shardok::storage::fb::Unit;
|
||||
using std::shared_ptr;
|
||||
using std::vector;
|
||||
|
||||
class alignas(128) AttackLocations {
|
||||
private:
|
||||
@@ -165,7 +163,7 @@ public:
|
||||
|
||||
auto CachedLocations(const Coords& singleTarget, bool lateGame) -> const AttackLocations&;
|
||||
auto CachedLocations(const CoordsSet& targets, bool lateGame) -> AttackLocations;
|
||||
auto CachedLocations(const vector<const Unit*>& enemies, bool lateGame) -> AttackLocations;
|
||||
auto CachedLocations(const std::vector<const Unit*>& enemies, bool lateGame) -> AttackLocations;
|
||||
};
|
||||
|
||||
using ALCache = std::unique_ptr<AttackLocationsCache>;
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
#include <chrono>
|
||||
#include <cmath>
|
||||
#include <future>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
|
||||
#include "AICommandFilter.hpp"
|
||||
@@ -309,16 +311,16 @@ auto AICommandEvaluator::FindBestCommand(
|
||||
const auto filteredCommandCount = filteredIndices.size();
|
||||
const int currentRound = gameState->current_round();
|
||||
|
||||
printf("AI_COMMAND_COUNT: Round %d, Player %d, Defender %d, MinDist %.1f, Commands %zu -> "
|
||||
"%zu "
|
||||
"(%.1f%% filtered)\n",
|
||||
currentRound,
|
||||
static_cast<int>(pid),
|
||||
isDefender ? 1 : 0,
|
||||
minDistToEnemies,
|
||||
allCommandCount,
|
||||
filteredCommandCount,
|
||||
100.0 * (allCommandCount - filteredCommandCount) / allCommandCount);
|
||||
const auto flags = std::cout.flags();
|
||||
const auto precision = std::cout.precision();
|
||||
std::cout << "AI_COMMAND_COUNT: Round " << currentRound << ", Player "
|
||||
<< static_cast<int>(pid) << ", Defender " << (isDefender ? 1 : 0) << ", MinDist "
|
||||
<< std::fixed << std::setprecision(1) << minDistToEnemies << ", Commands "
|
||||
<< allCommandCount << " -> " << filteredCommandCount << " ("
|
||||
<< 100.0 * (allCommandCount - filteredCommandCount) / allCommandCount
|
||||
<< "% filtered)\n";
|
||||
std::cout.flags(flags);
|
||||
std::cout.precision(precision);
|
||||
}
|
||||
|
||||
const auto commandCount = filteredIndices.size();
|
||||
|
||||
@@ -13,14 +13,11 @@
|
||||
|
||||
namespace shardok {
|
||||
|
||||
using std::shared_ptr;
|
||||
using std::vector;
|
||||
|
||||
auto DefenderDistanceBuf(
|
||||
const Coords &defenderLocation,
|
||||
const HexMap *hexMap,
|
||||
const MapId &mapId,
|
||||
const vector<const Unit *> &attackerUnits,
|
||||
const std::vector<const Unit *> &attackerUnits,
|
||||
const APDCache &apdCache,
|
||||
const ALCache &alCache,
|
||||
const BattalionTypeGetter &battalionTypeGetter,
|
||||
|
||||
@@ -8,12 +8,29 @@
|
||||
|
||||
#include "AIFleeDecisionCalculator.hpp"
|
||||
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
|
||||
#include "src/main/cpp/net/eagle0/shardok/ai/AIScoreUtilities.hpp"
|
||||
#include "src/main/cpp/net/eagle0/shardok/ai/AIUnitScoreCalculator.hpp"
|
||||
#include "src/main/cpp/net/eagle0/shardok/library/util/HexMapUtils.hpp"
|
||||
|
||||
namespace shardok {
|
||||
|
||||
namespace {
|
||||
|
||||
void WritePercent(std::ostream& output, const double value) {
|
||||
const auto flags = output.flags();
|
||||
const auto precision = output.precision();
|
||||
|
||||
output << std::fixed << std::setprecision(1) << value;
|
||||
|
||||
output.flags(flags);
|
||||
output.precision(precision);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
auto AIFleeDecisionCalculator::GetFleeCommandIndex(
|
||||
const CommandList::const_iterator& fleeCommand,
|
||||
const CommandListSPtr& availableCommands) -> size_t {
|
||||
@@ -144,15 +161,14 @@ auto AIFleeDecisionCalculator::EvaluateFleeVsFight(
|
||||
const int fleeSuccessChance = (*fleeCommand)->GetOddsPercentile();
|
||||
|
||||
if (enableDebugLogging) {
|
||||
printf("AI FinalRound: Evaluating flee (odds=%d%%)...\n", fleeSuccessChance);
|
||||
std::cout << "AI FinalRound: Evaluating flee (odds=" << fleeSuccessChance << "%)...\n";
|
||||
}
|
||||
|
||||
// Check if flee odds are good enough to attempt
|
||||
if (fleeSuccessChance >= minimumFleeOddsThreshold) {
|
||||
if (enableDebugLogging) {
|
||||
printf("AI FinalRound: Good flee odds (%d%% >= %d%%), choosing flee\n",
|
||||
fleeSuccessChance,
|
||||
minimumFleeOddsThreshold);
|
||||
std::cout << "AI FinalRound: Good flee odds (" << fleeSuccessChance
|
||||
<< "% >= " << minimumFleeOddsThreshold << "%), choosing flee\n";
|
||||
}
|
||||
return FleeDecision{
|
||||
true,
|
||||
@@ -166,9 +182,9 @@ auto AIFleeDecisionCalculator::EvaluateFleeVsFight(
|
||||
// If combat situation is hopeless, even bad flee odds are better than certain death
|
||||
if (combatWinChance <= 0.05 && fleeSuccessChance >= desperateFleeThreshold) {
|
||||
if (enableDebugLogging) {
|
||||
printf("AI FinalRound: Combat hopeless (%.1f%%), desperate flee attempt (%d%%)\n",
|
||||
combatWinChance * 100,
|
||||
fleeSuccessChance);
|
||||
std::cout << "AI FinalRound: Combat hopeless (";
|
||||
WritePercent(std::cout, combatWinChance * 100);
|
||||
std::cout << "%), desperate flee attempt (" << fleeSuccessChance << "%)\n";
|
||||
}
|
||||
return FleeDecision{
|
||||
true,
|
||||
@@ -188,20 +204,21 @@ auto AIFleeDecisionCalculator::EvaluateFleeVsFight(
|
||||
const double adjustedCombatThreshold = combatWinChance * FLEE_VS_COMBAT_MARGIN;
|
||||
|
||||
if (enableDebugLogging) {
|
||||
printf("AI FinalRound: Flee=%d%%, Combat=%.1f%%, Threshold=%.1f%% -> ",
|
||||
fleeSuccessChance,
|
||||
combatWinChance * 100,
|
||||
adjustedCombatThreshold * 100);
|
||||
std::cout << "AI FinalRound: Flee=" << fleeSuccessChance << "%, Combat=";
|
||||
WritePercent(std::cout, combatWinChance * 100);
|
||||
std::cout << "%, Threshold=";
|
||||
WritePercent(std::cout, adjustedCombatThreshold * 100);
|
||||
std::cout << "% -> ";
|
||||
}
|
||||
|
||||
if (fleeChance > adjustedCombatThreshold) {
|
||||
if (enableDebugLogging) { printf("FLEE (better odds)\n"); }
|
||||
if (enableDebugLogging) { std::cout << "FLEE (better odds)\n"; }
|
||||
return FleeDecision{
|
||||
true,
|
||||
GetFleeCommandIndex(fleeCommand, availableCommands),
|
||||
"Flee has better expected outcome"};
|
||||
} else {
|
||||
if (enableDebugLogging) { printf("FIGHT (better expected outcome)\n"); }
|
||||
if (enableDebugLogging) { std::cout << "FIGHT (better expected outcome)\n"; }
|
||||
// Return 0 to indicate we should use standard command selection
|
||||
return FleeDecision{
|
||||
false,
|
||||
|
||||
@@ -5,9 +5,6 @@
|
||||
#ifndef EAGLE0_SHARDOK_AI_AI_MINIMUM_DISTANCE_AND_TARGET_HPP
|
||||
#define EAGLE0_SHARDOK_AI_AI_MINIMUM_DISTANCE_AND_TARGET_HPP
|
||||
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "src/main/cpp/net/eagle0/shardok/library/action_point_distances/ActionPointDistances.hpp"
|
||||
#include "src/main/cpp/net/eagle0/shardok/library/map/CoordsSet.hpp"
|
||||
#include "src/main/protobuf/net/eagle0/shardok/common/coords.pb.h"
|
||||
@@ -15,7 +12,6 @@
|
||||
namespace shardok {
|
||||
|
||||
using net::eagle0::shardok::storage::fb::Coords;
|
||||
using std::shared_ptr;
|
||||
|
||||
struct CoordsAndDistance {
|
||||
Coords coords;
|
||||
|
||||
@@ -16,8 +16,6 @@ namespace shardok {
|
||||
|
||||
using ScoreValue = double;
|
||||
|
||||
using std::vector;
|
||||
|
||||
using GameState = net::eagle0::shardok::storage::fb::GameState;
|
||||
using PlayerInfo = net::eagle0::shardok::storage::fb::PlayerInfo;
|
||||
using Unit = net::eagle0::shardok::storage::fb::Unit;
|
||||
|
||||
@@ -116,15 +116,6 @@ auto CalculateTimeBudget(
|
||||
const auto clampedBudgetMs = std::clamp(budgetMs, 200.0, maxBudgetMs);
|
||||
const auto remainingBudget = std::chrono::milliseconds(static_cast<int64_t>(clampedBudgetMs));
|
||||
|
||||
// TEMPORARY DEBUG OUTPUT
|
||||
printf("[DEBUG CalculateTimeBudget] numCommands=%zu, msPerCommand=%.2f, budgetMs=%.2f, "
|
||||
"clampedBudgetMs=%.2f, isClose=%d\n",
|
||||
numCommands,
|
||||
msPerCommand,
|
||||
budgetMs,
|
||||
clampedBudgetMs,
|
||||
isClose);
|
||||
|
||||
// Get minimum depth requirement
|
||||
const size_t minDepth = settingsGetter.Backing().min_lookahead_turns();
|
||||
|
||||
@@ -134,4 +125,4 @@ auto CalculateTimeBudget(
|
||||
.isCloseToEnemy = isClose};
|
||||
}
|
||||
|
||||
} // namespace shardok
|
||||
} // namespace shardok
|
||||
|
||||
@@ -14,9 +14,6 @@
|
||||
namespace shardok {
|
||||
|
||||
using net::eagle0::shardok::storage::fb::Unit;
|
||||
using std::shared_ptr;
|
||||
using std::vector;
|
||||
|
||||
using ScoreValue = double;
|
||||
class AttackLocations;
|
||||
|
||||
@@ -29,8 +26,8 @@ auto GetRangedAttackBonus(
|
||||
const Terrain *terrain,
|
||||
const AttackLocations &attackLocations,
|
||||
int roundsRemaining,
|
||||
const vector<const Unit *> &attackerUnits,
|
||||
const vector<const Unit *> &defenderUnits,
|
||||
const std::vector<const Unit *> &attackerUnits,
|
||||
const std::vector<const Unit *> &defenderUnits,
|
||||
int meteorRange,
|
||||
double minVigorToCast,
|
||||
ActionPoints archeryActionPointCost = 0) -> double;
|
||||
@@ -38,10 +35,10 @@ auto GetRangedAttackBonus(
|
||||
auto UnitValue(
|
||||
const Unit *unit,
|
||||
bool isAttacker,
|
||||
const vector<const Unit *> &attackerUnits,
|
||||
const std::vector<const Unit *> &attackerUnits,
|
||||
bool attackerWantsCastles,
|
||||
bool includeCastleBonus,
|
||||
const vector<const Unit *> &defenderUnits,
|
||||
const std::vector<const Unit *> &defenderUnits,
|
||||
const HexMap *map,
|
||||
int roundsRemaining,
|
||||
const AttackLocations &locationsThisSideCanAttackFrom,
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
#include "IterativeDeepeningAI.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
#include <numeric>
|
||||
#include <utility>
|
||||
@@ -21,6 +23,20 @@ namespace shardok {
|
||||
|
||||
constexpr bool kDebugIterativeDeepeningTimings = true;
|
||||
|
||||
namespace {
|
||||
|
||||
void WriteFixed(std::ostream& output, const double value, const int precision) {
|
||||
const auto flags = output.flags();
|
||||
const auto originalPrecision = output.precision();
|
||||
|
||||
output << std::fixed << std::setprecision(precision) << value;
|
||||
|
||||
output.flags(flags);
|
||||
output.precision(originalPrecision);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
IterativeDeepeningAI::IterativeDeepeningAI(
|
||||
const PlayerId playerId,
|
||||
const bool isDefender,
|
||||
@@ -55,7 +71,7 @@ auto IterativeDeepeningAI::IterativeSearch(
|
||||
// g_transpositionTable.clear(); // Uncomment to test without cross-search caching
|
||||
if (commands->empty()) {
|
||||
if (kDebugIterativeDeepeningTimings) {
|
||||
printf("ID AI: Commands are empty, returning early\n");
|
||||
std::cout << "ID AI: Commands are empty, returning early\n";
|
||||
}
|
||||
result.searchCompleted = true;
|
||||
return result;
|
||||
@@ -169,21 +185,21 @@ auto IterativeDeepeningAI::IterativeSearch(
|
||||
// Log if best command changed from previous depth
|
||||
if (currentDepth > 1 && currentBestCommand != previousBestCommand) {
|
||||
if (kDebugIterativeDeepeningTimings) {
|
||||
printf("ID AI: Best command changed at depth %lu:\n", currentDepth);
|
||||
printf(" Depth %lu best: command %zu (score %.2f) - type: %s\n",
|
||||
currentDepth - 1,
|
||||
previousBestCommand,
|
||||
scoresByDepth[previousBestCommand][currentDepth - 1],
|
||||
net::eagle0::shardok::common::CommandType_Name(
|
||||
(*commands)[previousBestCommand]->GetCommandType())
|
||||
.c_str());
|
||||
printf(" Depth %lu best: command %zu (score %.2f) - type: %s\n",
|
||||
currentDepth,
|
||||
currentBestCommand,
|
||||
currentBestScore,
|
||||
net::eagle0::shardok::common::CommandType_Name(
|
||||
(*commands)[currentBestCommand]->GetCommandType())
|
||||
.c_str());
|
||||
std::cout << "ID AI: Best command changed at depth " << currentDepth << ":\n"
|
||||
<< " Depth " << currentDepth - 1 << " best: command "
|
||||
<< previousBestCommand << " (score ";
|
||||
WriteFixed(std::cout, scoresByDepth[previousBestCommand][currentDepth - 1], 2);
|
||||
std::cout << ") - type: "
|
||||
<< net::eagle0::shardok::common::CommandType_Name(
|
||||
(*commands)[previousBestCommand]->GetCommandType())
|
||||
<< '\n'
|
||||
<< " Depth " << currentDepth << " best: command "
|
||||
<< currentBestCommand << " (score ";
|
||||
WriteFixed(std::cout, currentBestScore, 2);
|
||||
std::cout << ") - type: "
|
||||
<< net::eagle0::shardok::common::CommandType_Name(
|
||||
(*commands)[currentBestCommand]->GetCommandType())
|
||||
<< '\n';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -239,9 +255,9 @@ auto IterativeDeepeningAI::IterativeSearch(
|
||||
static_cast<double>(initialBudgetMs.count());
|
||||
|
||||
if (budgetUsedPercent > 0.5) {
|
||||
printf("ID AI: Stopping after depth %lu - used %.1f%% of time budget\n",
|
||||
currentDepth,
|
||||
budgetUsedPercent * 100);
|
||||
std::cout << "ID AI: Stopping after depth " << currentDepth << " - used ";
|
||||
WriteFixed(std::cout, budgetUsedPercent * 100, 1);
|
||||
std::cout << "% of time budget\n";
|
||||
completionReason = EvaluationCompletionReason::NOT_ENOUGH_TIME_TO_CONTINUE;
|
||||
break;
|
||||
}
|
||||
@@ -271,9 +287,9 @@ auto IterativeDeepeningAI::IterativeSearch(
|
||||
// Validation: if completion reason is RAN_OUT_OF_COMMANDS, evaluation should be 100%
|
||||
if (completionReason == EvaluationCompletionReason::RAN_OUT_OF_COMMANDS &&
|
||||
result.commandCountEvaluated < result.availableCommandCount) {
|
||||
printf("ERROR: Completion reason RAN_OUT_OF_COMMANDS but evaluation %lu/%zu < 100%%\n",
|
||||
result.commandCountEvaluated,
|
||||
result.availableCommandCount);
|
||||
std::cerr << "ERROR: Completion reason RAN_OUT_OF_COMMANDS but evaluation "
|
||||
<< result.commandCountEvaluated << '/' << result.availableCommandCount
|
||||
<< " < 100%\n";
|
||||
}
|
||||
|
||||
// Print TranspositionTable statistics
|
||||
|
||||
@@ -15,9 +15,12 @@
|
||||
#include <chrono>
|
||||
#include <fstream>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#endif
|
||||
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <set>
|
||||
#include <unordered_map>
|
||||
|
||||
@@ -174,25 +177,20 @@ auto ShardokAIClient::StandardChooseCommandIndex(
|
||||
|
||||
// Verify that the AI's guessed state produces the same available commands as reality
|
||||
if (commandCount != realAvailableCommands->size()) {
|
||||
fprintf(stderr,
|
||||
"AI command count mismatch: guessed=%zu real=%zu player=%d round=%d\n",
|
||||
commandCount,
|
||||
realAvailableCommands->size(),
|
||||
playerId,
|
||||
guessedState->current_round());
|
||||
std::cerr << "AI command count mismatch: guessed=" << commandCount
|
||||
<< " real=" << realAvailableCommands->size() << " player=" << playerId
|
||||
<< " round=" << guessedState->current_round() << "\n";
|
||||
|
||||
const auto maxDump = std::max(commandCount, realAvailableCommands->size());
|
||||
for (size_t i = 0; i < maxDump; i++) {
|
||||
const auto *realName = i < realAvailableCommands->size()
|
||||
? net::eagle0::shardok::common::CommandType_Name(
|
||||
(*realAvailableCommands)[i]->GetCommandType())
|
||||
.c_str()
|
||||
: "(none)";
|
||||
const auto *guessedName = i < commandCount
|
||||
? net::eagle0::shardok::common::CommandType_Name(
|
||||
(*guessedCommands)[i]->GetCommandType())
|
||||
.c_str()
|
||||
: "(none)";
|
||||
const auto realName = i < realAvailableCommands->size()
|
||||
? net::eagle0::shardok::common::CommandType_Name(
|
||||
(*realAvailableCommands)[i]->GetCommandType())
|
||||
: "(none)";
|
||||
const auto guessedName = i < commandCount
|
||||
? net::eagle0::shardok::common::CommandType_Name(
|
||||
(*guessedCommands)[i]->GetCommandType())
|
||||
: "(none)";
|
||||
const int realActor = i < realAvailableCommands->size()
|
||||
? (*realAvailableCommands)[i]->GetActorUnitId()
|
||||
: -1;
|
||||
@@ -206,17 +204,10 @@ auto ShardokAIClient::StandardChooseCommandIndex(
|
||||
: -1;
|
||||
const int guessedRow = i < commandCount ? (*guessedCommands)[i]->GetTargetRow() : -1;
|
||||
const int guessedCol = i < commandCount ? (*guessedCommands)[i]->GetTargetColumn() : -1;
|
||||
fprintf(stderr,
|
||||
" [%zu] real: %s unit=%d (%d,%d) guessed: %s unit=%d (%d,%d)\n",
|
||||
i,
|
||||
realName,
|
||||
realActor,
|
||||
realRow,
|
||||
realCol,
|
||||
guessedName,
|
||||
guessedActor,
|
||||
guessedRow,
|
||||
guessedCol);
|
||||
std::cerr << " [" << i << "] real: " << realName << " unit=" << realActor << " ("
|
||||
<< realRow << "," << realCol << ") guessed: " << guessedName
|
||||
<< " unit=" << guessedActor << " (" << guessedRow << "," << guessedCol
|
||||
<< ")\n";
|
||||
}
|
||||
|
||||
// Find positions in real commands that are missing from guessed commands
|
||||
@@ -238,45 +229,34 @@ auto ShardokAIClient::StandardChooseCommandIndex(
|
||||
for (const auto &[unitId, positions] : realPositions) {
|
||||
for (const auto &[row, col] : positions) {
|
||||
if (!guessedPositions[unitId].contains({row, col})) {
|
||||
fprintf(stderr,
|
||||
" Missing from guessed: unit=%d pos=(%d,%d)",
|
||||
unitId,
|
||||
row,
|
||||
col);
|
||||
std::cerr << " Missing from guessed: unit=" << unitId << " pos=(" << row << ","
|
||||
<< col << ")";
|
||||
const Coords missingCoords(row, col);
|
||||
const auto *occupant = guessedState.GetOccupant(missingCoords);
|
||||
if (occupant) {
|
||||
fprintf(stderr,
|
||||
" -> guessed occupant: unit_id=%d player=%d status=%d "
|
||||
"loc=(%d,%d) hidden=%d battalion_size=%d\n",
|
||||
occupant->unit_id(),
|
||||
occupant->player_id(),
|
||||
static_cast<int>(occupant->status()),
|
||||
occupant->location().row(),
|
||||
occupant->location().column(),
|
||||
occupant->hidden(),
|
||||
occupant->battalion().size());
|
||||
std::cerr << " -> guessed occupant: unit_id=" << occupant->unit_id()
|
||||
<< " player=" << occupant->player_id()
|
||||
<< " status=" << static_cast<int>(occupant->status()) << " loc=("
|
||||
<< occupant->location().row() << ","
|
||||
<< occupant->location().column()
|
||||
<< ") hidden=" << occupant->hidden()
|
||||
<< " battalion_size=" << occupant->battalion().size() << "\n";
|
||||
} else {
|
||||
fprintf(stderr, " -> no occupant in guessed state\n");
|
||||
std::cerr << " -> no occupant in guessed state\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Dump all guessed state units for full picture
|
||||
fprintf(stderr, " Guessed state units (%u total):\n", guessedState->units()->size());
|
||||
std::cerr << " Guessed state units (" << guessedState->units()->size() << " total):\n";
|
||||
for (size_t i = 0; i < guessedState->units()->size(); i++) {
|
||||
const auto *u = guessedState->units()->Get(static_cast<unsigned int>(i));
|
||||
fprintf(stderr,
|
||||
" unit_id=%d player=%d status=%d loc=(%d,%d) hidden=%d "
|
||||
"starting_pos_idx=%d\n",
|
||||
u->unit_id(),
|
||||
u->player_id(),
|
||||
static_cast<int>(u->status()),
|
||||
u->location().row(),
|
||||
u->location().column(),
|
||||
u->hidden(),
|
||||
u->starting_position_index());
|
||||
std::cerr << " unit_id=" << u->unit_id() << " player=" << u->player_id()
|
||||
<< " status=" << static_cast<int>(u->status()) << " loc=("
|
||||
<< u->location().row() << "," << u->location().column()
|
||||
<< ") hidden=" << u->hidden()
|
||||
<< " starting_pos_idx=" << u->starting_position_index() << "\n";
|
||||
}
|
||||
|
||||
throw ShardokInternalErrorException(
|
||||
@@ -356,9 +336,9 @@ auto ShardokAIClient::StandardChooseCommandIndex(
|
||||
|
||||
// Write the flatbuffer game state to file using SaveTo method
|
||||
if (guessedState.SaveTo(statePath)) {
|
||||
printf("Game state dumped to: %s\n", statePath.c_str());
|
||||
std::cout << "Game state dumped to: " << statePath << '\n';
|
||||
} else {
|
||||
printf("Failed to dump game state to: %s\n", statePath.c_str());
|
||||
std::cout << "Failed to dump game state to: " << statePath << '\n';
|
||||
}
|
||||
#endif // ENABLE_MCTS_DEBUG_DUMP
|
||||
|
||||
@@ -396,19 +376,17 @@ auto ShardokAIClient::StandardChooseCommandIndex(
|
||||
|
||||
if constexpr (kPerformanceLogging) {
|
||||
if (result.commandCountEvaluated < result.availableCommandCount) {
|
||||
printf("ID AI: Depth %d - evaluated %lu/%zu commands\n",
|
||||
result.depthAchieved,
|
||||
result.commandCountEvaluated,
|
||||
result.availableCommandCount);
|
||||
std::cout << "ID AI: Depth " << result.depthAchieved << " - evaluated "
|
||||
<< result.commandCountEvaluated << '/' << result.availableCommandCount
|
||||
<< " commands\n";
|
||||
}
|
||||
const auto chosenCommandType =
|
||||
(*realAvailableCommands)[result.chosenIndex]->GetCommandType();
|
||||
printf("ID AI: Search complete - achieved depth %d for best command %zu (%s)\n",
|
||||
result.depthAchieved,
|
||||
result.chosenIndex,
|
||||
net::eagle0::shardok::common::CommandType_Name(chosenCommandType).c_str());
|
||||
std::cout << "ID AI: Search complete - achieved depth " << result.depthAchieved
|
||||
<< " for best command " << result.chosenIndex << " ("
|
||||
<< net::eagle0::shardok::common::CommandType_Name(chosenCommandType) << ")\n";
|
||||
|
||||
fflush(stdout);
|
||||
std::cout << std::flush;
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -510,7 +488,7 @@ auto ShardokAIClient::ChooseCommandIndex(
|
||||
totalChoices++;
|
||||
|
||||
if (totalChoices % 1000 == 0) {
|
||||
printf("TYPES CHOSEN:\n");
|
||||
std::cout << "TYPES CHOSEN:\n";
|
||||
vector<std::pair<int, CommandType>> choices{};
|
||||
for (int i = 0; i <= net::eagle0::shardok::common::CommandType_MAX; i++) {
|
||||
if (typeChosenCount[i] != 0) {
|
||||
@@ -521,9 +499,9 @@ auto ShardokAIClient::ChooseCommandIndex(
|
||||
std::ranges::sort(choices);
|
||||
std::ranges::reverse(choices);
|
||||
for (const auto &[index, choice] : choices) {
|
||||
printf("%5d %s\n", index, CommandType_Name(choice).c_str());
|
||||
std::cout << std::setw(5) << index << ' ' << CommandType_Name(choice) << '\n';
|
||||
}
|
||||
printf("\n\n");
|
||||
std::cout << "\n\n";
|
||||
}
|
||||
|
||||
return results;
|
||||
@@ -533,7 +511,7 @@ auto ShardokAIClient::ChooseCommandIndex(const ShardokEngine &engine) const
|
||||
-> CommandChoiceResults {
|
||||
if (const auto &availableCommands = engine.GetAvailableCommandsForAIPlayer(playerId);
|
||||
availableCommands->empty()) {
|
||||
printf("no commands for player %d\n", playerId);
|
||||
std::cout << "no commands for player " << playerId << '\n';
|
||||
throw ShardokInternalErrorException(
|
||||
"Asked to choose a command, but there are none available");
|
||||
} else {
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
|
||||
#include "TranspositionTable.hpp"
|
||||
|
||||
#include <cinttypes>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
|
||||
namespace shardok {
|
||||
|
||||
@@ -100,15 +100,23 @@ void TranspositionTable::clear() {
|
||||
current_age = 0;
|
||||
}
|
||||
|
||||
void TranspositionTable::printStats() const {
|
||||
printf("TranspositionTable Stats:\n");
|
||||
printf(" Probes: %" PRIu64 "\n", stats.probes.load());
|
||||
printf(" Hits: %" PRIu64 " (%.1f%%)\n", stats.hits.load(), stats.hitRate());
|
||||
printf(" Stores: %" PRIu64 "\n", stats.stores.load());
|
||||
printf(" Collisions: %" PRIu64 "\n", stats.collisions.load());
|
||||
printf(" Table size: %zu entries (%.1f MB)\n",
|
||||
TABLE_SIZE,
|
||||
(TABLE_SIZE * sizeof(TTEntry)) / (1024.0 * 1024.0));
|
||||
void TranspositionTable::printStats() const { printStats(std::cout); }
|
||||
|
||||
void TranspositionTable::printStats(std::ostream& output) const {
|
||||
const auto flags = output.flags();
|
||||
const auto precision = output.precision();
|
||||
|
||||
output << "TranspositionTable Stats:\n"
|
||||
<< " Probes: " << stats.probes.load() << '\n'
|
||||
<< " Hits: " << stats.hits.load() << " (" << std::fixed << std::setprecision(1)
|
||||
<< stats.hitRate() << "%)\n"
|
||||
<< " Stores: " << stats.stores.load() << '\n'
|
||||
<< " Collisions: " << stats.collisions.load() << '\n'
|
||||
<< " Table size: " << TABLE_SIZE << " entries ("
|
||||
<< (TABLE_SIZE * sizeof(TTEntry)) / (1024.0 * 1024.0) << " MB)\n";
|
||||
|
||||
output.flags(flags);
|
||||
output.precision(precision);
|
||||
}
|
||||
|
||||
} // namespace shardok
|
||||
} // namespace shardok
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <atomic>
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
#include <ostream>
|
||||
#include <vector>
|
||||
|
||||
#include "src/main/cpp/net/eagle0/shardok/library/GameStateW.hpp"
|
||||
@@ -81,6 +82,7 @@ public:
|
||||
|
||||
// Print statistics to stdout
|
||||
void printStats() const;
|
||||
void printStats(std::ostream& output) const;
|
||||
};
|
||||
|
||||
// Global instance for the AI to use
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <numeric>
|
||||
|
||||
#include "ShardokAction.hpp"
|
||||
@@ -509,7 +511,9 @@ size_t ShardokGameEngine::mapFilteredIndexToOriginal(
|
||||
return shardokAction->getIndex();
|
||||
}
|
||||
|
||||
void ShardokGameEngine::reportCacheStatistics() const {
|
||||
void ShardokGameEngine::reportCacheStatistics() const { reportCacheStatistics(std::cout); }
|
||||
|
||||
void ShardokGameEngine::reportCacheStatistics(std::ostream& output) const {
|
||||
const uint64_t hits = cacheHits_.load(std::memory_order_relaxed);
|
||||
const uint64_t misses = cacheMisses_.load(std::memory_order_relaxed);
|
||||
const uint64_t hashTime = timeInHashComputation_.load(std::memory_order_relaxed);
|
||||
@@ -523,27 +527,29 @@ void ShardokGameEngine::reportCacheStatistics() const {
|
||||
const double avgActionsTimeUs =
|
||||
misses > 0 ? static_cast<double>(actionsTime) / static_cast<double>(misses) : 0.0;
|
||||
|
||||
printf("Legal Actions Cache Stats:\n");
|
||||
printf(" Lookups: %llu hits, %llu misses, %.1f%% hit rate, %zu entries\n",
|
||||
static_cast<unsigned long long>(hits),
|
||||
static_cast<unsigned long long>(misses),
|
||||
hitRate * 100.0,
|
||||
legalActionsCache_.size());
|
||||
printf(" Timing: %.2f us avg hash, %.2f us avg actions (on miss)\n",
|
||||
avgHashTimeUs,
|
||||
avgActionsTimeUs);
|
||||
printf(" Total time: %.2f ms in hash, %.2f ms in actions\n",
|
||||
hashTime / 1000.0,
|
||||
actionsTime / 1000.0);
|
||||
|
||||
// Calculate if transposition table is worth it
|
||||
const double timeWithCache = hashTime + actionsTime;
|
||||
const double timeWithoutCache =
|
||||
avgActionsTimeUs * static_cast<double>(totalLookups); // All lookups recompute
|
||||
const double savings = (timeWithoutCache - timeWithCache) / timeWithoutCache * 100.0;
|
||||
printf(" Cache savings: %.1f%% vs. no cache (%.2f ms saved)\n",
|
||||
savings,
|
||||
(timeWithoutCache - timeWithCache) / 1000.0);
|
||||
|
||||
const auto flags = output.flags();
|
||||
const auto precision = output.precision();
|
||||
|
||||
output << "Legal Actions Cache Stats:\n"
|
||||
<< " Lookups: " << hits << " hits, " << misses << " misses, " << std::fixed
|
||||
<< std::setprecision(1) << hitRate * 100.0 << "% hit rate, "
|
||||
<< legalActionsCache_.size() << " entries\n"
|
||||
<< " Timing: " << std::setprecision(2) << avgHashTimeUs << " us avg hash, "
|
||||
<< avgActionsTimeUs << " us avg actions (on miss)\n"
|
||||
<< " Total time: " << hashTime / 1000.0 << " ms in hash, " << actionsTime / 1000.0
|
||||
<< " ms in actions\n"
|
||||
<< " Cache savings: " << std::setprecision(1) << savings << "% vs. no cache ("
|
||||
<< std::setprecision(2) << (timeWithoutCache - timeWithCache) / 1000.0
|
||||
<< " ms saved)\n";
|
||||
|
||||
output.flags(flags);
|
||||
output.precision(precision);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <functional>
|
||||
#include <gtl/phmap.hpp>
|
||||
#include <memory>
|
||||
#include <ostream>
|
||||
#include <vector>
|
||||
|
||||
#include "src/main/cpp/net/eagle0/common/mcts/abstract/MCTSGameEngine.hpp"
|
||||
@@ -92,6 +93,7 @@ public:
|
||||
|
||||
// Report transposition table statistics
|
||||
void reportCacheStatistics() const;
|
||||
void reportCacheStatistics(std::ostream& output) const;
|
||||
|
||||
// Reset cache statistics
|
||||
void resetCacheStatistics();
|
||||
|
||||
@@ -5,8 +5,6 @@
|
||||
#ifndef EAGLE0_SHARDOK_AI_SCORE_AI_SCORE_CALCULATOR_HPP
|
||||
#define EAGLE0_SHARDOK_AI_SCORE_AI_SCORE_CALCULATOR_HPP
|
||||
|
||||
#include <future>
|
||||
|
||||
#include "src/main/cpp/net/eagle0/shardok/ai/AIAttackLocations.hpp"
|
||||
#include "src/main/cpp/net/eagle0/shardok/library/GameStateW.hpp"
|
||||
#include "src/main/cpp/net/eagle0/shardok/library/ShardokCTypes.h"
|
||||
@@ -16,8 +14,6 @@
|
||||
namespace shardok {
|
||||
|
||||
using shardok::PlayerId;
|
||||
using std::future;
|
||||
using std::vector;
|
||||
|
||||
using ScoreValue = double;
|
||||
|
||||
|
||||
@@ -20,7 +20,6 @@ namespace shardok {
|
||||
|
||||
using GameState = net::eagle0::shardok::storage::fb::GameState;
|
||||
using net::eagle0::shardok::storage::fb::PlayerInfo;
|
||||
using std::vector;
|
||||
|
||||
using ScoreValue = double;
|
||||
|
||||
|
||||
@@ -8,6 +8,9 @@
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
#include <cmath>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "private/AIScoreCalculatorSharedUtilities.hpp"
|
||||
@@ -57,11 +60,12 @@ struct AttackerScorePerformanceLogger {
|
||||
if (callCount.load() % LOG_INTERVAL == 0) {
|
||||
double intervalAvg = intervalTime.load() / LOG_INTERVAL;
|
||||
double overallAvg = totalTime.load() / callCount.load();
|
||||
printf("AttackerScoreForState: %d calls, last %d avg: %.1f µs, overall avg: %.1f µs\n",
|
||||
callCount.load(),
|
||||
LOG_INTERVAL,
|
||||
intervalAvg * 1000000.0,
|
||||
overallAvg * 1000000.0);
|
||||
std::ostringstream message;
|
||||
message << std::fixed << std::setprecision(1)
|
||||
<< "AttackerScoreForState: " << callCount.load() << " calls, last "
|
||||
<< LOG_INTERVAL << " avg: " << intervalAvg * 1000000.0
|
||||
<< " µs, overall avg: " << overallAvg * 1000000.0 << " µs\n";
|
||||
std::cout << message.str();
|
||||
intervalTime.store(0.0); // Reset for next interval
|
||||
}
|
||||
}
|
||||
|
||||
@@ -359,7 +359,8 @@ GameStateW AiBattleSimulator::CreateInitialGameState() const {
|
||||
std::vector<net::eagle0::shardok::storage::fb::Unit> units;
|
||||
|
||||
// Attacker units
|
||||
for (int i = 0; i < config_.attacker().units_size(); ++i) {
|
||||
const int attackerUnitCount = config_.attacker().units_size();
|
||||
for (int i = 0; i < attackerUnitCount; ++i) {
|
||||
const auto& unitConfig = config_.attacker().units(i);
|
||||
|
||||
net::eagle0::shardok::storage::fb::Unit unit{};
|
||||
@@ -453,8 +454,9 @@ GameStateW AiBattleSimulator::CreateInitialGameState() const {
|
||||
}
|
||||
|
||||
// Defender units
|
||||
int defenderUnitIdStart = config_.attacker().units_size();
|
||||
for (int i = 0; i < config_.defender().units_size(); ++i) {
|
||||
const int defenderUnitIdStart = attackerUnitCount;
|
||||
const int defenderUnitCount = config_.defender().units_size();
|
||||
for (int i = 0; i < defenderUnitCount; ++i) {
|
||||
const auto& unitConfig = config_.defender().units(i);
|
||||
|
||||
net::eagle0::shardok::storage::fb::Unit unit{};
|
||||
@@ -678,8 +680,9 @@ BattleResult AiBattleSimulator::RunConfiguredSetupPhase(ShardokEngine& engine) {
|
||||
playerConfig,
|
||||
int unitIdOffset) {
|
||||
std::vector<UnitPlacementInfo> placements;
|
||||
placements.reserve(playerConfig.units_size());
|
||||
for (int i = 0; i < playerConfig.units_size(); ++i) {
|
||||
const int unitCount = playerConfig.units_size();
|
||||
placements.reserve(unitCount);
|
||||
for (int i = 0; i < unitCount; ++i) {
|
||||
const auto& unitConfig = playerConfig.units(i);
|
||||
if (!unitConfig.has_fixed_position()) {
|
||||
throw std::invalid_argument(
|
||||
|
||||
@@ -18,7 +18,15 @@
|
||||
#include "src/main/cpp/net/eagle0/shardok/library/ShardokEngine.hpp"
|
||||
#include "src/main/protobuf/net/eagle0/shardok/common/command_type.pb.h"
|
||||
|
||||
using namespace shardok;
|
||||
using shardok::AIAlgorithmType;
|
||||
using shardok::AIPerformanceMetrics;
|
||||
using shardok::EvaluationCompletionReason;
|
||||
using shardok::PerformanceTestConfig;
|
||||
using shardok::PerformanceTestGameStateBuilder;
|
||||
using shardok::PlayerId;
|
||||
using shardok::ShardokAIClient;
|
||||
using shardok::ShardokEngine;
|
||||
namespace ai_testing_common = shardok::ai_testing_common;
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -300,4 +308,4 @@ int main(int argc, char* argv[]) {
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,13 +5,15 @@
|
||||
#ifndef EAGLE0_SHARDOK_CONTROLLER_GAME_UPDATE_RECEIVER_HPP
|
||||
#define EAGLE0_SHARDOK_CONTROLLER_GAME_UPDATE_RECEIVER_HPP
|
||||
|
||||
#include <atomic>
|
||||
#include <vector>
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wdeprecated-redundant-constexpr-static-def"
|
||||
#include "src/main/protobuf/net/eagle0/shardok/api/action_result_view.pb.h"
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
namespace shardok {
|
||||
using std::vector;
|
||||
|
||||
class GameUpdateReceiver {
|
||||
private:
|
||||
@@ -25,7 +27,7 @@ public:
|
||||
virtual ~GameUpdateReceiver() = default;
|
||||
virtual void ReceiveActionResult(const net::eagle0::shardok::api::ActionResultView& result) = 0;
|
||||
virtual void ReceiveActionResults(
|
||||
const vector<net::eagle0::shardok::api::ActionResultView>& results) = 0;
|
||||
const std::vector<net::eagle0::shardok::api::ActionResultView>& results) = 0;
|
||||
|
||||
[[nodiscard]] auto GetIdentifier() const -> long { return identifier; }
|
||||
};
|
||||
|
||||
@@ -27,7 +27,6 @@ using net::eagle0::common::ScopedShardokLatencyTrace;
|
||||
using std::condition_variable;
|
||||
using std::mutex;
|
||||
using std::scoped_lock;
|
||||
using std::string;
|
||||
using std::unique_lock;
|
||||
using std::weak_ptr;
|
||||
|
||||
@@ -40,7 +39,7 @@ private:
|
||||
PlayerId shardokPlayerId;
|
||||
int eagleFactionId;
|
||||
|
||||
string message;
|
||||
std::string message;
|
||||
|
||||
public:
|
||||
MismatchedPlayerIdException(const PlayerId shardokPid, const int eagleFid)
|
||||
@@ -57,7 +56,7 @@ class MissingPlayerIdException : public std::exception {
|
||||
private:
|
||||
PlayerId shardokPlayerId;
|
||||
|
||||
string message;
|
||||
std::string message;
|
||||
|
||||
public:
|
||||
MissingPlayerIdException(const PlayerId shardokPid) : shardokPlayerId(shardokPid) {
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "AvailableCommandsFactory.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <ranges>
|
||||
|
||||
#include "src/main/cpp/net/eagle0/shardok/library/FireUtils.hpp"
|
||||
@@ -21,8 +22,6 @@
|
||||
#include "src/main/cpp/net/eagle0/shardok/library/view_filters/GameStateFilter.hpp"
|
||||
#include "src/main/cpp/net/eagle0/shardok/library/view_filters/GameStateGuesser.hpp"
|
||||
|
||||
using std::make_shared;
|
||||
|
||||
namespace shardok {
|
||||
|
||||
class AvailableCommandsFactoryImpl : public AvailableCommandsFactory {
|
||||
@@ -51,7 +50,7 @@ private:
|
||||
return (player == end(*gameState->player_infos()) || !player->is_defender());
|
||||
}
|
||||
|
||||
const vector<shared_ptr<const CommandFactory>> commandFactories;
|
||||
const std::vector<std::shared_ptr<const CommandFactory>> commandFactories;
|
||||
const PlayerSetupCommandFactory playerSetupCommandFactory;
|
||||
|
||||
// AvailableCommands helpers for a single unit
|
||||
@@ -97,7 +96,7 @@ auto AvailableCommandsFactoryImpl::GetPlayerSetupCommands(
|
||||
gameState,
|
||||
reinforcementPositions);
|
||||
|
||||
return make_shared<CommandList>(previewCommands);
|
||||
return std::make_shared<CommandList>(previewCommands);
|
||||
}
|
||||
|
||||
void AvailableCommandsFactoryImpl::AddAvailableCommandsForOneUnit(
|
||||
@@ -116,7 +115,7 @@ void AvailableCommandsFactoryImpl::AddAvailableCommandsForOneUnit(
|
||||
const Coords ¤tCoords = unit->location();
|
||||
|
||||
const bool isEligibleCharger = unit->unit_id() == gameState->eligible_charger_id();
|
||||
vector<UnitId> possibleChargees{};
|
||||
std::vector<UnitId> possibleChargees{};
|
||||
for (const UnitId cid : *gameState->possible_chargee_ids()) {
|
||||
if (cid != -1) { possibleChargees.push_back(cid); }
|
||||
}
|
||||
@@ -195,11 +194,11 @@ auto AvailableCommandsFactoryImpl::GetAvailableCommands(
|
||||
const std::optional<std::vector<Coords>> &reinforcementPositions) const -> CommandListSPtr {
|
||||
CommandList commands{};
|
||||
|
||||
vector<AdjacentTile> adjacentTiles;
|
||||
std::vector<AdjacentTile> adjacentTiles;
|
||||
|
||||
playerSetupCommandFactory
|
||||
.AddAvailablePlayerSetupCommands(commands, playerId, gameState, reinforcementPositions);
|
||||
if (!commands.empty()) return make_shared<CommandList>(commands);
|
||||
if (!commands.empty()) return std::make_shared<CommandList>(commands);
|
||||
|
||||
for (const Unit *unit : *gameState->units()) {
|
||||
if (unit->status() != net::eagle0::shardok::storage::fb::UnitStatus_NORMAL_UNIT) continue;
|
||||
@@ -251,7 +250,7 @@ auto AvailableCommandsFactoryImpl::GetAvailableCommands(
|
||||
}
|
||||
|
||||
if (commands.empty()) return nullptr;
|
||||
return make_shared<CommandList>(commands);
|
||||
return std::make_shared<CommandList>(commands);
|
||||
}
|
||||
|
||||
} // namespace shardok
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#ifndef EAGLE0_SHARDOK_LIBRARY_AVAILABLE_COMMANDS_FACTORY_HPP
|
||||
#define EAGLE0_SHARDOK_LIBRARY_AVAILABLE_COMMANDS_FACTORY_HPP
|
||||
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
@@ -20,14 +21,12 @@
|
||||
|
||||
namespace shardok {
|
||||
|
||||
using std::optional;
|
||||
using std::unique_ptr;
|
||||
using UnitIdOptional = optional<UnitId>;
|
||||
using UnitIdOptional = std::optional<UnitId>;
|
||||
|
||||
class AvailableCommandsFactory {
|
||||
public:
|
||||
static auto MakeAvailableCommandsFactory(const SettingsGetter &settingsGetter)
|
||||
-> unique_ptr<AvailableCommandsFactory>;
|
||||
-> std::unique_ptr<AvailableCommandsFactory>;
|
||||
|
||||
virtual ~AvailableCommandsFactory() = default;
|
||||
|
||||
|
||||
@@ -8,17 +8,18 @@
|
||||
|
||||
#include "BattalionType.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <mutex>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "src/main/cpp/net/eagle0/common/MapUtils.hpp"
|
||||
|
||||
namespace shardok {
|
||||
using std::unordered_map;
|
||||
|
||||
using BattalionTypeId = net::eagle0::shardok::storage::fb::BattalionTypeId;
|
||||
|
||||
ActionCost actionCostForKey(const unordered_map<string, string> &map, const string &key) {
|
||||
ActionCost actionCostForKey(
|
||||
const std::unordered_map<std::string, std::string> &map,
|
||||
const std::string &key) {
|
||||
const int pointCost = IntForKey(map, key);
|
||||
|
||||
return pointCost == -1 ? IMPOSSIBLE_ACTION_COST : ActionCost::StandardActionCost(pointCost);
|
||||
@@ -27,7 +28,7 @@ ActionCost actionCostForKey(const unordered_map<string, string> &map, const stri
|
||||
std::shared_ptr<const BattalionType> BattalionType::NewBattalionTypeFromMap(
|
||||
const std::unordered_map<std::string, std::string> &map) {
|
||||
try {
|
||||
auto *newType = new BattalionType{
|
||||
return std::make_shared<const BattalionType>(BattalionType{
|
||||
map.at("TypeName"),
|
||||
BattalionTypeId(std::stoi(map.at("TypeId"))),
|
||||
IntForKey(map, "Capacity"),
|
||||
@@ -171,11 +172,9 @@ std::shared_ptr<const BattalionType> BattalionType::NewBattalionTypeFromMap(
|
||||
DoubleForKey(map, "AmbushOddsWithoutHero"),
|
||||
DoubleForKey(map, "BaseStunChanceOnCharge"),
|
||||
DoubleForKey(map, "TrainingDifferenceMultiplierForStunChanceOnCharge"),
|
||||
DoubleForKey(map, "MonthlyFoodCost")};
|
||||
|
||||
return std::shared_ptr<const BattalionType>(newType);
|
||||
DoubleForKey(map, "MonthlyFoodCost")});
|
||||
} catch (const std::out_of_range &e) {
|
||||
printf("Failed to parse file map; caught exception %s\n", e.what());
|
||||
std::cerr << "Failed to parse file map; caught exception " << e.what() << '\n';
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@@ -244,33 +245,27 @@ public:
|
||||
}
|
||||
|
||||
[[nodiscard]] auto ToString() const -> std::string {
|
||||
std::array<char, 1024> buffer{};
|
||||
snprintf(
|
||||
buffer.data(),
|
||||
buffer.size(),
|
||||
"slashing=%f / %f, puncturing=%f / %f, stabbing=%f / %f, crushing=%f / %f, "
|
||||
"fire=%f / "
|
||||
"%f, cold=%f / %f, lightning=%f / %f, aessence=%f / %f, impact=%f / %f",
|
||||
GetNormalDamageOfType(DamageType_slashing),
|
||||
GetPenetratingDamageOfType(DamageType_slashing),
|
||||
GetNormalDamageOfType(DamageType_puncturing),
|
||||
GetPenetratingDamageOfType(DamageType_puncturing),
|
||||
GetNormalDamageOfType(DamageType_stabbing),
|
||||
GetPenetratingDamageOfType(DamageType_stabbing),
|
||||
GetNormalDamageOfType(DamageType_crushing),
|
||||
GetPenetratingDamageOfType(DamageType_crushing),
|
||||
GetNormalDamageOfType(DamageType_fire),
|
||||
GetPenetratingDamageOfType(DamageType_fire),
|
||||
GetNormalDamageOfType(DamageType_cold),
|
||||
GetPenetratingDamageOfType(DamageType_cold),
|
||||
GetNormalDamageOfType(DamageType_lightning),
|
||||
GetPenetratingDamageOfType(DamageType_lightning),
|
||||
GetNormalDamageOfType(DamageType_aessence),
|
||||
GetPenetratingDamageOfType(DamageType_aessence),
|
||||
GetNormalDamageOfType(DamageType_impact),
|
||||
GetPenetratingDamageOfType(DamageType_impact));
|
||||
|
||||
return {buffer.data()};
|
||||
std::ostringstream out;
|
||||
out << std::fixed << std::setprecision(6)
|
||||
<< "slashing=" << GetNormalDamageOfType(DamageType_slashing) << " / "
|
||||
<< GetPenetratingDamageOfType(DamageType_slashing)
|
||||
<< ", puncturing=" << GetNormalDamageOfType(DamageType_puncturing) << " / "
|
||||
<< GetPenetratingDamageOfType(DamageType_puncturing)
|
||||
<< ", stabbing=" << GetNormalDamageOfType(DamageType_stabbing) << " / "
|
||||
<< GetPenetratingDamageOfType(DamageType_stabbing)
|
||||
<< ", crushing=" << GetNormalDamageOfType(DamageType_crushing) << " / "
|
||||
<< GetPenetratingDamageOfType(DamageType_crushing)
|
||||
<< ", fire=" << GetNormalDamageOfType(DamageType_fire) << " / "
|
||||
<< GetPenetratingDamageOfType(DamageType_fire)
|
||||
<< ", cold=" << GetNormalDamageOfType(DamageType_cold) << " / "
|
||||
<< GetPenetratingDamageOfType(DamageType_cold)
|
||||
<< ", lightning=" << GetNormalDamageOfType(DamageType_lightning) << " / "
|
||||
<< GetPenetratingDamageOfType(DamageType_lightning)
|
||||
<< ", aessence=" << GetNormalDamageOfType(DamageType_aessence) << " / "
|
||||
<< GetPenetratingDamageOfType(DamageType_aessence)
|
||||
<< ", impact=" << GetNormalDamageOfType(DamageType_impact) << " / "
|
||||
<< GetPenetratingDamageOfType(DamageType_impact);
|
||||
return out.str();
|
||||
}
|
||||
|
||||
class Builder {
|
||||
|
||||
@@ -10,12 +10,10 @@
|
||||
|
||||
namespace shardok {
|
||||
|
||||
using std::vector;
|
||||
|
||||
auto ShardokAction::Execute(
|
||||
const GameStateW& currentState,
|
||||
const std::shared_ptr<RandomGenerator>& generator) const -> vector<ActionResult> {
|
||||
vector<ActionResult> results = InternalExecute(currentState, generator);
|
||||
const std::shared_ptr<RandomGenerator>& generator) const -> std::vector<ActionResult> {
|
||||
std::vector<ActionResult> results = InternalExecute(currentState, generator);
|
||||
|
||||
return results;
|
||||
}
|
||||
@@ -23,10 +21,10 @@ auto ShardokAction::Execute(
|
||||
auto ShardokAction::ExecuteWithRoll(
|
||||
const GameStateW& currentState,
|
||||
const std::shared_ptr<RandomGenerator>& generator,
|
||||
const std::optional<int32_t> roll) const -> vector<ActionResult> {
|
||||
vector<ActionResult> results = InternalExecuteWithRoll(currentState, generator, roll);
|
||||
const std::optional<int32_t> roll) const -> std::vector<ActionResult> {
|
||||
std::vector<ActionResult> results = InternalExecuteWithRoll(currentState, generator, roll);
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
} // namespace shardok
|
||||
} // namespace shardok
|
||||
|
||||
@@ -9,6 +9,9 @@
|
||||
#ifndef EAGLE0_SHARDOK_LIBRARY_SHARDOK_ACTION_HPP
|
||||
#define EAGLE0_SHARDOK_LIBRARY_SHARDOK_ACTION_HPP
|
||||
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "ShardokException.hpp"
|
||||
@@ -22,8 +25,6 @@
|
||||
namespace shardok {
|
||||
|
||||
using net::eagle0::shardok::storage::ActionResult;
|
||||
using std::shared_ptr;
|
||||
using std::vector;
|
||||
using PercentileRollOdds = net::eagle0::shardok::storage::Odds;
|
||||
|
||||
class IllegalActionException : public ShardokException {
|
||||
|
||||
@@ -57,9 +57,9 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
using CommandSPtr = shared_ptr<ShardokCommand>;
|
||||
using CommandList = vector<CommandSPtr>;
|
||||
using CommandListSPtr = shared_ptr<const CommandList>;
|
||||
using CommandSPtr = std::shared_ptr<ShardokCommand>;
|
||||
using CommandList = std::vector<CommandSPtr>;
|
||||
using CommandListSPtr = std::shared_ptr<const CommandList>;
|
||||
|
||||
} // namespace shardok
|
||||
|
||||
|
||||
@@ -14,12 +14,11 @@
|
||||
#include <utility>
|
||||
|
||||
namespace shardok {
|
||||
using std::string;
|
||||
|
||||
class ShardokException : public std::exception {
|
||||
protected:
|
||||
string description;
|
||||
explicit ShardokException(string desc) : description(std::move(desc)) {}
|
||||
std::string description;
|
||||
explicit ShardokException(std::string desc) : description(std::move(desc)) {}
|
||||
|
||||
public:
|
||||
[[nodiscard]] auto what() const noexcept -> const char* override {
|
||||
@@ -30,13 +29,13 @@ public:
|
||||
// Thrown when the client has provided us with bad info. The game state should still be OK.
|
||||
class ShardokClientErrorException : public ShardokException {
|
||||
public:
|
||||
explicit ShardokClientErrorException(const string& desc) : ShardokException(desc) {}
|
||||
explicit ShardokClientErrorException(const std::string& desc) : ShardokException(desc) {}
|
||||
};
|
||||
|
||||
// Thrown when we have some bad internal state. Probably not recoverable.
|
||||
class ShardokInternalErrorException : public ShardokException {
|
||||
public:
|
||||
explicit ShardokInternalErrorException(const string& desc) : ShardokException(desc) {}
|
||||
explicit ShardokInternalErrorException(const std::string& desc) : ShardokException(desc) {}
|
||||
};
|
||||
|
||||
static inline void internalAssert(const bool condition) {
|
||||
@@ -49,13 +48,13 @@ static inline void internalAssert(const bool condition, const std::string& messa
|
||||
|
||||
class ShardokNotImplementedException : public ShardokException {
|
||||
public:
|
||||
explicit ShardokNotImplementedException(const string& operation)
|
||||
explicit ShardokNotImplementedException(const std::string& operation)
|
||||
: ShardokException("Operation " + operation + " is not yet implemented.") {}
|
||||
};
|
||||
|
||||
class ShardokEagleInterfaceException : public ShardokException {
|
||||
public:
|
||||
explicit ShardokEagleInterfaceException(const string& desc) : ShardokException(desc) {}
|
||||
explicit ShardokEagleInterfaceException(const std::string& desc) : ShardokException(desc) {}
|
||||
};
|
||||
} // namespace shardok
|
||||
|
||||
|
||||
+14
-16
@@ -11,9 +11,6 @@
|
||||
#include "src/main/cpp/net/eagle0/shardok/library/util/HexMapUtils.hpp"
|
||||
|
||||
namespace shardok {
|
||||
using std::begin;
|
||||
using std::end;
|
||||
using std::vector;
|
||||
|
||||
struct ActionPointDistances::BraveableTileInfo {
|
||||
struct BraveableFromInfo {
|
||||
@@ -22,7 +19,7 @@ struct ActionPointDistances::BraveableTileInfo {
|
||||
};
|
||||
|
||||
CoordsSet cs;
|
||||
vector<BraveableFromInfo> details;
|
||||
std::vector<BraveableFromInfo> details;
|
||||
|
||||
explicit BraveableTileInfo(const HexMap* hexMap) : cs(hexMap) {}
|
||||
};
|
||||
@@ -68,10 +65,10 @@ auto ActionPointDistances::BraveWaterPossibleCoords(const HexMap* hexMap) const
|
||||
return info;
|
||||
}
|
||||
|
||||
auto ActionPointDistances::CreateIndexToCoords(const HexMap* hexMap) -> vector<Coords> {
|
||||
auto ActionPointDistances::CreateIndexToCoords(const HexMap* hexMap) -> std::vector<Coords> {
|
||||
const int8_t columnCount = hexMap->column_count();
|
||||
const int indexCount = hexMap->row_count() * columnCount;
|
||||
vector<Coords> indexToCoords;
|
||||
std::vector<Coords> indexToCoords;
|
||||
indexToCoords.reserve(indexCount);
|
||||
for (int i = 0; i < indexCount; i++) {
|
||||
indexToCoords.emplace_back(
|
||||
@@ -82,10 +79,10 @@ auto ActionPointDistances::CreateIndexToCoords(const HexMap* hexMap) -> vector<C
|
||||
}
|
||||
|
||||
auto ActionPointDistances::CreateAdjacencyTable(const HexMap* hexMap)
|
||||
-> vector<std::array<int, 6>> {
|
||||
-> std::vector<std::array<int, 6>> {
|
||||
const int8_t columnCount = hexMap->column_count();
|
||||
const int indexCount = hexMap->row_count() * columnCount;
|
||||
vector<std::array<int, 6>> adjacencyTable;
|
||||
std::vector<std::array<int, 6>> adjacencyTable;
|
||||
adjacencyTable.reserve(indexCount);
|
||||
for (int i = 0; i < indexCount; i++) {
|
||||
const Coords coords(
|
||||
@@ -105,22 +102,23 @@ auto ActionPointDistances::CreateAdjacencyTable(const HexMap* hexMap)
|
||||
}
|
||||
|
||||
void ActionPointDistances::PopulateOne(
|
||||
vector<DIST_T>& ds,
|
||||
std::vector<DIST_T>& ds,
|
||||
const HexMap* hexMap,
|
||||
const bool includeBravingWater,
|
||||
const int braveWaterCost,
|
||||
const BattalionTypeSPtr& battalionType,
|
||||
const std::shared_ptr<BraveableTileInfo>& braveWaterPossibleCoords,
|
||||
const vector<Coords>& indexToCoords,
|
||||
const vector<std::array<int, 6>>& adjacencyTable) {
|
||||
vector<uint8_t> visited(ds.size());
|
||||
const std::vector<Coords>& indexToCoords,
|
||||
const std::vector<std::array<int, 6>>& adjacencyTable) {
|
||||
std::vector<uint8_t> visited(ds.size());
|
||||
|
||||
// Priority queue for efficient minimum selection: {distance, index}
|
||||
std::priority_queue<std::pair<DIST_T, int>, std::vector<std::pair<DIST_T, int>>, std::greater<>>
|
||||
pq;
|
||||
|
||||
// Find starting index (the one with distance 0)
|
||||
for (int i = 0; i < static_cast<int>(ds.size()); i++) {
|
||||
const int distanceCount = static_cast<int>(ds.size());
|
||||
for (int i = 0; i < distanceCount; i++) {
|
||||
if (ds[i] == 0) {
|
||||
pq.emplace(0, i);
|
||||
break;
|
||||
@@ -206,9 +204,9 @@ auto ActionPointDistances::GenerateDistances(
|
||||
const bool includeBravingWater,
|
||||
const int braveWaterCost,
|
||||
const BattalionTypeSPtr& battalionType,
|
||||
const std::shared_ptr<BraveableTileInfo>& braveWaterPossibleCoords) -> vector<DIST_T> {
|
||||
const std::shared_ptr<BraveableTileInfo>& braveWaterPossibleCoords) -> std::vector<DIST_T> {
|
||||
const int indexCount = hexMap->row_count() * hexMap->column_count();
|
||||
auto ds = vector(indexCount, IMPOSSIBLE);
|
||||
auto ds = std::vector(indexCount, IMPOSSIBLE);
|
||||
|
||||
ds[fromIndex] = 0;
|
||||
|
||||
@@ -259,4 +257,4 @@ OnDemandActionPointDistances::OnDemandActionPointDistances(
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace shardok
|
||||
} // namespace shardok
|
||||
|
||||
+12
-11
@@ -5,8 +5,11 @@
|
||||
#ifndef EAGLE0_SHARDOK_LIBRARY_ACTION_POINT_DISTANCES_ACTION_POINT_DISTANCES_HPP
|
||||
#define EAGLE0_SHARDOK_LIBRARY_ACTION_POINT_DISTANCES_ACTION_POINT_DISTANCES_HPP
|
||||
|
||||
#include <array>
|
||||
#include <future>
|
||||
#include <optional>
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "src/main/cpp/net/eagle0/shardok/library/BattalionType.hpp"
|
||||
#include "src/main/cpp/net/eagle0/shardok/library/fb_helpers/FlatbufferWrapper.hpp"
|
||||
@@ -21,9 +24,6 @@ namespace shardok {
|
||||
using HexMap = net::eagle0::shardok::storage::fb::HexMap;
|
||||
using HexMapW = Wrapper<HexMap>;
|
||||
using Coords = net::eagle0::shardok::storage::fb::Coords;
|
||||
using std::optional;
|
||||
using std::shared_future;
|
||||
using std::vector;
|
||||
|
||||
using DIST_T = int16_t;
|
||||
|
||||
@@ -35,28 +35,29 @@ protected:
|
||||
struct BraveableTileInfo;
|
||||
|
||||
static void PopulateOne(
|
||||
vector<DIST_T> &ds,
|
||||
std::vector<DIST_T> &ds,
|
||||
const net::eagle0::shardok::storage::fb::HexMap *hexMap,
|
||||
bool includeBravingWater,
|
||||
int braveWaterCost,
|
||||
const BattalionTypeSPtr &battalionType,
|
||||
const std::shared_ptr<BraveableTileInfo> &braveWaterPossibleCoords,
|
||||
const vector<Coords> &indexToCoords,
|
||||
const vector<std::array<int, 6>> &adjacencyTable);
|
||||
const std::vector<Coords> &indexToCoords,
|
||||
const std::vector<std::array<int, 6>> &adjacencyTable);
|
||||
static auto GenerateDistances(
|
||||
int fromIndex,
|
||||
const HexMap *hexMap,
|
||||
bool includeBravingWater,
|
||||
int braveWaterCost,
|
||||
const BattalionTypeSPtr &battalionType,
|
||||
const std::shared_ptr<BraveableTileInfo> &braveWaterPossibleCoords) -> vector<DIST_T>;
|
||||
const std::shared_ptr<BraveableTileInfo> &braveWaterPossibleCoords)
|
||||
-> std::vector<DIST_T>;
|
||||
auto BraveWaterPossibleCoords(const HexMap *hexMap) const -> std::shared_ptr<BraveableTileInfo>;
|
||||
|
||||
// Create coordinate lookup table for efficient index->coords conversion
|
||||
static auto CreateIndexToCoords(const HexMap *hexMap) -> vector<Coords>;
|
||||
static auto CreateIndexToCoords(const HexMap *hexMap) -> std::vector<Coords>;
|
||||
|
||||
// Create adjacency lookup table for efficient neighbor access
|
||||
static auto CreateAdjacencyTable(const HexMap *hexMap) -> vector<std::array<int, 6>>;
|
||||
static auto CreateAdjacencyTable(const HexMap *hexMap) -> std::vector<std::array<int, 6>>;
|
||||
|
||||
[[nodiscard]] auto ToIndex(const Coords &coords) const -> int {
|
||||
return coords.row() * column_count + coords.column();
|
||||
@@ -79,7 +80,7 @@ private:
|
||||
const HexMapW hexMap;
|
||||
const BattalionTypeSPtr battalionType;
|
||||
|
||||
vector<shared_future<vector<int16_t>>> distances;
|
||||
std::vector<std::shared_future<std::vector<int16_t>>> distances;
|
||||
|
||||
public:
|
||||
explicit OnDemandActionPointDistances(
|
||||
|
||||
+11
-10
@@ -6,6 +6,8 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
#include <iostream>
|
||||
#include <ostream>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "src/main/cpp/net/eagle0/shardok/library/action_point_distances/FixedActionPointDistances.hpp"
|
||||
@@ -32,22 +34,21 @@ thread_local struct {
|
||||
} cacheStats;
|
||||
|
||||
// Helper function to print stats periodically
|
||||
static void MaybePrintCacheStats() {
|
||||
static void MaybePrintCacheStats(std::ostream& output) {
|
||||
auto now = std::chrono::steady_clock::now();
|
||||
if (std::chrono::duration_cast<std::chrono::seconds>(now - cacheStats.lastReportTime).count() >=
|
||||
kCacheStatsFrequencySeconds) {
|
||||
printf("Thread cache stats: %d persistent hits, %d persistent misses, %d local hits, "
|
||||
"%d local misses, %d shared accesses, %d eviction events\n",
|
||||
cacheStats.persistentHits,
|
||||
cacheStats.persistentMisses,
|
||||
cacheStats.localHits,
|
||||
cacheStats.localMisses,
|
||||
cacheStats.sharedAccesses,
|
||||
cacheStats.evictionEvents);
|
||||
output << "Thread cache stats: " << cacheStats.persistentHits << " persistent hits, "
|
||||
<< cacheStats.persistentMisses << " persistent misses, " << cacheStats.localHits
|
||||
<< " local hits, " << cacheStats.localMisses << " local misses, "
|
||||
<< cacheStats.sharedAccesses << " shared accesses, " << cacheStats.evictionEvents
|
||||
<< " eviction events\n";
|
||||
cacheStats.lastReportTime = now;
|
||||
}
|
||||
}
|
||||
|
||||
static void MaybePrintCacheStats() { MaybePrintCacheStats(std::cout); }
|
||||
|
||||
class BadHashException final : public std::exception {
|
||||
public:
|
||||
BadHashException() = default;
|
||||
@@ -154,7 +155,7 @@ auto ActionPointDistancesCache::GetRaw(
|
||||
if (kCacheStatsLogging) { cacheStats.localMisses++; }
|
||||
|
||||
// Check shared cache before expensive ice-clearing operation
|
||||
shared_ptr<ActionPointDistances> sharedResult;
|
||||
std::shared_ptr<ActionPointDistances> sharedResult;
|
||||
if (sharedDistances.if_contains(cacheKey, [&sharedResult](const auto& kv) {
|
||||
sharedResult = kv.second;
|
||||
})) {
|
||||
|
||||
+7
-7
@@ -5,6 +5,7 @@
|
||||
#ifndef EAGLE0_SHARDOK_LIBRARY_ACTION_POINT_DISTANCES_ACTION_POINT_DISTANCES_CACHE_HPP
|
||||
#define EAGLE0_SHARDOK_LIBRARY_ACTION_POINT_DISTANCES_ACTION_POINT_DISTANCES_CACHE_HPP
|
||||
|
||||
#include <memory>
|
||||
#include <shared_mutex>
|
||||
#include <unordered_map>
|
||||
|
||||
@@ -17,8 +18,6 @@
|
||||
|
||||
namespace shardok {
|
||||
|
||||
using std::shared_ptr;
|
||||
|
||||
struct MapId {
|
||||
uint64_t terrainTypesId;
|
||||
uint64_t modifierId;
|
||||
@@ -58,9 +57,10 @@ struct FullCacheKeyHash {
|
||||
class ActionPointDistancesCache {
|
||||
private:
|
||||
struct CacheEntry {
|
||||
shared_ptr<ActionPointDistances> sharedPtr;
|
||||
std::shared_ptr<ActionPointDistances> sharedPtr;
|
||||
|
||||
explicit CacheEntry(shared_ptr<ActionPointDistances> ptr) : sharedPtr(std::move(ptr)) {}
|
||||
explicit CacheEntry(std::shared_ptr<ActionPointDistances> ptr)
|
||||
: sharedPtr(std::move(ptr)) {}
|
||||
};
|
||||
|
||||
// Tier 1: persistent map. This is NOT safe to write to while reads may be happening.
|
||||
@@ -70,10 +70,10 @@ private:
|
||||
|
||||
using APDMap = gtl::parallel_flat_hash_map<
|
||||
FullCacheKey,
|
||||
shared_ptr<ActionPointDistances>,
|
||||
std::shared_ptr<ActionPointDistances>,
|
||||
FullCacheKeyHash,
|
||||
std::equal_to<FullCacheKey>,
|
||||
std::allocator<std::pair<const FullCacheKey, shared_ptr<ActionPointDistances>>>,
|
||||
std::allocator<std::pair<const FullCacheKey, std::shared_ptr<ActionPointDistances>>>,
|
||||
6,
|
||||
std::mutex>;
|
||||
|
||||
@@ -119,7 +119,7 @@ public:
|
||||
static size_t GetThreadLocalCacheSize();
|
||||
};
|
||||
|
||||
using APDCache = shared_ptr<ActionPointDistancesCache>;
|
||||
using APDCache = std::shared_ptr<ActionPointDistancesCache>;
|
||||
|
||||
} // namespace shardok
|
||||
|
||||
|
||||
@@ -54,31 +54,3 @@ cc_library(
|
||||
"//src/main/cpp/net/eagle0/shardok/library/fb_helpers:hex_map_helpers",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "fixed_action_point_distances_timer",
|
||||
srcs = ["FixedActionPointDistancesTimer.cpp"],
|
||||
copts = COPTS,
|
||||
data = [
|
||||
"//src/main/resources/net/eagle0/shardok/maps",
|
||||
],
|
||||
deps = [
|
||||
"//src/main/cpp/net/eagle0/common:sequence_random_generator",
|
||||
"//src/main/cpp/net/eagle0/shardok/library/action_point_distances:fixed_action_point_distances",
|
||||
"//src/main/cpp/net/eagle0/shardok/library/settings_loader",
|
||||
"//src/main/cpp/net/eagle0/shardok/util:map_loader",
|
||||
"@googletest//:gtest",
|
||||
"@googletest//:gtest_main",
|
||||
],
|
||||
)
|
||||
|
||||
cc_binary(
|
||||
name = "fixed_action_point_distances_timer_app",
|
||||
copts = COPTS,
|
||||
data = [
|
||||
"//src/main/resources/net/eagle0/shardok/maps",
|
||||
],
|
||||
deps = [
|
||||
":fixed_action_point_distances_timer",
|
||||
],
|
||||
)
|
||||
|
||||
+3
-4
@@ -4,6 +4,7 @@
|
||||
|
||||
#include "src/main/cpp/net/eagle0/shardok/library/action_point_distances/FixedActionPointDistances.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <thread>
|
||||
|
||||
#include "src/main/cpp/net/eagle0/shardok/library/map/CoordsSet.hpp"
|
||||
@@ -13,10 +14,8 @@ static const int ASYNC_COUNT = []() {
|
||||
const int cores = static_cast<int>(std::thread::hardware_concurrency());
|
||||
// Use cores-2 to leave room for OS and other processes, minimum 4 threads
|
||||
const int threadCount = std::max(4, cores - 4);
|
||||
fprintf(stderr,
|
||||
"ActionPointDistances using %d threads (detected %d cores)\n",
|
||||
threadCount,
|
||||
cores);
|
||||
std::cerr << "ActionPointDistances using " << threadCount << " threads (detected " << cores
|
||||
<< " cores)\n";
|
||||
return threadCount;
|
||||
}();
|
||||
|
||||
|
||||
+1
-2
@@ -13,12 +13,11 @@
|
||||
|
||||
namespace shardok {
|
||||
|
||||
using std::vector;
|
||||
using BattalionTypeSPtr = std::shared_ptr<const BattalionType>;
|
||||
|
||||
class FixedActionPointDistances final : public ActionPointDistances {
|
||||
private:
|
||||
vector<vector<DIST_T>> distances;
|
||||
std::vector<std::vector<DIST_T>> distances;
|
||||
|
||||
// Private constructor - use Create factory method instead
|
||||
explicit FixedActionPointDistances(const HexMap *map, int columnCount);
|
||||
|
||||
-48
@@ -1,48 +0,0 @@
|
||||
//
|
||||
// Created by Dan Crosby on 11/26/22.
|
||||
//
|
||||
|
||||
#include <include/gtest/gtest.h>
|
||||
|
||||
#include "src/main/cpp/net/eagle0/shardok/library/action_point_distances/ActionPointDistances.hpp"
|
||||
#include "src/main/cpp/net/eagle0/shardok/library/action_point_distances/FixedActionPointDistances.hpp"
|
||||
#include "src/main/cpp/net/eagle0/shardok/library/fb_helpers/HexMapHelpers.hpp"
|
||||
#include "src/main/cpp/net/eagle0/shardok/library/settings_loader/SettingsLoader.hpp"
|
||||
#include "src/main/cpp/net/eagle0/shardok/util/MapLoader.hpp"
|
||||
|
||||
using namespace std::chrono;
|
||||
using namespace shardok;
|
||||
|
||||
auto main(int argc, char** argv) -> int {
|
||||
FilesystemUtils::SetExecPath(
|
||||
"/Users/dancrosby/CodingProjects/github/eagle0/bazel-bin/src/main/cpp/net/eagle0/"
|
||||
"shardok/library/action_point_distances/fixed_action_point_distances_timer_app");
|
||||
const auto gameSettings = SettingsLoader::LoadSettings();
|
||||
|
||||
const vector<string> mapNames = GetMapNames();
|
||||
vector<HexMapW> hexMaps;
|
||||
|
||||
for (const string& name : mapNames) {
|
||||
auto hexMapProto = LoadMap(name);
|
||||
flatbuffers::FlatBufferBuilder fbb;
|
||||
const auto offset = shardok::fb::ConvertHexMapProto(fbb, hexMapProto);
|
||||
fbb.Finish(offset);
|
||||
|
||||
hexMaps.emplace_back(fbb);
|
||||
}
|
||||
|
||||
const auto& battalionType = gameSettings->GetGetter().GetBattalionType(
|
||||
net::eagle0::shardok::storage::fb::BattalionTypeId_LIGHT_INFANTRY);
|
||||
|
||||
const auto start = system_clock::now();
|
||||
|
||||
for (int i = 0; i < 100; i++) {
|
||||
for (const HexMapW& hexMap : hexMaps) {
|
||||
shardok::FixedActionPointDistances
|
||||
distances(hexMap, 0x1234, 0xABCD, battalionType, true, 5);
|
||||
}
|
||||
}
|
||||
const auto end = system_clock::now();
|
||||
|
||||
std::cerr << duration_cast<microseconds>(end - start).count() << " µs" << '\n';
|
||||
}
|
||||
+6
-12
@@ -19,8 +19,6 @@
|
||||
|
||||
namespace shardok {
|
||||
|
||||
using std::unique_ptr;
|
||||
|
||||
using ResolvedUnitProto = net::eagle0::shardok::storage::ResolvedUnit;
|
||||
using GameState = net::eagle0::shardok::storage::fb::GameState;
|
||||
using GameStateT = net::eagle0::shardok::storage::fb::GameStateT;
|
||||
@@ -249,12 +247,13 @@ void MutatingApplyResult(
|
||||
internalAssert(mutatingGameState->mutable_status()->mutate_state(
|
||||
static_cast<net::eagle0::shardok::storage::fb::GameStatus_::State>(
|
||||
result.game_status().state())));
|
||||
for (int i = 0; i < result.game_status().winning_shardok_ids_size(); i++) {
|
||||
const int winningShardokIdCount = result.game_status().winning_shardok_ids_size();
|
||||
for (int i = 0; i < winningShardokIdCount; i++) {
|
||||
mutatingGameState->mutable_status()->mutable_winning_shardok_ids()->Mutate(
|
||||
i,
|
||||
result.game_status().winning_shardok_ids(i));
|
||||
}
|
||||
for (int i = result.game_status().winning_shardok_ids_size(); i < 10; i++) {
|
||||
for (int i = winningShardokIdCount; i < 10; i++) {
|
||||
mutatingGameState->mutable_status()->mutable_winning_shardok_ids()->Mutate(i, -1);
|
||||
}
|
||||
|
||||
@@ -302,12 +301,6 @@ void MutatingApplyResult(
|
||||
for (const auto &changedUnitBytes : result.changed_units_fb()) {
|
||||
const Unit *changedUnit = &UnitFromBytes(changedUnitBytes);
|
||||
|
||||
if (changedUnit->battalion().type() ==
|
||||
net::eagle0::shardok::storage::fb::BattalionTypeId_UNDEAD &&
|
||||
changedUnit->battalion().morale() != 50.0) {
|
||||
printf("bad morale\n");
|
||||
}
|
||||
|
||||
internalAssert(
|
||||
changedUnit->unit_id() < (int32_t)mutatingGameState->units()->size(),
|
||||
"Got a changed unit outside acceptable range");
|
||||
@@ -390,10 +383,11 @@ void MutatingApplyResult(
|
||||
} else {
|
||||
internalAssert(mutatingGameState->mutate_eligible_charger_id(-1));
|
||||
}
|
||||
for (int i = 0; i < result.possible_chargees_size(); i++) {
|
||||
const int possibleChargeeCount = result.possible_chargees_size();
|
||||
for (int i = 0; i < possibleChargeeCount; i++) {
|
||||
mutatingGameState->mutable_possible_chargee_ids()->Mutate(i, result.possible_chargees(i));
|
||||
}
|
||||
for (int i = result.possible_chargees_size(); i < 6; i++) {
|
||||
for (int i = possibleChargeeCount; i < 6; i++) {
|
||||
mutatingGameState->mutable_possible_chargee_ids()->Mutate(i, -1);
|
||||
}
|
||||
|
||||
|
||||
@@ -19,8 +19,6 @@ using net::eagle0::shardok::storage::fb::VictoryCondition;
|
||||
using PlayerInfoFb = net::eagle0::shardok::storage::fb::PlayerInfo;
|
||||
using GameStatusFb = net::eagle0::shardok::storage::fb::GameStatus;
|
||||
using GameStatusProto = net::eagle0::shardok::common::GameStatus;
|
||||
using std::optional;
|
||||
using std::unordered_set;
|
||||
|
||||
static inline auto GameIsOver(const GameStatusFb* status) -> bool {
|
||||
return (status->state() == net::eagle0::shardok::storage::fb::GameStatus_::State_VICTORY);
|
||||
@@ -41,12 +39,12 @@ static inline auto HasVictoryCondition(const PlayerInfoFb* pi, const VictoryCond
|
||||
return false;
|
||||
}
|
||||
|
||||
auto UpdateGameStatusAction::SurvivingPlayers() const -> unordered_set<PlayerId> {
|
||||
auto UpdateGameStatusAction::SurvivingPlayers() const -> std::unordered_set<PlayerId> {
|
||||
if (gameState->status()->state() ==
|
||||
net::eagle0::shardok::storage::fb::GameStatus_::State_SET_UP)
|
||||
return unordered_set<PlayerId>{};
|
||||
return std::unordered_set<PlayerId>{};
|
||||
|
||||
unordered_set<PlayerId> survivingPids{};
|
||||
std::unordered_set<PlayerId> survivingPids{};
|
||||
|
||||
for (const Unit* unit : *gameState->units()) {
|
||||
if (unit->status() != net::eagle0::shardok::storage::fb::UnitStatus_NORMAL_UNIT) continue;
|
||||
@@ -288,7 +286,7 @@ auto UpdateGameStatusAction::InternalExecute(
|
||||
}
|
||||
|
||||
// Second check: allied players collectively holding all critical tiles
|
||||
unordered_set<PlayerId> occupantPlayerIds{};
|
||||
std::unordered_set<PlayerId> occupantPlayerIds{};
|
||||
bool allTilesOccupiedWithHeroes = true;
|
||||
for (const auto& criticalTile : criticalTileLocations) {
|
||||
const auto* possibleOccupant = currentState.GetOccupant(criticalTile);
|
||||
@@ -356,4 +354,4 @@ auto UpdateGameStatusAction::InternalExecute(
|
||||
// If we got all the way through, keep the status as it is
|
||||
return results;
|
||||
}
|
||||
} // namespace shardok
|
||||
} // namespace shardok
|
||||
|
||||
+1
-2
@@ -16,7 +16,6 @@
|
||||
#include "src/main/protobuf/net/eagle0/shardok/api/unit_view.pb.h"
|
||||
|
||||
namespace shardok {
|
||||
using std::vector;
|
||||
|
||||
class ChallengeDuelCommandFactory : public CommandFactory {
|
||||
private:
|
||||
@@ -32,7 +31,7 @@ public:
|
||||
ActionPoints remainingActionPoints,
|
||||
const HexMap *map,
|
||||
const Units *units,
|
||||
const vector<PlayerId> &allyPids) const;
|
||||
const std::vector<PlayerId> &allyPids) const;
|
||||
|
||||
void AddAvailableCommands(CommandList &commands, const CommandParams ¶ms) const override;
|
||||
};
|
||||
|
||||
+33
-31
@@ -4,6 +4,8 @@
|
||||
|
||||
#include "CommandFactoriesList.hpp"
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "src/main/cpp/net/eagle0/shardok/library/command_factories/BlowBridgeCommandFactory.hpp"
|
||||
#include "src/main/cpp/net/eagle0/shardok/library/command_factories/BraveWaterCommandFactory.hpp"
|
||||
#include "src/main/cpp/net/eagle0/shardok/library/command_factories/BuildBridgeCommandFactory.hpp"
|
||||
@@ -34,42 +36,42 @@
|
||||
|
||||
namespace shardok {
|
||||
|
||||
using std::make_shared;
|
||||
|
||||
auto MakeFactories(const SettingsGetter& settings) -> vector<shared_ptr<const CommandFactory>> {
|
||||
auto MakeFactories(const SettingsGetter& settings)
|
||||
-> std::vector<std::shared_ptr<const CommandFactory>> {
|
||||
// Command factories that produce "must-do" commands like Meteor Target should be first.
|
||||
// Ultimately I should probably move that metadata into the CommandFactory and sort it here.
|
||||
|
||||
return {make_shared<MeteorTargetCommandFactory>(settings),
|
||||
make_shared<ControlCommandFactory>(settings),
|
||||
make_shared<ArcheryCommandFactory>(settings),
|
||||
make_shared<BlowBridgeCommandFactory>(settings),
|
||||
make_shared<BraveWaterCommandFactory>(settings),
|
||||
make_shared<BuildBridgeCommandFactory>(settings),
|
||||
make_shared<ChallengeDuelCommandFactory>(settings),
|
||||
make_shared<ChargeCommandFactory>(settings),
|
||||
make_shared<EvacuatePrisonersCommandFactory>(settings),
|
||||
make_shared<ExtinguishFireCommandFactory>(settings),
|
||||
make_shared<FearCommandFactory>(settings),
|
||||
make_shared<FleeCommandFactory>(settings),
|
||||
make_shared<FortifyCommandFactory>(settings),
|
||||
make_shared<FreezeWaterCommandFactory>(settings),
|
||||
make_shared<HideCommandFactory>(settings),
|
||||
make_shared<HolyWaveCommandFactory>(settings),
|
||||
make_shared<LightningBoltCommandFactory>(settings),
|
||||
make_shared<MeleeCommandFactory>(settings),
|
||||
make_shared<MeteorStartCommandFactory>(settings),
|
||||
make_shared<RaiseDeadCommandFactory>(settings),
|
||||
make_shared<ReduceCommandFactory>(settings),
|
||||
make_shared<ReinforceCommandFactory>(settings),
|
||||
make_shared<RepairCommandFactory>(settings),
|
||||
make_shared<RetreatCommandFactory>(settings),
|
||||
make_shared<ScoutCommandFactory>(settings),
|
||||
make_shared<StartFireCommandFactory>(settings),
|
||||
make_shared<MoveCommandFactory>(settings)};
|
||||
return {std::make_shared<MeteorTargetCommandFactory>(settings),
|
||||
std::make_shared<ControlCommandFactory>(settings),
|
||||
std::make_shared<ArcheryCommandFactory>(settings),
|
||||
std::make_shared<BlowBridgeCommandFactory>(settings),
|
||||
std::make_shared<BraveWaterCommandFactory>(settings),
|
||||
std::make_shared<BuildBridgeCommandFactory>(settings),
|
||||
std::make_shared<ChallengeDuelCommandFactory>(settings),
|
||||
std::make_shared<ChargeCommandFactory>(settings),
|
||||
std::make_shared<EvacuatePrisonersCommandFactory>(settings),
|
||||
std::make_shared<ExtinguishFireCommandFactory>(settings),
|
||||
std::make_shared<FearCommandFactory>(settings),
|
||||
std::make_shared<FleeCommandFactory>(settings),
|
||||
std::make_shared<FortifyCommandFactory>(settings),
|
||||
std::make_shared<FreezeWaterCommandFactory>(settings),
|
||||
std::make_shared<HideCommandFactory>(settings),
|
||||
std::make_shared<HolyWaveCommandFactory>(settings),
|
||||
std::make_shared<LightningBoltCommandFactory>(settings),
|
||||
std::make_shared<MeleeCommandFactory>(settings),
|
||||
std::make_shared<MeteorStartCommandFactory>(settings),
|
||||
std::make_shared<RaiseDeadCommandFactory>(settings),
|
||||
std::make_shared<ReduceCommandFactory>(settings),
|
||||
std::make_shared<ReinforceCommandFactory>(settings),
|
||||
std::make_shared<RepairCommandFactory>(settings),
|
||||
std::make_shared<RetreatCommandFactory>(settings),
|
||||
std::make_shared<ScoutCommandFactory>(settings),
|
||||
std::make_shared<StartFireCommandFactory>(settings),
|
||||
std::make_shared<MoveCommandFactory>(settings)};
|
||||
}
|
||||
|
||||
auto CommandFactoriesList::GetFactories() const -> vector<shared_ptr<const CommandFactory>> {
|
||||
auto CommandFactoriesList::GetFactories() const
|
||||
-> std::vector<std::shared_ptr<const CommandFactory>> {
|
||||
return factories;
|
||||
}
|
||||
|
||||
|
||||
@@ -12,17 +12,14 @@
|
||||
|
||||
namespace shardok {
|
||||
|
||||
using std::shared_ptr;
|
||||
using std::vector;
|
||||
|
||||
class CommandFactoriesList {
|
||||
private:
|
||||
vector<shared_ptr<const CommandFactory>> factories;
|
||||
std::vector<std::shared_ptr<const CommandFactory>> factories;
|
||||
|
||||
public:
|
||||
explicit CommandFactoriesList(const SettingsGetter& settings);
|
||||
|
||||
auto GetFactories() const -> vector<shared_ptr<const CommandFactory>>;
|
||||
auto GetFactories() const -> std::vector<std::shared_ptr<const CommandFactory>>;
|
||||
};
|
||||
} // namespace shardok
|
||||
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
#include "src/main/cpp/net/eagle0/shardok/library/unit/Unit.hpp"
|
||||
|
||||
namespace shardok {
|
||||
using std::vector;
|
||||
|
||||
class FearCommandFactory : public CommandFactory {
|
||||
private:
|
||||
@@ -31,7 +30,7 @@ public:
|
||||
const Coords &position,
|
||||
const HexMap *hexMap,
|
||||
const Units *units,
|
||||
const vector<PlayerId> &allyPids) const;
|
||||
const std::vector<PlayerId> &allyPids) const;
|
||||
|
||||
void AddAvailableCommands(CommandList &commands, const CommandParams ¶ms) const override;
|
||||
};
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
#include "src/main/cpp/net/eagle0/shardok/library/unit/Unit.hpp"
|
||||
|
||||
namespace shardok {
|
||||
using std::vector;
|
||||
|
||||
class ScoutCommandFactory : public CommandFactory {
|
||||
private:
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
#include "src/main/cpp/net/eagle0/shardok/library/util/CombatUtils.hpp"
|
||||
|
||||
namespace shardok {
|
||||
using std::vector;
|
||||
|
||||
ArcheryCommand::ArcheryCommand(
|
||||
const SettingsGetter& settingsGetter,
|
||||
@@ -32,7 +31,7 @@ ArcheryCommand::ArcheryCommand(
|
||||
auto ArcheryCommand::InternalExecuteWithRoll(
|
||||
const GameStateW& currentState,
|
||||
const std::shared_ptr<RandomGenerator>& generator,
|
||||
const std::optional<int32_t> roll) const -> vector<ActionResult> {
|
||||
const std::optional<int32_t> roll) const -> std::vector<ActionResult> {
|
||||
const auto ambushRoll = generator->Percentile();
|
||||
const auto attackerRoll = roll.value_or(generator->OpenEndedPercentile());
|
||||
return ExecuteWithRolls(currentState, ambushRoll, attackerRoll);
|
||||
@@ -41,7 +40,7 @@ auto ArcheryCommand::InternalExecuteWithRoll(
|
||||
[[nodiscard]] auto ArcheryCommand::ExecuteWithRolls(
|
||||
const GameStateW& currentState,
|
||||
double ambushRoll,
|
||||
double attackerRoll) const -> vector<ActionResult> {
|
||||
double attackerRoll) const -> std::vector<ActionResult> {
|
||||
Unit attackerAfter = *currentState->units()->Get(attackerId);
|
||||
MutatingSpendActionPoints(
|
||||
&attackerAfter,
|
||||
@@ -114,4 +113,4 @@ auto ArcheryCommand::GetCommandProto() const -> CommandProto {
|
||||
return proto;
|
||||
}
|
||||
|
||||
} // namespace shardok
|
||||
} // namespace shardok
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
|
||||
#include "RaiseDeadCommand.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "src/main/cpp/net/eagle0/shardok/library/actions/ActionRequiresHeroException.hpp"
|
||||
#include "src/main/cpp/net/eagle0/shardok/library/unit/Unit.hpp"
|
||||
#include "src/main/cpp/net/eagle0/shardok/library/util/ActionResultFlatbufferHelpers.hpp"
|
||||
@@ -107,7 +109,7 @@ auto GetNewUnit(
|
||||
unit.mutate_player_id(playerId);
|
||||
unit.mutate_commanding_unit_id(commandingUnitId);
|
||||
|
||||
for (int i = 0; i < unit.opponent_knowledge()->size(); i++) {
|
||||
for (uint32_t i = 0; i < unit.opponent_knowledge()->size(); i++) {
|
||||
unit.mutable_opponent_knowledge()->Mutate(i, 0);
|
||||
}
|
||||
|
||||
|
||||
+2
-4
@@ -13,8 +13,6 @@
|
||||
#include "src/main/cpp/net/eagle0/shardok/library/view_filters/UnitFilter.hpp"
|
||||
|
||||
namespace shardok {
|
||||
using std::vector;
|
||||
|
||||
constexpr int NUM_RUNS = 10;
|
||||
constexpr int COMBAT_ROUNDS = 50;
|
||||
constexpr double BATTALION_STRENGTH_WEIGHT = 0.5;
|
||||
@@ -28,8 +26,8 @@ auto GetAcceptOdds(
|
||||
const Terrain &defenderTerrain) -> PercentileRollOdds {
|
||||
net::eagle0::shardok::api::UnitView filteredView =
|
||||
UnitFilteredForPlayer(settings, challenger, defender->player_id(), {});
|
||||
vector<double> stats = {static_cast<double>(defender->attached_hero().bravery())};
|
||||
vector<OtherFactor> otherFactors{};
|
||||
std::vector<double> stats = {static_cast<double>(defender->attached_hero().bravery())};
|
||||
std::vector<OtherFactor> otherFactors{};
|
||||
|
||||
Unit believedChallenger = *challenger;
|
||||
MutatingSpendActionPoints(
|
||||
|
||||
@@ -8,9 +8,9 @@
|
||||
#include <unistd.h>
|
||||
|
||||
#include <cerrno>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include <mutex>
|
||||
|
||||
namespace shardok {
|
||||
@@ -23,15 +23,15 @@ public:
|
||||
mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0));
|
||||
|
||||
if (b == MAP_FAILED) {
|
||||
std::fputs("mmap failed\n", stderr);
|
||||
abort();
|
||||
std::cerr << "mmap failed\n";
|
||||
std::abort();
|
||||
}
|
||||
return b;
|
||||
}
|
||||
auto deallocate(uint8_t* buf, const size_t size) -> void override {
|
||||
if (const auto result = munmap(buf, size); result != 0) {
|
||||
std::fprintf(stderr, "munmap failed, errno %s\n", strerror(errno));
|
||||
abort();
|
||||
std::cerr << "munmap failed, errno " << strerror(errno) << '\n';
|
||||
std::abort();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,8 +45,8 @@ public:
|
||||
auto* b = static_cast<uint8_t*>(malloc(size));
|
||||
|
||||
if (b == nullptr) {
|
||||
std::fputs("malloc failed\n", stderr);
|
||||
abort();
|
||||
std::cerr << "malloc failed\n";
|
||||
std::abort();
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
@@ -6,6 +6,9 @@
|
||||
|
||||
#include <flatbuffers/flatbuffers.h>
|
||||
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "src/main/cpp/net/eagle0/shardok/library/fb_helpers/HexMapHelpers.hpp"
|
||||
#include "src/main/cpp/net/eagle0/shardok/library/fb_helpers/InvalidProtoException.hpp"
|
||||
#include "src/main/cpp/net/eagle0/shardok/library/settings/GameSettings.hpp"
|
||||
@@ -13,8 +16,6 @@
|
||||
|
||||
namespace shardok::fb {
|
||||
|
||||
using std::unique_ptr;
|
||||
using std::unordered_map;
|
||||
using namespace net::eagle0::shardok::storage::fb;
|
||||
using GameStatusProto = net::eagle0::shardok::common::GameStatus;
|
||||
|
||||
@@ -44,12 +45,14 @@ auto ConvertVictoryCondition(const net::eagle0::shardok::common::VictoryConditio
|
||||
|
||||
auto FromPlayerInfoProto(flatbuffers::FlatBufferBuilder& fbb, const PlayerInfoProto& piProto)
|
||||
-> flatbuffers::Offset<net::eagle0::shardok::storage::fb::PlayerInfo> {
|
||||
auto alliesVec = vector<AlliedPlayer>();
|
||||
auto alliesVec = std::vector<AlliedPlayer>();
|
||||
for (const auto& apProto : piProto.allies()) { alliesVec.emplace_back(apProto.player_id()); }
|
||||
const auto alliesOffset = fbb.CreateVectorOfStructs(alliesVec);
|
||||
|
||||
auto vcVec = vector<int8_t>();
|
||||
for (int i = 0; i < piProto.victory_conditions_size(); i++) {
|
||||
auto vcVec = std::vector<int8_t>();
|
||||
const int victoryConditionCount = piProto.victory_conditions_size();
|
||||
vcVec.reserve(victoryConditionCount);
|
||||
for (int i = 0; i < victoryConditionCount; i++) {
|
||||
vcVec.push_back(ConvertVictoryCondition(piProto.victory_conditions(i)));
|
||||
}
|
||||
const auto vcOffset = fbb.CreateVector(vcVec);
|
||||
@@ -73,10 +76,10 @@ auto RequiredMonthlyFood(const Unit& unit, const SettingsGetter& settingsGetter)
|
||||
}
|
||||
|
||||
auto FoodPercentageByPid(
|
||||
const vector<PlayerInfoProto>& playerInfoProtos,
|
||||
const vector<Unit>& units,
|
||||
const SettingsGetter& settings) -> unordered_map<int, double> {
|
||||
unordered_map<int, double> foodRequirementsByPid;
|
||||
const std::vector<PlayerInfoProto>& playerInfoProtos,
|
||||
const std::vector<Unit>& units,
|
||||
const SettingsGetter& settings) -> std::unordered_map<int, double> {
|
||||
std::unordered_map<int, double> foodRequirementsByPid;
|
||||
for (const auto& unit : units) {
|
||||
const auto cost = RequiredMonthlyFood(unit, settings);
|
||||
if (foodRequirementsByPid.count(unit.player_id()) > 0) {
|
||||
@@ -109,8 +112,8 @@ auto BaseMorale(const Unit& unit) -> double {
|
||||
auto SetupInitialGameState(
|
||||
const GameId& gameId,
|
||||
const HexMapProto& hexMapProto,
|
||||
const vector<PlayerInfoProto>& playerInfoProtos,
|
||||
vector<Unit>& units,
|
||||
const std::vector<PlayerInfoProto>& playerInfoProtos,
|
||||
std::vector<Unit>& units,
|
||||
int month,
|
||||
bool isWinter,
|
||||
const SettingsGetter& settings) -> GameStateW {
|
||||
@@ -138,7 +141,7 @@ auto SetupInitialGameState(
|
||||
&endGameCondition);
|
||||
auto gameIdOffset = fbb.CreateString(gameId);
|
||||
|
||||
auto playerInfoVec = vector<Offset<PlayerInfo>>();
|
||||
auto playerInfoVec = std::vector<Offset<PlayerInfo>>();
|
||||
for (const auto& piProto : playerInfoProtos) {
|
||||
playerInfoVec.push_back(FromPlayerInfoProto(fbb, piProto));
|
||||
}
|
||||
@@ -157,7 +160,7 @@ auto SetupInitialGameState(
|
||||
// Add slack units: 3 per necromancer, minimum 5 for general use
|
||||
int slackUnits = std::max(5, necromancerCount * 3);
|
||||
|
||||
auto unitsVec = vector<Unit>();
|
||||
auto unitsVec = std::vector<Unit>();
|
||||
unitsVec.reserve(units.size() + slackUnits);
|
||||
for (const auto& unit : units) {
|
||||
Unit modifiedUnit = unit;
|
||||
@@ -200,7 +203,7 @@ auto SetupInitialGameState(
|
||||
|
||||
auto unitsOffset = fbb.CreateVectorOfSortedStructs(&unitsVec);
|
||||
|
||||
vector<UnitId> possibleChargeeIdsVec = {-1, -1, -1, -1, -1, -1};
|
||||
std::vector<UnitId> possibleChargeeIdsVec = {-1, -1, -1, -1, -1, -1};
|
||||
auto possibleChargeeIdsOffset = fbb.CreateVector(possibleChargeeIdsVec);
|
||||
|
||||
GameStateBuilder builder(fbb);
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
|
||||
namespace shardok::fb {
|
||||
|
||||
using std::vector;
|
||||
using HexMapProto = net::eagle0::shardok::common::HexMap;
|
||||
using PlayerInfoProto = net::eagle0::shardok::common::PlayerInfo;
|
||||
using net::eagle0::shardok::storage::fb::GameState;
|
||||
@@ -32,8 +31,8 @@ using GameStatusProto = net::eagle0::shardok::common::GameStatus;
|
||||
auto SetupInitialGameState(
|
||||
const GameId& gameId,
|
||||
const HexMapProto& hexMapProto,
|
||||
const vector<PlayerInfoProto>& playerInfoProtos,
|
||||
vector<Unit>& units,
|
||||
const std::vector<PlayerInfoProto>& playerInfoProtos,
|
||||
std::vector<Unit>& units,
|
||||
int month,
|
||||
bool isWinter,
|
||||
const SettingsGetter& settings) -> GameStateW;
|
||||
|
||||
@@ -15,7 +15,6 @@ namespace shardok::fb {
|
||||
using TerrainProto = net::eagle0::shardok::common::Terrain;
|
||||
|
||||
using namespace net::eagle0::shardok::storage::fb;
|
||||
using std::vector;
|
||||
|
||||
auto ConvertType(const net::eagle0::shardok::common::Terrain_Type protoType) -> Terrain_::Type {
|
||||
using namespace Terrain_;
|
||||
@@ -50,7 +49,7 @@ auto CreateStartingPositionsList(
|
||||
FlatBufferBuilder& fbb,
|
||||
const net::eagle0::shardok::common::StartingPositionList& splProto)
|
||||
-> Offset<StartingPositionList> {
|
||||
vector<Coords> coordsVec;
|
||||
std::vector<Coords> coordsVec;
|
||||
coordsVec.reserve(splProto.positions_size());
|
||||
for (const auto& position : splProto.positions()) {
|
||||
coordsVec.emplace_back(position.row(), position.column());
|
||||
@@ -120,14 +119,14 @@ auto ConvertHexMapProto(
|
||||
const float initialWinterIceIntegrity) -> Offset<HexMap> {
|
||||
const auto dspOffset = CreateStartingPositionsList(fbb, mapProto.defender_starting_positions());
|
||||
|
||||
vector<Offset<StartingPositionList>> asplOffsets;
|
||||
std::vector<Offset<StartingPositionList>> asplOffsets;
|
||||
asplOffsets.reserve(mapProto.attacker_starting_positions_size());
|
||||
for (const auto& aspl : mapProto.attacker_starting_positions()) {
|
||||
asplOffsets.push_back(CreateStartingPositionsList(fbb, aspl));
|
||||
}
|
||||
const auto aspOffset = fbb.CreateVector(asplOffsets);
|
||||
|
||||
vector<MonthlyWeather> monthlyWeatherVec;
|
||||
std::vector<MonthlyWeather> monthlyWeatherVec;
|
||||
monthlyWeatherVec.reserve(mapProto.monthly_weather_size());
|
||||
for (const auto& mwp : mapProto.monthly_weather()) {
|
||||
monthlyWeatherVec.emplace_back(
|
||||
@@ -144,7 +143,7 @@ auto ConvertHexMapProto(
|
||||
const auto monthlyWeatherOffset = fbb.CreateVectorOfStructs(monthlyWeatherVec);
|
||||
|
||||
const auto emptyModifier = SingleModifier(false, 0.0);
|
||||
vector<Terrain> terrainVec;
|
||||
std::vector<Terrain> terrainVec;
|
||||
terrainVec.reserve(mapProto.terrain_size());
|
||||
|
||||
const bool calculateHash = mapProto.base_hash() == 0;
|
||||
@@ -202,7 +201,7 @@ auto ConvertHexMapProto(
|
||||
}
|
||||
|
||||
auto CopyStartingPositionsList(FlatBufferBuilder& fbb, const StartingPositionList* spl) {
|
||||
vector<Coords> coordsVec = {};
|
||||
std::vector<Coords> coordsVec = {};
|
||||
|
||||
if (spl && spl->positions()) {
|
||||
coordsVec.reserve(spl->positions()->size());
|
||||
@@ -216,17 +215,17 @@ auto CopyHexMap(const HexMap* hexMap) -> HexMapW {
|
||||
FlatBufferBuilder fbb;
|
||||
fbb.ForceDefaults(true);
|
||||
|
||||
vector<Terrain> terrainVec;
|
||||
std::vector<Terrain> terrainVec;
|
||||
terrainVec.reserve(hexMap->terrain()->size());
|
||||
for (const auto* t : *hexMap->terrain()) terrainVec.push_back(*t);
|
||||
const auto terrainOffset = fbb.CreateVectorOfStructs(terrainVec);
|
||||
|
||||
vector<MonthlyWeather> weatherVec;
|
||||
std::vector<MonthlyWeather> weatherVec;
|
||||
weatherVec.reserve(hexMap->monthly_weather()->size());
|
||||
for (const auto* w : *hexMap->monthly_weather()) weatherVec.push_back(*w);
|
||||
const auto weatherOffset = fbb.CreateVectorOfStructs(weatherVec);
|
||||
|
||||
vector<Offset<StartingPositionList>> asplVec = {};
|
||||
std::vector<Offset<StartingPositionList>> asplVec = {};
|
||||
asplVec.reserve(hexMap->attacker_starting_positions()->size());
|
||||
for (const auto* spl : *hexMap->attacker_starting_positions()) {
|
||||
asplVec.push_back(CopyStartingPositionsList(fbb, spl));
|
||||
|
||||
@@ -23,7 +23,6 @@ constexpr size_t STANDARD_SIZE = 12 * 14;
|
||||
|
||||
using HexMap = net::eagle0::shardok::storage::fb::HexMap;
|
||||
using BackingBitset = common::IterableBitset<168>;
|
||||
using std::vector;
|
||||
|
||||
class CoordsSet {
|
||||
private:
|
||||
@@ -101,8 +100,8 @@ public:
|
||||
[[nodiscard]] auto empty() const -> bool { return store.empty(); }
|
||||
|
||||
// Should only be used for debugging.
|
||||
[[nodiscard]] auto as_vector() const -> vector<Coords> {
|
||||
return vector<Coords>{this->begin(), this->end()};
|
||||
[[nodiscard]] auto as_vector() const -> std::vector<Coords> {
|
||||
return std::vector<Coords>{this->begin(), this->end()};
|
||||
}
|
||||
|
||||
auto operator+=(const CoordsSet& rhs) -> CoordsSet& {
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
|
||||
namespace shardok {
|
||||
using BattalionTypeId = net::eagle0::shardok::storage::fb::BattalionTypeId;
|
||||
using std::vector;
|
||||
|
||||
const SettingsKeys kSettingsKeys = SettingsKeys();
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
namespace shardok {
|
||||
|
||||
auto SettingsLoader::LoadSettings() -> shared_ptr<GameSettings> {
|
||||
auto SettingsLoader::LoadSettings() -> std::shared_ptr<GameSettings> {
|
||||
auto gameSettings = std::make_shared<GameSettings>();
|
||||
auto setter = gameSettings->GetSetter();
|
||||
|
||||
|
||||
@@ -11,11 +11,9 @@
|
||||
|
||||
namespace shardok {
|
||||
|
||||
using std::shared_ptr;
|
||||
|
||||
class SettingsLoader {
|
||||
public:
|
||||
static auto LoadSettings() -> shared_ptr<GameSettings>;
|
||||
static auto LoadSettings() -> std::shared_ptr<GameSettings>;
|
||||
};
|
||||
|
||||
} // namespace shardok
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
|
||||
#include <limits>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
#include "src/main/cpp/net/eagle0/shardok/library/ActionCost.hpp"
|
||||
#include "src/main/cpp/net/eagle0/shardok/library/CombatDamage.hpp"
|
||||
@@ -23,7 +22,6 @@
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
namespace shardok {
|
||||
using std::string;
|
||||
|
||||
using Hero = net::eagle0::shardok::storage::fb::Hero;
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "src/main/cpp/net/eagle0/shardok/library/unit/Unit.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <utility>
|
||||
|
||||
namespace shardok {
|
||||
@@ -44,7 +45,7 @@ auto OpponentKnowledge(const Unit &unit, const PlayerId toPlayer) -> int {
|
||||
if (toPlayer == -1) {
|
||||
// handle observer, with pid -1
|
||||
int8_t max = 0;
|
||||
for (int i = 0; i < unit.opponent_knowledge()->size(); i++) {
|
||||
for (uint32_t i = 0; i < unit.opponent_knowledge()->size(); i++) {
|
||||
max = std::max(max, unit.opponent_knowledge()->Get(i));
|
||||
}
|
||||
return max;
|
||||
@@ -58,7 +59,7 @@ auto OpponentKnowledge(const Unit *unit, const PlayerId toPlayer) -> int {
|
||||
if (toPlayer == -1) {
|
||||
// handle observer, with pid -1
|
||||
int8_t max = 0;
|
||||
for (int i = 0; i < unit->opponent_knowledge()->size(); i++) {
|
||||
for (uint32_t i = 0; i < unit->opponent_knowledge()->size(); i++) {
|
||||
max = std::max(max, unit->opponent_knowledge()->Get(i));
|
||||
}
|
||||
return max;
|
||||
@@ -189,7 +190,7 @@ void MutatingBumpOpponentKnowledge(Unit *unit, const PlayerId pid, const int bum
|
||||
|
||||
void MutatingBumpAllKnowledgeToMinimum(Unit *unit, const int minimum) {
|
||||
const auto current = unit->opponent_knowledge();
|
||||
for (int i = 0; i < current->size(); i++) {
|
||||
for (uint32_t i = 0; i < current->size(); i++) {
|
||||
if (current->Get(i) < minimum) { unit->mutable_opponent_knowledge()->Mutate(i, minimum); }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
#ifndef EAGLE0_SHARDOK_LIBRARY_UNIT_UNIT_HPP
|
||||
#define EAGLE0_SHARDOK_LIBRARY_UNIT_UNIT_HPP
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "src/main/cpp/net/eagle0/shardok/library/ShardokCTypes.h"
|
||||
#include "src/main/cpp/net/eagle0/shardok/library/settings/GameSettings.hpp"
|
||||
#include "src/main/cpp/net/eagle0/shardok/library/unit/Battalion.hpp"
|
||||
@@ -20,7 +22,6 @@ namespace shardok {
|
||||
using std::begin;
|
||||
using std::end;
|
||||
using std::find_if;
|
||||
using std::map;
|
||||
using std::optional;
|
||||
using std::remove_if;
|
||||
|
||||
@@ -76,8 +77,8 @@ void MutatingBumpCharismaXp(Unit *unit, int newXp);
|
||||
void MutatingBumpOpponentKnowledge(Unit *unit, PlayerId pid, int bump);
|
||||
void MutatingBumpAllKnowledgeToMinimum(Unit *unit, int bump);
|
||||
|
||||
auto ReserveUnitsForPlayer(const Units *units, PlayerId pid) -> map<UnitId, const Unit *>;
|
||||
auto PlacedUnitsForPlayer(const Units *units, PlayerId pid) -> map<UnitId, const Unit *>;
|
||||
auto ReserveUnitsForPlayer(const Units *units, PlayerId pid) -> std::map<UnitId, const Unit *>;
|
||||
auto PlacedUnitsForPlayer(const Units *units, PlayerId pid) -> std::map<UnitId, const Unit *>;
|
||||
|
||||
} // namespace shardok
|
||||
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
|
||||
namespace shardok {
|
||||
|
||||
using std::string;
|
||||
using ActionResult = net::eagle0::shardok::storage::ActionResult;
|
||||
using ResolvedUnit = net::eagle0::shardok::storage::ResolvedUnit;
|
||||
using Unit = net::eagle0::shardok::storage::fb::Unit;
|
||||
@@ -22,7 +21,7 @@ static inline void AddChangedUnit(ActionResult& result, const Unit& unit) {
|
||||
}
|
||||
|
||||
static inline void AddUnitToResolved(ResolvedUnit& resolvedUnit, const Unit& unit) {
|
||||
*resolvedUnit.mutable_unit_bytes() = string((char*)&unit, sizeof(Unit));
|
||||
*resolvedUnit.mutable_unit_bytes() = std::string((char*)&unit, sizeof(Unit));
|
||||
}
|
||||
|
||||
} // namespace shardok
|
||||
|
||||
@@ -18,7 +18,6 @@ namespace shardok {
|
||||
|
||||
using net::eagle0::shardok::common::ActionType;
|
||||
using net::eagle0::shardok::storage::ActionResult;
|
||||
using std::vector;
|
||||
|
||||
using BattalionFb = net::eagle0::shardok::storage::fb::Battalion;
|
||||
using HeroFb = net::eagle0::shardok::storage::fb::Hero;
|
||||
|
||||
@@ -26,8 +26,8 @@ auto CubeToOffset(const Cube &cube) -> Coords {
|
||||
return Coords(row, column);
|
||||
}
|
||||
|
||||
auto CubesWithinDistance(const Cube &c1, const int distance) -> vector<Cube> {
|
||||
vector<Cube> cubes{};
|
||||
auto CubesWithinDistance(const Cube &c1, const int distance) -> std::vector<Cube> {
|
||||
std::vector<Cube> cubes{};
|
||||
|
||||
for (int x = -distance; x <= distance; x++) {
|
||||
for (int y = std::max(-distance, -x - distance); y <= std::min(distance, -x + distance);
|
||||
@@ -40,8 +40,8 @@ auto CubesWithinDistance(const Cube &c1, const int distance) -> vector<Cube> {
|
||||
return cubes;
|
||||
}
|
||||
|
||||
auto CubesWithExactDistance(const Cube &c1, const int distance) -> vector<Cube> {
|
||||
vector<Cube> cubes{};
|
||||
auto CubesWithExactDistance(const Cube &c1, const int distance) -> std::vector<Cube> {
|
||||
std::vector<Cube> cubes{};
|
||||
|
||||
for (int x = -distance; x <= distance; x++) {
|
||||
for (int y = std::max(-distance, -x - distance); y <= std::min(distance, -x + distance);
|
||||
@@ -76,7 +76,7 @@ auto FixupCube(
|
||||
// Always rounds half up, instead of away from zero.
|
||||
auto RoundHalfUp(const double d) -> double { return std::floor(d + 0.5); }
|
||||
|
||||
auto CubeLerp(const Cube &c1, const Cube &c2, const double t) -> vector<Cube> {
|
||||
auto CubeLerp(const Cube &c1, const Cube &c2, const double t) -> std::vector<Cube> {
|
||||
const auto floatX = std::lerp(c1.x, c2.x, t);
|
||||
const auto newX = RoundHalfUp(floatX);
|
||||
const auto xDiff = abs(newX - floatX);
|
||||
@@ -89,7 +89,7 @@ auto CubeLerp(const Cube &c1, const Cube &c2, const double t) -> vector<Cube> {
|
||||
const auto newZ = RoundHalfUp(floatZ);
|
||||
const auto zDiff = abs(newZ - floatZ);
|
||||
|
||||
vector<Cube> cubes{};
|
||||
std::vector<Cube> cubes{};
|
||||
cubes.push_back(FixupCube(newX, xDiff, newY, yDiff, newZ, zDiff));
|
||||
|
||||
// The 0.5 case represents a situation where the line passes exactly between two hexes. In that
|
||||
@@ -107,8 +107,8 @@ auto CubeLerp(const Cube &c1, const Cube &c2, const double t) -> vector<Cube> {
|
||||
// Slight variation of the method described in
|
||||
// https://www.redblobgames.com/grids/hexagons/#line-drawing
|
||||
// When rounding, we include *both* hexes for the in-between case.
|
||||
auto CubeLineInclusive(const Cube &c1, const Cube &c2) -> vector<Cube> {
|
||||
vector<Cube> cubes;
|
||||
auto CubeLineInclusive(const Cube &c1, const Cube &c2) -> std::vector<Cube> {
|
||||
std::vector<Cube> cubes;
|
||||
|
||||
const auto dist = CubeDistance(c1, c2);
|
||||
const double reciprocal = 1.0 / dist;
|
||||
@@ -120,4 +120,4 @@ auto CubeLineInclusive(const Cube &c1, const Cube &c2) -> vector<Cube> {
|
||||
return cubes;
|
||||
}
|
||||
|
||||
} // namespace shardok
|
||||
} // namespace shardok
|
||||
|
||||
@@ -5,12 +5,12 @@
|
||||
#ifndef EAGLE0_SHARDOK_LIBRARY_UTIL_HEX_CUBE_UTILS_HPP
|
||||
#define EAGLE0_SHARDOK_LIBRARY_UTIL_HEX_CUBE_UTILS_HPP
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "src/main/cpp/net/eagle0/shardok/library/map/Coordinates.hpp"
|
||||
|
||||
namespace shardok {
|
||||
|
||||
using std::vector;
|
||||
|
||||
struct Cube {
|
||||
int16_t x;
|
||||
int16_t y;
|
||||
@@ -28,12 +28,12 @@ static inline auto CubeDistance(const Cube &c1, const Cube &c2) -> int {
|
||||
return (abs(c1.x - c2.x) + abs(c1.y - c2.y) + abs(c1.z - c2.z)) / 2;
|
||||
}
|
||||
|
||||
auto CubesWithinDistance(const Cube &c1, int distance) -> vector<Cube>;
|
||||
auto CubesWithExactDistance(const Cube &c1, int distance) -> vector<Cube>;
|
||||
auto CubesWithinDistance(const Cube &c1, int distance) -> std::vector<Cube>;
|
||||
auto CubesWithExactDistance(const Cube &c1, int distance) -> std::vector<Cube>;
|
||||
|
||||
// Returns all the hexes that are on the line between c1 and c2, including the endpoints.
|
||||
// In a case where the line passes exactly between two hexes, includes BOTH hexes.
|
||||
auto CubeLineInclusive(const Cube &c1, const Cube &c2) -> vector<Cube>;
|
||||
auto CubeLineInclusive(const Cube &c1, const Cube &c2) -> std::vector<Cube>;
|
||||
|
||||
} // namespace shardok
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "HexMapUtils.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <ranges>
|
||||
|
||||
#include "HexCubeUtils.hpp"
|
||||
@@ -17,9 +18,6 @@
|
||||
|
||||
namespace shardok {
|
||||
|
||||
using std::any_of;
|
||||
using std::begin;
|
||||
using std::end;
|
||||
using Terrain = net::eagle0::shardok::storage::fb::Terrain;
|
||||
|
||||
const vector<Coords> ADJACENT_TILE_MODS_EVEN_ROW =
|
||||
@@ -88,13 +86,16 @@ auto HasForestAccess(
|
||||
|
||||
const CoordsSet adjacentCoords = HexMapUtils::GetAdjacentCoords(hexMap, coords);
|
||||
|
||||
return any_of(begin(adjacentCoords), end(adjacentCoords), [&](const Coords &adjCoords) {
|
||||
if (KnownEnemyOccupant(player, units, allyPids, adjCoords)) return false;
|
||||
if (GetTerrain(hexMap, adjCoords)->type() ==
|
||||
net::eagle0::shardok::storage::fb::Terrain_::Type_FOREST)
|
||||
return true;
|
||||
return false;
|
||||
});
|
||||
return std::any_of(
|
||||
std::begin(adjacentCoords),
|
||||
std::end(adjacentCoords),
|
||||
[&](const Coords &adjCoords) {
|
||||
if (KnownEnemyOccupant(player, units, allyPids, adjCoords)) return false;
|
||||
if (GetTerrain(hexMap, adjCoords)->type() ==
|
||||
net::eagle0::shardok::storage::fb::Terrain_::Type_FOREST)
|
||||
return true;
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
const std::vector<CoordsSet> HexMapUtils::standardCoords =
|
||||
@@ -160,16 +161,18 @@ auto HexMapUtils::GetAdjacentCoords(const HexMap *map, const Coords &origin) ->
|
||||
// the standard map size, and tests usually use something else. So let's use some statics here
|
||||
// for tests, knowing that we generally make a new one between runs.
|
||||
|
||||
static std::vector<CoordsSet *> *cachedCoords = nullptr;
|
||||
if (cachedCoords == nullptr) {
|
||||
cachedCoords = new vector<CoordsSet *>(map->column_count() * map->row_count());
|
||||
static std::vector<std::unique_ptr<CoordsSet>> cachedCoords;
|
||||
const auto mapSize = map->column_count() * map->row_count();
|
||||
if (cachedCoords.size() != static_cast<size_t>(mapSize)) {
|
||||
cachedCoords.clear();
|
||||
cachedCoords.resize(mapSize);
|
||||
}
|
||||
const auto index = origin.row() * map->column_count() + origin.column();
|
||||
if ((*cachedCoords)[index] == nullptr) {
|
||||
(*cachedCoords)[index] =
|
||||
new CoordsSet(ComputeAdjacentCoords(map->row_count(), map->column_count(), origin));
|
||||
if (cachedCoords[index] == nullptr) {
|
||||
cachedCoords[index] = std::make_unique<CoordsSet>(
|
||||
ComputeAdjacentCoords(map->row_count(), map->column_count(), origin));
|
||||
}
|
||||
return *(*cachedCoords)[index];
|
||||
return *cachedCoords[index];
|
||||
}
|
||||
|
||||
auto HexMapUtils::GetAdjacentTiles(const HexMap *map, const Coords &origin)
|
||||
@@ -324,7 +327,7 @@ void MaybeAdd(const Cube &cube, CoordsSet &set, const HexMap *map) {
|
||||
const auto c2 = OffsetToCube(coords2);
|
||||
|
||||
auto line = CubeLineInclusive(c1, c2);
|
||||
return std::any_of(begin(line), end(line), [&map](const Cube &c) {
|
||||
return std::any_of(std::begin(line), std::end(line), [&map](const Cube &c) {
|
||||
const auto betweenCoords = CubeToOffset(c);
|
||||
if (CoordsAreValid(map, betweenCoords) &&
|
||||
GetTerrain(map, betweenCoords)->type() ==
|
||||
|
||||
@@ -30,7 +30,7 @@ auto NextPlayerId(const GameState *gameState, const PlayerId pid, const bool all
|
||||
return nextPid;
|
||||
}
|
||||
|
||||
auto AlliedPids(const GameState *gameState, int playerId) -> vector<PlayerId> {
|
||||
auto AlliedPids(const GameState *gameState, int playerId) -> std::vector<PlayerId> {
|
||||
if (gameState->player_infos() == nullptr) return {};
|
||||
const auto &pi = std::find_if(
|
||||
std::begin(*gameState->player_infos()),
|
||||
@@ -38,7 +38,7 @@ auto AlliedPids(const GameState *gameState, int playerId) -> vector<PlayerId> {
|
||||
[playerId](const PlayerInfoFb *pi) { return pi->player_id() == playerId; });
|
||||
|
||||
if (pi == std::end(*gameState->player_infos())) { return std::vector<PlayerId>{}; }
|
||||
vector<PlayerId> allyPids{};
|
||||
std::vector<PlayerId> allyPids{};
|
||||
|
||||
if (pi->allies()) {
|
||||
for (const auto &ally : *pi->allies()) { allyPids.push_back(ally->player_id()); }
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
#ifndef EAGLE0_SHARDOK_LIBRARY_UTIL_PLAYER_UTILS_HPP
|
||||
#define EAGLE0_SHARDOK_LIBRARY_UTIL_PLAYER_UTILS_HPP
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "src/main/cpp/net/eagle0/shardok/library/ShardokCTypes.h"
|
||||
#include "src/main/flatbuffer/net/eagle0/shardok/storage/game_state.hpp"
|
||||
|
||||
@@ -12,12 +14,11 @@ namespace shardok {
|
||||
|
||||
using PlayerInfoFb = net::eagle0::shardok::storage::fb::PlayerInfo;
|
||||
using GameState = net::eagle0::shardok::storage::fb::GameState;
|
||||
using std::vector;
|
||||
|
||||
auto PlayerIsDefender(const GameState *gameState, int playerId) -> bool;
|
||||
auto NextPlayerId(const GameState *gameState, PlayerId pid, bool allowUncontrolled = true)
|
||||
-> PlayerId;
|
||||
auto AlliedPids(const GameState *gameState, int playerId) -> vector<PlayerId>;
|
||||
auto AlliedPids(const GameState *gameState, int playerId) -> std::vector<PlayerId>;
|
||||
|
||||
} // namespace shardok
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include "src/main/cpp/net/eagle0/shardok/library/view_filters/GameStateGuesser.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
@@ -15,10 +16,6 @@
|
||||
|
||||
namespace shardok {
|
||||
|
||||
using std::begin;
|
||||
using std::end;
|
||||
using std::vector;
|
||||
|
||||
using flatbuffers::FlatBufferBuilder;
|
||||
using flatbuffers::Offset;
|
||||
|
||||
@@ -156,7 +153,7 @@ auto GameStateGuesser::GuessedState(
|
||||
|
||||
auto gameIdOffset = fbb.CreateString(gameStateView.game_id());
|
||||
|
||||
vector<Offset<net::eagle0::shardok::storage::fb::PlayerInfo>> piVec{};
|
||||
std::vector<Offset<net::eagle0::shardok::storage::fb::PlayerInfo>> piVec{};
|
||||
for (const PlayerInfoProto &pi : gameStateView.player_infos()) {
|
||||
piVec.push_back(fb::FromPlayerInfoProto(fbb, pi));
|
||||
}
|
||||
@@ -164,9 +161,9 @@ auto GameStateGuesser::GuessedState(
|
||||
|
||||
auto statusDescription = fbb.CreateString(gameStateView.status().description());
|
||||
|
||||
vector<PlayerId> winningShardokIdsVec = {
|
||||
begin(gameStateView.status().winning_shardok_ids()),
|
||||
end(gameStateView.status().winning_shardok_ids())};
|
||||
std::vector<PlayerId> winningShardokIdsVec = {
|
||||
std::begin(gameStateView.status().winning_shardok_ids()),
|
||||
std::end(gameStateView.status().winning_shardok_ids())};
|
||||
for (int i = gameStateView.status().winning_shardok_ids_size(); i < 10; i++) {
|
||||
winningShardokIdsVec.push_back(-1);
|
||||
}
|
||||
@@ -211,8 +208,8 @@ auto GameStateGuesser::GuessedState(
|
||||
bool foundDefender = false;
|
||||
UnitId maxId = 0;
|
||||
|
||||
vector<UnitId> foundUnits{};
|
||||
vector<Unit> unitsVec{};
|
||||
std::vector<UnitId> foundUnits{};
|
||||
std::vector<Unit> unitsVec{};
|
||||
for (const auto &uv : gameStateView.units()) {
|
||||
unitsVec.push_back(GuessedUnit(
|
||||
settings,
|
||||
@@ -348,8 +345,8 @@ auto GameStateGuesser::GuessedState(
|
||||
auto unitsOffset = fbb.CreateVectorOfSortedStructs(&unitsVec);
|
||||
|
||||
auto chargeeIdsVec = std::vector<UnitId>(
|
||||
begin(gameStateView.possible_chargee_ids()),
|
||||
end(gameStateView.possible_chargee_ids()));
|
||||
std::begin(gameStateView.possible_chargee_ids()),
|
||||
std::end(gameStateView.possible_chargee_ids()));
|
||||
for (int i = gameStateView.possible_chargee_ids_size(); i < 6; i++) {
|
||||
chargeeIdsVec.push_back(-1);
|
||||
}
|
||||
@@ -481,7 +478,7 @@ auto GuessedUnit(
|
||||
|
||||
unit.mutate_has_moved_in_zoc(uv.has_moved_in_zoc());
|
||||
|
||||
for (int i = 0; i < unit.opponent_knowledge()->size(); i++) {
|
||||
for (uint32_t i = 0; i < unit.opponent_knowledge()->size(); i++) {
|
||||
unit.mutable_opponent_knowledge()->Mutate(i, 0);
|
||||
}
|
||||
unit.mutable_opponent_knowledge()->Mutate(toPid, uv.my_knowledge());
|
||||
@@ -693,4 +690,4 @@ auto KnownUnitStats(const GameStateView &gameStateView)
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace shardok
|
||||
} // namespace shardok
|
||||
|
||||
@@ -146,9 +146,11 @@ auto MakeGameStateViewDiff(const GameStateView &before, const GameStateView &aft
|
||||
changed = true;
|
||||
}
|
||||
|
||||
for (int i = 0; i < after.player_totals_size(); i++) {
|
||||
const int afterPlayerTotalCount = after.player_totals_size();
|
||||
const int beforePlayerTotalCount = before.player_totals_size();
|
||||
for (int i = 0; i < afterPlayerTotalCount; i++) {
|
||||
const auto &afterTotal = after.player_totals(i);
|
||||
if (before.player_totals_size() <= i) {
|
||||
if (beforePlayerTotalCount <= i) {
|
||||
*diff.add_changed_player_totals() = afterTotal;
|
||||
} else {
|
||||
const auto &beforeTotal = before.player_totals(i);
|
||||
@@ -164,4 +166,4 @@ auto MakeGameStateViewDiff(const GameStateView &before, const GameStateView &aft
|
||||
return changed ? diff : std::optional<GameStateViewDiff>();
|
||||
}
|
||||
|
||||
} // namespace shardok
|
||||
} // namespace shardok
|
||||
|
||||
@@ -17,7 +17,6 @@ namespace shardok {
|
||||
|
||||
using net::eagle0::shardok::api::UnitView;
|
||||
using net::eagle0::shardok::common::CommandType;
|
||||
using std::vector;
|
||||
|
||||
auto UnknownUnit(
|
||||
UnitId uid,
|
||||
|
||||
@@ -14,7 +14,6 @@ namespace shardok {
|
||||
|
||||
using net::eagle0::shardok::api::UnitView;
|
||||
using Unit = net::eagle0::shardok::storage::fb::Unit;
|
||||
using std::vector;
|
||||
|
||||
[[nodiscard]] auto UnitFilteredForPlayer(
|
||||
const SettingsGetter &settings,
|
||||
|
||||
@@ -110,7 +110,9 @@ auto ConvertPlayerInfo(
|
||||
const int32_t eagleFactionId = pi.eagle_faction_id();
|
||||
|
||||
vector<PlayerId> allPids{};
|
||||
for (int i = 0; i < allPis.size(); i++) { allPids.push_back(i); }
|
||||
const int playerInfoCount = allPis.size();
|
||||
allPids.reserve(playerInfoCount);
|
||||
for (int i = 0; i < playerInfoCount; i++) { allPids.push_back(static_cast<PlayerId>(i)); }
|
||||
|
||||
vector<Unit> shardokUnits;
|
||||
shardokUnits.reserve(pi.units().size());
|
||||
@@ -132,9 +134,9 @@ auto ConvertPlayerInfo(
|
||||
alliedPids.reserve(pi.allies_size());
|
||||
for (const auto &ally : pi.allies()) {
|
||||
const int32_t alliedFid = ally.eagle_faction_id();
|
||||
for (int i = 0; i < allPis.size(); i++) {
|
||||
for (int i = 0; i < playerInfoCount; i++) {
|
||||
if (allPis[i].eagle_faction_id() == alliedFid) {
|
||||
alliedPids.push_back(i);
|
||||
alliedPids.push_back(static_cast<PlayerId>(i));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -182,8 +184,9 @@ void EagleInterfaceImpl::StartGame(const NewGameRequest &request) {
|
||||
|
||||
// Convert each interface player struct into the Shardok storage equivalents
|
||||
vector<PlayerInfoWithUnits> playersInfo{};
|
||||
playersInfo.reserve(request.user_infos_size());
|
||||
for (int i = 0; i < request.user_infos_size(); i++) {
|
||||
const int userInfoCount = request.user_infos_size();
|
||||
playersInfo.reserve(userInfoCount);
|
||||
for (int i = 0; i < userInfoCount; i++) {
|
||||
playersInfo.push_back(ConvertPlayerInfo(request.user_infos(), static_cast<PlayerId>(i)));
|
||||
}
|
||||
|
||||
@@ -218,7 +221,7 @@ void EagleInterfaceImpl::StartGame(const NewGameRequest &request) {
|
||||
watcherAllies.reserve(request.watcher_eagle_faction_ids_size());
|
||||
for (const int32_t watcherFid : request.watcher_eagle_faction_ids()) {
|
||||
std::vector<PlayerId> allyPids;
|
||||
for (int i = 0; i < request.user_infos_size(); i++) {
|
||||
for (int i = 0; i < userInfoCount; i++) {
|
||||
for (const auto &ally : request.user_infos(i).allies()) {
|
||||
if (ally.eagle_faction_id() == watcherFid) {
|
||||
allyPids.push_back(static_cast<PlayerId>(i));
|
||||
|
||||
@@ -14,12 +14,10 @@
|
||||
namespace shardok {
|
||||
|
||||
using net::eagle0::common::VictoryCondition;
|
||||
using std::string;
|
||||
using std::vector;
|
||||
|
||||
namespace {
|
||||
auto EagleFactionIdForPlayer(
|
||||
const vector<net::eagle0::shardok::common::PlayerInfo> &resolvedPlayerInfos,
|
||||
const std::vector<net::eagle0::shardok::common::PlayerInfo> &resolvedPlayerInfos,
|
||||
const PlayerId playerId) -> std::optional<int32_t> {
|
||||
const auto it = std::ranges::find_if(
|
||||
resolvedPlayerInfos,
|
||||
@@ -32,10 +30,10 @@ auto EagleFactionIdForPlayer(
|
||||
} // namespace
|
||||
|
||||
auto PopulateGameOverResponse(
|
||||
const string &gameId,
|
||||
const std::string &gameId,
|
||||
const net::eagle0::shardok::common::GameStatus &gameStatus,
|
||||
const vector<net::eagle0::shardok::common::PlayerInfo> &resolvedPlayerInfos,
|
||||
const vector<net::eagle0::shardok::storage::ResolvedUnit> &resolvedUnits,
|
||||
const std::vector<net::eagle0::shardok::common::PlayerInfo> &resolvedPlayerInfos,
|
||||
const std::vector<net::eagle0::shardok::storage::ResolvedUnit> &resolvedUnits,
|
||||
net::eagle0::common::GameOverResponse *gameOverResponse) -> bool {
|
||||
const auto &endCondition = gameStatus.end_game_condition();
|
||||
|
||||
|
||||
@@ -19,32 +19,30 @@
|
||||
#ifdef __clang__
|
||||
#pragma GCC diagnostic ignored "-Wexit-time-destructors"
|
||||
#endif
|
||||
const string ServerConfiguration::kShardokGrpcAddress = "shardokGrpcAddress";
|
||||
const string ServerConfiguration::kEagleInterfaceGrpcAddress = "eagleInterfaceGrpcAddress";
|
||||
const string ServerConfiguration::kEagleGrpcAddress = "eagleGrpcAddress";
|
||||
const string ServerConfiguration::kSslCertPath = "sslCertPath";
|
||||
const string ServerConfiguration::kSslPrivateKeyPath = "sslPrivateKeyPath";
|
||||
const string ServerConfiguration::kAuthTokenPath = "authTokenPath";
|
||||
const std::string ServerConfiguration::kShardokGrpcAddress = "shardokGrpcAddress";
|
||||
const std::string ServerConfiguration::kEagleInterfaceGrpcAddress = "eagleInterfaceGrpcAddress";
|
||||
const std::string ServerConfiguration::kEagleGrpcAddress = "eagleGrpcAddress";
|
||||
const std::string ServerConfiguration::kSslCertPath = "sslCertPath";
|
||||
const std::string ServerConfiguration::kSslPrivateKeyPath = "sslPrivateKeyPath";
|
||||
const std::string ServerConfiguration::kAuthTokenPath = "authTokenPath";
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
using std::unordered_map;
|
||||
std::unordered_map<std::string, std::string> DefaultValues();
|
||||
|
||||
unordered_map<string, string> DefaultValues();
|
||||
|
||||
unordered_map<string, string> DefaultValues() {
|
||||
std::unordered_map<std::string, std::string> DefaultValues() {
|
||||
// Check environment variables for Docker deployment
|
||||
// Docker containers should set SHARDOK_EAGLE_INTERFACE_ADDRESS=0.0.0.0:40042
|
||||
// to listen on all interfaces for container networking
|
||||
const char* eagleInterfaceAddr = getenv("SHARDOK_EAGLE_INTERFACE_ADDRESS");
|
||||
const char* shardokAddr = getenv("SHARDOK_GRPC_ADDRESS");
|
||||
|
||||
return unordered_map<string, string>{
|
||||
return std::unordered_map<std::string, std::string>{
|
||||
{ServerConfiguration::kShardokGrpcAddress, shardokAddr ? shardokAddr : "localhost"},
|
||||
{ServerConfiguration::kEagleInterfaceGrpcAddress,
|
||||
eagleInterfaceAddr ? eagleInterfaceAddr : "localhost:40042"}};
|
||||
}
|
||||
|
||||
ServerConfiguration::ServerConfiguration(const string& filePath) {
|
||||
ServerConfiguration::ServerConfiguration(const std::string& filePath) {
|
||||
if (!FilesystemUtils::FileExistsAtPath(filePath)) {
|
||||
std::cerr << "Config file not found at " << filePath << '\n';
|
||||
configValues = DefaultValues();
|
||||
@@ -56,20 +54,22 @@ ServerConfiguration::ServerConfiguration(const string& filePath) {
|
||||
while (!istr.eof()) {
|
||||
istr.getline(line, 256);
|
||||
if (strnlen(line, 256) < 3) continue;
|
||||
string key = strtok(line, " =");
|
||||
string value = strtok(nullptr, " =");
|
||||
std::string key = strtok(line, " =");
|
||||
std::string value = strtok(nullptr, " =");
|
||||
|
||||
configValues[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
int ServerConfiguration::intForKey(const string& key, const int defaultValue) {
|
||||
int ServerConfiguration::intForKey(const std::string& key, const int defaultValue) {
|
||||
const auto foundVal = configValues.find(key);
|
||||
if (foundVal == configValues.end()) { return defaultValue; }
|
||||
return std::stoi(foundVal->second);
|
||||
}
|
||||
|
||||
string ServerConfiguration::stringForKey(const string& key, const string& defaultValue) {
|
||||
std::string ServerConfiguration::stringForKey(
|
||||
const std::string& key,
|
||||
const std::string& defaultValue) {
|
||||
const auto foundVal = configValues.find(key);
|
||||
if (foundVal == configValues.end()) { return defaultValue; }
|
||||
return foundVal->second;
|
||||
|
||||
@@ -12,24 +12,22 @@
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
using std::string;
|
||||
|
||||
class ServerConfiguration {
|
||||
private:
|
||||
std::unordered_map<string, string> configValues;
|
||||
std::unordered_map<std::string, std::string> configValues;
|
||||
|
||||
public:
|
||||
explicit ServerConfiguration(const string& filePath);
|
||||
explicit ServerConfiguration(const std::string& filePath);
|
||||
|
||||
int intForKey(const string& key, int defaultValue = 0);
|
||||
string stringForKey(const string& key, const string& defaultValue = "");
|
||||
int intForKey(const std::string& key, int defaultValue = 0);
|
||||
std::string stringForKey(const std::string& key, const std::string& defaultValue = "");
|
||||
|
||||
const static string kShardokGrpcAddress;
|
||||
const static string kEagleInterfaceGrpcAddress;
|
||||
const static string kEagleGrpcAddress;
|
||||
const static string kSslCertPath;
|
||||
const static string kSslPrivateKeyPath;
|
||||
const static string kAuthTokenPath;
|
||||
const static std::string kShardokGrpcAddress;
|
||||
const static std::string kEagleInterfaceGrpcAddress;
|
||||
const static std::string kEagleGrpcAddress;
|
||||
const static std::string kSslCertPath;
|
||||
const static std::string kSslPrivateKeyPath;
|
||||
const static std::string kAuthTokenPath;
|
||||
};
|
||||
|
||||
#endif // EAGLE0_SHARDOK_SERVER_SERVER_CONFIGURATION_HPP
|
||||
|
||||
@@ -23,27 +23,27 @@
|
||||
#include "src/main/flatbuffer/net/eagle0/shardok/storage/unit.hpp"
|
||||
|
||||
namespace shardok {
|
||||
using std::shared_ptr;
|
||||
|
||||
auto SetUpController(
|
||||
const GameSettingsSPtr &gameSettings,
|
||||
const GameId &gameId,
|
||||
const string &mapName,
|
||||
const string &customMapBytes,
|
||||
const std::string &mapName,
|
||||
const std::string &customMapBytes,
|
||||
int month,
|
||||
const vector<Unit> &units,
|
||||
const vector<PlayerInfoProto> &playerSetupInfos,
|
||||
const std::vector<Unit> &units,
|
||||
const std::vector<PlayerInfoProto> &playerSetupInfos,
|
||||
const TutorialBattleConfigProto &tutorialConfig,
|
||||
const string &serializedRequest,
|
||||
const std::string &serializedRequest,
|
||||
const std::vector<std::pair<int32_t, std::vector<PlayerId>>> &watcherAllies = {})
|
||||
-> shared_ptr<ShardokGameController>;
|
||||
-> std::shared_ptr<ShardokGameController>;
|
||||
|
||||
ShardokGamesManager::ShardokGamesManager(const std::vector<std::string> &extraSettings) {
|
||||
gameSettings = SettingsLoader::LoadSettings();
|
||||
|
||||
for (const string &str : extraSettings) {
|
||||
for (const std::string &str : extraSettings) {
|
||||
std::stringstream stream(str);
|
||||
string key, value;
|
||||
std::string key;
|
||||
std::string value;
|
||||
std::getline(stream, key, '=');
|
||||
std::getline(stream, value);
|
||||
std::cerr << key << " << " << value << '\n';
|
||||
@@ -69,7 +69,7 @@ void ShardokGamesManager::RemoveController(const GameId &gameId) {
|
||||
auto ShardokGamesManager::UnlockedCreateFromGameStateBytes(
|
||||
const byte_vector &gameStateBytes,
|
||||
int32_t startingHistoryCount,
|
||||
const string &mapName) -> GameId {
|
||||
const std::string &mapName) -> GameId {
|
||||
std::unique_lock<std::shared_mutex> lk(runningControllersLock);
|
||||
|
||||
auto gs = GameStateW::FromByteVector(gameStateBytes);
|
||||
@@ -83,13 +83,13 @@ auto ShardokGamesManager::UnlockedCreateFromGameStateBytes(
|
||||
}
|
||||
|
||||
auto ShardokGamesManager::UnlockedCreateSpecifiedGame(
|
||||
const string &gameId,
|
||||
const vector<PlayerInfoWithUnits> &playerSetupInfos,
|
||||
const string &mapName,
|
||||
const string &customMapBytes,
|
||||
const std::string &gameId,
|
||||
const std::vector<PlayerInfoWithUnits> &playerSetupInfos,
|
||||
const std::string &mapName,
|
||||
const std::string &customMapBytes,
|
||||
const int month,
|
||||
const TutorialBattleConfigProto &tutorialConfig,
|
||||
const string &serializedRequest,
|
||||
const std::string &serializedRequest,
|
||||
const std::vector<std::pair<int32_t, std::vector<PlayerId>>> &watcherAllies) -> GameId {
|
||||
// Check for existing game with this ID and early-exit
|
||||
std::unique_lock<std::shared_mutex> lk(runningControllersLock);
|
||||
@@ -104,19 +104,19 @@ auto ShardokGamesManager::UnlockedCreateSpecifiedGame(
|
||||
return gameId;
|
||||
}
|
||||
|
||||
vector<PlayerInfoProto> playerInfos{};
|
||||
std::vector<PlayerInfoProto> playerInfos{};
|
||||
std::transform(
|
||||
std::begin(playerSetupInfos),
|
||||
std::end(playerSetupInfos),
|
||||
std::back_inserter(playerInfos),
|
||||
[](const PlayerInfoWithUnits &psi) { return psi.playerInfo; });
|
||||
|
||||
vector<Unit> units{};
|
||||
std::vector<Unit> units{};
|
||||
for (const auto &info : playerSetupInfos) {
|
||||
units.insert(std::end(units), std::begin(info.units), std::end(info.units));
|
||||
}
|
||||
|
||||
const shared_ptr<ShardokGameController> controller = SetUpController(
|
||||
const std::shared_ptr<ShardokGameController> controller = SetUpController(
|
||||
gameSettings,
|
||||
gameId,
|
||||
mapName,
|
||||
@@ -132,9 +132,9 @@ auto ShardokGamesManager::UnlockedCreateSpecifiedGame(
|
||||
}
|
||||
|
||||
auto ShardokGamesManager::LockedCreateGame(
|
||||
const shared_ptr<ShardokGameController> &controller,
|
||||
const vector<PlayerInfoWithUnits> & /*playerInfos*/,
|
||||
const string & /*serializedRequest*/) -> GameId {
|
||||
const std::shared_ptr<ShardokGameController> &controller,
|
||||
const std::vector<PlayerInfoWithUnits> & /*playerInfos*/,
|
||||
const std::string & /*serializedRequest*/) -> GameId {
|
||||
std::vector<std::shared_ptr<ShardokAIClient>> aiClients{};
|
||||
|
||||
GameId newGameId = controller->GetGameId();
|
||||
@@ -147,15 +147,15 @@ auto ShardokGamesManager::LockedCreateGame(
|
||||
auto SetUpController(
|
||||
const GameSettingsSPtr &gameSettings,
|
||||
const GameId &gameId,
|
||||
const string &mapName,
|
||||
const string &customMapBytes,
|
||||
const std::string &mapName,
|
||||
const std::string &customMapBytes,
|
||||
const int month,
|
||||
const vector<Unit> &units,
|
||||
const vector<PlayerInfoProto> &playerInfos,
|
||||
const std::vector<Unit> &units,
|
||||
const std::vector<PlayerInfoProto> &playerInfos,
|
||||
const TutorialBattleConfigProto &tutorialConfig,
|
||||
const string &serializedRequest,
|
||||
const std::string &serializedRequest,
|
||||
const std::vector<std::pair<int32_t, std::vector<PlayerId>>> &watcherAllies)
|
||||
-> shared_ptr<ShardokGameController> {
|
||||
-> std::shared_ptr<ShardokGameController> {
|
||||
auto unplacedUnits = std::vector<Unit>();
|
||||
|
||||
UnitId nextUnitId = 0;
|
||||
@@ -187,7 +187,7 @@ auto SetUpController(
|
||||
// These units exist in the game state from the start but are invisible and inactive
|
||||
// until the TutorialBattleController activates them at the triggered round.
|
||||
if (tutorialConfig.enabled()) {
|
||||
vector<PlayerId> allPlayerIds;
|
||||
std::vector<PlayerId> allPlayerIds;
|
||||
for (size_t i = 0; i < playerInfos.size(); i++) {
|
||||
allPlayerIds.push_back(static_cast<PlayerId>(i));
|
||||
}
|
||||
|
||||
@@ -27,8 +27,6 @@ class GameStatePersister;
|
||||
using net::eagle0::shardok::common::GameStatus;
|
||||
using PlayerInfoProto = net::eagle0::shardok::common::PlayerInfo;
|
||||
using TutorialBattleConfigProto = net::eagle0::common::TutorialBattleConfig;
|
||||
using std::string;
|
||||
using std::vector;
|
||||
using VictoryConditionProto = net::eagle0::shardok::common::VictoryCondition;
|
||||
|
||||
namespace shardok {
|
||||
@@ -38,14 +36,14 @@ class ShardokGameController;
|
||||
struct PlayerInfoWithUnits {
|
||||
public:
|
||||
const PlayerInfoProto playerInfo;
|
||||
const vector<Unit> units;
|
||||
const std::vector<Unit> units;
|
||||
|
||||
static auto MakePlayerInfo(
|
||||
const PlayerId pid,
|
||||
const bool def,
|
||||
const int food,
|
||||
const vector<VictoryConditionProto> &victoryConditions,
|
||||
const vector<PlayerId> &alliedPids,
|
||||
const std::vector<VictoryConditionProto> &victoryConditions,
|
||||
const std::vector<PlayerId> &alliedPids,
|
||||
const int32_t eagleFactionId,
|
||||
const bool isAi,
|
||||
const bool cannotBecomeOutlaw) -> PlayerInfoProto {
|
||||
@@ -68,9 +66,9 @@ public:
|
||||
const int32_t eagleFactionId,
|
||||
const bool def,
|
||||
const int food,
|
||||
const vector<VictoryConditionProto> &victoryConditions,
|
||||
const vector<PlayerId> &alliedPids,
|
||||
vector<Unit> us,
|
||||
const std::vector<VictoryConditionProto> &victoryConditions,
|
||||
const std::vector<PlayerId> &alliedPids,
|
||||
std::vector<Unit> us,
|
||||
const bool cannotBecomeOutlaw)
|
||||
: playerInfo(MakePlayerInfo(
|
||||
pid,
|
||||
@@ -93,8 +91,8 @@ private:
|
||||
|
||||
auto LockedCreateGame(
|
||||
const std::shared_ptr<ShardokGameController> &controller,
|
||||
const vector<PlayerInfoWithUnits> &playerInfos,
|
||||
const string &serializedRequest) -> GameId;
|
||||
const std::vector<PlayerInfoWithUnits> &playerInfos,
|
||||
const std::string &serializedRequest) -> GameId;
|
||||
|
||||
public:
|
||||
explicit ShardokGamesManager(const std::vector<std::string> &extraSettings);
|
||||
@@ -105,19 +103,19 @@ public:
|
||||
|
||||
auto UnlockedCreateSpecifiedGame(
|
||||
const GameId &gameId,
|
||||
const vector<PlayerInfoWithUnits> &playerSetupInfos,
|
||||
const string &mapName,
|
||||
const string &customMapBytes,
|
||||
const std::vector<PlayerInfoWithUnits> &playerSetupInfos,
|
||||
const std::string &mapName,
|
||||
const std::string &customMapBytes,
|
||||
int month,
|
||||
const TutorialBattleConfigProto &tutorialConfig,
|
||||
const string &serializedRequest,
|
||||
const std::string &serializedRequest,
|
||||
const std::vector<std::pair<int32_t, std::vector<PlayerId>>> &watcherAllies = {})
|
||||
-> GameId;
|
||||
|
||||
auto UnlockedCreateFromGameStateBytes(
|
||||
const byte_vector &gameStateBytes,
|
||||
int32_t startingHistoryCount,
|
||||
const string &mapName) -> GameId;
|
||||
const std::string &mapName) -> GameId;
|
||||
};
|
||||
} // namespace shardok
|
||||
|
||||
|
||||
@@ -1,140 +0,0 @@
|
||||
//
|
||||
// Created by Dan Crosby on 6/24/20.
|
||||
//
|
||||
|
||||
#include "src/main/cpp/net/eagle0/common/FilesystemUtils.hpp"
|
||||
#include "src/main/cpp/net/eagle0/common/TsvParser.hpp"
|
||||
#include "src/main/cpp/net/eagle0/common/byte_vector.hpp"
|
||||
#include "src/main/cpp/net/eagle0/shardok/library/ShardokEngine.hpp"
|
||||
#include "src/main/cpp/net/eagle0/shardok/library/fb_helpers/GameStateHelpers.hpp"
|
||||
#include "src/main/flatbuffer/net/eagle0/shardok/storage/unit.hpp"
|
||||
#include "src/main/protobuf/net/eagle0/shardok/storage/game.pb.h"
|
||||
|
||||
using net::eagle0::shardok::storage::Game;
|
||||
using Unit = net::eagle0::shardok::storage::fb::Unit;
|
||||
|
||||
void PrintChangedUnits(const net::eagle0::shardok::storage::ActionResult& result);
|
||||
|
||||
auto MakeEngine(const net::eagle0::shardok::storage::Game& game, int includeResultCount)
|
||||
-> std::shared_ptr<shardok::ShardokEngine>;
|
||||
|
||||
auto main(int argc, char** argv) -> int {
|
||||
if (argc < 2) {
|
||||
printf("Please supply a path.");
|
||||
return 1;
|
||||
}
|
||||
|
||||
const auto* path = argv[1];
|
||||
FilesystemUtils::SetExecPath(argv[0]);
|
||||
|
||||
printf("Using path %s\n", path);
|
||||
|
||||
const auto protoBytes = byte_vector::FromPath(path);
|
||||
Game game{};
|
||||
game.ParseFromArray(protoBytes.data(), protoBytes.size());
|
||||
|
||||
auto engine = MakeEngine(game, 200);
|
||||
auto result = game.action_result(201).action_result();
|
||||
|
||||
auto availableCommands = engine->GetAvailableCommandProtos(0, true);
|
||||
for (size_t i = 0; i < availableCommands.size(); i++) {
|
||||
auto cmd = availableCommands[i];
|
||||
if (result.has_actor() == cmd.has_actor() &&
|
||||
result.actor().value() == cmd.actor().value() && result.has_target_coords() &&
|
||||
result.target_coords() == cmd.target()) {
|
||||
printf("Command: %s\n", cmd.DebugString().c_str());
|
||||
engine->PostCommand(0, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
availableCommands = engine->GetAvailableCommandProtos(0, true);
|
||||
for (size_t i = 0; i < availableCommands.size(); i++) {
|
||||
auto cmd = availableCommands[i];
|
||||
if (cmd.type() == net::eagle0::shardok::common::END_TURN_COMMAND) {
|
||||
printf("Command: %s\n", cmd.DebugString().c_str());
|
||||
engine->PostCommand(0, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
availableCommands = engine->GetAvailableCommandProtos(1, true);
|
||||
for (size_t i = 0; i < availableCommands.size(); i++) {
|
||||
auto cmd = availableCommands[i];
|
||||
if (cmd.type() == net::eagle0::shardok::common::END_TURN_COMMAND) {
|
||||
printf("Command: %s\n", cmd.DebugString().c_str());
|
||||
engine->PostCommand(1, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
result = game.action_result(218).action_result();
|
||||
availableCommands = engine->GetAvailableCommandProtos(0, true);
|
||||
for (size_t i = 0; i < availableCommands.size(); i++) {
|
||||
auto cmd = availableCommands[i];
|
||||
if (result.has_actor() == cmd.has_actor() &&
|
||||
result.actor().value() == cmd.actor().value() && result.has_target_coords() &&
|
||||
result.target_coords() == cmd.target()) {
|
||||
printf("Command: %s\n", cmd.DebugString().c_str());
|
||||
engine->PostCommand(0, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// for (int i=180; i<219; i++) {
|
||||
// const auto& result = game.action_result(i).action_result();
|
||||
// // if (result.type() == net::eagle0::shardok::common::REDUCE || result.type() ==
|
||||
// net::eagle0::shardok::common::METEOR_UNIT_DAMAGE) {
|
||||
// printf("%d ", i);
|
||||
// PrintChangedUnits(result);
|
||||
// printf("id 0 after size: %d\n\n",
|
||||
// game.action_result(i).state_after().units().at(0).battalion().size());
|
||||
// // }
|
||||
// }
|
||||
|
||||
// for (const auto& kv : firstState.units()) {
|
||||
// printf("id: %d name: %s\n", kv.second.attached_hero().eagle_hero_id(),
|
||||
// kv.second.attached_hero().name().c_str());
|
||||
// }
|
||||
printf("Finished");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void PrintChangedUnits(const net::eagle0::shardok::storage::ActionResult& result) {
|
||||
printf("%s\n", net::eagle0::shardok::common::ActionType_Name(result.type()).c_str());
|
||||
for (const string& changedUnitData : result.changed_units_fb()) {
|
||||
const auto& changedUnit = *reinterpret_cast<const Unit*>(changedUnitData.data());
|
||||
printf("id: %d name: %s sizeAfter: %d\n",
|
||||
changedUnit.unit_id(),
|
||||
changedUnit.has_attached_hero() ? changedUnit.attached_hero().name().c_str() : "N/A",
|
||||
changedUnit.battalion().size());
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
auto MakeEngine(const net::eagle0::shardok::storage::Game& game, int includeResultCount)
|
||||
-> std::shared_ptr<shardok::ShardokEngine> {
|
||||
auto settings = std::make_shared<shardok::GameSettings>();
|
||||
|
||||
TsvParser parser;
|
||||
const string settingsPath = "src/main/resources/net/eagle0/shardok/settings.tsv";
|
||||
printf("Settings path is %s\n", settingsPath.c_str());
|
||||
string settingsTsv = string(byte_vector::FromPath(settingsPath));
|
||||
auto setter = shardok::GameSettings::Setter(*settings);
|
||||
|
||||
auto valuesAndTypes = parser.ParseColumnEntryTsv(settingsTsv);
|
||||
setter.SetFromTypesAndValues(valuesAndTypes[1], valuesAndTypes[0]);
|
||||
|
||||
const string battalionTypesPath = "src/main/resources/net/eagle0/shardok/battalionTypes.tsv";
|
||||
string tsv = string(byte_vector::FromPath(battalionTypesPath));
|
||||
auto battalionMaps = parser.ParseColumnEntryTsv(tsv);
|
||||
for (const std::unordered_map<string, string>& map : battalionMaps) {
|
||||
setter.RegisterBattalionType(shardok::BattalionType::NewBattalionTypeFromMap(map));
|
||||
}
|
||||
|
||||
return std::make_shared<shardok::ShardokEngine>(
|
||||
settings,
|
||||
shardok::fb::GameStateW::FromByteString(
|
||||
game.action_result(includeResultCount).state_after_fb()));
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user