SIMPLE BEGINNINGS OF THE ROBOT WARPER PROGRAM
This is the beginnings of a program: here we just set up some essential routines and check that we get a line and a triangle drawn, matrix-like, on the screen. The output is shown in the included screencopy.
So, we are going to develop, step by step, a gradually larger and larger program, really well commented, and in edible doses. This program will enable us to have perhaps a bit of fun, if we're lucky, with a very symbolic, simple concept of some kind of robot-like equipment moving about in a kind of flatland seem from above. The beauty of the simplicity of this set-up is that we can explore the PRINCIPLES of software robotics engineering--to use a very fancy word. But I wish to say it, for simplicity is often a key to come to new insights, when it is the right type of simplicity.
If you've looked around in our educational texts, you have perhaps recently read something about matrices. How to set big matrices up. And armed with that knowledge, as well as with a bit of experience with other sorts of bits of the G15 PMN programming language, such as adjusting variable values, and finding the warp of a function, as we call it, by the FF function,--then this will be easy ride.
It will especially be an easy ride if you have read about, in the previous educational unit in this series, just what it takes to get going with expanding a simple included program in the G15 PMN platform, such as the Triangles program, which is at the first utility menu--easily reached by clicking around at the ':' colons at the Homepage, the G15 card, that G15 PMN greets you with, as soon as you've typed in the word CAR in the beginning.
For we are here going to expand the Triangle program. So, when you copy a lot of cards around, back and forth, you use how to get going with card-editing really quickly. To make space for a card when you need it, between two other cards, for instance, you just copy a whole lot of bunch of them to the right. So, in the Edit mode, you press CTR-C to copy, type a more than big enough number (presuming you have nothing important stored in cards just above the present area you are using of a disk), press PgDn to go to next card, and CTR-T to put it in, followed by a SPACE-click to confirm (or ESC to not do a putting or pasting after all).
So in the previous educational unit in this series, you got it going with the Triangle program all the way to the beginning of the disk i. And so the first card you see here is i:1479,--the screencopy is done while it's in the Edit mode. As you know, you switch between the Edit mode and the Menu mode by CTR-W and Right-Click on the mouse.
So the first card just have some comments about what this program is going to be.
Be sure, by the way, that the two phrases &TRIANGLES& and ZZ from the card just before it (you can use PgUp) are removed. We don't want the Triangles program to start up, we want our own program to start up, and it'll call on whatever it likes from the Triangles subroutines or functions or subprograms, in whatever way it likes.
And to start this new program, you have modified card i:1. It also has a place for date, a place for author, and a place for name and for type of the program. When, at some time, you do modify such fields when they are, as now, at the start of a G15 assembly program, please put in hyphens (_) or some sign like that between the words and digits, and retain the completing plus (+) that indicates that this is just an inessential 'extra', a comment, not essential for the computer.
What you modify i:1 to is, as we said in the previous educational unit, that the disk# is 9 for i, and the card number for the start of PMN code is 1092. If you like, you can browse back and forth around in these pages just to get to see how truly open source the G15 PMN language and compiler is, and how it all builds up gradually: and is compiled Just in Time, JIT, each time you run a program. (We use the word 'compilation' although it is only the first part that is compiled to G15 machine code, while the second part is converted to a quick format easily performed BY the G15 machine code: but it is not uncommon to call both of these 'compilations'; in addition, G15 may be run virtually on top of something, in which case there is a further level of performance before the actual electronics is touched.)
By the way: in order to learn a language it is a great good practise to type stuff in, and let your fingers learn to know it, and get to know to see it on the screen as you type it in--and if you type something that has to be corrected, there's additional memorizing advantages of that, too! Of course it is also fun to get, wholesale, full open source programs like the finished Robot Warper program in as an app, but to learn, we need to look at some parts at a time, and take time to think and reflect and ponder and try out things.
The ROBOTW program, as we also call it, first defines a matrx called SKETCH. This is set up to be exactly the same size as the type of matrix-like set of pixels that the Triangles program operates with. It means visible pixels, and while it admits to quite a lot of complexity, it will also be simple to relate to, and the routines will be fast--we can allow ourselves to go through every pixel as often as we like, without having to use G15 assembly code to do it--we can use ordinary PMN loops like LL:nnn .. LO to go through these matrices. And these are 144 in width and 100 in height and represented on the screen as you see in the output--with a black-green type of outline of square in each position, inside of which we 'paint' bright-green or moderate-toned green where we like.
The SKETCH matrix is where we draw. But when we move a robot, we want to check whether it bumps into something--another robot, for instance. We don't want the substance of our robots to mysteriously 'overlap'. So at some point, we need to have a detector for such 'touching'. We don't have to make it just as yet: but we must think through how to do this before we program too much.
And so we make SKETCH as the place where the Triangles routines draw. And when we have drawn all we want, and done all the detection we want, we put the SKETCH to the screen. For this, we have a routine called APPROVESKETCH.
However, we may also want to try out things, and go back a step, and try something else: for instance, if one robot gets too close another, or an item, then we want the original sketch back. So we need a SKETCHEXTRA. This is what we have on the next card.
We then see--at what is here numbered i:1482--that FRESHSKETCH calls on CLRTHISMANY. It is a filling up with nilchars, or zeroes,--which in our visible matrix corresponds to black. The tones are numbered 0..255, where 255 is bright green.
One of the huge advantages of having a language that isn't insisting on just one interpretation of a data structure like a matrix, is that we can use routines made for other data structures, like an array, on them--as long as we pay attention to what we do, when we do such little 'tricks'. In i:1483, we use the array-copy routine FW, which we can think of 'create a ForWard copy of this data here, to here, and this many of it'. Note that we write 14500 as quantity, for 144x100 is within this range; and this range is again within the 15000 we defined the arrays as in the first place. Such vaste of 50 32-bit numbers here and 50 32-bit numbers there was a thing unheard of in the 1960s and for a long while. Fortunately, to program today is a luxury experience, when we combine elementary good hardcore programming in a 32-bit oriented language, with an early 21st century computer speed, a RAM size going into many millions of such numbers, and more such. To engage in very much higher speeds or very much higher capacities may be necessary for certain extremely statistical-like tasks, but it is more humane and psychologically benefitting to match the computer's capacity with the ways and modes and speeds and attention spans of the human beings in charge of these computers. And computers are just machines, not minds, they have no real intelligence although they may be cunningly programmed: and so we must never set computers to program themselves except within extremely well-defined boundaries, and never set computers to make new computers, and the same applies for robots.
Talking about the limitations of machines, let us also mention something about the limitations of simplicity: why simplicity can be overdone.
For instance, there is such a thing as Goedel's incompleteness work, as we talk about in the G15 PMN App section, in an essay there, and other places as well.
Imagine that you made a formalism, somehow, in which the entire work of Goedel, that led Alan Turing to say that it seems to show that intuition is necessary in the understanding of anything, was 'expressable', if that's the word I want, by a statement this short:
"Proof of Goedel's 2nd incompl.theorem in our Ultra-mangificent-super-simple language: We write singularity(gform)=f and the machine produces t So this single line is a full representation and deduction and proof of Goedel's theorem."
I hope you agree that this is nonsense: the whole point of such a theorem is that it is perceived to be a clear idea in thought. We have no use for such a formalism. Nor should we be impressed by a language that can do virtual robots in 3d by a single line, or do an over-complicated (and computationally ineffective routine for nearly sorted lists) such as 'quicksort' by one or two or three program lines.
So simplicity can be a trap, we shouldn't pursue it at all costs. Larry Wall used to say that Perl is a mess because its data domain is a mess. Well, that's going a bit too far--the language doesn't exactly have to be 'a mess' in order to map a complicated data zone, but a language is supposed to stretch out so it meets thought. Human thought. Your mind! But it certainly should make sense. You don't write a novel, or even a short story, in just one line. A musical composition isn't finished in one nanosecond. Etc.
Companies, and simple-minded and perhaps not altogether well-educated researchers, may line up together and speak bold words about 'Artificial Intelligence'. They do so, because they haven't spent careful time thinking through the issues. There can only be algorithms, and rules for how to make rules, that apply WITHIN a context. The whole notion of speaking about 'hyper-intelligent machines' can only come from irreflectivity. By this it doesn't mean that a noticable proportion of the population cannot be fooled, just as one can sell homebrew alcohol bottled as a twelve-year old classical Whiskey. But it is not scientific to speak of Artificial Intelligence, except so as to negate it.
Let's walk back to the program. We were at i:1483. It has COPYSKETCH and GETSKETCH. These two allows to 'backup' and 'restore' the SKETCH. The SKETCHEXTRA can handle a matrix of the size of SKETCH. It exists for that purpose.
In i:1484, we do something that fitted just in one card, and these lines are best read together: and so we skipped having comments inserted here. Instead, the explanation is here.
First, we define a function PXTOSKETCH, short for 'put a new pixel of such and such tone to this place X and Y in our SKETCH.'
You notice that it says S3 then S2 then S1. This is a storing of the three values, X, Y and tone.
Why write S3 then S2 then S1? That is because it is easy to do so, as a convention,--to write such storage statements in the reverse sequence, as we pick numbers off the stack. On top of the stack, as the function starts, is tone. Right? And this goes into S3. Then Y goes into S2. Then X goes into S1. In other words, I1, I2, I3 will have X, Y and tone--in THAT sequence. So it is a psychologically convenient mechanism to preserve the feeling of the sequence of stuff put into a function, into a little program like PXTOSKETCH.
Then, the predefined (PD) word YY is used to put something to the sketch. I3 is given first, that is the value. Then I1 and I2, these are the X and Y coordinates for the SKETCH. Then the word SKETCH, and LK to get the hook to the matrix itself out of that variable. Finally YY is called and there that big dot (.).
Now, we want to override the earlier situation, where the Triangles-routines were writing straight to the screen. Fortunately, there is a variable called NORMALMATRF--short for 'holder for a warp to the NORMAL MATRField function', holder for a warp to the normal function to write to the screen. It is called MATRFIELD--all this we don't have to know, this is just a feature of the Triangle program. So by looking into the code of this program, this variable turns out to be defined there. And NORMALISEMATR makes use of this variable in just the right way.
So by this little hocus-pocus we have, by warps--let's make note again of how useful these little things are--connected our brand new definition of a sketch to PREVIOUSLY defined functions. Because these functions were well written (we were lucky with them), we don't have to copy these functions and modify them under a new name or anything. We just have to plug the new stuff into the slots.
Then, let's go to next card. There things are spelled out more leisurely.
APPROVESKETCH is what we call when we want to put the finished SKETCH to the screen for all to see. So we can call various drawing routines, and it'll all get stored to SKETCH. Then we call APPROVESKETCH, and it calls repeatedly--in fact one hundred times 144 times--on MATRFIELD1. That's the original pixel-draw function made by the Triangels program. It is defined very early in that series of cards. It wants X, then Y, then tone as input--exactly the same sequence as the little function we made on the previous card.
Let us note that at i:1485, we have LL:100 and LL:144 and we have LO and yet another LO. So this is what in all programming languages is called a 'nested loop', ie, a loop that is peacefully at home within another, socalled 'outer' loop.
When we make any use of LL:nnn .. LO, then I1 automatically get a counter value from 1..nnn. We can also use M1, that is the same value but one less, so it starts at zero, and goes only up to nnn minus 1.
When we have one or a couple of LL's inside one another, then the values get to I2 and some more.
When doing any loop, it matters to take an extra deep breath and look at it. The same goes for call to a function that loops through a lot--like the FW mentioned earlier, that copies an array from somewhere to somewhere else. A slight issue with such a loop can expand into a bigger issues, because of the repetitions. So it matters that it is right.
When dealing with X and Y stuff, it is often convenient to loop the Y in the other, for then the inmost loop will deal with the first row, the first line, with the starting-value for Y, where X varies.
So the height is Y, and height of our matrix is here 100. The width, X, is 144. So the inmost loop is 144. This is I2. So I2 is given first, then I1. X, then Y. Alphabetical.
Then we fetch the tone from SKETCH by using WW, which is the converse of YY. What we put into a matrix by YY we get out by WW. So I2 I1 SKETCH LK WW is one conceptual unit, we might say: it produces the tone at X=I2 and Y=I1. It doesn't matter that in other routines, X may be I1 and Y may be I2, for I1 and I2 and J1 and J2 (set by T1 and T2 instead of S1 and S2), and such, up to 9 and even X (as IX and SX), are all what we call 'local' variables. These are, in a sense, 'forgotten' as the computer exits that function, each time.
Well, there isn't much left, we're soon ready to test these routines by drawing a line and also a triangle by them.
First, after looking again into how the little Triangles program was made, it turned out that it would be nice to make a more compact way of creating a triangle by just one function call. This is then done in i:1486, by NEWTRIANGLE. It receives no less than six coordinates--three times the {X,Y} for each point in the triangle on the matrix in the {1..144, 1..100} range. Then SHAPETRIANGLE is the real magical core and crux of the Triangles program. When we call it it will use our new SKETCH-drawing routine, due to the work we did a couple of cards ago.
At the next card, i:1487, the INITSCREEN just produces a heading, RP uses ROBOTFONT to Print on screen, on top right; the word NEWMATRIX readies some variables used in Triangles, and also call VW which in some implementations of G15 is required in order to show the mouse pointer. But NEWMATRIX, defined rather late in the Triangles program, sets the area to bright green. We want it dark-dark-green, and so we have copied the numbers in that routine and written them again there, with a new tone. A G15 PC should be so fast that it is hardly noticable that the screen is done over twice.
Finally, ROBOTW is the main program. What we see at i:1488 is that this ROBOTW advices that this is just a very early, preliminary form of what we are going to make. Many more functions indeed will be defined before ROBOTW does its full job.
Anyway, at i:1489 there is a call to our new NEWTRIANGLE and also a call to a function inside the Triangles program, namely SHAPELINES. Both of them are supposed to now draw to the sketch, rather than to the screen directly. Sometimes, in programming, one speaks of this as drawing to a 'buffer'. In some cases, one can draw to a buffer, then to another from this, and THEN to the screen, in order to provide programs that flicker less in their graphical output. However, flickering may be a good thing for those programmers who are doing hardcore programming and who are making program that stimulate the mind instead of putting them to sleep by overly much gliding motions at all points!
The NEWTRIANGLE has tone first, while SHAPELINES has tone last. It is convenient to allow variations like this. For instance, the NEWTRIANGLE wants to do something with all the six coordinate values first--and only after that, deal with tone. But we need to look at each function definition when we write a program unless we're clearly certain about the sequence. There is no 'canonical' sequence.
Note that SHAPELINES has the feature that it calculates slopes, and can do lines between points that aren't lined up horisontally or vertically. In terms of the matrix, we will then see a staircase-like progress of lines that aren't aligned with the X nor the Y-axis. So SHAPELINES provides additional graphical functionality beyond the typically predefined, PD words for graphical output does, in terms of the High-Powered PMN Terminal. And the Triangle-drawing stuff builds on this type of stuff.
It is a key principle, a construction principle, we might say, of G15 PMN that nothing in the platform has been clipped from a book or another programming language and recoded here: rather, all is written simply by thinking through what is required in each case. That also means that you get first-hand programs, you get readable programs, programs that make sense if you only spend time with them, when you know something of G15 and G15 PMN as such.
Finally, at card i:1490, it says APPROVESKETCH. If you type in lines manually without typing in APPROVESKETCH, the triangle and the line won't show. Also, if you type in the program but put a comment | bar in front of the word (or at the A, so it becomes |PPROVESKETCH), then the line and the triangle won't show either. So this is a way to check that we've been doing fruitful thinking.
It waits until you press a key,--it reads it by the more advanced Keyboard Input routine that the High-Powered PMN Terminal provides (and this hi-pow terminal is part of the Triangles program, also). The SH shucks this key.
And then it says &ROBOTW& and ZZ to indicate that this is the new startup. Note that if you have a finished program, that you also have tested really well, it is normal to put QU into the program at its last line. In that way, it will quit back to the CAR menu that it started from. Instead, here we get a chance to try things manually, check the stack if we like (type F then NN and it should show 123456), and then manually type QU. This while the graphics is showing.
It is good, isn't it, that in G15 PMN there is always the sense of text ruling over the graphics: you type CAR, before it starts; then it starts in EDIT mode, fully willing to accept changes; as you do anything graphical in G15 PMN, you do it by typed in statements, or text on cards that you start; and then, having got the graphics up, you can type in still more, in the interactive mode of the language. In this way, you can learn to correct programs much much faster than in most other programming languages I know of: the fact that texts, SIMPLE texts (and not cluttered long lines with lots of commas, semicolons, colons, and such all put together in a particular sequence) rule over the computer and its graphics.
Notice that the drawing routine we have here, the PXTOSKETCH, at i:1484, doesn't check if there is anything at the pixels in the sketch already. So the 'detection' of 'bumping' or touching still remains to be done. Somehow, then, we'll do it by means if a little expansion of PXTOSKETCH, and then this expansion is hooked up to the NORMALISEMATR stuff. But the advantage of having this simpler sketch-writing routine is that it will definitely be a bit faster: remember that each line put into the pixel-drawing-routine is performed more than fourteen thousand times. And so if we want e.g. to draw a background area without bothering about touching pixels or not, we can have good use for PXTOSKETCH as it is. Given the fact of warps, it is easy to improve on how we do this later on in this programming process.















