# a polyomino is a collection of elements, defined in elements.py from kivy.graphics import Color,Line,Rectangle from point import l_infinity from element import Element_square # parent class of all polyominos class Polyomino(): def __init__(self,**kwargs): # elements that make up the polyomino self.elements=kwargs.get("elements",[]) self.color=kwargs.get("color",(0,0,1)) self.selected=False # mesh of background grid (no grid for mesh size 0) self.grid=kwargs.get("grid",0) # draw function def draw(self,painter,**kwargs): alpha=kwargs.get("alpha",1) # set color if not self.selected: Color(*self.color,alpha) else: (r,g,b)=self.color # darken selected Color(r/2,g/2,b/2,alpha) for element in self.elements: Rectangle(pos=(painter.pos_tocoord_x(element.pos.x-0.5*element.size),painter.pos_tocoord_y(element.pos.y-0.5*element.size)),size=(element.size*painter.base_size,element.size*painter.base_size)) # draw boundary self.stroke(painter) # draw boundary (override for connected polyominos) def stroke(self,painter): # convert to graphical coordinates coordx=painter.pos_tocoord_x(square.pos.x) coordy=painter.pos_tocoord_y(square.pos.y) # white Color(1,1,1) for element in self.elements: Line(points=( *(coordx-0.5*element.size*painter.base_size,coordy-0.5*element.size*painter.base_size), *(coordx-0.5*element.size*painter.base_size,coordy+0.5*element.size*painter.base_size), *(coordx+0.5*element.size*painter.base_size,coordy+0.5*element.size*painter.base_size), *(coordx+0.5*element.size*painter.base_size,coordy-0.5*element.size*painter.base_size), *(coordx-0.5*element.size*painter.base_size,coordy-0.5*element.size*painter.base_size) )) # move by delta def move(self,delta): for element in self.elements: element.pos+=delta # whether x is in the support of the polyomino def in_support(self,x): for element in self.elements: if element.in_support(x): return True return False # check whether self interacts with candidate if candidate were moved by offset def check_interaction(self,candidate,offset): for element1 in self.elements: for element2 in candidate.elements: # add offset element2.pos+=offset if element1.check_interaction(element2): # reset offset element2.pos-=offset return True # reset offset element2.pos-=offset return False # square class Square(Polyomino): def __init__(self,x,y,**kwargs): super(Square,self).__init__(**kwargs,elements=[Element_square(x,y,size=kwargs.get("size",1.0))]) # cross class Cross(Polyomino): def __init__(self,x,y,**kwargs): super(Cross,self).__init__(**kwargs,elements=[\ Element_square(x,y,1),\ Element_square(x+1,y,1),\ Element_square(x-1,y,1),\ Element_square(x,y+1,1),\ Element_square(x,y-1,1)\ ]) # redefine stroke to avoid lines between touching elements def stroke(self,painter): # convert to graphical coordinates coordx=painter.pos_tocoord_x(self.elements[0].pos.x) coordy=painter.pos_tocoord_y(self.elements[0].pos.y) Color(1,1,1) Line(points=( *(coordx-0.5*painter.base_size,coordy-0.5*painter.base_size), *(coordx-0.5*painter.base_size,coordy-1.5*painter.base_size), *(coordx+0.5*painter.base_size,coordy-1.5*painter.base_size), *(coordx+0.5*painter.base_size,coordy-0.5*painter.base_size), *(coordx+1.5*painter.base_size,coordy-0.5*painter.base_size), *(coordx+1.5*painter.base_size,coordy+0.5*painter.base_size), *(coordx+0.5*painter.base_size,coordy+0.5*painter.base_size), *(coordx+0.5*painter.base_size,coordy+1.5*painter.base_size), *(coordx-0.5*painter.base_size,coordy+1.5*painter.base_size), *(coordx-0.5*painter.base_size,coordy+0.5*painter.base_size), *(coordx-1.5*painter.base_size,coordy+0.5*painter.base_size), *(coordx-1.5*painter.base_size,coordy-0.5*painter.base_size), *(coordx-0.5*painter.base_size,coordy-0.5*painter.base_size), ))