Showing posts with label generator. Show all posts
Showing posts with label generator. Show all posts

Friday, January 3, 2014

Petit Computer Journal #32


Lottery Number Generator

A while ago, I wrote a simple Lottery Number Generator. It may interests you that it has these words in it: "...THEN A MIRACLE OCCURS" Of course, that was done as a joke, but in reality, choosing a bunch of random number isn't rocket science. Especially so, if the programming language provides a built-in random number generator, such as Petit Computer.

All of these talk about the biggest million jackpot ever got me fired up again, and well, I think it's time to update that program. This time, though, I want it to be an actual program that I can use. Speaking of which, there is more than one lottery, so I decided to write a customizable lottery number generator.


  1. CLS:CLEAR
  2. PNLTYPE "OFF"
  3. DIM MN[10]
  4. DIM MB[10]

  5. @INIT
  6. NT=15:'NUMBER OF TICKETS
  7. NS=2:'NUMBER OF SLOTS
  8. CS=0:'CURRENT SLOT
  9. MN[0]=75:'MAXNUM 1-75
  10. MB[0]=5:'NUMBER OF BALLS
  11. MN[1]=15
  12. MB[1]=1
  13. SE=0:'SELECTOR
  14. SSL=0:'SAVE SLOT
  15. DIR=0:'GOSUB @MSL


It's clear that I'm planning to have more than one slot. The old version only has one slot, and this one have more than one. I put in initial value for the most common configuration. Also notice that you can have more than one slot for saving. I do it via MEM$ for saving/loading.


  1. @LOOP
  2. VSYNC 1:B=BUTTON(1):TS=TCHST:TT=TCHTIME
  3. IF TS THEN GOTO @ROLL
  4. IF B AND 1 THEN SE=SE-1
  5. IF B AND 2 THEN SE=SE+1
  6. IF B AND 4 THEN DIR=-1:ON SE GOSUB @MNT,@MNS,@MCS,@MMN,@MMB,@MSL
  7. IF B AND 8 THEN DIR=1:ON SE GOSUB @MNT,@MNS,@MCS,@MMN,@MMB,@MSL

  8. IF B AND 64 THEN GOSUB @SAVER
  9. IF B AND 128 THEN GOSUB @LOADER


That's all for the user interface. There are 6 different actions you can take, and U/D refers to the different action. L/R refers to the value being changed. In truth, there's a simpler 2 dimensional way that you can do this, but I decided to stick with this generic form for now.


  1. COLOR 15
  2. PNLSTR 0,0,"LOTTERY GENERATOR"
  3. PNLSTR 0,1,"(C) 2013 HARRY M. HARDJONO"
  4. PNLSTR 0,3,"  NUMBER OF TICKETS: "+STR$(NT)+"   "
  5. PNLSTR 0,4,"  NUMBER OF SLOTS: "+STR$(NS)+"   "
  6. PNLSTR 0,5,"  CURRENT SLOT: "+STR$(CS)+"   "
  7. PNLSTR 0,6,"  MAXNUM  1-"+STR$(MN[CS])+"   "
  8. PNLSTR 0,7,"  MAXBALL 1-"+STR$(MB[CS])+"   "
  9. PNLSTR 0,8,"  SAVE NAME:"+MM$+"            "
  10. PNLSTR 0,20,"  TOUCH SCREEN TO ROLL"
  11. PNLSTR 0,21,"(X) TO SAVE   (Y) TO LOAD"
  12. PNLSTR 0,23,MID$(MEM$,0,32)

  13. SE=(SE+6)%6
  14. PNLSTR 0,SE+3,">"
  15. GOTO @LOOP


And that's about it for the User Interface. There's really nothing new here. It's just displaying some variables, and that's about it.


  1. @MNT
  2. NT=(NT+DIR+21)%21
  3. RETURN
  4. @MNS
  5. NS=(NS+DIR+10)%10
  6. RETURN
  7. @MCS
  8. CS=(CS+DIR+NS)%NS
  9. RETURN
  10. @MMN
  11. MN[CS]=(MN[CS]+DIR+100)%100
  12. RETURN
  13. @MMB
  14. MB[CS]=(MB[CS]+DIR+10)%10
  15. RETURN
  16. @MSL
  17. SSL=(SSL+DIR+10)%10
  18. MM$="L"+STR$(SSL)+"TTOCFG"
  19. RETURN


As you can see, the structure is all the same. Therefore, I can very well use a 2 dimensional array to do the whole thing. Doing it this way is actually more complicated, although it does have the benefit of mindless coding. Ha! Mindless coding. Isn't that an oxymoron? Haha, joking aside, it's true that simply adhering to plan is on the low end of the difficulty scale.


  1. @ROLL
  2. CLS
  3. FOR I=0 TO NT-1
  4. COLOR 15
  5. ?RIGHT$("  "+STR$(I),2);
  6. FOR J=0 TO NS-1
  7. CNL$=""
  8. IF MB[J]<1 THEN MB[J]=1
  9. FOR K=0 TO MB[J]-1
  10. IF MN[J]<1 THEN MN[J]=1
  11. @THROW
  12. NUM$=" "+RIGHT$("00"+STR$(RND(MN[J])+1),2)
  13. IF INSTR(CNL$,NUM$)>=0 THEN GOTO @THROW
  14. CNL$=CNL$+NUM$
  15. NEXT K
  16. COLOR 12+FLOOR((I%10)/5)
  17. COLOR 4+FLOOR((I%10)/5)
  18. ? CNL$+" -";
  19. NEXT J
  20. ?" "
  21. NEXT I
  22. GOTO @LOOP


Then a miracle occurs...

In fact, it's just a simple string search. Everytime I roll a number, the number is checked via INSTR whether or not the it exists in the string. If so, roll another number, else add the number to the string. Pretty simple, yet devious at the same time. Normally, you use an array, associative array, or hash, depending on the language you're using.


  1. @SAVER
  2. MEM$=RIGHT$("00"+STR$(NT),2
  3. MEM$=MRM$+RIGHT$(STR$(NS),1)
  4. FOR J=0 TO 8:'MAX NS
  5. MEM$=MEM$+RIGHT$("00"+STR$(MN[J]),2)
  6. MEM$=MRM$+RIGHT$(STR$(MB[J]),1)
  7. NEXT J
  8. SAVE "MEM:"+MM$
  9. RETURN
  10.  
  11. @LOADER
  12. LOAD "MEM:"+MM$
  13. NT=VAL(MID$(MEM$,0,2))
  14. NS=VAL(MID$(MEM$,2,1))
  15. FOR J=0 TO 8:'MAX NS
  16. MN[J]=VAL(MID$(MEM$,J*3+3,2))
  17. MB[J]=VAL(MID$(MEM$,J*3+3+2,1))
  18. NEXT J
  19. RETURN


Saving and loading are really just building the string and decoding it. You can see the string on the last line. I made several mistakes here, mainly because I didn't write anything down, and just winging it. I build a long string array because I'm multiplying it by the number of tickets, which is silly because one ticket is the same as the other. Another one is that I multiplied J by 8. Oops. How did that happen?

I was on my bed trying to sleep, so I guess that kind of mistakes can't be helped. Now that I think of it, such mistakes are laughable silly. I guess I shouldn't be programming when I'm trying to sleep. Nah. Who cares? Some people read books on their bed. I'm doing computer programming. That's that.

Thursday, September 12, 2013

Petit Computer Journal #16

Petit Computer Coral Maze


SmileBoom entry for Coral Maze

I wrote the Amazing Maze a while back, and bluerobin2 decided to make a game out of it. One thing led to another and before we know it, we have a full-fledge game on our hand.

SmileBoom was having a competition, and I entered this one. I was going to enter another game, but polishing this game, as simple as it is, took a long time, and I didn't finish my other game.

Still, I thought the fact that it was a spontaneous teamwork who never met in person would be interesting. It's a great feeling to be nominated! Kindly, SmileBoom has this to say about it:

"I've seen you everyone working together and making enjoying. It is one of the ideal way of PetitCom."

An obvious machine translation, but kind words, nevertheless.

There will be an entry in petit computer wiki, and I'll update the link when it happens.

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

Wednesday, August 21, 2013

Petit Computer Journal #14



Amazing Mazes!


It has been a long time, hasn't it? I took one month sabbatical. It became 3 months. How time flies! I got jolted into action by the bugs on my windshield! It's spring! Time to get moving! Haha, joking aside, it IS time for me to get up and do something.

I have been working on this maze generation program that I planned to use on D&D type of game. The eventual code will create "rooms" out of the maze.
And here is the whole program

'MAZE
'APRIL 2013
'HARRY HARDJONO
CLS:CLEAR
DIM XDIR[5]
DIM YDIR[5]


'ROOM: MAKE ROOMS
'PATH: DRAW PATH
'CHOICE: CHOOSE PATH
'INIT: SET PARAMS
'MAZE: MAKE MAZE

GOTO @INIT

So far, so good. I'm allocating memory in the beginning of the program. I also map out the structure of the program in terms of subroutines.

@ROOM
'I'M SKIPPING THIS FOR NOW. TOO LAZY.
'LOOK IT UP ON QR CODE
RETURN

You're probably wondering what goes on here. All it does is scan the maze for straight walls, and removing them. Any bend in the wall and it will be left alone. The resulting "rooms" are unique. Setting the LINK variable to 0 will render this subroutine useless. For lots of spaces, I find LINK=8 is a good value to use. Higher values means less room.

@PATH
LOCATE CX,CY:?CHR$(32);
FOR PC=1 TO LEN(M$)-1
PDX=XDIR[INSTR(CIDX$,MID$(M$,PC,1))]
PDY=YDIR[INSTR(CIDX$,MID$(M$,PC,1))]
CX=CX+PDX:CY=CY+PDY
LOCATE CX,CY:?CHR$(32);
CX=CX+PDX:CY=CY+PDY
LOCATE CX,CY:?CHR$(32);
NEXT
RETURN

Path really draws the path of the maze. It goes by "UDLR" values of XDIR,YDIR arrays. I have the idea of making the subroutine generic by using string and draws all the path. No error checking here, so be careful when using this subroutine as-is.

@CHOICE
CS$=""
FOR CI=0 TO 3
CJ$=MID$(CIDX$,CI,1)
CPX=CX+(2*XDIR[CI])
CPY=CY+(2*YDIR[CI])
IF LEN(M$)>250 THEN CJ$=""
IF CPX<SCXMIN THEN CJ$=""
IF CPX>SCXMAX THEN CJ$=""
IF CPY<SCYMIN THEN CJ$=""
IF CPY>SCYMAX THEN CJ$=""
IF LINK==0 OR RND(LINK) THEN IF CHKCHR(CPX,CPY)!=151 THEN CJ$=""
CS$=CS$+CJ$
NEXT
C$=MID$(CS$,RND(LEN(CS$)),1)
RETURN

This subroutine merely take the current cursor position and looks at 4 different directions. Valid direction gets added to CS$. Invalid directions are those that are nested too deep, out-of-bounds, and dead-ended in a maze.

@INIT
CIDX$="UDLR"
XDIR(0)=0:YDIR(0)=-1
XDIR(1)=0:YDIR(1)=1
XDIR(2)=-1:YDIR(2)=0
XDIR(3)=1:YDIR(3)=0
SCXMIN=1:SCXMAX=29
SCYMIN=1:SCYMAX=21
SCXCUR=RND(SCXMAX/2)*2+1
SCYCUR=RND(SCYMAX/2)*2+1
LINK=88:'CHANGE THIS FOR CONNECTEDNESS
ROOM=FALSE

CLS:M$=""
FOR II=SCYMIN-1 TO SCYMAX+1:?CHR$(151)*31:NEXT

@INIT subroutine establishes the parameters of the program. The maze characteristics, other than SCXMAX,SCYMAX which defines the size of the maze would be LINK and ROOM=(TRUE/FALSE). Set ROOM to TRUE if you want open areas in the maze.

Also draws the initial background.

@MAZE
'HEAVY WIZARDRY
CX=SCXCUR:CY=SCYCUR
GOSUB @PATH
GOSUB @CHOICE
M$=M$+C$+C$
M$=LEFT$(M$,LEN(M$)-1)
IF LEN(M$) GOTO @MAZE
BEEP:IF ROOM THEN GOSUB @ROOM

This is the heart of the program. Traditionally, this is implemented by a recursive function. Obviously, BASIC has no recursion. I managed to flattened the whole algorithm. This used to be a double FOR-LOOP. Now, it's a single REPEAT-LOOP. Very clean and simple. I like it.

@END
IF BUTTON(0) GOTO @INIT
GOTO @END
Press any key to continue...

And there you have it. A short, simple and sweet maze generator routine. Feel free to use it on your games! I'm looking forward to see what you can come up with. Happy coding!