Monday, August 27, 2012

Petit Computer Journal #4



Petit Computer Journal #4

Knowing that computer is composed of numbers makes it easy to understand. That does not make it easy to do, you see, just to understand. The point is: The computer does what you tell it to do, not what you think you tell the computer to do. Faulty language implementation is an exception to that rule, and even then, you need to figure out a way around the problem.

Computer programming can be fun, but it can be very frustrating, indeed. The question is, what will you do to make computer programming fun? If the answer is to make games, then you're probably off to the wrong start. If the answer is to make games that people want to play, then you're probably off to the right start.

You see, computer programming is all about problem solving. What problem are you trying to solve? Without a clear goal, you probably will just do things randomly. Maybe you discover something, or maybe not. With a clear goal, however, you can work on the steps to achieving that goal. Then, when you finally solve that problem and arrive at your goal, your satisfaction level is quite high. That, my friend, is the fun of computer programming.

It's like winning a game, solving a puzzle, guessing a riddle. Before you did it, you don't know. After you did it, you know. That's fun.

Speaking of goals, you are still a beginner, so let's keep things simple for now. Let's start by figuring out how to tell a computer to do something simple.

Inkey$, input, linput

Let's get the keyboard input out of the way real quick. What is the difference between INKEY$, INPUT, AND LINPUT? Write a small program to check it out!

'Keyboard input source code example
@MAINLOOP
VSYNC 1: A$=INKEY$
IF A$!="" THEN B$=A$
LOCATE 0,0:?"A$=";A$;"   "
LOCATE 0,2:?"B$=";B$;"   "
GOTO @MAINLOOP

There are 3 things you have to see here:
VSYNC 1: This synchronized the system 1/60 second. Try it with different values and see what happens!
A$=INKEY$: This gets the keyboard value and assign it to A$
IF A$!="" THEN B$=A$: Since the value disappear at the next iteration, and we want to keep the old value, we assign the value of A$ to B$, but only if there is something to copy.

And that's it! If you are writing a computer game that cannot wait for user input, then INKEY$ is the way to go. I understand that it isn't the easiest to use, but it's there if you want it.

What's the difference between INPUT AND LINPUT? Try them out and see!

@MAINLOOP
VSYNC 1: INPUT "X,Y",X,Y
?"X=";X:?"Y=";Y
?:?:'DOUBLE BLANK LINES
VSYNC 1: LINPUT "DATA:";A$
?"A$=";A$
WAIT 300
GOTO @MAINLOOP

INPUT takes several inputs and assign them to different variables. This is very useful for inputting numeric values. Just type them out and separate them with comma. LINPUT takes in a string, commas included. Just one string.

Can you take string and numbers using INPUT? Try it and see!

@MAINLOOP
VSYNC 1: INPUT "X$,Y",X$,Y  '<==change here
?"X=";X$:?"Y=";Y            '<==Change here
?:?:'DOUBLE BLANK LINES
VSYNC 1: LINPUT "DATA:";A$
?"A$=";A$
WAIT 300
GOTO @MAINLOOP

Yes, you can! If the program doesn't understand your input, it will ask you to re-enter the data "?Redo from start". In which case, you re-enter the data, hopefully without mistake this time!


Touch Screen TCHX,TCHY,TCHST,TCHTIME PNLTYPE

Buttons and keyboard are nice, but we have something there that is just begging to be used: Touchscreen! I know I'm bucking the convention here, since most people are satisfied writing their beginner's program using INPUT or BUTTON(), but I really want to use the touch screen. Fortunately, it's as easy to use as INKEY$.

It's just some variables, and you even use it like you do INKEY$. The difference is that there is more than one, and you use numeric variables. Let's do it. It is helpful if we disable the on-screen keyboard. We do it via PNLTYPE command. Simply set it to "OFF".

'Touchscreen input source code example
PNLTYPE "OFF"
CLS
@MAINLOOP
VSYNC 1
X=TCHX:Y=TCHY:S=TCHST:T=TCHTIME
LOCATE 0,0:?"X=";X;"   "
LOCATE 0,2:?"Y=";Y;"   "
LOCATE 0,4:?"S=";S;"   "
LOCATE 0,6:?"T=";T;"   "
GOTO @MAINLOOP

Hit the Select button to stop the program. Yup. Just like INKEY$. The difference is, X and Y values are not reset to zero when the stylus is off the screen even though the status (TCHST) and timer (TCHTIME) are reset.


Math - Arithmetic

Alright, I need you to confess: Who among you have not yet finished 1st Grade? You know, the school grade right after Kindergarten? Whaat? You don't know Arithmetic? Oh, dear. This is bad. I think maybe you need to learn how before we can continue.

Haha, joking aside, you do need to know Arithmetic. Some Trigonometry, too. How about Algebra? Yes, you do need to know how to manipulate variables. Fortunately, if you know Show-and-Tell, you may be alright. Here's a little something that's useful to know: Mapping function.

map() is something that is built-in in Processing computer programming language. It's a good programming language. Check out www.processing.org for details.

In the meantime, let's implement it in BASIC. The idea is, if you have a number that is between two numbers, given another two numbers, what will be the number that has the same ratio as the first? In mathematical format, assuming X is the first number, and Y is the second, we have

X1-X2-X3 X2 is between X1 & X3
Y1-Y2-Y3 Y2 is between Y1 & Y3
Since the ratio is the same, we have
(X2-X1)/(X3-X1)=(Y2-Y1)/(Y3-Y1)

Solve for Y2:
(Y2-Y1)/(Y3-Y1)=(X2-X1)/(X3-X1)
(Y2-Y1)=((X2-X1)/(X3-X1))*/(Y3-Y1)
Y2=(((X2-X1)/(X3-X1))*/(Y3-Y1))+Y1

And that's all there is to it! Work it out on paper if you're having trouble. I find it helpful to draw triangles to visualize the problem.


A Math Explorer sample program

We want to feature a lot of math here, so we're going to just do it all in one program. The program will features different modes, and take inputs from touch screen, normalized to 0-5 for both X and Y. Furthermore, if the stylus is on top-left corner, we'll change the mode.

0: Simple Arithmetic
1: Math functions
2: Logical Math
3: Exponent

Here goes:

Part 1: Touch screen input. No problem there. Just copy it from the sample program above.


'Math Explorer
PNLTYPE "OFF"
CLS
@MAINLOOP
VSYNC 1
X=TCHX:Y=TCHY:S=TCHST:T=TCHTIME

Part 2: Display X,Y, Mode, and Cycle Mode. If you remember our COUNTER program example? Yup, just like that!

IF (X<32 AND Y<24 AND T==1) THEN MODE=MODE+1
MODE=MODE%4:'MODE=0-3
LOCATE 0,0
?"X=";X;"     Y=";Y;"     MODE=";MODE

Part 3: Normalize X and Y. We already have the mathematical formula for this. Just implement that using GOSUB.

X1=0:X2=X:X3=255:Y1=0:Y3=5:GOSUB @MAP:XP=Y2:'CALCULATES XP=Y2
X1=0:X2=Y:X3=191:Y1=0:Y3=5:GOSUB @MAP:YP=Y2:'CALCULATES YP=Y2
?"XP=";XP;"     YP=";YP;"     "

GOTO @MAINLOOP

@MAP
Y2=(((X2-X1)/(X3-X1))*(Y3-Y1))+Y1
RETURN


And that's the beginning. We'll continue with Part 4 next, but first, run this program and see that we have normalized XP and YP, and that the MODE cycles 0-3 satisfactorily.



Change the program slightly to this before continuing. Yes, I expect you to be able to read! I know it's hard in the beginning, but please persevere.

'Math Explorer
PNLTYPE "OFF"
CLS
@MAINLOOP
VSYNC 1:IF MODE!=2 THEN CLS
X=TCHX:Y=TCHY:S=TCHST:T=TCHTIME

IF (X<32 AND Y<24 AND T==1) THEN MODE=MODE+1
MODE=MODE%4:'MODE=0-3
LOCATE 0,0
?"X=";X;"     Y=";Y;"     MODE=";MODE;"     "

X1=0:X2=X:X3=255:Y1=0:Y3=5:GOSUB @MAP:XP=Y2:'CALCULATES XP=Y2
X1=0:X2=Y:X3=191:Y1=0:Y3=5:GOSUB @MAP:YP=Y2:'CALCULATES YP=Y2
?"XP=";XP;"     YP=";YP;"     "

GOTO @MAINLOOP

@MAP
Y2=(((X2-X1)/(X3-X1))*(Y3-Y1))+Y1
RETURN


And that's the program. Now, here is some snippets of code. I trust that you know where to put this.

?:?
ON MODE GOTO @ARIT, @FUNC,@LOGI, @EXPO
GOTO @MAINLOOP:'INVALID CHOICE

@ARIT
?"X+Y=";(X+Y)
?"X-Y=";(X-Y)
?"X*Y=";(X*Y)
IF Y!=0 THEN ?"X/Y=";(X/Y)
IF Y!=0 THEN ?"X%Y=";(X%Y)
IF YP!=0 THEN ?"X%YP=";(X%YP)
GOTO @ENDLOOP

@FUNC
?"FLOOR(XP)=";FLOOR(XP)
?"RND(X)=";RND(X)
?"RND(XP)+20=";RND(XP)+20
?"ABS(X-128)=";ABS(X-128)
?"SGN(X-128)=";SGN(X-128)
?"SWAP  ":SWAP XP,YP
?"XP=";XP;"     YP=";YP
IF S==1 THEN WAIT 30
GOTO @ENDLOOP


@LOGI
LOCATE 0,4
?"X=  ";:V=X:GOSUB @BIN
?"Y=  ";:V=Y:GOSUB @BIN
?"AND ";:V=(X AND Y):GOSUB @BIN
?"OR  ";:V=(X OR Y):GOSUB @BIN
?"XOR ";:V=(X XOR Y):GOSUB @BIN
?
?"X=  ";:V=X:GOSUB @BIN
?"NOT ";:v=NOT(X):GOSUB @BIN
?"!   ";:v=!X:GOSUB @BIN
GOTO @ENDLOOP

@EXPO
?"SQR(X)=";SQR(X)
?"EXP(XP)=";EXP(XP)
IF X!=0 THEN ?"LOG(X)=";LOG(X)
?"POW(2,XP)=";POW(2,XP)
?"POW(3,XP)=";POW(3,XP)


@ENDLOOP
GOTO @MAINLOOP

'SPLIT THIS TO THE END

@BIN
FOR I=0 TO 7
P=POW(2,I)
IF (P AND V) THEN ?"1"; ELSE ?"0";
NEXT
PRINT
RETURN




One more round of Math and we'll be done! It's all about Trigonometry. We'll save it for later until after we learn Graphics!



Monday, August 20, 2012

Petit Computer Journal#3


Petit Computer Journal #3

How to use Buttons and Directional Pad

Let's do something real quick. Let's make a counter that will increase when a button is pushed. Looking at the various commands, it is obvious that it is either BUTTON() or BTRIG(). Let's use BTRIG(). Reading the Help entry shows that the value returned by BTRIG() is usually 0. Non-zero if there's a button pushed. Perfect. We come up with this very quickly:

CLS
@COUNTER
B=BTRIG()
IF B==0 GOTO @COUNTER
A=A+1:A=A%1000:'0-999 CYCLE
?A;"      "
GOTO COUNTER

We run the program, and press a button. We see that the counter increments, all right. And it cycles to 999 like it should. However, the program registers so many button presses. That is not what we want. We want 1 increment per button push. So, we need to fix it. At this point, most people would do the sensible thing and type into Google: "Petit Computer how to use button". 

Haha, joking aside, we do need to understand how to read buttons properly. What do we do when the platform does not have built-in debugger? Well, we make our own!


What to do when things go wrong

I know I'm bucking the convention, here, but writing self-debugging program isn't that much trouble. The most important thing is that you want to understand what's going on. The simplest, easiest method to do it is read the manual. When the manual fails, however, we need to do better. That means we need to try things out and see what happens. It's called, "Learning without a teacher" or "Research". If you passed high school, then you know how to do it.

First make a hypothesis: One button press=one event. (desired behavior)

Then gather data: One button press=many events (observed)

Therefore, the conclusion is: what we want, and what we have are two different things. Error!

There are many kinds of errors in computer programming, but let's just simplify things a bit for now.

Computers are stupid, remember? If you mistype a command, the computer cannot handle it. If you forget a variable, the computer cannot handle it. If you transposed commands or letters or anything, the computer cannot handle it. The computer will complain: "Syntax Error!" That means, you have typed something incorrectly as to confuse the computer.

Another kind of error occurs when you ask the computer to do the impossible. Dividing by zero is one. GOTO a unlabelled section is another. These kind of errors are called "Run-time Error", because they occur at the running of the program.

Sometimes the program runs fine, but doing something else than what we want. We want to roll 5 dice, but only 1 is rolled. That means that what we say and what we want to say are two different things. We need to figure out a different way to say what we want. This is called "Semantic Error".

If, however, your screen is cracked, plastic is chipped, and stylus bent, then we have what is called PEBKAC Error: Problem Exists Between Keyboard And Chair. You probably should stay off computer programming for a while.

A binary review

If you're wondering why the values for the buttons are 1,2,4,8 etc, the answer is that the buttons do not have separate variables. The figure is all one number! There are different bits to the number, and that is what we're seeing. We can take a look at various bits by doing this code:

V=9
FOR I=0 TO 7
P=POW(2,I)
IF (P AND V) THEN ?"1"; ELSE ?"0";
NEXT
PRINT

In this case, we're doing a "Binary AND" (instead of "Logical AND") using bit 0-7. You can, of course, increase the bits to 31. I'm trying to keep it simple. Try putting in different values into V variable.


Source code for button readings

If we want to see what the buttons do, then it is very simple to do this:

CLS
@MAINLOOP
A=BUTTON(0)
B=BUTTON(1)
C=BUTTON(2)
D=BUTTON(3)
E=BTRIG()
LOCATE 0,0
?"BUTTON(0) ";:V=A:GOSUB @BIN
?"BUTTON(1) ";:V=B:GOSUB @BIN
?"BUTTON(2) ";:V=C:GOSUB @BIN
?"BUTTON(3) ";:V=D:GOSUB @BIN
?"BTRIG()   ";:V=E:GOSUB @BIN

'PLACEHOLDER

GOTO @MAINLOOP

@BIN
FOR I=0 TO 7
P=POW(2,I)
IF (P AND V) THEN ?"1"; ELSE ?"0";
NEXT
PRINT
RETURN

You can see the flickers for Button 1-3. That means the change happens in an instant. In this case, the change happens only in one frame, or 1/60 of a second. That's fast! I also see that the flickers on B is identical with the flicker on E. From that, I deduce that BTRIG() is equivalent to BUTTON(1). Is there any delay or waiting either with BTRIG() or BUTTON()? None that I can see.

If you want to make sure, replace the "'PLACEHOLDER" with these lines:

IF A!=E THEN LOCATE 0,7 :V=A:GOSUB @BIN:V=E:GOSUB @BIN
IF B!=E THEN LOCATE 0,10:V=B:GOSUB @BIN:V=E:GOSUB @BIN
IF C!=E THEN LOCATE 0,13:V=C:GOSUB @BIN:V=E:GOSUB @BIN
IF D!=E THEN LOCATE 0,16:V=D:GOSUB @BIN:V=E:GOSUB @BIN

The suspicion that BTRIG()==BUTTON(1) is confirmed! Now that's what I call successful research!



The fixed source code

Now that we know what is happening, we can do different things to fix it. 

First, we can specify that the increase is between Button Push and Button Release, like so:

CLS
@COUNTER
B=BUTTON(2)
IF B==0 GOTO @COUNTER
A=A+1:A=A%1000:'0-999 CYCLE
@C2
B=BUTTON(3)
IF B==0 GOTO @C2
?A;"      "
GOTO COUNTER

And that works nicely. However, let's see if we can improve things a bit. The manual mention VSYNC 1, as a way to get the input right. So, let's use that

CLS
@COUNTER
B=BUTTON(2):VSYNC 1
IF B==0 GOTO @COUNTER
A=A+1:A=A%1000:'0-999 CYCLE
?A;"      "
GOTO COUNTER

That also works, and notice that it is cleaner. What happens if VSYNC is set to something other than 1? Try it! You'll see that you will be missing some button presses. The exception to that is if you use BUTTON(0), and only at the sync.

CLS
@COUNTER
B=BUTTON(0):VSYNC 15:IF B==0 GOTO @COUNTER
A=A+1:A=A%1000:'0-999 CYCLE
?A;"      "
GOTO COUNTER

And that's what we want. Problem solved!

The rest of Console Entry Commands

Try out this command: BREPEAT 4,60,4
That will cause the A button to be repeated if you press it longer than 1 second. Pretty neat, eh?

Also, what is the difference between INKEY$, INPUT, and LINPUT?
INKEY$ behaves just like BUTTON(), in that it doesn't stop and wait for keypress.
LINPUT, LINE-INPUT, takes the whole line, including commas.
INPUT takes the line, and assign different values separated by commas.

And that's all there is to it!

Tuesday, August 14, 2012

Japanese Abacus Soroban 2



'Soroban - Japanese Abacus - SKH302-2
'Harry Hardjono
'August 2012
'
'Apparently, moving shapes is faster than show/hide shapes.

InitLoop:
GraphicsWindow.MouseUp=OnMouse
GraphicsWindow.Title="Small Basic Abacus"
GraphicsWindow.Width = 400
GraphicsWindow.Height=400
GraphicsWindow.FontSize=20
GraphicsWindow.FontName="Courier"
GraphicsWindow.Clear()
GraphicsWindow.Show()
GraphicsWindow.BrushColor="white"
GraphicsWindow.FillRectangle(0,0,GraphicsWindow.Width,GraphicsWindow.Height)
GraphicsWindow.BrushColor="black"

DoBG()
SetBead()
For i=0 To 14
BB[i]=0
SB[i]=0
EndFor
DoBead()
DoDigit()
IBB=BB
ISB=SB

DrawLoop:
BB=IBB
SB=ISB
x= GraphicsWindow.MouseX
y= GraphicsWindow.MouseY

DoMouse()
DoBead()
DoDigit()


Program.Delay(150) 'Wait 150 miliseconds
Goto DrawLoop

Sub DoBG
  GraphicsWindow.BrushColor="Black" 'Draw Frame
  GraphicsWindow.FillRectangle(0,0,399,212)
  GraphicsWindow.BrushColor="White"
  GraphicsWindow.FillRectangle(12,12,375,188)
  GraphicsWindow.BrushColor="Brown"
  For i=0 to 14
  GraphicsWindow.FillRectangle(23+(i*25),12,3,188)
  endfor
  GraphicsWindow.BrushColor="Black" 'Draw Slate & Rod
  GraphicsWindow.FillRectangle(0,62,399,13)

EndSub

Sub SetBead
'BigBead
  For i=0 to 14
  GraphicsWindow.BrushColor=GraphicsWindow.GetRandomColor()
  SSBB[0][i]=Shapes.AddEllipse(25,25)
  Shapes.Move(SSBB[0][i],12+(i*25),12)
  EndFor

'SmallBead
For j=0 To 3
  For i=0 to 14
  GraphicsWindow.BrushColor=GraphicsWindow.GetRandomColor()
  SSSB[j][i]=Shapes.AddEllipse(25,25)
  Shapes.Move(SSSB[j][i],12+(i*25),75+(j*25))
  EndFor
endfor

'Digits
  For i=0 to 14
  GraphicsWindow.BrushColor=GraphicsWindow.GetRandomColor()
  SSDG[i]=Shapes.AddText("0")
  Shapes.Move(SSDG[i],17+(i*25),212)
  EndFor

EndSub

Sub DoDigit
  For i=0 to 14
      Shapes.SetText(SSDG[i],(5*BB[i]+SB[i]))
endFor
EndSub


Sub DoBead
  For i=0 to 14
        Shapes.Move(SSBB[0][i],12+(i*25),12+(BB[i]*25))
EndFor

    For i=0 to 14
     For j=0 to 3
      If (SB[i]<=j) then
        Shapes.Move(SSSB[j][i],12+(i*25),75+((j+1)*25))
        Else
        Shapes.Move(SSSB[j][i],12+(i*25),75+((j)*25))
    endif  
    EndFor
EndFor

EndSub


Sub DoMouse
  map_var="mx1=12;mx2="+x+";mx3=387;my1=0;my3=15" 'Xcoord mapped to 0-14
  map()
  cx=Math.Floor(map_var["my2"])
  If (cx>=0 and cx<=14) then
    If (y>12 And y<62 p="p" then="then">      map_var="mx1=12;mx2="+y+";mx3=62;my1=2;my3=0" 'Ycoord mapped to 1-0
      map()
      cy=Math.Floor(map_var["my2"])
      If (cy>=0 And cy<=1) Then
        BB[cx]=cy
      EndIf
    EndIf

    If (y>75 And y<200 p="p" then="then">      map_var="mx1=75;mx2="+y+";mx3=200;my1=0;my3=5" 'Ycoord mapped to 4-0
      map()
      cy=Math.Floor(map_var["my2"])
      If (cy>=0 And cy<=4) Then
        SB[cx]=cy
      EndIf
    EndIf
  EndIf

EndSub

'----------------------------------------------
'map function
'----------------------------------------------
Sub map
  'x1-x2-x3 y1-y2-y3
  '(x2-x1)/(x3-x1)=(y2-y1)/(y3-y1)
  'y1+(y3-y1)*(x2-x1)/(x3-x1)=y2
  map_var["my2"]=((map_var["my3"]-map_var["my1"])*(map_var["mx2"]-map_var["mx1"])/(map_var["mx3"]-map_var["mx1"]))+map_var["my1"]
EndSub
 
'----------------------------------------------
'event function
'----------------------------------------------
Sub OnMouse
  if (BB<>IBB Or ISB<>SB) Then
    Sound.PlayClick()
  EndIf
  IBB=BB
  ISB=SB
EndSub

 

Small Basic Soroban Abacus


'Soroban - Japanese Abacus - SKH302
'Harry Hardjono
'August 2012
'
'These Unicode Characters draw Card Suits: Spade, Heart, Diamond,Club
'TestStr=Text.GetCharacter(9828)+Text.GetCharacter(9825)+Text.GetCharacter(9826)+Text.GetCharacter(9831)
'
'Over one hour is wasted because the Unicode characters for CharCL (empty bead) DO NOT LINE UP.
'


InitLoop:
GraphicsWindow.MouseUp=OnMouse
GraphicsWindow.Title="Small Basic Abacus"
GraphicsWindow.Width = 400
GraphicsWindow.Height=400
GraphicsWindow.FontSize=20
'GraphicsWindow.FontName="Courier"
GraphicsWindow.Clear()
GraphicsWindow.Show()
GraphicsWindow.BrushColor="white"
GraphicsWindow.FillRectangle(0,0,GraphicsWindow.Width,GraphicsWindow.Height)
GraphicsWindow.BrushColor="black"


CharCL=text.GetCharacter(9508)  '+text.GetCharacter(9474)+text.GetCharacter(9553)


SKB[0]=Text.GetCharacter(9556)
SKB[1]=Text.GetCharacter(9553)
SKB[2]=Text.GetCharacter(9553)
SKB[3]=Text.GetCharacter(9568)
SKB[4]=Text.GetCharacter(9553)
SKB[5]=Text.GetCharacter(9553)
SKB[6]=Text.GetCharacter(9553)
SKB[7]=Text.GetCharacter(9553)
SKB[8]=Text.GetCharacter(9553)
SKB[9]=Text.GetCharacter(9562)
DGT=" "


For i=1 To 15
  SKB[0]=Text.Append(SKB[0],Text.GetCharacter(9572))
  SKB[1]=Text.Append(SKB[1],Text.GetCharacter(9830))
  SKB[2]=Text.Append(SKB[2],Text.GetCharacter(9830))
  SKB[3]=Text.Append(SKB[3],Text.GetCharacter(9578))
  SKB[4]=Text.Append(SKB[4],Text.GetCharacter(9830))
  SKB[5]=Text.Append(SKB[5],Text.GetCharacter(9830))
  SKB[6]=Text.Append(SKB[6],Text.GetCharacter(9830))
  SKB[7]=Text.Append(SKB[7],Text.GetCharacter(9830))
  SKB[8]=Text.Append(SKB[8],Text.GetCharacter(9830))
  SKB[9]=Text.Append(SKB[9],Text.GetCharacter(9575))


IBB[i]=0
ISB[i]=0
DGT=Text.Append(DGT,(5*BB[i]+SB[i]))
EndFor


SKB[0]=Text.Append(SKB[0],Text.GetCharacter(9559))
SKB[1]=Text.Append(SKB[1],Text.GetCharacter(9553))
SKB[2]=Text.Append(SKB[2],Text.GetCharacter(9553))
SKB[3]=Text.Append(SKB[3],Text.GetCharacter(9571))
SKB[4]=Text.Append(SKB[4],Text.GetCharacter(9553))
SKB[5]=Text.Append(SKB[5],Text.GetCharacter(9553))
SKB[6]=Text.Append(SKB[6],Text.GetCharacter(9553))
SKB[7]=Text.Append(SKB[7],Text.GetCharacter(9553))
SKB[8]=Text.Append(SKB[8],Text.GetCharacter(9553))
SKB[9]=Text.Append(SKB[9],Text.GetCharacter(9565))




DrawLoop:
GraphicsWindow.FontSize=32
DKB=SKB
BB=IBB
SB=ISB
x= GraphicsWindow.MouseX
y= GraphicsWindow.MouseY
DGT=""


DoMouse()
DoBead()


For i=1 To 15
  DGT=Text.Append(DGT,(5*BB[i]+SB[i]))
EndFor


GraphicsWindow.FontSize=32
  GraphicsWindow.BrushColor="white"
  GraphicsWindow.FillRectangle(30,254,334,35)
  GraphicsWindow.BrushColor="black"
GraphicsWindow.DrawText(35,250,DGT)


GraphicsWindow.FontSize=40
For i=0 To 9
  If (ODKB[i]<>DKB[i]) Then
  GraphicsWindow.BrushColor="white"
  GraphicsWindow.FillRectangle(39,14+i*25,315,25)
  GraphicsWindow.BrushColor="black"
  EndIf
  GraphicsWindow.DrawText(20,i*25,DKB[i])
  ODKB[i]=DKB[i]
EndFor


Program.Delay(150) 'Wait 150 miliseconds
Goto DrawLoop


Sub DoBead
  For i=1 to 15
      DKB[2-BB[i]]=Text.Append(Text.Append(Text.GetSubText(DKB[2-BB[i]],1,i),text.GetCharacter(9553)),Text.GetSubTextToEnd(DKB[2-BB[i]],i+2))
      DKB[4+SB[i]]=Text.Append(Text.Append(Text.GetSubText(DKB[4+SB[i]],1,i),text.GetCharacter(9553)),Text.GetSubTextToEnd(DKB[4+SB[i]],i+2))  
  EndFor
EndSub




Sub DoMouse
  map_var="mx1=39;mx2="+x+";mx3=354;my1=1;my3=16" 'Xcoord mapped to 1-15
  map()
  cx=Math.Floor(map_var["my2"])
  If (cx>=1 and cx<=15) then
    If (y>39 And y < 85) Then
      map_var="mx1=39;mx2="+y+";mx3=85;my1=2;my3=0" 'Ycoord mapped to 1-0
      map()
      cy=Math.Floor(map_var["my2"])
      If (cy>=0 And cy<=1) Then
        BB[cx]=cy
      EndIf
    EndIf


    If (y>114 And y < 237) Then
      map_var="mx1=114;mx2="+y+";mx3=237;my1=0;my3=5" 'Ycoord mapped to 1-0
      map()
      cy=Math.Floor(map_var["my2"])
      If (cy>=0 And cy<=5) Then
        SB[cx]=cy
      EndIf
    EndIf
  EndIf


EndSub


'----------------------------------------------
'map function
'----------------------------------------------
Sub map
  'x1-x2-x3 y1-y2-y3
  '(x2-x1)/(x3-x1)=(y2-y1)/(y3-y1)
  'y1+(y3-y1)*(x2-x1)/(x3-x1)=y2
  map_var["my2"]=((map_var["my3"]-map_var["my1"])*(map_var["mx2"]-map_var["mx1"])/(map_var["mx3"]-map_var["mx1"]))+map_var["my1"]
EndSub
  
'----------------------------------------------
'event function
'----------------------------------------------
Sub OnMouse
IBB=BB
ISB=SB
EndSub  

Monday, August 13, 2012

Petit Computer Journal #2


Petit Computer Journal#2

Hello World!

It is a long-standing tradition among computer programmers to write a "Hello World" program when first learning a new computer language. It encompasses a fully functioning program. It tells the user that the computer is alive and kicking. So, here I will present the program. But since I like to do more than usual, I will first present the version of the program that is very popular in the old days. You can usually find it on display computers. Here it is:

10 PRINT "HELLO WORLD"
20 GOTO 10

That's it! The computer will display the words "HELLO WORLD" over and over again. What's with the numbers in the beginning of the line? They are called line numbers. Petit Computer Smile Basic does not use line numbers. No, really. Those line numbers you see in Petit Computer editor is totally unlike the line numbers you see here. Petit Computer line numbers are reference numbers. Good for telling you where your errors lie. Did you mistype PRINT as PRONTO? Error!

So, if Smile Basic does not use line numbers, how do we tell it to GOTO line 10? Well, first of all, I hope you know what GOTO does. Here's a bit of background:

Computer programs are made of different instructions. You see two of them here: PRINT, which displays the text, and GOTO which causes the instruction to go to the line number specified (in this case 10).

The computer uses something like a "Program Counter" - PC for short. All it does is specify which instruction is to be executed (or run). You can see this in action using TRACE command. Petit Computer does not have TRACE. Anyway, you have lines, and line numbers. The instructions is executed one after the other. GOTO will cause the instruction to go to the line specified. Petit Computer does not use line numbers. It uses label. You create a label by typing character '@' in front of the name. So the Hello World program goes like this:

@A :'Start of the program
PRINT "Hello World"
GOTO @A


A Word about @label

This isn't mentioned in the Help manual, but the program ignores everything after the space in label. So, theoretically, you can type this:

@A Start of the program

But I like to put in colon (command separator) and tick (comment) just in case the creator changed their mind and decide to allow something like this:

@A :PRINT "Hello World":GOTO @A

By the way, a question mark (?) is a shorthand for PRINT. So you can type ?"Hello World" instead of PRINT "HELLO WORLD"


What computers are made of?

By now, you are no doubt mesmerized by the powers of computer. The machine is capable of wonderful things. I know I'm bucking the convention here, but the computer is actually stupid. As in Forrest Gump stupid. No. Even worse than that! What are computers made of? A bunch of numbers. Really.

You see, a computer memory is a contiguous section of numbers. If you see the advertisement that a computer has 64KB. You know that a computer have about 64,000 numbers. Actually 2 to the power of 16 or 65536. Somewhere among those numbers are entries for touchscreen, buttons, various pixels on screen, and other things. But really, it's all just a bunch of numbers. Bits and bytes.

Fortunately, you don't have to know them. I usually tell people that there are two different things you can use: Text and Numbers.

Numbers are basically digits: 1,4,1234,3.5,3.46,3.121428. There is a difference between Integer and Real (Float), but not that much. Petit Computer uses 32 bit Fixed notation that is not too accurate. Be careful of round of error.

Strings are basically text. Strings are defined by enclosing text in quotation marks: "This is a text", "This is also a text", "That is a chair with a panda on it." 

You can assign numbers and text to variables (named references):
A=42 :'number.
A$="Hello World" :'string. Notice $ mark at the end of variable name!


What about bits?

Ah, yes. Bits and bytes. For user convenience, we don't deal with bits and bytes, mostly. There are times when we will have to, usually when we're interfacing with hardware. You can do binary digits by using "&b" and hexadecimal digits by using "&h". Try this:

PRINT &B1000 :'Prints 8
PRINT &B0100 :'Prints 4
PRINT &B0001 :'Prints 1
PRINT &B1100 :'Prints 12

PRINT &HACE :'Prints 2766
PRINT &HC :'Prints 12
PRINT &HC4 :'Prints 196
PRINT &HEAD :' Prints 3757


A quick sample program?

So, ready for a quick sample program? Didn't we just have one? Hello World is a program, isn't it? Oh, you want something that COMPUTES. Ok, how about this?

?2+2

The computer should print "4" underneath that statement. If not, try doing it in direct mode. Push the orange |>RUN button on the lower screen. Got it? There you go. A full functioning program!

Haha, joking aside, that is the original purpose of the computer: To compute numbers. But I can give you something else. This one is more substantial. You type this in /EDIT mode as it will not fit in one line in direct mode. Make sure that this is the only line. Type NEW in direct mode to erase any program in memory. Then enter edit mode and type this all in one line.

INPUT "NUMBER";N:FOR A=2 TO N-1:IF N%A==0 THEN ?"NOT PRIME" ELSE NEXT:?"PRIME"

Now enter direct mode. Type RUN. Here are some sample runs:

NUMBER?
267
NOT PRIME

NUMBER?
13457
PRIME

The interesting thing is, this line will also work in old style BASIC that allows IF-THEN-ELSE structure. The commands are as follow:
1. INPUT "NUMBER";N  'The program prints out the text "NUMBER", append question mark, and waits for user input. You type in a number. The computer copies the number to variable N
2. FOR A=2 TO N-1  'This is a loop. It assigns to variable A some numbers, starting from 2 to a number 1 less than you typed. It then repeats the command between this and the keyword "NEXT"
3. IF N%A==0 THEN 'This checks whether or not N is evenly divisible by A. 
4. ?"NOT PRIME" 'Prints out "NOT PRIME" if TRUE
5. ELSE 'A keyword that means the comparison is FALSE
6. NEXT 'This is the NEXT in FOR-NEXT LOOP. Increment the value of A by one and repeat the process.
7. ?"PRIME" 'This prints the word "PRIME". It is displayed when A has reached the value N-1 (as specified in the loop declaration)

Quite a program, eh? You have 7 steps all put into one line! I know that the loop may terminate after the square root of N, but I like to keep things simple.

Here's another program. Use it to practice inputting the program into the computer:
PRINT"FACTORS"
FOR A=2 TO N
@F :'LABEL FOR WHILE LOOP
IF N%A==0 THEN ?A:N=N/A:GOTO @F
NEXT

You type this underneath the PRIME 1-liner program. It uses the N from the INPUT "NUMBER";N instruction above. There is a little trick here that isn't mentioned in the help file. You can use multiple lines in IF-THEN by using colon. So, the statements ?A:N=N/A:GOTO @F will only be executed if N is evenly divisible by A. This isn't true for old BASIC, so don't be surprised if you need some modification in order to run it in old BASIC.

What have we learned?

You know:
Text and Numbers
Labels and GOTO
Direct (RUN) mode
Edit mode
PRINT and INPUT
RUN the program (executing the program).
Walk through the code (reading the code in editor)
The computer is stupid, stupid, stupid!

Try this:
What is the largest number that can be typed after the prompt? 
Shorthand for REM(REMARK)?

Edit:
You can also do this:


PRINT"FACTORS"
INPUT "NUMBER";N
FOR A=2 TO N
IF N%A==0 THEN ?A:N=N/A:A=A-1
NEXT

If works by adjusting the value of A one step backward, effectively making it the same value as before when it gets incremented by the loop.

Tuesday, August 7, 2012

Small Basic Auto Indent (with Subroutine lister)

'Indent - LDH635
'Harry Hardjono
'August 2012
'
CSD=0
indentlevel=0
indenttext="  "
indentarray=""
indentPlus=" sub for while if else elseif "
indentMin=" endsub endfor endwhile endif else elseif "


Filename=Program.Directory+"\indent1.sb"
FileSlurp()
For i=1 To Array.GetItemCount(FileData)
  SkipLeadSpace()
  CatalogSub()
  DoIndent()
  'TextWindow.WriteLine(OutData[i])
endfor


TextWindow.WriteLine("Sub List:")
For i=1 To Array.GetItemCount(SubData)
  TextWindow.Write(SubData[i])
  TextWindow.WriteLine("() ")
EndFor


Sub DoIndent
  StrIn=Text.ConvertToLowerCase(OutData[i])
  SpcInx=text.GetIndexOf(StrIn," ")
  If SpcInx=0 then
    SpcInx=Text.GetLength(StrIn)
  endif 
  StrIn=Text.GetSubText(OutData[i],1,SpcInx)
  StrIn=Text.ConvertToLowerCase(StrIn)
  If (text.GetLength(StrIn) > 1 And Text.GetIndexOf(indentMin,text.Append(" ",StrIn))>0) then
    indentlevel=indentlevel-1
    If indentlevel < 0 then
      indentlevel=0
    endif
    If indentlevel=0 then 
      indentarray[0]=""
    else
      indentarray[indentlevel]=text.Append(indentarray[indentlevel-1],indenttext)
    endif
    'TextWindow.WriteLine("DoIndentMin: "+StrIn)
  endif
  
  TextWindow.WriteLine(indentarray[indentlevel] + OutData[i])
  
  
  If (Text.GetIndexOf(indentPlus,StrIn) > 0) then
    indentlevel=indentlevel+1
    If indentlevel=0 then 
      indentarray[0]=""
    else
      indentarray[indentlevel]=text.Append(indentarray[indentlevel-1],indenttext)
    endif
    'TextWindow.WriteLine("DoIndentPlus: "+StrIn)
  endif
endsub




Sub CatalogSub
  StrIn=Text.ConvertToLowerCase(OutData[i])
  if text.StartsWith(StrIn,"sub ") then
    StrIn=Text.GetSubTextToEnd(StrIn,5)
    SpcInx=text.GetIndexOf(StrIn," ")
    If SpcInx=0 then
      SpcInx=Text.GetLength(StrIn)
    endif 
    StrOut=Text.GetSubText(OutData[i],1,SpcInx+4)
    
    CSD=CSD+1
    SubData[CSD]=StrOut
  endif
endsub


Sub SkipLeadSpace
  StrIn=FileData[i]
  StrOut=""
  For SLS_i=1 to Text.GetLength(StrIn)
    If (Text.GetCharacterCode(Text.GetSubText(StrIn,SLS_i,1))>32) then 'Non-space
      if (StrOut="") then  
        StrOut=Text.GetSubTextToEnd(StrIn,SLS_i)
      EndIf
    EndIf
  endfor  
  OutData[i]=StrOut
endsub




Sub FileSlurp
  'Read a file and assign it to an array
  'Input Filename (string)
  'Output FileData (array)
  FileLength=Text.GetLength(File.ReadContents(Filename))
  FileData=""
  FL=0
  FS_i=1
  While FL
    FileData[FS_i]=File.ReadLine(Filename,FS_i)
    FL=FL+Text.GetLength(FileData[FS_i])+2
    If FileData[FS_i]="" Then 'Fudge for blank lines in file
      FileData[FS_i]=" "
    EndIf
    FS_i=FS_i+1
  Endwhile
EndSub


Monday, August 6, 2012

Petit Computer #1


Petit Computer Journal#1

What is Petit Computer?

If you have been following Nintendo DSi development, then you'd know that SmileBoom has developed a downloadable computer program called Petit Computer. This is a development environment to create your own games on Nintendo DSi using BASIC. The idea is that you will write your own programs, and instead of buying other people software, you just write your own program. It's that easy! No more useless junk!

Why would you want to do that? In the beginning of computer history, there was simply no computer program available. You can either hire expensive professionals, or write your own program. Most people who grew up with early Personal Computer would write their own program. There are old magazines that tells people how to program their computer.

Later in the development of personal computer, softwares have become very complicated. Programming a computer is no longer within the realm of hobbyist computer. I still remember the disbelief that a C development system is 4 Gigabytes. Just how complicated can writing a computer program be? Very, very complicated!

And yet, most people do not need complicated programs. It does not take a rocket scientist to write a simple Blackjack program. Or create a maze. Or word search program. I did Sudoku program in one afternoon.

You don't need ridiculous amount of education in other to write useful program. You don't even need to write one. You can simply read what other people have done, and run their program on your Nintendo DS.

In short, Petit Computer is what Nintendo DSi homebrew, had it officially be done by Nintendo. Notice I said Nintendo DSi. That's because even though it's billed to be compatible with Nintendo 3DS, it doesn't take advantage of that platform. You can of course use Nintendo 3DS to run the program, but it's not necessary. If you don't have the device yet, I suggest the XL version. You won't have to squint at the small screen, and you can actually tap the keys with your fingernails, instead of stylus.

What's the difference between this and other BASIC?

SmileBasic, the BASIC language of Petit Computer, is very different from other BASIC languages. Most people are probably familiar with MS QBasic. Well, the difference between the two is that if you put this command "A=10:A=A/10:PRINT A" into Petit Computer, you'd get a "1". With QBasic, you'd get a "10".

Haha, joking aside, there is quite a big difference with the other BASIC. For one thing, this version of BASIC is very primitive when it comes to program structures. There is only FOR-NEXT loop. There is no such thing as WHILE-WEND, REPEAT-UNTIL, SWITCH-CASE. Rumor has it, you can't even GOTO out of the FOR-NEXT loop because you will corrupt the stack. That is strange. I will need to check for that. I think what happens is that the stack will run out because you cannot nest loops too deep.

Another difference is that SmileBasic is heavily tied into the Nintendo DSi hardware. This means sprites, background pictures, music synthesizers. Very powerful capabilities that is available for your use. You can easily make a Mario level game. Really.

The flip side to it is that if you aspire to make "modern" program such as the ones made by Visual Basic, then you are out of luck. This style of BASIC is old-style. Looking at the keywords of the language, I can't help to think that maybe this version isn't too friendly for beginners. Too much closely resembling Assembly Language/Machine Language. And you know what they say about Machine Language. If you cannot think in terms of Hexadecimal, then you may as well give up.

How hard is it to program a computer?

Paraphrasing an old joke:
Typing the program: $10.
Knowing what to type: $9990.

Computer programming is one of the easiest, if not the easiest job around. The qualification of that is IF YOU KNOW WHAT YOU'RE DOING. Do people know what they're doing? Surprisingly enough, no.

That's actually normal. Unless you're doing routine database programming, you probably will have to dissect the problem enough to come up with a solution. The problem you're solving is unique because if it's a common problem, then other people would have solved it already. Therefore, your problem solving skill must be top-notch.

The good news is, as a beginner, you don't have to be an expert solver. You're just starting out! By definition, other people have trodden the path before you, and you are going through familiar territory. If you get stuck anywhere, a simple question to the appropriate forum will suffice to get you going. There are plenty of tutorials on the Net. I plan to make some myself.

Do you need to be good at Math? No, you don't. I know I'm bucking the convention here, but we're talking about hobbyist computer programming. If you can balance your checkbook, then you can write computer program. If you know how to use spreadsheet program. You definitely have all the skills required. Higher level math is only necessary if you aspire to be a software ENGINEER. For hobbyist level, the most important skill needed is "Show and Tell". Really.


Should I really do this?

Why would you spend your time writing computer program on a very primitive system when you can have the world given to you by the latest and greatest in computer programming technology? How about Python? Ruby? Aren't they so great? Yes, they are, if you want to be productive.

If, however, you want to have fun and make games on Nintendo DSi, then this is the system to use! Not despite it being primitive, but because of it. Remember that old style 8 bit Apple, Atari, Commodore computer are rather primitive, and those computers were very useful. It doesn't take much to write useful programs.

I regularly write programs in Small Basic because it's fun. I will write programs in Smile Basic because it's fun. Remember: computer programming is easy, IF you know what you're doing. So the trick is, to first learn what you need to know in order to write the program, then write the program. By then, it'd be easy.

This is especially true with drag and drop programming. Let's take, for example, Macromedia Director. It's a very powerful platform, to be sure. But do you really learn how to program? Or do you learn to do use the package? Take away Director, and given Basic, can you replicate what you did with Director? Doubt it. Take away Basic, can you replicate what you did with Director? In my case, it took only 2 days, including learning the Director!

I hope I have convinced you to do this. If not, well, there's always Small Basic. :)