Run this program:
10 FOR m=4 TO 1: BRIGHT m 20 FOR n=1 TO 14 30 FOR c=4 TO 7 40 PAPER c: PRINT " ";: REM 4 coloured spaces 50 NEXT c: NEXT n: NEXT m 60 FOR m=0 TO 1: BRIGHT m: PAPER 7 70 FOR c=0 TO 3 80 INK c: PRINT c;" "; 90 NEXT c: PAPER 0 100 FOR c=4 T0 7 110 INK c: PRINT c;" "; 120 NEXT c: NEXT m 130 PAPER 7: INK 0: BRIGHT 0
This shows the eight colours (including white and black) and the two levels of brightness that the ZX Spectrum can produce on a colour television. (If your television is black and white, then you will just see various shades of grey.) Here is a list of them for reference; they are also written over the appropriate number keys.
0 - black 1 - blue 2 - red 3 - purple, or magenta 4 - green 5 - pale blue, technically called cyan 6 - yellow 7 - white
On a black and white television, these numbers are in order of brightness.
To use these colours properly, you need to understand a bit about how the picture is arranged.
The picture is divided up into 768 (24 lines of 32) positions where characters can be printed, and each character is printed as an 8x8 square of dots like that below for a. This should remind you of the user-defined graphics in Chapter 14, where we had 0s for the white dots and 1s for the black dots.
The character position also has associated with it two colours: the ink, or foreground colour, which is the colour for the black dots in our square, and the paper, or background colour, which is used for the white dots. To start off with, every position has black ink and white paper so writing appears as black on white.
The character position also has a brightness (normal or extra bright) and something to say whether it flashes or not - flashing is done by swapping the ink and paper colours. This can all be coded into numbers, so a character position then has
Note that since the ink and paper colours cover a whole character position, you cannot possibly have more than two colours in a given block of 64 dots. The same goes for the brightness and flash number: they refer to the whole character position, not individual dots. The colours, brightness and flash number at a given position are called attributes.
When you print something on the screen, you change the dot pattern at that position; it is less obvious, but still true, that you also change the attributes at that position. To start off with you do not notice this because everything is printed with black ink on white paper (and normal brightness and no flashing), but you can vary this with the INK, PAPER, BRIGHT and FLASH statements. Try
and then print a few things: they will all appear on cyan paper, because as they are printed the paper colours at the positions they occupy are set to cyan (which has code 5).
The others work the same way, so after
PAPER number between 0 and 7 INK number between 0 and 7 BRIGHT 0 or 1 } Think of 0 as off or } and 1 as on FLASH 0 or 1 }
any printing will set the corresponding attribute at all the character positions it uses. Try some of these out. You should now be able to see how the program at the beginning worked (remember that a space is a character that has INK and PAPER the same colour).
There are some more numbers you can use in these statements that have less direct effects.
8 can be used in all four statements, and means 'transparent' in the sense that the old attribute shows through. Suppose, for instance, that you do
No character position will ever have its paper colour set to 8 because there is no such colour; what happens is that when a position is printed on, its paper colour is left the same as it was before. INK 8, BRIGHT 8 and FLASH 8 work the same way for the other attributes.
9 can be used only with PAPER and INK, and means 'contrast'. The colour (ink or paper) that you use it with is made to contrast with the other by being made white if the other is a dark colour (black, blue, red or magenta), and black if the other is a light colour (green, cyan, yellow or white).
Try this by doing
INK 9: FOR c=0 TO 7: PAPER c: PRINT c: NEXT c
A more impressive display of its power is to run the program at the beginning to make coloured stripes, and then doing
INK 9: PAPER 8: PRINT AT 0,8;: FOR n=l TO 1080: PRINT n;: NEXT n
The ink colour here is always made to contrast with the old paper colour at each position.
Colour television relies on the rather curious fact that the human eye can only really see three colours - the primary colours, blue, red and green. The other colours are mixtures of these. For instance, magenta is made by mixing blue with red - which is why its code, 3, is the sum of the codes for blue and red.
To see how all eight colours fit together, imagine three rectangular spotlights, coloured blue, red and green, shining at not quite the same place on a piece of white paper in the dark. Where they overlap you will see mixtures of colours, as shown by this program (note that ink spaces are obtained by using either SHIFT with 8 when in G mode):
10 BORDER 0: PAPER 0: INK 7: CLS 20 FOR a=1 TO 6 30 PRINT TAB 6; INK 1; "nnnnnnnnnnnnnnnnnn": REM 18 ink squares 40 NEXT a 50 LET dataline=20 60 GO SUB 1000 70 LET dataline=210 80 GO SUB 1000 90 STOP 200 DATA 2,3,7,5,4 210 DATA 2,2,6,4,4 1000 FOR a=1 TO 6 1010 RESTORE dataline 1020 FOR b=1 TO 5 1030 READ c: PRINT INK c;"nnnnnn";: REM 6 ink squares 1040 NEXT b: PRINT: NEXT a 1050 RETURN
There is a function called ATTR that finds out what the attributes are at a given position on the screen. It is a fairly complicated function, so it has been relegated to the end of this chapter.
There are two more statements, INVERSE and OVER, which control not the attributes, but the dot pattern that is printed on the screen. They use the numbers 0 for off and 1 for on in the same way as FLASH and BRIGHT do, but those are the only possibilities. If you do INVERSE 1, then the dot patterns printed will be the inverse of their usual form: paper dots will be replaced by ink dots and vice versa. Thus a would be printed as
If (as at switch-on) we have black ink and white paper, then this a will appear as white on black - but we still have black ink and white paper at that character position. It is the dots that have changed.
sets into action a particular sort of overprinting. Normally when something is written into a character position it completely obliterates what was there before; but now the new character will simply be added in on top of the old one (but see Exercise 1). This can be particularly useful for writing composite characters, like letters with accents on them, as in this program to print out German letters - an 'o' with an umlaut above it. (Do NEW first.)
10 OVER 1 20 FOR n=1 TO 32 30 PRINT "o"; CHR$ 8;""""; 40 NEXT n
(notice the control character CHR$ 8 which backs up one space.)
There is another way of using INK, PAPER and so on which you will probably find more useful than having them as statements. You can put them as items in a PRINT statement (followed by ;), and they then do exactly the same as they would have done if they had been used as statements on their own, except that their effect is only temporary: it lasts as far as the end of the PRINT statement that contains them. Thus if you type
PRINT PAPER 6;"x";: PRINT "y"
then only the x will be on yellow.
INK and the rest when used as statements do not affect the colours of the lower part of the screen, where commands and INPUT data are typed in. The lower part of the screen uses the colour of the border for its paper colour and code 9 for contrast for its INK colour, has flashing off, and everything at normal brightness. You can change the border colour to any of the eight normal colours (not 8 or 9) using statement
When you type in INPUT data, it follows this rule of using contrasting ink on border coloured paper; but you can change the colour of the captions written by the computer by using INK and PAPER (and so on) items in the INPUT statement, just as you would in a PRINT statement. Their effect lasts either to the end of the statement, or until some INPUT data is typed in, whichever comes first. Try
INPUT FLASH 1; INK 1;"What is your number?";n
There is one more way of changing the colours by using control characters - rather like the control characters for AT and TAB in Chapter 15.
CHR$ 16 corresponds to INK CHR$ 17 corresponds to PAPER CHR$ 18 corresponds to FLASH CHR$ 19 corresponds to BRIGHT CHR$ 20 corresponds to INVERSE CHR$ 21 corresponds to OVER
These are each followed by one character that shows a colour by its code: so (for instance)
PRINT CHR$ 16+CHR$ 9; . . .
has the same effect as
PRINT INK 9; . . .
On the whole, you would not bother to use these control characters because you might just as well use the colour items. However, one very useful thing you can do with them is put them in programs: this results in different parts being listed in different colours, to set them apart from each other or even just to look pretty. You must put them in after the line number, or they will just get lost.
To get these into the program, you have to enter them from the keyboard, mostly using extended mode with the digits.
The digits 0 to 7 set the corresponding colour- ink if CAPS SHIFT is also pressed, paper if it is not. More precisely, if you are in E mode and you press a digit (let us say 6 for yellow; at any rate it has to be between 0 and 7 - not 8 or 9) then two characters are inserted: first CHR$ 17 for PAPER, and CHR$ 6 meaning 'set it to yellow'. If you had been pressing CAPS SHIFT when you pressed the digit, you would have got CHR$ 16 meaning 'set ink colour' instead of CHR$ 17.
Since these are two characters you can get some odd effects when you rub them out - you must press DELETE twice, and after the first time you will often get a question mark or even odder things appearing. Do not worry; just press DELETE again.
and can also behave strangely while the cursor is moving past the control characters.
Still in extended mode,
8 gives CHR$ 19 and CHR$ 0 for normal brightness 9 gives CHR$ 19 and CHR$ 1 for extra brightness CAPS SHIFT with 8 gives CHR$ 18 and CHR$ 0 for no flashing CAPS SHIFT with 9 gives CHR$ 18 and CHR$ 1 for flashing
There are a couple more in ordinary (L) mode:
CAPS SHIFT with 3 gives CHR$ 20 and CHR$ 0 for normal characters CAPS SHIFT with 4 gives CHR$ 20 and CHR$ 1 for inverse characters
To summarize. here is a complete description of the top row on the keyboard:
The ATTR function has the form
ATTR (line column)
Its two arguments are the line and column numbers that you would use in an AT item, and its result is a number that shows the colours and so on at the corresponding character position on the television screen You can use this as freely in expressions as you can any other function.
The number that is the result is the sum of four other numbers as follows:
128 If the character position is flashing, 0 if it is steady 64 if the character position is bright, 0 if it is normal 8* the code for the paper colour the code for the ink colour
For instance, if the character position is flashing and normal with yellow paper and blue ink then the four numbers that we have to add together are 128, 0, 8*6=48 and 1, making 177 altogether. Test this with
PRINT AT 0,0; FLASH 1; PAPER 6; INK 1;" "; ATTR (0,0)
PRINT "B"; CHR$ 8; OVER 1;"/";
Where the / has cut through the B, it has left a white dot This is the way overprinting works on the ZX Spectrum: two papers or two inks give a paper, one of each gives an ink. This has the interesting property that if you overprint with the same thing twice you get back what you started off with. If you now type
PRINT CHR$ 8; OVER 1;"r'
why do vou recover an unblemished B?
PAPER 0: INK 0
- isn't it just as well that these don't affect the lower part of the screen? Now type
and see how well the computer looks after you!
10 POKE 22527+RND*704, RND*127 20 GO TO 10
Never mind how this works; it is changing the colours of squares on the television screen and the RNDs should ensure that this happens randomly. The diagonal stripes that you eventually see are a manifestation of the hidden pattern in RND - the pattern that makes it pseudorandom instead of truly random.
5 REM draw blank board 10 LET bb=1: LET bw=2: REM red and blue for board 15 PAPER bw: INK bb: CLS 20 PLOT 79,128: REM border 30 DRAW 65,0: DRAW 0,-65 40 DRAW -65,0: DRAW 0,65 50 PAPER bb 60 REM board 70 FOR n=0 TO 3: FOR m=0 TO 3 80 PRINT AT 6+2*n, 11+2*m;" " 90 PRINT AT 7+2*n, 10+2*m;" " 100 NEXT m: NEXT n 110 PAPER 8 120 LET pw=6: LET pb=5: REM colours of white and black pieces 200 DIM b$ (8,8): REM positions of pieces 205 REM set up initial positions 210 LET b$(1)="rnbqkbnr" 220 LET bS(2)="pppppppp" 230 LET b$(7)= PPPPPPPP 240 LET b$(8)="RNBQKBNR" 300 REM display board 310 FOR n=1 TO 8: FOR m=1 TO 8 320 LET bc=CODE b$(n,m): INK pw 325 IF bc=CODE" " THEN GO TO 350: REM space 330 IF bc>CODE "Z" THEN INK pb: LET bc=bc-32: REM lower case for black 340 LET bc=bc+79: REM convert to graphics 350 PRINT AT 5+n, 9+m; CHR$ bc 360 NEXT m: NEXT n 400 PAPER 7: INK 0