Monday, December 17, 2012

Petit Computer Journal #13

Importing Data Into Petit Computer

One of the most important aspect in computing is data. In fact, I would say that the most important factor in computing is data. Everything that is important in computer can be traced to a database. Whether it is searching book titles such as Amazon.com, email, or managing your finances, data is usually the most important part of computing experience.

This has not always been true. Such early computer, say, having only 4 kilobytes of memory, downplayed the importance of data. However, without a good data reader, such as tape recorder, or worse, punch cards, such computer capability is wasted. Sure,there was Pong, but what good is it? The seminal early program was Adventure, or Collosal Cave, modelling the Mammoth Cave in Kentucky. Data is very important!

How can we enter data into the computer, specifically Petit Computer? Well, we can use the DATA keyword and type it in. But what if we already have it in our main computer? Here are the steps I use to import stock market data into Petit Computer.

1. Download the Historical stock data into your computer as CSV (Comma Separated Values)

Goto Yahoo.com and download a historical stock prices of your favorite stock. Make sure to save it as CSV format.

2. Open the file into your spreadsheet.

I use Microsoft Works, a cheaper alternative to Microsoft Office. Whatever works. Import the CSV file into the spreadsheet. Remove any unwanted columns. Insert column in the beginning. Fill it with "DATA". Save.

3. Open the file into Text Editor

I use Notepad. Replace all "DATA" with DATA, where you type a space character right after the text DATA. Add DATA "End",-1,-1,-1,-1,-1 at the end. This is assuming you're keeping the same data as me. Adjust accordingly.

4. Open up PTCUtilities.

Open up PRG Editor. Copy and Paste the text into the window. Comment out the first line. Make QR code out of it.

5. Scan with Petit Computer

Pick up your Nintendo DSi. Run Petit Computer program. Select "Scan QR Code". Import it to your Petit Computer. Let's call it STOKDATA.

6. Open up your main program.

I'm using the stock candlestick chart. The source code is at the end of the file. Load the program. Then on the RUN window, type "APPEND STOKDATA". This will add the content of STOKDATA to your current program. Save accordingly.

And there you have it, an easy way to import data to your Petit Computer Program.


'Stock Chart
@MAINLOOP
ACLS
GPAINT 6,6,6

C=0:MN=9999:MX=0
RESTORE @STOK
@STEP1
READ A$,OP,HI,LO,CL,AD
IF OP==-1 GOTO @STEP2
C=C+1:?C
IF MN>LO THEN MN=LO
IF HI>MX THEN MX=HI
GOTO @STEP1

@STEP2
RESTORE @STOK

FOR I=C TO 1 STEP -1
READ A$,OP,HI,LO,CL,AD
X1=C:X2=I:X3=1:Y1=247:Y3=24
GOSUB @MAP:DX=Y2
X1=MN:X2=HI:X3=MX:Y1=190:Y3=20
GOSUB @MAP:DHI=Y2
X1=MN:X2=LO:X3=MX:Y1=190:Y3=20
GOSUB @MAP:DLO=Y2

X1=MN:X2=OP:X3=MX:Y1=190:Y3=20
GOSUB @MAP:DOP=Y2
X1=MN:X2=CL:X3=MX:Y1=190:Y3=20
GOSUB @MAP:DCL=Y2

WAIT 1
GLINE DX,DHI,DX,DLO,8
IF OP>CL THEN GFILL DX-1,DOP,DX+1,DCL,15
IF CL>OP THEN GFILL DX-1,DOP,DX+1,DCL,14
GBOX DX-1,DOP,DX+1,DCL,15

NEXT

FOR I=BUTTON(3) TO 1:I=BUTTON(3):NEXT
GOTO @MAINLOOP

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



@STOK
'DATA "Date","Open","High","Low","Close","Adj Close"
DATA "2012-12-10",11.41,11.58,11.03,11.1,11.1
DATA "2012-12-03",11.56,11.7,11.18,11.48,11.48
DATA "2012-11-26",11.05,11.6,10.97,11.45,11.45
DATA "2012-11-19",10.65,11.1,10.65,11.1,11.1
DATA "2012-11-12",11.03,11.16,10.38,10.5,10.5
DATA "2012-11-05",11.15,11.59,10.71,10.93,10.93
DATA "2012-10-31",10.7,11.38,10.6,11.17,11.17
DATA "2012-10-22",10.14,10.49,9.97,10.36,10.31
DATA "2012-10-15",10.11,10.57,10.09,10.18,10.13
DATA "2012-10-08",10.06,10.26,9.95,10.12,10.07
DATA "2012-10-01",9.89,10.28,9.71,10.16,10.11
DATA "2012-09-24",10.3,10.4,9.81,9.86,9.81
DATA "2012-09-17",10.27,10.66,10.26,10.4,10.35
DATA "2012-09-10",10.08,10.57,10.06,10.53,10.48
DATA "2012-09-04",9.37,10.23,9.35,10.14,10.09
DATA "2012-08-27",9.51,9.52,9.25,9.34,9.29
DATA "2012-08-20",9.58,9.7,9.4,9.49,9.44
DATA "2012-08-13",9.35,9.67,9.25,9.63,9.58
DATA "2012-08-06",9.13,9.46,9.09,9.35,9.3
DATA "2012-07-30",9.04,9.42,8.82,9.09,9.05
DATA "2012-07-23",9.08,9.24,8.83,9,8.91
DATA "2012-07-16",9.22,9.52,9.12,9.21,9.12
DATA "2012-07-09",9.46,9.55,9.12,9.27,9.18
DATA "2012-07-02",9.5,9.79,9.3,9.5,9.4
DATA "2012-06-25",10.13,10.18,9.46,9.59,9.49
DATA "2012-06-18",10.35,10.74,10.18,10.19,10.09
DATA "2012-06-11",10.77,10.8,10.21,10.35,10.24
DATA "2012-06-04",10.15,10.78,9.91,10.66,10.55
DATA "2012-05-29",10.69,10.88,10.06,10.12,10.02
DATA "2012-05-21",10.02,10.68,10,10.6,10.49
DATA "2012-05-14",10.41,10.53,9.96,10.01,9.91
DATA "2012-05-07",10.53,10.86,10.4,10.58,10.47
DATA "2012-04-30",11.42,11.47,10.63,10.67,10.56
DATA "2012-04-23",11.15,12.04,11.15,11.6,11.43
DATA "2012-04-16",12.01,12.05,11.39,11.41,11.24
DATA "2012-04-09",12.26,12.29,11.65,11.92,11.75
DATA "2012-04-02",12.5,12.95,12.32,12.47,12.29
DATA "2012-03-26",12.45,12.61,12.18,12.48,12.3
DATA "2012-03-19",12.52,12.68,12.18,12.32,12.14
DATA "2012-03-12",12.57,13.04,12.37,12.51,12.33
DATA "2012-03-05",12.67,12.73,12,12.58,12.4
DATA "2012-02-27",12.11,12.94,11.99,12.72,12.54
DATA "2012-02-21",12.74,12.76,12.16,12.23,12.05
DATA "2012-02-13",12.74,12.88,12.33,12.75,12.57
DATA "2012-02-06",12.85,13,12.37,12.44,12.26
DATA "2012-01-30",12.06,12.84,12,12.79,12.6
DATA "2012-01-23",12.69,13.05,11.79,12.21,12.03
DATA "2012-01-17",12.2,12.72,11.96,12.59,12.36
DATA "2012-01-09",11.83,12.18,11.63,12.04,11.82
DATA "2012-01-03",11,11.8,10.99,11.71,11.5
DATA "2011-12-27",10.87,10.98,10.43,10.76,10.56
DATA "2011-12-19",10.25,11,9.99,10.95,10.75
DATA "END",-1,-1,-1,-1,-1



Tuesday, December 11, 2012

Petit Computer Picross


I'm curious of how well can people copying code from text as opposed to just scan QR code. So, this will come only as source code, no QR. Let's see how well you can copy this, and hopefully understand it. I won't be explaining anything. The source code tells all!
Major bragging rights to the first person who can change P[] array to meaningful numbers. 
PS: I did this in 2 hours pecking at the screen with the stylus! How far can you go? Keep pushing!
CLS:CLEAR
DIM P[16]
GOSUB @INIT
GOSUB @DISP
@LOOP
GOSUB @PANE
GOSUB @MOVE
IF G$==P$ GOTO @END
GOTO @LOOP
@END
BEEP 7:LOCATE 18,18:?"WIN!"
FOR I=1 TO 1:VSYNC 1:I=BUTTON(3):NEXT
END
@MOVE
FOR I=1 TO 1:VSYNC 1:B=BUTTON(3):I=B:NEXT
BEEP 66
IF B AND 32 THEN G$=SUBST$(G$,CY*16+CX,1,"0")
IF B AND 16 THEN G$=SUBST$(G$,CY*16+CX,1,"1")
IF B AND 1 THEN CY=CY+15
IF B AND 2 THEN CY=CY+1
IF B AND 4 THEN CX=CX+15
IF B AND 8 THEN CX=CX+1
CX=CX%16:CY=CY%16
SPOFS 1,CX*8,CY*8
RETURN
@PANE
FOR I=0 TO 15:FOR J=0 TO 15
LOCATE J,I
IF "0"==MID$(G$,I*16+J,1) THEN ?CHR$(32) ELSE ?CHR$(224)
NEXT:NEXT
RETURN
@DISP
CLS
FOR I=0 TO 255 STEP 16
H$="":C=0
FOR J=0 TO 15
IF "1"==MID$(P$,I+J,1) THEN C=C+1
IF "0"==MID$(p$,I+J,1) THEN IF C THEN H$=H$+STR$(C):C=0
NEXT
IF C THEN H$=H$+STR$(C)
LOCATE 17,I/16:?H$
NEXT
FOR I=0 TO 15
H$="":C=0
FOR J=0 TO 15
IF "1"==MID$(P$,I+(J*16),1) THEN C=C+1
IF "0"==MID$(p$,I+(J*16),1) THEN IF C THEN H$=H$+STR$(C):C=0
NEXT
IF C THEN H$=H$+STR$(C)
FOR J=0 TO LEN(H$)
LOCATE I,16+J:?MID$(H$,J,1);
NEXT
NEXT
RETURN
@INIT
P[0]=2016
P[1]=14364
P[2]=16770
P[3]=33729
P[4]=35793
P[5]=40377
P[6]=24186
P[7]=19506
P[8]=12300
P[9]=21066
P[10]=18834
P[11]=38505
P[12]=44085
P[13]=25638
P[14]=24582
P[15]=4104
FOR I=0 TO 15
V=P[I]:T$=""
FOR J=0 TO 15
T$=STR$(V%2)+T$:V=FLOOR(V/2)
NEXT
P$=P$+T$
NEXT
G$="0"*LEN(P$)
SPSET 1,156,0,0,0,0,16,16
SPANIM 1,4,15
SPSCALE 1,50
CX=0:CY=0
RETURN

Saturday, November 24, 2012

Black Friday Shopping

I just bought Modernist Cuisine at Home. It was on sale for 50% off, so I paid just $70. Good deal! I also bought Make Magazine 3D Printing special. I sure would like to print some in the future. Will be visiting Hackerspace nearby when I have time. I guess I'm a maker at heart.

Friday, November 23, 2012

Review The 4 Hour CHEF


I've just finished reading Timothy Ferriss' book The 4-Hour CHEF. It's a strange cooking book, to say the least. It's the only book I've read so far that includes not only recipes for various meals, but also catching food in the wild or even pigeons in the park. Also mentioned in there is memorization techniques good for developing vocabulary and random numbers.

I suppose it all dove in with his goal of "Meta Learning." As a jack of all trades myself, I approve. True that the book will not make you a Master Chef, as opposed to Joy of Cooking, but that's what the references are for. There's a lot of links in the book that goes back to his website. I have yet to check them all.

There's a lot of interesting tid bits, including how to win eating contest (he didn't, not exactly) and still be thin (he is). I'm not too happy about the fried rice meal. My favorite is the chicken fried rice, and although he has chicken, and fried rice, the featured fried rice featured mealworms, instead of chicken. Well, I suppose adapting his recipes is a given.

I am also not too happy with his tool selection. Way too many tools for what is supposedly a simple chef. I suppose now I have to get myself a 7 inch chef knife. That and a thermometer. Not to mention Modernist Cuisine book by Nathan Myhrvold. He also didn't mention my favorite cooking implement: Rice cooker. Using rice cooker effectively is what enables me to write 1000 words essay while the food is cooking. To be fair, he did mention 2 hour chicken meal, and I can fit in more than 1000 words with that kind of meal, but I digress.

A section of surviving catastrophe, like San Francisco earthquake is very interesting. Apparently, you need to be able to survive on your own for about 7-10 days without electricity or water. Get out a generator, because that is what you need to power your refrigerator! Very interesting and important knowledge to have. I just didn't expect to find it in a cookbook!

If Timothy Ferriss would come down my way sometimes, I'd like to ask him if he's interested in learning computer languages. After all, I learned my first computer language, the Applesoft Basic, in 3 hours. That's one hour shorter than his 4 hours learning. Admittedly, the subsequent computer language took longer than that, at about 2 days to one week. It's still relatively fast approach, though, compared to the traditional computer programming learning.

Maybe I'm an outlier. My life has never been an easy conformance. I sure want to know whether that 5 minutes per week weight-lifting exercise is any good. I suppose I'll need to add his other book to my library as well. Sigh. I'm supposed to be writing Nanowrimo right now! I wonder if Barry Ross wrote a book? Will have to check that out.

This book review was written while my food is cooking on rice cooker. It just beeped me, so I’m done!

Monday, November 19, 2012

No post this week

I'm way behind 8000 words with Nanowrimo. I guess life does have an interference. But if I make it, I know I can do anything! So, here's to keep trying. Hang in there!

Monday, November 12, 2012

Busy...

No Petit Computer post this week. I'm behind with Nanowrimo. :(

Monday, November 5, 2012

Petit Computer Journal #12


Packing, Saving, and Loading Data

One of the most desirable feature of computer programming is data loading and saving. Nintendo DS is used mainly for gaming, and the ability to save and load large amount of data is mostly an afterthought. However, there is a built-in feature to do so: MEM$. Basically, we simply assign the the string to MEM$, and save that.

We can enter multiple data into MEM$ by using splitting numbers technique: MID$. Let's say that we put the data for score in MEM$ location 10-15. We can extract that by using MID$, like this:

SCORE=MID$(MEM$,10,5)

A similar technique is to pack numbers into one large number. You can split them out like so:

CLS
?"FOR BITS:"
?"DEC:1=10;2=100;3=1000"
?"BIN:1=2;2=4;3=8;4=16"
INPUT "NUMBER,BITS";N,B
@LOOP
?N%B
N=FLOOR(N/B)
IF N!=0 GOTO @LOOP
?"DONE!"

SAMPLE OUTPUT:
123456,100
56
34
12


Let's say that we have data in multiple column format, that we want to save. I'm going to make it easy for testing, and just use 192*16*16. First, we make the data, then we save it two ways: Graphic and MEM$. We also load it 2 ways. Finally, we're going to put some timer on each operation.

'Make up data
DIM D[50000]
FOR X=0 TO 191
FOR Y=0 TO 15
FOR Z=0 TO 15
D[X*256+Y*16+Z]=RND(256)
NEXT:NEXT:NEXT

'SAVE DATA GRAPH
T0=MAINCNTL
FOR X=0 TO 191
FOR Y=0 TO 15
FOR Z=0 TO 15
GPSET (Y*16+Z),X,D[X*256+Y*16+Z]
NEXT:NEXT:NEXT
?"SAVE GRP0:TEST1"
T1=MAINCNTL

'SAVE DATA MEM$
T2=MAINCNTL
FOR X=0 TO 191
MEM$=""
FOR Y=0 TO 15
FOR Z=0 TO 15
MEM$=MEM$+CHR$(D[X*256+Y*16+Z])
NEXT:NEXT
S$="MEM:MEM"+RIGHT$("000"+STR$(X),3):?"SAVE ";S$
NEXT
T3=MAINCNTL

?"GRAPH:",T1-T0
?"MEM$: ",T3-T2

However way I look at it, the MEM$ version is harder, longer, and slower. I purposely skip the actual saving process because it asks whether or not you want to overwrite existing files, which in MEM$ case, rather ponderous. Even so, GRAPH method is faster than MEM$

GRAPH:  300
MEM$:   632

Now let's do LOAD:

'LOAD DATA GRAPH
T0=MAINCNTL
?"LOAD GRP0:TEST1"
FOR X=0 TO 191
FOR Y=0 TO 15
FOR Z=0 TO 15
D[X*256+Y*16+Z]=GSPOIT(Y*16+Z,x)
NEXT:NEXT:NEXT
T1=MAINCNTL

'LOAD DATA MEM$
MEM$="A"*256
T2=MAINCNTL
FOR X=0 TO 191
S$="MEM:MEM"+RIGHT$("000"+STR$(X),3):?"LOAD ";S$
FOR Y=0 TO 15
FOR Z=0 TO 15
D[X*256+Y*16+Z]=VAL(MID$(MEM$,Y*16+Z,1))
NEXT:NEXT:NEXT
T3=MAINCNTL

?"GRAPH:",T1-T0
?"MEM$: ",T3-T2

And the result?

GRAPH:  266
MEM$:   840

In all cases, the Graph version is leaner, cleaner, and faster than the use of multiple MEM$.


Monday, October 29, 2012

Petit Computer Journal #11


Trigonometry



Our last unfinished business about Math is now about to be concluded! It's pretty simple, really, so I'll add a few more things to round things up.

1. Map() we've seen this already

Let's begin by including an old function: MAP(). This is a function that lets you do numbers interpolation. It's a very useful subroutine, especially when dealing with graphics.

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

2. LOR Left Or Right.

This is very useful in game making, as well as different programs requiring graphics and the ability to tell left from right. The idea behind it is very simple: You take the slope of a line, and compare it to the slope of the other line. That is: dy1/dx1 cmp dy2/dx2. With some algebraic manipulation, we get this:

@LOR
LOR=SGN((DY1*DX2)-(DY2*DX1))
RETURN

3. Angle Measurements and Rotation

We want the ability to tell heading. Fortunately, ATAN functions takes two variables, and returns the angle (in radian), so it is trivial to do so. To check the angle from center screen:

A=ATAN(TCHY-96,TCHX-128) :'ATAN(DY,DX)

For drawing the line from the center, we can have

DX=R*COS(A):DY=R*SIN(A)
GLINE 128,96,128+DX,96+DY

Where R is the radius desired. Change the value of R for shorter or longer line.

4. Perpendicular line + angle offset

By changing the value of A, we can have different offset angle. Here's if you want 90 degree angle or perpendicular line.


DX=R*COS(A+(PI()/2)):DY=R*SIN(A+(PI()/2))


5. Cone Whether or not a point is within a cone

Take a point (X,Y), and two lines. We can see whether or not the point lines inside the cone by taking the LOR values and compare them. You have to be mindful of the angle.

You can also check whether or not a point is inside triangle, by doing so:

TX=TCHX:TY=TCHY
TX1=128:TY1=30
TX2=18:TY2=135
TX3=228:TY3=100

GLINE TX1,TY1,TX2,TY2
GLINE TX2,TY2,TX3,TY3
GLINE TX3,TY3,TX1,TY1

@LOOP
TX=TCHX:TY=TCHY
DX1=TX2-TX1:DY1=TY2-TY1:DX2=TX-TX1:DY2=TY-TY1:GOSUB @LOR:LOR1=LOR
DX1=TX3-TX2:DY1=TY3-TY2:DX2=TX-TX2:DY2=TY-TY2:GOSUB @LOR:LOR2=LOR
DX1=TX1-TX3:DY1=TY1-TY3:DX2=TX-TX3:DY2=TY-TY3:GOSUB @LOR:LOR3=LOR

IF LOR1==LOR2 AND LOR2=LOR3 THEN GPAINT 128,96,4 ELSE GPAINT 128,96,6
GOTO @LOOP

6. Intersection between 2 lines

We can also use LOR to check intersection between to lines. If the points of line 1 is on opposite side of line 2 AND the points of line 2 is on opposite sites of line 1, then we have intersection.

@LOOP
ACLS

PX1=RND(256):PY1=RND(192)
PX2=RND(256):PY2=RND(192)
PX3=RND(256):PY3=RND(192)
PX4=RND(256):PY4=RND(192)

GLINE PX1,PY1,PX2,PY2,6
GLINE PX3,PY3,PX4,PY4,10

GOSUB @ISCROSS
IF ISCROSS THEN ?"INTERSECT"

LINPUT A$
GOTO @LOOP

@ISCROSS
ISCROSS=TRUE
DX1=PX2-PX1:DY1=PY2-PY1
DX2=PX3-PX1:DY2=PY3-PY1
GOSUB @LOR:LOR1=LOR
DX2=PX4-PX1:DY2=PY4-PY1
GOSUB @LOR:LOR=LOR
IF LOR1==LOR2 THEN ISCROSS=FALSE

DX1=PX4-PX3:DY1PY4-PY3
DX2=PX1-PX3:DY2=PY1-PY3
GOSUB @LOR:LOR1-LOR
DX2=PX2-PX3:DY2=PY2-PY3
GOSUB @LOR:LOR2=LOR
IF LOR1==LOR2 THEN ISCROSS=FALSE
RETURN

@LOR
LOR=SGN((DY1*DX2)-(DY2*DX1))
RETURN


7. Movement: Direction and Speed

Let's take a simple spaceship movement real quick. Actually, it can be a car, duck, or whatever.

ACLS
SPSET 0,256,0,0,0,0,16,8
SPHOME 0.8.4
SX=128:SY=96:'SHIP POSITION
SD=0:SS=0:'DIRECTION AND SPEED

@LOOP
VSYNC 1:GCLS:CLS

GOSUB @SETB
IF B$=="U" THEN SS=SS+1
IF B$=="D" THEN SS=SS-1
IF B$=="L" THEN SD=SD-3
IF B$=="R" THEN SD=SD+3

IF 0>SS THEN SS=0
SD=(SD+360)%360

DX=(SS/16)*COS(RAD(SD))
DY=(SS/16)*SIN(RAD(SD))

SX=(SX+DX+256)%256
SY=(SY+DY+192)192

SPANGLE 0,SD
SPOFS 0,SX,SY

GOTO @LOOP

@SETB
B=BUTTON(0):B$=""
IF B AND 1 THEN B$="U"
IF B AND 2 THEN B$="D"
IF B AND 4 THEN B$="L"
IF B AND 8 THEN B$="R"
RETURN

8. A simple game: Asteroid

Let's see if you can take what we have, and build a simple game of Asteroid.

ACLS
SPSET 0,136,0,0,0,0,16,16
SPHOME 0,8,8
SPCOL 0,0,0,8,8,FALSE,&H10
SPANGLE 0,270
SPOFS 0,128,96
SX=128:SY=96:'SHIP POSITION
VX=0:VY=0:'SHIP VELOCITY
SD=0:SS=0:'DIRECTION AND SPEED
BL=0
NX=-50:NY=-50
GOSUB @BSTART
GOSUB @RSTART
SCORE=0:SHOT=1:COL=0
MAXEN=50:TT=0
WAIT 30

@LOOP
LOCATE 0,0
?"HIT=";SCORE;"   SHOT=";SHOT;"   COL=";COL;"   "
?"ACC=";FLOOR(SCORE*100/SHOT);"   MAXEN=";MAXEN;"   "
VSYNC 1:'GCLS:CLS

B=BUTTON(0)
IF B AND 1 THEN SS=1 ELSE SS=0
IF B AND 2 THEN SS=0
IF B AND 4 THEN SD=SD-3
IF B AND 8 THEN SS=0
SD=(SD+360)%360
'IF B AND 16 THEN GOSUB @FIRE

DX=(SS/16)*COS(RAD(SD))
DY=(SS/16)*SIN(RAD(SD))

VX=(VX+DX)
VY=(VY+DY)
IF VX< -5 THEN VX=-5
IF VY< -5 THEN VY=-5
IF VX>5 THEN VX=5
IF VY>5 THEN VY=5

SX=(SX+VX+256)%256
SY=(SY+VY+192)%192
SPANGLE 0,SD
IF SPHIT(0)!=0 THEN COL=COL+1
IF B AND 16 THEN GOSUB @FIRE
GOSUB @BLT
GOSUB @RLT

CNT=CNT+1:IF CNT>1000 THEN CNT=1000
TT=TT+1
GOTO @LOOP

@RLT
FOR I=50 TO 99
IF I>MAXEN GOTO @RLT2
IF SPCHK(I)==8 THEN SPOFS I,RND(256),RND(192),RND(300)+100
@RLT2
NEXT
LOCATE 0,3:?"C=";C;"  "
IF C+50>MAXEN THEN MAXEN=MAXEN+1:C=0
RETURN

@BLT
LOCATE 20,0
FOR I=1 TO 20
IF SPCHK(I)==8 THEN SPOFS I,NX,NT
IF SPHIT(I)!=0 THEN GOSUB @HIT
NEXT
RETURN

@HIT
IF SPHITNO<=20 THEN RETURN
SPOFS SPHITNO,NX,NY
SPOFS SPHITNO,RND(512)-128,NY-30,700
SPOFS I,NX,NY
SPCHR SPHITNO,192+8*RND(4)
BEEP 13
SCORE=SCORE+1
C=C+1
RETURN

@BSTART
FOR BL=1 TO 20
SPSET BL,40,0,0,0,0,16,16
SPHOME BL,8,8
SPCOL BL,0,0,4,4,FALSE,&H01
SPANIM BL,2,10,0
SPANGLE BL,SD
SPOFS BL,NX,NT
NEXT
RETURN

@RSTART
FOR I=50 TO 99
SPSET I,200,RND(16),0,0,0,16,16
SPHOME I,8,8
SPCOL I,0,0,8,8,FALSE,&H11
SPANIM I,2,10,0
SPOFS I,299,265
NEXT
RETURN

@FIRE
IF CNT>5 THEN CNT=0 ELSE RETURN
BL=BL+1:IF BL>20 THEN BL=1
SPOFS BL,SX,SY
SPANGLE BL,SD
DX=300*COS(RAD(SD))
DY=300*SIN(RAD(SD))
SPOFS BL,SX+VX+DX,SY+VY+DY,100
BEEP 10
SHOT=SHOT+1
RETURN




Thursday, October 25, 2012

Game Journalist Integrity

I would like to highlight a link that I found on the web.

http://botherer.org/2012/10/24/games-journalists-and-the-perception-of-corruption/

I think that it is a well-written piece. It is obvious that the piece was slanted. That is common. What is uncommon is that the writer, John Walker, specified exactly how he was slanted, and specified it, enabling me, the reader, to understand his true point-of-view, with higher degree of accuracy than usual. I think that most reviews should be like this.

I have mentioned earlier how some game reviewers are so bad and lazy at reviewing games. Here is an interesting excerpt from the comments:

"I remember going on a press trip to Italy where one very experienced writer happily boasted that he’d reviewed several games without even installing the product."

Yes, that actually happens. Can we say "yellow journalism" here? Absolutely. This is why I would go out and look at reviewers, then see whether or not their reviews matches common perception. You can do the same thing. Go to a game website reviews, and look at certain game scores. It helps if the game is not AAA game. Look for a score for a small Indie game.

Then go to a place to with forum that reviews the game. Amazon is a good site. There is a lot of honest reviews for the place where people vote with their own money. See if the review matches. If not? Then the reviewer doesn't know what his doing, and you can safely ignore his writings.

I do not personally write to the magazine/website that his reviewer is no good. I simply stop going there.

And that's the thing. For people who defend their false actions, there is a false sense of accomplishment. People who don't trust the bad reviewers won't tell the reviewers that they're bad. Or at least more than once. Thus, false sense of accomplishment.

The proof is in the pudding. Follow the money. If the game is critical success, but financial failure, then it makes it a suspect that either the reviewers don't know what they're doing, or maybe the PR is heavily influencing the outcome. Suspect either the reviewer or the game company. Simple.


Request for Nintendo (update)

Speaking of update, I did have request from August 8, 2010:

I do have some requests, assuming Nintendo is listening:
1. I want to watch movies on the device. Can you please provide official alternative other than Moonshell homebrew? Especially since you sue homebrew device out of existence.
2. I want a decent paint program, like Colors! homebrew. Arts Academy is fine, but a full fledge paint program will work great with portable mobile printer.
3. Family BASIC, or any kind of BASIC interpreter out there. WarioWare DIY is excellent, and I love it. But I have more imagination than what that program can handle.
4. Animation Studio. Excuse me. Please make that _3D_ Animation Studio. :) Or alternatively, VRML.
5. Some kind of wordprocessor, spreadsheet not a bad idea. Even if it's on the level of MS Windows CE kind.
6. And as long as I'm dreaming: Idol Master 3D, and Love Plus!

And now, here it is with Nintendo 3DS:
1. Watch movies: Yes! With NetFlix and Nintendo Video. Too bad YouTube isn't doable. But you do have the option to create your own movies up to 10 minutes at a time. 
2. Paint Program: They nailed it perfectly with Colors! 3D. A new Art Academy is available, too!  Mobile Printer? They allow image upload with their browser. Perfect! Can't ask better than that! Thank you Nintendo!
3. Family BASIC: Yes! With Petit Computer and Smile Basic. It is everything I want! Thank you SmileBoom. Okay, so this one is for DSi, instead of 3DS, but hey, it's compatible!
4. Animation Studio: Still waiting. They promised FlipNote 3D, but it has been a long time. SwapNote is nice, though, but I really want a good animation program. Inchworm Animation is great, but lacking memory and storage space. Could be better.
5. Not yet. The lack of a good keyboard is a killer. I think that if Pokemon Bluetooth keyboard catches on, it is doable, but as of right now? Nope.
6. Idol Master? Nope. Which is too bad, but they do have some singing programs out there. And recently there is a Blackjack game that is similar to Love Plus Light. The reviewers missed the point of the game. But I have to say that this one is a definite Yes!

Four out of six isn't bad. It's great! 

Alpha Colony Update

Back then on July 18, 2012, I mentioned Alpha Colony project by DreamQuest on Kickstarter. It failed. I have been following it on and off, and the last thing I heard about it is that they're looking for a 3D Maya animator. It surprised me that they're looking for one right now. They have been putting out new animation so far. How come the walk cycle animation is work-in-progress? But I digress.

Apparently, they learn their lesson well. They are working on a new Alpha Colony Kickstarter project, this time without the license. They are also downgrading their goal from $500,000 down to $50,000. You probably wonder whether or not they can do $500,000 game for $50,000. The answer is: They can't.

They acknowledge this by going to stretch goals: Mac and Linux version at $130,000. Multiplayer version at $250,000. And that is as it should be. They should have done it that way the first time!

Still, it is good that they learn from their mistake. I am waiting for their newly relaunch Kickstarter project. It has been delayed several times, which tells me that they are rather over-ambitious regarding their capabilities, especially in the fact that animation isn't done yet.

I would like to see a lot of concept art in the newly re-launch kickstarter project. It will be interesting indeed, since they promised to let you design a new alien character along with its special ability. I'm sure that right isn't cheap, but hey, you're a professional game designer! If you can't work it, buy your way into the industry!

Lest you think that is bad, actually it's pretty common for some uppity business person to design a game and hire professional game designer to flesh out the ideas and implement it. There has been some extremely questionable games in the gaming history! I'm sure this one will be fine, though. The premise is fixed, and the gameplay is based on existing game. It'll be very hard to mess it up.

If there is a chink in the armor, it'll be game balancing. I don't know how good they are in balancing their games, but looking at their catalog, it doesn't really give me confidence that they'll be great at it. Oh, well. We'll see.

Friday, October 19, 2012

No Update This Week

I got excited over the Nanowrimo stuff. I did make a new blog and well, it's just started, so there's nothing there. Eventually, it will contain fictional stories. But maybe I'm a slow worker or something. I keep running out of hours. Will be back to posting Petit Computer blog next week.

Monday, October 8, 2012

Petit Computer Journal#10


Petit Computer Journal #10

Graphics and Paint



We are going to go ahead and do all the graphic routines. I think the best way to do it is to just make a paint program. It won't be the prettiest paint program ever, but it'll do to make us understand how the graphic works. For the interface, I'll use Directional Pad for choosing colors and Tools. Touchscreen is for drawing. Turn the panel off by PNLTYPE "OFF"

'SHAPE MAKER
ACLS:GPAGE1:PNLTYPE "OFF"
S=0:MAXS=12:

S is current shape number. MAXS is Max shape number. Starts with one, and as time goes on, keep increasing it.

@LOOP
GOSUB @DT
VSYNC 1:B=BUTTON(3)
IF B AND 1 THEN C=(C+1)%16
IF B AND 2 THEN C=(C+16-1)%16
IF B AND 4 THEN S=(S+MAXS-1)%MAXS
IF B AND 8 THEN S=(S+1)%MAXS

X=TCHX:Y=TCHY
FOR I=1 TO 1:I=!TCHST:IF I==0 THEN GOSUB SETR:GOSUB @DRAW
NEXT
GOTO @LOOP

The interface routine is simplicity itself. Basically, either use the directional pad to change color and shape, or detect Touch screen for drawing. This is done simply because it was done spontaneously while waiting for something. I added the number of shapes gradually over time.

@DT
CLS:COLOR 0
?"COLOR=";
GPAGE 0:GFILL 50,0,100,50,C:GPAGE 1
LOCATE 0,10:?"SHAPE=";
IF S==0 THEN ?"CIRCLE"
IF S==1 THEN ?"LINE"
IF S==2 THEN ?"BOX"
IF S==3 THEN ?"FILL"
IF S==4 THEN ?"LINETO"
IF S==5 THEN ?"PAINT"
IF S==6 THEN ?"PSET"
IF S==7 THEN ?"PAINT BORDER"
IF S==8 THEN ?"AIRBRUSH"
IF S==9 THEN ?"AIRBRUSH STENCIL"
IF S==10 THEN ?"PSET STENCIL"
IF S==11 THEN ?"HEAVY AIRBRUSH STENCIL"
RETURN

This is to draw the top screen, showing the color and the shape tools. If the selection is somewhat random, it is because I add to it random. The first four was done immediately. Then I add LINETO. PAINT,PSET follows. PAINT BORDER because I want to learn how to use it. The rest is my desire to add stipling to the graphic.
It is actually an improvisation. A good way to do it is using ELSE-IF ladder. A better way to do it would be using Array. The best way to do it is by using Graphics, icons, and highlights. I'm not going to do that for now.

@SETR
DX=TCHX-X:DY=TCHY-Y
R=SQR(DX*DX+DY*DY)
RETURN

Set Radius. This is used for CIRCLE.

@DRAW
GCOLOR C
S=S%MAXS:ON S GOSUB @CIR,@LIN,@BOX,@FIL,@LI2,@PAI,@SET,@BOR,@AIR,@STE,@PST,@HAIR

It doesn't get any simpler than that. Who knew computer programming can be so easy? I know I'm bucking the convention here, but I really don't think much about computer programming. Computer programming is merely the translation from English (human) language to BASIC (computer) language. It can be done mechanically. Design, which requires you to specify something that doesn't exists, is a much more challenging endeavour, simply because there is no way to be sure what you do is the best way to do it. You must experiments with different things.

I like to have 3 different solutions to the problem: A good one, a better one, and a best one. It has served me well throughout the years and something I suggest you adopt in order to expand your skills as computer programmer.

@CIR
FOR J=0 TO R:GCIRCLE X,Y,J:NEXT
RETURN

@LIN
GLINE X,Y,TCHX,TCHY
RETURN

@BOX
GBOX X,Y,TCHX,TCHY
RETURN

@FIL
GFILL X,Y,TCHX,TCHY
RETURN

Do I really need to explain these? They are self-explanatory. I will mention that loop for circle. The circle command isn't filled. I don't find much use for rings. I want circles. This is a design decision. So, I wrote it like that. Filled CIRCLE! It's not perfect, though, and you are encourage to fix it.

The color was set by GCOLOR C statement above. I could, and indeed, should, use the expanded command of specifying color at the end: GLINE X,Y,TCHX,TCHY,C on all commands. It's part of unifying aspect of the program.

@LI2
X2=TCHX:Y2=TCHY
GLINE X,Y,X2,Y2
X=X2:Y=Y2
RETURN

This is simply connecting line. If you look at the Touch screen code above, you will see that the last point of the line becomes the first point of the next line. Easy as pie!

@PAI
GPAINT X,Y
RETURN

@SET
IF TCHST==1 THEN GPSET TCHX,TCHY:GOTO @SET

@BOR
GPAINT X,Y,C,C+1
RETURN

GPAINT is easy enough. How about @BOR? That's GPAINT with border. I want to see how the paint functions with border color specified. Here, I specified C+1 as the border. Obviously, you can specify any color you want as the border, not just the next one.

Regarding GPSET, I put it in a loop because I want to do stippling technique. No mystery there.

@AIR
FOR W=1 TO 200:NEXT
IF TCHST==1 THEN GPSET TCHX+(RND(17)-8,TCHY+(RND(17)-8):GOTO @AIR
RETURN

@STE
VC=GSPOIT(X,Y)
@STE2
VSYNC 1:VX=TCHX+(RND(11)-5):VY=TCHY+(RND(11)-5)
IF GSPOIT(VX,VY)==VC THEN GPSET VX,VY
IF TCHST==1 GOTO @STE2
RETURN

@PST
VC=GSPOIT(X,Y)
@PST2
VX=TCHX:VY=TCHY
IF GSPOIT(VX,VY)==VC THEN GPSET VX,VY
IF TCHST==1 GOTO @PST2
RETURN

@HAIR
VC=GSPOIT(X,Y)
@HAIR2
VX=TCHX+(RND(11)-5):VY=TCHY+(RND(11)-5)
IF GSPOIT(VX,VY)==VC THEN GPSET VX,VY
FOR W=1 TO 200:NEXT:'WAIT AWHILE
IF TCHST==1 GOTO @HAIR2
RETURN

The @AIR airbrush is simple enough. There is a WAIT 200 cycles because if not, the pixels are sprayed remarkably quickly. Otherwise, it's just a random GPSET within a square.

@STE Stencil is the same way with the added factor GSPOIT() where VC is set to the current color. The pixel won't be plotted unless the pixel color is the same as the original VC.

@PST GPSET with Stencil. Enough said.

@HAIR Heavy airbrush. This is where I experimented the most. The discoveries found here was shared with other functions, notably the WAIT 200 cycles.

And you know what? The implementation of the program itself was really quick. So much so, in fact, that it was done while there was still waiting time. I spent the rest of the time doodling. Dogs, Flowers, People, and other sketches. It really works! It makes me wonder whether or not I should spend points getting The New Art Academy!

Haha, joking aside, I did do several renderings that I like very much. I experimented with saving the pictures. Not too successful, so I will need to revisit the issue in later journal. Until then, please have fun with drawing sketches, and share!

UPDATE:

I managed to implement LOAD/SAVE GRP files. Pretty simple. SAVE GRP0:filename (top screen). GRP1:filename (bottom screen). Also GRP2, and GRP3, for back buffer screens. I will give you the subroutine codes only. I assume you know how to integrate it to the program.

@BIG :'BIG LINE TO
X2=TCHX:Y2=TCHY
GLINE X,Y,X2,Y2
GLINE X+1,Y,X2+1,Y2
GLINE X-1,Y,X2-1,Y2
GLINE X,Y+1,X2,Y2+1
GLINE X,Y-1,X2,Y2-1
X=X2:Y=Y2
RETURN

@SAV
SAVE "GRP1:G0"
RETURN

@LOA
LOAD "GRP1:G0"
RETURN

Also, there's no reason why we can't have at least reasonable User Interface. Try this:

@LOOP
GOSUB @DT
VSYNC 1:B=BUTTON(3)
IF B AND 8 THEN C=(C+1)%16
IF B AND 4 THEN C=(C+16-1)%16
IF B AND 1 THEN S=(S+MAXS-1)%MAXS
IF B AND 2 THEN S=(S+1)%MAXS

That's right. We just exchanged the up/down with left/right. What does this change give us? How about this?

@DT
CLS:GPAGE 0

GFILL 0,160,255,175
GFILL C*16,160,(C+1)*16,175,C
FOR I=0 TO 15
GFILL I*16,175,(I+1)*16-2,191,I
NEXT

COLOR 0
LOCATE 0,0:?"ACTION"
?"   CIRCLE"
?"   LINE"
?"   BOX"
?"   FILL"
?"   LINETO"
?"   PAINT"
?"   PSET"
?"   PAINT BORDER"
?"   AIRBRUSH"
?"   AIRBRUSH STENCIL"
?"   PSET STENCIL"
?"   HEAVY AIRBRUSH STENCIL"
?"   BIG LINETO"
?"   SAVE GRP1:G0"
?"   LOAD GRP1:G0"

LOCATE 0,S+1:?">"

GPAGE 1
RETURN

Now the interface have gone from only a Dilbert nerd would tolerate, to the average programmer would tolerate. Quite a big difference with only small changes involved. Small, but significant changes. I made the mistake of coding a lot of PRINT, only to take them out once I realized this small change is all it takes. The lessons here are:
1. Good is the enemy of Great
2. Do not be afraid in discarding bad code!
3. Think then Do. Do then Think results in a lot of time wasted writing and discarding bad code.

I would love to have zoom, but the whole interface must be redesigned. Maybe a speech balloon and layer option, hmmm?

Monday, October 1, 2012

Petit Computer Journal #9


Petit Computer Journal #9

Loops and Banner

A quick diversion here, I want to discuss a little bit about loops. We have been doing it, and it's not hard to do, but that doesn't mean people understand them completely. I keep seeing people do things in inefficient ways. I know I'm bucking the convention here, but I think making the program work the way you want it is the minimum requirement. You should also improve the program in such a way that it is well structured, implemented, and clear.

So, what's so hard about loops? Nothing. That's why it's important for you to master loops. There are several kinds:

1. Infinite loop: This is easy. You basically want to repeat something over and over. Most C programmers would use this construct:

while (1) { ... }

That's an infinite loop. But I think this is the case where GOTO is better. Here it is in Smile BASIC:

@LOOP
...
GOTO @LOOP

And that's it for infinite loop. It's good for use as IDLE loop.

2. REPEAT-UNTIL loop: Also known as DO-WHILE, this is just like infinite loop, but it ends when there is a certain condition to be met. You can do it like this:

@LOOP
...
IF (NUM

or this

@LOOP
...
IF !(NUM>=MAXNUM) GOTO @LOOP

or this

FOR I=1 TO 1:VSYNC 1:I=BTRIG():NEXT

That last example is basically "Press any BUTTON to continue". It works because as long as I is zero, the loop repeats.

Another example of REPEAT-LOOP would be this program in finding out the value of PI using fraction:

'PI
N1=3:N2=1
R1=ABS(PI()-(N1/N2))

FOR I=1 TO 1
R2=(ABS(PI()-(N1/N2)))
IF (N1/N2)
IF (N1/N2)>PI() THEN N2=N2+1
I=!R2:'TERMINATE WHEN I==0.

IF R2
NEXT

?PI()
?(N1/N2)

The structure is similar to HI-LO game, and it's a good exercise for you to do in order to see if you understand the concept. In the meantime, if you see the statement I=!R2 where R2 is fraction, we can say that I'm abusing ! operator to the max!

Haha, joking aside, I do tend to push the interpreter beyond standard convention. It takes a lot of trial and error, with mostly error on the result. But you can't argue that the result is good.

3. WHILE-WEND loop: This loop differs from REPEAT-UNTIL loop by the fact that the code may not be executed at least once. By putting the condition on top of the loop, the whole code may be skipped.

@LOOP
IF (NUM>=MAXNUM) GOTO ENDLOOP
...
GOTO @LOOP
@ENDLOOP

or this

@LOOP
GOTO @ENDLOOP
...
@ENDLOOP
IF (NUM

or this MADLIBS example

A$="HELLO [N]. HOWDY [N]. GOODBYE [N]."
LINPUT "NAME";N$
T$="[N]"

@WHILE LOOP
FOR I=0 TO INSTR(A$,T$)
A$=SUBST$(A$,INSTR(A$,T$),LEN(T$),N$)
NEXT
?A$

Yes, it's that easy! See explanation on FOR-LOOP on how this works.

4. FOR-LOOP. The standard BASIC loop. The workhorse loop of BASIC. How difficult can it be? It's just like WHILE loop, except the value of I is incremented within the code. Smile BASIC will not execute the loop when the parameters do not match, such as this:

FOR I=0 TO -1 STEP 1

I took advantage of this fact by putting INSTR() directly on the loop declaration. You don't see "STEP 1" written out, but it is implied. If you need stepping other than 1, then you need to write it out. STEP 4, STEP -1, and so on.

NUM=0
@LOOP
IF (NUM>MAXNUM) GOTO ENDLOOP
...
NUM=NUM+1:'OR NUM=NUM+N WHERE N IS THE STEP VALUE
GOTO @LOOP
@ENDLOOP

FOR NUM=0 TO MAXNUM: ... :NEXT

And that's it for LOOP structures. There is a couple more things we need to talk about. BREAK and CONTINUE.

CONTINUE is the way for the loop to skip processing to the next step. That is, whatever we want to do, we're done! We don't want to do any more.

@LOOP
...
IF CONTINUE GOTO LOOP
...
GOTO @LOOP

Let's do an example with FOR loop. Let's say we want to skip displaying vowels. We can do this:

A$="HELLO SAILOR!"
FOR I=0 TO LEN(A$)-1
IF INSTR("AEIOU",MID$(A$,I,1))>=0 THEN NEXT
? MID$(A$,I,1);
NEXT
?:?"DONE!"

Yes, you have two NEXT statements in there. The NEXT on IF line functions as CONTINUE. Pretty easy, right? (1)

BREAK, however, is not so easy. Not that it's difficult to understand, but it's difficult to implement because we cannot GOTO out of LOOP. Or maybe we can, but I don't quite understand how it works exactly despite my numerous experiments. So, we won't GOTO out of FOR loop.

@LOOP
...
IF BREAK GOTO @ENDLOOP
...
GOTO @LOOP
@ENDLOOP

That's it. Just breaking out of the loop cycle. Now let's see it with FOR loop.

A$="HELLO SAILOR!"
FOR I=0 TO LEN(A$)-1
IF INSTR(" ",MID$(A$,I,1))>=0 THEN I=LEN(A$):GOTO @ENDLOOP:'NEXT
? MID$(A$,I,1);
@ENDLOOP
NEXT
?:?"I=";I

You can see immediately that the structure isn't good. We have to use GOTO @ENDLOOP, instead of a simple NEXT because the program will return to the line of execution, resulting NEXT without FOR error. We have to put the label @ENDLOOP in separate line. The value of I is 14, which may not be what we want. In all, BREAKing out of loop isn't a good solution with this BASIC.

SAMPLE PROGRAM: TOUCH SCREEN KEYBOARD
@TOUCH
MX=256:MY=192:'MAXX,MAXY
SX=8:SY=6:'SPANX,SPANY
WX=FLOOR(MX/SX):WY=FLOOR(MY/SY):'WIDTHX,WIDTHY
TX=TCHX:TY=TCHY
FOR I=1 TO TCHST
IF TX
VSYNC 1:GFILL 0,0,MX,MY,0:GFILL KX*WX,KY*WY,(KX+1)*WX,(KY+1)*WY,8
LOCATE 0,0:?"KX=";KX;"  KY=";KY;"   "
NEXT
GOTO @TOUCH

Here is a simple way to divide the screen to rectangular areas.
MAXX,MAXY = SCREEN AREA/KEYBOARD SIZE
SPANX,SPANY=NUMBER OF KEYSPAN X,Y
WIDTHX,WIDTHY=INTERNAL VALUES USED FOR DRAWING
KX and KY =THE VALUE IN SPANX,SPANY THAT DENOTES ACTIVE CELL

If you look at FOR I=1 TO TCHST code, you maybe forgiven to think that it is a loop. It's not a loop. It is a multi-line IF, which is something Petit Computer does not support. It works in this case, but it's a special case.


SAMPLE PROGRAM: BANNER

Here is an example of nested loop. That is, loop within loop structure. It is also an example of GPUTCHR, where I'm using it for fine scrolling and zooming technique.

@ASKB
ACLS
LINPUT "MESSAGE 1/3?";B1$
LINPUT "MESSAGE 2/3?";B2$
LINPUT "MESSAGE 3/3?";B3$
B$="      "+B1$+B2$+B3$+"      "
ACLS

@LOOP
FOR I=1 TO LEN(B$)-5
FOR X=63 TO 0 STEP -4
VSYNC 1:IF BTRIG() THEN GOTO @ASKB
GCLS
FOR J=-1 TO 3:GPUTCHAR X+(J*64),40,"BGF0",ASC(MID$(B$,I+J,1)),0,8:NEXT
NEXT
NEXT
GOTO @LOOP

The sharp eyes among you will see that I did GOTO out of FOR loop with GOTO @ASKB. How does that work? Isn't GOTO out of loop is bad? Yes, it is. I don't understand it myself. It seems to work fine in this case, but I still discourage its use. Good for demos, but please don't use it for professional programs.

'HI-LO
S=RND(100)+1
FOR I=1 TO 1
INPUT "GUESS A NUMBER(1-99)";N
IF N>S THEN ?"TOO HIGH"
IF N
I=!ABS(N-S)
NEXT
?"CORRECT!"

'HI-LO
S=RND(100)+1
@LOOP
INPUT "GUESS A NUMBER(1-99)";N
IF N>S THEN ?"TOO HIGH"
IF N
IF N==S THEN ?"CORRECT!":END
GOTO @LOOP





(1) BTW, even though the CONTINUE looks fine, you have to be careful that you don't end the loop at CONTINUE, because the loop will end there and you will get NEXT without FOR error. There is the reason why I end the string with "!" when the condition only checks for vowels. That's being sneaky, and it's all right for you to do it, but do document it. Try adding exclamation mark at INSTR:

A$="HELLO SAILOR!"
FOR I=0 TO LEN(A$)-1
IF INSTR("AEIOU!",MID$(A$,I,1))>=0 THEN NEXT
? MID$(A$,I,1);
NEXT
?:?"DONE!"