hoodscript 1.2.0__tar.gz → 1.3.1__tar.gz
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.
- {hoodscript-1.2.0 → hoodscript-1.3.1}/CHANGELOG.md +104 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/CONTRIBUTING.md +19 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/PKG-INFO +25 -1
- {hoodscript-1.2.0 → hoodscript-1.3.1}/README.md +19 -0
- hoodscript-1.3.1/docs/adr/0004-no-regional-dialect-overlays.md +45 -0
- hoodscript-1.3.1/docs/grammar.ebnf +59 -0
- hoodscript-1.3.1/examples/solutions/beatlab/stage1.hs +10 -0
- hoodscript-1.3.1/examples/solutions/beatlab/stage2.hs +15 -0
- hoodscript-1.3.1/examples/solutions/beatlab/stage3.hs +11 -0
- hoodscript-1.3.1/examples/solutions/beatlab/stage4.hs +14 -0
- hoodscript-1.3.1/examples/solutions/beatlab/stage5.hs +13 -0
- hoodscript-1.3.1/examples/solutions/cookout/stage1.hs +9 -0
- hoodscript-1.3.1/examples/solutions/cookout/stage2.hs +8 -0
- hoodscript-1.3.1/examples/solutions/cookout/stage3.hs +5 -0
- hoodscript-1.3.1/examples/solutions/cookout/stage4.hs +26 -0
- hoodscript-1.3.1/examples/solutions/cookout/stage5.hs +13 -0
- hoodscript-1.3.1/examples/solutions/dropday/stage1.hs +13 -0
- hoodscript-1.3.1/examples/solutions/dropday/stage2.hs +14 -0
- hoodscript-1.3.1/examples/solutions/dropday/stage3.hs +12 -0
- hoodscript-1.3.1/examples/solutions/dropday/stage4.hs +11 -0
- hoodscript-1.3.1/examples/solutions/dropday/stage5.hs +16 -0
- hoodscript-1.3.1/examples/solutions/level1.hs +9 -0
- hoodscript-1.3.1/examples/solutions/level2.hs +9 -0
- hoodscript-1.3.1/examples/solutions/level3.hs +14 -0
- hoodscript-1.3.1/examples/solutions/level4.hs +18 -0
- hoodscript-1.3.1/examples/solutions/level5.hs +38 -0
- hoodscript-1.3.1/examples/solutions/level6.hs +14 -0
- hoodscript-1.3.1/examples/solutions/level7.hs +37 -0
- hoodscript-1.3.1/examples/solutions/level8.hs +41 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/pyproject.toml +11 -1
- hoodscript-1.3.1/scripts/gen_ebnf.py +33 -0
- hoodscript-1.3.1/scripts/hooks/pre-push +11 -0
- hoodscript-1.3.1/scripts/install-hooks.sh +7 -0
- hoodscript-1.3.1/src/hoodarcade/__init__.py +9 -0
- hoodscript-1.3.1/src/hoodarcade/cli.py +357 -0
- hoodscript-1.3.1/src/hoodarcade/core/runtime.py +148 -0
- hoodscript-1.3.1/src/hoodarcade/core/ui.py +232 -0
- hoodscript-1.3.1/src/hoodarcade/games/beatlab.py +393 -0
- hoodscript-1.3.1/src/hoodarcade/games/cookout.py +446 -0
- hoodscript-1.3.1/src/hoodarcade/games/dropday.py +415 -0
- hoodscript-1.3.1/src/hoodfarm/__init__.py +3 -0
- hoodscript-1.3.1/src/hoodfarm/cli.py +262 -0
- hoodscript-1.3.1/src/hoodfarm/drone.py +158 -0
- hoodscript-1.3.1/src/hoodfarm/grid.py +216 -0
- hoodscript-1.3.1/src/hoodfarm/levels.py +402 -0
- hoodscript-1.3.1/src/hoodfarm/renderer.py +249 -0
- hoodscript-1.3.1/src/hoodfarm/runner.py +224 -0
- hoodscript-1.3.1/src/hoodlib/__init__.py +9 -0
- hoodscript-1.3.1/src/hoodlib/disk.py +177 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/src/hoodscript/_version.py +2 -2
- {hoodscript-1.2.0 → hoodscript-1.3.1}/src/hoodscript/cli.py +41 -4
- {hoodscript-1.2.0 → hoodscript-1.3.1}/src/hoodscript/errors/translator.py +1 -1
- {hoodscript-1.2.0 → hoodscript-1.3.1}/src/hoodscript/kernel/kernel.py +4 -1
- {hoodscript-1.2.0 → hoodscript-1.3.1}/src/hoodscript/patterns.py +21 -11
- hoodscript-1.3.1/src/hoodscript/zen.py +60 -0
- hoodscript-1.3.1/src/vibe.py +8 -0
- hoodscript-1.3.1/tests/test_arcade.py +224 -0
- hoodscript-1.3.1/tests/test_arcade_gates.py +72 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/tests/test_cli.py +14 -0
- hoodscript-1.3.1/tests/test_fuzz_ebnf.py +178 -0
- hoodscript-1.3.1/tests/test_game_engine.py +249 -0
- hoodscript-1.3.1/tests/test_grammar_ebnf.py +19 -0
- hoodscript-1.3.1/tests/test_hoodlib_disk.py +101 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/tests/test_kernel.py +14 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/tests/test_patterns.py +13 -0
- hoodscript-1.3.1/tests/test_wheel_contents.py +34 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/.gitignore +0 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/CODE_OF_CONDUCT.md +0 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/LICENSE +0 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/SECURITY.md +0 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/SPRINT_PLAN.md +0 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/docs/adr/0001-token-pipeline-over-parser.md +0 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/docs/adr/0002-keyword-reconciliation.md +0 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/docs/adr/0003-inclusive-ranges.md +0 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/docs/adr/README.md +0 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/docs/archive/HOODSCRIPT_COMPLETE_MASTER_SYSTEM.md +0 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/docs/archive/HOODSCRIPT_FULL_ENGINEERING_SUITE.md +0 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/docs/archive/HOODSCRIPT_UNSPRED_FEATURES_ROADMAP.md +0 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/docs/curriculum.md +0 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/docs/keywords.md +0 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/docs/onboarding.md +0 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/examples/quickstart.ipynb +0 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/out.txt +0 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/playground/app.js +0 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/playground/bundle.js +0 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/playground/examples.js +0 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/playground/hoodscript-latest-py3-none-any.whl +0 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/playground/index.html +0 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/playground/style.css +0 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/playground/worker.js +0 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/scripts/build_playground.py +0 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/scripts/gen_keywords.py +0 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/src/hoodscript/__init__.py +0 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/src/hoodscript/__main__.py +0 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/src/hoodscript/cache.py +0 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/src/hoodscript/constants.py +0 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/src/hoodscript/debugger.py +0 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/src/hoodscript/errors/__init__.py +0 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/src/hoodscript/errors/catalog.py +0 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/src/hoodscript/errors/renderer.py +0 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/src/hoodscript/formatter.py +0 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/src/hoodscript/importer.py +0 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/src/hoodscript/kernel/__init__.py +0 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/src/hoodscript/kernel/__main__.py +0 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/src/hoodscript/kernel/installer.py +0 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/src/hoodscript/kernel/magics.py +0 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/src/hoodscript/linter.py +0 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/src/hoodscript/lsp.py +0 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/src/hoodscript/migrator.py +0 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/src/hoodscript/repl.py +0 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/src/hoodscript/sandbox.py +0 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/src/hoodscript/stubs.py +0 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/src/hoodscript/traceback_handler.py +0 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/src/hoodscript/transpiler.py +0 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/src/hoodscript/tutor.py +0 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/tests/security/conftest.py +0 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/tests/security/corpus/deep_nesting.hs +0 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/tests/security/corpus/fork_bomb.hs +0 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/tests/security/corpus/huge_literal.hs +0 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/tests/security/corpus/import_escapes.hs +0 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/tests/security/corpus/infinite_recursion.hs +0 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/tests/security/corpus/open_file.hs +0 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/tests/security/corpus/pathological_indent.hs +0 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/tests/security/corpus/runaway_output.hs +0 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/tests/security/corpus/runaway_time.hs +0 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/tests/security/test_corpus.py +0 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/tests/security/test_exec_sites.py +0 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/tests/security/test_fuzz.py +0 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/tests/security/test_sandbox.py +0 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/tests/test_conformance.py +0 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/tests/test_debugger.py +0 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/tests/test_docs.py +0 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/tests/test_errors.py +0 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/tests/test_fmt.py +0 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/tests/test_grammar_canonical.py +0 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/tests/test_importer.py +0 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/tests/test_kernel_zmq.py +0 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/tests/test_keywords_doc.py +0 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/tests/test_learn.py +0 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/tests/test_lint.py +0 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/tests/test_lsp_features.py +0 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/tests/test_playground.py +0 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/tests/test_release.py +0 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/tests/test_repl.py +0 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/tests/test_transpiler.py +0 -0
- {hoodscript-1.2.0 → hoodscript-1.3.1}/tests/test_vscode_extension.py +0 -0
|
@@ -3,6 +3,110 @@
|
|
|
3
3
|
All notable changes to HoodScript. Format: [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
4
4
|
Versioning: the keyword set is the public API; changing it is at least a minor bump.
|
|
5
5
|
|
|
6
|
+
## [Unreleased]
|
|
7
|
+
|
|
8
|
+
## [1.3.1] — 2026-09-12
|
|
9
|
+
|
|
10
|
+
Patch release: what the fresh-machine check of 1.3.0 found, plus two audit
|
|
11
|
+
leftovers. No keyword or API changes.
|
|
12
|
+
|
|
13
|
+
### Fixed
|
|
14
|
+
|
|
15
|
+
- Fresh-machine check of v1.3.0 (`pip install "hoodscript[all]"` in a clean
|
|
16
|
+
venv, `docs/onboarding.md` §2–§11 verbatim): everything passed except
|
|
17
|
+
`hoodfarm test` and `hoodarcade test`, which reported "No Sol" for every
|
|
18
|
+
level and **exited 0** — the reference solutions were not in the wheel and a
|
|
19
|
+
missing solution counted as a pass. The solutions now ship
|
|
20
|
+
(`hoodscript/data/solutions`, found by both CLIs after the repo checkout), a
|
|
21
|
+
missing one is a red `MISSING` row and a non-zero exit, and
|
|
22
|
+
`tests/test_wheel_contents.py` builds the wheel and asserts the runtime
|
|
23
|
+
data (curriculum, `vibe.py`, solutions) is inside it.
|
|
24
|
+
|
|
25
|
+
- `hoodscript --sandbox run f.hs` now works (the flags may come before or after
|
|
26
|
+
`run`; `run` is recognised as the first positional, not only as `argv[0]`).
|
|
27
|
+
- Jupyter: `%hood_tb` is honoured by the error card — the Python traceback
|
|
28
|
+
section opens by default and the plain-text fallback carries it too.
|
|
29
|
+
- MANUAL §16 documents that `hoodscript fmt` writes `ain't nobody x` back as
|
|
30
|
+
`ain't x` (same Python, one canonical spelling).
|
|
31
|
+
- `cli.py` had the `arcade` dispatch block twice; the copy is gone.
|
|
32
|
+
|
|
33
|
+
## [1.3.0] — 2026-09-12
|
|
34
|
+
|
|
35
|
+
Three features that were on `main` but not on PyPI: the two games and the
|
|
36
|
+
ecosystem sprint. Keyword set unchanged (v1.1); minor bump for the new
|
|
37
|
+
packages and CLI commands.
|
|
38
|
+
|
|
39
|
+
### Added
|
|
40
|
+
|
|
41
|
+
- `hoodarcade levels [game]`: the stage table for one game (`list` stays the
|
|
42
|
+
all-games form). Added while aligning a stale "Arcade + Ecosystem" prompt
|
|
43
|
+
with the release — the reconciliation is `PROMPTS.md` §3.5.
|
|
44
|
+
|
|
45
|
+
- **The Drone Was Replaced** (`hoodfarm`, `pip install "hoodscript[farm]"`, also
|
|
46
|
+
`hoodscript farm …`): a terminal grid-automation game in the style of *The
|
|
47
|
+
Farmer Was Replaced*. Program a drone (`bot.move/harvest/plant/water/till/
|
|
48
|
+
inspect_ground/measure_water`, `bot.bag/energy/ticks_used`) in HoodScript
|
|
49
|
+
across 8 levels (single-tile harvest → loops → 2D traversal → conditional
|
|
50
|
+
weeding → irrigation → inventory quotas → companion planting → an
|
|
51
|
+
energy-budgeted supply chain). Rich TUI with emoji tiles, telemetry,
|
|
52
|
+
inventory ledger and log console (ASCII fallback); `hoodfarm play <level>`
|
|
53
|
+
hot-reloads `solution.hs` on save; `hoodfarm run --benchmark` and
|
|
54
|
+
`hoodfarm test` run headless with proper exit codes. Deterministic ticks.
|
|
55
|
+
Reference solutions for all 8 levels in `examples/solutions/`.
|
|
56
|
+
- QA on acceptance (external batch): it shipped with a **private game lexicon**
|
|
57
|
+
— `cook`/`serve`/`run_thru`/`Facts` (cut under Rule Zero) and `dip`
|
|
58
|
+
remapped to `break` — so 7 of 8 solutions did not parse under `hoodscript`
|
|
59
|
+
and the game taught a different language. Removed; every starter template
|
|
60
|
+
and solution translated to v1.1 and verified to win through the real
|
|
61
|
+
transpiler. Crashes now go through the JPE engine with the player's line and
|
|
62
|
+
the game state ("drone at (2, 4), energy 0, tick 50"). Cut builtin aliases
|
|
63
|
+
injected as globals (`span`, `lineup`, `ledger`, `count_up`) removed.
|
|
64
|
+
Tests guard all of it (no cut word as a code token anywhere in the game).
|
|
65
|
+
|
|
66
|
+
- **HoodArcade** (`hoodarcade`, `pip install "hoodscript[arcade]"`, also
|
|
67
|
+
`hoodscript arcade …`): three terminal games, five stages each, with Rich
|
|
68
|
+
viewports (grill rack + Spades table, 16-step 808 matrix, SNKRS drop feed),
|
|
69
|
+
hot-reload on save, and progress in `~/.hoodarcade/progress.json`:
|
|
70
|
+
*Big Mama's Cookout* (grill timing, the potato-salad exception test, aux-cord
|
|
71
|
+
sorting, a Spades rule engine, an autonomous Spades partner), *BeatLab 808*
|
|
72
|
+
(four-on-the-floor, trap-hat triplets by modulo, sample chopping, 808 glide
|
|
73
|
+
interpolation, a full arrangement), *Drop Day* (stock monitor, legit-check
|
|
74
|
+
filter, exponential backoff with `tryna`/`catch`, multi-cart, a circular
|
|
75
|
+
trade-graph search). Reference solutions for all 15 stages.
|
|
76
|
+
- QA on acceptance (external batch): same defect as the farm — a **private
|
|
77
|
+
lexicon** (`cook`/`serve`/`run_thru`/`Facts`, `dip`→`break`) meant no stage
|
|
78
|
+
solution ran under `hoodscript`; removed, everything translated to v1.1.
|
|
79
|
+
**Every "starter" template was the finished solution** — a player opened a
|
|
80
|
+
stage already solved; all 15 rewritten as real scaffolds (API shown,
|
|
81
|
+
algorithm left to the player; tests assert scaffolds fail and solutions
|
|
82
|
+
pass). Crashes in player code, including ones the stage checkers catch, now
|
|
83
|
+
surface as JPE reports with the failing line; a checker fed the wrong
|
|
84
|
+
return type fails the stage in plain English instead of raising.
|
|
85
|
+
|
|
86
|
+
- **HPEP 20 — The Zen of HoodScript.** `hoodscript zen` (add `--notes` to see
|
|
87
|
+
which file each line points at) and `import vibe` from any program, like
|
|
88
|
+
`import this`. Nineteen lines, each a decision this repo actually made.
|
|
89
|
+
- **`docs/grammar.ebnf`** — the formal grammar as its own artifact, generated
|
|
90
|
+
from `GRAMMAR.md` by `scripts/gen_ebnf.py`; a test fails if they drift and
|
|
91
|
+
another checks every keyword has a production (that found `ask` missing).
|
|
92
|
+
- **Grammar-directed fuzzing** (`tests/test_fuzz_ebnf.py`, Hypothesis): generates
|
|
93
|
+
valid programs from the grammar and asserts they transpile, compile, keep
|
|
94
|
+
their line count, contain no leaked sentinels or keywords, and that
|
|
95
|
+
`py2hood(transpile(p))` transpiles back to the same Python. Found and fixed
|
|
96
|
+
two pattern-layer bugs on its first run: `x = ask "name? "` was a syntax
|
|
97
|
+
error (R12 only fired at statement start; now anywhere), and `holla (x)` was
|
|
98
|
+
not reversible (whitespace now decides: `holla(x)` is a call, `holla (x)` is
|
|
99
|
+
the statement form). `HYPOTHESIS_PROFILE=thorough` runs 2,000 examples per
|
|
100
|
+
property.
|
|
101
|
+
- **`hoodlib.disk`** — atomic, thread-safe JSON/CSV read/write and backups,
|
|
102
|
+
standard library only (`from hoodlib import disk`). Errors are the Python
|
|
103
|
+
exceptions the crash reporter already explains.
|
|
104
|
+
- **ADR-0004: no regional dialect overlays.** A proposal for Bay Area / Atlanta
|
|
105
|
+
/ DMV / MLE token overlays was declined under Rule Zero; a cited, single-
|
|
106
|
+
variety Tier B extension remains possible via the sourcing procedure. Two
|
|
107
|
+
companion proposals (`hoodpkg`/`hood.lock`, and a `hoodlib` with AES-GCM and
|
|
108
|
+
an async HTTP client) were dropped as duplicating Python and its packaging.
|
|
109
|
+
|
|
6
110
|
## [1.2.0] — 2026-09-11
|
|
7
111
|
|
|
8
112
|
### Added
|
|
@@ -64,6 +64,15 @@ Before every push:
|
|
|
64
64
|
ruff check && pytest
|
|
65
65
|
```
|
|
66
66
|
|
|
67
|
+
Enforce it locally once per clone — the versioned pre-push hook runs exactly
|
|
68
|
+
this and refuses the push if it fails:
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
./scripts/install-hooks.sh
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
(If you pipe `ruff check` into anything, you lose its exit code. Don't.)
|
|
75
|
+
|
|
67
76
|
That is exactly what CI runs, on Ubuntu, macOS, and Windows × Python
|
|
68
77
|
3.10–3.13, plus a CLI smoke test. Python's exception *messages* differ between
|
|
69
78
|
versions (`was never closed` vs `EOF in multi-line statement`), so a catalog
|
|
@@ -107,6 +116,16 @@ with a gate. Commit at the gate with a message that says what changed and
|
|
|
107
116
|
why; the changelog is written from those messages. Update `CLAUDE.md` when a
|
|
108
117
|
decision changes — stale context is worse than none.
|
|
109
118
|
|
|
119
|
+
## Landing changes
|
|
120
|
+
|
|
121
|
+
`main` is protected: the Ubuntu/macOS/Windows test legs and the build must be
|
|
122
|
+
green, force-pushes and deletions are refused, and pull requests need a
|
|
123
|
+
code-owner review (`.github/CODEOWNERS`). **Work you did not write yourself —
|
|
124
|
+
an agent's output included — lands as a pull request**, gets `/code-review`
|
|
125
|
+
and the end-to-end audit in [`PROMPTS.md`](PROMPTS.md) §2.8, and only then
|
|
126
|
+
merges. Two batches arrived on 2026-09-11 claiming completion with defects
|
|
127
|
+
their own tests could not see; that is why.
|
|
128
|
+
|
|
110
129
|
## Working with an AI agent
|
|
111
130
|
|
|
112
131
|
Paste the standing brief from [`PROMPTS.md`](PROMPTS.md) §0 at the top of
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: hoodscript
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.3.1
|
|
4
4
|
Summary: A production-grade Python 3 conlang based on AAVE with 1:1 AST parity.
|
|
5
5
|
License: MIT
|
|
6
6
|
License-File: LICENSE
|
|
@@ -14,10 +14,13 @@ Requires-Dist: prompt-toolkit>=3.0.40; extra == 'all'
|
|
|
14
14
|
Requires-Dist: pygls<2,>=1.3.1; extra == 'all'
|
|
15
15
|
Requires-Dist: rich>=13.7; extra == 'all'
|
|
16
16
|
Requires-Dist: ruff>=0.3.0; extra == 'all'
|
|
17
|
+
Provides-Extra: arcade
|
|
18
|
+
Requires-Dist: rich>=13.7; extra == 'arcade'
|
|
17
19
|
Provides-Extra: dev
|
|
18
20
|
Requires-Dist: build>=1.1.0; extra == 'dev'
|
|
19
21
|
Requires-Dist: debugpy>=1.8.0; extra == 'dev'
|
|
20
22
|
Requires-Dist: hatch-vcs>=0.4.0; extra == 'dev'
|
|
23
|
+
Requires-Dist: hypothesis>=6.100; extra == 'dev'
|
|
21
24
|
Requires-Dist: ipykernel>=6.0.0; extra == 'dev'
|
|
22
25
|
Requires-Dist: ipython>=8.0.0; extra == 'dev'
|
|
23
26
|
Requires-Dist: jedi>=0.19.1; extra == 'dev'
|
|
@@ -28,6 +31,8 @@ Requires-Dist: pytest-cov>=4.1.0; extra == 'dev'
|
|
|
28
31
|
Requires-Dist: pytest>=8.0.0; extra == 'dev'
|
|
29
32
|
Requires-Dist: rich>=13.7; extra == 'dev'
|
|
30
33
|
Requires-Dist: ruff>=0.3.0; extra == 'dev'
|
|
34
|
+
Provides-Extra: farm
|
|
35
|
+
Requires-Dist: rich>=13.7; extra == 'farm'
|
|
31
36
|
Provides-Extra: jupyter
|
|
32
37
|
Requires-Dist: ipykernel>=6.0.0; extra == 'jupyter'
|
|
33
38
|
Requires-Dist: ipython>=8.0.0; extra == 'jupyter'
|
|
@@ -108,6 +113,7 @@ hoodscript kernel install # Jupyter kernel (pip install "hoodscript[jupyter]
|
|
|
108
113
|
hoodscript fmt|lint <file.hs> # formatter / linter (pip install "hoodscript[tools]")
|
|
109
114
|
hoodscript learn [topic] # interactive tutor driving docs/curriculum.md
|
|
110
115
|
hoodscript # a short tour of all commands
|
|
116
|
+
hoodscript zen # the Zen of HoodScript (HPEP 20); or `import vibe`
|
|
111
117
|
hoodscript lsp # language server over stdio, for editors
|
|
112
118
|
hoodscript make-stubs f.py # emit a .pyi-style stub with empty bodies
|
|
113
119
|
```
|
|
@@ -167,6 +173,24 @@ Everything else — `if`, `else`, `while`, `import`, `with`, `match`, `None`,
|
|
|
167
173
|
`self`, every builtin — is Python's own word, and every Python keyword still
|
|
168
174
|
works in a `.hs` file.
|
|
169
175
|
|
|
176
|
+
## Play
|
|
177
|
+
|
|
178
|
+
```bash
|
|
179
|
+
pip install "hoodscript[farm]"
|
|
180
|
+
hoodfarm levels # the 8 challenges
|
|
181
|
+
hoodfarm play 1 # edit solution.hs in your editor; the farm re-runs on every save
|
|
182
|
+
hoodfarm run my.hs -b # headless benchmark, exit 0 on pass
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
*The Drone Was Replaced*: program a farming drone in HoodScript, one level at
|
|
186
|
+
a time. Same language, same crash reports — the game just adds a `bot`.
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
pip install "hoodscript[arcade]"
|
|
190
|
+
hoodarcade # Big Mama's Cookout · BeatLab 808 · Drop Day
|
|
191
|
+
hoodarcade play cookout 1 # edit the solution file; the stage re-runs on save
|
|
192
|
+
```
|
|
193
|
+
|
|
170
194
|
## Learn
|
|
171
195
|
|
|
172
196
|
- [`docs/onboarding.md`](docs/onboarding.md) — from zero to a running program in ten minutes
|
|
@@ -63,6 +63,7 @@ hoodscript kernel install # Jupyter kernel (pip install "hoodscript[jupyter]
|
|
|
63
63
|
hoodscript fmt|lint <file.hs> # formatter / linter (pip install "hoodscript[tools]")
|
|
64
64
|
hoodscript learn [topic] # interactive tutor driving docs/curriculum.md
|
|
65
65
|
hoodscript # a short tour of all commands
|
|
66
|
+
hoodscript zen # the Zen of HoodScript (HPEP 20); or `import vibe`
|
|
66
67
|
hoodscript lsp # language server over stdio, for editors
|
|
67
68
|
hoodscript make-stubs f.py # emit a .pyi-style stub with empty bodies
|
|
68
69
|
```
|
|
@@ -122,6 +123,24 @@ Everything else — `if`, `else`, `while`, `import`, `with`, `match`, `None`,
|
|
|
122
123
|
`self`, every builtin — is Python's own word, and every Python keyword still
|
|
123
124
|
works in a `.hs` file.
|
|
124
125
|
|
|
126
|
+
## Play
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
pip install "hoodscript[farm]"
|
|
130
|
+
hoodfarm levels # the 8 challenges
|
|
131
|
+
hoodfarm play 1 # edit solution.hs in your editor; the farm re-runs on every save
|
|
132
|
+
hoodfarm run my.hs -b # headless benchmark, exit 0 on pass
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
*The Drone Was Replaced*: program a farming drone in HoodScript, one level at
|
|
136
|
+
a time. Same language, same crash reports — the game just adds a `bot`.
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
pip install "hoodscript[arcade]"
|
|
140
|
+
hoodarcade # Big Mama's Cookout · BeatLab 808 · Drop Day
|
|
141
|
+
hoodarcade play cookout 1 # edit the solution file; the stage re-runs on save
|
|
142
|
+
```
|
|
143
|
+
|
|
125
144
|
## Learn
|
|
126
145
|
|
|
127
146
|
- [`docs/onboarding.md`](docs/onboarding.md) — from zero to a running program in ten minutes
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# ADR-0004: No Regional Dialect Overlays (Rule Zero Stands)
|
|
2
|
+
|
|
3
|
+
## Status
|
|
4
|
+
Accepted (2026-09-12)
|
|
5
|
+
|
|
6
|
+
## Context
|
|
7
|
+
A proposal asked for a "modular regional dialect engine": token overlays for
|
|
8
|
+
Bay Area, Atlanta, DMV, and UK Drill / MLE slang, selectable via `hood.toml` or
|
|
9
|
+
`--dialect`, resolving to standard HoodScript tokens before transpilation.
|
|
10
|
+
|
|
11
|
+
## Decision
|
|
12
|
+
**Not adopted.** The keyword set is governed by Rule Zero and the sourcing
|
|
13
|
+
procedure in `hoodscript/docs/lexical-sourcing.md` §5. A dialect overlay is a
|
|
14
|
+
keyword table; every entry in it would need the same evidence as every other
|
|
15
|
+
keyword, and an owner-signed `GRAMMAR.md` revision. Four overlays of roughly
|
|
16
|
+
fifteen words each is four times the size of the entire v1.1 reconciliation.
|
|
17
|
+
|
|
18
|
+
Three further reasons:
|
|
19
|
+
|
|
20
|
+
1. **It grows the wrong tier.** The language's thesis is Tier A — AAVE aspect
|
|
21
|
+
marking (`be`, `steady`, `BIN`, `done`) mapped onto execution semantics.
|
|
22
|
+
Overlays add only Tier B naming, which was deliberately capped small:
|
|
23
|
+
"every alias is a thing to learn, and 1:1 legibility suffers as aliases
|
|
24
|
+
grow." Regional slang is also the most perishable vocabulary there is,
|
|
25
|
+
which is exactly what Rule Zero excludes.
|
|
26
|
+
2. **The mechanism is the known failure mode.** "Resolve dialect tokens to
|
|
27
|
+
standard tokens first" is the private-keyword-map pattern that three
|
|
28
|
+
external batches reintroduced in one day (2026-09-11/12), two of which
|
|
29
|
+
silently changed the meaning of `dip`. See CHANGELOG, QA sections.
|
|
30
|
+
3. **A player who learns a dialect learns a language that runs nowhere else.**
|
|
31
|
+
The 1:1 promise is that what you write in HoodScript is HoodScript.
|
|
32
|
+
|
|
33
|
+
## The door that stays open
|
|
34
|
+
The named varieties are real objects of sociolinguistic study. A *cited*
|
|
35
|
+
extension — one variety, each word through the seven steps, `UNVERIFIED`
|
|
36
|
+
where the literature is thin, signed by the owner — would be a legitimate
|
|
37
|
+
Tier B addition and can be proposed with `PROMPTS.md` §2.1. It is a sourcing
|
|
38
|
+
sprint first and a loader second, if ever.
|
|
39
|
+
|
|
40
|
+
## Consequences
|
|
41
|
+
- No `--dialect` flag, no dialect section in any config, no overlay loader.
|
|
42
|
+
- `constants.py` remains the single keyword table; `patterns.py` the single
|
|
43
|
+
multi-token layer.
|
|
44
|
+
- Proposals that arrive with a dialect map are declined at review with a
|
|
45
|
+
pointer to this ADR.
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
(* HoodScript v1.1 — formal grammar (EBNF).
|
|
2
|
+
Descriptive: the implementation is a token rewrite (src/hoodscript/transpiler.py)
|
|
3
|
+
plus the pattern rules R1–R12 (src/hoodscript/patterns.py), not a parser.
|
|
4
|
+
This file is extracted verbatim from GRAMMAR.md; tests/test_grammar_ebnf.py
|
|
5
|
+
fails if the two drift. Edit GRAMMAR.md, then regenerate:
|
|
6
|
+
python scripts/gen_ebnf.py > docs/grammar.ebnf
|
|
7
|
+
*)
|
|
8
|
+
|
|
9
|
+
program = { statement } ;
|
|
10
|
+
|
|
11
|
+
statement = output_stmt | assignment | const_decl | func_def | class_def
|
|
12
|
+
| return_stmt | habitual_loop | continuative_loop | while_loop
|
|
13
|
+
| conditional | try_stmt | throw_stmt | import_stmt
|
|
14
|
+
| loop_control | pass_stmt | python_stmt | expr_stmt ;
|
|
15
|
+
|
|
16
|
+
output_stmt = "holla" [ expression { "," expression } | "(" [ args ] ")" ] ;
|
|
17
|
+
input_expr = "ask" ( expression | "(" [ args ] ")" ) ;
|
|
18
|
+
assignment = target "=" expression ;
|
|
19
|
+
const_decl = "BIN" IDENT "=" expression ;
|
|
20
|
+
|
|
21
|
+
func_def = [ "finna" ] "bet" IDENT "(" [ params ] ")" ":" block ;
|
|
22
|
+
return_stmt = ( "dip" | "return" ) [ expression ] ;
|
|
23
|
+
class_def = "fam" IDENT [ "(" IDENT { "," IDENT } ")" ] ":" block ;
|
|
24
|
+
|
|
25
|
+
habitual_loop = "be" target "in" expression ":" block ;
|
|
26
|
+
continuative_loop = "steady" ":" block ;
|
|
27
|
+
while_loop = "while" expression ":" block ;
|
|
28
|
+
loop_control = "skip" | "break" ;
|
|
29
|
+
pass_stmt = "chill" ;
|
|
30
|
+
|
|
31
|
+
conditional = "if" expression ":" block
|
|
32
|
+
{ "else" "if" expression ":" block }
|
|
33
|
+
[ "else" ":" block ] ;
|
|
34
|
+
|
|
35
|
+
try_stmt = "tryna" ":" block { handler } [ "regardless" ":" block ] ;
|
|
36
|
+
handler = "catch" [ expression [ "as" IDENT ] ] ":" block ;
|
|
37
|
+
throw_stmt = "throw" [ expression ] ;
|
|
38
|
+
|
|
39
|
+
import_stmt = "import" dotted [ "as" IDENT ]
|
|
40
|
+
| "from" dotted "import" IDENT { "," IDENT } ;
|
|
41
|
+
|
|
42
|
+
python_stmt = (* any Python statement: with, match, del, global, nonlocal,
|
|
43
|
+
assert, yield, decorators, comprehensions — passed through *) ;
|
|
44
|
+
|
|
45
|
+
block = INDENT { statement } DEDENT ;
|
|
46
|
+
|
|
47
|
+
expression = or_expr ;
|
|
48
|
+
or_expr = and_expr { "or" and_expr } ;
|
|
49
|
+
and_expr = not_expr { "and" not_expr } ;
|
|
50
|
+
not_expr = [ "ain't" [ "nobody" ] | "not" ] comparison ;
|
|
51
|
+
comparison = term { comp_op term } ;
|
|
52
|
+
primary = NUMBER | STRING | IDENT
|
|
53
|
+
| "cap" | "no" "cap" | "None"
|
|
54
|
+
| "it's" expression
|
|
55
|
+
| "done" expression
|
|
56
|
+
| input_expr
|
|
57
|
+
| "(" expression ")"
|
|
58
|
+
| list_lit | dict_lit | range_lit | python_expr ;
|
|
59
|
+
range_lit = expression ".." expression ;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# Stage 1: Four on the Floor
|
|
2
|
+
# Instructions: Load 16-step patterns for 'Kick' and 'Snare'.
|
|
3
|
+
|
|
4
|
+
kicks = [0, 4, 8, 12]
|
|
5
|
+
snares = [4, 12]
|
|
6
|
+
|
|
7
|
+
sequencer.load_track("Kick", kicks)
|
|
8
|
+
sequencer.load_track("Snare", snares)
|
|
9
|
+
sequencer.play()
|
|
10
|
+
holla("Classic 4-on-the-floor sequence loaded!")
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Stage 2: Trap Hat Triplets
|
|
2
|
+
# Instructions: Generate hi-hat steps combining straight 8ths and a triplet roll.
|
|
3
|
+
|
|
4
|
+
hats = []
|
|
5
|
+
# Standard 8th notes on even steps 0 to 10
|
|
6
|
+
be step in range(12):
|
|
7
|
+
if step % 2 == 0:
|
|
8
|
+
hats.append(step)
|
|
9
|
+
|
|
10
|
+
# Triplet roll on turnaround steps 12 to 15
|
|
11
|
+
be step in range(12, 16):
|
|
12
|
+
hats.append(step)
|
|
13
|
+
|
|
14
|
+
sequencer.load_track("HiHat", hats)
|
|
15
|
+
holla("Trap hats rolling across matrix: ", hats)
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Stage 3: Soul Sample Chopper
|
|
2
|
+
# Instructions: Chop 16 consecutive 1000ms slices onto pads 1 to 16, reversing every 4th pad.
|
|
3
|
+
|
|
4
|
+
be i in range(1, 17):
|
|
5
|
+
start_ms = (i - 1) * 1000
|
|
6
|
+
end_ms = i * 1000
|
|
7
|
+
mpc.chop_sample(start_ms, end_ms, i)
|
|
8
|
+
if i % 4 == 0:
|
|
9
|
+
mpc.reverse_pad(i)
|
|
10
|
+
|
|
11
|
+
holla("Vinyl chopped and reversed into 16 quantized MPC pads!")
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Stage 4: 808 Slide Calculus
|
|
2
|
+
# Instructions: Define calculate_808_glide(start_note, end_note, steps) returning linear frequency curve.
|
|
3
|
+
|
|
4
|
+
bet calculate_808_glide(start_note, end_note, steps):
|
|
5
|
+
freqs = {"C1": 32.70, "D1": 36.71, "E1": 41.20, "F1": 43.65, "G1": 49.00, "A1": 55.00}
|
|
6
|
+
f_start = freqs[start_note]
|
|
7
|
+
f_end = freqs[end_note]
|
|
8
|
+
|
|
9
|
+
result = []
|
|
10
|
+
step_delta = (f_end - f_start) / (steps - 1)
|
|
11
|
+
be i in range(steps):
|
|
12
|
+
result.append(round(f_start + (i * step_delta), 2))
|
|
13
|
+
|
|
14
|
+
dip result
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Stage 5: The Metro Drop
|
|
2
|
+
# Instructions: Assemble full track arrangement, drop producer tag, and render final WAV.
|
|
3
|
+
|
|
4
|
+
bet produce_metro_drop(mpc, sequencer, mastering):
|
|
5
|
+
mpc.set_bpm(144)
|
|
6
|
+
|
|
7
|
+
sequencer.load_track("Kick", [0, 6, 8, 14])
|
|
8
|
+
sequencer.load_track("Snare", [4, 12])
|
|
9
|
+
sequencer.load_track("808", [0, 6, 8, 14])
|
|
10
|
+
sequencer.load_track("HiHat", [0, 2, 4, 6, 8, 10, 12, 13, 14, 15])
|
|
11
|
+
|
|
12
|
+
mastering.drop_tag("metro_tag.wav", 4)
|
|
13
|
+
mastering.render_wav("hit_single_master.wav")
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# Stage 1: Grill Master Basics
|
|
2
|
+
# Instructions: Loop through all grill items, season with Lawry's, and flip twice so they are cooked!
|
|
3
|
+
|
|
4
|
+
items = grill.get_items()
|
|
5
|
+
be item in items:
|
|
6
|
+
grill.season(item, "Lawry's Seasoned Salt")
|
|
7
|
+
grill.flip(item)
|
|
8
|
+
grill.flip(item)
|
|
9
|
+
holla("Cooked to perfection: ", item)
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# Stage 2: The Potato Salad Litmus Test
|
|
2
|
+
# Instructions: Validate ingredients. Crash out with BadValueTrip if raisins are present!
|
|
3
|
+
|
|
4
|
+
bet potato_salad_check(recipe):
|
|
5
|
+
if "raisins" in recipe:
|
|
6
|
+
throw BadValueTrip("Who put raisins in Big Mama's potato salad?!")
|
|
7
|
+
else:
|
|
8
|
+
dip no cap
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Stage 4: Spades Rule Engine
|
|
2
|
+
# Instructions: Determine winning card between card1 and card2 given led_suit.
|
|
3
|
+
|
|
4
|
+
bet spades_trick_winner(led_suit, card1, card2):
|
|
5
|
+
suit1 = card1[-1]
|
|
6
|
+
suit2 = card2[-1]
|
|
7
|
+
|
|
8
|
+
if suit1 == "♠" and suit2 != "♠":
|
|
9
|
+
dip card1
|
|
10
|
+
else if suit2 == "♠" and suit1 != "♠":
|
|
11
|
+
dip card2
|
|
12
|
+
|
|
13
|
+
ranks = {"2": 2, "3": 3, "4": 4, "5": 5, "6": 6, "7": 7, "8": 8, "9": 9, "10": 10, "J": 11, "Q": 12, "K": 13, "A": 14}
|
|
14
|
+
rank1 = ranks[card1[:-1]]
|
|
15
|
+
rank2 = ranks[card2[:-1]]
|
|
16
|
+
|
|
17
|
+
if suit1 == suit2:
|
|
18
|
+
if rank1 > rank2:
|
|
19
|
+
dip card1
|
|
20
|
+
else:
|
|
21
|
+
dip card2
|
|
22
|
+
|
|
23
|
+
if suit1 == led_suit:
|
|
24
|
+
dip card1
|
|
25
|
+
else:
|
|
26
|
+
dip card2
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Stage 5: The Unbeatable Partner
|
|
2
|
+
# Instructions: Count books, bid a Boston (13), and play all winning cards in sequence!
|
|
3
|
+
|
|
4
|
+
bet autonomous_spades_partner(spades):
|
|
5
|
+
books = spades.count_books()
|
|
6
|
+
spades.bid(13)
|
|
7
|
+
|
|
8
|
+
hand = spades.get_hand()
|
|
9
|
+
be c in hand:
|
|
10
|
+
if spades.verify_renege(c) == cap:
|
|
11
|
+
spades.play_card(c)
|
|
12
|
+
|
|
13
|
+
dip 13
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Stage 1: Drop Monitor
|
|
2
|
+
# Instructions: Check stock. When available, solve captcha and checkout!
|
|
3
|
+
|
|
4
|
+
bet monitor_and_cop(bot, sku):
|
|
5
|
+
stock = bot.listen_drop(sku)
|
|
6
|
+
if stock > 0:
|
|
7
|
+
bot.solve_captcha("TOKEN_X77")
|
|
8
|
+
billing = {"card_num": "4111222233334444", "cvv": "123"}
|
|
9
|
+
bot.add_to_cart(sku, 10.5)
|
|
10
|
+
bot.checkout(billing)
|
|
11
|
+
dip no cap
|
|
12
|
+
else:
|
|
13
|
+
dip cap
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Stage 2: Legit Check AI
|
|
2
|
+
# Instructions: Inspect each shoe ledger and collect all authentic pairs.
|
|
3
|
+
|
|
4
|
+
bet filter_authentic_kicks(shoes):
|
|
5
|
+
legit_pairs = []
|
|
6
|
+
be s in shoes:
|
|
7
|
+
is_density_valid = s["stitch_density"] >= 8.5
|
|
8
|
+
is_uv_valid = s["uv_box_stamp"] == no cap
|
|
9
|
+
is_sku_valid = s["sku_label_matches"] == no cap
|
|
10
|
+
|
|
11
|
+
if is_density_valid and is_uv_valid and is_sku_valid:
|
|
12
|
+
legit_pairs.append(s)
|
|
13
|
+
|
|
14
|
+
dip legit_pairs
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# Stage 3: Anti-Rate Limit Backoff
|
|
2
|
+
# Instructions: Query endpoint with retry loop catching RateLimitError with increasing delays.
|
|
3
|
+
|
|
4
|
+
bet fetch_with_backoff(endpoint, sku, max_retries):
|
|
5
|
+
delay = 0.01
|
|
6
|
+
be attempt_num in range(max_retries):
|
|
7
|
+
tryna:
|
|
8
|
+
dip endpoint.query_stock(sku)
|
|
9
|
+
catch:
|
|
10
|
+
delay = delay * 2
|
|
11
|
+
|
|
12
|
+
dip None
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Stage 4: Asynchronous Multi-Cart Engine
|
|
2
|
+
# Instructions: Add all target sizes to cart, solve captcha, and checkout.
|
|
3
|
+
|
|
4
|
+
bet multi_cart_cop(bot, sku, sizes):
|
|
5
|
+
be s in sizes:
|
|
6
|
+
bot.add_to_cart(sku, s)
|
|
7
|
+
|
|
8
|
+
bot.solve_captcha("CAPTCHA_FAST_PASS")
|
|
9
|
+
billing = {"card_num": "5500112233445566", "cvv": "999"}
|
|
10
|
+
bot.checkout(billing)
|
|
11
|
+
dip no cap
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# Stage 5: The 3-Way Grail Trade
|
|
2
|
+
# Instructions: Trace the trade dependencies from starting item to target grail.
|
|
3
|
+
|
|
4
|
+
bet solve_grail_trade_cycle(traders, start_item, target_grail):
|
|
5
|
+
cycle = []
|
|
6
|
+
current_item = start_item
|
|
7
|
+
|
|
8
|
+
be _ in range(len(traders)):
|
|
9
|
+
be name in traders:
|
|
10
|
+
t = traders[name]
|
|
11
|
+
if t["has"] == current_item:
|
|
12
|
+
cycle.append(name)
|
|
13
|
+
current_item = t["wants"]
|
|
14
|
+
break
|
|
15
|
+
|
|
16
|
+
dip cycle
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Level 3: Field of 9
|
|
2
|
+
# Instructions: Nested loops to traverse and harvest 3x3 grid.
|
|
3
|
+
|
|
4
|
+
be y in range(3):
|
|
5
|
+
be x in range(3):
|
|
6
|
+
bot.harvest()
|
|
7
|
+
if x < 2:
|
|
8
|
+
bot.move("east")
|
|
9
|
+
if y < 2:
|
|
10
|
+
bot.move("south")
|
|
11
|
+
bot.move("west")
|
|
12
|
+
bot.move("west")
|
|
13
|
+
|
|
14
|
+
holla("3x3 field cleared!")
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Level 4: Weed Control
|
|
2
|
+
# Instructions: Inspect soil. If weed, till it; otherwise harvest mature hay!
|
|
3
|
+
|
|
4
|
+
be y in range(4):
|
|
5
|
+
be x in range(4):
|
|
6
|
+
ground = bot.inspect_ground()
|
|
7
|
+
if ground["is_weed"]:
|
|
8
|
+
bot.till()
|
|
9
|
+
else:
|
|
10
|
+
bot.harvest()
|
|
11
|
+
if x < 3:
|
|
12
|
+
bot.move("east")
|
|
13
|
+
if y < 3:
|
|
14
|
+
bot.move("south")
|
|
15
|
+
be _ in range(3):
|
|
16
|
+
bot.move("west")
|
|
17
|
+
|
|
18
|
+
holla("Level 4 weed control completed!")
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Level 5: Smart Irrigation & Soil
|
|
2
|
+
# Instructions: Till, hydrate, and plant carrots, then harvest once mature.
|
|
3
|
+
|
|
4
|
+
bet prepare_and_plant():
|
|
5
|
+
bot.till()
|
|
6
|
+
bot.water(0.40)
|
|
7
|
+
bot.plant("carrot")
|
|
8
|
+
|
|
9
|
+
# Step 1: Prepare and seed the 4x4 field
|
|
10
|
+
be y in range(4):
|
|
11
|
+
be x in range(4):
|
|
12
|
+
prepare_and_plant()
|
|
13
|
+
if x < 3:
|
|
14
|
+
bot.move("east")
|
|
15
|
+
if y < 3:
|
|
16
|
+
bot.move("south")
|
|
17
|
+
be _ in range(3):
|
|
18
|
+
bot.move("west")
|
|
19
|
+
|
|
20
|
+
# Step 2: Return drone to top-left (0, 0)
|
|
21
|
+
be _ in range(3):
|
|
22
|
+
bot.move("west")
|
|
23
|
+
bot.move("north")
|
|
24
|
+
|
|
25
|
+
# Step 3: Harvest all carrots once mature
|
|
26
|
+
be y in range(4):
|
|
27
|
+
be x in range(4):
|
|
28
|
+
while cap == bot.inspect_ground()["is_mature"]:
|
|
29
|
+
bot.water(0.1)
|
|
30
|
+
bot.harvest()
|
|
31
|
+
if x < 3:
|
|
32
|
+
bot.move("east")
|
|
33
|
+
if y < 3:
|
|
34
|
+
bot.move("south")
|
|
35
|
+
be _ in range(3):
|
|
36
|
+
bot.move("west")
|
|
37
|
+
|
|
38
|
+
holla("All 16 carrots harvested!")
|