Grid Program Flow

Wrapping Edges and Toroidal Space

What happens when a pointer leaves the edge of a grid? Learn how wrap-around works, why it forms a torus, and how it shapes the layout of grid programs.

On this page
  1. What happens at the boundary
  2. Why it is called a torus
  3. Wrapping in Befunge-93
  4. Wrapping in Funge-98
  5. Using wrap-around in a layout
  6. Common problems
  7. A mental model that helps

What happens at the boundary

A grid has edges, and a pointer that keeps moving in one direction will eventually reach one. A language has to say what happens next. There are a few possible answers: stop the program, treat it as an error, bounce the pointer back, or wrap the pointer around to the opposite side. Befunge-style languages choose wrapping, and it has large consequences for how programs are laid out.

In wrapping, the pointer that moves off the right edge reappears at the left end of the same row, still heading right. A pointer moving off the left edge reappears on the right. Moving off the top puts it at the bottom, and moving off the bottom puts it at the top. The row or column stays the same, so only one coordinate changes.

Why it is called a torus

If you imagine gluing the left edge of the grid to the right edge, the rectangle becomes a tube. Then glue the top edge to the bottom edge, and the tube bends around into a ring shape, like a doughnut. The mathematical name for that surface is a torus, and a grid with wrapping on both axes is therefore described as toroidal, or as a toroidal playfield.

Nothing physical is going on, of course. The torus is a way of saying that the grid has no boundaries from the pointer’s point of view: there is no edge to fall off and no wall. Every cell has a neighbor in every direction. The same arrangement appears outside programming languages. Many simulations of cellular automata use a wrapped grid so that cells at the border behave like all the others, and the Game of Life is often run that way for the same reason.

Wrapping in Befunge-93

In Befunge-93, the playfield has a fixed size, commonly given as 80 columns by 25 rows. The wrap happens at those limits, whatever the length of the source text. That has a surprising effect: a short program with a left-pointing arrow in column 0 does not wrap to the end of the visible text, but to column 79, and the pointer has to cross all the blank cells in between. Crossing blank cells does nothing, so the program still behaves properly, but it takes a number of steps.

It follows that some programs rely on wrapping on purpose. A pointer heading right along a row with no more instructions will cross the blank space to the edge, reappear at column 0, and meet the first instruction of that row again. This is a natural way to make a row loop with no turning arrows at all, and a cheap one, since it needs no extra cells. The pointer also passes the same row every time, so the loop is predictable.

Wrapping is part of the Befunge-93 limits: the fixed field is both a boundary and a feature. When a text file is loaded into the field, anything beyond those dimensions is typically dropped or rejected, depending on the implementation. How program loading handles an over-long line is one of the details an implementer has to decide.

Wrapping in Funge-98

Funge-98 describes its space as unbounded, so there is no fixed edge to wrap around. Instead, the behavior is typically described in terms of the used part of the space: when the pointer goes beyond the occupied cells, it is treated as returning from the opposite side of the occupied area. The result looks similar for typical programs, but the position where the pointer reappears depends on where the program’s cells are, not on a fixed size. Because the details are specific to the standard and to each implementation, check the documentation of the one you are using before relying on an exact behavior.

The same idea extends to additional dimensions. In a three-dimensional version, there are three pairs of boundaries, and the same wrap-around applies along each axis.

Using wrap-around in a layout

Programmers use wrapping in a few ways.

  • Free return paths. A route that must come back to the left side after traveling right can simply continue off the edge rather than looping back with arrows.
  • Compact loops. A one-row loop that wraps costs fewer cells than a ring of arrows. The geometric loops article treats the ring as the general case, and wrapping is the thinnest special case.
  • Hiding code. Placing an instruction in column 0 and an arrow pointing away from it can make a program hard to follow, since the connection runs off the edge. This is a common trick in puzzle programs, and part of why such programs end up as obfuscated code.
  • Edge-safe design. Putting data and unused space in the middle, and keeping routes well inside the boundaries, avoids accidental wraps.

Common problems

The most common mistake is an unplanned wrap. An arrow with the wrong direction, or a conditional cell with no exit, sends the pointer off an edge, and it returns somewhere unexpected and starts executing whatever is on that line. The resulting behavior can look random even though it is entirely determined.

When a program seems to run into the wrong code, check what lies on the opposite edge of the row or column where the pointer left. Tracing by hand with the wrap rules written beside the page is the quickest way to find an accidental crossing. A trace visualizer that shows the pointer’s last several cells makes wrap-arounds easy to see, since the pointer visibly jumps from one side to the other.

A mental model that helps

Treat the grid as a repeating pattern: imagine copies of it tiled in all directions. The pointer then travels in a straight line through that pattern, and the cell it reaches is the same as the one in your own grid. Thinking this way makes wrapped routes feel like ordinary straight lines, which is usually how they are meant to be read.

The complete guide to grid program flow

How Grid-Based Program Flow Works
Read the guide

Keep exploring

Guides from other topics

All topics →