Jump to content
IGNORED

Any interest in Atari LOGO examples?


Recommended Posts

Hey all, what's the best way to post code here for everyone to easily import it into your emulator or Fujinet or whatever? Keep on posting it as text in the Code widget, attach it as a CR/LF formatted text file, an Atari formatted file straight from the .ATR, what? Some of my little projects are getting to be over 4KB, like the bouncing turtles and an incremental Sieve of Eratosthenes using a min heap of the next multiple of the primes. In Altirra 4.10 it can find the primes up to about 1600 in under an hour and a half before running out of nodes. (That 4KB RAM soaked up by DOS is beginning to hurt!) I'm sure the code would be cumbersome to copy if pasted into a post.

 

EDIT: Launching LOGO with no DOS and that extra 4K of free RAM makes a huge difference. The sieve now finds the primes under 1600 in about 2600 seconds and up to 2333 in 4500 seconds, with Altirra in Warp Speed and using the system jiffies counter to time it. That node churn is a killer! I guess it's back to LOAD  "C: for me 🙃

Edited by yetanothertroll
  • Like 1
Link to comment
Share on other sites

  • 2 weeks later...

Another rainy weekend, time to launch LOGO :)

 

it seems MAKE is every bit as dangerous as I thought, but it can also make code like QSORT back on page 3 much easier to read, especially on a 40 character wide display. But first, madness:

forever.thumb.png.c7e732b8e28ee3d42cc04d978347ce27.png

FOREVER is cribbed from pg. 261 of the Apple Logo II Reference Manual. Similar shenanigans can be done with MAP, WHILE, or most anywhere else you see a call to RUN

 

Maybe code like QSORT is clearer if done with mutable local variables, maybe not. Opinions?

qsort.thumb.png.a1c106e47db66577e6dcbcf210448f40.png

TO QSORT :LIST
IF EMPTYP :LIST [OUTPUT :LIST]
OP QSORT.1 FIRST :LIST "NIL "NIL BUTFIRST :LIST [] []
END

TO QSORT.1 :PIVOT :FIRST :ISLESS :RESTOFLIST :TOLEFT :TORIGHT
IF EMPTYP :RESTOFLIST [OUTPUT SE ( QSORT :TOLEFT ) FPUT :PIVOT ( QSORT :TORIGHT )]
MAKE "FIRST FIRST :RESTOFLIST
MAKE "ISLESS :FIRST < :PIVOT
MAKE "RESTOFLIST BUTFIRST :RESTOFLIST
IF :ISLESS [MAKE "TOLEFT FPUT :FIRST :TOLEFT]
IF NOT :ISLESS [MAKE "TORIGHT FPUT :FIRST :TORIGHT]
OP QSORT.1 :PIVOT "NIL "NIL :RESTOFLIST :TOLEFT :TORIGHT
END

TO RANDUMB :N :MAX
IF :N < 1 [OUTPUT []]
OP FPUT RANDOM :MAX RANDUMB :N - 1 :MAX
END

Here's an example run using a random list generated with RANDUMB

qexample.thumb.png.2e6047e693cf5068c8ef780a9cdb06db.png

  • Thanks 1
Link to comment
Share on other sites

  • 1 month later...
On 10/28/2023 at 12:08 PM, ascrnet said:

 

Hi @yetanothertroll

 

I recommend a good logo book rather than making geometric figures, this one contains several games. 😉

 

greetings

I do have a couple of projects kicking around that could be turned into a game or two if I didn't keep running out of nodes. BOUNCE.LG (launched by BOUNCE) has the turtles bouncing off the walls and each other. Except when an automatic garbage collection happens at the wrong time. GRAVITY.LG (launched by DRIVER) is halfway to the 60s SPACEWAR / 70s Computer Space game. I can't get much further with either one without falling back to using the cassette instead of disk, and I'm running into situations in which a project can be edited, run, and saved but is then too big to reload, even after a cold reset. .CAS files are easy enough to attach to posts here, but what about folks using real hardware instead of Altirra or maybe a800? I think I can come up with a Logo program that does its own buffering to copy files from disk to cassette without corrupting the tape, maybe even very large files. If weekends here get very rainy and I get very ambitious, maybe even something that can catenate a list of disk or cassette files to a single file? It might be possible to catenate multiple tape files to a single disk file but probably not tape to tape. Unless. Hmm. A multiple pass project sorter that could handle ridiculously large projects that 8-bit Logo couldn't possibly actually load and run? There's no engineering like absurd overengineering! 😄

Gravity1.png

Gravity2.png

B7.png

B6.png

GRAVITY.LG BOUNCE.LG

Edited by yetanothertroll
There's always room for one more quip
Link to comment
Share on other sites

  • 4 weeks later...

I guess I just can't get enough of those geometric figures. This time it's a fractal that maybe Logo isn't so well suited for, the Mandelbrot Set! I adapted it from a screenshot of BASIC code found here: https://hackaday.com/2020/06/23/boot-to-basic-box-packs-a-killer-graphics-engine/

 

The turtles did come in handy for sidestepping having to convert between the languages' differing coordinate systems. I just sort of used them like carriages on old school typewriters. Maybe I should add some typewriter sound effects when I advance them one y coordinate and back them up to the left 😄

 

Let's see if a deeplink to the screenshot of the BASIC code I stole ripped off plagiarized 'adapted' will load:

https://hackaday.com/wp-content/uploads/2020/06/cmax800d.png

 

I guess not? Anyway, here's a frame grab from Altirra running the Logo code and the code. The lines on the far left and right are to make sure the turtles aren't drifting due to an off-by-one error in the program or maybe some sort of cumulative error in XCOR like what happens in the fractal trees. And be patient. Each pixel can take up to around eight seconds or so to calculate even after my attempts to optimize it in MANDEL.ITER and MANDEL.ITER.1.

Mandel.thumb.png.2060296cea810e42a9a63d9713df1adb.png

TO MANDEL
CS
MANDEL.1 77 158 * 2 1 + ( 119 * 2 )
END

TO MANDEL.1 :MAXX :W :H
MANDEL.2 1 + ( :H / 2 )
END

TO MANDEL.2 :HH
TELL [0 1]
PU
ASK 1 [RT 180]
FORWARD :HH + 1
ASK 0 [RIGHT 90]
ASK 1 [LEFT 90]
FORWARD :W / 2
MANDEL.PY 0
END

TO MANDEL.PY :PY
IF :HH < :PY [STOP]
PD
SETPN 2
FORWARD 1
BACK 1
PU
BACK :W
ASK 0 [RIGHT 90]
ASK 1 [LEFT 90]
FORWARD 1
ASK 0 [LEFT 90]
ASK 1 [RIGHT 90]
PD
SETPN 1
BACK 1
FORWARD 1
MANDEL.PY.1 1.042 * ( ( ( :PY / :H ) * 2 ) - 1
END

TO MANDEL.PY.1 :SCALEY
( PR :PY :SCALEY
MANDEL.PX 0
MANDEL.PY :PY + 1
END

TO MANDEL.PX :PX
IF NOT ( :PX < :W ) [STOP]
MANDEL.PX.1 ( ( :PX / :W ) * 2.5 ) - 2
END

TO MANDEL.PX.1 :SCALEX
MANDEL.PLOT MANDEL.ITER 0 0 0
MANDEL.PX :PX + 1
END

TO MANDEL.PLOT :I
( PR :PY :PX :SCALEY :SCALEX :I
SETPN IF :I < 15 [2] [IF :I < :MAXX [0] [1]]
IF :I < 10 [PU] [PD]
FORWARD 1
END

TO BETWEEN :I :MIN :MAX
IF :I < :MIN [OUTPUT FALSE]
IF :I > :MAX [OUTPUT FALSE]
OUTPUT TRUE
END

TO MANDEL.ITER :I :X :Y
IF :I = :MAXX [OUTPUT :I]
OP MANDEL.ITER.1 :X * :X :Y * :Y
END

TO MANDEL.ITER.1 :X2 :Y2
IF 4 < :X2 + :Y2 [OUTPUT :I]
OP MANDEL.ITER :I + 1 :X2 - :Y2 + :SCALEX ( 2 * :X * :Y ) + :SCALEY
END

 

MANDEL.LG

  • Like 1
Link to comment
Share on other sites

  • 3 weeks later...

Well this is inconvenient: It appears that at least in both Altirra/x64 4.20 and in Colleen, the apparently "official" port of Atari800 to Android, booting Logo from diskette or cassette will cause TOOT to reject frequencies under 62, while launching Logo from ROM causes TOOT to accept frequencies down to 14, even with Atari DOS loaded. Colleen only appears to like the .CAR version of the Logo ROM dump. This is impacting my 1930 Model 15 Teletype sound effects for the Mandelbrot program 😄

Edited by yetanothertroll
Added a link to a second video with the tty bells
Link to comment
Share on other sites

Happy Valentine's Day everyone! How many big fibs have you had to tell today?

 

This program started off as simply printing the Fibonacci sequence using bignums, stored as lists of integers between [0 .. 999999999], but it kind of got away from me. There are now functions to compare them, multiply, check if they're odd or even, and convert ordinary numbers like 9.87654321e+97. There's no need to use TOBIG on 0, 1, 2, ..., 9, but 12 will be interpreted as 2000000001 and 1.2 will throw an error.

 

Exponentiation, tetration, debugging cruft cleanup, adding even more ridiculous checks to DOUBLEDOWN, etc., are left as exercises for the student

 

TO BIGFIB
BIGFIB.1 BIGTEE 0 BIGTEE 1
END

TO BIGADD :B1 :B2
OUTPUT REVERSE BIGADD.1 :B1 :B2 0 []
END

TO BIGADD.1 :B1 :B2 :CARRY :RESULT
IF ( AND EMPTYP :B1 EMPTYP :B2 0 = :CARRY ) [OUTPUT :RESULT]
OP BIGADD.2 SAFEBF :B1 SAFEBF :B2 ( SUM SAFEF :B1 SAFEF :B2 :CARRY )
END

TO BIGADD.2 :B1 :B2 :NEW
OP BIGADD.1 :B1 :B2 ( INT ( :NEW / 1000000000 ) ) FPUT ( REMAINDER :NEW 1000000000 ) :RESULT
END

TO BIGEQ :B1 :B2
IF AND EMPTYP :B1 EMPTYP :B2 [OUTPUT TRUE]
IF NOT ( ( SAFEF :B1 ) = ( SAFEF :B2 ) ) [OUTPUT FALSE]
OUTPUT BIGEQ SAFEBF :B1 SAFEBF :B2
END

TO BIGEVEN :B1
IF EMPTYP :B1 [OUTPUT TRUE]
OUTPUT 0 = REMAINDER FIRST :B1 2
END

TO BIGFIB.1 :B1 :B2
BIGFIB.1 :B2 BIGTEE BIGADD :B1 :B2
END

TO BIGHALF :B1
OUTPUT BIGHALF.1 REVERSE :B1 0 []
END

TO BIGHALF.1 :B1 :CARRY :RESULT
IF EMPTYP :B1 [OUTPUT :RESULT]
OP BIGHALF.1 BUTFIRST :B1 ( REMAINDER FIRST :B1 2 ) FPUT ( :CARRY * 500000000 ) + INT 0.5 * FIRST :B1 :RESULT
END

TO BIGMUL :B1 :B2
OUTPUT BIGMUL.1 :B1 :B2 0
END

TO BIGMUL.1 :B1 :B2 :RESULT
BIGTYPE :B1
TYPE [*]
BIGTYPE :B2
TYPE [+]
BIGTYPE :RESULT
PRINT []
IF OR BIGZERO :B1 BIGZERO :B2 [OP :RESULT]
OP BIGMUL.1 ( BIGADD :B1 :B1 ) ( BIGHALF :B2 ) IF BIGEVEN :B2 [:RESULT] [BIGADD :B1 :RESULT]
END

TO BIGODD :B1
IF EMPTYP :B1 [OUTPUT FALSE]
OUTPUT 0 < REMAINDER FIRST :B1 2
END

TO BIGTEE :B1
BIGTYPE :B1
TYPE CHAR 32
SHOW :B1
OUTPUT :B1
END

TO BIGTYPE :B1
BIGTYPE.1 REVERSE :B1 TRUE
END

TO BIGTYPE.1 :B1 :FIRST
IF AND :FIRST EMPTYP :B1 [TYPE 0 STOP]
IF EMPTYP :B1 [STOP]
IF NOT :FIRST [BIGTYPE.2 FIRST :B1 100000000]
IF AND :FIRST 0 < FIRST :B1 [TYPE FIRST :B1]
BIGTYPE.1 BUTFIRST :B1 AND :FIRST 0 = FIRST :B1
END

TO BIGTYPE.2 :N :D
IF :D = 1 [TYPE :N STOP]
TYPE INT :N / :D
BIGTYPE.2 REMAINDER :N :D INT :D / 10
END

TO BIGZERO :B1
IF EMPTYP :B1 [OUTPUT TRUE]
IF 0 < FIRST :B1 [OUTPUT FALSE]
OUTPUT BIGZERO BUTFIRST :B1
END

TO DOUBLEDOWN :N
DOUBLEDOWN.1 BIGTEE TOBIG :N
END

TO DOUBLEDOWN.1 :B1
DOUBLEDOWN.1 BIGTEE BIGMUL 2 BIGHALF BIGADD :B1 :B1 BIGHALF BIGADD :B1 :B1
END

TO REVERSE :LIST
OUTPUT REVERSE.1 :LIST []
END

TO REVERSE.1 :LIST :RESULT
IF EMPTYP :LIST [OUTPUT :RESULT]
OP REVERSE.1 BUTFIRST :LIST FPUT FIRST :LIST :RESULT
END

TO SAFEBF :B1
OP IF EMPTYP :B1 [:B1] [BUTFIRST :B1]
END

TO SAFEF :B1
OUTPUT IF EMPTYP :B1 [0] [FIRST :B1]
END

TO TOBIG :N
IF :N = 0 [OUTPUT []]
IF :N < 0 [OUTPUT TOBIG - :N]
OUTPUT FPUT REMAINDER INT :N 1000000000 TOBIG INT :N / 1000000000
END

 

bigfib.png

bigmul.png

BIGFIB.LG

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...