# Adapted by AgentCalc from Maelan Gallais Minesweeper (MIT). See README.md.
from kandinsky import fill_rect as fr,draw_string as ds
from ion import keydown as kd
from random import randint as rd
from time import sleep as sl,monotonic as mn

slct,itfc=(0,255,0),(255,181,59)
bk,wh,bw=(0,)*3,(255,)*3,(200,)*3
bl,re,gr=(0,0,255),(255,0,0),(0,200,0)
flpa=[[0,0,0,2,2,0,0,0],[0,2,2,2,2,0,0,0],[2,2,2,2,2,0,0,0],[0,2,2,2,2,0,0,0],[0,0,0,2,2,0,0,0],[0,0,0,0,1,0,0,0],[0,0,0,0,1,0,0,0],[0,0,1,1,1,1,0,0],[1,1,1,1,1,1,1,1],[1,1,1,1,1,1,1,1]]
mnpa=[[0,0,0,0,1,1,0,0,0,0],[0,0,1,0,0,0,0,1,0,0],[0,1,0,1,1,1,1,0,1,0],[0,0,1,1,0,0,1,1,0,0],[0,0,1,0,1,1,0,1,0,0],[0,0,1,0,1,1,0,1,0,0],[0,0,1,1,0,0,1,1,0,0],[0,1,0,1,1,1,1,0,1,0],[0,0,1,0,0,0,0,1,0,0],[0,0,0,0,1,1,0,0,0,0]]

posX=[(12*i)+5 for i in range(26)]
posY=[4+20*i for i in range(11)]
dspl=[[0]*11 for i in range(26)]
dfct=[[10,15],[15,20],[20,25]]
w,h,nd=10,18,0

def spawn(x,y):
 spx,spy=rd(0,25),rd(0,10)
 if dspl[spx][spy]==0:dspl[spx][spy]=1 
 else:spawn(x,y)
def flag(x,y):
 for a in range(10):
  for b in range(8):
   if flpa[a][b]==1:fr(posX[x]+1+b,posY[y]+4+a,1,1,bk)
   elif flpa[a][b]==2:fr(posX[x]+1+b,posY[y]+4+a,1,1,re)
def mine(x,y):
 for a in range(10):
  for b in range(10):
   if mnpa[a][b]==1:fr(posX[x]+b,posY[y]+4+a,1,1,bk)
def win():
 global nd,game
 cv,er=0,0
 for a in range(26):
  for b in range(11):
   if dspl[a][b]==0:cv+=1
   elif dspl[a][b]==3:er+=1
 if cv==0 and er==0:
  tf=mn()
  for a in range(26):
   for b in range(11):
    if dspl[a][b] in [1,4]:fr(posX[a],posY[b],w,h,gr),mine(a,b),sl(0.1)
  fr(90,47,140,28,bk),ds("You win!",95,52,gr)
  fr(70,85,180,28,bk),ds("Level "+str(nd+1)+" cleared!",75,90,bl)
  if nd<2:nd+=1
  fr(65,123,190,28,bk),ds("Next level: "+str(nd+1),70,128,re)
  tm=len(str(round(tf-t)))*5
  fr(90-tm,163,140+tm*2,28,bk),ds("Time: "+str(int(round(tf-t)))+"s !",95-tm,168,itfc)
  while True:
   if kd(4):break
  game=False
def lose():
 global game
 for a in range(26):
  for b in range(11):
   if dspl[a][b]==0:fr(posX[a],posY[b],w,h,bk)
   elif dspl[a][b]==1:fr(posX[a],posY[b],w,h,re),mine(a,b),sl(0.05)
   elif dspl[a][b]==4:fr(posX[a],posY[b],w,h,gr),mine(a,b),sl(0.05)
 while True:
  if kd(4):break
 game=False
def scan(x,y,c=0,d=0):
 ba=0
 for a in range(-1,2):
  for b in range(-1,2):
   bx,by=x+a,y+b
   if bx<0 or by<0:continue
   elif bx>25 or by>10:continue
   if dspl[bx][by] in [1,4]:ba+=1
 if c==0:c1,c2=wh,((ba-1)*36,(ba-1)%3*80,255-(ba-1)*36)
 elif c==1:c1,c2=slct,slct
 if ba==0:fr(posX[x],posY[y],w,h,c1)
 else:ds(str(ba),posX[x],posY[y],c2)
 if d==1:dspl[x][y]=2
 if d==1 and ba==0:
  for a in range(-1,2):
   for b in range(-1,2):
    bx,by=x+a,y+b
    if bx<0 or by<0:continue
    elif bx>25 or by>10:continue
    if dspl[bx][by]==0:
     scan(bx,by,0,1)
     dspl[bx][by]=2

while True:
 fr(0,0,320,222,bw),fr(0,0,5,222,itfc),fr(315,0,5,222,itfc),fr(0,0,320,4,itfc)
 for i in range(1,len(posX)):fr(posX[i]-2,4,2,218,bk)
 for i in range(1,len(posY)):fr(5,posY[i]-2,310,2,bk)
 dspl=[[0]*11 for i in range(26)]
 game,new,first,p=True,True,True,False
 px,py,x,y,t=13,5,13,5,mn()
 while game:
  if p:
   if kd(4):
    while kd(4):sl(0.01)
    p=False
    t+=mn()-pt
    new=True
    fr(0,0,320,222,bw),fr(0,0,5,222,itfc),fr(315,0,5,222,itfc),fr(0,0,320,4,itfc)
    for i in range(1,len(posX)):fr(posX[i]-2,4,2,218,bk)
    for i in range(1,len(posY)):fr(5,posY[i]-2,310,2,bk)
    for a in range(26):
     for b in range(11):
      if dspl[a][b]==2:scan(a,b)
      elif dspl[a][b] in [3,4]:fr(posX[a],posY[b],w,h,wh),flag(a,b)
   else:sl(0.01)
   continue
  if new:
   new=False
   if dspl[px][py] in [3,4]:fr(posX[px],posY[py],w,h,wh),flag(px,py)
   elif dspl[px][py]==2:scan(px,py)
   else:fr(posX[px],posY[py],w,h,bw)
   fr(posX[x],posY[y],w,h,slct)
   if dspl[x][y] in [3,4]:flag(x,y)
   elif dspl[x][y]==2:scan(x,y,1)
   if p:fr(0,0,320,222,bk)
   sl(0.06),win()
  if kd(0):
   px,py,new=x,y,True
   if x>0:x-=1
  elif kd(1):
   px,py,new=x,y,True
   if y>0:y-=1
  elif kd(2):
   px,py,new=x,y,True
   if y<10:y+=1
  elif kd(3):
   px,py,new=x,y,True
   if x<25:x+=1
  elif kd(16):
   if dspl[x][y] in [0,1]:
    dspl[x][y]+=3
    flag(x,y)
   elif dspl[x][y] in [3,4]:dspl[x][y]-=3
   new=True
   while kd(16):sl(0.01)
  elif kd(17):
   if first:
    first=False
    for a in range(-1,2):
     for b in range(-1,2):
      bx,by=x+a,y+b
      if bx<0 or by<0:continue
      elif bx>25 or by>10:continue
      dspl[bx][by]=2
    for i in range(rd(dfct[nd][0],dfct[nd][1])*(26*11)//100):spawn(x,y)
    for a in range(-1,2):
     for b in range(-1,2):
      bx,by=x+a,y+b
      if bx<0 or by<0:continue
      elif bx>25 or by>10:continue
      scan(bx,by,0,1)
   if dspl[x][y]==1:lose()
   elif dspl[x][y]==0:
    new=True
    scan(x,y,0,1)
   elif dspl[x][y]==2:
    ba,da=0,0
    for a in range(-1,2):
     for b in range(-1,2):
      bx,by=x+a,y+b
      if bx<0 or by<0:continue
      elif bx>25 or by>10:continue
      if dspl[bx][by] in [1,4]:ba+=1
      if dspl[bx][by] in [3,4]:da+=1
    if ba==da:
     for a in range(-1,2):
      for b in range(-1,2):
       bx,by=x+a,y+b
       if bx<0 or by<0:continue
       elif bx>25 or by>10:continue
       if dspl[bx][by]==1:lose()
       elif dspl[bx][by]==0:
        scan(bx,by,0,1)
        dspl[bx][by]=2
     new=True
   while kd(17):sl(0.01)
  elif kd(12):game,nd=False,0
  elif kd(13):game,nd=False,1
  elif kd(14):game,nd=False,2
  elif kd(4):
   p,pt=True,mn()
   fr(0,0,320,222,bk)
   ds("Paused - OK to resume",55,100,wh,bk)
   while kd(4):sl(0.01)
