Programs and Procedures: the Basics
The simplest BASIC programs take this form:
REM [program commands] END
The first couple of Turtle example programs (from the Examples menu) are like this. But the ‘Olympic rings’ program introduces a global variable: it is called ringsize%
and specifies the size of the rings. Such variables are ‘declared’ by assigning a value, like this:
ringsize% = 130 REM [other program commands] END
Complicated programs are usually divided into subroutines, to separate the various tasks and make them easier to understand. BASIC has two types of subroutine, procedures (which are like mini-programs) and functions (which are designed to calculate some value).
The ‘Simple procedure’ example program has a procedure to draw a ‘prong’ – a line ending in a blot – and then return to the starting point. Procedures fit into a BASIC program after the end of the main program, indicated by END
. They look like this:
DEF PROCmyprocedure(par1%) LOCAL local1%, local2$ REM [procedure commands] ENDPROC
All procedure names must begin with ‘PROC’, e.g. PROCmyprocedure
. A procedure can have its own local variables, declared using LOCAL
. A PRIVATE
variable is declared the same way, but unlike a LOCAL
variable, it retains its value between procedure calls. A procedure can also have parameters (or ‘arguments’) that are values sent into the subroutine when it is called from the program, and given a name within the subroutine (e.g. par1%
above).
A function is similar to a procedure, with the addition that it returns a value. Also a function name must begin with ‘FN’, for example:
DEF FNmyfunction$(par1%) REM [procedure commands] = "output"
The last statement of a function always begins with =
and the "output"
provides the return value for the function. If a function returns a string (as above), then its name must end with $
; otherwise an integer return type will be assumed.
Reserved Words, Declarations, Types, and Variables
The words REM
, END
, DEF
, etc. are all capitalized to emphasise the program structure. BASIC takes notice of capitalization. These three words are also in red here (or gray for comments) – this is to indicate that they are special ‘reserved’ words that cannot be used for other purposes (so you can’t call a procedure or variable ‘END’).
Variables all end with either a ‘%’ or a ‘$’ – Turtle will tell you if you forget! Turtle BASIC allows two types of variables:
integer | whole number (name ends in ‘%’) |
---|---|
string | sequence of characters (name ends in ‘$’) |
Most of your variables are likely to be integer variables, like a transparent box that stores a number. You can look at the box to see which number it contains at any time, and you can change the number by assigning a new value. In the ‘Olympic rings’ example program, ringsize%
is declared by assigning the value 130
using the command:
ringsize% = 130
Six special integer variables are ‘built in’ from the start, and these are called the Turtle’s fields:
turtx% | The Turtle’s x-coordinate |
---|---|
turty% | The Turtle’s y-coordinate |
turtd% | The Turtle’s direction |
turta% | The Turtle’s angles |
turtt% | The Turtle’s pen thickness |
turtc% | The Turtle’s colour setting |
These automatically change to keep track of the Turtle’s state, and are shown above the Canvas.
For a use of turtd%
, see the ‘Simple procedure’ example.
Programs and Procedures: the Basics
Documentation for Turtle C is still being prepared. Please check back here soon.
Programs and Procedures: the Basics
Documentation for Turtle Java is still being prepared. Please check back here soon.
Programs and Procedures: the Basics
The simplest Pascal programs take this form:
PROGRAM myprog; BEGIN {program commands} END.
The first couple of Turtle example programs (from the Help menu) are like this. But the ‘Olympic rings’ program introduces a global variable: it is called ringsize
and specifies the size of the rings. Such variables are ‘declared’ at the beginning of the program, like this:
PROGRAM myprog; VAR global1: integer; global2, global3: integer; BEGIN {program commands} END.
Complicated programs are usually divided into subroutines, to separate the various tasks and make them easier to understand. Pascal has two types of subroutine, procedures (which are like mini-programs) and functions (which are designed to calculate some value). The ‘Simple procedure’ example program has a procedure to draw a ‘prong’ – a line ending in a blot – and then return to the starting point. Procedures fit into a Pascal program after the global variables and before the BEGIN
of the main program; they look like this:
Procedure myprocedure(par1: integer); Var local1, local2: integer; Begin {procedure commands} End;
A procedure can have its own local variables, declared much like global variables. But it can also have parameters (or ‘arguments’) that are values sent into the subroutine when it is called from the program, and given a name within the subroutine (e.g. par1
above).
Reserved Words, Declarations, Types, and Variables
The words PROGRAM
, BEGIN
and END
are often capitalized to emphasise the program structure, but Pascal actually takes no notice of capitalization (so you could write program
, Program
or even PrOgRaM
!). These three words are also in red here – this is to indicate that they are special ‘reserved’ words that cannot be used for other purposes (so you can’t call a procedure or variable ‘begin’). As well as variables, a program can use constants to give a convenient name to a particular value. Any constants must be ‘declared’ even before the variables, like this:
PROGRAM myprog; CONST limit = 4; VAR global1: integer; {and so on}
Notice that variable and constant declarations must all end with a semicolon – Turtle will tell you if you forget! Notice also that while constants are given a value when declared (e.g. limit
is given the value 4
above), variables are given a type, to indicate the sort of data that they can store. Turtle Pascal allows four main types of variables:
integer | whole number |
---|---|
boolean | true or false |
char | single character |
string | sequence of character(s) |
Most of your variables are likely to be integer variables, like a transparent box that stores a number. You can look at the box to see which number it contains at any time, and you can change the number by assigning a new value, e.g.
VAR ringsize: integer;
is declared in the ‘Olympic rings’ example program, and ringsize
is later assigned the value 130
using the command:
ringsize := 130;
Five special integer variables are ‘built in’ from the start, and these are called the Turtle’s fields:
turtx | The Turtle’s x-coordinate |
---|---|
turty | The Turtle’s y-coordinate |
turtd | The Turtle’s direction |
turta | The Turtle’s angles |
turtt | The Turtle’s pen thickness |
turtc | The Turtle’s colour setting |
These automatically change to keep track of the Turtle’s state, and are shown above the Canvas.
For a use of turtd
, see the ‘Simple procedure’ example.
Programs and Functions: the Basics
A Turtle Python program is a sequence of statements, separated either by a semicolon, or by being placed on a new line. For example, the following two programs are equivalent:
colour(green); blot(200); colour(red); blot(100)
colour(green) blot(200) colour(red) blot(100)
Statements are either simple or compound. Compound statements are discussed later. Simple statements, first, are either function calls, variable declarations/assignments, return
statements, or global
/nonlocal
statements.
Function calls
A function is like a separate program you can use within your main program. Later you will see how to create your own functions, but you can also use any of the Turtle System’s built-in commands. To call a function, type its name followed by opening and closing brackets. If the function takes any arguments, type these in between the brackets, separated by commas. For example:
home() colour(red) circle(50) ellipse(50, 80)
A full list of built-in commands is available from the ‘Commands’ tab of this Language Guide.
Some functions return a value, like the max(a, b)
function, which returns the highest of the two numbers a
and b
. You can use these anywhere you would use a named value. For example:
blot(max(100, 200))
Variable declarations/assignments
Variables are like boxes where you can store one value at a time. There are three types of variables in Turtle Python: integers, Booleans, and strings. You must declare a variable (specify its type) before you can assign it a value. Variables in Turtle Python are declared like this:
ringsize: int draw: bool name: str
After they have been declared, variables can be assigned a value like this:
ringsize = 130 draw = True name = 'Turtle Python'
Once you have given your variable a value, you can recall that value at any time by typing the variable’s name.
Variable declarations and initial assignments can also be combined into a single statement, like this:
ringsize: int = 130 draw: bool = True name: str = 'Turtle Python'
Five special integer variables are built in to your program from the start, and these are called the Turtle’s fields:
turtx | The Turtle’s x-coordinate |
---|---|
turty | The Turtle’s y-coordinate |
turtd | The Turtle’s direction |
turta | The Turtle’s angles |
turtt | The Turtle’s pen thickness |
turtc | The Turtle’s colour setting |
These automatically change to keep track of the Turtle’s state, and are shown above the Canvas.
Python vs Turtle Python
In Python itself, specifying the type of your variables is called type hinting, and it is optional. Also, Python itself is a dynamically typed language, which means that you can change the types of your variables midway through a program. Turtle Python, however, is a statically typed language, which means that you cannot change the types of your variables (so if you try to assign a string value to an integer variable, for example, you will get an error). The type hinting that is optional in Python itself is compulsory in Turtle Python.
User-defined functions and return statements
Compound statements are groups of statements that cover several lines. Most compound statements are command structures, described on the &lsquoStructures’ tab of his Language Guide. One kind of compound statement, however, is a custom function definition. Function definitions begin with the keyword def
, followed by the function’s name, opening and closing brackets, and a colon. The function’s commands then follow on a newline, indented with one or more spaces at the start. For example:
def prong(): forward(400) blot(20) back(400)
Following a definition like this, you can then call your function in the same way you would call any built-in command: prong()
Functions can also be given parameters, which are specified inside the brackets after the function name. These are like variables for the function that are assinged a value each time the function is called. For example:
def prong(size: int): forward(size) blot(20) back(size)
Values for these parameters must then be specified each time the function is called: prong(100)
If you want your function to return a value, you must specify the type of value after the function’s closing brackets, and end the function’s commands with a return
statement specifying which value to return. For example:
def double(a: int) -> int: return a * 2
global
/nonlocal
statements
Variables declared inside your main program are called global variables. Variables declared inside a custom function are called local variables. Local variables are only visible inside the function where they are declared; the main program, and any other custom function, will not be able to do anything with these variables. Global variables, in contrast, are visible throughout your program, including inside any custom functions. For example, the following program will draw a circle of radius 100 on the canvas:
x: int def drawCircle(): circle(x) x = 100 drawCircle()
The following example, however, will generate an error, because the variable x
is not visible within the main program:
def declarex(): x: int = 100 declarex() circle(x)
Although global variables are visible inside custom functions, meaning that you can access their current value, by default you cannot assign them a new value within a function. If you want to assign them a new value within a function, you must declare them in a global
statement at the start of your function definition. Thus:
x: int = 100 # x is now a global variable def foo(): x = 200 # this is an error; # the global x cannot be assigned a value here # and no local x has been declared def bar(): global x x = 200 # this is fine, and will set the value of the global x
Custom functions can be defined inside other custom functions. A function’s local variables are all visible within any of its subfunctions (and any of their subfunctions, etc.), but cannot be assigned new values there. In these cases, nonlocal
statements operate exactly like global
statements, and are used to make it possible to assign a value to a local variable from a function higher up in the tree.
Programs and Procedures: the Basics
Documentation for Turtle TypeScript is still being prepared. Please check back here soon.
Command Structures
Selection and ordering of commands is done by sequencing, conditional selection, and looping.
Sequencing of Commands
Commands to be performed in sequence are usually placed in the appropriate order within the program, e.g.:
COLOUR(GREEN) BLOT(100) PAUSE(1000) COLOUR(RED) FORWARD(450) REM etc.
(From the first example program in the Help menu.)
Conditional Selection of Commands
Suppose you want to draw a blot with a given radius (stored as the integer variable radius%
), but only if that value is less than 500; do it like this:
IF radius% < 500 THEN BLOT(radius%) ENDIF
If you want to do something different when the condition is not met (e.g. drawing a blot with half the radius), extend the IF - THEN
structure by adding ELSE
and then the new command:
IF radius% < 500 THEN BLOT(radius%) ELSE BLOT(radius% / 2) ENDIF
Grouping of Commands
A sequence of commands within an IF - THEN - ELSE - ENDIF
structure is always treated as a single command. The ELSE
and ENDIF
words bracket off the sequence of commands. (Another possibility is to package them into a procedure.) You can also write these on a single line without the ENDIF
, like this:
IF radius% < 500 THEN BLOT(radius%)
Spacing and Indenting
Unnecessary ‘white space’ is ignored by BASIC, so you can use line breaks and indenting to make the structure of your program easy to read. However, each statement must be on its own line, unless separated by a colon ‘:’.
Looping Structures
BASIC provides three different structures for looping (or ‘iterating’) commands. If you know in advance how many times you want to loop – or you want to ‘loop over’ a particular range of values (e.g. from 1 to 200), then the simplest is a ‘FOR
loop’ (or ‘counting loop’):
FOR count% = 1 TO 200 FORWARD(count% / 3) RIGHT(5) REM etc. NEXT
(From the first FOR
loop example program in the Help menu.)
Here, NEXT
is used to bracket together a number of commands, and indenting is used to show the structure.
To count downwards, use STEP -1
at then end (as in the ‘Procedure with parameter’ example program).
In a FOR
loop, the ‘loop variable’ (here count%
) is given in turn each of the values in the range (here 1, 2, 3, …, 199, 200), and the loop instructions are performed each time. So in the example above, a spiral is drawn as the Turtle moves forward gradually more and more (as count%
increases).
If instead of looping a specific number of times, you want to loop through some sequence of commands until some particular condition becomes true, then you can use:
REPEAT REM command1 REM command2 (etc.) UNTIL REM condition
The ‘Simple procedure’ example program does this, looping until the Turtle is pointing directly north (i.e., TURTD% = 0
).
Alternatively, you can loop through a sequence of commands while some condition is true (so that it stops when the condition becomes false):
WHILE REM condition REM sequence of commands ENDWHILE
Things that can be done with a REPEAT
loop can equally be done with a WHILE
loop (and vice-versa), but sometimes one is more natural than the other. Notice also that a REPEAT
loop always executes the sequence of commands at least once, because it tests the condition at the end of the loop. But a WHILE
loop tests the condition before executing the sequence of commands, and so will not execute them even once if condition is false to start with. (For examples of the various loops, see the second set of example programs, ‘Further commands and structures’.)
Command Structures
Documentation for Turtle C is still being prepared. Please check back here soon.
Command Structures
Documentation for Turtle Java is still being prepared. Please check back here soon.
Command Structures
Selection and ordering of commands is done by sequencing, conditional selection, and looping.
Sequencing of Commands
Commands to be performed in sequence are usually placed in the appropriate order within the program, separated by semicolons, e.g.:
colour(green); blot(100); pause(1000); colour(red); forward(450); {etc.}
(From the first example program in the Help menu.)
Conditional Selection of Commands
Suppose you want to draw a blot with a given radius (stored as the integer variable radius
), but only if that value is less than 500; do it like this:
if radius < 500 then blot(radius);
If you want to do something different when the condition is not met (e.g. drawing a blot with half the radius), extend the if condition then
structure by adding else
and then the new command:
if radius < 500 then blot(radius) else blot(radius / 2);
Notice that this is a single complex command, so you must not put a semicolon before the else
(if you do, Turtle will give you a warning).
Grouping of Commands
Sometimes you will want to do a sequence of commands within an if {condition} then {command} else
structure, in which case you can bracket them between begin
and end
, e.g.
if {condition} then begin {sequence1} end else begin {sequence2} end;
Any such bracketed sequence of commands is always treated as a single command. (Another possibility is to package them into a procedure.)
Spacing and Indenting
Unnecessary ‘white space’ is ignored by Pascal, so you can use line breaks and indenting to make the structure of your program easy to read.
Looping Structures
Pascal provides three different structures for looping (or ‘iterating’) commands. If you know in advance how many times you want to loop – or you want to ‘loop over’ a particular range of values (e.g. from 1 to 200), then the simplest is a ‘for
loop’ (or ‘counting loop’):
for count := 1 to 200 do begin forward(count / 3); right(5); {etc.} end;
(From the first for
loop example program in the Help menu.)
Again begin {commands} end
is used to bracket together a number of commands, and indenting is used to show the structure.
In a for
loop, the ‘loop variable’ (here count
) is given in turn each of the values in the range (here 1, 2, 3, …, 199, 200), and the loop instructions are performed each time. So in the example above, a spiral is drawn as the Turtle moves forward gradually more and more (as count
increases).
To count downwards, use downto
instead of to
(as in the ‘Procedure with parameter’ example program.
If instead of looping a specific number of times, you want to loop through some sequence of commands until some particular condition becomes true, then you can use:
repeat {command1;} {command2; (etc.)} until {condition}
The ‘Simple procedure’ example program does this, looping until the Turtle is pointing directly north (i.e., turtd = 0
). Alternatively, you can loop through a sequence of commands while some condition is true (so that it stops when the condition becomes false):
while {condition} do begin {sequence of commands} end;
Things that can be done with a ‘repeat
loop’ can equally be done with a ‘while
loop’ (and vice-versa), but sometimes one is more natural than the other. Notice also that a repeat
loop always executes the sequence of commands at least once, because it tests the condition at the end of the loop. But a while
loop tests the condition before executing the sequence of commands, and so will not execute them even once if condition is false to start with. (For examples of the various loops, see the second set of example programs, ‘Further commands and structures’.
Command Structures
Selection and ordering of commands is done by sequencing, conditional selection, and looping.
Sequencing of Commands
Commands to be performed in sequence are usually placed in the appropriate order within the program, with the same indent, e.g.:
colour(green) blot(100) pause(1000) # etc.
(From the first example program in the Help menu.)
Conditional Selection of Commands
Suppose you want to draw a blot with a given radius (stored as the integer variable radius
), but only if that value is less than 500; do it like this:
if radius < 500: blot(radius)
If you want to do something different when the condition is not met (e.g. drawing a blot with half the radius), extend the if
structure by adding else
and then the new command:
if radius < 500: blot(radius) else: blot(radius // 2)
Notice that this is a single complex command, so the else
must have the same indent as if
and the sub-commands must be further indented (if you do not indent correctly, Turtle will give you a warning).
Grouping of Commands
Sometimes you will want to do a sequence of commands within an if - else
structure, in which case you can group them by indenting them all by the same amount. Any such indented sequence of commands is treated as a single command. (Another possibility is to package them into a function.)
Note that indents must be consistent, so the following will generate several errors:
if radius < 500: blot(radius) blot(radius // 3) # too many indents else: # should match the if line blot(radius // 2) # needs indent after else
Looping Structures
Python provides two different structures for looping (or ‘iterating’) commands. If you know in advance how many times you want to loop – or you want to ‘loop over’ a particular range of values (e.g. from 1 to 200), then the simplest is a ‘for
loop’ (or ‘counting loop’):
for count in range(1, 201, 1): forward(count // 3) right(5) # etc.
(From the first for
loop example program in the Help menu.)
Again indenting is used to group together a number of commands.
In a for
loop, the ‘loop variable’ (here count
) is given in turn each of the values in the range (here 1, 2, 3, …, 199, 200), and the loop instructions are performed each time. So in the example above, a spiral is drawn as the Turtle moves forward gradually more and more (as count
increases).
The range
function specifies the values that the loop variable will take as follows:
range(firstValue, lastValue + 1, increment)
The increment can be either 1 or -1. To count down through a loop, use an increment of -1.
If instead of looping a specific number of times, you want to loop through some sequence of commands while some condition is true (so that it stops when the condition becomes false), then you can use:
while condition: # sequence of commands
A while
loop tests the condition before executing the sequence of commands, and so will not execute them even once if condition is false to start with. (For examples of the various loops, see the second set of example programs, ‘Further commands and structures’.)
Command Structures
Documentation for Turtle TypeScript is still being prepared. Please check back here soon.
Arithmetical Operators
The four main arithmetical operators are represented as:
+ | addition (also used for string concatenation) |
- | subtraction |
* | multiplication |
/ | division |
/
is integer division, with the remainder discarded (e.g. 14 / 3 = 4
). Remainders are given by:
MOD | remainder |
(e.g. 14 MOD 3 = 2
; 67 MOD 10 = 7
).
Doing Fractional (e.g. Decimal) Arithmetic
The Turtle Machine is designed to handle memory simply and transparently for the learning of computer science, and so has no special type for representing fractional numbers; which is why /
is integer division. But the Turtle System can handle fractional numbers by treating them explicitly as fractions, with both a numerator (above the line) and a denominator (below the line). A denominator of 1000000, for instance, allows decimal arithmetic to 6 decimal places.
Thus to get the sine of 34.56 degrees to 6 decimal places, you could use n% = SIN(3456, 100, 1000000)
– this makes n%
equal to the sine of the angle 3456/100, multiplied by 1000000 (and rounded). WRITELN(QSTR$(n%, 1000000, 6))
will then print n%/1000000 to six decimal places, i.e. "0.567269"
. For more illustrations of this sort of decimal arithmetic, see the example program ‘Mathematical functions’.
Boolean Operators
The four main boolean operators are represented in the standard way:
NOT | negation |
AND | conjunction |
OR | disjunction (inclusive) |
EOR | exclusive disjunction |
These are used between integers, where zero stands for false and any other number stands for true. FALSE
stands for 0
and TRUE
for -1
. The Boolean operators can also be used in a bitwise fashion (i.e. each binary bit in the result is calculated as the result of the relevant boolean operation on the corresponding bits of the inputs, e.g. 21 AND 6 = 4
(binary 10101 AND 00110 = 100
); 21 OR 6 = 23
(10111
); 21 EOR 6 = 19
(10011
).
Comparison Operators
The six comparison operators are applicable to all types (with strings compared alphabetically):
= | equality |
<> | inequality |
< | less than |
<= | less than or equal |
> | greater than |
>= | greater than or equal |
Bracketing
Complex expressions require brackets, e.g.
IF (n% < 0) OR (n% > 9) THEN n% = ((a% + 1) * (b% + 3) + c%) MOD 10
Arithmetical Operators
Documentation for Turtle C is still being prepared. Please check back here soon.
Arithmetical Operators
Documentation for Turtle Java is still being prepared. Please check back here soon.
Arithmetical Operators
The four main arithmetical operators are represented as:
+ | addition (also used for string concatenation) |
- | subtraction |
* | multiplication |
/ | division |
/
is integer division, with the remainder discarded (e.g. 14 / 3 = 4
). Remainders are given by:
mod | remainder |
(e.g. 14 mod 3 = 2
; 67 mod 10 = 7
).
Doing Fractional (e.g. Decimal) Arithmetic
The Turtle Machine is designed to handle memory simply and transparently for the learning of computer science, and so has no special type for representing fractional numbers; which is why /
is integer division. But the Turtle System can handle fractional numbers by treating them explicitly as fractions, with both a numerator (above the line) and a denominator (below the line). A denominator of 1000000, for instance, allows decimal arithmetic to 6 decimal places.
Thus to get the sine of 34.56 degrees to six decimal places, you could use n := sin(3456, 100, 1000000)
– this makes n
equal to the sine of the angle 3456/100, multiplied by 1000000 (and rounded). writeln(qstr(n, 1000000, 6))
will then print n/1000000 to six decimal places, i.e. "0.567269"
. For more illustrations of this sort of decimal arithmetic, see the example program ‘Mathematical functions’.
Boolean Operators
The four main boolean operators are represented in the standard way:
not | negation |
and | conjunction |
or | disjunction (inclusive) |
xor | exclusive disjunction |
These can also be used between integers, in a bitwise fashion (i.e. each binary bit in the result is calculated as the result of the relevant boolean operation on the corresponding bits of the inputs), e.g. 21 and 6 = 4
(binary 10101 and 00110 = 100
); 21 or 6 = 23
(10111
); 21 xor 6 = 19
(10011
).
Comparison Operators
The six comparison operators are applicable to all types (with strings compared alphabetically):
= | equality |
<> | inequality |
< | less than |
<= | less than or equal |
> | greater than |
>= | greater than or equal |
Bracketing
Complex expressions require brackets, e.g.
if (n < 0) or (n > 9) then n := ((a + 1) * (b + 3) + c) mod 10
Arithmetical Operators
The four main arithmetical operators are represented as:
+ | addition (also used for string concatenation) |
- | subtraction |
* | multiplication |
// | division |
//
is integer division, with the remainder discarded (e.g. 14 // 3 = 4
). Remainders are given by:
mod | remainder |
(e.g. 14 mod 3 == 2
; 67 mod 10 == 7
).
Doing Fractional (e.g. Decimal) Arithmetic
The Turtle Machine is designed to handle memory simply and transparently for the learning of computer science, and so has no special type for representing fractional numbers; which is why //
is integer division. But the Turtle System can handle fractional numbers by treating them explicitly as fractions, with both a numerator (above the line) and a denominator (below the line). A denominator of 1000000, for instance, allows decimal arithmetic to 6 decimal places.
Thus to get the sine of 34.56 degrees to six decimal places, you could use n = sin(3456, 100, 1000000)
– this makes n
equal to the sine of the angle 3456/100, multiplied by 1000000 (and rounded). writeln(qstr(n, 1000000, 6))
will then print n/1000000 to six decimal places, i.e. '0.567269'
. For more illustrations of this sort of decimal arithmetic, see the example program ‘Mathematical functions’.
Boolean Operators
The four main boolean operators are represented in the standard way:
not | negation |
and | conjunction |
or | disjunction (inclusive) |
xor | exclusive disjunction |
These can also be used between integers, in a bitwise fashion (i.e. each binary bit in the result is calculated as the result of the relevant boolean operation on the corresponding bits of the inputs), e.g. 21 and 6 = 4
(binary 10101 and 00110 = 100
); 21 or 6 = 23
(10111
); 21 xor 6 = 19
(10011
).
Comparison Operators
The six comparison operators are applicable to all types (with strings compared alphabetically):
== | equality |
!= | inequality |
< | less than |
<= | less than or equal |
> | greater than |
>= | greater than or equal |
Bracketing
Complex expressions require brackets, e.g.
if (n < 0) or (n > 9): n = ((a + 1) * (b + 3) + c) mod 10
Arithmetical Operators
Documentation for Turtle TypeScript is still being prepared. Please check back here soon.
User Input
The facilities for user input – via keyboard or mouse – are designed to be as straightforward and comprehensible as possible, while operating strictly through simple processes that are consistent with the workings of the Turtle Machine.
Mouse Position Detection
The x- and y-coordinates of the mouse’s current position can be found at any time by using the special global variables ?mousex
and ?mousey
– these do not require the mouse to be clicked.
Mouse Click Detection
When a mouse click is performed, the x- and y-coordinates of the click position are remembered by the variables ?clickx
and ?clicky
. However to identify the type of click, use the variable ?click
, which is initially set to a value of -1, but after any click has taken place is set to a numerical value of 128 plus additions as follows:
1 | if the click was with the left mouse button |
2 | if the click was with the right mouse button |
4 | if the click was with the middle mouse button |
8 | if the shift key was held down while clicking |
16 | if the alt key was held down while clicking |
32 | if the ctrl key was held down while clicking |
64 | if it was a double-click |
So if n% = ?click
makes n%
equal to 137 (128+8+1), this indicates that a left-click is currently under way, with the shift key held down. When the click event is finished, the ?click
value will become negative. Thus if ?click
returns a value of -137, this indicates that the last click event – now finished – was shift+left; the coordinate position of that click can still be identified – until the next click takes place – as (?clickx
, ?clicky
). On a left-click, the variable ?lmouse
records the relevant value (as calculated above); likewise ?rmouse
and ?mmouse
record any right-click or middle-click. Again, these are all made negative when the click is released, so an empty loop like:
REPEAT UNTIL ?lmouse > 0
waits for a left-click with the mouse. Afterwards, ?clickx
and ?clicky
indicate where that click event occurred, and ?click
can be queried using the bitwise AND
operator to discover which special keys were pressed (e.g. IF (ABS(?click) AND 8) > 0
will test whether shift was being held down).
Key Press Detection
Detecting key presses (rather than typing in of characters) uses the variables ?key
and ?kshift
, and the function KEYSTATUS
. ?key
gives the code of the last key to be pressed – these codes can be tested using the special keycode constants \\alt
, \\backspace
, \\capslock
, \\ctrl
, \\delete
, \\down
, \\end
, \\escape
, \\home
, \\insert
, \\left
, \\lwin
, \\pgdn
, \\pgup
, \\return
, \\right
, \\rwin
, \\shift
, \\space
, \\tab
, and \\up
, as well as \\a
to \\z
, \\0
to \\9
, \\hash
, \\equals
etc. Keys on the numeric keypad have codes \\#0
, \\#1
etc., and function keys \\f1
, \\f2
etc. All these stand for numeric values (e.g. \\return
is 13, \\escape
is 27), but IF ?key = \\return
is easier to understand than IF ?key = 13
.
Like the mouse-click variables, ?key
becomes negative after the key is released, so REPEAT : UNTIL ?key = -\\a
will wait until the ‘A’ key has been released. If you want to identify the last key whether it is still pressed or not, use ABS
(e.g. IF ABS(?key) = \\a THEN
).
Whenever a key is pressed, the variable ?kshift
gives its ‘shift-status’, calculated in the same way as ?click
(i.e. 128 plus 8 if shift was down, 16 for alt, 32 for ctrl, and turning negative after the key is released). So to test if ctrl was down on the last keypress, use IF (ABS(?kshift) AND 32) > 0
, with AND
here acting as a bitwise boolean operator.
To recover the shift-status for the last press of the X key (say), use KEYSTATUS(\\x)
, which can tell you (a) whether shift / alt / ctrl were down; (b) whether the X is still pressed (since KEYSTATUS
goes negative on release); (c) whether X has been pressed at all (since all of these input codes are set to -1 initially, and can be reset to -1 using RESET(\\x)
etc.).
Keyboard Input
The system provides a keyboard buffer to store typed characters. Initially this is set to store up to 32 characters, but can be extended using e.g. KEYBUFFER(50)
. To read from the buffer into a string, use e.g. s$ = GET$(10)
, which reads up to 10 characters (depending on how many are in the buffer). KEYSTATUS(\\keybuffer)
returns the number of characters it contains, and RESET(\\keybuffer)
flushes it.
s$ = GETLINE$
reads a line of text, waiting until the return key is pressed and then making s$
equal to what has been typed into the buffer (discarding the return character).
The function DETECT
waits a given time for some input to be received (e.g. a specific key pressed), and returns TRUE
when that input is received, or FALSE
if it is not received in time. Thus IF DETECT(\\escape, 5000) THEN - ELSE -
gives 5 seconds to press the escape key (meanwhile continuing to collect any typed characters in the keyboard buffer). By default, text that goes into the keyboard buffer is also ‘echoed’ to the console (below the Canvas), along with text that is output (using WRITE
or WRITELN
). This behaviour can be turned on and off with KEYECHO(TRUE)
and KEYECHO(FALSE)
.
User Input
Documentation for Turtle C is still being prepared. Please check back here soon.
User Input
Documentation for Turtle Java is still being prepared. Please check back here soon.
User Input
The facilities for user input – via keyboard or mouse – are designed to be as straightforward and comprehensible as possible, while operating strictly through simple processes that are consistent with the workings of the Turtle Machine.
Mouse Position Detection
The x- and y-coordinates of the mouse’s current position can be found at any time by using the special global variables ?mousex
and ?mousey
– these do not require the mouse to be clicked.
Mouse Click Detection
When a mouse click is performed, the x- and y-coordinates of the click position are remembered by the variables ?clickx
and ?clicky
. However to identify the type of click, use the variable ?click
, which is initially set to a value of -1, but after any click has taken place is set to a numerical value of 128 plus additions as follows:
1 | if the click was with the left mouse button |
2 | if the click was with the right mouse button |
4 | if the click was with the middle mouse button |
8 | if the shift key was held down while clicking |
16 | if the alt key was held down while clicking |
32 | if the ctrl key was held down while clicking |
64 | if it was a double-click |
So if n := ?click
makes n
equal to 137 (128 + 8 + 1), this indicates that a left-click is currently under way, with the shift key held down. When the click event is finished, the ?click
value will become negative. Thus if ?click
returns a value of -137, this indicates that the last click event – now finished – was shift+left; the coordinate position of that click can still be identified – until the next click takes place – as (?clickx
, ?clicky
). On a left-click, the variable ?lmouse
records the relevant value (as calculated above); likewise ?rmouse
and ?mmouse
record any right-click or middle-click. Again, these are all made negative when the click is released, so an empty loop like:
repeat until ?lmouse > 0;
waits for a left-click with the mouse. Afterwards, ?clickx
and ?clicky
indicate where that click event occurred, and ?click
can be queried using the bitwise and
operator to discover which special keys were pressed (e.g. if (abs(?click) and 8) > 0
will test whether shift was being held down).
Key Press Detection
Detecting key presses (rather than typing in of characters) uses the variables ?key
and ?kshift
, and the function keystatus
. ?key
gives the code of the last key to be pressed – these codes can be tested using the special keycode constants \\alt
, \\backspace
, \\capslock
, \\ctrl
, \\delete
, \\down
, \\end
, \\escape
, \\home
, \\insert
, \\left
, \\lwin
, \\pgdn
, \\pgup
, \\return
, \\right
, \\rwin
, \\shift
, \\space
, \\tab
, and \\up
, as well as \\a
to \\z
, \\0
to \\9
, \\hash
, \\equals
etc. Keys on the numeric keypad have codes \\#0
, \\#1
etc., and function keys \\f1
, \\f2
etc. All these stand for numeric values (e.g. \\return
is 13, \\escape
is 27), but if ?key = eturn
is easier to understand than if ?key = 13
.
Like the mouse-click functions, ?key
becomes negative after the key is released, so repeat until ?key = -\\a
will wait until the A key has been released. If you want to identify the last key whether it is still pressed or not, use abs
(e.g. if abs(?key) = \\a then {commands}
).
Whenever a key is pressed, the variable ?kshift
gives its ‘shift-status’, calculated in the same way as ?click
(i.e. 128 plus 8 if shift was down, 16 for alt, 32 for ctrl, and turning negative after the key is released). So to test if ctrl was down on the last keypress, use if (abs(?kshift) and 32) > 0
, with and
here acting as a bitwise boolean operator.
To recover the shift-status for the last press of the X key (say), use keystatus(\\x)
, which can tell you (a) whether shift / alt / ctrl were down; (b) whether the X is still pressed (since keystatus
goes negative on release); (c) whether X has been pressed at all (since all of these input codes are set to -1 initially, and can be reset to -1 using reset(\\x)
etc.).
Keyboard Input
The system provides a keyboard buffer to store typed characters. Initially this is set to store up to 32 characters, but can be extended using e.g. keybuffer(50)
. To read from the buffer into a string, use e.g. s := read(10)
, which reads up to 10 characters (depending on how many are in the buffer). keystatus(\\keybuffer)
returns the number of characters it contains, and reset(\\keybuffer)
flushes it.
s := readln
reads a line of text, waiting until the return key is pressed and then making s
equal to what has been typed into the buffer (discarding the return character).
The function detect
waits a given time for some input to be received (e.g. a specific key pressed), and returns true
when that input is received, or false
if it is not received in time. Thus if detect(\\escape, 5000) then {command1} else {command2}
gives 5 seconds to press the escape key (meanwhile continuing to collect any typed characters in the keyboard buffer). By default, text that goes into the keyboard buffer is also ‘echoed’ to the console (below the Canvas), along with text that is output (using write
or writeln
). This behaviour can be turned on and off with keyecho(true)
and keyecho(false)
.
User Input
The facilities for user input – via keyboard or mouse – are designed to be as straightforward and comprehensible as possible, while operating strictly through simple processes that are consistent with the workings of the Turtle Machine.
Mouse Position Detection
The x- and y-coordinates of the mouse’s current position can be found at any time by using the special global variables ?mousex
and ?mousey
– these do not require the mouse to be clicked.
Mouse Click Detection
When a mouse click is performed, the x- and y-coordinates of the click position are remembered by the variables ?clickx
and ?clicky
. However to identify the type of click, use the variable ?click
, which is initially set to a value of -1, but after any click has taken place is set to a numerical value of 128 plus additions as follows:
1 | if the click was with the left mouse button |
2 | if the click was with the right mouse button |
4 | if the click was with the middle mouse button |
8 | if the shift key was held down while clicking |
16 | if the alt key was held down while clicking |
32 | if the ctrl key was held down while clicking |
64 | if it was a double-click |
So if n = ?click
makes n
equal to 137 (128 + 8 + 1), this indicates that a left-click is currently under way, with the shift key held down. When the click event is finished, the ?click
variable will become negative. Thus if ?click
returns a value of -137, this indicates that the last click event – now finished – was shift+left; the coordinate position of that click can still be identified – until the next click takes place – as (?clickx
, ?clicky
). On a left-click, the variable ?lmouse
records the relevant value (as calculated above); likewise ?rmouse
and ?mmouse
record any right-click or middle-click. Again, these are all made negative when the click is released, so an empty loop like:
while not(?lmouse > 0): pass # this statement does nothing!
waits for a left-click with the mouse. Afterwards, ?clickx
and ?clicky
indicate where that click event occurred, and ?click
can be queried using the bitwise and
operator to discover which special keys were pressed (e.g. if (abs(?click) and 8) > 0
will test whether shift was being held down).
Key Press Detection
Detecting key presses (rather than typing in of characters) uses the variables ?key
and ?kshift
, and the function keystatus
. ?key
gives the code of the last key to be pressed – these codes can be tested using the special keycode constants \\alt
, \\backspace
, \\capslock
, \\ctrl
, \\delete
, \\down
, \\end
, \\escape
, \\home
, \\insert
, \\left
, \\lwin
, \\pgdn
, \\pgup
, \\return
, \\right
, \\rwin
, \\shift
, \\space
, \\tab
, and \\up
, as well as \\a
to \\z
, \\0
to \\9
, \\hash
, \\equals
etc. Keys on the numeric keypad have codes \\#0
, \\#1
etc., and function keys \\f1
, \\f2
etc. All these stand for numeric values (e.g. \\return
is 13, \\escape
is 27), but if ?key = \\return
is easier to understand than if ?key = 13
.
Like the mouse-click variables, ?key
becomes negative after the key is released, so while not(?key = -\\a): pass
will wait until the A key has been released. If you want to identify the last key, whether it is still pressed or not, use abs
(e.g. if abs(?key) = \\a: # command
).
Whenever a key is pressed, the variable ?kshift
gives its ‘shift-status’, calculated in the same way as ?click
(i.e. 128 plus 8 if shift was down, 16 for alt, 32 for ctrl, and turning negative after the key is released). So to test if ctrl was down on the last keypress, use if (abs(?kshift) and 32) > 0
, with and
here acting as a bitwise boolean operator.
To recover the shift-status for the last press of the X key (say), use keystatus(\\x)
, which can tell you (a) whether shift / alt / ctrl were down; (b) whether the X is still pressed (since keystatus
goes negative on release); (c) whether X has been pressed at all (since all of these input codes are set to -1 initially, and can be reset to -1 using reset(\\x)
etc.).
Keyboard Input
The system provides a keyboard buffer to store typed characters. Initially this is set to store up to 32 characters, but can be extended using e.g. keybuffer(50)
. To read from the buffer into a string, use e.g. s = read(10)
, which reads up to 10 characters (depending on how many are in the buffer). keystatus(\\keybuffer)
returns the number of characters it contains, and reset(\\keybuffer)
flushes it.
s = readln
reads a line of text, waiting until the return key is pressed and then making s
equal to what has been typed into the buffer (discarding the return character).
The function detect
waits a given time for some input to be received (e.g. a specific key pressed), and returns True
when that input is received, or False
if it is not received in time. Thus if detect(\\escape, 5000): #command1
else: #command2
gives 5 seconds to press the escape key (meanwhile continuing to collect any typed characters in the keyboard buffer). By default, text that goes into the keyboard buffer is also ‘echoed’ to the console (below the Canvas), along with text that is output (using write
or writeln
). This behaviour can be turned on and off with keyecho(True)
and keyecho(False)
.
User Input
Documentation for Turtle TypeScript is still being prepared. Please check back here soon.