A long while ago, I made an interpreter for a custom Turtle language in Hybrid BASIC for the 84+CSE. I have long wanted to port this to the CE using C. In fact, that was the impetus to turtle library diving the Spirographic Generative Art program.

Well, I started working on it. As with the previous version, parameters are evaluated using the operation system's eval, so all math and variables are supported.

You can find the readme in the github repo with more info on commands:
https://github.com/merthsoft/tugace/blob/main/readme.md

Still a work in progress. No release availble yet.

Here are some screenshots to show off what it's capable of so far.

A spiral:


Code: https://github.com/merthsoft/tugace/blob/main/programs/SPIRAL.txt

A more advanced spiral, using the OS variables:

With different inputs:


Code: https://github.com/merthsoft/tugace/blob/main/programs/SPIRAL2.txt


A tree, showing off the ability to push and pop the turtle state onto a stack at will:


Code: https://github.com/merthsoft/tugace/blob/main/programs/TREE.txt

I'm current working on GOSUB and RET for TREEFREC to work:
https://github.com/merthsoft/tugace/blob/main/programs/TREEFRAC.txt
So cool! The graphical demonstrations are very nice.

I think it was a great idea to use the calculators ability to eval and such, lots of flexibility!
Yeah, makes it a lot easier for me, too, because then I don't need to worry about variables and such. And all commands can take lists, where it will use the first X elements where X is the number of params. So FORWARD L1 is the same as FORWARD L1(1 and GOTO L1 is the same as GOTO {L1(1),L1(2). Additionally, complexes are accepted, but the imaginary value is dropped. So you can do wild imaginary stuff if you want.

GOTO and LABEL actually work the same way. LABEL A doesn't create a label called A. It creates assigns the label number that A evaluates to. So if A is 13.2, LABEL A creates LABEL 13 at that spot. Labels only support real and complex values right now, not lists, so a small limitation. But I suspect I'll combine some of that code to make it easier and then that won't be the case.

I'm curious how people feel about this part of the spec:
https://github.com/merthsoft/tugace/blob/main/readme.md#additional-shorthands

Then programs could be written more tersely. E.g. SPIRAL would look like:

Code:
TURT:Return
"DRAWS A SPIRAL
R0
P1
0F
:1
?F/4=iPart(F/4
CrandInt(0,255
^F
(92
+F
.1


Which is equivalent to:

Code:
TURT:Return
"DRAWS A SPIRAL
CLEAR 0
PEN 1
ZERO F
LABEL 1
IF F/4=iPart(F/4
COLOR randInt(0,255
FORWARD F
LEFT 92
INC F
GOTO 1


No matter what I'm keeping the colon for label definitions just because it makes them stand out and therefore more readable. The programmer could of course pick which shorthands they prefer to use. It would see a small performance increase.

Some additional design thoughts I had:

- I want to support using colon as a line delimiter. This is easy enough in the code. I just need to then
choose a different shorthand for LABEL. Perhaps pi.
- Right now, the interpreter is a big switch statement on non-contigurous values which are the commands hashed. This performs ok because it can be optimized to a binary search. Shorthands are turned into their equivalent hash.
- This will be changed to be a switch on contiguous values to make use of potentially a jump table. To that end, shorthands will be converted to their opcodes, as well as hashes, and then the switch will drive that.
- Given that change, I have planned a pre-processor pass which will pre-cache labels (where static) and tokenize the commands to their opcode value, thus the translation doeasn't need to happen on the fly and performance will improve.
- Tokenized commands will include pre-computed versions where operands have already been evaluated. This is appropriate if it's a constant value rather than a variable

Stack thoughts:
- There will be a system stack for GOSUB, RET, and any other commands that need a stack
- This is STACK -1 in terms of stack commands, you can access it as a programmer and do nasty things so beware
- The idea is to have a stack per turtle. You choose which stack is active, though, so it's up to you if you follow convention.
- It's one contiguous block of memory, one stack after the other. Right now you can't bleed over to other stacks, but It hink I will change that. So it's more like stack pages than separate stacks.

Header/launcher
- Soon it will check for program name in Ans and run that program. This will allow the Tuga programs to launch TUGA itself from the header.
- If it's launched without a valid program name in Ans, it'll have a little shell to select program, and only list them if they have the header "TUGA:"
- The first comment in the program (the second line after the header) is a description of the program. Up to you what you put.
- After the standard header will be an optional second comment which serves as the flags comment. This is how you will tun on the pre-processor and possibly various debugging flags and such
I finished GOSUB and RET, and added FADEIN and FADEOUT. Also, when done, you can press enter to restart from the top.


Code:
TURT:Return
"Draws a tree fractal, by Shaun McFall
FADEOUT 2
COLOR 126
PEN 0
MOVE {160,200
STO {I,80
STO {G,5
CLEAR 0
FADEIN 10
PEN 1
COLOR randInt(135,255
FORWARD I
STACK 3
PUSHVEC
PUSH 0
PUSH 0
,0
STACK 1
PUSHVEC
STO {I,I/1.5
LEFT 60
COLOR randInt(135,255
FORWARD I
STACK 3
PUSHVEC
PUSH G
PUSH I
STACK 1
POPVEC
RIGHT 60
COLOR randInt(135,255
FORWARD I
DEC G
IF G<=0
GOSUB 1
.0
,1
STACK 3
POP
POP
POPVEC
POP
STO {I,Ans
POP
STO {G,Ans-1
POPVEC
IF G>0
RET


You can see here that I've changed the shorthand for label to comma, and goto to period. I may revert to a colon for label as I debate with myself whether to support colon-delimited lines.
I made some further progress today. I have fixed some bugs in the palette handling and fading in and out, as well as improved performance in the drawing code. No screenshots to share, but here's a screenshot of the planned remaining commands:

(POP [var] was removed, actually, because of ambiguity.)

On top of those remaining commands, the following is planned:
1) Start program from Ans when invoked
2) Small shell to browse TUGA programs
3) Shorthand commands
4) Pre-processor (Tokenize commands, pre-compute labels where able, some other things)
5) Invoking other TUGA programs from within a program
6) Tilemap support
Today I mostly did some under the hood stuff. However, I did add a new command, INIT, which returns the currently selected turtle to the initial conditions. I also implemented some OS BASIC token shorthands. Here's the familiar pretty spiral:

And this is the code for is:
SourceCoder 3 (SPIRALB) wrote:
:TUGA:"SPIRALB":prgmTUGA:Return
:"Draws a spiral
:Lbl 0
:INIT
:CLEAR 0
:PEN 1
:ZERO F
:COLOR randInt(1,255
:Lbl 1
:If F/4=iPart(F/4
:COLOR randInt(1,255
:FORWARD F
:LEFT 92
:INC F
:If F<150
:Goto 1
:Goto 0


You can see I'm using Lbl and Goto and If from the OS commands. Additionally, "LEFT" here is an OS token that's being interpreted as the "LEFT" command. Another one I added earlier is that "POPVEC" can use the single "PV" token. Good for when types on the computer.

I do still plan on supporting a more complete shorthand as well. The idea being the most used things are all on the main keyboard. So the above program could also be written like this:
SourceCoder 3 (SPIRALSH) wrote:
:TUGA:"SPIRALSH":prgmTUGA:Return
:"Draws a spiral
::0
:[i]
:R0
:P1
:0F
:CrandInt(0,255
::1
:?F/4=iPart(F/4
:CrandInt(0,255
:^F
:(92
:+F
:?F<100
:.1
:.0


I also did some work on the readme. It's got a lot of sections now:
Today I worked on letting PUSH accept a list, and POP accept a variable, as well as the RECT command. It will draw an empty rectangle if the pen is down, otherwise it will draw a filled rectangle. I did this in order to more easily implement this fractal:



Code:
TUGA:"SQUARES":prgmTUGA:Return
Draws fractal squares
FADEOUT 2
PEN 0
COLOR 0
CLEAR 0
FADEIN 10
PUSH {0,0,320,240
GOSUB 0
:1
.1
:0
}H
}W
}Y
}X
?H<=15
RET
COLOR randInt(1,255
MOVE {X,Y
RECT {W/2,H/2
PUSH {X,Y+H/2,W/2,H/2
PUSH {X+W/2,Y,W/2,H/2
PUSH {X+W/2,Y+H/2,W/2,H/2
*0
*0
*0
RET


The is recursively drawing a squares.

An animated PNG of it drawing:


As a fun milestone, I recently passed 1,000 significant lines of C code for this project, which is about the same amount of code in Block Dude CE.
I'm trying to think of how to grant access to the turtle's internal values for reading. You can right now do a PUSHVEC and then POP W\POP P\POP C\POP A\POP Y\POP X to have Width, Pen, Color, Angle, Y and X. Seven commands just to get the Turtle's X value into X seems excessive. So I'm thinking either something like:

Code:
GETPOS {X,Y
GETANGLE A
GETCOLOR C
GETPEN P
GETWIDTH W

GETVEC
GETVEC {X,Y,A,C,P,W

First five get values directly. Other two let yo get the turtle into Ans (first one) or the vars that are passed in (second one) in-order and anything left out is just ignored, so GETVEC {D,E,Z,C would have the turtle's location in D,E, angle in Z, and color in C.

Additionally, a SETVEC that takes in a list and can set the turtle vector based on that list. This gives the progammer more direct control over the values in a direct way. SETVEC {X,Y then becomes an easy way to teleport without having to deal with the pen. I will need to decide if that wraps based on the t->wrap parameter.
I started to work on key input. Here's a picture:

Here's the code to do that:
SourceCoder 3 (KEYSCAN) wrote:
:TUGA:Return
:"keyscan test
:CLEAR 0
:COLOR 128
:INIT 0
::0
:KEYSCAN
:KEYDOWN 21
:?Ans
:COLOR randInt(1,255
:KEYDOWN 24
:?Ans
:LEFT 10
:KEYDOWN 26
:?Ans
:RIGHT 10
:KEYDOWN 25
:?Ans
:FORWARD 5
:FORWARD 5
:GOTO 0


Those familiar with BASIC should recognize those keycodes. Right now, KEYDOWN returns 1 in ans if the key is down. Originally, I had planned on making it work like If, but I think having it in Ans is better. GETKEY will also put the key in ans, or in the var passed in.
  
Register to Join the Conversation
Have your own thoughts to add to this or any other topic? Want to ask a question, offer a suggestion, share your own programs and projects, upload a file to the file archives, get help with calculator and computer programming, or simply chat with like-minded coders and tech and calculator enthusiasts via the site-wide AJAX SAX widget? Registration for a free Cemetech account only takes a minute.

» Go to Registration page
Page 1 of 1
» All times are UTC - 5 Hours
 
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum

 

Advertisement