Sometimes you just want to see part of the level. This routine prints a rectangular slice of a map as digits. It is a useful room display for a text game, or a quick view of the collision data while a graphical game is being built.
It prints at the current text cursor. It does not position a hardware tile window, choose colours or draw bitmap artwork. The numeric map array is zero-based.

Include and call it
Include query.bas at lines 1000–1360 and region.bas at 1400–1580. Copy the allocation and map initialisation from the caller before your game loop. If your program already contains the same map-query routines, keep one copy and check every entry number.
Choose and print a three-by-two map region
5 MODE 6:VDU 23,1,0;0;0;0;
10 W=8:H=6:S=8:L=3
20 DIM M(W*H-1),P(L)
30 FOR I=0 TO 47:M(I)=0:NEXT I
40 FOR I=0 TO 7:M(I)=1:M(40+I)=1:NEXT I
50 FOR I=0 TO 5:M(I*8)=1:M(I*8+7)=1:NEXT I
60 M(19)=2:M(28)=3
70 P(0)=0:P(1)=1:P(2)=2:P(3)=4
80 Q=0:U=0:A=8:B=6
90 Q=2:U=1:A=3:B=2
100 GOSUB 1400
110 PRINT "DONE"
120 ENDThe example prints 000 followed by 020. Q/U are zero-based source column/row; A/B are width/height in cells. They must be integers, the dimensions positive, and the whole rectangle must fit inside W by H. L is the highest permitted tile ID; this digit adapter requires 0–9. The map must remain unchanged during the call.
Validate the complete source region, then print it
1400 E=0
1410 IF Q<0 THEN RETURN
1420 IF U<0 THEN RETURN
1430 IF A<1 THEN RETURN
1440 IF B<1 THEN RETURN
1450 IF Q+A>W THEN RETURN
1460 IF U+B>H THEN RETURN
1470 IF Q<>INT(Q) THEN RETURN
1480 IF U<>INT(U) THEN RETURN
1490 IF A<>INT(A) THEN RETURN
1500 IF B<>INT(B) THEN RETURN
1501 Z=0
1502 C=Q+Z-A*(INT(Z/A)):R=U+(INT(Z/A)):GOSUB 1000
1503 E=0
1504 IF T<0 THEN RETURN
1505 IF T>L THEN RETURN
1506 IF T<>INT(T) THEN RETURN
1507 Z=Z+1
1508 IF Z<A*B THEN GOTO 1502
1510 FOR K=U TO U+B-1
1520 FOR J=Q TO Q+A-1
1530 C=J:R=K:GOSUB 1000
1540 PRINT CHR$(48+T);
1550 NEXT J
1560 PRINT
1570 NEXT K
1580 E=1:RETURNCall 1400 with GOSUB (GO SUB on Spectrum), then check E. E=1 means the complete region was printed; E=0 means nothing was printed. The routine first checks bounds and every tile ID, then makes a second pass to print. A malformed last tile cannot leave the first rows on screen. This costs an extra lookup per cell, which is a deliberate trade for predictable failure.
Map access routines used by the renderer
1000 E=0:T=-1
1010 IF C<0 THEN RETURN
1020 IF R<0 THEN RETURN
1030 IF C>=W THEN RETURN
1040 IF R>=H THEN RETURN
1050 IF C<>INT(C) THEN RETURN
1060 IF R<>INT(R) THEN RETURN
1070 D=R*W+C:T=M(D):E=1
1080 RETURN
1100 E=0
1110 IF V<0 THEN RETURN
1120 IF V>L THEN RETURN
1130 IF V<>INT(V) THEN RETURN
1140 GOSUB 1000
1150 IF E=0 THEN RETURN
1160 M(D)=V:T=V
1170 RETURN
1200 E=0:F=-1
1210 IF T<0 THEN RETURN
1220 IF T>L THEN RETURN
1230 IF T<>INT(T) THEN RETURN
1240 F=P(T):E=1
1250 RETURN
1300 E=0:C=-1:R=-1:T=-1
1310 IF S<=0 THEN RETURN
1320 IF X<0 THEN RETURN
1330 IF Y<0 THEN RETURN
1340 C=INT(X/S):R=INT(Y/S)
1350 GOSUB 1000
1360 RETURNWhat it owns
Keep the caller-owned map M() (MM() on Atom), W/H/L and its query inputs valid. The complete supplied query file also uses P()/PP() and S for its separate property/world-position calls. Region drawing uses Q/U/A/B and overwrites E/C/R/T/D/J/K/Z. Do not surround it with a loop that needs J or K preserved. Calls are synchronous, global-state routines, not re-entrant components.
Output uses character code 48+T and a newline after each row. Leave enough text columns and rows at the cursor. Wrapping and scrolling belong to the interpreter; source-map bounds do not prevent the display scrolling. A successful call does not promise to leave the screen cursor where it started.
Make it yours
Change Q/U to inspect another room, or A/B to make a small moving view. A one-cell region is a useful first test before drawing a larger area. Change the character conversion at line 1540 to choose different glyphs, preserving the ID preflight and the newline behaviour. For a custom alphabet, use a table rather than assuming every ID is a character code.
If the second row is displaced, check the map stride: it is W, not the region width A. The executed wrong-stride example shows the difference. If a bad tile leaves a partial picture, validation has moved into the printing pass; put the complete preflight back before the first PRINT. If calling this inside another loop breaks that loop, check its variable names against J/K/Z and the query scratch.
Map queries explain the row-major index and world-to-cell conversion. Maths for Games provides the wider context for coordinates and units. The same logical rectangle can feed a native renderer later; its screen layout and timing need their own implementation.

Take it and check it
Complete source, caller and execution records. The native checks compare every decoded screenshot pixel with literal expected text, reject invalid/empty/fractional rectangles where the dialect supports them, test a malformed late tile, then require a wrong stride to fail. Firmware is identified by hash and is not redistributed. No frame-rate or original-hardware claim follows from this text renderer.