CoolFace
Datasetpublic

blind-review-data/StarCraftMotion_sample

StarCraftMotion StarCraftMotion is a large-scale benchmark for agent simulation under adversarial and partial observability scenarios (built from StarCraft replays). Each example is a fixed-length scenario window (145 frames at 16 FPS, ~9 seconds) containing all unit states, dynamic map layers, and per-player economy time series. The released split is adversarial: scenarios are subsampled to overweight interaction-heavy windows (mutual-visibility and inter-player transitions)… See the full description on the dataset page: https://huggingface.co/datasets/blind-review-data/StarCraftMotion_sample.

sourceHugging Facecc-by-nc-4.0updated 5mo agoView on Hugging Face
0likes16downloads
Dataset Card

StarCraftMotion

StarCraftMotion is a large-scale benchmark for agent simulation under adversarial and partial observability scenarios (built from StarCraft replays). Each example is a fixed-length scenario window (145 frames at 16 FPS, ~9 seconds) containing all unit states, dynamic map layers, and per-player economy time series.

The released split is adversarial: scenarios are subsampled to overweight interaction-heavy windows (mutual-visibility and inter-player transitions), making it a stress test for multi-agent prediction under partial observability.

  • —Total scenarios: 469,187
  • —Train / Val / Test: 362,075 / 45,121 / 61,991
  • —Source replays: 64,327 replay-level HDF5 files (Blizzard 3.16.1-Pack_1-fix)
  • —Maps (ID): AbyssalReefLE, AcolyteLE, AscensiontoAiurLE, InterloperLE, MechDepot_LE
  • —Maps (OOD, test only): CatallenaLE(Void), Odyssey_LE
  • —Splits are replay-level — windows from the same replay never cross splits.

Why parquet, and how to read

Each row is one scenario. All per-frame / per-unit array columns are stored as typed Arrow `large_list` arrays (e.g. LIST<float16>, LIST<bool>). n_timesteps = 145 and n_units varies per scenario (stored per row). The dynamic map layers (map_creep, map_fow_p1, map_fow_p2) are sampled every 16 frames, giving map_T = 10 snapshots per scenario. Spatial dimensions map_H and map_W are stored as explicit scalar columns per row (map-dependent; e.g. AbyssalReefLE is 176 × 200).

python
import numpy as np
from datasets import load_dataset

ds = load_dataset("blind-review-data/StarCraftMotion", split="train", streaming=True)
row = next(iter(ds))

T, N = row["n_timesteps"], row["n_units"]
map_T, map_H, map_W = row["map_T"], row["map_H"], row["map_W"]

coord = np.asarray(row["coordinate"], dtype=np.float16).reshape(T, N, 3)
alive = np.asarray(row["is_alive"],   dtype=bool    ).reshape(T, N)
owner = np.asarray(row["unit_owner"], dtype=np.uint8 ).reshape(N)
utype = np.asarray(row["unit_type"],  dtype=np.uint32).reshape(T, N)
creep = np.asarray(row["map_creep"],  dtype=bool    ).reshape(map_T, map_H, map_W)

Schema

Scalar fields
FieldTypeDescription
splitstringtrain, val, or test
map_namestringMap name (spaces replaced with _)
replay_hashstringHash of the parent SC2Replay file
segment_idxint32Index of this 145-frame window inside the parent replay
n_timestepsint32Number of frames per row (constant 145 in this release)
n_unitsint32Number of unique unit rows in this scenario (variable)
map_Tint32Number of map snapshots per row (constant 10 in this release)
map_Hint32Map grid height in cells (map-dependent)
map_Wint32Map grid width in cells (map-dependent)
Map data — shape (map_T, map_H, map_W) where map_T = 10

map_H and map_W are map-specific (each StarCraft II ladder map has its own native grid). All three layers below share the same shape per scenario.

Fielddtype
map_creepbool
map_fow_p1bool
map_fow_p2bool
Player economy — shape (145, 2), column 0 = Player 1, column 1 = Player 2
Fielddtype
food_capuint8
food_useduint8
mineralsuint16
vespeneuint16
Per-unit constants — shape (n_units,)
FielddtypeDescription
unit_owneruint81 = P1, 2 = P2, 16 = neutral
unit_taguint64Raw SC2 engine tag (unique per unit instance)
Per-frame, per-unit — shape (145, n_units) unless noted
FielddtypeShapeDescription
coordinatefloat16(145, n_units, 3)Native (x, y, z) map coordinates
target_posfloat16(145, n_units, 2)Order target ground position
healthfloat16
health_maxfloat16
shieldfloat16Protoss shield
energyfloat16
headingfloat16Facing direction in radians (0 to 2π)
radiusfloat16Unit collision radius
build_progressfloat160.0–1.0
unit_typeuint32Raw SC2 unit type ID
ability_iduint32First order's ability ID
target_iduint32Target's row index (0xFFFFFFFF = no target)
mineral_contentsuint16Remaining minerals (mineral fields)
vespene_contentsuint16Remaining vespene (geysers)
is_alivebool
is_burrowedboolZerg burrowed
is_carriedboolInside a transport
is_flyingboolAir unit / lifted building
visible_statusuint8Combined P1/P2 visibility (see below)

visible_status = p1_state * 3 + p2_state, with each state in {0 = unseen, 1 = snapshot, 2 = visible}. Examples: 8 = visible to both, 6 = visible to P1 only, 2 = visible to P2 only.

Action labels

The ability_id column stores the raw SC2 ability ID as `uint32` (e.g. MOVE = 16, ATTACK_ATTACK = 23, HARVEST_GATHER_DRONE = 1183, ability_id == 0 means the unit has no active order). It is not class-indexed.

For action prediction tasks we provide an 11-class coarse mapping in the source repository at [sc2sensor/utils/coarse_action_mapping.py].

LabelNameDescription
0NO_OPability_id == 0; unit idle
1MOVEmove, patrol, hold position, stop, smart (right-click)
2ATTACKattack, attack-move, attack building
3HARVESTgather resources, return cargo
4TRAINproduce units from buildings / larvae / warp-in
5BUILDconstruct structures, add-ons, creep tumors
6RESEARCHupgrades and tech research
7MORPHunit/structure transformation (siege, archon, lair, etc.)
8EFFECTcombat abilities, spells, auto-cast effects
9TRANSPORTload, unload, lift off, land
10BURROWburrow down / burrow up (Zerg)
255UNKNOWNunmapped or cosmetic

Sources for the mapping:

  • —Blizzard s2client-api ABILITY_ID enum: https://blizzard.github.io/s2client-api/sc2_typeenums8h.html
  • —Blizzard s2client-proto stableid.json: https://github.com/Blizzard/s2client-proto/blob/master/stableid.json

Coverage on the released split is 100% of all action occurrences (every ability_id either matches a Blizzard enum prefix, is one of 10 explicit stableid.json overrides, or is 0 / falls into UNKNOWN).

Applying the mapping
python
import numpy as np
from sc2sensor.utils.coarse_action_mapping import ABILITY_ID_TO_COARSE_ACTION

T, N = row["n_timesteps"], row["n_units"]
ability_id = np.frombuffer(row["ability_id"], dtype=np.uint32).reshape(T, N)

# Vectorized lookup via a dense uint8 table.
max_id = max(ABILITY_ID_TO_COARSE_ACTION) + 1
lut = np.full(max_id, 255, dtype=np.uint8)
for aid, label in ABILITY_ID_TO_COARSE_ACTION.items():
    lut[aid] = label

coarse = np.where(ability_id < max_id, lut[np.clip(ability_id, 0, max_id - 1)], 255)

Pipeline summary

  1. 1.Replay extraction (extract_replay_level.py): three SC2 engine passes (omniscient + per-player FOW) into one HDF5 per replay, preserving native coordinates, raw SC2 unit/ability IDs, and per-player visibility.
  2. 2.Scenario windowing (split_scenarios.py): chunk into 145-frame windows at 16 FPS (1 s history + current + 8 s future). Drops replays with duration < 120 s or either player at APM < 1.
  3. 3.Replay-level split (create_dataset_split.py): 80/10/10 train/val/test over ID maps; OOD maps go to test only. Keeps 10% of each replay's windows.
  4. 4.Adversarial weighting: window sampling weight is log(1 + mutual_unit_sum) + log(1 + transition_cnt); zero-score windows are excluded.

Dataset statistics

Player-unit counts (units with owner != 16)

SplitMeanStdMinP25MedianP75Max
Train204.56113.0611109189284921
Val203.56112.5118109188282689
Test202.78111.7013107189281779

Race matchups

SplitPvPPvTPvZTvTTvZZvZ
Train23,32282,81966,13954,819104,78030,196
Val3,0379,9788,5146,85313,3263,413
Test4,11213,92710,8839,53618,5315,002

Mutual visibility (units with visible_status == 8 and is_alive)

SplitMean mutually-visible units / frame
Train23.56
Val23.40
Test23.43

Intended use

  • —Multi-agent simulation under adversarial partial observability.
  • —Benchmarks for fog-of-war handling, ID vs OOD-map generalization, and interaction-heavy scenes.

Limitations and ethical considerations

  • —Replay provenance: raw replays come from Blizzard's 3.16.1-Pack_1-fix distribution. Per-replay curation, demographics of players, and any prior filtering performed by Blizzard are not documented.
  • —MMR caveat: raw MMR values include sentinel-like negatives (down to -36400) for some replays. League-tier bucketing should be recomputed rather than relied upon naively.
  • —Single game version: all replays are SC2 build 3.16.1; balance and meta-game differ from current ladder versions.
  • —No personally identifying content is included beyond what Blizzard publishes in replay packs. Player names are not surfaced as columns.
  • —Game-balance / strategic bias: the corpus is whatever Blizzard released in the pack and is not a uniform sample of competitive play.

License

The released parquet artifacts are licensed under **Creative Commons Attribution-NonCommercial 4.0 International (CC-BY-NC-4.0)** (SPDX: CC-BY-NC-4.0).

The released parquet files are derivative ML features (float16 unit trajectories, fog-of-war and creep masks, per-player economy time series, and raw SC2 unit/ability identifiers) extracted from StarCraft II replays. The dataset does not redistribute raw .SC2Replay files, SC2 game maps, or any portion of the StarCraft II Software. Use of the underlying StarCraft II replays and the SC2 engine is separately governed by Blizzard's AI and Machine Learning License; that license explicitly permits use of derived ML data for personal or internal research and development.

Citation

Underlying replays:

bibtex
@misc{blizzard_sc2_replaypacks,
  title  = {StarCraft II Replay Packs (3.16.1-Pack\_1-fix)},
  author = {{Blizzard Entertainment}},
  howpublished = {\url{https://blzdistsc2-a.akamaihd.net/ReplayPacks/3.16.1-Pack_1-fix.zip}}
}

Acknowledgments

Built on top of DeepMind's pysc2 and Blizzard's StarCraft II AI/ML infrastructure.