This is a larger piece of sample code written in NewtonScript. Admittedly
algorithm code is not very enlighting to illustrate the NewtonScript
principles. The problem is that in fact NewtonScript programs cannot be
written just with a text
editor, but have to be put together using the Newton Toolkit environment,
therefore it is not possible to demonstrate a piece of GUI code because
most of it is done graphically. The inheritance mechanisms are
automatically invoked by the
environment and normally not assigned by the programmer. Anyway, just to
get a feeling of the syntax which is close to Pascal and really easy to
understand:
func native(int destx, int desty)
/* This procedure finds the shortest way through a grid labyrinth with
walls along the grid line from the current location to a given
point. It is taken from the class project I conducted using
NewtonScript. Is is compiled native for speed. Very much is
inlined because calls are expensive. Execution time for
a 20x20 array with some walls going from one end to the other
is about half a second, so it is still bearable.
The whole program including this function is available from
my homepage http://wwwwbs.cs.tu-berlin.de/~schoedl */
begin
/* Gets the X dimension of the labyrinth */
local int xsize:=leftWalls.bounds.right-leftWalls.bounds.left;
/* and create an array with an entry for each position between the
grid lines to store the distance to each point in there */
local array dist:=Array((leftWalls.bounds.bottom
-leftWalls.bounds.top)*xsize,nil);
/* This queue contains the outer limit of our distance knowledge.
Neighbors of these places need to be set next. */
local array queue:=[youx,youy];
local int read:=0;
/* Pointer, up to which point the queue was already worked on.
For simplicity storage space in the queue is not freed until
the end of the procedure */
local int x;
local int y;
local int curdist;
local int store;
/* the distance to our current position given by youx and youy
is defined to be 1 and put into the array which is initialised
to 0 by NewtonScript. Distances to points whose entry in the
array is 0 were Places are still not determined, so initially
no distance is known except the one to our current location.
*/
dist[youx+xsize*youy]:=1;
loop begin
/* This infinite loop takes a pair of coordinates from the queue
and sets the distance to all the neighbors of this
place in the grid if it has not been set by someone else
already. If the distance is set the neighbor is enqueued
in the queue to let his neighbors processed sometime later.*/
/* read from queue */
x:=queue[read];
y:=queue[read+1];
/* If we reached our destination break out of loop */
if x=destx and y=desty then break;
/* if we are not at the border of the grid and there is no
wall between us and the neighbor set the distance and
add neighbor to queue (which is just an array).
Pixels in a BMP picture which is set up at compile time to
contain the wall locations, two picture, one for vertical,
one for horizontal walls. */
if x>0 then if dist[x-1+xsize*y]=nil
and not PtInPicture(x,y,leftWalls) then begin
dist[x-1+xsize*y]:=dist[x+xsize*y]+1;
AddArraySlot(queue,x-1);
AddArraySlot(queue,y);
end;
/* And do the same thing for the other three neighbors
*/
if dist[x+1+xsize*y]=nil
and not PtInPicture(x+1,y,leftWalls) then begin
dist[x+1+xsize*y]:=dist[x+xsize*y]+1;
AddArraySlot(queue,x+1);
AddArraySlot(queue,y);
end;
if y>0 then if dist[x+xsize*y-xsize]=nil
and not PtInPicture(x,y,topWalls) then begin
dist[x+xsize*y-xsize]:=dist[x+xsize*y]+1;
AddArraySlot(queue,x);
AddArraySlot(queue,y-1);
end;
if dist[x+xsize*y+xsize]=nil
and not PtInPicture(x,y+1,topWalls) then begin
dist[x+xsize*y+xsize]:=dist[x+xsize*y]+1;
AddArraySlot(queue,x);
AddArraySlot(queue,y+1);
end;
/* There are tuples of two coordinates in the array, so advance
array resp. queue pointer by two. */
read:=read+2;
end;
/* Now the array is walked back from the destination to the origin
(you can do it either way) to find the right way which is
stored as a set of lines which are used to paint the shortest
way into a moving map on the Newton screen. curdist contains
the current distance to out origin. */
curdist:=dist[x+xsize*y];
/* If the destination was not the current position */
if curdist>1 then begin
/* the coordinates of the destination which is still
contained in (x,y) is the first point of our line */
wayArray:=[x,y];
loop begin
/* if we go any distance in one direction we have to store
the endpoint of our walk, but if one direction does
not work at all, we do not store the endpoint. We don't
want one point to be stored more than once, that will
cost us drawing performance. */
store:=0;
/* Again, check for grid boundary (some guard walls would
be
better here, but I did it the hacky way) */
if x>0 then
/* Go as far as you can while the distance to our
is decreasing, if you can go at all, store the
endpoint */
while dist[x-1+xsize*y]=curdist-1
and not PtInPicture(x,y,leftWalls) do begin
store:=1;
x:=x-1;
curdist:=curdist-1;
if x=0 then break;
end;
/* Here the endpoint is stored into an array. When the
current distance went down to 1 we reached our
origin and can quit. wayArray contains pairs
of coordinates then describing the way through the
labyrinth around the walls */
if store=1 then begin
AddArraySlot(wayArray,x);
AddArraySlot(wayArray,y);
if curdist=1 then break;
end;
/* Do the same thing for the other three neighbors
*/
store:=0;
while dist[x+1+xsize*y]=curdist-1
and not PtInPicture(x+1,y,leftWalls) do begin
store:=1;
x:=x+1;
curdist:=curdist-1;
end;
if store=1 then begin
AddArraySlot(wayArray,x);
AddArraySlot(wayArray,y);
if curdist=1 then break;
end;
store:=0;
if y>0 then
while dist[x-xsize+xsize*y]=curdist-1
and not PtInPicture(x,y,topWalls) do begin
store:=1;
y:=y-1;
curdist:=curdist-1;
if y=0 then break;
end;
if store=1 then begin
AddArraySlot(wayArray,x);
AddArraySlot(wayArray,y);
if curdist=1 then break;
end;
store:=0;
while dist[x+xsize+xsize*y]=curdist-1
and not PtInPicture(x,y+1,topWalls) do begin
store:=1;
y:=y+1;
curdist:=curdist-1;
end;
if store=1 then begin
AddArraySlot(wayArray,x);
AddArraySlot(wayArray,y);
if curdist=1 then break;
end;
end;
/* This sets up a timer that causes a repaint of the map
somewhere else */
:SetupIdle(200);
end;
end