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,975 @@
|
|
|
1
|
+
---
|
|
2
|
+
recipe: dig-and-guards
|
|
3
|
+
toolchain: oscar64
|
|
4
|
+
output_format: PRG
|
|
5
|
+
region: both
|
|
6
|
+
techniques: [dig_and_refill]
|
|
7
|
+
file_formats: [PRG]
|
|
8
|
+
uses_registers: [D011, D020, D021, DC06, DC07, DC0F]
|
|
9
|
+
uses_kernal: []
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
<!-- doc-type: recipe -->
|
|
13
|
+
|
|
14
|
+
# Oscar64 Dig and Guards: holes that refill, a guard that falls in, climbs out and dies
|
|
15
|
+
|
|
16
|
+
## Synopsis
|
|
17
|
+
|
|
18
|
+
A 28 x 16 cell level with a brick floor, two ladders and a solid bottom.
|
|
19
|
+
A scripted player (autopilot) digs a hole beside it, waits for the guard
|
|
20
|
+
to fall in, walks over the trapped guard's head, runs on and digs a
|
|
21
|
+
second hole. The guard climbs out of the first hole before it refills,
|
|
22
|
+
falls into the second, and is still inside when it refills: it dies and
|
|
23
|
+
respawns on the top row, lands on the brick floor, walks to the nearest
|
|
24
|
+
ladder and climbs down after the player. Every tick folds the map and
|
|
25
|
+
all actor states into a 16-bit checksum, and every 16th tick compares it
|
|
26
|
+
with a value from a Python model of the same rules, compiled in. After
|
|
27
|
+
the script one stress tick runs the technique's worst frame on purpose.
|
|
28
|
+
The screen shows event counts, CIA1 timer B cycles and PASS or FAIL.
|
|
29
|
+
`$02FF` = `01` and a green border on pass, `02` and red on fail. This is
|
|
30
|
+
the `dig_and_refill` technique in `docs/techniques/logic.md`; the
|
|
31
|
+
result-byte contract is `headless-verify.md`.
|
|
32
|
+
|
|
33
|
+
## Source
|
|
34
|
+
|
|
35
|
+
```c
|
|
36
|
+
// dig-and-guards.c
|
|
37
|
+
//
|
|
38
|
+
// Dig-and-refill bricks and a chasing guard on a 28 x 16 cell map. The
|
|
39
|
+
// player digs a brick diagonally below-left or below-right when the cell
|
|
40
|
+
// above it is empty. The hole goes into an eight-slot timer list: it
|
|
41
|
+
// shows a refill glyph for its last 16 ticks and is brick again at 0.
|
|
42
|
+
// A guard that falls into a hole is trapped for 30 guard ticks, then
|
|
43
|
+
// climbs out and steps sideways. Anyone standing over a trapped guard is
|
|
44
|
+
// held up by it. A hole that refills on a guard kills it, and the guard
|
|
45
|
+
// respawns on the top row. Guards move on even ticks by a greedy rule:
|
|
46
|
+
// straight at the player along a clear row, up or down a ladder they
|
|
47
|
+
// stand on, else to the nearest column on their row that offers a move
|
|
48
|
+
// toward the player's row, else toward the player's column.
|
|
49
|
+
// The player follows a script (autopilot). A checksum of the map and all
|
|
50
|
+
// actor states is folded every tick and compared every 16 ticks with the
|
|
51
|
+
// values from a Python model of the same rules, compiled in.
|
|
52
|
+
// After the script, one stress tick: four free guards scan their whole
|
|
53
|
+
// row, eight live holes on the ledge (one expires, one starts refilling),
|
|
54
|
+
// and the player tries a dig with the hole list full.
|
|
55
|
+
// Row 0: tick, digs, traps, escapes, kills, walk-over ticks. Row 1: CIA1
|
|
56
|
+
// timer B cycles, worst hole-list update, worst single guard update,
|
|
57
|
+
// worst tick. Row 2: stress tick total, its hole-list update and its
|
|
58
|
+
// worst guard, checkpoint misses, result. Row 3: final checksum, worst
|
|
59
|
+
// player update (move or dig).
|
|
60
|
+
// The screen keeps the scenario's last tick; the stress tick is not drawn.
|
|
61
|
+
// $02FF = 01 and a green border on pass, 02 and red on fail.
|
|
62
|
+
// Build: oscar64 -tm=c64 -O2 -o=dig-and-guards.prg dig-and-guards.c
|
|
63
|
+
#include <c64/vic.h>
|
|
64
|
+
#include <c64/cia.h>
|
|
65
|
+
#include <string.h>
|
|
66
|
+
|
|
67
|
+
#define SCREEN ((char *)0x0400)
|
|
68
|
+
#define COLOUR ((char *)0xd800)
|
|
69
|
+
#define RESULT (*(volatile char *)0x02ff)
|
|
70
|
+
#define CODE_PASS 0x01
|
|
71
|
+
#define CODE_FAIL 0x02
|
|
72
|
+
|
|
73
|
+
#define W 28
|
|
74
|
+
#define H 16
|
|
75
|
+
#define ROW0 5 // screen row of map row 0
|
|
76
|
+
#define COL0 6 // screen column of map column 0
|
|
77
|
+
|
|
78
|
+
enum { T_E, T_B, T_S, T_L, T_HOLE, T_FILL };
|
|
79
|
+
|
|
80
|
+
#define HOLE_T 80 // ticks from dig to brick
|
|
81
|
+
#define REFILL_T 16 // refill glyph from this count
|
|
82
|
+
#define T_TRAP 30 // guard ticks spent in a hole
|
|
83
|
+
#define NH 8
|
|
84
|
+
#define NG 4
|
|
85
|
+
#define RESPAWN_X 13
|
|
86
|
+
|
|
87
|
+
static const char level[H][W + 1] = {
|
|
88
|
+
"............................",
|
|
89
|
+
"............................",
|
|
90
|
+
"............................",
|
|
91
|
+
"###########.................",
|
|
92
|
+
"............................",
|
|
93
|
+
"............................",
|
|
94
|
+
"............................",
|
|
95
|
+
"SS#H######################HS",
|
|
96
|
+
"...H......................H.",
|
|
97
|
+
"...H......................H.",
|
|
98
|
+
"...H......................H.",
|
|
99
|
+
"...H......................H.",
|
|
100
|
+
"...H......................H.",
|
|
101
|
+
"...H......................H.",
|
|
102
|
+
"...H......................H.",
|
|
103
|
+
"SSSSSSSSSSSSSSSSSSSSSSSSSSSS",
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
// Autopilot: action, ticks. Z digs left, X digs right, W waits.
|
|
107
|
+
struct Step { char act, n; };
|
|
108
|
+
static const struct Step script[] = {
|
|
109
|
+
{'X', 1}, {'W', 12}, {'R', 16}, {'Z', 1}, {'W', 82},
|
|
110
|
+
{'R', 2}, {'D', 8}, {'L', 10}, {'W', 36},
|
|
111
|
+
};
|
|
112
|
+
#define NSTEPS (sizeof(script) / sizeof(script[0]))
|
|
113
|
+
|
|
114
|
+
// From dig_model.py (see the page): checksum after every 16th tick,
|
|
115
|
+
// after the last tick (168), and after the stress tick.
|
|
116
|
+
static const unsigned exp_check[] = {
|
|
117
|
+
0xbfa0, 0x2b2a, 0x8f96, 0x94c2, 0x3c57,
|
|
118
|
+
0x859c, 0x585a, 0xb6b3, 0x1f4b, 0x3dfa,
|
|
119
|
+
};
|
|
120
|
+
#define NCHECK 10
|
|
121
|
+
#define EXP_TICKS 168
|
|
122
|
+
#define EXP_FINAL 0xefbe
|
|
123
|
+
#define EXP_STRESS 0x9760
|
|
124
|
+
|
|
125
|
+
char map[H][W];
|
|
126
|
+
char *rowp[H]; // row pointers: no multiply by 28
|
|
127
|
+
char hx[NH], hy[NH], ht[NH]; // hole list: cell and timer
|
|
128
|
+
char gx[NG], gy[NG], gst[NG], gcnt[NG], gon[NG]; // st 0 free, 1 trapped, 2 escaping
|
|
129
|
+
char px, py, alive;
|
|
130
|
+
char digs, traps, escs, kills, walk;
|
|
131
|
+
|
|
132
|
+
char dirty_x[24], dirty_y[24], ndirty;
|
|
133
|
+
|
|
134
|
+
static inline void set_tile(char x, char y, char t)
|
|
135
|
+
{
|
|
136
|
+
rowp[y][x] = t;
|
|
137
|
+
dirty_x[ndirty] = x;
|
|
138
|
+
dirty_y[ndirty] = y;
|
|
139
|
+
ndirty++;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
static inline bool blocked(char t)
|
|
143
|
+
{
|
|
144
|
+
return t == T_B || t == T_S;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
signed char guard_at(char x, char y)
|
|
148
|
+
{
|
|
149
|
+
for (char i = 0; i < NG; i++)
|
|
150
|
+
if (gon[i] && gx[i] == x && gy[i] == y)
|
|
151
|
+
return i;
|
|
152
|
+
return -1;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
bool trapped_at(char x, char y)
|
|
156
|
+
{
|
|
157
|
+
signed char i = guard_at(x, y);
|
|
158
|
+
return i >= 0 && gst[i] == 1;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
bool supported(char x, char y)
|
|
162
|
+
{
|
|
163
|
+
if (rowp[y][x] == T_L)
|
|
164
|
+
return true;
|
|
165
|
+
char b = rowp[y + 1][x];
|
|
166
|
+
if (b == T_B || b == T_S || b == T_L)
|
|
167
|
+
return true;
|
|
168
|
+
return (b == T_HOLE || b == T_FILL) && trapped_at(x, y + 1);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// --- digging and the hole list -------------------------------------------
|
|
172
|
+
void dig(signed char dx)
|
|
173
|
+
{
|
|
174
|
+
signed char tx = (signed char)px + dx;
|
|
175
|
+
char ty = py + 1;
|
|
176
|
+
if (tx < 0 || tx >= W)
|
|
177
|
+
return;
|
|
178
|
+
if (rowp[ty][tx] != T_B || rowp[py][tx] != T_E || guard_at(tx, py) >= 0)
|
|
179
|
+
return;
|
|
180
|
+
for (char i = 0; i < NH; i++) {
|
|
181
|
+
if (ht[i] == 0) {
|
|
182
|
+
hx[i] = tx; hy[i] = ty; ht[i] = HOLE_T;
|
|
183
|
+
set_tile(tx, ty, T_HOLE);
|
|
184
|
+
digs++;
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
void holes_update(void)
|
|
191
|
+
{
|
|
192
|
+
for (char i = 0; i < NH; i++) {
|
|
193
|
+
if (ht[i] == 0)
|
|
194
|
+
continue;
|
|
195
|
+
char t = --ht[i];
|
|
196
|
+
char x = hx[i], y = hy[i];
|
|
197
|
+
if (t == REFILL_T) {
|
|
198
|
+
set_tile(x, y, T_FILL);
|
|
199
|
+
} else if (t == 0) {
|
|
200
|
+
set_tile(x, y, T_B);
|
|
201
|
+
for (char g = 0; g < NG; g++) {
|
|
202
|
+
if (gon[g] && gx[g] == x && gy[g] == y) {
|
|
203
|
+
gx[g] = RESPAWN_X; gy[g] = 0; gst[g] = 0; gcnt[g] = 0;
|
|
204
|
+
kills++;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
if (px == x && py == y)
|
|
208
|
+
alive = 0;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// --- player --------------------------------------------------------------
|
|
214
|
+
void player_update(char a)
|
|
215
|
+
{
|
|
216
|
+
char x = px, y = py;
|
|
217
|
+
if (!supported(x, y))
|
|
218
|
+
py++;
|
|
219
|
+
else if (a == 'L' && x > 0 && !blocked(rowp[y][x - 1]))
|
|
220
|
+
px--;
|
|
221
|
+
else if (a == 'R' && x < W - 1 && !blocked(rowp[y][x + 1]))
|
|
222
|
+
px++;
|
|
223
|
+
else if (a == 'U' && rowp[y][x] == T_L && !blocked(rowp[y - 1][x]))
|
|
224
|
+
py--;
|
|
225
|
+
else if (a == 'D' && !blocked(rowp[y + 1][x]) && guard_at(x, y + 1) < 0)
|
|
226
|
+
py++;
|
|
227
|
+
else if (a == 'Z')
|
|
228
|
+
dig(-1);
|
|
229
|
+
else if (a == 'X')
|
|
230
|
+
dig(1);
|
|
231
|
+
char b = rowp[py + 1][px];
|
|
232
|
+
if ((b == T_HOLE || b == T_FILL) && trapped_at(px, py + 1))
|
|
233
|
+
walk++;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// --- guards --------------------------------------------------------------
|
|
237
|
+
signed char mdx, mdy;
|
|
238
|
+
|
|
239
|
+
// The guard's row and the rows above and below it, fetched once per
|
|
240
|
+
// decision so the scan does no row arithmetic.
|
|
241
|
+
const char *r_up, *r_at, *r_dn;
|
|
242
|
+
char s_y;
|
|
243
|
+
|
|
244
|
+
static inline bool held(signed char c) // can stand at column c
|
|
245
|
+
{
|
|
246
|
+
if (r_at[c] == T_L)
|
|
247
|
+
return true;
|
|
248
|
+
char b = r_dn[c];
|
|
249
|
+
if (b == T_B || b == T_S || b == T_L)
|
|
250
|
+
return true;
|
|
251
|
+
return (b == T_HOLE || b == T_FILL) && trapped_at(c, s_y + 1);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// One cell of the row scan: 0 the scan stops here, 1 this column offers
|
|
255
|
+
// a move toward the player's row, 2 walk on past it.
|
|
256
|
+
char probe(signed char c)
|
|
257
|
+
{
|
|
258
|
+
if (c < 0 || c >= W || blocked(r_at[c]))
|
|
259
|
+
return 0;
|
|
260
|
+
if (py < s_y) {
|
|
261
|
+
if (r_at[c] == T_L && !blocked(r_up[c]))
|
|
262
|
+
return 1;
|
|
263
|
+
} else {
|
|
264
|
+
char b = r_dn[c];
|
|
265
|
+
if (b == T_L || b == T_E)
|
|
266
|
+
return 1;
|
|
267
|
+
}
|
|
268
|
+
return held(c) ? 2 : 0;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
void decide(char g)
|
|
272
|
+
{
|
|
273
|
+
char x = gx[g], y = gy[g];
|
|
274
|
+
s_y = y;
|
|
275
|
+
r_at = rowp[y];
|
|
276
|
+
r_dn = rowp[y + 1];
|
|
277
|
+
r_up = y ? rowp[y - 1] : r_at;
|
|
278
|
+
mdx = 0; mdy = 0;
|
|
279
|
+
if (y == py && x != px) {
|
|
280
|
+
signed char d = px > x ? 1 : -1;
|
|
281
|
+
signed char c = x;
|
|
282
|
+
for (;;) {
|
|
283
|
+
c += d;
|
|
284
|
+
if (blocked(r_at[c]) || !held(c))
|
|
285
|
+
break;
|
|
286
|
+
if (c == px) { mdx = d; return; }
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
if (py < y && r_at[x] == T_L && !blocked(r_up[x])) { mdy = -1; return; }
|
|
290
|
+
if (py > y) {
|
|
291
|
+
char b = r_dn[x];
|
|
292
|
+
if (b == T_L || b == T_E) { mdy = 1; return; }
|
|
293
|
+
}
|
|
294
|
+
if (py != y) {
|
|
295
|
+
signed char cl = x, cr = x;
|
|
296
|
+
bool open_l = true, open_r = true;
|
|
297
|
+
while (open_l || open_r) {
|
|
298
|
+
if (open_l) {
|
|
299
|
+
char r = probe(--cl);
|
|
300
|
+
if (r == 1) { mdx = -1; return; }
|
|
301
|
+
if (r == 0) open_l = false;
|
|
302
|
+
}
|
|
303
|
+
if (open_r) {
|
|
304
|
+
char r = probe(++cr);
|
|
305
|
+
if (r == 1) { mdx = 1; return; }
|
|
306
|
+
if (r == 0) open_r = false;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
if (px != x)
|
|
311
|
+
mdx = px > x ? 1 : -1;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
bool guard_step(char g, signed char dx, signed char dy)
|
|
315
|
+
{
|
|
316
|
+
signed char nx = (signed char)gx[g] + dx;
|
|
317
|
+
char ny = gy[g] + dy;
|
|
318
|
+
if (nx < 0 || nx >= W || blocked(rowp[ny][nx]) || guard_at(nx, ny) >= 0)
|
|
319
|
+
return false;
|
|
320
|
+
gx[g] = nx; gy[g] = ny;
|
|
321
|
+
return true;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
void guard_update(char g)
|
|
325
|
+
{
|
|
326
|
+
if (!gon[g])
|
|
327
|
+
return;
|
|
328
|
+
if (gst[g] == 1) {
|
|
329
|
+
if (--gcnt[g] == 0) {
|
|
330
|
+
if (guard_step(g, 0, -1)) { gst[g] = 2; escs++; }
|
|
331
|
+
else gcnt[g] = 1;
|
|
332
|
+
}
|
|
333
|
+
} else if (gst[g] == 2) {
|
|
334
|
+
signed char d = px >= gx[g] ? 1 : -1;
|
|
335
|
+
if (!guard_step(g, d, 0))
|
|
336
|
+
guard_step(g, -d, 0);
|
|
337
|
+
gst[g] = 0;
|
|
338
|
+
} else if (!supported(gx[g], gy[g])) {
|
|
339
|
+
gy[g]++;
|
|
340
|
+
char t = rowp[gy[g]][gx[g]];
|
|
341
|
+
if (t == T_HOLE || t == T_FILL) {
|
|
342
|
+
gst[g] = 1; gcnt[g] = T_TRAP;
|
|
343
|
+
traps++;
|
|
344
|
+
}
|
|
345
|
+
} else {
|
|
346
|
+
decide(g);
|
|
347
|
+
if (mdx || mdy)
|
|
348
|
+
guard_step(g, mdx, mdy);
|
|
349
|
+
}
|
|
350
|
+
if (gx[g] == px && gy[g] == py)
|
|
351
|
+
alive = 0;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
// --- checksum (outside the timed work) --------------------------------------
|
|
355
|
+
unsigned digest(void)
|
|
356
|
+
{
|
|
357
|
+
unsigned v = 0;
|
|
358
|
+
const char *p = &map[0][0];
|
|
359
|
+
for (unsigned i = 0; i < W * H; i++)
|
|
360
|
+
v += p[i];
|
|
361
|
+
for (char g = 0; g < NG; g++)
|
|
362
|
+
v += gx[g] + (unsigned)gy[g] * 32 + (unsigned)gst[g] * 1024 + gcnt[g]
|
|
363
|
+
+ (unsigned)gon[g] * 4096;
|
|
364
|
+
v += px + (unsigned)py * 32 + (unsigned)alive * 1024;
|
|
365
|
+
return v;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
static inline unsigned rol16(unsigned c)
|
|
369
|
+
{
|
|
370
|
+
return (c << 1) | (c >> 15);
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
// --- CIA1 timer B harness ----------------------------------------------------
|
|
374
|
+
static inline void timer_start(void)
|
|
375
|
+
{
|
|
376
|
+
cia1.crb = 0x00;
|
|
377
|
+
cia1.tb = 0xffff;
|
|
378
|
+
cia1.crb = 0x11;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
static inline unsigned timer_stop(void)
|
|
382
|
+
{
|
|
383
|
+
cia1.crb = 0x00;
|
|
384
|
+
return 0xffff - cia1.tb;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
// --- drawing ----------------------------------------------------------------
|
|
388
|
+
static const char tile_char[6] = { 0x20, 0x66, 0xa0, 0x08, 0x20, 0x62 };
|
|
389
|
+
static const char tile_col[6] = { VCOL_BLACK, VCOL_RED, VCOL_LT_GREY,
|
|
390
|
+
VCOL_YELLOW, VCOL_BLACK, VCOL_ORANGE };
|
|
391
|
+
|
|
392
|
+
void draw_cell(char x, char y)
|
|
393
|
+
{
|
|
394
|
+
unsigned o = (unsigned)(ROW0 + y) * 40 + COL0 + x;
|
|
395
|
+
char t = rowp[y][x];
|
|
396
|
+
SCREEN[o] = tile_char[t];
|
|
397
|
+
COLOUR[o] = tile_col[t];
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
void draw_actor(char x, char y, char ch, char col)
|
|
401
|
+
{
|
|
402
|
+
unsigned o = (unsigned)(ROW0 + y) * 40 + COL0 + x;
|
|
403
|
+
SCREEN[o] = ch;
|
|
404
|
+
COLOUR[o] = col;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
void put_str(char *p, const char *s)
|
|
408
|
+
{
|
|
409
|
+
while (*s)
|
|
410
|
+
*p++ = *s++;
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
void put_dec(char *p, unsigned v, char digits)
|
|
414
|
+
{
|
|
415
|
+
for (char i = digits; i > 0; i--) {
|
|
416
|
+
p[i - 1] = 0x30 + v % 10;
|
|
417
|
+
v /= 10;
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
void put_hex(char *p, unsigned v)
|
|
422
|
+
{
|
|
423
|
+
for (char i = 4; i > 0; i--) {
|
|
424
|
+
char n = v & 15;
|
|
425
|
+
p[i - 1] = n < 10 ? 0x30 + n : n - 9;
|
|
426
|
+
v >>= 4;
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
char ogx[NG], ogy[NG], opx, opy;
|
|
431
|
+
|
|
432
|
+
void redraw(void)
|
|
433
|
+
{
|
|
434
|
+
for (char i = 0; i < ndirty; i++)
|
|
435
|
+
draw_cell(dirty_x[i], dirty_y[i]);
|
|
436
|
+
ndirty = 0;
|
|
437
|
+
draw_cell(opx, opy);
|
|
438
|
+
for (char g = 0; g < NG; g++)
|
|
439
|
+
draw_cell(ogx[g], ogy[g]);
|
|
440
|
+
draw_actor(px, py, 0x53, VCOL_CYAN); // heart: the player
|
|
441
|
+
for (char g = 0; g < NG; g++) {
|
|
442
|
+
if (gon[g])
|
|
443
|
+
draw_actor(gx[g], gy[g], 0x51, gst[g] == 1 ? VCOL_PURPLE : VCOL_WHITE);
|
|
444
|
+
ogx[g] = gx[g]; ogy[g] = gy[g];
|
|
445
|
+
}
|
|
446
|
+
opx = px; opy = py;
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
int main(void)
|
|
450
|
+
{
|
|
451
|
+
__asm { sei }
|
|
452
|
+
vic.color_border = VCOL_BLACK;
|
|
453
|
+
vic.color_back = VCOL_BLACK;
|
|
454
|
+
memset(SCREEN, 0x20, 1000);
|
|
455
|
+
memset(COLOUR, VCOL_WHITE, 1000);
|
|
456
|
+
|
|
457
|
+
for (char y = 0; y < H; y++)
|
|
458
|
+
rowp[y] = map[y];
|
|
459
|
+
for (char y = 0; y < H; y++) {
|
|
460
|
+
for (char x = 0; x < W; x++) {
|
|
461
|
+
char c = level[y][x], t = T_E;
|
|
462
|
+
if (c == '#') t = T_B;
|
|
463
|
+
else if (c == 'S') t = T_S;
|
|
464
|
+
else if (c == 'H') t = T_L;
|
|
465
|
+
rowp[y][x] = t;
|
|
466
|
+
draw_cell(x, y);
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
gon[0] = 1; gx[0] = 14; gy[0] = 6;
|
|
470
|
+
px = 8; py = 6; alive = 1;
|
|
471
|
+
opx = px; opy = py;
|
|
472
|
+
redraw();
|
|
473
|
+
|
|
474
|
+
put_str(SCREEN, s"t dig trap esc kill walk");
|
|
475
|
+
put_str(SCREEN + 40, s"holes guard tick");
|
|
476
|
+
put_str(SCREEN + 80, s"st sh sg m r");
|
|
477
|
+
put_str(SCREEN + 120, s"cs pl");
|
|
478
|
+
|
|
479
|
+
unsigned cs = 0, tick = 0, t_hole = 0, t_guard = 0, t_tick = 0, t_play = 0;
|
|
480
|
+
char step = 0, left = script[0].n, miss = 0, ci = 0;
|
|
481
|
+
|
|
482
|
+
while (step < NSTEPS) {
|
|
483
|
+
vic_waitFrame();
|
|
484
|
+
char a = script[step].act;
|
|
485
|
+
|
|
486
|
+
unsigned tt = 0;
|
|
487
|
+
timer_start();
|
|
488
|
+
player_update(a);
|
|
489
|
+
tt = timer_stop();
|
|
490
|
+
if (tt > t_play) t_play = tt;
|
|
491
|
+
timer_start();
|
|
492
|
+
holes_update();
|
|
493
|
+
unsigned t = timer_stop();
|
|
494
|
+
tt += t;
|
|
495
|
+
if (t > t_hole) t_hole = t;
|
|
496
|
+
if ((tick & 1) == 0) {
|
|
497
|
+
for (char g = 0; g < NG; g++) {
|
|
498
|
+
timer_start();
|
|
499
|
+
guard_update(g);
|
|
500
|
+
t = timer_stop();
|
|
501
|
+
tt += t;
|
|
502
|
+
if (t > t_guard) t_guard = t;
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
if (tt > t_tick) t_tick = tt;
|
|
506
|
+
|
|
507
|
+
cs = rol16(cs) ^ digest();
|
|
508
|
+
tick++;
|
|
509
|
+
if ((tick & 15) == 0) {
|
|
510
|
+
if (ci >= NCHECK || cs != exp_check[ci])
|
|
511
|
+
miss++;
|
|
512
|
+
ci++;
|
|
513
|
+
}
|
|
514
|
+
redraw();
|
|
515
|
+
|
|
516
|
+
put_dec(SCREEN + 2, tick, 3);
|
|
517
|
+
put_dec(SCREEN + 10, digs, 1);
|
|
518
|
+
put_dec(SCREEN + 16, traps, 1);
|
|
519
|
+
put_dec(SCREEN + 22, escs, 1);
|
|
520
|
+
put_dec(SCREEN + 28, kills, 1);
|
|
521
|
+
put_dec(SCREEN + 34, walk, 3);
|
|
522
|
+
put_dec(SCREEN + 40 + 6, t_hole, 5);
|
|
523
|
+
put_dec(SCREEN + 40 + 18, t_guard, 5);
|
|
524
|
+
put_dec(SCREEN + 40 + 29, t_tick, 5);
|
|
525
|
+
|
|
526
|
+
if (--left == 0) {
|
|
527
|
+
step++;
|
|
528
|
+
if (step < NSTEPS)
|
|
529
|
+
left = script[step].n;
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
char fault = 0;
|
|
534
|
+
if (ci != NCHECK || miss) fault = 1;
|
|
535
|
+
else if (tick != EXP_TICKS || cs != EXP_FINAL) fault = 2;
|
|
536
|
+
else if (digs != 2 || traps != 2 || escs != 1 || kills != 1 || !walk || !alive) fault = 3;
|
|
537
|
+
|
|
538
|
+
// Stress tick: the technique's worst frame, built on purpose. One dig
|
|
539
|
+
// a tick and a fixed HOLE_T mean at most one hole expires and one
|
|
540
|
+
// starts refilling per tick. The holes sit on the ledge, off row 7,
|
|
541
|
+
// so they do not cut the guards' scans short.
|
|
542
|
+
static const char st_t[NH] = { 1, 17, 30, 40, 50, 60, 70, 79 };
|
|
543
|
+
for (char i = 0; i < NH; i++) {
|
|
544
|
+
hx[i] = 3 + i; hy[i] = 3; ht[i] = st_t[i];
|
|
545
|
+
set_tile(3 + i, 3, st_t[i] <= REFILL_T ? T_FILL : T_HOLE);
|
|
546
|
+
}
|
|
547
|
+
for (char g = 0; g < NG; g++) {
|
|
548
|
+
gon[g] = 1; gx[g] = 7 + 5 * g; gy[g] = 6; gst[g] = 0; gcnt[g] = 0;
|
|
549
|
+
}
|
|
550
|
+
px = 1; py = 2; // on the ledge; the dig finds the list full
|
|
551
|
+
vic_waitFrame();
|
|
552
|
+
timer_start();
|
|
553
|
+
player_update('X');
|
|
554
|
+
unsigned s_play = timer_stop();
|
|
555
|
+
timer_start();
|
|
556
|
+
holes_update();
|
|
557
|
+
unsigned s_hole = timer_stop(), s_guard = 0, t_stress = s_play + s_hole;
|
|
558
|
+
for (char g = 0; g < NG; g++) {
|
|
559
|
+
timer_start();
|
|
560
|
+
guard_update(g);
|
|
561
|
+
unsigned t = timer_stop();
|
|
562
|
+
t_stress += t;
|
|
563
|
+
if (t > s_guard) s_guard = t;
|
|
564
|
+
}
|
|
565
|
+
cs = rol16(cs) ^ digest();
|
|
566
|
+
if (!fault && cs != EXP_STRESS) fault = 4;
|
|
567
|
+
ndirty = 0; // the screen keeps the scenario's last tick
|
|
568
|
+
|
|
569
|
+
put_dec(SCREEN + 80 + 3, t_stress, 5);
|
|
570
|
+
put_dec(SCREEN + 80 + 12, s_hole, 5);
|
|
571
|
+
put_dec(SCREEN + 80 + 21, s_guard, 5);
|
|
572
|
+
put_dec(SCREEN + 80 + 29, miss, 2);
|
|
573
|
+
put_hex(SCREEN + 120 + 3, cs);
|
|
574
|
+
put_dec(SCREEN + 120 + 12, t_play, 5);
|
|
575
|
+
char code = fault ? CODE_FAIL : CODE_PASS;
|
|
576
|
+
RESULT = code;
|
|
577
|
+
vic.color_border = fault ? VCOL_RED : VCOL_GREEN;
|
|
578
|
+
SCREEN[80 + 34] = 0x30 + code;
|
|
579
|
+
SCREEN[80 + 35] = 0x30 + fault;
|
|
580
|
+
for (;;)
|
|
581
|
+
;
|
|
582
|
+
return 0;
|
|
583
|
+
}
|
|
584
|
+
```
|
|
585
|
+
|
|
586
|
+
## Build
|
|
587
|
+
|
|
588
|
+
```bash
|
|
589
|
+
oscar64 -tm=c64 -O2 -o=dig-and-guards.prg dig-and-guards.c
|
|
590
|
+
```
|
|
591
|
+
|
|
592
|
+
Oscar64 1.32.271 builds it with no warnings; the PRG is 4,629 bytes.
|
|
593
|
+
|
|
594
|
+
The checkpoint checksums, the final checksum and the stress checksum
|
|
595
|
+
come from this script (Python 3). It keeps the same map and rules as
|
|
596
|
+
objects and lists, not the C's arrays, and prints `ticks 168 digs 2
|
|
597
|
+
traps 2 escs 1 kills 1 walk 1 alive 1`, the ten checkpoints, `final
|
|
598
|
+
0xefbe` and `stress 0x9760`.
|
|
599
|
+
|
|
600
|
+
```python
|
|
601
|
+
# dig_model.py: the reference for dig-and-guards.c. Same map, same rules,
|
|
602
|
+
# same order of work per tick, written from the page's rule list, not
|
|
603
|
+
# from the C. Prints the checkpoint checksums, the event counts and the
|
|
604
|
+
# final positions the listing compiles in.
|
|
605
|
+
W, H = 28, 16
|
|
606
|
+
E, B, S, L, HO, F = 0, 1, 2, 3, 4, 5
|
|
607
|
+
HOLE_T, REFILL_T, T_TRAP, NH, NG = 80, 16, 30, 8, 4
|
|
608
|
+
RESPAWN_X = 13
|
|
609
|
+
LEVEL = [
|
|
610
|
+
"............................",
|
|
611
|
+
"............................",
|
|
612
|
+
"............................",
|
|
613
|
+
"###########.................",
|
|
614
|
+
"............................",
|
|
615
|
+
"............................",
|
|
616
|
+
"............................",
|
|
617
|
+
"SS#H######################HS",
|
|
618
|
+
"...H......................H.",
|
|
619
|
+
"...H......................H.",
|
|
620
|
+
"...H......................H.",
|
|
621
|
+
"...H......................H.",
|
|
622
|
+
"...H......................H.",
|
|
623
|
+
"...H......................H.",
|
|
624
|
+
"...H......................H.",
|
|
625
|
+
"SSSSSSSSSSSSSSSSSSSSSSSSSSSS",
|
|
626
|
+
]
|
|
627
|
+
SCRIPT = [("X", 1), ("W", 12), ("R", 16), ("Z", 1), ("W", 82),
|
|
628
|
+
("R", 2), ("D", 8), ("L", 10), ("W", 36)]
|
|
629
|
+
CHECK_EVERY = 16
|
|
630
|
+
|
|
631
|
+
class G:
|
|
632
|
+
def __init__(s, x, y, on):
|
|
633
|
+
s.x, s.y, s.st, s.cnt, s.on = x, y, 0, 0, on
|
|
634
|
+
|
|
635
|
+
def blocked(t):
|
|
636
|
+
return t == B or t == S
|
|
637
|
+
|
|
638
|
+
class World:
|
|
639
|
+
def __init__(s):
|
|
640
|
+
code = {'.': E, '#': B, 'S': S, 'H': L}
|
|
641
|
+
s.m = [[code[c] for c in row] for row in LEVEL]
|
|
642
|
+
s.hx, s.hy, s.ht = [0] * NH, [0] * NH, [0] * NH
|
|
643
|
+
s.g = [G(14, 6, 1), G(0, 0, 0), G(0, 0, 0), G(0, 0, 0)]
|
|
644
|
+
s.px, s.py, s.alive = 8, 6, 1
|
|
645
|
+
s.digs = s.traps = s.escs = s.kills = s.walk = 0
|
|
646
|
+
|
|
647
|
+
def guard_at(s, x, y):
|
|
648
|
+
for i, g in enumerate(s.g):
|
|
649
|
+
if g.on and g.x == x and g.y == y:
|
|
650
|
+
return i
|
|
651
|
+
return -1
|
|
652
|
+
|
|
653
|
+
def trapped_at(s, x, y):
|
|
654
|
+
i = s.guard_at(x, y)
|
|
655
|
+
return i >= 0 and s.g[i].st == 1
|
|
656
|
+
|
|
657
|
+
def supported(s, x, y):
|
|
658
|
+
if s.m[y][x] == L:
|
|
659
|
+
return True
|
|
660
|
+
b = s.m[y + 1][x]
|
|
661
|
+
if b in (B, S, L):
|
|
662
|
+
return True
|
|
663
|
+
return b in (HO, F) and s.trapped_at(x, y + 1)
|
|
664
|
+
|
|
665
|
+
def dig(s, dx):
|
|
666
|
+
tx, ty = s.px + dx, s.py + 1
|
|
667
|
+
if tx < 0 or tx >= W:
|
|
668
|
+
return
|
|
669
|
+
if s.m[ty][tx] != B or s.m[s.py][tx] != E or s.guard_at(tx, s.py) >= 0:
|
|
670
|
+
return
|
|
671
|
+
for i in range(NH):
|
|
672
|
+
if s.ht[i] == 0:
|
|
673
|
+
s.hx[i], s.hy[i], s.ht[i] = tx, ty, HOLE_T
|
|
674
|
+
s.m[ty][tx] = HO
|
|
675
|
+
s.digs += 1
|
|
676
|
+
return
|
|
677
|
+
|
|
678
|
+
def player(s, a):
|
|
679
|
+
x, y = s.px, s.py
|
|
680
|
+
if not s.supported(x, y):
|
|
681
|
+
s.py += 1
|
|
682
|
+
elif a == 'L' and x > 0 and not blocked(s.m[y][x - 1]):
|
|
683
|
+
s.px -= 1
|
|
684
|
+
elif a == 'R' and x < W - 1 and not blocked(s.m[y][x + 1]):
|
|
685
|
+
s.px += 1
|
|
686
|
+
elif a == 'U' and s.m[y][x] == L and not blocked(s.m[y - 1][x]):
|
|
687
|
+
s.py -= 1
|
|
688
|
+
elif a == 'D' and not blocked(s.m[y + 1][x]) and s.guard_at(x, y + 1) < 0:
|
|
689
|
+
s.py += 1
|
|
690
|
+
elif a == 'Z':
|
|
691
|
+
s.dig(-1)
|
|
692
|
+
elif a == 'X':
|
|
693
|
+
s.dig(1)
|
|
694
|
+
b = s.m[s.py + 1][s.px]
|
|
695
|
+
if b in (HO, F) and s.trapped_at(s.px, s.py + 1):
|
|
696
|
+
s.walk += 1
|
|
697
|
+
|
|
698
|
+
def holes(s):
|
|
699
|
+
for i in range(NH):
|
|
700
|
+
if s.ht[i] == 0:
|
|
701
|
+
continue
|
|
702
|
+
s.ht[i] -= 1
|
|
703
|
+
x, y = s.hx[i], s.hy[i]
|
|
704
|
+
if s.ht[i] == REFILL_T:
|
|
705
|
+
s.m[y][x] = F
|
|
706
|
+
elif s.ht[i] == 0:
|
|
707
|
+
s.m[y][x] = B
|
|
708
|
+
for g in s.g:
|
|
709
|
+
if g.on and g.x == x and g.y == y:
|
|
710
|
+
g.x, g.y, g.st, g.cnt = RESPAWN_X, 0, 0, 0
|
|
711
|
+
s.kills += 1
|
|
712
|
+
if s.px == x and s.py == y:
|
|
713
|
+
s.alive = 0
|
|
714
|
+
|
|
715
|
+
def decide(s, g):
|
|
716
|
+
x, y, m = g.x, g.y, s.m
|
|
717
|
+
if y == s.py and x != s.px:
|
|
718
|
+
d = 1 if s.px > x else -1
|
|
719
|
+
c = x
|
|
720
|
+
while True:
|
|
721
|
+
c += d
|
|
722
|
+
if blocked(m[y][c]) or not s.supported(c, y):
|
|
723
|
+
break
|
|
724
|
+
if c == s.px:
|
|
725
|
+
return d, 0
|
|
726
|
+
if s.py < y and m[y][x] == L and not blocked(m[y - 1][x]):
|
|
727
|
+
return 0, -1
|
|
728
|
+
if s.py > y and m[y + 1][x] in (L, E):
|
|
729
|
+
return 0, 1
|
|
730
|
+
if s.py != y:
|
|
731
|
+
open_l = open_r = True
|
|
732
|
+
for dist in range(1, W):
|
|
733
|
+
for d in (-1, 1):
|
|
734
|
+
if (open_l if d < 0 else open_r) is False:
|
|
735
|
+
continue
|
|
736
|
+
c = x + d * dist
|
|
737
|
+
if c < 0 or c >= W or blocked(m[y][c]):
|
|
738
|
+
if d < 0: open_l = False
|
|
739
|
+
else: open_r = False
|
|
740
|
+
continue
|
|
741
|
+
if s.py < y and m[y][c] == L and not blocked(m[y - 1][c]):
|
|
742
|
+
return d, 0
|
|
743
|
+
if s.py > y and m[y + 1][c] in (L, E):
|
|
744
|
+
return d, 0
|
|
745
|
+
if not s.supported(c, y):
|
|
746
|
+
if d < 0: open_l = False
|
|
747
|
+
else: open_r = False
|
|
748
|
+
if s.px != x:
|
|
749
|
+
return (1 if s.px > x else -1), 0
|
|
750
|
+
return 0, 0
|
|
751
|
+
|
|
752
|
+
def step(s, g, dx, dy):
|
|
753
|
+
nx, ny = g.x + dx, g.y + dy
|
|
754
|
+
if nx < 0 or nx >= W or blocked(s.m[ny][nx]) or s.guard_at(nx, ny) >= 0:
|
|
755
|
+
return False
|
|
756
|
+
g.x, g.y = nx, ny
|
|
757
|
+
return True
|
|
758
|
+
|
|
759
|
+
def guard(s, g):
|
|
760
|
+
if not g.on:
|
|
761
|
+
return
|
|
762
|
+
if g.st == 1:
|
|
763
|
+
g.cnt -= 1
|
|
764
|
+
if g.cnt == 0:
|
|
765
|
+
if s.step(g, 0, -1):
|
|
766
|
+
g.st = 2
|
|
767
|
+
s.escs += 1
|
|
768
|
+
else:
|
|
769
|
+
g.cnt = 1
|
|
770
|
+
elif g.st == 2:
|
|
771
|
+
d = 1 if s.px >= g.x else -1
|
|
772
|
+
if not s.step(g, d, 0):
|
|
773
|
+
s.step(g, -d, 0)
|
|
774
|
+
g.st = 0
|
|
775
|
+
elif not s.supported(g.x, g.y):
|
|
776
|
+
g.y += 1
|
|
777
|
+
if s.m[g.y][g.x] in (HO, F):
|
|
778
|
+
g.st, g.cnt = 1, T_TRAP
|
|
779
|
+
s.traps += 1
|
|
780
|
+
else:
|
|
781
|
+
dx, dy = s.decide(g)
|
|
782
|
+
if dx or dy:
|
|
783
|
+
s.step(g, dx, dy)
|
|
784
|
+
if g.x == s.px and g.y == s.py:
|
|
785
|
+
s.alive = 0
|
|
786
|
+
|
|
787
|
+
def digest(s):
|
|
788
|
+
v = sum(sum(r) for r in s.m)
|
|
789
|
+
for g in s.g:
|
|
790
|
+
v += g.x + g.y * 32 + g.st * 1024 + g.cnt + g.on * 4096
|
|
791
|
+
v += s.px + s.py * 32 + s.alive * 1024
|
|
792
|
+
return v & 0xffff
|
|
793
|
+
|
|
794
|
+
def rol(c):
|
|
795
|
+
return ((c << 1) | (c >> 15)) & 0xffff
|
|
796
|
+
|
|
797
|
+
def run():
|
|
798
|
+
w, cs, tick, checks = World(), 0, 0, []
|
|
799
|
+
for a, n in SCRIPT:
|
|
800
|
+
for _ in range(n):
|
|
801
|
+
w.player(a)
|
|
802
|
+
w.holes()
|
|
803
|
+
if tick & 1 == 0:
|
|
804
|
+
for g in w.g:
|
|
805
|
+
w.guard(g)
|
|
806
|
+
cs = rol(cs) ^ w.digest()
|
|
807
|
+
tick += 1
|
|
808
|
+
if tick % CHECK_EVERY == 0:
|
|
809
|
+
checks.append(cs)
|
|
810
|
+
return w, cs, tick, checks
|
|
811
|
+
|
|
812
|
+
def stress(w, cs):
|
|
813
|
+
# Worst frame: four free guards on row 6 each scan the whole row (the
|
|
814
|
+
# player is above and no column offers a climb); eight live holes on
|
|
815
|
+
# the ledge, off the guards' row, one expiring and one turning to the
|
|
816
|
+
# refill glyph; the player, on the ledge, tries a dig with the list full.
|
|
817
|
+
for i, t in enumerate((1, 17, 30, 40, 50, 60, 70, 79)):
|
|
818
|
+
x, y = 3 + i, 3
|
|
819
|
+
w.m[y][x] = F if t <= REFILL_T else HO
|
|
820
|
+
w.hx[i], w.hy[i], w.ht[i] = x, y, t
|
|
821
|
+
for i, gx in enumerate((7, 12, 17, 22)):
|
|
822
|
+
g = w.g[i]
|
|
823
|
+
g.on, g.x, g.y, g.st, g.cnt = 1, gx, 6, 0, 0
|
|
824
|
+
w.px, w.py = 1, 2
|
|
825
|
+
w.player('X')
|
|
826
|
+
w.holes()
|
|
827
|
+
for g in w.g:
|
|
828
|
+
w.guard(g)
|
|
829
|
+
return rol(cs) ^ w.digest()
|
|
830
|
+
|
|
831
|
+
if __name__ == "__main__":
|
|
832
|
+
w, cs, tick, checks = run()
|
|
833
|
+
print("ticks", tick, "digs", w.digs, "traps", w.traps, "escs", w.escs,
|
|
834
|
+
"kills", w.kills, "walk", w.walk, "alive", w.alive)
|
|
835
|
+
print("player", w.px, w.py, "guard", w.g[0].x, w.g[0].y, w.g[0].st)
|
|
836
|
+
print("checks", ", ".join("0x%04x" % c for c in checks))
|
|
837
|
+
print("final 0x%04x" % cs)
|
|
838
|
+
print("stress 0x%04x" % stress(w, cs))
|
|
839
|
+
```
|
|
840
|
+
|
|
841
|
+
## Expected output
|
|
842
|
+
|
|
843
|
+
Black background, green border. Rows 0 to 3 are the HUD. Below them the
|
|
844
|
+
level: an eleven-cell red brick ledge at the top left (used only by the
|
|
845
|
+
stress tick), a red brick floor with grey solid ends, two yellow `H`
|
|
846
|
+
ladders at map columns 3 and 26, and a grey solid bottom. The player, a
|
|
847
|
+
cyan heart, stands on the bottom row at map column 16; the guard, a white
|
|
848
|
+
ball, is on the same row at column 9, walking toward it. Both holes have
|
|
849
|
+
refilled, so the brick floor is whole again. The stress tick is not
|
|
850
|
+
drawn.
|
|
851
|
+
|
|
852
|
+
HUD at 16,000,000 cycles (measured in VICE x64sc 3.10, decoded against
|
|
853
|
+
the character ROM with PIL):
|
|
854
|
+
|
|
855
|
+
| Row | PAL | NTSC |
|
|
856
|
+
|---|---|---|
|
|
857
|
+
| 0 | `T 168 DIG 2 TRAP2 ESC 1 KILL1 WALK001` | same |
|
|
858
|
+
| 1 | `HOLES 00366 GUARD 03516 TICK 04075` | `HOLES 00366 GUARD 03559 TICK 04118` |
|
|
859
|
+
| 2 | `ST 19759 SH 00659 SG 04780 M 00 R 10` | `ST 19716 SH 00659 SG 04761 M 00 R 10` |
|
|
860
|
+
| 3 | `CS 9760 PL 00505` | same |
|
|
861
|
+
|
|
862
|
+
Row 0: 168 ticks, two digs, two traps, one escape, one kill, one tick
|
|
863
|
+
with the player held up by a trapped guard. Row 1, worst over the
|
|
864
|
+
scenario in CIA1 cycles: the hole-list update, one guard's update, and a
|
|
865
|
+
whole tick (player, holes and every guard). Row 2: the stress tick
|
|
866
|
+
(`ST`), its hole-list update (`SH`) and its slowest guard (`SG`), then
|
|
867
|
+
checkpoint misses (`M 00`) and the result, code 1 and fault 0. Row 3:
|
|
868
|
+
the final checksum, equal to the model's stress value `0x9760`, and the
|
|
869
|
+
worst player update (`PL`, a dig). The border is (98, 213, 50) on PAL
|
|
870
|
+
and (114, 189, 103) on NTSC.
|
|
871
|
+
|
|
872
|
+
A copy of the listing with one checkpoint constant changed by one bit
|
|
873
|
+
printed `M 01 R 21` and a red border (175, 60, 88) on PAL, so the
|
|
874
|
+
comparison can fail.
|
|
875
|
+
|
|
876
|
+
The two models differ only where the timed work reaches the visible
|
|
877
|
+
screen. `vic_waitFrame()` returns when the raster reaches line 256, so
|
|
878
|
+
the work starts in the vertical blank: about 104 lines, 6,552 cycles,
|
|
879
|
+
before the first badline on PAL and about 55 lines, 3,575 cycles, on
|
|
880
|
+
NTSC (arithmetic from 63 and 65 cycles a line; rung 3). The 4,075-cycle
|
|
881
|
+
tick fits the PAL gap and not the NTSC one. The stress tick is longer
|
|
882
|
+
than a whole frame on both models, so each run crosses every badline
|
|
883
|
+
once and the two figures end up 43 cycles apart; the CIA counts the
|
|
884
|
+
stolen cycles.
|
|
885
|
+
|
|
886
|
+
Screenshots at 16,000,000 cycles, both after the verdict and each
|
|
887
|
+
identical over two runs: `screenshots/dig-and-guards.png` (PAL) and
|
|
888
|
+
`screenshots/dig-and-guards-ntsc.png` (NTSC). Measured on both with PIL:
|
|
889
|
+
every one of the 448 map cells matches the model's last tick, glyph from
|
|
890
|
+
the character ROM and ink from the palette, with 0 wrong pixels. The
|
|
891
|
+
script:
|
|
892
|
+
|
|
893
|
+
```python
|
|
894
|
+
# Every map cell on the exit screenshot against the model's last tick:
|
|
895
|
+
# glyph from the character ROM, ink colour from the palette per model.
|
|
896
|
+
from PIL import Image
|
|
897
|
+
import dig_model
|
|
898
|
+
ROM = open('/opt/homebrew/opt/vice/share/vice/C64/chargen-901225-01.bin', 'rb').read()[:2048]
|
|
899
|
+
PAL = {0: (0, 0, 0), 1: (255, 255, 255), 2: (175, 60, 88), 3: (126, 243, 214),
|
|
900
|
+
4: (170, 64, 245), 7: (255, 255, 70), 8: (183, 99, 30), 15: (205, 205, 205)}
|
|
901
|
+
NTSC = {0: (0, 0, 0), 1: (255, 255, 255), 2: (169, 71, 100), 3: (138, 230, 203),
|
|
902
|
+
4: (154, 88, 185), 7: (255, 248, 141), 8: (196, 98, 65), 15: (205, 205, 205)}
|
|
903
|
+
GLYPH = {0: 0x20, 1: 0x66, 2: 0xa0, 3: 0x08, 4: 0x20, 5: 0x62}
|
|
904
|
+
INK = {0: 0, 1: 2, 2: 15, 3: 7, 4: 0, 5: 8}
|
|
905
|
+
def check(png, ntsc):
|
|
906
|
+
px = Image.open(png).convert('RGB').load()
|
|
907
|
+
top, pal = (23, NTSC) if ntsc else (35, PAL)
|
|
908
|
+
w, cs, tick, _ = dig_model.run()
|
|
909
|
+
exp = {}
|
|
910
|
+
for y in range(16):
|
|
911
|
+
for x in range(28):
|
|
912
|
+
t = w.m[y][x]
|
|
913
|
+
exp[(x, y)] = (GLYPH[t], INK[t])
|
|
914
|
+
exp[(w.px, w.py)] = (0x53, 3)
|
|
915
|
+
for g in w.g:
|
|
916
|
+
if g.on:
|
|
917
|
+
exp[(g.x, g.y)] = (0x51, 4 if g.st == 1 else 1)
|
|
918
|
+
bad = 0
|
|
919
|
+
for (x, y), (ch, ink) in exp.items():
|
|
920
|
+
X, Y = 32 + 8 * (6 + x), top + 8 * (5 + y)
|
|
921
|
+
want = ROM[(ch & 0x7f) * 8:(ch & 0x7f) * 8 + 8]
|
|
922
|
+
for j in range(8):
|
|
923
|
+
for i in range(8):
|
|
924
|
+
on = (want[j] >> (7 - i)) & 1
|
|
925
|
+
if ch & 0x80: on ^= 1
|
|
926
|
+
c = px[X + i, Y + j]
|
|
927
|
+
if c != (pal[ink] if on else (0, 0, 0)):
|
|
928
|
+
bad += 1
|
|
929
|
+
return bad, len(exp)
|
|
930
|
+
for png, n in (('dig-and-guards.png', 0), ('dig-and-guards-ntsc.png', 1)):
|
|
931
|
+
print(png, 'wrong pixels %d over %d cells' % check(png, n))
|
|
932
|
+
```
|
|
933
|
+
|
|
934
|
+
## Why this works
|
|
935
|
+
|
|
936
|
+
The hole list is the whole refill mechanism. A dig writes the hole into
|
|
937
|
+
the map and puts its cell and a timer into a free slot of eight; one
|
|
938
|
+
loop per tick counts every live slot down, swaps the glyph at 16 and
|
|
939
|
+
writes brick back at 0. At 0 it asks which actor stands in the cell: a
|
|
940
|
+
guard there is killed and moved to the top row, the player there dies.
|
|
941
|
+
Nothing else in the program tracks holes, so the map cell and the slot
|
|
942
|
+
can never disagree. The player digs at most once a tick and every hole
|
|
943
|
+
lives 80 ticks, so at most one slot expires and one turns to the refill
|
|
944
|
+
glyph in any tick. Eight live slots with one of each cost 659 cycles in
|
|
945
|
+
the stress tick; two live holes cost at most 366 in the scenario.
|
|
946
|
+
|
|
947
|
+
Standing is one function for everyone. `supported()` says an actor at a
|
|
948
|
+
cell is held up when the cell is a ladder, when the cell below is
|
|
949
|
+
brick, solid or ladder, or when the cell below is a hole holding a
|
|
950
|
+
trapped guard. The last clause is the walk-over rule, and it also keeps
|
|
951
|
+
a second guard from falling into an occupied hole. A guard that is not
|
|
952
|
+
held up falls one cell a guard tick; landing in a hole traps it for 30
|
|
953
|
+
guard ticks, after which it climbs one cell and steps sideways on the
|
|
954
|
+
next guard tick without the fall test, so it does not drop straight
|
|
955
|
+
back in.
|
|
956
|
+
|
|
957
|
+
The guard's rule is greedy and costs a row scan at most. On the player's
|
|
958
|
+
row it walks straight at the player if every cell between can be stood
|
|
959
|
+
on. On a ladder with the player above it climbs; with a ladder or empty
|
|
960
|
+
cell below and the player below it descends. Otherwise it scans its row
|
|
961
|
+
outward, left before right at each distance, for the nearest column
|
|
962
|
+
that offers a move toward the player's row, and stops a side at a wall,
|
|
963
|
+
a map edge or a cell it would fall from. Failing all of that it steps
|
|
964
|
+
toward the player's column. The stress tick puts four free guards on a
|
|
965
|
+
row with no such column and the player above, so each scans all 27
|
|
966
|
+
other columns: 4,780 cycles for the slowest on PAL, about 165 cycles a
|
|
967
|
+
probe (arithmetic over 29 probes). That is the cost of an Oscar64 `-O2`
|
|
968
|
+
function call per cell, not of the rule. With eight live holes and the
|
|
969
|
+
failed dig, the tick takes 19,759 cycles on PAL and 19,716 on NTSC:
|
|
970
|
+
101% of a PAL frame (19,656 cycles) and 115% of an NTSC one (17,095).
|
|
971
|
+
Four guards scanning full rows overrun a frame in this C. A copy of the
|
|
972
|
+
listing with the fourth guard switched off took 15,085 cycles on PAL
|
|
973
|
+
(77%) and 15,299 on NTSC (89%), so three fit. More guards need their
|
|
974
|
+
decisions staggered over frames; the technique page lists that and
|
|
975
|
+
other ways to bound the scan.
|