The aim of the game is to discover the code made up of four 'pegs' randomly selected from 6 possible colours. To place your guess, first click on the colour you want, then click on the black square at the foot of the column you wish to place it in. When you have completed a row, a score will appear on the left. Each black dot means you have a peg of the right colour in the right place. Each white dot means you have the right colour in the wrong place. Until you complete a row, you can overwite a peg which you have already placed with a different colour. The game ends when your guess is correct or your 9th attempt is wrong. Immediately, the correct code replaces the grey circles at the top. Also a button appears inviting you to play another game. Solving the puzzle in less than 5 tries is excellent (or lucky!); 5 or 6 is good; more than 6 suggests that your logic could be improved..
from math import pi
from random import randint
from pyodide import create_proxy
from js import document
global clrsel,guess,rownum
canvas = document.getElementById("ctx")
ctx = canvas.getContext("2d")
top = 100
ls = 30
lp = 160
hlft = 134 # hidden code dimensions
htop = 16
hw = 232
hh = 52
hth = 1
hcx = 160
hco = 60
hcy = 42
hcr = 20
phy = hcy + hco
bdr = 4 # width of border
rows = 9 # layout
pegsperrow = 4
wht = '#fff' # colours
blk = '#000'
red = '#f00'
yel = '#fd0'
grn = '#0c2'
blu = '#06f'
colours = [wht,blk,red,yel,grn,blu]
mgr = '#aaa'
bgc = '#ccf'
scr = 3 # score hole dimensions
scth = 2
phr = 8 # peg hole radius
pcx = 40 # piece colour location
pcy = 690
prl = 24
rownum = 0
guess = [-1,-1,-1,-1]
###
def assess():
global clrsel,endofgame,guess,rownum
gf = [0,0,0,0,0,0] # calculate color frequencies in guess
for n in guess:
gf[n] += 1
wf = [0,0,0,0,0,0]
for i in range(len(gf)): # determine total hits
if gf[i]<=cf[i]: wf[i] = gf[i]
else: wf[i] = cf[i]
tp = 0
for n in wf:
tp = tp + n
bp = 0 # determine number of black pegs
for i in range(pegsperrow):
if guess[i]==code[i]: bp += 1
wp = tp - bp # & white pegs
for i in range(wp): # display pegs
circle(4*ls-i*ls,phy+rownum*60,6,wht)
for i in range(bp):
circle(ls+i*ls,phy+rownum*60,6,blk)
guess = [-1,-1,-1,-1]
rownum += 1
if bp==pegsperrow:
reveal(code)
nwg.classList.remove("hide")
endofgame = True
###
def clickwht(event):
global clrsel, endofgame
if clrsel==-1 and not endofgame:
clrsel = 0
circle(pcx,pcy,prl,wht)
###
def clickblk(event):
global clrsel, endofgame
if clrsel==-1 and not endofgame:
clrsel = 1
circle(pcx+hco,pcy,prl,blk)
###
def clickred(event):
global clrsel, endofgame
if clrsel==-1 and not endofgame:
clrsel = 2
circle(pcx+2*hco,pcy,prl,red)
###
def clickyel(event):
global clrsel, endofgame
if clrsel==-1 and not endofgame:
clrsel = 3
circle(pcx+3*hco,pcy,prl,yel)
##
def clickgrn(event):
global clrsel, endofgame
if clrsel==-1 and not endofgame:
clrsel = 4
circle(pcx+4*hco,pcy,prl,grn)
###
def clickblu(event):
global clrsel, endofgame
if clrsel==-1 and not endofgame:
clrsel = 5
circle(pcx+5*hco,pcy,prl,blu)
###
def clickc0(event):
global clrsel,guess,rownum
if clrsel>-1:
circle(hcx,phy+rownum*hco,hcr,clrsel)
circle(pcx+clrsel*hco,pcy,prl+1,bgc)
guess[0] = clrsel
if -1 not in guess:
assess()
clrsel = -1
###
def clickc1(event):
global clrsel,guess,rownum
if clrsel>-1:
circle(hcx+hco,phy+rownum*hco,hcr,clrsel)
circle(pcx+clrsel*hco,pcy,prl+1,bgc)
guess[1] = clrsel
if -1 not in guess:
assess()
clrsel = -1
###
def clickc2(event):
global clrsel,guess,rownum
if clrsel>-1:
circle(hcx+2*hco,phy+rownum*hco,hcr,clrsel)
circle(pcx+clrsel*hco,pcy,prl+1,bgc)
guess[2] = clrsel
if -1 not in guess:
assess()
clrsel = -1
###
def clickc3(event):
global clrsel,guess,rownum
if clrsel>-1:
circle(hcx+3*hco,phy+rownum*hco,hcr,clrsel)
circle(pcx+clrsel*hco,pcy,prl+1,bgc)
guess[3] = clrsel
if -1 not in guess:
assess()
clrsel = -1
###
def circle(x,y,r,clr):
ctx.beginPath()
ctx.arc(x, y, r, 0, 2 * pi)
ctx.fillStyle = clr
ctx.fill()
###
def end():
global clrsel
nwg.classList.remove("hide")
clrsel = -2
ctx.font = "30px Arial";
ctx.fillText(clrsel, 10, 550);
###
def getcode():
lc = len(colours) - 1
code = [randint(0,lc), randint(0,lc), randint(0,lc), randint(0,lc)]
cf = [0,0,0,0,0,0]
for n in code:
cf[n] += 1
return code, cf
###
def hidden():
ctx.beginPath(); # hidden code rectangle
ctx.rect(hlft,htop,hw,hh);
ctx.stroke();
for i in range(pegsperrow): # hidden code circles
ctx.beginPath()
ctx.arc(hcx+i*hco, hcy, hcr, 0, 2 * pi)
ctx.fillStyle = mgr
ctx.fill()
###
def holesscr():
for i in range(rows): # score holes
for j in range(pegsperrow):
ctx.beginPath()
ctx.arc(ls+j*ls,phy+i*hco, scr, 0, 2 * pi)
ctx.stroke()
###
def holespeg():
for i in range(rows): # peg holes
for j in range(pegsperrow):
ctx.beginPath()
ctx.arc(hcx+j*hco, phy+i*hco, phr, 0, 2 * pi)
ctx.fillStyle = blk
ctx.fill()
###
def newgame(event):
nwg.classList.add("hide")
ctx.fillStyle = bgc
ctx.fillRect(2,2,576,736)
init()
###
def reveal(code):
for i in range(pegsperrow):
circle(hcx+i*hco,hcy,hcr,colours[code[i]])
###
def init():
global cf, clrsel, code, endofgame, guess
global rownum, textsur
endofgame = False
code, cf = getcode()
clrsel = -1
rownum = 0
guess = [-1,-1,-1,-1]
hidden() # board layout
holesscr()
holespeg()
##
init()
click_proxy = create_proxy(newgame)
nwg = document.getElementById("ng")
nwg.addEventListener("click",click_proxy)
click_proxy = create_proxy(clickc0)
document.getElementById("c0").addEventListener("click",click_proxy)
click_proxy = create_proxy(clickc1)
document.getElementById("c1").addEventListener("click",click_proxy)
click_proxy = create_proxy(clickc2)
document.getElementById("c2").addEventListener("click",click_proxy)
click_proxy = create_proxy(clickc3)
document.getElementById("c3").addEventListener("click",click_proxy)
click_proxy = create_proxy(clickwht)
document.getElementById("bwht").addEventListener("click",click_proxy)
click_proxy = create_proxy(clickblk)
document.getElementById("bblk").addEventListener("click",click_proxy)
click_proxy = create_proxy(clickred)
document.getElementById("bred").addEventListener("click",click_proxy)
click_proxy = create_proxy(clickyel)
document.getElementById("byel").addEventListener("click",click_proxy)
click_proxy = create_proxy(clickgrn)
document.getElementById("bgrn").addEventListener("click",click_proxy)
click_proxy = create_proxy(clickblu)
document.getElementById("bblu").addEventListener("click",click_proxy)