[comp.sys.handhelds] Reversi for the HP48SX

grue@batserver.cs.uq.oz.au (Frobozz) (12/20/90)

hiya,

Sorry, but the HP28 version isn't ready yet and it isn't going to be for
several weeks at the minimum (my 28 is going on a holiday without me).
Luckily, the 48 version is here.  Sorry if the following posting doesn't
make all that much sense in places, I wrote it to be a join posting that
included both versions of the program and I have cut it up quite a bit
to make it for the 48 only.



	A new improved version of my old reversi program!  The main features
of this version of the proram are:

* Features a true machine code move generator (including ALL searching and
	position evalulation).

* And a machine code move checker.

These improvements mean that the program runs much faster than
before and it responds to invalid moves much faster as well (especially
when the invalid move is a pass).


The user interface remains basically unchanged.  The biggest variation in
this department is the renumber of the rows of the board to conform to
normal reversi ordering (row 1 is now at the top!!).


The game is started by pressing the PLAY softkey.  The board will be drawn
and the player asked if they desire to go first (this question should be
answered Y or N).  To enter a move, you should first type the column number
1 (left most) to 8 (right most) followed by the column number 1 (top) to
8 (bottom).  Your move will be made if it is legal.
The other commands available are:

key | action
----+-----------------------------------------------
 P  | Pass move (only allowed if no moves are legal)
 Q  | Quit game
 O  | Turn calculator off
 U  | Take back last move (once only)

The input code will turn the calculator off if no key is pressed for a
minute and pressing on will continue the game as if nothing had happened.

If anybody finds problems with this program or can think of improvements
I'd like to hear about them.  I don't want to hear from people who think
that the disply of moves is too slow, I made the making of moves slow on
purpose (So that a player can see what effect a move really had while
playing.  A move that just appears on the display is quite disconcerting
to the player).

This version of the program doesn't play as well as the previous version
(which is a bit of a pity since the older version played a good novice
game).  This is mainly due to the very primative evalulation function
which is used (it simply counts the number of disks each side has and
maximises the difference).  I'm currently working on both improving the
evalulation function and making the move generator search more than one
ply ahead.  Both of these modifications will improve the play (I hope).
The updated move selector should only require the replacement of the
MVGEN routine (neat huh?).


The usual disclaimers apply.  (i.e. the stuff about using undocumented
features of the machine and any damage caused isn't my problem or fault).
I'm also not responsible for this program causing memory losts.  I'll just
say that I my calculator they don't cause them, your may be different.

The program is also copyright myself 1990, and it cannot be used for any
commercial purpose without my permission.  Any NON-PROFIT usage is permitted
without my prior approval.


Enjoy...(full listing for HP48 is included at the end of this file).
If enough interest is shown, I'll post the assembly source for the
various routines.  (this source is commented quite well, but the comments
haven't always kept up to date with the code [ it got modified quite a
lot during its evolution] :-(


							Pauli
seeya

Paul Dale               | Internet/CSnet:            grue@batserver.cs.uq.oz.au
Dept of Computer Science| Bitnet:       grue%batserver.cs.uq.oz.au@uunet.uu.net
Uni of Qld              | JANET:           grue%batserver.cs.uq.oz.au@uk.ac.ukc
Australia, 4072         | EAN:                          grue@batserver.cs.uq.oz
                        | UUCP:           uunet!munnari!batserver.cs.uq.oz!grue
f4e6g4Qh4++             | JUNET:                     grue@batserver.cs.uq.oz.au

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

Nice and simple for HP48 users out there, download the
directory object (see below) and STO it (I use the name
OTHL).  Enter the newly created directory and do the
following:
	INITP ASC-> 'INITP' STO
	PUTN ASC-> 'PUTN' STO
	GETN ASC-> 'GETN' STO
	CKMOV ASC-> 'CKMOV' STO
	MVGEN ASC-> 'MVGEN' STO
You should now be able to press PLAY to play the game!
You might want to type { PLAY } ORDER before running the game.
[ Remember to make a backup copy of your memory before
	you run the game, just in case! ]

The checksum for the directory is: F47h (using the BYTES
command here folks).
---------------------------8<-----------------------------
%%HP: T(3)A(R)F(.);
DIR
  PLAY
    \<< SETUP
"You first?" 4 DISS
      WHILE GETK
DUP 13 <
      REPEAT DROP
      END
      IF 13 ==
      THEN SWAPC
      END
      WHILE 1 FC?C
      REPEAT BD 5
R\->S GETN SWAP DROP
1 == 'PMOV' 'CMOV'
IFTE SCOR
        IF 8 FS?C
        THEN
          IF 2 FS?
          THEN 1 SF
          ELSE 2 SF
          END
        ELSE 2 CF
          IF CCT
PCT + 64 ==
          THEN 1 SF
          END
        END
      END
      IF 3 FC?
      THEN PCT CCT
-
        IF DUP 0 <
        THEN
"I win"
        ELSE
          IF DUP 0
>
          THEN
"You win"
          ELSE
"Draw"
          END
        END 1 DISS
ABS "by " SWAP \->STR
+ " disks" + 4 DISS
      END CLEAN
    \>>
  CLEAN
    \<< { PCT CCT BD
OLDP } PURGE STOF 7
FREEZE
    \>>
  SETUP
    \<< RCLF 1 9
      FOR j j CF
      NEXT 2 DUP
'PCT' STO 'CCT' STO
INITP NEWOB 'BD'
STO { } 'OLDP' STO
PICT PURGE { # 0h
# 0h } PVIEW 1 8
      FOR j PICT
# 60h j 6 * R\->B 2
\->LIST j 1 \->GROB GOR
      NEXT PICT {
# 64h # 0h }
"12345678" 1 \->GROB
GOR 4 4 1 DRWP 4 5
-1 DRWP 5 4 -1 DRWP
5 5 1 DRWP
    \>>
  SCOR
    \<< "  My total "
CCT \->STR + 2 DISS
"Your total " PCT
\->STR + 3 DISS
    \>>
  INITP
"C2A205E00066000F0000088888888880000000080000000080000000080001F0
008000F1000800000000800000000800000000888888888851C145B571A172E2
24946595819103739304758512221363A3F3E4F4023282D23484D40561B1E152
B42555A592C24474A2B22353B3E35464F142C41500FA22"
  SWAPC
    \<< 5 R\->S BD OVER
GETN NEG ROT SWAP
PUTN DROP
    \>>
  FLIPS
    \<< \-> x y
      \<< PICT x 4 *
# 60h + y 6 * R\->B 2
\->LIST
GROB 4 6 707020500000
GXOR
      \>>
    \>>
  DRWP
    \<< \-> x y c
      \<< PICT x 4 *
# 60h + y 6 * R\->B 2
\->LIST c 1 ==
GROB 4 6 705050700000
GROB 4 6 002070200000
IFTE REPL
      \>>
    \>>
  MKMOV
    \<< BD 5 R\->S GETN
\-> x y j c
      \<< BD x y XY\->S
c PUTN x y c DRWP 1
        IF c -1 ==
        THEN 'CCT'
        ELSE 'PCT'
        END STO+ -1
1
        FOR a -1 1
          FOR b 1
'j' STO
            WHILE x
a j * + y b j * +
XY\->S GETN c NEG ==
            REPEAT
1 j + 'j' STO
            END
            IF x a
j * + y b j * +
XY\->S GETN c ==
            THEN
              DO j
1 - 'j' STO
IF x a j * + y b j
* + XY\->S SWAP OVER
GETN c NEG ==
THEN SWAP c PUTN x
a j * + y b j * +
FLIPS 'PCT' 'CCT'
  IF c -1 ==
  THEN SWAP
  END -1 STO+ 1
STO+
ELSE SWAP DROP 7 SF
END
              UNTIL
7 FS?C
              END
            END
          NEXT
        NEXT DROP
      \>> SWAPC
    \>>
  PUTN
"CCD2065000147108174E78F1466013706135147C2135179110349C2A28A29030
F660030115D007135142164808C6DE5"
  GETN
"CCD2056000137061358F14660147C2135179D015B030F902D2D6C4C4C2C4C4CA
344B2A2CA07135141CF142164808CD0808212D69DF1A9E"
  CMOV
    \<< "Thinking..."
4 DISS BD NEWOB DUP
NEWOB MVGEN S\->XY
      IF DUP 0 <
      THEN DROP2
"I pass" 1 DISS
SWAPC 8 SF
      ELSE DUP2 R\->C
\->STR "My move "
SWAP + 1 DISS MKMOV
      END
    \>>
  DISS
    \<< PICT SWAP
# Ah * # 10h + # 0h
SWAP 2 \->LIST ROT
# 60h # Ah BLANK {
# 0h # 0h } ROT 2
\->GROB GOR REPL
    \>>
  PMOV
    \<< 0 DUP \-> c1 c2
      \<< "Your move"
4 DISS
        WHILE 4
FC?C
        REPEAT GETK
'c1' STO
          IF c1
          THEN
            IF c1 8
>
            THEN 5
SF { OFF
              \<<
IF BD 0 R\->S CKMOV
THEN 4 SF 8 SF
SWAPC
ELSE 5 CF
END
              \>>
              \<< 1 3
4 6 SF SF SF SF
              \>>
              \<<
OLDP SIZE 4 ==
\<< OLDP LIST\-> DROP
PICT { # 0h # 0h }
ROT REPL 'BD' STO
'PCT' STO 'CCT' STO
{ } 'OLDP' STO
\>>
\<< 5 CF
\>> IFTE
              \>>
              \<< 5
CF
              \>>
              \<< 5
CF
              \>> }
c1 8 - GET EVAL
            ELSE c1
\->STR 1 DISS GETK
'c2' STO c1 \->STR c2
\->STR + 1 DISS
              IF BD
c1 c2 XY\->S CKMOV
              THEN
4 SF CCT PCT BD
NEWOB PICT RCL 4
\->LIST 'OLDP' STO c1
c2 MKMOV
              END
            END
          END
          IF 4 FC?
5 FC?C AND
          THEN
"Illegal" 1 DISS
ERRBELL
          END
        END
      \>>
    \>>
  S\->XY
    \<< S\->R 11 - DUP
9 MOD SWAP 9 / IP
    \>>
  XY\->S
    \<< 9 * + 11 +
R\->S
    \>>
  GETK
    \<< TICKS \-> sttme
      \<<
        DO
          IF TICKS
sttme - B\->R 491520
>
          THEN OFF
TICKS 'sttme' STO
          END
        UNTIL KEY
        END
      \>> KMAP SWAP
POS
    \>>
  KMAP { 82 83 84
72 73 74 62 63 33
34 35 43 52 32 }
  R\->S
    \<< # 18CEAh
SYSEVAL
    \>>
  S\->R
    \<< # 18DBFh
SYSEVAL
    \>>
  CKMOV
"CCD20451008F146608FB9760D20B0614713517EC213416915F0B0690A508528A
C0316A169D23184D715E090EB07150871D2160CF8AF6E651015E090E61713086
1D0349C2A26A00344B2A2DA8F2D760141070A142164808CD2CE7040D23087730
D23097E20D230A7520D2E67D10348FFFF7210347FFFF7700346FFFFD5132130C
013115F0862B0E690AB001CE90E00C013115F090A0080820890200133862F0E6
90AADCE6C00CE90ADCE6851013B92"
  MVGEN
"CCD20A5200179E7E78FB97601C9D20B067090070A8F73560142164808CD51321
30C013115F0862B0E690AB001CE90E00C013115F090A0080820890200133862F
0E690AADCE6C00CE90ADCE6851F9C013115B09080015D01336AEF13713513417
414213016913610B14313117913710A74408AAB27E21AF41011321007B208AA9
175111119F8DE6EDFD21080111011BFACA1000111A13411B1351567D72580820
F902508522687B2125B8A2034660002D155716F17F152715170D880DE11BCBE7
E7134D014A968B611BCA130156090EBD841D2CE7F8ED2308768ED23097D7ED23
0A747ED2E67C6E348FFFF716E347FFFF765E346FFFF7B4E861786900D2641030
F8625030115C0DB1121311450111313117A179D23184D73104AF1D515B030F90
601E5170CF8AFAE01301906EECD69EF1614"
END
---------------------------8<-----------------------------
--

akcs.falco@hpcvbbs.UUCP (Andrey Dolgachev) (12/23/90)

I was thinking of two improvements:  A two-player option on one
calculator, and a two-player option through the i/o.  The two-player
option is obviously not hard at all, since the programs are virtually
there already.  The i/o option is a little harder, but I have already
made a two-player tank arcade game thorugh the i-red, so it shouldn't be
too hard to do either.  Well, hopefully, I will get around to this, and
post it up, making sure I give credit to the original creator

grue@batserver.cs.uq.oz.au (Frobozz) (12/24/90)

In <27740d10:1481.1comp.sys.handhelds;1@hpcvbbs.UUCP> akcs.falco@hpcvbbs.UUCP (Andrey Dolgachev) writes:

>I was thinking of two improvements:  A two-player option on one
>calculator, and a two-player option through the i/o.  The two-player
>option is obviously not hard at all, since the programs are virtually
>there already.  The i/o option is a little harder, but I have already
>made a two-player tank arcade game thorugh the i-red, so it shouldn't be
>too hard to do either.  Well, hopefully, I will get around to this, and
>post it up, making sure I give credit to the original creator

Well, I'm the creator and patching the program to play 2 player is very easy.
The following version of play should do the trick...  (Note, I don't have my
48 with me and I edited the original posting by HAND.  You should also note
that the following code has NOT be tested at all.)
I'll briefly write about the changes needed.
The routine PMOV lets the player enter a legal move.  It then makes that move
on the board and changes the colour to move.  By calling PMOV repeatedly the
player will get to enter lots of moves of alternating colour.  This works
because the move checker uses the colour to move from the board string as
does the move maker routine  (for interests sake, it is located in the 5th
nibble of the board description string,  get it using BD 5 R->S GETN).
So, all that has to be changed is to remove the you first message at the
start and to also remove the bit of code which checks the colour to move
and calls PMOV or CMOV as necessary.

To make it nicer, it might be sensible to copy PMOV into some other name
and edit it so that it doesn't display 'Your move' at the bottom of the
screen.  Making it display player 1 / player 2 would be a very simple
addition.
in fact this bit of code should do the trick:
	BD 5 R->S GETN SWAP DROP
	1 == "Player 2" "Player 1" IFTE
Just plug that bit of code into the spot occupied by the "Your move" string
in PMOV (or the copy of it, called PMV2?  You'd also have to change the PMOV
in the new version of play below into PMV2).

I'd rename the patched version of PLAY into PL2 or some such, so that the
one player game was still accessable.


I personally don't care for the ir two player version.  It would require too
much work for the benifits gained.


Enjoy...


							Pauli
seeya

Paul Dale               | Internet/CSnet:            grue@batserver.cs.uq.oz.au
Dept of Computer Science| Bitnet:       grue%batserver.cs.uq.oz.au@uunet.uu.net
Uni of Qld              | JANET:           grue%batserver.cs.uq.oz.au@uk.ac.ukc
Australia, 4072         | EAN:                          grue@batserver.cs.uq.oz
                        | UUCP:           uunet!munnari!batserver.cs.uq.oz!grue
f4e6g4Qh4++             | JUNET:                     grue@batserver.cs.uq.oz.au



  PLAY
    \<< SETUP
      WHILE 1 FC?C
      REPEAT PMOV
        SCOR
        IF 8 FS?C
        THEN
          IF 2 FS?
          THEN 1 SF
          ELSE 2 SF
          END
        ELSE 2 CF
          IF CCT
PCT + 64 ==
          THEN 1 SF
          END
        END
      END
      IF 3 FC?
      THEN PCT CCT
-
        IF DUP 0 <
        THEN
"I win"
        ELSE
          IF DUP 0
>
          THEN
"You win"
          ELSE
"Draw"
          END
        END 1 DISS
ABS "by " SWAP \->STR
+ " disks" + 4 DISS
      END CLEAN
    \>>

--