Plz Help with this runtime error:_tkinter.TclError: item "12" doesn't exist

Here is the script

import turtle
import math

def main():
print("myrobot sv1 lets go")

SnapDistance = 5
RotationGuideTicks = 24
wn = turtle.Screen()
wn.bgcolor("lightgrey")
wn.setup(900,650)
shp = ((-10, 0), (10, 0), (0, 0), (0, 10), (0, -10), (0, 0))
wn.register_shape("cross", shp)

# some string colors
TBLACK = '\033[30m'
TRED = '\033[31m'
TGREEN = '\033[32m'
TYELLOW = '\033[33m'
TBLUE = '\033[34m'
TPURPLE = '\033[35m'
TCYAN = '\033[36m'
TWHITE = '\033[37m'
ENDC = '\033[m'

class workspaces:

def __init__(self, scrn):
self.workspaces = {}
self.scrn = scrn
self.activeworkspace = None
[self.tt](http://self.tt) = turtle.Turtle()
self.tt.hideturtle()
self.tt.pensize(2)
self.tt.speed(0)
h = self.scrn.window_height()
w = self.scrn.window_width()
self.stop = (h-22)/2
self.xside = (w-22)/2
self.mbox = ((-self.xside, self.stop),(self.xside, self.stop),(self.xside, self.stop-20),(-self.xside, self.stop-20))
self.lastmenutxt = "Welcome"
self.drawmbox()

def appendworkspace(self, ws):
self.workspaces[[ws.name](http://ws.name)] = ws
print("appendworkspace ws ", ws, " workspaces ",self.workspaces)
#input("adding ws")

def setactiveworkspace(self, name):
ws = self.getworkspace(name)
print("setactiveworkspace name {0} ws {1} ws=None {2}\n wkspcs {3}".format(name, ws, ws==None, self.workspaces))
if ws == None:
return
self.activeworkspace = ws
ws.displayworkspace()

def getworkspace(self, name=None):
"""Return named workspace, if name = None return activeworkspace"""
if name == None:
return self.activeworkspace
else:
return self.workspaces.get(name, None)

def drawmbox(self):
self.tt.penup()
self.tt.color("black","darkblue")
x,y = self.mbox[0]
self.tt.goto(x,y)
self.tt.pendown()
self.tt.begin_fill()
for i in range(1,4):
x,y = self.mbox[i]
self.tt.goto(x,y)
self.tt.end_fill()
self.tt.penup()
x,y = self.mbox[3] #position for write
self.tt.goto(x+1,y-2)
self.tt.color("white")
self.tt.write(self.lastmenutxt, font=("Arial", 16, "normal"))

def write_menu(self, txt):
self.tt.undo()
self.tt.write(txt, font=("Arial", 14, "normal"))
self.lastmenutxt = txt

def redrawmenu(self):
self.drawmbox()
self.write_menu(self.lastmanutxt)

class workspace:

def __init__(self, name, item, wkspcs):
[self.name](http://self.name) = name
self.item = item
self.workspaces = wkspcs
self.workspaces.appendworkspace(self)

def displayworkspace(self):
self.workspaces.scrn.clear()
self.workspaces.scrn.bgcolor(self.item.bgcolor)
self.workspaces.drawmbox()
self.item.displayme()

class playground:
"""this is the robots playground"""
def __init__(self, w, bgcolor="lightgrey"):
self.scrn = w
[self.tt](http://self.tt) = turtle.Turtle()
self.tt.hideturtle()
self.tt.pensize(2)
self.tt.speed(0)
self.seltt = turtle.Turtle()
self.seltt.hideturtle()
self.seltt.pensize(2)
self.seltt.speed(0)
self.seltt.penup()
self.mkrtt = turtle.Turtle()
self.mkrtt.hideturtle()
self.mkrtt.pensize(2)
self.mkrtt.speed(0)
self.mkrtt.penup()
self.mkrtt2 = turtle.Turtle()
self.mkrtt2.hideturtle()
self.mkrtt2.pensize(2)
self.mkrtt2.speed(0)
self.mkrtt2.penup()
self.bgcolor = bgcolor
self.obstacles = []
self.robots = {}
self.selectedobs = None
self.lastloadfn = ""
self.lastsavefn = ""
"""
h = self.scrn.window_height()
w = self.scrn.window_width()
self.stop = (h-22)/2
self.xside = (w-22)/2
self.mbox = ((-self.xside, self.stop),(self.xside, self.stop),(self.xside, self.stop-20),(-self.xside, self.stop-20))
self.drawmbox()
"""

def __str__(self):
rslt = "playg: scrn {0} tt {1} seltt {2} obs {3} rbots {4}"
rslt = rslt.format(self.scrn, [self.tt](http://self.tt), self.seltt, self.obstacles, self.robots)
return rslt

def displayme(self):
self.scrn.bgcolor(self.bgcolor)
for o in self.obstacles:
o.drawme()
"""
def drawmbox(self):
self.tt.penup()
self.tt.color("black","darkblue")
x,y = self.mbox[0]
self.tt.goto(x,y)
self.tt.pendown()
self.tt.begin_fill()
for i in range(1,4):
x,y = self.mbox[i]
self.tt.goto(x,y)
self.tt.end_fill()
self.tt.penup()
x,y = self.mbox[3] #position for write
self.tt.goto(x+1,y-2)
self.tt.color("white")
self.tt.write("Welcome",font=("Arial", 16, "normal"))

def write_menu(self, txt):
self.tt.undo()
self.tt.write(txt, font=("Arial", 16, "normal"))
"""

def selectobs(self, x,y):
for ob in self.obstacles:
xhi, xlo = ob.range[0]
yhi, ylo = ob.range[1]
print("selectobs ----\n x {0} y {1} xhi {4} xlo {5} yhi {6} ylo {7} range {2} issel {3}".format(x,y,ob.range, ob.isselected, xhi, xlo, yhi, ylo))
if x <= xhi and x >= xlo and y <= yhi and y >= ylo:
if self.selectedobs != None:
self.selectedobs.setselected(False, self.seltt)
print(f" test setting ondrag for seltt {self.seltt})\n seltt.onftsg= {self.seltt.ondrag}")
self.seltt.ondrag(None)
self.seltt.ondrag(self.tt.goto)
ob.setselected(True, self.seltt)
self.selectedobs = ob
print("selectobs this is it ob ----\n", ob)

def saveplayg(self):
dflt = self.lastsavefn
if dflt == "":
dflt = self.lastloadfn
fn = getfilename(dflt, "save", ".obs")
if fn != None:
print("saving obs to ", fn)
fo = open(fn, "w")
for o in pg.obstacles:
s = "obstacle\n"
fo.write(s)
s = "border_color=" + o.border_color + "\n"
fo.write(s)
s = "fill_color=" + o.fill_color + "\n"
fo.write(s)
s = "border_size=" + str(o.border_size) + "\n"
fo.write(s)
s = "poly=" + str(o.poly) + "\n"
fo.write(s)
fo.close()
self.lastsavefn = fn
print("Leaving saveplayg")

def loadplayg(self):
dflt = self.lastloadfn
if dflt == "":
dflt = self.lastsavefn
fn = getfilename(dflt, "load", ".obs")
if fn != None:
fi = open(fn, "r")
while True:
s = fi.readline()
if len(s) == 0:
break
l = s.split("=")
if l[0] == "obstacle":
pass
if l[0] == "fill_color":
fc = str(l[1])
if l[0] == "border_color":
bc = str(l[1])
if l[0] == "border_size":
bz = int(l[1])
if l[0] == "poly":
print("from obs l[1] {6} bc {0} tytpe(bc) {1} fc {2} type(fc) {3} bz {4} type(bz) {5}".format(bc,type(bc),fc,type(fc),bz,type(bz), l[1]))
p = strtopoly(l[1])
print("load poly ", p)
x,y = p[0]
o = obstacle(x, y, wn, pg, obstacle.begin_obs, "red", "green",bz)
o.setpoly(p)
o.drawme()
pg.obstacles.append(o)
fi.close
self.lastloadfn = fn
print("loaded obses")

"""
wss = workspaces(wn)
pg = playground(wn)
wb = workbench(wn)
wspg = workspace("playground", pg, wss)
wswb = workspace("workbench", wb, wss)
print("playg ",pg)
"""
def pushnewbot(mnu):
wss.setactiveworkspace("workbench")
mn.pushmenu(mnu)

def pushobsselect(mnu):
wss.setactiveworkspace("playground")
wn.onclick(pg.selectobs)
print("-->SETTING wn.onclick to selectobs in pushobsselect")
mn.pushmenu(mnu)

def dosaveplayg(mnu):
pg.saveplayg()
mn.armkeys(mnu)

def doloadplayg(mnu):
pg.loadplayg()
mn.armkeys(mnu)

class workbench:
"""a place to build and modify robots"""

gridcoord = ()
gridtopleft = ()

def __init__(self,scrn, bgcolor="beige"):
self.scrn = scrn
self.bgcolor = bgcolor
[self.tt](http://self.tt) = turtle.Turtle()
self.tt.pensize(2)
self.tt.speed(0)
self.tt.penup()
# self.tt.hideturtle()
self.gridxs = []
self.gridys = []

"""
def showbuildgrid(self):
self.showbuildgridz()
input("lets do it again")
self.tt.clear()
self.showbuildgridz()
"""

def showbuildgrid(self):
""" draw a grid to build robot on"""
self.vertlines = 20
self.horzlines = 32
self.linespacing = 10
workbench.gridtopleft = (-self.linespacing*self.vertlines/2, self.linespacing*self.horzlines/2)
self.tt.penup()
self.tt.goto(0, 0)
x, y = workbench.gridtopleft
self.tt.goto(x, y)
self.tt.goto(-x, y)
self.gridys = []
self.tt.showturtle()
self.tt.shape("cross")
self.tt.shapesize(2,2,5)
for i in range(self.horzlines + 2):
if i == 0 or i == 1 or i == self.horzlines + 1:
self.tt.pensize(3)
self.tt.color("blue")
else:
self.tt.pensize(1)
self.tt.pencolor("orange")
self.tt.penup()
self.tt.goto(x, y)
#input("leftside i "+ str(i))
self.tt.pendown()
self.tt.goto(-x, y)
if i == 0:
continue
#input("went right side pendown")
print("pos ", self.tt.position())
#input("x "+str(x)+ " y "+ str(y)+ " i "+ str(i))
self.gridys.append(y)
y -= self.linespacing
x, y = self.gridtopleft
self.gridxs = []
for i in range(self.vertlines + 1):
if i == 0 or i == self.vertlines:
self.tt.pensize(3)
self.tt.color("blue")
else:
self.tt.pensize(1)
self.tt.color("orange")
self.tt.penup()
self.tt.goto(x, y)
self.tt.pendown()
self.tt.goto(x, -y)
self.gridxs.append(x)
x += self.linespacing
workbench.gridcoord = (self.gridxs, self.gridys)
self.tt.penup()
self.tt.shape("circle")
self.tt.shapesize(.3, .3, .3)
self.tt.goto(0, 0)
self.tt.stamp()
self.tt.hideturtle()

def displayme(self):
self.showbuildgrid()

wss = workspaces(wn)
pg = playground(wn)
wb = workbench(wn)
wspg = workspace("playground", pg, wss)
wswb = workspace("workbench", wb, wss)
print("playg ",pg)

class obstacle:
"""a playground area robot cannot enter"""

@classmethod
def begin_obs(cls, x,y,sc=wn,p=pg):
print("begin_obs sc ", sc, " p ", p)
print("brgin_obs obstacles ", str(p.obstacles))
o = obstacle(x, y, p.scrn, p, obstacle.begin_obs)
print("obs poly ", o.poly)
#o.open()
o.startobs(x,y)

def __init__(self, x, y, w, pg, newofun,bcolor="red", fcolor="green", bsize=3):
self.poly = [(x,y)]
self.scrn = w
[self.tt](http://self.tt) = turtle.Turtle()
self.border_color = bcolor
self.fill_color = fcolor
self.border_size = bsize
self.playg = pg
self.newfun = newofun
self.range = ()
self.rangecentere = ()
self.isselected = False
self.rotatecenter = ()
self.tt.pensize(self.border_size)
self.tt.color(self.border_color, self.fill_color)
self.tt.speed(0)

def __str__(self):
rslt = "obstacle ----\n poly {0} scrn {1} tt {2} bord_clr {3} fill_clr {4} "
rslt = rslt.format(self.poly, self.scrn != None, [self.tt](http://self.tt) != None, self.border_color, self.fill_color)
rslt += "bord_size {0} playg {1} newfun {2} range {3} isseltd {4}\n"
rslt = rslt.format(self.border_size, self.playg, self.newfun,self.range,self.isselected)
return rslt

def setpoly(self, p):
self.poly = p
self.setrange()

def drawme(self):
first = True
self.tt.penup()
print("drawme poly\n ", self.poly)
idx = 0
for v in self.poly:
x,y = v
#print("drawme idx {3} x {0} y {1} v {2}".format(x, y, v, idx))
#input("new pt")
self.tt.goto(x, y)
if first:
self.tt.pendown()
self.tt.begin_fill()
first = False
idx += 1
#input("pdone")
self.tt.end_fill()
self.tt.penup()
self.tt.hideturtle()
if self.isselected:
self.setselected(False, self.playg.seltt)
self.setselected(True, self.playg.seltt)

def drawselection(self,clr, tt):
xhi, xlo = self.range[0]
yhi, ylo = self.range[1]
tt.clear()
tt.goto(xhi, yhi)
tt.color(clr)
tt.pendown()
tt.goto(xhi, ylo)
tt.goto(xlo, ylo)
tt.goto(xlo, yhi)
tt.goto(xhi,yhi)
tt.penup()
tt.hideturtle()

def setrange(self):
xmax =-9999
xmin = 9999
ymax = -9999
ymin = 9999
for v in self.poly:
x,y = v
if x > xmax:
xmax = x
if x < xmin:
xmin = x
if y > ymax:
ymax = y
if y < ymin:
ymin = y
self.range = ((xmax, xmin), (ymax, ymin))
self.rangecenter = ((xmax+xmin)/2, (ymax+ymin)/2)
print("setrange\n range {0}\n poly {1}".format(self.range, self.poly))

def setselected(self, selected, tt):
print("setselected ---- isselected will draw",selected, " tt ", tt)
if selected:
self.drawselection("black", tt)
self.isselected = True
print("setseleced ------activeitem ", menues.lastmenu.activeitem) ,
if menues.lastmenu.activeitem != None:
mname, k = menues.lastmenu.activeitem
print("----for activeitem mname= ", mname, " k= ", k)
if mname == "Obstacles" and k == "t":
print("----setting up translate drag")
x,y = self.poly[0]
tt.goto(x, y)
tt.shape("cross")
tt.shapesize(1,1,4)
print(".... tt ", tt)
tt.ondrag(tt.goto)
self.scrn.onclick(self.doxlate, 3, False)
print("-->SETTING wn.onclick to doxlate in setselected")
tt.showturtle()
print("----finished drag setup")
else:
if mname == "Obstacles" and k == "r":
print("----setting up rotaate sel center")
self.drawselection("blue", tt)
tt.shape("cross")
tt.shapesize(1,1,4)
tt.ondrag(tt.goto)
x,y = self.rangecenter
tt.goto(x, y)
self.scrn.onclick(None)
print("-->SETTING wn.onclick to None in setselected")
tt.onrelease(self.setrotationcenter)
self.scrn.onclick(self.getrotateangle, 3, False)
tt.showturtle()
else:
tt.clear()
self.isselected = False

def getrotateangle(self, x, y):
tt = self.playg.mkrtt
x, y = self.rotatecenter
self.drawrotateguide(x,y, 50,RotationGuideTicks,"darkblue",tt)
tt.showturtle()
tt.color("lightblue")
tt.goto(x, y)
tt.setheading(0)
tt.fd(65)
tt.penup()
tt.ondrag(self.dragangle)
tt.onrelease(self.showangle)
self.scrn.onclick(self.dorotate, 3, False)

def showangle(self, x, y):
tt = self.playg.mkrtt2
cx, cy = self.rotatecenter
tt.clear()
tt.penup()
tt.goto(cx, cy)
tt.pendown()
tt.goto(x, y)
tt.penup()

def dragangle(self, x,y):
tt = self.playg.mkrtt
tt.goto(x,y)
"""
tt2 = self.playg.mkrtt2
tt2.color("lightblue")
#tt2.clear()
cx, cy = self.rotatecenter
tt2.penup()
tt2.goto(cx,cy)
tt2.pendown()
tt2,goto(x,y)
"""

def dorotate(self, x, y):
print("dorotate----in\n ", self),
x,y = self.playg.mkrtt.position()
cx, cy = self.rotatecenter
da = math.atan2(y-cy, x-cx)
#print("dorotate----\n da {0} x,y ({1}, {2} ) cx,cy ({3}, {4})".format(math.degrees(da),x,y,cx,cy))
newpoly = []
for t in self.poly:
ox,oy = t
dox = ox - cx
doy = oy - cy
r = ((dox**2)+(doy**2))**.5
oa = math.atan2(doy, dox)
#print("dorotate ----\noa {0} r {1}".format(math.degrees(oa), r))
pt = (cx + r*math.cos(da+oa), cy + r*math.sin(da+oa))
newpoly.append(pt)
print("dorotate nrwpoly\n ", newpoly, " oldpoly\n ", self.poly)
self.setpoly(newpoly)
self.tt.clear()
self.drawme()
self.setselected(False, self.playg.seltt)
self.playg.seltt.clear()
self.playg.mkrtt.clear()
self.playg.mkrtt.hideturtle()
self.playg.mkrtt2.clear()
self.playg.scrn.onclick(self.playg.selectobs)

def setrotationcenter(self, x, y):
x,y = self.snaptopolypts(x ,y)
self.rotatecenter = (x, y)
self.drawrotateguide(x,y, 50,RotationGuideTicks,"orange",self.playg.mkrtt)
self.playg.mkrtt.ondrag(self.dragangle)

def snaptopolypts(self, x, y):
"""if x, y are witnin SnapDistance to poly vertex or range center return those pts else retuirn input x, y tuple"""
newx = x
newy = y
notfound = True
for pt in self.poly:
px, py = pt
if abs(px - x) <= SnapDistance and abs(py -y) <= SnapDistance:
newx = px
newy = py
notfound = False
break
if notfound:
px, py = self.rangecenter
if abs(px - x) <= SnapDistance and abs(py -y) <= SnapDistance:
newx = px
newy = py
return (newx, newy)

def doxlate(self, x, y):
print("doxlate----in ", self),
x,y = self.playg.seltt.position()
cx, cy = self.poly[0]
dx = x - cx
dy = y - cy
newpoly = []
for t in self.poly:
pt = (t[0]+dx, t[1]+dy)
newpoly.append(pt)
self.setpoly(newpoly)
self.tt.clear()
self.drawme()

def drawrotateguide(self, x, y, r, p, clr, t):
""" draw circle at x, y radius r with p tick marks using turtke t"""
print("drawrotateguide ---- x {0} y {1} clr {2}".format(x, y,clr))
t.reset()
t.speed(0)
t.hideturtle()
t.penup()
t.pensize(3)
t.color(clr)
t.goto(x,y-r)
t.pendown()
t.circle(r)
t.penup()
t.goto(x,y)
for i in range(p):
t.fd(0.95*r)
t.pendown()
if i%(p/4) == 0:
t.fd(0.15*r)
else:
t.fd(0.1*r)
t.penup()
t.goto(x,y)
t.right(360/p)
t.shape("cross")
t.shapesize(1,1,4)
t.pendown()
t.fd(1.3*r)
t.penup()
t.showturtle()

def endp(self, x, y):
print("endp enter x {0} y {1} poly {2}".format(x,y,self.poly))
x,y = self.poly[0]
self.tt.goto(x,y)
self.tt.end_fill()
self.tt.penup()
self.tt.hideturtle()
self.setrange()
self.playg.obstacles.append(self)
idx = 0
for o in self.playg.obstacles:
print("obs["+ str(idx) +"]", o)
idx += 1
#print("playg", len(self.playg.obstacles), self.playg)
self.scrn.onclick(self.newfun)
print("-->SETTING wn.onclick to ", self.newfun, " s in pushobsselect")
self.scrn.onclick(None, 3, True)
print("endp exit x {0} y {1} poly {2} me {3}".format(x,y,self.poly, str(self)))

def endl(self, x,y):
print("endl enter x {0} y {1} poly {2}".format(x,y,self.poly))
a,b = self.poly[len(self.poly)-1]
c=x
d=y
while abs(c-a)>0.0001 or abs(d-b)>0.0001:
self.tt.undo()
c,d = self.tt.position()
self.tt.penup()
self.tt.goto(a,b)
self.tt.pendown()
self.tt.goto(x,y)
self.poly.append((x,y))
print("endl exit x {0} y {1} poly {2}".format(x,y,self.poly))

def drag(self,x,y):
self.tt.goto(x,y)
print("have x {0} and y {1} dl [2]".format(x,y,dl))
self.scrn.onclick(None)
print("-->SETTING wn.onclick to None in drag")

def startobs(self, x, y):
print("startobs self {2} x {0} y {1}".format(x, y, self))
self.tt.penup()
self.tt.goto(x,y)
self.tt.pendown()
self.tt.begin_fill()
self.scrn.onclick(None)
print("-->SETTING wn.onclick to None in startobs")
self.tt.ondrag(self.drag)
self.scrn.onclick(self.endp, 3, False)
self.tt.onrelease(self.endl)
print("startp x {0} y {1} poly {2}".format(x,y,self.poly))

#def __str__(self):
#return "obs at {0} with {1} sides".format(self.poly[0],len(self.poly)-1)

"""
def begin_obs(x,y,sc=wn,p=pg):
print("brgin_obs obstacles ", str(p.obstacles))
o = obstacle(x, y, sc,p, begin_obs)
print("obs poly ", o.poly)
#o.open()
o.startobs(x,y)
"""

class robot:

texttt = turtle.Turtle()

@classmethod
def begin_bot(cls, sc=wn,p=pg):
print("begin_bot sc ", sc, " p ", p)
print("brgin_bot obstacles ", str(p.obstacles))
name = cls.getbotname()
r = robot(p.scrn, p, robot.begin_bot, name)
#print("obs poly ", o.poly)
#o.open()
r.startbot()

@classmethod
def getbotname(cls,):
actn = "New robot name"
prmt = "Enter your robot's name cannot be blank"
notvalid = True
while notvalid:
rn = turtle.textinput(actn, prmt)
if rn != None and rn != "":
notvalid = False
robot.texttt.speed(0)
robot.texttt.penup()
x, y = workbench.gridtopleft
rnlen = len(rn)
lbllen = len("My name is")
robot.texttt.goto(-8-rnlen*12/2, y+2)
robot.texttt.color("Brown")
robot.texttt.write(rn, font=("Arial", 18, "bold"))
robot.texttt.goto(8-lbllen*11/2, y+28)
robot.texttt.write("My name is", font=("Arial", 14, "normal"))
return rn

rn

def __init__(self, w, pg, newfun, name, bodycolor="blue"):
self.scrn = w
self.playg = pg
self.newfun = newfun
[self.name](http://self.name) = name
self.bodycolor = bodycolor
self.outlinecolor = bodycolor
self.location = (0,0)
self.bodypoly = []
self.driveaxelcenter = ()
self.wheeldiam = 0
self.heading = 0
[self.tt](http://self.tt) = turtle.Turtle()
self.tt.pensize(2)
self.tt.speed(0)
self.tt.shape("cross")
self.tt.shapesize(1,1,3)
self.tt.color(self.outlinecolor, self.bodycolor)
self.isonplayg = False

def startbot(self):
self.scrn.onclick(self.firstpt)
self.scrn.onclick(self.endrb, 3, False)
self.tt.begin_fill()
self.tt.penup()

def firstpt(self, x, y):
self.scrn.onclick(self.nextpt)
np = self.snaptobuildgrid(x, y)
self.bodypoly.append(np)
self.tt.goto(np)
self.tt.begin_fill()
self.tt.pendown()

def nextpt(self, x, y):
np = self.snaptobuildgrid(x, y)
self.bodypoly.append(np)
self.tt.goto(np)

def endrb(self, x, y):
self.tt.end_fill()
self.playg.robots[[self.name](http://self.name)] = self
self.scrn.onclick(None)
self.scrn.onclick(None, 3, False)

def snaptobuildgrid(self, x, y):
""" return the build grid coord closest to given x, y """
xords, yords = workbench.gridcoord
lastcx = xords[0]
lastdx = 9999999
for cx in xords:
dx = abs(x-cx)
if dx < lastdx:
lastdx = dx
lastcx = cx
else:
break
lastdy = 999999
for cy in yords:
dy = abs(y-cy)
if dy < lastdy:
lastdy = dy
lastcy = cy
else:
break
return (lastcx, lastcy)

class dropmenu:
""" build display and get result from a drop down list """
working = None

@classmethod
def getdropselection(cls, topleft, width, items, returnfun, sc=wn, itemheight=15):
cls.working = dropmenu(topleft, width, itemheight, returnfunm, sc)
cls.woking.showdrop(items)
cls.working.scrn.onclick(cls.working.checkclick)

def __init__(self, toplrft, width, itemheight, rtnfun, scrn):
self.topleft = topleft
self.width = width
self.scrn = scrn
self.returnfun = rtnfun
self.ysteps = []
self.itemheight = itemheight
[self.tt](http://self.tt) = turtle.Turtle()
self.tt.speed(0)
self.tt.penup()

def showdrop(self, items):
self.tt.penup()
self.tt.goto(self.topleft)
x, ytop = self.topleft
self.tt.pendown()
for i in range(len(items)):
self.tt.pendown()
self.tt.begin_fill()
self.tt.goto(x+self.width, ytop)
self.tt.goto(x+self.width, ytop-self.itemheight)
self.tt.goto(x, ytop-self.itemheight)
self.tt.goto(x.ytop)
self.tt.end_fill()
self.tt.penup()
self.tt.goto(x+1,ytop-self.itemheight+1)
self.tt.write(items[i], font=("Arial", 12, "normal"))
self.ysteps.append((ytop-1, ytop-self.itemheight+1), items[i])
ytop -= self.itemheight
self.tt.goto(x, ytop)

def checkclick(self,x,y):
xlo = self.topleft[0]
xhi = xlo + self.width
if x >= xlo and x <= xhi:
for yr in self.ysteps:
yhi, ylo = yr[0]
if y <= yhi and y >= ylo:
self.tt.clear()
self.returnfun(yr[1])

class menuitem:
""" holds each menu item
toggle; 0-= no toggle, -1 = each key event toggles between on (1) and off (-1)F"""

def __init__(self, key, desc, dsplorder, toggle, onkeyfun, onkeyprms, enfun=None, enprms=None, exfun=None, exprms=None):
msg = "menuitem {10} key {0} desc {1} order {2} tog {3} onkeyfun {4} onkeyprm {5} enfun {6} enprm {7} exfun {8} exprm {9}"
print(msg.format(key,desc,dsplorder,toggle,onkeyfun,onkeyprms,enfun,enprms,exfun,exprms,"En"))
self.key = key
self.desc = desc
self.dsplorder = dsplorder
self.enfun = enfun
self.enprms = enprms
self.exfun = exfun
self.exprms = exprms
self.toggle = toggle
self.onkeyfun = onkeyfun
self.onkeyprms = onkeyprms
print(msg.format(self.key,self.desc,self.dsplorder,self.toggle,self.onkeyfun,self.onkeyprms,self.enfun,self.enprms,self.exfun,self.exprms,"eX"))

def __str__(self):
rslt = "menuitem: key={0} des={1} dspidx={2} toggle {3}"
rslt = rslt.format(self.key, self.desc, self.dsplorder, self.toggle)
rslt += " onkeyfun={0} onkeyprms {1} enfun {2} enprms {3} exfun={4} exprms {5} "
return rslt.format(self.onkeyfun, self.onkeyprms, self.enfun, self.enprms, self.exfun, self.exprms)

class menues:
""" menu definition mlists is dict keyed by menue name with value as dict of menuitems"""

lastmenu = None
counter = 0

@classmethod
def cntr(cls):
cls.counter += 1
return cls.counter -1

def __init__(self, w, wss ):
self.wn = w
self.wss = wss
[self.tt](http://self.tt) = turtle.Turtle()
self.tt.hideturtle()
self.tt.penup()
self.mlists = {}
self.mstack = [0]
self.keyfuns = {}
self.activeitem = None
menues.lastmenu = self

def appendmenuitem(self, mnuname,mnuitem):
print("apmi mlists ", self.mlists)
print("apmi get", self.mlists.get(mnuname,{}), " mn ", mnuname)
self.mlists[mnuname] = self.mlists.get(mnuname,[{},[]])
self.mlists[mnuname][0][mnuitem.key] = mnuitem
self.mlists[mnuname][1] = self.ordermi(self.mlists[mnuname][0])

def ordermi(self, itms):
print("ordermi itms ", itms)
rslt = []
found = True
hiorder = 0
while found:
found = False
lastodr = 9999
lastk = ""
for v in itms.values():
if v.dsplorder > hiorder and v.dsplorder < lastodr:
lastodr = v.dsplorder
lastk = v.key
if lastk != "":
found = True
hiorder = lastodr
rslt.append(lastk)
return rslt

def pushmenu(self, mnuname):
print("pushmenu ", mnuname, "mstack ", self.mstack)
if len(self.mstack) < self.mstack[0] + 2:
self.mstack.append(None)
if self.mstack[0] > 0:
self.disarmkeys(self.mstack[self.mstack[0]])
self.mstack[0] += 1
self.mstack[self.mstack[0]] = mnuname
self.makemenu(mnuname)

def popmenu(self):
if self.mstack[0] > 0:
self.disarmkeys(self.mstack[self.mstack[0]])
self.mstack[0] -= 1
print("popmenu mstack ", self.mstack)
self.makemenu(self.mstack[self.mstack[0]])

def disarmkeys(self, mname):
print("disarming keys menu ", mname)
mo = self.mlists[mname][1]
for k in mo:
self.wn.onkey(None, k.lower())
self.wn.onkey(None, k.upper())

def armkeys(self, mname):
mo = self.mlists[mname][1]
msg = "\n keys set "
for k in mo:
self.wn.onkey(self.keyfuns[k][0], k.lower())
self.wn.onkey(self.keyfuns[k][1], k.upper())
msg += k + ", "
self.wn.listen()
print("armed keys menu ", mname, " ordr ", mo, msg )

def atest(self):
print("atest WHY?????")

def makemenu(self, mn):
print("makemenu[", menues.cntr(), "].....", mn)
md = self.mlists[mn][0]
mo = self.mlists[mn][1]
mtxt = mn + ": "
for k in mo:
itm = "<" + k + ">" +md[k].desc + " | "
print(" mkmu k {0} toggle {1}".format(k, md[k].toggle))
if md[k].toggle == 1:
itm = itm.upper()
print(" mkmu set upper itm", itm)
mtxt += itm
print(" mkmu mn=>" + mn + "<\n mtxt=>" + mtxt + "< \n toggle ", md[k].toggle)
self.wss.write_menu(mtxt)
self.armkeys(mn)

def showmenu():
PRINT()

def doonkey(self, k):
print("doonkey[", menues.cntr(), "].....k= ", k)
k = k.lower()
if self.activeitem != None:
mname, mkey = self.activeitem
print("Turning off activeitem ", self.activeitem)
self.activeitem = None
self.doonkey(mkey)
return
mnn = self.mstack[self.mstack[0]]
md = self.mlists[mnn][0]
mi = md[k]
print("doonkkey ----\n mi= {0}, \n mi.onkeyprms {1}".format(mi, mi.onkeyprms))
enex = mi.toggle
print(f"doonkey enex {enex} k {k}")
if enex == 0:
if mi.onkeyfun != None:
self.executefun(mi.onkeyfun, mi.onkeyprms)
if enex == -1:
if mi.enfun != None:
self.executefun(mi.enfun, mi.enprms)
mi.toggle = 1
self.activeitem = (mnn, k)
print(f"doonkey set toggle to {mi.toggle} enex {enex} k {k}")
if enex == 1:
if mi.exfun != None:
self.executefun(mi.exfun, mi.exprms)
mi.toggle = -1
self.activeitem = None
print(f"doonkey set toggle to {mi.toggle} enex {enex} k {k}")
self.makemenu(self.mstack[self.mstack[0]])

def executefun(self, fun, prmtuple):
print("Executefun fun= {0} prms= {1}".format(fun, prmtuple))
np = len(prmtuple)
if np == 0:
fun()
if np == 1:
fun(prmtuple[0])
if np == 2:
fun(onkeyprnd[0], onkeyprnd[1])
if np == 3:
fun(onkeyprnd[0], onkeyprnd[1], onkeyprnd[2])
if np > 3:
print("<<>>executefun action function {0} has {1} prms which is > 3".format(fun, np))

"""Define Key Event Functions"""

def ke_a():
mn.doonkey("a")

def ke_A():
mn.doonkey("A")

def ke_b():
mn.doonkey("b")

def ke_B():
mn.doonkey("B")

def ke_c():
mn.doonkey("c")

def ke_C():
mn.doonkey("C")

def ke_d():
mn.doonkey("d")

def ke_D():
mn.doonkey("D")

def ke_g():
mn.doonkey("g")

def ke_G():
mn.doonkey("G")

def ke_l():
print("ke_l hit")
mn.doonkey("l")

def ke_L():
mn.doonkey("L")

def ke_n():
mn.doonkey("n")

def ke_N():
mn.doonkey("N")

def ke_o():
mn.doonkey("o")

def ke_O():
mn.doonkey("O")

def ke_p():
mn.doonkey("p")

def ke_P():
mn.doonkey("P")

def ke_r():
mn.doonkey("r")

def ke_R():
mn.doonkey("R")

def ke_s():
mn.doonkey("s")

def ke_S():
mn.doonkey("S")

def ke_t():
print("ke_t hit")
mn.doonkey("t")

def ke_T():
mn.doonkey("T")

def ke_u():
mn.doonkey("u")

def ke_U():
mn.doonkey("U")

def ke_w():
mn.doonkey("w")

def ke_W():
mn.doonkey("W")

def buildmenus(wkspss):
mnu = menues(wn, wkspss)
mi = menuitem("p", "Playground", 1, 0, mnu.pushmenu, ("Playground",), None, None)
print("mi main p ", mi)
mnu.appendmenuitem("Main", mi)
mnu.keyfuns["p"] = (ke_p, ke_P)
mi = menuitem("r", "Robots", 2, 0, mnu.pushmenu, ("Robots",), None, None)
print("mi main r ", mi)
mnu.appendmenuitem("Main", mi)
mnu.keyfuns["r"] = (ke_r, ke_R)
mi = menuitem("l", "Load what", 5, 0, mnu.pushmenu, ("Load what",), None, (), None, None)
print("mi main l ", mi)
mnu.appendmenuitem("Main", mi)
mnu.keyfuns["l"] = (ke_l, ke_L)
mi = menuitem("s", "Save what", 6, 0, mnu.pushmenu, ("Save what",), None, (), None, None)
print("mi main s ", mi)
mnu.appendmenuitem("Main", mi)
mnu.keyfuns["s"] = (ke_s, ke_S)
mi = menuitem("o", "Obstacles", 1, 0, None, ("Save what",), None, (), None, None)
print("mi ld wt o ", mi)
mnu.appendmenuitem("Load what", mi)
mnu.keyfuns["o"] = (ke_o, ke_O)
mi = menuitem("r", "Robots", 2, 0, None, ("Save what",), None, (), None, None)
print("mi ld wt r ", mi)
mnu.appendmenuitem("Load what", mi)
mnu.keyfuns["r"] = (ke_r, ke_R)
mi = menuitem("a", "All", 3, 0, None, ("Save what",), None, (), None, None)
print("mi ld wt a ", mi)
mnu.appendmenuitem("Load what", mi)
mnu.keyfuns["a"] = (ke_a, ke_A)
mi = menuitem("o", "Obstacles", 1, 0, None, ("Save what",), None, (), None, None)
print("mi ld wt o ", mi)
mnu.appendmenuitem("Save what", mi)
mnu.keyfuns["o"] = (ke_o, ke_O)
mi = menuitem("r", "Robots", 2, 0, None, ("Save what",), None, (), None, None)
print("mi ld wt r ", mi)
mnu.appendmenuitem("Save what", mi)
mnu.keyfuns["r"] = (ke_r, ke_R)
mi = menuitem("a", "All", 3, 0, None, ("Save what",), None, (), None, None)
print("mi ld wt a ", mi)
mnu.appendmenuitem("Save what", mi)
mnu.keyfuns["a"] = (ke_a, ke_A)
mi = menuitem("o", "Obstacles", 1, 0, pushobsselect, ("Obstacles",), None, None)
print("mi playg o ", mi)
mnu.appendmenuitem("Playground", mi)
mnu.keyfuns["o"] = (ke_o, ke_O)
mi = menuitem("l", "Load", 5, 0, doloadplayg, ("Playground",), None, (), None, None)
print("mi obs l ", mi)
mnu.appendmenuitem("Playground", mi)
mnu.keyfuns["l"] = (ke_l, ke_L)
mi = menuitem("s", "Save", 6, 0, dosaveplayg, ("Playground",), None, (), None, None)
print("mi obs s ", mi)
mnu.appendmenuitem("Playground", mi)
mnu.keyfuns["s"] = (ke_s, ke_S)
mi = menuitem("b", "Back", 10, 0, mnu.popmenu, (), None, None)
print("mi obs b ", mi)
mnu.appendmenuitem("Playground", mi)
mnu.appendmenuitem("Robots", mi)
mnu.appendmenuitem("Workshop", mi)
mnu.appendmenuitem("Obstacles", mi)
mnu.appendmenuitem("Garage", mi)
mnu.appendmenuitem("Load what", mi)
mnu.appendmenuitem("Save what", mi)
mnu.keyfuns["b"] = (ke_b, ke_B)
mi = menuitem("d", "Draw", 1, -1, None, (), wn.onclick, (obstacle.begin_obs,), wn.onclick, (pg.selectobs,))
print("mi obs d ", mi)
mnu.appendmenuitem("Obstacles", mi)
mnu.keyfuns["d"] = (ke_d, ke_D)
mi = menuitem("t", "Translate", 2, -1, None, (), None, (), None , ())
print("mi obs t ", mi)
mnu.appendmenuitem("Obstacles", mi)
mnu.keyfuns["t"] = (ke_t, ke_T)
mi = menuitem("r", "Rotate", 3, -1, None, (), None, (), pg.seltt.onrelease, (None,))
print("mi obs r ", mi)
mnu.appendmenuitem("Obstacles", mi)
mi = menuitem("c", "Colors", 4, 0, 'pg.colors', ())
print("mi obs c ", mi)
mnu.appendmenuitem("Obstacles", mi)
mnu.keyfuns["c"] = (ke_c, ke_C)
mi = menuitem("w", "Workshop", 1, 0, pushnewbot, ("Workshop",))
print("mi bots w ", mi)
mnu.appendmenuitem("Robots", mi)
mnu.keyfuns["w"] = (ke_w, ke_W)
mi = menuitem("g", "Garage", 2, 0, pushnewbot, ("Garage",))
print("mi bots g ", mi)
mnu.appendmenuitem("Robots", mi)
mnu.keyfuns["w"] = (ke_w, ke_W)
mi = menuitem("l", "Load", 5, 0, "doloadbots", ("Playground",), None, (), None, None)
print("mi bots l ", mi)
mnu.appendmenuitem("Garage", mi)
mnu.keyfuns["l"] = (ke_l, ke_L)
mi = menuitem("s", "Save", 6, 0, "dosavebots", ("Playground",), None, (), None, None)
print("mi bots s ", mi)
mnu.appendmenuitem("Garage", mi)
mnu.keyfuns["s"] = (ke_s, ke_S)
mi = menuitem("d", "Draw Body", 1, 0, robot.begin_bot, () )
print("mi wksh d ", mi)
mnu.appendmenuitem("Workshop", mi)
mnu.keyfuns["d"] = (ke_d, ke_D)
mi = menuitem("u", "Undo", 2, 0, None, () )
print("mi wksh u ", mi)
mnu.appendmenuitem("Workshop", mi)
mnu.keyfuns["u"] = (ke_u, ke_U)
mi = menuitem("r", "Redraw", 3, 0, None, () )
print("mi wksh r ", mi)
mnu.appendmenuitem("Workshop", mi)
mnu.keyfuns["r"] = (ke_r, ke_R)
mi = menuitem("c", "Colors", 5, 0, None, () )
print("mi wksh c ", mi)
mnu.appendmenuitem("Workshop", mi)
mnu.keyfuns["c"] = (ke_c, ke_C)
mi = menuitem("w", "Wheels", 4, 0, None, () )
print("mi wksh w ", mi)
mnu.appendmenuitem("Workshop", mi)
mnu.keyfuns["d"] = (ke_d, ke_D)
mi = menuitem("g", "Garage", 6, 0, None, () )
print("mi wksh g ", mi)
mnu.appendmenuitem("Workshop", mi)
mnu.keyfuns["g"] = (ke_g, ke_G)
mi = menuitem("p", "Playground", 1, 0, None, () )
print("mi grge p ", mi)
mnu.appendmenuitem("Garage", mi)
mnu.keyfuns["p"] = (ke_p, ke_P)
mi = menuitem("r", "Rework", 2, 0, robot.begin_bot, () )
print("mi wksh r ", mi)
mnu.appendmenuitem("Garage", mi)
mnu.keyfuns["r"] = (ke_r, ke_R)
mi = menuitem("l", "Load", 5, 0, "doloadplayg", ("Playground",), None, (), None, None)
print("mi obs l ", mi)
mnu.appendmenuitem("Garage", mi)
mnu.keyfuns["l"] = (ke_l, ke_L)
mi = menuitem("s", "Save", 6, 0, "dosaveplayg", ("Playground",), None, (), None, None)
print("mi obs s ", mi)
mnu.appendmenuitem("Garage", mi)
mnu.keyfuns["s"] = (ke_s, ke_S)
mnu.pushmenu("Main")
return mnu

def getfilename(default, use, sufx):
if use == "save":
actn = "Save To"
if use == "load":
actn = "Load From"
prmt = "Current file name is '" + default + "'\nLeaving filename blank will " + actn.lower() + " the current file.\nCancel will abort " + use
print(prmt)
notvalid = True
while notvalid:
print("getting fn")
fn = turtle.textinput(actn + " Filename", prmt)
print("txtin = ",fn, "|", fn == None)
if fn == None:
return fn
if fn == "":
if default != "":
fn = default
else:
return None
fnl = fn.split(".")
fnlen = len(fnl)
if fnlen <= 2:
if fnlen == 2:
fnl[1] = sufx
if fnlen == 1:
fnl.append(sufx)
fn = fnl[0] + fnl[1]
notvalid = False
return fn

def strtopoly(s):
rslt = []
s = s.replace("[","")
s = s.replace("]","")
s = s.replace("),",")),,")
l = s.split("),")
print("stop l ", l)
for v in l:
print("stop v0 ", v)
v = v.replace(", (","(")
print("stop v1", v)
v = v.replace("(","")
print("stop v2", v)
v = v.replace(")","")
print("stop v3", v)
l2 = v.split(",")
print("stop l2", l2)
t = (float(l2[0]), float(l2[1]))
rslt.append(t)
return rslt

def a():
print("I'm in a")

def b():
print("I'm in b")

"""
menul = [['a', False, 'attack'], ['b', False, 'better'],["c", False, "charle"]]
tl = makemenu(menul)
print(tl)
menul[1][1] = True
print(menul)
t2 = makemenu(menul)
print(t2)
wn = turtle.Screen()
makescreen(wn, menul)
"""

main()
print("going ppayground obs {0} robots {1}".format(pg.obstacles, pg.robots))
#wss = workspaces(wn)
mn = buildmenus(wss)

print("mn.stack {0} \nmlissts {1} \nml[main][o] {2}".format(mn.mstack, mn.mlists, mn.mlists["Main"][0]))
for m in mn.mlists.keys():
print(str(mn.mlists[m]))
print("===================Menues Loaded=====================")
#wn.onclick(begin_obs)
#wn.onkey(ke_o, "o")
wn.listen()
#wn.onclick(endp, 3, True)
wn.mainloop()