To Hell In A Hamper (2006) — an old new game

development and releases of new/rewritten text adventures
User avatar
lurkio
Posts: 4351
Joined: Wed Apr 10, 2013 12:30 am
Location: Doomawangara
Contact:

To Hell In A Hamper (2006) — an old new game

Post by lurkio »

The single-location "room-escape" text adventure game To Hell In A Hamper is now available from bbcmicro.co.uk:

http://bbcmicro.co.uk/game.php?id=3199

Disc999-ToHellInAHamper.png

The original game was quirky, ingenious, and amusing. The BBC BASIC port is nicely implemented and fun to play, although it's a bit slow because of all the floppy-disc accesses.

To Hell In A Hamper was originally written by J.J. Guest using the ADRIFT development system. The BBC BASIC port was created by Dave Edwards (who also seems to have written a review of his own work!?). One of the original author's suggested tweaks was then incorporated and a couple of bugs were fixed, and the result was the version that's now online at bbcmicro.co.uk. A summary of the changes:
  • Added the synonym X for the EXAMINE command
  • And the synonyms I and INV for the INVENTORY command
  • Fixed a bug where <rot13> bcravat gur cnepry jbhyq bcra vg ohg gura fnl vg pna'g or bcrarq! </rot13>
  • Fixed the crash mentioned in the CASA walkthrough (rot13: RKNZVAR YVAVAT)
  • Corrected some typos
  • Added a space after the "What now?" prompt
  • Disabled the Escape key (in !BOOT)
  • Fixed a bug where <rot13> rknzvavat gur napube ebcr </rot13> would end the program!
  • Tweaked cursor on/off transitions
  • Fixed a bug where <rot13> TRG UNAQ sbyybjrq ol GUEBJ UNAQ </rot13> would crash when repeated
  • Added synonym <rot13> GVA {OBK} sbe OBK </rot13>
  • Added synonym <rot13> PBNG sbe BIREPBNG </rot13>
  • Handled just <rot13> UVG UHOREG </rot13>
The above bugfixes and changes were made sometime before July in 2019. Then, later that year:
  • Offloaded all text strings into an external datafile which is read by a function call (FNx). Hugely fiddly to get right.
Then, in 2023, work resumed:
  • Massively compressed the game code so that it would all fit into one main program file (G.HAMP01) which loads at &1300 and uses a constantly open filehandle to read text from the datafile $.TEXT throughout gameplay.
  • Fixed bug around line 4110 where <rot13>PYBP</rot13> couldn't be <rot13>RKNZvarq</rot13> because of the condition IF(?&917=1AND?&917=5) !!!
  • Fixed bug around line 4300 where <rot13>XRL</rot13> couldn't be <rot13>RKNZvarq</rot13> because of the condition (?&91B=1AND?&91B=5) !!!
  • Fixed bug around line 4410: faulty logic (missing parens): IFB$="SCIS"AND?&909=1OR?&909=5
  • Fixed a typo: <rot13>fjrrg-fzryyvat fzbxr</rot13> … *"ad the" for "...and the". Fix involved carefully hexediting the disc-image so as not to disturb the string-start offsets for FNx!
  • Added a response for EXAMining existent objects that don't have explicit EXAM-text.
  • Programmatically fixed message 44487 wordwrap!: <rot13>Gurer'f ab tbbq fhesnpr ba gur Fnvag Oreaneq qbt.</rot13>
  • Programmatically added a missing inverted comma in one of <rot13>Tregvr'f NFX ercyvrf</rot13> and on <rot13>GUEBJ ZNYYRG</rot13>.
  • Fixed call to PROCquit by adding ENDPROC in DEFPROCact to prevent "I don't know that word" message!
  • Added DEFFNb. Fixed implementation of blank line before "What now?" prompt.
  • Reduced the height (and the flickeriness) of the status line at the top of the screen.
  • Added credits (G.HAMP09).
  • Programmatically fixed message 52263 (DEFPROCopenup).
  • Tweaked inter-paragraph spacing of messages about <rot13>gur onfxrg oheavat</rot13>.
  • Removed junk data from $.TEXT and then had to correct all offsets higher than 21620 in G.HAMP01!
  • Integrated PROCsplit and PROCact into PROCm.
  • Improved input routine (treat multiple spaces as single space). Eliminated PROCa.
  • Found that PAGE can be raised to &1900, thanks to the CLEAR trick. So created a new init routine: PROCa.

:idea:

EDIT: obfuscated spoilers.
EDIT: more bugfixes.
EDIT: changed release year from 2003 to 2006 because of this: https://web.archive.org/web/20121104023 ... guest.html
EDIT: more synonyms.
EDIT: handled another command.
EDIT, 2023: massive changes.
Last edited by lurkio on Sat Jun 24, 2023 9:22 am, edited 18 times in total.
User avatar
Dave_E
Posts: 908
Joined: Fri Jun 16, 2006 1:55 pm
Location: Middlesbrough
Contact:

Re: To Hell In A Hamper (2003) — an old new game

Post by Dave_E »

Ideally I wouldn't have written a review of my own conversion but back in the days of EUG, I had to wear quite a few hats. I recall it took me about a week to write this. Worth it I think though. A really good adventure which BBC/Elk owners otherwise would never have seen.
User avatar
lurkio
Posts: 4351
Joined: Wed Apr 10, 2013 12:30 am
Location: Doomawangara
Contact:

Re: To Hell In A Hamper (2003) — an old new game

Post by lurkio »

Dave_E wrote: Mon Jul 08, 2019 11:59 pmI recall it took me about a week to write this. Worth it I think though.
Definitely! Did you have to disassemble/decompile the ADRIFT version? (I don't know how ADRIFT works at all.) Or was it a different version that you ported?

:?:
User avatar
Dave_E
Posts: 908
Joined: Fri Jun 16, 2006 1:55 pm
Location: Middlesbrough
Contact:

Re: To Hell In A Hamper (2003) — an old new game

Post by Dave_E »

Oooh, now you're asking. If I remember correctly, I had the solution and I wrote the whole thing first by following it through. Then I was able to get a list of all the messages in the game and the variables that were set for them to appear, so then I just put them in. Obviously there was *so* much text that it *had* to be split up into all of the different files, because clearly it wasn't written with any of the Electron's limitations in mind...!
User avatar
leenew
Posts: 4900
Joined: Wed Jul 04, 2012 4:27 pm
Location: Doncaster, Yorkshire
Contact:

Re: To Hell In A Hamper (2003) — an old new game

Post by leenew »

Hi Dave,
While you are online.... could I direct your attention here for a moment? :wink: viewtopic.php?f=7&t=15952&p=241419&hili ... es#p241406

Lee.
Rod C
Posts: 1000
Joined: Wed Jul 04, 2018 3:26 pm
Location: Australia
Contact:

Re: To Hell In A Hamper (2003) — an old new game

Post by Rod C »

I've been having some fun with this quirky adventure today. Found lots of things but can't work out what to do with most of them.

Just want to say thanks and also there seems to be a bug which crashes the program after <rot 13> rknzvar napube ebcr </rot 13>. This happened consistently until I made a bit more progress then it didn't crash (but didn't help either).

Rod
User avatar
BigEd
Posts: 6261
Joined: Sun Jan 24, 2010 10:24 am
Location: West Country
Contact:

Re: To Hell In A Hamper (2003) — an old new game

Post by BigEd »

Thanks for the rot13!
User avatar
lurkio
Posts: 4351
Joined: Wed Apr 10, 2013 12:30 am
Location: Doomawangara
Contact:

Re: To Hell In A Hamper (2003) — an old new game

Post by lurkio »

Rod C wrote: Tue Jul 09, 2019 10:38 am I've been having some fun with this quirky adventure today. Found lots of things but can't work out what to do with most of them.
Have you tried the HINT command?

Rod C wrote: Tue Jul 09, 2019 10:38 amJust want to say thanks and also there seems to be a bug which crashes the program after <rot 13> rknzvar napube ebcr </rot 13>. This happened consistently until I made a bit more progress then it didn't crash (but didn't help either)
Thanks. I’ll have a look.

:idea:
Rod C
Posts: 1000
Joined: Wed Jul 04, 2018 3:26 pm
Location: Australia
Contact:

Re: To Hell In A Hamper (2003) — an old new game

Post by Rod C »

Have you tried the HINT command?
Ahh, there are hints!! They look a bit like spoilers so I'll try to resist temptation but I think I have some direction now.

By the way, tempting though it is to push my companion it seems that he is "har too heave for me to move"

Rod
Rod C
Posts: 1000
Joined: Wed Jul 04, 2018 3:26 pm
Location: Australia
Contact:

Re: To Hell In A Hamper (2003) — an old new game

Post by Rod C »

Love the crazy humour in this game. Found another bug too. If I <rot13> guebj unaqxrepuvrsf </rot13> Hubert intervenes, then if I try to take them again, we crash out with : No such FN/PROC at line 1570.

Rod
User avatar
lurkio
Posts: 4351
Joined: Wed Apr 10, 2013 12:30 am
Location: Doomawangara
Contact:

Re: To Hell In A Hamper (2003) — an old new game

Post by lurkio »

Rod C wrote: Tue Jul 09, 2019 2:28 pm Love the crazy humour in this game. Found another bug too. If I <rot13> guebj unaqxrepuvrsf </rot13> Hubert intervenes, then if I try to take them again, we crash out with : No such FN/PROC at line 1570.
Thanks. I've fixed this bug and the previous ones you reported.

:idea:
Rod C
Posts: 1000
Joined: Wed Jul 04, 2018 3:26 pm
Location: Australia
Contact:

Re: To Hell In A Hamper (2006) — an old new game

Post by Rod C »

Huzzah!!! I finally survived but needed one big hint near the end or I would have gone loonier than Mr Booby. Thanks guys!
User avatar
lurkio
Posts: 4351
Joined: Wed Apr 10, 2013 12:30 am
Location: Doomawangara
Contact:

Re: To Hell In A Hamper (2006) — an old new game

Post by lurkio »

Rod C wrote: Thu Jul 11, 2019 3:38 pm Huzzah!!! I finally survived but needed one big hint near the end or I would have gone loonier than Mr Booby. Thanks guys!
Well done, and thanks for the bug reports!

:idea:
User avatar
lurkio
Posts: 4351
Joined: Wed Apr 10, 2013 12:30 am
Location: Doomawangara
Contact:

Re: To Hell In A Hamper (2006) — an old new game

Post by lurkio »

Rod C wrote: Thu Jul 11, 2019 3:38 pmneeded one big hint near the end
Was it to do with <rot13> ZNXR CNENPUHGR </rot13> by any chance?

:?:
Rod C
Posts: 1000
Joined: Wed Jul 04, 2018 3:26 pm
Location: Australia
Contact:

Re: To Hell In A Hamper (2006) — an old new game

Post by Rod C »

HA HA I think I can say yes to that without even decoding! I tried every combination of actions I could think of until my brain hurt. A couple of things seemed to be false clues too but that's fine. After getting the decisive hint I thought it was so random that nobody could ever get it but now I think about it the clues are there. I just needed to think outside the rut I was in. I probably gave in too quickly because it would be a buzz to get it. Perhaps it would be one of those problems where you sleep on it and then the answer appears from nowhere...

A great little game that has made me think I might try some other adventures. Probably have another go at Maze of Madness when my brain settles down! :lol:
User avatar
Dave_E
Posts: 908
Joined: Fri Jun 16, 2006 1:55 pm
Location: Middlesbrough
Contact:

Re: To Hell In A Hamper (2006) — an old new game

Post by Dave_E »

Nice to see this has finally got a bit of love... You could always play my game Sunday too:

http://www.everygamegoing.com/egg/landi ... le/Sunday/

It's not on the BBC archive site for some reason, although To Hell And A Hamper is.
User avatar
lurkio
Posts: 4351
Joined: Wed Apr 10, 2013 12:30 am
Location: Doomawangara
Contact:

Re: To Hell In A Hamper (2006) — an old new game

Post by lurkio »

Dave_E wrote: Sat Jul 13, 2019 10:18 am You could always play my game Sunday too:

http://www.everygamegoing.com/egg/landi ... le/Sunday/

It's not on the BBC archive site for some reason, although To Hell And A Hamper is.
I’ll have a look.

Btw, I notice the “Book” link seems to be broken..?

:!:
User avatar
Dave_E
Posts: 908
Joined: Fri Jun 16, 2006 1:55 pm
Location: Middlesbrough
Contact:

Re: To Hell In A Hamper (2006) — an old new game

Post by Dave_E »

I need to investigate how to fix that... It's the same for all books on the site. It times out before the book completes downloading. There must be a simple fix for this because I've downloaded huge files through the browser on other sites.
User avatar
Dave_E
Posts: 908
Joined: Fri Jun 16, 2006 1:55 pm
Location: Middlesbrough
Contact:

Re: To Hell In A Hamper (2006) — an old new game

Post by Dave_E »

Fixed.
User avatar
lurkio
Posts: 4351
Joined: Wed Apr 10, 2013 12:30 am
Location: Doomawangara
Contact:

Re: To Hell In A Hamper (2006) — an old new game

Post by lurkio »

Dave_E wrote: Sat Jul 13, 2019 10:18 am Nice to see this has finally got a bit of love... You could always play my game Sunday too:

http://www.everygamegoing.com/egg/landi ... le/Sunday/
Is it me or is it impossible to get past the options screen?

I've tried various Beeb emulators.

:?:
User avatar
Dave_E
Posts: 908
Joined: Fri Jun 16, 2006 1:55 pm
Location: Middlesbrough
Contact:

Re: To Hell In A Hamper (2006) — an old new game

Post by Dave_E »

From memory, you have to press M to stop the music before setting the options. There are full instructions on the Everygamegoing site:

https://www.everygamegoing.com/egg/land ... tle/Sunday
User avatar
lurkio
Posts: 4351
Joined: Wed Apr 10, 2013 12:30 am
Location: Doomawangara
Contact:

Re: To Hell In A Hamper (2006) — an old new game

Post by lurkio »

TL/DR: To Hell In A Hamper is faster now: http://bbcmicro.co.uk/game.php?id=3199

In 2019, after my first batch of bugfixes to the game To Hell In A Hamper had been completed, I continued to work on the code to try to make it more performant because the game itself is so delightful that I wanted to make the experience of playing it on a Beeb as frictionless as possible. And I thought that the best way to do that would be to try to compress the BASIC code in the seven separate programs that made up the game. The seven programs resided in seven separate files, and they CHAINed each other, back and forth, per Dave Edwards's ingenious design which he came up with when he first ported the game from ADRIFT to BBC BASIC for the Electron back in 2006.

My overall aim was to reduce the total number of separate programs that needed to be CHAINed during gameplay, and hence speed up the gameplay experience for the player. But how many of the seven separate programs could I merge? What was the minimum number of BASIC programs that I could squeeze all this game-code into, given the constraints of the main RAM in a standard Beeb..? (I didn't want to start dabbling with Sideways RAM because it's beyond me!)

(NOTE: While this *is* a technical post, it's *not* the sort of terrifying assembler/mathematical wizardry that can be seen in, say, the posts that Mark Moxon's been writing about hacking Elite. If you understand Mark's posts, you simply have no business being here or reading *this* post: it's absurdly long and pathetically self-satisfied, and it'll only fill you with scorn or pity.)

Anyway, I started by offloading all the text-strings, which had been hardcoded into the seven BASIC programs that made up the main game code, into a datafile on disc because the strings were taking up massive amounts of space in the program listings. I did that by exporting the BASIC program listings from BeebEm to plain textfiles on my host OS (macOS, as it happens) so that I could inspect and manipulate the listings in a modern text-editor (BBEdit, as it happens). I then used a combination of BBEdit's regex features, macOS commandline tools, and some simple BASIC programs to extract the strings from the BASIC sources and write them to a datafile on disc ($.TEXT), keeping a note, for each string, of its starting offset within the datafile, so that I could use that offset in a function call in the BASIC game code, instead of quoting the string in full.

So, now, rather than saying things like this...

Code: Select all

PRINT"You are standing in the basket of a hot-air balloon, and you are very, very worried!"
...the programs would just be able to say something like this instead:

Code: Select all

PRINT FNx(27955)
Which saves a considerable amount of space in main memory!

I did all that in 2019 and then ran out of steam and forgot about the project. I recently rediscovered it, though, and found that not only had I offloaded the strings and tweaked the BASIC programs to read the strings in from disc with a function call, but I also seemed to have moved some of the BASIC code from six of the seven programs into the first program (the "main" program), in a half-hearted or abortive attempt to reduce the amount of CHAINing during gameplay. There was some speedup, but the game was still grinding to a halt whenever the main program needed to call out to one of the other six programs to handle a command it didn't know enough about. Which was happening far too often.

So I needed to find a way to get more of the BASIC code into the main program -- ideally, to get *all* of the BASIC code into just that one main program! But was that even possible? Surely it was the stuff of a madman's dreams? As they stood, in 2019, post string-offloadification, the seven game programs still had a total size of 40,818 bytes -- or 39K! There was surely no way to shrink that down into a single program that was small enough to run on a standard Beeb, in, at *most*, 26K (in MODE7 with PAGE at &1300)! But, because I like a challenge (and am an idiot), I persevered.

I had to find more ways to merge more of the code into the first main program and compress it so that it would all still somehow fit into memory. That's where SteveF's excellent basiclabel and basictool utilities came in. (I used basiclabel simply to remove REMs from the BASIC source textfile, so that I didn't have to worry about REMs cluttering up the code and making the program too big to fit into main RAM prior to compression by basictool.)

basictool compresses BASIC programs on a modern commandline by emulating the 6502 CPU of a Beeb and implementing the minimum number of OS calls and other affordances that are needed by the Pack feature of the PRES Advanced BASIC Editor (ABE) ROM: thus basictool effectively allows you to run PRES ABE Pack on the commandline of your modern OS (macOS, in my case).

So I set about merging and compressing, merging and compressing, merging and compressing... And I seemed to be making progress! I was moving more and more of the command-handling code from the other six programs into the first, running the resulting bigger main program through basictool after each move. And it was working! I was sailing through the clouds, with my destination in sight..!

And then I ran out of memory.

The main program had become so big -- so much of the other six programs' code had been merged into it -- that it would no longer fit into the main RAM of basictool's virtual Beeboid, and so PRES ABE Pack couldn't even see it! The main prog was just too big to fit into RAM in the first place, so PRES ABE Pack was never gonna be able to get a look at it, let alone start to compress it!

And the partial merge I'd achieved so far hadn't speeded up the gameplay enough for my liking. The main program still couldn't handle all the commands that the player might be expected to use. It still had to CHAIN one of the subsequent six progs from time to time. And that was slowing gameplay down. Argh!

What to do? What to do..?!

Oh, sure, I could come up with clever little Harstonian optimisations for, say, the following code (210 bytes, tokenised)...

Code: Select all

1030DEFPROCr:F=RND(7)+2:IF F=3 F$="three" ELSE IF F=4 F$="four" ELSE IF F=5 F$="five" ELSE IF F=6 F$="six" ELSE IF F=7 F$="seven" ELSE IF F=8 F$="eight" ELSE F=9:F$="nine"
1040PRINT'"The clock chimes ";F$;" times:":FOR G=1 TO F:PRINT"CUCKOO! ";:NEXT:PRINT':ENDPROC
...and manually rewrite it into code that looked like this (146 bytes, tokenised)...

Code: Select all

1030DEFPROCr:F=RND(7):PRINT'"The clock chimes "MID$("threefourfivesixseveneightnine",VALMID$("01061014172227",2*F-1,2),VALMID$("5443554",F,1))" times:"'STRING$(F+2,"CUCKOO! ")':ENDPROC
...thus saving sixty-four whole bytes!

And then there was this (640 bytes, tokenised)...

Code: Select all

1821IFc=?&901PRINTFNx(49351)
1822IFc=?&902PRINTFNx(49364)
1823IFc=?&903PRINTFNx(49371)
1830IFc=?&904PRINTFNx(49382)
1840IFc=?&905PRINTFNx(49399)
1850IFc=?&906PRINTFNx(49410)
1860IFc=?&907PRINTFNx(49437)
1870IFc=?&908PRINTFNx(49458)
1880IFc=?&909PRINTFNx(49469)
1890IFc=?&90APRINTFNx(49489)
1900IFc=?&90BPRINTFNx(49499)
1910IFc=?&90CPRINTFNx(49515)
1920IFc=?&90DPRINTFNx(49534)
1930IFc=?&90EPRINTFNx(49546)
1940IFc=?&90FPRINTFNx(49568)
1950IFc=?&910PRINTFNx(49581)
1960IFc=?&911PRINTFNx(49593)
1970IFc=?&912PRINTFNx(49612)
1980IFc=?&913PRINTFNx(49625)
1990IFc=?&914PRINTFNx(49641)
2000IFc=?&917PRINTFNx(49655)
2010IFc=?&918PRINTFNx(49671)
2020IFc=?&919PRINTFNx(49683)
2030IFc=?&91APRINTFNx(49696)
2040IFc=?&91BPRINTFNx(49704)
2050IFc=?&91CPRINTFNx(49711)
2060IFc=?&91DPRINTFNx(49733)
2070IFc=?&91EPRINTFNx(49743)
2080IFc=?&91FPRINTFNx(49759)
...which could be rewritten like this (235 bytes, tokenised)...

Code: Select all

1830D.49351,49364,49371,49382,49399,49410,49437,49458,49469,49489,49499,49515,49534,49546,49568,49581,49593,49612,49625,49641,49655,49671,49683,49696,49704,49711,49733,49743,49759
1840RES.1830:F.I=1TO&1F:IFI=&15ORI=&16N.EL.READM:IFc=I?&900P.FNx(M):N.EL.N.
...thus saving 405 bytes!

But it wasn't enough! It wasn't enough! The main prog was still too bloody big..!

There was only one option left.

I would just have to grit my teeth and liposuck.

"Liposucking" is a rather disgusting term which I came up with while I was manually crunching Lee's perilously prolix progs for his SIGMA Experiment game: the term refers to the process of turning yourself into a robot and mindlessly applying a simple but tedious algorithm to a piece of code to drastically reduce its size -- but you have to do it all manually! Hence the tedium. It sucks.

Liposucking depends on the insight that the following code (59 bytes, tokenised)...

Code: Select all

10DEFPROCA(A)
20IF A=1 PRINT"1":ENDPROC
30IF A=5 PRINT"5":ENDPROC
40PRINT "Other":ENDPROC
...can be rewritten like this (55 bytes, tokenised)...

Code: Select all

10DEFPROCA(A)
20IF A=1 PRINT"1":ENDPROC ELSEIF A=5 PRINT"5":ENDPROC ELSEPRINT "Other":ENDPROC
...thus saving a whopping four bytes sterling.

Concatenating two consecutive lines can save space because it eliminates the overhead of the "hidden" metadata that needs to be stored at the start of each new line in a BASIC program. The example above is trivial, and the space saved is small, but, as Tesco is fond of reminding us, every little helps. And it can add up:

Code: Select all

3850DEFPROCexam
3860IFB$="ALTI" PRINTFNx(12831)'A%;FNx(12867)''FNx(12891):ENDPROC
3870IFB$="ARMS"AND(?&91F=1OR?&91F=5) PRINTFNx(12973)
3880IFB$="ARMS"AND(?&91F=1OR?&91F=5) PRINTFNx(13174)'FNx(13252)'FNx(13290):ENDPROC
3890IFB$="UNDE"AND(?&90E=1OR?&90E=5OR?&90E=7) PRINTFNx(13326)'FNx(13405):ENDPROC
3900IFB$="ANCH"ANDC$="ROPE"ANDD%=0 PROCanc:ENDPROC
3910IFB$="ANCH"ANDC$="ROPE"ANDD%>0 PRINTFNx(13417)'FNx(13452)'FNx(13490):ENDPROC
3920IFB$="ANDE" PRINTFNx(13512)'FNx(13551):ENDPROC
3930IFB$="APRO" AND ?&901=5 PRINTFNx(13586):ENDPROC
3940IFB$="BALL" AND ?&90B=1 AND ?&91E=1 PRINTFNx(13704):ENDPROC
3950IFB$="BALL" AND ?&90B=1 AND ?&91E=0 B$="YARN"
3960IFB$="BALL" AND ?&90B=0 AND ?&91E=1 B$="CRIC":C$="BALL"
3970IFB$="BALO" PRINTFNx(13766)'FNx(13844)
3980IFB$="BALO" PRINTFNx(13964)'FNx(14003)
3990IFB$="BALO" PRINT'FNx(14154)'FNx(14191):ENDPROC
4000IFB$="BOOB" AND ?&900=5 PROCeb:ENDPROC
4010IF B$="BOX" AND ?&905=1 PROCbox:ENDPROC
4020IFB$="BARR" AND ?&916=5 PRINTFNx(14223)'FNx(14260):ENDPROC
4030IFB$="BASK" PRINTFNx(14331)'FNx(14406)'FNx(14444)
4040IFB$="BASK" PRINT'FNx(14478)'FNx(14557)'FNx(14634)
4050IFB$="BASK" PRINTFNx(14675)'FNx(14713)'FNx(14789)''FNx(14809):ENDPROC
4060IFB$="BUTT" AND O%=1 PRINTFNx(14865)'FNx(14903)
4070IFB$="BUTT" AND O%=1 PRINTFNx(15063):ENDPROC
4080IFB$="BOOM"AND(?&912=1OR?&912=5) PRINTFNx(15084):ENDPROC
4090IFB$="BOTT" AND ?&901=5 PRINTFNx(15236):ENDPROC
4100IFB$="BREA" AND C$="POCK" PROCbreast:ENDPROC
4110IFB$="CARP"AND(?&90F=1OR?&90F=5) PROCcarpetbag:ENDPROC
4120IFB$="CLOC"AND(?&917=1AND?&917=5) PRINTFNx(15323)'FNx(15360)'FNx(15439);
4130IFB$="CLOC"AND(?&917=1AND?&917=5) PRINTFNx(15481)'FNx(15521)'FNx(15559)'FNx(15637):ENDPROC
4140IFB$="CRIC"ANDC$="BALL"AND(?&91E=1AND?&91F=5) PRINTFNx(15663)'FNx(15698):ENDPROC
4150IFB$="DOG"AND(?&902=5OR?&902=9) PROCdog:ENDPROC
4160IFB$="DONK"AND(?&914=1OR?&914=5) PRINTFNx(15773)'FNx(15809)'FNx(15847):ENDPROC
4170IFB$="GAS"ANDC$="VALV" PROCval:ENDPROC
4180IFB$="HAND" AND ?&906=3 PRINTFNx(15938)'FNx(16010)'FNx(16048);:ENDPROC
4190IFB$="HAND"AND(?&906=1OR?&906=5) PRINTFNx(16090)'FNx(16124):ENDPROC
4200IFB$="HAT" AND(?&918=9OR?&918=1OR?&918=5) PRINTFNx(16174)'FNx(16213);:IF?&918=1OR?&918=5PRINT:ENDPROC
4210IFB$="HAT"AND?&918=9 PRINTFNx(16319)'FNx(16372):ENDPROC
4220IFB$="CANE" AND ?&901=5 PRINTFNx(16468)'FNx(16506):ENDPROC
4230IFB$="EYES" PRINTFNx(16547):ENDPROC
4240IFB$="HAIR" PRINTFNx(16619)'FNx(16657):ENDPROC
4250IFB$="LINI" AND O%>1 PROCli:ENDPROC
4260IFB$="LIGH"ANDO%>1AND(?&907=1OR?&907=5) PRINTFNx(16709)'FNx(16743):ENDPROC
4270IFB$="GERT" AND ?&901=5 PRINTFNx(16779)'FNx(16898):ENDPROC
4280IFB$="HATC"AND(?&908=1OR?&908=5) PRINTFNx(16979):ENDPROC
4290IFB$="HEAV" PRINTFNx(17067):ENDPROC
4300IFB$="KEY"AND(?&91B=1AND?&91B=5) PRINTFNx(17157)'FNx(17193):ENDPROC
4310IFB$="MALL"AND(?&904=1OR?&904=5) PRINTFNx(17203)'FNx(17242):ENDPROC
4320IFB$="MUMM"AND(?&90C=1OR?&90C=5) PRINTFNx(17298)'FNx(17333):ENDPROC
4330IFB$="PADL"AND(?&915=1OR?&915=5) PROCpad:ENDPROC
4340IFB$="PAIN"AND(?&910=1OR?&910=5) PRINTFNx(17344)'FNx(17381)'FNx(17460):ENDPROC
4350IFB$="PARC"AND(?&91C=1OR?&91C=5) PRINTFNx(17506):ENDPROC
4360IFB$="PARA"AND(?&919=1OR?&919=5) PRINTFNx(17584)'FNx(17622):ENDPROC
4370IFB$="OVER"AND?&900=5ANDO%>0 PROCexamovercoat:ENDPROC
4380IFB$="POCK"AND?&900=5ANDO%=1 PRINTFNx(17654)'FNx(17690):ENDPROC
4390IFB$="POCK"AND?&900=5ANDO%>1 PRINTFNx(17654)'FNx(17756):ENDPROC
4400IFB$="ROPE" PRINTFNx(17805)'FNx(17844)'FNx(17880)'FNx(17919):ENDPROC
4410IFB$="INSI"ANDC$="POCK"AND?&900=5ANDO%>1 PROCip:ENDPROC
4420IFB$="SCIS"AND?&909=1OR?&909=5 PROCexamscissors:ENDPROC
4430IFB$="LABE"AND?&909=1ANDV%=1 PROClabel:ENDPROC
4440IFB$="SIDE"ANDC$="POCK"AND?&900=5 PROCsip:ENDPROC
4450IFB$="TROM"AND(?&90D=1OR?&90D=5) PROCtrom:ENDPROC
4460IFB$="TRUM"AND(?&913=1OR?&913=5) PRINTFNx(17978):ENDPROC
4470IFB$="TWIG"AND(?&911=1OR?&911=5) PROCess:ENDPROC
4480IFB$="VASE"AND(?&91A=1OR?&91A=5) PRINTFNx(18011)'FNx(18089)''FNx(18136);
4490IFB$="VASE"AND(?&91A=1OR?&91A=5) PRINTFNx(18178)'FNx(18216):ENDPROC
4500IFB$="VOLC" PRINTFNx(18244)
4510IFB$="VOLC" PRINTFNx(18444)'FNx(18559):ENDPROC
4520PRINTFNx(18638)
4530ENDPROC
The above (3105 bytes, tokenised) can be turned into the following unreadable mess (2769 bytes, tokenised)...

Code: Select all

3850DEFPROCexam
3860IFB$="ALTI"P.FNx(12831)'A%;FNx(12867)''FNx(12891):END. EL.IFB$="ARMS"A.(?&91F=1OR?&91F=5)P.FNx(12973)'FNx(13174)'FNx(13252)'FNx(13290):END. EL.IFB$="UNDE"A.(?&90E=1OR?&90E=5OR?&90E=7)P.FNx(13326)'FNx(13405):END.
3900IFB$="ANCH"A.C$="ROPE"A.D%=0PROCanc:END. EL.IFB$="ANCH"A.C$="ROPE"A.D%>0 P.FNx(13417)'FNx(13452)'FNx(13490):END. EL.IFB$="ANDE"P.FNx(13512)'FNx(13551):END. EL.IFB$="APRO"A.?&901=5P.FNx(13586):END.
3940IFB$<>"BALL"EL.IF?&90B<>1EL.IF?&91E=1P.FNx(13704):END. EL.IF?&91E=0B$="YARN"
3960IFB$="BALL"A.?&90B=0A.?&91E=1B$="CRIC":C$="BALL"EL.IFB$="BALO" PRINTFNx(13766)'FNx(13844)'FNx(13964)'FNx(14003)''FNx(14154)'FNx(14191):END. EL.IFB$="BOOB"A.?&900=5PROCeb:END. EL.IF B$="BOX"A.(?&905=1OR?&905=5)PROCbox:END.
4020IFB$="BARR"A.?&916=5P.FNx(14223)'FNx(14260):END. EL.IFB$="BASK"P.FNx(14331)'FNx(14406)'FNx(14444)''FNx(14478)'FNx(14557)'FNx(14634)'FNx(14675)'FNx(14713)'FNx(14789)''FNx(14809):END.
4060IFB$="BUTT"A.O%=1P.FNx(14865)'FNx(14903)'FNx(15063):END. EL.IFB$="BOOM"A.(?&912=1OR?&912=5)P.FNx(15084):END. EL.IFB$="BOTT"A.?&901=5P.FNx(15236):END. EL.IFB$="BREA"A.C$="POCK"PROCbreast:END.
4110IFB$="CARP"A.(?&90F=1OR?&90F=5)PROCcarpetbag:END. EL.IFB$="CLOC"A.(?&917=1OR?&917=5)P.FNx(15323)'FNx(15360)'FNx(15439);FNx(15481)'FNx(15521)'FNx(15559)'FNx(15637):END.
4140IFB$="CRIC"A.C$="BALL"A.(?&91E=1A.?&91F=5)P.FNx(15663)'FNx(15698):END. EL.IFB$="DOG"A.(?&902=5OR?&902=9)PROCdog:END. EL.IFB$="DONK"A.(?&914=1OR?&914=5)P.FNx(15773)'FNx(15809)'FNx(15847):END. EL.IFB$="GAS"A.C$="VALV"PROCval:END.
4180IFB$<>"HAND"EL.IF?&906=3P.FNx(15938)'FNx(16010)'FNx(16048);:END. EL.IF(?&906=1OR?&906=5)P.FNx(16090)'FNx(16124):END.
4200IFB$="HAT" AND(?&918=9OR?&918=1OR?&918=5) PRINTFNx(16174)'FNx(16213);:IF?&918=1OR?&918=5PRINT:ENDPROC
4210IFB$="HAT"A.?&918=9P.FNx(16319)'FNx(16372):END. EL.IFB$="CANE"A.?&901=5P.FNx(16468)'FNx(16506):END. EL.IFB$="EYES"P.FNx(16547):END. EL.IFB$="HAIR"P.FNx(16619)'FNx(16657):END. EL.IFB$="LINI"A.O%>1PROCli:END.
4260IFB$="LIGH"A.O%>1A.(?&907=1OR?&907=5)P.FNx(16709)'FNx(16743):END. EL.IFB$="GERT"A.?&901=5P.FNx(16779)'FNx(16898):END. EL.IFB$="HATC"A.(?&908=1OR?&908=5)P.FNx(16979):END. EL.IFB$="HEAV"P.FNx(17067):END.
4300IFB$="KEY"A.(?&91B=1OR?&91B=5)P.FNx(17157)'FNx(17193):END. EL.IFB$="MALL"A.(?&904=1OR?&904=5)P.FNx(17203)'FNx(17242):END. EL.IFB$="MUMM"A.(?&90C=1OR?&90C=5)P.FNx(17298)'FNx(17333):END. EL.IFB$="PADL"A.(?&915=10)PROCpad:END.
4340IFB$="PAIN"A.(?&910=1OR?&910=5)P.FNx(17344)'FNx(17381)'FNx(17460):END. EL.IFB$="PARC"A.(?&91C=1OR?&91C=5)P.FNx(17506):END. EL.IFB$="PARA"AND(?&919=1OR?&919=5)P.FNx(17584)'FNx(17622):END.
4370IFB$="OVER"A.?&900=5A.O%>0PROCexamovercoat:END. EL.IFB$="POCK"A.?&900=5A.O%=1P.FNx(17654)'FNx(17690):END. EL.IFB$="POCK"A.?&900=5A.O%>1P.FNx(17654)'FNx(17756):END. EL.IFB$="ROPE"P.FNx(17805)'FNx(17844)'FNx(17880)'FNx(17919):END.
4410IFB$="INSI"A.C$="POCK"A.?&900=5A.O%>1PROCip:END. EL.IFB$="SCIS"A.(?&909=1OR?&909=5)PROCexamscissors:END. EL.IFB$="LABE"A.?&909=1A.V%=1PROClabel:END. EL.IFB$="SIDE"A.C$="POCK"A.?&900=5PROCsip:END.
4450IFB$="TROM"A.(?&90D=1OR?&90D=5)PROCtrom:END. EL.IFB$="TRUM"A.(?&913=1OR?&913=5)P.FNx(17978):END. EL.IFB$="TWIG"AND(?&911=1OR?&911=5)PROCess:END.
4480IFB$="VASE"A.(?&91A=1OR?&91A=5)P.FNx(18011)'FNx(18089)''FNx(18136);FNx(18178)'FNx(18216):END. EL.IFB$="VOLC"P.FNx(18244)'FNx(18444)'FNx(18559):END.
4520IFFNlookup(B$)<>""A.(?Z%=1OR?Z%=5)P."It is what it is."EL.PRINTFNx(18638)
...for a saving of 336 bytes. Not bad! (Btw, the reason for my spewing abbreviations like a thing possessed is that I wanted to make each untokenised line as short as I could, so that I would then be able to concatenate as many lines as possible while observing BASIC's line-length limit.)

This ENDPROC/ELSE line-concatenation is the sort of optimisation that PRES ABE Pack can't do because there probably wasn't enough room in a ROM (or even two ROMs) to encode the knowledge that a line in a PROC that begins with an IF and terminates with an ENDPROC can be joined to the following line if you insert an ELSE between the two. But we -- as clever humans with too much time on our hands and not enough brains to write assembly code -- can. So I did. And it took ages to do because I didn't want to automate the process with regexes or similar because I would never have trusted myself not to cock the automation up, and I would probably have ended up double-checking everything by eye anyway.

So I iterated the process of adding more code to the main program, and liposucking the hell out of it, till I had in fact managed to reduce the original seven interCHAINing programs down to one unreadable shrunken liposucked mass of gibberish which I then ran through basictool to crush it down even further… and it worked! It all worked! Seven programs down to one! I couldn't believe it.

See the unreadable main game program here -- click "Display" next to HAMP01:

http://bbcmicro.co.uk/explore.php?id=3199

(Throughout the process there was the constant worry that if I hadn't compacted the main program enough, then when it was running -- and as variables were being created and procedures were being called -- there still might not be enough spare RAM for the BASIC heap and the BASIC stack to grow. But I was rescued by a side-effect of the way Dave Edwards designed the original programs: because they had to CHAIN each other, they couldn't save the state of gameplay (the state of the player's progress so far) in ordinary BASIC variables because the values of ordinary BASIC variables are lost when one program CHAINs the next! So, instead, Dave decided to store state in the resident integer vars (A%, B%, ..., Z%) and in some memory locations at the beginning of Page &9 (i.e. memory locations &900, &901, etc.). That meant that I could add this sneaky line to the start of the main program loop...

Code: Select all

IFHIMEM-(!2AND&FFFF)<256CLEAR ...
...which would check whether the BASIC heap had grown too big and was in danger of causing a "No room" error -- and, if it had, would do a CLEAR, which erases the heap and the stack altogether, which is fine to do in this case because, as I said, nothing crucial will be lost: CLEAR doesn't touch the resident integer variables or memory locations below PAGE… In the end, though, I managed to liposuck the program to such an extent that this workaround wasn't needed.)

So, there you have it: seven programs, compressed into just one! (Okay, so the big main game program still has to CHAIN another prog if you type HINT or LOAD or SAVE coz I couldn't quite squeeze the code for LOAD and SAVE into main -- and I certainly hadn't a hope in hell of squeezing in the code for HINT... but come on! Gimme a break!)

And the compressed game feels much snappier than the previous interCHAINing version, and it runs well in emulators (especially if you disable disc-drive noises!), and it runs well on real Beebs too, especially from solid-state storage devices like MMFS-based SD-card solutions, or Goteks, or Datacentres. It's even tolerable when run from an actual physical floppy drive -- if you can put up with the noisy disc-access after almost every command you type into the game!

In summary, then: yay for me.

I've updated the first post in this thread with some of the bugfixes and other changes I made in the course of compacting the game.

You can play the compacted game online (or download it) at bbcmicro.co.uk:

http://bbcmicro.co.uk/game.php?id=3199

:idea:
Last edited by lurkio on Wed Jan 03, 2024 12:00 pm, edited 8 times in total.
User avatar
colinhoad
Posts: 228
Joined: Fri Mar 15, 2019 2:25 pm
Location: London, UK
Contact:

Re: To Hell In A Hamper (2006) — an old new game

Post by colinhoad »

This was an absolutely fascinating read, well done on persevering! There are some excellent tips here for compression, most of which I'd never come across before - although I'd seen your "liposuck" technique in certain type-in listings from magazines (though you get the credit for naming the technique thus!)

Thanks for doing this and for sharing the route you took. I personally thoroughly enjoyed reading it (and I actually *understood* it :lol: )
Last edited by colinhoad on Sat Mar 04, 2023 1:28 pm, edited 1 time in total.
User avatar
lurkio
Posts: 4351
Joined: Wed Apr 10, 2013 12:30 am
Location: Doomawangara
Contact:

Re: To Hell In A Hamper (2006) — an old new game

Post by lurkio »

colinhoad wrote: Sat Mar 04, 2023 9:17 am This was an absolutely fascinating read, well done on persevering! There are some excellent tips here for compression, most of which I'd never come across before - although I'd seen your "liposuck" technique in certain type-in listing from magazines (though you get the credit for naming the technique thus!)
Thank you, Colin! And thank you for doing your programming videos on YouTube, which I really enjoy -- and hope to see more of!

I think inventing the term "liposuck" (for this specific context) will be my lasting legacy. And I'm fine with that.

:-s :^o
fuzzel
Posts: 1191
Joined: Sun Jan 02, 2005 1:16 pm
Location: Cullercoats, North Tyneside
Contact:

Re: To Hell In A Hamper (2006) — an old new game

Post by fuzzel »

Very, very well done. =D> This was a high-stakes game you were playing in that you either succeeded and managed to merge the seven programs into one or you ended up failing. There's not really a half-way house solution that would have been worth replacing the original game for. I'd go so far as to say as you must now be the goto guy :) for Basic compression on Stardot with that toolkit of techniques of yours. And you're forgiven for excluding load, save and hints as these are not time-sensitive elements of the main game. I've recently come across a number of old text adventures of mine written back in my misspent youth :wink: but, unfortunately, when playing them again I've encountered "No room" errors because I just didn't understand how the Basic stack worked (although I've noticed there have been at least one set of articles in The Micro User over the years which explain exactly how it works and they're well worth a read). My own preference for avoiding out of memory errors, btw, is to use assembly language. As for the game itself, I've played it at least twice in the last few years but I've never managed to get out of the first location. :)
User avatar
lurkio
Posts: 4351
Joined: Wed Apr 10, 2013 12:30 am
Location: Doomawangara
Contact:

Re: To Hell In A Hamper (2006) — an old new game

Post by lurkio »

fuzzel wrote: Sat Mar 04, 2023 7:33 pm Very, very well done ... you either succeeded and managed to merge the seven programs into one or you ended up failing. There's not really a half-way house solution that would have been worth replacing the original game for.
Thanks, fuzzel! If I'd failed to merge all seven progs into one I simply wouldn't have mentioned any of this, and no one would have been any the wiser about my private shame... :)

fuzzel wrote: Sat Mar 04, 2023 7:33 pm My own preference for avoiding out of memory errors, btw, is to use assembly language
If I had a clue about assembly language I'd probably have used it -- but I just don't! For me, the string-offloading, code-merging and liposucking were actually easier than trying to become good enough at assembler to convert the game from BASIC!

:roll: :lol:
User avatar
leenew
Posts: 4900
Joined: Wed Jul 04, 2012 4:27 pm
Location: Doncaster, Yorkshire
Contact:

Re: To Hell In A Hamper (2006) — an old new game

Post by leenew »

Lurkio said summat like: "I had no option but to start liposucking..."

Yes, I shall be eternally grateful for your sucking skills that you had the patience to go through SIGMA line by line.
It was important to me that the game ran on a standard beeb, but with my playground-level IF THEN coding, I just couldn't make it fit!
Several pounds of lipo later.... :-& and voila! it (still only-just-by the skin of its teeth) fitted.
So... well done, and thanks again =D>
Lee.
User avatar
lurkio
Posts: 4351
Joined: Wed Apr 10, 2013 12:30 am
Location: Doomawangara
Contact:

Re: To Hell In A Hamper (2006) — an old new game

Post by lurkio »

leenew wrote: Wed Mar 08, 2023 6:24 pm Yes, I shall be eternally grateful for your sucking skills that you had the patience to go through SIGMA line by line.
I still wake up screaming...

:shock:
User avatar
lurkio
Posts: 4351
Joined: Wed Apr 10, 2013 12:30 am
Location: Doomawangara
Contact:

Re: To Hell In A Hamper (2006) — an old new game

Post by lurkio »

Just found a weird VPN app called “Volcanically Parallel Noesis” which seems to connect you to networks in alternate realities. It somehow led me to this game box art from some strange side pocket in the multiverse where To Hell In A Hamper was released by Acornsoft in the 1980s:

42EABE97-F0FC-44DC-80FE-9D78F3DB9CCA.jpeg
fuzzel
Posts: 1191
Joined: Sun Jan 02, 2005 1:16 pm
Location: Cullercoats, North Tyneside
Contact:

Re: To Hell In A Hamper (2006) — an old new game

Post by fuzzel »

lurkio wrote: Sun Mar 19, 2023 12:42 pm Just found a weird VPN app called “Volcanically Parallel Noesis” which seems to connect you to networks in alternate realities. It somehow led me to this game box art from some strange side pocket in the multiverse where To Hell In A Hamper was released by Acornsoft in the 1980s:
Hi lurkio, I've just searched for your “Volcanically Parallel Noesis” app and come up with a blank so I can only presume that you managed to obtain a copy from your alternate reality :-k Oddly, that other reality doesn't appear to have a version of Kingdom of Hamil so perhaps some weird temporal-interdimensional induced mishap prevented Jonathan Partington or Peter Killworth from writing it (sounds like an idea for a text adventure). Can't wait to see what else you discover...
Post Reply

Return to “new projects and releases: text and graphic adventures”