Showing preview only (4,448K chars total). Download the full file or copy to clipboard to get everything.
Repository: google-deepmind/pysc2
Branch: master
Commit: 0df53d38c153
Files: 247
Total size: 25.5 MB
Directory structure:
gitextract_2o40zztk/
├── .gitignore
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── WORKSPACE
├── bazel/
│ ├── BUILD
│ ├── BUILD.dm_env
│ ├── BUILD.dm_env_rpc
│ ├── BUILD.s2protocol
│ ├── create_external_repos.bzl
│ ├── protobuf.patch
│ ├── requirements.txt
│ ├── s2clientprotocol.patch
│ └── setup_external_repos.bzl
├── docs/
│ ├── bazel.md
│ ├── converters.md
│ ├── environment.md
│ ├── maps.md
│ └── mini_games.md
├── pysc2/
│ ├── BUILD
│ ├── __init__.py
│ ├── agents/
│ │ ├── BUILD
│ │ ├── __init__.py
│ │ ├── base_agent.py
│ │ ├── no_op_agent.py
│ │ ├── random_agent.py
│ │ └── scripted_agent.py
│ ├── bin/
│ │ ├── BUILD
│ │ ├── __init__.py
│ │ ├── agent.py
│ │ ├── agent_remote.py
│ │ ├── battle_net_maps.py
│ │ ├── benchmark_observe.py
│ │ ├── benchmark_replay.py
│ │ ├── check_apm.py
│ │ ├── compare_binaries.py
│ │ ├── gen_actions.py
│ │ ├── gen_data.py
│ │ ├── gen_versions.py
│ │ ├── map_list.py
│ │ ├── mem_leak_check.py
│ │ ├── play.py
│ │ ├── play_vs_agent.py
│ │ ├── reencode_replays.py
│ │ ├── replay_actions.py
│ │ ├── replay_info.py
│ │ ├── replay_version.py
│ │ ├── run_tests.py
│ │ ├── update_battle_net_cache.py
│ │ └── valid_actions.py
│ ├── build_defs.bzl
│ ├── env/
│ │ ├── BUILD
│ │ ├── __init__.py
│ │ ├── available_actions_printer.py
│ │ ├── base_env_wrapper.py
│ │ ├── converted_env.py
│ │ ├── converted_env_test.py
│ │ ├── converter/
│ │ │ ├── BUILD
│ │ │ ├── __init__.py
│ │ │ ├── cc/
│ │ │ │ ├── BUILD
│ │ │ │ ├── __init__.py
│ │ │ │ ├── castops.h
│ │ │ │ ├── check_protos_equal.h
│ │ │ │ ├── convert_obs.cc
│ │ │ │ ├── convert_obs.h
│ │ │ │ ├── convert_obs_test.cc
│ │ │ │ ├── converter.cc
│ │ │ │ ├── converter.h
│ │ │ │ ├── converter_test.cc
│ │ │ │ ├── encode_image_data.h
│ │ │ │ ├── features.cc
│ │ │ │ ├── features.h
│ │ │ │ ├── file_util.cc
│ │ │ │ ├── file_util.h
│ │ │ │ ├── game_data/
│ │ │ │ │ ├── BUILD
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── proto/
│ │ │ │ │ │ ├── BUILD
│ │ │ │ │ │ ├── __init__.py
│ │ │ │ │ │ ├── buffs.proto
│ │ │ │ │ │ ├── units.proto
│ │ │ │ │ │ └── upgrades.proto
│ │ │ │ │ ├── python/
│ │ │ │ │ │ ├── BUILD
│ │ │ │ │ │ ├── __init__.py
│ │ │ │ │ │ ├── uint8_lookup.cc
│ │ │ │ │ │ └── uint8_lookup_test.py
│ │ │ │ │ ├── raw_actions.cc
│ │ │ │ │ ├── raw_actions.h
│ │ │ │ │ ├── uint8_lookup.cc
│ │ │ │ │ ├── uint8_lookup.h
│ │ │ │ │ ├── visual_actions.cc
│ │ │ │ │ └── visual_actions.h
│ │ │ │ ├── general_order_ids.cc
│ │ │ │ ├── general_order_ids.h
│ │ │ │ ├── map_util.cc
│ │ │ │ ├── map_util.h
│ │ │ │ ├── python/
│ │ │ │ │ ├── BUILD
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ └── converter.cc
│ │ │ │ ├── raw_actions_encoder.cc
│ │ │ │ ├── raw_actions_encoder.h
│ │ │ │ ├── raw_actions_encoder_test.cc
│ │ │ │ ├── raw_camera.cc
│ │ │ │ ├── raw_camera.h
│ │ │ │ ├── raw_converter.cc
│ │ │ │ ├── raw_converter.h
│ │ │ │ ├── tensor_util.cc
│ │ │ │ ├── tensor_util.h
│ │ │ │ ├── test_data/
│ │ │ │ │ ├── BUILD
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── actions/
│ │ │ │ │ │ ├── feature_camera_move.pbtxt
│ │ │ │ │ │ ├── feature_unit_command.pbtxt
│ │ │ │ │ │ ├── feature_unit_selection_point.pbtxt
│ │ │ │ │ │ ├── ui_control_group_append.pbtxt
│ │ │ │ │ │ └── ui_control_group_recall.pbtxt
│ │ │ │ │ ├── obs_data1.pbtxt
│ │ │ │ │ └── recordings/
│ │ │ │ │ └── tvt_trunk.pb
│ │ │ │ ├── unit_lookups.cc
│ │ │ │ ├── unit_lookups.h
│ │ │ │ ├── unit_lookups_test.cc
│ │ │ │ ├── visual_actions.cc
│ │ │ │ ├── visual_actions.h
│ │ │ │ ├── visual_actions_test.cc
│ │ │ │ ├── visual_converter.cc
│ │ │ │ ├── visual_converter.h
│ │ │ │ └── visual_converter_test.cc
│ │ │ ├── converter.py
│ │ │ ├── converter_test.py
│ │ │ ├── derive_interface_options.py
│ │ │ └── proto/
│ │ │ ├── BUILD
│ │ │ ├── __init__.py
│ │ │ └── converter.proto
│ │ ├── enums.py
│ │ ├── environment.py
│ │ ├── host_remote_agent.py
│ │ ├── lan_sc2_env.py
│ │ ├── mock_sc2_env.py
│ │ ├── mock_sc2_env_comparison_test.py
│ │ ├── mock_sc2_env_test.py
│ │ ├── remote_sc2_env.py
│ │ ├── run_loop.py
│ │ ├── sc2_env.py
│ │ └── sc2_env_test.py
│ ├── lib/
│ │ ├── BUILD
│ │ ├── __init__.py
│ │ ├── actions.py
│ │ ├── buffs.py
│ │ ├── colors.py
│ │ ├── features.py
│ │ ├── features_test.py
│ │ ├── gfile.py
│ │ ├── image_differencer.py
│ │ ├── image_differencer_test.py
│ │ ├── memoize.py
│ │ ├── metrics.py
│ │ ├── named_array.py
│ │ ├── named_array_test.py
│ │ ├── np_util.py
│ │ ├── np_util_test.py
│ │ ├── point.py
│ │ ├── point_flag.py
│ │ ├── point_test.py
│ │ ├── portspicker.py
│ │ ├── portspicker_test.py
│ │ ├── proto_diff.py
│ │ ├── proto_diff_test.py
│ │ ├── protocol.py
│ │ ├── remote_controller.py
│ │ ├── renderer_ascii.py
│ │ ├── renderer_human.py
│ │ ├── replay/
│ │ │ ├── BUILD
│ │ │ ├── __init__.py
│ │ │ ├── replay_converter.py
│ │ │ ├── replay_observation_stream.py
│ │ │ ├── sc2_replay.py
│ │ │ ├── sc2_replay_test.py
│ │ │ ├── sc2_replay_utils.py
│ │ │ ├── sc2_replay_utils_test.py
│ │ │ └── test_data/
│ │ │ ├── replay_01.SC2Replay
│ │ │ ├── replay_01.skips.txt
│ │ │ ├── replay_02.SC2Replay
│ │ │ ├── replay_02.skips.txt
│ │ │ ├── replay_03.SC2Replay
│ │ │ ├── replay_03.skips.txt
│ │ │ ├── replay_04.SC2Replay
│ │ │ ├── replay_04.skips.txt
│ │ │ ├── replay_05.SC2Replay
│ │ │ ├── replay_05.skips.txt
│ │ │ ├── replay_06.SC2Replay
│ │ │ ├── replay_06.skips.txt
│ │ │ ├── replay_07.SC2Replay
│ │ │ ├── replay_07.skips.txt
│ │ │ ├── replay_08.SC2Replay
│ │ │ ├── replay_08.skips.txt
│ │ │ ├── replay_09.SC2Replay
│ │ │ └── replay_09.skips.txt
│ │ ├── replay.py
│ │ ├── resources.py
│ │ ├── run_parallel.py
│ │ ├── run_parallel_test.py
│ │ ├── sc_process.py
│ │ ├── static_data.py
│ │ ├── stopwatch.py
│ │ ├── stopwatch_test.py
│ │ ├── transform.py
│ │ ├── units.py
│ │ ├── upgrades.py
│ │ └── video_writer.py
│ ├── maps/
│ │ ├── BUILD
│ │ ├── __init__.py
│ │ ├── ladder.py
│ │ ├── lib.py
│ │ ├── melee.py
│ │ ├── mini_games/
│ │ │ ├── BuildMarines.SC2Map
│ │ │ ├── CollectMineralShards.SC2Map
│ │ │ ├── CollectMineralsAndGas.SC2Map
│ │ │ ├── DefeatRoaches.SC2Map
│ │ │ ├── DefeatZerglingsAndBanelings.SC2Map
│ │ │ ├── FindAndDefeatZerglings.SC2Map
│ │ │ └── MoveToBeacon.SC2Map
│ │ └── mini_games.py
│ ├── run_configs/
│ │ ├── BUILD
│ │ ├── __init__.py
│ │ ├── lib.py
│ │ └── platforms.py
│ └── tests/
│ ├── BUILD
│ ├── __init__.py
│ ├── actions_test.py
│ ├── debug_test.py
│ ├── dummy_observation.py
│ ├── dummy_observation_test.py
│ ├── easy_scripted_test.py
│ ├── general_actions_test.py
│ ├── host_remote_agent_test.py
│ ├── multi_player_env_test.py
│ ├── multi_player_test.py
│ ├── obs_spec_test.py
│ ├── obs_test.py
│ ├── observer_test.py
│ ├── ping_test.py
│ ├── protocol_error_test.py
│ ├── random_agent_test.py
│ ├── render_test.py
│ ├── replay_obs_test.py
│ ├── step_mul_override_test.py
│ ├── utils.py
│ └── versions_test.py
└── setup.py
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
*.pyc
*_pb2.py
================================================
FILE: CONTRIBUTING.md
================================================
Want to contribute? Great! First, read this page (including the small print at
the end).
### Before you contribute
Before we can use your code, you must sign the
[Google Individual Contributor License Agreement]
(https://cla.developers.google.com/about/google-individual)
(CLA), which you can do online. The CLA is necessary mainly because you own the
copyright to your changes, even after your contribution becomes part of our
codebase, so we need your permission to use and distribute your code. We also
need to be sure of various other things—for instance that you'll tell us if you
know that your code infringes on other people's patents. You don't have to sign
the CLA until after you've submitted your code for review and a member has
approved it, but you must do it before we can put your code into our codebase.
Before you start working on a larger contribution, you should get in touch with
us first through the issue tracker with your idea so that we can help out and
possibly guide you. Coordinating up front makes it much easier to avoid
frustration later on.
### Code reviews
All submissions, including submissions by project members, require review. We
use Github pull requests for this purpose.
### The small print
Contributions made by corporations are covered by a different agreement than
the one above, the
[Software Grant and Corporate Contributor License Agreement]
(https://cla.developers.google.com/about/google-corporate).
================================================
FILE: LICENSE
================================================
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2017 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
================================================
FILE: README.md
================================================
<div align="center">
<a href="https://www.youtube.com/watch?v=-fKUyT14G-8"
target="_blank">
<img src="http://img.youtube.com/vi/-fKUyT14G-8/0.jpg"
alt="DeepMind open source PySC2 toolset for Starcraft II"
width="240" height="180" border="10" />
</a>
<a href="https://www.youtube.com/watch?v=6L448yg0Sm0"
target="_blank">
<img src="http://img.youtube.com/vi/6L448yg0Sm0/0.jpg"
alt="StarCraft II 'mini games' for AI research"
width="240" height="180" border="10" />
</a>
<a href="https://www.youtube.com/watch?v=WEOzide5XFc"
target="_blank">
<img src="http://img.youtube.com/vi/WEOzide5XFc/0.jpg"
alt="Trained and untrained agents play StarCraft II 'mini-game'"
width="240" height="180" border="10" />
</a>
</div>
# PySC2 - StarCraft II Learning Environment
[PySC2](https://github.com/deepmind/pysc2) is [DeepMind](http://deepmind.com)'s
Python component of the StarCraft II Learning Environment (SC2LE). It exposes
[Blizzard Entertainment](http://blizzard.com)'s [StarCraft II Machine Learning
API](https://github.com/Blizzard/s2client-proto) as a Python RL Environment.
This is a collaboration between DeepMind and Blizzard to develop StarCraft II
into a rich environment for RL research. PySC2 provides an interface for RL
agents to interact with StarCraft 2, getting observations and sending actions.
We have published an accompanying
[blogpost](https://deepmind.com/blog/deepmind-and-blizzard-open-starcraft-ii-ai-research-environment/)
and [paper](https://arxiv.org/abs/1708.04782), which outlines our
motivation for using StarCraft II for DeepRL research, and some initial research
results using the environment.
## About
Disclaimer: This is not an official Google product.
If you use the StarCraft II Machine Learning API and/or PySC2 in your research,
please cite the [StarCraft II Paper](https://arxiv.org/abs/1708.04782)
You can reach us at [pysc2@deepmind.com](mailto:pysc2@deepmind.com).
# Quick Start Guide
## Get PySC2
### PyPI
The easiest way to get PySC2 is to use pip:
```shell
$ pip install pysc2
```
That will install the `pysc2` package along with all the required dependencies.
[virtualenv](https://pypi.python.org/pypi/virtualenv) can help manage your
dependencies. You may also need to upgrade pip: `pip install --upgrade pip`
for the `pysc2` install to work. If you're running on an older system you may
need to install `libsdl` libraries for the `pygame` dependency.
Pip will install a few of the binaries to your bin directory. `pysc2_play` can
be used as a shortcut to `python -m pysc2.bin.play`.
### From Source
Alternatively you can install latest PySC2 codebase from git master branch:
```shell
$ pip install --upgrade https://github.com/deepmind/pysc2/archive/master.zip
```
or from a local clone of the git repo:
```shell
$ git clone https://github.com/deepmind/pysc2.git
$ pip install --upgrade pysc2/
```
## Get StarCraft II
PySC2 depends on the full StarCraft II game and only works with versions that
include the API, which is 3.16.1 and above.
### Linux
Follow Blizzard's [documentation](https://github.com/Blizzard/s2client-proto#downloads) to
get the linux version. By default, PySC2 expects the game to live in
`~/StarCraftII/`. You can override this path by setting the `SC2PATH`
environment variable or creating your own run_config.
### Windows/MacOS
Install of the game as normal from [Battle.net](https://battle.net). Even the
[Starter Edition](http://battle.net/sc2/en/legacy-of-the-void/) will work.
If you used the default install location PySC2 should find the latest binary.
If you changed the install location, you might need to set the `SC2PATH`
environment variable with the correct location.
PySC2 should work on MacOS and Windows systems running Python 3.8+,
but has only been thoroughly tested on Linux. We welcome suggestions and patches
for better compatibility with other systems.
## Get the maps
PySC2 has many maps pre-configured, but they need to be downloaded into the SC2
`Maps` directory before they can be played.
Download the [ladder maps](https://github.com/Blizzard/s2client-proto#downloads)
and the [mini games](https://github.com/deepmind/pysc2/releases/download/v1.2/mini_games.zip)
and extract them to your `StarCraftII/Maps/` directory.
## Run an agent
You can run an agent to test the environment. The UI shows you the actions of
the agent and is helpful for debugging and visualization purposes.
```shell
$ python -m pysc2.bin.agent --map Simple64
```
It runs a random agent by default, but you can specify others if you'd like,
including your own.
```shell
$ python -m pysc2.bin.agent --map CollectMineralShards --agent pysc2.agents.scripted_agent.CollectMineralShards
```
You can also run two agents against each other.
```shell
$ python -m pysc2.bin.agent --map Simple64 --agent2 pysc2.agents.random_agent.RandomAgent
```
To specify the agent's race, the opponent's difficulty, and more, you can pass
additional flags. Run with `--help` to see what you can change.
## Play the game as a human
There is a human agent interface which is mainly used for debugging, but it can
also be used to play the game. The UI is fairly simple and incomplete, but it's
enough to understand the basics of the game. Also, it runs on Linux.
```shell
$ python -m pysc2.bin.play --map Simple64
```
In the UI, hit `?` for a list of the hotkeys. The most basic ones are: `F4` to
quit, `F5` to restart, `F8` to save a replay, and `Pgup`/`Pgdn` to control the
speed of the game. Otherwise use the mouse for selection and keyboard for
commands listed on the left.
The left side is a basic rendering. The right side is the feature layers that
the agent receives, with some coloring to make it more useful to us. You can
enable or disable RGB or feature layer rendering and their resolutions with
command-line flags.
## Watch a replay
Running an agent and playing as a human save a replay by default. You can watch
that replay by running:
```shell
$ python -m pysc2.bin.play --replay <path-to-replay>
```
This works for any replay as long as the map can be found by the game.
The same controls work as for playing the game, so `F4` to exit, `pgup`/`pgdn`
to control the speed, etc.
You can save a video of the replay with the `--video` flag.
## List the maps
[Maps](docs/maps.md) need to be configured before they're known to the
environment. You can see the list of known maps by running:
```shell
$ python -m pysc2.bin.map_list
```
## Run the tests
If you want to submit a pull request, please make sure the tests pass on both
python 2 and 3.
```shell
$ python -m pysc2.bin.run_tests
```
# Environment Details
For a full description of the specifics of how the environment is configured,
the observations and action spaces work read the
[environment documentation](docs/environment.md).
Note that an alternative to this environment is now available which provides
an enriched action and observation format using the C++ wrappers developed
for AlphaStar. See [the converter documentation](docs/converters.md) for more
information.
# Mini-game maps
The mini-game map files referenced in the paper are stored under `pysc2/maps/`
but must be installed in `$SC2PATH/Maps`. Make sure to follow the download
instructions above.
Maps are configured in the Python files in `pysc2/maps/`. The configs can set
player and time limits, whether to use the game outcome or curriculum score, and
a handful of other things. For more information about the maps, and how to
configure your own, read the [maps documentation](docs/maps.md).
# Replays
A replay lets you review what happened during a game. You can see the actions
and observations that each player made as they played.
Blizzard is releasing a large number of anonymized 1v1 replays played on the
ladder. You can find instructions for how to get the
[replay files](https://github.com/Blizzard/s2client-proto#downloads) on their
site. You can also review your own replays.
Replays can be played back to get the observations and actions made during that
game. The observations are rendered at the resolution you request, so may differ
from what the human actually saw. Similarly the actions specify a point, which
could reflect a different pixel on the human's screen, so may not have an exact
match in our observations, though they should be fairly similar.
Replays are version dependent, so a 3.16 replay will fail in a 3.16.1 or 3.17
binary.
You can visualize the replays with the full game, or with `pysc2.bin.play`.
Alternatively you can run `pysc2.bin.replay_actions` to process many replays
in parallel.
================================================
FILE: WORKSPACE
================================================
workspace(name = "pysc2")
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
load("//bazel:create_external_repos.bzl", "pysc2_create_external_repos")
pysc2_create_external_repos(pysc2_repo_name = "pysc2")
load("//bazel:setup_external_repos.bzl", "pysc2_setup_external_repos")
pysc2_setup_external_repos()
bind(
name = "python_headers",
actual = "@local_config_python//:python_headers",
)
http_archive(
name = "bazel_skylib",
strip_prefix = "bazel-skylib-main",
urls = ["https://github.com/bazelbuild/bazel-skylib/archive/main.zip"],
)
http_archive(
name = "rules_python",
url = "https://github.com/bazelbuild/rules_python/releases/download/0.4.0/rules_python-0.4.0.tar.gz",
sha256 = "954aa89b491be4a083304a2cb838019c8b8c3720a7abb9c4cb81ac7a24230cea",
)
load("@rules_python//python:pip.bzl", "pip_install")
http_archive(
name = "rules_cc",
urls = ["https://github.com/bazelbuild/rules_cc/archive/68cb652a71e7e7e2858c50593e5a9e3b94e5b9a9.zip"],
strip_prefix = "rules_cc-68cb652a71e7e7e2858c50593e5a9e3b94e5b9a9",
sha256 = "1e19e9a3bc3d4ee91d7fcad00653485ee6c798efbbf9588d40b34cbfbded143d",
)
load("@rules_cc//cc:repositories.bzl", "rules_cc_dependencies")
rules_cc_dependencies()
# Create a central external repo, @my_deps, that contains Bazel targets for all the
# third-party packages specified in the requirements.txt file.
pip_install(
name = "my_deps",
requirements = "@//bazel:requirements.txt",
)
http_archive(
name = "rules_proto",
sha256 = "66bfdf8782796239d3875d37e7de19b1d94301e8972b3cbd2446b332429b4df1",
strip_prefix = "rules_proto-4.0.0",
urls = [
"https://mirror.bazel.build/github.com/bazelbuild/rules_proto/archive/refs/tags/4.0.0.tar.gz",
"https://github.com/bazelbuild/rules_proto/archive/refs/tags/4.0.0.tar.gz",
],
)
load("@rules_proto//proto:repositories.bzl", "rules_proto_dependencies", "rules_proto_toolchains")
rules_proto_dependencies()
rules_proto_toolchains()
# C++ dependencies.
http_archive(
name = "com_google_googletest",
sha256 = "ff7a82736e158c077e76188232eac77913a15dac0b22508c390ab3f88e6d6d86",
strip_prefix = "googletest-b6cd405286ed8635ece71c72f118e659f4ade3fb",
urls = [
"https://storage.googleapis.com/mirror.tensorflow.org/github.com/google/googletest/archive/b6cd405286ed8635ece71c72f118e659f4ade3fb.zip",
"https://github.com/google/googletest/archive/b6cd405286ed8635ece71c72f118e659f4ade3fb.zip",
],
)
http_archive(
name = "com_google_absl",
sha256 = "35f22ef5cb286f09954b7cc4c85b5a3f6221c9d4df6b8c4a1e9d399555b366ee", # SHARED_ABSL_SHA
strip_prefix = "abseil-cpp-997aaf3a28308eba1b9156aa35ab7bca9688e9f6",
urls = [
"https://storage.googleapis.com/mirror.tensorflow.org/github.com/abseil/abseil-cpp/archive/997aaf3a28308eba1b9156aa35ab7bca9688e9f6.tar.gz",
"https://github.com/abseil/abseil-cpp/archive/997aaf3a28308eba1b9156aa35ab7bca9688e9f6.tar.gz",
],
)
================================================
FILE: bazel/BUILD
================================================
licenses(["notice"])
exports_files(
[
"BUILD.dm_env",
"BUILD.dm_env_rpc",
"BUILD.s2protocol",
"protobuf.patch",
"requirements.txt",
"s2clientprotocol.patch",
],
visibility = ["//visibility:public"],
)
================================================
FILE: bazel/BUILD.dm_env
================================================
load("@my_deps//:requirements.bzl", "requirement")
licenses(["notice"])
py_library(
name = "dm_env",
srcs = [
"dm_env/__init__.py",
"dm_env/_environment.py",
"dm_env/_metadata.py",
],
visibility = ["//visibility:public"],
deps = [
"@dm_env_archive//:specs",
],
)
py_library(
name = "specs",
srcs = [
"dm_env/specs.py",
],
visibility = ["//visibility:public"],
)
py_library(
name = "test_utils",
srcs = [
"dm_env/_abstract_test_mixin.py",
"dm_env/test_utils.py",
],
deps = [
requirement("dm-tree"),
],
visibility = ["//visibility:public"],
)
================================================
FILE: bazel/BUILD.dm_env_rpc
================================================
load("@com_github_grpc_grpc//bazel:python_rules.bzl", "py_proto_library")
licenses(["notice"])
proto_library(
name = "dm_env_rpc_proto",
srcs = ["dm_env_rpc/v1/dm_env_rpc.proto"],
visibility = ["//visibility:public"],
deps = [
"@com_google_googleapis//google/rpc:status_proto",
"@com_google_protobuf//:any_proto",
],
)
cc_proto_library(
name = "dm_env_rpc_cc_proto",
visibility = ["//visibility:public"],
deps = [":dm_env_rpc_proto"],
)
py_proto_library(
name = "dm_env_rpc_pb2",
deps = ["@dm_env_rpc_archive//:dm_env_rpc_proto"],
)
py_proto_library(
name = "status_pb2",
deps = ["@com_google_googleapis//google/rpc:status_proto"],
)
py_library(
name = "dm_env_rpc",
srcs = glob(["dm_env_rpc/**/*.py"]),
visibility = ["//visibility:public"],
deps = [
":dm_env_rpc_pb2",
":status_pb2",
],
)
================================================
FILE: bazel/BUILD.s2protocol
================================================
licenses(["notice"])
py_library(
name = "s2protocol",
srcs = [
"s2protocol/__init__.py",
"s2protocol/attributes.py",
"s2protocol/build.py",
"s2protocol/compat.py",
"s2protocol/decoders.py",
"s2protocol/encoders.py",
"s2protocol/namespaces.py",
],
visibility = ["//visibility:public"],
)
py_library(
name = "versions",
srcs = glob(["s2protocol/versions/*.py"]) + ["s2protocol/__init__.py"],
visibility = ["//visibility:public"],
deps = [":s2protocol"],
)
================================================
FILE: bazel/create_external_repos.bzl
================================================
# Copyright 2021 DeepMind Technologies Ltd. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS-IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Creates external repos needed by PySC2 and by its consumers."""
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
def pysc2_create_external_repos(pysc2_repo_name):
"""Creates external repos needed by PySC2 and by its consumers.
Args:
pysc2_repo_name: The name of the PySC2 repo, as instantiated in
the local WORKSPACE. When executing this function from the pysc2
WORKSPACE, this name is "pysc2". But external consumers shouldn't
use that name as it leads to Python import problems due to the
pysc2/pysc2 subdirectory. Hence a name such as "pysc2_archive"
is recommended.
Example:
http_archive(
name = "pysc2_archive",
# ...
)
load("@pysc2_archive//bazel:create_external_repos.bzl",
"pysc2_create_external_repos")
pysc2_create_external_repos(pysc2_repo_name = "pysc2_archive")
"""
if not native.existing_rule("absl_py"):
# It is important that this isn't named simply 'absl' as the project has a
# subdirectory named that, and Python module lookup fails if we have absl/absl.
http_archive(
name = "absl_py",
strip_prefix = "abseil-py-main",
urls = ["https://github.com/abseil/abseil-py/archive/main.zip"],
)
# Required by glog.
if not native.existing_rule("com_github_gflags_gflags"):
http_archive(
name = "com_github_gflags_gflags",
sha256 = "34af2f15cf7367513b352bdcd2493ab14ce43692d2dcd9dfc499492966c64dcf",
strip_prefix = "gflags-2.2.2",
urls = [
"https://github.com/gflags/gflags/archive/v2.2.2.tar.gz",
],
)
if not native.existing_rule("glog"):
http_archive(
name = "glog",
sha256 = "6281aa4eeecb9e932d7091f99872e7b26fa6aacece49c15ce5b14af2b7ec050f",
urls = [
"https://github.com/google/glog/archive/96a2f23dca4cc7180821ca5f32e526314395d26a.zip",
],
strip_prefix = "glog-96a2f23dca4cc7180821ca5f32e526314395d26a",
)
if not native.existing_rule("com_google_protobuf"):
http_archive(
name = "com_google_protobuf",
patches = ["@" + pysc2_repo_name + "//bazel:protobuf.patch"],
urls = ["https://github.com/protocolbuffers/protobuf/archive/refs/tags/v3.19.1.zip"],
strip_prefix = "protobuf-3.19.1",
)
if not native.existing_rule("com_google_googleapis"):
http_archive(
name = "com_google_googleapis",
sha256 = "1f742f6cafe616fe73302db010e0b7ee6579cb1ce06010427b7d0995cbd80ce4",
strip_prefix = "googleapis-6a813acf535e4746fa4a135ce23547bb6425c26d",
urls = [
"https://github.com/googleapis/googleapis/archive/6a813acf535e4746fa4a135ce23547bb6425c26d.tar.gz",
],
)
if not native.existing_rule("pybind11_bazel"):
http_archive(
name = "pybind11_bazel",
strip_prefix = "pybind11_bazel-master",
urls = ["https://github.com/pybind/pybind11_bazel/archive/refs/heads/master.zip"],
)
if not native.existing_rule("pybind11"):
http_archive(
name = "pybind11",
build_file = "@pybind11_bazel//:pybind11.BUILD",
strip_prefix = "pybind11-2.8.1",
urls = ["https://github.com/pybind/pybind11/archive/v2.8.1.tar.gz"],
)
if not native.existing_rule("s2client_proto"):
http_archive(
name = "s2client_proto",
urls = ["https://github.com/Blizzard/s2client-proto/archive/refs/heads/master.zip"],
strip_prefix = "s2client-proto-master",
patches = ["@" + pysc2_repo_name + "//bazel:s2clientprotocol.patch"],
)
if not native.existing_rule("s2protocol_archive"):
http_archive(
name = "s2protocol_archive",
urls = ["https://github.com/Blizzard/s2protocol/archive/refs/heads/master.zip"],
strip_prefix = "s2protocol-master",
build_file = "@" + pysc2_repo_name + "//bazel:BUILD.s2protocol",
)
if not native.existing_rule("dm_env_archive"):
# We can't use the wheels for dm_env because that pulls in
# proto code which leads to incompatibilities with our our protos.
http_archive(
name = "dm_env_archive",
urls = ["https://github.com/deepmind/dm_env/archive/refs/heads/master.zip"],
strip_prefix = "dm_env-master",
build_file = "@" + pysc2_repo_name + "//bazel:BUILD.dm_env",
)
if not native.existing_rule("dm_env_rpc_archive"):
# We can't use the wheels for dm_env_rpc because that pulls in
# proto code which leads to incompatibilities with our our protos.
http_archive(
name = "dm_env_rpc_archive",
urls = ["https://github.com/deepmind/dm_env_rpc/archive/refs/heads/master.zip"],
strip_prefix = "dm_env_rpc-master",
build_file = "@" + pysc2_repo_name + "//bazel:BUILD.dm_env_rpc",
)
if not native.existing_rule("com_github_grpc_grpc"):
http_archive(
name = "com_github_grpc_grpc",
strip_prefix = "grpc-master",
urls = ["https://github.com/grpc/grpc/archive/refs/heads/master.zip"],
)
================================================
FILE: bazel/protobuf.patch
================================================
--- BUILD
+++ BUILD
@@ -889,6 +889,8 @@
"//conditions:default": [],
":use_fast_cpp_protos": ["//external:python_headers"],
}),
+
+ visibility = ["//visibility:public"],
)
config_setting(
================================================
FILE: bazel/requirements.txt
================================================
deepdiff
dm-tree
mock
mpyq
numpy>=1.10.0
portpicker>=1.2.0
psutil
pygame
requests
s2protocol
sk-video
typing-extensions
websocket-client
================================================
FILE: bazel/s2clientprotocol.patch
================================================
+++ s2clientprotocol/BUILD 2021-11-18 12:14:07.885666323 +0000
@@ -0,0 +1,255 @@
+load("@com_github_grpc_grpc//bazel:python_rules.bzl", "py_proto_library")
+
+package(default_visibility = ["//visibility:public"])
+
+proto_library(
+ name = "common_proto",
+ srcs = ["common.proto"],
+)
+
+cc_proto_library(
+ name = "common_cc_proto",
+ deps = [":common_proto"],
+)
+
+py_proto_library(
+ name = "common_pb2",
+ deps = [":common_proto"],
+)
+
+py_library(
+ name = "common_py_pb2",
+ deps = [":common_pb2"],
+)
+
+proto_library(
+ name = "data_proto",
+ srcs = ["data.proto"],
+ deps = [":common_proto"],
+)
+
+cc_proto_library(
+ name = "data_cc_proto",
+ deps = [":data_proto"],
+)
+
+py_proto_library(
+ name = "data_pb2",
+ deps = [":data_proto"],
+)
+
+py_library(
+ name = "data_py_pb2",
+ deps = [
+ ":common_pb2",
+ ":data_pb2",
+ ],
+)
+
+proto_library(
+ name = "debug_proto",
+ srcs = ["debug.proto"],
+ deps = [":common_proto"],
+)
+
+cc_proto_library(
+ name = "debug_cc_proto",
+ deps = [":debug_proto"],
+)
+
+py_proto_library(
+ name = "debug_pb2",
+ deps = [":debug_proto"],
+)
+
+py_library(
+ name = "debug_py_pb2",
+ deps = [
+ ":common_pb2",
+ ":debug_pb2",
+ ],
+)
+
+proto_library(
+ name = "error_proto",
+ srcs = ["error.proto"],
+)
+
+cc_proto_library(
+ name = "error_cc_proto",
+ deps = [":error_proto"],
+)
+
+py_proto_library(
+ name = "error_pb2",
+ deps = [":error_proto"],
+)
+
+py_library(
+ name = "error_py_pb2",
+ deps = [
+ ":error_pb2",
+ ],
+)
+
+proto_library(
+ name = "query_proto",
+ srcs = ["query.proto"],
+ deps = [
+ ":common_proto",
+ ":error_proto",
+ ],
+)
+
+cc_proto_library(
+ name = "query_cc_proto",
+ deps = [":query_proto"],
+)
+
+py_proto_library(
+ name = "query_pb2",
+ deps = [":query_proto"],
+)
+
+py_library(
+ name = "query_py_pb2",
+ deps = [
+ ":common_pb2",
+ ":error_pb2",
+ ":query_pb2",
+ ],
+)
+
+proto_library(
+ name = "raw_proto",
+ srcs = ["raw.proto"],
+ deps = [":common_proto"],
+)
+
+cc_proto_library(
+ name = "raw_cc_proto",
+ deps = [":raw_proto"],
+)
+
+py_proto_library(
+ name = "raw_pb2",
+ deps = [":raw_proto"],
+)
+
+py_library(
+ name = "raw_py_pb2",
+ deps = [
+ ":common_pb2",
+ ":raw_pb2",
+ ],
+)
+
+proto_library(
+ name = "sc2api_proto",
+ srcs = ["sc2api.proto"],
+ deps = [
+ ":common_proto",
+ ":data_proto",
+ ":debug_proto",
+ ":error_proto",
+ ":query_proto",
+ ":raw_proto",
+ ":score_proto",
+ ":spatial_proto",
+ ":ui_proto",
+ ],
+)
+
+cc_proto_library(
+ name = "sc2api_cc_proto",
+ deps = [":sc2api_proto"],
+)
+
+py_proto_library(
+ name = "sc2api_pb2",
+ deps = [":sc2api_proto"],
+)
+
+py_library(
+ name = "sc2api_py_pb2",
+ deps = [
+ ":common_pb2",
+ ":data_pb2",
+ ":debug_pb2",
+ ":error_pb2",
+ ":query_pb2",
+ ":raw_pb2",
+ ":sc2api_pb2",
+ ":score_pb2",
+ ":spatial_pb2",
+ ":ui_pb2",
+ ],
+)
+
+proto_library(
+ name = "score_proto",
+ srcs = ["score.proto"],
+)
+
+cc_proto_library(
+ name = "score_cc_proto",
+ deps = [":score_proto"],
+)
+
+py_proto_library(
+ name = "score_pb2",
+ deps = [":score_proto"],
+)
+
+py_library(
+ name = "score_py_pb2",
+ deps = [
+ ":score_pb2",
+ ],
+)
+
+proto_library(
+ name = "spatial_proto",
+ srcs = ["spatial.proto"],
+ deps = [":common_proto"],
+)
+
+cc_proto_library(
+ name = "spatial_cc_proto",
+ deps = [":spatial_proto"],
+)
+
+py_proto_library(
+ name = "spatial_pb2",
+ deps = [":spatial_proto"],
+)
+
+py_library(
+ name = "spatial_py_pb2",
+ deps = [
+ ":common_pb2",
+ ":spatial_pb2",
+ ],
+)
+
+proto_library(
+ name = "ui_proto",
+ srcs = ["ui.proto"],
+)
+
+cc_proto_library(
+ name = "ui_cc_proto",
+ deps = [":ui_proto"],
+)
+
+py_proto_library(
+ name = "ui_pb2",
+ deps = [":ui_proto"],
+)
+
+py_library(
+ name = "ui_py_pb2",
+ deps = [
+ ":ui_pb2",
+ ],
+)
+++ WORKSPACE 2021-11-18 12:14:07.885666323 +0000
@@ -0,0 +1,21 @@
+workspace(name = "s2client-proto")
+
+load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")
+
+# The protobuf library, for protoc.
+git_repository(
+ name = "com_google_protobuf",
+ remote = "https://github.com/protocolbuffers/protobuf",
+ branch = "master",
+)
+load("@com_google_protobuf//:protobuf_deps.bzl", "protobuf_deps")
+protobuf_deps()
+
+# GRPC, for the py_proto_library rule.
+git_repository(
+ name = "com_github_grpc_grpc",
+ remote = "https://github.com/grpc/grpc.git",
+ branch = "master",
+)
+load("@com_github_grpc_grpc//bazel:grpc_deps.bzl", "grpc_deps")
+grpc_deps()
================================================
FILE: bazel/setup_external_repos.bzl
================================================
# Copyright 2021 DeepMind Technologies Ltd. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS-IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Sets up external repos needed by PySC2 and by its consumers."""
load("@com_google_googleapis//:repository_rules.bzl", "switched_rules_by_language")
load("@com_github_grpc_grpc//bazel:grpc_deps.bzl", "grpc_deps")
load("@com_google_protobuf//:protobuf_deps.bzl", "protobuf_deps")
load("@pybind11_bazel//:python_configure.bzl", "python_configure")
def pysc2_setup_external_repos():
"""Sets up external repos needed by PySC2 and by its consumers.
Ideally these would happen as part of pysc2_deps, but load statements are
only permitted at the top level currently, necessitating this workaround.
"""
protobuf_deps()
switched_rules_by_language(
name = "com_google_googleapis_imports",
cc = True,
python = True,
)
python_configure(name = "local_config_python")
grpc_deps()
================================================
FILE: docs/bazel.md
================================================
# Building with Bazel
Prior to the inclusion of C++ code it was sufficient to install the
[pip](https://pypi.org/project/pip/) dependencies of PySC2 and to execute the
Python code directly using the Python interpreter. This is still possible if
installing from a [wheel](https://pypi.org/project/wheel/) with a pre-built
distribution matching the platform on which you are running, else when not
referencing any of the C++ code. Where that is not the case, or where you would
like to make changes to the C++ code, a build system becomes necessary. We
support the use of [Bazel](https://bazel.build/), Google's open-source build
tool, for this purpose.
## Supported platforms
We support building with Bazel on Ubuntu Linux with C++ 17. In future we may
support other platforms, should there be demand.
## Example
First of all,
[get Bazel](https://docs.bazel.build/versions/main/install-ubuntu.html). Next,
you may need the Python development environment.
```shell
$ sudo apt update
$ sudo apt install python3 python3-dev python3-venv
```
Build all PySC2 targets (from the workspace root).
```shell
$ bazel build --cxxopt='-std=c++17' ...
```
Run some tests.
```shell
$ bazel test --cxxopt='-std=c++17' pysc2/lib/...
```
Beyond that, everything should be the same as running Python directly as
described in the readme, only rather than using the Python interpreter you use
Bazel to run. For instance...
```shell
$ python -m pysc2.bin.agent --map Simple64
```
becomes...
```shell
$ bazel run --cxxopt='-std=c++17' pysc2/bin:agent -- --map Simple64
```
You may wish to use a [.bazelrc file](https://docs.bazel.build/versions/main/guide.html#bazelrc-the-bazel-configuration-file) to avoid the need to repeatedly specify command-line options, for instance `--cxxopt='-std=c++17'`.
================================================
FILE: docs/converters.md
================================================
# Environment converters
## Overview
The SC2 API uses protos to communicate actions to and observations from the
environment. `sc2_env.py` contains code to marshall between these protos and a
more neural network friendly dictionary of numpy arrays, with accompanying
environment specs. During development of AlphaStar this code was translated to
C++, and new features added. This code is now available in PySC2. See
`converter.cc`, `converter.py`, `converted_env.py`, `replay_converter.py`, for
instance.
Converters are instantiated per-agent, per-episode. They are configurable via
the `ConverterSettings` proto; see `converter.proto`. Though they can be used
directly, it is more typical to use them as part of an environment wrapper
(`converted_env.py`), or via the replay conversion code (`replay_converter.py`).
Note that converters don't have to be used from Python. The C++ code is wrapped
using [pybind11](https://github.com/pybind/pybind11), but may also be used
directly.
Note also that, because converters are implemented in C++, changes to them
require compilation. See [this page](bazel.md) for further information.
## Supported platforms
Use of converters requires either [building with Bazel](bazel.md) or use of an
appropriate pre-built wheel. Only Linux is supported at present.
## Raw mode
If raw settings are provided as part of the converter settings the converter
will operate in raw mode. This mode is so called because it provides raw access
to numerical data, with only limited spatial data for the minimap. Actions are
specified directly for units using their tags. There is support for limiting the
data which the agent receives to the view implied by the current camera
position, similar to how humans perceive the game.
### Action spec
name | shape | dtype | min | max | enabled?
--------------- | -------------------------------- | ----- | --- | ------------------------------------------- | --------
function | () | int32 | 0 | `num_action_types` | always
delay | () | int32 | 1 | 127 | always
queued | () | int32 | 0 | 1 | always
repeat | () | int32 | 0 | 2 | `raw.enable_action_repeat`
target_unit_tag | () | int32 | 0 | `raw.max_unit_count` - 1 | always
unit_tags | (`raw.max_unit_selection_size`,) | int32 | 0 | `raw.max_unit_count` | always
world | () | int32 | 0 | `raw.resolution.x` * `raw.resolution.y` - 1 | always
### Observation spec
name | shape | dtype | min | max | enabled?
------------------------------ | ------------------------------------------- | ----- | --------- | ------------------------------------------- | --------
action/function | () | int32 | 0 | `num_action_types` | `supervised`
action/delay | () | int32 | 1 | 127 | `supervised`
action/queued | () | int32 | 0 | 1 | `supervised`
action/repeat | () | int32 | 0 | 2 | `supervised` and `raw.enable_action_repeat`
action/target_unit_tag | () | int32 | 1 | `raw.max_unit_count` - 1 | `supervised`
action/unit_tags | (`raw.max_unit_selection_size`,) | int32 | 0 | `raw.max_unit_count` | `supervised`
action/world | () | int32 | 0 | `raw.resolution.x` * `raw.resolution.y` - 1 | `supervised`
away_race_observed | () | int32 | - | - | always
away_race_requested | () | int32 | - | - | always
camera | (`raw.resolution.x`, `raw.resolution.y`) | int32 | 0 | 1 | `raw.camera`
camera_position | (2,) | int32 | - | - | `raw.use_camera_position`
camera_size | (2,) | int32 | - | - | `raw.use_camera_position`
game_loop | () | int32 | - | - | always
home_race_requested | () | int32 | - | - | always
minimap_alerts | (`minimap.x`, `minimap.y`) | uint8 | 0 | 1 | 'alerts' in `minimap features`
minimap_buildable | (`minimap.x`, `minimap.y`) | uint8 | 0 | 1 | 'buildable' in `minimap features`
minimap_creep | (`minimap.x`, `minimap.y`) | uint8 | 0 | 1 | 'creep' in `minimap features`
minimap_height_map | (`minimap.x`, `minimap.y`) | uint8 | 0 | 255 | 'height_map' in `minimap features`
minimap_pathable | (`minimap.x`, `minimap.y`) | uint8 | 0 | 1 | 'pathable' in `minimap features`
minimap_player_relative | (`minimap.x`, `minimap.y`) | uint8 | 0 | 4 | 'player_relative' in `minimap features`
minimap_visibility_map | (`minimap.x`, `minimap.y`) | uint8 | 0 | 3 | 'visibility_map' in `minimap features`
mmr | () | int32 | - | - | always
opponent_player | (10,) | int32 | - | - | `add_opponent_features`
opponent_unit_counts_bow | (`num_unit_types`,) | int32 | - | - | `add_opponent_features`
opponent_upgrades_fixed_length | (`max_num_upgrades`,) | int32 | 0 | `num_upgrade_types + 1` | `add_opponent_features`
player | (11,) | int32 | - | - | always
raw_units | (`max_unit_count`, `num_unit_features` + 2) | int32 | 0 | varies | always
unit_counts_bow | (`num_unit_types`,) | int32 | - | - | always
upgrades_fixed_length | (`max_num_upgrades`,) | int32 | minimum=0 | maximum=`num_upgrade_types` + 1 | always
## Visual mode
If visual settings are provided as part of the converter settings the converter
will operate in visual mode. In this mode the majority of the data provided to
the agent is represented spatially, with planes reflecting the attributes of
units on the screen and minimap. Actions in this mode are more similar to how a
human would interact, point-and-click.
### Action spec
| name | shape | dtype | min | max | enabled? |
| ----------------- | ----- | ----- | --- | ------------------- | -------- |
| function | () | int32 | 0 | `num_action_types` | always |
| build_queue_id | () | int32 | 0 | 9 | always |
| control_group_act | () | int32 | 0 | 4 | always |
| control_group_id | () | int32 | 0 | 9 | always |
| delay | () | int32 | 1 | 127 | always |
| minimap | () | int32 | 0 | `minimap.x` * | always |
: : : : : `minimap.y` - 1 : :
| queued | () | int32 | 0 | 1 | always |
| screen | () | int32 | 0 | `visual.screen.x` * | always |
: : : : : `visual.screen.y` - : :
: : : : : 1 : :
| screen2 | () | int32 | 0 | `visual.screen.x` * | always |
: : : : : `visual.screen.y` - : :
: : : : : 1 : :
| select_add | () | int32 | 0 | 1 | always |
| select_point_act | () | int32 | 0 | 3 | always |
| select_unit_act | () | int32 | 0 | 3 | always |
| select_unit_id | () | int32 | 0 | 499 | always |
| select_worker | () | int32 | 0 | 3 | always |
| unload_id | () | int32 | 0 | 499 | always |
### Observation spec
name | shape | dtype | min | max | enabled?
------------------------------ | -------------------------------------- | ----- | --- | ----------------------------------------- | --------
action/build_queue_id | () | int32 | 0 | 9 | `supervised`
action/control_group_act | () | int32 | 0 | 4 | `supervised`
action/control_group_id | () | int32 | 0 | 9 | `supervised`
action/delay | () | int32 | 1 | 127 | `supervised`
action/function | () | int32 | 0 | `num_action_types` | `supervised`
action/minimap | () | int32 | 0 | `minimap.x` * `minimap.y` - 1 | `supervised`
action/queued | () | int32 | 0 | 1 | `supervised`
action/screen | () | int32 | 0 | `visual.screen.x` * `visual.screen.y` - 1 | `supervised`
action/screen2 | () | int32 | 0 | `visual.screen.x` * `visual.screen.y` - 1 | `supervised`
action/select_add | () | int32 | 0 | 1 | `supervised`
action/select_point_act | () | int32 | 0 | 3 | `supervised`
action/select_unit_act | () | int32 | 0 | 3 | `supervised`
action/select_unit_id | () | int32 | 0 | 499 | `supervised`
action/select_worker | () | int32 | 0 | 3 | `supervised`
action/unload_id | () | int32 | 0 | 499 | `supervised`
available_actions | (`num_action_types`,) | int32 | - | - | always
away_race_observed | () | int32 | - | - | always
away_race_requested | () | int32 | - | - | always
game_loop | () | int32 | | - | -
home_race_requested | () | int32 | - | - | always
minimap_alerts | (`minimap.x`, `minimap.y`) | uint8 | 0 | 1 | 'alerts' in `minimap_features`
minimap_buildable | (`minimap.x`, `minimap.y`) | uint8 | 0 | 1 | 'buildable' in `minimap_features`
minimap_camera | (`minimap.x`, `minimap.y`) | uint8 | 0 | 1 | 'camera' in `minimap_features`
minimap_creep | (`minimap.x`, `minimap.y`) | uint8 | 0 | 1 | 'creep' in `minimap_features`
minimap_height_map | (`minimap.x`, `minimap.y`) | uint8 | 0 | 255 | 'height_map' in `minimap_features`
minimap_pathable | (`minimap.x`, `minimap.y`) | uint8 | 0 | 1 | 'pathable' in `minimap_features`
minimap_player_relative | (`minimap.x`, `minimap.y`) | uint8 | 0 | 4 | 'player_relative' in `minimap_features`
minimap_selected | (`minimap.x`, `minimap.y`) | uint8 | 0 | 1 | 'selected' in `minimap_features`
minimap_visibility_map | (`minimap.x`, `minimap.y`) | uint8 | 0 | 3 | 'visibility_amp' in `minimap_features`
mmr | () | int32 | - | - | always
opponent_player | (10,) | int32 | - | - | `add_opponent_features`
opponent_unit_counts_bow | (217,) | int32 | - | - | `add_opponent_features`
opponent_upgrades_fixed_length | (`max_num_upgrades`,) | int32 | 0 | `num_upgrade_types` - 1 | `add_opponent_features`
player | (11,) | int32 | - | - | always
screen_active | (`visual.screen.x`, `visual.screen.y`) | uint8 | 0 | 1 | 'active' in `visual.screen_features`
screen_blip | (`visual.screen.x`, `visual.screen.y`) | uint8 | 0 | 1 | 'blip' in `visual.screen_features`
screen_buff_duration | (`visual.screen.x`, `visual.screen.y` | uint8 | 0 | 255 | 'buff_duration' in `visual.screen_features`
screen_buffs | (`visual.screen.x`, `visual.screen.y`) | uint8 | 0 | 47 | 'buffs' in `visual.screen_features`
screen_build_progress | (`visual.screen.x`, `visual.screen.y`) | uint8 | 0 | 255 | 'build_progress' in `visual.screen_features`
screen_buildable | (`visual.screen.x`, `visual.screen.y`) | uint8 | 0 | 1 | 'buildable' in `visual.screen_features`
screen_cloaked | (`visual.screen.x`, `visual.screen.y`) | uint8 | 0 | 1 | 'cloaked' in `visual.screen_features`
screen_creep | (`visual.screen.x`, `visual.screen.y`) | uint8 | 0 | 1 | 'creep' in `visual.screen_features`
screen_effects | (`visual.screen.x`, `visual.screen.y`) | uint8 | 0 | 15 | 'effects' in `visual.screen_features`
screen_hallucinations | (`visual.screen.x`, `visual.screen.y`) | uint8 | 0 | 1 | 'hallucinations' in `visual.screen_features`
screen_height_map | (`visual.screen.x`, `visual.screen.y`) | uint8 | 0 | 255 | 'height_map' in `visual.screen_features`
screen_pathable | (`visual.screen.x`, `visual.screen.y`) | uint8 | 0 | 1 | 'pathable' in `visual.screen_features`
screen_player_relative | (`visual.screen.x`, `visual.screen.y`) | uint8 | 0 | 4 | 'player_relative' in `visual.screen_features`
screen_power | (`visual.screen.x`, `visual.screen.y`) | uint8 | 0 | 1 | 'power' in `visual.screen_features`
screen_selected | (`visual.screen.x`, `visual.screen.y`) | uint8 | 0 | 1 | 'selected' in `visual.screen_features`
screen_unit_density_aa | (`visual.screen.x`, `visual.screen.y`) | uint8 | 0 | 255 | 'unit_density_aa' in `visual.screen_features`
screen_unit_energy_ratio | (`visual.screen.x`, `visual.screen.y`) | uint8 | 0 | 255 | 'unit_energy_ratio' in `visual.screen_features`
screen_unit_hit_points_ratio | (`visual.screen.x`, `visual.screen.y`) | uint8 | 0 | 255 | 'unit_hit_points_ratio' in `visual.screen_features`
screen_unit_shields_ratio | (`visual.screen.x`, `visual.screen.y`) | uint8 | 0 | 255 | 'unit_shields_ratio' in `visual.screen_features`
screen_unit_type | (`visual.screen.x`, `visual.screen.y`) | uint8 | 0 | `num_unit_types` | 'unit_type' in `visual.screen_features`
screen_visibility_map | (`visual.screen.x`, `visual.screen.y`) | uint8 | 0 | 3 | 'visibility_map' in `visual.screen_features`
unit_counts_bow | (`num_unit_types`,) | int32 | - | - | always
upgrades_fixed_length | (`max_num_upgrades`,) | int32 | 0 | `num_upgrade_types`-1 | always
================================================
FILE: docs/environment.md
================================================
## Environment Table of Contents
- [Starcraft II](#starcraft-ii)
- [What is StarCraft II](#what-is-starcraft-ii)
- [Versions](#versions)
- [Game and Action Speed](#game-and-action-speed)
- [Game speed](#game-speed)
- [APM Calculation](#apm-calculation)
- [APM and fairness](#apm-and-fairness)
- [Determinism and Randomness](#determinism-and-randomness)
- [Actions and Observations](#actions-and-observations)
- [Observation](#observation)
- [Spatial/Visual](#spatialvisual)
- [RGB Pixels](#rgb-pixels)
- [Feature layers](#feature-layers)
- [Minimap](#minimap)
- [Screen](#screen)
- [Structured](#structured)
- [General player information](#general-player-information)
- [Control groups](#control-groups)
- [Single Select](#single-select)
- [Multi Select](#multi-select)
- [Cargo](#cargo)
- [BuildQueue](#build-queue)
- [AvailableActions](#available-actions)
- [LastActions](#last-actions)
- [ActionsResult](#action-result)
- [Alerts](#alerts)
- [Actions](#actions)
- [List of actions](#list-of-actions)
- [Action categories](#action-categories)
- [General vs Specific actions](#general-vs-specific-actions)
- [Example usage](#example-usage)
- [RL Environment](#rl-environment)
- [Environment wrappers](#environment-wrappers)
- [Agents](#agents)
<!-- /TOC -->
## StarCraft II
### What is StarCraft II
[StarCraft II](https://en.wikipedia.org/wiki/StarCraft_II:_Legacy_of_the_Void)
is a [Real Time Strategy
(RTS)](https://en.wikipedia.org/wiki/Real-time_strategy) game written by
[Blizzard](http://blizzard.com/). It's the successor to [StarCraft
Broodwar](https://en.wikipedia.org/wiki/StarCraft:_Brood_War), which is one of
the most successful RTS games. StarCraft II is played by millions of people, and
has a [professional league](https://wcs.starcraft2.com/en-us/).
The [goal in StarCraft](http://us.battle.net/sc2/en/game/guide/whats-sc2) is to
build a base, manage an economy, build an army, and destroy your enemies. You
control your base and army from a third person perspective, then multi-task and
micro-manage your units for maximum effect. StarCraft has 3 distinct races:
[Terran](https://www.youtube.com/watch?v=Fmu8PsUDDtQ),
[Protoss](https://www.youtube.com/watch?v=m0g0MpllFCs) and
[Zerg](https://www.youtube.com/watch?v=Lq74R7wWAnQ), which have different units
and strategies.
The game has a single player campaign, though most people play multiplayer on
[Battle.net](http://battle.net/sc2/en/). There are built-in bots, but they are
fairly weak and predictable, and the stronger ones cheat.
There are many resources online for learning about Starcraft, including
[Battle.net](http://battle.net/sc2/en/),
[Liquipedia](http://liquipedia.net/starcraft2/StarCraft) and
[Wikia](http://starcraft.wikia.com/). For map making check out
[SC2Mapster](https://sc2mapster.gamepedia.com/SC2Mapster_Wiki).
### Versions
Blizzard regularly updates StarCraft II. These updates are roughly monthly, can
introduce new features, and often have minor gameplay and balance changes to
make the races more even. Replays are tied to the specific version they were
generated with.
### Game and Action Speed
Being a real-time strategy game means the game runs in real-time. In reality
though, the simulation updates 16-22 times per second, depending on your [game
speed](http://wiki.teamliquid.net/starcraft2/Game_Speed), and all the
intermediate rendered frames are just interpolated.
#### Game speed
Acting through an API allows you to control the clock. Instead of running at
16-22 steps per second, you can step as fast or as slow as you want, when you
want. This allows you to run much faster than real-time if the agent is capable,
or much slower if the agent needs to pause to spend some time learning. This
also means there is never any lag. The max speed depends on the step_mul/render
frequency, and the scene complexity/unit count. 10x real-time is not uncommon
and can be much higher for simple maps.
#### APM Calculation
The game calculates and reports APM in a non-obvious way. It isn't obvious how
to count the action of moving the camera with edge scrolling, or how many
actions is building a building. Here are the rules of how it's actually counted
by the game.
There are actually two types reported by the game:
* Actions Per Minute (APM): counts every action.
* Effective Actions Per Minute (EPM): filters out actions that have no effect
(eg: redundant selections).
Different actions count as different number of actions:
* Commands with target = 2 (eg: move, attack, build building)
* Commands with no target = 1 (eg: stop, train unit, unload cargo)
* Smart = 1 (right click)
* Selection and control groups = 1
* Everything else = 0 (eg: camera movement)
The in game replay UI exposes this with two different time intervals: average
(average over the entire game so far), and current (average over the last 5
seconds). The API only exposes the average APM.
#### APM and fairness
Humans can't do one action per frame. They range from 30-500 actions per minute
(APM), with 30 being a beginner, 60-100 being average, and professionals
being >200 (over 3 per second!). This is trivial compared to what a fast bot is
capable of though. With the [BWAPI](http://bwapi.github.io/) they control units
individually and routinely go over 5000 APM accomplishing things that are
clearly impossible for humans and considered
[unfair](https://youtu.be/IKVFZ28ybQs?t=45s) or even
[broken](https://youtu.be/0EYH-csTttw?t=28s). Even without controlling the units
individually it would be unfair to be able to act much faster with high
precision.
To at least resemble playing fairly it is a good idea to artificially limit the
APM. The easy way is to limit how often the agent gets observations and can make
an action, and limit it to one action per observation. For example you can do
this by only taking every `N`th observation, where `N` is up for debate. A value
of 20 is roughly equal to 50 apm while 5 is roughly 200 apm, so that's a
reasonable range to play with. A more sophisticated way is to give the agent
every observation but limit the number of actions that actually have an effect,
forcing it to mainly make no-ops which wouldn't count as actions.
It's probably better to consider all actions as equivalent, including camera
movement, since allowing very fast camera movement could allow agents to cheat.
### Determinism and Randomness
Starcraft II is mostly deterministic, but it does have some randomness mainly
for cosmetic reasons. The two main random elements are weapon speed and update
order.
Weapon randomness is essentially how fast a unit can get its next shot off after
firing and is between -1 to +2 game steps for almost all units. The idea
being that a group of marines may all start firing together, but the minor
random +/- for the next shot will make the group look less robotic and prevent
them from firing in sync forever. This also means a fair matchup (eg 1v1 marine)
will result in a random outcome.
The update order is random and determines the order of events in a given game
loop. For example, if you have two High Templar that cast feedback on each other
on the same game loop, it will be random which one performs the damage first and
wins.
Unit auto-targeting is deterministic, but complicated. It is based on weapon
scan distance, threat and assistance. Units will consider any enemies with
weapon a higher threat than those without, and enemies that can return fire will
be a higher priority than those that can’t return fire. Units that can't return
fire (eg a missile turret vs a marine) but that are attacking an allied unit (eg
a medivac) will trigger a call for help and increase the priority. A healer
raises its priority when it is healing. If two targets have the same priority
the nearest one will be chosen.
These sources of randomness can be removed/mitigated by setting a random seed.
Replays work by saving the game setup including the random seed, as well as the
list of actions by all players, and then playing forward the simulation.
## Actions and Observations
Starcraft II has a very rich action and observation space. The game outputs
both spatial/visual and structured elements. The structured elements are given
because there is a lot of text and numbers which agents aren't expected to learn
to read, especially at low resolution. It's also because it's hard to reverse
replays back to exactly the same visuals that the human saw.
__Important Note:__
Spatial observations are in y-major screen coordinate space as `(y, x)`. Actions
that require points on the screen or the minimap, however, expect the
coordinates as `(x, y)`. The origin `(0, 0)` is at the top-left corner in both
cases.
See the [scripted agents](../pysc2/agents/scripted_agent.py) for an example of
passing a screen coordinate to an action:
```python
# Spatial observations have the y-coordinate first:
y, x = (obs.observation["feature_screen"][_PLAYER_RELATIVE] == _PLAYER_NEUTRAL).nonzero()
# Actions expect x-coordinate first:
target = [int(x.mean()), int(y.mean())]
action = actions.FunctionCall.Move_screen("now", target)
```
### Observation
#### Spatial/Visual
##### RGB Pixels
RGB pixels are available for both the main screen area as well as for the
minimap at a resolution of your choice. This uses the same perspective camera as
a human would see, but doesn't include all the extra chrome around the screen
like the command card, selection box, build queue, etc. They are exposed as
`rgb_screen` and `rgb_minimap`.
##### Feature layers
The game also exposes feature layers. They represent roughly the same
information as RGB pixels except that the information is decomposed and
structured. There are ~25 feature layers broken down between the screen and
minimap and exposed as `feature_screen` and `feature_minimap`.
The full list is defined in `pysc2.lib.features`.
###### Minimap
The minimap is a low resolution view of the entire map. It gives an overview of
everything going on, but with less detail than the screen.
You can specify the resolution of the minimap. Maps range from
32-256<sup>2</sup>, with common human maps in the 100-256<sup>2</sup> range.
Humans playing at 1080p get a resolution of ~250<sup>2</sup> in the bottom left
corner of their screen.
These are the minimap feature layers:
* **height_map**: Shows the terrain levels.
* **visibility**: Which part of the map are hidden, have been seen or are
currently visible.
* **creep**: Which parts have zerg creep.
* **camera**: Which part of the map are visible in the screen layers.
* **player_id**: Who owns the units, with absolute ids.
* **player_relative**: Which units are friendly vs hostile. Takes values in
[0, 4], denoting [background, self, ally, neutral, enemy] units
respectively.
* **selected**: Which units are selected.
###### Screen
The screen is a higher resolution view of part of the map.
It is rendered from a top down orthogonal camera, as opposed to a perspective
camera that a human would get in a real game. This makes certain visuals harder
(eg you can't see elevation by size), but it also makes other things easier (eg
units don't change size as they or the camera moves). This also means that the
visible area is a rectangular part of the map, as opposed to the more
trapezoidal shape in the real game. This means there are bits of the map that an
agent can see that humans can't, and vice versa, but it is roughly similar.
A small unit (eg marine or zergling) is ~0.75 game units across. The camera is
24 game units wide. If you specify a screen resolution of 32<sup>2</sup>, that
means a unit will be 1 pixel wide, meaning you have very low accuracy of its
location. If you have a large group of them you may not be able to tell how many
of them you have. A resolution of at least 64<sup>2</sup> is recommended to be
playable.
These are the screen feature layers:
* **height_map**: Shows the terrain levels.
* **visibility**: Which part of the map are hidden, have been seen or are
currently visible.
* **creep**: Which parts have zerg creep.
* **power**: Which parts have protoss power, only shows your power.
* **player_id**: Who owns the units, with absolute ids.
* **player_relative**: Which units are friendly vs hostile. Takes values in
[0, 4], denoting [background, self, ally, neutral, enemy] units
respectively.
* **unit_type**: A unit type id, which can be looked up in pysc2/lib/units.py.
* **selected**: Which units are selected.
* **hit_points**: How many hit points the unit has.
* **energy**: How much energy the unit has.
* **shields**: How much shields the unit has. Only for protoss units.
* **unit_density**: How many units are in this pixel.
* **unit_density_aa**: An anti-aliased version of unit_density with a maximum
of 16 per unit per pixel. This gives you sub-pixel unit location and size.
For example if a unit is exactly 1 pixel diameter, `unit_density` will show
it in exactly 1 pixel regardless of where in that pixel it is actually
centered. `unit_density_aa` will instead tell you how much of each pixel is
covered by the unit. A unit that is smaller than a pixel and centered in the
pixel will give a value less than the max. A unit with diameter 1 centered
near the corner of a pixel will give roughly a quarter of its value to each
of the 4 pixels it covers. If multiple units cover a pixel their proportion
of the pixel covered will be summed, up to a max of 256.
#### Structured
The game offers a fair amount of structured data which agents aren't expected
to read from pixels. Instead these are given as tensors with direct semantic
meaning.
##### General player information
A `(11)` tensor showing general information.
* player_id
* minerals
* vespene
* food used (otherwise known as supply)
* food cap
* food used by army
* food used by workers
* idle worker count
* army count
* warp gate count (for protoss)
* larva count (for zerg)
##### Control groups
A `(10, 2)` tensor showing the (unit leader type and count) for each of the 10
control groups. The indices in this tensor are referenced by the `control-group`
action.
[Control groups](http://learningsc2.com/tag/control-groups/) are a way to
remember a selection set so that you can recall them easily later.
##### Single Select
A `(7)` tensor showing information about a selected unit.
* unit type
* player_relative
* health
* shields
* energy
* transport slot taken if it's in a transport
* build progress as a percentage if it's still being built
##### Multi Select
A `(n, 7)` tensor with the same as [single select](#single-select) but for all
`n` selected units. The indices in this tensor are referenced by the
`select_unit` action.
##### Cargo
A `(n, 7)` tensor similar to [single select](#single-select), but for all the
units in a transport. The indices in this tensor are referenced by the `unload`
action.
##### Build Queue
A `(n, 7)` tensor similar to [single select](#single-select), but for all the
units being built by a production building. The indices in this tensor are
referenced by the `build_queue` action.
##### Available Actions
A `(n)` tensor listing all the action ids that are available at the time of this
observation.
##### Last Actions
A `(n)` tensor listing all the action ids that were made successfully since the
last observation. An action that was attempted but failed is not included here.
##### Action Result
A `(n)` tensor (usually size 1) giving the result of the action. The values are
listed in
[error.proto](https://github.com/Blizzard/s2client-proto/blob/master/s2clientprotocol/error.proto)
##### Alerts
A `(n)` tensor (usually empty, occasionally size 1, max 2) for when you're being attacked in a major way.
### Actions
The SC2 action space is very big. There are hundreds of possible actions, many
of which take a point in either screen or minimap space, and many of which take
an additional modifier. If you were to flatten the action space into a single
dimension, it'd have millions or even billions of possible actions, most of
which aren't valid, and many of which are highly correlated. Therefore, a flat
discrete action space is not very appropriate.
Instead, we created function actions that are rich enough to give
composability, without the complexity of an arbitrary hierarchy. This is based
on the mental model of a C-style function call which can take some arguments of
specific types. The full set of valid types and functions are defined in
`ValidActions` in `pysc2.lib.actions`, and then each observation specifies which
of the available function is valid this frame. Each action is a single
`FunctionCall` in `pysc2.lib.actions` with all its arguments filled.
The full set of types and functions are defined in `pysc2.lib.actions`. The set
of functions is hard coded and limited to just the actions that humans have
taken, as seen by a large number of replays. Hard coding the functions means
that actions created in custom maps won't be usable until they are added to
`pysc2.lib.actions`.
The semantic meaning of these actions can mainly be found by searching:
[liquipedia.net/starcraft2](http://liquipedia.net/starcraft2/) or
[starcraft.wikia](http://starcraft.wikia.com/).
#### List of actions
To see which actions exist run:
```shell
$ python -m pysc2.bin.valid_actions
```
optionally with `--hide_specific`, `--screen_resolution` or
`--minimap_resolution` if you care about the exact values. This prints something
similar to:
```
0/no_op ()
1/move_camera (1/minimap [64, 64])
2/select_point (6/select_point_act [4]; 0/screen [84, 84])
3/select_rect (7/select_add [2]; 0/screen [84, 84]; 2/screen2 [84, 84])
4/select_control_group (4/control_group_act [5]; 5/control_group_id [10])
5/select_unit (8/select_unit_act [4]; 9/select_unit_id [500])
6/select_idle_worker (10/select_worker [4])
7/select_army (7/select_add [2])
8/select_warp_gates (7/select_add [2])
9/select_larva ()
10/unload (12/unload_id [500])
11/build_queue (11/build_queue_id [10])
12/Attack_screen (3/queued [2]; 0/screen [84, 84])
13/Attack_minimap (3/queued [2]; 1/minimap [64, 64])
14/Attack_Attack_screen (3/queued [2]; 0/screen [84, 84])
19/Scan_Move_screen (3/queued [2]; 0/screen [84, 84])
23/Behavior_CloakOff_quick (3/queued [2])
26/Behavior_CloakOn_quick (3/queued [2])
42/Build_Barracks_screen (3/queued [2]; 0/screen [84, 84])
44/Build_CommandCenter_screen (3/queued [2]; 0/screen [84, 84])
220/Effect_Repair_screen (3/queued [2]; 0/screen [84, 84])
221/Effect_Repair_autocast ()
264/Harvest_Gather_screen (3/queued [2]; 0/screen [84, 84])
303/Morph_Lair_quick (3/queued [2])
317/Morph_SiegeMode_quick (3/queued [2])
322/Morph_Unsiege_quick (3/queued [2])
331/Move_screen (3/queued [2]; 0/screen [84, 84])
333/Patrol_screen (3/queued [2]; 0/screen [84, 84])
405/Research_Stimpack_quick (3/queued [2])
451/Smart_screen (3/queued [2]; 0/screen [84, 84])
452/Smart_minimap (3/queued [2]; 1/minimap [64, 64])
453/Stop_quick (3/queued [2])
477/Train_Marine_quick (3/queued [2])
*** 100s more lines ***
```
This should be read as: `<function id>/<function name>(<type id>/<type name>
[<value size>, *]; *)`.
Some examples:
* `1/move_camera (1/minimap [64, 64])` is the `move_camera` function (id `1`),
which takes one argument named `minimap` (id `1`) which requires two ints
each in the range `[0, 64)` which represent the coordinates on the minimap.
* `331/Move_screen (3/queued [2]; 0/screen [84, 84])` is the `Move_screen`
function (id `331`) which takes two arguments: `queued` (id `3`) which is a
bool and signifies whether this action should happen now or after previous
actions, and `screen` (id `0`) which takes two ints each in the range `[0,
84)` which represent a pixel on the screen.
The function names should be unique, stable and meaningful. The function and
type ids are the index into the list of `functions` and `types`.
The `types` are a predefined list of argument types that can be used in a
function call. The exact definitions are in `pysc2.lib.actions.TYPES`
#### Action categories
A `Morph` action transform a unit to a different unit, at least according to the
unit_type in the observation. For example `Morph_Lair_quick` morphs a hatchery
to a lair; `Morph_SiegeMode_quick` and `Morph_Unsiege_quick` morphs a siege tank
between tank and siege mode. An `Effect` is a single effect, rarely cancelable.
A `Behavior` can be turned on and off but doesn't change the unit type.
#### General vs Specific actions
StarCraft II speaks in terms of abilities. Sometimes a single concept that can
be done by many units is implemented as a single ability (eg Move, Halt,
Patrol), and sometimes as many abilities (eg Attack, Burrow, Cancel, Lift/Land).
`Burrow` is a simple example where each zerg unit that can burrow has its own
ability (`BurrowDown_Drone`, `BurrowDown_Zergling`, etc). Exposing those
individually would make the action space even more complicated, and make it hard
to burrow a whole army at once given a [limited APM](#apm-and-fairness), so we
added a concept of general abilities that merge all of the specific abilities
that would happen together or using the same key in the game UI. If you give the
specific ability (eg `BurrowDown_Zergling`) it'll only affect the specific units
that support that ability (eg Zerglings), while if you give the corresponding
general ability (`BurrowDown`) it'll affect all units that support it.
Attack is a non-obvious case of this. There is `Attack`, which is the general
ability that corresponds to what the UI does, but under the hood that actually
executes `Attack_Attack` for offensive units, `Scan_Move` for support units like
medivacs that can't attack but should come along as if they can,
`Attack_AttackBuilding` for defensive buildings (eg missile turret) and
`Attack_Redirect` for bunkers to tell their loaded units to attack.
For now only the general actions are exposed through the environment api so only
the general actions should be returned in the available actions observation.
In `pysc2.lib.actions.FUNCTIONS` specific functions have an additional parameter
that references the general parameter.
#### Example usage
Take a look at the [random agent](../pysc2/agents/random_agent.py) for an
example of how to consume `ValidActions` and fill `FunctionCall`s.
The following snippet shows how to print a human-readable list of available
actions:
```python
from pysc2.lib import actions
for action in obs.observation.available_actions:
print(actions.FUNCTIONS[action])
```
## RL Environment
The main SC2 environment is at `pysc2.env.sc2_env`, with the action and
observation space defined in `pysc2.lib.features`.
The most important argument is `map_name`, which is how to find the map.
Find the names by using `pysc2.bin.map_list` or by looking in `pysc2/maps/*.py`.
`players` lets your specify the number and type of players. At the moment only
one or two players are supported. Give it a list of `sc2_env.Agent` or
`sc2_env.Bot` objects, specifying the race and difficulty. Specifying two agents
will start up two instances of SC2 which communicate between themselves, and
consume double the memory and cpu as playing single player.
`agent_interface_format` lets you specify the observation and action interface
to be used by each agent. `feature_dimensions` and `rgb_dimensions` let you
specify the resolution of the spatial observations. Higher resolution obviously
gives higher location precision, at the cost of larger observations as well as a
larger action space, and slower rendering time.
If you ask for both feature and rgb observations you'll need to specify the
action space that you want to use. This lets you act in one while learning from
the other.
`step_mul` let's you skip observations and actions. For example a `step_mul` of
16 means that the environment gets stepped forward 16 times in between the
actions of the agent (16 steps = 1 second of game time). It is equivalent to
ignoring certain observations and not sending actions on those frames, except it
also speeds up the environment since it doesn't need to render the skipped
frames.
`save_replay_episodes` and `replay_dir` specify how often to save replays and
where to save them.
Use the `run_loop.py` to have your agent interact with the environment.
### Environment wrappers
There is one pre-made environment wrapper:
* `available_actions_printer`: Prints each available action as it is seen.
## Agents
There are a couple basic agents.
* `random_agent`: Just plays randomly, shows how to make valid moves.
* `scripted_agent`: These are scripted for a single mini game.
================================================
FILE: docs/maps.md
================================================
# StarCraft II Maps
## Map config
SC2Map files are what is used by the SC2 game, but they can be used differently,
and those differences are defined in our map configs. The config gives
information like how long the episodes last, how many players it can play, and
how to score it.
To create your own map config, just subclass the base Map class and override
some of the settings. The most important is to define the directory and filename
for the SC2Map. Any Map subclass will be automatically picked up as long as it's
imported somewhere.
## DeepMind Mini-Games
The [mini-games](mini_games.md) are designed to be single-player, fixed length
and exercise different aspects of the game. They expose a score/reward which
lets the agent know how well it is doing. The score should differentiate poor
agents (eg random) from good agents.
## Ladder
[Ladder maps](http://wiki.teamliquid.net/starcraft2/Maps/Ladder_Maps/Legacy_of_the_Void)
are the maps played by human players on Battle.net. There are just a handful
active at a time. Every few months a new season starts bringing a new set of
maps.
Some of the maps have suffixes LE or TE. LE means Ladder Edition. These are
community maps that were edited by Blizzard for bugs and made ready for the
ladder pool. TE means Tournament Edition. These maps were used in tournaments.
They are all multiplayer maps with fairly long time limits.
## Melee
These are maps made specifically for machine learning. They resemble
ladder maps in format, but may be smaller sizes and aren't necessarily balanced
for high level play.
The **Flat** maps have no special features on the terrain, encouraging easy
attacking. The number specifies the map size.
The **Simple** maps are more normal with expansions, ramps, and lanes of attack,
but are smaller than normal ladder maps. The number specifies the map size.
================================================
FILE: docs/mini_games.md
================================================
# DeepMind Mini Games
## MoveToBeacon
#### Description
A map with 1 Marine and 1 Beacon. Rewards are earned by moving the marine to the
beacon. Whenever the Marine earns a reward for reaching the Beacon, the Beacon
is teleported to a random location (at least 5 units away from Marine).
#### Initial State
* 1 Marine at random location (unselected)
* 1 Beacon at random location (at least 4 units away from Marine)
#### Rewards
* Marine reaches Beacon: +1
#### End Condition
* Time elapsed
#### Time Limit
* 120 seconds
#### Additional Notes
* Fog of War disabled
* No camera movement required (single-screen)
## CollectMineralShards
#### Description
A map with 2 Marines and an endless supply of Mineral Shards. Rewards are earned
by moving the Marines to collect the Mineral Shards, with optimal collection
requiring both Marine units to be split up and moved independently. Whenever all
20 Mineral Shards have been collected, a new set of 20 Mineral Shards are
spawned at random locations (at least 2 units away from all Marines).
#### Initial State
* 2 Marines at random locations (unselected)
* 20 Mineral Shards at random locations (at least 2 units away from all
Marines)
#### Rewards
* Marine collects Mineral Shard: +1
#### End Condition
* Time elapsed
#### Time Limit
* 120 seconds
#### Additional Notes
* Fog of War disabled
* No camera movement required (single-screen)
* This is the only map in the set to require the Liberty (Campaign) mod, which
is needed for the Mineral Shard unit.
## FindAndDefeatZerglings
#### Description
A map with 3 Marines and an endless supply of stationary Zerglings. Rewards are
earned by using the Marines to defeat Zerglings, with the optimal strategy
requiring a combination of efficient exploration and combat. Whenever all 25
Zerglings have been defeated, a new set of 25 Zerglings are spawned at random
locations (at least 9 units away from all Marines and at least 5 units away from
all other Zerglings).
#### Initial State
* 3 Marines at map center (preselected)
* 2 Zerglings spawned at random locations inside player's vision range
(between 7.5 and 9.5 units away from map center and at least 5 units away
from all other Zerglings)
* 23 Zerglings spawned at random locations outside player's vision range (at
least 10.5 units away from map center and at least 5 units away from all
other Zerglings)
#### Rewards
* Zergling defeated: +1
* Marine defeated: -1
#### End Conditions
* Time elapsed
* All Marines defeated
#### Time Limit
* 180 seconds
#### Additional Notes
* Fog of War enabled
* Camera movement required (map is larger than single-screen)
## DefeatRoaches
#### Description
A map with 9 Marines and a group of 4 Roaches on opposite sides. Rewards are
earned by using the Marines to defeat Roaches, with optimal combat strategy
requiring the Marines to perform focus fire on the Roaches. Whenever all 4
Roaches have been defeated, a new group of 4 Roaches is spawned and the player
is awarded 5 additional Marines at full health, with all other surviving Marines
retaining their existing health (no restore). Whenever new units are spawned,
all unit positions are reset to opposite sides of the map.
#### Initial State
* 9 Marines in a vertical line at a random side of the map (preselected)
* 4 Roaches in a vertical line at the opposite side of the map from the
Marines
#### Rewards
* Roach defeated: +10
* Marine defeated: -1
#### End Conditions
* Time elapsed
* All Marines defeated
#### Time Limit
* 120 seconds
#### Additional Notes
* Fog of War disabled
* No camera movement required (single-screen)
* This map and DefeatZerglingsAndBanelings are currently the only maps in the
set that can include an automatic, mid-episode state change for
player-controlled units. The Marine units are automatically moved back to a
neutral position (at a random side of the map opposite the Roaches) when new
units are spawned, which occurs whenever the current set of Roaches is
defeated. This is done in order to guarantee that new units do not spawn
within combat range of one another.
## DefeatZerglingsAndBanelings
#### Description
A map with 9 Marines on the opposite side from a group of 6 Zerglings and 4
Banelings. Rewards are earned by using the Marines to defeat Zerglings and
Banelings. Whenever all Zerglings and Banelings have been defeated, a new group
of 6 Zerglings and 4 Banelings is spawned and the player is awarded 4 additional
Marines at full health, with all other surviving Marines retaining their
existing health (no restore). Whenever new units are spawned, all unit positions
are reset to opposite sides of the map.
#### Initial State
* 9 Marines in a vertical line at a random side of the map (preselected)
* 6 Zerglings and 4 Banelings in a group at the opposite side of the map from
the Marines
#### Rewards
* Zergling defeated: +5
* Baneling defeated: +5
* Marine defeated: -1
#### End Conditions
* Time elapsed
* All Marines defeated
#### Time Limit
* 120 seconds
#### Additional Notes
* Fog of War disabled
* No camera movement required (single-screen)
* This map and DefeatRoaches are currently the only maps in the set that can
include an automatic, mid-episode state change for player-controlled units.
The Marine units are automatically moved back to a neutral position (at a
random side of the map opposite the Roaches) when new units are spawned,
which occurs whenever the current set of Zerglings and Banelings is
defeated. This is done in order to guarantee that new units do not spawn
within combat range of one another.
## CollectMineralsAndGas
#### Description
A map with 12 SCVs, 1 Command Center, 16 Mineral Fields and 4 Vespene Geysers.
Rewards are based on the total amount of Minerals and Vespene Gas collected.
Spending Minerals and Vespene Gas to train new units does not decrease your
reward tally. Optimal collection will require expanding your capacity to gather
Minerals and Vespene Gas by constructing additional SCVs and an additional
Command Center.
#### Initial State
* 12 SCVs beside the Command Center (unselected)
* 1 Command Center at a fixed location
* 16 Mineral Fields at fixed locations
* 4 Vespene Geysers at fixed locations
* Player Resources: 50 Minerals, 0 Vespene, 12/15 Supply
#### Rewards
Reward total is equal to the total amount of Minerals and Vespene Gas collected
#### End Condition
Time elapsed
#### Time Limit
300 seconds
## BuildMarines
#### Description
A map with 12 SCVs, 1 Command Center, and 8 Mineral Fields. Rewards are earned
by building Marines. This is accomplished by using SCVs to collect minerals,
which are used to build Supply Depots and Barracks, which can then build
Marines.
#### Initial State
* 12 SCVs beside the Command Center (unselected)
* 1 Command Center at a fixed location
* 8 Mineral Fields at fixed locations
* Player Resources: 50 Minerals, 0 Vespene, 12/15 Supply
#### Rewards
Reward total is equal to the total number of Marines built
#### End Condition
Time elapsed
#### Time Limit
900 seconds
#### Additional Notes
* Fog of War disabled
* No camera movement required (single-screen)
* This is the only map in the set that explicitly limits the available actions
of the units to disallow actions which are not pertinent to the goal of the
map. Actions that are not required for building Marines have been removed.
================================================
FILE: pysc2/BUILD
================================================
load("@bazel_skylib//:bzl_library.bzl", "bzl_library")
licenses(["notice"])
exports_files(["LICENSE"])
bzl_library(
name = "build_defs",
srcs = ["build_defs.bzl"],
)
================================================
FILE: pysc2/__init__.py
================================================
# Copyright 2017 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS-IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""PySC2 module: https://github.com/deepmind/pysc2 ."""
import os
def load_tests(loader, standard_tests, unused_pattern):
"""Our tests end in `_test.py`, so need to override the test discovery."""
this_dir = os.path.dirname(__file__)
package_tests = loader.discover(start_dir=this_dir, pattern="*_test.py")
standard_tests.addTests(package_tests)
return standard_tests
================================================
FILE: pysc2/agents/BUILD
================================================
load("@my_deps//:requirements.bzl", "requirement")
load("//pysc2:build_defs.bzl", "pytype_library", "pytype_strict_library")
package(default_visibility = ["//visibility:public"])
licenses(["notice"])
py_library(
name = "agents",
srcs_version = "PY3",
deps = [
":base_agent",
":random_agent",
":scripted_agent",
],
)
pytype_library(
name = "base_agent",
srcs = ["base_agent.py"],
srcs_version = "PY3",
deps = [
"//pysc2/lib:actions",
],
)
pytype_strict_library(
name = "no_op_agent",
srcs = ["no_op_agent.py"],
deps = [
":base_agent",
"@s2client_proto//s2clientprotocol:sc2api_py_pb2",
],
)
pytype_library(
name = "scripted_agent",
srcs = ["scripted_agent.py"],
srcs_version = "PY3",
deps = [
":base_agent",
requirement("numpy"),
"//pysc2/lib:actions",
"//pysc2/lib:features",
],
)
pytype_library(
name = "random_agent",
srcs = ["random_agent.py"],
srcs_version = "PY3",
deps = [
":base_agent",
requirement("numpy"),
"//pysc2/lib:actions",
],
)
================================================
FILE: pysc2/agents/__init__.py
================================================
# Copyright 2017 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS-IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
================================================
FILE: pysc2/agents/base_agent.py
================================================
# Copyright 2017 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS-IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""A base agent to write custom scripted agents."""
from pysc2.lib import actions
class BaseAgent(object):
"""A base agent to write custom scripted agents.
It can also act as a passive agent that does nothing but no-ops.
"""
def __init__(self):
self.reward = 0
self.episodes = 0
self.steps = 0
self.obs_spec = None
self.action_spec = None
def setup(self, obs_spec, action_spec):
self.obs_spec = obs_spec
self.action_spec = action_spec
def reset(self):
self.episodes += 1
def step(self, obs):
self.steps += 1
self.reward += obs.reward
return actions.FunctionCall(actions.FUNCTIONS.no_op.id, [])
================================================
FILE: pysc2/agents/no_op_agent.py
================================================
# Copyright 2021 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS-IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""A no-op agent for starcraft."""
from pysc2.agents import base_agent
from s2clientprotocol import sc2api_pb2 as sc_pb
class NoOpAgent(base_agent.BaseAgent):
"""A no-op agent for starcraft."""
def step(self, obs):
super(NoOpAgent, self).step(obs)
return sc_pb.Action()
================================================
FILE: pysc2/agents/random_agent.py
================================================
# Copyright 2017 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS-IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""A random agent for starcraft."""
import numpy
from pysc2.agents import base_agent
from pysc2.lib import actions
class RandomAgent(base_agent.BaseAgent):
"""A random agent for starcraft."""
def step(self, obs):
super(RandomAgent, self).step(obs)
function_id = numpy.random.choice(obs.observation.available_actions)
args = [[numpy.random.randint(0, size) for size in arg.sizes]
for arg in self.action_spec.functions[function_id].args]
return actions.FunctionCall(function_id, args)
================================================
FILE: pysc2/agents/scripted_agent.py
================================================
# Copyright 2017 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS-IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Scripted agents."""
import numpy
from pysc2.agents import base_agent
from pysc2.lib import actions
from pysc2.lib import features
_PLAYER_SELF = features.PlayerRelative.SELF
_PLAYER_NEUTRAL = features.PlayerRelative.NEUTRAL # beacon/minerals
_PLAYER_ENEMY = features.PlayerRelative.ENEMY
FUNCTIONS = actions.FUNCTIONS
RAW_FUNCTIONS = actions.RAW_FUNCTIONS
def _xy_locs(mask):
"""Mask should be a set of bools from comparison with a feature layer."""
y, x = mask.nonzero()
return list(zip(x, y))
class MoveToBeacon(base_agent.BaseAgent):
"""An agent specifically for solving the MoveToBeacon map."""
def step(self, obs):
super(MoveToBeacon, self).step(obs)
if FUNCTIONS.Move_screen.id in obs.observation.available_actions:
player_relative = obs.observation.feature_screen.player_relative
beacon = _xy_locs(player_relative == _PLAYER_NEUTRAL)
if not beacon:
return FUNCTIONS.no_op()
beacon_center = numpy.mean(beacon, axis=0).round()
return FUNCTIONS.Move_screen("now", beacon_center)
else:
return FUNCTIONS.select_army("select")
class CollectMineralShards(base_agent.BaseAgent):
"""An agent specifically for solving the CollectMineralShards map."""
def step(self, obs):
super(CollectMineralShards, self).step(obs)
if FUNCTIONS.Move_screen.id in obs.observation.available_actions:
player_relative = obs.observation.feature_screen.player_relative
minerals = _xy_locs(player_relative == _PLAYER_NEUTRAL)
if not minerals:
return FUNCTIONS.no_op()
marines = _xy_locs(player_relative == _PLAYER_SELF)
marine_xy = numpy.mean(marines, axis=0).round() # Average location.
distances = numpy.linalg.norm(numpy.array(minerals) - marine_xy, axis=1)
closest_mineral_xy = minerals[numpy.argmin(distances)]
return FUNCTIONS.Move_screen("now", closest_mineral_xy)
else:
return FUNCTIONS.select_army("select")
class CollectMineralShardsFeatureUnits(base_agent.BaseAgent):
"""An agent for solving the CollectMineralShards map with feature units.
Controls the two marines independently:
- select marine
- move to nearest mineral shard that wasn't the previous target
- swap marine and repeat
"""
def setup(self, obs_spec, action_spec):
super(CollectMineralShardsFeatureUnits, self).setup(obs_spec, action_spec)
if "feature_units" not in obs_spec:
raise Exception("This agent requires the feature_units observation.")
def reset(self):
super(CollectMineralShardsFeatureUnits, self).reset()
self._marine_selected = False
self._previous_mineral_xy = [-1, -1]
def step(self, obs):
super(CollectMineralShardsFeatureUnits, self).step(obs)
marines = [unit for unit in obs.observation.feature_units
if unit.alliance == _PLAYER_SELF]
if not marines:
return FUNCTIONS.no_op()
marine_unit = next((m for m in marines
if m.is_selected == self._marine_selected), marines[0])
marine_xy = [marine_unit.x, marine_unit.y]
if not marine_unit.is_selected:
# Nothing selected or the wrong marine is selected.
self._marine_selected = True
return FUNCTIONS.select_point("select", marine_xy)
if FUNCTIONS.Move_screen.id in obs.observation.available_actions:
# Find and move to the nearest mineral.
minerals = [[unit.x, unit.y] for unit in obs.observation.feature_units
if unit.alliance == _PLAYER_NEUTRAL]
if self._previous_mineral_xy in minerals:
# Don't go for the same mineral shard as other marine.
minerals.remove(self._previous_mineral_xy)
if minerals:
# Find the closest.
distances = numpy.linalg.norm(
numpy.array(minerals) - numpy.array(marine_xy), axis=1)
closest_mineral_xy = minerals[numpy.argmin(distances)]
# Swap to the other marine.
self._marine_selected = False
self._previous_mineral_xy = closest_mineral_xy
return FUNCTIONS.Move_screen("now", closest_mineral_xy)
return FUNCTIONS.no_op()
class CollectMineralShardsRaw(base_agent.BaseAgent):
"""An agent for solving CollectMineralShards with raw units and actions.
Controls the two marines independently:
- move to nearest mineral shard that wasn't the previous target
- swap marine and repeat
"""
def setup(self, obs_spec, action_spec):
super(CollectMineralShardsRaw, self).setup(obs_spec, action_spec)
if "raw_units" not in obs_spec:
raise Exception("This agent requires the raw_units observation.")
def reset(self):
super(CollectMineralShardsRaw, self).reset()
self._last_marine = None
self._previous_mineral_xy = [-1, -1]
def step(self, obs):
super(CollectMineralShardsRaw, self).step(obs)
marines = [unit for unit in obs.observation.raw_units
if unit.alliance == _PLAYER_SELF]
if not marines:
return RAW_FUNCTIONS.no_op()
marine_unit = next((m for m in marines if m.tag != self._last_marine))
marine_xy = [marine_unit.x, marine_unit.y]
minerals = [[unit.x, unit.y] for unit in obs.observation.raw_units
if unit.alliance == _PLAYER_NEUTRAL]
if self._previous_mineral_xy in minerals:
# Don't go for the same mineral shard as other marine.
minerals.remove(self._previous_mineral_xy)
if minerals:
# Find the closest.
distances = numpy.linalg.norm(
numpy.array(minerals) - numpy.array(marine_xy), axis=1)
closest_mineral_xy = minerals[numpy.argmin(distances)]
self._last_marine = marine_unit.tag
self._previous_mineral_xy = closest_mineral_xy
return RAW_FUNCTIONS.Move_pt("now", marine_unit.tag, closest_mineral_xy)
return RAW_FUNCTIONS.no_op()
class DefeatRoaches(base_agent.BaseAgent):
"""An agent specifically for solving the DefeatRoaches map."""
def step(self, obs):
super(DefeatRoaches, self).step(obs)
if FUNCTIONS.Attack_screen.id in obs.observation.available_actions:
player_relative = obs.observation.feature_screen.player_relative
roaches = _xy_locs(player_relative == _PLAYER_ENEMY)
if not roaches:
return FUNCTIONS.no_op()
# Find the roach with max y coord.
target = roaches[numpy.argmax(numpy.array(roaches)[:, 1])]
return FUNCTIONS.Attack_screen("now", target)
if FUNCTIONS.select_army.id in obs.observation.available_actions:
return FUNCTIONS.select_army("select")
return FUNCTIONS.no_op()
class DefeatRoachesRaw(base_agent.BaseAgent):
"""An agent specifically for solving DefeatRoaches using raw actions."""
def setup(self, obs_spec, action_spec):
super(DefeatRoachesRaw, self).setup(obs_spec, action_spec)
if "raw_units" not in obs_spec:
raise Exception("This agent requires the raw_units observation.")
def step(self, obs):
super(DefeatRoachesRaw, self).step(obs)
marines = [unit.tag for unit in obs.observation.raw_units
if unit.alliance == _PLAYER_SELF]
roaches = [unit for unit in obs.observation.raw_units
if unit.alliance == _PLAYER_ENEMY]
if marines and roaches:
# Find the roach with max y coord.
target = sorted(roaches, key=lambda r: r.y)[0].tag
return RAW_FUNCTIONS.Attack_unit("now", marines, target)
return FUNCTIONS.no_op()
================================================
FILE: pysc2/bin/BUILD
================================================
load("@my_deps//:requirements.bzl", "requirement")
load("//pysc2:build_defs.bzl", "pytype_binary", "pytype_strict_binary")
package(default_visibility = ["//visibility:public"])
licenses(["notice"])
pytype_binary(
name = "replay_actions",
srcs = ["replay_actions.py"],
python_version = "PY3",
srcs_version = "PY3",
deps = [
"//pysc2/lib:features",
"//pysc2/lib:gfile",
"//pysc2/lib:point",
"//pysc2/lib:protocol",
"//pysc2/lib:remote_controller",
"//pysc2/lib:replay",
"//pysc2/lib:static_data",
"//pysc2/maps", # build_cleaner: keep
"//pysc2/run_configs",
"@absl_py//absl:app",
"@absl_py//absl/flags",
"@s2client_proto//s2clientprotocol:sc2api_py_pb2",
],
)
pytype_binary(
name = "gen_actions",
srcs = ["gen_actions.py"],
python_version = "PY3",
srcs_version = "PY3",
deps = [
"//pysc2/lib:static_data",
"//pysc2/maps",
"//pysc2/run_configs",
"@absl_py//absl:app",
"@absl_py//absl/flags",
"@s2client_proto//s2clientprotocol:sc2api_py_pb2",
],
)
pytype_binary(
name = "gen_data",
srcs = ["gen_data.py"],
python_version = "PY3",
srcs_version = "PY3",
deps = [
"//pysc2/lib:static_data",
"//pysc2/maps",
"//pysc2/run_configs",
"@absl_py//absl:app",
"@s2client_proto//s2clientprotocol:sc2api_py_pb2",
],
)
pytype_binary(
name = "check_apm",
srcs = ["check_apm.py"],
python_version = "PY3",
srcs_version = "PY3",
deps = [
"//pysc2/lib:actions",
"//pysc2/lib:features",
"//pysc2/lib:point",
"//pysc2/lib:units",
"//pysc2/maps",
"//pysc2/run_configs",
"@absl_py//absl:app",
"@s2client_proto//s2clientprotocol:sc2api_py_pb2",
],
)
pytype_binary(
name = "benchmark_observe",
srcs = ["benchmark_observe.py"],
python_version = "PY3",
srcs_version = "PY3",
deps = [
"//pysc2/lib:replay",
"//pysc2/lib:stopwatch",
"//pysc2/maps",
"//pysc2/run_configs",
"@absl_py//absl:app",
"@absl_py//absl/flags",
"@s2client_proto//s2clientprotocol:sc2api_py_pb2",
],
)
pytype_binary(
name = "benchmark_replay",
srcs = ["benchmark_replay.py"],
python_version = "PY3",
srcs_version = "PY3",
deps = [
"//pysc2/lib:actions",
"//pysc2/lib:features",
"//pysc2/lib:point_flag",
"//pysc2/lib:replay",
"//pysc2/lib:stopwatch",
"//pysc2/run_configs",
"@absl_py//absl:app",
"@absl_py//absl/flags",
"@s2client_proto//s2clientprotocol:sc2api_py_pb2",
],
)
pytype_binary(
name = "mem_leak_check",
srcs = ["mem_leak_check.py"],
python_version = "PY3",
srcs_version = "PY3",
deps = [
"@absl_py//absl:app",
"@absl_py//absl/flags",
requirement("psutil"), # build_cleaner: keep
"//pysc2/lib:protocol",
"//pysc2/maps",
"//pysc2/run_configs",
"@s2client_proto//s2clientprotocol:sc2api_py_pb2",
],
)
pytype_binary(
name = "gen_versions",
srcs = ["gen_versions.py"],
python_version = "PY3",
srcs_version = "PY3",
deps = [
"@absl_py//absl:app",
requirement("requests"),
],
)
pytype_binary(
name = "map_list",
srcs = ["map_list.py"],
python_version = "PY3",
srcs_version = "PY3",
deps = [
"//pysc2/maps",
"@absl_py//absl:app",
],
)
pytype_binary(
name = "play",
srcs = ["play.py"],
python_version = "PY3",
srcs_version = "PY3",
deps = [
"//pysc2/env:sc2_env",
"//pysc2/lib:point_flag",
"//pysc2/lib:renderer_human",
"//pysc2/lib:replay",
"//pysc2/lib:stopwatch",
"//pysc2/maps",
"//pysc2/run_configs",
"@absl_py//absl:app",
"@absl_py//absl/flags",
"@s2client_proto//s2clientprotocol:sc2api_py_pb2",
],
)
pytype_binary(
name = "play_vs_agent",
srcs = ["play_vs_agent.py"],
python_version = "PY3",
srcs_version = "PY3",
deps = [
"@absl_py//absl:app",
"@absl_py//absl/flags",
"@absl_py//absl/logging",
requirement("portpicker"),
"//pysc2/agents", # build_cleaner: keep
"//pysc2/env:lan_sc2_env",
"//pysc2/env:run_loop",
"//pysc2/env:sc2_env",
"//pysc2/lib:point_flag",
"//pysc2/lib:renderer_human",
"//pysc2/maps",
"//pysc2/run_configs",
"@s2client_proto//s2clientprotocol:sc2api_py_pb2",
],
)
pytype_binary(
name = "agent_remote",
srcs = ["agent_remote.py"],
python_version = "PY3",
srcs_version = "PY3",
deps = [
"//pysc2/agents", # build_cleaner: keep
"//pysc2/env:remote_sc2_env",
"//pysc2/env:run_loop",
"//pysc2/env:sc2_env",
"//pysc2/lib:point_flag",
"//pysc2/lib:portspicker",
"//pysc2/lib:renderer_human",
"//pysc2/maps",
"//pysc2/run_configs",
"@absl_py//absl:app",
"@absl_py//absl/flags",
"@absl_py//absl/logging",
"@s2client_proto//s2clientprotocol:sc2api_py_pb2",
],
)
pytype_binary(
name = "replay_info",
srcs = ["replay_info.py"],
python_version = "PY3",
srcs_version = "PY3",
deps = [
"//pysc2/lib:gfile",
"//pysc2/lib:remote_controller",
"//pysc2/lib:replay",
"//pysc2/run_configs",
"@absl_py//absl:app",
"@absl_py//absl/flags",
"@s2client_proto//s2clientprotocol:common_py_pb2",
"@s2client_proto//s2clientprotocol:sc2api_py_pb2",
],
)
pytype_binary(
name = "agent",
srcs = ["agent.py"],
python_version = "PY3",
srcs_version = "PY3",
deps = [
"//pysc2/agents", # build_cleaner: keep
"//pysc2/env:available_actions_printer",
"//pysc2/env:run_loop",
"//pysc2/env:sc2_env",
"//pysc2/lib:point_flag",
"//pysc2/lib:stopwatch",
"//pysc2/maps",
"@absl_py//absl:app",
"@absl_py//absl/flags",
],
)
pytype_binary(
name = "valid_actions",
srcs = ["valid_actions.py"],
python_version = "PY3",
srcs_version = "PY3",
deps = [
"//pysc2/lib:actions",
"//pysc2/lib:features",
"//pysc2/lib:point_flag",
"@absl_py//absl:app",
"@absl_py//absl/flags",
],
)
pytype_binary(
name = "compare_binaries",
srcs = ["compare_binaries.py"],
python_version = "PY3",
srcs_version = "PY3",
deps = [
"//pysc2/lib:image_differencer",
"//pysc2/lib:proto_diff",
"//pysc2/lib:remote_controller",
"//pysc2/lib:replay",
"//pysc2/lib:stopwatch",
"//pysc2/run_configs",
"@absl_py//absl:app",
"@absl_py//absl/flags",
"@s2client_proto//s2clientprotocol:sc2api_py_pb2",
],
)
pytype_strict_binary(
name = "battle_net_maps",
srcs = ["battle_net_maps.py"],
python_version = "PY3",
srcs_version = "PY3",
deps = [
"//pysc2/run_configs",
"@absl_py//absl:app",
],
)
pytype_strict_binary(
name = "reencode_replays",
srcs = ["reencode_replays.py"],
python_version = "PY3",
srcs_version = "PY3",
deps = [
"//pysc2/lib:replay",
"//pysc2/run_configs",
"@absl_py//absl:app",
"@absl_py//absl/flags",
"@s2client_proto//s2clientprotocol:sc2api_py_pb2",
],
)
pytype_strict_binary(
name = "update_battle_net_cache",
srcs = ["update_battle_net_cache.py"],
python_version = "PY3",
srcs_version = "PY3",
deps = [
"@absl_py//absl:app",
"@absl_py//absl/flags",
requirement("mpyq"),
"//pysc2/run_configs",
"@s2protocol_archive//:versions",
],
)
pytype_strict_binary(
name = "replay_version",
srcs = ["replay_version.py"],
deps = [
"//pysc2/lib:replay",
"//pysc2/run_configs",
"@absl_py//absl:app",
],
)
================================================
FILE: pysc2/bin/__init__.py
================================================
# Copyright 2017 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS-IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
================================================
FILE: pysc2/bin/agent.py
================================================
#!/usr/bin/python
# Copyright 2017 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS-IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Run an agent."""
import importlib
import threading
from absl import app
from absl import flags
from pysc2 import maps
from pysc2.env import available_actions_printer
from pysc2.env import run_loop
from pysc2.env import sc2_env
from pysc2.lib import point_flag
from pysc2.lib import stopwatch
FLAGS = flags.FLAGS
flags.DEFINE_bool("render", True, "Whether to render with pygame.")
point_flag.DEFINE_point("feature_screen_size", "84",
"Resolution for screen feature layers.")
point_flag.DEFINE_point("feature_minimap_size", "64",
"Resolution for minimap feature layers.")
point_flag.DEFINE_point("rgb_screen_size", None,
"Resolution for rendered screen.")
point_flag.DEFINE_point("rgb_minimap_size", None,
"Resolution for rendered minimap.")
flags.DEFINE_enum("action_space", None, sc2_env.ActionSpace._member_names_, # pylint: disable=protected-access
"Which action space to use. Needed if you take both feature "
"and rgb observations.")
flags.DEFINE_bool("use_feature_units", False,
"Whether to include feature units.")
flags.DEFINE_bool("use_raw_units", False,
"Whether to include raw units.")
flags.DEFINE_bool("disable_fog", False, "Whether to disable Fog of War.")
flags.DEFINE_integer("max_agent_steps", 0, "Total agent steps.")
flags.DEFINE_integer("game_steps_per_episode", None, "Game steps per episode.")
flags.DEFINE_integer("max_episodes", 0, "Total episodes.")
flags.DEFINE_integer("step_mul", 8, "Game steps per agent step.")
flags.DEFINE_string("agent", "pysc2.agents.random_agent.RandomAgent",
"Which agent to run, as a python path to an Agent class.")
flags.DEFINE_string("agent_name", None,
"Name of the agent in replays. Defaults to the class name.")
flags.DEFINE_enum("agent_race", "random", sc2_env.Race._member_names_, # pylint: disable=protected-access
"Agent 1's race.")
flags.DEFINE_string("agent2", "Bot", "Second agent, either Bot or agent class.")
flags.DEFINE_string("agent2_name", None,
"Name of the agent in replays. Defaults to the class name.")
flags.DEFINE_enum("agent2_race", "random", sc2_env.Race._member_names_, # pylint: disable=protected-access
"Agent 2's race.")
flags.DEFINE_enum("difficulty", "very_easy", sc2_env.Difficulty._member_names_, # pylint: disable=protected-access
"If agent2 is a built-in Bot, it's strength.")
flags.DEFINE_enum("bot_build", "random", sc2_env.BotBuild._member_names_, # pylint: disable=protected-access
"Bot's build strategy.")
flags.DEFINE_bool("profile", False, "Whether to turn on code profiling.")
flags.DEFINE_bool("trace", False, "Whether to trace the code execution.")
flags.DEFINE_integer("parallel", 1, "How many instances to run in parallel.")
flags.DEFINE_bool("save_replay", True, "Whether to save a replay at the end.")
flags.DEFINE_string("map", None, "Name of a map to use.")
flags.DEFINE_bool("battle_net_map", False, "Use the battle.net map version.")
flags.mark_flag_as_required("map")
def run_thread(agent_classes, players, map_name, visualize):
"""Run one thread worth of the environment with agents."""
with sc2_env.SC2Env(
map_name=map_name,
battle_net_map=FLAGS.battle_net_map,
players=players,
agent_interface_format=sc2_env.parse_agent_interface_format(
feature_screen=FLAGS.feature_screen_size,
feature_minimap=FLAGS.feature_minimap_size,
rgb_screen=FLAGS.rgb_screen_size,
rgb_minimap=FLAGS.rgb_minimap_size,
action_space=FLAGS.action_space,
use_feature_units=FLAGS.use_feature_units,
use_raw_units=FLAGS.use_raw_units),
step_mul=FLAGS.step_mul,
game_steps_per_episode=FLAGS.game_steps_per_episode,
disable_fog=FLAGS.disable_fog,
visualize=visualize) as env:
env = available_actions_printer.AvailableActionsPrinter(env)
agents = [agent_cls() for agent_cls in agent_classes]
run_loop.run_loop(agents, env, FLAGS.max_agent_steps, FLAGS.max_episodes)
if FLAGS.save_replay:
env.save_replay(agent_classes[0].__name__)
def main(unused_argv):
"""Run an agent."""
if FLAGS.trace:
stopwatch.sw.trace()
elif FLAGS.profile:
stopwatch.sw.enable()
map_inst = maps.get(FLAGS.map)
agent_classes = []
players = []
agent_module, agent_name = FLAGS.agent.rsplit(".", 1)
agent_cls = getattr(importlib.import_module(agent_module), agent_name)
agent_classes.append(agent_cls)
players.append(sc2_env.Agent(sc2_env.Race[FLAGS.agent_race],
FLAGS.agent_name or agent_name))
if map_inst.players >= 2:
if FLAGS.agent2 == "Bot":
players.append(sc2_env.Bot(sc2_env.Race[FLAGS.agent2_race],
sc2_env.Difficulty[FLAGS.difficulty],
sc2_env.BotBuild[FLAGS.bot_build]))
else:
agent_module, agent_name = FLAGS.agent2.rsplit(".", 1)
agent_cls = getattr(importlib.import_module(agent_module), agent_name)
agent_classes.append(agent_cls)
players.append(sc2_env.Agent(sc2_env.Race[FLAGS.agent2_race],
FLAGS.agent2_name or agent_name))
threads = []
for _ in range(FLAGS.parallel - 1):
t = threading.Thread(target=run_thread,
args=(agent_classes, players, FLAGS.map, False))
threads.append(t)
t.start()
run_thread(agent_classes, players, FLAGS.map, FLAGS.render)
for t in threads:
t.join()
if FLAGS.profile:
print(stopwatch.sw)
def entry_point(): # Needed so setup.py scripts work.
app.run(main)
if __name__ == "__main__":
app.run(main)
================================================
FILE: pysc2/bin/agent_remote.py
================================================
#!/usr/bin/python
# Copyright 2017 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS-IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
r"""Play an agent with an SC2 instance that isn't owned.
This can be used to play on the sc2ai.net ladder, as well as to play vs humans.
To play on ladder:
$ python -m pysc2.bin.agent_remote --agent <import path> \
--host_port <GamePort> --lan_port <StartPort>
To play vs humans:
$ python -m pysc2.bin.agent_remote --human --map <MapName>
then copy the string it generates which is something similar to above
If you want to play remotely, you'll need to port forward (eg with ssh -L or -R)
the host_port from localhost on one machine to localhost on the other.
You can also set your race, observation options, etc by cmdline flags.
When playing vs humans it launches both instances on the human side. This means
you only need to port-forward a single port (ie the websocket betwen SC2 and the
agent), but you also need to transfer the entire observation, which is much
bigger than the actions transferred over the lan connection between the two SC2
instances. It also makes it easy to maintain version compatibility since they
are the same binary. Unfortunately it means higher cpu usage where the human is
playing, which on a Mac becomes problematic as OSX slows down the instance
running in the background. There can also be observation differences between
Mac/Win and Linux. For these reasons, prefer play_vs_agent which runs the
instance next to the agent, and tunnels the lan actions instead.
"""
import getpass
import importlib
import platform
import sys
import time
from absl import app
from absl import flags
from absl import logging
from pysc2 import maps
from pysc2 import run_configs
from pysc2.env import remote_sc2_env
from pysc2.env import run_loop
from pysc2.env import sc2_env
from pysc2.lib import point_flag
from pysc2.lib import portspicker
from pysc2.lib import renderer_human
from s2clientprotocol import sc2api_pb2 as sc_pb
FLAGS = flags.FLAGS
flags.DEFINE_bool("render", platform.system() == "Linux",
"Whether to render with pygame.")
flags.DEFINE_bool("realtime", False, "Whether to run in realtime mode.")
flags.DEFINE_string("agent", "pysc2.agents.random_agent.RandomAgent",
"Which agent to run, as a python path to an Agent class.")
flags.DEFINE_string("agent_name", None,
"Name of the agent in replays. Defaults to the class name.")
flags.DEFINE_enum("agent_race", "random", sc2_env.Race._member_names_, # pylint: disable=protected-access
"Agent's race.")
flags.DEFINE_float("fps", 22.4, "Frames per second to run the game.")
flags.DEFINE_integer("step_mul", 8, "Game steps per agent step.")
point_flag.DEFINE_point("feature_screen_size", "84",
"Resolution for screen feature layers.")
point_flag.DEFINE_point("feature_minimap_size", "64",
"Resolution for minimap feature layers.")
point_flag.DEFINE_point("rgb_screen_size", "256",
"Resolution for rendered screen.")
point_flag.DEFINE_point("rgb_minimap_size", "128",
"Resolution for rendered minimap.")
flags.DEFINE_enum("action_space", "FEATURES",
sc2_env.ActionSpace._member_names_, # pylint: disable=protected-access
"Which action space to use. Needed if you take both feature "
"and rgb observations.")
flags.DEFINE_bool("use_feature_units", False,
"Whether to include feature units.")
flags.DEFINE_string("user_name", getpass.getuser(),
"Name of the human player for replays.")
flags.DEFINE_enum("user_race", "random", sc2_env.Race._member_names_, # pylint: disable=protected-access
"User's race.")
flags.DEFINE_string("host", "127.0.0.1", "Game Host")
flags.DEFINE_integer("host_port", None, "Host port")
flags.DEFINE_integer("lan_port", None, "Host port")
flags.DEFINE_string("map", None, "Name of a map to use to play.")
flags.DEFINE_bool("human", False, "Whether to host a game as a human.")
flags.DEFINE_integer("timeout_seconds", 300,
"Time in seconds for the remote agent to connect to the "
"game before an exception is raised.")
def main(unused_argv):
if FLAGS.human:
human()
else:
agent()
def agent():
"""Run the agent, connecting to a (remote) host started independently."""
agent_module, agent_name = FLAGS.agent.rsplit(".", 1)
agent_cls = getattr(importlib.import_module(agent_module), agent_name)
logging.info("Starting agent:")
with remote_sc2_env.RemoteSC2Env(
map_name=FLAGS.map,
host=FLAGS.host,
host_port=FLAGS.host_port,
lan_port=FLAGS.lan_port,
name=FLAGS.agent_name or agent_name,
race=sc2_env.Race[FLAGS.agent_race],
step_mul=FLAGS.step_mul,
agent_interface_format=sc2_env.parse_agent_interface_format(
feature_screen=FLAGS.feature_screen_size,
feature_minimap=FLAGS.feature_minimap_size,
rgb_screen=FLAGS.rgb_screen_size,
rgb_minimap=FLAGS.rgb_minimap_size,
action_space=FLAGS.action_space,
use_feature_units=FLAGS.use_feature_units),
visualize=FLAGS.render) as env:
agents = [agent_cls()]
logging.info("Connected, starting run_loop.")
try:
run_loop.run_loop(agents, env)
except remote_sc2_env.RestartError:
pass
logging.info("Done.")
def human():
"""Run a host which expects one player to connect remotely."""
run_config = run_configs.get()
map_inst = maps.get(FLAGS.map)
if not FLAGS.rgb_screen_size or not FLAGS.rgb_minimap_size:
logging.info("Use --rgb_screen_size and --rgb_minimap_size if you want rgb "
"observations.")
ports = portspicker.pick_contiguous_unused_ports(4) # 2 * num_players
host_proc = run_config.start(extra_ports=ports, host=FLAGS.host,
timeout_seconds=FLAGS.timeout_seconds,
window_loc=(50, 50))
client_proc = run_config.start(extra_ports=ports, host=FLAGS.host,
connect=False, window_loc=(700, 50))
create = sc_pb.RequestCreateGame(
realtime=FLAGS.realtime, local_map=sc_pb.LocalMap(map_path=map_inst.path))
create.player_setup.add(type=sc_pb.Participant)
create.player_setup.add(type=sc_pb.Participant)
controller = host_proc.controller
controller.save_map(map_inst.path, map_inst.data(run_config))
controller.create_game(create)
print("-" * 80)
print("Join host: agent_remote --map %s --host %s --host_port %s "
"--lan_port %s" % (FLAGS.map, FLAGS.host, client_proc.port, ports[0]))
print("-" * 80)
sys.stdout.flush()
join = sc_pb.RequestJoinGame()
join.shared_port = 0 # unused
join.server_ports.game_port = ports.pop(0)
join.server_ports.base_port = ports.pop(0)
join.client_ports.add(game_port=ports.pop(0), base_port=ports.pop(0))
join.race = sc2_env.Race[FLAGS.user_race]
join.player_name = FLAGS.user_name
if FLAGS.render:
join.options.raw = True
join.options.score = True
if FLAGS.feature_screen_size and FLAGS.feature_minimap_size:
fl = join.options.feature_layer
fl.width = 24
FLAGS.feature_screen_size.assign_to(fl.resolution)
FLAGS.feature_minimap_size.assign_to(fl.minimap_resolution)
if FLAGS.rgb_screen_size and FLAGS.rgb_minimap_size:
FLAGS.rgb_screen_size.assign_to(join.options.render.resolution)
FLAGS.rgb_minimap_size.assign_to(join.options.render.minimap_resolution)
controller.join_game(join)
if FLAGS.render:
renderer = renderer_human.RendererHuman(
fps=FLAGS.fps, render_feature_grid=False)
renderer.run(run_configs.get(), controller, max_episodes=1)
else: # Still step forward so the Mac/Windows renderer works.
try:
while True:
frame_start_time = time.time()
if not FLAGS.realtime:
controller.step()
obs = controller.observe()
if obs.player_result:
break
time.sleep(max(0, frame_start_time - time.time() + 1 / FLAGS.fps))
except KeyboardInterrupt:
pass
for p in [host_proc, client_proc]:
p.close()
portspicker.return_ports(ports)
def entry_point(): # Needed so setup.py scripts work.
app.run(main)
if __name__ == "__main__":
app.run(main)
================================================
FILE: pysc2/bin/battle_net_maps.py
================================================
#!/usr/bin/python
# Copyright 2019 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS-IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Print the list of available maps according to the game."""
from absl import app
from pysc2 import run_configs
def main(unused_argv):
with run_configs.get().start(want_rgb=False) as controller:
available_maps = controller.available_maps()
print("\n")
print("Local map paths:")
for m in sorted(available_maps.local_map_paths):
print(" ", m)
print()
print("Battle.net maps:")
for m in sorted(available_maps.battlenet_map_names):
print(" ", m)
if __name__ == "__main__":
app.run(main)
================================================
FILE: pysc2/bin/benchmark_observe.py
================================================
#!/usr/bin/python
# Copyright 2018 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS-IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Benchmark observation times."""
import time
from absl import app
from absl import flags
from pysc2 import maps
from pysc2 import run_configs
from pysc2.lib import replay
from pysc2.lib import stopwatch
from s2clientprotocol import common_pb2 as sc_common
from s2clientprotocol import sc2api_pb2 as sc_pb
flags.DEFINE_integer("count", 1000, "How many observations to run.")
flags.DEFINE_integer("step_mul", 16, "How many game steps per observation.")
flags.DEFINE_string("replay", None, "Which replay to run.")
flags.DEFINE_string("map", "Catalyst", "Which map to run.")
FLAGS = flags.FLAGS
def interface_options(score=False, raw=False, features=None, rgb=None,
crop=True):
"""Get an InterfaceOptions for the config."""
interface = sc_pb.InterfaceOptions()
interface.score = score
interface.raw = raw
if features:
if isinstance(features, int):
screen, minimap = features, features
else:
screen, minimap = features
interface.feature_layer.width = 24
interface.feature_layer.resolution.x = screen
interface.feature_layer.resolution.y = screen
interface.feature_layer.minimap_resolution.x = minimap
interface.feature_layer.minimap_resolution.y = minimap
interface.feature_layer.crop_to_playable_area = crop
if rgb:
if isinstance(rgb, int):
screen, minimap = rgb, rgb
else:
screen, minimap = rgb
interface.render.resolution.x = screen
interface.render.resolution.y = screen
interface.render.minimap_resolution.x = minimap
interface.render.minimap_resolution.y = minimap
return interface
configs = [
("raw", interface_options(raw=True)),
("raw-feat-48", interface_options(raw=True, features=48)),
("raw-feat-128", interface_options(raw=True, features=128)),
("raw-feat-128-48", interface_options(raw=True, features=(128, 48))),
("feat-32", interface_options(features=32)),
("feat-48", interface_options(features=48)),
("feat-72-no-crop", interface_options(features=72, crop=False)),
("feat-72", interface_options(features=72)),
("feat-96", interface_options(features=96)),
("feat-128", interface_options(features=128)),
("rgb-64", interface_options(rgb=64)),
("rgb-128", interface_options(rgb=128)),
]
def main(unused_argv):
stopwatch.sw.enable()
results = []
try:
for config, interface in configs:
print((" Starting: %s " % config).center(60, "-"))
timeline = []
run_config = run_configs.get()
if FLAGS.replay:
replay_data = run_config.replay_data(FLAGS.replay)
start_replay = sc_pb.RequestStartReplay(
replay_data=replay_data, options=interface, disable_fog=False,
observed_player_id=2)
version = replay.get_replay_version(replay_data)
run_config = run_configs.get(version=version) # Replace the run config.
else:
map_inst = maps.get(FLAGS.map)
create = sc_pb.RequestCreateGame(
realtime=False, disable_fog=False, random_seed=1,
local_map=sc_pb.LocalMap(map_path=map_inst.path,
map_data=map_inst.data(run_config)))
create.player_setup.add(type=sc_pb.Participant)
create.player_setup.add(type=sc_pb.Computer, race=sc_common.Terran,
difficulty=sc_pb.VeryEasy)
join = sc_pb.RequestJoinGame(options=interface, race=sc_common.Protoss)
with run_config.start(
want_rgb=interface.HasField("render")) as controller:
if FLAGS.replay:
info = controller.replay_info(replay_data)
print(" Replay info ".center(60, "-"))
print(info)
print("-" * 60)
if info.local_map_path:
start_replay.map_data = run_config.map_data(info.local_map_path)
controller.start_replay(start_replay)
else:
controller.create_game(create)
controller.join_game(join)
for _ in range(FLAGS.count):
controller.step(FLAGS.step_mul)
start = time.time()
obs = controller.observe()
timeline.append(time.time() - start)
if obs.player_result:
break
results.append((config, timeline))
except KeyboardInterrupt:
pass
names, values = zip(*results)
print("\n\nTimeline:\n")
print(",".join(names))
for times in zip(*values):
print(",".join("%0.2f" % (t * 1000) for t in times))
print(stopwatch.sw)
if __name__ == "__main__":
app.run(main)
================================================
FILE: pysc2/bin/benchmark_replay.py
================================================
#!/usr/bin/python
# Copyright 2018 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS-IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Benchmark observation times."""
from absl import app
from absl import flags
from pysc2 import run_configs
from pysc2.lib import actions
from pysc2.lib import features
from pysc2.lib import point_flag
from pysc2.lib import replay
from pysc2.lib import stopwatch
from s2clientprotocol import sc2api_pb2 as sc_pb
FLAGS = flags.FLAGS
flags.DEFINE_integer("step_mul", 8, "Game steps per observation.")
point_flag.DEFINE_point("feature_screen_size", "64",
"Resolution for screen feature layers.")
point_flag.DEFINE_point("feature_minimap_size", "64",
"Resolution for minimap feature layers.")
point_flag.DEFINE_point("rgb_screen_size", None,
"Resolution for rendered screen.")
point_flag.DEFINE_point("rgb_minimap_size", None,
"Resolution for rendered minimap.")
flags.DEFINE_bool("use_feature_units", True,
"Whether to include feature units.")
flags.DEFINE_bool("use_raw_units", True,
"Whether to include raw units.")
flags.DEFINE_string("replay", None, "Name of a replay to show.")
flags.DEFINE_string("map_path", None, "Override the map for this replay.")
flags.mark_flag_as_required("replay")
def main(argv):
if len(argv) > 1:
raise app.UsageError("Too many command-line arguments.")
stopwatch.sw.enable()
interface = sc_pb.InterfaceOptions()
interface.raw = FLAGS.use_feature_units or FLAGS.use_raw_units
interface.score = True
interface.feature_layer.width = 24
if FLAGS.feature_screen_size and FLAGS.feature_minimap_size:
FLAGS.feature_screen_size.assign_to(interface.feature_layer.resolution)
FLAGS.feature_minimap_size.assign_to(
interface.feature_layer.minimap_resolution)
if FLAGS.rgb_screen_size and FLAGS.rgb_minimap_size:
FLAGS.rgb_screen_size.assign_to(interface.render.resolution)
FLAGS.rgb_minimap_size.assign_to(interface.render.minimap_resolution)
run_config = run_configs.get()
replay_data = run_config.replay_data(FLAGS.replay)
start_replay = sc_pb.RequestStartReplay(
replay_data=replay_data,
options=interface,
observed_player_id=1)
version = replay.get_replay_version(replay_data)
run_config = run_configs.get(version=version) # Replace the run config.
try:
with run_config.start(
want_rgb=interface.HasField("render")) as controller:
info = controller.replay_info(replay_data)
print(" Replay info ".center(60, "-"))
print(info)
print("-" * 60)
map_path = FLAGS.map_path or info.local_map_path
if map_path:
start_replay.map_data = run_config.map_data(map_path)
controller.start_replay(start_replay)
feats = features.features_from_game_info(
game_info=controller.game_info(),
use_feature_units=FLAGS.use_feature_units,
use_raw_units=FLAGS.use_raw_units,
use_unit_counts=interface.raw,
use_camera_position=False,
action_space=actions.ActionSpace.FEATURES)
while True:
controller.step(FLAGS.step_mul)
obs = controller.observe()
feats.transform_obs(obs)
if obs.player_result:
break
except KeyboardInterrupt:
pass
print(stopwatch.sw)
if __name__ == "__main__":
app.run(main)
================================================
FILE: pysc2/bin/check_apm.py
================================================
# Copyright 2018 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS-IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Test the apm values of various actions."""
import random
from absl import app
from pysc2 import maps
from pysc2 import run_configs
from pysc2.lib import actions
from pysc2.lib import features
from pysc2.lib import point
from pysc2.lib import units
from s2clientprotocol import common_pb2 as sc_common
from s2clientprotocol import error_pb2 as sc_error
from s2clientprotocol import sc2api_pb2 as sc_pb
def get_units(obs, filter_fn=None, owner=None, unit_type=None, tag=None):
"""Return a dict of units that match the filter."""
if unit_type and not isinstance(unit_type, (list, tuple)):
unit_type = (unit_type,)
return {u.tag: u for u in obs.observation.raw_data.units # pylint: disable=g-complex-comprehension
if ((filter_fn is None or filter_fn(u)) and
(owner is None or u.owner == owner) and
(unit_type is None or u.unit_type in unit_type) and
(tag is None or u.tag == tag))}
def get_unit(*args, **kwargs):
"""Return the first unit that matches, or None."""
try:
return next(iter(get_units(*args, **kwargs).values()))
except StopIteration:
return None
def _xy_locs(mask):
"""Mask should be a set of bools from comparison with a feature layer."""
ys, xs = mask.nonzero()
return [point.Point(x, y) for x, y in zip(xs, ys)]
class Env(object):
"""Test the apm values of various actions."""
def __init__(self):
run_config = run_configs.get()
map_inst = maps.get("Flat64")
self._map_path = map_inst.path
self._map_data = map_inst.data(run_config)
self._sc2_proc = run_config.start(want_rgb=False)
self._controller = self._sc2_proc.controller
self._summary = []
self._features = None
def close(self):
self._controller.quit()
self._sc2_proc.close()
print(" apm name")
for name, info in self._summary:
print("%4d %s" % (info.player_info[0].player_apm, name))
def __enter__(self):
return self
def __exit__(self, unused_exception_type, unused_exc_value, unused_traceback):
self.close()
def __del__(self):
self.close()
def step(self, count=22):
self._controller.step(count)
return self._controller.observe()
def fl_obs(self, obs):
return self._features.transform_obs(obs)
def raw_unit_command(self, ability_id, unit_tags, pos=None, target=None):
"""Send a raw unit command."""
if isinstance(ability_id, str):
ability_id = actions.FUNCTIONS[ability_id].ability_id
action = sc_pb.Action()
cmd = action.action_raw.unit_command
cmd.ability_id = ability_id
if isinstance(unit_tags, (list, tuple)):
cmd.unit_tags.extend(unit_tags)
else:
cmd.unit_tags.append(unit_tags)
if pos:
cmd.target_world_space_pos.x = pos[0]
cmd.target_world_space_pos.y = pos[1]
elif target:
cmd.target_unit_tag = target
response = self._controller.act(action)
for result in response.result:
assert result == sc_error.Success
def fl_action(self, obs, act, *args):
return self._controller.act(self._features.transform_action(
obs.observation, actions.FUNCTIONS[act](*args), skip_available=True))
def check_apm(self, name):
"""Set up a game, yield, then check the apm in the replay."""
interface = sc_pb.InterfaceOptions(raw=True, score=False)
interface.feature_layer.width = 24
interface.feature_layer.resolution.x = 64
interface.feature_layer.resolution.y = 64
interface.feature_layer.minimap_resolution.x = 64
interface.feature_layer.minimap_resolution.y = 64
create = sc_pb.RequestCreateGame(
random_seed=1, local_map=sc_pb.LocalMap(map_path=self._map_path,
map_data=self._map_data))
create.player_setup.add(type=sc_pb.Participant)
create.player_setup.add(type=sc_pb.Computer, race=sc_common.Protoss,
difficulty=sc_pb.VeryEasy)
join = sc_pb.RequestJoinGame(race=sc_common.Protoss, options=interface)
self._controller.create_game(create)
self._controller.join_game(join)
self._info = self._controller.game_info()
self._features = features.features_from_game_info(
self._info, use_feature_units=True, use_raw_units=True)
self._map_size = point.Point.build(self._info.start_raw.map_size)
for i in range(60):
yield i, self.step()
data = self._controller.save_replay()
replay_info = self._controller.replay_info(data)
self._summary.append((name, replay_info))
def main(unused_argv):
env = Env()
def rand_fl_coord():
return (point.Point.unit_rand() * 64).floor()
def rand_world_coord():
return (point.Point.unit_rand() * 20).floor() + 20
def random_probe_loc(obs):
return random.choice(_xy_locs(
env.fl_obs(obs).feature_screen.unit_type == units.Protoss.Probe))
def random_probe_tag(obs):
return random.choice(get_units(obs, unit_type=units.Protoss.Probe).keys())
for i, obs in env.check_apm("no-op"):
pass
for i, obs in env.check_apm("fl stop, single probe"):
if i == 0:
env.fl_action(obs, "select_point", "select", random_probe_loc(obs))
env.fl_action(obs, "Stop_quick", "now")
for i, obs in env.check_apm("fl smart, single probe, random location"):
if i == 0:
env.fl_action(obs, "select_point", "select", random_probe_loc(obs))
env.fl_action(obs, "Smart_screen", "now", rand_fl_coord())
for i, obs in env.check_apm("fl move, single probe, random location"):
if i == 0:
env.fl_action(obs, "select_point", "select", random_probe_loc(obs))
env.fl_action(obs, "Move_screen", "now", rand_fl_coord())
for i, obs in env.check_apm("fl stop, random probe"):
env.fl_action(obs, "select_point", "select", random_probe_loc(obs))
env.fl_action(obs, "Stop_quick", "now")
for i, obs in env.check_apm("fl move, random probe, random location"):
env.fl_action(obs, "select_point", "select", random_probe_loc(obs))
env.fl_action(obs, "Move_screen", "now", rand_fl_coord())
for i, obs in env.check_apm("raw stop, random probe"):
env.raw_unit_command("Stop_quick", random_probe_tag(obs))
for i, obs in env.check_apm("raw move, random probe, random location"):
env.raw_unit_command("Move_screen", random_probe_tag(obs),
rand_world_coord())
probe = None
for i, obs in env.check_apm("raw move, single probe, random location"):
if not probe:
probe = random_probe_tag(obs)
env.raw_unit_command("Move_screen", probe, rand_world_coord())
if __name__ == "__main__":
app.run(main)
================================================
FILE: pysc2/bin/compare_binaries.py
================================================
#!/usr/bin/python
# Copyright 2019 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS-IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Compare the observations from multiple binaries."""
import collections
import sys
from absl import app
from absl import flags
from pysc2 import run_configs
from pysc2.lib import image_differencer
from pysc2.lib import proto_diff
from pysc2.lib import remote_controller
from pysc2.lib import replay
from pysc2.lib import stopwatch
from s2clientprotocol import sc2api_pb2 as sc_pb
FLAGS = flags.FLAGS
flags.DEFINE_bool("diff", False, "Whether to diff the observations.")
flags.DEFINE_integer("truncate", 0,
"Number of characters to truncate diff values to, or 0 "
"for no truncation.")
flags.DEFINE_integer("step_mul", 8, "Game steps per observation.")
flags.DEFINE_integer("count", 100000, "How many observations to run.")
flags.DEFINE_string("replay", None, "Name of a replay to show.")
def _clear_non_deterministic_fields(obs):
for unit in obs.observation.raw_data.units:
unit.ClearField("tag")
for order in unit.orders:
order.ClearField("target_unit_tag")
for action in obs.actions:
if action.HasField("action_raw"):
if action.action_raw.HasField("unit_command"):
action.action_raw.unit_command.ClearField("target_unit_tag")
def _is_remote(arg):
return ":" in arg
def main(argv):
"""Compare the observations from multiple binaries."""
if len(argv) <= 1:
sys.exit(
"Please specify binaries to run / to connect to. For binaries to run, "
"specify the executable name. For remote connections, specify "
"<hostname>:<port>. The version must match the replay.")
targets = argv[1:]
interface = sc_pb.InterfaceOptions()
interface.raw = True
interface.raw_affects_selection = True
interface.raw_crop_to_playable_area = True
interface.score = True
interface.show_cloaked = True
interface.show_placeholders = True
interface.feature_layer.width = 24
interface.feature_layer.resolution.x = 48
interface.feature_layer.resolution.y = 48
interface.feature_layer.minimap_resolution.x = 48
interface.feature_layer.minimap_resolution.y = 48
interface.feature_layer.crop_to_playable_area = True
interface.feature_layer.allow_cheating_layers = True
run_config = run_configs.get()
replay_data = run_config.replay_data(FLAGS.replay)
start_replay = sc_pb.RequestStartReplay(
replay_data=replay_data,
options=interface,
observed_player_id=1,
realtime=False)
version = replay.get_replay_version(replay_data)
timers = []
controllers = []
procs = []
for target in targets:
timer = stopwatch.StopWatch()
timers.append(timer)
with timer("launch"):
if _is_remote(target):
host, port = target.split(":")
controllers.append(remote_controller.RemoteController(host, int(port)))
else:
proc = run_configs.get(
version=version._replace(binary=target)).start(want_rgb=False)
procs.append(proc)
controllers.append(proc.controller)
diff_counts = [0] * len(controllers)
diff_paths = collections.Counter()
try:
print("-" * 80)
print(controllers[0].replay_info(replay_data))
print("-" * 80)
for controller, t in zip(controllers, timers):
with t("start_replay"):
controller.start_replay(start_replay)
# Check the static data.
static_data = []
for controller, t in zip(controllers, timers):
with t("data"):
static_data.append(controller.data_raw())
if FLAGS.diff:
diffs = {i: proto_diff.compute_diff(static_data[0], d)
for i, d in enumerate(static_data[1:], 1)}
if any(diffs.values()):
print(" Diff in static data ".center(80, "-"))
for i, diff in diffs.items():
if diff:
print(targets[i])
diff_counts[i] += 1
print(diff.report(truncate_to=FLAGS.truncate))
for path in diff.all_diffs():
diff_paths[path.with_anonymous_array_indices()] += 1
else:
print("No diffs in static data.")
# Run some steps, checking speed and diffing the observations.
for _ in range(FLAGS.count):
for controller, t in zip(controllers, timers):
with t("step"):
controller.step(FLAGS.step_mul)
obs = []
for controller, t in zip(controllers, timers):
with t("observe"):
obs.append(controller.observe())
if FLAGS.diff:
for o in obs:
_clear_non_deterministic_fields(o)
diffs = {i: proto_diff.compute_diff(obs[0], o)
for i, o in enumerate(obs[1:], 1)}
if any(diffs.values()):
print((" Diff on step: %s " %
obs[0].observation.game_loop).center(80, "-"))
for i, diff in diffs.items():
if diff:
print(targets[i])
diff_counts[i] += 1
print(diff.report([image_differencer.image_differencer],
truncate_to=FLAGS.truncate))
for path in diff.all_diffs():
diff_paths[path.with_anonymous_array_indices()] += 1
if obs[0].player_result:
break
except KeyboardInterrupt:
pass
finally:
for c in controllers:
c.quit()
c.close()
for p in procs:
p.close()
if FLAGS.diff:
print(" Diff Counts by target ".center(80, "-"))
for target, count in zip(targets, diff_counts):
print(" %5d %s" % (count, target))
print()
print(" Diff Counts by observation path ".center(80, "-"))
for path, count in diff_paths.most_common(100):
print(" %5d %s" % (count, path))
print()
print(" Timings ".center(80, "-"))
for v, t in zip(targets, timers):
print(v)
print(t)
if __name__ == "__main__":
app.run(main)
================================================
FILE: pysc2/bin/gen_actions.py
================================================
#!/usr/bin/python
# Copyright 2017 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS-IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Generate the action definitions for actions.py."""
import itertools
from absl import app
from absl import flags
from pysc2 import maps
from pysc2 import run_configs
from pysc2.lib import static_data
from s2clientprotocol import common_pb2 as sc_common
from s2clientprotocol import data_pb2 as sc_data
from s2clientprotocol import sc2api_pb2 as sc_pb
flags.DEFINE_enum("command", None, ["csv", "python"], "What to generate.")
flags.DEFINE_string("map", "Acropolis", "Which map to use.")
flags.mark_flag_as_required("command")
FLAGS = flags.FLAGS
def get_data():
"""Retrieve static data from the game."""
run_config = run_configs.get()
with run_config.start(want_rgb=False) as controller:
m = maps.get(FLAGS.map)
create = sc_pb.RequestCreateGame(local_map=sc_pb.LocalMap(
map_path=m.path, map_data=m.data(run_config)))
create.player_setup.add(type=sc_pb.Participant)
create.player_setup.add(type=sc_pb.Computer, race=sc_common.Random,
difficulty=sc_pb.VeryEasy)
join = sc_pb.RequestJoinGame(race=sc_common.Random,
options=sc_pb.InterfaceOptions(raw=True))
controller.create_game(create)
controller.join_game(join)
return controller.data()
def generate_name(ability):
return (ability.friendly_name or ability.button_name or
ability.link_name)
def sort_key(data, ability):
# Alphabetical, with specifics immediately after their generals.
name = generate_name(ability)
if ability.remaps_to_ability_id:
general = data.abilities[ability.remaps_to_ability_id]
name = "%s %s" % (generate_name(general), name)
return name
def generate_csv(data):
"""Generate a CSV of the abilities for easy commenting."""
print(",".join([
"ability_id",
"link_name",
"link_index",
"button_name",
"hotkey",
"friendly_name",
"remap_to",
"mismatch",
]))
for ability in sorted(data.abilities.values(),
key=lambda a: sort_key(data, a)):
ab_id = ability.ability_id
if ab_id in skip_abilities or (ab_id not in data.general_abilities and
ab_id not in used_abilities):
continue
general = ""
if ab_id in data.general_abilities:
general = "general"
elif ability.remaps_to_ability_id:
general = ability.remaps_to_ability_id
mismatch = ""
if ability.remaps_to_ability_id:
def check_mismatch(ability, parent, attr):
if getattr(ability, attr) != getattr(parent, attr):
return "%s: %s" % (attr, getattr(ability, attr))
parent = data.abilities[ability.remaps_to_ability_id]
mismatch = "; ".join(filter(None, [
check_mismatch(ability, parent, "available"),
check_mismatch(ability, parent, "target"),
check_mismatch(ability, parent, "allow_minimap"),
check_mismatch(ability, parent, "allow_autocast"),
check_mismatch(ability, parent, "is_building"),
check_mismatch(ability, parent, "footprint_radius"),
check_mismatch(ability, parent, "is_instant_placement"),
check_mismatch(ability, parent, "cast_range"),
]))
print(",".join(map(str, [
ability.ability_id,
ability.link_name,
ability.link_index,
ability.button_name,
ability.hotkey,
ability.friendly_name,
general,
mismatch,
])))
def generate_py_abilities(data):
"""Generate the list of functions in actions.py."""
def print_action(func_id, name, func, ab_id, general_id):
args = [func_id, '"%s"' % name, func, ab_id]
if general_id:
args.append(general_id)
print(" Function.ability(%s)," % ", ".join(str(v) for v in args))
func_ids = itertools.count(12) # Leave room for the ui funcs.
for ability in sorted(data.abilities.values(),
key=lambda a: sort_key(data, a)):
ab_id = ability.ability_id
if ab_id in skip_abilities or (ab_id not in data.general_abilities and
ab_id not in used_abilities):
continue
name = generate_name(ability).replace(" ", "_")
if ability.target in (sc_data.AbilityData.Target.Value("None"),
sc_data.AbilityData.PointOrNone):
print_action(next(func_ids), name + "_quick", "cmd_quick", ab_id,
ability.remaps_to_ability_id)
if ability.target != sc_data.AbilityData.Target.Value("None"):
print_action(next(func_ids), name+ "_screen", "cmd_screen", ab_id,
ability.remaps_to_ability_id)
if ability.allow_minimap:
print_action(next(func_ids), name + "_minimap", "cmd_minimap", ab_id,
ability.remaps_to_ability_id)
if ability.allow_autocast:
print_action(next(func_ids), name + "_autocast", "autocast", ab_id,
ability.remaps_to_ability_id)
def main(unused_argv):
data = get_data()
print("-" * 60)
if FLAGS.command == "csv":
generate_csv(data)
elif FLAGS.command == "python":
generate_py_abilities(data)
used_abilities = set(static_data.ABILITIES)
frivolous = {6, 7} # Dance and Cheer
# These need a slot id and so are exposed differently.
cancel_slot = {313, 1039, 305, 307, 309, 1832, 1834, 3672}
unload_unit = {410, 415, 397, 1440, 2373, 1409, 914, 3670}
skip_abilities = cancel_slot | unload_unit | frivolous
if __name__ == "__main__":
app.run(main)
================================================
FILE: pysc2/bin/gen_data.py
================================================
#!/usr/bin/python
# Copyright 2017 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS-IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Generate the unit definitions for units.py."""
import collections
from absl import app
from pysc2 import maps
from pysc2 import run_configs
from pysc2.lib import static_data
from s2clientprotocol import common_pb2 as sc_common
from s2clientprotocol import sc2api_pb2 as sc_pb
def get_data():
"""Get the game's static data from an actual game."""
run_config = run_configs.get()
with run_config.start(want_rgb=False) as controller:
m = maps.get("Sequencer") # Arbitrary ladder map.
create = sc_pb.RequestCreateGame(local_map=sc_pb.LocalMap(
map_path=m.path, map_data=m.data(run_config)))
create.player_setup.add(type=sc_pb.Participant)
create.player_setup.add(type=sc_pb.Computer, race=sc_common.Random,
difficulty=sc_pb.VeryEasy)
join = sc_pb.RequestJoinGame(race=sc_common.Random,
options=sc_pb.InterfaceOptions(raw=True))
controller.create_game(create)
controller.join_game(join)
return controller.data_raw()
def generate_py_units(data):
"""Generate the list of units in units.py."""
units = collections.defaultdict(list)
for unit in sorted(data.units, key=lambda a: a.name):
if unit.unit_id in static_data.UNIT_TYPES:
units[unit.race].append(unit)
def print_race(name, race):
print("class %s(enum.IntEnum):" % name)
print(' """%s units."""' % name)
for unit in units[race]:
print(" %s = %s" % (unit.name, unit.unit_id))
print("\n")
print(" units.py ".center(60, "-"))
print_race("Neutral", sc_common.NoRace)
print_race("Protoss", sc_common.Protoss)
print_race("Terran", sc_common.Terran)
print_race("Zerg", sc_common.Zerg)
def generate_py_buffs(data):
"""Generate the list of buffs in buffs.py."""
print(" buffs.py ".center(60, "-"))
print("class Buffs(enum.IntEnum):")
print(' """The list of buffs, as returned from RequestData."""')
for buff in sorted(data.buffs, key=lambda a: a.name):
if buff.name and buff.buff_id in static_data.BUFFS:
print(" %s = %s" % (buff.name, buff.buff_id))
print("\n")
def generate_py_upgrades(data):
"""Generate the list of upgrades in upgrades.py."""
print(" upgrades.py ".center(60, "-"))
print("class Upgrades(enum.IntEnum):")
print(' """The list of upgrades, as returned from RequestData."""')
for upgrade in sorted(data.upgrades, key=lambda a: a.name):
if upgrade.name and upgrade.upgrade_id in static_data.UPGRADES:
print(" %s = %s" % (upgrade.name, upgrade.upgrade_id))
print("\n")
def main(unused_argv):
data = get_data()
generate_py_units(data)
generate_py_buffs(data)
generate_py_upgrades(data)
if __name__ == "__main__":
app.run(main)
================================================
FILE: pysc2/bin/gen_versions.py
================================================
#!/usr/bin/python
# Copyright 2017 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS-IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Generate the list of versions for run_configs."""
from absl import app
import requests
# raw version of:
# https://github.com/Blizzard/s2client-proto/blob/master/buildinfo/versions.json
VERSIONS_FILE = "https://raw.githubusercontent.com/Blizzard/s2client-proto/master/buildinfo/versions.json"
def main(argv):
del argv # Unused.
versions = requests.get(VERSIONS_FILE).json()
for v in versions:
version_str = v["label"]
if version_str.count(".") == 1:
version_str += ".0"
print(' Version("%s", %i, "%s", None),' % (
version_str, v["base-version"], v["data-hash"]))
if __name__ == "__main__":
app.run(main)
================================================
FILE: pysc2/bin/map_list.py
================================================
#!/usr/bin/python
# Copyright 2017 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS-IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Print the list of defined maps."""
from absl import app
from pysc2 import maps
def main(unused_argv):
for _, map_class in sorted(maps.get_maps().items()):
mp = map_class()
if mp.path:
print(mp, "\n")
if __name__ == "__main__":
app.run(main)
================================================
FILE: pysc2/bin/mem_leak_check.py
================================================
#!/usr/bin/python
# Copyright 2018 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS-IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Test for memory leaks."""
# pylint: disable=g-import-not-at-top
import collections
import random
import sys
import time
from absl import app
from absl import flags
try:
import psutil
except ImportError:
sys.exit(
"`psutil` library required to track memory. This can be installed with:\n"
"$ pip install psutil\n"
"and needs the python-dev headers installed, for example:\n"
"$ apt install python-dev")
from pysc2 import maps
from pysc2 import run_configs
from pysc2.lib import protocol
from s2clientprotocol import common_pb2 as sc_common
from s2clientprotocol import sc2api_pb2 as sc_pb
# pylint: enable=g-import-not-at-top
races = {
"random": sc_common.Random,
"protoss": sc_common.Protoss,
"terran": sc_common.Terran,
"zerg": sc_common.Zerg,
}
flags.DEFINE_integer("mem_limit", 2000, "Max memory usage in Mb.")
flags.DEFINE_integer("episodes", 200, "Max number of episodes.")
flags.DEFINE_enum("race", "random", races.keys(), "Which race to play as.")
flags.DEFINE_list("map", "Catalyst", "Which map(s) to test on.")
FLAGS = flags.FLAGS
class Timestep(collections.namedtuple(
"Timestep", ["episode", "time", "cpu", "memory", "name"])):
def __str__(self):
return "[%3d: %7.3f] cpu: %5.1f s, mem: %4d Mb; %s" % self
def main(unused_argv):
for m in FLAGS.map: # Verify they're all valid.
maps.get(m)
interface = sc_pb.InterfaceOptions()
interface.raw = True
interface.score = True
interface.feature_layer.width = 24
interface.feature_layer.resolution.x = 84
interface.feature_layer.resolution.y = 84
interface.feature_layer.minimap_resolution.x = 64
interface.feature_layer.minimap_resolution.y = 64
timeline = []
start = time.time()
run_config = run_configs.get()
proc = run_config.start(want_rgb=interface.HasField("render"))
process = psutil.Process(proc.pid)
episode = 1
def add(s):
cpu_times = process.cpu_times() # pytype: disable=wrong-arg-count
cpu = cpu_times.user + cpu_times.system
mem = process.memory_info().rss / 2 ** 20 # In Mb # pytype: disable=wrong-arg-count
step = Timestep(episode, time.time() - start, cpu, mem, s)
print(step)
timeline.append(step)
if mem > FLAGS.mem_limit:
raise MemoryError("%s Mb mem limit exceeded" % FLAGS.mem_limit)
try:
add("Started process")
controller = proc.controller
for _ in range(FLAGS.episodes):
map_inst = maps.get(random.choice(FLAGS.map))
create = sc_pb.RequestCreateGame(
realtime=False, disable_fog=False, random_seed=episode,
local_map=sc_pb.LocalMap(map_path=map_inst.path,
map_data=map_inst.data(run_config)))
create.player_setup.add(type=sc_pb.Participant)
create.player_setup.add(type=sc_pb.Computer, race=races[FLAGS.race],
difficulty=sc_pb.CheatInsane)
join = sc_pb.RequestJoinGame(race=races[FLAGS.race], options=interface)
controller.create_game(create)
add("Created game on %s" % map_inst.name)
controller.join_game(join)
add("Joined game")
for i in range(2000):
controller.step(16)
obs = controller.observe()
if obs.player_result:
add("Lost on step %s" % i)
break
if i > 0 and i % 100 == 0:
add("Step %s" % i)
episode += 1
add("Done")
except KeyboardInterrupt:
pass
except (MemoryError, protocol.ConnectionError) as e:
print(e)
finally:
proc.close()
print("Timeline:")
for t in timeline:
print(t)
if __name__ == "__main__":
app.run(main)
================================================
FILE: pysc2/bin/play.py
================================================
#!/usr/bin/python
# Copyright 2017 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS-IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Run SC2 to play a game or a replay."""
import getpass
import platform
import sys
import time
from absl import app
from absl import flags
from pysc2 import maps
from pysc2 import run_configs
from pysc2.env import sc2_env
from pysc2.lib import point_flag
from pysc2.lib import renderer_human
from pysc2.lib import replay
from pysc2.lib import stopwatch
from s2clientprotocol import sc2api_pb2 as sc_pb
FLAGS = flags.FLAGS
flags.DEFINE_bool("render", True, "Whether to render with pygame.")
flags.DEFINE_bool("realtime", False, "Whether to run in realtime mode.")
flags.DEFINE_bool("full_screen", False, "Whether to run full screen.")
flags.DEFINE_float("fps", 22.4, "Frames per second to run the game.")
flags.DEFINE_integer("step_mul", 1, "Game steps per observation.")
flags.DEFINE_bool("render_sync", False, "Turn on sync rendering.")
point_flag.DEFINE_point("feature_screen_size", "84",
"Resolution for screen feature layers.")
point_flag.DEFINE_point("feature_minimap_size", "64",
"Resolution for minimap feature layers.")
flags.DEFINE_integer("feature_camera_width", 24,
"Width of the feature layer camera.")
point_flag.DEFINE_point("rgb_screen_size", "256,192",
"Resolution for rendered screen.")
point_flag.DEFINE_point("rgb_minimap_size", "128",
"Resolution for rendered minimap.")
point_flag.DEFINE_point("window_size", "640,480",
"Screen size if not full screen.")
flags.DEFINE_string("video", None, "Path to render a video of observations.")
flags.DEFINE_integer("max_game_steps", 0, "Total game steps to run.")
flags.DEFINE_integer("max_episode_steps", 0, "Total game steps per episode.")
flags.DEFINE_string("user_name", getpass.getuser(),
"Name of the human player for replays.")
flags.DEFINE_enum("user_race", "random", sc2_env.Race._member_names_, # pylint: disable=protected-access
"User's race.")
flags.DEFINE_enum("bot_race", "random", sc2_env.Race._member_names_, # pylint: disable=protected-access
"AI race.")
flags.DEFINE_enum("difficulty", "very_easy", sc2_env.Difficulty._member_names_, # pylint: disable=protected-access
"Bot's strength.")
flags.DEFINE_enum("bot_build", "random", sc2_env.BotBuild._member_names_, # pylint: disable=protected-access
"Bot's build strategy.")
flags.DEFINE_bool("disable_fog", False, "Disable fog of war.")
flags.DEFINE_integer("observed_player", 1, "Which player to observe.")
flags.DEFINE_bool("profile", False, "Whether to turn on code profiling.")
flags.DEFINE_bool("trace", False, "Whether to trace the code execution.")
flags.DEFINE_bool("save_replay", True, "Whether to save a replay at the end.")
flags.DEFINE_string("map", None, "Name of a map to use to play.")
flags.DEFINE_bool("battle_net_map", False, "Use the battle.net map version.")
flags.DEFINE_string("map_path", None, "Override the map for this replay.")
flags.DEFINE_string("replay", None, "Name of a replay to show.")
def main(unused_argv):
"""Run SC2 to play a game or a replay."""
if FLAGS.trace:
stopwatch.sw.trace()
elif FLAGS.profile:
stopwatch.sw.enable()
if (FLAGS.map and FLAGS.replay) or (not FLAGS.map and not FLAGS.replay):
sys.exit("Must supply either a map or replay.")
if FLAGS.replay and not FLAGS.replay.lower().endswith("sc2replay"):
sys.exit("Replay must end in .SC2Replay.")
if FLAGS.realtime and FLAGS.replay:
# TODO(tewalds): Support realtime in replays once the game supports it.
sys.exit("realtime isn't possible for replays yet.")
if FLAGS.render and (FLAGS.realtime or FLAGS.full_screen):
sys.exit("disable pygame rendering if you want realtime or full_screen.")
if platform.system() == "Linux" and (FLAGS.realtime or FLAGS.full_screen):
sys.exit("realtime and full_screen only make sense on Windows/MacOS.")
if not FLAGS.render and FLAGS.render_sync:
sys.exit("render_sync only makes sense with pygame rendering on.")
run_config = run_configs.get()
interface = sc_pb.InterfaceOptions()
interface.raw = FLAGS.render
interface.raw_affects_selection = True
interface.raw_crop_to_playable_area = True
interface.score = True
interface.show_cloaked = True
interface.show_burrowed_shadows = True
interface.show_placeholders = True
if FLAGS.feature_screen_size and FLAGS.feature_minimap_size:
interface.feature_layer.width = FLAGS.feature_camera_width
FLAGS.feature_screen_size.assign_to(interface.feature_layer.resolution)
FLAGS.feature_minimap_size.assign_to(
interface.feature_layer.minimap_resolution)
interface.feature_layer.crop_to_playable_area = True
interface.feature_layer.allow_cheating_layers = True
if FLAGS.render and FLAGS.rgb_screen_size and FLAGS.rgb_minimap_size:
FLAGS.rgb_screen_size.assign_to(interface.render.resolution)
FLAGS.rgb_minimap_size.assign_to(interface.render.minimap_resolution)
max_episode_steps = FLAGS.max_episode_steps
if FLAGS.map:
create = sc_pb.RequestCreateGame(
realtime=FLAGS.realtime,
disable_fog=FLAGS.disable_fog)
try:
map_inst = maps.get(FLAGS.map)
except maps.lib.NoMapError:
if FLAGS.battle_net_map:
create.battlenet_map_name = FLAGS.map
else:
raise
else:
if map_inst.game_steps_per_episode:
max_episode_steps = map_inst.game_steps_per_episode
if FLAGS.battle_net_map:
create.battlenet_map_name = map_inst.battle_net
else:
create.local_map.map_path = map_inst.path
create.local_map.map_data = map_inst.data(run_config)
create.player_setup.add(type=sc_pb.Participant)
create.player_setup.add(type=sc_pb.Computer,
race=sc2_env.Race[FLAGS.bot_race],
difficulty=sc2_env.Difficulty[FLAGS.difficulty],
ai_build=sc2_env.BotBuild[FLAGS.bot_build])
join = sc_pb.RequestJoinGame(
options=interface, race=sc2_env.Race[FLAGS.user_race],
player_name=FLAGS.user_name)
version = None
else:
replay_data = run_config.replay_data(FLAGS.replay)
start_replay = sc_pb.RequestStartReplay(
replay_data=replay_data,
options=interface,
disable_fog=FLAGS.disable_fog,
observed_player_id=FLAGS.observed_player)
version = replay.get_replay_version(replay_data)
run_config = run_configs.get(version=version) # Replace the run config.
with run_config.start(
full_screen=FLAGS.full_screen,
window_size=FLAGS.window_size,
want_rgb=interface.HasField("render")) as controller:
if FLAGS.map:
controller.create_game(create)
controller.join_game(join)
else:
info = controller.replay_info(replay_data)
print(" Replay info ".center(60, "-"))
print(info)
print("-" * 60)
map_path = FLAGS.map_path or info.local_map_path
if map_path:
start_replay.map_data = run_config.map_data(map_path,
len(info.player_info))
controller.start_replay(start_replay)
if FLAGS.render:
renderer = renderer_human.RendererHuman(
fps=FLAGS.fps, step_mul=FLAGS.step_mul,
render_sync=FLAGS.render_sync, video=FLAGS.video)
renderer.run(
run_config, controller, max_game_steps=FLAGS.max_game_steps,
game_steps_per_episode=max_episode_steps,
save_replay=FLAGS.save_replay)
else: # Still step forward so the Mac/Windows renderer works.
try:
while True:
frame_start_time = time.time()
if not FLAGS.realtime:
controller.step(FLAGS.step_mul)
obs = controller.observe()
if obs.player_result:
break
time.sleep(max(0, frame_start_time + 1 / FLAGS.fps - time.time()))
except KeyboardInterrupt:
pass
print("Score: ", obs.observation.score.score)
print("Result: ", obs.player_result)
if FLAGS.map and FLAGS.save_replay:
replay_save_loc = run_config.save_replay(
controller.save_replay(), "local", FLAGS.map)
print("Replay saved to:", replay_save_loc)
# Save scores so we know how the human player did.
with open(replay_save_loc.replace("SC2Replay", "txt"), "w") as f:
f.write("{}\n".format(obs.observation.score.score))
if FLAGS.profile:
print(stopwatch.sw)
def entry_point(): # Needed so setup.py scripts work.
app.run(main)
if __name__ == "__main__":
app.run(main)
================================================
FILE: pysc2/bin/play_vs_agent.py
================================================
#!/usr/bin/python
# Copyright 2017 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS-IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Play as a human against an agent by setting up a LAN game.
This needs to be called twice, once for the human, and once for the agent.
The human plays on the host. There you run it as:
$ python -m pysc2.bin.play_vs_agent --human --map <map> --remote <agent ip>
And on the machine the agent plays on:
$ python -m pysc2.bin.play_vs_agent --agent <import path>
The `--remote` arg is used to create an SSH tunnel to the remote agent's
machine, so can be dropped if it's running on the same machine.
SC2 is limited to only allow LAN games on localhost, so we need to forward the
ports between machines. SSH is used to do this with the `--remote` arg. If the
agent is on the same machine as the host, this arg can be dropped. SSH doesn't
forward UDP, so this also sets up a UDP proxy. As part of that it sets up a TCP
server that is also used as a settings server. Note that you won't have an
opportunity to give ssh a password, so you must use ssh keys for authentication.
"""
import getpass
import importlib
import platform
import sys
import time
from absl import app
from absl import flags
from absl import logging
import portpicker
from pysc2 import maps
from pysc2 import run_configs
from pysc2.env import lan_sc2_env
from pysc2.env import run_loop
from pysc2.env import sc2_env
from pysc2.lib import point_flag
from pysc2.lib import renderer_human
from s2clientprotocol import sc2api_pb2 as sc_pb
FLAGS = flags.FLAGS
flags.DEFINE_bool("render", platform.system() == "Linux",
"Whether to render with pygame.")
flags.DEFINE_bool("realtime", False, "Whether to run in realtime mode.")
flags.DEFINE_string("agent", "pysc2.agents.random_agent.RandomAgent",
"Which agent to run, as a python path to an Agent class.")
flags.DEFINE_string("agent_name", None,
"Name of the agent in replays. Defaults to the class name.")
flags.DEFINE_enum("agent_race", "random", sc2_env.Race._member_names_, # pylint: disable=protected-access
"Agent's race.")
flags.DEFINE_float("fps", 22.4, "Frames per second to run the game.")
flags.DEFINE_integer("step_mul", 8, "Game steps per agent step.")
point_flag.DEFINE_point("feature_screen_size", "84",
"Resolution for screen feature layers.")
point_flag.DEFINE_point("feature_minimap_size", "64",
"Resolution for minimap feature layers.")
point_flag.DEFINE_point("rgb_screen_size", "256",
"Resolution for rendered screen.")
point_flag.DEFINE_point("rgb_minimap_size", "128",
"Resolution for rendered minimap.")
flags.DEFINE_enum("action_space", "FEATURES",
sc2_env.ActionSpace._member_names_, # pylint: disable=protected-access
"Which action space to use. Needed if you take both feature "
"and rgb observations.")
flags.DEFINE_bool("use_feature_units", False,
"Whether to include feature units.")
flags.DEFINE_string("user_name", getpass.getuser(),
"Name of the human player for replays.")
flags.DEFINE_enum("user_race", "random", sc2_env.Race._member_names_, # pylint: disable=protected-access
"User's race.")
flags.DEFINE_string("host", "127.0.0.1", "Game Host. Can be 127.0.0.1 or ::1")
flags.DEFINE_integer(
"config_port", 14380,
"Where to set/find the config port. The host starts a tcp server to share "
"the config with the client, and to proxy udp traffic if played over an "
"ssh tunnel. This sets that port, and is also the start of the range of "
"ports used for LAN play.")
flags.DEFINE_string("remote", None,
"Where to set up the ssh tunnels to the client.")
flags.DEFINE_string("map", None, "Name of a map to use to play.")
flags.DEFINE_bool("human", False, "Whether to host a game as a human.")
def main(unused_argv):
if FLAGS.human:
human()
else:
agent()
def agent():
"""Run the agent, connecting to a (remote) host started independently."""
agent_module, agent_name = FLAGS.agent.rsplit(".", 1)
agent_cls = getattr(importlib.import_module(agent_module), agent_name)
logging.info("Starting agent:")
with lan_sc2_env.LanSC2Env(
host=FLAGS.host,
config_port=FLAGS.config_port,
race=sc2_env.Race[FLAGS.agent_race],
step_mul=FLAGS.step_mul,
realtime=FLAGS.realtime,
agent_interface_format=sc2_env.parse_agent_interface_format(
feature_screen=FLAGS.feature_screen_size,
feature_minimap=FLAGS.feature_minimap_size,
rgb_screen=FLAGS.rgb_screen_size,
rgb_minimap=FLAGS.rgb_minimap_size,
action_space=FLAGS.action_space,
use_unit_counts=True,
use_camera_position=True,
show_cloaked=True,
show_burrowed_shadows=True,
show_placeholders=True,
send_observation_proto=True,
crop_to_playable_area=True,
raw_crop_to_playable_area=True,
allow_cheating_layers=True,
add_cargo_to_units=True,
use_feature_units=FLAGS.use_feature_units),
visualize=FLAGS.render) as env:
agents = [agent_cls()]
logging.info("Connected, starting run_loop.")
try:
run_loop.run_loop(agents, env)
except lan_sc2_env.RestartError:
pass
logging.info("Done.")
def human():
"""Run a host which expects one player to connect remotely."""
run_config = run_configs.get()
map_inst = maps.get(FLAGS.map)
if not FLAGS.rgb_screen_size or not FLAGS.rgb_minimap_size:
logging.info("Use --rgb_screen_size and --rgb_minimap_size if you want rgb "
"observations.")
ports = [FLAGS.config_port + p for p in range(5)] # tcp + 2 * num_players
if not all(portpicker.is_port_free(p) for p in ports):
sys.exit("Need 5 free ports after the config port.")
proc = None
ssh_proc = None
tcp_conn = None
udp_sock = None
try:
proc = run_config.start(extra_ports=ports[1:], timeout_seconds=300,
host=FLAGS.host, window_loc=(50, 50))
tcp_port = ports[0]
settings = {
"remote": FLAGS.remote,
"game_version": proc.version.game_version,
"realtime": FLAGS.realtime,
"map_name": map_inst.name,
"map_path": map_inst.path,
"map_data": map_inst.data(run_config),
"ports": {
"server": {"game": ports[1], "base": ports[2]},
"client": {"game": ports[3], "base": ports[4]},
}
}
create = sc_pb.RequestCreateGame(
realtime=settings["realtime"],
local_map=sc_pb.LocalMap(map_path=settings["map_path"]))
create.player_setup.add(type=sc_pb.Participant)
create.player_setup.add(type=sc_pb.Participant)
controller = proc.controller
controller.save_map(settings["map_path"], settings["map_data"])
controller.create_game(create)
if FLAGS.remote:
ssh_proc = lan_sc2_env.forward_ports(
FLAGS.remote, proc.host, [settings["ports"]["client"]["base"]],
[tcp_port, settings["ports"]["server"]["base"]])
print("-" * 80)
print("Join: play_vs_agent --host %s --config_port %s" % (proc.host,
tcp_port))
print("-" * 80)
tcp_conn = lan_sc2_env.tcp_server(
lan_sc2_env.Addr(proc.host, tcp_port), settings)
if FLAGS.remote:
udp_sock = lan_sc2_env.udp_server(
lan_sc2_env.Addr(proc.host, settings["ports"]["client"]["game"]))
lan_sc2_env.daemon_thread(
lan_sc2_env.tcp_to_udp,
(tcp_conn, udp_sock,
lan_sc2_env.Addr(proc.host, settings["ports"]["server"]["game"])))
lan_sc2_env.daemon_thread(lan_sc2_env.udp_to_tcp, (udp_sock, tcp_conn))
join = sc_pb.RequestJoinGame()
join.shared_port = 0 # unused
join.server_ports.game_port = settings["ports"]["server"]["game"]
join.server_ports.base_port = settings["ports"]["server"]["base"]
join.client_ports.add(game_port=settings["ports"]["client"]["game"],
base_port=settings["ports"]["client"]["base"])
join.race = sc2_env.Race[FLAGS.user_race]
join.player_name = FLAGS.user_name
if FLAGS.render:
join.options.raw = True
join.options.score = True
join.options.raw_affects_selection = True
join.options.raw_crop_to_playable_area = True
join.options.show_cloaked = True
join.options.show_burrowed_shadows = True
join.options.show_placeholders = True
if FLAGS.feature_screen_size and FLAGS.feature_minimap_size:
fl = join.options.feature_layer
fl.width = 24
FLAGS.feature_screen_size.assign_to(fl.resolution)
FLAGS.feature_minimap_size.assign_to(fl.minimap_resolution)
if FLAGS.rgb_screen_size and FLAGS.rgb_minimap_size:
FLAGS.rgb_screen_size.assign_to(join.options.render.resolution)
FLAGS.rgb_minimap_size.assign_to(join.options.render.minimap_resolution)
controller.join_game(join)
if FLAGS.render:
renderer = renderer_human.RendererHuman(
fps=FLAGS.fps, render_feature_grid=False)
renderer.run(run_configs.get(), controller, max_episodes=1)
else: # Still step forward so the Mac/Windows renderer works.
while True:
frame_start_time = time.time()
if not FLAGS.realtime:
controller.step()
obs = controller.observe()
if obs.player_result:
break
time.sleep(max(0, frame_start_time - time.time() + 1 / FLAGS.fps))
except KeyboardInterrupt:
pass
finally:
if tcp_conn:
tcp_conn.close()
if proc:
proc.close()
if udp_sock:
udp_sock.close()
if ssh_proc:
ssh_proc.terminate()
for _ in range(5):
if ssh_proc.poll() is not None:
break
time.sleep(1)
if ssh_proc.poll() is None:
ssh_proc.kill()
ssh_proc.wait()
def entry_point(): # Needed so setup.py scripts work.
app.run(main)
if __name__ == "__main__":
app.run(main)
================================================
FILE: pysc2/bin/reencode_replays.py
================================================
#!/usr/bin/python
# Copyright 2019 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS-IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Run through a set of replays, generating new replays from them."""
import os
from absl import app
from absl import flags
from pysc2 import run_configs
from pysc2.lib import replay
from s2clientprotocol import sc2api_pb2 as sc_pb
FLAGS = flags.FLAGS
flags.DEFINE_string("input_dir", None, "Director
gitextract_2o40zztk/ ├── .gitignore ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── WORKSPACE ├── bazel/ │ ├── BUILD │ ├── BUILD.dm_env │ ├── BUILD.dm_env_rpc │ ├── BUILD.s2protocol │ ├── create_external_repos.bzl │ ├── protobuf.patch │ ├── requirements.txt │ ├── s2clientprotocol.patch │ └── setup_external_repos.bzl ├── docs/ │ ├── bazel.md │ ├── converters.md │ ├── environment.md │ ├── maps.md │ └── mini_games.md ├── pysc2/ │ ├── BUILD │ ├── __init__.py │ ├── agents/ │ │ ├── BUILD │ │ ├── __init__.py │ │ ├── base_agent.py │ │ ├── no_op_agent.py │ │ ├── random_agent.py │ │ └── scripted_agent.py │ ├── bin/ │ │ ├── BUILD │ │ ├── __init__.py │ │ ├── agent.py │ │ ├── agent_remote.py │ │ ├── battle_net_maps.py │ │ ├── benchmark_observe.py │ │ ├── benchmark_replay.py │ │ ├── check_apm.py │ │ ├── compare_binaries.py │ │ ├── gen_actions.py │ │ ├── gen_data.py │ │ ├── gen_versions.py │ │ ├── map_list.py │ │ ├── mem_leak_check.py │ │ ├── play.py │ │ ├── play_vs_agent.py │ │ ├── reencode_replays.py │ │ ├── replay_actions.py │ │ ├── replay_info.py │ │ ├── replay_version.py │ │ ├── run_tests.py │ │ ├── update_battle_net_cache.py │ │ └── valid_actions.py │ ├── build_defs.bzl │ ├── env/ │ │ ├── BUILD │ │ ├── __init__.py │ │ ├── available_actions_printer.py │ │ ├── base_env_wrapper.py │ │ ├── converted_env.py │ │ ├── converted_env_test.py │ │ ├── converter/ │ │ │ ├── BUILD │ │ │ ├── __init__.py │ │ │ ├── cc/ │ │ │ │ ├── BUILD │ │ │ │ ├── __init__.py │ │ │ │ ├── castops.h │ │ │ │ ├── check_protos_equal.h │ │ │ │ ├── convert_obs.cc │ │ │ │ ├── convert_obs.h │ │ │ │ ├── convert_obs_test.cc │ │ │ │ ├── converter.cc │ │ │ │ ├── converter.h │ │ │ │ ├── converter_test.cc │ │ │ │ ├── encode_image_data.h │ │ │ │ ├── features.cc │ │ │ │ ├── features.h │ │ │ │ ├── file_util.cc │ │ │ │ ├── file_util.h │ │ │ │ ├── game_data/ │ │ │ │ │ ├── BUILD │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── proto/ │ │ │ │ │ │ ├── BUILD │ │ │ │ │ │ ├── __init__.py │ │ │ │ │ │ ├── buffs.proto │ │ │ │ │ │ ├── units.proto │ │ │ │ │ │ └── upgrades.proto │ │ │ │ │ ├── python/ │ │ │ │ │ │ ├── BUILD │ │ │ │ │ │ ├── __init__.py │ │ │ │ │ │ ├── uint8_lookup.cc │ │ │ │ │ │ └── uint8_lookup_test.py │ │ │ │ │ ├── raw_actions.cc │ │ │ │ │ ├── raw_actions.h │ │ │ │ │ ├── uint8_lookup.cc │ │ │ │ │ ├── uint8_lookup.h │ │ │ │ │ ├── visual_actions.cc │ │ │ │ │ └── visual_actions.h │ │ │ │ ├── general_order_ids.cc │ │ │ │ ├── general_order_ids.h │ │ │ │ ├── map_util.cc │ │ │ │ ├── map_util.h │ │ │ │ ├── python/ │ │ │ │ │ ├── BUILD │ │ │ │ │ ├── __init__.py │ │ │ │ │ └── converter.cc │ │ │ │ ├── raw_actions_encoder.cc │ │ │ │ ├── raw_actions_encoder.h │ │ │ │ ├── raw_actions_encoder_test.cc │ │ │ │ ├── raw_camera.cc │ │ │ │ ├── raw_camera.h │ │ │ │ ├── raw_converter.cc │ │ │ │ ├── raw_converter.h │ │ │ │ ├── tensor_util.cc │ │ │ │ ├── tensor_util.h │ │ │ │ ├── test_data/ │ │ │ │ │ ├── BUILD │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── actions/ │ │ │ │ │ │ ├── feature_camera_move.pbtxt │ │ │ │ │ │ ├── feature_unit_command.pbtxt │ │ │ │ │ │ ├── feature_unit_selection_point.pbtxt │ │ │ │ │ │ ├── ui_control_group_append.pbtxt │ │ │ │ │ │ └── ui_control_group_recall.pbtxt │ │ │ │ │ ├── obs_data1.pbtxt │ │ │ │ │ └── recordings/ │ │ │ │ │ └── tvt_trunk.pb │ │ │ │ ├── unit_lookups.cc │ │ │ │ ├── unit_lookups.h │ │ │ │ ├── unit_lookups_test.cc │ │ │ │ ├── visual_actions.cc │ │ │ │ ├── visual_actions.h │ │ │ │ ├── visual_actions_test.cc │ │ │ │ ├── visual_converter.cc │ │ │ │ ├── visual_converter.h │ │ │ │ └── visual_converter_test.cc │ │ │ ├── converter.py │ │ │ ├── converter_test.py │ │ │ ├── derive_interface_options.py │ │ │ └── proto/ │ │ │ ├── BUILD │ │ │ ├── __init__.py │ │ │ └── converter.proto │ │ ├── enums.py │ │ ├── environment.py │ │ ├── host_remote_agent.py │ │ ├── lan_sc2_env.py │ │ ├── mock_sc2_env.py │ │ ├── mock_sc2_env_comparison_test.py │ │ ├── mock_sc2_env_test.py │ │ ├── remote_sc2_env.py │ │ ├── run_loop.py │ │ ├── sc2_env.py │ │ └── sc2_env_test.py │ ├── lib/ │ │ ├── BUILD │ │ ├── __init__.py │ │ ├── actions.py │ │ ├── buffs.py │ │ ├── colors.py │ │ ├── features.py │ │ ├── features_test.py │ │ ├── gfile.py │ │ ├── image_differencer.py │ │ ├── image_differencer_test.py │ │ ├── memoize.py │ │ ├── metrics.py │ │ ├── named_array.py │ │ ├── named_array_test.py │ │ ├── np_util.py │ │ ├── np_util_test.py │ │ ├── point.py │ │ ├── point_flag.py │ │ ├── point_test.py │ │ ├── portspicker.py │ │ ├── portspicker_test.py │ │ ├── proto_diff.py │ │ ├── proto_diff_test.py │ │ ├── protocol.py │ │ ├── remote_controller.py │ │ ├── renderer_ascii.py │ │ ├── renderer_human.py │ │ ├── replay/ │ │ │ ├── BUILD │ │ │ ├── __init__.py │ │ │ ├── replay_converter.py │ │ │ ├── replay_observation_stream.py │ │ │ ├── sc2_replay.py │ │ │ ├── sc2_replay_test.py │ │ │ ├── sc2_replay_utils.py │ │ │ ├── sc2_replay_utils_test.py │ │ │ └── test_data/ │ │ │ ├── replay_01.SC2Replay │ │ │ ├── replay_01.skips.txt │ │ │ ├── replay_02.SC2Replay │ │ │ ├── replay_02.skips.txt │ │ │ ├── replay_03.SC2Replay │ │ │ ├── replay_03.skips.txt │ │ │ ├── replay_04.SC2Replay │ │ │ ├── replay_04.skips.txt │ │ │ ├── replay_05.SC2Replay │ │ │ ├── replay_05.skips.txt │ │ │ ├── replay_06.SC2Replay │ │ │ ├── replay_06.skips.txt │ │ │ ├── replay_07.SC2Replay │ │ │ ├── replay_07.skips.txt │ │ │ ├── replay_08.SC2Replay │ │ │ ├── replay_08.skips.txt │ │ │ ├── replay_09.SC2Replay │ │ │ └── replay_09.skips.txt │ │ ├── replay.py │ │ ├── resources.py │ │ ├── run_parallel.py │ │ ├── run_parallel_test.py │ │ ├── sc_process.py │ │ ├── static_data.py │ │ ├── stopwatch.py │ │ ├── stopwatch_test.py │ │ ├── transform.py │ │ ├── units.py │ │ ├── upgrades.py │ │ └── video_writer.py │ ├── maps/ │ │ ├── BUILD │ │ ├── __init__.py │ │ ├── ladder.py │ │ ├── lib.py │ │ ├── melee.py │ │ ├── mini_games/ │ │ │ ├── BuildMarines.SC2Map │ │ │ ├── CollectMineralShards.SC2Map │ │ │ ├── CollectMineralsAndGas.SC2Map │ │ │ ├── DefeatRoaches.SC2Map │ │ │ ├── DefeatZerglingsAndBanelings.SC2Map │ │ │ ├── FindAndDefeatZerglings.SC2Map │ │ │ └── MoveToBeacon.SC2Map │ │ └── mini_games.py │ ├── run_configs/ │ │ ├── BUILD │ │ ├── __init__.py │ │ ├── lib.py │ │ └── platforms.py │ └── tests/ │ ├── BUILD │ ├── __init__.py │ ├── actions_test.py │ ├── debug_test.py │ ├── dummy_observation.py │ ├── dummy_observation_test.py │ ├── easy_scripted_test.py │ ├── general_actions_test.py │ ├── host_remote_agent_test.py │ ├── multi_player_env_test.py │ ├── multi_player_test.py │ ├── obs_spec_test.py │ ├── obs_test.py │ ├── observer_test.py │ ├── ping_test.py │ ├── protocol_error_test.py │ ├── random_agent_test.py │ ├── render_test.py │ ├── replay_obs_test.py │ ├── step_mul_override_test.py │ ├── utils.py │ └── versions_test.py └── setup.py
SYMBOL INDEX (1456 symbols across 157 files)
FILE: pysc2/__init__.py
function load_tests (line 19) | def load_tests(loader, standard_tests, unused_pattern):
FILE: pysc2/agents/base_agent.py
class BaseAgent (line 19) | class BaseAgent(object):
method __init__ (line 25) | def __init__(self):
method setup (line 32) | def setup(self, obs_spec, action_spec):
method reset (line 36) | def reset(self):
method step (line 39) | def step(self, obs):
FILE: pysc2/agents/no_op_agent.py
class NoOpAgent (line 21) | class NoOpAgent(base_agent.BaseAgent):
method step (line 24) | def step(self, obs):
FILE: pysc2/agents/random_agent.py
class RandomAgent (line 22) | class RandomAgent(base_agent.BaseAgent):
method step (line 25) | def step(self, obs):
FILE: pysc2/agents/scripted_agent.py
function _xy_locs (line 30) | def _xy_locs(mask):
class MoveToBeacon (line 36) | class MoveToBeacon(base_agent.BaseAgent):
method step (line 39) | def step(self, obs):
class CollectMineralShards (line 52) | class CollectMineralShards(base_agent.BaseAgent):
method step (line 55) | def step(self, obs):
class CollectMineralShardsFeatureUnits (line 71) | class CollectMineralShardsFeatureUnits(base_agent.BaseAgent):
method setup (line 80) | def setup(self, obs_spec, action_spec):
method reset (line 85) | def reset(self):
method step (line 90) | def step(self, obs):
class CollectMineralShardsRaw (line 128) | class CollectMineralShardsRaw(base_agent.BaseAgent):
method setup (line 136) | def setup(self, obs_spec, action_spec):
method reset (line 141) | def reset(self):
method step (line 146) | def step(self, obs):
class DefeatRoaches (line 175) | class DefeatRoaches(base_agent.BaseAgent):
method step (line 178) | def step(self, obs):
class DefeatRoachesRaw (line 196) | class DefeatRoachesRaw(base_agent.BaseAgent):
method setup (line 199) | def setup(self, obs_spec, action_spec):
method step (line 204) | def step(self, obs):
FILE: pysc2/bin/agent.py
function run_thread (line 83) | def run_thread(agent_classes, players, map_name, visualize):
function main (line 108) | def main(unused_argv):
function entry_point (line 154) | def entry_point(): # Needed so setup.py scripts work.
FILE: pysc2/bin/agent_remote.py
function main (line 113) | def main(unused_argv):
function agent (line 120) | def agent():
function human (line 151) | def human():
function entry_point (line 228) | def entry_point(): # Needed so setup.py scripts work.
FILE: pysc2/bin/battle_net_maps.py
function main (line 22) | def main(unused_argv):
FILE: pysc2/bin/benchmark_observe.py
function interface_options (line 38) | def interface_options(score=False, raw=False, features=None, rgb=None,
function main (line 83) | def main(unused_argv):
FILE: pysc2/bin/benchmark_replay.py
function main (line 47) | def main(argv):
FILE: pysc2/bin/check_apm.py
function get_units (line 31) | def get_units(obs, filter_fn=None, owner=None, unit_type=None, tag=None):
function get_unit (line 42) | def get_unit(*args, **kwargs):
function _xy_locs (line 50) | def _xy_locs(mask):
class Env (line 56) | class Env(object):
method __init__ (line 59) | def __init__(self):
method close (line 70) | def close(self):
method __enter__ (line 78) | def __enter__(self):
method __exit__ (line 81) | def __exit__(self, unused_exception_type, unused_exc_value, unused_tra...
method __del__ (line 84) | def __del__(self):
method step (line 87) | def step(self, count=22):
method fl_obs (line 91) | def fl_obs(self, obs):
method raw_unit_command (line 94) | def raw_unit_command(self, ability_id, unit_tags, pos=None, target=None):
method fl_action (line 114) | def fl_action(self, obs, act, *args):
method check_apm (line 118) | def check_apm(self, name):
function main (line 152) | def main(unused_argv):
FILE: pysc2/bin/compare_binaries.py
function _clear_non_deterministic_fields (line 44) | def _clear_non_deterministic_fields(obs):
function _is_remote (line 56) | def _is_remote(arg):
function main (line 60) | def main(argv):
FILE: pysc2/bin/gen_actions.py
function get_data (line 36) | def get_data():
function generate_name (line 55) | def generate_name(ability):
function sort_key (line 60) | def sort_key(data, ability):
function generate_csv (line 69) | def generate_csv(data):
function generate_py_abilities (line 124) | def generate_py_abilities(data):
function main (line 157) | def main(unused_argv):
FILE: pysc2/bin/gen_data.py
function get_data (line 28) | def get_data():
function generate_py_units (line 47) | def generate_py_units(data):
function generate_py_buffs (line 68) | def generate_py_buffs(data):
function generate_py_upgrades (line 79) | def generate_py_upgrades(data):
function main (line 90) | def main(unused_argv):
FILE: pysc2/bin/gen_versions.py
function main (line 25) | def main(argv):
FILE: pysc2/bin/map_list.py
function main (line 22) | def main(unused_argv):
FILE: pysc2/bin/mem_leak_check.py
class Timestep (line 60) | class Timestep(collections.namedtuple(
method __str__ (line 63) | def __str__(self):
function main (line 67) | def main(unused_argv):
FILE: pysc2/bin/play.py
function main (line 84) | def main(unused_argv):
function entry_point (line 225) | def entry_point(): # Needed so setup.py scripts work.
FILE: pysc2/bin/play_vs_agent.py
function main (line 107) | def main(unused_argv):
function agent (line 114) | def agent():
function human (line 153) | def human():
function entry_point (line 284) | def entry_point(): # Needed so setup.py scripts work.
FILE: pysc2/bin/reencode_replays.py
function main (line 32) | def main(_):
FILE: pysc2/bin/replay_actions.py
function sorted_dict_str (line 56) | def sorted_dict_str(d):
class ReplayStats (line 61) | class ReplayStats(object):
method __init__ (line 64) | def __init__(self):
method merge (line 84) | def merge(self, other):
method __str__ (line 109) | def __str__(self):
class ProcessStats (line 143) | class ProcessStats(object):
method __init__ (line 146) | def __init__(self, proc_id):
method update (line 153) | def update(self, stage):
method __str__ (line 157) | def __str__(self):
function valid_replay (line 166) | def valid_replay(info, ping):
class ReplayProcessor (line 182) | class ReplayProcessor(multiprocessing.Process):
method __init__ (line 185) | def __init__(self, proc_id, run_config, replay_queue, stats_queue):
method run (line 192) | def run(self):
method _print (line 249) | def _print(self, s):
method _update_stage (line 253) | def _update_stage(self, stage):
method process_replay (line 257) | def process_replay(self, controller, replay_data, map_data, player_id):
function stats_printer (line 320) | def stats_printer(stats_queue):
function replay_queue_filler (line 351) | def replay_queue_filler(replay_queue, replay_list):
function main (line 357) | def main(unused_argv):
FILE: pysc2/bin/replay_info.py
function _replay_index (line 33) | def _replay_index(replay_dir):
function _replay_info (line 104) | def _replay_info(replay_path):
function main (line 122) | def main(argv):
function entry_point (line 138) | def entry_point(): # Needed so the setup.py scripts work.
FILE: pysc2/bin/replay_version.py
function main (line 25) | def main(argv):
FILE: pysc2/bin/update_battle_net_cache.py
function mkdirs (line 38) | def mkdirs(*paths):
function test_looks_like_battle_net (line 44) | def test_looks_like_battle_net(path):
function replay_paths (line 52) | def replay_paths(paths):
function update_battle_net_cache (line 63) | def update_battle_net_cache(replays, bnet_base):
function main (line 108) | def main(argv):
FILE: pysc2/bin/valid_actions.py
function main (line 30) | def main(unused_argv):
FILE: pysc2/env/available_actions_printer.py
class AvailableActionsPrinter (line 19) | class AvailableActionsPrinter(base_env_wrapper.BaseEnvWrapper):
method __init__ (line 22) | def __init__(self, env):
method step (line 27) | def step(self, *args, **kwargs):
method _print (line 36) | def _print(self, s):
FILE: pysc2/env/base_env_wrapper.py
class BaseEnvWrapper (line 19) | class BaseEnvWrapper(environment.Base):
method __init__ (line 22) | def __init__(self, env):
method close (line 25) | def close(self, *args, **kwargs):
method action_spec (line 28) | def action_spec(self, *args, **kwargs):
method observation_spec (line 31) | def observation_spec(self, *args, **kwargs):
method reset (line 34) | def reset(self, *args, **kwargs):
method step (line 37) | def step(self, *args, **kwargs):
method save_replay (line 40) | def save_replay(self, *args, **kwargs):
method state (line 44) | def state(self):
FILE: pysc2/env/converted_env.py
function squeeze_if_necessary (line 36) | def squeeze_if_necessary(x: np.ndarray) -> np.ndarray:
function squeeze_spec_if_necessary (line 44) | def squeeze_spec_if_necessary(x):
class ConverterFactory (line 52) | class ConverterFactory(typing_extensions.Protocol):
method __call__ (line 54) | def __call__(self, game_info: sc2api_pb2.ResponseGameInfo) -> Any:
class ConvertedEnvironment (line 58) | class ConvertedEnvironment(dm_env.Environment):
method __init__ (line 72) | def __init__(self,
method reset (line 96) | def reset(self) -> dm_env.TimeStep:
method step (line 106) | def step(self, actions) -> dm_env.TimeStep:
method observation_spec (line 141) | def observation_spec(self):
method action_spec (line 144) | def action_spec(self):
method close (line 147) | def close(self):
method send_chat_messages (line 151) | def send_chat_messages(self, messages: Sequence[str], broadcast: bool ...
method save_replay (line 158) | def save_replay(self, replay_dir, prefix=None):
method action_delays (line 161) | def action_delays(self):
method num_players (line 164) | def num_players(self):
method is_player_turn (line 167) | def is_player_turn(self):
method _convert_timesteps (line 170) | def _convert_timesteps(self, timesteps):
class _Stream (line 190) | class _Stream(dm_env.Environment):
method __init__ (line 193) | def __init__(self, player: int, environment: '_StreamedEnvironment'):
method reset (line 197) | def reset(self) -> dm_env.TimeStep:
method step (line 200) | def step(self, action) -> dm_env.TimeStep:
method action_spec (line 203) | def action_spec(self):
method observation_spec (line 206) | def observation_spec(self):
method close (line 209) | def close(self):
method save_replay (line 212) | def save_replay(self, replay_dir, prefix=None):
class _StreamedEnvironment (line 216) | class _StreamedEnvironment:
method __init__ (line 219) | def __init__(self, underlying_env: ConvertedEnvironment):
method reset (line 233) | def reset(self, player: int) -> dm_env.TimeStep:
method step (line 241) | def step(self, action, player: int) -> dm_env.TimeStep:
method action_spec (line 256) | def action_spec(self, player: int):
method observation_spec (line 259) | def observation_spec(self, player: int):
method close (line 262) | def close(self, player: int):
method save_replay (line 268) | def save_replay(self, replay_dir, prefix=None):
method _wait_for_other_player (line 272) | def _wait_for_other_player(self):
method _player_timestep (line 281) | def _player_timestep(self, player: int):
function make_streams (line 290) | def make_streams(converted_environment: ConvertedEnvironment):
function _dummy_game_info (line 312) | def _dummy_game_info() -> sc2api_pb2.ResponseGameInfo:
class EnvironmentSpec (line 327) | class EnvironmentSpec(NamedTuple):
function get_environment_spec (line 332) | def get_environment_spec(
function make_converter_factories (line 349) | def make_converter_factories(
FILE: pysc2/env/converted_env_test.py
function _action (line 33) | def _action(delay: int):
function _converter_factory (line 45) | def _converter_factory(game_info: sc2api_pb2.ResponseGameInfo):
function _agent_interface_format (line 60) | def _agent_interface_format():
class StreamedEnvTest (line 65) | class StreamedEnvTest(absltest.TestCase):
method _check_episode (line 67) | def _check_episode(self, stream):
method test_single_player (line 77) | def test_single_player(self):
method test_two_player (line 95) | def test_two_player(self):
class StreamedEnvConformanceTest (line 122) | class StreamedEnvConformanceTest(test_utils.EnvironmentTestMixin,
method make_object_under_test (line 125) | def make_object_under_test(self):
FILE: pysc2/env/converter/cc/castops.h
function namespace (line 22) | namespace pysc2 {
FILE: pysc2/env/converter/cc/check_protos_equal.h
function namespace (line 23) | namespace pysc2 {
FILE: pysc2/env/converter/cc/convert_obs.cc
type pysc2 (line 30) | namespace pysc2 {
function GameLoop (line 85) | dm_env_rpc::v1::Tensor GameLoop(
function PlayerCommon (line 91) | dm_env_rpc::v1::Tensor PlayerCommon(const SC2APIProtocol::Observation&...
function MapPlayerIdToOne (line 111) | dm_env_rpc::v1::Tensor MapPlayerIdToOne(const dm_env_rpc::v1::Tensor& ...
function Upgrades (line 117) | dm_env_rpc::v1::Tensor Upgrades(const SC2APIProtocol::Observation& obs) {
function UpgradesUint8FixedLength (line 129) | dm_env_rpc::v1::Tensor UpgradesUint8FixedLength(
function RawUnitsSpec (line 140) | dm_env_rpc::v1::TensorSpec RawUnitsSpec(int max_unit_count, int num_un...
function RawUnitsFullVec (line 218) | dm_env_rpc::v1::Tensor RawUnitsFullVec(
function RawUnitsToUint8 (line 500) | dm_env_rpc::v1::Tensor RawUnitsToUint8(const dm_env_rpc::v1::Tensor& t...
function CameraPosition (line 521) | dm_env_rpc::v1::Tensor CameraPosition(
function CameraSize (line 544) | dm_env_rpc::v1::Tensor CameraSize(const SC2APIProtocol::Size2DI& raw_r...
function SeparateCamera (line 559) | dm_env_rpc::v1::Tensor SeparateCamera(
function GetUnitTypeIndex (line 590) | int GetUnitTypeIndex(int unit_type_id, bool using_uint8_unit_ids) {
function UnitCounts (line 598) | dm_env_rpc::v1::Tensor UnitCounts(const SC2APIProtocol::Observation& obs,
function AddUnitCountsBowData (line 633) | dm_env_rpc::v1::Tensor AddUnitCountsBowData(
FILE: pysc2/env/converter/cc/convert_obs.h
function namespace (line 33) | namespace pysc2 {
FILE: pysc2/env/converter/cc/convert_obs_test.cc
type pysc2 (line 31) | namespace pysc2 {
function TEST (line 39) | TEST(ConvertObs, FeatureLayerFieldIndicesAreInOrderSpecified) {
function TEST (line 47) | TEST(ConvertObsDeathTest, FeatureLayerFieldIndicesDiesIfLayerNotFound) {
function TEST (line 54) | TEST(ConvertObs, FeatureLayers8Bit) {
function TEST (line 78) | TEST(ConvertObsDeathTest, FeatureLayers8BitDiesIfLayerNameMismatch) {
function TEST (line 96) | TEST(ConvertObs, RawUnitsFullVecTerranAddonPopulated) {
FILE: pysc2/env/converter/cc/converter.cc
type pysc2 (line 37) | namespace pysc2 {
function MakeConverter (line 45) | absl::StatusOr<Converter> MakeConverter(
FILE: pysc2/env/converter/cc/converter.h
function namespace (line 28) | namespace pysc2 {
FILE: pysc2/env/converter/cc/converter_test.cc
type pysc2 (line 34) | namespace pysc2 {
function GetKeys (line 50) | std::vector<std::string> GetKeys(
function ToVector (line 61) | std::vector<T> ToVector(const google::protobuf::RepeatedField<T>& repe...
function ToVector (line 65) | std::vector<int> ToVector(const dm_env_rpc::v1::TensorSpec::Value& val...
function EnvironmentInfo (line 79) | EnvironmentInfo MakeEnvironmentInfo() {
function ConverterSettings (line 92) | ConverterSettings MakeSettingsRaw() {
function ConverterSettings (line 113) | ConverterSettings MakeSettingsVisual() {
function MakeTensor (line 132) | dm_env_rpc::v1::Tensor MakeTensor(int value) {
function MakeNoOp (line 138) | absl::flat_hash_map<std::string, dm_env_rpc::v1::Tensor> MakeNoOp(
function Observation (line 146) | Observation MakeObservation() {
function TEST (line 180) | TEST(RawConverterTest, ActionSpec) {
function TEST (line 212) | TEST(RawConverterTest, ConvertActionMoveCamera) {
function TEST (line 241) | TEST(RawConverterTest, ConvertActionSmartUnit) {
function TEST (line 274) | TEST(VisualConverterTest, ActionSpec) {
function TEST (line 317) | TEST(VisualConverterTest, ConvertActionMoveCamera) {
function TEST (line 344) | TEST(VisualConverterTest, ConvertActionSmartScreen) {
class ConverterTest (line 373) | class ConverterTest : public testing::TestWithParam<std::string> {}
function TEST_P (line 375) | TEST_P(ConverterTest, Construction) {
function TEST_P (line 382) | TEST_P(ConverterTest, ConvertActionDelay) {
function TEST_P (line 396) | TEST_P(ConverterTest, ObservationSpec) {
function TEST_P (line 485) | TEST_P(ConverterTest, ObservationMatchesSpec) {
FILE: pysc2/env/converter/cc/encode_image_data.h
function namespace (line 27) | namespace pysc2 {
FILE: pysc2/env/converter/cc/features.cc
type pysc2 (line 27) | namespace pysc2 {
function GetScreenFeatures (line 71) | std::vector<std::string> GetScreenFeatures() {
function GetMinimapFeatures (line 80) | std::vector<std::string> GetMinimapFeatures() {
function GetScreenFeatureScale (line 93) | absl::StatusOr<int> GetScreenFeatureScale(const absl::string_view name) {
function GetMinimapFeatureScale (line 102) | absl::StatusOr<int> GetMinimapFeatureScale(const absl::string_view nam...
FILE: pysc2/env/converter/cc/features.h
function namespace (line 24) | namespace pysc2 {
FILE: pysc2/env/converter/cc/file_util.cc
type pysc2 (line 26) | namespace pysc2 {
function GetBinaryProto (line 28) | absl::Status GetBinaryProto(absl::string_view filename,
function GetTextProto (line 45) | absl::Status GetTextProto(absl::string_view filename, google::protobuf...
FILE: pysc2/env/converter/cc/file_util.h
function namespace (line 22) | namespace pysc2 {
FILE: pysc2/env/converter/cc/game_data/python/uint8_lookup.cc
function PYBIND11_MODULE (line 19) | PYBIND11_MODULE(uint8_lookup, m) {
FILE: pysc2/env/converter/cc/game_data/python/uint8_lookup_test.py
class Uint8LookupTest (line 22) | class Uint8LookupTest(absltest.TestCase):
method test_pysc2_to_uint8 (line 24) | def test_pysc2_to_uint8(self):
method test_pysc2_to_uint8_buffs (line 28) | def test_pysc2_to_uint8_buffs(self):
method test_pysc2_to_uint8_upgrades (line 33) | def test_pysc2_to_uint8_upgrades(self):
method test_uint8_to_pysc2 (line 37) | def test_uint8_to_pysc2(self):
method test_uint8_to_pysc2_upgrades (line 41) | def test_uint8_to_pysc2_upgrades(self):
method test_effect_id_identity (line 45) | def test_effect_id_identity(self):
FILE: pysc2/env/converter/cc/game_data/raw_actions.cc
type pysc2 (line 19) | namespace pysc2 {
FILE: pysc2/env/converter/cc/game_data/raw_actions.h
function namespace (line 24) | namespace pysc2 {
FILE: pysc2/env/converter/cc/game_data/uint8_lookup.cc
type pysc2 (line 28) | namespace pysc2 {
function BuildTable (line 452) | absl::flat_hash_map<int, uint8_t> BuildTable(
function LookUp (line 463) | int LookUp(int data, const std::array<int32_t, size> list,
function PySc2ToUint8 (line 484) | int PySc2ToUint8(int data) {
function PySc2ToUint8Buffs (line 488) | int PySc2ToUint8Buffs(int data) {
function PySc2ToUint8Upgrades (line 492) | int PySc2ToUint8Upgrades(int data) {
function MaximumUnitTypeId (line 496) | int MaximumUnitTypeId() {
function MaximumBuffId (line 500) | int MaximumBuffId() {
function Uint8ToPySc2 (line 504) | int Uint8ToPySc2(int utype) {
function Uint8ToPySc2Upgrades (line 510) | int Uint8ToPySc2Upgrades(int upgrade_type) {
function EffectIdIdentity (line 516) | int EffectIdIdentity(int effect_id) { return effect_id; }
FILE: pysc2/env/converter/cc/game_data/uint8_lookup.h
function namespace (line 18) | namespace pysc2 {
FILE: pysc2/env/converter/cc/game_data/visual_actions.cc
type pysc2 (line 19) | namespace pysc2 {
FILE: pysc2/env/converter/cc/game_data/visual_actions.h
function namespace (line 23) | namespace pysc2 {
FILE: pysc2/env/converter/cc/general_order_ids.cc
type pysc2 (line 24) | namespace pysc2 {
class OrderIdToGeneralLookup (line 27) | class OrderIdToGeneralLookup {
method OrderIdToGeneralLookup (line 29) | OrderIdToGeneralLookup() {
method Lookup (line 61) | int Lookup(int game_id) const {
function OrderIdToGeneralLookup (line 76) | const OrderIdToGeneralLookup& OrderIdToGeneral() {
method OrderIdToGeneralLookup (line 29) | OrderIdToGeneralLookup() {
method Lookup (line 61) | int Lookup(int game_id) const {
function GeneralOrderId (line 83) | int GeneralOrderId(int order_id, int num_action_types) {
function GeneralOrderIds (line 92) | void GeneralOrderIds(dm_env_rpc::v1::Tensor* raw_units, int num_action...
FILE: pysc2/env/converter/cc/general_order_ids.h
function namespace (line 20) | namespace pysc2 {
FILE: pysc2/env/converter/cc/map_util.cc
type pysc2 (line 24) | namespace pysc2 {
function WorldToMinimapPx (line 26) | SC2APIProtocol::PointI WorldToMinimapPx(
function WorldToMinimapPx (line 42) | SC2APIProtocol::PointI WorldToMinimapPx(
function WorldToMinimapDistance (line 51) | int WorldToMinimapDistance(float distance,
function MakeSize2DI (line 58) | SC2APIProtocol::Size2DI MakeSize2DI(int x, int y) {
FILE: pysc2/env/converter/cc/map_util.h
function namespace (line 20) | namespace pysc2 {
FILE: pysc2/env/converter/cc/python/converter.cc
class ConverterWrapper (line 28) | class ConverterWrapper {
method ConverterWrapper (line 36) | ConverterWrapper(pysc2::Converter converter)
method ObservationSpec (line 38) | std::map<std::string, pybind11::bytes> ObservationSpec() {
method ActionSpec (line 49) | std::map<std::string, pybind11::bytes> ActionSpec() {
method ConvertObservation (line 60) | std::map<std::string, pybind11::bytes> ConvertObservation(
method ConvertAction (line 76) | pybind11::bytes ConvertAction(
function ConverterWrapper (line 96) | ConverterWrapper MakeConverterWrapper(const std::string& settings,
method ConverterWrapper (line 36) | ConverterWrapper(pysc2::Converter converter)
method ObservationSpec (line 38) | std::map<std::string, pybind11::bytes> ObservationSpec() {
method ActionSpec (line 49) | std::map<std::string, pybind11::bytes> ActionSpec() {
method ConvertObservation (line 60) | std::map<std::string, pybind11::bytes> ConvertObservation(
method ConvertAction (line 76) | pybind11::bytes ConvertAction(
function PYBIND11_MODULE (line 112) | PYBIND11_MODULE(converter, m) {
FILE: pysc2/env/converter/cc/raw_actions_encoder.cc
type pysc2 (line 34) | namespace pysc2 {
class AbilityIdToGameIdTable (line 37) | class AbilityIdToGameIdTable {
method AbilityIdToGameIdTable (line 39) | AbilityIdToGameIdTable() {
method Lookup (line 47) | int Lookup(int ability_id) const {
function FindOriginalTag (line 62) | int64_t FindOriginalTag(int position,
function LookupSelectedUnitTags (line 74) | std::vector<int64_t> LookupSelectedUnitTags(
function FindFunction (line 94) | int FindFunction(int ability_id, RawFunctionType type,
function FindSelectionIndices (line 120) | std::vector<int> FindSelectionIndices(const SC2APIProtocol::Observatio...
function KeysString (line 137) | std::string KeysString(const absl::flat_hash_map<std::string, V>& map) {
function PrintAllActions (line 516) | void PrintAllActions() {
function RawAbilityToGameId (line 523) | int RawAbilityToGameId(int ability_id) {
FILE: pysc2/env/converter/cc/raw_actions_encoder.h
function namespace (line 29) | namespace pysc2 {
FILE: pysc2/env/converter/cc/raw_actions_encoder_test.cc
type dm_env_rpc (line 33) | namespace dm_env_rpc {
type v1 (line 34) | namespace v1 {
type pysc2 (line 44) | namespace pysc2 {
function GetResponseObservation (line 52) | SC2APIProtocol::ResponseObservation GetResponseObservation() {
function TEST (line 62) | TEST(RawActionsEncoderTest, RawAutocastActions) {
function TEST (line 92) | TEST(RawActionsEncoderTest, ActionRoundTrip) {
function TEST (line 132) | TEST(RawActionsEncoderTest, RepeatActionRoundTrip) {
FILE: pysc2/env/converter/cc/raw_camera.cc
type pysc2 (line 23) | namespace pysc2 {
function MakePoint (line 27) | SC2APIProtocol::Point2D MakePoint(float x, float y) {
FILE: pysc2/env/converter/cc/raw_camera.h
function namespace (line 23) | namespace pysc2 {
FILE: pysc2/env/converter/cc/raw_converter.cc
type pysc2 (line 30) | namespace pysc2 {
FILE: pysc2/env/converter/cc/raw_converter.h
function namespace (line 30) | namespace pysc2 {
FILE: pysc2/env/converter/cc/tensor_util.cc
type pysc2 (line 25) | namespace pysc2 {
function TensorSpec (line 27) | dm_env_rpc::v1::TensorSpec TensorSpec(absl::string_view name,
function TensorSpec (line 47) | dm_env_rpc::v1::TensorSpec TensorSpec(absl::string_view name,
function Int32TensorSpec (line 59) | dm_env_rpc::v1::TensorSpec Int32TensorSpec(absl::string_view name,
function Int32ScalarSpec (line 64) | dm_env_rpc::v1::TensorSpec Int32ScalarSpec(absl::string_view name,
function Int32ScalarSpec (line 70) | dm_env_rpc::v1::TensorSpec Int32ScalarSpec(absl::string_view name) {
function ToScalar (line 77) | int ToScalar(const dm_env_rpc::v1::Tensor& tensor) {
function ToVector (line 93) | std::vector<int> ToVector(const dm_env_rpc::v1::Tensor& tensor) {
function MakeTensor (line 117) | dm_env_rpc::v1::Tensor MakeTensor(int value) {
function MakeTensor (line 123) | dm_env_rpc::v1::Tensor MakeTensor(const std::vector<int>& values) {
function GetNumElements (line 174) | int GetNumElements(const google::protobuf::RepeatedField<int32_t>& ten...
FILE: pysc2/env/converter/cc/tensor_util.h
function namespace (line 25) | namespace pysc2 {
FILE: pysc2/env/converter/cc/unit_lookups.cc
type pysc2 (line 22) | namespace pysc2 {
function UnitTypeToRace (line 58) | SC2APIProtocol::Race UnitTypeToRace(uint32_t unit_type) {
function UnitTypeToString (line 65) | std::string UnitTypeToString(uint32_t unit_type) {
FILE: pysc2/env/converter/cc/unit_lookups.h
function namespace (line 24) | namespace pysc2 {
FILE: pysc2/env/converter/cc/unit_lookups_test.cc
type pysc2 (line 20) | namespace pysc2 {
function TEST (line 23) | TEST(UnitLookupsTest, UnitTypeToRace) {
function TEST (line 30) | TEST(UnitLookupsTest, UnitTypeToString) {
FILE: pysc2/env/converter/cc/visual_actions.cc
type pysc2 (line 30) | namespace pysc2 {
function ActionComparator (line 33) | bool ActionComparator(const VisualAction& lhs, const VisualAction& rhs) {
class VisualActions (line 37) | class VisualActions {
method VisualActions (line 39) | explicit VisualActions(const std::vector<Function>& functions) {
method VisualAction (line 63) | const VisualAction& GetAction(int action_id) const {
method HasAbility (line 74) | bool HasAbility(AbilityId ability_id) const {
function VisualActions (line 85) | const VisualActions& GetActions() {
method VisualActions (line 39) | explicit VisualActions(const std::vector<Function>& functions) {
method VisualAction (line 63) | const VisualAction& GetAction(int action_id) const {
method HasAbility (line 74) | bool HasAbility(AbilityId ability_id) const {
function Val (line 91) | int Val(const dm_env_rpc::v1::Tensor& tensor) { return ToScalar(tensor...
function Option (line 93) | int Option(const dm_env_rpc::v1::Tensor& arg) {
function MakePoint (line 99) | SC2APIProtocol::PointI MakePoint(int arg, int width) {
function PointTo1D (line 106) | int PointTo1D(const SC2APIProtocol::PointI& point, int width) {
function MoveCamera (line 120) | SC2APIProtocol::Action MoveCamera(
function SelectPoint (line 133) | SC2APIProtocol::Action SelectPoint(
function SelectRect (line 149) | SC2APIProtocol::Action SelectRect(
function SelectIdleWorker (line 172) | SC2APIProtocol::Action SelectIdleWorker(
function SelectArmy (line 183) | SC2APIProtocol::Action SelectArmy(
function SelectWarpGates (line 193) | SC2APIProtocol::Action SelectWarpGates(
function SelectLarva (line 203) | SC2APIProtocol::Action SelectLarva(
function SelectUnit (line 212) | SC2APIProtocol::Action SelectUnit(
function SelectControlGroup (line 226) | SC2APIProtocol::Action SelectControlGroup(
function Unload (line 242) | SC2APIProtocol::Action Unload(
function BuildQueue (line 252) | SC2APIProtocol::Action BuildQueue(
function CmdQuick (line 262) | SC2APIProtocol::Action CmdQuick(
function CmdScreen (line 275) | SC2APIProtocol::Action CmdScreen(
function CmdMinimap (line 290) | SC2APIProtocol::Action CmdMinimap(
function Autocast (line 305) | SC2APIProtocol::Action Autocast(
function MakeFunctionCall (line 314) | absl::flat_hash_map<std::string, dm_env_rpc::v1::Tensor> MakeFunctionC...
function NoOp (line 325) | absl::flat_hash_map<std::string, dm_env_rpc::v1::Tensor> NoOp() {
function Ability (line 329) | absl::flat_hash_map<std::string, dm_env_rpc::v1::Tensor> Ability(
function VisualAction (line 433) | const VisualAction& GetAction(ActionId action_id) {
function Decode (line 441) | absl::flat_hash_map<std::string, dm_env_rpc::v1::Tensor> Decode(
FILE: pysc2/env/converter/cc/visual_actions.h
function namespace (line 25) | namespace pysc2 {
FILE: pysc2/env/converter/cc/visual_actions_test.cc
type pysc2 (line 26) | namespace pysc2 {
class VisualActionsTest (line 29) | class VisualActionsTest : public testing::TestWithParam<const char*> {}
function TEST_P (line 31) | TEST_P(VisualActionsTest, DecodeEncodeTest) {
FILE: pysc2/env/converter/cc/visual_converter.cc
type pysc2 (line 36) | namespace pysc2 {
function AvailableActions (line 43) | dm_env_rpc::v1::Tensor AvailableActions(const SC2APIProtocol::Observat...
FILE: pysc2/env/converter/cc/visual_converter.h
function namespace (line 28) | namespace pysc2 {
FILE: pysc2/env/converter/cc/visual_converter_test.cc
type pysc2 (line 28) | namespace pysc2 {
function ConverterSettings (line 31) | ConverterSettings MakeSettings() {
function MakePlayerObservation (line 41) | pysc2::Observation MakePlayerObservation() {
function TEST (line 65) | TEST(VisualConverterTest, Construct) {
function TEST (line 69) | TEST(VisualConverterTest, FeaturePlanes) {
FILE: pysc2/env/converter/converter.py
class Converter (line 33) | class Converter:
method __init__ (line 51) | def __init__(self, settings: converter_pb2.ConverterSettings,
method observation_spec (line 57) | def observation_spec(self) -> Mapping[str, specs.Array]:
method action_spec (line 70) | def action_spec(self) -> Mapping[str, specs.Array]:
method convert_observation (line 83) | def convert_observation(
method convert_action (line 112) | def convert_action(self, action: Mapping[str, Any]) -> converter_pb2.A...
FILE: pysc2/env/converter/converter_test.py
function _make_dummy_env_info (line 38) | def _make_dummy_env_info():
function _make_converter_settings_common (line 51) | def _make_converter_settings_common(**kwargs):
function _make_converter_settings (line 63) | def _make_converter_settings(mode: str):
function _make_observation (line 79) | def _make_observation():
class RawConverterTest (line 107) | class RawConverterTest(absltest.TestCase):
method test_action_spec (line 109) | def test_action_spec(self):
method test_action_move_camera (line 138) | def test_action_move_camera(self):
method test_action_smart_unit (line 158) | def test_action_smart_unit(self):
class VisualConverterTest (line 189) | class VisualConverterTest(absltest.TestCase):
method test_action_spec (line 191) | def test_action_spec(self):
method test_action_move_camera (line 229) | def test_action_move_camera(self):
method test_action_smart_screen (line 248) | def test_action_smart_screen(self):
class ConverterTest (line 278) | class ConverterTest(parameterized.TestCase):
method test_construction (line 280) | def test_construction(self, mode):
method test_convert_action_delay (line 285) | def test_convert_action_delay(self, mode):
method test_observation_spec (line 294) | def test_observation_spec(self, mode):
method test_observation_matches_spec (line 368) | def test_observation_matches_spec(self, mode):
FILE: pysc2/env/converter/derive_interface_options.py
function from_settings (line 23) | def from_settings(settings: converter_pb2.ConverterSettings):
FILE: pysc2/env/enums.py
class Race (line 22) | class Race(enum.IntEnum):
class Difficulty (line 29) | class Difficulty(enum.IntEnum):
class BotBuild (line 43) | class BotBuild(enum.IntEnum):
FILE: pysc2/env/environment.py
class TimeStep (line 21) | class TimeStep(collections.namedtuple(
method first (line 43) | def first(self):
method mid (line 46) | def mid(self):
method last (line 49) | def last(self):
class StepType (line 53) | class StepType(enum.IntEnum):
class Base (line 63) | class Base(metaclass=abc.ABCMeta): # pytype: disable=ignored-abstractme...
method reset (line 67) | def reset(self):
method step (line 80) | def step(self, action):
method observation_spec (line 105) | def observation_spec(self):
method action_spec (line 114) | def action_spec(self):
method close (line 122) | def close(self):
method __enter__ (line 144) | def __enter__(self):
method __exit__ (line 148) | def __exit__(self, unused_exception_type, unused_exc_value, unused_tra...
method __del__ (line 152) | def __del__(self):
FILE: pysc2/env/host_remote_agent.py
class VsAgent (line 26) | class VsAgent(object):
method __init__ (line 44) | def __init__(self):
method __enter__ (line 60) | def __enter__(self):
method __exit__ (line 63) | def __exit__(self, exception_type, exception_value, traceback):
method __del__ (line 66) | def __del__(self):
method create_game (line 69) | def create_game(self, map_name):
method _disconnect (line 97) | def _disconnect(self):
method _reconnect (line 102) | def _reconnect(self, **kwargs):
method save_replay (line 108) | def save_replay(self, replay_dir, replay_name):
method hosts (line 114) | def hosts(self):
method host_ports (line 119) | def host_ports(self):
method lan_ports (line 124) | def lan_ports(self):
method close (line 128) | def close(self):
class VsBot (line 146) | class VsBot(object):
method __init__ (line 163) | def __init__(self):
method __enter__ (line 170) | def __enter__(self):
method __exit__ (line 173) | def __exit__(self, exception_type, exception_value, traceback):
method __del__ (line 176) | def __del__(self):
method create_game (line 179) | def create_game(
method _disconnect (line 221) | def _disconnect(self):
method _reconnect (line 225) | def _reconnect(self, **kwargs):
method save_replay (line 230) | def save_replay(self, replay_dir, replay_name):
method host (line 236) | def host(self):
method host_port (line 241) | def host_port(self):
method close (line 245) | def close(self):
FILE: pysc2/env/lan_sc2_env.py
class Addr (line 40) | class Addr(collections.namedtuple("Addr", ["ip", "port"])):
method __str__ (line 42) | def __str__(self):
function daemon_thread (line 47) | def daemon_thread(target, args):
function udp_server (line 54) | def udp_server(addr):
function tcp_server (line 61) | def tcp_server(tcp_addr, settings):
function tcp_client (line 79) | def tcp_client(tcp_addr):
function log_msg (line 105) | def log_msg(prefix, msg):
function udp_to_tcp (line 110) | def udp_to_tcp(udp_sock, tcp_conn):
function tcp_to_udp (line 119) | def tcp_to_udp(tcp_conn, udp_sock, udp_to_addr):
function read_tcp (line 128) | def read_tcp(conn):
function read_tcp_size (line 138) | def read_tcp_size(conn, size):
function write_tcp (line 153) | def write_tcp(conn, msg):
function forward_ports (line 159) | def forward_ports(remote_host, local_host, local_listen_ports,
class RestartError (line 195) | class RestartError(Exception):
class LanSC2Env (line 199) | class LanSC2Env(sc2_env.SC2Env):
method __init__ (line 206) | def __init__(self,
method _launch_remote (line 299) | def _launch_remote(self, host, config_port, race, name, interface,
method _restart (line 347) | def _restart(self):
method close (line 352) | def close(self):
FILE: pysc2/env/mock_sc2_env.py
class _TestEnvironment (line 30) | class _TestEnvironment(environment.Base):
method __init__ (line 53) | def __init__(self, num_agents, observation_spec, action_spec):
method reset (line 80) | def reset(self):
method step (line 85) | def step(self, actions, step_mul=None):
method action_spec (line 122) | def action_spec(self):
method observation_spec (line 126) | def observation_spec(self):
method _default_observation (line 130) | def _default_observation(self, obs_spec, agent_index):
class SC2TestEnv (line 138) | class SC2TestEnv(_TestEnvironment):
method __init__ (line 158) | def __init__(self,
method game_info (line 258) | def game_info(self):
method save_replay (line 261) | def save_replay(self, *args, **kwargs):
method _default_observation (line 264) | def _default_observation(self, obs_spec, agent_index):
function _make_dummy_game_info (line 300) | def _make_dummy_game_info(players, interface_formats):
FILE: pysc2/env/mock_sc2_env_comparison_test.py
class TestCompareEnvironments (line 23) | class TestCompareEnvironments(absltest.TestCase):
method setUpClass (line 26) | def setUpClass(cls):
method tearDownClass (line 56) | def tearDownClass(cls):
method test_observation_spec (line 61) | def test_observation_spec(self):
method test_action_spec (line 65) | def test_action_spec(self):
FILE: pysc2/env/mock_sc2_env_test.py
class _TestMixin (line 32) | class _TestMixin(object):
method assert_spec (line 34) | def assert_spec(self, array, shape, dtype):
method assert_equal (line 38) | def assert_equal(self, actual, expected):
method assert_reset (line 41) | def assert_reset(self, env):
method assert_first_step (line 47) | def assert_first_step(self, env):
method assert_mid_step (line 53) | def assert_mid_step(self, env):
method assert_last_step (line 59) | def assert_last_step(self, env):
method _test_episode (line 66) | def _test_episode(self, env):
method _test_episode_length (line 80) | def _test_episode_length(self, env, length):
class TestTestEnvironment (line 92) | class TestTestEnvironment(_TestMixin, absltest.TestCase):
method setUp (line 94) | def setUp(self):
method test_observation_spec (line 101) | def test_observation_spec(self):
method test_action_spec (line 104) | def test_action_spec(self):
method test_default_observation (line 107) | def test_default_observation(self):
method test_episode (line 112) | def test_episode(self):
method test_two_episodes (line 116) | def test_two_episodes(self):
method test_episode_length (line 121) | def test_episode_length(self):
class TestSC2TestEnv (line 126) | class TestSC2TestEnv(_TestMixin, absltest.TestCase):
method test_episode (line 128) | def test_episode(self):
method test_episode_length (line 136) | def test_episode_length(self):
method test_screen_minimap_size (line 144) | def test_screen_minimap_size(self):
method test_feature_units_are_supported (line 158) | def test_feature_units_are_supported(self):
method test_game_info (line 167) | def test_game_info(self):
FILE: pysc2/env/remote_sc2_env.py
class RestartError (line 29) | class RestartError(Exception):
class RemoteSC2Env (line 33) | class RemoteSC2Env(sc2_env.SC2Env):
method __init__ (line 42) | def __init__(self,
method close (line 156) | def close(self):
method _connect_remote (line 174) | def _connect_remote(self, host, host_port, lan_ports, race, name, map_...
method _restart (line 211) | def _restart(self):
FILE: pysc2/env/run_loop.py
function run_loop (line 19) | def run_loop(agents, env, max_frames=0, max_episodes=0):
FILE: pysc2/env/sc2_env.py
function to_list (line 59) | def to_list(arg):
function get_default (line 63) | def get_default(a, b):
class Agent (line 67) | class Agent(collections.namedtuple("Agent", ["race", "name"])):
method __new__ (line 70) | def __new__(cls, race, name=None):
class Bot (line 74) | class Bot(collections.namedtuple("Bot", ["race", "difficulty", "build"])):
method __new__ (line 77) | def __new__(cls, race, difficulty, build=None):
class SC2Env (line 90) | class SC2Env(environment.Base):
method __init__ (line 97) | def __init__(self,
method _finalize (line 266) | def _finalize(self, visualize):
method _get_interface (line 291) | def _get_interface(interface_format, require_raw):
method _launch_game (line 328) | def _launch_game(self):
method _create_join (line 352) | def _create_join(self):
method map_name (line 438) | def map_name(self):
method game_info (line 442) | def game_info(self):
method static_data (line 446) | def static_data(self):
method observation_spec (line 449) | def observation_spec(self):
method action_spec (line 453) | def action_spec(self):
method action_delays (line 457) | def action_delays(self):
method _restart (line 473) | def _restart(self):
method reset (line 484) | def reset(self):
method step (line 507) | def step(self, actions, step_mul=None):
method _step (line 537) | def _step(self, step_mul=None):
method _apply_action_delays (line 554) | def _apply_action_delays(self, actions):
method _send_delayed_actions (line 580) | def _send_delayed_actions(self, up_to_game_loop, current_game_loop):
method _step_to (line 606) | def _step_to(self, game_loop, current_game_loop):
method _get_observations (line 615) | def _get_observations(self, target_game_loop):
method _observe (line 657) | def _observe(self, target_game_loop):
method send_chat_messages (line 723) | def send_chat_messages(self, messages, broadcast=True):
method save_replay (line 731) | def save_replay(self, replay_dir, prefix=None):
method close (line 739) | def close(self):
function crop_and_deduplicate_names (line 769) | def crop_and_deduplicate_names(names):
function _get_game_loop (line 811) | def _get_game_loop(agent_obs):
function _get_score (line 818) | def _get_score(agent_obs, score_index=0):
FILE: pysc2/env/sc2_env_test.py
class TestNameCroppingAndDeduplication (line 23) | class TestNameCroppingAndDeduplication(parameterized.TestCase):
method test (line 48) | def test(self, names, expected_output):
FILE: pysc2/lib/actions.py
class ActionSpace (line 27) | class ActionSpace(enum.Enum):
function spatial (line 33) | def spatial(action, action_space):
function no_op (line 43) | def no_op(action, action_space):
function move_camera (line 47) | def move_camera(action, action_space, minimap):
function select_point (line 52) | def select_point(action, action_space, select_point_act, screen):
function select_rect (line 59) | def select_rect(action, action_space, select_add, screen, screen2):
function select_idle_worker (line 69) | def select_idle_worker(action, action_space, select_worker):
function select_army (line 75) | def select_army(action, action_space, select_add):
function select_warp_gates (line 81) | def select_warp_gates(action, action_space, select_add):
function select_larva (line 87) | def select_larva(action, action_space):
function select_unit (line 93) | def select_unit(action, action_space, select_unit_act, select_unit_id):
function control_group (line 101) | def control_group(action, action_space, control_group_act, control_group...
function unload (line 109) | def unload(action, action_space, unload_id):
function build_queue (line 115) | def build_queue(action, action_space, build_queue_id):
function cmd_quick (line 121) | def cmd_quick(action, action_space, ability_id, queued):
function cmd_screen (line 128) | def cmd_screen(action, action_space, ability_id, queued, screen):
function cmd_minimap (line 136) | def cmd_minimap(action, action_space, ability_id, queued, minimap):
function autocast (line 144) | def autocast(action, action_space, ability_id):
function raw_no_op (line 150) | def raw_no_op(action):
function raw_move_camera (line 154) | def raw_move_camera(action, world):
function raw_cmd (line 160) | def raw_cmd(action, ability_id, queued, unit_tags):
function raw_cmd_pt (line 170) | def raw_cmd_pt(action, ability_id, queued, unit_tags, world):
function raw_cmd_unit (line 181) | def raw_cmd_unit(action, ability_id, queued, unit_tags,
function raw_autocast (line 193) | def raw_autocast(action, ability_id, unit_tags):
function numpy_to_python (line 202) | def numpy_to_python(val):
class ArgumentType (line 216) | class ArgumentType(collections.namedtuple(
method __str__ (line 232) | def __str__(self):
method __reduce__ (line 235) | def __reduce__(self):
method enum (line 239) | def enum(cls, options, values):
method scalar (line 249) | def scalar(cls, value):
method point (line 254) | def point(cls): # No range because it's unknown at this time.
method spec (line 261) | def spec(cls, id_, name, sizes):
method unit_tags (line 266) | def unit_tags(cls, count, size):
class Arguments (line 276) | class Arguments(collections.namedtuple("Arguments", [
method types (line 304) | def types(cls, **kwargs):
method __reduce__ (line 310) | def __reduce__(self):
class RawArguments (line 314) | class RawArguments(collections.namedtuple("RawArguments", [
method types (line 330) | def types(cls, **kwargs):
method __reduce__ (line 336) | def __reduce__(self):
function _define_position_based_enum (line 340) | def _define_position_based_enum(name, options):
class Function (line 463) | class Function(collections.namedtuple(
method ui_func (line 484) | def ui_func(cls, id_, name, function_type, avail_fn=always):
method ability (line 490) | def ability(cls, id_, name, function_type, ability_id, general_id=0):
method raw_ability (line 497) | def raw_ability(cls, id_, name, function_type, ability_id, general_id=0,
method raw_ui_func (line 505) | def raw_ui_func(cls, id_, name, function_type, avail_fn=always):
method spec (line 511) | def spec(cls, id_, name, args):
method __hash__ (line 515) | def __hash__(self): # So it can go in a set().
method __str__ (line 518) | def __str__(self):
method __call__ (line 521) | def __call__(self, *args):
method __reduce__ (line 525) | def __reduce__(self):
method str (line 528) | def str(self, space=False):
class Functions (line 535) | class Functions(object):
method __init__ (line 542) | def __init__(self, functions):
method __getattr__ (line 549) | def __getattr__(self, name):
method __getitem__ (line 552) | def __getitem__(self, key):
method __getstate__ (line 557) | def __getstate__(self):
method __setstate__ (line 561) | def __setstate__(self, functions):
method __iter__ (line 565) | def __iter__(self):
method __len__ (line 568) | def __len__(self):
method __eq__ (line 571) | def __eq__(self, other):
class FunctionCall (line 1767) | class FunctionCall(collections.namedtuple(
method init_with_validation (line 1779) | def init_with_validation(cls, function, arguments, raw=False):
method all_arguments (line 1826) | def all_arguments(cls, function, arguments, raw=False):
method __reduce__ (line 1848) | def __reduce__(self):
class ValidActions (line 1852) | class ValidActions(collections.namedtuple(
method __reduce__ (line 1863) | def __reduce__(self):
FILE: pysc2/lib/buffs.py
class Buffs (line 20) | class Buffs(enum.IntEnum):
FILE: pysc2/lib/colors.py
class Color (line 25) | class Color(collections.namedtuple("Color", ["r", "g", "b"])):
method set (line 29) | def set(self, r=None, g=None, b=None):
method round (line 32) | def round(self):
method floor (line 35) | def floor(self):
method ceil (line 39) | def ceil(self):
method __str__ (line 43) | def __str__(self):
method __add__ (line 46) | def __add__(self, o):
method __sub__ (line 49) | def __sub__(self, o):
method __mul__ (line 52) | def __mul__(self, val):
method __truediv__ (line 55) | def __truediv__(self, val):
method __floordiv__ (line 58) | def __floordiv__(self, val):
function smooth_hue_palette (line 73) | def smooth_hue_palette(scale):
function shuffled_hue (line 119) | def shuffled_hue(scale):
function piece_wise_linear (line 125) | def piece_wise_linear(scale, points):
function winter (line 147) | def winter(scale):
function hot (line 152) | def hot(scale):
function height_map (line 159) | def height_map(scale):
function unit_type (line 211) | def unit_type(scale=None):
function buffs (line 216) | def buffs(scale=None):
function categorical (line 221) | def categorical(options, scale=None):
FILE: pysc2/lib/features.py
class FeatureType (line 39) | class FeatureType(enum.Enum):
class PlayerRelative (line 44) | class PlayerRelative(enum.IntEnum):
class Visibility (line 53) | class Visibility(enum.IntEnum):
class Effects (line 60) | class Effects(enum.IntEnum):
class ScoreCumulative (line 79) | class ScoreCumulative(enum.IntEnum):
class ScoreByCategory (line 96) | class ScoreByCategory(enum.IntEnum):
class ScoreCategories (line 111) | class ScoreCategories(enum.IntEnum):
class ScoreByVital (line 120) | class ScoreByVital(enum.IntEnum):
class ScoreVitals (line 127) | class ScoreVitals(enum.IntEnum):
class Player (line 134) | class Player(enum.IntEnum):
class UnitLayer (line 149) | class UnitLayer(enum.IntEnum):
class UnitCounts (line 160) | class UnitCounts(enum.IntEnum):
class FeatureUnit (line 166) | class FeatureUnit(enum.IntEnum):
class EffectPos (line 216) | class EffectPos(enum.IntEnum):
class Radar (line 226) | class Radar(enum.IntEnum):
class ProductionQueue (line 233) | class ProductionQueue(enum.IntEnum):
class Feature (line 239) | class Feature(collections.namedtuple(
method unpack (line 263) | def unpack(self, obs):
method unpack_layer (line 271) | def unpack_layer(plane):
method unpack_rgb_image (line 289) | def unpack_rgb_image(plane):
method color (line 297) | def color(self, plane):
class ScreenFeatures (line 303) | class ScreenFeatures(collections.namedtuple("ScreenFeatures", [
method __new__ (line 313) | def __new__(cls, **kwargs):
class MinimapFeatures (line 328) | class MinimapFeatures(collections.namedtuple("MinimapFeatures", [
method __new__ (line 335) | def __new__(cls, **kwargs):
function _to_point (line 402) | def _to_point(dims):
class Dimensions (line 426) | class Dimensions(object):
method __init__ (line 437) | def __init__(self, screen=None, minimap=None):
method screen (line 447) | def screen(self):
method minimap (line 451) | def minimap(self):
method __repr__ (line 454) | def __repr__(self):
method __eq__ (line 457) | def __eq__(self, other):
method __ne__ (line 461) | def __ne__(self, other):
class AgentInterfaceFormat (line 465) | class AgentInterfaceFormat(object):
method __init__ (line 468) | def __init__(
method feature_dimensions (line 636) | def feature_dimensions(self):
method rgb_dimensions (line 640) | def rgb_dimensions(self):
method action_space (line 644) | def action_space(self):
method camera_width_world_units (line 648) | def camera_width_world_units(self):
method use_feature_units (line 652) | def use_feature_units(self):
method use_raw_units (line 656) | def use_raw_units(self):
method raw_resolution (line 660) | def raw_resolution(self):
method raw_resolution (line 664) | def raw_resolution(self, value):
method use_raw_actions (line 668) | def use_raw_actions(self):
method max_raw_actions (line 672) | def max_raw_actions(self):
method max_selected_units (line 676) | def max_selected_units(self):
method use_unit_counts (line 680) | def use_unit_counts(self):
method use_camera_position (line 684) | def use_camera_position(self):
method show_cloaked (line 688) | def show_cloaked(self):
method show_burrowed_shadows (line 692) | def show_burrowed_shadows(self):
method show_placeholders (line 696) | def show_placeholders(self):
method hide_specific_actions (line 700) | def hide_specific_actions(self):
method action_delay_fn (line 704) | def action_delay_fn(self):
method send_observation_proto (line 708) | def send_observation_proto(self):
method add_cargo_to_units (line 712) | def add_cargo_to_units(self):
method action_dimensions (line 716) | def action_dimensions(self):
method crop_to_playable_area (line 720) | def crop_to_playable_area(self):
method raw_crop_to_playable_area (line 724) | def raw_crop_to_playable_area(self):
method allow_cheating_layers (line 728) | def allow_cheating_layers(self):
function parse_agent_interface_format (line 732) | def parse_agent_interface_format(
function features_from_game_info (line 803) | def features_from_game_info(game_info, agent_interface_format=None,
function _init_valid_functions (line 884) | def _init_valid_functions(action_dimensions):
function _init_valid_raw_functions (line 903) | def _init_valid_raw_functions(raw_resolution, max_selected_units):
class Features (line 920) | class Features(object):
method __init__ (line 932) | def __init__(self, agent_interface_format=None, map_size=None,
method init_camera (line 979) | def init_camera(
method _update_camera (line 1027) | def _update_camera(self, camera_center):
method observation_spec (line 1033) | def observation_spec(self):
method action_spec (line 1113) | def action_spec(self):
method map_size (line 1118) | def map_size(self):
method requested_races (line 1122) | def requested_races(self):
method transform_obs (line 1126) | def transform_obs(self, obs):
method available_actions (line 1544) | def available_actions(self, obs):
method transform_action (line 1574) | def transform_action(self, obs, func_call, skip_available=False):
method reverse_action (line 1678) | def reverse_action(self, action):
method reverse_raw_action (line 1779) | def reverse_raw_action(self, action, prev_obs):
class Passthrough (line 1870) | class Passthrough:
method observation_spec (line 1873) | def observation_spec(self):
method transform_obs (line 1876) | def transform_obs(self, observation):
method action_spec (line 1879) | def action_spec(self):
method transform_action (line 1882) | def transform_action(self, observation, action, skip_available):
method available_actions (line 1887) | def available_actions(self, observation):
method reverse_action (line 1892) | def reverse_action(self, action):
FILE: pysc2/lib/features_test.py
class AvailableActionsTest (line 54) | class AvailableActionsTest(absltest.TestCase):
method setUp (line 61) | def setUp(self):
method hideSpecificActions (line 66) | def hideSpecificActions(self, hide_specific_actions): # pylint: disab...
method assertAvail (line 71) | def assertAvail(self, expected):
method testAlways (line 76) | def testAlways(self):
method testSelectUnit (line 79) | def testSelectUnit(self):
method testSelectIdleWorkder (line 83) | def testSelectIdleWorkder(self):
method testSelectArmy (line 87) | def testSelectArmy(self):
method testSelectWarpGates (line 91) | def testSelectWarpGates(self):
method testSelectLarva (line 95) | def testSelectLarva(self):
method testQuick (line 99) | def testQuick(self):
method testScreen (line 103) | def testScreen(self):
method testScreenMinimap (line 107) | def testScreenMinimap(self):
method testScreenAutocast (line 111) | def testScreenAutocast(self):
method testScreenQuick (line 115) | def testScreenQuick(self):
method testGeneral (line 130) | def testGeneral(self):
method testGeneralType (line 137) | def testGeneralType(self):
method testMany (line 151) | def testMany(self):
class ToPointTest (line 209) | class ToPointTest(absltest.TestCase):
method testIntAsString (line 211) | def testIntAsString(self):
method testIntStringTwoTuple (line 215) | def testIntStringTwoTuple(self):
method testNoneInputReturnsNoneOutput (line 219) | def testNoneInputReturnsNoneOutput(self):
method testNoneAsFirstElementOfTupleRaises (line 223) | def testNoneAsFirstElementOfTupleRaises(self):
method testNoneAsSecondElementOfTupleRaises (line 227) | def testNoneAsSecondElementOfTupleRaises(self):
method testSingletonTupleRaises (line 231) | def testSingletonTupleRaises(self):
method testThreeTupleRaises (line 235) | def testThreeTupleRaises(self):
class DimensionsTest (line 240) | class DimensionsTest(absltest.TestCase):
method testScreenSizeWithoutMinimapRaises (line 242) | def testScreenSizeWithoutMinimapRaises(self):
method testScreenWidthWithoutHeightRaises (line 246) | def testScreenWidthWithoutHeightRaises(self):
method testScreenWidthHeightWithoutMinimapRaises (line 250) | def testScreenWidthHeightWithoutMinimapRaises(self):
method testMinimapWidthAndHeightWithoutScreenRaises (line 254) | def testMinimapWidthAndHeightWithoutScreenRaises(self):
method testNoneNoneRaises (line 258) | def testNoneNoneRaises(self):
method testSingularZeroesRaises (line 262) | def testSingularZeroesRaises(self):
method testTwoZeroesRaises (line 266) | def testTwoZeroesRaises(self):
method testThreeTupleScreenRaises (line 270) | def testThreeTupleScreenRaises(self):
method testThreeTupleMinimapRaises (line 274) | def testThreeTupleMinimapRaises(self):
method testNegativeScreenRaises (line 278) | def testNegativeScreenRaises(self):
method testNegativeMinimapRaises (line 282) | def testNegativeMinimapRaises(self):
method testNegativeScreenTupleRaises (line 286) | def testNegativeScreenTupleRaises(self):
method testNegativeMinimapTupleRaises (line 290) | def testNegativeMinimapTupleRaises(self):
method testEquality (line 294) | def testEquality(self):
class TestParseAgentInterfaceFormat (line 302) | class TestParseAgentInterfaceFormat(parameterized.TestCase):
method test_no_arguments_raises (line 304) | def test_no_arguments_raises(self):
method test_invalid_feature_combinations_raise (line 309) | def test_invalid_feature_combinations_raise(self, screen, minimap):
method test_valid_feature_specification_is_parsed (line 315) | def test_valid_feature_specification_is_parsed(self):
method test_invalid_minimap_combinations_raise (line 329) | def test_invalid_minimap_combinations_raise(self, screen, minimap):
method test_valid_minimap_specification_is_parsed (line 335) | def test_valid_minimap_specification_is_parsed(self):
method test_invalid_action_space_raises (line 348) | def test_invalid_action_space_raises(self):
method test_valid_action_space_is_parsed (line 356) | def test_valid_action_space_is_parsed(self, action_space):
method test_camera_width_world_units_are_parsed (line 369) | def test_camera_width_world_units_are_parsed(self):
method test_use_feature_units_is_parsed (line 377) | def test_use_feature_units_is_parsed(self):
class FeaturesTest (line 386) | class FeaturesTest(absltest.TestCase):
method testFunctionsIdsAreConsistent (line 388) | def testFunctionsIdsAreConsistent(self):
method testAllVersionsOfAnAbilityHaveTheSameGeneral (line 392) | def testAllVersionsOfAnAbilityHaveTheSameGeneral(self):
method testValidFunctionsAreConsistent (line 397) | def testValidFunctionsAreConsistent(self):
method gen_random_function_call (line 408) | def gen_random_function_call(self, action_spec, func_id):
method testIdsMatchIndex (line 413) | def testIdsMatchIndex(self):
method testReversingUnknownAction (line 422) | def testReversingUnknownAction(self):
method testSpecificActionsAreReversible (line 431) | def testSpecificActionsAreReversible(self):
method testRawActionUnitTags (line 463) | def testRawActionUnitTags(self):
method testCanPickleSpecs (line 495) | def testCanPickleSpecs(self):
method testCanPickleFunctionCall (line 505) | def testCanPickleFunctionCall(self):
method testCanDeepcopyNumpyFunctionCall (line 509) | def testCanDeepcopyNumpyFunctionCall(self):
method testSizeConstructors (line 516) | def testSizeConstructors(self):
method testFlRgbActionSpec (line 556) | def testFlRgbActionSpec(self):
method testFlRgbObservationSpec (line 575) | def testFlRgbObservationSpec(self):
FILE: pysc2/lib/image_differencer.py
function image_differencer (line 24) | def image_differencer(path, proto_a, proto_b):
FILE: pysc2/lib/image_differencer_test.py
class ImageDifferencerTest (line 27) | class ImageDifferencerTest(absltest.TestCase):
method testFilteredOut (line 29) | def testFilteredOut(self):
method testFilteredIn (line 36) | def testFilteredIn(self):
FILE: pysc2/lib/memoize.py
function memoize (line 17) | def memoize(func):
FILE: pysc2/lib/metrics.py
class _EventTimer (line 17) | class _EventTimer(object):
method __enter__ (line 20) | def __enter__(self):
method __exit__ (line 23) | def __exit__(self, unused_exception_type, unused_exc_value, unused_tra...
class Metrics (line 27) | class Metrics(object):
method __init__ (line 30) | def __init__(self, map_name):
method increment_instance (line 33) | def increment_instance(self):
method increment_episode (line 36) | def increment_episode(self):
method measure_step_time (line 39) | def measure_step_time(self, num_steps=1):
method measure_observation_time (line 44) | def measure_observation_time(self):
method close (line 48) | def close(self):
method __del__ (line 51) | def __del__(self):
FILE: pysc2/lib/named_array.py
class NamedDict (line 27) | class NamedDict(dict):
method __init__ (line 30) | def __init__(self, *args, **kwargs):
class NamedNumpyArray (line 39) | class NamedNumpyArray(np.ndarray):
method __new__ (line 64) | def __new__(cls, values, names, *args, **kwargs):
method __array_finalize__ (line 126) | def __array_finalize__(self, obj):
method __getattr__ (line 131) | def __getattr__(self, name):
method __setattr__ (line 137) | def __setattr__(self, name, value):
method __getitem__ (line 143) | def __getitem__(self, indices):
method __setitem__ (line 201) | def __setitem__(self, indices, value):
method __getslice__ (line 204) | def __getslice__(self, i, j): # deprecated, but still needed...
method __setslice__ (line 208) | def __setslice__(self, i, j, seq): # deprecated, but still needed...
method __repr__ (line 211) | def __repr__(self):
method __reduce__ (line 232) | def __reduce__(self):
method __setstate__ (line 238) | def __setstate__(self, state):
method _indices (line 243) | def _indices(self, indices):
method _get_index (line 261) | def _get_index(self, dim, index):
FILE: pysc2/lib/named_array_test.py
class NamedDictTest (line 28) | class NamedDictTest(absltest.TestCase):
method test_named_dict (line 30) | def test_named_dict(self):
class TestEnum (line 40) | class TestEnum(enum.IntEnum):
class BadEnum (line 46) | class BadEnum(enum.IntEnum):
class TestNamedTuple (line 52) | class TestNamedTuple(collections.namedtuple("TestNamedTuple", ["a", "b",...
class BadNamedTuple (line 56) | class BadNamedTuple(collections.namedtuple("BadNamedTuple", ["a", "b"])):
class NamedArrayTest (line 60) | class NamedArrayTest(parameterized.TestCase):
method assertArrayEqual (line 62) | def assertArrayEqual(self, a, b):
method test_bad_names (line 77) | def test_bad_names(self, names):
method test_single_dimension (line 92) | def test_single_dimension(self, names):
method test_empty_array (line 167) | def test_empty_array(self):
method test_named_array_multi_first (line 180) | def test_named_array_multi_first(self):
method test_named_array_multi_second (line 224) | def test_named_array_multi_second(self):
method test_masking (line 238) | def test_masking(self):
method test_slicing (line 246) | def test_slicing(self):
method test_string (line 305) | def test_string(self):
method test_pickle (line 350) | def test_pickle(self):
FILE: pysc2/lib/np_util.py
function summarize_array_diffs (line 19) | def summarize_array_diffs(lhs, rhs):
FILE: pysc2/lib/np_util_test.py
class NpUtilTest (line 23) | class NpUtilTest(parameterized.TestCase):
method testSummarizeArrayDiffs (line 32) | def testSummarizeArrayDiffs(self, lhs, rhs, expected):
FILE: pysc2/lib/point.py
class Point (line 21) | class Point(collections.namedtuple("Point", ["x", "y"])):
method build (line 26) | def build(cls, obj):
method unit_rand (line 31) | def unit_rand(cls):
method assign_to (line 35) | def assign_to(self, obj):
method dist (line 40) | def dist(self, other):
method dist_sq (line 46) | def dist_sq(self, other):
method round (line 52) | def round(self):
method floor (line 56) | def floor(self):
method ceil (line 60) | def ceil(self):
method abs (line 64) | def abs(self):
method len (line 68) | def len(self):
method scale (line 72) | def scale(self, target_len):
method scale_max_size (line 76) | def scale_max_size(self, max_size):
method scale_min_size (line 80) | def scale_min_size(self, min_size):
method min_dim (line 84) | def min_dim(self):
method max_dim (line 87) | def max_dim(self):
method transpose (line 90) | def transpose(self):
method rotate_deg (line 94) | def rotate_deg(self, angle):
method rotate_rad (line 97) | def rotate_rad(self, angle):
method rotate_rand (line 101) | def rotate_rand(self, angle=180):
method contained_circle (line 104) | def contained_circle(self, pt, radius):
method bound (line 108) | def bound(self, p1, p2=None):
method __str__ (line 113) | def __str__(self):
method __neg__ (line 119) | def __neg__(self):
method __add__ (line 122) | def __add__(self, pt_or_val):
method __sub__ (line 128) | def __sub__(self, pt_or_val):
method __mul__ (line 134) | def __mul__(self, pt_or_val):
method __truediv__ (line 140) | def __truediv__(self, pt_or_val):
method __floordiv__ (line 146) | def __floordiv__(self, pt_or_val):
class Rect (line 158) | class Rect(collections.namedtuple("Rect", ["t", "l", "b", "r"])):
method __new__ (line 162) | def __new__(cls, *args):
method __str__ (line 183) | def __str__(self):
method center (line 190) | def center(self):
method top (line 194) | def top(self):
method left (line 198) | def left(self):
method bottom (line 202) | def bottom(self):
method right (line 206) | def right(self):
method width (line 210) | def width(self):
method height (line 214) | def height(self):
method tl (line 218) | def tl(self):
method br (line 222) | def br(self):
method tr (line 226) | def tr(self):
method bl (line 230) | def bl(self):
method diagonal (line 234) | def diagonal(self):
method size (line 238) | def size(self):
method area (line 242) | def area(self):
method round (line 246) | def round(self):
method floor (line 249) | def floor(self):
method ceil (line 252) | def ceil(self):
method contains_point (line 255) | def contains_point(self, pt):
method contains_circle (line 260) | def contains_circle(self, pt, radius):
method intersects_circle (line 265) | def intersects_circle(self, pt, radius):
FILE: pysc2/lib/point_flag.py
class PointParser (line 24) | class PointParser(flags.ArgumentParser):
method parse (line 27) | def parse(self, argument):
method flag_type (line 50) | def flag_type(self):
class PointSerializer (line 54) | class PointSerializer(flags.ArgumentSerializer):
method serialize (line 57) | def serialize(self, value):
function DEFINE_point (line 61) | def DEFINE_point(name, default, help_string, flag_values=flags.FLAGS, **...
FILE: pysc2/lib/point_test.py
class FakePoint (line 22) | class FakePoint(object):
method __init__ (line 24) | def __init__(self):
class PointTest (line 29) | class PointTest(absltest.TestCase):
method testBuild (line 31) | def testBuild(self):
method testAssignTo (line 34) | def testAssignTo(self):
method testDist (line 42) | def testDist(self):
method testDistSq (line 47) | def testDistSq(self):
method testLen (line 52) | def testLen(self):
method testScale (line 56) | def testScale(self):
method testScaleMaxSize (line 60) | def testScaleMaxSize(self):
method testScaleMinSize (line 67) | def testScaleMinSize(self):
method testMinDim (line 74) | def testMinDim(self):
method testMaxDim (line 77) | def testMaxDim(self):
method testTranspose (line 80) | def testTranspose(self):
method testRound (line 83) | def testRound(self):
method testCeil (line 89) | def testCeil(self):
method testFloor (line 95) | def testFloor(self):
method testRotate (line 101) | def testRotate(self):
method testContainedCircle (line 107) | def testContainedCircle(self):
method testBound (line 111) | def testBound(self):
class RectTest (line 119) | class RectTest(absltest.TestCase):
method testInit (line 121) | def testInit(self):
method testInitBad (line 132) | def testInitBad(self):
method testInitOnePoint (line 142) | def testInitOnePoint(self):
method testInitTwoPoints (line 156) | def testInitTwoPoints(self):
method testInitTwoPointsReversed (line 170) | def testInitTwoPointsReversed(self):
method testArea (line 184) | def testArea(self):
method testContains (line 188) | def testContains(self):
method testIntersectsCircle (line 195) | def testIntersectsCircle(self):
FILE: pysc2/lib/portspicker.py
function pick_unused_ports (line 25) | def pick_unused_ports(num_ports, retry_interval_secs=1, retry_attempts=5):
function pick_contiguous_unused_ports (line 46) | def pick_contiguous_unused_ports(
function return_ports (line 68) | def return_ports(ports):
FILE: pysc2/lib/portspicker_test.py
class PortsTest (line 22) | class PortsTest(parameterized.TestCase):
method testNonContiguousReservation (line 25) | def testNonContiguousReservation(self, num_ports):
method testContiguousReservation (line 31) | def testContiguousReservation(self, num_ports):
method testInvalidReservation (line 36) | def testInvalidReservation(self):
method testInvalidContiguousReservation (line 40) | def testInvalidContiguousReservation(self):
FILE: pysc2/lib/proto_diff.py
class ProtoPath (line 23) | class ProtoPath(object):
method __init__ (line 26) | def __init__(self, path):
method get_field (line 34) | def get_field(self, proto):
method with_anonymous_array_indices (line 45) | def with_anonymous_array_indices(self):
method path (line 52) | def path(self):
method __lt__ (line 55) | def __lt__(self, other):
method __getitem__ (line 64) | def __getitem__(self, item):
method __len__ (line 67) | def __len__(self):
method __eq__ (line 70) | def __eq__(self, o):
method __hash__ (line 73) | def __hash__(self):
method __repr__ (line 76) | def __repr__(self):
class ProtoDiffs (line 87) | class ProtoDiffs(object):
method __init__ (line 90) | def __init__(self, proto_a, proto_b, changed, added, removed):
method proto_a (line 107) | def proto_a(self):
method proto_b (line 111) | def proto_b(self):
method changed (line 115) | def changed(self):
method added (line 119) | def added(self):
method removed (line 123) | def removed(self):
method all_diffs (line 126) | def all_diffs(self):
method report (line 129) | def report(self, differencers=None, truncate_to=0):
method __repr__ (line 174) | def __repr__(self):
function _truncate (line 179) | def _truncate(val, truncate_to):
function _dict_path_to_proto_path (line 187) | def _dict_path_to_proto_path(dict_path):
function compute_diff (line 194) | def compute_diff(proto_a, proto_b):
FILE: pysc2/lib/proto_diff_test.py
class ProtoPathTest (line 24) | class ProtoPathTest(absltest.TestCase):
method testCreationFromTuple (line 26) | def testCreationFromTuple(self):
method testCreationFromList (line 31) | def testCreationFromList(self):
method testCreationFromGenerator (line 36) | def testCreationFromGenerator(self):
method testStringRepr (line 41) | def testStringRepr(self):
method testOrdering (line 46) | def testOrdering(self):
method testEquals (line 59) | def testEquals(self):
method testNotEqual (line 65) | def testNotEqual(self):
method testIndexing (line 71) | def testIndexing(self):
method testGetField (line 78) | def testGetField(self):
method testWithAnonymousArrayIndices (line 90) | def testWithAnonymousArrayIndices(self):
function _alert_formatter (line 102) | def _alert_formatter(path, proto_a, proto_b):
class ProtoDiffTest (line 110) | class ProtoDiffTest(absltest.TestCase):
method testNoDiffs (line 112) | def testNoDiffs(self):
method testAddedField (line 118) | def testAddedField(self):
method testAddedFields (line 129) | def testAddedFields(self):
method testRemovedField (line 148) | def testRemovedField(self):
method testRemovedFields (line 160) | def testRemovedFields(self):
method testChangedField (line 180) | def testChangedField(self):
method testChangedFields (line 190) | def testChangedFields(self):
method testTruncation (line 211) | def testTruncation(self):
FILE: pysc2/lib/protocol.py
class ConnectionError (line 48) | class ConnectionError(Exception): # pylint: disable=redefined-builtin
class ProtocolError (line 53) | class ProtocolError(Exception): # pylint: disable=g-bad-exception-name
function catch_websocket_connection_errors (line 59) | def catch_websocket_connection_errors():
class StarcraftProtocol (line 72) | class StarcraftProtocol(object):
method __init__ (line 75) | def __init__(self, sock):
method status (line 82) | def status(self):
method close (line 85) | def close(self):
method read (line 92) | def read(self):
method write (line 116) | def write(self, request):
method send_req (line 124) | def send_req(self, request):
method send (line 129) | def send(self, **kwargs):
method _packet_str (line 155) | def _packet_str(self, packet):
method _log (line 168) | def _log(self, s, *args):
method _read (line 175) | def _read(self):
method _write (line 186) | def _write(self, request):
FILE: pysc2/lib/remote_controller.py
class ConnectError (line 44) | class ConnectError(Exception):
class RequestError (line 48) | class RequestError(Exception):
method __init__ (line 50) | def __init__(self, description, res):
function check_error (line 55) | def check_error(res, error_enum):
function decorate_check_error (line 65) | def decorate_check_error(error_enum):
function skip_status (line 75) | def skip_status(*skipped):
function valid_status (line 86) | def valid_status(*valid):
function catch_game_end (line 100) | def catch_game_end(func):
class RemoteController (line 128) | class RemoteController(object):
method __init__ (line 140) | def __init__(self, host, port, proc=None, timeout_seconds=None):
method _connect (line 148) | def _connect(self, host, port, proc, timeout_seconds):
method close (line 178) | def close(self):
method status_ended (line 182) | def status_ended(self):
method create_game (line 188) | def create_game(self, req_create_game):
method save_map (line 195) | def save_map(self, map_path, map_data):
method join_game (line 203) | def join_game(self, req_join_game):
method restart (line 210) | def restart(self):
method start_replay (line 217) | def start_replay(self, req_start_replay):
method game_info (line 223) | def game_info(self):
method data_raw (line 229) | def data_raw(self, ability_id=True, unit_type_id=True, upgrade_id=True,
method data (line 236) | def data(self):
method observe (line 242) | def observe(self, disable_fog=False, target_game_loop=0):
method available_maps (line 275) | def available_maps(self):
method step (line 281) | def step(self, count=1):
method actions (line 289) | def actions(self, req_action):
method act (line 299) | def act(self, action):
method observer_actions (line 307) | def observer_actions(self, req_observer_action):
method observer_act (line 317) | def observer_act(self, action):
method chat (line 323) | def chat(self, message, channel=sc_pb.ActionChat.Broadcast):
method leave (line 333) | def leave(self):
method save_replay (line 339) | def save_replay(self):
method debug (line 346) | def debug(self, debug_commands):
method query (line 354) | def query(self, query):
method quit (line 360) | def quit(self):
method ping (line 371) | def ping(self):
method replay_info (line 376) | def replay_info(self, replay_data):
method status (line 381) | def status(self):
FILE: pysc2/lib/renderer_ascii.py
function get_printable_unit_types (line 20) | def get_printable_unit_types():
function _summary (line 58) | def _summary(obs, view, width):
function screen (line 65) | def screen(obs):
function minimap (line 95) | def minimap(obs):
FILE: pysc2/lib/renderer_human.py
function with_lock (line 58) | def with_lock(lock):
function clamp (line 69) | def clamp(n, smallest, largest):
class MouseButtons (line 73) | class MouseButtons(enum.IntEnum):
class SurfType (line 82) | class SurfType(enum.IntEnum):
class ActionCmd (line 91) | class ActionCmd(enum.Enum):
class _Ability (line 97) | class _Ability(collections.namedtuple("_Ability", [
method __new__ (line 101) | def __new__(cls, ability, static_data):
class _Surface (line 117) | class _Surface(object):
method __init__ (line 120) | def __init__(self, surf, surf_type, surf_rect, world_to_surf, world_to...
method draw_line (line 139) | def draw_line(self, color, start_loc, end_loc, thickness=1):
method draw_arc (line 146) | def draw_arc(self, color, world_loc, world_radius, start_angle, stop_a...
method draw_circle (line 155) | def draw_circle(self, color, world_loc, world_radius, thickness=0):
method draw_rect (line 163) | def draw_rect(self, color, world_rect, thickness=0):
method blit_np_array (line 170) | def blit_np_array(self, array):
method write_screen (line 177) | def write_screen(self, font, color, screen_pos, text, align="left",
method write_world (line 193) | def write_world(self, font, color, world_loc, text):
class MousePos (line 200) | class MousePos(collections.namedtuple("MousePos", ["world_pos", "surf"])):
method surf_pos (line 205) | def surf_pos(self):
method obs_pos (line 209) | def obs_pos(self):
method action_spatial (line 212) | def action_spatial(self, action):
class PastAction (line 222) | class PastAction(collections.namedtuple("PastAction", [
function _get_desktop_size (line 228) | def _get_desktop_size():
function circle_mask (line 244) | def circle_mask(shape, pt, radius):
class RendererHuman (line 253) | class RendererHuman(object):
method __init__ (line 301) | def __init__(self, fps=22.4, step_mul=1, render_sync=False,
method close (line 335) | def close(self):
method init (line 345) | def init(self, game_info, static_data):
method init_window (line 411) | def init_window(self):
method _update_camera (line 702) | def _update_camera(self, camera_center):
method zoom (line 717) | def zoom(self, factor):
method get_mouse_pos (line 726) | def get_mouse_pos(self, window_pos=None):
method clear_queued_action (line 738) | def clear_queued_action(self):
method save_replay (line 742) | def save_replay(self, run_config, controller):
method get_actions (line 752) | def get_actions(self, run_config, controller):
method camera_action (line 887) | def camera_action(self, mouse_pos):
method camera_action_raw (line 895) | def camera_action_raw(self, world_pos):
method camera_action_observer_pt (line 901) | def camera_action_observer_pt(self, world_pos):
method camera_action_observer_player (line 907) | def camera_action_observer_player(self, player_id):
method select_action (line 913) | def select_action(self, pos1, pos2, ctrl, shift):
method select_idle_worker (line 959) | def select_idle_worker(self, ctrl, shift):
method select_army (line 970) | def select_army(self, shift):
method select_warp_gates (line 976) | def select_warp_gates(self, shift):
method select_larva (line 982) | def select_larva(self):
method control_group (line 988) | def control_group(self, control_group_id, ctrl, shift, alt):
method unit_action (line 1009) | def unit_action(self, cmd, pos, shift):
method _abilities (line 1045) | def _abilities(self, fn=None):
method _visible_units (line 1054) | def _visible_units(self):
method _units_in_area (line 1062) | def _units_in_area(self, rect):
method get_unit_name (line 1068) | def get_unit_name(self, surf, name, radius):
method draw_units (line 1082) | def draw_units(self, surf):
method draw_effects (line 1188) | def draw_effects(self, surf):
method draw_selection (line 1207) | def draw_selection(self, surf):
method draw_build_target (line 1218) | def draw_build_target(self, surf):
method draw_overlay (line 1236) | def draw_overlay(self, surf):
method draw_help (line 1269) | def draw_help(self, surf):
method draw_commands (line 1286) | def draw_commands(self, surf):
method draw_panel (line 1326) | def draw_panel(self, surf):
method draw_actions (line 1429) | def draw_actions(self):
method prepare_actions (line 1443) | def prepare_actions(self, obs):
method draw_base_map (line 1518) | def draw_base_map(self, surf):
method draw_mini_map (line 1556) | def draw_mini_map(self, surf):
method check_valid_queued_action (line 1615) | def check_valid_queued_action(self):
method draw_rendered_map (line 1625) | def draw_rendered_map(self, surf):
method draw_screen (line 1630) | def draw_screen(self, surf):
method draw_feature_layer (line 1647) | def draw_feature_layer(self, surf, feature):
method draw_raw_layer (line 1656) | def draw_raw_layer(self, surf, from_obs, name, color):
method all_surfs (line 1668) | def all_surfs(self, fn, *args, **kwargs):
method render (line 1674) | def render(self, obs):
method render_thread (line 1688) | def render_thread(self):
method render_obs (line 1710) | def render_obs(self, obs):
method run (line 1735) | def run(self, run_config, controller, max_game_steps=0, max_episodes=0,
method __del__ (line 1807) | def __del__(self):
FILE: pysc2/lib/replay.py
function get_replay_version (line 24) | def get_replay_version(replay_data):
FILE: pysc2/lib/replay/replay_converter.py
function _unconverted_observation (line 31) | def _unconverted_observation(observation, actions):
function get_flat_action (line 43) | def get_flat_action(obs: Dict[str, Any]) -> Dict[str, Any]:
function _convert_observation (line 53) | def _convert_observation(converter, player_observation, force_action_delay,
function converted_observations (line 68) | def converted_observations(observations_iterator, converter, accept_step...
function converted_observation_stream (line 139) | def converted_observation_stream(
function get_step_sequence (line 182) | def get_step_sequence(action_skips: Iterable[int]) -> Sequence[int]:
FILE: pysc2/lib/replay/replay_observation_stream.py
function _get_replay_version (line 27) | def _get_replay_version(replay_data):
class ReplayError (line 41) | class ReplayError(Exception):
class ReplayObservationStream (line 45) | class ReplayObservationStream(object):
method __init__ (line 68) | def __init__(self,
method _get_controllers (line 105) | def _get_controllers(self, version):
method _close (line 121) | def _close(self):
method start_replay_from_data (line 132) | def start_replay_from_data(self, replay_data, player_id):
method replay_info (line 173) | def replay_info(self):
method game_info (line 176) | def game_info(self):
method static_data (line 179) | def static_data(self):
method observations (line 182) | def observations(self, step_sequence=None):
method close (line 230) | def close(self):
method __enter__ (line 235) | def __enter__(self):
method __exit__ (line 238) | def __exit__(self, exception_type, exception_value, traceback):
FILE: pysc2/lib/replay/sc2_replay.py
function _convert_to_str (line 25) | def _convert_to_str(s):
function _convert_all_to_str (line 32) | def _convert_all_to_str(structure):
class SC2Replay (line 39) | class SC2Replay(object):
method __init__ (line 42) | def __init__(self, replay_data):
method details (line 47) | def details(self):
method init_data (line 55) | def init_data(self):
method tracker_events (line 60) | def tracker_events(self, filter_fn=None):
method game_events (line 68) | def game_events(self, filter_fn=None):
method message_events (line 76) | def message_events(self, filter_fn=None):
method attributes_events (line 84) | def attributes_events(self, filter_fn=None):
method metadata (line 93) | def metadata(self):
method protocol (line 97) | def protocol(self):
function _extract (line 101) | def _extract(contents):
FILE: pysc2/lib/replay/sc2_replay_test.py
class Sc2ReplayTest (line 26) | class Sc2ReplayTest(absltest.TestCase):
method setUp (line 28) | def setUp(self):
method testDetails (line 36) | def testDetails(self):
method testInitData (line 74) | def testInitData(self):
method testTrackerEvents (line 86) | def testTrackerEvents(self):
method testGameEvents (line 102) | def testGameEvents(self):
method testMessageEvents (line 119) | def testMessageEvents(self):
method testAttributesEvents (line 127) | def testAttributesEvents(self):
FILE: pysc2/lib/replay/sc2_replay_utils.py
function _readable_event_type (line 42) | def _readable_event_type(full_event_type):
class EventData (line 47) | class EventData:
function raw_action_skips (line 52) | def raw_action_skips(replay: sc2_replay.SC2Replay) -> Mapping[int, List[...
FILE: pysc2/lib/replay/sc2_replay_utils_test.py
function _read_replay (line 30) | def _read_replay(name):
function _read_skips (line 37) | def _read_skips(name):
class Sc2ReplayUtilsTest (line 43) | class Sc2ReplayUtilsTest(parameterized.TestCase):
method test_raw_action_skips (line 48) | def test_raw_action_skips(self, replay_name, skips_file):
FILE: pysc2/lib/resources.py
function GetResourceFilename (line 17) | def GetResourceFilename(path):
FILE: pysc2/lib/run_parallel.py
class RunParallel (line 24) | class RunParallel(object):
method __init__ (line 27) | def __init__(self, timeout=None):
method run (line 32) | def run(self, funcs):
method shutdown (line 79) | def shutdown(self, wait=True):
method __del__ (line 85) | def __del__(self):
FILE: pysc2/lib/run_parallel_test.py
class Barrier (line 23) | class Barrier(object):
method __init__ (line 25) | def __init__(self, n):
method wait (line 30) | def wait(self):
method clear (line 42) | def clear(self):
function bad (line 48) | def bad():
class RunParallelTest (line 52) | class RunParallelTest(absltest.TestCase):
method test_returns_expected_values (line 54) | def test_returns_expected_values(self):
method test_run_in_parallel (line 62) | def test_run_in_parallel(self):
method test_avoids_deadlock (line 69) | def test_avoids_deadlock(self):
method test_exception (line 78) | def test_exception(self):
method test_partial (line 89) | def test_partial(self):
FILE: pysc2/lib/sc_process.py
class SC2LaunchError (line 44) | class SC2LaunchError(Exception):
class StarcraftProcess (line 48) | class StarcraftProcess(object):
method __init__ (line 58) | def __init__(self, run_config, exec_path, version, full_screen=False,
method close (line 144) | def close(self):
method controller (line 159) | def controller(self):
method host (line 163) | def host(self):
method port (line 167) | def port(self):
method version (line 171) | def version(self):
method __enter__ (line 174) | def __enter__(self):
method __exit__ (line 177) | def __exit__(self, unused_exception_type, unused_exc_value, unused_tra...
method __del__ (line 180) | def __del__(self):
method _check_exists (line 184) | def _check_exists(self, exec_path):
method _launch (line 191) | def _launch(self, run_config, args, **kwargs):
method _shutdown (line 201) | def _shutdown(self):
method running (line 209) | def running(self):
method pid (line 216) | def pid(self):
function _shutdown_proc (line 220) | def _shutdown_proc(p, timeout):
FILE: pysc2/lib/static_data.py
class StaticData (line 17) | class StaticData(object):
method __init__ (line 20) | def __init__(self, data):
method abilities (line 34) | def abilities(self):
method upgrades (line 38) | def upgrades(self):
method units (line 42) | def units(self):
method unit_stats (line 46) | def unit_stats(self):
method general_abilities (line 50) | def general_abilities(self):
FILE: pysc2/lib/stopwatch.py
class Stat (line 25) | class Stat(object):
method __init__ (line 29) | def __init__(self):
method reset (line 32) | def reset(self):
method add (line 39) | def add(self, val):
method avg (line 49) | def avg(self):
method dev (line 53) | def dev(self):
method merge (line 59) | def merge(self, other):
method build (line 67) | def build(summation, average, standard_deviation, minimum, maximum, nu...
method parse (line 78) | def parse(s):
method __str__ (line 84) | def __str__(self):
class StopWatchContext (line 91) | class StopWatchContext(object):
method __init__ (line 95) | def __init__(self, stopwatch, name):
method __enter__ (line 99) | def __enter__(self):
method __exit__ (line 102) | def __exit__(self, unused_exception_type, unused_exc_value, unused_tra...
class TracingStopWatchContext (line 106) | class TracingStopWatchContext(StopWatchContext):
method __enter__ (line 109) | def __enter__(self):
method __exit__ (line 113) | def __exit__(self, *args, **kwargs):
method _log (line 118) | def _log(self, s):
class FakeStopWatchContext (line 122) | class FakeStopWatchContext(object):
method __enter__ (line 126) | def __enter__(self):
method __exit__ (line 129) | def __exit__(self, unused_exception_type, unused_exc_value, unused_tra...
class StopWatch (line 136) | class StopWatch(object):
method __init__ (line 153) | def __init__(self, enabled=True, trace=False):
method disable (line 163) | def disable(self):
method enable (line 166) | def enable(self):
method trace (line 169) | def trace(self):
method custom (line 172) | def custom(self, factory):
method __call__ (line 175) | def __call__(self, name):
method decorate (line 178) | def decorate(self, name_or_func):
method push (line 212) | def push(self, name):
method pop (line 219) | def pop(self):
method cur_stack (line 225) | def cur_stack(self):
method clear (line 228) | def clear(self):
method add (line 231) | def add(self, name, duration):
method __getitem__ (line 234) | def __getitem__(self, name):
method times (line 238) | def times(self):
method merge (line 241) | def merge(self, other):
method parse (line 246) | def parse(s):
method str (line 258) | def str(self, threshold=0.1):
method __str__ (line 288) | def __str__(self):
FILE: pysc2/lib/stopwatch_test.py
function ham_dist (line 25) | def ham_dist(str1, str2):
class StatTest (line 31) | class StatTest(absltest.TestCase):
method testRange (line 33) | def testRange(self):
method testParse (line 44) | def testParse(self):
class StopwatchTest (line 55) | class StopwatchTest(absltest.TestCase):
method testStopwatch (line 58) | def testStopwatch(self, mock_time):
method testDivideZero (line 95) | def testDivideZero(self):
method testDecoratorDisabled (line 104) | def testDecoratorDisabled(self):
method testDecoratorEnabled (line 110) | def testDecoratorEnabled(self):
method testSpeed (line 115) | def testSpeed(self):
FILE: pysc2/lib/transform.py
class Transform (line 31) | class Transform(object):
method fwd_dist (line 34) | def fwd_dist(self, dist):
method fwd_pt (line 37) | def fwd_pt(self, pt):
method back_dist (line 40) | def back_dist(self, dist):
method back_pt (line 43) | def back_pt(self, pt):
class Linear (line 47) | class Linear(Transform):
method __init__ (line 50) | def __init__(self, scale=None, offset=None):
method fwd_dist (line 60) | def fwd_dist(self, dist):
method fwd_pt (line 63) | def fwd_pt(self, pt):
method back_dist (line 66) | def back_dist(self, dist):
method back_pt (line 69) | def back_pt(self, pt):
method __str__ (line 72) | def __str__(self):
class Chain (line 76) | class Chain(Transform):
method __init__ (line 79) | def __init__(self, *args):
method fwd_dist (line 82) | def fwd_dist(self, dist):
method fwd_pt (line 87) | def fwd_pt(self, pt):
method back_dist (line 92) | def back_dist(self, dist):
method back_pt (line 97) | def back_pt(self, pt):
method __str__ (line 102) | def __str__(self):
class PixelToCoord (line 106) | class PixelToCoord(Transform):
method fwd_dist (line 109) | def fwd_dist(self, dist):
method fwd_pt (line 112) | def fwd_pt(self, pt):
method back_dist (line 115) | def back_dist(self, dist):
method back_pt (line 118) | def back_pt(self, pt):
method __str__ (line 121) | def __str__(self):
FILE: pysc2/lib/units.py
class Neutral (line 20) | class Neutral(enum.IntEnum):
class Protoss (line 102) | class Protoss(enum.IntEnum):
class Terran (line 151) | class Terran(enum.IntEnum):
class Zerg (line 215) | class Zerg(enum.IntEnum):
function get_unit_type (line 295) | def get_unit_type(unit_id):
FILE: pysc2/lib/upgrades.py
class Upgrades (line 20) | class Upgrades(enum.IntEnum):
FILE: pysc2/lib/video_writer.py
class VideoWriter (line 19) | class VideoWriter(io.FFmpegWriter):
method __init__ (line 25) | def __init__(self, filename, frame_rate):
method add (line 29) | def add(self, frame):
method __del__ (line 33) | def __del__(self):
FILE: pysc2/maps/ladder.py
class Ladder (line 25) | class Ladder(lib.Map):
FILE: pysc2/maps/lib.py
class DuplicateMapError (line 36) | class DuplicateMapError(Exception):
class NoMapError (line 40) | class NoMapError(Exception):
class Map (line 44) | class Map(object):
method path (line 73) | def path(self):
method data (line 81) | def data(self, run_config):
method name (line 92) | def name(self):
method __str__ (line 95) | def __str__(self):
method all_subclasses (line 107) | def all_subclasses(cls):
function get_maps (line 115) | def get_maps():
function get (line 127) | def get(map_name):
FILE: pysc2/maps/melee.py
class Melee (line 19) | class Melee(lib.Map):
FILE: pysc2/maps/mini_games.py
class MiniGame (line 19) | class MiniGame(lib.Map):
FILE: pysc2/run_configs/__init__.py
function get (line 27) | def get(version=None):
FILE: pysc2/run_configs/lib.py
class Version (line 23) | class Version(collections.namedtuple("Version", [
function version_dict (line 29) | def version_dict(versions):
class RunConfig (line 108) | class RunConfig(object):
method __init__ (line 111) | def __init__(self, replay_dir, data_dir, tmp_dir, version,
method map_data (line 130) | def map_data(self, map_name, players=None):
method abs_replay_path (line 144) | def abs_replay_path(self, replay_path):
method replay_data (line 148) | def replay_data(self, replay_path):
method replay_paths (line 153) | def replay_paths(self, replay_dir):
method save_replay (line 163) | def save_replay(self, replay_data, replay_dir, prefix=None):
method start (line 194) | def start(self, version=None, **kwargs):
method all_subclasses (line 199) | def all_subclasses(cls):
method name (line 207) | def name(cls):
method priority (line 211) | def priority(cls):
method get_versions (line 215) | def get_versions(self, containing=None):
method _get_version (line 222) | def _get_version(self, game_version):
FILE: pysc2/run_configs/platforms.py
function _read_execute_info (line 36) | def _read_execute_info(path, parents):
class LocalBase (line 50) | class LocalBase(lib.RunConfig):
method __init__ (line 53) | def __init__(self, base_dir, exec_name, version, cwd=None, env=None):
method start (line 67) | def start(self, want_rgb=True, **kwargs):
method get_versions (line 86) | def get_versions(self, containing=None):
class Windows (line 109) | class Windows(LocalBase):
method __init__ (line 112) | def __init__(self, version=None):
method priority (line 120) | def priority(cls):
class Cygwin (line 125) | class Cygwin(LocalBase):
method __init__ (line 128) | def __init__(self, version=None):
method priority (line 135) | def priority(cls):
class MacOS (line 140) | class MacOS(LocalBase):
method __init__ (line 143) | def __init__(self, version=None):
method priority (line 152) | def priority(cls):
class Linux (line 157) | class Linux(LocalBase):
method __init__ (line 168) | def __init__(self, version=None):
method priority (line 178) | def priority(cls):
method start (line 182) | def start(self, want_rgb=True, **kwargs):
FILE: pysc2/tests/actions_test.py
function raw_ability_ids (line 25) | def raw_ability_ids(obs):
class ActionsTest (line 30) | class ActionsTest(utils.GameReplayTestCase):
method test_general_attack (line 33) | def test_general_attack(self):
FILE: pysc2/tests/debug_test.py
class DebugTest (line 28) | class DebugTest(absltest.TestCase):
method test_multi_player (line 30) | def test_multi_player(self):
FILE: pysc2/tests/dummy_observation.py
class Unit (line 30) | class Unit(object):
method __init__ (line 33) | def __init__(
method fill (line 51) | def fill(self, unit_proto):
method as_array (line 61) | def as_array(self):
method as_dict (line 73) | def as_dict(self):
class FeatureUnit (line 77) | class FeatureUnit(object):
method __init__ (line 80) | def __init__(
method as_dict (line 136) | def as_dict(self):
class Builder (line 140) | class Builder(object):
method __init__ (line 143) | def __init__(self, obs_spec):
method game_loop (line 182) | def game_loop(self, game_loop):
method player_common (line 187) | def player_common(
method score (line 208) | def score(self, score):
method score_details (line 212) | def score_details(
method score_by_category (line 235) | def score_by_category(
method score_by_vital (line 247) | def score_by_vital(self, entry_name, life, shields, energy):
method single_select (line 255) | def single_select(self, unit):
method multi_select (line 259) | def multi_select(self, units):
method build_queue (line 263) | def build_queue(self, build_queue, production=None):
method feature_units (line 268) | def feature_units(self, feature_units):
method build (line 272) | def build(self):
FILE: pysc2/tests/dummy_observation_test.py
class DummyObservationTest (line 39) | class DummyObservationTest(parameterized.TestCase):
method setUp (line 41) | def setUp(self):
method testFeatureScreenMatchesSpec (line 57) | def testFeatureScreenMatchesSpec(self):
method testFeatureMinimapMatchesSpec (line 63) | def testFeatureMinimapMatchesSpec(self):
method testRgbScreenMatchesSpec (line 69) | def testRgbScreenMatchesSpec(self):
method testGameLoopCanBeSet (line 73) | def testGameLoopCanBeSet(self):
method testPlayerCommonCanBeSet (line 78) | def testPlayerCommonCanBeSet(self):
method testScoreCanBeSet (line 103) | def testScoreCanBeSet(self):
method testScoreDetailsCanBeSet (line 108) | def testScoreDetailsCanBeSet(self):
method testScoreByCategorySpec (line 136) | def testScoreByCategorySpec(self):
method testScoreByCategory (line 143) | def testScoreByCategory(self, entry_name):
method testScoreByVitalSpec (line 170) | def testScoreByVitalSpec(self):
method testScoreByVital (line 177) | def testScoreByVital(self, entry_name):
method testRgbMinimapMatchesSpec (line 198) | def testRgbMinimapMatchesSpec(self):
method testNoSingleSelect (line 202) | def testNoSingleSelect(self):
method testWithSingleSelect (line 206) | def testWithSingleSelect(self):
method testNoMultiSelect (line 211) | def testNoMultiSelect(self):
method testWithMultiSelect (line 215) | def testWithMultiSelect(self):
method testBuildQueue (line 223) | def testBuildQueue(self):
method testFeatureUnitsAreAdded (line 243) | def testFeatureUnitsAreAdded(self):
method _get_obs (line 277) | def _get_obs(self):
method _check_layer (line 280) | def _check_layer(self, layer, x, y, bits):
method _check_attributes_match (line 285) | def _check_attributes_match(self, a, b, attributes):
method _check_unit (line 289) | def _check_unit(self, proto, builder):
method _check_feature_unit (line 292) | def _check_feature_unit(self, proto, builder):
FILE: pysc2/tests/easy_scripted_test.py
class TestEasy (line 25) | class TestEasy(utils.TestCase):
method test_move_to_beacon (line 29) | def test_move_to_beacon(self):
method test_collect_mineral_shards (line 46) | def test_collect_mineral_shards(self):
method test_collect_mineral_shards_feature_units (line 63) | def test_collect_mineral_shards_feature_units(self):
method test_collect_mineral_shards_raw (line 81) | def test_collect_mineral_shards_raw(self):
method test_defeat_roaches (line 97) | def test_defeat_roaches(self):
method test_defeat_roaches_raw (line 114) | def test_defeat_roaches_raw(self):
FILE: pysc2/tests/general_actions_test.py
class TestGeneralActions (line 27) | class TestGeneralActions(utils.TestCase):
method test_general_actions (line 30) | def test_general_actions(self):
FILE: pysc2/tests/host_remote_agent_test.py
class TestHostRemoteAgent (line 32) | class TestHostRemoteAgent(utils.TestCase):
method testVsBot (line 34) | def testVsBot(self):
method testVsAgent (line 59) | def testVsAgent(self):
FILE: pysc2/tests/multi_player_env_test.py
class TestMultiplayerEnv (line 30) | class TestMultiplayerEnv(parameterized.TestCase, utils.TestCase):
method test_multi_player_env (line 57) | def test_multi_player_env(self, agent_interface_format):
FILE: pysc2/tests/multi_player_test.py
function print_stage (line 33) | def print_stage(stage):
class TestMultiplayer (line 37) | class TestMultiplayer(utils.TestCase):
method test_multi_player (line 39) | def test_multi_player(self):
FILE: pysc2/tests/obs_spec_test.py
class TestObservationSpec (line 24) | class TestObservationSpec(utils.TestCase):
method test_observation_matches_obs_spec (line 26) | def test_observation_matches_obs_spec(self):
method test_heterogeneous_observations (line 62) | def test_heterogeneous_observations(self):
method check_observation_matches_spec (line 113) | def check_observation_matches_spec(self, obs, obs_spec):
FILE: pysc2/tests/obs_test.py
class ObsTest (line 36) | class ObsTest(utils.GameReplayTestCase):
method test_hallucination (line 39) | def test_hallucination(self):
method test_hide_cloaked (line 82) | def test_hide_cloaked(self):
method test_show_cloaked (line 134) | def test_show_cloaked(self):
method test_pos (line 187) | def test_pos(self):
method test_fog (line 217) | def test_fog(self):
method test_effects (line 250) | def test_effects(self):
method test_active (line 366) | def test_active(self):
method test_disable_fog (line 434) | def test_disable_fog(self):
method test_action_delay (line 466) | def test_action_delay(self):
method test_camera_movement_delay (line 512) | def test_camera_movement_delay(self):
FILE: pysc2/tests/observer_test.py
class TestObserver (line 27) | class TestObserver(utils.TestCase):
method test_observer (line 29) | def test_observer(self):
FILE: pysc2/tests/ping_test.py
class TestPing (line 24) | class TestPing(utils.TestCase):
method test_ping (line 26) | def test_ping(self):
FILE: pysc2/tests/protocol_error_test.py
class TestProtocolError (line 29) | class TestProtocolError(utils.TestCase):
method test_error (line 32) | def test_error(self):
method test_replay_a_replay (line 40) | def test_replay_a_replay(self):
FILE: pysc2/tests/random_agent_test.py
class TestRandomAgent (line 26) | class TestRandomAgent(parameterized.TestCase, utils.TestCase):
method test_random_agent (line 40) | def test_random_agent(self, agent_interface_format):
FILE: pysc2/tests/render_test.py
class TestRender (line 30) | class TestRender(utils.TestCase):
method test_render (line 32) | def test_render(self):
FILE: pysc2/tests/replay_obs_test.py
function identity_function (line 38) | def identity_function(name, args):
function any_point (line 42) | def any_point(unit_type, obs):
function avg_point (line 50) | def avg_point(unit_type, obs):
function select (line 58) | def select(func, unit_type):
class Config (line 62) | class Config(object):
method __init__ (line 65) | def __init__(self):
class GameController (line 103) | class GameController(object):
method __init__ (line 106) | def __init__(self, config):
method _initialize (line 118) | def _initialize(self):
method start_replay (line 128) | def start_replay(self, replay_data):
method create_game (line 137) | def create_game(self):
method controller (line 155) | def controller(self):
method close (line 158) | def close(self):
method __enter__ (line 167) | def __enter__(self):
method __exit__ (line 170) | def __exit__(self, exception_type, exception_value, traceback):
class ReplayObsTest (line 174) | class ReplayObsTest(utils.TestCase):
method _get_replay_data (line 176) | def _get_replay_data(self, controller, config):
method _process_replay (line 231) | def _process_replay(self, controller, observations, config):
method test_replay_observations_match (line 274) | def test_replay_observations_match(self):
FILE: pysc2/tests/step_mul_override_test.py
class StepMulOverrideTest (line 29) | class StepMulOverrideTest(utils.TestCase):
method test_returns_game_loop_zero_on_first_step_despite_override (line 31) | def test_returns_game_loop_zero_on_first_step_despite_override(self):
method test_respects_override (line 45) | def test_respects_override(self):
FILE: pysc2/tests/utils.py
class TestCase (line 37) | class TestCase(absltest.TestCase):
method setUp (line 40) | def setUp(self):
method tearDown (line 45) | def tearDown(self):
function get_units (line 53) | def get_units(obs, filter_fn=None, owner=None, unit_type=None, tag=None):
function get_unit (line 67) | def get_unit(*args, **kwargs):
function xy_locs (line 75) | def xy_locs(mask):
function only_in_game (line 81) | def only_in_game(func):
class GameReplayTestCase (line 89) | class GameReplayTestCase(TestCase):
method setup (line 93) | def setup(**kwargs):
method start_game (line 116) | def start_game(self, show_cloaked=True, disable_fog=False, players=2):
method start_replay (line 175) | def start_replay(self):
method close (line 190) | def close(self): # Instead of tearDown.
method step (line 209) | def step(self, count=4):
method observe (line 212) | def observe(self, disable_fog=False):
method move_camera (line 217) | def move_camera(self, x, y):
method raw_unit_command (line 224) | def raw_unit_command(self, player, ability_id, unit_tags, pos=None,
method debug (line 246) | def debug(self, player=0, **kwargs):
method god (line 249) | def god(self):
method create_unit (line 254) | def create_unit(self, unit_type, owner, pos, quantity=1):
method kill_unit (line 262) | def kill_unit(self, unit_tags):
method set_energy (line 267) | def set_energy(self, tag, energy):
method assert_point (line 272) | def assert_point(self, proto_pos, pos):
method assert_layers (line 276) | def assert_layers(self, layers, pos, **kwargs):
method assert_unit (line 282) | def assert_unit(self, unit, **kwargs):
FILE: pysc2/tests/versions_test.py
function major_version (line 27) | def major_version(v):
function log_center (line 31) | def log_center(s, *args):
class TestVersions (line 35) | class TestVersions(absltest.TestCase):
method test_version_numbers (line 37) | def test_version_numbers(self):
method test_versions_create_game (line 62) | def test_versions_create_game(self):
FILE: setup.py
class BuildCommand (line 37) | class BuildCommand(distutils.command.build.build):
method initialize_options (line 39) | def initialize_options(self):
Condensed preview — 247 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (5,205K chars).
[
{
"path": ".gitignore",
"chars": 15,
"preview": "*.pyc\n*_pb2.py\n"
},
{
"path": "CONTRIBUTING.md",
"chars": 1453,
"preview": "Want to contribute? Great! First, read this page (including the small print at\nthe end).\n\n### Before you contribute\n\nBef"
},
{
"path": "LICENSE",
"chars": 11342,
"preview": "\n Apache License\n Version 2.0, January 2004\n "
},
{
"path": "README.md",
"chars": 8665,
"preview": "<div align=\"center\">\n <a href=\"https://www.youtube.com/watch?v=-fKUyT14G-8\"\n target=\"_blank\">\n <img src=\"http://"
},
{
"path": "WORKSPACE",
"chars": 2994,
"preview": "workspace(name = \"pysc2\")\n\nload(\"@bazel_tools//tools/build_defs/repo:http.bzl\", \"http_archive\")\n\nload(\"//bazel:create_ex"
},
{
"path": "bazel/BUILD",
"chars": 262,
"preview": "licenses([\"notice\"])\n\nexports_files(\n [\n \"BUILD.dm_env\",\n \"BUILD.dm_env_rpc\",\n \"BUILD.s2protocol"
},
{
"path": "bazel/BUILD.dm_env",
"chars": 673,
"preview": "load(\"@my_deps//:requirements.bzl\", \"requirement\")\n\nlicenses([\"notice\"])\n\npy_library(\n name = \"dm_env\",\n srcs = [\n"
},
{
"path": "bazel/BUILD.dm_env_rpc",
"chars": 896,
"preview": "load(\"@com_github_grpc_grpc//bazel:python_rules.bzl\", \"py_proto_library\")\n\nlicenses([\"notice\"])\n\nproto_library(\n name"
},
{
"path": "bazel/BUILD.s2protocol",
"chars": 544,
"preview": "licenses([\"notice\"])\n\npy_library(\n name = \"s2protocol\",\n srcs = [\n \"s2protocol/__init__.py\",\n \"s2pro"
},
{
"path": "bazel/create_external_repos.bzl",
"chars": 6065,
"preview": "# Copyright 2021 DeepMind Technologies Ltd. All rights reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the"
},
{
"path": "bazel/protobuf.patch",
"chars": 217,
"preview": "--- BUILD\n+++ BUILD\n@@ -889,6 +889,8 @@\n \"//conditions:default\": [],\n \":use_fast_cpp_protos\": [\"//extern"
},
{
"path": "bazel/requirements.txt",
"chars": 137,
"preview": "deepdiff\ndm-tree\nmock\nmpyq\nnumpy>=1.10.0\nportpicker>=1.2.0\npsutil\npygame\nrequests\ns2protocol\nsk-video\ntyping-extensions\n"
},
{
"path": "bazel/s2clientprotocol.patch",
"chars": 4968,
"preview": "+++ s2clientprotocol/BUILD\t2021-11-18 12:14:07.885666323 +0000\n@@ -0,0 +1,255 @@\n+load(\"@com_github_grpc_grpc//bazel:pyt"
},
{
"path": "bazel/setup_external_repos.bzl",
"chars": 1445,
"preview": "# Copyright 2021 DeepMind Technologies Ltd. All rights reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the"
},
{
"path": "docs/bazel.md",
"chars": 1790,
"preview": "# Building with Bazel\n\nPrior to the inclusion of C++ code it was sufficient to install the\n[pip](https://pypi.org/projec"
},
{
"path": "docs/converters.md",
"chars": 19398,
"preview": "# Environment converters\n\n## Overview\n\nThe SC2 API uses protos to communicate actions to and observations from the\nenvir"
},
{
"path": "docs/environment.md",
"chars": 25468,
"preview": "## Environment Table of Contents\n\n- [Starcraft II](#starcraft-ii)\n - [What is StarCraft II](#what-is-starcraft-ii)\n "
},
{
"path": "docs/maps.md",
"chars": 1856,
"preview": "# StarCraft II Maps\n\n## Map config\n\nSC2Map files are what is used by the SC2 game, but they can be used differently,\nand"
},
{
"path": "docs/mini_games.md",
"chars": 7577,
"preview": "# DeepMind Mini Games\n\n## MoveToBeacon\n\n#### Description\n\nA map with 1 Marine and 1 Beacon. Rewards are earned by moving"
},
{
"path": "pysc2/BUILD",
"chars": 177,
"preview": "load(\"@bazel_skylib//:bzl_library.bzl\", \"bzl_library\")\n\nlicenses([\"notice\"])\n\nexports_files([\"LICENSE\"])\n\nbzl_library(\n "
},
{
"path": "pysc2/__init__.py",
"chars": 978,
"preview": "# Copyright 2017 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# "
},
{
"path": "pysc2/agents/BUILD",
"chars": 1147,
"preview": "load(\"@my_deps//:requirements.bzl\", \"requirement\")\nload(\"//pysc2:build_defs.bzl\", \"pytype_library\", \"pytype_strict_libra"
},
{
"path": "pysc2/agents/__init__.py",
"chars": 597,
"preview": "# Copyright 2017 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# "
},
{
"path": "pysc2/agents/base_agent.py",
"chars": 1257,
"preview": "# Copyright 2017 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# "
},
{
"path": "pysc2/agents/no_op_agent.py",
"chars": 884,
"preview": "# Copyright 2021 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# "
},
{
"path": "pysc2/agents/random_agent.py",
"chars": 1117,
"preview": "# Copyright 2017 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# "
},
{
"path": "pysc2/agents/scripted_agent.py",
"chars": 7967,
"preview": "# Copyright 2017 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# "
},
{
"path": "pysc2/bin/BUILD",
"chars": 8114,
"preview": "load(\"@my_deps//:requirements.bzl\", \"requirement\")\nload(\"//pysc2:build_defs.bzl\", \"pytype_binary\", \"pytype_strict_binary"
},
{
"path": "pysc2/bin/__init__.py",
"chars": 597,
"preview": "# Copyright 2017 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# "
},
{
"path": "pysc2/bin/agent.py",
"chars": 6447,
"preview": "#!/usr/bin/python\n# Copyright 2017 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 ("
},
{
"path": "pysc2/bin/agent_remote.py",
"chars": 8911,
"preview": "#!/usr/bin/python\n# Copyright 2017 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 ("
},
{
"path": "pysc2/bin/battle_net_maps.py",
"chars": 1133,
"preview": "#!/usr/bin/python\n# Copyright 2019 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 ("
},
{
"path": "pysc2/bin/benchmark_observe.py",
"chars": 5137,
"preview": "#!/usr/bin/python\n# Copyright 2018 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 ("
},
{
"path": "pysc2/bin/benchmark_replay.py",
"chars": 3913,
"preview": "#!/usr/bin/python\n# Copyright 2018 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 ("
},
{
"path": "pysc2/bin/check_apm.py",
"chars": 7178,
"preview": "# Copyright 2018 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# "
},
{
"path": "pysc2/bin/compare_binaries.py",
"chars": 6372,
"preview": "#!/usr/bin/python\n# Copyright 2019 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 ("
},
{
"path": "pysc2/bin/gen_actions.py",
"chars": 6086,
"preview": "#!/usr/bin/python\n# Copyright 2017 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 ("
},
{
"path": "pysc2/bin/gen_data.py",
"chars": 3334,
"preview": "#!/usr/bin/python\n# Copyright 2017 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 ("
},
{
"path": "pysc2/bin/gen_versions.py",
"chars": 1268,
"preview": "#!/usr/bin/python\n# Copyright 2017 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 ("
},
{
"path": "pysc2/bin/map_list.py",
"chars": 883,
"preview": "#!/usr/bin/python\n# Copyright 2017 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 ("
},
{
"path": "pysc2/bin/mem_leak_check.py",
"chars": 4237,
"preview": "#!/usr/bin/python\n# Copyright 2018 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 ("
},
{
"path": "pysc2/bin/play.py",
"chars": 9266,
"preview": "#!/usr/bin/python\n# Copyright 2017 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 ("
},
{
"path": "pysc2/bin/play_vs_agent.py",
"chars": 10687,
"preview": "#!/usr/bin/python\n# Copyright 2017 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 ("
},
{
"path": "pysc2/bin/reencode_replays.py",
"chars": 2728,
"preview": "#!/usr/bin/python\n# Copyright 2019 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 ("
},
{
"path": "pysc2/bin/replay_actions.py",
"chars": 15231,
"preview": "#!/usr/bin/python\n# Copyright 2017 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 ("
},
{
"path": "pysc2/bin/replay_info.py",
"chars": 4308,
"preview": "#!/usr/bin/python\n# Copyright 2017 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 ("
},
{
"path": "pysc2/bin/replay_version.py",
"chars": 1941,
"preview": "#!/usr/bin/python\n# Copyright 2022 DeepMind Technologies Ltd. All Rights Reserved.\n#\n# Licensed under the Apache License"
},
{
"path": "pysc2/bin/run_tests.py",
"chars": 863,
"preview": "#!/usr/bin/python\n# Copyright 2017 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 ("
},
{
"path": "pysc2/bin/update_battle_net_cache.py",
"chars": 3831,
"preview": "#!/usr/bin/python\n# Copyright 2019 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 ("
},
{
"path": "pysc2/bin/valid_actions.py",
"chars": 1854,
"preview": "#!/usr/bin/python\n# Copyright 2017 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 ("
},
{
"path": "pysc2/build_defs.bzl",
"chars": 1019,
"preview": "# Copyright 2021 DeepMind Technologies Ltd. All rights reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the"
},
{
"path": "pysc2/env/BUILD",
"chars": 5259,
"preview": "load(\"@my_deps//:requirements.bzl\", \"requirement\")\nload(\"//pysc2:build_defs.bzl\", \"pytype_library\")\n\npackage(default_vis"
},
{
"path": "pysc2/env/__init__.py",
"chars": 597,
"preview": "# Copyright 2017 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# "
},
{
"path": "pysc2/env/available_actions_printer.py",
"chars": 1345,
"preview": "# Copyright 2017 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# "
},
{
"path": "pysc2/env/base_env_wrapper.py",
"chars": 1467,
"preview": "# Copyright 2017 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# "
},
{
"path": "pysc2/env/converted_env.py",
"chars": 12722,
"preview": "# Copyright 2021 DeepMind Technologies Ltd. All rights reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the"
},
{
"path": "pysc2/env/converted_env_test.py",
"chars": 4573,
"preview": "# Copyright 2021 DeepMind Technologies Ltd. All rights reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the"
},
{
"path": "pysc2/env/converter/BUILD",
"chars": 1508,
"preview": "load(\"@my_deps//:requirements.bzl\", \"requirement\")\nload(\"//pysc2:build_defs.bzl\", \"pytype_library\", \"pytype_strict_libra"
},
{
"path": "pysc2/env/converter/__init__.py",
"chars": 613,
"preview": "# Copyright 2021 DeepMind Technologies Ltd. All rights reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the"
},
{
"path": "pysc2/env/converter/cc/BUILD",
"chars": 10596,
"preview": "load(\"//pysc2:build_defs.bzl\", \"pytype_strict_library\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\nlicenses"
},
{
"path": "pysc2/env/converter/cc/__init__.py",
"chars": 613,
"preview": "# Copyright 2021 DeepMind Technologies Ltd. All rights reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the"
},
{
"path": "pysc2/env/converter/cc/castops.h",
"chars": 2974,
"preview": "// Copyright 2021 DeepMind Technologies Ltd. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 ("
},
{
"path": "pysc2/env/converter/cc/check_protos_equal.h",
"chars": 1458,
"preview": "// Copyright 2021 DeepMind Technologies Ltd. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 ("
},
{
"path": "pysc2/env/converter/cc/convert_obs.cc",
"chars": 22112,
"preview": "// Copyright 2021 DeepMind Technologies Ltd. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 ("
},
{
"path": "pysc2/env/converter/cc/convert_obs.h",
"chars": 6104,
"preview": "// Copyright 2021 DeepMind Technologies Ltd. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 ("
},
{
"path": "pysc2/env/converter/cc/convert_obs_test.cc",
"chars": 4757,
"preview": "// Copyright 2021 DeepMind Technologies Ltd. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 ("
},
{
"path": "pysc2/env/converter/cc/converter.cc",
"chars": 14644,
"preview": "// Copyright 2021 DeepMind Technologies Ltd. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 ("
},
{
"path": "pysc2/env/converter/cc/converter.h",
"chars": 3369,
"preview": "// Copyright 2021 DeepMind Technologies Ltd. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 ("
},
{
"path": "pysc2/env/converter/cc/converter_test.cc",
"chars": 20440,
"preview": "// Copyright 2021 DeepMind Technologies Ltd. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 ("
},
{
"path": "pysc2/env/converter/cc/encode_image_data.h",
"chars": 3987,
"preview": "// Copyright 2021 DeepMind Technologies Ltd. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 ("
},
{
"path": "pysc2/env/converter/cc/features.cc",
"chars": 3451,
"preview": "// Copyright 2021 DeepMind Technologies Ltd. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 ("
},
{
"path": "pysc2/env/converter/cc/features.h",
"chars": 1153,
"preview": "// Copyright 2021 DeepMind Technologies Ltd. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 ("
},
{
"path": "pysc2/env/converter/cc/file_util.cc",
"chars": 1942,
"preview": "// Copyright 2021 DeepMind Technologies Ltd. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 ("
},
{
"path": "pysc2/env/converter/cc/file_util.h",
"chars": 1134,
"preview": "// Copyright 2021 DeepMind Technologies Ltd. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 ("
},
{
"path": "pysc2/env/converter/cc/game_data/BUILD",
"chars": 1161,
"preview": "load(\"//pysc2:build_defs.bzl\", \"pytype_strict_library\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\nlicenses"
},
{
"path": "pysc2/env/converter/cc/game_data/__init__.py",
"chars": 612,
"preview": "# Copyright 2021 DeepMind Technologies Ltd. All rights reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the"
},
{
"path": "pysc2/env/converter/cc/game_data/proto/BUILD",
"chars": 1050,
"preview": "load(\"@com_github_grpc_grpc//bazel:python_rules.bzl\", \"py_proto_library\")\n\nlicenses([\"notice\"])\n\nproto_library(\n name"
},
{
"path": "pysc2/env/converter/cc/game_data/proto/__init__.py",
"chars": 612,
"preview": "# Copyright 2021 DeepMind Technologies Ltd. All rights reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the"
},
{
"path": "pysc2/env/converter/cc/game_data/proto/buffs.proto",
"chars": 1375,
"preview": "// LINT: LEGACY_NAMES\n\nsyntax = \"proto2\";\n\npackage pysc2.Buffs;\n\n\n\nenum Buffs {\n UnknownBuff = 0;\n BansheeCloak = 7;\n "
},
{
"path": "pysc2/env/converter/cc/game_data/proto/units.proto",
"chars": 6558,
"preview": "// LINT: LEGACY_NAMES\n\nsyntax = \"proto2\";\n\npackage pysc2;\n\nenum Neutral {\n UnknownNeutral = 0;\n BattleStationMineralFi"
},
{
"path": "pysc2/env/converter/cc/game_data/proto/upgrades.proto",
"chars": 2615,
"preview": "// LINT: LEGACY_NAMES\n\nsyntax = \"proto2\";\n\npackage pysc2.Upgrades;\n\nenum Upgrades {\n AdaptiveTalons = 293;\n AdrenalGla"
},
{
"path": "pysc2/env/converter/cc/game_data/python/BUILD",
"chars": 822,
"preview": "load(\"//pysc2:build_defs.bzl\", \"pytype_strict_library\")\nload(\"@pybind11_bazel//:build_defs.bzl\", \"pybind_extension\")\n\npa"
},
{
"path": "pysc2/env/converter/cc/game_data/python/__init__.py",
"chars": 613,
"preview": "# Copyright 2021 DeepMind Technologies Ltd. All rights reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the"
},
{
"path": "pysc2/env/converter/cc/game_data/python/uint8_lookup.cc",
"chars": 1408,
"preview": "// Copyright 2021 DeepMind Technologies Ltd. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 ("
},
{
"path": "pysc2/env/converter/cc/game_data/python/uint8_lookup_test.py",
"chars": 1770,
"preview": "# Copyright 2021 DeepMind Technologies Ltd. All rights reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the"
},
{
"path": "pysc2/env/converter/cc/game_data/raw_actions.cc",
"chars": 34304,
"preview": "// Copyright 2021 DeepMind Technologies Ltd. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 ("
},
{
"path": "pysc2/env/converter/cc/game_data/raw_actions.h",
"chars": 1314,
"preview": "// Copyright 2021 DeepMind Technologies Ltd. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 ("
},
{
"path": "pysc2/env/converter/cc/game_data/uint8_lookup.cc",
"chars": 16396,
"preview": "// Copyright 2021 DeepMind Technologies Ltd. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 ("
},
{
"path": "pysc2/env/converter/cc/game_data/uint8_lookup.h",
"chars": 1094,
"preview": "// Copyright 2021 DeepMind Technologies Ltd. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 ("
},
{
"path": "pysc2/env/converter/cc/game_data/visual_actions.cc",
"chars": 37569,
"preview": "// Copyright 2021 DeepMind Technologies Ltd. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 ("
},
{
"path": "pysc2/env/converter/cc/game_data/visual_actions.h",
"chars": 1690,
"preview": "// Copyright 2021 DeepMind Technologies Ltd. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 ("
},
{
"path": "pysc2/env/converter/cc/general_order_ids.cc",
"chars": 3426,
"preview": "// Copyright 2021 DeepMind Technologies Ltd. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 ("
},
{
"path": "pysc2/env/converter/cc/general_order_ids.h",
"chars": 1415,
"preview": "// Copyright 2021 DeepMind Technologies Ltd. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 ("
},
{
"path": "pysc2/env/converter/cc/map_util.cc",
"chars": 2218,
"preview": "// Copyright 2021 DeepMind Technologies Ltd. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 ("
},
{
"path": "pysc2/env/converter/cc/map_util.h",
"chars": 1437,
"preview": "// Copyright 2021 DeepMind Technologies Ltd. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 ("
},
{
"path": "pysc2/env/converter/cc/python/BUILD",
"chars": 684,
"preview": "load(\"//pysc2:build_defs.bzl\", \"pytype_strict_library\")\nload(\"@pybind11_bazel//:build_defs.bzl\", \"pybind_extension\")\n\npa"
},
{
"path": "pysc2/env/converter/cc/python/__init__.py",
"chars": 613,
"preview": "# Copyright 2021 DeepMind Technologies Ltd. All rights reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the"
},
{
"path": "pysc2/env/converter/cc/python/converter.cc",
"chars": 4650,
"preview": "// Copyright 2021 DeepMind Technologies Ltd. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 ("
},
{
"path": "pysc2/env/converter/cc/raw_actions_encoder.cc",
"chars": 18163,
"preview": "// Copyright 2021 DeepMind Technologies Ltd. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 ("
},
{
"path": "pysc2/env/converter/cc/raw_actions_encoder.h",
"chars": 2925,
"preview": "// Copyright 2021 DeepMind Technologies Ltd. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 ("
},
{
"path": "pysc2/env/converter/cc/raw_actions_encoder_test.cc",
"chars": 6903,
"preview": "// Copyright 2021 DeepMind Technologies Ltd. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 ("
},
{
"path": "pysc2/env/converter/cc/raw_camera.cc",
"chars": 3232,
"preview": "// Copyright 2021 DeepMind Technologies Ltd. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 ("
},
{
"path": "pysc2/env/converter/cc/raw_camera.h",
"chars": 1443,
"preview": "// Copyright 2021 DeepMind Technologies Ltd. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 ("
},
{
"path": "pysc2/env/converter/cc/raw_converter.cc",
"chars": 9025,
"preview": "// Copyright 2021 DeepMind Technologies Ltd. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 ("
},
{
"path": "pysc2/env/converter/cc/raw_converter.h",
"chars": 2344,
"preview": "// Copyright 2021 DeepMind Technologies Ltd. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 ("
},
{
"path": "pysc2/env/converter/cc/tensor_util.cc",
"chars": 7282,
"preview": "// Copyright 2021 DeepMind Technologies Ltd. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 ("
},
{
"path": "pysc2/env/converter/cc/tensor_util.h",
"chars": 3638,
"preview": "// Copyright 2021 DeepMind Technologies Ltd. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 ("
},
{
"path": "pysc2/env/converter/cc/test_data/BUILD",
"chars": 501,
"preview": "load(\"//pysc2:build_defs.bzl\", \"pytype_strict_library\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\nlicenses"
},
{
"path": "pysc2/env/converter/cc/test_data/__init__.py",
"chars": 613,
"preview": "# Copyright 2021 DeepMind Technologies Ltd. All rights reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the"
},
{
"path": "pysc2/env/converter/cc/test_data/actions/feature_camera_move.pbtxt",
"chars": 96,
"preview": "action_feature_layer {\n camera_move {\n center_minimap {\n x: 33\n y: 41\n }\n }\n}\n"
},
{
"path": "pysc2/env/converter/cc/test_data/actions/feature_unit_command.pbtxt",
"chars": 145,
"preview": "action_feature_layer {\n unit_command {\n ability_id: 1\n target_screen_coord {\n x: 27\n y: 26\n }\n qu"
},
{
"path": "pysc2/env/converter/cc/test_data/actions/feature_unit_selection_point.pbtxt",
"chars": 130,
"preview": "action_feature_layer {\n unit_selection_point {\n selection_screen_coord {\n x: 23\n y: 16\n }\n type: Sel"
},
{
"path": "pysc2/env/converter/cc/test_data/actions/ui_control_group_append.pbtxt",
"chars": 82,
"preview": "action_ui {\n control_group {\n action: Append\n control_group_index: 1\n }\n}\n"
},
{
"path": "pysc2/env/converter/cc/test_data/actions/ui_control_group_recall.pbtxt",
"chars": 82,
"preview": "action_ui {\n control_group {\n action: Recall\n control_group_index: 2\n }\n}\n"
},
{
"path": "pysc2/env/converter/cc/test_data/obs_data1.pbtxt",
"chars": 2975130,
"preview": "actions {\n action_feature_layer {\n unit_selection_point {\n selection_screen_coord {\n x: 127\n y: 1"
},
{
"path": "pysc2/env/converter/cc/unit_lookups.cc",
"chars": 2826,
"preview": "// Copyright 2021 DeepMind Technologies Ltd. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 ("
},
{
"path": "pysc2/env/converter/cc/unit_lookups.h",
"chars": 1043,
"preview": "// Copyright 2021 DeepMind Technologies Ltd. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 ("
},
{
"path": "pysc2/env/converter/cc/unit_lookups_test.cc",
"chars": 1394,
"preview": "// Copyright 2021 DeepMind Technologies Ltd. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 ("
},
{
"path": "pysc2/env/converter/cc/visual_actions.cc",
"chars": 20666,
"preview": "// Copyright 2021 DeepMind Technologies Ltd. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 ("
},
{
"path": "pysc2/env/converter/cc/visual_actions.h",
"chars": 2543,
"preview": "// Copyright 2021 DeepMind Technologies Ltd. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 ("
},
{
"path": "pysc2/env/converter/cc/visual_actions_test.cc",
"chars": 2572,
"preview": "// Copyright 2021 DeepMind Technologies Ltd. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 ("
},
{
"path": "pysc2/env/converter/cc/visual_converter.cc",
"chars": 10276,
"preview": "// Copyright 2021 DeepMind Technologies Ltd. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 ("
},
{
"path": "pysc2/env/converter/cc/visual_converter.h",
"chars": 1921,
"preview": "// Copyright 2021 DeepMind Technologies Ltd. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 ("
},
{
"path": "pysc2/env/converter/cc/visual_converter_test.cc",
"chars": 3834,
"preview": "// Copyright 2021 DeepMind Technologies Ltd. All rights reserved.\n//\n// Licensed under the Apache License, Version 2.0 ("
},
{
"path": "pysc2/env/converter/converter.py",
"chars": 5417,
"preview": "# Copyright 2021 DeepMind Technologies Ltd. All rights reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the"
},
{
"path": "pysc2/env/converter/converter_test.py",
"chars": 13724,
"preview": "# Copyright 2021 DeepMind Technologies Ltd. All rights reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the"
},
{
"path": "pysc2/env/converter/derive_interface_options.py",
"chars": 1656,
"preview": "# Copyright 2021 DeepMind Technologies Ltd. All rights reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the"
},
{
"path": "pysc2/env/converter/proto/BUILD",
"chars": 568,
"preview": "load(\"@com_github_grpc_grpc//bazel:python_rules.bzl\", \"py_proto_library\")\n\nlicenses([\"notice\"])\n\nproto_library(\n name"
},
{
"path": "pysc2/env/converter/proto/__init__.py",
"chars": 612,
"preview": "# Copyright 2021 DeepMind Technologies Ltd. All rights reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the"
},
{
"path": "pysc2/env/converter/proto/converter.proto",
"chars": 5863,
"preview": "syntax = \"proto2\";\n\npackage pysc2;\n\nimport \"s2clientprotocol/common.proto\";\nimport \"s2clientprotocol/sc2api.proto\";\n\nmes"
},
{
"path": "pysc2/env/enums.py",
"chars": 1451,
"preview": "# Copyright 2021 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# "
},
{
"path": "pysc2/env/environment.py",
"chars": 4704,
"preview": "# Copyright 2017 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# "
},
{
"path": "pysc2/env/host_remote_agent.py",
"chars": 7848,
"preview": "# Copyright 2018 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# "
},
{
"path": "pysc2/env/lan_sc2_env.py",
"chars": 12474,
"preview": "# Copyright 2017 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# "
},
{
"path": "pysc2/env/mock_sc2_env.py",
"chars": 12603,
"preview": "# Copyright 2017 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# "
},
{
"path": "pysc2/env/mock_sc2_env_comparison_test.py",
"chars": 2254,
"preview": "#!/usr/bin/python\n# Copyright 2017 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 ("
},
{
"path": "pysc2/env/mock_sc2_env_test.py",
"chars": 7397,
"preview": "#!/usr/bin/python\n# Copyright 2017 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 ("
},
{
"path": "pysc2/env/remote_sc2_env.py",
"chars": 8292,
"preview": "# Copyright 2017 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# "
},
{
"path": "pysc2/env/run_loop.py",
"chars": 1733,
"preview": "# Copyright 2017 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# "
},
{
"path": "pysc2/env/sc2_env.py",
"chars": 32028,
"preview": "# Copyright 2017 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# "
},
{
"path": "pysc2/env/sc2_env_test.py",
"chars": 1828,
"preview": "#!/usr/bin/python\n# Copyright 2019 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 ("
},
{
"path": "pysc2/lib/BUILD",
"chars": 8338,
"preview": "load(\"@my_deps//:requirements.bzl\", \"requirement\")\nload(\"//pysc2:build_defs.bzl\", \"pytype_library\")\n\npackage(default_vis"
},
{
"path": "pysc2/lib/__init__.py",
"chars": 597,
"preview": "# Copyright 2017 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# "
},
{
"path": "pysc2/lib/actions.py",
"chars": 113588,
"preview": "# Copyright 2017 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# "
},
{
"path": "pysc2/lib/buffs.py",
"chars": 2004,
"preview": "# Copyright 2018 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# "
},
{
"path": "pysc2/lib/colors.py",
"chars": 14258,
"preview": "# Copyright 2017 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# "
},
{
"path": "pysc2/lib/features.py",
"chars": 69238,
"preview": "# Copyright 2017 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# "
},
{
"path": "pysc2/lib/features_test.py",
"chars": 21736,
"preview": "#!/usr/bin/python\n# Copyright 2017 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 ("
},
{
"path": "pysc2/lib/gfile.py",
"chars": 941,
"preview": "# Copyright 2017 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# "
},
{
"path": "pysc2/lib/image_differencer.py",
"chars": 1367,
"preview": "#!/usr/bin/python\n# Copyright 2019 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 ("
},
{
"path": "pysc2/lib/image_differencer_test.py",
"chars": 2919,
"preview": "#!/usr/bin/python\n# Copyright 2019 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 ("
},
{
"path": "pysc2/lib/memoize.py",
"chars": 985,
"preview": "# Copyright 2018 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# "
},
{
"path": "pysc2/lib/metrics.py",
"chars": 1503,
"preview": "# Copyright 2017 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# "
},
{
"path": "pysc2/lib/named_array.py",
"chars": 10767,
"preview": "# Copyright 2018 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# "
},
{
"path": "pysc2/lib/named_array_test.py",
"chars": 13685,
"preview": "#!/usr/bin/python\n# Copyright 2018 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 ("
},
{
"path": "pysc2/lib/np_util.py",
"chars": 1235,
"preview": "# Copyright 2019 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# "
},
{
"path": "pysc2/lib/np_util_test.py",
"chars": 1422,
"preview": "#!/usr/bin/python\n# Copyright 2019 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 ("
},
{
"path": "pysc2/lib/point.py",
"chars": 8090,
"preview": "# Copyright 2017 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# "
},
{
"path": "pysc2/lib/point_flag.py",
"chars": 2039,
"preview": "# Copyright 2018 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# "
},
{
"path": "pysc2/lib/point_test.py",
"chars": 6789,
"preview": "#!/usr/bin/python\n# Copyright 2017 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 ("
},
{
"path": "pysc2/lib/portspicker.py",
"chars": 2586,
"preview": "# Copyright 2018 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# "
},
{
"path": "pysc2/lib/portspicker_test.py",
"chars": 1566,
"preview": "#!/usr/bin/python\n# Copyright 2018 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 ("
},
{
"path": "pysc2/lib/proto_diff.py",
"chars": 6631,
"preview": "# Copyright 2019 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# "
},
{
"path": "pysc2/lib/proto_diff_test.py",
"chars": 8803,
"preview": "#!/usr/bin/python\n# Copyright 2019 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 ("
},
{
"path": "pysc2/lib/protocol.py",
"chars": 6600,
"preview": "# Copyright 2017 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# "
},
{
"path": "pysc2/lib/remote_controller.py",
"chars": 13585,
"preview": "# Copyright 2017 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# "
},
{
"path": "pysc2/lib/renderer_ascii.py",
"chars": 3509,
"preview": "# Copyright 2017 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# "
},
{
"path": "pysc2/lib/renderer_human.py",
"chars": 73033,
"preview": "# Copyright 2017 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# "
},
{
"path": "pysc2/lib/replay/BUILD",
"chars": 2632,
"preview": "load(\"@my_deps//:requirements.bzl\", \"requirement\")\nload(\"//pysc2:build_defs.bzl\", \"pytype_strict_library\")\n\npackage(defa"
},
{
"path": "pysc2/lib/replay/__init__.py",
"chars": 612,
"preview": "# Copyright 2021 DeepMind Technologies Ltd. All rights reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the"
},
{
"path": "pysc2/lib/replay/replay_converter.py",
"chars": 9792,
"preview": "# Copyright 2021 DeepMind Technologies Ltd. All rights reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the"
},
{
"path": "pysc2/lib/replay/replay_observation_stream.py",
"chars": 8030,
"preview": "# Copyright 2021 DeepMind Technologies Ltd. All rights reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the"
},
{
"path": "pysc2/lib/replay/sc2_replay.py",
"chars": 3932,
"preview": "# Copyright 2021 DeepMind Technologies Ltd. All rights reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the"
},
{
"path": "pysc2/lib/replay/sc2_replay_test.py",
"chars": 5370,
"preview": "# Copyright 2021 DeepMind Technologies Ltd. All rights reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the"
},
{
"path": "pysc2/lib/replay/sc2_replay_utils.py",
"chars": 3557,
"preview": "# Copyright 2021 DeepMind Technologies Ltd. All rights reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the"
},
{
"path": "pysc2/lib/replay/sc2_replay_utils_test.py",
"chars": 1788,
"preview": "# Copyright 2021 DeepMind Technologies Ltd. All rights reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the"
},
{
"path": "pysc2/lib/replay/test_data/replay_01.skips.txt",
"chars": 9103,
"preview": "6,16,24,34,36,39,44,67,70,71,209,212,216,221,225,248,258,337,340,343,357,360,363,366,385,389,424,427,429,434,441,444,448"
},
{
"path": "pysc2/lib/replay/test_data/replay_02.skips.txt",
"chars": 9576,
"preview": "0,1,6,22,31,41,48,62,67,117,119,121,133,140,150,153,156,159,189,193,196,245,247,251,273,324,342,345,347,353,355,362,363,"
},
{
"path": "pysc2/lib/replay/test_data/replay_03.skips.txt",
"chars": 13755,
"preview": "6,16,24,34,39,41,104,163,165,287,288,297,311,314,317,320,329,339,349,353,356,360,369,372,375,392,402,440,442,445,450,454"
},
{
"path": "pysc2/lib/replay/test_data/replay_04.skips.txt",
"chars": 11840,
"preview": "9,18,24,36,42,51,54,58,64,67,70,155,166,186,191,193,196,199,202,214,218,275,280,281,306,336,339,357,378,434,440,447,452,"
},
{
"path": "pysc2/lib/replay/test_data/replay_05.skips.txt",
"chars": 7392,
"preview": "8,28,40,167,172,175,182,191,194,197,246,251,256,272,320,378,398,413,416,418,421,428,444,476,490,629,647,666,676,683,688,"
},
{
"path": "pysc2/lib/replay/test_data/replay_06.skips.txt",
"chars": 13093,
"preview": "4,14,21,25,63,182,296,302,308,312,315,323,329,342,382,408,423,428,534,539,544,548,582,588,591,594,618,627,726,762,785,84"
},
{
"path": "pysc2/lib/replay/test_data/replay_07.skips.txt",
"chars": 11244,
"preview": "7,15,21,30,157,164,169,179,227,230,240,253,282,287,375,392,395,408,443,476,480,483,487,490,493,498,500,505,518,522,526,5"
},
{
"path": "pysc2/lib/replay/test_data/replay_08.skips.txt",
"chars": 11662,
"preview": "7,21,31,35,51,67,76,79,89,92,115,148,159,169,241,243,244,256,257,260,279,290,306,332,344,346,349,352,358,382,449,453,457"
},
{
"path": "pysc2/lib/replay/test_data/replay_09.skips.txt",
"chars": 4726,
"preview": "8,18,25,35,40,43,54,57,61,71,76,203,206,211,215,220,236,241,244,247,250,254,283,285,287,290,297,315,332,335,401,457,472,"
},
{
"path": "pysc2/lib/replay.py",
"chars": 1233,
"preview": "#!/usr/bin/python\n# Copyright 2018 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 ("
},
{
"path": "pysc2/lib/resources.py",
"chars": 727,
"preview": "# Copyright 2021 DeepMind Technologies Ltd. All rights reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the"
},
{
"path": "pysc2/lib/run_parallel.py",
"chars": 3144,
"preview": "# Copyright 2017 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# "
},
{
"path": "pysc2/lib/run_parallel_test.py",
"chars": 2617,
"preview": "#!/usr/bin/python\n# Copyright 2017 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 ("
},
{
"path": "pysc2/lib/sc_process.py",
"chars": 7509,
"preview": "# Copyright 2017-2018 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\""
},
{
"path": "pysc2/lib/static_data.py",
"chars": 6573,
"preview": "# Copyright 2017 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# "
},
{
"path": "pysc2/lib/stopwatch.py",
"chars": 7728,
"preview": "# Copyright 2017 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# "
},
{
"path": "pysc2/lib/stopwatch_test.py",
"chars": 3916,
"preview": "#!/usr/bin/python\n# Copyright 2017 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 ("
},
{
"path": "pysc2/lib/transform.py",
"chars": 3254,
"preview": "# Copyright 2017 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# "
},
{
"path": "pysc2/lib/units.py",
"chars": 7178,
"preview": "# Copyright 2017 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# "
},
{
"path": "pysc2/lib/upgrades.py",
"chars": 3226,
"preview": "# Copyright 2018 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# "
},
{
"path": "pysc2/lib/video_writer.py",
"chars": 1125,
"preview": "# Copyright 2017 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# "
},
{
"path": "pysc2/maps/BUILD",
"chars": 485,
"preview": "load(\"//pysc2:build_defs.bzl\", \"pytype_library\")\n\npackage(default_visibility = [\"//visibility:public\"])\n\nlicenses([\"noti"
},
{
"path": "pysc2/maps/__init__.py",
"chars": 1187,
"preview": "# Copyright 2017 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# "
},
{
"path": "pysc2/maps/ladder.py",
"chars": 4253,
"preview": "# Copyright 2017 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# "
}
]
// ... and 47 more files (download for full content)
About this extraction
This page contains the full source code of the google-deepmind/pysc2 GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 247 files (25.5 MB), approximately 1.1M tokens, and a symbol index with 1456 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.