Classic Computer Magazine Archive START VOL. 4 NO. 1 / AUGUST 1989

An
Animations
Simulations
Language

Pogo

BY JIM KENT
START CONTRIBUTING EDITOR

If you think there's nothing new in programming languages, then think again. Premiere ST programmer Jim Kent has created a great new "creature-oriented" language. It has features of C, Logo and even C + + and SmallTalk. It's Pogo and it's on the START disk this month. You'll need a color monitor to run Pogo.

Learn creature programming with POGO.ARC and POGOSRC.ARC on your START disk.

Pogo has its origins in the computer language Logo, which Seymour Papert created in part as a teaching tool for programming. Graphics in Logo employs the metaphor of a turtle with a pen tied to its tail; you move the turtle around the screen and it can leave a trail of where its been. You can tell the turtle to move forward or backwards, turn left or right, lift up or put down the pen and change the pen colors. A function to draw a circle using turtle graphics might look like this:

to circle()
{
for i = 1 to 36
     {
      forward(5)
      right(10)
     }
}


Turtle graphics programs are fun to write and easy to debug because the results are immediately visible on the screen. I've seen eight-year-olds write beautiful snowflake generators and intricate software spirographs in the time it takes their parents to reach the bottom line of their income tax spreadsheet.

Pogo, like Logo, uses turtle graphics. Pogo also has built-in animation features and a simple but effective approach to multiprocessing. Most of Pogo's syntax looks like C, but I borrowed a few things from BASIC. Even if you're a beginning BASIC or C programmer you should have no trouble writing Pogo code after studying some of the sample programs on disk.

Running Pogo
Pogo is an interpreted language. Pogo programs must be in ASCII format to run. To get started with Pogo, copy the files POGO.ARC and ARCX.TTP onto a blank, formatted disk and un-ARC POGO.ARC following the Disk Instructions elsewhere in this issue. (The Aztec C and assembler source code to Pogo is in the file POGOSRC.ARC.)

Pogo is a TTP (TOS Takes Parameters) program, which means that when you double-click on POGO.TTP you will see the TOS Open Application dialog box. Type in the name of the Pogo program you wish to run; if you omit the file extension Pogo will use P0G.
 

Pogo in Action!
This is one of several simple graphics demos on your STARIT disk. Built-in Pogo graphics functions make drawing lines, circles, disks and rectangles a snap.
Archive File: POGO.ARC
Filename: L1NES.POG
Related programs: CIRCLES.POG, DISKS.POG

You can install also Pogo as an application. From the Desktop, click once to highlight the POGO.TTP icon and select Install Application from the Options menu. Under document type enter POG and click on OK. Now all you have to do is double-click on a POG file to run it. If you'd like to install Pogo as an application permanently, you must save your Desktop before shutting off your computer.

All Pogo programs run in low resolution; however; you can run Pogo from either a low or medium resolution Desktop. You can exit from any Pogo program by pressing [Control]-[C].

Creature Comfort
The main thing that sets Pogo apart from traditional programming languages is its unique approach to multiprocessing. Traditional systems simulate multiprocessing on a single processor using a method known as time-slicing. A peripheral clock chip is programmed to interrupt the CPU at regular intervals. On receiving a clock tick, the current process is halted and the next process on the ready list is started. However, communicating between processes requires elaborate synchronization safeguards so that one process doesn't read data that another process hadn't finished updating when the clock interrupt was received.
 

Pogo in Action!
By defining a snowflake creature once, you can simulate a snowy evening simply by spawning and evolving snowflakes inside a loop. A more ambitious program could draw more complex snowflake shapes.
Archive File: POGO.ARC
Filename: SNOWING.POG

Pogo, on the other hand, uses a technique I borrowed from the world of video games. In an arcade game, for example, the program must manage aliens, asteroids and one to four or five human players and each of these processes should appear to be happening at once. In Pogo, such processes are called creatures.

Each creature has its own code and private data and can take care of moving and displaying itself. Pogo has built-in routines for a creature to find its closest neighbor; so a creature can be responsible for killing whoever it collides with as well.
 

Pogo in Action!
This ecological simulation features fountains that create green dots, creatures that eat the green dots and creatures that eat the creatures that eat the green dots. Watch this fascinating demonstration to see which species survive!

Archive File: POGO.ARC
Filename: ECOLOGY.POG

Tell Me That It's Evolution
A typical Pogo program consists of a main section of code which creates the various creatures. The program then executes the creatures using the Evolve() function; usually this statement is inside a loop. Finally the program might print some status when the creatures are done.

Once you've written the code for a single Pogo creature you can spawn multiple instances (copies) of it as easily as spawning one. For example, to fill the screen with stars you would first define a star creature as a flickering point of light, and then generate many stars in the loop:

for i = 1 to 64
   spawn(star,random(320),
   random(200),0,0)

Once creatures have been spawned, it is only necessary to use an Evolve() statement to have the program execute the star's code. Similarly, a single Evolve() statement will execute the code of all creatures that have been spawned as of that point.

This is a key feature of Pogo, one that places it closer to the class of object-oriented languages such as C+ + or Smalltalk than BASIC, C or assembly language.

See the sidebar take-apart of the Warblers program for a complete example of creature-oriented programming in action.

And That's Not All.
We've included several sample Pogo programs on your START disk; they are all in the file POGO.ARC. LINES.POG, CIRCLES.POG and DISKS.POG are all graphic demos. BUSH.POG draws a pretty turtle graphics recursive bush; and the screen is saved to disk as a DEGAS .PC1 file.

FOLLOW.POG is a simple video game. Move the disk with the mouse and try to avoid the little circles that come out of the upper left corner and go into orbit around you. If you get hit by a circle your disk grows, making it that much harder to avoid other circles. Eventually your disk gets so big you blow out and the game is over. The longer you stay alive the higher your score.

ECOLOGY.POG is an ecological simulation that really shows off the power of Pogo. The world contains fountains which generate green dots; red circles, blue circles and "purplers" all use green dots for food. When a green dot comes into range of a red, blue or purpler that creature gets a little bigger Each of these creatures approaches survival in its environment a little differently. For example, purplers actively chase dots, whereas reds stake out a good position early in their lives and stay put.
 

Pogo in Action!
This video game forces you, the large disk, against a host of smaller circles who follow you about. Use the mouse to control the disk: if one of the little circles touches you you grow even larger!
Archive File: POGO.ARC
Filename: FOLLOW.POG

The Ecology world also has a predator creature named Harry an orange circle that hunts down reds, blues and purplers; when Harry encloses one of their center points, he gobbles them up and grows a little larger The larger the creature he eats, the larger he grows.

When a red, blue or purpler-or Harry-gets big enough, it reproduces. It will get smaller and eventually die if there isn't any food around. Purplers are the only creatures smart enough to run away from Harry; however, often their flight takes them offscreen and away from their source of energy.

Ecology's screen shows some status information; it tells how many times the creatures have evolved and how many of each there are.

Implementing Pogo
The source code for Pogo is in POGOSRC.ARC. Pogo is written in Aztec C and assembler Much of the code is computer-independent; the files that are specific to the ST (mostly low-level graphics and I/O) all start with the letters ST.

Pogo is a one-pass recursive descent compiler that generates an intermediate code for a stack-based virtual machine, which currently has about 32 instructions. Most of these are to implement all the operators it has. Upon sighting a constant or variable, it pushes it onto the stack. Binary operations take the top two members of the stack and replace them with the result. Unary operations act on the top of the stack. Each instruction is six bytes long-two bytes of op-code and four for data.

If you'd like to hack a new function into Pogo (perhaps some sound or a way to save Cyber Paint sequences), look at the file PREDEFS.C. If you'd like to see how a compiler can convert something like this statement into machine code:

d = SqrRoot( (x1-x2)*(x1-x2) + (y1-y2)*(y1-y2))

try studying the files EXPRESS.C and STATEMEN.C. If you just want to know how Pogo can read in a .PC1 file so much faster than DEGAS Elite, check out STGFX.C and STUNPACK.ASM and look for the function rpcl().
 

Pogo in Action!
This program uses a recursive function to draw branches. This program uses turtle graphics, which is a way to program graphics by giving directions to an imaginary turtle who moves about the screen. When the program is finished, it uses a built-in Pogo function to save the screen as a DEGAS.PC1 file.
Archive File: POGO.ARC
Filename: BUSH.POG

Conclusion
I've learned a lot writing the Pogo compiler. I hope you'll enjoy programming in Pogo as much as I do. I've always liked the C language, but C tends to crash the computer if you make a mistake. On the other hand, Pogo will usually tell you politely where the error occurred and let you exit cleanly without a reboot. You can break out of a hung-up Pogo program with [Control]-[C].

Pogo is not as fast as C, but most programs will spend most of their time doing graphics and other built-in functions which are in high performance machine code already. I'm not sure if Pogo is the answer to GFA BASIC 3.0, but for quick simulations and video games on a color system you'll find it hard to beat.

Jim Kent is a START Contributing Editor and the author of Cyber Paint Aegis Animator, Flicker and the Audio-Video Sequencer

Pogo at a Glance

Here is a brief overview of Pogo's syntax and built-in functions. A complete description of each function and a more thorough discussion of the language itself is in the file POGO.TXT in the POGO.ARC file. After you've un-ARCed POGO.ARC, double-click on POGO.TXT to view or print the file from the Desktop.

Comments:
Everything to the right of a semicolon is disregarded.

Variables:
Declaration (type is either string or int)
   type i,j,k
   type linkcount
Arrays
   int bigarray[500], littlearray[16]

Numeric Constants:
Decimal constants. No floating point
   5 100 -200
Hexidecimal constants
   0x10 0xFF 0xabc
Character constants in single quotes.
   'a' '*'

Numeric Expressions (listed in decreasing precedence):
Unary plus and minus, binary not
    +5 -x ~a

Multiplication, division, modulus, binary left shift, right shift, binary and
   5 * 5 a/b 4%3 a<<b b>>c b&c

Addition, subtraction, binary or, xor
   a+b x-5 a|b a^b

Comparison operators: Equal to, not equal, greater. less, etc.
   a==b a!=b a>b a<b a>=b a<=b hello == "Hi Doc!"

Logical not
   !a

Logical and
   a && b

Logical or
   a||b

(Note: Comparison and logical operations evaluate to 1 for true, 0 for false~ In conditional branches any non-zero is considered true.)

String Expressions:
A string constant enclosed in quotes
"Hello World"
A function returning a string
    StrNum(100)
Two strings concatenated with a plus sign
   filename = "FRAME" + StrNum(i) + ".PC1"

Assignment statements:
var = expression

Compound blocks of statements:
{
statement1
statement2
...
}

If statements:
if expression
    statement1
else
    statement2

Loop statements:
loop
   statement
loop
    {
   statement1
   statement2
   if expression
      break
   statement3
    }

For statements:
for var = expression to expression [step]
    statement
for i = 0 to x
   statement
for i = 100 to 50 step -5
   statement

While statements:
while expression
   statement

Goto statements:
goto label
forever:
   Prints ("Hello")
   goto forever

Constant declarations:
constant red = 3

Function declarations:
function say_hello()
   {
   Prints ("helld')
   }
to add2(a,b)
   {
   return(a+b)
   }

Function usages:
say_hello()
a = add2(5, 2*c)

Creature declarations:
creature name
   {
   statement
   statement. . .
   }

Input oriented functions:
InKey()
Keyboard()
WaitKey()
MouseX()
MouseY()
MouseLeft()
MouseRightO
Clock()
UsejoystickO
UseMouse()
Joystick() (see POGO.TXT for value
returned)

Text output functions:
Print number in decimal on a line
   Print(number)
Print string and a new line
   Prints(string)
   Prints(NULL)
Print string without a new line
   Text(string)

General-purpose graphics functions:
ToText()
ToGraphics()
PutDot(color, x, y)
GetDot(x,y)
Rectangle(color xl, yl, x2, y2)
Disk(x, y, radius, color)
Circle(x, y, radius, color)
Gtext(color, x, y, string)
Gnumber(color, x, y, digits. number)
Line(color,xl,yl,x2,y2)
ClearScreen()
SetColor(color, r, g, b)
   (Note: the values for r, g and b are from 0 to 255.)
LoadPic(fllename)
SavePic(filename)

Screen-oriented graphics functions:
AllocScreen()
Pscreen()
UseScreen(screen)
CopyScreen(sscreen, dscreen)
Blit(w,h,sscreen,sx,sy,dscreen,dx,dy)
FreeScreen(screen)

Animation display functions:
PreSwap()
Swap()
DeSwap()
Vsync()

Turtle graphics:
(Note: turtle is floating point position. Not much good for real-time, but you can do lots of LOGO tricks.)
Right(degrees)
Left(degrees)
PenUp()
PenDown()
PenColor(color)
Forward(pixels)
Reverse(pixels)

Math functions:
Random(max)
XYangle(x,y)
SquareRoot(x)
Distance(xl,yl,x2,y2)
ArcX(angle,radius)
ArcY(angle,radius)

String-oriented functions:
StrNum(number)
StrChar(char)
StrLen(string)
CharAt(string, index)
CharTo(string, index, char)
NULL

Text file functions:
Fopen(name, mode)
Fclose(f)
GetChar(f)
GetWord(f)
GetLine(f)

Creature locating functions:
ClosestCreature(id,x,y)
ClosestT(type,x,y)
NamedCreature(name)
ExistsCreacure(id)

Creature information functions:
CreatureX(id)
CreatureY(id)
CreatureAge(id)
CreatureNewBorn(id)
CreatureName(id)
value = Cread(type, var, id)
Cwnte(type, var, id, value)

Creature life and death functions:
id = Spawn(creature,x,y,dx,dy)
Evolve()
Kill(id) (Note: Kill(cid) amounts to suicide.)
KillAll()

Creature spawn parameters:
Cx
Cy
Cdx
Cdy

Other system-maintained local creature variables:
Cid
Cage
Cnew
Cname

A Sample Program-the Warblers Game

A warbler is a circle that grows and shrinks as it moves across the screen. Some warblers pulse rapidly while others grow and shrink more slowly. You have a disk which follows the motion of the mouse. The object of the game is to surround the warblers with the disk when they are smaller than you are. If your disk surrounds a warbler, you eat it and your disk gets a little bigger if the warbler surrounds your disk, it eats you and the game is over.

The warblers Pogo program is fairly simple. There are only two types of creatures-one for the warbler circles and one for the mouse disk. (Note: Pogo function and variable names are not case-sensitive. For clarity in this take-apart I'll use names starting with an uppercase letter for built-in Pogo functions and variables and lowercase for the ones defined in the warblers program. A semicolon marks the rest of the line as a comment.)
 
The code starts out with a few global 
variables.
int mouseid  ;The creature id of mouse so warblers can find it.
int mouserad  ;Radius of mouse. Gets bigger every other warbler you eat.
int warblers  ;Number of warbiers alive. If it gets down to zero you win!
When a warbler goes offscreen it
comes back on the other side. Here are 
two functions that help implement this
"wrap around."
to wrapx(x)
{
 if (x> 320+ 50)  ; offscreen 50 to the right?
    x = -50;   ; then move it to left of screen
 if (x < -50)   ; offscreen 50 to the left?
    x = 320+ 50  ; then move it to right of screen
 retum(x)
}
to wrapy(y)
{
if (y> 200+50)
   y = -50
if(y< -50)
   y = 200+50
return(y)
}
Here is the code for the warbler crea-
ture. This is the brains of the program.
The warbiers take care of pulsating 
themselves and also see if they are hav-
ing a run-in with the mouse
       ;The pulsating circle creature.
creature warbler
{
int csize ;current size
int dsz ;rate of change of size
int cmax ;maximum size
int cmin ;minimum size
int color ;color of this warbler
int md ;used to hold distance to mouse
1st time through randomly initialize
some of our variables.
if (Cnew) ;Cnew is true only first time a warbler is Evolve()'d
   {
   cmin = Random(5)+2;    ;min radius
   cmax = Random(16)+5  ;max radius
   dsz = Random(3)+1   ;speed of radius change
   if (Random(1))      ;randomly make it start out shrinking or growing
      dsz = -dsz;
   csize = (cmin + cmax )/2  ;start 1/z way through size cycle
   color = Random(4)+1 ;color random between 1 and 4
   }
Do stuff to figure out what size warbler
is this frame.
if (!(Cage&31))   ;every 32 ticks increase max radius size by 1
   cmax = cmax +1
csize = csize + dsz
if (csize > cmax || csize < cmin)   ;if hit mm or max reverse delta radius
   dsz = -dsz
Move warbler by adding its speed to its
position, and piping through a 'wrap'
function in case result is off-screen.
 
Cx = wrapx(Cx + Cdx)  ;Cx and Cdx are passed from the 'Spawn' call below.
Cy = wrapy(Cy + Cdy)
Interact with the mouse creature if (mouseid) ;if the mouse creature is still alive.
   {
   ;find distance to mouse
   md = D istance(Creaturex(mouseid ),Creaturey(mouseid), Cx, Cy)
   ;if inside mouse radius, suicide
   if (md < mouserad && csize < mouserad)
      {
      if (warblers&1) ;every other warbler increment mouse radius
         mouserad = mouserad+1
      Kill(cid);
      warbiers = warblers-1
      return;
      }
 If mouse inside our radius kill it.    if (md < csize && csize > mouserad)
      {
      Kill(mouseid);
      mouseid = 0;
      }
   }
Circle(Cx,Cycsize,color) ;draw ourselves
}
The mouse creature is quite simple
since it doesn't need to figure out whether
it has hit a warbler or not. It just calls
the built-in Mouse functions to set its
current position on the screen (Cx and
Cy) and then draws a disk in color 13.
 
creature mouse
{
Cx = MouseX()
Cy = MouseY()
Disk(Cx,Cy,mouserad,13
}
 
Finally there's the main code for the game: loop   ;repeat forever (or until user doesn't want to play again)
   {
   KillAll()    ;Kill any creatures left from last game
   mouserad = 8    ;mouse starts with an 8 pixel radius
   mouseid = Spawn(mouse,0,0,0,0)    ;make the mouse
   for warbiers = 0 to 12     ;make 13 warblers
      {
      int ix,iy
Make a warbler at random position on
screen and random speed between
-3and3
      ix = Random(6)-3    ;speed from -3 to 3
      if (ix = = 0)  ;don't allow 0 x speed
         ix=1
      iy = Random(6)-3
      if(iy == 0)
         iy = 1
      Spawn(warbler, Random(320), Random(200), ix, iy)
      }
   PreSwap()    ;Set up for double buffering
Here's the main game loop. Keep going as
long as there's warbiers alive and the
mouse is alive too.
   while (mouseid && warblers>0)
      {
      ClearScreen()   ;set screen quickly to black
      Evolve()   ;let all creatures live one tick
      Swap()  ;swap drawing screen and viewing screen
      }
   ToText()   ;back into text mode
   Prints(StrNum(warblers) + ' Warblers left");
   if (warblers <= 0)
      {
      Prints("You won!!!")
      }
   PrintsC Play again? (y/n)")
   int key   ;oops, need another variable. .
   key = WaitKey()
   if (key = = 'n'|| key = = 'N')
      break
And that's all there is to it: a video
game in about 100 lines of code!
   }