Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Locked thread
JamieTheD
Nov 4, 2011

LPer, Reviewer, Mad Welshman

(Yes, that's a self portrait)
Being A Participation Let's Play In Several Parts, Also Known As "Let's Go Back To BASICs!"



When I was a wee lad, creating games was all about cheating. Or, y'know, writing in BBC Basic and changing numbers around in the hope that the games you made somehow became fair. Or that calling the DRAW command to make something truly nice didn't take forever (I have never found a good solution to this.)

But BASIC still has a place in my heart, because of the attitude to educating in it. Every time I open a game programming book, it's either peppered with poo poo that the writer expects you to already know, or uses specialist terms. Back in the day, though, there was a major push for computer literacy by the British Broadcasting Corporation, and the BBC Micro was born. A little bit later, a publishing group called Usborne-Hayes (Now just Usborne) created a series of educational books on... Well, programming for kids.

...They're super accessible, and it's not just because they're using BASIC. There's a machine code one in there too, and that, also, is pretty accessible (Although it is the weakest in the series, in terms of what it actually teaches you)

Okay, So... An Ancient Language On An 8 Bit System... Why Should I Care Today?

Because this Let's Play isn't just about the language... It's about how we forget to make teaching poo poo accessible. It's about game design history. And, just as importantly, it's about showing you that yes, you can have fun with limitations. And trying to hack this poo poo for different architecture. And the fact that this isn't a new problem.

In short, me (and hopefully some buddies) will be edjumitainmenting you. And hopefully, some of you goons will write your own tutorials for other languages and engines that learn the lessons these old books have to teach.

Oh, and folks still play with BASIC to this day, on all sorts of systems. In fact, here's a music video coded... On an Apple II. (https://www.youtube.com/watch?v=Gxe40xXQKko). The creator even released the source code: here (Thanks to InternetJanitor for that!)

Wait, Edjumitainment? Does That Mean You'll Actually Teach Us Stuff?

Oh yeah! In fact, I'll be setting little class exercises! If you want to play along, you can use BeebEM (BE link), and save your program to a disk image you've made. Don't worry, because BASIC programs are pretty drat small, you can fit loads of them on the same disc! As an example, here's a copy of the programs in Computer Space Games in Single Sided Disk Format, typed out by yours truly, with the other coursebooks we'll be using to follow (Computer Battle Games, Creepy Games [found on the Internet Archive], Write Your Own Adventure Programs, and Write Your Own Fantasy Games

BeebEM is a beautiful thing. It can emulate the main BBC models (Imperfectly, but it can do it), and, for the majority of this LP, we'll be using the bog-standard Model B (Something like 16K of RAM for all practical intents and purposes.) So, once you're in BeebEM, here's what you do.

1) Type in your program. This will, I guarantee, be the most frustrating part if you haven't spent some planning time.
2) File --> New Disc 0. You get to name it.
3) Type SAVE “[progname, no more than 7 letters]”, hit enter.
4) If you then go EDIT -> Export Files From Disc, you should see your BASIC Program listed, along with hex numbers that basically tell you where it is on disc, and how big it is (in 8 bit "blocks")
5) Put the disk somewhere I can reach it, and tell me it's there!
6) You can even put multiple programs on one disk! Although by the end of the thread, you may need another one.

If you want to check what's on the disc, type “*CAT” and hit enter. It'll chug a little, then show you what's on the disc. LOAD “[progname]” loads it, and then RUN runs the program (or just CH. "[progname]"...) Simple! And for those who don't particularly want entertainment? I'll be picking certain BBC Games to have a brief play of, to give you some idea of the variety of games that existed on the system. Also, I will be playing some of the games on the discs.

Oh, I'm Not Much Of A Programmer

Anyone can be a programmer. Seriously. The main obstacles aren't as much in the languages/engines and their quirks themselves (Although they do factor in, as we'll see), but in how we teach this kind of thing. We don't teach in terms of "What Do You Want To Do?" and "Adapt What You Know", so much as "Here are some programs, and how they work. Now check the reference guide for more ideas." Once you understand the basics of how a language works, you really can do amazing things from day 1. The key, as we'll see, is properly working out what you want to do first.

Can I Use Another 8-Bit System?

While the Beeb is preferable, and I will go into porting between different BASICs later, I can keep up, so if you're more comfortable with, say, a Speccy or an Apple, then sure! Not all the books, however, will help you as much as you'd like. For example, the C64 may not do everything the way other Commodore models did, so it's important to read the reference book for your chosen system!

The books have conversion keys, and this is what will be used for the main books. When you see one of these, that means you'll want to check the bottom of the listing to see what changes you need to make. Some of them, you'll get quite used to (Such as RND):


Because I know some folks want to use other than the Beeb, here's the conversion key

Now... Let's get started!



...Er... Well, at least that reminds me of a tune (Thanks, Great Joe!) that somewhat fits the situation we're in?

Contents and Stuff

Part 0.5 - Know The BASICs.
Part 1 - Guessing Games ... IN SPAAAAACE!!!
Part 1.5 - Exercise For The Class 1!
Part 2 - Creating A Shooting Gallery Via Text

EXTRA CREDIT

This is where nice thread contributions from the class have come in!

BABA FEKK - A Bounty Hunting Game By Tiggum
Paul.Power spreads the good word of Usborne, who have nicely released the set books. :dance:

JamieTheD fucked around with this message at 18:59 on Feb 24, 2016

Adbot
ADBOT LOVES YOU

JamieTheD
Nov 4, 2011

LPer, Reviewer, Mad Welshman

(Yes, that's a self portrait)
Part 0.5 – Know The BASICs


Not actually a bad way to learn!

There are good ways to learn BASIC, and bad ways to learn BASIC, just as with any tool or language out there. For example, I could have asked you to make a Tic-Tac-Toe game using just PRINT, IF (AND/OR) – THEN, LET, GOTO, and INPUT. Even if I explained these well, you would be tearing your hair out and calling me very rude names, because, even if they are the absolute basics you need to make a game, there is a reason there are more commands in BASIC, and at least part of that is to get around kludge. But before we can do any of this, we have to know how BASIC works.

Imagine a list. If you don't have any numbers on this list, things will only be done as you write them. For example, we could type “LET B=1” … And B will be one until we change it. Even though we can use that B for other commands now, it's pretty loving useless on its own, and isn't really a program. It's certainly not a game!

So we need a way of making sure the list will only run when we want it to. This is where numbered lines come in. BASIC runs on numbered lines, and the BBC will keep those numbered lines in its somewhat limited memory until either it can't keep any more (At which point it will tell you), until you type “NEW” and hit enter (In which case, it'll erase the whole program), or until you reset the BBC (Which resets the memory as its first step.) The BBC understands numbered lines, in its way, knowing that if you've put a number before a command, it's to save it to that numbered spot, and, when you type “RUN”, and hit ENTER, it'll go down those lines, one at a time, until it's done everything you asked it to, in the order you asked it to. This is what's known as a procedural language.

So let's build a simple program, to show you how it works. At least on 8-bit systems. Later versions, such as QuickBASIC for DOS, would allow you to write without numbers, and modern BASICs, like BlitzBASIC, DarkBASIC, and BBC Basic For Windows, are object oriented...

5 CLS
10 PRINT “HELLO WORLD!”
20 LET DAY$=”TUESDAY”
30 INPUT “WHAT'S TODAY AGAIN? “;WOTDAY$
40 IF WOTDAY$<>”TUESDAY” GOTO 70
50 PRINT “OH, GOOD, TODAY IS INDEED TUESDAY!”
60 END
70 PRINT “WAIT, TODAY IS “;WOTDAY$;”? CRAAAAAP!”

This program has all the simplest stuff. PRINT prints stuff on screen, with the “;” meaning “Add this on the end without any spaces or tabs”, LET stores stuff in memory ($ on the end for text, no $ on the end for numbers), INPUT can either be used on its own (for just straight up asking for text or number input, same as LET), or doubles as a combo of PRINT and INPUT without the quotes, GOTO goes to a certain line in the code (Fun Fact: BBC BASIC, and indeed, all the other procedural types of BASIC, check what line to GOTO by counting all the way from the beginning of the code. So the later a GOTO is in your program, the longer it takes!), while END... Ends the program before it's meant to. You'll notice I didn't put an END at the end of the program, because, once it's finished with the program, it's back to single commands.

You'll also notice two things: I didn't tell you about CLS (Clear Screen... Does what it says on the tin), and that the first line is the only one without a multiple of 10 being in the program listing. That's because it was standard practice to list the lines in multiples of 10, because you could then edit in 9 extra lines between each line, in case you wanted to add to the code without changing what you had. This convention will be used throughout, because it's useful.

But I did say these are the absolute basics of making a game. Why did I say that? Because a game, at a bare minimum, tells you a situation (or shows you), asks for your input, and then does something based on the input (often refreshing the screen to do so.) Modern games, even simple ones, follow these rules... It's just that they partition things better (Thanks to Object Oriented Programming), and they do it more (Because even a simple mouse pointer requires its own rules to follow)

By the end of this, you'll not only know enough BASIC to make something much classier, I'll also be showing you how the skills you're going to learn apply to games programming in general, and a little bit about changing attitudes in game design, for different values of “then” and “now”.

JamieTheD
Nov 4, 2011

LPer, Reviewer, Mad Welshman

(Yes, that's a self portrait)
Part 1 – Guessing Games... IN SPAAAACE!



Computer Space Games, released in the early 80s, is the first of the books we're going to visit. And it's going to tell us about many of the same things I told you in 0.5, but in a more practical and measured way. While another book in the series (Beginning BASIC) deals with individual commands, and what you can do with them, and the BBC User Guide has the skinny on all the BASIC commands, Computer Space Games is more like a cookbook: It spends a whole two pages saying:

“Here are your programs, you'll have to type them in, remember that BASIC has some differences across different systems (Just remember your symbol and you'll be fine [ours is a star]), you can edit these to your heart's content [and we're going to], you will make mistakes [Because typing out a program is mind numbing at the best of times], and here's how to list and run your program once it's done. HAVE FUN!”

There. That was nice and easy. And then it immediately launches into the programs. Here's our first. It's a guessing game. In fact, this, the next three or so games after it, and the majority of games in the book, are guessing games. They're nice and simple to program, you see. Let's take a look at the listing for this one.



EDIT: And the listing in text form, for ease of use. Thanks to Tiggum and RickVoid for noting this!

Tiggum posted:

It's an asterisk (*), for multiply. IIRC, the way it works is that RND generates a number between 0 and 1, so multiplying by a value and then converting to integer gives you a whole number between 0 and whatever value you chose, eg. if RND gives you 0.356 and you multiply by 20 you get 7.12, which rounds to 7.


Also, for this example, here's the original code:
pre:
10 CLS
20 PRINT "STARSHIP TAKE-OFF"
30 LET G=INT(RND(1)*20)
40 LET W=INT(RND(1)*40)
50 LET R=G*W
60 PRINT "GRAVITY= ";G
70 PRINT "TYPE IN FORCE"
80 FOR C=1 TO 10
90 INPUT F
100 IF F>R THEN PRINT "TOO HIGH";
110 IF F<R THEN PRINT TOO LOW";
120 IF F=R THEN GOTO 190
130 IF C<>10 THEN PRINT ", TRY AGAIN"
140 NEXT C
150 PRINT
160 PRINT "YOU FAILED -"
170 PRINT "THE ALIENS GOT YOU"
180 STOP
190 PRINT "GOOD TAKE OFF"

Now, you'll already have noticed the first nice thing about this book: It actually comments on the loving code (unlike many programmers you're going to meet). And, since it's procedural, we can literally go down this list to see what order it does things. So, let's examine that ourselves.

First, it clears the screen. This is loving useful, and most of these programs don't do it enough. Seriously, when you see a screenshot of how this thing looks in play, it's kludgy as gently caress. But it's a First Game, and decent screen refresh is easy to do. So easy to do, in fact, that that's going to be our exercise for this update. You don't even need to show me a file, just post what lines you'd add/change to fix the problem you're going to see.

Next, and most importantly, it a) Tells us what the game is called, and b) Sets the components of what we're going to be guessing. It does this using a shiny command I haven't talked about yet: RND, aka “Random Number Generator (Not clock based)” RN Jesus, as it is often known, is complicated stuff... But games programmers of the 80s didn't always appreciate how our good buddy RN Jesus worked, so they often used this instead of something more complicated. Put simply, it doesn't actually roll a dice or anything, with all that physics and micro interactions and other fun stuff that fucks with a “natural” random result, it generates a number based on the cycling of a list of numbers it keeps, making it pseudo­random.

It's not really random, and sadly, it does have some bias, being a maximum of 2^48 possibilities with certain numbers appearing more often. However, if they're given the same data, at the same time, with the same maths applied to them, two different BBCs will spit out the same “random” sequence. Which is why it's really important, when making games, to craft your RN Jesus with love. But either way, we get a range of numbers between 0 (G=0 or W=0) and 800 (20 and 40 respectively) to guess. (EDIT: The er... 0 isn't actually intended behaviour, but a typo. It should be 1 and 800. I fell for this too. :v:)

Except we're then told one half of the equation, and we start a FOR loop (More on that in a minute) to give us 10 guesses. It took me years to realise how important that first bit was, and when I did, I kicked myself, because 8 year old me genuinely thought “I have to get the right number in only 10 goes? But there's 800 of them!”

...Younger me was surprisingly dumb sometimes.

You already know the smaller number (G), so what you're actually looking for is which multiple of that is the right one. And there's 40 multiples. It also tells us if we went too high or too low, so we can get to the right number in a maximum of 5 moves (20*G, move 10*G up or down, move 5*G up or down, move 2*G up or down, move 1*G up or down)



On my emulated runs of the program, the first time I run it, the gravity is always 8, and the answer is always 56 (YMMV on this one, because of variances between computers, but on a reset, without seeding, it should be the same number every time you reset, load, and run). The second time, the gravity is always 5, and the answer is always 50... So on, so forth. This is why taking care with your Random Number Generator is very important. In the case of the BBC, however, it's stupidly difficult to make a decent RNG (Although an OK one exists), and said RNG is biased (Some numbers appear in the register more often than others).



For those who are curious, the way to seed (“randomly” set) the RNG is by adding this line before the rest of the program.

[variable letter/name you're not using]=RND(-RND(TIME))

...It reseeds the RNG based on how long the BBC's been running. It won't make it completely unpredictable, but it will ensure there's another layer of pseudorandom you can't fully control in between you and confidently predicting the answer will always be 8 the first time you run it. :v:

So now we talk about the FOR loop. The FOR loop is quite simple. You declare a variable to loop between (1 and whatever the gently caress you want the end to be, for basic loops), and the program goes down the line, executing instructions, until it gets to “NEXT [variable you declared]”. Then it goes all the way back, adding 1 to its counter, and repeats this until that counter hits the number you wanted it to. Then the program gets out of the loop. It's mostly used as either a timer or a counter for repetitive actions.

No, you can't hang your BBC by changing the endpoint halfway through. But you can do other, clever things with FOR loops that are X to Y, instead of just 1 to X. We'll deal with that though, another time...

Exercise For This Session: I want you to spice this program up. Just a little bit. Right now, it looks like this when you run it -


As the image title says: Kludgy... As... gently caress.

And that's a bit cluttered. We don't want clutter, we just want three lines of text, maximum, on screen at any one time... A clear-ish screen, until the end. But we want to still know if we were too forceful or not. As mentioned, this is a post exercise, just post what lines you'd add/change/get rid of, and why you did it. 24 hours for this one. :)

Guessing Games On The Disks

UHayesSpaceGams.SSD (More on the way!)

STOFF - Starship Take Off (pp4-5 , Computer Space Games)
LIFTOFF - Starship Take Off with time seeding
IGGAMES – Intergalactic Games (pp6-7, Computer Space Games)
EVALIEN – Evil Alien (pp 8-9, Computer Space Games)
LANDER1 – Moon Lander (p12-13, Computer Space Games)
MGALAC – Monsters of Galacticon (pp 14-15, Computer Space Games)
TTRAVEL – Trip Into The Future (pp 20-21, Computer Space Games)

Things You Can Possibly Do Later On With These.

Add actual graphics (P. much all of them, but especially Evil Alien and InterGalactic Games)
Add sound (Again, p. much all of them. We'll be dealing with SOUND later, because the books mostly gloss over it.)

Random BBC Game: Repton (Superior Software, 1985)

Vid

Superior Software, still somehow around today, lived up to their name at the time as one of the premier publishers for the BBC and Acorn Electron, and Repton was one of their longest running franchises. While many can definitely criticise the first game as “Just a Boulderdash clone” (Despite the fact that Tim Tyler, the creator, wrote the game after seeing a review of Boulderdash, never having played it until after said criticisms came in. :v: ), later games in the series would gain their own identity, and not just because of the character of Repton himself, who, for an alien, got around a bit. Proof below:



But for now, the simplest game in the series. For simplification, Repton 2 was the only “single world” game in the series, and Repton 3's engine (And rules) were used for the majority of the series. Repton Infinity was a tool for making, essentially, your own Repton game. And yes, Repton is still around.

JamieTheD fucked around with this message at 12:30 on Dec 11, 2015

QwertySanchez
Jun 19, 2009

a wacky guy
Man, I loved these books as a kid, and BASIC. Impressed all the kids at school with my programming skill on the lovely computers we had while out in the real world you could get windows 98. Played the poo poo out of Repton, too.

Julias
Jun 24, 2012

Strum in a harmonizing quartet
I want to cause a revolution

What can I do? My savage
nature is beyond wild
Not much of of programmer, but this seems super interesting and cool. Will definitely keep an eye on this.

reignofevil
Nov 7, 2008
I just barely eyeballed the code for a second but it looks like I would add "91 CLS" to clear the screen after the user has input some information but while still leaving what they should need to guess the number on their screen.

JamieTheD
Nov 4, 2011

LPer, Reviewer, Mad Welshman

(Yes, that's a self portrait)

reignofevil posted:

I just barely eyeballed the code for a second but it looks like I would add "91 CLS" to clear the screen after the user has input some information but while still leaving what they should need to guess the number on their screen.

A worthy quick guess, and this is indeed part of what can be done (Yes, there are multiple possible answers)... But it doesn't lead to all the information you need. If you 91 CLS, here's what gets shown on your second attempt onwards (Obviously, with "Too High" if you got it wrong.



Note the lack of Gravity, as PRINT [gravity] was outside the FOR loop. However, to identify that yes, the screen doesn't clear after every turn, while seemingly obvious, is important. Imagine that one program comprised of something like 600 lines of code, rather than the 19 it actually has, and you missed something that simple. BBC BASIC, unlike many later versions, doesn't really have commenting (EDIT: The longest single program in these books is the Silver Mountain adventure, at approximately 489 lines of code. Technically, the Adventure Program is longer, but is split into three separate programs, for memory reasons)

Now, obviously, a thread takes time to get going, and I understand this. So this is being extended for 48 hours to give folks a proper chance. But this post has provided an important clue... The winning message is outside the loop, so are the losing message, the title (Eh, that one's unimportant for now), and the Gravity. Part 0.5 also has a useful extra in INPUT "[printed words]" [variable].


QwertySanchez posted:

Man, I loved these books as a kid, and BASIC. Impressed all the kids at school with my programming skill on the lovely computers we had while out in the real world you could get windows 98. Played the poo poo out of Repton, too.

I wish I could find the little comics that came with the later Repton games, because my god, distilled 80s. But yeah, for those outside the UK, the BBC Micro was still in schools in the late 90s. They were some sturdy fuckin' things.

I'll be talking a little later on in the LP about both the good and the bad in the books, as they definitely embody design philosophies of the 80s. It wasn't until the late 80s/early 90s that game designers really started to stretch themselves, so to speak, although the money you could have made in programming back in the day was bloody silly. Another goon and I were going through, looking for a specific program of the 80s, and we found this: Writing for the Early UK Home Computing Mags. CTRL-F "£75" , and prepare to be shocked. For reference, that's almost £177 in today's money, for a SINCLAIR BASIC program for a magazine. As the thread continues, and thread-goers get more used to BBC BASIC and how it works, this will most likely become even more shocking. I know, when I read it, my reaction was "The gently caress? WHY DID NOBODY TELL ME THIS BACK THEN?!?" :bang:

JamieTheD fucked around with this message at 17:47 on Dec 10, 2015

Paul.Power
Feb 7, 2009

The three roles of APCs:
Transports.
Supply trucks.
Distractions.

Cool stuff! The BBC Micro's heyday was a little before my time, but I used to love getting books like Computer Spacegames out of the library and trying to convert the programs into QBASIC. RANDOMISE was a nice command for resetting the random seed in QBASIC, and you could use RANDOMISE TIMER to set the seed as the number of seconds since midnight.

On the other hand, QBASIC was nowhere near as good at handling music as the BBC Micro was. And all the time-wasting loops in the programs had to have their numbers increased dramatically to cope with the blinding speed of a 386 processor! :v:

Snorb
Nov 19, 2010
Growing up, I had the books BASIC Computer Games, More BASIC Computer Games, and an old 286 with GW-BASIC on it. This is bringing back memories of transcribing those programs line-for-line only to find out GW-BASIC had some kind of hosed up RNG so everything went the same way.

Also,

10 print "GET YOUR rear end TO MARS"
20 goto 10
run

Polsy
Mar 23, 2007

JamieTheD posted:

I wish I could find the little comics that came with the later Repton games, because my god, distilled 80s.

There was the one on the front cover Life of Repton, like this. Can't find a more easily readable copy of it, though. I feel like my copy of the game is at my parents' house still, but who knows where.

"'ere, we've been looking for you, bog brush head". classic.

Polsy fucked around with this message at 22:48 on Dec 10, 2015

reignofevil
Nov 7, 2008
Continuing to utilize this hammer; I will begin to work on my next nail.

91 CLS

141 CLS

Unless I miss my guess that should leave us dealing only with the relevant prompts after we enter the loop (which is what I am kind of assuming is the object of this lesson).

Edit- I guess we still probably want to see Gravity all the time. Maybe I oughta try putting that in there.

Edit 2, Also add in 121 PRINT "GRAVITY= ";G

Hopefully that will make it so that on each iteration of the loop it will remind our user what the gravity is (assuming they failed to guess properly)

reignofevil fucked around with this message at 00:42 on Dec 11, 2015

Tiggum
Oct 24, 2007

Your life and your quest end here.


pre:
1 X=RND(-RND(TIME))
2 MODE 1
3 LET G=INT(RND(1)*20)
4 LET W=INT(RND(1)*40)
5 LET R=G*W
6 LET H=800
7 LET L=0
8 FOR C=1 TO 10
10 CLS
11 PRINT
20 PRINT "   *****   STARSHIP TAKE-OFF   *****"
30 LET G=INT(RND(1)*20)
40 LET W=INT(RND(1)*40)
50 LET R=G*W
30 PRINT
40 PRINT
60 PRINT "GRAVITY = ";G
62 PRINT
64 PRINT "FORCE WITHIN RANGE ";L;"-";H
66 PRINT
70 PRINT "TYPE IN FORCE"
80 FOR C=1 TO 10
90 INPUT F
70 PRINT
80 INPUT "TYPE IN FORCE: ";F
100 IF F>R THEN PRINT "TOO HIGH";
110 IF F<R THEN PRINT TOO LOW";
90 IF F>R THEN LET H=F
100 IF F<R THEN LET L=F
110 PRINT
120 IF F=R THEN GOTO 190
130 IF C<>10 THEN PRINT ", TRY AGAIN"
140 NEXT C
150 PRINT
160 PRINT "YOU FAILED -"
170 PRINT "THE ALIENS GOT YOU"
180 STOP
180 END
190 PRINT "GOOD TAKE OFF"
Download


I got a second-hand Apple II when I was about 7, and I loved writing programs like this, and years later I played around with QBASIC a lot too. I remember the Apple II manual was really good for learning the basic stuff - the BASIC stuff - but a lot of it was probably to do with the fact that I had a lot of free time and not much to do with it.

Tiggum fucked around with this message at 09:28 on Dec 11, 2015

RickVoid
Oct 21, 2010
Okay, so here's the thing, I'm trying to follow along with this and optimize the code we're using for the first game and I've got a big issue:

JamieTheD posted:


I can't read this fuckin' thing. It's too small, and too blurry to make out some of it. So before I can work on it, I need to get the base code down on something (I'm using Notepad) and it's just not working.

On lines 30 and 40, there's a symbol after RND. My eyes are telling me it could be any of $, * (multiply), or != (the equals sign with a diagonal line through in denoting "not equal to). Logic tells me that line 30 should be (RND*20+1), but I just don't know. In the future, in addition to posting the page from the book, could you post the base code in a readable format?

Please tell me if I'm missing something super obvious here.

Edit: Okay, so I now know what I just struck out has to be wrong, because those lines are setting up the range for the RND function and therefore I'm not multiplying anything. So is it $? This is kind of infuriating.

Edit II: Okay, so I found that you linked a page that has copies of the PDFs. So... that'll be useful.

Edit III: Okay zooming in on the damned thing tells me it is an asterisk. WTF.

RickVoid fucked around with this message at 05:31 on Dec 11, 2015

Tiggum
Oct 24, 2007

Your life and your quest end here.


RickVoid posted:

On lines 30 and 40, there's a symbol after RND. My eyes are telling me it could be any of $, * (multiply), or != (the equals sign with a diagonal line through in denoting "not equal to). Logic tells me that line 30 should be (RND*20+1), but I just don't know.

It's an asterisk (*), for multiply. IIRC, the way it works is that RND generates a number between 0 and 1, so multiplying by a value and then converting to integer gives you a whole number between 0 and whatever value you chose, eg. if RND gives you 0.356 and you multiply by 20 you get 7.12, which rounds to 7.


Also, for this example, here's the original code:
pre:
10 CLS
20 PRINT "STARSHIP TAKE-OFF"
30 LET G=INT(RND(1)*20)
40 LET W=INT(RND(1)*40)
50 LET R=G*W
60 PRINT "GRAVITY= ";G
70 PRINT "TYPE IN FORCE"
80 FOR C=1 TO 10
90 INPUT F
100 IF F>R THEN PRINT "TOO HIGH";
110 IF F<R THEN PRINT TOO LOW";
120 IF F=R THEN GOTO 190
130 IF C<>10 THEN PRINT ", TRY AGAIN"
140 NEXT C
150 PRINT
160 PRINT "YOU FAILED -"
170 PRINT "THE ALIENS GOT YOU"
180 STOP
190 PRINT "GOOD TAKE OFF"

Tiggum fucked around with this message at 05:35 on Dec 11, 2015

RickVoid
Oct 21, 2010

Tiggum posted:

It's an asterisk (*), for multiply. IIRC, the way it works is that RND generates a number between 0 and 1, so multiplying by a value and then converting to integer gives you a whole number between 0 and whatever value you chose, eg. if RND gives you 0.356 and you multiply by 20 you get 7.12, which rounds to 7.

Thank you, that now actually makes sense to me.

RickVoid
Oct 21, 2010
Okay, I think I hosed around with the code enough that I've got something I actually like.

code:
1 Z=RND(-RND(TIME))
2 LET G=INT(RND(1)*20)
3 LET W=INT(RND(1)*40)
4 LET R=G*W
5 LET H=800
6 LET L = 0
7 FOR C=1 TO 10
10 CLS
20 PRINT "STARSHIP TAKE-OFF"
30 PRINT "PLANETARY GRAVITY= ";G
40 PRINT "TO ACHIEVE ESCAPE VELOCITY, THRUST MUST BE WITHIN" ;L; "-" ;H
50 INPUT "SET THRUST" ;T
60 IF T>R THEN LET H=T
70 IF T<R THEN LET L=T
80 IF T=R THEN GOTO 140
90 IF C<>10 THEN PRINT "TRY AGAIN."
100 NEXT C
110 PRINT "INSUFFICIENT THRUST!"
120 PRINT "THE ALIENS WATCH AS YOU FALL BACK TO THE PLANET!"
130 STOP
140 PRINT "ESCAPE VELOCITY ACHIEVED. GOOD FLYING!"
I absolutely admit to stealing Tiggum's neat trick that automatically updates the possible min and max values for "force". I did however rename F for Force to T for Thrust, because that makes more sense to me as a variable given what we're doing here. Which also wasn't really explained very well in the barebones instructions the base game gives you, so I expanded that a bit, plus added a little flavor text here an there. Feels a little more like a game now.

FredMSloniker
Jan 2, 2008

Why, yes, I do like Kirby games.
If we're more familiar with BASIC in another OS (for instance, the Commodore 64 I used as a youth), can we use that, or do I need to learn the Beeb to take part?

Also, this is a neat idea for a thread. I remember the book Basic Computer Games fondly, even if the games it contains are (for the most part) not so good, and I definitely remember coding up lots of little programs as a kid. Heck, I wrote my own text adventure from scratch! It wasn't a terribly good text adventure, about as complex as a Scott Adams game with what plot there was vaguely inspired by 'Tron', but I was, like, 11 when I wrote it.

FredMSloniker fucked around with this message at 06:59 on Dec 11, 2015

Tiggum
Oct 24, 2007

Your life and your quest end here.


RickVoid posted:

Okay, I think I hosed around with the code enough that I've got something I actually like.

The player will never see the text "TRY AGAIN" because you've got it immediately followed by the end of the loop, which throws you back to the start and clears the screen.

JamieTheD
Nov 4, 2011

LPer, Reviewer, Mad Welshman

(Yes, that's a self portrait)
[wakes up... looks at thread] Oh my! Right, discussion and data entry time, it seems!

FredMSloniker posted:

If we're more familiar with BASIC in another OS (for instance, the Commodore 64 I used as a youth), can we use that, or do I need to learn the Beeb to take part?

Also, this is a neat idea for a thread. I remember the book Basic Computer Games fondly, even if the games it contains are (for the most part) not so good, and I definitely remember coding up lots of little programs as a kid. Heck, I wrote my own text adventure from scratch! It wasn't a terribly good text adventure, about as complex as a Scott Adams game with what plot there was vaguely inspired by 'Tron', but I was, like, 11 when I wrote it.

While it's preferable to use the Beeb (Especially since a later post will have me converting to the good ol' C64 with its PEEK and POKE, and since the C64 just doesn't have quite the same limitations as the Beeb), I certainly wouldn't like folks not to be able to participate, so just lemme know which BASIC you're using in advance, and I'll try to keep up.

And yeah, text adventures would definitely be the first things to come to mind for most of us younguns. I remember writing those looooong DATA statements, and will again before the thread is out. :) As to the games being not so good, you are quite correct, they are nearly all text based, but they teach things fairly organically for most of the books, going from simple guessing games, to not so simple guessing games, shooting galleries (Our next subject, funnily enough), racers and reflex games (of a sort), to graphics of both kinds. My main criticism of the series is that it really doesn't go into SOUND very much, so I'm going to have to take up the slack there. The BBC's sound chip is not great (Certainly not on the level of the C64's SID, which people still play with today!), but it does have some potential, as we're going to see next time. :)

RickVoid posted:

I can't read this fuckin' thing. It's too small, and too blurry to make out some of it. So before I can work on it, I need to get the base code down on something (I'm using Notepad) and it's just not working.

Ah, that is indeed an issue, and I shall make sure to post original code, as Tiggum has so helpfully done! Any other suggestions to make the thread more accessible are gratefully accepted!

Tiggum posted:

It's an asterisk (*), for multiply. IIRC, the way it works is that RND generates a number between 0 and 1, so multiplying by a value and then converting to integer gives you a whole number between 0 and whatever value you chose, eg. if RND gives you 0.356 and you multiply by 20 you get 7.12, which rounds to 7.


Also, for this example, here's the original code:
pre:
10 CLS
20 PRINT "STARSHIP TAKE-OFF"
30 LET G=INT(RND(1)*20)
40 LET W=INT(RND(1)*40)
50 LET R=G*W
60 PRINT "GRAVITY= ";G
70 PRINT "TYPE IN FORCE"
80 FOR C=1 TO 10
90 INPUT F
100 IF F>R THEN PRINT "TOO HIGH";
110 IF F<R THEN PRINT TOO LOW";
120 IF F=R THEN GOTO 190
130 IF C<>10 THEN PRINT ", TRY AGAIN"
140 NEXT C
150 PRINT
160 PRINT "YOU FAILED -"
170 PRINT "THE ALIENS GOT YOU"
180 STOP
190 PRINT "GOOD TAKE OFF"

Now, small but important note here: Remember how I said there would be typos? I forgot this one for my own listing, but there is a reason there should be a +1 on the end of the INT(RND) in the brackets. Namely, that a small enough number here will get rounded down, leading to a thrust of 0... You can tell I fell for this typo myself, if you look in the main post. :v:

Checking code, and both Tiggum and RickVoid have got pretty good answers, with Tiggum using Screen MODE a lil' bit early to give the game that good, chunky feel, earning a silver star. As Tiggum notes, however, the "Try again" will ne'er be seen, because the loop clears too quickly...

...However, another use for FOR loops has been mentioned in the thread (And, funnily enough, this second use is going to be the theme of the second and third updates), so, I'll give this one for free.

code:
89 PRINT
92 FOR Y=1 to 600
93 NEXT Y
Those changes should not only make things a teeny bit tidier, but should also hold the screen for around a second and a half so folks can see that. The PRINT before the "TRY AGAIN" adds a line.

So, it should be noted that there are multiple ways of doing things, even in these early stages, and happily, Tiggum and RickVoid have happened on a different way than what I was going to show. This is a good thing, because, this early on, unless you try really hard, there isn't really a bad way of doing things.

It's also good to mention that MODE 1 is, technically, the "best" graphics mode, as, while the text is chunky, it doubles the actual pixel height compared to the other graphics MODE we'll be using, MODE 5. We'll be talking about the strangeness of how the BBC handles DRAW calls in about four updates, but suffice to say, graphics are definitely dealt with differently than text, and it's one of the BBC's more annoying quirks. Still got until 6PM tomorrow to explore things, but in the meantime, I'd like to thank everyone who's posting to the thread, as this definitely wouldn't be half as fun without your input!

JamieTheD fucked around with this message at 09:19 on Dec 11, 2015

Paul.Power
Feb 7, 2009

The three roles of APCs:
Transports.
Supply trucks.
Distractions.

FredMSloniker posted:

If we're more familiar with BASIC in another OS (for instance, the Commodore 64 I used as a youth), can we use that, or do I need to learn the Beeb to take part?

Also, this is a neat idea for a thread. I remember the book Basic Computer Games fondly, even if the games it contains are (for the most part) not so good, and I definitely remember coding up lots of little programs as a kid. Heck, I wrote my own text adventure from scratch! It wasn't a terribly good text adventure, about as complex as a Scott Adams game with what plot there was vaguely inspired by 'Tron', but I was, like, 11 when I wrote it.
It may be worth noting that the star, square, triangle and circle mean "replace this line with something else if you're using something other than a ZX81". - the stars are for the Acorn BBC Micro and Electron, the triangles are for the Commodore VIC and PET (which are probably the closest thing to a 64 here?), the squares are TRS-80 and the circles are Apple. There's also S for Spectrum changes, although I guess this program didn't need any.

Paul.Power fucked around with this message at 13:50 on Dec 11, 2015

Polsy
Mar 23, 2007

JamieTheD posted:

code:
92 FOR Y=1 to 600
93 NEXT Y

Now that's a good reminder of how much computing power and/or language interpreters have advanced in 35 years, you'd have to try a lot harder than 600 to get a noticeable delay these days.

JamieTheD
Nov 4, 2011

LPer, Reviewer, Mad Welshman

(Yes, that's a self portrait)

Polsy posted:

Now that's a good reminder of how much computing power and/or language interpreters have advanced in 35 years, you'd have to try a lot harder than 600 to get a noticeable delay these days.

Yeah, for comparison, the BBC Model B processor runs at an amazing... 2 MHz. An Intel 486 runs between 16 and 150 MHz. The ZX Spectrum runs at 3.5 MHz. And my current system has 6 independent cores, each running at around 4 GHz. We've come a long way. We'll be seeing some silly numbers when conversion time rolls around.

Paul.Power posted:

It may be worth noting that the star, square, triangle and circle mean "replace this line with something else if you're using something other than a ZX81". - the stars are for the BBC Micro and Electron, the triangles are for the Commodore VIC and PET (which are probably the closest thing to a 64 here?), the squares are TRS-80 and the circles are Apple. There's also S for Spectrum changes, although I guess this program didn't need any.

Conversion chart is added to the OP, for ease of use. :)

As to changes, the major differences are in Data storage/retrieval, and how DRAW/User Defined ASCII symbols are handled. I... Honestly expect to get lynched when updates 4 and 5 roll around, because the... Somewhat unique way the Beeb handles drawing is... Well, you'll see when we get there. Suffice to say, this is as much an education that yes, sometimes odd decisions were made when making older systems. :v:

RickVoid
Oct 21, 2010

Tiggum posted:

The player will never see the text "TRY AGAIN" because you've got it immediately followed by the end of the loop, which throws you back to the start and clears the screen.

Okay, I don't have time to check right now, but most programming languages have a command that makes the machine wait for the user to input a response (the "Press any key to continue" command, essentially) before continuing to follow the program. I have no idea what the command is for it and no time to check, but I would put that after "PRINT "TRY AGAIN"". Assuming BASIC has it (which it really should, come on).

RickVoid posted:

code:
1 Z=RND(-RND(TIME))
2 LET G=INT(RND(1)*20+1)
3 LET W=INT(RND(1)*40+1)
4 LET R=G*W
5 LET H=861
6 LET L = 1
7 FOR C=1 TO 10
10 CLS
20 PRINT "STARSHIP TAKE-OFF"
30 PRINT "PLANETARY GRAVITY= ";G
40 PRINT "TO ACHIEVE ESCAPE VELOCITY, THRUST MUST BE WITHIN" ;L; "-" ;H
50 INPUT "SET THRUST" ;T
60 IF T>R THEN LET H=T
70 IF T<R THEN LET L=T
80 IF T=R THEN GOTO 150
90 IF C<>10 THEN PRINT "TRY AGAIN."
100 *CHUNK OF CODE THAT MAKES SYSTEM PAUSE AND WAIT FOR USER TO PRESS A KEY*
110 NEXT C
120 PRINT "INSUFFICIENT THRUST!"
130 PRINT "THE ALIENS WATCH AS YOU FALL BACK TO THE PLANET!"
140 STOP
150 PRINT "ESCAPE VELOCITY ACHIEVED. GOOD FLYING!"

Okay, there. Also, if we're adding one to each number then that makes the possible range 1-861, so I've changed my range code to reflect this.

RickVoid
Oct 21, 2010
Double post, I think it's been long enough to get away with it.

I think I solved my "TRY AGAIN" not appearing on the screen issue, without having to deal with a random wait factor between attempts, despite the fact that BASIC doesn't actually have a specific "wait for the operator to strike a key before moving to the next instruction" command. Which is terrible. (Or, at least, it's not in the kids manual.)

code:
1 Z=RND(-RND(TIME))
2 LET G=INT(RND(1)*20+1)
3 LET W=INT(RND(1)*40+1)
4 LET R=G*W
5 LET H=861
6 LET L = 1
7 FOR C=1 TO 10
10 CLS
20 PRINT "STARSHIP TAKE-OFF"
30 PRINT "PLANETARY GRAVITY= ";G
40 PRINT "TO ACHIEVE ESCAPE VELOCITY, THRUST MUST BE WITHIN" ;L; "-" ;H
50 INPUT "SET THRUST" ;T
60 IF T>R THEN LET H=T
70 IF T<R THEN LET L=T
80 IF T=R THEN GOTO 140
90 IF C<>10 THEN INKEY$ "PRESS ANY KEY TO TRY AGAIN." ;K
100 NEXT C
110 PRINT "INSUFFICIENT THRUST!"
120 PRINT "THE ALIENS WATCH AS YOU FALL BACK TO THE PLANET!"
130 STOP
140 PRINT "ESCAPE VELOCITY ACHIEVED. GOOD FLYING!"
Okay, so I read ahead a bit. To the glossary. Sue me. Anyway, the INKEY$ function operates the same as INPUT, but it takes a keystroke instead of a value. The important thing to take away from this is that it doesn't go on to the next instruction until they push a key. I don't care what key they push, as I'm not going to use variable K for anything, but the function of "do nothing until you receive input" is exactly what I want.

Paul.Power
Feb 7, 2009

The three roles of APCs:
Transports.
Supply trucks.
Distractions.

Yeah, INKEY$ is useful for stuff like that. I remember it being a thing in QBASIC, but couldn't remember if it was in older versions of the language as well. Looks like it is!

reignofevil
Nov 7, 2008
I don't really have any other guesses right now but I am curious; how is this program dealing with bad input? Are letters just ruled out somehow?

JamieTheD
Nov 4, 2011

LPer, Reviewer, Mad Welshman

(Yes, that's a self portrait)

reignofevil posted:

I don't really have any other guesses right now but I am curious; how is this program dealing with bad input? Are letters just ruled out somehow?

Sort of. The way it handles it without any help from you is this: If you're asking for a number, and you give it letters, it assumes you meant 0. If you asked for letters and you gave it numbers, it assumes the input is a text string. Since the game's only asking for a number, it's an assumed fail if you type text instead, although, now we've ruled out 0 being a number, a special case could be added where you would ask again if the answer you gave was "out of bounds" via an IF...OR statement (like IF N=0 OR F>800 THEN GOTO [ASK AGAIN]) , and other games in Computer Space Games do exactly that, most notably Space Mines, which won't let you spend more money than you have. Ruling out 0, in this case, would also rule out text inputs to a number request.

Now, to be 100% clear, because I don't think I was: The replacement code actually has a typo in it that I'd not noticed (but fell for this once), and INT(RND(1)*20) would actually result in zero to 19, as the BBC always rounds down. That's what the +1 at the end is for. So, with the +1, the range is 1 to 20.

Paul.Power posted:

Yeah, INKEY$ is useful for stuff like that. I remember it being a thing in QBASIC, but couldn't remember if it was in older versions of the language as well. Looks like it is!

Sadly, RickVoid's code isn't quite right. Specifically, it needs to be something along the lines of this:

code:
K$=INKEY$(200)
That way, it will indeed ask for a key, but if it doesn't get one after a few seconds, it'll keep going. However, Space Rescue (Another guessing game on the disc) has another way to do things. The GET (Get Key) command. It's very similar to INKEY, but it won't go anywhere until a key is pressed.

code:
I=GET
Of course, it's not going to tell you it's asking for a key, but most BBC users' first instinct when the cursor is blinking, but nothing is happening, is to first press a key, then hit BREAK (Which resets the computer), so it wasn't considered bad coding form. Plus, y'know, you can have a PRINT statement before it, if you feel like warning people.

As to reading ahead, feel free! There's definitely no rules against it, and it's definitely worth looking at the more complex games to see how they handle things. For example, you would encounter a most useful thing if you want tidy code: The humble colon ( : ). This lil' feller, so long as you're aware there's a 248 character limit per line, allows you to concatenate any lines that would make sense running in order except for multiple IF statements. For IFs, we'd have to do the thing we usually do with IFs... IF X=Y THEN [Thing] ELSE (Sometimes with an IF of its own, but in the case of binary "Right/Wrong", you can just have a GOTO or other command.)

So, for example, line 1-6 should be able to fit in one line with the colon between them, and if we had a FOR...NEXT loop on its lonesome without commands, it would make perfect sense to just put them together like this:

code:
FOR I=1 TO 200: NEXT I
But it's not recommended to try and fit half a FOR loop's stuff on one line, and half on another. So, for example, lines 1-6 can be put together in RickVoid's code, as can lines 20-50, but putting lines 60-80 in one line using the colon would mean every IF except the first is ignored (I don't entirely know why), so to make that one line, it would have to be an IF...ELSE chain (IF T>R ...ELSE IF T<R... ELSE...)

What's this useful for? Mostly, I use it as a tool to break BASIC code into rough guides as to what each block does. It doesn't, as far as I know, make the program run any quicker, and it does, to be fair, look ugly as hell writing it down anywhere outside of MODE 0 (The most character heavy mode.) Still, it saves a lil' bit on typing.

RickVoid
Oct 21, 2010
Wait, it always rounds down? Then yes, my new numbers are wrong for the range, it is 1 to 800. You had stated earlier that it rounds down very small numbers (I went back to check, so this clarification is good to know.

Decided to try something fancy based off some of the new information you've given us.

code:
1 Z=RND(-RND(TIME))
2 LET G=INT(RND(1)*20+1)
3 LET W=INT(RND(1)*40+1)
4 LET R=G*W
5 LET H=800
6 LET L=1
7 FOR C=1 TO 10
10 CLS
20 PRINT "STARSHIP TAKE-OFF"
30 PRINT "PLANETARY GRAVITY= ";G
40 PRINT "TO ACHIEVE ESCAPE VELOCITY, THRUST MUST BE WITHIN" ;L; "-" ;H
50 INPUT "SET THRUST" ;T
60 IF T>R THEN LET H=T
70 IF T<R THEN LET L=T
80 IF T=R THEN GOTO 140
90 IF C<>10 THEN INKEY$ "TRY AGAIN? (Y/N)" ;O : ELSE GOTO 110
100 IF O="Y" THEN NEXT C : IF O="N" THEN STOP : ELSE PRINT "PLEASE ENTER A VALID CHARACTER" : GOTO 90
110 PRINT "INSUFFICIENT THRUST!"
120 PRINT "THE ALIENS WATCH AS YOU FALL BACK TO THE PLANET!"
130 STOP
140 PRINT "ESCAPE VELOCITY ACHIEVED. GOOD FLYING!"
The big change is in the "TRY AGAIN?" section. I hate it when a program decide to run without my input and you know what, what if I didn't want to try again? So now (if my IF statements are correct and I've got the format right for checking the value of O, and WHO KNOWS, I SURE DON'T) it should accept either "Y" in which case it will continue as it should, or "N", which will just stop the game. The else is for the rear end in a top hat who types in GO gently caress SELF, which will just send him back to the "TRY AGAIN?" prompt. You'll also notice I added a line that makes you go straight to line 110 if line 90 is false, this is because I now have two things working against me after that line: the first is the variable O, which will already have "Y" assigned to it. If that else statement is not there, then at 10 attempts it will skip line 90 (as the if statement is not true), go to line 100, read that yes O does in fact ="Y", and then I'm not sure what the hell it will do because that will put C at 11 out of a possible range of 10. And if it does pass that, I have GOTO 90 at the end of that line anyway, so if nothing else there is true it will jump back to 90, which is not a true statement, so it will go to line 100 again. Infinite loop.

Look at that, I'm already hacking in solutions to problems I made for myself with my lovely coding. Just like a real programmer.
I could probably fix it, but I've been staring at it for a good while now, it "should" work, and I have other things I'd like to do. Just like a real programmer.

Tiggum
Oct 24, 2007

Your life and your quest end here.



In case anyone wants to use this to actually read a keypress, there are two ways to do that. GET always returns a number, specifically the ASCII code for whatever character was entered (capital A is 65, for example). You can convert that value back to the character by using the CHR$ function like so:
code:
10 PRINT "PRESS A KEY"
20 LET K = GET
30 LET C$ = CHR$(K)
But the easier way is to use GET$ instead:
code:
10 PRINT "PRESS A KEY"
20 LET C$ = GET$
And if you want to convert a character into its ASCII code for some reason (ie. reverse CHR$), use the ASC function:
code:
>PRINT ASC("A")
65
If you enter a string longer than a single character, the ASCII code for the first character will be returned (ie. "A" and "ABCDE" will both return 65).

tiistai
Nov 1, 2012

Solo Melodica
INT is indeed actually a flooring function, it doesn't round to the nearest integer. INT(3.1) returns 3, INT(3.9) returns 3 and INT(-3.1) returns -4. Apparently what's happening is that the decimal fraction part is truncated and the result returned, unless the number was negative in which case it returns the truncated number minus one.

Personally I was just expecting it to do a simple truncating cast from a float to int, negative or not. Good thing I thought to check first.

I'm a bit of a programmer myself but while I did play with a C64 back in the day, at the time I was only barely old enough to read, and so I have no real experience with BASIC. This should be a fun thread to follow.

FredMSloniker
Jan 2, 2008

Why, yes, I do like Kirby games.
So when's the next exercise go up? I admit, this one isn't grabbing me, mainly because I keep thinking gravity does not work that way rrrrrrgh

Nidoking
Jan 27, 2009

I fought the lava, and the lava won.

RickVoid posted:

code:
90 IF C<>10 THEN INKEY$ "TRY AGAIN? (Y/N)" ;O : ELSE GOTO 110
100 IF O="Y" THEN NEXT C : IF O="N" THEN STOP : ELSE PRINT "PLEASE ENTER A VALID CHARACTER" : GOTO 90

I believe it needs to be O$ in all cases, because it's a string, not a number.

Also, this goes a bit more smoothly as
code:
90 IF C=10 THEN GOTO 110
95 INKEY$ "TRY AGAIN? (Y/N)" ;O$
100 IF O$="Y" THEN NEXT C : IF O$="N" THEN STOP : ELSE PRINT "PLEASE ENTER A VALID CHARACTER" : GOTO 90
It uses another line (unless you want to consolidate with colons), but it makes one additional command non-conditional, and I think the less you have in condition statements, the better. Like they say, check your error/stop conditions first. You could also replace the STOP there with GOTO 110 to print the failure message before exiting.

FredMSloniker
Jan 2, 2008

Why, yes, I do like Kirby games.
What the hell. Since I'm bored, here's a version that satisfies the criteria and makes things a bit more interesting. I haven't actually plugged it into an Acorn emulator, but it should work. Note that the numbers in 20-80 can be adjusted to tweak the game a bit; you might, for instance, change the step values to 0.1. (Be sure that GM is evenly divisible by GS, and WM by WS.) Note also that this assumes that variables do not have to be declared integer or float; in other words, 1 / 3 = 0.333..., not 0. I also borrowed a quality-of-life feature from RickVoid's version, though I didn't pretty up the game as much as he did. The code's also a bit clunky, as I don't want to use features we haven't been introduced to yet.

Incidentally, with the original values for GM, GS, WM, and WS, MG = 10, so the original game requires perfect play...

code:
10 ZZ=RND(-RND(TIME)):REM Randomize RNG
20 GM=20:REM Maximum value for G
30 GS=1:REM Step value for G
40 WM=40:REM Maximum value for W
50 WS=1:REM Step value for W
60 FM=GM*WM:REM Maximum value for F
70 FS=GS*WS:REM Step value for F
80 PV=INT(FM/FS):REM Possible values for F
90 ZZ=PV:REM Calculate minimum number of guesses needed
100 MG=0:REM This would be simpler with math functions
110 MG=MG+1:REM not yet introduced, but I'm keeping
120 ZZ=ZZ/2:REM to the spirit of the challenge
130 IF ZZ>1 THEN GOTO 110
140 EZ=1.2:REM Easiness; 1=perfect play, 2=pretty lax
150 GS=INT(MG*EZ):REM Number of guesses allowed
160 G=INT(RND(1)*GM/GS+1)*GS:REM You don't have to
170 R=INT(RND(1)*FM/FS+1)*FS:REM actually generate W
180 L=FS:REM Convenience feature: lowest and
190 H=FM:REM highest possible values
200 PRINT"STARSHIP TAKE-OFF"
210 PRINT"GRAVITY = ";G
220 PRINT"YOU HAVE ";GS;" TRIES"
230 PRINT"ENTER FORCE BETWEEN ";L;
240 PRINT" AND ";H;
250 INPUT F
260 F=INT(F/FS+0.5)*FS:REM Round guess to a valid number
270 IF F>=L THEN GOTO 310
280 CLS:REM Guess out of bounds low.
290 PRINT"GUESS TOO LOW."
300 GOTO 220:REM Doesn't cost a guess.
310 IF F<=H THEN GOTO 350
320 CLS:REM Guess out of bounds high.
330 PRINT"GUESS TOO HIGH."
340 GOTO 220:REM Doesn't cost a guess.
350 IF F>=R THEN GOTO 400
360 CLS: REM Guess in bounds, but too low.
370 PRINT"GUESS TOO LOW."
380 L=F+FS
390 GOTO 440
400 IF F=R THEN GOTO 500
410 CLS:REM Guess in bounds, but too high.
420 PRINT"GUESS TOO HIGH."
430 H=F-FS
440 GS=GS-1
450 IF GS>0 THEN GOTO 220
460 PRINT
470 PRINT"YOU FAILED -"
480 PRINT"THE ALIENS GOT YOU"
490 END
500 PRINT "GOOD TAKE OFF"
E: a patch for one of the little things that annoy me in games:
code:
220 PRINT"YOU HAVE ";GS;
223 IF GS<>1 THEN PRINT" TRIES"
226 IF GS=1 THEN PRINT" TRY"

FredMSloniker fucked around with this message at 08:46 on Dec 12, 2015

JamieTheD
Nov 4, 2011

LPer, Reviewer, Mad Welshman

(Yes, that's a self portrait)

FredMSloniker posted:

So when's the next exercise go up? I admit, this one isn't grabbing me, mainly because I keep thinking gravity does not work that way rrrrrrgh

Next class exercise will be tomorrow, but there'll be a post archiving everyone's efforts, plus showing you a third way to handle things (RickVoid and Tiggum have done one, while FredMSloniker decided to ditch the FOR loop entirely, going with a GOTO/Counter variable based approach) later today! I had thought about posting a little class note, as you'd see in primary schools of the 80s, with the Bronze/Silver/Gold stars, but I'll leave it up to the thread if we really want to do that. I know that, while it would thematically fit, it might lead to friction, and I like my threads to be as conflict free as possible. :)

RickVoid
Oct 21, 2010

JamieTheD posted:

Next class exercise will be tomorrow, but there'll be a post archiving everyone's efforts, plus showing you a third way to handle things (RickVoid and Tiggum have done one, while FredMSloniker decided to ditch the FOR loop entirely, going with a GOTO/Counter variable based approach) later today! I had thought about posting a little class note, as you'd see in primary schools of the 80s, with the Bronze/Silver/Gold stars, but I'll leave it up to the thread if we really want to do that. I know that, while it would thematically fit, it might lead to friction, and I like my threads to be as conflict free as possible. :)

Have you considered following the Spacechem thread format? I seem to recall that threads OP having a pretty good system put together for it.

FredMSloniker
Jan 2, 2008

Why, yes, I do like Kirby games.
Curiosity question: what level of programming experience do folks in the thread have already? As I mentioned earlier, I'm an old salt at BASIC, and I'm wondering if anyone taking part is learning for the first time.

RickVoid
Oct 21, 2010

FredMSloniker posted:

Curiosity question: what level of programming experience do folks in the thread have already? As I mentioned earlier, I'm an old salt at BASIC, and I'm wondering if anyone taking part is learning for the first time.

I took a year of either C or C++ in High School, which should give you an idea of exactly how much I remember about it. I've also tooled around a bit with Inform7 (a language used for making Text Adventures) and ChoiceScript (another Text Adventure language, used by the Choice of Games folks for their awful Superhero CYOA, and their much better other games). As a result, playing around with Basic here has felt kind of familiar in an ethereal sort of way.

JamieTheD
Nov 4, 2011

LPer, Reviewer, Mad Welshman

(Yes, that's a self portrait)
Update 1.5 – Exercise 1 Results

Well, it's been an alright start so far, with folks gamely stepping up to the plate, and things being learned! Two out of the three main entries for this first exercise have taken roughly the same path, and each has done something extra that would get them an approving smile from their teacher! Let's start with the simplest, Tiggum's tight and functional code!

code:
1 X=RND(-RND(TIME))
2 MODE 1
3 LET G=INT(RND(1)*20)
4 LET W=INT(RND(1)*40)
5 LET R=G*W
6 LET H=800
7 LET L=0
8 FOR C=1 TO 10
10 CLS
11 PRINT
20 PRINT "   *****   STARSHIP TAKE-OFF   *****"
30 PRINT
40 PRINT
60 PRINT "GRAVITY = ";G
62 PRINT
64 PRINT "FORCE WITHIN RANGE ";L;"-";H
66 PRINT
70 PRINT
80 INPUT "TYPE IN FORCE: ";F
90 IF F>R THEN LET H=F
100 IF F<R THEN LET L=F
110 PRINT
120 IF F=R THEN GOTO 190
140 NEXT C
150 PRINT
160 PRINT "YOU FAILED -"
170 PRINT "THE ALIENS GOT YOU"
180 END
190 PRINT "GOOD TAKE OFF"
Although it's not obvious from looking at the code, Tiggum did some research. Specifically, into Graphics MODEs and their character limits. The BBC has character display limitations, but these can be used to organise things to look prettier, and Tiggum decided to use MODE 1 (Hi-Graphics Mode.) Within those character limits, they then fiddled about to center the title of the game, and put everything that's displayed within the loop. This is important, as, for proper clearing after each input, the game needs to CLear Screen each time we take a go. They also introduced a method by which the game tells you what range of numbers you can guess between, which others have used... Amusingly, nobody decided to set the limits for the guesses as based on the Gravity and Weight, using the absolute maximum ranges of 0 (Technically 1, for 1*1) and 800 (20*40.)

To be fair, old guessing game programs of this type like to do that too, when they remember to display ranges... The big ol' meanies. :v:


Tiggum's Starship Take-Off in action.

RickVoid, meanwhile, edited his code as the time limit went by, asking questions and looking up commands he needed. He also used Tiggum's method, but decided to add a “Try Again” prompt. Alas, in the first draft, the “TRY AGAIN” went by too fast before the screen cleared. The problem was specifically in the bolded section... The CLS happening almost immediately after the PRINT statement...

pre:
1 Z=RND(-RND(TIME))
2 LET G=INT(RND(1)*20)
3 LET W=INT(RND(1)*40)
4 LET R=G*W
5 LET H=800
6 LET L = 0
7 FOR C=1 TO 10
10 CLS
20 PRINT "STARSHIP TAKE-OFF"
30 PRINT "PLANETARY GRAVITY= ";G
40 PRINT "TO ACHIEVE ESCAPE VELOCITY, THRUST MUST BE WITHIN" ;L; "-" ;H
50 INPUT "SET THRUST" ;T
60 IF T>R THEN LET H=T
70 IF T<R THEN LET L=T
80 IF T=R THEN GOTO 140
90 IF C<>10 THEN PRINT "TRY AGAIN."
100 NEXT C
110 PRINT "INSUFFICIENT THRUST!"
120 PRINT "THE ALIENS WATCH AS YOU FALL BACK TO THE PLANET!"
130 STOP
140 PRINT "ESCAPE VELOCITY ACHIEVED. GOOD FLYING!"

I deliberately lost here to show you the spiced up text

Teacher helpfully pointed out to how to make a wait timer with a FOR loop:

JamieTheD posted:

Checking code, and both Tiggum and RickVoid have got pretty good answers, with Tiggum using Screen MODE a lil' bit early to give the game that good, chunky feel, earning a silver star. As Tiggum notes, however, the "Try again" will ne'er be seen, because the loop clears too quickly...

...However, another use for FOR loops has been mentioned in the thread (And, funnily enough, this second use is going to be the theme of the second and third updates), so, I'll give this one for free.

code:
89 PRINT
92 FOR Y=1 to 600
93 NEXT Y
Those changes should not only make things a teeny bit tidier, but should also hold the screen for around a second and a half so folks can see that. The PRINT before the "TRY AGAIN" adds a line.

But Rick wanted more player input, and so looked up INKEY$ (Input Key.) Other members of the class decided to chip in, and eventually, this code resulted.

code:
1 Z=RND(-RND(TIME))
2 LET G=INT(RND(1)*20+1)
3 LET W=INT(RND(1)*40+1)
4 LET R=G*W
5 LET H=800
6 LET L=1
7 FOR C=1 TO 10
10 CLS
20 PRINT "STARSHIP TAKE-OFF"
30 PRINT "PLANETARY GRAVITY= ";G
40 PRINT "TO ACHIEVE ESCAPE VELOCITY, THRUST MUST BE WITHIN" ;L; "-" ;H
50 INPUT "SET THRUST" ;T
60 IF T>R THEN LET H=T
70 IF T<R THEN LET L=T
80 IF T=R THEN GOTO 140
90 IF C<>10 THEN INKEY$ "TRY AGAIN? (Y/N)" ;O$ : ELSE GOTO 110
100 IF O$="Y" THEN NEXT C : IF O$="N" THEN STOP : ELSE PRINT "PLEASE ENTER A VALID CHARACTER" : GOTO 90
110 PRINT "INSUFFICIENT THRUST!"
120 PRINT "THE ALIENS WATCH AS YOU FALL BACK TO THE PLANET!"
130 STOP
140 PRINT "ESCAPE VELOCITY ACHIEVED. GOOD FLYING!"

The dreaded Syntax Error. It gets everyone, sooner or later...

Alas... This code needed a little more research. But the original code still works just fine with the exception of the Try Again, and that's fine! RickVoid decided to spice up what seemed a bit of a deadpan narration of danger with his own text. Overall, a good effort!

Finally, FredMSloniker, although not overly familiar with BBC BASIC (Having a C64 outside the class), still gamely chipped in with code that ditches FOR loops altogether, instead using a lot of GOTO line codes and counters. However, he also made the game more complex, adding a small piece of code to calculate the minimum number of guesses needed, a guess counter, adjustable difficulty, and cases to allow the player who just didn't get that you have minimums and maximums for your guesses to try again until they hit upon a number that worked. Finally, they made Teacher blush a little, as he'd made some comments about not being able to comment your code, forgetting that REMark (which does just that, turning a line into a comment) exists.

FredMSloniker posted:

What the hell. Since I'm bored, here's a version that satisfies the criteria and makes things a bit more interesting. I haven't actually plugged it into an Acorn emulator, but it should work. Note that the numbers in 20-80 can be adjusted to tweak the game a bit; you might, for instance, change the step values to 0.1. (Be sure that GM is evenly divisible by GS, and WM by WS.) Note also that this assumes that variables do not have to be declared integer or float; in other words, 1 / 3 = 0.333..., not 0. I also borrowed a quality-of-life feature from RickVoid's version, though I didn't pretty up the game as much as he did. The code's also a bit clunky, as I don't want to use features we haven't been introduced to yet.

Incidentally, with the original values for GM, GS, WM, and WS, MG = 10, so the original game requires perfect play...

code:
10 ZZ=RND(-RND(TIME)):REM Randomize RNG
20 GM=20:REM Maximum value for G
30 GS=1:REM Step value for G
40 WM=40:REM Maximum value for W
50 WS=1:REM Step value for W
60 FM=GM*WM:REM Maximum value for F
70 FS=GS*WS:REM Step value for F
80 PV=INT(FM/FS):REM Possible values for F
90 ZZ=PV:REM Calculate minimum number of guesses needed
100 MG=0:REM This would be simpler with math functions
110 MG=MG+1:REM not yet introduced, but I'm keeping
120 ZZ=ZZ/2:REM to the spirit of the challenge
130 IF ZZ>1 THEN GOTO 110
140 EZ=1.2:REM Easiness; 1=perfect play, 2=pretty lax
150 GS=INT(MG*EZ):REM Number of guesses allowed
160 G=INT(RND(1)*GM/GS+1)*GS:REM You don't have to
170 R=INT(RND(1)*FM/FS+1)*FS:REM actually generate W
180 L=FS:REM Convenience feature: lowest and
190 H=FM:REM highest possible values
200 PRINT"STARSHIP TAKE-OFF"
210 PRINT"GRAVITY = ";G
220 PRINT"YOU HAVE ";GS;" TRIES"
230 PRINT"ENTER FORCE BETWEEN ";L;
240 PRINT" AND ";H;
250 INPUT F
260 F=INT(F/FS+0.5)*FS:REM Round guess to a valid number
270 IF F>=L THEN GOTO 310
280 CLS:REM Guess out of bounds low.
290 PRINT"GUESS TOO LOW."
300 GOTO 220:REM Doesn't cost a guess.
310 IF F<=H THEN GOTO 350
320 CLS:REM Guess out of bounds high.
330 PRINT"GUESS TOO HIGH."
340 GOTO 220:REM Doesn't cost a guess.
350 IF F>=R THEN GOTO 400
360 CLS: REM Guess in bounds, but too low.
370 PRINT"GUESS TOO LOW."
380 L=F+FS
390 GOTO 440
400 IF F=R THEN GOTO 500
410 CLS:REM Guess in bounds, but too high.
420 PRINT"GUESS TOO HIGH."
430 H=F-FS
440 GS=GS-1
450 IF GS>0 THEN GOTO 220
460 PRINT
470 PRINT"YOU FAILED -"
480 PRINT"THE ALIENS GOT YOU"
490 END
500 PRINT "GOOD TAKE OFF"
E: a patch for one of the little things that annoy me in games:
code:
220 PRINT"YOU HAVE ";GS;
223 IF GS<>1 THEN PRINT" TRIES"
226 IF GS=1 THEN PRINT" TRY"


Fred's code in action

And now, it's my turn, as Teacher, to show a third way to handle these loops! First up, let's tidy the code a little, with the help of the colon, which concatenates lines. It's not perfect, as each line has a practical character limit of 248, and IF cases are better handled with ELSE routines... But it helps us group the code into lines that make sense, like so:

code:
10 CLS : PRINT "STARSHIP TAKEOFF"
20 LET G = INT(RND(1)*20+1) : LET W = INT (RND(1)*40+1) : LET R = G*W
30 PRINT "GRAVITY= ";G : PRINT "TYPE IN FORCE"
40 FOR C = 1 TO 10
50 INPUT F
60 IF F>R THEN PRINT "TOO HIGH"; ELSE IF F<R THEN PRINT "TOO LOW"; ELSE IF F=R THEN GOTO 100
70 IF C<>10 THEN PRINT ", TRY AGAIN"
80 NEXT C
90 PRINT : PRINT "YOU FAILED -" : PRINT "THE ALIENS GOT YOU" : STOP
100 PRINT "GOOD TAKEOFF"
So there's our tidy code... First up, let's define F before we ask for it. That can be added to 20 with no worries. Then, let's move things around, and add the time based random line.

code:
5 Z = RND(-RND(TIME))
10 LET G = INT(RND(1)*20+1) : LET W = INT(RND(1)*40+1) : LET R = G*W : LET F=0
20 FOR C= 1 TO 11
30 CLS : PRINT “STARSHIP TAKE-OFF” : PRINT : IF C = 1 THEN GOTO 50
35 IF C = 11 THEN GOTO 70
40 IF F>R THEN PRINT “TOO HIGH”; ELSE IF F<R THEN PRINT “TOO LOW”; ELSE IF F=R THEN GOTO 80
45 IF C<>11 THEN PRINT ;“,TRY AGAIN” 
50 PRINT “GRAVITY =” ;G : INPUT “TYPE IN FORCE”; F
60 NEXT C
70 PRINT “YOU FAILED -” : PRINT “THE ALIENS GOT YOU” : STOP
80 PRINT “GOOD TAKE OFF!”

...And finally, Teacher JamieTheD's showing...

How does this work, and so simply too? By taking advantage of the fact we can leave a loop at any time. We already guessed this from the fact we'd leave it for winning, but by organising the code properly, and adding two checks, we've left ourselves a lot of room for improvement. The first check is after we print the title: If it's the first turn, it skips checking for a result. Similarly, if it's turn “11”, there's no real need to check for a result, so we skip too. We could technically put those two together in the same line with an ELSE IF like we did the Warm/Cold routine in line 40, but hey, nobody's perfect, eh?

Anyways, a third method of doing things by thinking sideways a little.

JamieTheD fucked around with this message at 20:11 on Dec 12, 2015

JamieTheD
Nov 4, 2011

LPer, Reviewer, Mad Welshman

(Yes, that's a self portrait)
Well, that's a big auld post! It's provisional based on threadchat, but I think everybody did alright! An SSD with the progs all in one place will be edited into the post after tomorrow's update. :)

Adbot
ADBOT LOVES YOU

FredMSloniker
Jan 2, 2008

Why, yes, I do like Kirby games.

JamieTheD posted:

code:
5 Z = RND(-RND(TIME))
10 LET G = INT(RND(1)*20+1) : LET W = INT(RND(1)*40+1) : LET R = G*W : LET F=0
20 FOR C= 1 TO 11
30 CLS : PRINT “STARSHIP TAKE-OFF” : PRINT : IF C = 1 THEN GOTO 50
35 IF C = 11 THEN GOTO 70
40 IF F>R THEN PRINT “TOO HIGH”; ELSE IF F<R THEN PRINT “TOO LOW”; ELSE IF F=R THEN GOTO 70
45 IF C<>11 THEN PRINT ;“,TRY AGAIN” 
50 PRINT “GRAVITY =” ;G : INPUT “TYPE IN FORCE”; F
60 NEXT C
70 PRINT “YOU FAILED -” : PRINT “THE ALIENS GOT YOU” : STOP
80 PRINT “GOOD TAKE OFF!”

Shouldn't line 40 say GOTO 80?

  • Locked thread