TE
TechEcho
Home24h TopNewestBestAskShowJobs
GitHubTwitter
Home

TechEcho

A tech news platform built with Next.js, providing global tech news and discussions.

GitHubTwitter

Home

HomeNewestBestAskShowJobs

Resources

HackerNews APIOriginal HackerNewsNext.js

© 2025 TechEcho. All rights reserved.

Software Developer Tracks Down Code for a Beloved 41-Year-Old Text Adventure

4 pointsby logronoideabout 4 years ago

2 comments

hilbert42about 4 years ago
<i>&quot;All 78 pages of it.&quot;<p>“I was thrilled,” O’Dwyer told me, adding that none of the original programmers expected their filing had included a complete copy of all the code. Reunited with his code, Kershenblatt lovingly scanned in all 78 pages (at a local Staples store), and then uploaded the resulting files to Dropbox. This ran up against the limits of optical character recognition, O’Dwyer points out, and after exploring several ways to re-scan the results — O’Dwyer finally just decided to manually transcribe the PDFs himself.&quot;</i><p>After posting those bits of the Adventure source, I went back and reread the article and I continue to be in disbelief that <i>&#x27;Kershenblatt [had to] lovingly scan in all 78 pages (at a local Staples store)&#x27;</i> so I&#x27;ve just done a search for <i>&quot;advent.for&quot; Fortran</i> and, as I suspected, there are plenty of references to the game including the various&#x2F;different versions, its origins, etc.<p>Thus, I can only conclude that this story has to be a beat-up, for otherwise how could I find so many references with just one search? It seems to me that most of the versions and variations from its original concept&#x2F;inception will be available with very little searching (after all, it was almost universally popular at one time due to the fact that it was just about the only game about).<p>The disk that I mentioned in my previous post dates from the mid 1980s, so I&#x27;m now keen to find it and to check the lineage of the various games along with their variations and versions. If I recall correctly, I got these files as ZIPs from a BBS. You&#x27;ll note a date reference of 01-JAN-77 in parts of code that I&#x27;ve posted (however, this file dates from around six years later).<p>Finally, I&#x27;ve just cut-&amp;-pasted the full listing of the source I posted earlier from my text editor into MS Word and it makes an interesting comparison with Kershenblatt&#x27;s scans. With Word set to standard US Letter size pages with nominal 1 inch margins, I get the following:<p><pre><code> Ariel, 12-point, normal spacing: 79 pages (with the last four lines orphaning on page 80). Courier New, 12-point, normal spacing: 78 pages (with the last four lines orphaning on page 79). </code></pre> If the margins are extended to 1.25 inches all around then I get just over 83 pages for both (with 10 and 6 lines overlap respectfully on p84). That&#x27;s a remarkable similarity methinks. I&#x27;d bet the code is almost identical in both instances.
hilbert42about 4 years ago
<i>&quot;More than 40 years later, after five years of searching, the original Fortran code for that game has been re-discovered and resurrected, thanks to the diligent efforts of an amateur game preservationist who had fond memories of playing the game when he was 11. It’s a story of dedication and perseverance, but most of all how far one can go with the fondness for a minor piece of tech culture.&quot;</i><p>What&#x27;s the big deal about this? All he had to do was to ask me! ;-) I still have a copy of Adventure&#x27;s source code on my present laptop, it&#x27;s been there for years (it&#x27;s been moved from machine to machine over the years along with other source code and data). At one time I used to use it as test code—it was reasonably long and didn&#x27;t usually crash.<p>I cannot understand why anyone would have had trouble trying to find it, for at one time in the early&#x2F;mid 1980s just about every Fortran programmer had a copy of it (he can&#x27;t have tried very hard, at one time its source was even included in those free give-away disks that were stuck to the covers of computer magazines).<p>Adventure&#x27;s source file is <i>advent.for</i>, it&#x27;s written in Fortran and this version is 81,857 bytes long. Incidentally, there are several versions of the source and they differ from one another very slightly in the game&#x27;s messages, etc., and also there were minor tweaks for the different Fortran compilers. Somewhere in my archives I have about a half dozen or so of these different versions on a floppy disk (but I&#x27;ve not seen it in years). <i>(If I recall, the reason for me still having this version on my PC is that it was the one that compiled on the Fortran that was on my Godbout&#x2F;CompuPro CP&#x2F;M 8&#x2F;16 S-100 system.)</i><p>One of the fun tricks of having the source was to compile it with special messages embedded for specific people that one knew (unbeknownst to them of course). We arranged it so that after playing for, say, some hours players would stumble across messages specifically intended for them—much to their amazement (as most didn&#x27;t even know what a compiler was let alone know that I had one to tweak the game).<p><i>Fortran people, except for the bit at the end, sorry about the wrap (it would take up too much listing space otherwise). &#x27;Tis a shame I can&#x27;t list it in full.<p>For those who aren&#x27;t literate in Fortran, comment lines begins with &#x27;C&#x27;. (Programmers who learned on punched Hollerith cards always had plenty of &#x27;blank&#x27; comment cards to insert to separate&#x2F;tidy up their source).</i><p>Here&#x27;s the intro:<p>C ADVENTURES<p>C CURRENT LIMITS: C 9650 WORDS OF MESSAGE TEXT (LINES, LINSIZ). C 750 TRAVEL OPTIONS (TRAVEL, TRVSIZ). C 300 VOCABULARY WORDS (KTAB, ATAB, TABSIZ). C 150 LOCATIONS (LTEXT, STEXT, KEY, COND, ABB, ATLOC, LOCSIZ). C 100 OBJECTS (PLAC, PLACE, FIXD, FIXED, LINK (TWICE), PTEXT, PROP). C 35 &quot;ACTION&quot; VERBS (ACTSPK, VRBSIZ). C 205 RANDOM MESSAGES (RTEXT, RTXSIZ). C 12 DIFFERENT PLAYER CLASSIFICATIONS (CTEXT, CVAL, CLSMAX). C 20 HINTS, LESS 3 (HINTLC, HINTED, HINTS, HNTSIZ). C 35 MAGIC MESSAGES (MTEXT, MAGSIZ). C THERE ARE ALSO LIMITS WHICH CANNOT BE EXCEEDED DUE TO THE STRUCTURE OF C THE DATABASE. (E.G., THE VOCABULARY USES N&#x2F;1000 TO DETERMINE WORD TYPE, C SO THERE CAN&#x27;T BE MORE THAN 1000 WORDS.) THESE UPPER LIMITS ARE: C 1000 NON-SYNONYMOUS VOCABULARY WORDS C 300 LOCATIONS C 100 OBJECTS<p>IMPLICIT INTEGER(A-Z) LOGICAL DSEEN,BLKLIN,HINTED,YES,START<p>COMMON &#x2F;TXTCOM&#x2F; RTEXT,LINES COMMON &#x2F;BLKCOM&#x2F; BLKLIN COMMON &#x2F;VOCCOM&#x2F; KTAB,ATAB,TABSIZ COMMON &#x2F;PLACOM&#x2F; ATLOC,LINK,PLACE,FIXED,HOLDNG COMMON &#x2F;MTXCOM&#x2F; MTEXT COMMON &#x2F;PTXCOM&#x2F; PTEXT COMMON &#x2F;ABBCOM&#x2F; ABB COMMON &#x2F;WIZCOM&#x2F; WKDAY,WKEND,HOLID,HBEGIN,HEND,HNAME, 1 SHORT,MAGIC,MAGNM,LATNCY,SAVED,SAVET,SETUP<p>DIMENSION LINES(9650) DIMENSION TRAVEL(750) DIMENSION KTAB(300),ATAB(300) DIMENSION LTEXT(150),STEXT(150),KEY(150),COND(150),ABB(150), 1 ATLOC(150) DIMENSION PLAC(100),PLACE(100),FIXD(100),FIXED(100),LINK(200), 1 PTEXT(100),PROP(100) DIMENSION ACTSPK(35) DIMENSION RTEXT(205) DIMENSION CTEXT(12),CVAL(12) DIMENSION HINTLC(20),HINTED(20),HINTS(20,4) DIMENSION MTEXT(35) DIMENSION TK(20),DSEEN(6),DLOC(6),ODLOC(6),HNAME(4)<p>C C AVOID MAKING THE COMPILER WORRY ABOUT MODIFYING THE DO INDEX C INTEGER IDONDX C STATEMENT FUNCTIONS C C C TOTING(OBJ) = TRUE IF THE OBJ IS BEING CARRIED C HERE(OBJ) = TRUE IF THE OBJ IS AT &quot;LOC&quot; (OR IS BEING CARRIED) C AT(OBJ) = TRUE IF ON EITHER SIDE OF TWO-PLACED OBJECT C LIQ(DUMMY) = OBJECT NUMBER OF LIQUID IN BOTTLE C LIQLOC(LOC) = OBJECT NUMBER OF LIQUID (IF ANY) AT LOC C BITSET(L,N) = TRUE IF COND(L) HAS BIT N SET (BIT 0 IS UNITS BIT) C FORCED(LOC) = TRUE IF LOC MOVES WITHOUT ASKING FOR INPUT (COND=2) C DARK(DUMMY) = TRUE IF LOCATION &quot;LOC&quot; IS DARK C PCT(N) = TRUE N% OF THE TIME (N INTEGER FROM 0 TO 100) C C WZDARK SAYS WHETHER THE LOC HE&#x27;S LEAVING WAS DARK C LMWARN SAYS WHETHER HE&#x27;S BEEN WARNED ABOUT LAMP GOING DIM C CLOSNG SAYS WHETHER ITS CLOSING TIME YET C PANIC SAYS WHETHER HE&#x27;S FOUND OUT HE&#x27;S TRAPPED IN THE CAVE C CLOSED SAYS WHETHER WE&#x27;RE ALL THE WAY CLOSED C GAVEUP SAYS WHETHER HE EXITED VIA &quot;QUIT&quot; C SCORNG INDICATES TO THE SCORE ROUTINE WHETHER WE&#x27;RE DOING A &quot;SCORE&quot; COMMAND C DEMO IS TRUE IF THIS IS A PRIME-TIME DEMONSTRATION GAME C YEA IS RANDOM YES&#x2F;NO REPLY<p>LOGICAL TOTING,HERE,AT,BITSET,DARK,WZDARK,LMWARN,CLOSNG,PANIC, 1 CLOSED,GAVEUP,SCORNG,DEMO,YEA<p>TOTING(OBJ)=PLACE(OBJ).EQ.-1 HERE(OBJ)=PLACE(OBJ).EQ.LOC.OR.TOTING(OBJ) AT(OBJ)=PLACE(OBJ).EQ.LOC.OR.FIXED(OBJ).EQ.LOC LIQ2(PBOTL)=(1-PBOTL)*WATER+(PBOTL&#x2F;2)*(WATER+OIL) LIQ(DUMMY)=LIQ2(MAX0(PROP(BOTTLE),-1-PROP(BOTTLE))) LIQLOC(LOC)=LIQ2((MOD(COND(LOC)&#x2F;2*2,8)-5)*MOD(COND(LOC)&#x2F;4,2)+1) BITSET(L,N)=(COND(L).AND.SHIFT(1,N)).NE.0 FORCED(LOC)=COND(LOC).EQ.2 DARK(DUMMY)=MOD(COND(LOC),2).EQ.0.AND.(PROP(LAMP).EQ.0.OR. 1 .NOT.HERE(LAMP)) PCT(N)=RAN(100).LT.N C DATA LINSIZ&#x2F;9650&#x2F;,TRVSIZ&#x2F;750&#x2F;,TABSIZ&#x2F;300&#x2F;,LOCSIZ&#x2F;150&#x2F;, 1 VRBSIZ&#x2F;35&#x2F;,RTXSIZ&#x2F;205&#x2F;,CLSMAX&#x2F;12&#x2F;,HNTSIZ&#x2F;20&#x2F;,MAGSIZ&#x2F;35&#x2F; DATA SETUP&#x2F;0&#x2F;,BLKLIN&#x2F;.TRUE.&#x2F; C DESCRIPTION OF THE DATABASE FORMAT C C C THE DATA FILE CONTAINS SEVERAL SECTIONS. EACH BEGINS WITH A LINE CONTAINING C A NUMBER IDENTIFYING THE SECTION, AND ENDS WITH A LINE CONTAINING &quot;-1&quot;.<p>C &lt;...&gt;<p>*<p><i>Here&#x27;s the end of the listing (many of the subroutines are listed here but I&#x27;ve had to omit all but the last bit):</i><p>*<p>&lt;...&gt;<p>INTEGER FUNCTION RAN(RANGE)<p>C SINCE THE RAN FUNCTION IN LIB40 SEEMS TO BE A REAL LOSE, WE&#x27;LL USE ONE OF C OUR OWN. IT&#x27;S BEEN RUN THROUGH MANY OF THE TESTS IN KNUTH VOL. 2 AND C SEEMS TO BE QUITE RELIABLE. RAN RETURNS A VALUE UNIFORMLY SELECTED C BETWEEN 0 AND RANGE-1. NOTE RESEMBLANCE TO ALG USED IN WIZARD.<p>IMPLICIT INTEGER(A-Z) DATA R&#x2F;0&#x2F;<p>D=1 IF(R.NE.0)GOTO 1 CALL DATIME(D,T) R=18*T+5 D=1000+MOD(D,1000) 1 DO 2 T=1,D 2 R=MOD(R*1021,1048576) RAN=(RANGE*R)&#x2F;1048576 RETURN END<p>SUBROUTINE DATIME(D,T)<p>C RETURN THE DATE AND TIME IN D AND T. D IS NUMBER OF DAYS SINCE 01-JAN-77, C T IS MINUTES PAST MIDNIGHT. THIS IS HARDER THAN IT SOUNDS, BECAUSE THE C FINAGLED DEC FUNCTIONS RETURN THE VALUES ONLY AS ASCII STRINGS!<p>IMPLICIT INTEGER(A-Z) DIMENSION DAT(2),MONTHS(12),HATH(12) DATA MONTHS&#x2F;&#x27;-JAN-&#x27;,&#x27;-FEB-&#x27;,&#x27;-MAR-&#x27;,&#x27;-APR-&#x27;,&#x27;-MAY-&#x27;,&#x27;-JUN-&#x27;, 1 &#x27;-JUL-&#x27;,&#x27;-AUG-&#x27;,&#x27;-SEP-&#x27;,&#x27;-OCT-&#x27;,&#x27;-NOV-&#x27;,&#x27;-DEC-&#x27;&#x2F; DATA HATH&#x2F;31,28,31,30,31,30,31,31,30,31,30,31&#x2F;<p>C FUNCTION I2 TAKES 2-DIGIT ASCII AND YIELDS DECIMAL VALUE.<p>I2(X)=(SHIFT(X,-29).AND.15)*10+(SHIFT(X,-22).AND.15)<p>CALL DATE(DAT) CALL TIME(TIM)<p>YEAR=I2(SHIFT(DAT(2),14))-77 D=I2(DAT(1))-1 X=((SHIFT(DAT(1),14).OR.SHIFT(DAT(2),-21)).AND..NOT.&quot;1004020001) 1 .OR.&#x27;-@@@-&#x27; C ABOVE FUNNY EXPRESSION GUARANTEES (A) UPPER-CASE, AND (B) BOTTOM BIT OKAY. DO 1 MON=1,12 IF(X.EQ.MONTHS(MON))GOTO 2 1 D=D+HATH(MON) CALL BUG(28)<p>2 D=D+YEAR*365+YEAR&#x2F;4 IF(MOD(YEAR,4).EQ.3.AND.MON.GT.2)D=D+1 T=I2(TIM)*60+I2(SHIFT(TIM,21)) RETURN END<p>SUBROUTINE CIAO<p>C EXITS, AFTER ISSUING REMINDER TO SAVE NEW CORE IMAGE. USED WHEN SUSPENDING C AND WHEN CREATING NEW VERSION VIA MAGIC MODE. ON SOME SYSTEMS, THE CORE C IMAGE IS LOST ONCE THE PROGRAM EXITS. IF SO, SET K=31 INSTEAD OF 32.<p>IMPLICIT INTEGER(A-Z) DATA K&#x2F;32&#x2F;<p>CALL MSPEAK(K) IF(K.EQ.31)CALL GETIN(A,B,C,D) STOP END<p>SUBROUTINE BUG(NUM) IMPLICIT INTEGER(A-Z)<p>C THE FOLLOWING CONDITIONS ARE CURRENTLY CONSIDERED FATAL BUGS. NUMBERS &lt; 20<p>C ARE DETECTED WHILE READING THE DATABASE; THE OTHERS OCCUR AT &quot;RUN TIME&quot;.<p>C 0 MESSAGE LINE &gt; 70 CHARACTERS C 1 NULL LINE IN MESSAGE<p>C 2 TOO MANY WORDS OF MESSAGES C 3 TOO MANY TRAVEL OPTIONS<p>C 4 TOO MANY VOCABULARY WORDS<p>C 5 REQUIRED VOCABULARY WORD NOT FOUND C 6 TOO MANY RTEXT OR MTEXT MESSAGES<p>C 7 TOO MANY HINTS<p>C 8 LOCATION HAS COND BIT BEING SET TWICE<p>C 9 INVALID SECTION NUMBER IN DATABASE<p>C 20 SPECIAL TRAVEL (500&gt;L&gt;300) EXCEEDS GOTO LIST<p>C 21 RAN OFF END OF VOCABULARY TABLE<p>C 22 VOCABULARY TYPE (N&#x2F;1000) NOT BETWEEN 0 AND 3<p>C 23 INTRANSITIVE ACTION VERB EXCEEDS GOTO LIST<p>C 24 TRANSITIVE ACTION VERB EXCEEDS GOTO LIST<p>C 25 CONDITIONAL TRAVEL ENTRY WITH NO ALTERNATIVE<p>C 26 LOCATION HAS NO TRAVEL ENTRIES<p>C 27 HINT NUMBER EXCEEDS GOTO LIST<p>C 28 INVALID MONTH RETURNED BY DATE FUNCTION<p>TYPE 1, NUM<p>1 FORMAT (&#x27; Fatal error, see source code for interpretation.&#x27;&#x2F;<p>1 &#x27; Probable cause: erroneous info in database.&#x27;&#x2F;<p>2 &#x27; Error code =&#x27;,I2&#x2F;)<p>STOP<p>END