14

I am looking for an article from an issue of Personal Computer World (PCW) from 19821 which related to generating mazes/dungeons using pseudo random seeds, what I think are (now) called procedural dungeon maps.

This system/language agnostic article explained that (and I'm using ZXBasic terminology) if the RAND seed is the same, at the start of the program then the subsequent calls to RND would generate a consistent set of numbers each time the program was run, thereby creating a consistent dungeon.

The article also had a side bar which then went on to explain how a similar result could be obtained by using a certain range of places of the decimal part2 of the result of a mathematical function (I think a combination of TAN, SIN and COS was used), taking the x and y co-ordinates of the player as arguments, would also result in a repeatable sequence of numbers, from which a room in the dungeon could be described.

There isn't (currently) a complete archive of the PCW magazines on the web at the moment, for example, as discussed here, "Personal Computer World" magazine -1980's - pdfs?). There are a few snippets available on archive.org, see Personal Computer World search, but that is about it3. Hence, I am unable to find the article online.

Does someone has a copy of that article, and if so, could they provide a scan of it, as an answer?4


As an aside, I am pretty sure that the same edition of PCW that has this random generated dungeon article, also has the advertisement that I am asking about in Largest memory peripheral for Sinclair ZX81?


Notes

1 I don't know which month, but I think it would have been in the first six months. It may also have been a very late 1981 issue - I purchased my ZX81 either Dec 81 or Jan 82, and so I would have been buying magazines from that period. My first two magazines were C&VG Issue 3 Jan 82 and this missing PCW issue.

2 As a simplistic example, the third to sixth decimal places could be used, so if the result was 0.2345967 then 4596 would be used to generate the room.

3 Additionally, there are some links to scans from the chess related pages (Micro Chess) of PCW can be found here, Chess Programming - Personal Computer World and the magazine covers only at Computing History - Personal Computer World. I have also just found this, The Personal Computer World Preservation Project, which mentions:

All PCWs are available at The National Museum of Computing (http://tnmoc.org). They are currently being digitised too.

Here is their archive, but it isn't online.

4 Better still, in addition to the scan (so as to avoid a link-only answer), an online repository of PCW magazines from the 80's, where I could find the answer/article/issue myself?

6
  • 1
    Tables of contents for January, March, and June 1982 are here: archive.org/details/PCWTablesOfContentsSubset September 1983 has an article on random numbers. There's also eBay. May 17, 2019 at 22:44
  • Yes, the contents comes up in the search link (my second link). I hadn't thought about eBay, I'll have a look now. Thanks May 17, 2019 at 22:46
  • Interesting. I was just reading the manual to the 1990's game Dungeon Hack, which describes a similar seeding process to generate and save the dungeon. I wonder how closely related the techniques described in the article and Dungeon Hack implementations are.
    – Geo...
    May 18, 2019 at 0:07
  • 1
    @Greenonline This PCW-Index has an entry reading pseudo random generate (randi) dec81...
    – Uli
    May 18, 2019 at 1:05
  • @Uli - very very interesting... There's also labyrinth (jan82) as well as to zx81 conversion (dec81) and to zx81 conversion (mar82) which I also vaguely recall being in the issue[s] that I had. May 18, 2019 at 6:12

1 Answer 1

22

It turns out that the magazine was, in fact, Practical Compµting (and not PCW), the issue was March 1982, and on page 93:

Practical Computing, March 1982 - page 93

Practical Computing, March 1982 - page 95

Listing 1:

10 INPUT X
20 C = COS(X)
30 C = C*100
40 C = ABS(C)
50 C = C - INT(C)
60 C = C*100
70 C = INT(C)
80 PRINT C

Listing 2:

10 PRINT "MAMMOTH MAZE in 2.5K BYTES BY G.T.RELF"
20 REM SET STARTING POSITION (EAST, WEST, DOWN):
30 X=103 : Y=97 : Z=1
40 REM SET THREASHOLD
50 T=0.3
60 REM RANDOMIZE FOR EARTHQUAKES
70 RANDOM
80 REM INSERT ANY OTHER INITIALISING STATEMENTS HERE.
90 REM MAIN LOOP:
100 REM COMPUTE PROPERTIES OF CURRENT LOCATION
110 GOSUB 250
120 REM GET COMMAND & BRANCH ACCORDINGLY:
130 INPUT "COMMAND"; CM$
140 CM$=LEFT$(CM$,1)
150 IF CM$="N" THEN 490
160 IF CM$="E" THEN 530
170 IF CM$="W" THEN 570
180 IF CM$="S" THEN 610
190 IF CM$="U" THEN 650
200 IF CM$="D" THEN 690
210 PRINT "IMPOSSIBLE!"
220 GOTO 110
230 REM END OF MAIN LOOP
240 REM COMPUTE ATTRIBUTES OF CURRENT LOCATION:
250 V1=INT(W*1000)
260 IF V1>35 AND V1<39 AND Z>1 THEN PRINT "HERE IS A CROCK OF GOLD!"
270 REM (YOU WONT FIND CROCKS OF GOLD JUST LYING ON THE GROUND!)
280 REM INSERT OTHER ATTRIBUTE TESTS HERE.
290 REM CHECK FOR EARTHQUAKES:
300 IF RND(1000)=9 THEN PRINT "RUMBLE, RUMBLE..." : T=T+0.2*RND(0)-0.1
310 REM INSERT OTHER LOCATION-DEPENDANT TESTS HERE.
320 REM IDENTIFY CORRIDORS FROM CURRENT LOCATION (CHANGES W):
330 IF Z=1 THEN 440
340 PRINT "CORRIDORS: "; : NC=0
350 X=X+1: GOSUB 720 : IF W<T THEN PRINT "E" : NC=NC+1
360 X=X-2 : GOSUB 720 : X=X+1 : IF W<T THEN PRINT "W" : NC=NC+1
370 Y=Y+1: GOSUB 720 : IF W<T THEN PRINT "N" : NC=NC+1
380 Y=Y-2 : GOSUB 720 : Y=Y+1 : IF W<T THEN PRINT "S" : NC=NC+1
390 Z=Z+1: GOSUB 720 : IF W<T THEN PRINT "D" : NC=NC+1
400 Z=Z-2 : GOSUB 720 : Z=Z+1 : IF W<T OR Z=2 THEN PRINT "U" : NC=NC+1
410 IF NC=0 THEN PRINT "NONE - THE EARTHQUAKE HAS TRAPPED YOU!"
420 PRINT
430 RETURN
440 PRINT "GROUND LEVEL."
450 Z=Z+1 : GOSUB 720 : Z=Z-1
460 IF W<T THEN PRINT "A SHAFT DESCENDS FROM HERE."
470 RETURN
480 REM MOVE NORTH:
490 Y=Y+1 : IF Z=1 THEN 110
500 GOSUB 720 : IF W<T THEN 110
510 Y=Y-1 : GOTO 210
520 REM MOVE EAST:
530 X=X+1 : IF Z=1 THEN 110
540 GOSUB 720 : IF W<T THEN 110
550 X=X-1 : GOTO 210
560 REM MOVE WEST:
570 X=X-1 : IF Z=1 THEN 110
580 GOSUB 720 : IF W<T THEN 110
590 X=X+1 : GOTO 210
600 REM MOVE SOUTH:
610 Y=Y-1 : IF Z=1 THEN 110
620 GOSUB 720 : IF W<T THEN 110
630 Y=Y+1 : GOTO 210
640 REM MOVE UP:
650 IF Z=1 THEN 210
655 Z=Z-1 : IF Z=1 THEN 110
660 GOSUB 720 : IF W<T THEN 110
670 Z=Z+1 : GOTO 210
680 REM MOVE DOWN:
690 Z=Z+1 : GOSUB 720 : IF W<T THEN 110
700 Z=Z-1 : GOTO 210 
710 REM RANDOM FUNCTION
720 U=100*SQR(X*X+Y*Y*Z)
730 W=U-INT(U)
740 RETURN

Note that there is an omission in the published listing - the random number generator is not called at the beginning of the loop. The fix is as follows:

250 GOSUB 720
255 V1=INT(W*1000)

I have also posted the code on Github: AdventureFunction.


Note for BBC users

The code will run, as is, on BBC BASIC, if you delete line 70 - or if you want the maze to be the same each time, then use RND(-n), where n is a value in the range -2147483648 to -1 (see Notes on the use of RND), for example:

70 RND(-2)

Locating the answer

FWIW, I only finally managed to find the article via the very useful magazine issue synopsis provided by computinghistory.org.uk, which seems to be easier to find information in, than the actual magazine's own contents page (where the article isn't even listed!):

93 Repeatable functions for limitless mazes [Type-In Listing]

Graham Relf

Try your hand at Graham Relf's Monster Maze.

Here is a list of all of the Practical Computing issues, in case anyone needs them. Other magazines can be found here: Archive > Magazines. The actual PDFs are on World Radio History.


Bonus mini adventure

On pages 97 and 98, of the same issue, there is also a machine portable BASIC program for a mini adventure.

Practical Computing, March 1982 - page 97

Practical Computing, March 1982 - page 98

10 REM LABYRINTH P.J.GOSS 2-9-81
20 DIM A(24,24), B(121), C(121)
30 PRINT "****LABYRINTH****"
40 PRINT
50 PRINT "FOUR SIZES OF LABYRINTH ARE ABVAILABLE"
60 PRINT "AFTER SELECTING THE REQUIRED SIZE A"
70 PRINT "LABYRINTH WILL BE DISPLAYED AND THEN"
80 PRINT "DISAPPEAR FROM THE SCREEN."
90 PRINT "TO MOVE AROUND THE LABYRINTH YOU ARE"
100 PRINT "ASKED TO TYPE DIRECTIONS IN THE FORM"
110 PRINT "OF N, S, E OR W."
120 PRINT "TO FINISH, TYPE F."
130 PRINT
140 PRINT "SIZE:";
150 INPUT L
160 IF L<1 OR L>4 GOTO 130
170 LET M=7+(INT(L)*4)
180 GOTO 200
190 REM **** INITIATE ALL ARRAYS ****
200 FOR I=2 TO M+1 STEP 2
210 FOR J=2 TO M+1 STEP 2 
220 LET A[I,J]=0
230 LET A[I-1, J-1]=1
240 LET A[I,J-1]=2
250 LET A[I-1,J]=3
260 NEXT J
270 NEXT I
280 LET A[(M+1)/2,(M+1)/2]=4
290 GOTO 300
300 FOR I=1 TO 121
310 LET B(I)=C(I)=0
320 NEXT I
330 REM *** SELECT RANDOM PATH FROM CENTER ****
340 LET D=1
350 LET S=T=(M+1)/2
360 LET B(1)=C(1)=S
370 LET Z=0
380 GOTO INT(RND(1)*4)+10F 400, 500, 600, 700, 370
390 REM **** NORTHERN PATH SELECT ****
400 IF T-2=0 GOTO 460
410 IF A[S, T-2]=4 OR Z=1 GOTO 380
420 Z=1
430 LET A[S,T-1]=0
440 LET T=T-2
450 GOTO 750
460 IF D<M-(INT(M/2)) GOTO 380
470 LET A[S,T-1]=0
480 GOTO 830
490 REM  **** EASTERN PATH SELECT ****
500 IF S+2=M+1 GOTO 560
510 IF A[S+2, T]=4 OR Z=2 GOTO 380
520 Z=2
530 LET A[S+1,T]=5
540 LET S=S+2
550 GOTO 750
560 IF D<M-(INT(M/2)) GOTO 380
570 LET A[S+1,T]=0
580 GOTO 830
590 REM  **** SOUTHERN PATH SELECT ****
600 IF T+2=M-1 GOTO 660
610 IF A[S, T+2]=4 OR Z=3 GOTO 380
620 Z=3
630 LET A[S,T+1]=0
640 LET T=T+2
650 GOTO 750
660 IF D<M-(INT(M/2)) GOTO 380
670 LET A[S,T+1]=0
680 GOTO 830
690 REM  **** WESTERN PATH SELECT ****
700 IF S-2=0 GOTO 660
710 IF A[S-2, T]=4 OR Z=4 GOTO 380
720 Z=4
730 LET A[S-1,T]=5
740 LET S=S-2
750 LET D=D+1
760 LET A[S,T]=4
770 LET B[D]=S
780 LET C[D]=T
790 GOT 380
800 IF D<M-(INT(M/2)) GOTO 380
810 LET A[S-1,T]=5
820 REM *** CREATE REMAINDER OF LABYRINTH
830 LET E=F=G=D
840 FOR K=D+1 TO ((M-1)/2)*2
850 REM **** TEST FOR NORTH WALL BREAK ****
860 IF C[E]-2=0 THEN GOTO 940
870 IF A[B[E], C[E]-2]=4 THEN 940
880 LET A[B[E], C[E]-1]=0
890 LET A[B[E], C[E]-2]=4
900 LET B[K]=B[E]
910 LET C[K]=C[E]-2
920 GOTO 1160
930 REM **** TEST FOR SOUTH WALL BREAK ****
940 IF B[E]+2=M+1 THEN GOTO 1020
950 IF A[B[E]+2, C[E]]=4 THEN 1020
960 LET A[B[E]+1, C[E]]=5
970 LET A[B[E]+2, C[E]]=4
980 LET B[K]=B[E]+2
990 LET C[K]=C[E]
1000 GOTO 1160
1010 REM **** TEST FOR EAST WALL BREAK ****                      
1020 IF C[E]+2=M+1 THEN GOTO 1100
1030 IF A[B[E], C[E]+2]=4 THEN 1100
1040 LET A[B[E], C[E]+1]=0
1050 LET A[B[E], C[E]+2]=4
1060 LET B[K]=B[E]
1070 LET C[K]=C[E]+2
1090 GOTO 1160
1090 REM **** TEST FOR WEST WALL BREAK **** 
1100 IF B[E]-2=0 THEN GOTO 1190
1110 IF A[B[E]-2, C[E]]=4 THEN 1190
1120 LET A[B[E]-1, C[E]]=5
1130 LET A[B[E]-2, C[E]]=4
1140 LET B[K]=B[E]-2
1150 LET C[K]=C[E]
1160 LET E=K
1170 GOTO 1270
1180 REM **** TEST FOR PATHS OFF MAIN ROUTE ****
1190 IF F=2 GOTO 1240
1200 LET F=F-1
1210 LET E=F
1220 GOTO 860
1230 **** TEST FOR PATHS OFF PREVIOUS PATHS ****
1240 LET G=G+1
1250 LET E=G
1260 GOTO 860
1270 NEXT K
1280 **** DISPLAY LABYRINTH ****
1290 LET A[B[D],C[D]]=7
1300 LET A[(M+1)/2,(M+1)/2]=6
1310 PRINT
1320 PRINT
1330 GOSUB 2040
1340 **** CLEAR SCREEN ****
1350 FOR I-1 To 23
1360 PRINT
1370 NEXT I
1380 REM **** MOVE PLAYER, TEST FOR COLLISION AND EXIT ****
1390 LET S=B[D]
1400 T=C[D]
1410 LET P=D-1
1420 LET N=D
1430 LET W=R=V=0
1440 PRINT
1450 PRINT "N, S, E OR W";
1460 INPUT A$
1470 IF A$="N" GOTO 1530
1480 IF A$="S" GOTO 1570
1490 IF A$="E" GOTO 1610
1500 IF A$="W" GOTO 1650
1510 IF A$="F" GOTO 1960
1520 GOTO 1440
1530 IF A[S,T-1]=2 GOT0 1850 
1540 IF T-2=0 THEN 1890
1550 LET T=T-2
1560 GOT0 1690
1570 IF A[S,T+1]=2 GOT0 1850 
1580 IF T+2=M+1 GOTO 1890
1590 LET T=T+2
1600 GOT0 1690
1610 IF A[S+1,T]=3 GOT0 1850 
1620 IF S+2=M+1 GOTO 1890
1630 LET S=S+2
1640 GOT0 1690
1650 IF A[S-1,T]=3 GOT0 1850 
1660 IF S-2=0 GOTO 1890
1670 LET S=S-2
1680 REM **** CALCULATE STEPS TO CENTER ****
1690 FOR I=1 TO ((M+1)/2)*2
1700 IF S=B[I] AND T=C[I] GOTO 1720
1710 GOTO 1750
1720 IF I<N LET P=P-1
1730 IF I>N LET P=P+1
1740 LET N=I
1750 NEXT I
1760 LET R=R+1
1770 IF P=0 GOTO 1930
1780 IF R=7-L GOTO 1800
1790 GOTO 1440
1800 LET V=V+R
1810 LET R=0
1820 PRINT
1830 PRINT "NUMBER OF STEPS TO CENTER ARE ";P
1840 GOTO 1440
1850 PRINT
1860 PRINT "OUCH - YOU WALKED INTO A WALL"
1870 LET W=W+1
1880 GOTO 1440
1890 PRINT
1900 PRINT "YOU HAVE JUST TREID TO WALK OUT"
1910 PRINT "OF THE LABYRINTH"
1920 GOTO 1440
1930 PRINT
1940 PRINT "YOU HAVE FOUND THE CENTER IN " V+R+W
1950 PRINT "NUMBER OF BRUISES" W
1960 FOR I=2 TO D
1970 LET A[B[I], C[I]]=8
1980 NEXT I
1990 LET A[(M+1)/2,(M+1)/2]=6
2000 LET A[S,T]=7
2010 GOSUB 2040
2020 GOTO 2190
2030 REM **** LABYRINTH DISPLAY ROUTINE ****
2040 FOR I=1 To M
2050 FOR J=1 TO M
2060 IF A[I,J]=0 PRINT "   "
2070 IF A[I,J]=1 PRINT "+"
2080 IF A[I,J]=2 PRINT "---"
2090 IF A[I,J]=3 PRINT "|"
2100 IF A[I,J]=4 PRINT "   "
2110 IF A[I,J]=5 PRINT " "
2120 IF A[I,J]=6 PRINT " X "
2130 IF A[I,J]=7 PRINT " ? "
2140 IF A[I,J]=8 PRINT " * "
2150 NEXT I
2160 PRINT
2170 NEXT J
2180 RETURN
2190 END
8
  • Any idea what dialect is used for labyrinth? Not so familiar with the UK BASICs, but those square brackets are interesting, and your initial post suggests it's not Sinclair. BTW, did you OCR this listing or type it in? Nov 20, 2022 at 15:57
  • @MauryMarkowitz - That is a good question and I'm not sure. The contents page says "A portable adventure style game", and the first line says "machine portable" so the portable means some generic BASIC I guess. I (laboriously) typed the code in. Nov 20, 2022 at 16:55
  • Ok, I fixed a couple of typos, I'll keep checking. If that was an OCR I was going to buy it immediately, as my previous attempts with OCRs... ugh. Nov 20, 2022 at 16:56
  • Line 290 of the last listing looks a bit odd GOTO 300
    – JeremyP
    Nov 24, 2022 at 9:23
  • @MauryMarkowitz - thanks for the fixes, I found some others as well. I've updated the listing on github. I had assumed that the BASIC was similar to Atari or TRS-80, but not Apple. Maybe BBC Basic? I wonder if there is an online BASIC dialect detector? It would probably make a good question on this site "What BASIC dialect is this?", if on-topic. Note that the two programs don't share the same dialect, for example, the first has IF xxx THEN <linenumber> (no GOTO) whereas the second has IF xxx GOTO <line number> (no THEN). Nov 24, 2022 at 17:32

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .