[comp.sys.handhelds] Magic Square for the HP28s!

dougc@bert.cs.byu.edu (DOUG CANNON) (06/07/91)

Hello fellow comp.sys.handhelders.
This is my first post here, and I hope it's not out of line.
Moderatley fun game, so I guess it's ok.

--CUT HERE-------Or just leave as is, I don't care-------------

Magic Square by Doug Cannon Sept 27,1990

	This is quite an interesting program. I think I got the
idea from an ancient electronic game called MERLIN. One of the
games you could play was Magic Square. I never owned Merlin, but
I think this is how it goes. Anyway, it's a cute game, with a little
animation added to make it more exciting.

	The keys you may press are the number keys (0-9) and the letter
H. H is for help. It will tell you how many key presses left to win.
The number keys are oriented the same as the playing board.
If you press an edge key (2, 4, 6, 8) then it will inverse the
three dots along that edge. If you press it again, it just un-does
what it did. Pressing a corner key will inverse the four dots in that
corner. Of course, pressing it again will undo what it did.
Pressing the center key will inverse 5 dots in the shape of a plus.
(That is, the four edge dots, and the center dot.)
The object of the game is to have each dot "turned on" except the
center one. Then you win. Each time you press a key (including H)
It adds one to your score. The lower the score, the better.
I think I couldn't have made these instructions more unclear, but
just try it, and I think you'll get the hang of it.
Sorry that it is a lengthy program. It is fun, though.

One more thing. If you simply execute [MAGS] this is the starting
program. (I recommend you use a speed-up program first). Then you
will play 3 rounds of Magic Square. If you would like to play more
or less rounds, then enter a number onto the stack before pressing
[MAGS]. 

That's it! Enjoy!

----------------------------------------
 
'MAGS' [4299]
<< 64 STWS				;Set to 64 for bin operations
   DEPTH 0 == 3 IFT			;Check if nothing on stack, put a 3
   DUP TYPE 0 <> 3 IFT	 		;If level 1 not a number, put a 3
   IP MPGM >>				;Execute MPGM.

Please note that I used a <> symbol to mean <NOT EQUAL>. The HP28s, of
course has the real symbol, but my editor does not. Please enter
the proper symbol on your hp.

--------------------------------

'INIT' [2076]
<< #0b -> DTA
<< CLLCD CLRH 137 SUB CLRH		;Set up CLRH to be
   412 548 SUB SWAP OVER DUP + + +	;used with SCORE
   362 Z ANIM + 141 Z +			;Set up ANIM
   9 1 FOR Y				;9 total graphics to make
    "PLEASE WAIT " Y ->STR + 1 DISP
    ZERO PUSH Y GET 'DTA' STO
     1 9 FOR X				;9 possible dots
      DTA #1b AND
      #1b IF ==				;Check if this dot present
       THEN X DOTT OR			;if yes, make it
      END
      DTA SR 'DTA' STO
     NEXT
   -1 STEP
>> >>

----------------------------------------

'DCAL' [6C38]
<< #111101111b 0 -> DTA KTP		;Set local vars
<< 1 9 FOR X				;Need 9 possibilities
    RAND 2 *				;pick a 1 or 0
    IF					;if it was a 1
     THEN PUSH X GET DTA XOR		;Then it's a key
      'DTA' STP 2 X 1 - ^ KTP +		;to be pushed in game.
      'KTP' STO
     ELSE X 1 + PICK XOR		;else do graphic
    END
    X 5 IF ==				;#5 is a
     THEN 6 PICK XOR			;special case.
    END
   NEXT
   KTP R->B DTA 			;pass results
>> >>

----------------------------------------

'HELP' [862]
<< 0 -> KTP N				;Init local vars
<< 1 9 FOR X 				;Check 9 possibilities
    #1b KTP AND
    #1b if ==				;If there's a 1 ...
     THEN 1 N + 'N' STO			;Add 1 to N.
    END
    KTP SR 'KTP' STO			;Shift right one bit
   NEXT					;Check the rest
   120 Z SNUM N 6 * 1 + N 1 +		;Get the right
   6 * SUB + 422 Z + OR DUP		;Number,
   -> LCD				;Display it.
>> >>

----------------------------------------

'SCORE' [1EE4]
<< ->STR -> SC				;Make # into string, STO in SC
<< 12 PICK AND 257 Z			;Erase old score, get some zeros
   1 SC SIZE FOR X			;for X = 1 to SIZE(SC)
    BNUM SC X X SUB STR->		;get a digit
    6 * 1 + DUP 5 + SUB +		;get digit graphics
   NEXT					;do the rest
   548 OVER SIZE - Z			;get remaining blanks
   + OR					;merge it on
>> >>

----------------------------------------

'FANF' [8804]
<< BD 1 10 FOR F			;10 times
       DUP -> LCD 2000 1000		;display alternating pics.
       'SIGN(FP(F/2))' EVAL * +		;play alternating
       .05 BEEP SWAP			;tones
      NEXT
   SWAP DROP
>>

----------------------------------------

'DOTT' [EC32]
<< DUP 1 - 3 / IP 1 + SWAP		;converts a num (1-9)
   1 - 3 MOD 1 + -> S T			;into coords (S,T)
<< DDATA S GET LIST-> DROP 466		;Crazy calculations
   S 137 * - Z + 129 Z SWAP + +		;that actually
   Z SWAP + 3 T - 10 * Z +		;work!!
>> >>

----------------------------------------

'Z' [2F40]
<< ZERO 1 ROT SUB >>

----------------------------------------

'MGPM' [D118]
<< {"1" "2" "3" "4" "5" "6" "7" "8" "9" "H"}	;all keypresses
   0 0 0 #0b #0b 0 0 0 CHR		
   -> N KEYS SC LSC STOT KTP DTA	;init local vars
   CNT DIR BL				;same
<< INIT
   1 N FOR G				;do 1 to N rounds
    BD DCAL 'DTA' STO 'KTP' STO		;get BD, pick random dots
    DUP -> LCD				;show it
    DO
     KEYS 0 'CNT' STO
     DO					;Check for key,
      CNT 1 + 'CNT' STO			;fall out of loop
     UNTIL KEY 5 CNT == OR END		;if key or if take too long
     DUP TYPE				;Check to make sure
     IF 2 == 5 CNT <> OR		;key was pressed.	<NOT EQUAL>
      THEN CLRH 4 ROLL AND		;if yes, then erase
       3 ROLLD POS DUP			;help, find which key.
       0 IF <>				;if a good key		<NOT EQUAL>
        THEN SC 1 + 'SC' STO DUP	;add 1 to score
         10 IF <>			;if not "H"		<NOT EQUAL>
          THEN 2 OVER 1 - ^ R->B	;Then get a dot pattern,
           KTP XOR 'KTP' STO SWAP	;let KTP know
           OVER 2 + PICK XOR PUSH	;prepare picture
           ROT GET DTA XOR 'DTA'	;Let DTA know
           STO DUP ->LCD		;Display picture
           6000 .04 BEEP		;BEEP
          ELSE DROP KTP HELP		;if "H" pressed, run HELP
         END
        ELSE DROP 1000 .05 BEEP		;if a bad key, BEEP
       END
      ELSE DROP 11 PICK			;if too much time, then
       IF DIR				;if DIR = 1 (direction)
        THEN 0 'DIR' STO		;then set to 0
        ELSE 1 'DIR' STO BL SWAP	;if dir=0, set to 1
         + 1 548 SUB			;go other way
       END
       XOR SC LSC			;check if score should
       IF <> THEN SC SCORE SC		;be updated		<NOT EQUAL>
        'LSC' STO END
       DUP ->LCD			;show update
     END
    UNTIL KTP #0b == END		;keep playing until done (KTP=0)
    FANF DROP STOT SC + 'STOT'		;play fanfare, add score
    STO 0 'SC' STO			;to tot, score = 0
   NEXT					;do the other rounds.
   11 DROPN				;drop stack data
   "OUT OF " N ->STR +			;show # of rounds
   " GAMES" +
   "YOUR SCORE= " STOT ->STR +		;show score
   STOT N / ID * IP 10 / ->STR		;find ave per game
   " PER GAME" + CLMF			;show it
>> >>

----------------------------------------

Local		KEYS	(LIST)	of all possible keypresses
Variables:	N	(REAL)	Number of rounds
		SC	(REAL)	Score of round being played
		LSC	(REAL)	Last updated score
		STOT	(REAL)	Total score for all rounds
		KTP	(BIN)	Keys to be pressed to win
		DTA	(BIN)	Data showing where dots are
		CNT	(REAL)	Counter variable
		DIR	(REAL)	Direction of animation
		BL	(STR)	One single blank (CHR(0))

----------------------------------------

Now we need to create the various graphics used.
Most of them are quite simple.

There are two small utility programs we will need to aid us in
creating these graphics.

The following program converts a stack of numbers into a string.
'MAKE' [1C7]
<< "" DEPTH 1 - 1 SWAP START SWAP
   CHR SWAP + NEXT >>

The next program duplicates an opbject a specified number of times.
'DUPX' [7E46]
<< 1 - 1 SWAP START DUP NEXT >>

----------------------------------------

'ZERO' [0]
0 548 [DUPX] [MAKE] 'ZERO' [STO]

----------------------------------------

'CLRH' [DA25]
255 118 [DUPX] 0 19 [DUPX]
255 411 [DUPX] [MAKE]
'CLRH' [STO]

Of course you know that if I say [DUPX] it means you should push
the softkey to run the program [DUPX]. (Or [MAKE] or whatever.)

----------------------------------------

'ANIM' [8880]

This graphic requires that we enter a small program to be
executed only once.

<< 40 84 MAKE 1 5 START DUP + NEXT 1 39 SUB
   'ANIM' STO 64 32 80 MAKE ANIM + 'ANIM' STO
   20 8 4 MAKE ANIM SWAP + 'ANIM' STO >>

Now just press [EVAL] and the work is done.

----------------------------------------

'SNUM' [16E9]

Once again we will execute a small program.

<< "0123456789" 1 DISP LCD-> 1 60 SUB 
   'SNUM' STO CLMF >>

As before, press [EVAL] and HP does the hard stuff.

----------------------------------------

'BNUM' [E9A7]

This is a little bit harder than 'SNUM' but not too bad.
We need to enter the following numbers onto the stack,
then execute [MAKE].

126 255 195 255 126 0 0 196 254 255 192 0 230 247 211 223
206 0 66 195 219 255 102 0 31 31 24 255 255 0 95 223 219
251 115 0 126 255 219 251 114 0 3 227 251 31 7 0 126 255
219 255 126 0 78 223 219 255 126 0
[MAKE] 'BNUM' [STO]

----------------------------------------

Well, that's it for the easy graphics, now we need to create
the board. This is not so easy. So, I will give three options:

If you don't care much for graphics, then do this:
548 [Z] 'BD' [STO] and skip the rest. But this will not be as
pretty.

If you want only the bare essentials, then type in the first part.
The second part is a neat graphic that is just for show.

First part only: 	CHK [8087]
First and Second parts:	CHK [CFD4]

First part: ( Please pay attention to [DUPX] and [DUPN] )

Fourth row:

0 52 [DUPX] 255 255 192 8 [DUPX] 10 [DUPN] 10 [DUPN]
255 255 0 248 136 136 112 0 112 136 136 112 0 120 128 128
120 0 112 136 168 232 0 0 0 112 136 136 136 0 240 72
72 240 0 248 32 64 248 0 248 32 64 248 0 112 136 136
112 0 248 32 64 248 0
[MAKE] 'BD' [STO]

---------------
Third row:

0 52 [DUPX] 255 255 48 8 [DUPX] 10 [DUPN] 10 [DUPN]
255 255 0 128 192 224 176 152 204 230 178 154 206
4 [DUPN] 8 [DUPN] 16 [DUPN] 8 [DUPN] 102 50 26 14 6 2
[MAKE] [BD] + 'BD' [STO]

---------------
Second row:

0 52 [DUPX] 255 255 12 8 [DUPX] 10 [DUPN] 10 [DUPN]
255 255 0 102 239 219 247 102 0 126 255 195 231 102 0 126
255 195 255 126 0 255 255 27 255 238 0 255 255 219 219 195
0 0 108 108 0 0 126 255 195 255 126 0 12 [DUPX]
[MAKE] [BD] + 'BD' [STO]

---------------
First row:

0 52 [DUPX] 255 255 3 8 [DUPX] 10 [DUPN] 10 [DUPN]
255 255 0 127 65 119 20 119 65 127 0 127 127 107 107 99
0 127 127 96 96 96 0 127 127 27 31 14 0 0 54 54
0 23 [DUPX] [MAKE] [BD] + 'BD' [STO]

----------------------------------------

Now lets enter in the pretty graphic. (It really is worth it!)

Fourth row:

0 0 0 3 14 24 120 112 240 240 249 127 63 30 97 255
240 224 144 119 239 159 64 255 224 224 255 127 31 224 107 28
28 107 247 127 128 127 15 6 31 127 251 97 0 255 243 227
243 248 112 0 86 [DUPX] [MAKE] 'TEMP' [STO]

---------------
Third row:

0 15 127 128 0 0 60 126 127 239 199 199 142 92 225 252
60 28 60 252 248 224 28 248 0 0 248 252 248 0 252 28
28 252 248 224 24 252 60 28 60 252 248 224 24 252 60 28
60 124 56 0 86 [DUPX] [MAKE] [TEMP] + 'TEMP' [STO]

---------------
Second row:

63 255 255 63 3 1 1 3 7 15 3 0 0 0 224 127
63 15 0 31 61 26 7 7 7 26 61 31 0 7 31 62
57 59 59 59 29 6 0 31 63 31 0 7 31 63 60 56
60 62 28 0 86 [DUPX] [MAKE] [TEMP] + 'TEMP' [STO]

---------------

First row:

0 240 254 255 255 254 248 224 254 255 255 254 126 124 248 240
192 0 0 248 254 255 15 7 15 255 254 248 0 248 254 255
15 135 135 143 30 56 0 254 255 254 0 248 254 255 15 7
15 31 14 0 86 [DUPX] [MAKE] [TEMP] + 'TEMP' [STO]

---------------

There, now that wasn't so bad! I suggest that we check to see
if we have entered this graphic correctly.
'TEMP' CHK [4F53]
Now just do this: [BD] [TEMP] OR 'BD' [STO]
Do the check: 'BD' CHK [CFD4] ( As stated above )
And if it's OK, then do this: 'TEMP' [PURGE]

---------------------------------------

The last thing to enter are the two data files.
The first is easy.

'PUSH' [C503]
{ #D8h #1C0h #1B0h
  #49h #BAh  #124h
  #1Bh #7h   #36h  }

The next one you will need to use [MAKE] again.

15 31 63 63 63 63 31 15 [MAKE] 'TEMP' [STO]
0 128 192 192 192 192 128 0 [MAKE]
[TEMP] 2 ->LIST 'DDATA' [STO]

3 7 15 15 15 15 7 3 [MAKE] 'TEMP' [STO]
192 224 240 240 240 240 224 192 [MAKE]
[TEMP] 2 ->LIST [DDATA] 2 ->LIST 'DDATA' [STO]

0 1 3 3 3 3 1 0 [MAKE] 'TEMP' [STO]
240 248 252 252 252 252 248 240 [MAKE]
[TEMP] 2 ->LIST [DDATA] LIST-> [DROP] 3 ->LIST
'DDATA' [STO]
'DDATA' CHK [F995]

----------------------------------------

Please, Let me know if you've enjoyed this program.
Also, if you encounter any problems, let me know.
Drop me a line: dougc@bert.cs.byu.edu
I have many more of similar interest.

I even have a humdinger of an animation program that you
have to see to believe. The problem is that it requires 8
pictures of 548 numbers each, meaning you enter 4,384 numbers
onto the stack (in pieces of course!) and then the program
is quite simple. But very fascinating!

--CUT HERE TOO---------------------------

Doug Cannon, BYU, Provo, Utah
dougc@bert.cs.byu.edu