dungeoncoder 0.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- dungeoncoder/__init__.py +4 -0
- dungeoncoder/__main__.py +254 -0
- dungeoncoder/_api_config.py +6 -0
- dungeoncoder/_generated/__init__.py +8 -0
- dungeoncoder/_generated/api/__init__.py +1 -0
- dungeoncoder/_generated/api/game/__init__.py +1 -0
- dungeoncoder/_generated/api/game/get_statistics.py +158 -0
- dungeoncoder/_generated/api/game/get_version.py +166 -0
- dungeoncoder/_generated/api/hero/__init__.py +1 -0
- dungeoncoder/_generated/api/hero/ask_oracle.py +192 -0
- dungeoncoder/_generated/api/hero/configure.py +207 -0
- dungeoncoder/_generated/api/hero/drop.py +207 -0
- dungeoncoder/_generated/api/hero/get_inventory.py +188 -0
- dungeoncoder/_generated/api/hero/get_items_at_position.py +188 -0
- dungeoncoder/_generated/api/hero/interact.py +188 -0
- dungeoncoder/_generated/api/hero/is_abyss_in_front.py +188 -0
- dungeoncoder/_generated/api/hero/is_at_goal.py +192 -0
- dungeoncoder/_generated/api/hero/is_collision_in_front.py +188 -0
- dungeoncoder/_generated/api/hero/is_enemy_in_front.py +188 -0
- dungeoncoder/_generated/api/hero/is_facing_north.py +188 -0
- dungeoncoder/_generated/api/hero/is_switch_in_front.py +188 -0
- dungeoncoder/_generated/api/hero/is_torch_in_front.py +188 -0
- dungeoncoder/_generated/api/hero/move.py +188 -0
- dungeoncoder/_generated/api/hero/peek_item_value.py +211 -0
- dungeoncoder/_generated/api/hero/pickup.py +207 -0
- dungeoncoder/_generated/api/hero/read_item_value.py +188 -0
- dungeoncoder/_generated/api/hero/sense_goal.py +192 -0
- dungeoncoder/_generated/api/hero/set_pace.py +207 -0
- dungeoncoder/_generated/api/hero/turn_left.py +188 -0
- dungeoncoder/_generated/api/level/__init__.py +1 -0
- dungeoncoder/_generated/api/level/load_level.py +190 -0
- dungeoncoder/_generated/api/level/reset_level.py +158 -0
- dungeoncoder/_generated/client.py +271 -0
- dungeoncoder/_generated/errors.py +14 -0
- dungeoncoder/_generated/models/__init__.py +47 -0
- dungeoncoder/_generated/models/api_error_response.py +98 -0
- dungeoncoder/_generated/models/api_error_response_status.py +7 -0
- dungeoncoder/_generated/models/boolean_result.py +96 -0
- dungeoncoder/_generated/models/boolean_result_status.py +7 -0
- dungeoncoder/_generated/models/configure_params.py +84 -0
- dungeoncoder/_generated/models/distance_param.py +76 -0
- dungeoncoder/_generated/models/name_param.py +76 -0
- dungeoncoder/_generated/models/nullable_integer_result.py +104 -0
- dungeoncoder/_generated/models/nullable_integer_result_status.py +7 -0
- dungeoncoder/_generated/models/nullable_string_result.py +104 -0
- dungeoncoder/_generated/models/nullable_string_result_status.py +7 -0
- dungeoncoder/_generated/models/pace_params.py +76 -0
- dungeoncoder/_generated/models/statistics.py +217 -0
- dungeoncoder/_generated/models/statistics_result.py +104 -0
- dungeoncoder/_generated/models/statistics_result_status.py +7 -0
- dungeoncoder/_generated/models/string_array_result.py +100 -0
- dungeoncoder/_generated/models/string_array_result_status.py +7 -0
- dungeoncoder/_generated/models/tiled_level.py +67 -0
- dungeoncoder/_generated/models/version_result.py +104 -0
- dungeoncoder/_generated/models/version_result_result.py +84 -0
- dungeoncoder/_generated/models/version_result_status.py +7 -0
- dungeoncoder/_generated/types.py +53 -0
- dungeoncoder/asciimap.py +824 -0
- dungeoncoder/dungeoncoder.py +482 -0
- dungeoncoder/generator.py +213 -0
- dungeoncoder/packs/gelaende.json +1 -0
- dungeoncoder/packs/items.json +67 -0
- dungeoncoder/packs/station.json +1 -0
- dungeoncoder/packs/studio.json +1 -0
- dungeoncoder/packs/tilesets.json +1 -0
- dungeoncoder/packs/werkstatt.json +1 -0
- dungeoncoder/replay.py +80 -0
- dungeoncoder/requirements.txt +2 -0
- dungeoncoder/sim.py +792 -0
- dungeoncoder/testing.py +63 -0
- dungeoncoder/trace.py +92 -0
- dungeoncoder/variants.py +112 -0
- dungeoncoder-0.2.0.dist-info/METADATA +37 -0
- dungeoncoder-0.2.0.dist-info/RECORD +77 -0
- dungeoncoder-0.2.0.dist-info/WHEEL +5 -0
- dungeoncoder-0.2.0.dist-info/licenses/LICENSE.txt +25 -0
- dungeoncoder-0.2.0.dist-info/top_level.txt +1 -0
dungeoncoder/testing.py
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"""Helpers for testing Dungeon Coder programs with pytest, in the simulator.
|
|
2
|
+
|
|
3
|
+
from dungeoncoder.testing import spiel
|
|
4
|
+
|
|
5
|
+
def test_umdrehen_zweimal_ist_wie_vorher():
|
|
6
|
+
game, hero = spiel(\"\"\"
|
|
7
|
+
start: east
|
|
8
|
+
---
|
|
9
|
+
#####
|
|
10
|
+
#H..#
|
|
11
|
+
#####
|
|
12
|
+
\"\"\")
|
|
13
|
+
umdrehen(hero)
|
|
14
|
+
umdrehen(hero)
|
|
15
|
+
assert not hero.is_facing_north() and hero.move()
|
|
16
|
+
|
|
17
|
+
spiel(...) switches to the simulator (no VS Code needed, steps take no time) and
|
|
18
|
+
loads a level: a map text (see asciimap.py), a .txt map file, or a .json level.
|
|
19
|
+
"""
|
|
20
|
+
import os
|
|
21
|
+
import tempfile
|
|
22
|
+
import textwrap
|
|
23
|
+
|
|
24
|
+
from . import dungeoncoder as _core
|
|
25
|
+
from .asciimap import GRID_H, GRID_W, parse_text
|
|
26
|
+
from .dungeoncoder import Game, Hero
|
|
27
|
+
|
|
28
|
+
_versatz = (0, 0) # where the last map text was placed on the 30x20 field
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def spiel(level: str) -> tuple[Game, Hero]:
|
|
32
|
+
"""(game, hero) for a level in the simulator. `level` is a map text or a file path."""
|
|
33
|
+
if _core._simulator is None:
|
|
34
|
+
_core.use_simulator()
|
|
35
|
+
if "\n" in level:
|
|
36
|
+
path = os.path.join(tempfile.mkdtemp(prefix="dungeoncoder-test-"), "level.txt")
|
|
37
|
+
with open(path, "w", encoding="utf-8") as f:
|
|
38
|
+
f.write(textwrap.dedent(level).strip("\n") + "\n")
|
|
39
|
+
else:
|
|
40
|
+
path = level
|
|
41
|
+
global _versatz
|
|
42
|
+
if path.endswith(".txt"):
|
|
43
|
+
with open(path, encoding="utf-8") as f:
|
|
44
|
+
_, rows = parse_text(f.read())
|
|
45
|
+
_versatz = ((GRID_W - max((len(r) for r in rows), default=0)) // 2, (GRID_H - len(rows)) // 2)
|
|
46
|
+
else:
|
|
47
|
+
_versatz = (0, 0)
|
|
48
|
+
game = Game(path)
|
|
49
|
+
return game, game.get_hero()
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def wachen() -> list[tuple[int, int]]:
|
|
53
|
+
"""Nur für Tests im Simulator: wo die Wächter gerade stehen, (x, y) in den Koordinaten
|
|
54
|
+
der Karte, wie sie geschrieben ist. Im echten Spiel gibt es das nicht: dort sieht die
|
|
55
|
+
Heldin einen Wächter nur mit is_enemy_in_front()."""
|
|
56
|
+
if _core._simulator is None or _core._simulator.level is None:
|
|
57
|
+
raise RuntimeError("wachen() gibt es nur im Simulator, nach spiel(...)")
|
|
58
|
+
level = _core._simulator.level
|
|
59
|
+
ox, oy = _versatz
|
|
60
|
+
return [(c - ox, r - oy) for c, r in (level.cell_of(o) for o in level.objects if o.kind == "Guard")]
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
game_for = spiel # English name
|
dungeoncoder/trace.py
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
"""Traces: every call a program made, with what came back, per loaded level.
|
|
2
|
+
|
|
3
|
+
game.save_trace("spur.json") # in a program: the current level so far
|
|
4
|
+
DUNGEONCODER_TRACE=spur.json python prog.py # every level the program loads, written at the end
|
|
5
|
+
|
|
6
|
+
A trace holds the level itself (also a generated level or a variant) and the calls in
|
|
7
|
+
order, so it can be replayed exactly: `python -m dungeoncoder replay spur.json` shows it
|
|
8
|
+
in the game, `python -m dungeoncoder trace spur.json` lists it with the hero's field after
|
|
9
|
+
every call (computed in the simulator). Positions are not recorded while the program runs:
|
|
10
|
+
the program itself never learns where the hero stands.
|
|
11
|
+
|
|
12
|
+
Format (JSON):
|
|
13
|
+
{"format": "dungeoncoder-trace", "version": 1,
|
|
14
|
+
"runs": [{"level_file": "levels/x.json", "level": {...Tiled JSON...},
|
|
15
|
+
"calls": [["move", null, true], ["is_switch_in_front", null, false], ...],
|
|
16
|
+
"statistics": {...}}]}
|
|
17
|
+
"""
|
|
18
|
+
import atexit
|
|
19
|
+
import json
|
|
20
|
+
import os
|
|
21
|
+
import signal
|
|
22
|
+
import sys
|
|
23
|
+
import threading
|
|
24
|
+
|
|
25
|
+
FORMAT, VERSION = "dungeoncoder-trace", 1
|
|
26
|
+
# calls that only the host/tools make, or that don't belong in a replay
|
|
27
|
+
NOT_RECORDED = ("load_level", "get_version")
|
|
28
|
+
MAX_CALLS = 50_000 # per run: a program in an endless loop still gives a trace of its start
|
|
29
|
+
|
|
30
|
+
runs = [] # one entry per loaded level: {"level_file", "level", "calls", "statistics"}
|
|
31
|
+
_level_file = None # the path the next load_level comes from (set by Game)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def loading(path):
|
|
35
|
+
"""Game is about to load the level from `path`."""
|
|
36
|
+
global _level_file
|
|
37
|
+
_level_file = path
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def record(method, params, result):
|
|
41
|
+
"""Called by dungeoncoder._call for every call (cheap: one list append)."""
|
|
42
|
+
if method == "load_level":
|
|
43
|
+
if result:
|
|
44
|
+
runs.append({"level_file": _level_file, "level": params, "calls": []})
|
|
45
|
+
return
|
|
46
|
+
if method in NOT_RECORDED or not runs:
|
|
47
|
+
return
|
|
48
|
+
if len(runs[-1]["calls"]) >= MAX_CALLS:
|
|
49
|
+
runs[-1]["truncated"] = True
|
|
50
|
+
return
|
|
51
|
+
shown = result.to_dict() if hasattr(result, "to_dict") else result
|
|
52
|
+
if method == "get_statistics":
|
|
53
|
+
runs[-1]["statistics"] = shown
|
|
54
|
+
runs[-1]["calls"].append([method, params, shown])
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def document(which=None):
|
|
58
|
+
"""The trace as a JSON-ready dict: all runs, or only the run objects in `which`."""
|
|
59
|
+
chosen = runs if which is None else which
|
|
60
|
+
return {"format": FORMAT, "version": VERSION, "runs": chosen}
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def write(path, which=None):
|
|
64
|
+
with open(path, "w", encoding="utf-8") as f:
|
|
65
|
+
json.dump(document(which), f, ensure_ascii=False)
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def read(path):
|
|
69
|
+
"""The runs of a trace file; raises ValueError if it isn't one."""
|
|
70
|
+
with open(path, encoding="utf-8") as f:
|
|
71
|
+
data = json.load(f)
|
|
72
|
+
if not isinstance(data, dict) or data.get("format") != FORMAT:
|
|
73
|
+
raise ValueError(f"{path} is not a Dungeon Coder trace")
|
|
74
|
+
return data["runs"]
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def _write_at_exit():
|
|
78
|
+
path = os.environ.get("DUNGEONCODER_TRACE", "").strip()
|
|
79
|
+
if path and runs:
|
|
80
|
+
write(path)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
atexit.register(_write_at_exit)
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def _stop(signum, frame):
|
|
87
|
+
sys.exit(128 + signum) # runs the atexit hooks, so the trace is written
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
# a stopped program (e.g. `variants` ends one in an endless loop) still writes its trace
|
|
91
|
+
if os.environ.get("DUNGEONCODER_TRACE", "").strip() and threading.current_thread() is threading.main_thread():
|
|
92
|
+
signal.signal(signal.SIGTERM, _stop)
|
dungeoncoder/variants.py
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
"""Level variants: one level file, many levels. `Game("schalter.json", seed=17)`.
|
|
2
|
+
|
|
3
|
+
A level marks what may move: a rectangle object of class `Region` (drawn in Tiled, or
|
|
4
|
+
`region:` in a text map) and objects whose property `region` names it. Loading the level
|
|
5
|
+
with a seed puts those objects on different free fields of their region; the same seed
|
|
6
|
+
always gives the same variant, and the map property `seed` carries it (the game shows it
|
|
7
|
+
on its end screen, so a failure can be reproduced).
|
|
8
|
+
|
|
9
|
+
region: s 2,2 17,13 # text map: every switch s lies somewhere in this rectangle
|
|
10
|
+
|
|
11
|
+
Without a seed the level is loaded as drawn, unless its map property `variants` is
|
|
12
|
+
`random`: then every load is a new variant, and the seed is printed. The environment
|
|
13
|
+
variable DUNGEONCODER_SEED fixes such a random seed from outside (grading, tutors).
|
|
14
|
+
|
|
15
|
+
The variant is made here, in Python, before the level goes to the game or the simulator,
|
|
16
|
+
so both get exactly the same level.
|
|
17
|
+
"""
|
|
18
|
+
import copy
|
|
19
|
+
import os
|
|
20
|
+
import random
|
|
21
|
+
|
|
22
|
+
REGION = "Region"
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def random_seed():
|
|
26
|
+
"""A seed for "random": DUNGEONCODER_SEED if set (grading, reproducing), else a new one."""
|
|
27
|
+
fixed = os.environ.get("DUNGEONCODER_SEED", "").strip()
|
|
28
|
+
if fixed.lstrip("-").isdigit():
|
|
29
|
+
return int(fixed), False
|
|
30
|
+
return random.SystemRandom().randrange(1, 1_000_000), True
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def _prop(props, name):
|
|
34
|
+
return next((p.get("value") for p in props or [] if p.get("name") == name), None)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def _set_prop(level, name, type_, value):
|
|
38
|
+
props = [p for p in level.get("properties", []) or [] if p.get("name") != name]
|
|
39
|
+
props.append({"name": name, "type": type_, "value": value})
|
|
40
|
+
level["properties"] = props
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def has_regions(level):
|
|
44
|
+
return any(o.get("type") == REGION for layer in level.get("layers", []) for o in layer.get("objects", []) or [])
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def strip_regions(level):
|
|
48
|
+
"""The level without its Region rectangles (they only describe variants)."""
|
|
49
|
+
for layer in level.get("layers", []):
|
|
50
|
+
if "objects" in layer:
|
|
51
|
+
layer["objects"] = [o for o in layer["objects"] if o.get("type") != REGION]
|
|
52
|
+
return level
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def _walkable(level):
|
|
56
|
+
"""A function (col, row) -> walkable by the game's rules, or None if the tile rules aren't
|
|
57
|
+
available here (then the region is trusted as drawn)."""
|
|
58
|
+
try:
|
|
59
|
+
from . import sim
|
|
60
|
+
rules = sim.Level(strip_regions(copy.deepcopy(level)))
|
|
61
|
+
except Exception: # noqa: BLE001 - e.g. a missing asset pack: trust the region
|
|
62
|
+
return None
|
|
63
|
+
return rules.walkable
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def apply(level, seed):
|
|
67
|
+
"""A copy of the level with every object of a region on a field of that region chosen by
|
|
68
|
+
`seed` (no two on one field, never on a field another object occupies), map property
|
|
69
|
+
`seed` set. Raises ValueError if a region has fewer free fields than objects."""
|
|
70
|
+
level = copy.deepcopy(level)
|
|
71
|
+
tw, th = level.get("tilewidth", 16), level.get("tileheight", 16)
|
|
72
|
+
objects = [o for layer in level.get("layers", []) for o in layer.get("objects", []) or []]
|
|
73
|
+
regions = {o.get("name", ""): o for o in objects if o.get("type") == REGION}
|
|
74
|
+
walkable = _walkable(level)
|
|
75
|
+
rng = random.Random(seed)
|
|
76
|
+
|
|
77
|
+
def cell(o):
|
|
78
|
+
return int(o["x"] // tw), int((o["y"] - 1) // th)
|
|
79
|
+
|
|
80
|
+
movers = {name: [o for o in objects if o.get("type") != REGION and _prop(o.get("properties"), "region") == name]
|
|
81
|
+
for name in sorted(regions)}
|
|
82
|
+
moving = {id(o) for group in movers.values() for o in group}
|
|
83
|
+
taken = {cell(o) for o in objects if o.get("type") != REGION and id(o) not in moving and o.get("gid")}
|
|
84
|
+
for name, group in movers.items():
|
|
85
|
+
if not group:
|
|
86
|
+
continue
|
|
87
|
+
r = regions[name]
|
|
88
|
+
c0, r0 = int(r["x"] // tw), int(r["y"] // th)
|
|
89
|
+
c1, r1 = int((r["x"] + r["width"] - 1) // tw), int((r["y"] + r["height"] - 1) // th)
|
|
90
|
+
free = [(c, rr) for rr in range(r0, r1 + 1) for c in range(c0, c1 + 1)
|
|
91
|
+
if (c, rr) not in taken and (walkable is None or walkable(c, rr))]
|
|
92
|
+
if len(free) < len(group):
|
|
93
|
+
raise ValueError(f"region {name!r} has {len(free)} free field(s) for {len(group)} object(s)")
|
|
94
|
+
for o, (c, rr) in zip(group, rng.sample(free, len(group))):
|
|
95
|
+
o["x"], o["y"] = c * tw, (rr + 1) * th
|
|
96
|
+
taken.add((c, rr))
|
|
97
|
+
_set_prop(level, "seed", "int", seed)
|
|
98
|
+
return strip_regions(level)
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def prepare(level, seed=None):
|
|
102
|
+
"""(level to load, seed or None, chosen at random?) for Game(path, seed). Levels without
|
|
103
|
+
regions are returned unchanged (a seed given for them is ignored)."""
|
|
104
|
+
if not has_regions(level):
|
|
105
|
+
return level, None, False
|
|
106
|
+
chosen = False
|
|
107
|
+
if seed is None and str(_prop(level.get("properties"), "variants") or "").lower() == "random":
|
|
108
|
+
seed, _ = random_seed()
|
|
109
|
+
chosen = True
|
|
110
|
+
if seed is None:
|
|
111
|
+
return strip_regions(copy.deepcopy(level)), None, False
|
|
112
|
+
return apply(level, seed), seed, chosen
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: dungeoncoder
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Python API for Dungeon Coder: steer the hero from a script, in VS Code or in the built-in simulator
|
|
5
|
+
License-Expression: MIT
|
|
6
|
+
Classifier: Programming Language :: Python :: 3
|
|
7
|
+
Classifier: Intended Audience :: Education
|
|
8
|
+
Classifier: Topic :: Education
|
|
9
|
+
Requires-Python: >=3.10
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
License-File: LICENSE.txt
|
|
12
|
+
Requires-Dist: httpx>=0.27
|
|
13
|
+
Requires-Dist: attrs>=23.1
|
|
14
|
+
Dynamic: license-file
|
|
15
|
+
|
|
16
|
+
# dungeoncoder
|
|
17
|
+
|
|
18
|
+
The Python API for Dungeon Coder, a VS Code extension in which a Python script steers a hero through a pixel-art dungeon.
|
|
19
|
+
|
|
20
|
+
```python
|
|
21
|
+
from dungeoncoder import Game
|
|
22
|
+
|
|
23
|
+
game = Game("playground.json")
|
|
24
|
+
hero = game.get_hero()
|
|
25
|
+
while not hero.is_at_goal():
|
|
26
|
+
if hero.is_collision_in_front():
|
|
27
|
+
hero.turn_left()
|
|
28
|
+
else:
|
|
29
|
+
hero.move()
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
- **With the extension:** start the game in VS Code (`Dungeon Coder: Enter the dungeon`); the script talks to it over a local REST API.
|
|
33
|
+
- **Without VS Code:** `dungeoncoder.use_simulator()` (or `DUNGEONCODER_SIM=1`) runs the same script in a pure-Python simulator of the game's rules: no picture, no waiting. `dungeoncoder.testing.spiel(map_text)` gives `(game, hero)` for pytest.
|
|
34
|
+
- **Levels from text maps:** `Game("karte.txt")`.
|
|
35
|
+
- **Setup check:** `python -m dungeoncoder` says which Python and which copy of the package run, whether the game answers and whether its version fits.
|
|
36
|
+
|
|
37
|
+
The package has the same version as the extension. Install it with `pip install dungeoncoder`.
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
dungeoncoder/__init__.py,sha256=XrFyz332acwER5Y781xhNsC4izHNQNGxbo0hCTv_mDI,158
|
|
2
|
+
dungeoncoder/__main__.py,sha256=HYiXQM02zWpM75K3wpK5gD3FL85oTV-tPISkT6c8M7E,11331
|
|
3
|
+
dungeoncoder/_api_config.py,sha256=wWI57wQZgDT9fsL5Ljasf9B46Ukr1zD5qsKzcLc1zYI,187
|
|
4
|
+
dungeoncoder/asciimap.py,sha256=IpBHmu9xeto4bhWZczCpcOqqZd0V4mkZ9OKCQ_T9lxo,44901
|
|
5
|
+
dungeoncoder/dungeoncoder.py,sha256=fZ32hKKGmH8DrsiNmrWR4WAd0YF-huu2PZr_fUFkI8E,23167
|
|
6
|
+
dungeoncoder/generator.py,sha256=dmkW2C7-fIe2LmnaZzuYwB6THS5HTqBluW5t1C4asnQ,9427
|
|
7
|
+
dungeoncoder/replay.py,sha256=3nQEtXG19x2ZIK1jWgEWbvguNcEXOMNStquXMeSzKlE,3304
|
|
8
|
+
dungeoncoder/requirements.txt,sha256=F-GNwkLSOnRQ1ebP-ZUs2th-4HRn-7j-N_xkDLCn2to,24
|
|
9
|
+
dungeoncoder/sim.py,sha256=OOgKDJh5ak9LzIqnXV_HYaMVHTuQPa89yIdFrCpLym4,35924
|
|
10
|
+
dungeoncoder/testing.py,sha256=CiYsJLKKoU3GBU0bbxolkQkqFe8QZ3lEoFgbwuEFlgo,2252
|
|
11
|
+
dungeoncoder/trace.py,sha256=xE-CewFpmSq2aDCHtT5Lh74AMjmUbGV4eCAC7C1HxnE,3426
|
|
12
|
+
dungeoncoder/variants.py,sha256=3dhyBgmuurwIFG1VAZkzRrxYdRldbiQ_8sjKb8K-iis,4896
|
|
13
|
+
dungeoncoder/_generated/__init__.py,sha256=HIZSbxk1_1Zg9M8NfwBlcYFM1vI7OQsIoQ3a_MLDE1c,162
|
|
14
|
+
dungeoncoder/_generated/client.py,sha256=GDzw6T2uRmPlUb1DImpBGxwy0dNbhmBknfvvIQW0GuU,12387
|
|
15
|
+
dungeoncoder/_generated/errors.py,sha256=trp-p5qn1_JLRxGZhdHtICaNPaCrcDCe4TgIihBravk,546
|
|
16
|
+
dungeoncoder/_generated/types.py,sha256=k9-ddYg6Tq-sd90hvGkH8-9hLj94QeCGVmGNz2xM5JQ,1350
|
|
17
|
+
dungeoncoder/_generated/api/__init__.py,sha256=87ApBzKyGb5zsgTMOkQXDqsLZCmaSFoJMwbGzCDQZMw,47
|
|
18
|
+
dungeoncoder/_generated/api/game/__init__.py,sha256=wYN6A3_bvYW13B1J9YvYCmcv5Els-q-E07kZJwJ7Vto,58
|
|
19
|
+
dungeoncoder/_generated/api/game/get_statistics.py,sha256=xf3zg-Cmv1-vc6s6pGUeqUrjOMwBNZLG3J-dR1HQqOo,3998
|
|
20
|
+
dungeoncoder/_generated/api/game/get_version.py,sha256=qFQ9_6E5fq0krHDr_Zr_tsx6g2wGT4MSjhfmJu7g6Ck,4388
|
|
21
|
+
dungeoncoder/_generated/api/hero/__init__.py,sha256=wYN6A3_bvYW13B1J9YvYCmcv5Els-q-E07kZJwJ7Vto,58
|
|
22
|
+
dungeoncoder/_generated/api/hero/ask_oracle.py,sha256=2vF_NNscEi8AY1dLpjOhwRKCD56ts03ToXH-bWEh_yY,5009
|
|
23
|
+
dungeoncoder/_generated/api/hero/configure.py,sha256=TTusVxlNCF0gVUQli1L-7A8uU-VPKdxfvzF9Vyy7a6U,4880
|
|
24
|
+
dungeoncoder/_generated/api/hero/drop.py,sha256=9Uzizy5b-vAMdkw4YrtDYLElfG15pbdOQH0Puey7u_c,4805
|
|
25
|
+
dungeoncoder/_generated/api/hero/get_inventory.py,sha256=AY4jlFaEBY-x9qnNfXL7LprHAoLhyoNB76IgVuBds2U,4433
|
|
26
|
+
dungeoncoder/_generated/api/hero/get_items_at_position.py,sha256=sN_xsXLQcZ-y2UTRGtwlDBbiZVn8beOmJPqiF5n9voY,4433
|
|
27
|
+
dungeoncoder/_generated/api/hero/interact.py,sha256=fLZnyDjwzengqjbFwdvsPp4T3JAboSwCEWE95tcHeUk,4484
|
|
28
|
+
dungeoncoder/_generated/api/hero/is_abyss_in_front.py,sha256=aoc7FLrR2LK4h4e55KnW1mmR3f8Yfdv75cccFFfRZM0,4432
|
|
29
|
+
dungeoncoder/_generated/api/hero/is_at_goal.py,sha256=k6JwNK8ujRc6f92RL2NoerDSF7HzeAh3KwgjxhPEQZc,4669
|
|
30
|
+
dungeoncoder/_generated/api/hero/is_collision_in_front.py,sha256=4DSrSFRm_f4F0xfNvKw4z6mhxY_vk5kWrFztrd_jiNE,4440
|
|
31
|
+
dungeoncoder/_generated/api/hero/is_enemy_in_front.py,sha256=bH2fN45-8wVqoYSUGQYz86bvaCzNOpRXPhq3rj20JkQ,4412
|
|
32
|
+
dungeoncoder/_generated/api/hero/is_facing_north.py,sha256=YVGZs_4c7c3O7aXfZC_y3lsCGM0xdkFKKZ9-skWvOmE,4342
|
|
33
|
+
dungeoncoder/_generated/api/hero/is_switch_in_front.py,sha256=5hkQVGMfJE-hwBimmZMMmV68G5FAAaYCXeYAIbmI4XQ,4401
|
|
34
|
+
dungeoncoder/_generated/api/hero/is_torch_in_front.py,sha256=cT-1XHDlMxRgEUyAOC39aayKB650sP3pTHDb35rMQMA,4396
|
|
35
|
+
dungeoncoder/_generated/api/hero/move.py,sha256=XMol15DR6Lbxqui1YK7tVPrpghxk64eyI0NcZeVks8k,4300
|
|
36
|
+
dungeoncoder/_generated/api/hero/peek_item_value.py,sha256=Ml8mizVE7na7fMEd6tyhEMrm6JXbhvZRQAb-6qiryJE,5297
|
|
37
|
+
dungeoncoder/_generated/api/hero/pickup.py,sha256=VLDn2qD0iK2YY4Q1wzDEgEwV1QUoB1UTXiQBrXU2CbM,4839
|
|
38
|
+
dungeoncoder/_generated/api/hero/read_item_value.py,sha256=ockVa8TCfc3NHTIxVUfwi5T3DKWmXku-QFJirrZ79AA,4639
|
|
39
|
+
dungeoncoder/_generated/api/hero/sense_goal.py,sha256=eGmulE3qaGxrLwXua5M9urmVTceM2gTr52LM5uagXeg,4850
|
|
40
|
+
dungeoncoder/_generated/api/hero/set_pace.py,sha256=6YZosGxLyzfPyOTT0F3G11Q_5sMmeCZhNRnvwGCljA4,4820
|
|
41
|
+
dungeoncoder/_generated/api/hero/turn_left.py,sha256=AP7tYD-lyyHsVV969PJoQRJzt6jvAV5mVebCihToMoU,4329
|
|
42
|
+
dungeoncoder/_generated/api/level/__init__.py,sha256=wYN6A3_bvYW13B1J9YvYCmcv5Els-q-E07kZJwJ7Vto,58
|
|
43
|
+
dungeoncoder/_generated/api/level/load_level.py,sha256=1iVkkyXHZNbjjOMwIJ42yESplmPoMK51INzpectpn3U,4902
|
|
44
|
+
dungeoncoder/_generated/api/level/reset_level.py,sha256=Id6Vcsl1Wavj7lYWeSE82AKg0mBKbnk4JUZnpo3oOro,3824
|
|
45
|
+
dungeoncoder/_generated/models/__init__.py,sha256=c4f_16DlsbV6LRjLHFHGLehO_bTheQFs53DuzgLO8Qg,1675
|
|
46
|
+
dungeoncoder/_generated/models/api_error_response.py,sha256=2nXlvesqNRP-2VGzVUfWEe-XyU20PvlbrS2x0AX4QXQ,2212
|
|
47
|
+
dungeoncoder/_generated/models/api_error_response_status.py,sha256=oTCGPrkFh-gFE_hm12L8qZ2GL88N3A4S7rwMV75UkGw,146
|
|
48
|
+
dungeoncoder/_generated/models/boolean_result.py,sha256=eKwEKhKC7QtfuNTy8Mn6859GKHl_2hojy4Htno0Nukw,2039
|
|
49
|
+
dungeoncoder/_generated/models/boolean_result_status.py,sha256=4NOZA9jv11OspDKT2Ve_x3yusew6ulZFtssf2FdiFs4,147
|
|
50
|
+
dungeoncoder/_generated/models/configure_params.py,sha256=Lu13I-dBox_S2VW9eUGVj8coknictO5JUZ7kVw7TmtA,1845
|
|
51
|
+
dungeoncoder/_generated/models/distance_param.py,sha256=sBwka39M4n6JgHdsnAXGHXauUGiPGtyZIS7rClXUiB8,1677
|
|
52
|
+
dungeoncoder/_generated/models/name_param.py,sha256=HUKqlv7F5QMnUbnIz3PJx3Ut8oFRRBJ-fISHlAfBzm4,1599
|
|
53
|
+
dungeoncoder/_generated/models/nullable_integer_result.py,sha256=F_6lO01BDRuw4CJQjdflgrTM8VKmUqc0lK54C9ixKNg,2357
|
|
54
|
+
dungeoncoder/_generated/models/nullable_integer_result_status.py,sha256=HJ3Ja0c2Eh9vUZ-wiXOcgTYsnbRcmm-nr2BHAW3bszU,155
|
|
55
|
+
dungeoncoder/_generated/models/nullable_string_result.py,sha256=RKbXYPKIcXiSJk7y5EhidHKO8pmvpZ1N1Yx4Zt8TXF8,2347
|
|
56
|
+
dungeoncoder/_generated/models/nullable_string_result_status.py,sha256=2LBvP2NtWwYNVeTC-6gN_Y5KPG9_fxeuyl_c3q9XZrQ,154
|
|
57
|
+
dungeoncoder/_generated/models/pace_params.py,sha256=gLoWR0ripIbFNb0HrZo2wISspoUnkS3Kgp-U_zzXv2U,1618
|
|
58
|
+
dungeoncoder/_generated/models/statistics.py,sha256=l_cq5x-I30JY0xEgHgQ-IBCB03kIpjXEPYOnTFDEbrc,5718
|
|
59
|
+
dungeoncoder/_generated/models/statistics_result.py,sha256=u0fTcIDmZ75qIVePbsDjWJW9nuZBZH92_SpXWygBrtA,2346
|
|
60
|
+
dungeoncoder/_generated/models/statistics_result_status.py,sha256=HjJ92u3UfD1Oz4KDE_x-JA5_TtfOrNHXGrPHrLae9tw,150
|
|
61
|
+
dungeoncoder/_generated/models/string_array_result.py,sha256=j2IcdEamX8buigvKH5_9_If6ZbVk-GyImnqkNQ6TOqA,2137
|
|
62
|
+
dungeoncoder/_generated/models/string_array_result_status.py,sha256=H1mw62iwwZIgVElO3hI9d9nmGFOUTk5ZLVON_5UE9GE,151
|
|
63
|
+
dungeoncoder/_generated/models/tiled_level.py,sha256=IKVBujaSycyKteryR1BMoCStKAUWoeYe0HEbFpgZ6Hw,1496
|
|
64
|
+
dungeoncoder/_generated/models/version_result.py,sha256=lPLIS4bjzd7u-CxAuhCO1hdDCLt_6cGiBbNw2zpl_U0,2362
|
|
65
|
+
dungeoncoder/_generated/models/version_result_result.py,sha256=uzwIJdobBpNAJOOt7tXjUvwJuojGNzo91TR2WWk_HLk,1871
|
|
66
|
+
dungeoncoder/_generated/models/version_result_status.py,sha256=slTpNJowot9-yOXffNiV4mGptdobN3B85EWyZr33cMs,147
|
|
67
|
+
dungeoncoder/packs/gelaende.json,sha256=Q8NzzL6rVhA2Bymzd6tWa9zVv6h41e9rrcRXiauUvg4,8021
|
|
68
|
+
dungeoncoder/packs/items.json,sha256=ZcuYBLo8larn3JH2qJ4E0nkfKtryntelnJx6lk4b8cU,1554
|
|
69
|
+
dungeoncoder/packs/station.json,sha256=ItoPil_83LprELwygrDU9vMHGhKDlceaLK2n3VqpPwA,7918
|
|
70
|
+
dungeoncoder/packs/studio.json,sha256=-KqKBgTT5DnaJcco1789cZHI5rJINQ0NT3VxAFaOuAg,7854
|
|
71
|
+
dungeoncoder/packs/tilesets.json,sha256=vVHjE_dOBEalXKLoIu3FRDaTT8UiXe0hzrH37sIgkr8,54226
|
|
72
|
+
dungeoncoder/packs/werkstatt.json,sha256=DbPvym5jwiZokBDn7U79zps5jHMAtD0bKvr88sdwczk,8091
|
|
73
|
+
dungeoncoder-0.2.0.dist-info/licenses/LICENSE.txt,sha256=6Hbha-oiKVwW83FDLzR4iCqHHYsM2aPrxXCHWGw60P4,1178
|
|
74
|
+
dungeoncoder-0.2.0.dist-info/METADATA,sha256=opqoq7XqdogE2_4IDIN4emVhxdDf9jkFosagmbU7ePE,1517
|
|
75
|
+
dungeoncoder-0.2.0.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
|
|
76
|
+
dungeoncoder-0.2.0.dist-info/top_level.txt,sha256=LyJOZeLnQba_mjU-xD0fXxLBj343jnnUwhOeaOEVyPc,13
|
|
77
|
+
dungeoncoder-0.2.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
Copyright (c) Microsoft Corporation
|
|
2
|
+
Copyright (c) Munich University of Applied Sciences
|
|
3
|
+
Copyright (c) Benedikt Dietrich
|
|
4
|
+
|
|
5
|
+
All rights reserved.
|
|
6
|
+
|
|
7
|
+
MIT License
|
|
8
|
+
|
|
9
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
10
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
11
|
+
in the Software without restriction, including without limitation the rights
|
|
12
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
13
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
14
|
+
furnished to do so, subject to the following conditions:
|
|
15
|
+
|
|
16
|
+
The above copyright notice and this permission notice shall be included in all
|
|
17
|
+
copies or substantial portions of the Software.
|
|
18
|
+
|
|
19
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
20
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
21
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
22
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
23
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
24
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
25
|
+
SOFTWARE.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
dungeoncoder
|