Showing posts with label game. Show all posts
Showing posts with label game. Show all posts

Saturday, April 12, 2014

Chess: 3 Weak Squares


This is a game I played with Pure Chess at Scholar level. It's an interesting game, with me totally dominating Black's position. It's the finest game I've played so far. Just don't expect me to repeat this performance anytime soon!

1. e4 c5
2. g3 d5
3. Bg2 dxe4
4. Bxe4 Nf6
5. Bg2 

Oh, dear. 5 moves into the game, and I lost initiative already. There goes my hope for a good game.

5. ... h6
6. Nf3 e6
7. O-O Bd6
8. c3 O-O
9. d4 Nbd7
10. Be3 Ng4
11. Nbd2 Nxe3
12 fxe3 

A natural recapture. I moved a pawn from f file to e file, thus opening up my rook for attack on Black's King.

12. ... Re8?

This is strange. About the only thing I can think of is that Black has no concept of long range planning. By moving his rook there, he's setting up attack on f pawn. Right now, White can't attack that pawn, but after a few exchanges, things will be different!

13. Ne4 Bf8
14. Rf2 f5!

The situation is now clear. Black has no plan to save that pawn for defense after all. Black is using that pawn as an attacker!

15. Ned2 a5
16. Qc2 Ra6
17. Raf1 Qb6
18. Nc4 Qb5
19. Nce5 

A knight here is a very strong position. Notice that no pawn can attack that knight. It's a comfy perch that will make Black's movement difficult. It's also the first attacking piece so far. We are now moving into the middle game.

19. ... Nxe5
20. Nxe5 g5?

You should not voluntarily give up the pawns protecting the King. Just because you don't see anything wrong with the current position, does not mean it won't change in the future!

21. g4?

Ill-advised attack on my part. I failed to calculate the consequences of my gambit of trying to open the f file.

21. ... cxd4
22. exd4 Bg7
23. gxf5 exf5

I look at this position and stared in horror! My King has no pawn protection in view of 3 Black's pawns! About the only salvation is the fact that my pieces are consolidated while Black's pieces are scattered all over the board. If only I can attack on the Queenside while preventing Black to consolidate his pieces over to the King!

24. c4 Qb6
25. Bd5+ Kf8?

An unfortunate move for Black, lining up his King opposing my double Rook!

26. c5 Qf6?

Lining up his Queen to my double Rook?

27. Bxb7 Ra7
28. c6!

Looking at this position, I'm very happy! Black has 3 major problems that he needs to take care of. There are 3 pressure points


  1. The f5 square. Attacked twice, defended twice, defender wins. Attacked 3 times, defended twice, attacker wins.
  2. The d7 square. Possible King-Queen fork by the Knight.
  3. The c5 square. Possible King-Rook fork by the Queen.


Notice that I'm not looking at the position by the pieces. I'm evaluating the position by weak squares. This is not a common view, but I think squares are more important than pieces!

28. ... Rxb7
29. cxb7

Black attempts to solve problem #3 by trading his Rook for my Bishop. This is unfortunate for Black since I now have two attacks: the Bishop, and the b8 square promotion. As we play along, notice how Black's position crumbled rather quickly.

29. ... Be6
30. Rxf5 Bxf5

Black has solved problem #2, but his problem #1 remains.

31. Rxf5 Qxf5
32. Qxf5 Kg8

And now, I see a winning combo. I realize that in order for me to promote the pawn, I need to remove the Rook from the 8th rank. I know just how to do it! We are entering the Endgame phase. Black did not survive for long.

33. Qf7+ Kh7
34. Qg6+ Kh8
35. Qxe8+

And I have the Rook. I wasn't calculating mate, but since all moves are forced, it's a mating combination.

35. ... Kh7
36. Qg6+ Kh8
37. b8=Q+ Bf8
38. Nf7#

Yes! Mated the King in the corner! Notice that Black does not make obvious blunder. About the only inaccuracy that I can see is lack of long-term planning by Black. Overall, a great game that I do not expect to improve any time soon.

Thursday, December 26, 2013

Book Review #16


American Bar Association: Legal Guide to Game Development
Ross Dannenberg (Editor)

I have always wanted to have my own video game development company. I just don't know how. All the books out there is simply a guide on how to build a generic business. That's not true. I found a book on how to run your own Food Truck. Somebody actually recommended a good book on video game company development. That book is out of print. This book is my substitute.

Unfortunately, it makes for a boring reading. I suppose lawyers are boring creatures. I understand the need for precise wording, but it's like, they have no imagination whatsoever. Oh, well. All the pertinent info are there. At least I think so, since I'm not a lawyer. The book does details the game development process from idea to implementation to execution. Of course, all the pertinent regulations are highlighted. The book does an admirable job explaining the laws as they affect the gaming development.

It has enough examples and exposition to make the issues clear to me. Well. It's just so boring, though. Of course, the value of this book isn't entertainment. It's legal advice, as close as you can get without actually consulting a lawyer. On that, the book succeeds. Give it a try. You may be surprised as just how many of those laws apply to a simple game development process.

Friday, December 13, 2013

Petit Computer Journal #29

A Simple Sprite Game


I've always said that writing a computer program is pretty easy if you know what you're doing. The question is, how easy can it be? I've written a version of Snakes and Ladders game in under 10 minutes. How quickly and easily can I write a sprite based game? Certainly, not too difficult.

I'm curious as to just how easy it is to write one. Certainly, there is the control. I settled for Up-Down-Fire, which is a variation of Left-Right-Fire. I was hoping for a single screen challenge program, and I managed to do it. However, it isn't fun at all. Also, it turns out that I don't need the Up-Down movement at all. Just sit there and hit the fire button!


  1. CLS:Y=0:A=256:C=128:S=0
  2. SPSET 1,96,0,0,0,0:T=3600
  3. SPSET 2,40,0,0,0,0
  4. SPOFS 2,-16,0,0:SPANIM 2,2,15
  5. SPSET 10,13,3,0,0,0
  6. @LOOP
  7. T=T-1:IF T<0 THEN END
  8. VSYNC 1:B=BUTTON(0):DX=0:DY=0
  9. LOCATE 0,0:?"S=";S,"T=";T;" "
  10. IF SPHIT(10) THEN S=S+1:BEEP
  11. IF !SPCHK(10) THEN GOSUB @MM
  12. IF (B AND 16) THEN GOSUB @FR
  13. IF !(B AND 3) GOTO @LOOP
  14. DY=(B AND 3)*2-3
  15. Y=Y+DY:IF Y<0 THEN Y=Y+192
  16. Y=Y%192:SPOFS 1,0,Y,0
  17. GOTO @LOOP
  18. @FR
  19. SPOFS 2,0,Y,0:SPOFS 2,A,Y,C/2
  20. RETURN
  21. @MM
  22. SPOFS 10,99+RND(99),-20,0
  23. SPOFS 10,99+RND(99),2*C,C
  24. RETURN


It's all very well and good for a single screen challenge, but I was curious as to how much better it would be, had it been a better fleshed out game. So, forget about the single screen challenge and just do better!


  1. CLS:Y=0:A=256:C=128:S=0
  2. BGFILL 0,0,0,63,63,9,8,0,0
  3. FOR I=1 TO 32
  4. BGPUT 0,RND(64),RND(64),32,8,0,0
  5. NEXT
  6. SPSET 1,96,0,0,0,0
  7. SPSET 2,40,0,0,0,0
  8. SPOFS 2,-16,0,0:SPANIM 2,2,15
  9. FOR I=10 TO 70
  10. SPSET I,13,3,0,0,0
  11. SPOFS I,99,-50,0
  12. NEXT
  13. @INIT
  14. BGMPLAY 23
  15. T=10800:S=0
  16. @LOOP
  17. IF HYC<S THEN HC=S
  18. IF !BGCHK(0) THEN BGOFS 0,RND(512),RND(512),360
  19. T=T-1:M=FLOOR(T/180):IF T<0 THEN GOTO @END
  20. VSYNC 1:B=BUTTON(0):DX=0:DY=0
  21. LOCATE 0,0:?"$=";S,"TIME=";M;"   ","HI $=";HC;"   "
  22. FOR I=10 TO 70-M
  23. IF SPHITSP(I,2) THEN S=S+1:BEEP 3:GOSUB @HIT
  24. IF !SPCHK(I) THEN GOSUB @MM
  25. NEXT
  26. IF (B AND 16) THEN GOSUB @FR
  27. IF !(B AND 3) GOTO @LOOP
  28. DY=(B AND 3)*2-3
  29. Y=Y+DY:IF Y<0 THEN Y=Y+192
  30. Y=Y%192:SPOFS 1,0,Y,0
  31. GOTO @LOOP
  32. @FR
  33. SPOFS 2,0,Y,0:SPOFS 2,A,Y,C/2
  34. RETURN
  35. @MM
  36. SPCHR I,13
  37. SPOFS I,99+RND(99),-20+256*RND(2),0
  38. SPOFS I,99+RND(99),-20+256*RND(2),99+RND(C)
  39. RETURN
  40. @HIT
  41. SPCHR I,248
  42. SPANIM I,8,6,1
  43. RETURN
  44. @END
  45. BGMPLAY 6
  46. WAIT 360
  47. FOR I=0 TO 16:I=BUTTON(0):NEXT
  48. GOTO @INIT


So far, I'm using standard graphics. It's very convenient that the graphics are all built-in. However, there is always a way to have custom made graphic. I won't list the source code, but check out the QR made for this game.

http://petitcomputer.wikia.com/wiki/Santa_Helper










Saturday, October 12, 2013

Nintendo Journal 8


TopGun LCD game


I also picked up an old LCD games. TopGun by Konami. It's just a single board game with LCD screen. There's a small speaker on the back. It's amazing how simple these things are. I think games like these are perfect for Petit Computer projects. I will be rustling up a few.

I marvelled at how thin the LCD screen is. It's just a thin plastic, nothing more. I looked at the contacts, and they're sooo tiny! I really doubt that they can align it perfectly, and yet, when I reassembled the device, it works fine!

I don't know how they do it. As simple as it is, that's not something any rookie can do. There must have been some degree of experimentation in order to fit things just right.

Friday, September 13, 2013

Petit Computer Journal #17

WITCH

I wrote WITCH to showcase the SPRITE capabilities of Petit Computer. There are lots of people who doesn't know how to use sprites. In fact, Petit Computer sprites are so powerful, you can easily replicate old games.

So here is the WITCH program that is purposely SPRITE heavy. There are certain techniques where I could have done it traditionally, but chose to implement it using a sprite instead. Notably, there is a TIMER sprite, where the sole purpose is to spread the bullets so that they don't trip over one another.

I chose the firing of the fireball using stylus because somebody was asking the way to do it. He was wondering about how to fire the bullet in the direction of the stylus, without stopping at the point of the stylus. In my solution, I also took care of the speed of the bullets. Done carelessly, the bullets may have different speed.

'THE WITCH AND THE UNDEAD
'A SPRITE EXERCISE

'1. WITCH
'2. FIREBALL
'3. UNDEAD FALLING
'4. UNDEAD WALKING
'5. UNDEAD HIT
'6. WITCH HIT
'7. EXTRAS

@INIT
H=100:'HEALTH
NUMZ=1:'CURRENT NUM OF ENEMY
MAXZ=20:'MAXNUM OF ENEMY
SCORE=0

ACLS
PNLTYPE "OFF"
SPSET 1,108,1,0,0,0:'WITCH
SPCOL 1,0,0,16,16,FALSE
SPOFS 1,120,170

'BULLET
FOR I=2 TO 9
SPSET I,142,0,0,0,0
SPANIM I,2,10,0
SPOFS I,30,180,I*90
SPCOL I,0,0,16,16,FALSE,2
NEXT

'CURSOR
SPSET 10,253,1,0,0,0
SPCOL 10,0,0,16,16,FALSE,0

'TIMER
SPSET 11,3,1,0,0,0
SPCOL 11,0,0,16,16,FALSE,0
SPOFS 11,200,200

'UNDEAD
FOR I=20 TO 20+MAXZ
SPSET I,130,RND(16),0,0,0
SPANIM I,2,20,0
SPOFS I,200,-300
SPCOL I,0,0,16,16,FALSE,1+2
NEXT



@MAINLOOP
VSYNC 1:X=TCHX:Y=TCHY:S=TCHST:B=BUTTON(0)
LOCATE 0,0:?"HEALTH=";H;"   ":?"SCORE=";SCORE
SPOFS 10,X,Y
GOSUB @FIREBALL
GOSUB @ENEMY

IF SPHIT(1) THEN H=H-1:BEEP 37
IF B AND 4 THEN DX=-8: GOSUB @MOVE
IF B AND 8 THEN DX=8:GOSUB @MOVE
'IF B AND 16 GOTO @END
IF H<=0 GOTO @END
GOTO @MAINLOOP

@MOVE
SPREAD(1),SX,SY
IF SX+DX>0 AND SX+DX<240 THEN SPOFS 1,SX+DX,SY,8
RETURN

@ENEMY
SPREAD(1),SX,SY
FOR I=20 TO 20+NUMZ
SPREAD(I),ZX,ZY
IF (1 AND SPCHK(i)) GOTO @ENEMY2
IF ZY>SY THEN SPOFS I,SX,SY,SPEED:GOTO @ENEMY2
SPEED=(50000-SCORE)/100:IF SPEED<60 THEN SPEED=60
SPOFS I,RND(255),0
SPOFS I,RND(255),SY+1,SPEED
@ENEMY2
NEXT
RETURN

@FIREBALL
FOR I=2 TO 9
IF SPHIT(I) THEN GOSUB @HITZ
IF !(1 AND SPCHK(I)) THEN SPOFS I,I*18,300
IF S==1 AND !(1 AND SPCHK(11) THEN @SHOOT
NEXT
RETURN

@HITZ
BEEP 14
SPOFS I,80,0
SPOFS SPHITNO,30,-150
SCORE=SCORE+FLOOR(SQR((SPHITX-SX)*(SPHITX-SX)+(SPHITY-SY)*(SPHITY-SY))/3)
NUMZ=FLOOR(SCORE/1000)+1
IF NUMZ>MAXZ THEN NUMZ=MAXZ
RETURN

@SHOOT
CB=((CB+1)%8:CBS=CB+2
IF (1 AND SPCHK(CBS)) GOTO @SHOOT2
BEEP 10:SCORE=SCORE-1:IF SCORE<0 THEN SCORE=0
SPREAD(1),SX,SY
A=ATAN((X-SX),(Y-SY))
SPOFS CBS,SX,SY
SPOFS CBS,SX+300*SIN(A),SY+300*COS(A),150
SPOFS 11,250,250,20
@SHOOT2
RETURN

@END
CLS:?"GAMEOVER"
BGMPLAY 6
WAIT 60
END

Sunday, August 18, 2013

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, August 15, 2013

Petit Computer Journal #8


Petit Computer Journal #8

The Apple Picker Game part 2



The Apple Picker Game? We're going to finish it up proper! Actually, we're not going to really make it professional quality. But we'll put on some fancy dressing on it to make it really enjoyable!

Adding color:
It was later in the development cycle (fancy words for repeatedly finding and fixing numerous bugs) that I find myself squinting at the screen looking for that last apple among the many snakes. Adding colors solves this problem. I colored the apples pink because I find red is too strong among the snake green.

Adding music:
It makes a great game. Looking at the help menu, I see a list of ready made music. Use BGMPLAY N, where N is a number. BGMSTOP to stop the music. Remember that N is a number. If you do this: BGMPLAY FANCY. That means you're playing music as defined by variable FANCY, which would be zero if you haven't set it to anything.

I purposely did not add music for level playing. I found it to be too noisy. But if you want it, add this to @NEWLEVEL
BGMPLAY LEVEL+ADJ
This will launch a new background music with every new level, with ADJ as offset.

Adding Sound Effect:
Oh, this is a good one! I added scream, hit, and coin sounds immediately. Easy sound effects! It took me awhile to add steps sound, but once I did, I never want to go back! This is how you know what you did is good!

Adding walls:
This was a doozy! The program kept hanging up (a polite way to say unintended infinite loop) and I didn't know why! Obviously, I needed to work out the math on paper, and then do exhaustive analysis upon it. I did neither. I did hack-and-slash programming, so even now, I'm not sure the solution is correct.

I did test out this form:
FOR I=0 TO 0:T=RND(5)+5):I=ABS(MY-T)-1:NEXT:WX[0]=T
You probably wonder why I bothered to put the FOR loop in there. I use it as REPEAT loop, just so you know. Notice that I set the value of I everytime. When MY==T, the loop will repeat. That is, T of any value except WY.

The walls will erase snakes. That's fine. I also have to make sure that the walls will never form an enclosed space where the player cannot enter/exit. The easy way is to create some levels with array or DATA statements. I decided to create it dynamically, which isn't the easiest in the world, but I hate putting in DATA too much and results in repeat levels, making them boring.

Adding Lives:
I added this as I realize that the later levels may feature apples surrounded by snakes. I don't want the game to end immediately. Like any good design decision, once I put it in, I don't want to take it out.

Adding Time:
This comes in last. After a while, I started to add challenges. Can I finish 10 levels in 5 minutes? 20 levels in 10 minutes? Yes, I can! You can, too. Look at the levels and time completed. Major bragging rights, there!

Adding Alternative control:
It's not hard to do button controls. I simply extended the button readouts, and that's it! Noteworthy to mention is that I didn't put fast button where pushing L or R button results in faster movement. It's not hard to do, but I can pull the feature out after I put it in. Not a good design decision.

Adding moving snake:
I decided not to. It's not that kind of game. The game evolves from taking apples (Path Finding/Travelling Salesman) problem, to maze game, to Least Cost finding. Along the way, you have to be able to control the person very well to avoid running into snakes.

Adding customized graphic:
I decided not to. The game benefits from seeing the whole level all at once. If I use same size sprites, the size of the game would have expanded radically, for little returns. If I use double size sprites, the game will look great, but play suffers. If I use smaller playfield, the game becomes boring really quickly. If I use big sprite on top screen, and normal size for bottom screen as map, then the player will constantly look at the bottom screen. In which case, why bother?

How to CHEAT:
Yes, you can cheat! You have the source code in front of you! Whenever you feel like you want some extra lives, hit BREAK, then type this:
LIVE=20:CONT
You'll continue no problem. Your live is now 20! You have to be careful to do it so the screen does not scroll, and no apple is overwritten. I recommend waiting until the last apple is on upper right corner.

You can also add more apples, by typing this:
SCORE=9:CONT
Since the level advances every 10 points, this will cause new apples to appear at the next apple taken.

Level select is no problem either. Can you guess how?
LEVEL=15:CONT
Yup. It's that easy!

Finally, you may want a puzzle game, instead of an action game. Not a problem! Do this at @GAMELOOP

From this: VSYNC 15:GOSUB @SETB2
To this: VSYNC 1:GOSUB @SETB3

And you got yourself a puzzle game!

Professional Quality?

This game is a good Hobbyist effort, but I wouldn't call it a professional quality. There are different things that I can do as a professional, but choose not to. I already mentioned the exhaustive testing of walls. Here are some other things that I need to do in order to be professionals:

1. Limit the number of lives to 30, as to not mess up the display.
2. Add option to set background music to the levels
3. Add faster speed button
4. Save/Load High scores
5. Refresh whole screen to prevent display corruption
6. Add variety of enemies. Maybe some will add apples, others fling you randomly to another part of the screen.
7. Add time limit, allowing for levels of difficulty.
8. Also adjust player speed according to level of difficulty.
9. Add Puzzle mode from Option
10. Add replay option, play as demo on splash screen.
11. Tune up the presentation, not necessarily fancy graphics, but I would experiment with different placements of elements.
12. Make sure adding apples, snakes will not hang the game.

If I want to put this out for sale, I will add these:
13. Multiplayer option. 2 players. One is using Dpad. The other, buttons. Photo Dojo style
14. Computer player, single, double. With good path finding algorithm.
15. Selectable number of player
16. Sound/Music selection. Volume adjustable individually.
17. Optional level editor. It's not that hard.
18. Optional sprite editor. It's not that hard.
19. Optional music editor. It's not that hard.
20. Optional 3D graphic. This one is hard, and not at all useful. It's great marketing tool, though.


Wednesday, August 14, 2013

Petit Computer Journal #7


Petit Computer Journal #7

Character and String


So far we have dealt with numbers. It's time to deal with the other data type: String. What is a string? It's a string of characters. What is a character? That's a good question. It goes back to the beginning. What are computer made of? A bunch of numbers. Therefore a character is a number. It's a special number, however. What's the difference between this character number and ordinary number? An ordinary number can go to 524287. A character number is from 0 to 255. You can see what they are by going to Help Menu#12 "Text and Display" - Character Code List.

Please note that character 0 (NULL) and character 32 (SPACE) are two different characters!

Basic Character ASC() CHR$() VAL() STR$() HEX$()

You already know how to get a character given a number. Use CHR$() as given by this program from Petit Computer Journal#5:

'ASCII TABLE
S=0
@MAINLOOP
CLS
FOR I=S TO S+15
R=I%16
LOCATE 0,R:?I;:LOCATE 5,R:?CHR$(I) :'&lt;--Right here!
NEXT

GOSUB @SETB3

IF INBUTTON$=="U" THEN S=S+16
IF INBUTTON$=="D" THEN S=S+256-16
S=S%256
?:?"S=";S;"   ";INBUTTON$:WAIT 60:'OPTIONAL FOR DEBUGGING
GOTO @MAINLOOP

Given a number, CHR$() will show a character. What is the reverse function of it? The ASC(). Given a character, it will return a number. How about regular number? Let's say we have a number 1043, and we want a string "1043". How do we do it? We use STR$(). And the reverse? VAL(). Go to RUN Mode, and try these out:

?CHR$(31) 'Prints "!"
?CHR$(65) 'Prints "A"
?ASC("A") 'Prints 65
?ASC("a") 'Prints 97
?HEX$(80) 'Prints 50
?HEX$(80,4) 'Prints 0050 Note leading zeros.

?"ABC"+"DEF" 'Prints ABCDEF
?"ABC"*3 'Prints ABCABCABC


Let's do a couple quick functions. UCASE and LCASE, which returns Upper Case string and Lower case strings respectively.

@MAINLOOP
LINPUT "string",A$
?"Upper Case: ";:GOSUB @UCASE:?A$
?"Lower case: ";:GOSUB @LCASE:?A$
?:?
GOTO @MAINLOOP

@UCASE
T$=""
FOR I=0 TO LEN(A$)-1
C$=MID$(A$,I,1):'SINGLE CHARACTER AT LOCATION I
IF ASC(C$)&gt;=97 AND 122&gt;=ASC(C$) THEN C$=CHR$(ASC(C$)-32)
T$=T$+C$:'APPEND C$ TO T$
NEXT
A$=T$
RETURN


@LCASE
T$=""
FOR I=0 TO LEN(A$)-1
C$=MID$(A$,I,1):'SINGLE CHARACTER AT LOCATION I
IF ASC(C$)&gt;=65 AND 90&gt;=ASC(C$) THEN C$=CHR$(ASC(C$)+32)
T$=T$+C$:'APPEND C$ TO T$
NEXT
A$=T$
RETURN


Search and Replace LEN() MID$() RIGHT$() LEFT$() INSTR SUBST$

You have seen a few more string functions: LEN(A$). This is the number of character in A$. In other words, string LENgth of A$. We subtract 1 from LEN(A$) because strings are zero-based, while the LEN() is 1-based.


MID$(A$,I,1). You'll probably see this construct a lot. What it does is basically returns the character at position I (zero based). We can return more than 1 character. If we want 4 characters starting at position I, we'll do this: MID$(A$,I,4). It's that simple!

LEFT$() and RIGHT$() are just like MID$, except they don't start in the middle. They start at left and right respectively. Try this out in RUN Mode:

A$="Hello World"
?LEFT$(A$,5)  'Prints "Hello"
?RIGHT$(A$,5)  'Prints "World"

Type NEW. Start a new program. Type this program in Edit Mode and run it:

INPUT A$
CLS
@LOOP
LOCATE 0,0:?A$
WAIT 15
A$=RIGHT$(A$,LEN(A$)-1)+LEFT$(A$,1)
GOTO @LOOP

Did you see a rotating banner? Good! All this does is take the rest of A$ except the first character and add the first character. In other words, put the first character at the end. You can change the number '1' with any number to rotate that many characters.

Let's do a stack and queue real quick. Stacks puts in data (PUSH) and pull out data (POP) at the same place. We'll do it at the end. Queue in (ENQ) also at the end. but Queue Out (DEQ) is at the opposing end. We'll see it in action. Start a new program.

CLS:CLEAR
A$="A":GOSUB @PUSH
A$="B":GOSUB @PUSH
A$="C":GOSUB @PUSH
A$="D":GOSUB @PUSH
GOSUB @POP
GOSUB @POP
GOSUB @POP
A$="E":GOSUB @PUSH
A$="F":GOSUB @PUSH

CLEAR
A$="A":GOSUB @ENQ
A$="B":GOSUB @ENQ
A$="C":GOSUB @ENQ
A$="D":GOSUB @ENQ
GOSUB @DEQ
GOSUB @DEQ
GOSUB @DEQ
A$="E":GOSUB @ENQ
A$="F":GOSUB @ENQ

END

@PUSH
?"PUSH ";
S$=S$+A$
?"A$=";A$;" S$=";S$
RETURN

@POP
?"POP  ";
A$=RIGHT$(S$,1)
S$=LEFT$(S$,LEN(S$)-1) 
?"A$=";A$;" S$=";S$
RETURN

@ENQ :'Enqueue (same as PUSH!)
?"ENQ ";
S$=S$+A$
?"A$=";A$;" S$=";S$
RETURN

@DEQ :'Dequeue
?"DEQ ";
A$=RIGHT$(S$,1)
S$=LEFT$(S$,LEN(S$)-1) 
?"A$=";A$;" S$=";S$
RETURN

Compare the two. Do you see the difference between stack and queue?
Push enters data from the right side. Pops it from the right side.
Enqueue enters data from the right side. Takes it from the left side.
That's it,really. Simple. BTW, PUSHing from Left is S$=A$+S$.

I use INSTR function quite a lot. I use it as indexing function. Basically, If I want to know whether something is a vowel. I can use this:

L=INSTR("AEIOU",C$) :'Where C$ is a character to check for vowel. L=-1 means not a vowel.

SUBSTR$() is handy if you don't want to do a lot of shifting with LEFT$ AND RIGHT$. Let's say you want to replace <NAME> with the player's name. You can do this:

CLS:CLEAR
T$="HELLO <NAME>! TODAY IS <DATE>. THE TIME IS <TIME>"

INPUT "NAME";N$
S$=T$ :'COPIES T$ TO S$
L=INSTR(S$,"<NAME>"):LLEN=LEN("<NAME>")
S$=SUBST$(S$,L,LLEN,N$)
L=INSTR(S$,"<DATE>"):LLEN=LEN("<DATE>;")
S$=SUBST$(S$,L,LLEN,DATE$)
L=INSTR(S$,"<TIME>"):LLEN=LEN("<TIME>")
S$=SUBST$(S$,L,LLEN,TIME$)

?:?S$

Now you have the skeleton program for MadLibs. Add this to the program to see how you can replace the same string multiple times. This is also the way Mail Merge program works, BTW. Simple Template applications.

T$="HELLO <NAME>! GOODBYE <NAME>!"
S$=T$ :'COPIES T$ TO S$
L=INSTR(S$,"<NAME>"):LLEN=LEN("<NAME>")
S$=SUBST$(S$,L,LLEN,N$)
?:?S$ :'SUB THE FIRST <NAME>
L=INSTR(S$,"<NAME>"):LLEN=LEN("<NAME>")
S$=SUBST$(S$,L,LLEN,N$)
?:?S$ :'SUB THE SECOND <NAME>;

And that's all there is to it! Wow, we have written a lot of programs today, and we're still not done! I know I'm bucking the convention here, but I like to just go through the steps all at once. It's not that hard to go through the different commands. It's hard to understand the purpose of such commands, which is why I'm giving you all the different examples to use. You probably don't know why I choose these kind of programs. Trust me when I say that these programs are the basic building blocks of computer programming.

You may take a break here if you're tired. Come back later and we'll do one final program: a game that uses our newfound knowledge, and something that is doable in one hour, and fun, and something worthwhile that you can show off to other people. Wow, is that a tall order or what?

Haha, joking aside, I do have such program. And, no, it's not Mad Libs. That one is 15 minutes! Try to guess what it is before you proceed. who knows? Maybe you have a better suggestion than mine!




A Simple Game: Hangman

Let's do a Hangman program real quick. What is it? Show and Tell! what is Hangman? It's a game where you have to guess the secret sentence. Each wrong guess nets you a mark. Once 10 marks or whatever number decided is reach, you lose! It's simple enough to be done in one hour.

What do we need?
1. T$: The secret sentence.
2. G$: Guessed letters
3. W$: Wrong guesses
4. K$: Available characters to guess.

What are the steps?
1. Display all 4 strings. If T$ char not in G$ then show Square
2. Ask for input (set to UPPERCASE)
3. If the character is in K$, then proceed, else GOTO step 1.
4. if the character is in T$, then add to G$, else add to W$.
5. If LEN(w$)<=10 then LOSE
6. If all char in T$ is in G$ then WIN
7. GOTO 1


CLS:CLEAR

@INIT
T$="":G$=" ":W$=" "
K$="ABCDEFGHIJKLMNOPQRSTUVWXYZ"
C$="abcdefghijklmnopqrstuvwxyz"

T$="THIS IS THE SECRET WORD"

@MAIN
CLS:?"HANGMAN"
?:?
FOR I=0 TO LEN(T$):A$=MID$(T$,I,1)
IF INSTR(G$,A$)< 0 THEN ?"#"; ELSE ?A$;
NEXT
?:?:?"GUESSED LETTERS"
?G$
?:?:?"WRONG LETTERS"
?W$
?:?:?"AVAILABLE LETTERS"
FOR I=0 TO LEN(K$):A$=MID$(K$,I,1)
IF INSTR(G$,A$)< 0 AND INSTR(W$,A$)< 0 THEN ?A$;
NEXT
?:?:?:LINPUT "LETTER?";S$

First stage: 18 minutes. Now to complete the rest of the program.

CLS:CLEAR

@INIT
T$="":G$=" ":W$=" "
K$="ABCDEFGHIJKLMNOPQRSTUVWXYZ"
C$="abcdefghijklmnopqrstuvwxyz"

T$="THIS IS THE SECRET WORD"

@MAIN
CLS:?"HANGMAN"
?:?
FOR I=0 TO LEN(T$):A$=MID$(T$,I,1)
IF INSTR(G$,A$)< 0 THEN ?"#"; ELSE ?A$;
NEXT
?:?:?"GUESSED LETTERS"
?G$
?:?:?"WRONG LETTERS"
?W$
?:?:?"AVAILABLE LETTERS"
FOR I=0 TO LEN(K$):A$=MID$(K$,I,1)
IF INSTR(G$,A$)< 0 AND INSTR(W$,A$)< 0 THEN ?A$;
NEXT

@STEP2
?:?:?:LINPUT "LETTER?";S$
S$=LEFT$(S$,1):IF S$=="" GOTO @MAIN
IF INSTR(C$,S$)>=0 THEN S$=CHR$(ASC(S$)-32)
?"YOUR GUESS IS: ";S$

@STEP3
IF INSTR(G$,S$)>=0 GOTO @MAIN
IF INSTR(W$,S$)>=0 GOTO @MAIN

@STEP4
IF INSTR(T$,S$)>=0 THEN G$=G$+S$ ELSE W$=W$+S$

@STEP5
IF LEN(W$)>9 GOTO @LOSE

@STEP6
WIN=1
FOR I=0 TO LEN(T$)
C1=INSTR(K$,MID$(T$,I,1))
C2=INSTR(G$,MID$(T$,I,1))
IF C1< 0 GOTO @STEP6A
IF C2< 0 THEN WIN=0
@STEP6A
NEXT
IF WIN GOTO @WIN
GOTO @MAIN

@LOSE
?"YOU LOSE!"
GOTO @ANYKEY

@WIN
?"YOU WIN!"
GOTO @ANYKEY

@ANYKEY
WAIT 60
FOR I=0 TO 1:I=TCHST OR BUTTON(3):NEXT
GOTO @INIT

Second stage:  18 minutes




We have a complete program in about 36 minutes. That's typing it from scratch using stylus on the device. We'll add one more thing: READ and DATA

CLS:CLEAR

@INIT
T$="":G$=" ":W$=" "
K$="ABCDEFGHIJKLMNOPQRSTUVWXYZ"
C$="abcdefghijklmnopqrstuvwxyz"

'T$="THIS IS THE SECRET WORD"
I=1:RESTORE @TEXTDATA
@SETT
READ D$
IF D$=="" GOTO @MAIN
IF !RND(I) THEN T$=D$
I=I+1
GOTO @SETT

@MAIN
CLS:?"HANGMAN"
?:?
FOR I=0 TO LEN(T$):A$=MID$(T$,I,1)
IF INSTR(G$,A$)< 0 THEN ?"#"; ELSE ?A$;
NEXT
?:?:?"GUESSED LETTERS"
?G$
?:?:?"WRONG LETTERS"
?W$
?:?:?"AVAILABLE LETTERS"
FOR I=0 TO LEN(K$):A$=MID$(K$,I,1)
IF INSTR(G$,A$)< 0 AND INSTR(W$,A$)< 0 THEN ?A$;
NEXT

@STEP2
?:?:?:LINPUT "LETTER?";S$
S$=LEFT$(S$,1):IF S$=="" GOTO @MAIN
IF INSTR(C$,S$)>=0 THEN S$=CHR$(ASC(S$)-32)
?"YOUR GUESS IS: ";S$

@STEP3
IF INSTR(G$,S$)>=0 GOTO @MAIN
IF INSTR(W$,S$)>=0 GOTO @MAIN

@STEP4
IF INSTR(T$,S$)>=0 THEN G$=G$+S$ ELSE W$=W$+S$

@STEP5
IF LEN(W$)>9 GOTO @LOSE

@STEP6
WIN=1
FOR I=0 TO LEN(T$)
C1=INSTR(K$,MID$(T$,I,1))
C2=INSTR(G$,MID$(T$,I,1))
IF C1< 0 GOTO @STEP6A
IF C2< 0 THEN WIN=0
@STEP6A
NEXT
IF WIN GOTO @WIN
GOTO @MAIN

@LOSE
?"YOU LOSE!"
GOTO @ANYKEY

@WIN
?"YOU WIN!"
GOTO @ANYKEY

@ANYKEY
WAIT 60
FOR I=0 TO 1:I=TCHST OR BUTTON(3):NEXT
GOTO @INIT

@TEXTDATA
DATA "THIS IS THE SECRET WORD"
DATA "THIS IS A VERY LONG PHRASE THAT WILL WRAP AROUND"
DATA "I WOULD TYPE A LITTLE FASTER"
DATA "TO BOLDLY GO WHERE NO MAN HAS   GONE BEFORE"
DATA "THE QUICK BROWN FOX JUMPS OVER  THE LAZY DOG"
DATA ""

And that's the complete program. Obviously, if you have more time, you can add more data. That's the beauty of it. You can add as many as you like! Be careful about punctuation marks, since the program cannot handle them. Or put some punctuation marks on G$!

The program we have now is just a simple quick and dirty program. We don't draw the Hangman character, for one. Also, it would be nice to show the completed solution. But that's enough for now. Not bad for one hour computer programming using stylus pecking!

Tuesday, August 13, 2013

Petit Computer Journal #6



Petit Computer Journal #6 

The Apple Picker Game part 1


I don't know about you, but I'm itching for a game. I know I'm bucking the convention here, but I want a real game, none of this Hi-Lo stuff that some people call game. I actually have 2 choices: A word guessing game (Like Wheel of Fortune) or a Snake game. Let's do Snake game first. It's probably a good idea to set the difficulty in linear manner, but I think we can handle otherwise.

We'll lower the difficulty by making The Apple Picker Game. What kind of game is that? It's an Apple Eating Snake game without the Snake. Not that implementing a snake is difficult, but I want to explain how strings work before I do that. The reasonable approach is to do the other game first. We'll do this game first because, hey, sometimes it's good to live dangerously!

Haha, joking aside, I think we have all that we need in order to build it. Show-and-Tell time! What makes an Apple Picker game?

1. A Character who picks apples
2. Apples
3. Area
4. Obstacles (optional)
5. Time Limit (optional)
6. Score (optional)

The gameplay area is the console 32x24 character map. We'll use character for graphics. The movement will be once per second (VSYNC 60). A character will keep moving forward until it runs into an obstacle (wall). Do we need time limit? How about ending the game after all the apples are gone? Do we need score?

Let's keep things simple for now. We do a character, put some apples, and build wall along the perimeter. We'll split the program into 3 sections: Init, GameLoop, and Ending

Init:
1. Clear the screen CLS
2. Put character on location 10,20
3. Draw Wall along perimeter
4. Put 10 apples randomly

GameLoop:
1. Wait 1 second VSYNC 60
2. Read BUTTON(0) via @SETB2
3. Depending on UDLR, we check the next space
3a. Space - move character there
3b. Apple - Increase score by 1, and move character there
3c. Wall  - Set character movement to STOP.
4. If score is 10 then GOTO Ending

Ending:
1. Display "GAME OVER"
2. Wait 2 seconds
3. Wait for button press @SETB3
4. End Program.

That's not too bad. It's not even one page. How hard can it be? Notice how we reuse our old BUTTON reading code. That makes thing simple.

@INIT :'Program Initialization
'1. Clear the screen 
CLS
'2. Put character on location 10,20
LOCATE 10,20:?CHR$(244):'MAN
'3. Draw Wall along perimeter
LOCATE 0,1:?CHR$(3)*32
LOCATE 0,21:?CHR$(3)*32
FOR Y=1 TO 21
LOCATE 0,Y:?CHR$(3)
LOCATE 31,Y:?CHR$(3)
NEXT
'4. Put 10 apples randomly
GOSUB @PUTAPPLE


@ENDING :'Program Ending
'1. Display "GAME OVER"
LOCATE 10,22:?"GAME OVER";
'2. Wait 2 seconds
WAIT 120
'3. Wait for button press SETB3
GOSUB @SETB3
'4. End Program.
END

We need to work on @GameLoop. We also need to work on @PUTAPPLE. Otherwise, the program is half done. Here is PUTAPPLE:

@PUTAPPLE :'CHR$(233) IS APPLE
FOR I=1 TO 10
X=RND(31-1)+1:Y=RND(20-2)+2:C=CHKCHR(X,Y)
IF C==0 THEN LOCATE X,Y:?CHR$(233) ELSE I=I-1
NEXT
RETURN

The thing we want to watch out for is that we only put apple on bare ground. We also make sure that there are EXACTLY 10 apples. Ah, that was easy. We run it, and see if it works. Save it as APPLE.

Now for the main game loop. Wait 1 second. Read Input. Move pieces. Repeat until done. What can be the problem? Oh, wait. We forgot to store our man's location. Put this on Init: "MX=10:MY=20". We also forgot the score: "SCORE=0"


@GameLoop
'1. Wait 1 second 
'2. Read BUTTON(0) via SETB2
VSYNC 60:GOSUB @SETB2

'3. Depending on UDLR, we check the next space
GOSUB @NEXTSPACE:'SETS NX,NY
GOSUB @DOMOVE

'4. If score is 10 then GOTO Ending
IF SCORE==10 GOTO @ENDING
GOTO @GAMELOOP


'3a. Space - move character there
'3b. Apple - Increase score by 1, and move character there
'3c. Wall  - Set character movement to STOP.
@DOMOVE
C=CHKCHR(NX,NY)
IF C==0 THEN GOSUB @MANMOVE:RETURN
IF C==233 THEN GOSUB @EATAPPLE:GOSUB @MANMOVE:RETURN
IF C==3 THEN GOSUB @HITWALL:RETURN
RETURN

@MANMOVE
LOCATE MX,MY:?CHR$(0);
LOCATE NX,NY:?CHR$(244);
MX=NX:MY=NY
RETURN

@EATAPPLE
BEEP 7:'COIN
SCORE=SCORE+1
LOCATE 0,22:?"SCORE ";SCORE;
RETURN

@HITWALL
BEEP 11:'DAMAGE
RETURN

@NEXTSPACE
IF INBUTTON$=="U" THEN NX=MX:NY=MY-1:RETURN
IF INBUTTON$=="D" THEN NX=MX:NY=MY+1:RETURN
IF INBUTTON$=="L" THEN NX=MX-1:NY=MY:RETURN
IF INBUTTON$=="R" THEN NX=MX+1:NY=MY:RETURN
IF INBUTTON$=="" THEN NX=MX:NY=MY:RETURN
RETURN

If you look at @NEXTSPACE structure, you may wonder why I put in so many RETURNs in there. Actually, I'm using it as ELSE-IF ladder. Since SmileBASIC doesn't allow multi-line ELSE-IF ladder, I'm using Subroutine as substitute. It works fine. The many RETURNs can be skipped, at the cost of performance. Since this structure can be difficult to discover on your own, I figure I'll highlight it here.

It took me about one hour to do everything. Not bad at all. Save the game and pat yourself on the back. You have successfully completed a whole new game.

How about some improvements? Once per second is too slow. 3 per second seems about right. Change to VSYNC 20.

How about changing the movement so that once you move, you cannot stop?

How about putting in some other obstacle? Snakes? Who says we can't have snakes in there? Have the program ends when you hit a snake. Otherwise, keep going.

@PUTSNAKE :'CHR$(27) IS SNAKE
LEVEL=LEVEL+1
FOR I=1 TO LEVEL
X=RND(31-1)+1:Y=RND(20-2)+2:C=CHKCHR(X,Y)
IF C==0 THEN LOCATE X,Y:?CHR$(27) ELSE I=I-1
NEXT
LOCATE 21,22:?"LEVEL ";LEVEL;
RETURN




What Have We Learned?

1. We know multiplying a character repeats that character.
2. CHKCHR(X,Y) returns the value of the character on that console location.
3. CLS fills the console with CHR$(0).
4. BEEP makes easy sound effects.
5. Computer Programming is easy. Good Design is hard!