Home / Commodore 64 / Phase 0 / Lesson 9
Lesson 9 of 64

Gridlocked

What you'll learn:

  • Declare and populate two-dimensional arrays with `DIM`.
  • Use nested loops to render tile-based grids on the text screen.
  • Check available memory with `FRE(0)` to avoid crashes.
  • Manipulate grid data to place walls, hazards, and the player.
14% Complete

Lesson 9 – Gridlocked

Week 2 kicks off by turning the screen into a playfield. Arrays let you store whole maps, not just single scores. With a two-dimensional grid in memory, you can draw levels, place enemies, and update tiles as the player moves. This is the backbone of every maze, dungeon, and strategy game.

[📷 suggested: screenshot of a 10×10 grid with walls and a player marker]


The One-Minute Tour

  • DIM MAP(ROWS, COLS) reserves a grid with indices starting at 0.
  • Nested FOR loops make it easy to fill and print each cell.
  • Convert grid coordinates into screen addresses with 1024 + ROW*40 + COL.

Example Program

NEW
10 PRINT CHR$(147)
20 DIM MAP(9,9)
30 FOR R=0 TO 9
40 FOR C=0 TO 9
50 MAP(R,C)=0
60 NEXT C
70 NEXT R
80 FOR I=0 TO 9
90 MAP(0,I)=1 : MAP(9,I)=1 : MAP(I,0)=1 : MAP(I,9)=1
100 NEXT I
110 MAP(5,5)=2
120 FOR R=0 TO 9
130 FOR C=0 TO 9
140 LOC=1024+R*40+C
150 CELL=MAP(R,C)
160 IF CELL=0 THEN POKE LOC,32
170 IF CELL=1 THEN POKE LOC,35
180 IF CELL=2 THEN POKE LOC,64
190 NEXT C
200 NEXT R

Lines 20–70 initialise the 10×10 grid with zeros (floor tiles). Lines 80–110 add a border (value 1) and a player marker in the centre (2). Lines 120–200 walk the array and POKE the correct character into screen RAM: space for floor, # for walls, @ for the player.

Tip: Remember that DIM MAP(9,9) creates indices 0..9 in both directions. Going out of bounds triggers the dreaded “?ILLEGAL QUANTITY ERROR”.


Experiment Section

  • Change the map size to 12×12 (DIM MAP(11,11)), updating the loops accordingly.
  • Scatter random obstacles: inside line 90 insert IF RND(1)<0.2 THEN MAP(R,C)=1.
  • Add a goal tile with value 3 and render it as *.
  • Move the player: set MAP(5,5)=0, MAP(5,6)=2, and rerun the render loop to simulate a step.
  • Replace POKE with PRINT using CHR$(19) and SPC() if you prefer to stick to immediate printing.

[🎥 suggested: clip showing random walls appearing and the player repositioned]


Checking Available Memory with FRE()

Arrays consume memory fast—a 10×10 grid takes 100 bytes, but a 50×50 grid gobbles 2,500. The C64 has limited RAM for BASIC (about 38KB), and running out triggers ?OUT OF MEMORY ERROR. Use FRE(0) to check how much is left:

NEW
10 PRINT "FREE MEMORY:";FRE(0);"BYTES"
20 DIM MAP(49,49)
30 PRINT "AFTER ARRAY:";FRE(0);"BYTES"

Before you DIM a big array, do the maths: ROWS × COLS × 5 bytes (BASIC stores numbers inefficiently). If FRE(0) is less than you need, reduce the array size or split it into smaller chunks.

Tip: Call FRE(0) after your DIM statements in the main setup to catch memory issues early. If you’re close to the limit, avoid deep GOSUBs and long strings—they eat the stack.

Quick rule: If FRE(0) < 5000, you’re in the danger zone. Trim arrays, remove unused variables, or break your program into loadable segments.


Concept Expansion

Arrays give you a model of the world that lives in memory independent of the screen. Later lessons will store hit points, item IDs, and terrain flags in the same grid. Assembly lessons revisit these concepts with faster memory writes, but the structure you’re learning now carries over unchanged.


Game Integration

  • Maze generators: fill the grid with carve algorithms, then render.
  • Collision checks: before moving, test the target cell—IF MAP(NR,NC)=1 THEN BLOCKED.
  • Fog of war: keep a second array of discovery flags to hide unexplored tiles.
  • Level transitions: load predefined arrays via DATA statements for multiple stages.

From the Vault

  • Paradroid — study how grid layouts underpin its decks and terminals.

Quick Reference

PRINT FRE(0)            : REM check available memory
DIM MAP(9,9)            : REM 10×10 grid (0..9)
MAP(R,C) = VALUE        : REM store tile data
FOR R=0 TO MAX
FOR C=0 TO MAX
LOC = 1024 + R*40 + C
POKE LOC, CHARCODE
NEXT C
NEXT R
  • Use FRE(0) before large arrays to avoid memory crashes.
  • Use nested loops to process every cell.
  • Map values to characters carefully; avoid using the same value for multiple tile types.
  • Clearing and redrawing the grid is fine for small maps; optimise later when you only need partial updates.

What You’ve Learnt

  • Declared and manipulated two-dimensional arrays for map data.
  • Checked available memory with FRE(0) to prevent crashes from oversized arrays.
  • Converted array indices into screen positions using the 40-column layout.
  • Rendered different tile types by translating values into characters.
  • Built the foundation for tile-based worlds that evolve over time.

Next lesson: Logic & Motion — combine these grids with smarter movement rules so your worlds come alive.