c64-kb 0.17.0
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.
- package/CHANGELOG.md +2082 -0
- package/LICENSE +29 -0
- package/README.md +559 -0
- package/VERSION +25 -0
- package/dist/cli/setup.js +66 -0
- package/dist/cli/setup.js.map +1 -0
- package/dist/cli-memorize-audit.js +97 -0
- package/dist/cli-memorize-audit.js.map +1 -0
- package/dist/cli.js +335 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.js +83 -0
- package/dist/config.js.map +1 -0
- package/dist/context.js +53 -0
- package/dist/context.js.map +1 -0
- package/dist/domain/budget-notes.js +104 -0
- package/dist/domain/budget-notes.js.map +1 -0
- package/dist/domain/budget.js +417 -0
- package/dist/domain/budget.js.map +1 -0
- package/dist/domain/game-design.js +77 -0
- package/dist/domain/game-design.js.map +1 -0
- package/dist/domain/timing.js +39 -0
- package/dist/domain/timing.js.map +1 -0
- package/dist/graph/apply.js +132 -0
- package/dist/graph/apply.js.map +1 -0
- package/dist/graph/claims.js +231 -0
- package/dist/graph/claims.js.map +1 -0
- package/dist/graph/extract/archetype.js +118 -0
- package/dist/graph/extract/archetype.js.map +1 -0
- package/dist/graph/extract/common.js +69 -0
- package/dist/graph/extract/common.js.map +1 -0
- package/dist/graph/extract/failure.js +37 -0
- package/dist/graph/extract/failure.js.map +1 -0
- package/dist/graph/extract/game-design.js +189 -0
- package/dist/graph/extract/game-design.js.map +1 -0
- package/dist/graph/extract/hardware.js +124 -0
- package/dist/graph/extract/hardware.js.map +1 -0
- package/dist/graph/extract/pitfall.js +62 -0
- package/dist/graph/extract/pitfall.js.map +1 -0
- package/dist/graph/extract/raster-band.js +56 -0
- package/dist/graph/extract/raster-band.js.map +1 -0
- package/dist/graph/extract/recipe.js +71 -0
- package/dist/graph/extract/recipe.js.map +1 -0
- package/dist/graph/extract/technique-entities.js +180 -0
- package/dist/graph/extract/technique-entities.js.map +1 -0
- package/dist/graph/extract/technique.js +179 -0
- package/dist/graph/extract/technique.js.map +1 -0
- package/dist/graph/extract/toolchain.js +67 -0
- package/dist/graph/extract/toolchain.js.map +1 -0
- package/dist/graph/extract/types.js +3 -0
- package/dist/graph/extract/types.js.map +1 -0
- package/dist/graph/extract/vocabulary.js +65 -0
- package/dist/graph/extract/vocabulary.js.map +1 -0
- package/dist/graph/extract.js +43 -0
- package/dist/graph/extract.js.map +1 -0
- package/dist/graph/kernal-clobbers.js +64 -0
- package/dist/graph/kernal-clobbers.js.map +1 -0
- package/dist/graph/machine-variants.js +208 -0
- package/dist/graph/machine-variants.js.map +1 -0
- package/dist/ingest/files.js +99 -0
- package/dist/ingest/files.js.map +1 -0
- package/dist/ingest/passes.js +104 -0
- package/dist/ingest/passes.js.map +1 -0
- package/dist/ingest/points.js +50 -0
- package/dist/ingest/points.js.map +1 -0
- package/dist/ingest/report.js +140 -0
- package/dist/ingest/report.js.map +1 -0
- package/dist/ingest/tally.js +81 -0
- package/dist/ingest/tally.js.map +1 -0
- package/dist/ingest/verified-on.js +43 -0
- package/dist/ingest/verified-on.js.map +1 -0
- package/dist/ingest.js +135 -0
- package/dist/ingest.js.map +1 -0
- package/dist/schemas/cost-basis.js +5 -0
- package/dist/schemas/cost-basis.js.map +1 -0
- package/dist/schemas/machine-variant.js +25 -0
- package/dist/schemas/machine-variant.js.map +1 -0
- package/dist/schemas/plan-budget.js +121 -0
- package/dist/schemas/plan-budget.js.map +1 -0
- package/dist/schemas/tool-outputs.js +526 -0
- package/dist/schemas/tool-outputs.js.map +1 -0
- package/dist/server/define-tool.js +52 -0
- package/dist/server/define-tool.js.map +1 -0
- package/dist/server/defined-only.js +9 -0
- package/dist/server/defined-only.js.map +1 -0
- package/dist/server/tools-briefings.js +70 -0
- package/dist/server/tools-briefings.js.map +1 -0
- package/dist/server/tools-lookup.js +180 -0
- package/dist/server/tools-lookup.js.map +1 -0
- package/dist/server/tools-maintenance.js +116 -0
- package/dist/server/tools-maintenance.js.map +1 -0
- package/dist/server/tools-pitfalls.js +89 -0
- package/dist/server/tools-pitfalls.js.map +1 -0
- package/dist/server/tools-recipes.js +296 -0
- package/dist/server/tools-recipes.js.map +1 -0
- package/dist/server/tools-runtime.js +48 -0
- package/dist/server/tools-runtime.js.map +1 -0
- package/dist/server/tools.js +43 -0
- package/dist/server/tools.js.map +1 -0
- package/dist/server.js +95 -0
- package/dist/server.js.map +1 -0
- package/dist/services/analytics/schema.js +78 -0
- package/dist/services/analytics/schema.js.map +1 -0
- package/dist/services/analytics/statements.js +99 -0
- package/dist/services/analytics/statements.js.map +1 -0
- package/dist/services/analytics.js +195 -0
- package/dist/services/analytics.js.map +1 -0
- package/dist/services/bm25.js +158 -0
- package/dist/services/bm25.js.map +1 -0
- package/dist/services/chunker.js +81 -0
- package/dist/services/chunker.js.map +1 -0
- package/dist/services/embeddings.js +58 -0
- package/dist/services/embeddings.js.map +1 -0
- package/dist/services/falkor/base.js +85 -0
- package/dist/services/falkor/base.js.map +1 -0
- package/dist/services/falkor/links.js +361 -0
- package/dist/services/falkor/links.js.map +1 -0
- package/dist/services/falkor/nodes.js +183 -0
- package/dist/services/falkor/nodes.js.map +1 -0
- package/dist/services/falkor/params.js +45 -0
- package/dist/services/falkor/params.js.map +1 -0
- package/dist/services/falkor/schema.js +77 -0
- package/dist/services/falkor/schema.js.map +1 -0
- package/dist/services/falkor.js +100 -0
- package/dist/services/falkor.js.map +1 -0
- package/dist/services/qdrant.js +238 -0
- package/dist/services/qdrant.js.map +1 -0
- package/dist/services/versions.js +73 -0
- package/dist/services/versions.js.map +1 -0
- package/dist/services/vice-bin.js +51 -0
- package/dist/services/vice-bin.js.map +1 -0
- package/dist/tools/briefings/archetype.js +174 -0
- package/dist/tools/briefings/archetype.js.map +1 -0
- package/dist/tools/briefings/budget.js +177 -0
- package/dist/tools/briefings/budget.js.map +1 -0
- package/dist/tools/briefings/build-order.js +135 -0
- package/dist/tools/briefings/build-order.js.map +1 -0
- package/dist/tools/briefings/build.js +185 -0
- package/dist/tools/briefings/build.js.map +1 -0
- package/dist/tools/briefings/discovery.js +290 -0
- package/dist/tools/briefings/discovery.js.map +1 -0
- package/dist/tools/briefings/plan-pitfalls.js +69 -0
- package/dist/tools/briefings/plan-pitfalls.js.map +1 -0
- package/dist/tools/briefings/render.js +151 -0
- package/dist/tools/briefings/render.js.map +1 -0
- package/dist/tools/briefings/rows.js +41 -0
- package/dist/tools/briefings/rows.js.map +1 -0
- package/dist/tools/briefings/toolchain.js +63 -0
- package/dist/tools/briefings/toolchain.js.map +1 -0
- package/dist/tools/briefings/why-proposed.js +69 -0
- package/dist/tools/briefings/why-proposed.js.map +1 -0
- package/dist/tools/briefings.js +44 -0
- package/dist/tools/briefings.js.map +1 -0
- package/dist/tools/feedback.js +97 -0
- package/dist/tools/feedback.js.map +1 -0
- package/dist/tools/hydrate.js +75 -0
- package/dist/tools/hydrate.js.map +1 -0
- package/dist/tools/intelligence.js +67 -0
- package/dist/tools/intelligence.js.map +1 -0
- package/dist/tools/lint/asm-decimal.js +86 -0
- package/dist/tools/lint/asm-decimal.js.map +1 -0
- package/dist/tools/lint/asm-rules.js +221 -0
- package/dist/tools/lint/asm-rules.js.map +1 -0
- package/dist/tools/lint/asm-shared.js +3 -0
- package/dist/tools/lint/asm-shared.js.map +1 -0
- package/dist/tools/lint/c-rules.js +215 -0
- package/dist/tools/lint/c-rules.js.map +1 -0
- package/dist/tools/lint/text.js +122 -0
- package/dist/tools/lint/text.js.map +1 -0
- package/dist/tools/lint/types.js +40 -0
- package/dist/tools/lint/types.js.map +1 -0
- package/dist/tools/lint.js +76 -0
- package/dist/tools/lint.js.map +1 -0
- package/dist/tools/memorization-mcp.js +111 -0
- package/dist/tools/memorization-mcp.js.map +1 -0
- package/dist/tools/pitfalls/bm25.js +53 -0
- package/dist/tools/pitfalls/bm25.js.map +1 -0
- package/dist/tools/pitfalls/format.js +58 -0
- package/dist/tools/pitfalls/format.js.map +1 -0
- package/dist/tools/pitfalls/graph.js +124 -0
- package/dist/tools/pitfalls/graph.js.map +1 -0
- package/dist/tools/pitfalls.js +134 -0
- package/dist/tools/pitfalls.js.map +1 -0
- package/dist/tools/prompts.js +81 -0
- package/dist/tools/prompts.js.map +1 -0
- package/dist/tools/query/compatibility/closure.js +62 -0
- package/dist/tools/query/compatibility/closure.js.map +1 -0
- package/dist/tools/query/compatibility/facts.js +28 -0
- package/dist/tools/query/compatibility/facts.js.map +1 -0
- package/dist/tools/query/compatibility/fetch.js +164 -0
- package/dist/tools/query/compatibility/fetch.js.map +1 -0
- package/dist/tools/query/compatibility/hard-rules.js +159 -0
- package/dist/tools/query/compatibility/hard-rules.js.map +1 -0
- package/dist/tools/query/compatibility/index.js +27 -0
- package/dist/tools/query/compatibility/index.js.map +1 -0
- package/dist/tools/query/compatibility/kernal-zp-rule.js +90 -0
- package/dist/tools/query/compatibility/kernal-zp-rule.js.map +1 -0
- package/dist/tools/query/compatibility/render.js +106 -0
- package/dist/tools/query/compatibility/render.js.map +1 -0
- package/dist/tools/query/compatibility/rules.js +337 -0
- package/dist/tools/query/compatibility/rules.js.map +1 -0
- package/dist/tools/query/compatibility/unit-rules.js +253 -0
- package/dist/tools/query/compatibility/unit-rules.js.map +1 -0
- package/dist/tools/query/game-design.js +83 -0
- package/dist/tools/query/game-design.js.map +1 -0
- package/dist/tools/query/lookups.js +220 -0
- package/dist/tools/query/lookups.js.map +1 -0
- package/dist/tools/query/plan-budget.js +266 -0
- package/dist/tools/query/plan-budget.js.map +1 -0
- package/dist/tools/query/recipes.js +214 -0
- package/dist/tools/query/recipes.js.map +1 -0
- package/dist/tools/query/retrieval.js +128 -0
- package/dist/tools/query/retrieval.js.map +1 -0
- package/dist/tools/query/shared.js +121 -0
- package/dist/tools/query/shared.js.map +1 -0
- package/dist/tools/query/techniques.js +331 -0
- package/dist/tools/query/techniques.js.map +1 -0
- package/dist/tools/query/timing.js +106 -0
- package/dist/tools/query/timing.js.map +1 -0
- package/dist/tools/query/types.js +11 -0
- package/dist/tools/query/types.js.map +1 -0
- package/dist/tools/query.js +21 -0
- package/dist/tools/query.js.map +1 -0
- package/dist/tools/resources.js +186 -0
- package/dist/tools/resources.js.map +1 -0
- package/dist/tools/run-game.js +249 -0
- package/dist/tools/run-game.js.map +1 -0
- package/dist/tools/selfimprovement.js +367 -0
- package/dist/tools/selfimprovement.js.map +1 -0
- package/docker-compose.yml +35 -0
- package/docs/ARCHITECTURE.md +164 -0
- package/docs/CONVENTIONS-archetypes.md +158 -0
- package/docs/CONVENTIONS-failures.md +46 -0
- package/docs/CONVENTIONS-game-designs.md +75 -0
- package/docs/CONVENTIONS-hardware-reference.md +184 -0
- package/docs/CONVENTIONS-pitfalls.md +91 -0
- package/docs/CONVENTIONS-recipes.md +106 -0
- package/docs/CONVENTIONS-techniques.md +309 -0
- package/docs/CONVENTIONS-toolchain-reference.md +89 -0
- package/docs/ONTOLOGY.md +655 -0
- package/docs/art/art-production-reference.md +157 -0
- package/docs/art/asset-pipelines.md +586 -0
- package/docs/c64-failure-patterns.md +693 -0
- package/docs/demo-design/demo-composition.md +349 -0
- package/docs/demo-design/demo-design-philosophy.md +320 -0
- package/docs/demo-design/intro-cracktro-patterns.md +435 -0
- package/docs/figures/ctm-spd-embed-probe.png +0 -0
- package/docs/figures/dot-flag-mid-5000000.png +0 -0
- package/docs/figures/dot-flag-no-erase-12000000.png +0 -0
- package/docs/figures/edges.json +1 -0
- package/docs/figures/fig6-architecture.png +0 -0
- package/docs/figures/fig7-ontology.png +0 -0
- package/docs/figures/screen-dissolve-mid-frame25.png +0 -0
- package/docs/figures/screen-dissolve-wipe-frame25.png +0 -0
- package/docs/figures/spindle-two-parts-part1.png +0 -0
- package/docs/figures/spindle-two-parts-part2.png +0 -0
- package/docs/figures/starters/action-puzzle.png +0 -0
- package/docs/figures/starters/adventure.png +0 -0
- package/docs/figures/starters/beat-em-up.png +0 -0
- package/docs/figures/starters/demo.png +0 -0
- package/docs/figures/starters/platformer.png +0 -0
- package/docs/figures/starters/shmup-vertical.png +0 -0
- package/docs/figures/tape-kernal-master-ntsc.png +0 -0
- package/docs/figures/tape-kernal-master-pal.png +0 -0
- package/docs/figures/tape-turbo-loader-ntsc.png +0 -0
- package/docs/figures/tape-turbo-loader-pal.png +0 -0
- package/docs/figures/tape-turbo-master-ntsc.png +0 -0
- package/docs/figures/tape-turbo-master-pal.png +0 -0
- package/docs/figures/tech-tech-pad2-12000000.png +0 -0
- package/docs/figures/tech-tech-pad4-12000000.png +0 -0
- package/docs/figures/tech-tech-seven-12000000.png +0 -0
- package/docs/figures/twister-mid-5000000.png +0 -0
- package/docs/figures/twister-straight-12000000.png +0 -0
- package/docs/figures/vector-balls-nosort-ntsc.png +0 -0
- package/docs/figures/vector-balls-nosort.png +0 -0
- package/docs/formats/c64-file-formats.md +1212 -0
- package/docs/formats/iec-disk-reference.md +754 -0
- package/docs/game-design/c64-game-archetypes.md +273 -0
- package/docs/game-design/designs/falling-blocks.md +54 -0
- package/docs/game-design/designs/platformer-scaffold.md +48 -0
- package/docs/game-design/designs/simple-shmup.md +27 -0
- package/docs/game-design/enemy-behaviour-and-difficulty.md +349 -0
- package/docs/game-design/game-design-patterns.md +1189 -0
- package/docs/game-design/game-structure.md +354 -0
- package/docs/game-design/production-planning.md +349 -0
- package/docs/game-design/reference-game-sources.md +90 -0
- package/docs/hardware/6502-illegal-opcodes.md +1353 -0
- package/docs/hardware/6510-cpu-reference.md +2112 -0
- package/docs/hardware/c64-memory-map.md +3184 -0
- package/docs/hardware/c64-registers-reference.md +996 -0
- package/docs/hardware/cia-reference.md +1281 -0
- package/docs/hardware/kernal-routines-reference.md +1836 -0
- package/docs/hardware/pal-ntsc-reference.md +813 -0
- package/docs/hardware/sid-reference.md +1137 -0
- package/docs/hardware/vic-ii-reference.md +1714 -0
- package/docs/music/music-production-reference.md +403 -0
- package/docs/pitfalls/banking.md +1067 -0
- package/docs/pitfalls/cia.md +1147 -0
- package/docs/pitfalls/cpu.md +874 -0
- package/docs/pitfalls/input.md +282 -0
- package/docs/pitfalls/kernal-and-io.md +1615 -0
- package/docs/pitfalls/loader.md +1191 -0
- package/docs/pitfalls/logic.md +94 -0
- package/docs/pitfalls/maths.md +187 -0
- package/docs/pitfalls/raster-and-badline.md +721 -0
- package/docs/pitfalls/region-timing.md +660 -0
- package/docs/pitfalls/scroll.md +207 -0
- package/docs/pitfalls/sid.md +738 -0
- package/docs/pitfalls/sprite.md +979 -0
- package/docs/pitfalls/text-mode-render.md +1172 -0
- package/docs/recipes/cc65/cartridge-8k.md +398 -0
- package/docs/recipes/cc65/hello-world-conio.md +76 -0
- package/docs/recipes/cc65/memory-layout.md +312 -0
- package/docs/recipes/cc65/screenshots/README.md +14 -0
- package/docs/recipes/cc65/screenshots/cartridge-8k-ntsc.png +0 -0
- package/docs/recipes/cc65/screenshots/cartridge-8k.png +0 -0
- package/docs/recipes/cc65/screenshots/hello-world-conio.png +0 -0
- package/docs/recipes/cc65/screenshots/memory-layout-ntsc.png +0 -0
- package/docs/recipes/cc65/screenshots/memory-layout.png +0 -0
- package/docs/recipes/kickassembler/basic-float-calls.md +578 -0
- package/docs/recipes/kickassembler/basic-wedge.md +398 -0
- package/docs/recipes/kickassembler/big-font-scroller.md +620 -0
- package/docs/recipes/kickassembler/charset-copy-rom-to-ram.md +623 -0
- package/docs/recipes/kickassembler/cia-revision-detect.md +366 -0
- package/docs/recipes/kickassembler/colour-cycling.md +343 -0
- package/docs/recipes/kickassembler/colour-fade.md +303 -0
- package/docs/recipes/kickassembler/compare-16bit-signed.md +1007 -0
- package/docs/recipes/kickassembler/cracktro-template.md +526 -0
- package/docs/recipes/kickassembler/crt-banked.md +276 -0
- package/docs/recipes/kickassembler/dos-error-codes.md +466 -0
- package/docs/recipes/kickassembler/dot-flag.md +576 -0
- package/docs/recipes/kickassembler/drive-job-queue.md +667 -0
- package/docs/recipes/kickassembler/drive-via-probe.md +690 -0
- package/docs/recipes/kickassembler/dycp-scroller.md +568 -0
- package/docs/recipes/kickassembler/dypp-sprite-scroller.md +681 -0
- package/docs/recipes/kickassembler/dysp.md +670 -0
- package/docs/recipes/kickassembler/easyflash-save.md +800 -0
- package/docs/recipes/kickassembler/eight-way-scroll.md +1484 -0
- package/docs/recipes/kickassembler/file-io-roundtrip.md +546 -0
- package/docs/recipes/kickassembler/fire-effect.md +420 -0
- package/docs/recipes/kickassembler/fld.md +414 -0
- package/docs/recipes/kickassembler/fli-image.md +336 -0
- package/docs/recipes/kickassembler/four-player-read.md +672 -0
- package/docs/recipes/kickassembler/headless-verify.md +228 -0
- package/docs/recipes/kickassembler/hello-world.md +98 -0
- package/docs/recipes/kickassembler/high-score-insert.md +660 -0
- package/docs/recipes/kickassembler/hires-plot-line.md +723 -0
- package/docs/recipes/kickassembler/irq-chain.md +316 -0
- package/docs/recipes/kickassembler/irq-owns-port.md +668 -0
- package/docs/recipes/kickassembler/isometric-room.md +1145 -0
- package/docs/recipes/kickassembler/light-pen-read.md +926 -0
- package/docs/recipes/kickassembler/logic-rate-decoupling.md +670 -0
- package/docs/recipes/kickassembler/mci-interlace.md +543 -0
- package/docs/recipes/kickassembler/memory-layout.md +277 -0
- package/docs/recipes/kickassembler/mouse-1351-read.md +801 -0
- package/docs/recipes/kickassembler/nmi-timer-tick.md +562 -0
- package/docs/recipes/kickassembler/own-keyscan.md +881 -0
- package/docs/recipes/kickassembler/paddle-read.md +751 -0
- package/docs/recipes/kickassembler/palette-cells.md +219 -0
- package/docs/recipes/kickassembler/pseudo-3d-road.md +930 -0
- package/docs/recipes/kickassembler/pwm-digi.md +463 -0
- package/docs/recipes/kickassembler/raster-bars.md +264 -0
- package/docs/recipes/kickassembler/reu-dma.md +1019 -0
- package/docs/recipes/kickassembler/runtime-relocation.md +743 -0
- package/docs/recipes/kickassembler/screen-dissolve.md +545 -0
- package/docs/recipes/kickassembler/screen-wipe.md +408 -0
- package/docs/recipes/kickassembler/screenshots/README.md +72 -0
- package/docs/recipes/kickassembler/screenshots/basic-float-calls-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/basic-float-calls.png +0 -0
- package/docs/recipes/kickassembler/screenshots/basic-wedge-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/basic-wedge.png +0 -0
- package/docs/recipes/kickassembler/screenshots/big-font-scroller-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/big-font-scroller.png +0 -0
- package/docs/recipes/kickassembler/screenshots/charset-copy-rom-to-ram-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/charset-copy-rom-to-ram.png +0 -0
- package/docs/recipes/kickassembler/screenshots/cia-revision-detect-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/cia-revision-detect.png +0 -0
- package/docs/recipes/kickassembler/screenshots/colour-cycling-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/colour-cycling.png +0 -0
- package/docs/recipes/kickassembler/screenshots/colour-fade-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/colour-fade.png +0 -0
- package/docs/recipes/kickassembler/screenshots/compare-16bit-signed-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/compare-16bit-signed.png +0 -0
- package/docs/recipes/kickassembler/screenshots/cracktro-template.png +0 -0
- package/docs/recipes/kickassembler/screenshots/crt-banked-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/crt-banked.png +0 -0
- package/docs/recipes/kickassembler/screenshots/dos-error-codes-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/dos-error-codes.png +0 -0
- package/docs/recipes/kickassembler/screenshots/dot-flag-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/dot-flag.png +0 -0
- package/docs/recipes/kickassembler/screenshots/drive-job-queue-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/drive-job-queue.png +0 -0
- package/docs/recipes/kickassembler/screenshots/drive-via-probe-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/drive-via-probe.png +0 -0
- package/docs/recipes/kickassembler/screenshots/dycp-scroller-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/dycp-scroller.png +0 -0
- package/docs/recipes/kickassembler/screenshots/dypp-sprite-scroller-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/dypp-sprite-scroller.png +0 -0
- package/docs/recipes/kickassembler/screenshots/dysp-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/dysp.png +0 -0
- package/docs/recipes/kickassembler/screenshots/easyflash-save-ntsc-run2.png +0 -0
- package/docs/recipes/kickassembler/screenshots/easyflash-save-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/easyflash-save-run2.png +0 -0
- package/docs/recipes/kickassembler/screenshots/easyflash-save.png +0 -0
- package/docs/recipes/kickassembler/screenshots/eight-way-scroll-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/eight-way-scroll.png +0 -0
- package/docs/recipes/kickassembler/screenshots/file-io-roundtrip-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/file-io-roundtrip.png +0 -0
- package/docs/recipes/kickassembler/screenshots/fire-effect-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/fire-effect.png +0 -0
- package/docs/recipes/kickassembler/screenshots/fld-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/fld.png +0 -0
- package/docs/recipes/kickassembler/screenshots/fli-image.png +0 -0
- package/docs/recipes/kickassembler/screenshots/four-player-read-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/four-player-read.png +0 -0
- package/docs/recipes/kickassembler/screenshots/headless-verify-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/headless-verify.png +0 -0
- package/docs/recipes/kickassembler/screenshots/hello-world.png +0 -0
- package/docs/recipes/kickassembler/screenshots/high-score-insert-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/high-score-insert.png +0 -0
- package/docs/recipes/kickassembler/screenshots/hires-plot-line-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/hires-plot-line.png +0 -0
- package/docs/recipes/kickassembler/screenshots/irq-chain-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/irq-chain.png +0 -0
- package/docs/recipes/kickassembler/screenshots/irq-owns-port-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/irq-owns-port.png +0 -0
- package/docs/recipes/kickassembler/screenshots/isometric-room-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/isometric-room.png +0 -0
- package/docs/recipes/kickassembler/screenshots/light-pen-read-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/light-pen-read.png +0 -0
- package/docs/recipes/kickassembler/screenshots/logic-rate-decoupling-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/logic-rate-decoupling.png +0 -0
- package/docs/recipes/kickassembler/screenshots/mci-interlace-average.png +0 -0
- package/docs/recipes/kickassembler/screenshots/mci-interlace-frame-b.png +0 -0
- package/docs/recipes/kickassembler/screenshots/mci-interlace-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/mci-interlace.png +0 -0
- package/docs/recipes/kickassembler/screenshots/memory-layout-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/memory-layout.png +0 -0
- package/docs/recipes/kickassembler/screenshots/mouse-1351-read-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/mouse-1351-read.png +0 -0
- package/docs/recipes/kickassembler/screenshots/nmi-timer-tick-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/nmi-timer-tick.png +0 -0
- package/docs/recipes/kickassembler/screenshots/own-keyscan-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/own-keyscan.png +0 -0
- package/docs/recipes/kickassembler/screenshots/paddle-read-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/paddle-read.png +0 -0
- package/docs/recipes/kickassembler/screenshots/palette-cells-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/palette-cells.png +0 -0
- package/docs/recipes/kickassembler/screenshots/pseudo-3d-road-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/pseudo-3d-road.png +0 -0
- package/docs/recipes/kickassembler/screenshots/pwm-digi-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/pwm-digi.png +0 -0
- package/docs/recipes/kickassembler/screenshots/raster-bars.png +0 -0
- package/docs/recipes/kickassembler/screenshots/reu-dma-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/reu-dma.png +0 -0
- package/docs/recipes/kickassembler/screenshots/runtime-relocation-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/runtime-relocation.png +0 -0
- package/docs/recipes/kickassembler/screenshots/screen-dissolve-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/screen-dissolve.png +0 -0
- package/docs/recipes/kickassembler/screenshots/screen-wipe-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/screen-wipe.png +0 -0
- package/docs/recipes/kickassembler/screenshots/scroll-panel-split-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/scroll-panel-split.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sfx-in-player-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sfx-in-player.png +0 -0
- package/docs/recipes/kickassembler/screenshots/shadebobs-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/shadebobs.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sideborder-open.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sine-scroller.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sine-table-runtime-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sine-table-runtime.png +0 -0
- package/docs/recipes/kickassembler/screenshots/software-sprite-preshifted-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/software-sprite-preshifted.png +0 -0
- package/docs/recipes/kickassembler/screenshots/speedcode-generator-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/speedcode-generator.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sprite-border-scroller-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sprite-border-scroller.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sprite-cache-flip-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sprite-cache-flip.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sprite-multiplex-24.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sprite-multiplex-game-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sprite-multiplex-game.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sprite-priority-classes-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sprite-priority-classes.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sprite-sine-chain-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sprite-sine-chain.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sprite-stretcher-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sprite-stretcher.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sprites-only-screen-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sprites-only-screen.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sqrt-atan2-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sqrt-atan2.png +0 -0
- package/docs/recipes/kickassembler/screenshots/stable-raster-irq-control.png +0 -0
- package/docs/recipes/kickassembler/screenshots/stable-raster-irq.png +0 -0
- package/docs/recipes/kickassembler/screenshots/tech-tech-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/tech-tech.png +0 -0
- package/docs/recipes/kickassembler/screenshots/tod-alarm-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/tod-alarm.png +0 -0
- package/docs/recipes/kickassembler/screenshots/topbottom-border-open.png +0 -0
- package/docs/recipes/kickassembler/screenshots/twister-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/twister.png +0 -0
- package/docs/recipes/kickassembler/screenshots/unit-test-driver-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/unit-test-driver.png +0 -0
- package/docs/recipes/kickassembler/screenshots/vector-balls-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/vector-balls.png +0 -0
- package/docs/recipes/kickassembler/screenshots/wireframe-ships-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/wireframe-ships.png +0 -0
- package/docs/recipes/kickassembler/scroll-panel-split.md +381 -0
- package/docs/recipes/kickassembler/sfx-in-player.md +907 -0
- package/docs/recipes/kickassembler/shadebobs.md +522 -0
- package/docs/recipes/kickassembler/sideborder-open.md +338 -0
- package/docs/recipes/kickassembler/sine-scroller.md +321 -0
- package/docs/recipes/kickassembler/sine-table-runtime.md +815 -0
- package/docs/recipes/kickassembler/software-sprite-preshifted.md +725 -0
- package/docs/recipes/kickassembler/speedcode-generator.md +606 -0
- package/docs/recipes/kickassembler/sprite-border-scroller.md +696 -0
- package/docs/recipes/kickassembler/sprite-cache-flip.md +1071 -0
- package/docs/recipes/kickassembler/sprite-multiplex-24.md +326 -0
- package/docs/recipes/kickassembler/sprite-multiplex-game.md +986 -0
- package/docs/recipes/kickassembler/sprite-priority-classes.md +463 -0
- package/docs/recipes/kickassembler/sprite-sine-chain.md +338 -0
- package/docs/recipes/kickassembler/sprite-stretcher.md +501 -0
- package/docs/recipes/kickassembler/sprites-only-screen.md +550 -0
- package/docs/recipes/kickassembler/sqrt-atan2.md +1014 -0
- package/docs/recipes/kickassembler/stable-raster-irq.md +360 -0
- package/docs/recipes/kickassembler/tape-turbo-loader.md +875 -0
- package/docs/recipes/kickassembler/tech-tech.md +679 -0
- package/docs/recipes/kickassembler/tod-alarm.md +754 -0
- package/docs/recipes/kickassembler/topbottom-border-open.md +407 -0
- package/docs/recipes/kickassembler/twister.md +518 -0
- package/docs/recipes/kickassembler/unit-test-driver.md +314 -0
- package/docs/recipes/kickassembler/vector-balls.md +545 -0
- package/docs/recipes/kickassembler/wireframe-ships.md +2324 -0
- package/docs/recipes/oscar64/actor-activation-window.md +807 -0
- package/docs/recipes/oscar64/adventure-engine.md +1094 -0
- package/docs/recipes/oscar64/attract-replay.md +465 -0
- package/docs/recipes/oscar64/beat-em-up-lanes.md +563 -0
- package/docs/recipes/oscar64/bfs-distance-map.md +723 -0
- package/docs/recipes/oscar64/bitmap-koala-viewer.md +355 -0
- package/docs/recipes/oscar64/car-contact.md +950 -0
- package/docs/recipes/oscar64/cave-scan.md +609 -0
- package/docs/recipes/oscar64/char-bullets.md +477 -0
- package/docs/recipes/oscar64/charset-animation.md +383 -0
- package/docs/recipes/oscar64/charset-parallax.md +401 -0
- package/docs/recipes/oscar64/destructible-terrain.md +1099 -0
- package/docs/recipes/oscar64/difficulty-tables.md +654 -0
- package/docs/recipes/oscar64/dig-and-guards.md +975 -0
- package/docs/recipes/oscar64/directory-reader.md +535 -0
- package/docs/recipes/oscar64/divide-check.md +581 -0
- package/docs/recipes/oscar64/double-buffer-nomirror.md +205 -0
- package/docs/recipes/oscar64/double-buffer.md +255 -0
- package/docs/recipes/oscar64/falling-blocks.md +874 -0
- package/docs/recipes/oscar64/fixed-point-jump-velocity.md +289 -0
- package/docs/recipes/oscar64/fixed-point-jump.md +210 -0
- package/docs/recipes/oscar64/flip-screen-rooms.md +793 -0
- package/docs/recipes/oscar64/frame-sync-loop-overrun.md +214 -0
- package/docs/recipes/oscar64/frame-sync-loop.md +254 -0
- package/docs/recipes/oscar64/game-tree-search.md +743 -0
- package/docs/recipes/oscar64/ghost-targeting.md +867 -0
- package/docs/recipes/oscar64/headless-verify.md +345 -0
- package/docs/recipes/oscar64/hello-world.md +83 -0
- package/docs/recipes/oscar64/high-score-persist.md +772 -0
- package/docs/recipes/oscar64/iffl-kernal-skip.md +421 -0
- package/docs/recipes/oscar64/joystick-input.md +358 -0
- package/docs/recipes/oscar64/lane-pursuit.md +1028 -0
- package/docs/recipes/oscar64/level-rle-decoder.md +620 -0
- package/docs/recipes/oscar64/lfsr-random-seed2.md +338 -0
- package/docs/recipes/oscar64/lfsr-random.md +403 -0
- package/docs/recipes/oscar64/load-asset-runtime.md +492 -0
- package/docs/recipes/oscar64/memory-layout.md +232 -0
- package/docs/recipes/oscar64/mixed-fighters.md +781 -0
- package/docs/recipes/oscar64/multi-sprite-object.md +533 -0
- package/docs/recipes/oscar64/nav-area-pathfinding.md +881 -0
- package/docs/recipes/oscar64/object-pool.md +572 -0
- package/docs/recipes/oscar64/pal-ntsc-detect.md +257 -0
- package/docs/recipes/oscar64/password-state.md +532 -0
- package/docs/recipes/oscar64/per-frame-hitbox.md +651 -0
- package/docs/recipes/oscar64/petscii-screen-codes.md +428 -0
- package/docs/recipes/oscar64/platformer-scaffold.md +1467 -0
- package/docs/recipes/oscar64/print-number.md +367 -0
- package/docs/recipes/oscar64/raster-bars.md +239 -0
- package/docs/recipes/oscar64/raster-profile-bars.md +404 -0
- package/docs/recipes/oscar64/rel-side-sectors.md +391 -0
- package/docs/recipes/oscar64/relative-file-records.md +378 -0
- package/docs/recipes/oscar64/save-load-seq-file.md +365 -0
- package/docs/recipes/oscar64/screenshots/README.md +99 -0
- package/docs/recipes/oscar64/screenshots/actor-activation-window-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/actor-activation-window.png +0 -0
- package/docs/recipes/oscar64/screenshots/adventure-engine-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/adventure-engine.png +0 -0
- package/docs/recipes/oscar64/screenshots/attract-replay-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/attract-replay.png +0 -0
- package/docs/recipes/oscar64/screenshots/beat-em-up-lanes-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/beat-em-up-lanes.png +0 -0
- package/docs/recipes/oscar64/screenshots/bfs-distance-map-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/bfs-distance-map.png +0 -0
- package/docs/recipes/oscar64/screenshots/bitmap-koala-viewer.png +0 -0
- package/docs/recipes/oscar64/screenshots/car-contact-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/car-contact.png +0 -0
- package/docs/recipes/oscar64/screenshots/cave-scan-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/cave-scan.png +0 -0
- package/docs/recipes/oscar64/screenshots/char-bullets-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/char-bullets.png +0 -0
- package/docs/recipes/oscar64/screenshots/charset-animation-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/charset-animation.png +0 -0
- package/docs/recipes/oscar64/screenshots/charset-parallax-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/charset-parallax.png +0 -0
- package/docs/recipes/oscar64/screenshots/destructible-terrain-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/destructible-terrain.png +0 -0
- package/docs/recipes/oscar64/screenshots/difficulty-tables-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/difficulty-tables.png +0 -0
- package/docs/recipes/oscar64/screenshots/dig-and-guards-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/dig-and-guards.png +0 -0
- package/docs/recipes/oscar64/screenshots/directory-reader-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/directory-reader.png +0 -0
- package/docs/recipes/oscar64/screenshots/divide-check-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/divide-check.png +0 -0
- package/docs/recipes/oscar64/screenshots/double-buffer-nomirror.png +0 -0
- package/docs/recipes/oscar64/screenshots/double-buffer-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/double-buffer.png +0 -0
- package/docs/recipes/oscar64/screenshots/falling-blocks-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/falling-blocks.png +0 -0
- package/docs/recipes/oscar64/screenshots/fixed-point-jump-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/fixed-point-jump-velocity-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/fixed-point-jump-velocity.png +0 -0
- package/docs/recipes/oscar64/screenshots/fixed-point-jump.png +0 -0
- package/docs/recipes/oscar64/screenshots/flip-screen-rooms-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/flip-screen-rooms.png +0 -0
- package/docs/recipes/oscar64/screenshots/frame-sync-loop-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/frame-sync-loop-overrun.png +0 -0
- package/docs/recipes/oscar64/screenshots/frame-sync-loop.png +0 -0
- package/docs/recipes/oscar64/screenshots/game-tree-search-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/game-tree-search.png +0 -0
- package/docs/recipes/oscar64/screenshots/ghost-targeting-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/ghost-targeting.png +0 -0
- package/docs/recipes/oscar64/screenshots/headless-verify-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/headless-verify.png +0 -0
- package/docs/recipes/oscar64/screenshots/hello-world.png +0 -0
- package/docs/recipes/oscar64/screenshots/high-score-persist-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/high-score-persist.png +0 -0
- package/docs/recipes/oscar64/screenshots/iffl-kernal-skip-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/iffl-kernal-skip.png +0 -0
- package/docs/recipes/oscar64/screenshots/joystick-input-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/joystick-input.png +0 -0
- package/docs/recipes/oscar64/screenshots/lane-pursuit-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/lane-pursuit.png +0 -0
- package/docs/recipes/oscar64/screenshots/level-rle-decoder-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/level-rle-decoder.png +0 -0
- package/docs/recipes/oscar64/screenshots/lfsr-random-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/lfsr-random-seed2.png +0 -0
- package/docs/recipes/oscar64/screenshots/lfsr-random.png +0 -0
- package/docs/recipes/oscar64/screenshots/load-asset-runtime-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/load-asset-runtime.png +0 -0
- package/docs/recipes/oscar64/screenshots/memory-layout-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/memory-layout.png +0 -0
- package/docs/recipes/oscar64/screenshots/mixed-fighters-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/mixed-fighters.png +0 -0
- package/docs/recipes/oscar64/screenshots/multi-sprite-object-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/multi-sprite-object.png +0 -0
- package/docs/recipes/oscar64/screenshots/nav-area-pathfinding-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/nav-area-pathfinding.png +0 -0
- package/docs/recipes/oscar64/screenshots/object-pool-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/object-pool.png +0 -0
- package/docs/recipes/oscar64/screenshots/pal-ntsc-detect-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/pal-ntsc-detect-oldntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/pal-ntsc-detect-pal.png +0 -0
- package/docs/recipes/oscar64/screenshots/password-state-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/password-state.png +0 -0
- package/docs/recipes/oscar64/screenshots/per-frame-hitbox-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/per-frame-hitbox.png +0 -0
- package/docs/recipes/oscar64/screenshots/petscii-screen-codes-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/petscii-screen-codes.png +0 -0
- package/docs/recipes/oscar64/screenshots/platformer-scaffold-d64-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/platformer-scaffold-d64.png +0 -0
- package/docs/recipes/oscar64/screenshots/platformer-scaffold-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/platformer-scaffold.png +0 -0
- package/docs/recipes/oscar64/screenshots/print-number-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/print-number.png +0 -0
- package/docs/recipes/oscar64/screenshots/raster-bars.png +0 -0
- package/docs/recipes/oscar64/screenshots/raster-profile-bars-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/raster-profile-bars.png +0 -0
- package/docs/recipes/oscar64/screenshots/rel-side-sectors-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/rel-side-sectors.png +0 -0
- package/docs/recipes/oscar64/screenshots/relative-file-records-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/relative-file-records.png +0 -0
- package/docs/recipes/oscar64/screenshots/save-load-seq-file-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/save-load-seq-file.png +0 -0
- package/docs/recipes/oscar64/screenshots/seeded-level-fill-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/seeded-level-fill.png +0 -0
- package/docs/recipes/oscar64/screenshots/sfx-engine-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/sfx-engine.png +0 -0
- package/docs/recipes/oscar64/screenshots/sid-music-player.png +0 -0
- package/docs/recipes/oscar64/screenshots/simple-shmup.png +0 -0
- package/docs/recipes/oscar64/screenshots/slope-collision-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/slope-collision.png +0 -0
- package/docs/recipes/oscar64/screenshots/soft-scroll-h.png +0 -0
- package/docs/recipes/oscar64/screenshots/sprite-animation-table-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/sprite-animation-table.png +0 -0
- package/docs/recipes/oscar64/screenshots/sprite-multiplex-8.png +0 -0
- package/docs/recipes/oscar64/screenshots/stable-raster-irq.png +0 -0
- package/docs/recipes/oscar64/screenshots/text-input-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/text-input.png +0 -0
- package/docs/recipes/oscar64/screenshots/text-overlay-playfield-gameover.png +0 -0
- package/docs/recipes/oscar64/screenshots/text-overlay-playfield-notrail-control.png +0 -0
- package/docs/recipes/oscar64/screenshots/text-overlay-playfield-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/text-overlay-playfield-ungated-control.png +0 -0
- package/docs/recipes/oscar64/screenshots/text-overlay-playfield.png +0 -0
- package/docs/recipes/oscar64/screenshots/text-window-menu-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/text-window-menu.png +0 -0
- package/docs/recipes/oscar64/screenshots/tile-grid-collision-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/tile-grid-collision.png +0 -0
- package/docs/recipes/oscar64/screenshots/tile-map-render-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/tile-map-render.png +0 -0
- package/docs/recipes/oscar64/screenshots/two-player-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/two-player.png +0 -0
- package/docs/recipes/oscar64/screenshots/two-word-parser-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/two-word-parser.png +0 -0
- package/docs/recipes/oscar64/screenshots/vehicle-control-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/vehicle-control.png +0 -0
- package/docs/recipes/oscar64/screenshots/wave-director-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/wave-director.png +0 -0
- package/docs/recipes/oscar64/seeded-level-fill.md +364 -0
- package/docs/recipes/oscar64/sfx-engine.md +514 -0
- package/docs/recipes/oscar64/sid-music-player.md +441 -0
- package/docs/recipes/oscar64/simple-shmup.md +1000 -0
- package/docs/recipes/oscar64/slope-collision.md +610 -0
- package/docs/recipes/oscar64/soft-scroll-h.md +261 -0
- package/docs/recipes/oscar64/sprite-animation-table.md +671 -0
- package/docs/recipes/oscar64/sprite-multiplex-8.md +314 -0
- package/docs/recipes/oscar64/stable-raster-irq.md +236 -0
- package/docs/recipes/oscar64/text-input.md +274 -0
- package/docs/recipes/oscar64/text-overlay-playfield.md +617 -0
- package/docs/recipes/oscar64/text-window-menu.md +551 -0
- package/docs/recipes/oscar64/tile-grid-collision.md +563 -0
- package/docs/recipes/oscar64/tile-map-render.md +395 -0
- package/docs/recipes/oscar64/two-player.md +528 -0
- package/docs/recipes/oscar64/two-word-parser.md +510 -0
- package/docs/recipes/oscar64/vehicle-control.md +771 -0
- package/docs/recipes/oscar64/wave-director.md +787 -0
- package/docs/recipes/runs.json +1606 -0
- package/docs/runtime/sim6502-reference.md +466 -0
- package/docs/runtime/vice-mcp-reference.md +351 -0
- package/docs/runtime/vice-reference.md +1393 -0
- package/docs/techniques/bitmap-modes.md +685 -0
- package/docs/techniques/cpu-cycle-tricks.md +1570 -0
- package/docs/techniques/effects-vector-3d.md +1431 -0
- package/docs/techniques/file-io.md +1427 -0
- package/docs/techniques/input.md +1072 -0
- package/docs/techniques/loaders-packers.md +768 -0
- package/docs/techniques/logic.md +3091 -0
- package/docs/techniques/maths.md +1524 -0
- package/docs/techniques/memory-banking.md +1686 -0
- package/docs/techniques/music-sid.md +1144 -0
- package/docs/techniques/raster.md +1543 -0
- package/docs/techniques/scroll.md +1292 -0
- package/docs/techniques/sprite.md +2566 -0
- package/docs/techniques/text-mode-render.md +717 -0
- package/docs/techniques/text.md +1095 -0
- package/docs/techniques/transitions.md +405 -0
- package/docs/toolchains/cartconv-reference.md +262 -0
- package/docs/toolchains/cc1541-reference.md +316 -0
- package/docs/toolchains/cc65-reference.md +667 -0
- package/docs/toolchains/error-sources/cc65/README.md +1 -0
- package/docs/toolchains/error-sources/cc65/missing-setcpu.s +4 -0
- package/docs/toolchains/error-sources/cc65/range-error.s +4 -0
- package/docs/toolchains/error-sources/cc65/segment-overflow.c +6 -0
- package/docs/toolchains/error-sources/cc65/unresolved-external.c +6 -0
- package/docs/toolchains/error-sources/kickassembler/README.md +1 -0
- package/docs/toolchains/error-sources/kickassembler/branch-out-of-range.asm +4 -0
- package/docs/toolchains/error-sources/kickassembler/failed-assert.asm +3 -0
- package/docs/toolchains/error-sources/kickassembler/flat-lib.asm +4 -0
- package/docs/toolchains/error-sources/kickassembler/import-source-no-namespace.asm +5 -0
- package/docs/toolchains/error-sources/kickassembler/macro-without-parentheses.asm +6 -0
- package/docs/toolchains/error-sources/kickassembler/memory-block-overlap.asm +4 -0
- package/docs/toolchains/error-sources/kickassembler/symbol-clash-lib.asm +5 -0
- package/docs/toolchains/error-sources/kickassembler/symbol-clash-main.asm +6 -0
- package/docs/toolchains/error-sources/kickassembler/unknown-symbol.asm +4 -0
- package/docs/toolchains/error-sources/oscar64/README.md +1 -0
- package/docs/toolchains/error-sources/oscar64/asm-addressing-mode.c +7 -0
- package/docs/toolchains/error-sources/oscar64/region-overflow.c +6 -0
- package/docs/toolchains/error-sources/oscar64/undefined-extern-var.c +5 -0
- package/docs/toolchains/error-sources/oscar64/undefined-extern.c +6 -0
- package/docs/toolchains/error-sources/oscar64/unknown-vic-field.c +6 -0
- package/docs/toolchains/error-sources/oscar64/void-main.c +3 -0
- package/docs/toolchains/kickassembler-reference.md +1020 -0
- package/docs/toolchains/memory-layout-planning.md +362 -0
- package/docs/toolchains/oscar64-headers-reference.md +583 -0
- package/docs/toolchains/oscar64-reference.md +892 -0
- package/docs/toolchains/petcat-reference.md +290 -0
- package/docs/toolchains/png2prg.md +188 -0
- package/docs/toolchains/release-disk.md +314 -0
- package/docs/toolchains/sidreloc.md +236 -0
- package/docs/toolchains/spindle-reference.md +487 -0
- package/docs/toolchains/tape-mastering.md +592 -0
- package/docs/toolchains/unit-testing-6502.md +281 -0
- package/docs/workflow/agent-harness.md +478 -0
- package/package.json +105 -0
- package/templates/_harness/CLAUDE.md.template +91 -0
- package/templates/_harness/PLAN.md.template +72 -0
- package/templates/_harness/check.py +442 -0
- package/templates/_harness/claude/settings.json +17 -0
- package/templates/_harness/gen-asm-header.py +96 -0
- package/templates/_harness/harness.mk +273 -0
- package/templates/_harness/hooks/plan-gate.py +185 -0
- package/templates/_harness/meter/frame_meter.asm +311 -0
- package/templates/_harness/meter/frame_meter.c +155 -0
- package/templates/_harness/meter/frame_meter.h +80 -0
- package/templates/_harness/zp-used.py +104 -0
- package/templates/action-puzzle/.claude/settings.json +17 -0
- package/templates/action-puzzle/.mcp.json +10 -0
- package/templates/action-puzzle/CLAUDE.md +120 -0
- package/templates/action-puzzle/Makefile +125 -0
- package/templates/action-puzzle/PLAN.md +388 -0
- package/templates/action-puzzle/README.md +240 -0
- package/templates/action-puzzle/expect.json +25 -0
- package/templates/action-puzzle/src/cave.c +280 -0
- package/templates/action-puzzle/src/cave.h +80 -0
- package/templates/action-puzzle/src/gen_autopilot.h +20 -0
- package/templates/action-puzzle/src/gen_caves.h +59 -0
- package/templates/action-puzzle/src/gen_notes.h +16 -0
- package/templates/action-puzzle/src/hiscore.c +152 -0
- package/templates/action-puzzle/src/hiscore.h +41 -0
- package/templates/action-puzzle/src/level.c +64 -0
- package/templates/action-puzzle/src/level.h +24 -0
- package/templates/action-puzzle/src/main.c +599 -0
- package/templates/action-puzzle/src/render.c +239 -0
- package/templates/action-puzzle/src/render.h +31 -0
- package/templates/action-puzzle/src/sound.c +158 -0
- package/templates/action-puzzle/src/sound.h +22 -0
- package/templates/action-puzzle/tools/disk_check.py +77 -0
- package/templates/action-puzzle/tools/drive.py +106 -0
- package/templates/action-puzzle/tools/gen.py +454 -0
- package/templates/action-puzzle/tools/model_check.py +49 -0
- package/templates/action-puzzle/tools/verdict_codes.py +24 -0
- package/templates/adventure/.claude/settings.json +17 -0
- package/templates/adventure/.mcp.json +10 -0
- package/templates/adventure/CLAUDE.md +118 -0
- package/templates/adventure/Makefile +113 -0
- package/templates/adventure/PLAN.md +396 -0
- package/templates/adventure/README.md +277 -0
- package/templates/adventure/expect.json +25 -0
- package/templates/adventure/src/engine.c +543 -0
- package/templates/adventure/src/engine.h +48 -0
- package/templates/adventure/src/gen_script.h +141 -0
- package/templates/adventure/src/gen_world.h +511 -0
- package/templates/adventure/src/main.c +439 -0
- package/templates/adventure/src/picture.c +83 -0
- package/templates/adventure/src/picture.h +16 -0
- package/templates/adventure/src/save.c +159 -0
- package/templates/adventure/src/save.h +25 -0
- package/templates/adventure/src/sound.c +71 -0
- package/templates/adventure/src/sound.h +16 -0
- package/templates/adventure/src/text.c +349 -0
- package/templates/adventure/src/text.h +40 -0
- package/templates/adventure/tools/disk_check.py +128 -0
- package/templates/adventure/tools/drive.py +119 -0
- package/templates/adventure/tools/gen.py +1033 -0
- package/templates/adventure/tools/world.py +356 -0
- package/templates/beat-em-up/.claude/settings.json +17 -0
- package/templates/beat-em-up/.mcp.json +10 -0
- package/templates/beat-em-up/CLAUDE.md +136 -0
- package/templates/beat-em-up/Makefile +96 -0
- package/templates/beat-em-up/PLAN.md +502 -0
- package/templates/beat-em-up/README.md +315 -0
- package/templates/beat-em-up/expect-gameover.json +8 -0
- package/templates/beat-em-up/expect.json +29 -0
- package/templates/beat-em-up/src/anim.c +70 -0
- package/templates/beat-em-up/src/art.c +344 -0
- package/templates/beat-em-up/src/autopilot.h +154 -0
- package/templates/beat-em-up/src/brute.c +273 -0
- package/templates/beat-em-up/src/enemy.c +281 -0
- package/templates/beat-em-up/src/engine.asm +512 -0
- package/templates/beat-em-up/src/fighter.c +384 -0
- package/templates/beat-em-up/src/game.h +269 -0
- package/templates/beat-em-up/src/hud.c +135 -0
- package/templates/beat-em-up/src/main.c +341 -0
- package/templates/beat-em-up/src/sound.c +44 -0
- package/templates/beat-em-up/src/street.c +93 -0
- package/templates/beat-em-up/src/verdict.h +523 -0
- package/templates/beat-em-up/src/view.c +362 -0
- package/templates/beat-em-up/tools/drive.py +105 -0
- package/templates/beat-em-up/tools/flickercheck.py +273 -0
- package/templates/demo/.claude/settings.json +17 -0
- package/templates/demo/.mcp.json +10 -0
- package/templates/demo/CLAUDE.md +129 -0
- package/templates/demo/Makefile +66 -0
- package/templates/demo/PLAN.md +401 -0
- package/templates/demo/README.md +322 -0
- package/templates/demo/expect.json +945 -0
- package/templates/demo/src/config.asm +80 -0
- package/templates/demo/src/framework.asm +390 -0
- package/templates/demo/src/main.asm +139 -0
- package/templates/demo/src/music.asm +197 -0
- package/templates/demo/src/part_main.asm +279 -0
- package/templates/demo/src/part_title.asm +79 -0
- package/templates/demo/src/parts.asm +43 -0
- package/templates/demo/src/tables.asm +73 -0
- package/templates/demo/src/verdict.asm +179 -0
- package/templates/demo/tools/audio.py +80 -0
- package/templates/demo/tools/gen_expect.py +167 -0
- package/templates/demo/tools/probe.py +95 -0
- package/templates/hello/.claude/settings.json +17 -0
- package/templates/hello/.mcp.json +10 -0
- package/templates/hello/CLAUDE.md +100 -0
- package/templates/hello/Makefile +38 -0
- package/templates/hello/PLAN.md +200 -0
- package/templates/hello/expect.json +20 -0
- package/templates/hello/src/main.c +161 -0
- package/templates/hello/src/sprite.asm +27 -0
- package/templates/hello-kick/.claude/settings.json +17 -0
- package/templates/hello-kick/.mcp.json +10 -0
- package/templates/hello-kick/CLAUDE.md +100 -0
- package/templates/hello-kick/Makefile +17 -0
- package/templates/hello-kick/PLAN.md +199 -0
- package/templates/hello-kick/expect.json +20 -0
- package/templates/hello-kick/src/main.asm +233 -0
- package/templates/platformer/.claude/settings.json +17 -0
- package/templates/platformer/.mcp.json +10 -0
- package/templates/platformer/CLAUDE.md +125 -0
- package/templates/platformer/Makefile +86 -0
- package/templates/platformer/PLAN.md +360 -0
- package/templates/platformer/README.md +277 -0
- package/templates/platformer/expect.json +32 -0
- package/templates/platformer/src/actors.c +289 -0
- package/templates/platformer/src/anim.c +51 -0
- package/templates/platformer/src/art.c +212 -0
- package/templates/platformer/src/autopilot.h +30 -0
- package/templates/platformer/src/engine.asm +253 -0
- package/templates/platformer/src/game.h +248 -0
- package/templates/platformer/src/hud.c +90 -0
- package/templates/platformer/src/level.c +184 -0
- package/templates/platformer/src/main.c +306 -0
- package/templates/platformer/src/player.c +268 -0
- package/templates/platformer/src/sound.c +42 -0
- package/templates/platformer/src/verdict.h +206 -0
- package/templates/platformer/src/view.c +331 -0
- package/templates/platformer/stage-expect.json +6 -0
- package/templates/platformer/tools/drive.py +112 -0
- package/templates/platformer/tools/tearcheck.py +229 -0
- package/templates/shmup-vertical/.claude/settings.json +17 -0
- package/templates/shmup-vertical/.mcp.json +10 -0
- package/templates/shmup-vertical/CLAUDE.md +137 -0
- package/templates/shmup-vertical/Makefile +131 -0
- package/templates/shmup-vertical/PLAN.md +569 -0
- package/templates/shmup-vertical/README.md +189 -0
- package/templates/shmup-vertical/expect.json +38 -0
- package/templates/shmup-vertical/src/bullets.c +158 -0
- package/templates/shmup-vertical/src/bullets.h +35 -0
- package/templates/shmup-vertical/src/display.c +239 -0
- package/templates/shmup-vertical/src/display.h +40 -0
- package/templates/shmup-vertical/src/game.h +85 -0
- package/templates/shmup-vertical/src/glyph.asm +358 -0
- package/templates/shmup-vertical/src/hiscore.c +141 -0
- package/templates/shmup-vertical/src/hiscore.h +16 -0
- package/templates/shmup-vertical/src/hit.asm +180 -0
- package/templates/shmup-vertical/src/hitbox.c +59 -0
- package/templates/shmup-vertical/src/hitbox.h +25 -0
- package/templates/shmup-vertical/src/kernel.asm +330 -0
- package/templates/shmup-vertical/src/level.c +174 -0
- package/templates/shmup-vertical/src/level.h +27 -0
- package/templates/shmup-vertical/src/main.c +824 -0
- package/templates/shmup-vertical/src/mux.asm +321 -0
- package/templates/shmup-vertical/src/sound.asm +255 -0
- package/templates/shmup-vertical/src/step.asm +169 -0
- package/templates/shmup-vertical/src/waves.c +195 -0
- package/templates/shmup-vertical/src/waves.h +33 -0
- package/templates/shmup-vertical/stage-expect.json +6 -0
- package/templates/shmup-vertical/tools/drive.py +152 -0
- package/templates/shmup-vertical/tools/joytest.py +159 -0
- package/templates/shmup-vertical/tools/meter.py +15 -0
- package/templates/shmup-vertical/tools/phases.py +73 -0
|
@@ -0,0 +1,881 @@
|
|
|
1
|
+
---
|
|
2
|
+
recipe: nav-area-pathfinding
|
|
3
|
+
toolchain: oscar64
|
|
4
|
+
output_format: PRG
|
|
5
|
+
region: both
|
|
6
|
+
techniques: [nav_area_pathfinding]
|
|
7
|
+
file_formats: [PRG]
|
|
8
|
+
uses_registers: [D011, D020, D021, DC04, DC05, DC06, DC07, DC0E, DC0F]
|
|
9
|
+
uses_kernal: []
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
<!-- doc-type: recipe -->
|
|
13
|
+
|
|
14
|
+
# Oscar64 Nav-Area Pathfinding: a chaser routed over platforms, ladders, drops and jumps
|
|
15
|
+
|
|
16
|
+
## Synopsis
|
|
17
|
+
|
|
18
|
+
A chaser crosses a character-map level of twelve platform areas to reach
|
|
19
|
+
a player marker, which moves to the next of eight waypoints each time it
|
|
20
|
+
is caught. At start the program finds the areas (runs of cells an actor
|
|
21
|
+
can stand in), joins them with 43 links (walk, drop, jump, ladder, each
|
|
22
|
+
with a cost), runs one Dijkstra search per destination and keeps a
|
|
23
|
+
next-hop table: for every pair of areas, the link to take first. Each
|
|
24
|
+
move is then one table read. Odd frames spend the chaser's budget on one
|
|
25
|
+
step of a line-of-sight ray to the player instead. Every hop taken is
|
|
26
|
+
checked against a table computed in Python by a different method
|
|
27
|
+
(Floyd-Warshall) and compiled in, and the whole table is compared too.
|
|
28
|
+
The screen shows the build time, the worst search, query and ray step in
|
|
29
|
+
CIA1 cycles, and PASS or FAIL. `$02FF` = `01` and a green border on
|
|
30
|
+
pass, `02` and red on fail. This is the `nav_area_pathfinding` technique
|
|
31
|
+
in `docs/techniques/logic.md`; the result-byte contract is
|
|
32
|
+
`headless-verify.md`.
|
|
33
|
+
|
|
34
|
+
## Source
|
|
35
|
+
|
|
36
|
+
```c
|
|
37
|
+
// nav-area-pathfinding.c
|
|
38
|
+
//
|
|
39
|
+
// Platform-graph pathfinding on a character map. At start the program
|
|
40
|
+
// finds the walkable areas (runs of cells an actor can stand in), links
|
|
41
|
+
// them by walk, drop, jump and ladder moves with a cost each, runs one
|
|
42
|
+
// Dijkstra search per destination and keeps a next-hop table: for each
|
|
43
|
+
// (from, to) pair of areas, the link to take first. A chaser then follows
|
|
44
|
+
// a player marker that moves to the next waypoint each time it is caught.
|
|
45
|
+
// Even frames the chaser moves one cell and makes one table query; odd
|
|
46
|
+
// frames it takes one step of a line-of-sight ray to the player.
|
|
47
|
+
// Each hop taken is checked against a next-hop table computed in Python
|
|
48
|
+
// by a different method (Floyd-Warshall) and compiled in.
|
|
49
|
+
// Row 0: build cycles, worst single search, areas and links. Row 1:
|
|
50
|
+
// worst query, worst LOS step, area and link pass, next-hop pass, all
|
|
51
|
+
// CIA1 cycles. Row 2: steps, queries, bad hops, table mismatches, LOS
|
|
52
|
+
// pairs right, result. $02FF = 01 and a green border on
|
|
53
|
+
// pass, 02 and red on fail. The chaser leaves a cyan trail.
|
|
54
|
+
// Build: oscar64 -tm=c64 -O2 -o=nav-area-pathfinding.prg nav-area-pathfinding.c
|
|
55
|
+
#include <c64/vic.h>
|
|
56
|
+
#include <c64/cia.h>
|
|
57
|
+
#include <string.h>
|
|
58
|
+
|
|
59
|
+
#define SCREEN ((char *)0x0400)
|
|
60
|
+
#define COLOUR ((char *)0xd800)
|
|
61
|
+
#define RESULT (*(volatile char *)0x02ff)
|
|
62
|
+
#define CODE_PASS 0x01
|
|
63
|
+
#define CODE_FAIL 0x02
|
|
64
|
+
|
|
65
|
+
// Map rows 0-21 are screen rows 3-24. '#' solid, 'H' ladder, '.' air.
|
|
66
|
+
#define MAP_ROW0 3
|
|
67
|
+
#define MW 40
|
|
68
|
+
#define MH 22
|
|
69
|
+
const char map_text[MH][MW + 1] = {
|
|
70
|
+
"........................................", // 0
|
|
71
|
+
"........................................", // 1
|
|
72
|
+
"........................................", // 2
|
|
73
|
+
"..######H#####..........######H######...", // 3
|
|
74
|
+
"........H.....................H.........", // 4
|
|
75
|
+
"........H.....................H.........", // 5
|
|
76
|
+
"........H.....................H.........", // 6
|
|
77
|
+
"....#H######...##H####..####H###........", // 7
|
|
78
|
+
".....H...........H..........H...........", // 8
|
|
79
|
+
".....H...........H..........H...........", // 9
|
|
80
|
+
".....H...........H..........H...........", // 10
|
|
81
|
+
"..#H#####H#.########......#########H##..", // 11
|
|
82
|
+
"...H.....H.........................H....", // 12
|
|
83
|
+
"...H.....H.........................H....", // 13
|
|
84
|
+
"...H.....H.........................H....", // 14
|
|
85
|
+
"...H..#########.....####H#####.....H....", // 15
|
|
86
|
+
"...H....................H.....#####H....", // 16
|
|
87
|
+
"...H....................H..........H....", // 17
|
|
88
|
+
"...H....................H..........H....", // 18
|
|
89
|
+
"...H....................H..........H....", // 19
|
|
90
|
+
"...H....................H..........H....", // 20
|
|
91
|
+
"########################################", // 21
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
// Next area on a shortest route, from the Python model (Floyd-Warshall,
|
|
95
|
+
// first hop = lowest-numbered link on a shortest route). 255 on the
|
|
96
|
+
// diagonal.
|
|
97
|
+
#define EXP_N 12
|
|
98
|
+
const char exp_next[EXP_N * EXP_N] = {
|
|
99
|
+
255, 6, 2, 6, 6, 2, 6, 6, 2, 6, 6, 2,
|
|
100
|
+
4, 255, 4, 4, 4, 4, 4, 4, 4, 9, 9, 4,
|
|
101
|
+
0, 6, 255, 6, 6, 5, 6, 6, 5, 6, 6, 5,
|
|
102
|
+
6, 4, 6, 255, 4, 6, 6, 4, 6, 9, 9, 9,
|
|
103
|
+
3, 1, 3, 3, 255, 3, 3, 7, 3, 9, 9, 7,
|
|
104
|
+
2, 6, 2, 6, 6, 255, 6, 6, 8, 6, 6, 11,
|
|
105
|
+
5, 3, 5, 3, 3, 5, 255, 3, 8, 9, 9, 9,
|
|
106
|
+
4, 4, 4, 4, 4, 4, 4, 255, 4, 9, 9, 11,
|
|
107
|
+
5, 5, 5, 5, 5, 5, 5, 11, 255, 5, 5, 11,
|
|
108
|
+
11, 11, 11, 11, 11, 11, 11, 11, 11, 255, 10, 11,
|
|
109
|
+
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 255, 9,
|
|
110
|
+
5, 7, 5, 5, 7, 5, 5, 7, 5, 9, 9, 255,
|
|
111
|
+
};
|
|
112
|
+
#define EXP_STEPS 299
|
|
113
|
+
#define EXP_QUERIES 160
|
|
114
|
+
|
|
115
|
+
// Waypoints the player marker visits, (x, map row); each is a standing cell.
|
|
116
|
+
#define NWP 8
|
|
117
|
+
const char wp_x[NWP] = { 34, 4, 32, 10, 13, 7, 26, 38 };
|
|
118
|
+
const char wp_y[NWP] = { 2, 20, 15, 2, 10, 14, 6, 20 };
|
|
119
|
+
#define START_X 1
|
|
120
|
+
#define START_Y 20
|
|
121
|
+
|
|
122
|
+
// LOS test pairs: straight rows and columns, so any line algorithm gives
|
|
123
|
+
// the same answer. 1 clear, 2 blocked.
|
|
124
|
+
#define NLOS 4
|
|
125
|
+
const char los_x0[NLOS] = { 0, 10, 14, 0 };
|
|
126
|
+
const char los_y0[NLOS] = { 20, 10, 10, 7 };
|
|
127
|
+
const char los_x1[NLOS] = { 39, 10, 14, 20 };
|
|
128
|
+
const char los_y1[NLOS] = { 20, 14, 2, 7 };
|
|
129
|
+
const char los_exp[NLOS] = { 1, 2, 1, 2 };
|
|
130
|
+
|
|
131
|
+
// --- tiles ---------------------------------------------------------------
|
|
132
|
+
static inline char tile(signed char y, signed char x)
|
|
133
|
+
{
|
|
134
|
+
if (x < 0 || x >= MW || y < 0)
|
|
135
|
+
return '.';
|
|
136
|
+
if (y >= MH)
|
|
137
|
+
return '#';
|
|
138
|
+
return map_text[y][x];
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
bool standable(signed char y, signed char x)
|
|
142
|
+
{
|
|
143
|
+
if (y < 0 || y >= MH - 1 || x < 0 || x >= MW)
|
|
144
|
+
return false;
|
|
145
|
+
char c = map_text[y][x];
|
|
146
|
+
if (c == '#')
|
|
147
|
+
return false;
|
|
148
|
+
char b = map_text[y + 1][x];
|
|
149
|
+
return b == '#' || (b == 'H' && c != 'H');
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// --- areas and links -------------------------------------------------------
|
|
153
|
+
#define MAXA 16 // table stride; N <= 16
|
|
154
|
+
#define MAXL 64
|
|
155
|
+
#define NONE 255
|
|
156
|
+
enum { L_WALK, L_DROP, L_JUMP, L_LADDER };
|
|
157
|
+
|
|
158
|
+
char n_areas, n_links;
|
|
159
|
+
char ay[MAXA], ax0[MAXA], ax1[MAXA];
|
|
160
|
+
char area_at[MH][MW]; // area per standing cell, NONE elsewhere
|
|
161
|
+
char lf[MAXL], lt[MAXL], lty[MAXL], lsx[MAXL], lex[MAXL], ley[MAXL], lc[MAXL];
|
|
162
|
+
char dist[MAXA * MAXA]; // dist[from * MAXA + to]
|
|
163
|
+
char nextl[MAXA * MAXA]; // link to take first, NONE if none
|
|
164
|
+
|
|
165
|
+
void add_link(char f, char t, char ty, char sx, char ex, char ey, char c)
|
|
166
|
+
{
|
|
167
|
+
char i = n_links++;
|
|
168
|
+
lf[i] = f; lt[i] = t; lty[i] = ty;
|
|
169
|
+
lsx[i] = sx; lex[i] = ex; ley[i] = ey; lc[i] = c;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// Step sideways into (y, x) and fall: the landing row, or NONE.
|
|
173
|
+
char fall_from(char y, signed char x)
|
|
174
|
+
{
|
|
175
|
+
if (x < 0 || x >= MW || map_text[y][x] != '.')
|
|
176
|
+
return NONE;
|
|
177
|
+
for (;;) {
|
|
178
|
+
if (standable(y, x))
|
|
179
|
+
return y;
|
|
180
|
+
y++;
|
|
181
|
+
if (y >= MH - 1 || map_text[y][x] != '.')
|
|
182
|
+
return NONE;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
void build_areas(void)
|
|
187
|
+
{
|
|
188
|
+
memset(area_at, NONE, sizeof(area_at));
|
|
189
|
+
n_areas = 0;
|
|
190
|
+
for (char y = 0; y < MH; y++) {
|
|
191
|
+
char x = 0;
|
|
192
|
+
while (x < MW) {
|
|
193
|
+
if (standable(y, x)) {
|
|
194
|
+
char a = n_areas++;
|
|
195
|
+
ay[a] = y; ax0[a] = x;
|
|
196
|
+
while (x < MW && standable(y, x))
|
|
197
|
+
area_at[y][x++] = a;
|
|
198
|
+
ax1[a] = x - 1;
|
|
199
|
+
} else
|
|
200
|
+
x++;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
void build_links(void)
|
|
206
|
+
{
|
|
207
|
+
n_links = 0;
|
|
208
|
+
for (char a = 0; a < n_areas; a++) {
|
|
209
|
+
char y = ay[a], x0 = ax0[a], x1 = ax1[a];
|
|
210
|
+
// Right end, then left end: a one-row step down is a walk both
|
|
211
|
+
// ways, a longer fall is a one-way drop.
|
|
212
|
+
for (char e = 0; e < 2; e++) {
|
|
213
|
+
char sx = e ? x0 : x1;
|
|
214
|
+
signed char x = e ? (signed char)x0 - 1 : x1 + 1;
|
|
215
|
+
char land = fall_from(y, x);
|
|
216
|
+
if (land != NONE && land > y) {
|
|
217
|
+
char b = area_at[land][x];
|
|
218
|
+
if (land == y + 1) {
|
|
219
|
+
add_link(a, b, L_WALK, sx, x, land, 1);
|
|
220
|
+
add_link(b, a, L_WALK, x, sx, y, 1);
|
|
221
|
+
} else
|
|
222
|
+
add_link(a, b, L_DROP, sx, x, land, land - y + 1);
|
|
223
|
+
}
|
|
224
|
+
if (e == 0) {
|
|
225
|
+
// Jump right over a gap of 1 or 2 cells to the same row.
|
|
226
|
+
for (char gap = 1; gap <= 2; gap++) {
|
|
227
|
+
char bx = x1 + gap + 1;
|
|
228
|
+
if (bx >= MW || area_at[y][bx] == NONE)
|
|
229
|
+
continue;
|
|
230
|
+
bool clear = true;
|
|
231
|
+
for (char xx = x1; xx <= bx; xx++)
|
|
232
|
+
if (tile(y - 1, xx) != '.') clear = false;
|
|
233
|
+
for (char xx = x1 + 1; xx < bx; xx++)
|
|
234
|
+
if (map_text[y][xx] != '.') clear = false;
|
|
235
|
+
if (clear) {
|
|
236
|
+
char b = area_at[y][bx];
|
|
237
|
+
add_link(a, b, L_JUMP, x1, bx, y, gap + 2);
|
|
238
|
+
add_link(b, a, L_JUMP, bx, x1, y, gap + 2);
|
|
239
|
+
break;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
// Ladders going down from this area.
|
|
245
|
+
for (char x = x0; x <= x1; x++) {
|
|
246
|
+
if (tile(y + 1, x) != 'H')
|
|
247
|
+
continue;
|
|
248
|
+
char yb = y + 1;
|
|
249
|
+
while (tile(yb + 1, x) == 'H')
|
|
250
|
+
yb++;
|
|
251
|
+
char b = area_at[yb][x];
|
|
252
|
+
if (b != NONE) {
|
|
253
|
+
add_link(a, b, L_LADDER, x, x, yb, yb - y);
|
|
254
|
+
add_link(b, a, L_LADDER, x, x, y, yb - y);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// One search: cheapest cost from every area to area j, Dijkstra over the
|
|
261
|
+
// links read backwards. Writes column j of dist.
|
|
262
|
+
void search_to(char j)
|
|
263
|
+
{
|
|
264
|
+
char d[MAXA];
|
|
265
|
+
bool done[MAXA];
|
|
266
|
+
char n = n_areas;
|
|
267
|
+
for (char i = 0; i < n; i++) {
|
|
268
|
+
d[i] = NONE;
|
|
269
|
+
done[i] = false;
|
|
270
|
+
}
|
|
271
|
+
d[j] = 0;
|
|
272
|
+
for (char k = 0; k < n; k++) {
|
|
273
|
+
char best = NONE, u = NONE;
|
|
274
|
+
for (char i = 0; i < n; i++)
|
|
275
|
+
if (!done[i] && d[i] < best) {
|
|
276
|
+
best = d[i];
|
|
277
|
+
u = i;
|
|
278
|
+
}
|
|
279
|
+
if (u == NONE)
|
|
280
|
+
break;
|
|
281
|
+
done[u] = true;
|
|
282
|
+
for (char l = 0; l < n_links; l++)
|
|
283
|
+
if (lt[l] == u) {
|
|
284
|
+
unsigned c = best + lc[l];
|
|
285
|
+
char v = lf[l];
|
|
286
|
+
if (c < d[v])
|
|
287
|
+
d[v] = c;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
for (char i = 0; i < n; i++)
|
|
291
|
+
dist[i * MAXA + j] = d[i];
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
// First link on a shortest route from i to j: the lowest-numbered link
|
|
295
|
+
// out of i whose cost plus the rest of the route equals the route cost.
|
|
296
|
+
void build_next(void)
|
|
297
|
+
{
|
|
298
|
+
for (char i = 0; i < n_areas; i++)
|
|
299
|
+
for (char j = 0; j < n_areas; j++) {
|
|
300
|
+
char r = NONE, dij = dist[i * MAXA + j];
|
|
301
|
+
if (i != j && dij != NONE)
|
|
302
|
+
for (char l = 0; l < n_links; l++) {
|
|
303
|
+
char dt = dist[lt[l] * MAXA + j];
|
|
304
|
+
if (lf[l] == i && dt != NONE && lc[l] + dt == dij) {
|
|
305
|
+
r = l;
|
|
306
|
+
break;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
nextl[i * MAXA + j] = r;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
// --- CIA1 timers -------------------------------------------------------------
|
|
314
|
+
// Timer B alone for short work; timer B counting timer A underflows for
|
|
315
|
+
// the build, which runs past 65,535 cycles.
|
|
316
|
+
static inline void timer_start(void)
|
|
317
|
+
{
|
|
318
|
+
cia1.crb = 0x00;
|
|
319
|
+
cia1.tb = 0xffff;
|
|
320
|
+
cia1.crb = 0x11;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
static inline unsigned timer_stop(void)
|
|
324
|
+
{
|
|
325
|
+
cia1.crb = 0x00;
|
|
326
|
+
return 0xffff - cia1.tb;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
void long_start(void)
|
|
330
|
+
{
|
|
331
|
+
cia1.cra = 0x00;
|
|
332
|
+
cia1.crb = 0x00;
|
|
333
|
+
cia1.ta = 0xffff;
|
|
334
|
+
cia1.tb = 0xffff;
|
|
335
|
+
cia1.crb = 0x51; // load, start, count TA underflows
|
|
336
|
+
cia1.cra = 0x11; // load, start, count cycles
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
unsigned long long_stop(void)
|
|
340
|
+
{
|
|
341
|
+
cia1.cra = 0x00;
|
|
342
|
+
cia1.crb = 0x00;
|
|
343
|
+
return ((unsigned long)(0xffff - cia1.tb) << 16) + (0xffff - cia1.ta);
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
// --- actors ------------------------------------------------------------------
|
|
347
|
+
char cx, cy, px, py; // chaser and player, (x, map row)
|
|
348
|
+
char tr_ty = NONE, tr_sx, tr_ex, tr_ey; // link in progress, NONE when standing
|
|
349
|
+
|
|
350
|
+
// The query: which link to take first from the chaser's area to the
|
|
351
|
+
// player's. Two cell lookups and one table read.
|
|
352
|
+
char nav_query(void)
|
|
353
|
+
{
|
|
354
|
+
char a = area_at[cy][cx];
|
|
355
|
+
char p = area_at[py][px];
|
|
356
|
+
if (a == p)
|
|
357
|
+
return NONE;
|
|
358
|
+
return nextl[a * MAXA + p];
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
void transit_step(void)
|
|
362
|
+
{
|
|
363
|
+
signed char d = tr_ex > tr_sx ? 1 : (tr_ex < tr_sx ? -1 : 0);
|
|
364
|
+
switch (tr_ty) {
|
|
365
|
+
case L_WALK:
|
|
366
|
+
cx = tr_ex; cy = tr_ey;
|
|
367
|
+
break;
|
|
368
|
+
case L_LADDER:
|
|
369
|
+
if (tr_ey > cy) cy++; else cy--;
|
|
370
|
+
break;
|
|
371
|
+
case L_DROP:
|
|
372
|
+
if (cx != tr_ex) cx = tr_ex; else cy++;
|
|
373
|
+
break;
|
|
374
|
+
case L_JUMP: // up and over, across, down
|
|
375
|
+
if (cy == tr_ey && cx == tr_sx) { cx += d; cy--; }
|
|
376
|
+
else if (cx != tr_ex) cx += d;
|
|
377
|
+
else cy++;
|
|
378
|
+
break;
|
|
379
|
+
}
|
|
380
|
+
if (cx == tr_ex && cy == tr_ey)
|
|
381
|
+
tr_ty = NONE;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
// --- line of sight, one cell per call ------------------------------------------
|
|
385
|
+
signed char lx, ly, ltx, lty2, lsxs, lsys;
|
|
386
|
+
int ldx, ldy, lerr;
|
|
387
|
+
char los_state; // 0 idle, 1 running
|
|
388
|
+
|
|
389
|
+
void los_begin(char x0, char y0, char x1, char y1)
|
|
390
|
+
{
|
|
391
|
+
lx = x0; ly = y0; ltx = x1; lty2 = y1;
|
|
392
|
+
ldx = x1 > x0 ? x1 - x0 : x0 - x1;
|
|
393
|
+
ldy = -(int)(y1 > y0 ? y1 - y0 : y0 - y1);
|
|
394
|
+
lsxs = x0 < x1 ? 1 : -1;
|
|
395
|
+
lsys = y0 < y1 ? 1 : -1;
|
|
396
|
+
lerr = ldx + ldy;
|
|
397
|
+
los_state = 1;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
// 0 still running, 1 clear, 2 blocked.
|
|
401
|
+
char los_step(void)
|
|
402
|
+
{
|
|
403
|
+
if (lx == ltx && ly == lty2) {
|
|
404
|
+
los_state = 0;
|
|
405
|
+
return 1;
|
|
406
|
+
}
|
|
407
|
+
int e2 = 2 * lerr;
|
|
408
|
+
if (e2 >= ldy) { lerr += ldy; lx += lsxs; }
|
|
409
|
+
if (e2 <= ldx) { lerr += ldx; ly += lsys; }
|
|
410
|
+
if (map_text[ly][lx] == '#') {
|
|
411
|
+
los_state = 0;
|
|
412
|
+
return 2;
|
|
413
|
+
}
|
|
414
|
+
return 0;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
// --- drawing -------------------------------------------------------------------
|
|
418
|
+
#define C_FLOOR VCOL_GREEN
|
|
419
|
+
#define C_LADDER VCOL_ORANGE
|
|
420
|
+
#define C_TRAIL VCOL_CYAN
|
|
421
|
+
#define C_CHASER VCOL_WHITE
|
|
422
|
+
#define C_PLAYER VCOL_YELLOW
|
|
423
|
+
|
|
424
|
+
void draw_trail(char x, char y)
|
|
425
|
+
{
|
|
426
|
+
unsigned o = (y + MAP_ROW0) * 40 + x;
|
|
427
|
+
if (map_text[y][x] == '.')
|
|
428
|
+
SCREEN[o] = 0x2e; // '.'
|
|
429
|
+
COLOUR[o] = C_TRAIL;
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
void draw_at(char x, char y, char ch, char col)
|
|
433
|
+
{
|
|
434
|
+
unsigned o = (y + MAP_ROW0) * 40 + x;
|
|
435
|
+
SCREEN[o] = ch;
|
|
436
|
+
COLOUR[o] = col;
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
void put_str(char *p, const char *s)
|
|
440
|
+
{
|
|
441
|
+
while (*s)
|
|
442
|
+
*p++ = *s++;
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
void put_dec(char *p, unsigned long v, char digits)
|
|
446
|
+
{
|
|
447
|
+
for (char i = digits; i > 0; i--) {
|
|
448
|
+
p[i - 1] = 0x30 + (char)(v % 10);
|
|
449
|
+
v /= 10;
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
int main(void)
|
|
454
|
+
{
|
|
455
|
+
__asm { sei }
|
|
456
|
+
vic.color_border = VCOL_BLACK;
|
|
457
|
+
vic.color_back = VCOL_BLACK;
|
|
458
|
+
memset(SCREEN, 0x20, 1000);
|
|
459
|
+
memset(COLOUR, VCOL_LT_GREY, 1000);
|
|
460
|
+
for (char y = 0; y < MH; y++)
|
|
461
|
+
for (char x = 0; x < MW; x++) {
|
|
462
|
+
char c = map_text[y][x];
|
|
463
|
+
if (c == '#') draw_at(x, y, 0xa0, C_FLOOR);
|
|
464
|
+
else if (c == 'H') draw_at(x, y, 0x08, C_LADDER);
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
// Build: areas, links, one search per destination, next-hop table.
|
|
468
|
+
unsigned long t_search_max = 0;
|
|
469
|
+
long_start();
|
|
470
|
+
build_areas();
|
|
471
|
+
build_links();
|
|
472
|
+
unsigned long t_graph = long_stop();
|
|
473
|
+
for (char j = 0; j < n_areas; j++) {
|
|
474
|
+
long_start();
|
|
475
|
+
search_to(j);
|
|
476
|
+
unsigned long t = long_stop();
|
|
477
|
+
if (t > t_search_max) t_search_max = t;
|
|
478
|
+
}
|
|
479
|
+
long_start();
|
|
480
|
+
build_next();
|
|
481
|
+
unsigned long t_next = long_stop();
|
|
482
|
+
// Full build timed once more in one piece.
|
|
483
|
+
long_start();
|
|
484
|
+
build_areas();
|
|
485
|
+
build_links();
|
|
486
|
+
for (char j = 0; j < n_areas; j++)
|
|
487
|
+
search_to(j);
|
|
488
|
+
build_next();
|
|
489
|
+
unsigned long t_build = long_stop();
|
|
490
|
+
|
|
491
|
+
// Whole table against the model.
|
|
492
|
+
char mismatch = 0;
|
|
493
|
+
if (n_areas != EXP_N)
|
|
494
|
+
mismatch = 255;
|
|
495
|
+
else
|
|
496
|
+
for (char i = 0; i < EXP_N; i++)
|
|
497
|
+
for (char j = 0; j < EXP_N; j++) {
|
|
498
|
+
char l = nextl[i * MAXA + j];
|
|
499
|
+
// Not a ternary: Oscar64 1.32.271 at -O1 to -O3 drops the l == NONE
|
|
500
|
+
// test when lt has fewer than 256 entries and reads lt[255].
|
|
501
|
+
char h = NONE;
|
|
502
|
+
if (l != NONE)
|
|
503
|
+
h = lt[l];
|
|
504
|
+
if (h != exp_next[i * EXP_N + j]) mismatch++;
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
put_str(SCREEN, s"build");
|
|
508
|
+
put_dec(SCREEN + 6, t_build, 7);
|
|
509
|
+
put_str(SCREEN + 15, s"search");
|
|
510
|
+
put_dec(SCREEN + 22, t_search_max, 6);
|
|
511
|
+
put_str(SCREEN + 30, s"n");
|
|
512
|
+
put_dec(SCREEN + 32, n_areas, 2);
|
|
513
|
+
put_dec(SCREEN + 35, n_links, 2);
|
|
514
|
+
put_str(SCREEN + 40, s"qry");
|
|
515
|
+
put_str(SCREEN + 50, s"los");
|
|
516
|
+
put_str(SCREEN + 60, s"ar");
|
|
517
|
+
put_dec(SCREEN + 63, t_graph, 6);
|
|
518
|
+
put_str(SCREEN + 70, s"nx");
|
|
519
|
+
put_dec(SCREEN + 73, t_next, 6);
|
|
520
|
+
put_str(SCREEN + 80, s"st q bad mis los r");
|
|
521
|
+
|
|
522
|
+
cx = START_X; cy = START_Y;
|
|
523
|
+
char wp = 0;
|
|
524
|
+
px = wp_x[0]; py = wp_y[0];
|
|
525
|
+
draw_trail(cx, cy);
|
|
526
|
+
draw_at(px, py, 0x53, C_PLAYER);
|
|
527
|
+
draw_at(cx, cy, 0x51, C_CHASER);
|
|
528
|
+
|
|
529
|
+
unsigned steps = 0, queries = 0, t_q = 0, t_los = 0;
|
|
530
|
+
char bad = 0, frame = 0;
|
|
531
|
+
bool done = false;
|
|
532
|
+
|
|
533
|
+
for (;;) {
|
|
534
|
+
vic_waitFrame();
|
|
535
|
+
if (done)
|
|
536
|
+
continue;
|
|
537
|
+
frame++;
|
|
538
|
+
if (frame & 1) {
|
|
539
|
+
// Odd frame: one line-of-sight step toward the player.
|
|
540
|
+
timer_start();
|
|
541
|
+
if (los_state == 0)
|
|
542
|
+
los_begin(cx, cy, px, py);
|
|
543
|
+
else
|
|
544
|
+
los_step();
|
|
545
|
+
unsigned t = timer_stop();
|
|
546
|
+
if (t > t_los) t_los = t;
|
|
547
|
+
continue;
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
// Even frame: the chaser moves one cell.
|
|
551
|
+
draw_trail(cx, cy);
|
|
552
|
+
if (tr_ty != NONE)
|
|
553
|
+
transit_step();
|
|
554
|
+
else {
|
|
555
|
+
timer_start();
|
|
556
|
+
char l = nav_query();
|
|
557
|
+
unsigned t = timer_stop();
|
|
558
|
+
if (t > t_q) t_q = t;
|
|
559
|
+
if (l == NONE) {
|
|
560
|
+
if (px > cx) cx++;
|
|
561
|
+
else if (px < cx) cx--;
|
|
562
|
+
} else {
|
|
563
|
+
queries++;
|
|
564
|
+
char a = area_at[cy][cx], p = area_at[py][px];
|
|
565
|
+
if (lt[l] != exp_next[a * EXP_N + p]) bad++;
|
|
566
|
+
if (cx != lsx[l])
|
|
567
|
+
cx += cx < lsx[l] ? 1 : -1;
|
|
568
|
+
else {
|
|
569
|
+
tr_ty = lty[l]; tr_sx = lsx[l];
|
|
570
|
+
tr_ex = lex[l]; tr_ey = ley[l];
|
|
571
|
+
transit_step();
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
steps++;
|
|
576
|
+
if (tr_ty == NONE && cx == px && cy == py) {
|
|
577
|
+
wp++;
|
|
578
|
+
if (wp == NWP)
|
|
579
|
+
done = true;
|
|
580
|
+
else {
|
|
581
|
+
px = wp_x[wp]; py = wp_y[wp];
|
|
582
|
+
draw_at(px, py, 0x53, C_PLAYER);
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
draw_at(cx, cy, 0x51, C_CHASER);
|
|
586
|
+
put_dec(SCREEN + 44, t_q, 5);
|
|
587
|
+
put_dec(SCREEN + 54, t_los, 5);
|
|
588
|
+
put_dec(SCREEN + 80 + 3, steps, 3);
|
|
589
|
+
put_dec(SCREEN + 80 + 9, queries, 3);
|
|
590
|
+
|
|
591
|
+
if (done) {
|
|
592
|
+
char los_ok = 0;
|
|
593
|
+
for (char i = 0; i < NLOS; i++) {
|
|
594
|
+
los_begin(los_x0[i], los_y0[i], los_x1[i], los_y1[i]);
|
|
595
|
+
char r;
|
|
596
|
+
while ((r = los_step()) == 0)
|
|
597
|
+
;
|
|
598
|
+
if (r == los_exp[i]) los_ok++;
|
|
599
|
+
}
|
|
600
|
+
char fault = 0;
|
|
601
|
+
if (mismatch) fault = 1;
|
|
602
|
+
else if (bad) fault = 2;
|
|
603
|
+
else if (steps != EXP_STEPS || queries != EXP_QUERIES) fault = 3;
|
|
604
|
+
else if (los_ok != NLOS) fault = 4;
|
|
605
|
+
put_dec(SCREEN + 80 + 17, bad, 3);
|
|
606
|
+
put_dec(SCREEN + 80 + 25, mismatch, 3);
|
|
607
|
+
put_dec(SCREEN + 80 + 33, los_ok, 1);
|
|
608
|
+
char code = fault ? CODE_FAIL : CODE_PASS;
|
|
609
|
+
RESULT = code;
|
|
610
|
+
vic.color_border = fault ? VCOL_RED : VCOL_GREEN;
|
|
611
|
+
SCREEN[80 + 37] = 0x30 + code;
|
|
612
|
+
SCREEN[80 + 38] = 0x30 + fault;
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
return 0;
|
|
616
|
+
}
|
|
617
|
+
```
|
|
618
|
+
|
|
619
|
+
## Build
|
|
620
|
+
|
|
621
|
+
```bash
|
|
622
|
+
oscar64 -tm=c64 -O2 -o=nav-area-pathfinding.prg nav-area-pathfinding.c
|
|
623
|
+
```
|
|
624
|
+
|
|
625
|
+
Oscar64 1.32.271 builds it with no warnings; the PRG is 5,521 bytes.
|
|
626
|
+
|
|
627
|
+
The reference table and the step and query counts come from this
|
|
628
|
+
script (Python 3). It reads the same map with the same link rules but
|
|
629
|
+
finds route costs by Floyd-Warshall, so a fault in the listing's
|
|
630
|
+
Dijkstra search shows as a table mismatch. It prints `12 areas, 43
|
|
631
|
+
links`, the twelve rows of `exp_next` and `steps 299 queries 160 end
|
|
632
|
+
(38, 20) trail cells 156`.
|
|
633
|
+
|
|
634
|
+
```python
|
|
635
|
+
# nav_model.py: the reference for nav-area-pathfinding.c. Same map and
|
|
636
|
+
# link rules; route costs by Floyd-Warshall instead of Dijkstra. Prints
|
|
637
|
+
# the exp_next table and the step and query counts the listing compiles in.
|
|
638
|
+
MAP = [
|
|
639
|
+
"........................................",
|
|
640
|
+
"........................................",
|
|
641
|
+
"........................................",
|
|
642
|
+
"..######H#####..........######H######...",
|
|
643
|
+
"........H.....................H.........",
|
|
644
|
+
"........H.....................H.........",
|
|
645
|
+
"........H.....................H.........",
|
|
646
|
+
"....#H######...##H####..####H###........",
|
|
647
|
+
".....H...........H..........H...........",
|
|
648
|
+
".....H...........H..........H...........",
|
|
649
|
+
".....H...........H..........H...........",
|
|
650
|
+
"..#H#####H#.########......#########H##..",
|
|
651
|
+
"...H.....H.........................H....",
|
|
652
|
+
"...H.....H.........................H....",
|
|
653
|
+
"...H.....H.........................H....",
|
|
654
|
+
"...H..#########.....####H#####.....H....",
|
|
655
|
+
"...H....................H.....#####H....",
|
|
656
|
+
"...H....................H..........H....",
|
|
657
|
+
"...H....................H..........H....",
|
|
658
|
+
"...H....................H..........H....",
|
|
659
|
+
"...H....................H..........H....",
|
|
660
|
+
"########################################",
|
|
661
|
+
]
|
|
662
|
+
W, H = 40, len(MAP)
|
|
663
|
+
WALK, DROP, JUMP, LADDER = range(4)
|
|
664
|
+
|
|
665
|
+
def t(y, x):
|
|
666
|
+
if x < 0 or x >= W or y < 0:
|
|
667
|
+
return '.'
|
|
668
|
+
return '#' if y >= H else MAP[y][x]
|
|
669
|
+
|
|
670
|
+
def standable(y, x):
|
|
671
|
+
if not (0 <= y < H - 1 and 0 <= x < W) or t(y, x) == '#':
|
|
672
|
+
return False
|
|
673
|
+
return t(y + 1, x) == '#' or (t(y + 1, x) == 'H' and t(y, x) != 'H')
|
|
674
|
+
|
|
675
|
+
areas, area_at = [], {}
|
|
676
|
+
for y in range(H):
|
|
677
|
+
x = 0
|
|
678
|
+
while x < W:
|
|
679
|
+
if not standable(y, x):
|
|
680
|
+
x += 1
|
|
681
|
+
continue
|
|
682
|
+
x0 = x
|
|
683
|
+
while x < W and standable(y, x):
|
|
684
|
+
area_at[(y, x)] = len(areas)
|
|
685
|
+
x += 1
|
|
686
|
+
areas.append((y, x0, x - 1))
|
|
687
|
+
|
|
688
|
+
def fall_from(y, x):
|
|
689
|
+
if not 0 <= x < W or t(y, x) != '.':
|
|
690
|
+
return None
|
|
691
|
+
while not standable(y, x):
|
|
692
|
+
y += 1
|
|
693
|
+
if y >= H - 1 or t(y, x) != '.':
|
|
694
|
+
return None
|
|
695
|
+
return y
|
|
696
|
+
|
|
697
|
+
links = [] # (from, to, type, sx, ex, ey, cost)
|
|
698
|
+
for a, (y, x0, x1) in enumerate(areas):
|
|
699
|
+
for sx, d in ((x1, 1), (x0, -1)):
|
|
700
|
+
x = sx + d
|
|
701
|
+
land = fall_from(y, x)
|
|
702
|
+
if land is not None and land > y:
|
|
703
|
+
b = area_at[(land, x)]
|
|
704
|
+
if land == y + 1:
|
|
705
|
+
links += [(a, b, WALK, sx, x, land, 1), (b, a, WALK, x, sx, y, 1)]
|
|
706
|
+
else:
|
|
707
|
+
links.append((a, b, DROP, sx, x, land, land - y + 1))
|
|
708
|
+
if d == 1:
|
|
709
|
+
for gap in (1, 2):
|
|
710
|
+
bx = x1 + gap + 1
|
|
711
|
+
if (y, bx) in area_at and all(t(y - 1, i) == '.' for i in range(x1, bx + 1)) \
|
|
712
|
+
and all(t(y, i) == '.' for i in range(x1 + 1, bx)):
|
|
713
|
+
b = area_at[(y, bx)]
|
|
714
|
+
links += [(a, b, JUMP, x1, bx, y, gap + 2), (b, a, JUMP, bx, x1, y, gap + 2)]
|
|
715
|
+
break
|
|
716
|
+
for x in range(x0, x1 + 1):
|
|
717
|
+
if t(y + 1, x) == 'H':
|
|
718
|
+
yb = y + 1
|
|
719
|
+
while t(yb + 1, x) == 'H':
|
|
720
|
+
yb += 1
|
|
721
|
+
if (yb, x) in area_at:
|
|
722
|
+
b = area_at[(yb, x)]
|
|
723
|
+
links += [(a, b, LADDER, x, x, yb, yb - y), (b, a, LADDER, x, x, y, yb - y)]
|
|
724
|
+
|
|
725
|
+
N, INF = len(areas), 255
|
|
726
|
+
dist = [[0 if i == j else INF for j in range(N)] for i in range(N)]
|
|
727
|
+
for f, to, *_, c in links:
|
|
728
|
+
dist[f][to] = min(dist[f][to], c)
|
|
729
|
+
for k in range(N):
|
|
730
|
+
for i in range(N):
|
|
731
|
+
for j in range(N):
|
|
732
|
+
dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j])
|
|
733
|
+
nextlink = [[next((li for li, l in enumerate(links) if l[0] == i and dist[l[1]][j] < INF
|
|
734
|
+
and l[6] + dist[l[1]][j] == dist[i][j]), 255) if i != j else 255
|
|
735
|
+
for j in range(N)] for i in range(N)]
|
|
736
|
+
|
|
737
|
+
def step(tr, cx, cy):
|
|
738
|
+
ty, sx, ex, ey = tr
|
|
739
|
+
d = (ex > sx) - (ex < sx)
|
|
740
|
+
if ty == WALK:
|
|
741
|
+
return ex, ey
|
|
742
|
+
if ty == LADDER:
|
|
743
|
+
return cx, cy + (1 if ey > cy else -1)
|
|
744
|
+
if ty == DROP:
|
|
745
|
+
return (ex, cy) if cx != ex else (cx, cy + 1)
|
|
746
|
+
if cy == ey and cx == sx: # jump: up and over, across, down
|
|
747
|
+
return cx + d, cy - 1
|
|
748
|
+
return (cx + d, cy) if cx != ex else (cx, cy + 1)
|
|
749
|
+
|
|
750
|
+
def sim(start=(1, 20), wps=((34, 2), (4, 20), (32, 15), (10, 2), (13, 10), (7, 14), (26, 6), (38, 20))):
|
|
751
|
+
(cx, cy), wp, tr = start, 0, None
|
|
752
|
+
trail, steps, queries = {start}, 0, 0
|
|
753
|
+
while True:
|
|
754
|
+
px, py = wps[wp]
|
|
755
|
+
if tr:
|
|
756
|
+
cx, cy = step(tr, cx, cy)
|
|
757
|
+
elif area_at[(cy, cx)] == area_at[(py, px)]:
|
|
758
|
+
cx += (px > cx) - (px < cx)
|
|
759
|
+
else:
|
|
760
|
+
queries += 1
|
|
761
|
+
_, _, ty, sx, ex, ey, _ = links[nextlink[area_at[(cy, cx)]][area_at[(py, px)]]]
|
|
762
|
+
if cx != sx:
|
|
763
|
+
cx += (sx > cx) - (sx < cx)
|
|
764
|
+
else:
|
|
765
|
+
tr = (ty, sx, ex, ey)
|
|
766
|
+
cx, cy = step(tr, cx, cy)
|
|
767
|
+
if tr and (cx, cy) == tr[2:]:
|
|
768
|
+
tr = None
|
|
769
|
+
steps += 1
|
|
770
|
+
trail.add((cx, cy))
|
|
771
|
+
if not tr and (cx, cy) == (px, py):
|
|
772
|
+
wp += 1
|
|
773
|
+
if wp == len(wps):
|
|
774
|
+
return trail, steps, queries, (cx, cy)
|
|
775
|
+
|
|
776
|
+
if __name__ == '__main__':
|
|
777
|
+
print(N, 'areas,', len(links), 'links')
|
|
778
|
+
for i in range(N):
|
|
779
|
+
print(', '.join('%3d' % (links[nextlink[i][j]][1] if nextlink[i][j] != 255 else 255)
|
|
780
|
+
for j in range(N)) + ',')
|
|
781
|
+
trail, steps, queries, end = sim()
|
|
782
|
+
print('steps', steps, 'queries', queries, 'end', end, 'trail cells', len(trail))
|
|
783
|
+
```
|
|
784
|
+
|
|
785
|
+
## Expected output
|
|
786
|
+
|
|
787
|
+
Black background. Rows 0 to 2 are the HUD. Below them the level: green
|
|
788
|
+
platforms, orange ladders (`H`), a cyan trail of dots over every cell
|
|
789
|
+
the chaser passed through (ladder cells it climbed turn cyan), and the
|
|
790
|
+
chaser, a white ball, at the bottom right on column 38 of screen row 23.
|
|
791
|
+
The player marker (a yellow heart) is under the chaser at the end, so it
|
|
792
|
+
does not show.
|
|
793
|
+
|
|
794
|
+
The route uses all four link types: 138 of the 160 queries chose a
|
|
795
|
+
ladder, 9 a walk (the one-row step between the platform at map row 14
|
|
796
|
+
and the one at row 15), 7 a jump and 6 a drop (counted by the model).
|
|
797
|
+
|
|
798
|
+
HUD at 26,000,000 cycles (measured in VICE x64sc 3.10, decoded against
|
|
799
|
+
the character ROM):
|
|
800
|
+
|
|
801
|
+
| Row | PAL | NTSC |
|
|
802
|
+
|---|---|---|
|
|
803
|
+
| 0 | `BUILD 0703502 SEARCH 016061 N 12 43` | `BUILD 0709939 SEARCH 016134 N 12 43` |
|
|
804
|
+
| 1 | `QRY 00154 LOS 00369 AR 407948 NX 105602` | `QRY 00154 LOS 00369 AR 411726 NX 106063` |
|
|
805
|
+
| 2 | `ST 299 Q 160 BAD 000 MIS 000 LOS 4 R 10` | same |
|
|
806
|
+
|
|
807
|
+
`BUILD` is the whole start-up in cycles; `SEARCH` the worst of the
|
|
808
|
+
twelve single-destination searches; `AR` the area and link pass; `NX`
|
|
809
|
+
the next-hop pass. `QRY` and `LOS` are the worst query and the worst
|
|
810
|
+
ray step over the run. `ST` and `Q` are chaser steps and table queries,
|
|
811
|
+
equal to the model's 299 and 160. `BAD` counts hops that differed from
|
|
812
|
+
the compiled table, `MIS` table entries that differed, `LOS 4` the four
|
|
813
|
+
ray tests that gave the expected answer, `R 10` result code 1, fault 0.
|
|
814
|
+
The border is green: (98, 213, 50) on PAL, (114, 189, 103) on NTSC.
|
|
815
|
+
|
|
816
|
+
The build differs between models because the screen is on while it
|
|
817
|
+
runs. The 25 badlines of a frame steal the same cycles on both models,
|
|
818
|
+
a larger share of NTSC's 17,095-cycle frame than of PAL's 19,656, and
|
|
819
|
+
the CIA counts the stolen cycles (arithmetic, rung 3; not separated by
|
|
820
|
+
measurement here). The per-frame figures are identical because
|
|
821
|
+
they run after `vic_waitFrame()` returns, in the vertical blank. The
|
|
822
|
+
empty timer pair reads 5 cycles and the chained pair 17 (measured in a
|
|
823
|
+
separate build); the figures include them.
|
|
824
|
+
|
|
825
|
+
Screenshots at 26,000,000 cycles, both after the verdict and each
|
|
826
|
+
identical over two runs: `screenshots/nav-area-pathfinding.png` (PAL)
|
|
827
|
+
and `screenshots/nav-area-pathfinding-ntsc.png` (NTSC). Measured on both
|
|
828
|
+
with PIL: every map cell holding a cyan pixel, plus the one holding
|
|
829
|
+
white, is the set of cells the model's chaser visited, 156 cells with
|
|
830
|
+
none missing and none extra, and the white cell is (38, 20) in map
|
|
831
|
+
coordinates, the model's end position. The script:
|
|
832
|
+
|
|
833
|
+
```python
|
|
834
|
+
from PIL import Image
|
|
835
|
+
import nav_model
|
|
836
|
+
def visited(png, ntsc):
|
|
837
|
+
cyan = (138, 230, 203) if ntsc else (126, 243, 214)
|
|
838
|
+
top = 23 if ntsc else 35 # PNG row of text row 0
|
|
839
|
+
px = Image.open(png).convert('RGB').load()
|
|
840
|
+
cells = set()
|
|
841
|
+
for y in range(22): # map row y is screen row y + 3
|
|
842
|
+
for x in range(40):
|
|
843
|
+
cols = {px[32 + 8 * x + i, top + 8 * (y + 3) + j]
|
|
844
|
+
for i in range(8) for j in range(8)}
|
|
845
|
+
if cyan in cols or (255, 255, 255) in cols:
|
|
846
|
+
cells.add((x, y))
|
|
847
|
+
return cells
|
|
848
|
+
assert visited('nav-area-pathfinding.png', False) == nav_model.sim()[0]
|
|
849
|
+
```
|
|
850
|
+
|
|
851
|
+
## Why this works
|
|
852
|
+
|
|
853
|
+
The area graph is small because a platform game's walkable space is
|
|
854
|
+
mostly runs of floor. Twelve areas replace 880 map cells, so a search
|
|
855
|
+
touches twelve nodes and 43 links instead of hundreds of cells, and a
|
|
856
|
+
table of every answer is 144 bytes (the listing pads the stride to 16,
|
|
857
|
+
256 bytes, so the index is one table multiply). A standing actor then needs two
|
|
858
|
+
cell lookups and one table read per decision, 154 cycles here, where
|
|
859
|
+
one run-time search costs about 16,000. The build runs once at level
|
|
860
|
+
load, about 36 PAL frames here, most of it the cell-by-cell area pass.
|
|
861
|
+
|
|
862
|
+
The link rules carry the movement model. An area's end cell leads to a
|
|
863
|
+
fall; a one-row fall is a walk both ways, a longer one a one-way drop.
|
|
864
|
+
A gap of one or two cells to an area on the same row is a jump both
|
|
865
|
+
ways. A ladder joins the area over its top rung to the area at its
|
|
866
|
+
foot. The actor walks inside its area to the link's start cell and then
|
|
867
|
+
plays the link cell by cell, so the route chosen at the area level is
|
|
868
|
+
the route drawn on screen.
|
|
869
|
+
|
|
870
|
+
Link costs count cells moved during the link only; walking inside an
|
|
871
|
+
area is free to the search. That keeps the table exact for the graph
|
|
872
|
+
but lets a route cross a wide platform to save one cell of ladder. A
|
|
873
|
+
game that cares adds the walk from entry to exit, which needs areas
|
|
874
|
+
split at link points. The lowest-numbered link on a shortest route
|
|
875
|
+
breaks ties, the same rule in C and Python, so the two tables agree
|
|
876
|
+
byte for byte.
|
|
877
|
+
|
|
878
|
+
The line-of-sight ray steps one cell per call through the map and stops
|
|
879
|
+
at the first solid cell or the target. Spread over frames, one ray step
|
|
880
|
+
costs at most 369 cycles; the test pairs are straight rows and columns,
|
|
881
|
+
whose answer does not depend on the line algorithm.
|