HP Forums

Full Version: (11C) Code guessing game
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Also known as "Mastermind". I wrote it somewhere around 1985. The calculator takes a number of 3-10 digits and up to 9 colours for you to guess. C starts a new game, D enters a guess. Result: number in the form a,b where a = number of digits with right colour, and b is the number of digits of the right colour which are in the right place. Or: number FIX9 > you guessed it.

[attachment=5860]
Looks great!

I tried to get this working on a DM15L (HP15C clone), but couldn't. I changed register 1 to 7 to make sure that it's cleared by Clear Sum, but it's not enough. When I make a totally wrong guess I get 0.0, but other guesses only return 1.0 or 1.1. (Haven't tried it on my 11C emulator yet, but that one is inaccurate anyways).

Which other difference besides CLEAR SUM clearing 0-5 on 11C but 2-7 on 15C are there between these calculators?

Also, do you have a "human readable" version of the program?
Never mind, I just had a typo (confused FRAC with INT in one place). It works like that on the Android 11C app and if you change R1 to R7 it also works on the DM15L (and probably 15C).

Really great program!
(04-25-2018 06:18 PM)Rogier Wrote: [ -> ]Also known as "Mastermind". I wrote it somewhere around 1985. The calculator takes a number of 3-10 digits and up to 9 colours for you to guess. C starts a new game, D enters a guess. Result: number in the form a,b where a = number of digits with right colour, and b is the number of digits of the right colour which are in the right place. Or: number FIX9 > you guessed it.

Ah, Mastermind / Bagels / Code Breaker – one of the first useful programs I wrote for the 34C back then. I used a different approach that stored the code digits in individual registers. And the code always consisted of four different colors.

So let me add the following 11C/15C version to this thread.
(15C commands in brackets, where required)

Code:
001  LBL A
002  CLX
003  STO 0
004  4
005  STO ,0
006  LBL 1
007  RCL 0
008  STO I
009  RAN#
010  6
011  x
012  INT
013  1
014  +
015  LBL 2
016  RCL(i)
017  x<>y
018  X=Y?   (TEST 5)
019  GTO 1
020  DSE    (DSE I)
021  GTO 2
022  RCL 0
023  1
024  +
025  STO 0
026  STO I
027  R↓
028  STO(i)
029  RCL 0
030  RCL ,0
031  X>Y?   (TEST 7)
032  GTO 1
033  CLX
034  STO 9
035  LBL 0
036  FIX 1
037  R/S
038  LBL B
039  STO 7
040  RCL ,0
041  STO 0
042  CLX
043  STO 8
044  1
045  STO+9
046  LBL 3
047  RCL ,0
048  STO I 
049  1
050  0
051  STO÷7
052  RCL 7
053  FRAC
054  STO-7
055  x
056  LBL 4
057  RCL(i)
058  x<>y
059  X=Y?   (TEST 5)
060  GTO 6
061  DSE    (DSE I)
062  GTO 4
063  GTO 5
064  LBL 6
065  RCL 0
066  RCL I
067  X≠Y?   (TEST 6)
068  ,
069  1
070  STO+8
071  LBL 5
072  1
073  STO-0
074  RCL 0
075  X>0?   (TEST 1)
076  GTO 3
077  RCL ,0
078  RCL 8
079  X≠Y?   (TEST 6)
080  GTO 0
081  RCL 9
082  10^x
083  x
084  SCI 1
085  RTN

Registers:
R0: pointer / counter
R1...R6: code digit 1...6
R7: guess
R8: score
R9: guess counter
R,0: code length

Edit: changed the roles of R,0 and R7 for 11C compliance and removed an obsolete line.

Hint for 15C users – you may replace the final lines after "GTO 0" with RCL 9  FIX 0  SF 9  RTN. If the code has been correctly guessed this yields a flashing display with the number of required guesses. ;-)  You can also replace line 72...75 with DSE 0.

The code length is set in line 005, change it as desired to something between 1 and 6.
The number of different colors is set in line 010. Must be ≥ code length and ≤ 9.
Default is a 4-digit code with each digit between 1 and 6. For your first attemps you may change this to a 3-digit code with 5 colors.

[A] generates the code => 0,0

Enter your guess and press [R/S] or [B] => x,y
Here x is the number of right colors in the right place, and y is the number of colors that are correct, but in the wrong position.

Example:

[A] => 0,0

Note: generated code is assumed to be 4532

1234 [B] => 1,2
1325 [B] => 0,3
3254 [B] => 0,4
2534 [B] => 2,2
2435 [B] => 1,3
4532 [B] => 4,0       06

So you finally got all 4 colors right and required 6 guesses.

Dieter
I'll give your program a try, Dieter. Looks fine too. The scoring is more in line with "official" Mastermind rules and it is shorter.

Michaelzinn, what do you mean by human readable form?

(By the way: I added a PDF because I haven't figured out yet how to add a code block in a post.)
(04-26-2018 10:10 PM)Rogier Wrote: [ -> ](By the way: I added a PDF because I haven't figured out yet how to add a code block in a post.)

The message editor of this forum has a few buttons on top of the message window. There is a "#" Symbol. If you klick on it a "code" tag (enclosed in square brackets) is inserted. Press on "close tags" and the respective end tag is added. Now you can place your code between these two tags.

If you read this post and press the "quote" button below it you can see how it works:

Code:
This
is
a
code
sample

Of course you can also insert the code-tags manually. That's how I usually do it.

Dieter
(04-26-2018 10:10 PM)Rogier Wrote: [ -> ]I'll give your program a try, Dieter. Looks fine too. The scoring is more in line with "official" Mastermind rules and it is shorter.

I have tried to understand how your program works, especially the scoring routine, but I admit I haven't understood all details. For comparison here is how my version works:

LBL A: code generation. This generates four individual random digits. A counter in R0 is incremented on each loop and the loop at LBL 2 checks if the digit is equal to one of the previously generated ones. In this case a new digit is generated. Else the number is stored in the next higher data register. This way (assuming the default settings) R1...R4 are filled one after another with four different numbers between 1 and 6. The code length (here 4) is kept in R,0 so that it can be recalled from there later.

LBL B: score evaluation. The guess is stored in R7, the guess counter in R9 incremented and the loop counter in R0 is initialized with 4 (guess digits to compare). The main loop at LBL 3 splits off a single guess digit (from right to left) and checks if it matches one of the code digits. This is done in the loop at LBL 4. This way first the 4th guess digit is compared with the code digits #4, #3, #2, #1, then the 3rd guess digit is compared with the code digits #4, #3, #2, #1, ... etc.

If a match is detected the loop is exited (GTO 6) and the score is added: if the loop counter in R0 - which indicates the current digit's position in the guess - matches the position in the code - which is held in R I - the score in R8 is increased by 1. If the positions are not equal only 0,1 is added. This can be done very elegantly with a simple test that skips over the decimal point if the positions match.

Finally (LBL 5) the loop counter is decremented until it becomes zero. 15C owners may also use a simple DSE 0 here. After all digits have been compared the program checks if the score equals the code length, which means that all guess digits were correct. If not it jumps back to LBL 0 to display the score and stop, else it moves the number of guesses into the tens exponent so that the final display in scientific notation shows the score along with the number of required guesses, e.g. "4,0          12".

I hope this was clear enough. ;-)
If not, just ask.

Dieter

Edited to reflect the program's updated register use.
Thanks for the help on the "code" tag. I'll try it with another program.

As to my scoring routine: I slice off digits from code and guess and compare them. If they are equal, I add 1 to the score, if the integer part of (log [remaining part code] - log [remaining part guess]) = 0 then the digits are in the same place and I add 0,1 tot the score. What the program doesn't do, is check is whether a number in your guess has already been examined.

So:
Code = 451
Guess = 112 > 2,0 Two digits correct, not in the right place
Guess = 111 > 3,1 All correct, one in the right place

Code = 445
Guess = 411 > 1,1 One digit correct and in the right place

I give a bit more information than Mastermind rules, but with 10 places, 9 colours it's still quite a challenge. (And time-consuming; scoring 10 digits takes 2min24sec to 2min54sec on my HP-11C. Touch 11i free on my phone is even slower. Plus: it displays the X-register during program execution, which is a bit of a spoiler, because that shows you the code.)
(04-26-2018 10:10 PM)Rogier Wrote: [ -> ]Michaelzinn, what do you mean by human readable form?

To me, it was very difficult to understand how the program works. Comments, especially for the labels, would help. I reverse engineered the code and commented it a bit (Ignore the parens I'm currently experimenting with some ideas to "compile" code from edn):

Code:

        (LBL "check guess X"
            (CF "0: counted match")
            (STO "2: guess part")
            (STO "5: guess")
            (RCL "1: solution")
            (ISG        ; count guess?
                (X=Y?)) ; NOP ?

            ; display I
            (X><I))
            (PSE)
            (X><I)
            (FIX 9) ; won display
            (X=Y?    ; won?
                RTN) ; won! show fix 9
            (FIX 1) ; did not win, fix 1

            (STO "3: solution part") ; copy s1 to s3

            (LBL "2: compare current guess digit to every solution digit" ; 016

                ; solution checked?
                (X=0? (GTO 0)) ; check next guess digit

                (RCL "2 guess part") ; guess done?
                (X=0? (GTO 4)) ; all done, display result

                ; last digit correct?
                -
                10
                /
                FRAC
                (X=0? (GSB "7: found match")) ; yes

                ; no, cut last digit from s3 and try again
                (STO "3; solution part" (INT (* .1 (RCL "3solutionp"))))
                (GTO "2: compare lgd to every sd"))

            (LBL "0: proceed to next guess digit" ; 036 - 
                ; cut last digit from guess2
                (STO "guess2" (INT (/ (RCL "guess2") 10)))

                (CF "counted match")
                (STO "solution3" (RCL "soluton1"))
                (GTO "2: compare..."))

            (LBL "7: found match"
                (F "counted match"?
                    (GTO 7)) ; don't count again

                ; count 1 "right somewhere"
                (STO + "4: score guess" 1) ;right somewhere
                (SF 0) ;counted
                (LBL 7
                    ; correct position?
                    (INT (LOG (RCL "3: solution part")))
                    (INT (LOG (RCL "2: guess part")))
                    (-)
                    (X!=0?
                        RTN)
                    ; count as perfect match
                    (STO + "4: score guess" .1))

                (RTN))

        (LBL "C: new game"
            (FIX 1)
            (CLR SUM) ; 2-7
            3
            (STO I)
            (LBL "1: roll solution"
                ; move digits to the left
                (STO * "7: turns/loopC" 10)
                ; add another random digit
                (STO + "7:t/lc" (INT (+ 1 (* 9 RAN))))
                (CLx)
                (DSE I
                    (GTO "1: roll solution"))))
        (LBL "4: display score guess"
            (RCL 4)   ; show score, initally 0
            (STO - 4) ; clear R4
            (RTN))
Question about Mastermind, that is a short but intense game (ever tried to make little tournaments?).

Did anyone create some "computer opponent" on calculators for the game? So an heuristic search for solutions.
(04-28-2018 12:24 PM)Rogier Wrote: [ -> ]Code = 451
Guess = 112 > 2,0 Two digits correct, not in the right place
Guess = 111 > 3,1 All correct, one in the right place

Shouldn't this be 2,1 ?
The left and middle "1" are correct, but in the wrong place (1,0 + 1,0).
The right "1" is correct and in the right place (0,1).

Suppose the code is 333.
What should be returned for a guess of 333 (if it isn't already detected as "correct" at the beginning).

The first "3" in the guess is correct and in the right place (0,1) and also 2x correct but in the wrong place (2,0). This yields 2,1. Or, after all three digits have been evaluated: 6,3. Is this correct?

Dieter
Michealzinn, I'll try and add more comments to other programs, but since I wrote most of my programs over 30 years ago, you're not the only one having problems understanding the structure. At the time I was more interested in how to operate the programs than in documenting how they work.

Dieter, about the scoring:
I compare each digit of the code to the last digit of the guess, then I divide the guess by 10 and repeat the procedure until the guess is all sliced up.

The scores I quoted are correct (at least: as intended within the parameters of the program):
Code = 451
Guess = 112 > 2,0 Two digits correct, not in the right place
Guess = 111 > 3,1 All correct, one in the right place

If the code were 333, a guess of 333 should score 3,3; 3 digits correct, all of which in the right place. You never see that, but entering 3333 yields 4,3. (I don't check for the right length when you enter a guess. Would be relatively easy to fix of course.)
I'll have to adapt your program by the way Sto/,0 doesn't work on an HP-11c.

Pier4r: I have thought about reversing the roles and let the calculator guess, but gave up on it. Not a chance of fitting it in an HP-11c, and too complex (at least for me) to program it in my ZX-Spectrum or in GW-basic.
(04-29-2018 09:58 PM)Rogier Wrote: [ -> ]I compare each digit of the code to the last digit of the guess, then I divide the guess by 10 and repeat the procedure until the guess is all sliced up.

OK, this makes sense – let's do this for the example:

(04-29-2018 09:58 PM)Rogier Wrote: [ -> ]The scores I quoted are correct (at least: as intended within the parameters of the program):
Code = 451
Guess = 112 > 2,0 Two digits correct, not in the right place
Guess = 111 > 3,1 All correct, one in the right place

Take the last digit of the guess, 1. Compare it with the code from right to left:
1: correct and in the right place => +0,1
5: no match
4: no match

Slice off the rightmost digit, so the remaining guess is 11.

Take the last digit of the guess, 1. Compare it with the code from right to left:
1: correct, but in wrong place => +1,0
5: no match
4: no match

Slice off the rightmost digit, so the remaining guess is 1.

Take the last digit of the guess, 1. Compare it with the code from right to left:
1: correct, but in wrong place => +1,0
5: no match
4: no match

Slice off the rightmost digit, so the remaining guess is 0 => scoring completed.
Score is 0,1 + 1,0 + 1,0 = 2,1

You say you get 3,1. So the three guess digit gets four (!) scores. On a real Mastermind board you this would be equivalent to 3 white pegs and 1 black one. The correctly positioned "1" gets two (!) ratings: both a black one and a white one.

So the rightmost 1 in the code is evaluated this way:

Take the last digit of the guess, 1. Compare it with the code from right to left:
1: correct (is part of the code) => +1,0
furthermore it also is in the right place => +0,1
5: no match
4: no match

(04-29-2018 09:58 PM)Rogier Wrote: [ -> ]If the code were 333, a guess of 333 should score 3,3; 3 digits correct, all of which in the right place.

OK, so again the 3 guess digits are rated twice:
Once for the right digit being somewhere in the code, and another time for it being in the right position. If this is your intention the score is fine. But I wonder if it matches the Mastermind rules.

(04-29-2018 09:58 PM)Rogier Wrote: [ -> ]You never see that, but entering 3333 yields 4,3. (I don't check for the right length when you enter a guess. Would be relatively easy to fix of course.)
I'll have to adapt your program by the way Sto/,0 doesn't work on an HP-11c.

I suspected this (my good old 34C didn't allow storage arithmetics on R,0...R,9 either). Actually I wrote the program on a 15C emulator. #-)

You may simply swap R,0 and R7. I now have edited the original listing. Thank you very much for this hint.

(04-29-2018 09:58 PM)Rogier Wrote: [ -> ]Pier4r: I have thought about reversing the roles and let the calculator guess, but gave up on it. Not a chance of fitting it in an HP-11c, and too complex (at least for me) to program it in my ZX-Spectrum or in GW-basic.

Back in the days I have been thinking about such a program either, but even if it could have been done on a more powerful calculator like the 41C I admit my skills were (and still are) too limited for such a project.

Dieter
I'm pretty sure my scoring isn't official Mastermind, but it's what I came up with.
The minor problem is the double scoring of digits of a correct colour AND in the right place. That could easily be solved (multiply by 10 and subtract from the total of correct digits). I just never bothered. I can live with a result "a correct, of which b in the right place".
The major problem is that I don't check whether a colour has already been tested and with what kind of result:
- not present > ignore for the rest of this turn,
- present, wrong place > ignore unless you find one in the right place, then adjust score
- present, in the right place > ignore for the rest of this turn
I don't remember why I chose this system (I didn't know all Mastermind rules? Couldn't fit in a better one?).
With it's limitations I still think it's one of my better programs and fun to play (and a challenge if you use 10 places, 9 colours, possibility of one or more colours appearing more than once).

Playing your program with a slightly different set of rules should be fun too. I'm going to give it a try.
I've had a chance to look at your program now Dieter. Works great. I didn't clock them, but I think it feels faster than my routine as well. The use of the exponent to show the number of guesses is a very nice touch. Never thought of that.
You solve the problem of the double scores by not permitting multiple identical digits in the code. I think I have come up with a way to make my program Mastermind-proof, while retaining the option to use identically coloured pegs in the code. If I get it running I'll post it.
This program is based on Donald Knuth's paper The Computer as Master Mind.
It works only with 4 digits and the 6 colours 0-5.

The following formula to count the total number of misses is used:
\[ \max(n_1-n_1', 0)+\max(n_2-n_2', 0)+\ldots+\max(n_6-n_6', 0) \]
From this value the number of "black hits" is subtracted to get the number of "white hits".

Usage

Generate Code

[B]

Check Test Pattern

1 ENTER
2 ENTER
3 ENTER
4 [A]


Result

1.2

Code:
LBL A
STO .0  R↓
STO .1  R↓
STO .2  R↓
ST0 .3
CL∑
1
RCL 6  GSB 0
RCL 7  GSB 0
RCL 8  GSB 0
RCL 9  GSB 0
CHS
RCL .0  GSB 0
RCL .1  GSB 0
RCL .2  GSB 0
RCL .3  GSB 0
4
RCL 0  GSB 1
RCL 1  GSB 1
RCL 2  GSB 1
RCL 3  GSB 1
RCL 4  GSB 1
RCL 5  GSB 1
0
RCL 6  RCL .0  GSB 2
RCL 7  RCL .1  GSB 2
RCL 8  RCL .2  GSB 2
RCL 9  RCL .3  GSB 2
-
LSTx
x<>y
10
÷
+
RTN
LBL 0
STO I
R↓
STO+ (i)
RTN
LBL 1
x<0
CLx
-
RTN
LBL 2
x=y
GTO 3
R↓
R↓
RTN
LBL 3
R↓
R↓
1
+
RTN
LBL B
GSB 4  STO 6  CLx
GSB 4  STO 7  CLx
GSB 4  STO 8  CLx
GSB 4  STO 9  CLx
RTN
LBL 4
RAN#
6
×
INT
RTN

Well, not half as fancy as Dieter's solution but maybe you find the approach still interesting.

(04-28-2018 07:23 PM)pier4r Wrote: [ -> ]Did anyone create some "computer opponent" on calculators for the game? So an heuristic search for solutions.

Not sure if that's what you are looking for but in the linked paper Donald Knuth proves that the codebreaker can always succeed in five moves or less.

Cheers
Thomas
(04-30-2018 07:29 PM)Rogier Wrote: [ -> ]… The minor problem is the double scoring of digits of a correct colour AND in the right place. That could easily be solved (multiply by 10 and subtract from the total of correct digits) … I don't check whether a colour has already been tested and with what kind of result …

A modest suggestion: go ahead and score the color twice, irrespective of the correct position using the 1's digit BUT score the correct position(s) by adding nine to the score rather than ten. That is to say, score the colors first with sums of 1-digit in the one's column and then score the position second with sums of the 9-digit in the one's column.
Four color example:
a) 3 correct colors = 3
b) 1 correct position = 9
c) 3 + 9 = 12
d) 1 correct color in correct position, 2 correct colors in wrong position

Make sense? Give it a go!

[attachment=6155]
example work flow
BEST!
SlideRule
(07-23-2018 01:14 AM)Thomas Klemm Wrote: [ -> ]This program is based on Donald Knuth's paper The Computer as Master Mind.
It works only with 4 digits and the 6 colours 0-5.
...

Not sure if that's what you are looking for but in the linked paper Donald Knuth proves that the codebreaker can always succeed in five moves or less.

Cheers
Thomas

I read with interest all your interventions in all your posts for this thread.
Thanks for the link, Thomas Klemm.

So, I propose to everyone, the program I wrote for the HP11C.

Be assured, this is one of my achievements that I did not do in one step. This program indeed required several phases spread over several calculators. One of my last versions, among the most successful, was intended for the HP12C and works without the use of the indirect addressing mode on the registers.

I note with pleasure (and I reassure myself) by noting that my successive versions were indeed in accordance with the principles formulated in the document published by Donald E. Knuth.

So, this version gives the possibility to choose the size of the code to find (4 or 5 digits, for example) and the number of distinct colors that can be used (from 1 to 9) to compose the code.

Here is how to use it :

On LBL A, you choose the number of digits in the code : 4 or 5
On LBL B, you give the number of colors : 6 or 9
On LBL C, you enter the number of authorized trials before the calculator reveals the code if you have not yet discovered it (usually 6 or 12, but personally I choose 99)

Compose GSB D to prepare the code
Key in 4 or 5 digits and press GSB E (or R/S) to examine a proposition

The return format is c1c2c3c4c5.BW where c1c2c3c4c5 is your try, B the number of Black positions and W the number of White positions

Code:

001 -  f  LBL  E
002 -  STO  2
003 -  STO  4
004 -  EEX
005 -  STO + 0
006 -  GSB  C
007 -  RCL  0
008 -  f  x > y
009 -  GTO  6
010 -  g  CLx 
011 -  STO  7
012 -  STO  8
013 -  RCL  1
014 -  STO  3
015 -  GSB  A
016 -  10^x
017 -  STO ÷ 3
018 -  STO ÷ 4
019 -  f  LBL  1
020 -  RCL  4
021 -  g  x = 0
022 -  GTO  2
023 -  RCL  5
024 -  STO x 3
025 -  STO x 4
026 -  RCL  3
027 -  g  INT
028 -  STO - 3
029 -  RCL  4
030 -  g  INT
031 -  STO - 4
032 -  f  x = y
033 -  GTO  3
034 -  10^x
035 -  STO + 8
036 -  x ↔ y
037 -  10^x
038 -  STO + 7
039 -  GTO  1
040 -  f  LBL  3
041 -  RCL  5
042 -  1/x
043 -  STO + 2
044 -  GTO  1
045 -  f  LBL  2
046 -  GSB  B
047 -  STO  I  
048 -  10^x
049 -  STO ÷ 7
050 -  STO ÷ 8
051 -  f  LBL  5
052 -  RCL  7
053 -  g  INT
054 -  STO - 7
055 -  RCL 8
056 -  g  INT
057 -  STO - 8
058 -  f  x > y
059 -  x ↔ y
060 -  RCL  5
061 -  STO x 7
062 -  STO x 8
063 -  g  x^2
064 -  1/x
065 -  x
066 -  STO + 2
067 -  f  DSE
068 -  GTO  5
069 -  RCL  0
070 -  RCL  2
071 -  g  RTN
072 -  f  LBL  6
073 -  RCL  1
074 -  RCL  0
075 -  EEX
076 -  4
077 -  ÷
078 -  +
079 -  CHS
080 -  f  FIX  4
081 -  g  RTN
082 -  f  LBL  D
083 -  f  FIX  2
084 -  f  CLEAR  Σ
085 -  GSB  A
086 -  STO  I  
087 -  f  LBL  0
088 -  EEX
089 -  1
090 -  STO  5
091 -  STO  x  1
092 -  GSB  B
093 -  f  RAN#
094 -  x
095 -  EEX
096 -  +
097 -  g  INT
098 -  STO + 1
099 -  g  CLx
100 -  f  DSE
101 -  GTO  0
102 -  x
103 -  f  LBL  A
104 -  5
105 -  g  RTN
106 -  f  LBL  B
107 -  9
108 -  g  RTN
109 -  f  LBL  C
110 -  1
111 -  2
112 -  g  RTN

P-00  r- ,2
112 lines


Example of use :

0.123 STO f RAN#
GSB D
--> 5.00

(see RCL 1 with 26829)

22689 R/S (or GSB E)
--> 22689.23

22222 R/S
--> 22222.20

26829 R/S
--> 26829.50
x ↔ y
--> 3.00 so you win in 3 tries !!
Reference URL's