Author Topic: BASIC programming tips  (Read 54132 times)

0 Members and 2 Guests are viewing this topic.

Offline AMSDOS

  • Supporter
  • 6128 Plus
  • *
  • Posts: 3.871
  • Country: au
    • index.php?action=treasury
    • Programs for Turbo Pascal 3
  • Liked: 1078
  • Likes Given: 1823
Re: BASIC programming tips
« Reply #125 on: 08:48, 11 July 19 »
 :-[  Unfortunately I'm guilty of over complicating as usual by applying Math for LOCATE to use when the same result works without LOCATE and getting the job done in under 7 seconds with a Single Loop:


Code: [Select]
100 MODE 0:BORDER 0:INK 14,15:INK 15,9
110 DEFINT a-z
120 t1!=TIME
130 FOR a=1 TO 500
140   PEN INT(RND*15)+1
150   PRINT CHR$(248);
160 NEXT a
170 t2!=TIME
180 PEN 1:PRINT"Time =";(t2!-t1!)/300
190 END


I'm following up on this example from above to create a Game Screen with Ladders and Platforms using a Memory Array. It comes two parts, the 1st part fills the memory array with 32 (Lines 1010-1030), poke the platforms & pen colours to the memory array (Lines 1040-1070, Lines 140-180), Line 1060 also places gaps within the Platforms where the Ladders go, this is not needed through as Lines 1080-1090 place the Ladders over those areas from the Routine on lines 200-240. Lines 250-260 handles the Screen Character data and Lines 270-280 is used to store PEN colours.
Once that's done a Time is display onscreen for the Setup Time & Press any key to launch the 2nd part which draws the screen Lines 300-360 followed by the time it takes to do that. Just to play around with the Code a bit I added Line 311 which if the platform character is detected use PAPER 8 for it's background, otherwise it uses PAPER 0. Having that Line there also determines how fast the screen draws with different timings becoming the result as well as if Line 311 is commented, that also changes the Timings too.


Code: [Select]

100 MODE 2:BORDER 0:INK 1,26:INK 3,3
110 SYMBOL 255,255,0,24,36,66,129,0,255
120 SYMBOL 254,129,129,255,129,129,129,255,129
130 GOTO 1000
140 FOR x=1 TO 20
150   POKE &9FEB+x+(y*20),255
160   p=3:GOSUB 270
170 NEXT x
180 RETURN
200 FOR y=3 TO 20
210   GOSUB 250
220   GOSUB 270
230 NEXT y
240 RETURN
250 POKE &9FEB+x+(y*20),v
260 RETURN
270 POKE &A1EB+x+(y*20),p
280 RETURN
300 MODE 0:t1!=TIME
310 FOR a=0 TO 479
311   IF PEEK(&A000+a)=255 THEN PAPER 8 ELSE PAPER 0
320   PEN PEEK(&A200+a):PRINT CHR$(PEEK(&A000+a));
330 NEXT a
340 t2!=TIME
350 PEN 1:LOCATE 1,23:PRINT"Draw Time = ";USING"#.##";(t2!-t1!)/300
360 RETURN
1000 DEFINT a-z:MEMORY &9FFF:t1!=TIME
1010 FOR a=1 TO 500
1020   POKE &9FFF+a,32
1030 NEXT a
1040 FOR y=3 TO 21 STEP 3
1050   GOSUB 140
1060   IF y<>21 THEN x=2:v=32:GOSUB 250:x=18:GOSUB 250
1070 NEXT y
1080 x=2:v=254:p=1:GOSUB 200
1090 x=18:GOSUB 200
1100 t2!=TIME
1110 LOCATE 1,1:PRINT"Setup Time =";(t2!-t1!)/300
1120 CALL &BB18
1130 GOSUB 300
1140 END





* Using the old Amstrad Languages :D   * with the Firmware :P
* I also like to problem solve code in BASIC :)   * And type-in Type-Ins! :D

Home Computing Weekly Programs
Popular Computing Weekly Programs
Your Computer Programs
Updated Other Program Links on Profile Page (Update April 16/15 phew!)
Programs for Turbo Pascal 3

Offline Fabrizio

  • CPC464
  • **
  • Posts: 34
  • Country: fr
  • Liked: 16
  • Likes Given: 1
Reading character at given screen
« Reply #126 on: 23:32, 19 January 20 »
Is there a way in pure BASIC (+ possibly ROM-only routines) to read the character at a given position, e.g., cursor position.
I know the CPC only has graphics screens. I supposed that a text buffer is used. I have seen simply Assembly used in BASIC to do that. I have not found a BASIC-only (+ROM-only routines) solution. My solution has been to implement myself a buffer to remember the characters on the screen.

Does anyone here have a better idea?

Offline pelrun

  • Supporter
  • 6128 Plus
  • *
  • Posts: 620
  • Country: au
    • index.php?action=treasury
  • Liked: 312
  • Likes Given: 195
Re: BASIC programming tips
« Reply #127 on: 04:06, 20 January 20 »
BASIC 1.1 has COPYCHR$(), which will return the character at the cursor position. It does a graphical comparison against the character set, there's no internal char buffer.
Of course, that means 464's are out of luck, but the function is available in the ROM and can be accessed with a small asm routine. There's an example here: https://www.sean.co.uk/books/amstrad/amstrad2.shtm#COPYCHR
There's also some other examples of how to do it at http://www.cpcwiki.eu/forum/programming/study-of-464-only-game-helicopter-destination-saturn-from-acu/
« Last Edit: 04:09, 20 January 20 by pelrun »

Offline AMSDOS

  • Supporter
  • 6128 Plus
  • *
  • Posts: 3.871
  • Country: au
    • index.php?action=treasury
    • Programs for Turbo Pascal 3
  • Liked: 1078
  • Likes Given: 1823
Re: Reading character at given screen
« Reply #128 on: 07:35, 20 January 20 »
Is there a way in pure BASIC (+ possibly ROM-only routines) to read the character at a given position, e.g., cursor position.I know the CPC only has graphics screens. I supposed that a text buffer is used. I have seen simply Assembly used in BASIC to do that. I have not found a BASIC-only (+ROM-only routines) solution. My solution has been to implement myself a buffer to remember the characters on the screen.Does anyone here have a better idea?



As @pelrun mentioned COPYCHR$() is the function to use, apart from it being BASIC 1.1 only, the only other reason I can think of, of why not to use it, is a speed decrease during gameplay.


Other examples include Diamond Hunt. In those examples the BASIC 1.1 version uses COPYCHR$() and the screen is setup quicker than in my Revised version which used an array, but once the gameplay starts my version is faster than the original. In Bomb Drop which had a few COPYCHR$() in them, I replaced all that with a MEMORY Array and used POKE & PEEK to store and retreive the contents, it too has some setup time before the game starts, the original game can be found within the Depth Charge zip file in this thread, from memory the original had some problems if the Bombs were placed undernearth one another, which meant you couldn't get to them. When I switched the game to using a MEMORY Array, I was able to rectify that problem too.
Another approach (compatable on all systems) if you don't like Array's, is to use TEST(). Unfortunately TEST() only checks for a single Pixel using Graphical co-ordinates, though with Block calculations being used to obtain the XPOS & YPOS. The only problem with that is each graphic would need it's own Identifying Colour pixels and the TEST would have to be done on a spot where all Graphics has it's Colour Representation. I wrote a little BASIC game here, which does that.


It really up to you to decide what works best.
* Using the old Amstrad Languages :D   * with the Firmware :P
* I also like to problem solve code in BASIC :)   * And type-in Type-Ins! :D

Home Computing Weekly Programs
Popular Computing Weekly Programs
Your Computer Programs
Updated Other Program Links on Profile Page (Update April 16/15 phew!)
Programs for Turbo Pascal 3

Offline Sykobee (Briggsy)

  • 6128 Plus
  • ******
  • Posts: 769
  • Country: gb
  • Liked: 275
  • Likes Given: 398
Re: BASIC programming tips
« Reply #129 on: 14:28, 21 January 20 »
If you have a map or similar in-memory representation/abstraction of what is being displayed on screen, then always compare against the map rather than the very slow COPYCHR$ command.


Most games should have a map, or at least the current screen, in memory (2K for a full BASIC MODE 1 screen built up on character sized blocks, using an INT% array) - it all depends on the game really.

Offline AMSDOS

  • Supporter
  • 6128 Plus
  • *
  • Posts: 3.871
  • Country: au
    • index.php?action=treasury
    • Programs for Turbo Pascal 3
  • Liked: 1078
  • Likes Given: 1823
Re: BASIC programming tips
« Reply #130 on: 04:12, 25 January 20 »

For anyone interested, I made a simple comparision programme to test COPYCHR$, TEST using Functions, TEST using direct values and a BASIC Array (results in the Screenshot below).


The Test simply prints a Man moving Left to Right of the screen replacing and restoring background as it moves, the Gaps in the scenary are a part of testing TEST and have setup a short 2 byte array (a$) so if a gap is found 0 is returned and restores as printing that gap, otherwise it's CHR$(127), which represents 1.


Obviously with the test including COPYCHR$, this will be BASIC 1.1 only, the other tests are compatable in BASIC 1.0 and will work if Lines 210-350 are omitted.




Code: [Select]
100 MODE 1:DEFINT a-z:a$(0)=CHR$(32):a$(1)=CHR$(127):DIM m$(40):DEF FNxp=((x-1)*16):DEF FNyp=398-((y-1)*16)
110 BORDER 0:INK 0,11:INK 1,26
120 LOCATE 1,10:PRINT STRING$(40,127);
130 FOR x=1 TO 40:m$(x)=CHR$(127):NEXT x
140 FOR a=1 TO 3
150   x=(RND*38)+1
160   WHILE TEST(FNxp,398-(9*16))=0
170     x=(RND*38)+1
180   WEND
190   m$(x)=" ":MOVE FNxp,398-(9*16):TAG:PRINT CHR$(32);:TAGOFF
200 NEXT a
210 x=1:y=10
220 LOCATE x,y:a$=COPYCHR$(#0)
230 PRINT CHR$(250);
240 t1!=TIME
250 WHILE x<>40
260   LOCATE x,y
270   x=x+1
280   PRINT a$;
290   LOCATE x,y:a$=COPYCHR$(#0)
300   PRINT CHR$(250);
310 WEND
320 t2!=TIME
330 LOCATE 1,1:PRINT "COPYCHR$ Time =";USING"##.##";(t2!-t1!)/300
340 CALL &BB18
350 LOCATE 40,10:PRINT CHR$(127);
360 x=1:y=10
370 p=TEST(FNxp,FNyp)
380 MOVE FNxp,FNyp:TAG:PRINT CHR$(250);:TAGOFF
390 t1!=TIME
400 WHILE x<>40
410   MOVE FNxp,FNyp
420   x=x+1
430   TAG:PRINT a$(p);
440   MOVE FNxp,FNyp
450   p=TEST(FNxp,FNyp)
460   PRINT CHR$(250);:TAGOFF
470 WEND
480 t2!=TIME
490 LOCATE 1,2:PRINT "TEST using Functions Time =";USING"##.##";(t2!-t1!)/300
500 CALL &BB18
510 LOCATE 40,10:PRINT CHR$(127);
520 x=0:y=254
530 p=TEST(x,y)
540 MOVE x,y:TAG:PRINT CHR$(250);:TAGOFF
550 t1!=TIME
560 WHILE x<>624
570   MOVE x,y
580   x=x+16
590   TAG:PRINT a$(p);
600   MOVE x,y
610   p=TEST(x,y)
620   PRINT CHR$(250);:TAGOFF
630 WEND
640 t2!=TIME
650 LOCATE 1,3:PRINT "TEST with direct values Time =";USING"##.##";(t2!-t1!)/300
660 CALL &BB18
670 LOCATE 40,10:PRINT CHR$(127);
680 x=1:y=10
690 v$=m$(x)
700 LOCATE 1,10:PRINT CHR$(250);
710 t1!=TIME
720 WHILE x<>40
730   LOCATE x,y
740   x=x+1
750   PRINT v$;
760   LOCATE x,y
770   v$=m$(x)
780   PRINT CHR$(250);
790 WEND
800 t2!=TIME
810 LOCATE 1,4:PRINT "Array Time =";USING"##.##";(t2!-t1!)/300
820 END



* Using the old Amstrad Languages :D   * with the Firmware :P
* I also like to problem solve code in BASIC :)   * And type-in Type-Ins! :D

Home Computing Weekly Programs
Popular Computing Weekly Programs
Your Computer Programs
Updated Other Program Links on Profile Page (Update April 16/15 phew!)
Programs for Turbo Pascal 3

Offline mv

  • Supporter
  • CPC464
  • *
  • Posts: 34
  • Country: de
  • CPCBasic, CPCemu, CPC 6128
  • Liked: 75
  • Likes Given: 58
Re: BASIC programming tips
« Reply #131 on: 20:05, 25 January 20 »
For anyone interested, I made a simple comparision programme to test COPYCHR$, ...
Hey, great! Without knowing about your test (I will try it later), I also made a test for COPYCHR$, today. It has also some machine code for all CPCs...

Did you know that COPYCHR$ (or call &BB60, TXT RD CHAR) not only recognizes a character with the selected PEN, but also its inverse with the selected PAPER?
That means the PEN or PAPER can be pixelized without affecting the result, but not both. This also means that an inverted character cannot be recognized.
And if no PEN bits and no PAPER bits are set, there is a slight difference: The CPC 664/6128 returns space (char 32) and the CPC 464 the inverse of space (char 143).
Any more subtle findings?

Demo:
Code: [Select]
10 REM fancy - test copychr$
20 MODE 1:CLEAR:DEFINT a-z:RANDOMIZE TIME:PEN 1:PAPER 0
30 useCopychr=0: 'set this to use copychr$
40 c$=CHR$(&CD)+CHR$(&60)+CHR$(&BB)+CHR$(&32)+CHR$(0)+CHR$(0)+CHR$(&C9): 'call &BB60 (TXT RD CHAR)
50 fancy$="F"+CHR$(15)+CHR$(2)+"a"+CHR$(15)+CHR$(3)+"n"+CHR$(15)+CHR$(1)+CHR$(24)+"cy"+CHR$(24)+" s"+CHR$(14)+CHR$(2)+"t"+CHR$(14)+CHR$(3)+"u"+CHR$(14)+CHR$(0)+"ff"+"!"
60 LOCATE 1,1:PRINT fancy$;" ";fancy$
70 ' pixelize the first 12 characters
80 xstart=0
90 FOR i=1 TO 12
100 ckeep=1:IF i=2 OR i=3 OR i=7 OR i=10 THEN ckeep=0: 'the color to keep (1=pen or 0=paper)
110 FOR y=0 TO 7:FOR x=0 TO 7
120 xp=xstart+x*2:yp=399-y*2
130 IF TEST(xp,yp)=ckeep THEN 160
140 c=INT(RND*3+0.5):IF c=ckeep THEN 140
150 PLOT xp,yp,c :'set random color which is not the kept color
160 NEXT x,y
170 xstart=xstart+2*8
180 CALL &BD19:NEXT i
190 ' recognize characters in first line
200 a$="":FOR i=1 TO 12*2+1:LOCATE i,1:
210 GOSUB 290
220 a$=a$+t$
230 NEXT
240 LOCATE 1,5:PRINT a$;
250 t!=TIME+600:WHILE TIME<t! AND INKEY$="":CALL &BD19:WEND:LOCATE 1,5:PRINT CHR$(18);
260 GOTO 80
270 '
280 'call &BB60 (TXT RD CHAR) as COPYCHR$ on any CPC
290 IF useCopychr OR PEEK(&BB60)<>&CF THEN t$=COPYCHR$(#0):GOTO 330: 'flag set or CPCBasic
300 a%=UNT(PEEK(@c$+1)+PEEK(@c$+2)*&100)
310 CALL a%:b%=PEEK(0)
320 t$=CHR$(b%)
330 RETURN

(Can be found on: https://benchmarko.github.io/CPCBasic/cpcbasic.html?example=test/fancy)

Offline AMSDOS

  • Supporter
  • 6128 Plus
  • *
  • Posts: 3.871
  • Country: au
    • index.php?action=treasury
    • Programs for Turbo Pascal 3
  • Liked: 1078
  • Likes Given: 1823
Re: BASIC programming tips
« Reply #132 on: 22:14, 25 January 20 »
Did you know that COPYCHR$ (or call &BB60, TXT RD CHAR) not only recognizes a character with the selected PEN, but also its inverse with the selected PAPER?


Yes, I found out about that when I was fixing up Destination Saturn.

Quote
That means the PEN or PAPER can be pixelized without affecting the result, but not both. This also means that an inverted character cannot be recognized.


Quote
And if no PEN bits and no PAPER bits are set, there is a slight difference: The CPC 664/6128 returns space (char 32) and the CPC 464 the inverse of space (char 143).



er? As long as the PEN & PAPER checks match the colour when the COPYCHR$ check is done, it should be fine, but I found on a 464 it doesn't seem to matter.




Quote
Any more subtle findings?


If a different Graphical colour is used, COPYCHR$ won't pickup on it unless it's in the same colour scheme, I made a test programme of it here, which you've proabably seen.


* Using the old Amstrad Languages :D   * with the Firmware :P
* I also like to problem solve code in BASIC :)   * And type-in Type-Ins! :D

Home Computing Weekly Programs
Popular Computing Weekly Programs
Your Computer Programs
Updated Other Program Links on Profile Page (Update April 16/15 phew!)
Programs for Turbo Pascal 3

Offline AMSDOS

  • Supporter
  • 6128 Plus
  • *
  • Posts: 3.871
  • Country: au
    • index.php?action=treasury
    • Programs for Turbo Pascal 3
  • Liked: 1078
  • Likes Given: 1823
Re: BASIC programming tips
« Reply #133 on: 11:37, 15 February 20 »
I made a little routine to print out the Line Lengths of a BASIC programme, useful for working out which category your BASIC programme belongs in or adjusting it to size for those 10-Liners.


Code: [Select]
60000 a=&170
60010 v=PEEK(&170)
60020 n=0
60030 FOR l=1 TO 10
60040 PRINT v
60050 n = a + v
60060 a = n
60070 v = PEEK(n)
60080 CALL &BB18
60090 NEXT l
* Using the old Amstrad Languages :D   * with the Firmware :P
* I also like to problem solve code in BASIC :)   * And type-in Type-Ins! :D

Home Computing Weekly Programs
Popular Computing Weekly Programs
Your Computer Programs
Updated Other Program Links on Profile Page (Update April 16/15 phew!)
Programs for Turbo Pascal 3

Offline Gryzor

  • Administrator
  • 6128 Plus
  • *****
  • Posts: 15.813
  • Country: gr
  • CPC-Wiki maintainer
    • CPCWiki
  • Liked: 3335
  • Likes Given: 6007
Re: BASIC programming tips
« Reply #134 on: 12:31, 15 February 20 »
But this will increase your listing length 😄

Offline AMSDOS

  • Supporter
  • 6128 Plus
  • *
  • Posts: 3.871
  • Country: au
    • index.php?action=treasury
    • Programs for Turbo Pascal 3
  • Liked: 1078
  • Likes Given: 1823
Re: BASIC programming tips
« Reply #135 on: 14:04, 15 February 20 »
But this will increase your listing length 😄


Only to show a rundown of the process involved, it's that short a routine that it can be entered as a series of statements like this:


Code: [Select]
a=&170:v=PEEK(&170):n=0:FOR L=1 TO 10:PRINT v:n = a + v:a = n:v = PEEK(n):CALL &BB18:NEXT L

or from a KEY <num>,... statement.


The code works by obtaining the actual length of each line, BASIC programmes begin at &170 or 368 with the 1st byte representing that Line Length, so to get the Line Length of the second line and so on, the address (a) is added with the Line Length value (v) to get the new value (n) and then address (a) becomes that new value (n) and v becomes the next Line Length and so on until L = 10.


So I tested it on the Red's Exit game I wrote back in 2017 for the BASIC 10-Liners Contest and to my surprise 1 of the 10 Lines exceeded the Length category the game was put in, the funny thing about that is when a character count is carried out, it comes up shorter, which kind of explains why in some cases if too many variables are used on the same line a "Line Too Long" Error results.


Though here are the results I got from Red's Exit:
Code: [Select]
102
80
89
115
66
113
127
108
91
71
* Using the old Amstrad Languages :D   * with the Firmware :P
* I also like to problem solve code in BASIC :)   * And type-in Type-Ins! :D

Home Computing Weekly Programs
Popular Computing Weekly Programs
Your Computer Programs
Updated Other Program Links on Profile Page (Update April 16/15 phew!)
Programs for Turbo Pascal 3

Offline GFXOR

  • CPC664
  • ***
  • Posts: 55
  • Country: 00
    • Les Sucres en Morceaux
  • Liked: 62
  • Likes Given: 7
Re: BASIC programming tips
« Reply #136 on: 03:41, 30 April 20 »
The normal use of TAG / MOVE is that if you PRINT"HELLO EVERYBODY" too close from the right side of the screen, the text will be cut, where I would prerfer it to go on writing on the left. I guess the system is detecting if the text is exceeding the right limit of "640 pixels", where I would prefer it to going on writing wherever it is.

Do you know if there is a magical POKE to let the text write ?

Off-Topic:
Out of this subject :
As I am not really fluent english speaker, I don't read all the topics, so I juste discovered the old Morri question, 3 years after.
Quote from: Morri
Does anyone have some simple BASIC code to have the following sequence of numbers...
1 2 3 2 1 2 3 2 1 2 3 etc...
I can do it in the following code but just wondering if someone can do it faster
I am surprised not to have read a such simple solution :
Code: [Select]
10 FOR x=-1 to 2:PRINT 1+ABS(x);:NEXT
Supersly from the Les sucres en morceaux

Offline ZbyniuR

  • 464 Plus
  • *****
  • Posts: 320
  • Country: pl
  • 6128 A1230 PSX Win7
    • Jedyne polskie forum o CPC. :)
  • Liked: 344
  • Likes Given: 146
Re: BASIC programming tips
« Reply #137 on: 09:11, 07 May 20 »
Limits of graphics area are sets by command ORIGIN. If setting this way doesn't work, you can try by POKE.

Kernel guide shows adress of pixel x margin:

for 6128 at &B69B and &B69D (2byte both)
for  464 at &B330 and &B332

Let me know is it help. :)
In STARS, TREK is better than WARS.