Easy Programming forthe Oric-t
Lasy Programming for the Oric-1
lan Stewart
Mathematics Institute, University of Warwick
Robin jones
Computer Unit, South Kent College of technology
i
J | tt Shiva Publishing Limited
SHIVA PUBLISHING LIMITED 4 Church Lane, Nantwich, Cheshire CW5 5RQ, England
© Ian Stewart and Robin Jones, 1983
ISBN 0 906812 43 7
Cover photograph of the Oric-1 courtesy of Oric Products International Ltd.
To James and Christopher:
One day, all this will be... completely different.
All rights reserved. No part of this publication may be reproduced, stored in a retrieval system, or transmitted in any form or by any means, electronic, mechanical, photocopying recording and/or otherwise, without the prior written permission of the Publishers.
This book is sold subject to the Standard Conditions of Sale of Net Books and may not be resold in the UK below the net price given by the Publishers in their current price list.
Typeset by Gilbert Composing Services, Leighton Buzzard and printed by Devon Print Group, Exeter.
Contents
—_— ere COU ANI KDUN FP WN
Introduction
Up and Running
The Keyboard
Direct Commands Programs
Text Display
Variables
Inputs
Branching
Plot Positions
Looping
Debugging I
Sound and Colour
Using a Cassette Recorder Debugging II
Random Numbers
Strings
Substrings
Debugging III
The Art of Coarse Graphics Moving Graphics
Arrays
Music and Harmony Debugging IV
PEEK and POKE High-resolution Graphics Colour in High-resolution Debugging V User-defined Characters Subroutines
Debugging VI
What Next?
Appendix 1: Control Characters Appendix 2: Alternate Character Set Program Index
Commands and Symbols Index
10 13
23 27 31 36 42 51 56 65 68 70 74 78 83 88 96 102 105 113 120 125 136 143 145 149 154 156 158 159 161 162
introduction
Tangerine’s Oric-1 microcomputer offers sound, colour and high resolution graphics ata remarkably modest price. The aim of this book is to make the basic features of the Oric accessible to the newcomer to computing, and to provide useful information for the more experienced user who is transferring from another machine.
When you buy your Oric, you get a comprehensive User Manual with it. So why buy a book?
Since you’re reading this, you probably have an idea of the answer. It’s difficult for a Manual to be both comprehensive and comprehensible. Manuals have to be all things to all people, and they tend to lack the space needed for proper and careful explanations in the kind of detail that a beginner may need.
In addition, some of the more exciting features, such as sound and colour, are a little tricky to use effectively: a few general hints and sample programs can go a long way, helping you to use the Oric’s capabilities to the full.
So what’s on offer here?
First, a reasonably thorough description of the fundamentals of BASIC, the Oric’s native tongue. We’ve concentrated on the commands that are most important for a beginner: when you’ve mastered these, the Manual will look a great deal less daunting and you'll be able to fill in some of the gaps. We’ve deliberately avoided anything beyond the simplest mathematics: you can go a long way without it! Each command 6r group of commands is illustrated by sample programs, ranging from short test programs to more lengthy games and utility programs. These are not intended to be masterpieces of awe- inspiring power and beauty, because the listings for really fancy programs can become so long that nobody would have the energy to type them in. They are intended to illustrate how a little attention to detail can greatly improve the looks and function of a program, and to show you what the machine can be made to do with a reasonable amount of effort.
Each chapter also includes one or more projects for you to tackle. Answers are provided, so you can use the projects to test your understanding and to augment it.
The sample programs can be copied and run without having to understand how they work, and each is accompanied by an explanation of how it achieves its effects.
Second, we’ve included a series of chapters on debugging: how to find errors in programs ahd correct them. If you really want to write your own programs, these techniques are indispensible. Yet very few books bother to tell you about them. (The trick is seeing the wood for the trees. For example Oric has a trace command that will print out program lines as they are carried out; but if you list every line, the screen will fill up so fast you'll never see what’s going on. So you need to be selective.)
Third, we’ve described a few useful techniques for writing programs that are easy to understand and easy to get working. To begin with you’ll be happy if a program produces the right result, however messy or clumsy it may be; and that’s fair enough. But for longer and more sophisticated programs, a readable structure is important.
Fourth, we’ve included information on the way the Oric works, which is not listed in the Manual in sufficient detail: CTRL keys, alternate characters, using the screen editor....
Fifth, we provide much more explanation of how to use the sound and colour facilities: musical harmony, low and high resolution graphics, the use of colour commands (serial
attributes) in both low resolution and high resolution (in which colour commands must be ‘poked to the screen’), moving graphics and keyboard control.
The Oric is a versatile beast; but it takes a little effort to get the best out of it. This book certainly doesn’t exhaust the possibilities—it would take a great many books to do that—but it should help you get properly started.
After all, the hardest part is getting off the ground.
NOTE FOR EXPERTS
As we’ve just said, this is a book for first-time users: it’s not written for experts. In particular, the simplest way to achieve a desired result is not always the most efficient. So if we sometimes appear to be doing things in a clumsy way, we probably are. However, it makes good sense to learn to walk before you run; and to learn the simple features before moving on to sophisticated and more powerful ones.
Similarly, don’t expect the program-listings to be highly polished production versions with arcade-quality graphics, performing miracles of computation at breathtaking speed. The aim here is to produce simple listings that the reader can (a) type in ina finite time, and (b) work through and understand. The really fancy stuff should come later.
Note for Grammarians and Pedants
Some half-dozen books back, we decided that we ought to refer to ourselves collectively, as ‘I’. It’s perhaps a trifle unorthodox, but it’s very convenient because we occasionally have to relate personal experiences. “‘As we said to our wife this morning . . .”’—no, that doesn’t sound right. So ‘I’ is some sort of composite of us both. ‘We’ henceforth means ‘I and the reader’.
First, how to set up the hardware. You’ve probably managed this already, but if not, a few hints may help.
1 Up and Running
If you’ve ever connected up a TV game, or another breed of home computer, to your television set, you’ll have no trouble setting up the Oric. But in case you haven’t, I’ll start with a quick run through the procedure.
When you unpacked your Oric you should have found:
The computer.
The power-pack, like an overfed electric plug with a long lead ending at a much
tinier plug.
3. The TV connection cable, a single coaxial cable with a coaxial connector on each end.
4. The cassette connection cable, a double cable with more complicated plugs that have three pins inside a round outside bit (technically known as three-pin DIN plugs).
5. The book Oric-1: BASIC Programming Manual (which Ill shorten to Manual from
now on).
Ne
Before connecting everything together, it’s a good idea to decide on a civilized layout. Unless you’re using a spare TV set, the Oric is going to have to live somewhere near the usual place you put the TV. On the floor is not a good idea; you’ll risk treading dn the Oric and damaging it. Worse, you’ll end up with pins-and-needles from sitting cramped up. So get a table, something like a coffee-table, and a chair, and place them by the TV.
The Oric has a keyboard on top and a lot of sockets in the back. Plug the lead from the power-pack into the leftmost socket (as viewed from the front) which is a hole with a central pin, next to two long sockets with parallel pairs of pins. Plug the ‘male’ end of the TV cable into the rightmost socket (viewed from the front). Plug the other end of the TV cable into the TV, where the aerial connection usually goes. (This will be marked UHF on the TV.)
Incidentally, the Oric will work perfectly well on a black-and-white TV; but of course you won’t be able to use its colour facilities.
Some TVs have a numbered rotating dial to set the channels. If yours is like this, set the dial to Channel 36.
If not, you’ll have six or eight preset buttons to select channels. On most sets numbers 1, 2, 3 give BBC-1, BBC-2 and ITV. (And, these days, 4 gets Channel 4). In actual fact any button can be adjusted to set it to any channel, so your TV may not follow the usual pattern. Either way, select a number that you don’t use for anything, say number six, and press that button.
Now plug the power-pack directly into the mains. Switch on the TV and the Oric. If you’ve remembered to switch on at the socket, you’ll hear the Oric buzzing at you. This is perfectly normal and a sign of good health, like wet noses on dogs, so don’t worry.
At this stage you will probably see just a random screenful of ‘snow’ because you haven’t tuned the channel selector yet. Somewhere on the TV is a set of six (or eight) little rotating dials that do this. Often it’s concealed behind a little panel. If you’ve never noticed it have a good search: you'll be surprised! Sometimes the maker’s name flaps
down, sometimes a whole section pops out if you give it a push in the right place. Having found it, adjust dial number six (your chosen channel number) until the screen displays a message. You’ll probably have to turn the dial several times and you may need to reverse direction if turning it one way doesn’t seem to be working.
Figure 1.1 A tidy layout is recommended.
Even if you have a numbered dial and have found channel 36, a little fine-tuning may be needed to get the best picture. You may also need to adjust the brightness and contrast controls, and the colour setting (and just occasionally horizontal and vertical hold).
What you are looking for is a clear white screen with a black border displaying the message:
ORIC EXTENDED BASIC V1.0 © 1983 TANGERINE
47870 BYTES FREE
Ready
(That’s for the current 48K machine: the numbers in the message may be different depending on which version of the computer you’ve got.)
Sometimes you don’t get this: instead you get a picture made up of black and white blocks and stripes, possibly flickering quite rapidly. If so, switch off at the mains for a few seconds and switch on again: the Oric will then reset itself correctly and display its message.
Once you have found this, the computer is ready for action. If you can’t get anything, check that everything is switched on and connected properly, and that the plugs are firmly in their sockets; then try adjusting the tuning again. When you get close to the right place
you'll see flickering lines on the screen, dimly visible through the snow. If you still can’t pick up the message after tracking from one end of the tuning range to the other, either you’re turning the wrong dial or something isn’t quite right. If you’re at all handy, take a look at the connections on the leads and see whether any wires have come adrift, and/or check the continuity of the leads and test for short circuits using a battery anda torch bulb. If you still get nowhere, contact the shop that you bought the Oric from. Computer hardware is very reliable, but it can sometimes go wrong.
CASSETTE RECORDERS
Ata later stage you will wish to connect up a cassette recorder to your Oric to load or save programs on tape. But for the moment we won’t try to do this. See Chapter 13 if you particularly want to know how, or if you’re having problems with the Oric demonstration tape.
A DISCREET WORD OF ADVICE
It is just possible that certain members of your household are not as enamoured of the Oric as you are. They will conceal these feelings successfully, until the day they switch on the TV to watch Dallas and get a multicoloured hissing snowstorm. So, when you have finished using the Oric, restore the TV to its normal settings and check that it’s tuned correctly.
What do those keys on the Oric do? If you push them at random, not a lot! But at least that way you'll get a good feel for:
2 the Keyboard
The Oric keyboard is just like a typewriter keyboard, and the letters are arranged in the same ‘qwerty’ pattern. Basically this is a stupid arrangement that goes back to the early days of typewriters when keys often jammed; but it has become so utterly standardized that we all have to learn to live with it.
As well as the letters and numbers there are keys marked ESC, CTRL, and SHIFT down the left side; DEL, RETURN, SHIFT down the right side; and along the bottom is a long bar flanked by two pairs of keys with arrows. This is the space bar, just as on a typewriter; and the arrow keys are cursor control keys (see later).
The first step is to get the feel of the keyboard. It takes a while to get used to all the things that the keyboard can be made to do, but the one thing you can’t do by typing is damage the machine. So feel free to experiment: if you end up stuck with some weird effect (which is possible) just switch off and then on again (or see RESET on page 8).
Assuming you’ve just switched on, you’ll have the copyright message, and a flashing square called a cursor. This controls whereabouts on the TV screen things get printed. Press the key marked ‘A’; you’ll see an A appear where the cursor was, and the cursor itself moves one space right. You’ll also hear a fairly high-pitched bleep, which lets you know that the computer has reacted to the key-press—very useful when you’re typing in a long program and don’t want to look at the screen too often to check.
Press other keys. To make life easy, stick to the ones with letters and numbers on for a while. Hold a key down for a second or two: you’ll find it produces the same letter over and over again. This is called auto-repeat. After you’ve filled two lines of screen the computer will give a sharp, resounding PING! This just means you’ve exceeded the size limit for messages; ignore it for the moment.
PSH? UR
aa
Figure 2.1 Some of the features available from the keyboard.
SHIFT
The two keys marked SHIFT both have the same effect, which is just as ona typewriter. If you hold down a SHIFT key with one hand and press another key, you get upper case characters. For instance, hold down SHIFT and hit key ‘S’. What you see is a percentage sign ‘%’; and if you look at the key you’ll see that it has the ‘%’ marked over the top of the ‘5’. If a key has two symbols written by it, SHIFT produces the upper one, and no SHIFT the lower.
The letter keys A-Z are marked only in capitals; and at the moment that’s all they’ll produce, either with or without SHIFT. But there is a way to get lower case letters a-z, which I’ll explain later.
RETURN
In a way, this is the most important key on the computer. When you press it, whatever:
you’ve typed is shovelled into the computer’s memory. Until that point, all the computer
does is display things on the screen; but when you hit RETURN it will act on them. Type in some rubbish like:
AAABBBBB%%67QJ and then hit RETURN. What you get is a message:
? SYNTAX ERROR Ready This means that the Oric has received your instruction, but (not surprisingly) doesn’t
understand it. If you type ina more meaningful message it will carry it out. For example, press RETURN (to get rid of any junk) and then type:
EXPLODE (and hit RETURN)
It does! At least, it produces an explosion sound. So that message made sense, and was acted upon.
SPACE BAR
The long space bar at the bottom produces blank spaces, just as on a typewriter. These are useful for leaving gaps between words, and for getting tidy screen displays.
CURSOR KEYS
The keys with arrows on move the flashing cursor around. Try them out. The /eft(<) and right (>) arrows move the cursor along a row; the up (t) and down (1) move it vertically. If you try to go off the edge then two different things can happen:
1. For > and < : the cursor reappears on the other side of the screen, but one row lower (higher).
2. For t and 4: the cursor stays in place but the rest of the screen scrolls. That is, the symbols on the screen move up (like a piece of paper in a typewriter does when you go on to a new line) or down, depending on which arrow you’ve used.
Unlike a piece of paper, anything that scrolls off screen is lost: if you scroll back again, it is replaced by blanks.
DEL
This is the delete key, and it acts as an eraser. If you hit DEL then the cursor moves back a space, and rubs one character out. This is useful for correcting mistakes.
RESET
This ‘key’ isn’t on the top of the Oric: it’s hidden away underneath. There’s a square hole. When you poke a pencil through this and push the button inside the machine, it will reser to its normal state. For instance, fill the screen with junk, and now RESET. You'll find the screen has cleared, the cursor is back at top left, and you’re ready for action.
Figure 2.2 The RESET button lives inside this hole. Use a pencil to operate it.
RESET gives you a ‘warm start’ if you have a program in memory and something untoward occurs. It gets the the computer back into a ‘ready-to-run’ state, and unlike switching off the power, does not clear the contents of memory. So, if you get stuck in an endless loop, or you accidentally put the display out of synch, RESET!
CTRL
This stands for CONTROL, and I’ve left it towards the end because it’s a real Pandora’s box. If you hold down CTRL and press another key, all kinds of things can happen.
For instance, press CTRL and ‘G’. There, that startled you, didn’t it? You got that PING again. That’s all CTRL/G does: it pings. CTRL/L clears the screen completely: try it.
If you press CTRL/T and start typing letters A-Z, you'll find they now come out in lower case, aS a-z. (What happens if you now type SHIFT/A, etc.?)
To get out of this state, press CTRL/T again. You should see a message:
CAPS
at top right of screen; and now the shift has no effect. on letters. (Effectively, this makes CTRL/T a CAPS LOCK key; note that it does not affect the top row of numbered keys, which still respond to SHIFT. The reason for having this facility is that all programs must be written in capitals, so you want the caps lock on in these circumstances.)
If you press CTRL/T repeatedly, the message CAPS appears and then disappears again. This is what the Manual means by toggle action: one press switches on, another off, the next on, and so on. Most of the CTRL keys toggle like this.
One useful key for distraught mums is CTRL/F, which cuts out the keyboard bleep (which is too loud for my tastes). If your keyboard won’t bleep, try hitting CTRL/F in case you’ve accidentially toggled it off and need to toggle on again....
There are lots of more esoteric CTRL keys: see Appendix 1, and experiment.
ESC
I mention this only for completeness: you probably won’t need to use it, but experimenting may have left you with the impression that it does nothing at all. Actually it lets you send attributes (see Chapter 12) to the cursor position. For an example, position the cursor near the middle of the screen using the arrow keys, hit ESC, and then hit ‘T’. A blue stripe will appear. The attribute code (Chapter 12) corresponds to the position of ‘T’ in the alphabet. The control keys CTRL/[ and CTRL/Z also have this effect, which the Manual calls ‘Escape Character Routine’.
SPACES
Spaces cause problems in program listings, because they’re blank! In this book I'll adopta convention to show spaces when they’re important. Instead of printing a blank, I’ll print the symbol:
Vv
This is not available on the keyboard, so there should be no confusion. For example, I might write:
10 PRINT “STEWARTV ANDV JONES” or 20 PRINT “AVVBVVCVVD”
If it’s obvious where a space ought to go, I won’t necessarily show it as a V symbol.
A program is just a series of instructions, that are stored, to be carried out later. But first, you can try giving the commands direct from the keyboard.
3 Direct Commands
When you give the computer an instruction from the keyboard, so that it carries it out immediately the RETURN key is pressed, you are using it in immediate or direct mode. (‘Mode’ is computer jargon, and it would mean the ‘state of mind’ of the computer—if it had a mind. Hence the joke in a computer magazine that in a certain series of television programmes the presenter appeared to be funttioning throughout in ‘astonishment mode’.) There is another, deferred mode, in which the command is stored in memory and carried out later on. In fact a whole list of such commands is usually stored, forming a program. (The American spelling is standard in the industry and helps distinguish the technical term from the usual word ‘programme’, although the English version gets used a lot nowadays too.) I discuss programs in Chapter 4; for now, I’ll function in immediate mode.
An Oric in immediate mode makes an impressive calculator, as well as a typewriter. Try this:
PRINT 2 + 2
(and then RETURN). You’ll see the answer, 4, on the screen. Well, maybe that isn’t impressive; but if you ask it to:
PRINT 12345678 + 87654321 it gives you 99999999 just as quickly.
Project 1
Get the computer to work out:
(a) 7+4 (b) 17+ 41 (c) 5+ 16
(d) 15123 + 97784 The Oric can also do subtraction:
PRINT 11 — 5
PRINT 77 — 3
PRINT 55555 — 22222 and so on.
For multiplication you must use the asterisk * instead of the usual multiplication sign X (because programmers confuse this with the letter X). Try:
PRINT 2 * 2 PRINT 2 * 3
PRINT 5 * 5 PRINT 99 * 77
Finally Pll mention division: for this the symbol / is used, rather than +. So to divide 24 by 3 you must ask for:
PRINT 24/3 and to divide 777 by 7: PRINT 777/7
As well as whole numbers like these, the Oric can handle decimals like 27.342, and negative numbers like —99 or —27.342. It can also carry out a variety of mathematical calculations besides the arithmetical operations of addition, subtraction, multiplication and division. On the whole these refinements will not be required in this book.
Project 2 Try these commands out in immediate mode. What happens?
(a) ZAP
(b) PLOT 10, 10, 20
(c) PRINT ‘2 + 2”
(d) PRINT “ORIC”
(e) PRINT “ORIC’” BACKWARDS (f) PRINT “BACKWARDS”
(g) PRINT BACKWARDS
(h) PING
(i) DROP DEAD
G) PLOTS, 5, 17
(k) SOUND 1, 200, 3 (Use CTRL/C to stop this!) (1) PAPER 4
ALAS, POOR ORIC !
A FEEBLE EXCUSE
Once you’re happy with the keyboard, you’ll be able to type ina command, or an entire program, and make it work, without having to understand any of the instructions in it.* You can even ‘borrow’ listings from books and magazines. This is perfectly normal, and you shouldn’t feel guilty about it: everybody feels the urge from time to time. And it helps you to stay interested and to build confidence. (Like all good things, it shouldn’t be overdone. If the Government’s Information Technology year does nothing except produce a generation of people who can copy somebody else’s software but not write their own, it might have been better to spend the money on a subsidy to Channel 4.)
* You just have, in Project 2. Il
Sometimes, when demonstrating a particular BASIC command, especially early on when we don’t know very many, it would be nice to make use of a command that hasn’t been explained yet. And that’s precisely what I’m going to do if I feel it’s appropriate.
So don’t throw up your hands in horror and start moaning that the-silly-blighter- hasn’t-told-us-about-that-yet: just grit your teeth, key the command in regardless, and observe the effect. It’s there for your own good.
That’s my excuse, anyway.
ANSWERS
Project 1
(a) PRINT 7+ 4 (giving 11)
(b) PRINT 17+ 41 (giving 58)
(c) PRINT 5 + 16 (giving 21)
(d) PRINT 15123 + 97784 = (giving 112907)
Project 2
(a) Sound effect.
(b) Blue stripe.
(c) 2+ 2 appears on the screen, but it doesn’t give the result, 4.
(d) ORIC appears on screen.
(e) ORICO appears on screen. (Why? It thinks BACKWARDS is a variable, equal to @. See Chapter 6.)
(f) BACKWARDS appears on screen.
(g) @ appears on screen. (Reason as in (e).)
(h) Sound effect.
(i) ?SYNTAX ERROR.
G) Red stripe.
(k) Continuous tone, only stopping if you hit CTRL/C or switch off.
(1) Screen turns blue.
The way to get the computer to do what you want is to assemble the necessary instructions in a systematic list.
4 Programs
A program is a series of instructions for the computer to carry out. It’s very like a recipe in a cookery book:
Take two eggs
Break them into a pan Whisk them for 20 seconds Add 2 kg tapioca
Add 4 cans of baked beans
and so forth. But a computer program has to be written’in a very precise language. Here is a simple program.
10 PRINT “HELLO!”; 20 GOTO 10
You can type this into your computer. First, type NEW and hit RETURNthis will remove any remnants of previous programs. ALWAYS do this before typing in a new program. Then type in the first line:
10 PRINT “HELLO!”;
and RETURN. Because the instruction starts with a number, here 10, the computer treats it in deferred mode: it stores it away ready to carry it out when told to. Now type in:
20 GOTO 10
plus RETURN. Don’t worry about what any of this mumbo-jumbo means for the moment.
That’s got it into memory, but how do we tell the computer to execute it (as the jargon goes)? We input the command:
RUN
(plus RETURN, of course—I’m going to start omitting mention of that, but I’llexpect you to hit RETURN at the end of each ‘line’ of a program and each instruction in immediate mode).
Assuming you’ve copied it out exactly as listed, all hell(o) will break loose. The word ‘HELLO!’ will appear all over the screen, moving around at high speed in a frenzied sort of way. And it will keep on doing it forever, unless you stop it. But how?
14
BREAK
To interrupt the machine in its deliberations (for example if you think it’s got stuck because of a program bug) you just press:
CTRL/C (that is, the CTRL key and the C key)
and it will (fairly) promptly stop, with a message:
BREAK IN 294 (or whatever line it had reached) Ready
When you break the program above using CTRL/C, you'll get a BREAK message, usually referring to line 1@ (because that line takes much longer to execute) but sometimes to line 20 (if you just hit the right timing). You can always use CTRL/C to stop a program if it seems to have got stuck or is doing something wrong.
CONT
To start up after a CTRL/C, you can use the command: CONT
(short for ‘continue’). Try it now: away she goes again!
WHAT’S GOING ON?
In a BASIC program, every instruction has a number, called its /ine number. Here the line numbers are 10 and 20. Normally the machine carries out the commands in numerical order of line numbers—so here it will do line 10 first, line 20 second.
BUT: some commands have the effect of changing the next line number to be carried out. Here the command:
GOTO 16 means ‘ignore the next line if there is one, and carry out line 10 instead’.
To understand what the program is doing, we need to know one more thing. The semicolon (;) after the PRINT “HELLO!” statement tells the computer that the next item to be printed should follow on immediately after the end of the HELLO! If the semicolon is omitted, the machine will print on the next line of screen instead.
So, when RUN is pressed, this is what the machine does.
It looks for the first line:
10 PRINT “HELLO!” and carries it out, getting the screen display: HELLO!
Since that command did not tell it to change the pattern of line numbers from the usual one, it goes on to the next line in numerical order:
20 GOTO 10 Carrying this out, it gets back to line 10 again! So it now prints another HELLO}, giving: HELLO! HELLO! and moves on to line 20. But line 20 sends it back to line 10: HELLO! HELLO!HELLO!
and it keeps on printing HELLO! forever (or at least until something external, the BREAK key or Old Age or the End of the Universe, stops it). After the sixth occasion it runs off the end of the line and wraps round on to the next; and after about 180 turns it hits
the bottom line and the screen starts to scroll up. In practice this all happens so fast that you can’t see anything except flickering versions of HELLO! as the screen rushes past. To slow it down, add an extra line:
15 WAIT 20
(which Ill explain in Chapter 12). Now the pattern in which the printing takes place is clear.
LISTING
If you’ve typed a program in, you may at some stage want to have it displayed on the screen ina tidy form, to see what it was. (For instance, you may wish to change a line, but have forgotten its number.) To achieve this, type in immediate mode the command:
LIST
Try it now: enter CLS first so that the Oric can’t cheat by reading the TV screen. You can add extra lines to a program just by typing them in. Don’t worry about the ordering of the line riumbers: the Oric will automatically sort the lines into order. If you type in: 20 PRINT ‘NOT IN ORDER” 10 PRINT “THIS PROGRAM IS”
and then LIST, it will come out as:
19 PRINT ‘‘THIS PROGRAM IS” 20 PRINT “NOT IN ORDER”
Similarly you can change a line just by entering a new orie with the same number, type: 20 PRINT “IN ORDER”
and LIST again. To delete a line altogether, type its number but nothing else (except RETURN, of course). So:
20 (plus RETURN) deletes line 20. (The computer treats it as a program line with no actual command, only a number, and promptly ignores it.)
To list specific lines (which may be necessary for a long program because of scrolling) you use commands like:
LIST 50 - 180 which will list lines 50 to 180. See page 17 of the Manual for further information.
NEW AND CLS
There are some simple BASIC commands that require hardly any explanation, but are used all the time to clear out garbage and put the computer in the right frame of mind fora new task. The first is one I mentioned earlier:
NEW
This clears out any old program listings. You should a/ways type NEW (+ RETURN) before starting to key in a new program, otherwise old program lines can interfere with it.
When the screen is full of junk, the easiest way to clear it, and reset the cursor to top left, is to use:
CLS
16
(Clear Screen.) Recall that CTRL/L does this from the keyboard. On some computers, NEW automatically clears the screen, but the Oric lets you NEW while leaving the screen alone.
You can use both of these in programs; CLS is mandatory in any program that produces a nice display. The only effect of NEW is to produce the Wonderful Self-Destructive Program as soon as that program line is executed!
SIMPLE SAMPLES
Here are three short programs for you to type in and RUN. Each is presented asa project, because your job is to find out what they do. Remember to type NEW (+ RETURN) before entering each program.
Project 1
Type this in (don’t forget RETURN after each line!) and RUN it. What happens?
10 NS = “MARMADUKE”
20 PRINT 30 PRINT N$ 40 N$ = “IVE PRINTED (+ N§ + ‘)” 5@ ZAP 60 WAIT 160 70 GOTO 20 Project 2
10 FOR T=98@ TO 1000 20 PRINT T, “SQUARED IS”, T * T 30 NEXT T
Project 3 (Use CTRL/C to stop this.)
10 CLS
20 R= 26 * RND(1)
30 C= 38 * RND(I)
40 A= 16+ 8 * RND(1) 5@ PLOT C,R,A
60 GOTO 20
LINE NUMBERS IN BASIC
Not all high-level languages use line numbers to tell the machine in what order to carry out commands; but there is always some definite order. However, some instructions are designed to affect this natural order, thereby sending the machine back to repeat an earlier instruction (possibly subject to slight changes). It is this mixture of precise instructions and variable order in which they are performed, that makes the computer so flexible. In BASIC, and some other languages, every instruction is numbered. On the Oric you can use numbers between @ and 63999. You do not have to number the lines 1, 2,3, and so on; in fact it is common to start off using something like 10, 20, 30, ... going up in tens. The
object is to /eavé space to add extra lines in between if you later decide you need to: it would be hard to adda line between lines 2 and 3 of a program! But there is no rule that the numbers must be regular: you could number the lines 17, 18, 25, 356, 999, 1000, 1003, 1010, 1020, 5033 (say) if you wished. Most programs start with tidy-looking line numbers and end up with messy ones as mistakes are put right.
MULTI-STATEMENT LINES
You can put several commands on one line of program, provided you separate them by colons (:). For example: 10 CLS 20 PRINT “HELP! I AM A PRISONER IN AN ORIC!: PING: WAIT 50: GOTO 20
This can save space, and typing time; but it’s not always such a good idea because:
1. You can only jump to the start of a multi-statement line. 2. Changing the line if there’s a typing error will be harder.
However, there are occasions when using multiple statements like this saves a lot of work and causes no problems. For example, when assigning a whole lot of variables (see Chapter 6): @ A=1:B=2:C=3:D=4 E=5
In some of my listings you will occasionally find multiple statement lines, so I thought you ought to know about them. But you can manage perfectly well without them, and they certainly should not be used too heavily or the program becomes unreadable. A well- known publisher of educational software forbids multi-statement lines for precisely this reason.
THE TASK OF THE PROGRAMMER
It should now be clear what the task of the programmer is. In order to achieve a particular aim, the programmer must assemble a set of instructions which, when carried out exactly by the computer, achieves the desired result.
It is important to realize that the computer has no idea what the ‘purpose’ of a program is. It simply obeys instructions: it is a fast-thinking and utterly pedantic slave, and if you tell it do something stupid, it will. As you will most certainly discover very quickly when you set about writing programs.
ANSWERS Project 1
First, the computer prints: MARMADUKE Then it notices what it’s done, and says so: I'VE PRINTED (MARMADUKE) Then it notices that: I'VE PRINTED (I’VE PRINTED(MARMADUKE))
and so on until you get an error message:
STRING TOO LONG ERROR IN 40
and stops. This just means that the thing it’s trying to print out has got too long for it to handle.
Project 2
This prints out a table of squares. (The square of a number is what you get when you multiply it by itself; for instance 6 squared is 6 X 6 (or 6 * 6 in BASIC) which is 36.) The table continues until it reaches:
1000 SQUARED IS 1000000
and then stops.
oT 0 hI
pea Seite
The The The The The The The | The The i * i
eee gegege
998989838 3333353
MOOOUUUOOOUUUOY
Figure 4.1 Change T* T to T* T * T and squares to cubes for a variation on Project 2.
Project 3
This produces a changing pattern of coloured stripes on the screen, running horizontally: it’s a foretaste of Oric’s colour facilities. Note that each new stripe runs from a position somewhere on the screen and continues all the way to the right hand edge; but an old stripe may be overwritten by a new one.
This program will continue indefinitely, until you break using CTRL/C.
The keyboard lets you talk to your Oric. By using the TV screen, it can talk back.
5 fext Display
I’ve already used the (rather self-explanatory) command: PRINT
to produce output to the TV screen. The time has come to explore it in more detail.
DISPLAY MODES
The Oric’s screen display can work in four different ways, depending on how it’s been set up. These modes, as they are called, are:
TEXT
LORES@ Low resolution or coarse. LORES1
HIRES + High resolution or fine.
When you switch the Oric on, it automatically goes into TEXT mode, which gives a blank white screen and lets you plot letters and symbols from the keyboard. For LORES@ and LORES|! see Chapter 19; for HIRES see Chapter 25.
If this idea of several different modes seems a little daunting, think of the machine as having four different notepads, which it uses for different purposes. All you have to do is tell it which notepad to use. Here I’m sticking to TEXT which is automatic anyway unless you tell Oric otherwise.
The Oric deals with two different types of information: numbers and strings. Numbers are displayed in their usual form, possibly with minus signs and decimal points: things like:
25 —999 76.3332
Strings are just a series of symbols, or characters, considered as a single entity. To emphasize this, they are normally placed in quotes:
“MARMADUKE” “CATCH-22”
66a ok oe THE END 2K?
“%&4999 BCXXX/**GARBAGE+++>”
The PRINT command operates ina very slightly different way, depending on what’s being printed.
19
20
To PRINT a number, such as 42, you just use a program line like: 430 PRINT 42 To print a string, you place it within quotes: 449 PRINT “MARMADUKE”
If you try these ‘programs’ (don’t forget RETURN) and RUN them, you’ll find that the first gives:
42 on the TV screen, and the second: MARMADUKE
as you might expect. The difference is that the quotes round a string are not printed.
PUNCTUATED PRINTING
A PRINT command can be followed by one of three punctuation marks:
1. Semicolon (;). 2. Comma (,). 3. Nothing at all.
Corresponding examples would be things like:
1. 100 PRINT “THIS MAKES A HUMBLE COMPUTER VERY HAPPY”; 2. 110 PRINT “THIS MAKES A HUMBLE COMPUTER VERY HAPPY”, 3. 120 PRINT “THIS MAKES A HUMBLE COMPUTER VERY HAPPY”
Consider this as a three-line program, key it in, and RUN: you'll find that the messages start in different positions on the screen.
What the punctuation marks do is insert spaces after what’s been printed, thereby adjusting the next PRINT position on screen. They affect numbers differently from strings (this is intended for your convenience but personally I’m skeptical), like this:
Numbers Strings Semicolon Leave one space Leave no spaces Comma Leave four spaces Leave three spaces Nothing Move to next line Move to next line
While we’re at it, let me mention that plain: PRINT
just prints a blank line and moves on to the next—like CARRIAGE RETURN and LINE FEED on a typewriter. In computer jargon this operation is called a NEWLINE.
The reason for having these punctuation possibilities is that you can produce different formats of TV screen output. The main feature is that more than one item may be specified ina single PRINT command, provided punctuation marks are used to separate the items. For instance, you could write:
500 PRINT “FRED”, “LAURA”; 77, 4.22; “ROGERVANDVOUT” and get a display: FREDVVVLAURAV77V VV V4.22ROGERVANDVOUT
Now that’s not terribly pretty; but Project 1 produces neater results.
Project 1 Compare the results of the following ‘programs’.
(a) 10 PRINT1 20 PRINT 2 30 PRINT 3 40 PRINT 4
(b) 10 PRINT 1, 2, 3,4 (c) 10 PRINT 1; 2; 3; 4 (d) 10 PRINT 1,,2,,3,,4
(ce) 10 PRINT 1,,2,,3,,4 20 PRINT 5,,6,,7,,8
(f) 10 PRINT 1,,2,,3,,4,, 20 PRINT S,,6,,7,,8
(g) 10 PRINT 1,,2,,3,,4 20 PRINT 30 PRINT S,,6,,7,,8 (h) Try the programs in (a)-(g) again, but replace 1,2, ... , 8 by the strings “A”,
(i) As (h), but now use strings with varying lengths, such as ‘MARMADUKE”, “ORIC”, “*”, “JR”, “CAT”, “CABBAGE” and so on.
Take a look at projects | and 2 of Chapter 4 and work how the PRINT commands there produce the observed output when the program is run.
Short cut
Instead of typing the word: PRINT
you can use a single question mark: ?
This saves memory and typing time at the expense of being less immediately comprehensible. I suggest you get used to PRINT first, then switch to the question mark. For ease of comprehension, Ill always use PRINT in this book. The Oric has plenty of memory to spare anyway!
ANSWERS Project 1
(a)
RWN—
21
22
(f)
(g)
IVVVV2VVVV3VVV V4 1V2V3V4 IVVVVVVV2VVVVVVV3VVVVVVV4
IVVVVVVV2VVVVVVV3VVVVVVV4 SVVVVVVV6VVVVVVVIVVVVVVV8
IVVVVVVV2VVVVVVV3VVVVVVV4VVVVVVVSVVVVV VV6VVVVVVVIVVVVVVV8
IVVVVVVV2VVVVVVV3VVVVVV V4 (blank line) SVVVVVVV6VVVVVVVIVIVVVVVV8
(h), (i) As above, but with | less space between items.
In many programs, you need to take
several numbers, and manipulate them in
a particular way; but the numbers themselves may need to change. That’s the time to
use:
6 Variables
Often a program has to perform the same job on lots of different numbers. For instance, Project 2 in Chapter 4:
10 FOR T=0@ TO 1000
20 PRINT T; ‘SQUARED IS”, T * T
30 NEXT T This has to work out the square T * T of the number T as it ranges from @ to 1000. (See Chapter 10 for FOR... NEXT.) We say that T is a (numeric) variable. As well as having a fixed name, here T, it has a value that may change during the course of a program. Here it starts with value @, then acquires value 1, and so on, until at the end its value is 1000.
Every variable has a name. The first character in the name must be a letter, but the others can be any combination of letters and digits. However:
1. There is no limit to the length (except that it has to be less than 78 characters to fit when typed in).
2. The computer only looks at the first two characters, so the extra power available from long names is largely illusory.
For example:
P
PS
K
FRED
MULLIGATAWNY V SOUP
are valid names, but:
2K *WARS $43
are not. And the computer will not distinguish between variables named as follows:
FRED FR FR7 FREDA FRANCE FR12 FREDERICK FREESPACE FROGSPAWN
23
24
because it will ‘think’ of all these as being just the two letters FR. However, it is sometimes convenient for the programmer to use longer names, like PRICE or BALANCE or TAX V RATE, as a reminder of what they stand for in the program. The only danger is that you may have two variables whose names /ook different, like:
BALANCE BACKPAY
but which the computer thinks are the same because they’re both BA.
ILLEGAL NAMES
In fact there’s one other rule that might cause you some head-scratching if it’s not pointed out. If any part of a name is one of the BASIC command words, then the word cannot be used for a variable. For instance:
PRINTRUN is illegal since it starts PRINT. If you try to use this, the computer gives the error message: SYNTAX ERROR
It’s not just at the start of the word that the trouble occurs. For example, since ON is a BASIC keyword, none of the following are valid variable names:
LONDON MONTY CONTENTS BONGODRUMS MONDAY FRONT MOONS BONE44
You can easily think up some more. (That’s why JONI won’t work despite page 21 of the Manual.)
? SYNTAX ERROR IN LINE 10
19 SPIDER = 8
| ARREST YOU FOR ASSIGNING AN ILLEGAL VARIABLE
Project 1
Two of the following are valid names, the rest are not. Which, and why? (Hint: ask the Oric to PRINT each one.)
H#NINE BLEND BATNOSE JUNCTION 221B BAKER
STREET CHESHIRES MENDACITY COST TARGET IMPOSE TILLNUMBER GRANDSIRE NOTE WORKRATE OVERLORD PREMISE BARNDANCE
ASSIGNMENT OF A VARIABLE
The computer treats everything that looks like a variable as if it is a variable, and it assumes that its value is @ unless you say otherwise. There are two ways to assign a value to a variable. One is to use the LET command:
1@ LET K = 365
The short way is to omit the word LET! This would give the equally acceptable: 10 K = 365
The value can be assigned indirectly, by expressing the new variable as some combination of variables already defined. Thus:
10 LET A = 36
20 LET B=5 30 LETK=10* A+B
sets K to the value 10 * 36 + 5, that is, 365 again. For example, this program will multiply the two numbers 77 and 88:
10 LETA=77
20 LET B= 88
30 LETK=A*B 40 PRINT K
And you can change the lines 10 and 20 to multiply other numbers if you wish. Of course here there are shorter ways to do the same thing, such as:
10 LET K =77 * 88
20 PRINT K
or just: 10 PRINT 77 * 88
but that’s because I’ve chosen an unusually simple example. Project 2
At Tangerine Departmental Stores a jewelled tiara costs $135, a magic bull’s eye $32 and a packet of lizard-scales $3. Use three variables TIARA, BULL and LIZ to set up a program to calculate the cost of six tiaras, five eyes and twenty-nine packets of lizard- scales. Call this variable PRICE.
Project 3
By changing only one line in the program, calculate the cost of eleven tiaras, fourteen eyes and three packets of lizard-scales.
Project 4
By changing three more lines, answer Project 2 when the prices have changed to $147 fora tiara, $43 for a bull’s eye and $1 for a packet of lizard-scales (which are going out of fashion).
STRING VARIABLES
Variables can also be used to hold string values: this time the symbol $ (usually pronounced ‘string’ rather than ‘dollar’ but you may be feeling mercenary . . .) must be tacked on to the end of the name, like this:
FRED$ X$ BAKER$ BOW$ G$ MARMADUKE$
Suppose you want to print your name all over the screen. You could write a program like this:
25
26
10 NAME$ = ‘““MARMADUKE FAUNTLY-SNODE” 20 PRINT NAME$; 30 GOTO 20
Here NAMES is being used as a string variable—but it’s not actually varying yet. Now try:
10 NAME$ = ‘“‘“MARMADUKE FAUNTLY-SNODE” 20 PRINT NAME$,
30 NAME$ = “MARVIN RUNCID”
40 PRINT NAME$,
5@ GOTO 10
and see how NAMES assumes whichever value it has just been assigned. For more on strings, see Chapters 16, 17.
ANSWERS
Project 1
The valid names are BAKER and STREET. The names #NINE and 221B don’t start with letters. The rest include a BASIC keyword (or several) as follows: BLEND
BATNOSE JUNCTION CHESHIRES MENDACITY COST TARGET IMPOSE TILLNUMBER GRANDSIRE NOTE WORKRATE OVERLORD PREMISE BARNDANCE.
Project 2 16 CLS 20 TIARA = 135 30 BULL = 32 40 LIZ =3
50 PRICE = 6* TIARA + 5 * BULL + 29 * LIZ 60 PRINT “THE TOTAL COST IS $”; PRICE
(I’ve omitted explicit mention of the spaces in the message on line 60: from now on I’lldo this if it’s clear where they ought to go.)
Project 3
Change line 5@ to: 50 PRICE = 11 * TIARA + 14 * BULL + 3 * LIZ
Project 4 Change lines 20-40 to:
20 TIARA = 147 30 BULL = 43 40 LIZ=1
To feed information into the computer, just instruct it to remind you when it needs to know something.
? inputs
Projects 2-4 of the previous chapter did the job, all right; but it’s an awful nuisance having to change program lines every time you want to change the value of a variable. Fortunately this is not necessary, thanks to the command:
INPUT which lets you set up the value from the keyboard. Like this:
10 PRINT ‘“‘TYPE IN A NUMBER” 20 INPUT N 30 PRINT “THE NUMBER WAS V ”; N When you run this you'll get TY PE INA NUMBER and then a question-mark. If you now
type a number on the keyboard, and hit RETURN, the program will go on to line 30 and print out its message, plus your number.
MULTIPLE INPUTS
As in PRINT commands, you can INPUT several different variables, using commas to separate them. Try this: 10 INPUT A, B, C
20 PRINT A, B, C 27
28
You will get a ? sign: key in a number, say 3. Now you get?? for the second number: key in 5. Finally you get ?? again, so key in 7. The Oric promptly prints out the values 3, 5,7 that you have input for A, B, C; the final result looks like this:
RUN
23
5
7
3 5 7
Ready
PROMPTS You can print out a message to remind you what an input is for (a ? sign is not always helpful), like this:
10 INPUT “TYPE IN A NUMBER”; N
which has the same effect as lines 10 and 20 of the program that began this chapter. You can use multiple inputs with these prompt messages too. Note where the semicolon and the quotes go.
Here’s a better way to handle Projects 2-4 of the previous chapter in a general fashion. 10 CLS 20 INPUT “PRICES: TIARA, EYE, LIZARD?”; TI, BU, LI 30 INPUT “QUANTITIES?”; NT, NB, NL 40 PRICE = NT * TI + NB * BU+NL * LI 50 PRINT “TOTAL PRICE IS $”; PRICE To keep the listing short I’ve abbreviated to two-character variables. TI, BU and LI are
the old TIARA, BULL, LIZ; and I’ve got three new variables for the quantities of each, called NT, NB, NL.
GETTING A TIDY DISPLAY
Suppose you want to get someone to enter his age and telephone number, say. Your first attempt might go like this:
1@ CLS
20 INPUT “AGE”; A
30 PRINTA
40 INPUT “TELEPHONE NUMBER”; T 5@ PRINT T
It works, but at the end the screen looks like this:
AGE? 17
17
TELEPHONE NUMBER? 361005 361005
Ready
which isn’t exactly pretty. You could do better by changing the order a bit:
10 CLS
20 INPUT “AGE?”; A
36 INPUT “TELEPHONE NUMBER?”; T 40 CLS
5@ PRINT A, T
But sometimes you may not want to wait till the end to print everything out. A better way would then be to arrange for the messages to be printed near the top of the screen, and rub them out before going any further.
At first sight this looks hard to manage, because the Manual gives no command to control the position of INPUT prompts on the screen. Indeed the INPUT position seems to have a life of its own. Of course CLS sends the cursor back to top left (and the INPUT prompts appear there too); but it has the unfortunate property of wiping out the entire display, which isn’t always what you want.
However, there is a trick. One of the control characters will send the cursor back to top left without clearing the screen. The relevant command is:
PRINT CHR$(30)
and I intend to use this for the moment without explaining what CHR$ does, otherwise I’ll get sidetracked. It works like this:
10 CLS
20 PRINT CHR$(3@)
30 INPUT “AGE”; A
40 INPUT “TELEPHONE NUMBER”; T
5@ PRINT:PRINT:PRINT
60 PRINT A, T
70 GOTO 20 Line 5@ is just to separate out the PRINTing of the input values. RUN this, and watch where the input prompts appear: always at the top of screen, even though the last lot of PRINTing remains in view. The program cycles indefinitely, asking for new inputs.
One flaw is that the old input information is also left on screen and gets in the way. Try
adding:
22 PRINT“ [38 spaces] ”
24 PRINT‘ [38 spaces] ”
26 PRINT CHR$(30) This wipes out the old prompts before returning the cursor to top left (in line 26) for the new ones.
You'll still find a few traces of old telephone numbers lying around if you input very long numbers like 999999999999. To get rid of them, modify line 60 to:
60 PRINT A, T;“* [15 spaces or so] ”
Incidentally, when I write things like [38 spaces] what I mean is for you to hit the spacebar 38 times:
PRINT “VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV VVVVVV”
If, like me, you’re too lazy to want to.go through all of that, you can use the command:
29
30
22 PRINT SPC(38)
In general SPC(N) produces a string of N spaces, where N is an integer between @ and 255 inclusive.
DATA, READ, RESTORE
This is a good place to introduce an alternative to INPUT that’s useful when you have to set up a standard list of values for certain variables.
The READ statement is rather like INPUT except that instead of picking up data from the keyboard, it gets it from a DATA statement.
Suppose there’s a line:
10 READA and anywhere else in the program (say at line 250): 250 DATA 37
Then, when line 10 is executed, A will contain 37. Once the ‘37’ has been used, any READ statement executed later will search further on for something to READ so that:
18 READA 20 READ B 250 DATA 37 260 DATA 15
will set A to 37 and B to 15. You could also write:
1@ READ A, B
250 DATA 37, 15
with the same effect. DATA lines can go anywhere: only the order is important. If you want to re-read the same data, it’s possible to do this by issuing a RESTORE command. So a line 30:
30 READ X, Y will transfer 37 to X and 15 to Y provided it’s preceded by: 25 RESTORE
See Chapters 22, 28 for examples of these commands in programs.
Sometimes the computer must perform different tasks under different conditions. To achieve this, use:
§ Branching
We’ve met one command that affects the order in which the computer carries out commands, namely GOTO, which sends it to a given line. This is a little too regular for programs that have to react differently in different circumstances.
One way to make the program branch according to the circumstances is the command:
IF wc THEN ic 3
Here’s an example:
BANK BALANCE
This is a very simple example of a ‘practical’ program. It will work out your bank balance if you tell it your previous balance and list your income and expenditure item by item. To keep it simple I’ve not worried about the positions of the input messages, but you can think about tidying them up if you wish. 10 CLS 20 PRINT ‘“‘PREVIOUS BALANCE IS”; 30 INPUT B 40 PRINT “LIST DEBITS” 5@ INPUT D 60 IF D<@ THEN GOTO 96 70 LETB=B-D 80 GOTO 50 90 PRINT “LIST CREDITS” 100 INPUT D 110 IF D<@ THEN GOTO 140 120 LETB=B+D 130 GOTO 100 149 PRINT ‘‘;CURRENT BALANCE IS V”;B The crucial lines here are 60 and 110. To see how they work, you need to know that the sign ‘<’ means /ess than. So the condition D < 0 means ‘D is less than zero’. This isn’t a
number, so it doesn’t have a numerical value: instead it is a logical statement, and is either true or false (depending on whether D is less than zero, or not). For example:
3 <0 is false —7 <@ is true
31
A typical IF ... THEN statement will take the form: IF condition THEN command
If the condition is true, then the command is carried out. But if the condition is false, the program goes on to the next line. So line 60, for example sends the program to line 90 if D is negative, but to the next line, line 70, if D is positive.
Now let’s see how it works. It should be clear enough up to line 50. Let’s suppose you have three debits (outgoings of cash) of 15, 7, and 11 pounds (or dollars if you prefer—at the present rate they’ll soon be the same) respectively. On first being asked to input D you tell the computer the first one:
2-15
Since D < 0 is false it goes on to line 70 and line 80, which sends it back for another input at 50. So now you give it the second debit:
27 and after that the third:
211 but now it’s still hungry for an input:
? so you’ve got to do something. That’s where the D << @ comes in. Input a negative value, the obvious one being —1. Now it goes to line 90, because D <0 is true. The whole process repeats now for credits (incoming cash); and the inputs end when you give it —1 again.
The use of a nonsensical input value like —1 to control a branch is a common trick: we
say that —1 acts as a delimiter because it signals ‘end of input list’ to the machine.
Meanwhile lines 70 and 120 have deducted debits and added credits, so the final balance is calculated correctly.
Project 1
Write a program to add up the prices in a shopping list, using a‘delimiter —1 to signal the end of the inputs.
Project 2
Write a program to input a number, and print out whether it is less than 100, equal to 100, or greater than 100. (Hint: > means ‘greater than’.)
ORDER RELATIONS ON NUMBERS
There are a whole lot of symbols to decide if one number is larger than another, or the same, or different, or whatever. Here’s a complete list, with examples.
= Equal (3 = 3 true; 3 = 4 false). Greater than (3 > 2 true; 3 > 4 false).
< Less than (3 < 4 true; 3 < 2 false).
<> Not equal (3 < > 2 true; 3 < > 3 false).
>= Greater than or equal (3 > = 3, 3 > = 2 true; 3 > = 4 false).
<= Less than or equal (3 < = 3, 3 << = 4 true; 3 < = 2 false). LOGIC
The command words AND and OR can be used to combine conditions. If c and d represent conditions, then c AND d is true provided both c and d are. So:
X >@ AND X <3
is true only when X is greater than @ and also less than 3. For whole numbers X this means X must be | or 2; for decimals (which I’ve not discussed yet) it allows rather more possibilities.
In the same way c OR d is true provided at least one of c and d is (perhaps both). So:
X<5ORX=5
means the same as X < = 5 Finally, I should mention the logical command:
NOT
which changes true to false, and vice versa.
CONDITIONAL JUMPS
One common use of IF ... THEN is to redirect the program to a new line, like this:
830 IF X = Y THEN GOTO 990 840 whatever...
This is called a conditional jump. On the Oric it may be shortened to: 830 IF X = Y THEN 9906 (that is, the GOTO can be left out).
CONDITIONAL ASSIGNMENTS
Another use is to give a variable different values according to the truth or falsity of a condition:
899 IF X = Y THEN LET K =77
900 IF X<>/Y THEN LET K = 99
which makes K be 77 if X = Y and 99 if not. The LET can as usual be omitted:
890 IF X = Y THEN K =77 900 IF X<>Y THEN K = 99
Project 3
The Sales Tax levied on an article in Oric Country, Tangerinia depends on its tax code as follows:
Code 1 (Educational) 2% Code 2. (Children’s goods) 5% Code 3. (Government use) 0% Code 4 (The rest) 15%
Write a program which accepts as input the code number and prints out the percentage rate of tax.
ELSE
It’s a nuisance having to use two IF ... THENSs to set up two actions: one if a condition is true, the other if it is false. Oric BASIC has an extension of IF... THEN which is much more efficient in such cases. This is the command:
IF (condition) THEN (action 1) ELSE (action 2) 33
34
For instance, lines 890-900 on page 33 can be compressed into: 900 IF X = Y THEN K =77 ELSE K = 99.
Here we have:
Condition X=Y_ (logical statement, either true or false) Action 1 K =77 (command) Action 2 K = 99 (command) If the condition is true then action | is taken; if it is false, action 2 is taken instead. That is,
if X = Y then action | sets K = 77; and if X <> Y then action 2 sets K = 99. Figure 8.1 shows the ways that IF... THEN and IF... THEN... ELSE operate.
True
True
False
False
IF ... THEN IF ... THEN ... ELSE Figure 8.1 Comparison of flow of command in IF... THEN and IF... THEN... ELSE.
ANSWERS Project 1
10 CLS
20 PRINT “SHOPPING LIST” 30 INPUT X
40 IF X <@ THEN 70
5@ SUM =SUM + X
60 GOTO 30
70 PRINT “TOTAL IS V”; SUM
Project 2
10 CLS
20 INPUT N
30 IF N < 100 THEN PRINT “LESS THAN 100”
40 IF N = 100 THEN PRINT “EQUALS 100”
5@ IFN -> 100 THEN PRINT “GREATER THAN 160”
Project 3
10 20 30 40 50 60 70
CLS
INPUT “TAX CODE?”; TC
IF TC <1 OR TC > 4 THEN 20
IF TC = 1 THEN PRINT “2% EDUCATIONAL RATE”
IF TC = 2 THEN PRINT “5% CHILDRENS RATE”
IF TC = 3 THEN PRINT “0% GOVERNMENT RATE”
IF TC = 4 THEN PRINT “15% — TOUGH LUCK MATE!”
(Just for fun, I’ve mug-trapped at line 30, that is, protected against nonsensical inputs.)
35
The first refinement in communication: how to control the positioning of the computer’s screen display.
9 Plot Positions
When in TEXT mode (which is all I’ve used so far) the TV screen is divided up into 27 rows of character cells. Each row is 40 cells long, and each cell can hold one character. The layout is shown in Figure 9.1. The rows are numbered 0-26 and the columns @-38 as shown. The column in front of column 0 is always reserved by the computer for its own use (it sets the background colour), and in TEXT mode so is column @ (for the foreground colour). So for now I'll pretend that only columns 1-38 are accessible to us. (Row @ is not reserved by the system in any special way.)
Reserved
=
Column numbe' 1
177 T | PLOT 16,19, ‘'B’’
s | EEE EEE EEE EEE EEE EEL eo
| | | 23H Siefetesszerenenerere 2st { {|
26P TTT TTT Tree eee eee ee |
Figure 9.1 TEXT and Low-resolution screen format. Three PLOT positions are marked.
When text is printed to the screen, each character (including spaces) occupies one of these cells. So a program listing: 10 REM TEXT DISPLAY 20 PRINT “ORIC”; 30 GOTO 20
is placed on the screen as in Figure 9.2. 36
Reserved columns
PT efoy [efefmy rfetx{r] [ofits |e |e Jal pee] Pere Ny Pel Riel) oa
{stot fefolrfo] |2jo] | | tT
Figure 9.2 How a program listing is positioned on the Text Screen.
I’m going to call the layout in Figure 9.1 the Text Screen. The key to neat displays is the command:
PLOT C, R, “STRING” which writes the sequence of characters ‘STRING’ starting at the cell in column C, rowR. (HINT: to remember the order, remind yourself that Column precedes Row in the alphabet.) For example: 10 CLS 20 PLOT 10, 17, “‘£” 30 GOTO 30 (to fool the error-message demon)
will plot a £ sign in column 10, row 17. And:
10 CLS
20 PLOT 10, 17, ‘‘£1,000,000”
30 GOTO 30 will print out £1,000,000 with the £ sign in the same position.
Now try this.
10 CLS
20 FOR X = 1 TO 26 (See Chapter 10 for details)
30 PLOT X, X, “‘£1,000,000"
40 NEXT X
50 GOTO 50 Here the million pounds (salute when you say that!) gets printed out in a diagonal line down the screen. That’s because, as X goes from | to 26, obeying the FOR... NEXT instructions (see Chapter 10), the PLOT position goes 1, 1; then 2, 2; then 3,3... to 26, 26. And those positions run diagonally down the screen as in Figure 9.3.
If you want to obtain a particular format on the screen, all you have to do is sketch on the Text Screen Grid (Figure 9.1) the positions you want things to be printed in; and then use PLOT with the corresponding entries. For instance, to draw a cross of asterisks in the positions shown in Figure 9.4, you read off from that figure:
10 CLS
20 PLOT 16, 6, ‘“‘*” 30: -PLOT: 15,.7,.“***" 40 PLOT 16, 8, ‘*”
5@ GOTO 50 37
38
Calumn ————»>
1 2 3 26 | ! I * I | | | ! Row 1—--- 1,1 | | i 3 ! 2--------- 2:2 | I ! | See tee 3,3 | | I I I I I I I I
26—-—-—-- ---— ee ee ee ee ee ee ee 26,26 Figure 9.3 PLOT X, X runs diagonally. Columns (ncn E Rr 15 16 17
Figure 9.4 Layout for a cross made of asterisks.
Project 1
Print a block of four stars so that its top left corner is in the fifth row and third column, as in Figure 9.5.
Project 2
Choose a position near the middle of the screen and print a square frame of ‘$” signs like this:
RPRARAH PR AF RPRAAH
Figure 9.5 Block of four stars for Project 1.
THE MOVING ZIT
We now present a Computer Classic, the basis of many of the early arcade video games, and an excellent introduction to moving graphics and the use of branch commands. Start with this:
10 CLS
20 C=1:R=3
30 H=1:V=1
40 PLOT C,R, “#”
56 C=C+H: R=R+V
60 IF C=1 ORC = 38 THEN H = -H 70 IF R=@OR R= 26 THEN V =-V 86 GOTO 40
When you RUN this, a line of ‘#’ signs will grow across the screen at a rapid pace, bouncing off the edges. The bounce effect is produced in lines 60 and 70. The idea is that C, R is the current position of the moving zit #, and H, V are the changes to be made in C and R for the next position (H for horizontal, V for vertical). To begin with H and V are 1, so the zit moves down and to the right; but every time it hits an edge, either H or V reverses direction (see Figure 9.6).
The illusion of motion is fairly strong, but spoilt by the trail of zits left behind. To improve the illusion, we can erase each zit once the next has been plotted. First we have to remember its position:
45 C@=C:RO=R
Then, when C and R change in line 50, CO and RO do not. Having plotted the new zit in line 40, we erase the old one somewhere: a good place (delay the erasure as long as possible to give a less flickering picture) is at line 75:
75 PLOT CO, RO, “V”
Away she goes!
Instead of a single zit, let’s have a worm, made up of four zits ina row. You can achieve this by putting in a sort of ‘delay line’ where the PLOT position for erasure is passed down the line one stage each time, until finally it gets acted upon. Delete line 45 above; and replace it by:
39
42 44 46 48
CO = C1:RO= RI Cl = C2:R1 = R2 C2 = C3:R2 = R3 C3 = C:R3 =R
If you can work out how the delays do their job, you’ll have no trouble at all with:
Project 3
Replace lines 42-48 by seven lines that produce a 7-zit worm.
You haven’t heard the last of PLOT, by any means: it can produce colour too! See Chapters 12, 19.
Figure 9.6 First stage of the Moving Zit.
ANSWERS
Project 1 10 20 30 40
Project 2
10 20 30
40
CLS
PLOT'3;5, °**" PLOT 3, 6, ““**” GOTO 40
CLS PLOT 18, 11, “$$$$” PLOT 18, 12, “$V V$”
40 PLOT 18, 13, “$VV$” 50 PLOT 18, 14, “$$$3” 66 GOTO 50
Project 3 Delete lines 42-48 and add:
41 CO=CI:RO=RI 42 Cl =C2:R1 = R2 43 C2 =C3:R2 = R3 44 C3 =C4:R3 = R4 45 C4=CS:R4 = RS 46 C5 = C6:R5 = R6 47 C6=C:R6=R
Obviously there ought to be a neater way to achieve this, by making the computer do all the work. See Chapter 21 on Arrays.
41
A fundamental programming technique gets the computer to carry out a given task over and over again. Better still, it
can make regular changes to the task as well. Examples include multiplication tables and displaying rectangles.
10 Looping
In this chapter I say more about the FOR . .. NEXT command (used in Project 2 Chapter 4) which tells the machine to perform a given task several times over. This wouldn’t be very exciting, if the task were absolutely fixed; but it is possible to make some of the details of the task change at each step. The result is a very powerful addition to the programmer’s elbow. I also discuss an alternative, REPEAT ... UNTIL.
Feeling in an educational mood, I suggest you try out the following program. I'll explain it after you’ve done so.
MULTIPLICATION TABLES
10 CLS
20 PRINT “SEVEN TIMES TABLE” 30 PRINT
40 FORN=1TO12
50 PRINT N; “XV7V =V”";7*N 60 NEXTN
RUN this: if you haven’t made any mistakes, pretty quickly you should get:
1X7=7 2X7=14 3X7=21 4X7=28 5X 7 = 35 6X7=42 7X7=49 8X7 =56 9X7=63 10X7=70 11X7=77
12 X 7 = 84
HOW THE LOOP WORKS
This technique is known as a Joop. The loop starts with the FOR command in line 40, and ends with the NEXT command in line 60. As well as this, we have to set up anumber N to act as a counter, and tell the machine where to start counting (1) and stop (12). All this is done in line 40:
FOR (start loop here)
N (use N as counter) =1 (start value for N) TO (carry on as far as) 12 (finish value for N)
What happens is this. When the computer first encounters the loop it sets N equal to the start value (1) and carries out the commands until it hits NEXT. It then compares N with the finish value (12) and if N is less than this it increases N by 1 (to get 2) and goes back to the start of the loop, doing the commands all over again. On next meeting NEXT it compares again, and increases N to 3; then to 4, 5, 6,... until N becomes 12. When it hits NEXT and finds that now N has reached the finish value of 12, it leaves the loop and carries on to the next program line (if there is one) or stops (if not).
I'll go through this in detail in a second, but first a word about line 50. This is just a series of PRINT commands strung together, and it produces displays like:
1X7=7
Its spaces V are just to make the result look pretty. This particular display comes when it has the counter N set to value 1, and it arises like this:
PRINT N PRINT 1 1
2 don’t move on
“x V7IV=V” PRINT “X V7V=V” 1X7= : don’t move on
7*N PRINT 7 * 1 (which is 7) 1X7=7 (no semicolon) move on to next line
Note the use of PRINT N without quotation marks. If you write PRINT “‘N” then it just prints out the single /etter N. If the quotes are left out, it prints out the numerical value assigned to N. Since N starts at 1 and increases step by step to 12, the PRINT Ncommand has the effect of printing the numbers 1, 2, 3,..., 12, depending on the stage in the loop. Similarly 7 * N takes the values 7 * 1 =1,7*2=14,...,7* 12=84;so0 these numbers are printed in turn too. Now we can run through the program in sequence and see how it achieves its result.
10 CLS Clear the streen.
20 PRINT “SEVEN TIMES TABLE” SEVEN TIMES TABLE
30 PRINT Print a blank line to leave a space below the heading.
40 FORN=1 TO 12 Set up loop with N as
counter and ranging from 1 (start) to 12 (finish).
50 PRINTN; “X V7 V=V";7*N 1X7=7
60 NEXTN Is N = 12? No, it’s 1. Add 1 toN to get 2, and go back to line 50.
43
44
5@ PRINTN; “SX V7V=V";7*N 2X7=14
60 NEXTN Is N = 12? No, it’s 2. Bump it up to 3 and go back to 590. Continue this process .. .
60 NEXTN N is now 12, so exit the loop. There are no more commands: STOP! Project 1
Change lines 20 and 50 so that the computer prints out:
1. A five times table; 2. A nine times table; 3. And for the ambitious, a ninety-nine times table.
(Hint: change those 7s to 5, 6 or 99.)
LOOPING PRINT STATEMENTS
By combining loops with PLOT commands, a variety of effects can be obtained. For example, suppose we want to draw a vertical line of nine stars, starting from row 2 of column 5 and going downwards. Then all we need do is: 10 CLS 20 FORR=2T0O 10 360 PLOT R, 5, “*” 40 NEXTR 56 GOTO 50 Here we use the row number R as a counter and print everything in column 5. Using a fixed row and a variable column gives a horizontal line: 10 CLS 20 FORC=2T0O 10 30 PLOT 5, C, “**” 40 NEXTC 50 GOTO 50
Changing both row and column will give a diagonal line:
10 CLS
20 FOR K =1 TO 13 3@ PLOT K, K, “*” 40 NEXTK
5@ GOTO 50
Project 2 Combine the techniques for drawing horizontal and vertical lines to put a frame of stars
round the outside of the screen but placed one space in from the edge (thus leaving a blank frame round the very outside).
LOOPING THE LOOP
By placing loops inside other loops, more complex effects can be achieved. Suppose we want to draw a rectangle, seven spaces wide and five spaces high, made up of ‘$’ signs. For definiteness let’s put the top corner in row 3, column 4.
Each row of the rectangle is a line of characters, which we can draw using a loop as above. Then we need to draw a series of such lines to get the whole rectangle; so we use another loop.
Let’s build it up slowly. To draw a horizontal line of length 7 in row R, starting at column 4 (and so ending up at column b@) we would use:
100 FORC=4TO 10 110 PLOT R, C, “‘$”; 120 NEXT C
You could use FOR C = 1 TO 7; but then line 11@ has to be PLOT R, C +3, “‘$’’). Then to draw several lines, with R running from 3 to 7 (fora height of five) we’d need something like this:
5@ FORR=3TO7
(draw line in row R) 156 NEXTR
Now we know what commands will do the ‘draw line in row R’: they are lines 100-120 above. (I’ve chosen line numbers so that everything fits together at the end.) So the guts of the program will be this:
5@ FORR=3TO7 100 FORC=4TO 10
110 PLOTR,C, “$” inner outer — loop loop
120 NEXTC
150 NEXTR
That’s essentially it, although to keep it tidy you should do the usual:
10 CLS 200 GOTO 200
SOME DAY YOUR PRINTs WILL COME
S] 20 Ys XeKex
| 3@ NEXT X \140 PRINT X,Y
46
Notice that the line numbers aren’t especially tidy; no matter, the Oric doesn’t care. Observe that the way we built this up leads to the whole of the inner loop being between the ends of the outer one. That is, the FORs and NEXTs end up in the order:
FOR C FORR ‘
inner outer a loop loop NEXT R NEXT C
This is important, and the computer will not do what you expect if you get the last two in the wrong order.
Project 3
Overlap two rectangles to draw a cross of Hs shaped like this:
x
x Trrtrctcrtid rroctrtaid
x
x
STEP SIZE
When you write a command like: FOR R= 3 TO 14 The Oric assumes that it should count up in ones: 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14. But you can change this size by using the command STEP. To count up in twos you would type: FOR R = 3 TO 14 STEP 2 and it would give R the values: 33557-9511, 13
in turn. (It stops there, because the next, 15, would be bigger than the limiting value 14 in the command. It does not set R equal to the value 14 at all. However, if you’d written:
FOR R = 3 TO 15 STEP 2 it would give R the values: 3,°5,. 7; 911,13, 15 and the top value 15 in the FOR command would be reached.)
Project 4
Change line 40 of the SEVEN TIMES TABLE program so that it only prints out multiples of even numbers by 7.
Project 5 Like Project 4, but just the odd numbers. You can even count backwards by using a negative step size:
10 CLS 20 FORI=10TO9® STEP -1 30 PRINT I 40 NEXTI 5@ PRINT ‘WE HAVE LIFT-OFF!” Short cut’ In any NEXT command, the loop counter can be omitted. That is, you can
write just NEXT instead of NEXT I or NEXT R or whatever. This saves space, but you may lose track of which NEXT is which. (The computer, however, will not!)
REPEAT UNTIL
There is a different way to produce a loop, which is often clearer. It applies especially to cases where the number of times round the loop may depend on things that happen inside the loop.
Here’s a game you can play against a friend on the computer. You take it in turns to input ‘a number between | and 5: the first person to take the total over 99 /oses.
There are two loops involved. One checks the input to make sure it’s between | and 5, and if not, asks for it again. The other adds the input to the total, and checks if that’s over 99. If so, the program stops.
You can’t really do this kind of thing with FOR... NEXT: you don’t know how long the loops will go on for. The best you could do is something like this:
10 SUM = 0 (why can’t I use TOTAL?) 20 FOR T=1TO 100
30 INPUT D fs 40 IF D<1ORD>5 THEN 36 he 50 SUM=SUM+D
60 IF SUM <= 99 THEN 20
70 NEXT T
80 PRINT “YOU LOSE”
outer loop
But it’s bad practice to jump out of a FOR... NEXT loop using (a tacit) GOTO as in line 60. It leaves unwanted junk lying around inside the computer’s memory. And we only get away with it at all because we know that the loop is bound to terminate in at most 100 cycles. The other ‘loop’ in lines 30 and 49 might go on forever, so there’s no way to use FOR ...NEXT: instead we use (a silent) GOTO in line 49.
More proper, but far from satisfactory, is a method using only GOTOs:
10 SUM=90 20 INPUT D } innee 30 IF D<1ORD>5 THEN 20 loop
outer loop 40 SUM=SUM+D
5@ IF SUM < = 99 THEN 20
60 PRINT “YOU LOSE” 47
48
It’s easy to get lost among the (yet again silent) GOTOs in lines 30 and 5@. In fact GOTOs are somewhat frowned upon in polite (i.e. ‘Structured Programming’) society, because of this. (Actually, GOTOs can be used ina civilized way, so it’s best not to get too snobbish about them.) With REPEAT . .. UNTIL, all is sweetness and light:
10 SUM=80
20 REPEAT
30 REPEAT
49 INPUT D oa.
loop outer loop
5@ UNTIL D>=1ANDD<=5
686 SUM=SUM+D
70 UNTIL SUM > 99
80 PRINT “YOU LOSE”
Note the format:
REPEAT (series of program lines defining the action to be repeated) UNTIL (condition) which ensures that the action so defined is repeated until the stated condition is true.
Figure 10.1 shows in diagrammatic form the essential structures of FOR... NEXT and REPEAT ... UNTIL loops.
Start counter Increase counter Finished?
Yes
REPEAT
False
No
condition?
FOR ... NEXT REPEAT ... UNTIL
Figure 10.1 Comparison of flow of commands in FOR... NEXT and REPEAT... UNTIL loops.
ANSWERS
Project 1
1. 20 50
2. 20 50
3: 20 50
Project 2
10 20 30 40 50 60 70 80 90 100 110 120 130 140
fj
Project 3
10 20 30 40 50 60
PRINT “FIVE TIMES TABLE” PRINT N; “X V5 V=V";5*N
PRINT “NINE TIMES TABLE” PRINT N; “X V9 V=V";9*N
PRINT “NINETY-NINE TIMES TABLE” PRINT N; “X V 99 V=V";99 *N
CLS
FOR C = | TO 37 PLOT’, 1, ***” NEXT C
FOR C = | TO 37 PLOT C, 25, ‘**” NEXT C
FOR R = 2 TO 24 PLOT’ 1;:R, °°?" NEXT R
FOR R = 2 TO 24 PLOT 37, R, “*” NEXT R
GOTO 140
top line
bottom line
left side
right side
CLS
NEXT C
FOR R= 3 TO 8 FOR C = 20 TO 21 PLOT R, C, “‘H” first rectangle NEXT R
49
50
70 80 90 100 110 120
Project 4 40 Project 5 40 or
40
FOR R=5 TO 6
FOR C = 18 TO 23
PLOT R, C, “‘H” second rectangle NEXT C
NEXT R
GOTO 120
FOR N = 2 TO 12 STEP 2
FOR N = 1 TO 11 STEP 2
FOR N = 1 TO 12 STEP 2
(Either line works. Don’t forget to include all the other lines as before, though!)
It is said that the colourful term ‘getting the bugs out’ arose in the early days of computing, when insects used to crawl inside the machine and cause short circuits. Nowadays, if the computer goes wrong, it’s usually the programmer’s fault. But to put it right, you still need to know about...
li Debugging |
You should never be discouraged when a program doesn’t work correctly the first time you run it. Even for professional programmers, it hardly ever does!
So it’s important to have at your command techniques which will help you find the errors in a program quickly and easily. That’s what we call debugging.
SYNTAX ERRORS
To start with, let’s examine the kinds of errors which will come to light first when you runa program. For instance, suppose somewhere in a program you write:
5@ FORN=1-7
forgetting that you have to use ‘TO’ to separate the values in a FOR loop. Now the Oric will be happy to accept this when you type it in, but when the program is run, you’ll get the message:
ISYNTAX ERROR IN 50
In other words, the Oric doesn’t like the grammatical construction of the statement in line 50. It’s rather as if I said “‘Oric, him not understand this statement’’. You’d object to my syntax! The only difference is that you can make sense of my ungrammatical offering, but the Oric won’t try to make sense of line 50. It will simply throw it out, as we’ve seen.
Particularly when you’re learning a computer language, you’re likely to make quite a few errors of this kind, and it’s very annoying to type in a sixty-line program containing ten FOR statements, only to be told when you run it that you’ve remembered the construction of a FOR statement wrongly, and you’ll have to alter all of them. So you should make a habit of typing RUN after every couple of lines you enter. Of course, uncompleted programs probably won’t behave sensibly, and you may even get error messages which will go away when the next bit has been typed in, but at this stage you're only interested in finding the syntax errors before you’ve perpetrated too many of them.
CHOPPING AND CHANGING
Having identified the error, you need to alter the statement. Of course you can always delete a whole line by just typing the line number, followed by RETURN, and you can replace one completely by just typing the new line. However, to do all editing this way would be pretty tedious, particularly if there are quite a few longish lines to be hacked about.
The Oric provides you with a powerful tool which can be used for editing program lines, among (as we shall see) other things. To use it effectively, you must understand clearly the way in which data is transferred from the keyboard to the Oric’s memory. See Figure 11.2.
When a key is hit, the symbol on it is transferred to a special chunk of memory called the input buffer, and, at the same time, it is displayed on the screen. It does not, at this stage,
51
52
get passed on to the Oric’s main memory. That only happens when a whole line has been assembled in the buffer. And how does the system know when this has happened? Because you hit RETURN to tell it!
Figure 11.1 Positioning the cursor using CTRL/A during an edit.
So the input buffer is filled until the Oric seesa RETURN from the keyboard. Then, the whole buffer contents are shovelled to main memory and stored or acted
upon—depending on whether the symbols passed on represent a program line or a command (or, come to that, data).
Input buffer
Keyboard
Main memory
Screen
Figure 11.2 Keyboard to memory data transfer.
The eagle-eyed will have noticed that there seems to be another way of getting data into the input buffer—from the screen! (See the dotted line in Figure 11.2). This is indeed possible—all you have to do is hit CTRL/A (hold the CTRL key down and hit A at the same time) and a character will be copied from the screen to the input buffer. But which one? Well, it would make sense to make use of the cursor, and that’s exactly what happens; it’s the symbol at the current cursor position that is copied to the buffer. CTRL/A has a second effect, which is to move the cursor one character position right.
ADDING TO THE END OF A LINE
Now let’s make use of this information. We’ll start by adding a REM to an existing line; so that we might have:
230 IF B>6 THEN PRINT “No Good” and want to clarify things with: 230 IF B>6 THEN PRINT “No Good’’:REM B RANGE IS 1-6
First, make sure that line 230 (original version) is somewhere on the screen. If it isn’t type CTRL/L (to clear the screen) and then LIST 230. Now use the cursor keys to position the cursor over the ‘2’. Use CTRL/A repeatedly to transfer the characters in the line to the input buffer until the cursor is one position after the closing quote marks. Now type in:
:REM B RANGE IS 1-6
and hit RETURN.
What you’ve done is to combine characters coming from the screen with characters coming from the keyboard, in the input buffer. You can do this in numerous ways and nothing will be transferred into main memory until you hit RETURN. Here are some other examples.
CHANGING A LINE NUMBER
You’ve got the line: 115 IFA<7ORB> 10 THEN X= X * X:P=P+1
and you realize it should be line 1150 instead. Correct it like this:
Type 1150 (but don’t hit RETURN). Now position the cursor over the ‘I’ of ‘IF’. Use CTRL/A to move the rest of the line into the buffer, where it will join the 1150 already there. Finally, when the cursor is past the ‘1’ at the end of the line, hit RETURN.
It’s always worth checking that an edit has done what you intended by typing CTRL/L and then LIST. Do so now. Line 1150 is there all right but, of course, you haven’t overwritten line 115 so that’s still there too! There are occasions when you want identical, or at least, very similar lines in a program, and this is a useful technique then, but in this example you would have to get rid of line 115 by typing 115 and then RETURN.
DELETING PART OF A LINE
Suppose you have an initialization line: 10 P=1:N = 20:R = 0:Z = 0:M=@:A = 4
and during the program’s development, you realize that N and R do not need to be set up at this stage, so you’d like the line to read:
1@ P=1:Z=0:M=0:A =4 Position the cursor at the beginning of the line, as usual. Transfer: 10 P=1: to the buffer using CTRL/A. Now use the cursor right (—) key to skip over: N = 20:R = 0:
When the cursor is over ‘Z’ use CTRL/A again to transfer the other characters to the buffer, and finally hit RETURN.
ALTERING CHARACTERS
The line: 240 IF A=4 THEN FRED = 26
53
54
should read: 240 IF A= 4 THEN BERT = 20
(No, I don’t know why, either! Maybe because FRED is illegal—why?)
Set the cursor to the beginning of the line and transfer characters to the input buffer using CTRL/A until the cursor is over ‘F’. Type ‘BERT’. These letters will, of course, be transferred to the input buffer, but, because of the cursor position, you will also see them overwrite ‘FRED’ on the screen. (This is, to all intents and purposes, coincidental, and it is important not to think about the editing process as taking place on the screen, even though, in this one case, it looks like it.) The cursor is now over ‘=’ so three more CTRL/As will transfer the ‘= 20’, and then you can hit RETURN.
ADDING CHARACTERS WITHIN A LINE
Suppose that our line 240 above is to be altered from FRED to BERTRAM instead of just BERT (again, for reasons of less than total clarity).
Now, with the experience of the last example behind you, it should be apparent that there’s a nasty problem here, because if you proceed as before, the ‘RAM?’ will overwrite ‘= 20’ on the screen so that these characters are no longer available to be transferred to the buffer. Of course, you could retype ‘= 20’ but this could be a real nuisance if the line were longer.
You can deal with the problem like this. Go as far as inserting ‘BERT’ as before, so the cursor is now over ‘=’. Now move the cursor to another line. It doesn’t matter where, as long as it’s no longer interfering with the line You’re trying to edit. Usually, a convenient spot is one line up. Type ‘RAM’. This will, of course, appear in the input buffer. Now use the cursor keys to return to the ‘=’ sign, and transfer the ‘= 20’ using CTRL/A. Finally, hit RETURN, as usual.
You will probably have messed up the screen display during this process by overwriting a chunk of some poor unsuspecting line with the letters ‘RAM’. Don’t worry; you have done no harm. Never forget that it is only what is in the input buffer that can be transferred to main memory, and as I’ve said before, you mustn’t think of the Oric as having a screen editor—it hasn’t.
To convince yourself of this type CTRL/L and LIST.
THIS IS A HOLD -UP DO NOT MAKE ANY
SUDDEN MOVES
ORIC’S DATA PARTY TRICK
At the beginning of this chapter, I remarked that the ‘copy screen to buffer’ feature provided by CTRL/A had uses outside editing. Here’s one.
You’ve written a program which inputs some numbers and does something with them (it doesn’t matter what) like this:
10 INPUT A 20 IF A=@ THEN PRINT P:END es (processing)
100 GOTO 10
Now you want to test it, so you type something like:
RUN
2 7,38
? 12.46 ? 8.1012 ? 21.604 20
(Of course, it’s the Oric which generates the question marks). Anyway, the wrong answer is displayed, and you realize it’s because you forgot to take out line 93 as you’d intended (or whatever). So you’ve got to do the edit, rerun, and type in all the data again.
Or have you? Provided the data is still on the screen, you can use CTRL/A to copy it to the buffer, and when you hit RETURN, the Oric accepts it, neither knowing nor caring that the data came from the screen rather than the keyboard! So you can use the cursor keys to place the cursor over the ‘R’ of ‘RUN’, hit CTRL/A 3 times followed by RETURN (see, you don’t even have to type RUN) after which the Oric will generate a question mark which will overwrite the first one already on the screen, and move the cursor over the 7. Hit CTRL/A 4 times and 7.38 goes to the buffer. Hit RETURN and it’s passed to main memory. The Oric will generate the next question mark, leaving the cursor over the ‘1’ of ‘12.46’ and so on and so on.
Pretty sneaky eh?
55
56
Like the early days of the cinema, the simplest computer programs are silent black-and-white productions. But with a few extra commands you can add:
I? Sound and Colour
Deep in the caverns of Pluto, hordes of little green and purple monsters are stealthily sneaking up on you: graunch, graunch, graunch.. .
Yes, well. At the moment they will have to be little black monsters, preferably bearing a remarkable resemblance to an Oric keyboard character; and so stealthy will be the sneaking that you won’t hear a thing. We can improve the attractiveness of our programs tremendously by adding colour, sound and some interesting graphics. In this chapter I’m only going to do the easy stuff, and I don’t apologise for that: the first thing is to get used to handling sound and colour without having to think too hard about fine details. Later chapters (19, 22, 26) carry the story several stages further; but I have to stop somewhere because this book just isn’t big enough to hold everything I’d like to tell you.
SOUND
The Oric has a special chip dedicated to the production of sound effects. Four of these are accessible from BASIC using the commands: EXPLODE PING SHOOT ZAP which are fairly self-explanatory. Try them as direct commands: now apologise to the cat and help it down off the curtain-rail. There’s one point to take care of when using these commands. To appreciate the difficulty, take a look at this program and decide what the result ought to sound like. 1@ EXPLODE 20 PING 30 SHOOT 40 ZAP 5@ PRINT “FINISHED!” Well, it ought to string the four sounds together, one after the other. Try it out and listen. That’s quite odd, isn’t it? It’s as if each sound effect except the last ZAP is being snuffed out before it has a chance to get going. And that’s exactly what’s happening. Whenever you ask for a sound effect the sound chip stops whatever it’s currently doing and starts
doing what you’ve asked for, even though it may not have finished the previous sound effect.
The command to get round this problem is: WAIT
which should be followed by a number telling the computer how long to wait for. (I’ve used it occasionally already, without explanation, to delay the operation of the machine so that you can observe things that would otherwise change too rapidly.) The number N in:
WAIT(N)
produces a pause of N hundredths of a second. So: WAIT 100
gives a l-second pause, WAIT 200
gives a 2-second pause, and so on. Add the following pauses to the sound effects program:
15 WAIT 100 25. WAIT 100 35 WAIT 30 45 WAIT 30
and you'll be able to hear all four sounds. The WAIT times are about the shortest that will work satisfactorily, but you can experiment if you think you can do better. So:
EXPLODE and PING need a WAIT 100 (about | second) SHOOT and ZAP need a WAIT 30 (about 8.3 seconds)
if any other sounds are going to follow them. However, commands that don’t ask for sounds do not interfere with the sound chip, so you can often omit the WAITs. For more on sound, see Chapter 22.
COLOUR
You’ve seen a few examples of Oric colour, but not ina systematic way. Full control of the colour system takes a fair amount of practice so Ill start with the simplest ideas and work up. In TEXT (or LORES) mode, each character cell on the screen is assigned two colours, the background and the foreground. Sensibly, the commands that affect these (for the whole screen) are:
PAPER INK
These must be followed by a number between @ and 7, corresponding to the following colours:
Number Colour 0 Black 1 Red 2 Green 3 Yellow 4 Blue 5 Magenta (purple) 6 Cyan (light blue) 7 White
57
58
So the commands:
PAPER 4 INK 3
will produce yellow text (INK colour 3= yellow) ona blue (PAPER colour 4) background. Try them as direct commands; then type things on the screen to see the effect. Leave the screen uncleared, and type in:
PAPER 2 INK 0
You'll find that the colours change over the whole screen, but the text is otherwise unaffected.
Project 1
Write a program to display all eight colours, one after the other, as the PAPER colour ona clear screen—for long enough to be able to see the colours—say two seconds each.
You can use INK and PAPER commands in a program: every time you change the colours, they will change across the entire screen. NEW does not reset them to black-on- white, but RESET does.
DIFFERENT COLOURS ON THE SAME SCREEN
That’s fun, but not very impressive. It would be more interesting to ‘paint’ regions of the screen in different colours. And in fact this can be done, using what the Manual rather offputtingly calls seria/ attributes. Let’s take it one step at a time.
The main idea is that the PLOT command can be used to define colours as well as characters at a given position. Experiment with this:
10 REPEAT
20 INPUT T
30 UNTIL T>=0 ANDT<=7 40 PLOT 10, 12, T + 16
50 GOTO 10
This has a mug-trapped input for a number between @ and 7. Try each input in turn: what do you notice? Suppose for instance that T is 2 (the colour code for green). Then the whole of row 12, from column 10 onwards, turns green. I'll explain the T + 16 in line 4@ in the next section. What’s happening is this. A command like:
PLOT 10, 12, “X” produces a character X on the Text Screen. But a command: PLOT 16, 12, 18
produces a co/our—the exact colour depending on the number (here 18) in a way I'll explain later. The colour applies not only to the cell at 10, 12; it also affects the rest of that row. That’s what the word serial refers to. (The word attribute is explained in the next section, page 61.)
The colour change can, of course, be ‘turned off’ by another PLOT later in the same row. Try this:
PLOT 10, 12, 18 PLOT 28, 12, 21
Now you’ve got a stripe that starts green and turns magenta. Basically, that’s all you need to know, because careful selection of the PLOT points lets you set up any combination of colours you want. But there are two things to notice:
1. In TEXT mode, the paper colour for a row is set up in the reserved column to the left of column @. This is not accessible by the PLOT command. (It is accessible by a more subtle command POKE, but that’s a different kettle of fish entirely and I shouldn’t have mentioned it.)
2. Youcannot PLOT a character anda colour to the same character cell. If you PLOT a character to a cell that contains a colour, you wipe out that colour command.
The next program may make this clearer.
10 20 30 40 50 60 70 80
CLS
COL =90
FOR C = 6 TO 36 STEP 4 FOR R = @ TO 26
COL = COL + 1
IF COL > 7 THEN COL = 0 PLOT C, R, COL + 16 NEXT R
NEXT C
WAIT 300
FOR X = @ TO 26
PLOT X + 1, X, ““WHAMMO!” WAIT 50
NEXT X
Figure 12.1 A pattern of attributes...
59
60
Youll see the screen acquire a complicated pattern of colours. (Note ow the colours are painted in, always continuing to the end of their row at any given stage.) After a pause, the text goes in; see how the colours change whenever the text overprints a colour cell.
error Tae
Figure 12.2
Table 12.1
Code number
OMmAAIDMNAAHWNK BSB
. . and how overprinting text cancels them.
Attribute
Black INK
Red INK
Green INK
Yellow INK
Blue INK
Magenta INK
Cyan INK
White INK
Single height steady standard Single height steady alternate Double height steady standard Double height steady alternate Single height flashing standard Single height flashing alternate Double height flashing standard Double height flashing alternate Black PAPER
Red PAPER
Green PAPER
Yellow PAPER
Blue PAPER
Magenta PAPER
Cyan PAPER
White PAPER
Ignore—may affect screen synchronization
ATTRIBUTES
Those of you who have been wincing at the word ‘colour’ throughout can relax. There’s a great deal more‘to it than that. The PLOT C, R, T command actually sets an attribute— something that governs the way characters get printed. This can be an INK colour, a PAPER colour, or something like a FLASHING or DOUBLE HEIGHT command (of which more later). The attribute numbers run from @ to 31. The Manual lists them in Appendix C, but in such an obscure way that I’ve given you a comprehensible list of the ones you may want to use in Table 12.1. For the alternate set and standard set of characters, see Chapter 19; for the use of double height characters see the next section. To see the effect of these attributes, try the following program with INPUTs of @-23 in turn.
Edge of Screen
G Mm V7 sae qc Dy Va Ze q YS) Vii Uf Heee | 3 ¢ F. +210 Ve a Py YY) ’, WZ G7) i ‘ey | le i a ta la Ve Zz = YW
D ra Z Gy il kh “| sl | AA Wil GA ad ed
v2] 7 ie
(Bale ih
— 2.
ct
White paper
Black ink
Green paper Yellow ink (a es ere CJ
Figure 12.3 How serial attributes work. The numbers are attribute codes, the letters and blanks illustrate the effect on the screen. There are three groups: (a) INK colour, (b) PAPER colour, (c) flash, double height, standard/alternate. An attribute applies along its row until
cancelled by one in the same group. The rows in the diagram exemplify different combinations.
Blue paper
Flashing
61
62
1@ CLS 20 REPEAT 30 INPUT T 40 UNTIL T>=0 ANDT <= 23 5@ PLOT 20, 9, “HELLO” 60 PLOT 20, 10, “HELLO” 70 WAIT 200 80 PLOT 10, 9, T 96 PLOT 10, 10, T 100 PRINT CHR$(30) 110 PRINT SPC(1@) 120 PRINT CHR$(36) 130 GOTO 20 It’s assembled from ideas already explained, so you can work through the listing for yourself to see how it operates.
Note that while the INK attribute codes correspond to the usual colour codes, the PAPER codes are 16 larger. Hence the T + 16 in the previous section (page 58).
DOUBLE HEIGHT AND FLASHING
You may have wondered why the previous program printed out ‘HELLO’ twice. It was to show the double height features. Since any double height character stretches over two rows, you need to PLOT the attribute on both rows; and you print out the letters on both so that it has something to attribute itself to. In fact, on an odd-numbered row the double
THE GREAT SNAIL RACE
DOUBLE-HEIGHT DEN.
Figure 12.4 Demonstration of double height characters.
height attributes take the sop half of a character and stretch it; on the even rows they take the bottom half. You need both to get the full character; and the top row has to be one with an odd number. Try this:
10 CLS
20 INPUT “PHRASE TO BE DOUBLED”; T$
30 INPUT “DOUBLE HEIGHT ROW NUMBER”; DR 49 FORX=2* DR-1TO2* DR
5@ PLOT 1, X, 10
60 PLOT 2, X, T$
70 NEXT X
80 GOTO 86
Input ‘THE GREAT SNAIL RACE’ and then row number 6, for a test. This facility is especially useful for giving a program a nice ‘title page’.
The double height attribute is the 1@ in line 50. (The FOR .. . NEXT just gets the odd/even doubled lines right.) If you change it to 14, you'll find that the words flash, as well.
You can use PLOT @, X, 1@ in line 50; but your ink colour turns white if you do.
Project 2
Write a program that produces on the screen a series of coloured rectangular frames, one inside the other, shrinking down to the centre. Figure 12.5 shows the kind of thing. [Hint: think of this as a series of nested rectangular blocks, with the smaller ones painted over the top of the bigger: start with the bigger ones and recall that attributes are serial, so that in each row you need only to switch a given colour on, and then off at some later place, to get a rectangular block of colour.]
WVMC_CMHZ_TC@@CT@@@CHCT_T__=@_™=~CH_HCCCHC@T@XCHHC@CXT@_TC@CCTC=X@_CV@CCE@@TCEE00léllélly
MM
'?’™P>D[?$DV AAAI
Wy dcccdedeeccecccceecceccececcececcccccceccccccccdeccedeezze
SS
BDCDCE”K'W''W'WW«Wiéws JI
Dp cere enna \Y N | N
N
]GD$@.< QQ \I|J|DI i\\QQGMVMMVAMM
BD6CfDWCQKQKW MW
SS
Lid
y \N N N N \ Ee Ni N- VV N N \ N \s
YY a
G
dddedddddddddddddddddddddddddddddddddde eee”
\x
Figure 12.5 Nested coloured rectangles for Project 2.
63
64
ANSWERS
Project 1
10 20 30 40 50
Project 2
10 20 30 40 50 60 70 80 90 100 110 120
CLS
FOR P=@TO7 PAPER(P) WAIT 200 NEXT P
CLS
FOR K = 0 TO 13 COL=K
IF COL > 7 THEN COL = COL — 8 CP=COL- 1
IF CP<@ THEN CP=7 FOR R= K TO 26- K PLOT K, R, COL + 16 PLOT 38 — K, R, CP + 16 NEXT R
NEXT K
GOTO 120
Once you’ve got a program working, you can save it on tape and load it back later: Here’s how.
13 Using a Cassette Recorder
One of the first things you’ll want to do with your Oric is to run the demonstration program. To do so, you'll need to connect up a cassette recorder. The supplied connecting lead has two 3-pin DIN connectors, so unless you want to take one end to bits and replace it with 3.5mm jacks, you need a recorder with a DIN socket. Most (but by no means all) do, so be careful if you’re buying a new one for use with the Oric. I’ve tried three types with reasonable success:
Boots Audio CR 325 W.H. Smith CCR 800 Hitachi TRQ 295R
I say ‘reasonable’ success because, although each works independently, programs saved on one recorder do not necessarily load back successfully on one of the others. This probably won’t matter to you, but if you want to load something on a friend’s Oric it might be a good idea to take your recorder as well as the tape. The chances are that these problems arise because of slight differences in the azimuth adjustment of the recorder heads. If necessary, you can get a hi-fi shop to readjust this for you.
First, do a simple test. Connect the DIN cable to the recorder and the Oric. (The socket on the Oric is the one furthest from the aerial connector.)
Warning
Some recorders, the Hitachi among them, do not automatically disconnect the microphone when the DIN plug is inserted. In this case, you must insert a blanking plug (usually supplied for the purpose: if not, use a 3.5 mm jack plug without any leads) in the microphone (MIC) socket of the recorder.
CSAVE AND CLOAD
Now key in something quick and easy!
18 REM AAAAAAAA 20 REM BBBBBBBB 3@ REM CCCCCCCC until you’re fed up. (Don’t take very long to get fed up. If it doesn’t work you’re just wasting time.) Now type CSAVE“ FRED” but don’t hit RETURN yet. Start the recorder in RECORD
mode and make sure that magnetic tape (not just plastic leader tape) is winding on to the take-up spool. Now hit RETURN. You'll see the message:
Saving FRED
66
appear on the top line of the display and then a little later: Ready
When the ‘Ready’ prompt appears you can turn off the recorder and rewind the tape. Set the volume control to about three quarters full on. Type CLOAD ‘‘FRED”, hit RETURN and PLAY the tape. The message:
Searching ... will appear on the display top line. If all is well, this will be replaced rapidly by: Loading ... FRED
and then a ‘Ready’ prompt. Several things which can go wrong are:
1. The ‘Loading . . .” message never occurs. This is because the volume setting is probably too high. (Of course, it could be too low, but you have to get very low before the Oric fails to detect SAVEd information.)
2. The ‘Loading...’ message occurs but is then followed by a ‘FILE ERROR-LOAD ABORTED?’ message. This may be because the volume level is now. too low, or the heads need cleaning. Put the recorder in PLAY mode so that the heads are exposed, and polish them gently with a cotton bud soaked in head-cleaning fluid. Then use a dry cotton bud to polish them off. Also clean the rubber pinch-roiler in the same way, but be careful not to get the cotton bud close to the rotating capstan, or you may find the cotton unravelling round it, and it’s then a pain to get off. (In other words brush the cotton bud lightly against the pinch-roller to the right of the capstan.)
Another possibility is that the tape is poor quality, or has seen better days. In either case, the magnetic emulsion may have rubbed off in places and you can do nothing except resolve to use better tapes in future.
If the ‘Loading . . .’ message never occurs, you can hit the RESET button underneath the Oric and as your program will still be in the machine you can try again.
If you’ve gota FILE ERROR message, the Oric will have loaded the program up to the point where it noticed there was a problem. So you can LIST to see how much you’ve got, and, with luck, patch up the problem by adding the last few (optimistic!) lines.
It is also possible for the Oric to believe it has loaded a program correctly when it’s actually misread a line. I recently loaded a program, and on attempting to run it was immediately confronted with a syntax error message although the program had run perfectly before! On investigation, it turned out that a PLAY command had mysteriously become CIRCLE!
All being well, you should have squeaky-clean heads and a volume level which works. So now to the demo tape.
Type CLOAD “”’,S
hit RETURN and PLAY the tape.
If you don’t put anything between the quote marks (not even a space) the Oric will load the first program it comes across, whatever its name. (The name will not then appear in the loading message.) The ‘, S’ tells the Oric that the program has been saved at a slow speed (in fact, about 30 characters/second), and so it does not try to read it back at the normal speed, which is about 240 characters/second. The theory is that programs saved in ‘slow’ mode are likely to be read back more reliably than those in the normal fast mode, although I can’t say I’ve noticed the difference. If I have a loading problem, it’s usua!ly there, regardless of speed.
When there is more than one file on the tape you have to specify the name of the one you want between the quote marks. The Oric will then skip over unwanted ones. However, it doesn’t tell you what’s happening. The ‘Searching . . .” message remains until the appropriate file is found. This can be a little disconcerting if you’re not sure where a program is, or are worried about whether the tape is behaving itself.
The only way to provide yourself with some indication of what’s going on is to listen to the tape. Don’t do this via the loudspeaker unless you want burst eardrums. I leave a ‘deaf aid’ earpiece permanently connected to the external speaker socket of the cassette recorder.
67
68
Debugging I was about errors in ‘grammar’. But a statement may be perfectly grammatical, yet produce nonsense in a program.
4 Debugging ll
RUNTIME ERRORS
Although the Oric doesn’t actually tell you about syntax errors until you type RUN, 1. principle it could do so, because all it needs to do is scan a statement to see that something is wrong. But there are other kinds of errors which can’t possibly be identified until the program is run. These are called runtime errors.
Here’s a simple example:
10 FOR P=1 TO 20 20 N=5/(5- P) 36 PRINT N
40 NEXT P
Run this. You’ll find that it starts perfectly happily, and produces the values:
1.25 1.66666667 2.5
5
but then it generates an error message: ? DIVISION BY ZERO ERROR IN 20
So what’s gone wrong? Well, the message tells us that the Oric has found something fishy about line 20 and that reads:
20 N=5/(5-P)
Now, there can’t be anything wrong with the statement itself because it has already been executed four times to produce the four numbers listed above. So it has to be something to do with the value of P which is the only thing that is changing. Type ‘PRINT P’ (or, to make things quicker, you can type ‘?P’). The screen displays ‘5’.
So the machine is trying to work out:
oe Se
=) 0 and it can’t do that, because the result should be a number larger than any number you like to think of, and however big your Oric’s memory is, it still wouldn’t be able to hold it. So,
very sensibly, the Oric notices when you try to divide something by zero, and simply won’t attempt it, preferring to tell you that this is what has happened (by using the error code).
This error can crop up in much less obvious ways than this. How about this:
30 INPUT P,Q,R 40 A=(P+Q-R)/(5+(P— R)* (P— R)- 2*Q)
Try 7, 15 and 2 as values for P, Q and R and see! Project 1 What values would cause the ‘division by zero’ message in the following examples?
1 A=7/(B- C) 2, R=P+Q/(2* P— Q) 3. M=R+2/(R*R+R*R*R)
ANSWERS Project 1
You can get away with making all the variables zero in these examples, but other possibilities are:
1. Make B and C equal. 2. Make Q twice as big as P, e.g. Q=7, P=3.5. 3. Make R=~— 1.
You can always (and always should) prevent the message arising by including a test of your own. For instance, in doing example | above, you could write: 20 INPUT B,C 30 D=B-C 40 IF D=0 THEN PRINT “CAN’T DO THIS. TRY AGAIN”: GOTO 26 50 A=7/D
or:
20 REPEAT
30 INPUT B,C
40 D=B-C
5@ UNTILD<>@ 60 A=7/D
69
70
Even an Oric can be unpredictable!
IS Random Numbers
In some programs you want the computer to behave in an unpredictable way. The Oric has a command that will produce ‘random’ numbers, and you can use these when you want it to do something, but you don’t want to know in advance what it will do. This is especially useful in games: how many games can you think of that require the throw of a die or the drawing of a card?
The command for random numbers is:
RND
followed by a number in brackets. To get an idea of what this command will do, copy in and RUN the following program:
10 INPUT N
20 FOR T=1TO 10 30 PRINT RND(N) 40 NEXT T
5@ GOTO 10
First, input 1 for N. You get ten decimal numbers between @ and 1, with no obvious pattern. Try | again: you get more, still no pattern.
Now try @. You get the same number ten times; moreoever it’s the same as the last random number printed out when you used N = 1.
Now try —2. You get a number repeated ten times, but it’s not the same as anything that’s gone before.
In fact, the general result of RND(N) is this:
1. If N is positive, RND(N) generates random numbers between 0 and |. (@ may occur, 1 will not.)
2. If N is zero, then RND(O) gives you whatever random number was generated previously. (Sometimes useful to work out where youare, if the program isn’t storing the random numbers for you.)
3. If N is negative, RND(N) generates a particular ‘random’ number depending on N.
I suggest you ignore 3 altogether: it’s mostly useful for debugging, and is related to the actual process whereby the ‘random’ numbers are produced. (They aren’t really random, assuming that means anything; but the process that produces them is designed to give patternless results for most practical purposes.) In fact, the only command you'll ever be likely to need is:
RND(1)
and I’ll stick to that from now on.
DICE, CARDS, AND GAMBLING DEVICES
Hang on, there’s a knock at the door... No, Officer, Idon’t have a Gaming Licence... Well, since you insist, I’ll change the section title to:
CHANCE EVENTS
Pheew! Now, to business. When you throw a die it produces numbers between | and 6, at random. The Oric’s ‘die’ produces numbers between @ and 1, which may be decimals. Soa little mathematical jiggery-pokery (or, to maintain the gambling motif, piggery-pokery) is required.
Here’s a typical list of random Oric numbers (in the first column) together with what happens when you multiply by 6.
RND(1) 6 * RND(1)
131137465 .78682479 80924873 485549238
846447204 5.97868323 591965711 5.0492 1935 26800113 3.55179427
Now multiplying by 6 stretches the range of numbers 0-1 into 0-6. That’s a step in the right direction. The next is to get rid of those decimals. The command:
INT replaces a number by its integer part: the largest whole number not greater than it. For positive numbers this is the bit before the decimal point; for negative numbers it is | smaller. For instance:
INT(4.85549238) = 4
INT(—3.141592) = —4. If there’s nothing in front of the decimal point, INT gives 0 (for positive numbers). So if we take INTs of the right-hand column we get the sequence of numbers:
0645 5 3
which are almost right for die-throws. The only snag is they run from @ to 5 instead of | to 6. So we add 1:
15 6 6 4 and that’s just right. Putting it all together we get: INT(6 * RND(1)) + 1
which generates random whole numbers in the range 1-6, like a die. Project 1 What commands would you use to generate random whole numbers corresponding to:
(a) A pack of 52 cards?
(b) A single suit of 13 cards?
(c) A domino drawn from a full set of 28? (d) A birthday from a non-leap year?
(e) A number between 1@ and 99 (inclusive)?
71
72
FREQUENCY CHART
Here’s a program of vaguely serious intent: it throws a die 150 times and records how many times each number comes up.
10 PAPER @ 20 INK7 30 CLS 49 FORR=1TO6 5@ PLOT @, 3 * R, CHR$(48 + R) 606 NEXTR 70 FORT=1 TO 150 86 D=INT(6 * RND(1)) + 1 906 C(D)=C(D) +1 100 IF C(D) > 36 THEN STOP 110 PLOT C(D) + 2,3 * D, 16 120 PLOT C(D)+ 1,3* D, 16+ D 130 NEXT T 149 GOTO 140 The number of times the die has thrown a number 1, 2, 3, 4, 5, 6 is recorded in six variables C(1), C(2), C(3), C(4), C(5), C(6). I’ve cheated a bit because this list of variables is what’s called an array, and I’m not doing arrays until Chapter 21. No matter, the idea is clear enough. Lines 46-60 print out the numbers 1-6 ina column. The CHR$(48 + R) just generates the characters for 1-6, whose codes (see Appendix D of the Manual) are 49-54. Lines 70, 80, 130 throw the die 15@ times. Line 9@ increases the count for the given throw. Lines 110-120 use serial attributes to PLOT a block of colour on the screen in line with the number D. Line 10 just prevents the computer taking matters into its own hands if the PLOT position goes off the right-hand edge of the screen.
Note how the bars grow: although ona given run, one number may win, in the long run the wins even out. The Oric die is fair.
Project 2
Modify this program so that the computer throws two dice, each having only three sides (!) numbered 1, 2, 3 on one and 4, 5, 6 on the other; and adds the two scores. Do you expect the same results?
ANSWERS
Project 1
(a) INT(52 * RND(1)) + 1
(b) INT(13 * RND(1)) + 1
(c) INT(28 * RND(1)) + 1
(d) INT(365 * RND(1)) + |
(e) INT(90* RND(1)) +10 (Because 96 * RND(1) runs from @ to 89, so adding 10 gives the range 10-99. I got the 90 by counting the length of the range, 99 — 10 = 89 plus one on the end; then adjusted with the 10.)
You may have thought about doing the domino problem (c) by using INT(7 * RND(1)) to generate dots 0-6, with @ standing for a blank domino (half). Do this twice; but keep only those pairs M, N for which M<=N, otherwise you’ll get the non-doubled dominoes like BIé], twice, once this way and once as [63]; but the doubles only once, and that changes the probabilities.
Project 2
10 20 30 40 50 60 70 80 90 100 110 120 130 140
PAPER 6
INK 7
CLS
FOR R=1TOS
PLOT @, 3 * R, CHRS(52 + R) NEXT R
FOR T= 1 TO 150
D = INT(3 * RND(1)) + 1 + INT(3 * RND(1)) + 4 C(D) = C(D) + |
IF C(D) > 36 THEN STOP
PLOT C(D) + 2,3 * D— 12, 16 PLOT C(D) + 1,3* D—- 12,12+D NEXT T
GOTO 146
The dice-throws come in line 80. Everything else adjusts for the fact that the total (1,2, or 3) + (4, 5, or 6) must lie in the range 5-9. Theoretically, you can get the following combinations:
Second die
total
So in the long run, we expect a total of 7 for 1/3 of the throws, 6 or 8 for 2/9, and 5 or 9 for 1/9 of them. So that bar chart’s rows ought to be in the approximate sizes 1:2:3:2:1 and form a sort of triangle. Do they?
73
Computers can be made to manipulate words, or other kinds of symbolic notation, as well as numbers.
l6 Strings
The postman knocketh . . . with a letter. For you. A very personal letter. ‘Dear Mr Slugshaver,’ it says, ‘You have been selected from the people of Lower Pigpen to receive, absolutely free of charge...” Very gratifying. But next door, old Mrs Snagglechest has received the very same letter. In fact, the whole of Lower Pigpen has, along with most of the West Midlands. Here’s how it’s done. 10 INPUT “WHAT IS YOUR NAME”; N$ 20 INPUT “WHAT TOWN DO YOU LIVE IN”; T$ 30 CLS
40 PRINT “DEAR MR V”; N$
5@ PRINT “VVV YOU HAVE BEEN SELECTED FROM”
60 PRINT “THE PEOPLE OF V”; T$
70 PRINT “TO RECEIVE, ABSOLUTELY FREE OF”
80 PRINT “CHARGE (*), A MAGNIFICENT”
90 PRINT “MOULDED SOYA GARDEN PATH.”
100 PRINT “VVV WE ARE SURE, MR V”; N$
110 PRINT “THAT YOU WILL BE LED RIGHT”
120 PRINT “UP IT.”
130 PRINT “VVVV YOURS SINCERELY,”
140 PRINT “VVVVVV MILTON F. GNATBENDER”
150 PRINT “VVVVVV DEALER’S WRY JEST.”
160 PRINT
170 PRINT ‘** POSTAGE $1066 EXTRA”
Run this, and choose your inputs:
SLUGSHAVER LOWER PIGPEN
MOUSEBENDER GOAT END
and so forth. Try other names and towns. Hmmmmmmm... 74
Now imagine this automatically fed names and addresses from a data bank, churning out thousands of letters an hour.
The interesting thing, apart from how blatant the whole exercise is, is that absolutely no computation is involved. Merely memory, and some very simple manipulation of written text. The computer can manage this because, as well as numbers, it can store strings. That’s what those dollar signs $ signal, though there may be some Freudian significance too in the present context.
I’ve already introduced strings and string variables in Chapter 6. Now I'll show you how to manipulate them, starting with:
CONCATENATION
... which is a fancy word for ‘sticking together’. To jam two strings end to end you write a + sign between them. For example,
PRINT “HOT” + “DOG” which yields: HOTDOG
Notice the order: ““DOG + “HOT” gives ‘DOGHOT”’. Note also that the quotes are not part of the string: when a string is printed or otherwise manipulated, the quotes are there only to say where the ends are. You can combine several strings together in this way:
10 INPUT B$, C$
20 PRINT B$ + B$ + C$ What happens if you try:
B$ = “*B” C$ = ee
B$ = “CO” C$ = “NUT”
B$ = “BYEV” C$ = “BLACKBIRD” as inputs? Why?
If a particular sequence of characters (and that includes graphic characters) occurs several times in a program, you may find it worth while assigning it to a string variable.
THE LENGTH OF A STRING
The command: LEN
yields the /ength of a string—that is, the number of characters in it. For instance,
LEN(“FIDO”) = 4 LEN(““£££££££££££") = 11 LEN(“*2 + 2 = 5") = 5 LEN(“ ”) = 0
where “”’, the empty string, is a string with no characters in it. In general, to find the length of string K$, you ask for:
LEN(K$)
75
76
To test this out, try this program:
10 INPUT “STRING”; K$ 20 PRINT K$; “VY HAS LENGTH”; LEN(K$) 30 GOTO 16
It should be self-explanatory.
WORD-REVERSAL
The next program accepts as input a word, letter by letter, and uses string concatenation to produce the same word but in reverse. (By using more advanced commands like MID$, LEFT$, RIGHT$, it would be possible to input the whole word in one go, but for simplicity I'll take it one letter at a time here. See the next chapter for more details.) 10 INPUT “FIRST LETTER?”; F$ 26 INPUT “NEXT LETTER?”; N$ 30 IF N$ = “0” THEN 60 409 FE=N$+ FS 50 GOTO 20 60 CLS 70 PRINT F$ To stop the inputs, in line 20, enter ‘0’ instead of a letter. To see how this works, consider the word ‘YELLOW’. In line 10 we input the first letter,
‘y’, and so F$ is set to ‘Y’. Then in line 20 we input the next letter ‘E’. Line 40 now changes F$ to:
N$ + F$ = ssh?” + SON? = “Ry”? and line 50 sends us back to 20 for another letter, this time ‘L’. So F$ then becomes: N$ + F$ — sy? + “RY” = STRY”
and so on:
Input ‘L’: F$ = N$ + F$ = ‘L’ + “LEY” = “LLEY” Input ‘O°: F$ = N$ + F$ = “O” + “LLEY” = “OLLEY” Input ‘W’: F$ = N$ + F$ = “W” + “OLLEY” = ‘““WOLLEY” Input ‘@’: Program jumps to line 60 and prints ‘WOLLEY’ The crucial point is the order in which the strings are added in line 40. What happens if you write: 40 F$ = FS + N$
instead? Project 1
There is a word-game in which the first player makes up a simple sentence such as: YESTERDAY I SAW A BABOON
The next player adds an adjective describing the baboon: YESTERDAY I SAW A PINK BABOON
The next adds another adjective:
YESTERDAY I SAW A FIERCE PINK BABOON and so on, with the sentence getting longer and longer (until someone forgets which word comes where), ending up with something like:
YESTERDAY I SAW A SCRUPULOUS LAZY GULLIBLE FRAGRANT REFRESHING ENORMOUS PARTICULAR REINFORCED DISGRUNTLED PLASTIC DISTINGUISHED FIERCE PINK BABOON
or whatever. Write a program to let players build up such sentences by inputting the extra adjective at each stage.
ANSWERS Project 1
10 Y$ = “YESTERDAY I SAW AV” 20 BS = “BABOON”
30 A$=“”
40 PRINT Y$+ A$ + BS
50 INPUT “ADJECTIVE?” I$
60 A$=I$+ “V" + AS
70 GOTO 40
77
78
By picking out portions of a string, to get substrings, you can manipulate words. Examples given here include computer Spoonerisms, and
a program to tell you what day of the week your birthday was.
i? Substrings
In the previous chapter I introduced the idea of a string of characters. Now I’m going to talk about the commands:
LEFT$
RIGHT$
MID$
which let you select portions of a string—substrings. These are very useful commands for general string-handling.
LEFT, RIGHT AND CENTRE
To select the left-hand end of a string, you use the command: LEFT$(X$, N)
which gives the leftmost N characters of the string X$. For example,
10 LET X$ = “TEMPERATURE CHART” 20 LET Y$ = LEFTS(X$, 6) 30 PRINT Y$
gives TEMPER. Similarly there is a command for the right-hand N characters: RIGHT&(X$, N)
and
10 LET X$ = “TEMPERATURE CHART” 20 LET Y$ = RIGHTS$(X$, 3) 30 PRINT Y$ yields ART. (Incidentally, those LETs are optional, and can be left out just as for
assignments of numeric variables.) Finally in this order of ideas, there is a command:
MIDS$(X$, M, N)
which gives the N characters of X$ that start at position M. There is a restriction on M: it must be greater than @. If N is left out, everything from position M onwards is included. In
the above, if you put: 20 LET Y$ = MID$(X$, 6, 3) you get RAT. A typical use of this is to print the day of the week, given a number (I to 7 starting with Sunday): 10 W$ = “SUNMONTUEWEDTHUFRISAT” 20 INPUT “WHICH DAY?”; D 30 Y$ = MID&(WS, 3 * D — 2, 3) 40 PRINT Y$
The 3 * D — 2 gives the correct starting positions 1, 4, 7, 10, 13, 16 and 19 in W$. Project 1
Use a string “JANFEBMAR... DEC” to write a similar program to print out the month, given a number from | to 12.
STRINGS AND NUMBERS
The string “493” and the number 493 are considered to be different by the computer. You may not notice this if you just print them:
PRINT 493
PRINT “493”
give the same result. Now try:
PRINT 493 + 7 PRINT “493” + 7 PRINT “493” + “7”
You'll find you get three different results:
500 ? TYPE MISMATCH ERROR 4937
In the first case, it just adds the numbers.
In the second, it tries to add a string to a number, getting a type mismatch, which just means it can’t be done. (What should ‘‘CATCH” + 22 be? Well, maybe that’s not the best example after all... .)
In the third, it concatenates the strings “493” and ‘‘7” to get “4937” and then prints without the quotes.
This can be very useful, because you can do things with strings that aren’t so easy with numbers. For example, to find the first digit of 987654321 you just need LEFT$(‘‘987654321”, 1). With arithmetical methods, it’s a lot harder. Bur the result would be a string “9” and not the number 9. Now maybe you want to do some arithmetic with that 9. How?
A string which happens to be in the form of a number (with quotes round it) can be turned into a bona fide number by using the command word:
VAL
79
80
(for ‘value’). So: VAL(“‘9””) is the number 9. Try: PRINT VAL(‘‘493”) + VAL(‘‘7”’)
and you’ll see it really does work. There is a similar command:
STR$ that works the other way round: it converts a number to a string. For example: STR$(7751) is ‘*7751”
COMPUTER SPOONERISMS
The Reverend W. A. Spooner was notorious for his habit of interchanging the front ends of pairs of words, often to comic effect; so that instead of:
FORMLESS WISH he would say: WORMLESS FISH
and so on.
By using string-manipulations it is possible to get the computer to generate Spoonerisms. Whether they are funny, or not, is firstly a matter of taste, and secondly, up to the user to decide. The program has no opinions on the matter. Here it is:
10 INPUT “FIRST WORD”; A$ 20 INPUT “SECOND WORD”; B$ 30 P$ = LEFTS(AS, 1)
40 Q$ = MIDS(AS, 2)
5@ R$ = LEFTS(B$, 1)
60 S$ = MID$(B$, 2)
70 PRINT A$ + “V” + BS
80 PRINT “SPOONERIZED BECOMES:”
90 PRINT R$ + Q$ + “V” + P$ + S$
100 GOTO 10 Run this, and input “FLYING” and “PIG” in lines 10 and 20.
Now line 3@ takes the first character on the left of ‘FLYING’, so P$ =“‘F”’. And line 40
takes everything from character 2 onwards, making Q$ = “LYING”. Then line 50 gives R$ = “P”’; and line 60 gives S$ = “IG”.
Lines 70 and 8@set up the original word and suitable output messages; and line 90 prints out:
“Pp” + “LYING” + “V" + “F” + “IG” = PLYING FIG
which isn’t so bad, considering.
DAYFINDER
This program accepts as input a date (day number D, month M, year Y) and works out which day of the week it is.
10 A$ = 033614625035”
20 BS = ‘“SUNMONTUEWEDTHUFRISAT”
30 INPUT “DAY”; D
40 INPUT “MONTH”; M
50 INPUT “YEAR”; Y
60 PRINT “THE DAY ISV”;
70 Z=Y-1
80 C= INT(Z/4) — INT(Z/100) + INT(Z/400)
99 X=Y+D+C+ VAL(MIDS(AS, M, 1)) - 1
100 IF M>2 AND (Y = 4 * INT(Y/4) AND Y <> 100 * INT(Y/100) OR Y = 400 * INT(Y/400)) THEN X = X + 1
110 X=X-—7* INT(X/7)
120 PRINT MID$(B$, 3 * X + 1, 3)
Copy this out very carefully, especially the brackets in line 100. Run it, and input (as a test) 24 for D, 9 for M and 1945 for Y. (That is, 24th September 1945. You must input the full year and not just 45, or the program gets the wrong answer.) You should get:
THE DAY IS MON
for Monday. Try today’s date. Try your birthday. Find out what date Anne Boleyn died, and try that.
81
82
Line 1@ stores twelve ‘monthly correction numbers’ in compact form as a single string.
Line 20 sets up the ‘day-of-the-week’ string described above.
Lines 30-60 are input/output statements, nothing unusual.
Lines 80-100 perform a complicated calculation that takes into account leap years and the ‘monthly corrections’. Note the use of VAL and MID$ in line 90; what it actually does here is to find the Mth digit in A$ and convert it to a number.
Line 11@ produces a number in the range 0-6 for the day of the week (rather than the 1-7 used above in the illustration); and line 120 prints out the day itself using MID$ on B$.
ANSWERS Project 1 10 M$ = “JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC” 20 INPUT “WHICH MONTH”; M 30 Y$ = MID$(M$, 3 * M — 2, 3) 40 PRINT Y$
Pencil and paper still have their uses...
18 Debugging lll
DRY RUN TABLES
More often than not, runtime errors aren’t as easy to find as those in Debugging II. If you can’t see what’s wrong straight away, you need to check the coding in a careful and systematic way. It can bea rather laborious process, but if you stick to it rigidly, it’s almost guaranteed to pay off. I'll explain the techniques of ‘dry running’ a program with an example. We’ll imagine you’ve found the following piece of code in a magazine article: 10 INPUT “ENTER NEXT NO.”; N 20 IFN >@®THENS=S+N:C=C+I: GOTO 10 30 PRINT ‘AVERAGE IS”; S/C 40 INPUT “ANY MORE DATA (Y/N)”; Q$ 50 IF Q$=“Y” THEN 10 and the associated text tells you that this will find the average of a set of positive numbers, terminated by zero. In other words you could enter: ENTER NEXT NO. ? 3 ENTER NEXT NO. ? 4 ENTER NEXT NO. ? 5 ENTER NEXT NO. ? @
and it should come up with the message: AVERAGE IS 4
(The zero is not part of the data; it is the delimiter, see Chapter 8). The program will then ask the user if he wants to deal with another data set:
ANY MORE DATA (Y/N)?
If you type ‘Y’ in response to this question, the program will start all over again asking for a new set of numbers.
If you key the program in and run it with the numbers 3, 4, 5 and @, you’ll find that it doesn’t work. It accepts the numbers as you’d expect but when you've entered the zero, it crashes with the message:
? DIVISION BY ZERO ERROR IN 30
The zero gremlin has struck again!
83
84
Now, to find out what the silly machine has done, you pretend you are the machine and obey, slavishly, the program instructions as the machine would. You show how the various values the program handles change in a table like this:
mee Ts TET [oma
There are only four variables in this program: S, N, C and I. As every line is executed you enter the line number, the new values of S, N, C and I (if they are changed on that line) and, if the statement is an IF... THEN, a tick in the Branch column if a jump occurs, a cross otherwise.
Before we start though, there’s one thing the Oric will do as soon as you type RUN, and that is to zero all variables, so the table actually appears like this to start with:
foe TSS [SL] to 0 0 0 0
Suppose we test the program on the numbers 3, 4, 5 and @. The first time line 10 is executed, 3 will be passed to N, so:
ems [eT] om 0 0 0 0
At line 20, N is greater than zero, so the 3 is added to S, I (0) is added to C, and the branch to line 10 does take place:
<4—._ attempt to evaluate 12/0
So we can see why the ‘DIVISION BY ZERO’ error has cropped up. Now we can use the table to give some clues about how each variable is changing. Look at the N column first. We can see the 3, 4, 5 and @ which were input appearing in turn, which is what you’d
expect. S is more interesting. Here we can see the sum of the numbers in N gradually being formed. First the 3 appears, then 7 (3 + 4), then 12 (3 + 4 + 5). But what about C? Absolutely nothing is happening to it! Since three numbers have been entered, the average should be 12/3 = 4, so C ought to be 3. Actually, the reason C remains at zero is that it keeps having I added to it and I is fixed at zero. Suppose I is a misprint for 1? Then the table would look like this:
Print 12/3 = 4
So now things look promising. Edit line 20 to change the ‘I’ toa ‘I’ and RUN. Enter 3, 4, 5, 0 as before and 4 is displayed. So far so good. Now enter ‘Y’ when you’re asked if there’s any more data, and try 10, 20, 30, 0. The program prints out the answer 12, which is odd because the average of 10, 20 and 30 is 20!
LOGICAL ERRORS
Now this is an example of a new kind error—a logical error. The program does something, and completes its task without the Oric noticing anything wrong, but whatever it was that the program did, it was nor to take the average of 10, 20 and 30.
So let’s continue the dry run table to see what’s gone wrong. There’s little point in repeating the work done so far, so we can just note that, when we reach line 40, S = 12, N = @ and C = 3. Also, we now need the string variable Q$:
I don’t think we need go any further to see the problem. Since S is 12 to start with, it becomes 22 when it should only be 10, and C becomes 4 when it should be 1. In other words the Oric hasn’t forgotten the first set of values when it processes the second, so it will work out:
(3+4+5 + 10+ 20 + 30)/6 = 12 Now it’s easy to deal with; simply include a line 5: 5 S=0:C=0 and edit line 5@ to read: 50 IF Q$ = “Y” THEN 5
How likely are the kinds of errors we’ve seen here? Well, printing errors of the I for 1,2 for Z type are fairly common (although not in this book, I hope), and even if the error isn’t on the printed page, it’s quite likely you’ll make the odd transcription error without noticing it when you’re keying in a program. Even when you’re writing a program of your own,
85
86
you’d be surprised how often you can forget the name of a variable and use the wrong one, or even use the same variable for two different things. You should be careful, and note the name of every variable and what its function is as you invent it, but human nature being what itis...
The second error shows up two important things. First, although BASIC is trying to be helpful by initializing variables-to zero without you asking it to do so, it’s something of a mixed blessing. It’s good practice to set up all variables at the beginning of a program even though you may not need to do so, because it avoids the possibility of a mistake like this one. I’m not suggesting that you are likely to make an error as trivial as this one, but if a program is written to deal with one set of data, and only later is it altered to handle many sets, you can see how initializations could be forgotten.
Secondly it illustrates how careful you must be when testing a program. Just because a program works for one set of data, you mustn’t jump to the conclusion that it will work just as well for every other possible set.
Project 1
Here’s an example for you to try your skills on. The following program is supposed to accept a sequence of positive values (zero up to 1000) and, at the end, print out the largest and smallest values it has read. A negative number is used as a delimiter. For instance, if the data are 8, 4, 3, 9, —1 the program should print out:
9 3
I'll give you one clue—there are two errors to 4ook for.
10 MAX = 0: MIN = 6
20 INPUT N
30 IF N< MIN THEN MIN =N
40 IFN >MAX THEN MAX =N
50 IF N<@ THEN PRINT MAX, MIN: END 680 GOTO 20
1 STILL SAY YOU BOUGHT THE WRONG MANUAL
=
>
S S S = > >
ANSWER
Project 1
With my example dataset the dry run table will look like this:
0 0 0
Print 9, —1
So the /argest value is being correctly printed but the smallest isn’t. Looking down the MAX column we can see how the program is supposed to work. Every time a value larger than that in MAX at the moment comes along, it replaces the current value in MAX. MIN should, of course, behave in a similar way so that first 8, then 4, then 3 should appear there. But no changes occur in MIN until —1 is entered and that isn’t supposed to affect things at all, since it’s only the delimiter!
The reason that no new values are being placed in MIN is that there’s the smallest possible value (zero) already in it. MIN should start with a very large value in it so that the first value to come along will replace it, because the new value is bound to be smaller. Since the largest possible value is known to be 1000, anything greater than this will do. So line 10 becomes:
10 MAX = @: MIN = 1001
Now we must prevent the delimiting —1 getting into MIN. That’s easy. We must ask if the end of the data has been reached before trying to transfer the value to MAX or MIN. So line 50 should be deleted and rewritten as line 25.
87
88
There are two different levels of graphics on the Oric. The coarsest builds up shapes by using a selection of special characters to draw tiny blocks.
19 The Art of Coarse Graphics
As well as TEXT, the low-resolution screen can display graphics. It uses the same Text Screen arrangement (27 rows of 40 cells numbered in columns @-38 and rows 0-26, plus a reserved column at far left as in Figure 9.1); but uses two new mode-setting commands: LORES@ LORES1 (The word is LO-RES, short for LOw RESolution, and has nothing to do with Folk Tales
or lawyers who can’t spell.) These differ only in the way that character-printing commands are interpreted.
ASCII CODES
Every Oric character has a code number, its ASCII Code. (The letters stand for American Standard Code for Information Interchange.) The codes are listed in Appendix D of the Manual. You can ask for a character by name:
PRINT “A”
or by code: PRINT CHR$(65)
because the ASCII code for “tA” is 65. In general: CHR3$(N)
MeTRo -GOLowyn- I'B GEDDING
MAYFLY PRESENTS :
gives the character whose ASCII code is the number N. Conversely you can find out the code for a character by asking for:
ASC(character). So ASC(‘‘A”’) is 65. The codes actually run from @ to 255, but standard ASCII uses only 32-125, which are listed in Appendix D. To see what happens with the other numbers, try this: 10 INPUT N 20 PRINT CHR&(N) 30 GOTO 10
In particular try 126 as in input: it’s quite a useful character. Some codes can lead to the screen going out of synch: if this happens use the RESET button underneath.
Project 1
What effect do you get by adding 128 to the codes in Appendix D of the Manual?
LORESO@: THE STANDARD SET
In LORES@ mode, the computer uses the standard set of characters. In fact, LORES@O is rather similar to TEXT mode (Chapters 5, 9); but there are a few crucial differences. First, when it is first set up, the PAPER is black and the INK white. Second, the command:
PLOT X, Y, C
used to set attributes in Chapter 12, appears to affect only the cell at position X, Y. (Otherwise it functions as in TEXT mode.) For instance, this program plots random colours to the screen:
10 LORESO
20 C= 39 * RND(1)
30 R= 27 * RND(1)
40 COLOUR = 8 * RND(1) + 16
5@ PLOT C, R, COLOUR
60 GOTO 20
And this one jazzes that idea up, to produce random rectangles and a rather pretty Modern Art design:
10 LORESO
20 REPEAT
30 RT = 27 * RND(1)
40 RB=RT +10 * RND(1) 50 UNTIL RB < = 26
60 REPEAT
70 CL = 39 * RND(1)
80 CR=CL + 10 * RND(1) 90 UNTIL CR < = 38
89
90
108 COLOUR = 16 + 8 * RND(1) 116 FORC=CLTOCR 120 FOR R=RT TO RB 130 PLOT C, R, COLOUR 140 NEXTR 150 NEXT C 160 GOTO 20 Note the two REPEAT... UNTIL loops, which make sure PLOT points don’t go off
screen; the use of RND(1) for randomness; and the FOR... NEXT loop to plot the rectangles.
Figure 19.1 Modern Art.
Project 2 This is like Project 1, but in LORES@ and using PLOT. Type this in:
10 LORES@
20 INPUT N
30 PLOT 5, 5, CHRS(N) 40 GOTO 20
Now what happens if you add 128 to the ASCII code of a standard character such as ‘A’?
LORES1: ALTERNATE SET
The LORES1! mode is almost the same as LORESQ, excep? that the entire character set changes. Every program instruction that refers to a character, either directly or via the ASCII code, produces the corresponding character from the a/ternate set. For example, key this in:
10 LORESI1
20 PRINT “ABCDE” 30 PRINT “FGHIJ” 40 PRINT “KLMNO” 50 PRINT “*PQRST” 60 PRINT “UVWXY” 70 GOTO 70
Instead of the letters, you get a rather peculiarly shaped thing, like Figure 19.2.
Figure 19.2 Alternate characters yield unfamiliar results from familiar commands.
The letters from the standard character set have been systematically replaced by characters from the alternate set. Mostly, these are chunky block graphics shapes, known as teletext characters because they are compatible with TV Teletext systems like Oracle. The Oric Manual doesn’t say which characters are which, so I’ve listed them for you in Appendix 2. You can also list them out systematically by using the program in Project 2 but with line 10 replaced by LORESI.
You'll find that while you are in LORES1, anything you type comes out in Chunky Nutritious Teletext, at least until the screen starts scrolling. To get out of this state, type:
CLS
directly: ignore the printout on screen!
You can change INK colour within LORES1; but not PAPER colour (or you lose the alternate characters). After a scroll you may find that an initial CLS before the LORES1 command helps. The reason for all this would seem to be that the LORES! command sets up attributes in the reserved column of screen, telling the machine to use the alternate set. PAPER mucks these up, and scrolls shift them up the screen.
Sometimes when a program in LORES|I crashes, the error message is printed in the alternate character set and you can’t read it. If so, type:
PAPER @
in direct mode (and ignore what you see on the screen) to recover the standard set.
OT.
SKYLINES
The next program shows how you can mix colours on the screen by setting different attributes in different positions. It generates a random futuristic city skyline.
Figure 19.3 Typical screen plot from Skylines.
10 LORES1
20 FOR R=90 TO 26
36 PLOT @, R, 1 + 7 * RND(1)
40 NEXTR
5@ FOR C= 1 TO 38
60 X = 32+ 64 * RND(1)
70 RT = 26 — 20 * RND(1)
80 FOR R= 26 TO RT STEP -1
90 PLOT C, R, CHR$(X)
100 NEXTR
110 NEXT C
120 GOTO 120 Line 10 sets up the alternate character set. Lines 20-40 place random INK colour attributes in column @. Line 68 chooses a random alternate character; line 70 a random
height for the skyscraper in column C. Lines 80-100 draw the skyscraper from the bottom up; and 50 and 110 loop the column to get a whole skyline.
Project 3 Change line 7@ to:
70 RT = 26 — 20 * ABS(SIN(C/5))
and see what shape you get. (For ABS and SIN see the Manual pages 56 and 71: maths has its uses after all!)
92
BLOCK GRAPHICS
To all intents and purposes you should think of the teletext characters as living in a 3 X 3 grid, so that ‘A’ corresponds to Figure 19.4, and so on. (Strictly, it’s a 6 X 8 grid, with the 6 grouped 2/2/2 and the 8 grouped 3/2/3, but that’s splitting hairs.) So you can assemble pictures out of block graphics by drawing on a grid.
Standard Alternate
Figure 19.4 Standard and alternate characters with code 65. There is no special relation between one set and the other.
Figure 19.5 Eric the Nannygoat in Lo-res Graphics.
I don’t know what an Oric looks like, but maybe it’s a bit like a goat*. I’ve drawn a chunky goat in Figure 19.5 and broken her up into 3 X 3 sub-blocks. These turn out (from Appendix 2) to correspond to the standard characters whose codes are:
68 32 32 SO 52 32 95 95 87 61 32. 85 32 85 32
These are:
D Vv Vv 2 4 Vv £ £ WwW Vv U Vv U Vv
*Yes I do—it’s the little man with a square head in the Manual. Personally, I’d rather have a goat...
93
So I can print out my goat (actually, she’s called Eric, which is close enough, though the vet needs his eyes tested) like this:
10 20 30 40 50 60 70
CLS
LORES|1
INK 2 (for a green goat) PRINT “DV V24”
PRINT “V££W =”
PRINT “VUVUV”
GOTO 70
ae ee Pee eet ef ee ee ee ee ee ee a
So a 3 1 3 3 2
Figure 19.6 Looping Eric to get a flock of goats. What? Herd of goats? Of course I’ve heard
of goats!
ANSWERS
Project 1
Absolutely none.
Project 2
Video-inversion: INK and PAPER change round.
IT'S AMAZING WHAT PEOPLE
WILL PUT UP WITH FOR A JOB IN TELEVISION ...
Project 3
See Figure 19.7. ,
Figure 19.7 Trigonometric Skyline.
95
96
By printing the same characters in different positions, you can produce the illusion of movement. And the movements can be controlled from the keyboard.
70 Moving Graphics
Next, I’ll make Eric the nannygoat move. I’ll do this by printing her in lots of different places. Here’s the first (failed) attempt:
10 CLS
20 LORES1
30 INK 3 (yellow goats this time)
40 FOR C= 1 TO 30
5@ PLOT C, 10, “DVV24”
60 PLOT C, 11, “V££w=”"
70 PLOT C, 12, “VUVUV”
86 NEXTC
96 GOTO 90
Nearly, right: but Eric’s tail seems to streeeeeeeeetch somewhat . . . Of course: I’ve left traces of previous goats littered about the screen.
Without doubt the neatest way to take care of this is to equip Eric with an extra ‘invisible tail’ of blank spaces, which will follow along behind her and wipe out unwanted junk. (Legend has is that the fox erases his tracks with his tail: in the Age of the Computer, so do goats). Modify the following lines (a good chance to practise your editing) and leave the rest as before:
50 PLOT C, 10, “VDVV24” 60 PLOT C, Il, “VV££W=” 70 PLOT C, 12, “VVUVUV”
All I’ve done is put an extra space in each of the three strings that build up the goat. Project 1
Use the grid in Figure 20.1 to produce a dog. Make it move along the screen from right to left.
A word of warning: not all combinations of squares in a 3 X 3 grid are available in the alternate character set (you’d need 512 of them to do that) so you should select your designs carefully.
Figure 20.1 Dog design for Project 1.
READING THE KEYBOARD
At the moment, the only way we can send the Oric messages is via an INPUT command, which stops any screen activity, prints out messages, and generally tramples all over the graphic display. There are two other commands that can be used for messageless inputs: GET KEY$ The GET command lets you input a character, thought of as a string variable of length 1. If you type, say. GET F$
then the Oric will wait until a key is pressed, and give that value to the variable F$. Try this:
10 GET F$ 20 PRINT “YOU PRESSED KEYV”; F$ 30 GOTO 10
and press keys.
For most video-game programs, GET isn’t the command you want, because of the wait. Instead, you use KEY$. The syntax is slightly different: what corresponds to GET F$ above is:
F$ = KEY$ This sets F$ to the character being pressed, if there is one; and sets it to the empty string ‘‘’ if not. It does not wait. In other words, KEY$ lets you read the keyboard to see
which key, if any, is currently being pressed. You can then act on that information, as in the next section.
CYRIL THE SQUIRREL
(Or, for Americans, SHIRL THE SQUIRL.) Cyril the squirrel is sitting under a tree when nuts start falljng around him. He rushes off to collect them, but they keep on coming: can Cyril collect them all? Your job is to make Cyril chase round the screen. The program gets a good bit longer than any I’ve given you before, and even then it could be improved; but it will teach you several useful techniques.
97
98
Figure 20.2 shows Cyril and a nut. In the alternate character set, Cyril is “NN =” and the nut is ‘‘(’’. The four arrow keys at the bottom of the keyboard move Cyril in the corresponding directions. The REM statements are there to remind me what I was doing: I’ve put them at funny line numbers so that you can omit them without affecting GOTOs.
Figure 20.2
within it.
10 20 30
50
99
110 120
199 200 210 220
299 300 310 320 330 340
| ae
INK INK
° ii | Eee:
CYRIL NUT
Cyril the Squirrel and a Nut. Note Cyril’s border, and his attributes placed
REM INITIALIZE PRINT CHR3$(6) CLS
LORES|1
INK 3
C= 18:R = 12:T = 8
REM COLUMN OF NUTS FOR Q=8TO 15
PLOT 6, Q, “(”
NEXT Q
REM DISPLAY CYRIL
PLOT C, R- 1, “VVVVV”
PLOT C, R, CHR§$(5) + “NN = ” + CHR§$(3) PLOT C,R+ 1, “VVVVV”
REM RANDOM NUT
IF RND(1) < .95 THEN 400 NR = 3 + 20 * RND(1)
NC = 5 + 30 * RND()) PLOT NC, NR, “(’’ T=T+1
399 REM KEYBOARD SCAN 400 A$ = KEY$
410 IF A$ =“ ” THEN 600
420 A = ASC(A$)
430 IF A=8 THENC=C~-1 449 IF A=9 THENC=C+1 450 IFA=10THENR=R+1 400 IFA=11THENR=R-1 470 IF R<1THENR=1
480 IF R> 25 THEN R= 25 4909 IF C<2 THEN C=2
500 IF C > 32 THEN C = 32
599 REM SEARCH FOR NUTS
600 FORE=0TO4
616 FORF=-1TO1
620 IF SCRN(C + E, R + F) = 40 THEN ZAP: T= T - 1 630 NEXT F
640 NEXTE
699 REM CHECK NUT TOTAL
700 IF T>0 THEN 200
710 PLOT 1, 1, CHR$(8) + CHR$(17) + “WELL DONE CYRIL!” 720 PRINT CHRS$(6)
730 INK ®@
740 STOP
Now for the low-down...
Line 10 turns off the keyboard bleep; 20-40 go into-LORES1 and set yellow ink. In line 50, C and R are the positions directly ahead of Cyril’s nose; and T is the total number of nuts on screen.
Lines 100-120 set up eight nuts, to avoid the game being over before it’s begun.
Lines 200-220 plot Cyril. He has an ‘invisible border’ all round (for motion in all four directions, like the goat’s invisible tail but better). Two characters in the border are ink attributes, the characters CHR$(5) and CHR§(@) in line 210. See Figure 20.2. These make Cyril purple, but don’t affect the rest of the screen.
Lines 300-349 set up a random nut. If you dropa nut on every run through the program sequence, poor old Cyril soon gets buried: he just can’t keep up. So line 300 gives a one-in- twenty chance of dropping a nut. This is about right; but for an easier game change the .95 to about .97; for a much harder one, to .9. Recall that ‘“(” is the nut.
Lines 400 onwards are the main item to understand. They scan the keyboard looking for arrow key-presses. The ASCII codes for the arrow keys are like this:
« has ASCII code 8 — has ASCII code 9 4 has ASCII code 10 t has ASCII code 11
99
Figure 20.3 Cyril and some nuts as seen on TV.
Line 410 jumps if no key is pressed (to avoid a crash in line 420); lines 430-460 adjust the position of Cyril’s nose according to the arrows. Lines 470-500 protect against going off screen: when Cyril hits an edge, he waits until you send him back towards the centre.
Lines 600 onwards search for a nut. When Cyril or his invisible border lands on a nut, the nut disappears from the screen display; but the computer can only realize this—and change the nut total T accordingly—if we search through the area occupied by Cyril and his border (Figure 20.2 shows this to be a 3 X 5 rectangle) looking for nuts. This is where the command:
SCRN(C, R)
comes in handy. It gives the ASCII code of the screen character in column C, row R. The nut is “*(”? and has ASCII code 49, hence line 620. Did you know squirrels carry lasers?
Finally line 70@ tests whether all nuts are gone. If not, the program goes back to line 200 to print Cyril in his new position. If they are, you get a message. The CHR§$(8) produces printout in the standard character set. (See the Manual page 36.) CHR$(17) gives red paper. Line 720 turns the keyboard bleep back on, 73@ resets black ink. These are just for tidiness. (Incidentally, if you BREAK the program, press CTRL/F to get the bleep back. Otherwise it comes back next time you run Cyril.)
ANSWER
Project 1
The rows of the dog are characters numbered: 88 91 33 32 54 32. 75 95 95 33 32. 98 32 98 32
Corresponding to characters:
100
So we get:
10 CLS
20 LORES1
30 INK 4
40 FOR C= 30TO1 STEP ~-1 5@ PLOT C, 10, “X[!V6V”
60 PLOT C, 11, “VKE££!V”
70 PLOT C, 12, “VZVZVV” 80 NEXT C
90 GOTO 90
Note that the invisible tail is now at the right-hand end: not because the dog’s facing the other way, but because he’s moving the other way.
101
102
Computer programs often require lists of information: numbers or words. Many games programs use lists of numbers to control the positions of objects on the screen. These lists are called:
Zi Arrays
An array is essentially a numbered, list of items, like a laundry list:
1. Socks.
2. Shirt.
3. Pillowcase. 4. Pullover.
If someone wants item number 3, (s)he can look it up on the list to see what it is (here a pillowcase). There are two kinds of arrays: numeric arrays and string arrays. The rules for array names are just the same as for variable names. Suppose we want to store in the computer a list of the twelve months of the year, in order. Since month-names are strings, we need a string array, which we’ll call MTH$. (What’s wrong with using MONTH$?)
First, we must tell the computer how Jong the list will be. This is known as ‘dimensioning the array’ and it is done with a:
DIM command, like this: 10 DIM MTH§$§(12)
Strictly speaking, you could get away with 11 instead of 12 because (for reasons I won’t go into here) arrays in the Oric are numbered from @: an array dimensioned to 12 as above has entries numbered 9, 1, 2,3,4,5,6,7,8,9, 10, 11, 12—thirteen altogether! The simplest way to avoid getting confused is to ignore the @ entry. Next you need to tell the computer what the 12 entries are: 20 MTHS$§(1) = “JANUARY”
30 MTH$§(2) = “FEBRUARY”
130 MTH$(12) = “DECEMBER”
I’ve used dots, but you will have to type all twelve months. Hard luck. You can now refer to any given entry in the array by using the name of the array, followed by the item number in brackets. For example:
MTH$(7) turns out to be ‘JULY’, and so on. So, to print out a given month, you could add the lines: 149 INPUT ‘NUMBER OF MONTH”; N 150 PRINT MTHS(N)
Similarly, you might want to tell the computer how many days each month has. You’d set up a numeric array, say MTHLGTH, using:
10 DIM MTHLGTH(12)
and then assign values:
20 MTHLGTH(1) = 31 30 MTHLGTH(2) = 28 40 MTHLGTH(3) = 31
130 MTHLGTH(12) = 31 If any array contains 11 or fewer ‘slots’ for entries, including the zero slot, it is not strictly necessary to dimension it beforehand. That is, DIM ARRAY (N)
is only needed for N bigger than 1@. As always, it’s good practice to dimension a smaller array regardless, for clarity.
The Frequency Chart program in Chapter 15 used an array C of size 6. Icheated there, and didn’t dimension it, because I didn’t want to have to explain the DIM command at that stage. Go back and take a look at the way the array is used.
THE MOVING ZIT REVISITED
You may recall that in Chapter 9 I constructed a sort of ‘delay line’ to produce a moving worm. I used a whole list of variables C0,C1,...,C6and R1,R2,...,R6(in Project 4). As they stand, these do not form an array: the brackets are missing and as far as Oric is concerned, I might as well have called them SLEEPY, HAPPY, GRUMPY, BASHFUL and so on. Specifically, if I tried to refer to a general one of them by using CN, expecting to get C3 if N = 3, or CS if N=S, I'd be in fora nasty shock. Oric would look for a variable named:
CN fail to find it, and set it to zero by default. If however I’d put brackets in, and asked for: C(N)
it would check what value N had, say 5, and work out C(5). So the answer to Project 4 of Chapter 9 would become:
41 FORN=90TOS
42 C(N) = C(N + 1): R(N) = R(N + 1) 43 NEXTN
44 C(6)=C: R(6)=R
It would also be a good idea to dimension the two arrays:
15 DIM C(6) 16 DIM R(6)
and this could actually be shortened to: 15 DIM C(6), R(6)
Project 1
Modify the size of the arrays C and R, and the loop size, to produce a worm of length 17. (Now you must dimension C and R beforehand!)
103
104
MULTIDIMENSIONAL ARRAYS
So far my arrays have only required one entry N to specify which item I want: the array is
just a /ist. If I want a rectangular table of numbers or strings, I can use an array like this: ARRAY(M, N)
This is called a two-dimensional array, because it needs two numbers. You can think of the entries as being arranged like this:
ARRAY(@, 0) ARRAY(@, 1)... ARRAY(@, Y) ARRAY(I, 0) | ARRAY(I,1)... ARRAY(I, Y) ARRAY(2, 0) ARRAY(2, 1)... ARRAY(2, Y) ARRAY(X, 0) | ARRAY(X, 1)... ARRAY(X, Y)
which is set up by the command (which is never optional for two or more dimensions): DJM ARRAY{({X, Y)
with specific numbers for X and Y. As before, entries with values @ come as a bonus: I’ve separated them off by a dotted line. To avoid confusion, they can be ignored if they’re not useful. So, to represent an 8 X 8 chessboard, you would use something like:
DIM CHESS(8, 8)
and enter numerical codes for the various pieces on each square.
For an example of the use of a two-dimensional array, see the Character Builder program in Chapter 28.
There are also three-dimensional arrays (and higher!) using:
DIM(X, Y, Z,.. .)
but they’re rarely useful—and eat up memory wholesale.
ANSWER Project 1
15 DIM C(16), R(16) 41 FORN=6TO 15
42 C(N) = C(N + 1): R(N) = R(N +: 1) 43 NEXTN
44 C(16)=C: R(16)=R
(Plus the lines of the original program.)
Music hath charms .. . Here’s my contribution to the Bach-to-BASIC movement.
22 Music and Harmony
One of the nicest things about the Oric is its sophisticated sound chip. So far we’ve only used it to generate the standard games noises—ZAP, EXPLODE and so on. Now we should explore its capabilities somewhat further, and use it to play some music. When you write:
100 ZAP:ZAP
the Oric is actually doing quite a lot of work for you in forming the right sound, cr more precisely, combinations of sounds. In principle, it would be possible to extend this approach into music and have statements such as:
200 BEETHOVENS 5TH
and expect a whole symphony to be played. But huge amounts of memory would be involved, and while it might be possible to store a few tunes in the machine, it would obviously be much more sensible to allow the user to specify a melody in terms of what instruments are playing which notes at what times and for how long.
Put another way, we want the Oric to respond to a set of instructions in much the same way as an orchestra responds to a piece of sheet music. And that’s (almost) what the sound chip can be made to do.
MUSIC
The ‘orchestra’ is a little primitive, though. First, it has at most three musicians. (The Oric calls them tone channels.) Second, all of them have to play the same instrument! The distinction between different musical instruments is that, although they may be playing the same note, the quality of the sound varies in a number of ways. In practice, for instance, the number and volume of the harmonics in the note are characteristic of the instrument producing it. The Oric does not (directly) allow you to take account of this. However, a second feature is the way in which the volume of the note changes throughout its length. For instance, a guitar note starts loudly and gradually dies away; a violin has a more or less continuous volume, because the string is being continuously vibrated by the bow; the sound in an organ pipe builds up as it fills with air.
The Oric does allow us to mimic these features by specifying the envelope of the sound to be generated. The diagram at the bottom of page 100 of the Manual shows the possible envelopes, and for the above examples you can see that a guitar is equivalent to envelope mode I, a violin might be mode 7 and an organ, mode 2. Don’t expect the notes to sound too lifelike—you have to use a little imagination.
Now to play something. There are two commands needed—MUSIC and PLAY. Fora rough analogy, MUSIC is equivalent to the musician looking at his sheet music to decide what note to play, and PLAY is equivalent to the conductor saying when it should be played.
So a MUSIC command needs to specify which musician (or tone channel) it refers to, which note is to be played, and how loud the note is to be. The note to be played is actually
105
split into two parts; the octave (0-6) and the note within the octave. The note is evaluated like this:
C# D# F# G# A# Music Cc D E F G Symbols * 5 | | | | | Oric fi Be Be eae OR SH RE HE tO Be Value
Note that C# is the same as Db, D# is the same as Eb etc. There is no E# or B#. So suppose we want a middle C played by musician 2. We write:
20 MUSIC 2, 3, 1, 0
Volume level Note 1(C) Octave (the middle one)
i
Channel (musician) number
Notice that I’ve set the volume level to zero, which looks odd, because you might expect that to mean ‘noiseless’ or at least ‘very quiet’. I’ll explain its actual significance later.
Now for the conductor’s bit. He has to say which musician is to play and what he’s to sound like:
30 PLAY 2, @, 1, 2000 Time envelope lasts
Envelope mode | (guitar)
Always zero for our purposes
7
Channel 2 on
RUN this. You’ll hear a somewhat guitar-like note. Now experiment a little. Change the envelope length from 2000 to 20 0090. It lasts too long for a guitar note, doesn’t it? And 200 gives far too clipped a sound. Very roughly, for every 1000, you get 1 second, but the subjective effect is for the time to appear shorter than that, because it dies to a volume below the ear’s threshold before it actually disappears.
Now try envelope mode 4. We can hear the envelope shape all right, but why doesn’t it stop? Well, we haven’t told it to. For envelope modes | and 2 there’s an implied length in the final value of the PLAY instruction; but this is ignored by the ‘continuous’ modes 3-7. So now we need a way to stop the sound once it’s started.
Obviously, we need to turn off the tone channels. So another PLAY instruction should follow line 30 which will do this:
40 PLAY @, 0, 0, 0
should do.
RUN again. Now the sound has gone completely except for a hardly discernible click. The sound has been turned on at line 30 all right, but it’s then immediately turned off at line 40! We need a delay between the two:
106
35 WAIT 200
which should give about 2 seconds of sound. And it does!
Now change the @ (for volume level) in line 2 to 6. The note now has a fixed volume. So putting a value other than 0 in this position overrides the envelope shape in the subsequent PLAY command. And @ doesn’t mean ‘zero volume’: it means ‘use the envelope to control the volume’.
In principle, that’s all there is to using the tone channels, but, obviously, we need an easy way of getting the right note values and WAIT lengths into a program containing MUSIC commands. There are a number of possibilities for this, but one of the simplest involves using READ and DATA statements, as in Chapter 7.
So now to our program. For every note played, we need three pieces of information: the octave, the note and its length.
10 READ NTE, OCT, L (Careful! You can’t call a variable ‘NOTE’ because it includes the keyword ‘NOT’.) Now we want to play it: 20 MUSIC 2, OCT, NTE, @ (Output to channel 2)
25 PLAY 2, @, 2, 2200 (Open channel 2 with envelope 2 lasting around 2 seconds)
then wait for a bit:
30 WAIT 20* L and get the next note:
35 GOTO 10
We’ve created the dreaded endless loop, though, so we need a delimiter of some sort. Suppose the last note to be played is given a length of zero. Then we could insert:
15 IF L=0 THEN PLAY @, 6, 0, 0:END Now all that’s needed is a DATA list for the READ to get its numbers from. Try this:
50 DATA 1, 3, 2 60 DATA 5, 3, 2 70 DATA 5, 3, 2 80 DATA 3, 3, 2 99 DATA 1, 3, 2 100 DATA 6, 3, 2 110 DATA 6, 3, 2 120 DATA 5, 3, 2 130 DATA 3, 3, 2 149 DATA 5, 3, 2 150 DATA 8, 3, 2 160 DATA 8, 3, 2 170 DATA 7, 3, 2 180 DATA 8, 3, 4 199 DATA 5, 3, 2 200 DATA 10, 3, 3 210 DATA 8, 3, 1
220 DATA 6, 3, 2 230 DATA 5, 3, 2 240 DATA 3, 3, 2 250 DATA 1, 3, 2 260 DATA 12, 2, 2 270 DATAS, 3, 2 280 DATA 3, 3, 2 299 DATA 1, 3, 2 300 DATA 1, 3, 2 310 DATA 12, 2, 2 320 DATA 1, 3, 4 600 DATA 8, 6, 0 Maybe that’s topical if you had your Oric as a Christmas present! But my real reason for choosing it is that most of the notes are the same length and in the same octave, making it easy to work out. You’ll see that each DATA statement represents
one note, in the order ‘note, octave, length’ as you'd expect, since that’s the order READ wants them in. For instance:
170 DATA 7, 3, 2
specifies F# in octave 3 played for a length 2. I’ve chosen 2 as a standard length for a crotchet (so | will be a quaver) and, for two reasons, I’ve then multiplied this by 2 in the WAIT statement (line 3@) to give the actual delay. First, it’s easier to think Is, 2s and 3s when writing the DATA statements. Second, you can alter the tempo simply by changing the 20 in line 30. You could even input a tempo value at the start.
I could have worked out the values for each DATA statement by looking at the sheet music for ‘While Shepherds Watched’ (Oh, so that’s what it was!), but in fact I did it by ear and guesswork. (What do you mean, you can tell?) That’s why the delimiting statement is at 600. I put it in first, so that I could repeatedly run the program as I inserted new DATA statements, to check each additional one. 600 was just a guess at a line number which would not be likely to be reached.
Project 1
Using the same program, modify the DATA statements to play ‘Don’t Cry for Me, Argentina’.
HARMONY
The Oric’s sound chip is actually a lot cleverer than the previous example gives it credit for. Try this (I'll explain how it works after you’ve been suitably impressed): 5 CH=2 10 READ NTE, OCT, L, N2, 02 15 IFL=0THEN PLAY@,@,0,0:RESTORE: WAIT 50: CH= 5-— CH: GOTO 10 20 MUSIC 2, OCT, NTE, 7 22 MUSIC 1, O2 — 1, N2,7 25. PLAY CH, @, 0, 0 30 WAIT 26* L 35 GOTO 10
} Change 7 to 4 for lower volume if you wish.
108
40 50 60 70 80 90
110 120 130 140 150 160 170 180 190 200 210 220 230 240 250 260 270 280 290 300 310 320 330 340 350 360 370 380 390 400 410 420 430
DATA 5, 3, 1, 5, 3 DATA 1, 3, 1, 5, 3 DATA 3, 3, 1, 5, 3 DATA 5, 3, 1, 5, 3 DATA 8, 3, 1, 5, 3 DATA 6, 3, 1, 5, 3 DATA 6, 3, 1, 6, 3 DATA 19, 3, 1, 6, 3 DATA 8, 3, 1, 6, 3 DATA 8, 3, 1, 8, 3 DATA 1, 4, 1, 8, 3 DATA 12, 3, 1, 8, 3 DATA 1,4, 1, 8, 3 DATA 8, 3, 1, 8, 3 DATA 5, 3, 1, 8, 3 DATA 1, 3, 1, 6, 3 DATA 3, 3, 1, 6, 3 DATA 5, 3, 1, 6, 3 DATA 6, 3, 1, 5, 3 DATA 8, 3, 1, 5, 3 DATA 10, 3, 1, 5, 3 DATA 8, 3, 1, 5, 3 DATA 6, 3, 1, 5, 3 DATA 5, 3, 1, 5, 3 DATA 3, 3, 1, 1, 3 DATA 5, 3, 1, 1, 3 DATA 1, 3, 1, 1, 3 DATA 12, 2, 1, 12, 2 DATA 1, 3, 1, 12, 2 DATA 3, 3, 1, 12, 2 DATA 8, 2, 1, 12, 2 DATA 12, 2, 1, 12, 2 DATA 3, 3, 1, 12, 2 DATA 6, 3, 1, 12, 2 DATA 5, 3, 1, 12, 2 DATA 3, 3, 1, 12, 2 DATA 5, 3, 1, 5, 3 DATA 1, 3, 1, 5,3 DATA 3, 3, 1, 5, 3 DATA 5, 3, 1, 5, 3
109
110
440 DATA 8, 3, 1, 5,3 450 DATA 6, 3, 1, 5,3 460 DATA 6, 3, 1, 6, 3 470 DATA 19, 3, 1, 6, 3 480 DATA 8, 3, 1, 6, 3 490 DATA 8, 3, 1, 8, 3 500 DATA 1, 4, 1, 8,3 510 DATA 12, 3, 1, 8,3 520 DATA 1,4, 1, 8,3 530 DATA 8, 3, 1, 8, 3 540 DATA 5S, 3, 1, 8, 3 550 DATA 1, 3, 1, 6, 3 560 DATA 3, 3. 1, 6, 3 570 DATAS, 3, 1, 6, 3 580 DATA 14, 2, 1,5, 3 599 DATA 8, 3, 1, 5, 3 600 DATA 6, 3, 1, 5, 3 610 DATA S, 3, 1,5, 3 620 DATA 3, 3, 1, 5, 3 630 DATA 1, 3, 1, 5, 3 640 DATA 8, 2, 1, 12, 2 650 DATA 1, 3, 1, 12,2 660 DATA 12, 2, 1, 12, 2 670 DATA 1, 3, 6, 1, 3 1000 DATA @, 0, 0, 0, @ If you’ve been careful, and got all the DATA statements right, you should hear Bach’s ‘Jesu, Joy of Man’s Desiring’, played alternately without and with a harmony line. Sounds good, doesn’t it?
Now, how does it work? Well, in some respects it’s pretty similar to the previous program, except that now we’re giving instructions to two ‘musicians’ instead of just one. So each DATA statement now has five values associated with it. The first three are as before (note, octave, length). The last two are note and octave values for the second musician (channel). We don’t need a second length value, because the harmony line happens to be related very simply (in this case) to the melody.
You'll notice that there’s an additional line 22 which outputs the harmony line to channel | (N2 and O2 having been picked up in the READ statement). Note that the octave selected for the harmony is one below the melody (O2 — 1), to give some ‘spread’ to the sound. Of course, I could have allowed for this in the DATA statements, but I’d written a lot of them before I realized I needed to do this, so it was easier just to subtract
one in the appropriate MUSIC statement. Now to PLAY the MUSIC that’s been set up in lines 20 and 22:
25 PLAY CH, 9, 6, 0
We’re not using an envelope (because the volume is set to 7 in both MUSIC commands) so only the channel needs to be defined in PLAY. Hence the last three zeros. CH is initialized to 2 (line 5) which means that only channel 2 will be open. So although channel | is set up
ready to play a note, it can’t because PLAY won’t let it. Asa result, first time round there’s no harmony.
However, when the program reaches the delimiting data in line 1000, L is zero, and the condition in line 15 is met. Before restarting, CH is set to 5 — CH. Sincé CH is 2 at the moment, it will become 3, and CH = 3 opens channels | and 2! Next time CH will be 5 — 3 =2 and the harmony is turned off again, etc. etc., ad infinitum. See page 100 of the Manual under the heading ‘Tone enable’ for the effects of setting CH in the range 0-7.
Looking back on this, it’s clear that the program is trivial, and then there are piles of DATA statements. Couldn’t we reduce the requirement for repetitive data by making the program more complex? Well, yes, but I wanted to get an impressive result without having to spend pages discussing an appropriate data structure and ways of handling it. There simply isn’t space for that.
But I ought to give you some ideas to work on. The general problem is that we may have a melody line which looks something like this:
and a harmony like this:
ie eis ef ihe ee
In other words the harmony notes do not have to be the same multiples of the basic beat time. (In ‘Jesu, Joy of Man’s Desiring’ they are; that’s what makes it an easy example).
Now, to take the above example, it means we have to send channel information as well as note and octave (and volume if we want crescendos and pianissimos). Considering just note and channel:
Note Channel(s) Channel code Chl Ch2 Cc D 1+2 3 G D 1+2 3 F D* 1 1 G D* 1 [ G D* I 1 A F 1+2 3
The starred notes could actually be anything because they aren’t played. We need to put them in if we continue to adopt a system in which every set of data has a fixed number of items. We don’t have to do this, although if we don’t, it becomes necessary to read one item at a time, checking for appropriate delimiters as we go. This may make the processing longer for some notes than others, and so mess up the rhythm.
ANSWER
Project 1 The DATA lines you need are:
5@ DATA 7, 3, 4 60 DATA 7, 3, 2 70 DATA 7, 3, 2 80 DATA 7, 3.4
11
98 DATA 8, 3, 2 100 DATA 10, 3, 2 110 DATA 12, 3, 2 120 DATA 10, 3, 2 130 DATA 10, 3, 2 140 DATA 12, 3, 4 150 DATA 12, 3, 2 160 DATA 10, 3, 2 170 DATA 3, 4, 6 180 DATA 10, 3, 2 196 DATA 8, 3, 4 200 DATA 7, 3, 4 210 DATA 7, 3, 3 220 DATA 8, 3, 3 230 DATA 19, 3, 2 240 DATA 5, 3, 8 250 DATA5, 3, 3 260 DATA 7, 3, 3 270 DATA 8, 3, 2 280 DATA 3, 3, 10 296 DATA 3, 3, 2 300 DATA 5, 3, 2 310 DATA 3, 3, 2 320 DATA 7, 3, 4 330 DATA 10, 3, 6 340 DATA 10, 2, 2 350 DATA 10, 2, 2 360 DATA 10, 2, 2 370 DATA 12, 2, 4 380 DATA 3, 3, 6 600 DATA 0, 6,
Of course, yqu’ll get different values if you used a different musical key.
112
How to get the computer to debug itself?
23 Debugging iV
In Chapter 18 I talked about dry-running a program, to trace by hand the flow of commands. The main flaw in this technique is that the user-—you—must do all the work: the Oric just sits there smugly telling you it has no idea what you’re talking about, or worse still, gives all the wrong answers. It’s time to make it work for its living.
It can be made to generate its own dry-run tables. Take the program used as an example in Chapter 18, for instance. It’s supposed to find the maximum and minimum ofa series of inputs. But it doesn’t! Here’s how to find out where the error(s) are. Add a line 5, to print out the table headings, and then on every line, print the line number and any value which is altered on that line, in the appropriate columns:
5 PRINT “LNVVVMAXVVMINVVNV V¥VBRANCH” 10 MAX = @: MIN = @: PRINT “10”; TAB(5); MAX; TAB(10); MIN 20 INPUT N: PRINT “20”; TAB(15); N 30 IF N< MIN THEN MIN =N: PRINT “30”; TAB(16); MIN 40 IF N > MAX THEN MAX = N: PRINT “40”; TAB(5); MAX 50 IF N<@ THEN PRINT MAX, MIN: END 60 PRINT ‘60; TAB(2@); “V”: GOTO 20
The TAB command just produces printing in the corresponding screen column. The form of the resulting table is slightly different from the hand produced one. Lines on which no alterations occur are not listed but, if anything, that makes it easier to follow. A more serious problem is that the input prompts and values break the table up. If you’ve got a printer, it’s easy to get over this one—just replace each PRINT with LPRINT and the table will appear on the printer. In any case, it’s better to have printed output to study because the chances are the table will occupy more than a screenful.
If you haven’t got a printer, you may wish to economize on the number of values printed. For instance, in this case, simply knowing the values in MAX and MINat the end of every loop will probably be enough. So it would be adequate just to add a line 55 to the original program:
55 PRINT MAX, MIN
You may want to change the variables to examine on different test runs. A neat trick is to edit a REM into a PRINT statement you want to deactivate, like this:
55 REM PRINT MAX, MIN
Since line 55 is now a comment, the computer will ignore it. If you want it back later, this saves you retyping the line—just edit out the REM.
113
So the Oric can tell us how its variables are changing. There are two other useful things it could do:
1. It could tell us which lines it executes, and in which order. 2. It could tell us how often it executes particular lines or blocks of code.
TRACES
The first of these features is built into BASIC. There are two commands. TRON (nothing to do with Walt Disney—it’s short for TRace ON) and TROFF (TRace OFF).
Try typing TRON:RUN as a direct command, with a program already in memory. You’ll see the line numbers, enclosed in square brackets, appear on the screen as the lines are executed. (The Manual says that TRON can’t be used in immediate mode, which is true; but it will work that way if followed by RUN as part of a single multistatement commana.)
Traces can be more confusing than useful if they are used with gay abandon. With any debugging procedure you must be careful to ask sensible questions, and then get the machine to provide the answers to just those questions. There’s no point in doing a complete dry run if all you want to know is whether a particular variable ever gets to 25. The more data you ask the machine to print, the longer it will take you to analyse it. So it is with traces. If you are sure that a particular block of code is executing correctly, why bother to trace it? In other words, you should use TRON and TROFF as program statements to turn the trace on and off while the program is running. By and large, we’ll be concerned to trace a program in the vicinity of branches.
Here’s an example. We write a piece of code which accepts a day of the month for use elsewhere in a program. It’s good practice to test the value entered to ensure that it’s in the range 1-31. We could do more sophisticated tests to check that the value isn’t greater than 29 if the month is February and so on, but we’ll stick to the simplest checks here.
Our first attempt might be:
50 INPUT “ENTER DAY OF MONTH”; D 60 IF D>0ORD < 32 THEN 200
70 PRINT “NOT A POSSIBLE DAY” 80 GOTO 50
200 REM HERE FOR A VALID DAY The program doesn’t behave correctly, so we could insert:
45 TRON 90 TROFF 205 TROFF
and edit 200: 200 TRON: REM HERE FOR A VALID DAY
to trace just the code under suspicion. (Be careful not to insert a line 195 TRON—it would never be executed because of the . . . THEN 200 on line 60.)
When this is run we find that, regardless of what value is entered for D, the trace always shows up as:
[50] [60] [200] [205] Line 70 cannot be reached. Line 6@ should have read: 60 IF D>@ AND D < 32 THEN 200
If you think about it, any number is either greater than 9 or less than 32! 114
This problem crops up fairly often, because we are rather careless in the way we use the words AND and OR in ordinary speech, and this carelessness can be transferred to our programming. Most of the time, in conversation, a listener has a fair idea what the speaker means, probably even before he has completed a sentence, so we can gét away with little inexactitudes.
The Oric is much more pedantic.
PROGRAM PROFILES
A program profile shows how many times each line of a program has been executed. As usual, this is overkill, and we should be selective about the parts of a program we want to profile. It’s easy enough to do. Suppose that we want to find out how many times line 420 of a particular program is executed. We set up a count to zero at the beginning of the program and then increment it by | every time line 420 is passed through:
5@ PC=90
420 A=A*(P-1) 421 PC=PC+1
809 PRINT PC 810 STOP Let’s look at a concrete example. The following program is intended to accept a
maximum of 2 values, terminated by zero, and sort them into ascending order. Thus if the input sequence is:
3 8
Ss Nv
the resulting output should be:
1 2 3 4 8
The zero should not appear since it is only a delimiter. 10 DIM A(20) 20 FOR P=1 TO 20 30 INPUT A(P) 40 IF A(P) = 0 THEN 60 50 NEXT P 66 N=P
HS .
116
65 70 80 90 1) 110 120 130 140 150 160 170
F=0 FOR P=1TON IF A(P) < A(P + 1) THEN 130
T = A(P) A(P) = A(P + 1) A(P + 1)=T F=1
NEXT P
IF F = 1 THEN 65 FOR P=1 TON PRINT A(P) NEXT P
The program doesn’t quite do the job. (Key it in and try it.) Im fact it gets into an endless
loop.
So where to start looking? The first loop (20-50) looks harmless enough, and the final one (150-170) is just printing out the contents of the array, A. It seems sensible then to concentrate on the loop from 70 to 139@. It is clear from line 8@ that sometimes all the statements in the loop are executed, and sometimes those from 99 to 120 are ignored. So we’ll have two profile counts, Cl and C2, which count the number of times the loop is entered and the number of times the last part of the loop is executed, respectively.
We can achieve this with:
67 68 75 125 132
Cl=0 C2=06 cl=Cil+1 C2=C2+1 PRINT Cl, C2
While we are at it, we might as well print out the contents of the array at the end of each loop because it is obvious that numbers are being shovelled about inside it and that very few other variables are being used at all. So:
134 135 136 137 138
FOR Q=1 TON (because | to N seems to be the PRINT A(Q); relevant chunk of the array) NEXT Q
FOR X = | TO 200: NEXT X (pause)
Let’s try a few data sets and see what happens; if we enter:
3 6
Ss NN wo
we get:
6 4 316500 6 4 130056 6 2 100356 6 2 001356 6-2 001356 6 1 001356 6 | 001356 and so on, indefinitely.
Well, it seems to be getting values in order but we’ve lost the ‘8’ and where did the pair of zeros come from? Also, it goes round the main loop 6 times consistently but the number of times round the subloop decreases steadily until it reaches 1, where it stays.
One of the zeros is obviously the delimiter, and the other one is an element of the array
which is not set during the run, but is initialized to zero by the system. In other words, the program is dealing with two values too many. So let’s rewrite line 60:
66 N=P-2 and try yet again. Hope beats eternal . . . We get:
4 2 3165
4 2 1356
4 0 1356
1
3 5 6
It’s progress of a kind: we’ve got rid of those zeros. But we still haven’t got our 8 back.
It’s hard to see how it can have got lost. Perhaps it’s still there, but not being printed out. Where do we PRINT it? Lines 150-170. The range | TO N must be too small. Let’s increase it by 1:
150 FORP=1TON+I1
And, of course, while we’re at it, the trace in line 134 is presumably having the same problems. So let’s fix that up too:
134 FORQ=I1TON+#+1
117
Ho hum; once more unto the breach, dear friends, once more. . . This time we get (for the same data):
3 5 6 8 Great! we’ve cracked it. It’s doing the job perfectly. Or is it? Let’s try: 3 5 2 1
5 0
This time we get:
etc.
118
It’s getting the right answer, but it never comes out of the loop. We notice that C2 never gets down to zero in this case so it’s a fair bet that this is what terminates the program.
What decides whether the program enters the subloop or not? Line 80:
80 IF A(P) < A(P + 1) THEN 130
The difference between the two data sets is that the second has two identical values in it. Since 5 is not less than 5 the subloop will be executed whenever the pair of 5s is encountered. That’s why the program always goes round the subloop once. Perhaps the condition should be:
80 IF A(P) <= A(P + 1) THEN 130
This time everything works.
Now it works like a charm and we can take out the test lines.
I hope I have illustrated a couple of important points here. Firstly, we haven’t needed to know exactly how the procedure works. If you’ve worked through this carefully, it’s probably fairly clear by now; and a few dry runs would probably convince you that you understand it. (Dry runs are a good way of understanding how computer procedures work. I’ve often done a dozen or so on some obscure piece of code—someone else’s, of course—before being really clear in my mind about what’s going on.) Secondly, there is always a temptation to believe that when a program runs successfully for the first time, the job is done and there’s time for a quick pint down the local. As we’ve seen, the job is not done, because there may be other sets of data for which the program fails; and anyway, the pub closed an hour and a half ago, if time goes as fast for you as it does for me when I’m writing code.
119
120
Every location in the Oric’s memory has its own address label. Two commands let you see what’s stored at a given address, and change it:
24 Peek and Poke
This chapter delves a little more deeply than the rest into the actual way the machine works. Ordinarily, in BASIC, the machine itself does most of the routine work for you; so you don’t need to worry about awkward questions like ‘whereabouts in memory does this stuff live?’ But I'll need to use the POKE command to set colours in high-resolution graphics (Chapter 26), and that command is intimately bound up with the way information is held in memory. So this chapter may help you understand how the later POKEs work. If you find it confusing, skip to the next chapter and come back later.
MEMORY ORGANIZATION
Computer memory is extremely systematic. Each memory location is given a fixed number, its address. Each address contains a number between @ and 255 (one character’s worth of information). This number is actually stored in binary, as a string of @s and Is. See the Manual, page 60, for the gory details.
Numbers between @ and 255 can be written using eight binary digits 0 or 1; for instance:
173 (decimal) = 10101101 (binary).
A string of eight binary digits, or bits, is called a byte. (There is a numbering system ‘intermediate’ between the two, called hexadecimal: see the Manual pages 60-63 if you’re interested.)
The computer has two types of memory:
1. ROM (Read Only Memory) which contains its operating system, the instructions that make it work.
2. RAM (Random Access Memory) which stores the things that can be changed: the BASIC program, screen displays, scratchpad for calculations, and so on.
You can alter the contents of RAM, but not of ROM. So the worst you can do by mucking about in memory is get the machine into a state that requires a RESET: you can’t mess up the operating system. This lets you experiment without having to worry about ill-effects on the machine: there are none!
The front end of ROM looks like Table 24.1. And there are a good many thousand more