Example #1
0
class Ventana():
    
 
    def __init__(self, titulo, alto, ancho):
        
        assert isinstance(titulo, str)
        assert isinstance(alto, int) and alto > 0
        assert isinstance(ancho, int) and ancho > 0
 
        ## Crea la ventana y un canvas para dibujar
        self.root = TK.Tk()
        self.root.title(titulo)
        self.canvas = TK.Canvas(self.root, width=ancho, height=alto)
        self.canvas.pack()
         
        ## Crea un TurtleScreen y la tortuga para dibujar
        self.fondo_ventana = TurtleScreen(self.canvas)
        self.fondo_ventana.setworldcoordinates(0, alto, ancho, 0)
 
        ## Establece el color de fondo
        self.canvas["bg"] = "blue"
        self.canvas.pack()
 
        ## Crea una tortuga para dibujar
        self.pencil = RawTurtle(self.fondo_ventana)
        self.pencil.pencolor("white")
Example #2
0
class FractalCanvas(object):
    def __init__(self, parent, levels):
        self.levels = levels
        # Toggles screen update rate
        self.slow_drawing = False

        # Draw button
        button = Button(parent, text='Draw Fractal', command=self._draw_click)
        button.pack()

        width, height = (600, 600)

        self.canvas = Canvas(parent, width=600, height=600)
        # Constrain resizing to a 1:1 aspect ratio
        self.canvas.winfo_toplevel().aspect(1, 1, 1, 1)
        self.canvas.pack(fill=BOTH, expand=YES)

        # Setup a turtle
        self.turtleScreen = TurtleScreen(self.canvas)
        # 5px of padding
        self.turtleScreen.setworldcoordinates(-5, -height - 5, width + 5, 5)
        self.turtle = RawTurtle(self.turtleScreen)
        self.turtleScreen.colormode(255)

        # Listen to resize events
        self.canvas.bind('<Configure>', self._resize_and_draw)

        # Do an initial draw
        self.slow_drawing = True
        self._resize_and_draw()
        self.slow_drawing = False

    def _draw_click(self):
        """Handler for button click."""
        # Draw the fractal slowly when we press the button, but quickly
        # if we're drawing for a resize
        self.slow_drawing = True
        self._resize_and_draw()
        self.slow_drawing = False

    def _resize_and_draw(self, event=None):
        """Handler for when the canvas resizes (due to a window resize)."""
        self.draw(self.canvas.winfo_width(), self.canvas.winfo_height())

    def draw(self, width, height):
        """Draws the fractal."""
        pass

    def update_screen(self):
        """
        Conditionally updates the screen.
        If self.slow_drawing is set, then this method forces image data to be
        pushed to the screen, otherwise it does nothing.
        """
        if self.slow_drawing:
            self.turtleScreen.update()
class Ventana():
    def __init__(self, titulo, alto, ancho):

        assert isinstance(titulo, str)
        assert isinstance(alto, int) and alto > 0
        assert isinstance(ancho, int) and ancho > 0

        self.root = TK.Tk()
        self.root.title(titulo)
        self.canvas = TK.Canvas(self.root, width=ancho, height=alto)
        self.canvas.pack()

        self.fondo_ventana = TurtleScreen(self.canvas)
        self.fondo_ventana.setworldcoordinates(0, alto, ancho, 0)

        self.canvas["bg"] = "gold"
        self.canvas.pack()

        self.pencil = RawTurtle(self.fondo_ventana)
        self.pencil.pencolor("white")
class Snake():
    """ Implementa un Snake que puede moverse en una 
        cuadrícula imaginaria dede m filas por n columnas.
        Las filas y columnas se numeran a partir de 1.
        El snake tendrá una largo, que incluye su cabeza.
        El largo tiene que ser mayor que 1.
        La cabeza se pinta de un color y los segmentos de
        su cuerpo en otro.
        El snake se puede mover en forma horizontal o
        vertical.
        Para mover el snake se utilizan las flechas
        direccionales y la tecla "x" (que también mueve
        el snake hacia abajo).
    """

    ## Atributos de clase que definen el tamaño por
    ## defecto de la cuadrícula.
    FILAS = 40
    COLUMNAS = 30

    ## Atributos de clase que define el tamaño (en pixeles)
    ## de cada elemento de la cuadrícula.
    DIM = 10

    ## Atributo de clase que defifne el tamaño por
    ## defecto del snake.
    LARGO_SNAKE = 4

    ## Atributos de clase que define a partir de que
    ## coordenadas en el eje horizontal(x) y vertical(y)
    ## se empieza a dibujar la cuadrícula.
    DY = 20
    DX = 20

    @staticmethod
    def deme_posicion(i,j):
        """ Retorna la posicion superior izquierda en eje x, eje y
            de un elemento i,j en la cuadrícula imaginaria.
            Entradas:
                i     : Fila en la cuadrícula imaginaria.
                j     : Columna en la cuadrícula imaginaria.
            Salidas:
                (x,y) : Posición de la esquina superior izquierda
                        en donde se encuentra la entrada (i,j)
            Supuesto:
                (i,j) es una posición válida en la cuadrícula
                      imaginaria.
        """
        x = Snake.DX + (j - 1) * (Snake.DIM + 1)
        y = Snake.DY + (i - 1) * (Snake.DIM + 1)
        return (x, y)
    

    def __init__(self, filas = FILAS, columnas = COLUMNAS,
                 largo = LARGO_SNAKE, cabeza = "blue", cuerpo="red"):
        """Crea la culebra y su cuadrícula.
            Entradas:
                filas    : # de filas en la cuadrícula imaginaria.
                columnas : # de columna en la cuadrícula imaginaria.
                largo    : Tamaño del snake incluyendo la cabeza.
            Salidas:
                Snake en una cuadrícula según las dimensiones indicadas.
            Supuesto:
                La ventana, según las dimensiones establecidas,
                cabe en la ventana.
                El snake cabe en la cuadrícula.

        """

        ## Funciones locales al constructor ##
        
        def segmento(color, i, j):
            """ Dibuja un segmento del snake en posicion i, j con el color
                indicado.
            Entradas:
                color : Color del segmento a dibujar.
                (i,j) : Ubicación en que se desea dibujar el
                        segmento en la cuadrícula imaginaria.
            Salidas:
                Dibujo del segemento con el color indicado en
                la posición (i,j) de la cuadrícula imaginaria.
            Supuesto:
                El color es uno válido en Tkinter.
                (i,j) es una posición válida en la
                cuadrícula imaginaria.
            """

            ## Determina la posición en los ejes
            ## reales de la posición (i,j) de la
            ## cuadrícula imaginaria.
            x, y = Snake.deme_posicion(i, j)

            ## Prepara el lápiz para dibujar
            ## un rectánculo relleno.
            self.lapiz.fillcolor(color)
            self.lapiz.pu()
            self.lapiz.setpos(x, y)
            self.lapiz.seth(0)
            self.lapiz.pd()
            self.lapiz.begin_fill()

            ## Dibuja el rectángulo con 4
            ## movimientos !!!
            for i in range(4):
                self.lapiz.fd(Snake.DIM+1)
                self.lapiz.left(90)

            ## Cierra el relleno.
            self.lapiz.end_fill()

        def mueva_snake(direccion):
            """ Mueve el snake en la dirección indicada.
            Entradas:
                direccion : Dirección en que se mueve el snake.
            Salidas:
                Actualización del snkae en pantalla.
                Si el snake pega contra un borde o contra ella
                misma no avanza.
            Supuesto:
                dirección es alguno de los valores 
                "Up", "Down", "Left" o "Right".
            """

            ## Obtiene la posición actual de la cabeza del snake.

            ci, cj = self.snake[-1][0], self.snake[-1][1]
            
            ## Calcula la nueva posición de la cabeza según
            ## la dirección indicada por el usuario.

            if direccion == "Up":
                i, j = (ci if ci == 1 else ci - 1, cj)
            elif direccion == "Down":
                i, j = (ci if ci == self.filas else ci + 1, cj)
            elif direccion == "Left":
                i, j = (ci, cj if cj == 1 else cj - 1)
            elif direccion == "Right":
                i, j = (ci, cj if cj == self.columnas else cj + 1)

         
            if not((i,j) in self.snake): ## se asegura que el snake
                                         ## no choque contra sí mismo !!

                self.scr.tracer(False) 

                ## Borra la cola. La cola está en la
                ## posición 0 de la lista self.snake.

                segmento("white", self.snake[0][0], self.snake[0][1])
                del self.snake[0]

                ## Pinta la antigua cabeza de color azul para que sea
                ## parte del cuerpo.  La cabeza es el último elemento
                ## de la lista self.snake.

                segmento(cuerpo, self.snake[-1][0], self.snake[-1][1])

                ## Agrega la nueva cabeza.  La cabeza nueva cabeza
                ## se agrega al final de la lista. 

                self.snake.append((i, j))
                segmento(cabeza, i, j)

                self.scr.tracer(True)
                
        def dibuja_horizontales():
            """ Dibuja las filas+1 lineas horizontales.
            Entradas:
                Ninguna.
            Salidas:
                Dibujo de las líneas horizontales de la
                cuadrícula imaginaria en que se moverá el
                snake.
            """
            
            dy = Snake.DY ## Posición en eje y de la primera 
                          ## línea horizontal.

            ## Calcula la posición en eje x en que finalizan
            ## todas la líneas horizontales.
            
            posFin_x = Snake.DX + self.columnas * (Snake.DIM + 1)

            for i in range(self.filas+1):
                self.lapiz.up()
                self.lapiz.setpos(Snake.DX, dy)
                self.lapiz.down()
                self.lapiz.setpos(posFin_x, dy)
                dy += Snake.DIM + 1

        def dibuja_verticales():
            """ Dibuja las columnas+1 lineas verticales 
            Entradas:
                Ninguna.
            Salidas:
                Dibujo de las líneas verticales de la
                cuadrícula imaginaria en que se moverá el
                snake.
            """

            dx = Snake.DX ## Posición en eje x de la primera
                          ## línea vertical.

            ## Calcula la posición en eje y en que finalizan
            ## todas la líneas verticales.
            
            posFin_y = Snake.DY + self.filas * (Snake.DIM + 1)
            for j in range(self.columnas+1):
                self.lapiz.up()
                self.lapiz.setpos(dx,Snake.DY)
                self.lapiz.down()
                self.lapiz.setpos(dx, posFin_y)
                dx += Snake.DIM + 1

        def dibuja_escenario():
            """ Dibuja la cuadrícula y el snake: el cuerpo en azul y la
                cabeza en rojo.
            Entradas:
                Ninguna.
            Salidas:
                Dibujo de la cuadrícula imaginaria en que se moverá el
                snake.
            """

            self.scr.tracer(False)

            ## Dibuja la cuadricula
            dibuja_horizontales()
            dibuja_verticales()

            ## Dibuja el cuerpo del snake
            for x in self.snake[:-1]:
                segmento(cuerpo,x[0],x[1])

            ## Dibuja la cabeza
            segmento(cabeza, self.snake[-1][0], self.snake[-1][1])    

            self.scr.tracer(True)

        ############################################################    
        ## Inicio de las instrucciones del constructor __init__.  ##
        ############################################################

        ## Verifica restricciones, sino se cumplen dispara un
        ## SnakeError.
        if not (isinstance(filas,int) and isinstance(columnas,int) and \
           isinstance(largo,int)):
            raise SnakeError("Type Error")
        else:
            
            ## Guarda las dimensiones de la cuadrícula
            ## imaginaria y del snake en atributos de instancia.
            self.filas = filas
            self.columnas = columnas
            self.largo = largo

            ## Crea la ventana y estable un título para la misma.
            self.root = TK.Tk()
            self.root.title("Snake v1.0 / 2014")

            ## Obtiene la posición (x,y) en la ventana de la 
            ## última fila y columna de la cuadrícula imaginaria,
            ## lo anterior con el objetivo de establecer el
            ## tamaño de la ventana.
            x, y = Snake.deme_posicion(filas, columnas)

            ## Calcula el ancho y el alto de la ventana
            anchoVentana = x + Snake.DX + Snake.DIM + 1
            altoVentana  = y + Snake.DY + Snake.DIM + 1

            ## Crea un área de dibujo (canvas) con un ancho y
            ## alto que está en función de la cuadrícula
            ## en que se moverá el snake.
            
            self.canvas = TK.Canvas(self.root, width=anchoVentana,
                                    height=altoVentana)
            self.canvas.pack()

            ## Crea un área de dibujo para tortugas.
            self.scr = TurtleScreen(self.canvas)

            ## Establece un sistema de coordenadas en donde
            ## el punto (0,0) se ubica en la esquina superior
            ## izquierda.
            ## El eje x va de 0 a positivos de izquierda a derecha.
            ## El eje y va de 0 a positivos de arriba hacia abajo.
            self.scr.setworldcoordinates(0,altoVentana,anchoVentana,0)
            self.scr.reset()

            ## Crea la tortuga para dibujar
            self.lapiz = RawTurtle(self.scr)
            self.lapiz.ht()

            ## Crea el snake.
            ## El snake corresponde a una lista de pares
            ## ordenados (x, y) en donde cada uno de estos
            ## elementos corresponde a un segmento del snake.
            ## La cabeza del snake se ubica en la última
            ## posición de la lista.
            ## El snake creado queda en posición horizontal
            ## y su cabeza mira hacia la derecha.  La cola
            ## se ubica en la posición 1,1. Observe que se
            ## utilizaron listas por comprensión para
            ## construir el snake.  En este punto el snake
            ## no es visible.
            
            self.snake = [(1,eje_y) for eje_y in range(1, self.largo + 1)]

            ## Dibuja la cuadrícula y el snake.
            dibuja_escenario()

            ## Establece el binding entre las teclas para el movimiento
            ## del snake y las funciones que atenderán dicho movimiento.
            ## En todos los casos se utiliza la misma función solo que
            ## el parámetro con que se invoca es diferente.
            
            self.scr.onkeypress(lambda : mueva_snake("Up"), "Up")       # Arriba
            self.scr.onkeypress(lambda : mueva_snake("Right"), "Right") # Derecha
            self.scr.onkeypress(lambda : mueva_snake("Down"), "Down")   # Abajo
            self.scr.onkeypress(lambda : mueva_snake("Left"), "Left")   # Izquierda
            self.scr.onkeypress(lambda : mueva_snake("Down"), "x")      # Otra vez abajo

            ## Se queda escuchando los eventos.
            ## El programa termina cuando el usuario cierre la ventana.
            self.scr.listen()
Example #5
0
def loadAndDraw(load, draw, indicatorList, trades):
    def get_mouse_click_coor(x, y):
        print(x, y)
        barNumber = round(x / 10)
        barNumber = max(1, barNumber)
        print("Bar Number: ", barNumber, " ", d[startPt + barNumber - 1], " ",
              o[startPt + barNumber - 1], " ", highestHigh)
        # tkMessageBox("Information",str(barNumber)
        # # trtl.write('Vivax Solutions', font=("Arial", 20, "bold")) # chosing the font
        ##        trtl.goto(10,highestHigh-.05*(highestHigh - lowestLow))
        ##        trtl.pendown()
        indexVal = startPt + barNumber - 1
        outPutStr = str(d[indexVal]) + " " + str(o[indexVal]) + " " + str(
            h[indexVal]) + " " + str(l[indexVal]) + " " + str(
                c[indexVal])  # chosing the font
        root.focus_set()
        T.focus_set()
        T.insert(tk.END, outPutStr + "\n")
##        trtl.goto(20,highestHigh-60)
##        trtl.write(str(o[50-(50-barNumber)]), font=("Arial", 8, "bold")) # chosing the font
##        trtl.goto(20,highestHigh-80)
##        trtl.write(str(h[50-(50-barNumber)]), font=("Arial", 8, "bold")) # chosing the font
##        trtl.goto(20,highestHigh-100)
##        trtl.write(str(l[50-(50-barNumber)]), font=("Arial", 8, "bold")) # chosing the font
##        trtl.goto(20,highestHigh-120)
##        trtl.write(str(c[50-(50-barNumber)]), font=("Arial", 8, "bold")) # chosing the font

##
##    #root.withdraw()

    if load == True:
        cnt = 0
        file = askopenfilename(
            filetypes=(('CSV files', '*.csv'), ('TXT files', '*.txt'),
                       ('POR files', '*.por')),
            title='Select Markets or Ports. To Test- CSV format only!')
        with open(file) as f:
            f_csv = csv.reader(f)
            numDecs = 0
            for row in f_csv:
                numCols = len(row)
                cnt += 1
                d.append(int(row[0]))
                dt.append(datetime.datetime.strptime(row[0], '%Y%m%d'))
                o.append(float(row[1]))
                h.append(float(row[2]))
                l.append(float(row[3]))
                c.append(float(row[4]))
                v.append(float(row[5]))
                oi.append(float(row[6]))
                oString = str(o[-1])
                if '.' in oString:
                    decLoc = oString.index('.')
                    numDecs = max(numDecs, len(oString) - decLoc - 1)
        xDate = list()
        yVal = list()
        zVal = list()
        w.Button5.configure(state="normal")
        w.Entry1.insert(0, str(d[-1]))

    if draw == True:
        startDrawDateStr = w.Entry1.get()
        startDrawDate = int(startDrawDateStr)
        cnt = -1
        for x in range(0, len(d)):
            cnt += 1
            if startDrawDate >= d[x]: startPt = x
        numBarsPlot = 60
        if startPt + numBarsPlot > len(d): startPt = len(d) - (numBarsPlot + 1)
        print(startPt, " ", len(d), " ", numBarsPlot)

        indicCnt = 0
        screen = TurtleScreen(w.Canvas1)

        trtl = RawTurtle(screen)

        screen.tracer(False)

        screen.bgcolor('white')
        clr = ['red', 'green', 'blue', 'yellow', 'purple']
        trtl.pensize(6)
        trtl.penup()
        trtl.color("black")
        highestHigh = 0
        lowestLow = 99999999
        #        scaleMult = 10**numDecs
        scaleMult = 1
        for days in range(startPt, startPt + numBarsPlot):
            if h[days] * scaleMult > highestHigh:
                highestHigh = h[days] * scaleMult
            if l[days] * scaleMult < lowestLow: lowestLow = l[days] * scaleMult
        hhllDiffScale = (highestHigh - lowestLow) / 1.65
        hhllDiff = highestHigh - lowestLow
        botOfChart = lowestLow
        screen.setworldcoordinates(-10, highestHigh - hhllDiffScale, 673,
                                   highestHigh)
        print(highestHigh, " ", lowestLow)
        m = 0
        trtl.setheading(0)
        trtl.penup()

        for i in range(startPt, startPt + numBarsPlot + 1):
            m = m + 1
            trtl.goto(m * 10, h[i] * scaleMult)
            trtl.pendown()
            trtl.goto(m * 10, l[i] * scaleMult)
            trtl.penup()
            trtl.goto(m * 10, c[i] * scaleMult)
            trtl.pendown()
            trtl.goto(m * 10 + 5, c[i] * scaleMult)
            trtl.penup()
            trtl.goto(m * 10, o[i] * scaleMult)
            trtl.pendown()
            trtl.goto(m * 10 - 5, o[i] * scaleMult)
            trtl.penup()
            trtl.goto(10, highestHigh)
        print("Indicator List: ", indicatorList)
        if len(indicatorList) != 0:
            movAvgParams = list([])
            if "movAvg" in indicatorList:
                movAvgVal = 0
                movAvgParamIndexVal = indicatorList.index("movAvg")
                movAvgParams.append(indicatorList[movAvgParamIndexVal + 1])
                movAvgParams.append(indicatorList[movAvgParamIndexVal + 2])
                movAvgParams.append(indicatorList[movAvgParamIndexVal + 3])
                for j in range(0, 3):
                    n = 0
                    trtl.penup()
                    if j == 0: trtl.color("red")
                    if j == 1: trtl.color("green")
                    if j == 2: trtl.color("blue")
                    for i in range(startPt, startPt + numBarsPlot):
                        n = n + 1
                        movAvgVal = 0
                        for k in range(i - movAvgParams[j], i):
                            movAvgVal = movAvgVal + c[k] * scaleMult
                        if movAvgParams[j] != 0:
                            movAvgVal = movAvgVal / movAvgParams[j]
                            if i == startPt: trtl.goto(n * 10, movAvgVal)
                            trtl.pendown()
                            trtl.goto(n * 10, movAvgVal)
                trtl.penup()


#       print("PlotTrades : ",plotTrades)
        if trades.draw:
            debugTradeDate = tradeDate[0]
            debugDate = d[startPt]
            n = 0
            while debugTradeDate <= debugDate:
                n += 1
                debugTradeDate = tradeDate[n]

            m = 0
            for i in range(startPt, startPt + numBarsPlot):
                m = m + 1
                debugDate = d[i]
                if debugDate == debugTradeDate:
                    trtl.penup()
                    tradeValue = tradePrice[n]
                    if tradeType[n] == "buy":
                        trtl.color("Green")
                        trtl.goto(m * 10 - 5, tradeValue - hhllDiff * .03)
                        trtl.pensize(3)
                        trtl.pendown()
                        trtl.goto(m * 10, tradeValue)
                        trtl.goto(m * 10 + 5, tradeValue - hhllDiff * .03)
                        trtl.penup()
                    if tradeType[n] == "sell":
                        trtl.color("Red")
                        trtl.goto(m * 10 - 5, tradeValue + hhllDiff * .03)
                        trtl.pensize(3)
                        trtl.pendown()
                        trtl.goto(m * 10, tradeValue)
                        trtl.goto(m * 10 + 5, tradeValue + hhllDiff * .03)
                        trtl.penup()
                    if tradeType[n] == "longLiq":
                        trtl.color("Blue")
                        trtl.penup()
                        trtl.goto(m * 10 - 5, tradeValue)
                        trtl.pensize(3)
                        trtl.pendown()
                        trtl.goto(m * 10 + 5, tradeValue)
                        trtl.penup()
                    trtl.pensize(1)
                    print("Found a trade: ", tradeValue, " ", debugTradeDate,
                          " m= ", m, " ", tradeValue - hhllDiff * .05)
                    n += 1
                    if n < len(tradeDate): debugTradeDate = tradeDate[n]

        trtl.color("black")
        trtl.goto(-10, botOfChart)
        trtl.pendown()
        trtl.goto(673, botOfChart)
        trtl.penup()
        trtl.goto(-10, botOfChart)

        m = 0
        for i in range(startPt, startPt + numBarsPlot):
            if i % 10 == 0:
                m = m + 1
                trtl.pendown()
                trtl.write(str(d[i]),
                           font=("Arial", 8, "bold"))  # chosing the font
                trtl.penup()
                trtl.goto(m * 100, botOfChart)

        trtl.penup()
        trtl.goto(628, highestHigh)
        trtl.pendown()
        trtl.goto(628, botOfChart)
        trtl.penup()
        m = 0
        vertIncrement = hhllDiff / 10
        for i in range(0, 11):
            trtl.goto(630, highestHigh - m * vertIncrement)
            trtl.pendown()
            trtl.write(str(highestHigh - m * vertIncrement),
                       font=("Arial", 8, "bold"))
            trtl.penup()
            m += 1

        # turtle.done()
        screen.onscreenclick(get_mouse_click_coor)
Example #6
0
class TurtleGraphics(BasicGUI):
    """GUI with graphics created using 'turtle'."""

    _WORLD_COORDS = (-2, -2, 10, 10)
    _PEG_OFFSET = (0, 0.4)
    HADES = (0, 12)
    best_move = None

    @classmethod
    def _add_offset(cls, position):
        """Adds offset to peg's position coordinates."""
        peg_pos = tuple(map(add, position, cls._PEG_OFFSET))
        peg_pos = tuple(round(i, 1) for i in peg_pos)
        return peg_pos

    @classmethod
    def _subtract_offset(cls, position):
        """Subtracts offset from peg's position coordinates."""
        peg_pos = tuple(map(sub, position, cls._PEG_OFFSET))
        peg_pos = tuple(map(int, peg_pos))
        return peg_pos

    def _draw_board(self):
        """Draws board."""
        tri = ((-1.5, -0.5), (4, 9.5), (9.5, -0.5))
        artist = RawPen(self.window)
        # Draws grooves in wood:
        artist.pen(pendown=False, pensize=2, speed=0)
        x1, y1, x2, y2 = __class__._WORLD_COORDS
        for y in range(y1, y2 + 1, 2):
            artist.goto(x1, y)
            artist.pendown()
            artist.goto(x2, y)
            artist.penup()
        # Draws board:
        artist.pen(pencolor=(34, 16, 0),
                   fillcolor=(51, 25, 0),
                   pensize=6,
                   speed=0)
        artist.goto(tri[-1])
        artist.pendown()
        artist.begin_fill()
        for coord in tri:
            artist.goto(coord)
        artist.end_fill()
        # Draws peg holes:
        artist.pen(pencolor="gray", fillcolor="black", pensize=1)
        for peg_hole in self.game.board:
            artist.penup()
            artist.goto(peg_hole)
            artist.pendown()
            artist.begin_fill()
            artist.circle(0.4)
            artist.end_fill()
        artist.penup()
        artist.goto(__class__.HADES)

    def _place_pegs(self):
        """Places pegs."""
        for peg_hole in self.game.board:
            if self.game.board[peg_hole]:
                start_point = __class__._add_offset(peg_hole)
                peg = Peg(start_point, self)
                self.peg_dir.append(peg)

    def _add_callbacks(self):
        """Adds callbacks to buttons."""
        self.undo_btn["command"] = self.game.undo
        self.restart_btn["command"] = self.game.restart
        self.show_moves_btn["command"] = self.show_legal_moves
        self.best_move_btn["command"] = self.show_best_move

    def _find_best_move(self):
        """Finds best move possible for current game."""
        if len(self.game.moves) <= 3:
            with shelve.open("paths") as db:
                best_paths = db[str(self.game.moves)]
                best_path = choice(best_paths)
        else:
            self.path_finder(self.game)
            best_path = self.path_finder.best_path
        best_move = best_path[len(self.game.moves)]
        best_move = (__class__._add_offset(best_move[0]), best_move[1])
        return best_move

    def _disable_all(self):
        """Disables all buttons and pegs."""
        self.undo_btn["state"] = "disabled"
        self.restart_btn["state"] = "disabled"
        self.show_moves_btn["state"] = "disabled"
        self.best_move_btn["state"] = "disabled"
        for peg in self.peg_dir:
            peg.moveable = False

    def _restore_all(self):
        """Enables pegs and buttons that would normally be enabled."""
        self.update_gui()
        for peg in self.peg_dir:
            peg.moveable = True

    def _delayed_callback(self, arrows):
        """Banishes arrows and restores GUI."""
        for arrow in arrows:
            arrow.banish()
        self._restore_all()

    def construct(self):
        """Constructs graphics."""
        self.window = TurtleScreen(self.canvas)
        self.window.setworldcoordinates(*__class__._WORLD_COORDS)
        self.window.bgcolor(102, 51, 0)
        self.peg_dir = []
        self.arrow_dir = []
        self.graveyard = []
        self.path_finder = PathFinder()
        self._draw_board()
        self._place_pegs()
        self._add_callbacks()

    def update_(self, peg, move):
        """Updates the graphics when a move is made."""
        midpoint = __class__._add_offset(self.game._midpoint(peg, move))
        lower_bound = (midpoint[0], midpoint[1] - 0.01)
        upper_bound = (midpoint[0], midpoint[1] + 0.01)
        dead_peg = [
            peg for peg in self.peg_dir
            if peg.pos() > lower_bound and peg.pos() < upper_bound
        ][0]
        dead_peg.goto(__class__.HADES)
        self.peg_dir.remove(dead_peg)
        self.graveyard.append(dead_peg)

    def erase(self):
        """Updates the graphics when a move is undone."""
        last_peg_pos = __class__._add_offset(
            tuple(map(add, *self.game.moves[-1])))
        last_peg = [
            peg for peg in self.peg_dir if abs(peg.pos() - last_peg_pos) < 0.1
        ][0]
        last_peg.goto(__class__._add_offset(self.game.moves[-1][0]))
        last_peg.start_point = last_peg.pos()
        revived_peg = self.graveyard.pop()
        revived_peg.goto(revived_peg.start_point)
        self.peg_dir.append(revived_peg)

    def reset_(self):
        """Updates the graphics when the game is restarted."""
        for obj in [self.window, self.peg_dir, self.arrow_dir, self.graveyard]:
            del obj
        self.canvas.destroy()
        self.canvas = Canvas(self.mainframe,
                             width=500,
                             height=500,
                             relief="sunken",
                             borderwidth=3)
        self.canvas.grid(row=1, column=1, sticky=(N, S, E, W))
        self.construct()

    def show_legal_moves(self):
        """Shows the player all legal moves."""
        self._disable_all()
        move_count = 0
        legal_moves = self.game.find_legal_moves()
        for val in legal_moves.values():
            for move in val:
                move_count += 1
        arrows_needed = move_count - len(self.arrow_dir)
        for task in range(arrows_needed):
            self.arrow_dir.append(Arrow(self))
        used_arrows = []
        arrow_count = 0
        for start_peg in legal_moves:
            for move in legal_moves[start_peg]:
                arrow = self.arrow_dir[arrow_count]
                origin = __class__._add_offset(start_peg)
                destination = tuple(map(add, origin, move))
                arrow.draw(origin, destination)
                used_arrows.append(arrow)
                arrow_count += 1
        self.root.after(3000, self._delayed_callback, used_arrows)

    def show_best_move(self):
        """Shows the player the best move to make next."""
        self._disable_all()
        if not self.arrow_dir:
            self.arrow_dir.append(Arrow(self))
        arrow = self.arrow_dir[0]
        origin = self.best_move[0]
        destination = tuple(map(add, origin, self.best_move[1]))
        arrow.draw(origin, destination)
        self.root.after(3000, self._delayed_callback, [arrow])

    def update_peg_moves(self):
        """Updates move list for all pegs and updates best move, if
        required."""
        legal_moves = self.game.find_legal_moves()
        for peg in self.peg_dir:
            board_pos = __class__._subtract_offset(peg.pos())
            peg.possible_moves = legal_moves.get(board_pos, [])
        if legal_moves and self.game.moves:
            self.best_move = self._find_best_move()

    def update_gui(self):
        """Updates GUI to reflect current game conditions."""
        legal_moves = self.game.find_legal_moves()
        if self.game.moves:
            self.undo_btn["state"] = "!disabled"
            self.restart_btn["state"] = "!disabled"
            self.best_move_btn["state"] = "!disabled"
        else:
            self.undo_btn["state"] = "disabled"
            self.restart_btn["state"] = "disabled"
        if legal_moves:
            self.show_moves_btn["state"] = "!disabled"
        else:
            self.show_moves_btn["state"] = "disabled"
        if legal_moves and self.game.moves:
            self.best_move_btn["state"] = "!disabled"
        else:
            self.best_move_btn["state"] = "disabled"
Example #7
0
class TurtleWidget(CanvasWidget):
    def newTKWidget(self, parent, hOptions):
        return super().newTKWidget(parent, hOptions)

    def initialize(self, hOptions):
        self.screen = TurtleScreen(self.tkWidget)
        self.tkTurtle = RawTurtle(self.screen)
        self.screen.mode('world')

        self.tkTurtle.setheading(90)

        if 'speed' in hOptions:
            self.curSpeed = int(hOptions['speed'])
        else:
            self.curSpeed = 1
        self.lSaveStack = []  # stack to save/restore state on

    def setBounds(self, xmin, ymin, xmax, ymax, padding=15):
        width = xmax - xmin
        height = ymax - ymin
        if (width > height):
            halfdiff = (width - height) / 2
            ymin -= halfdiff
            ymax += halfdiff
        else:
            halfdiff = (height - width) / 2
            xmin -= halfdiff
            xmax += halfdiff
        self.screen.setworldcoordinates(
            xmin - padding,
            ymin - padding,
            xmax + padding,
            ymax + padding,
        )

    def reset(self):
        self.screen.reset()

    def move(self, n):
        tkTurtle = self.tkTurtle
        assert isinstance(tkTurtle, RawTurtle)
        tkTurtle.speed(self.curSpeed)
        tkTurtle.forward(n)

    def turn(self, d):
        tkTurtle = self.tkTurtle
        assert isinstance(tkTurtle, RawTurtle)
        tkTurtle.speed(self.curSpeed)
        tkTurtle.right(d)

    # --- Turtle state includes these fields:
    #     xpos, ypos, heading, isvisible, isdown

    def saveState(self):

        tkTurtle = self.tkTurtle
        assert isinstance(tkTurtle, RawTurtle)
        self.lSaveStack.append([
            tkTurtle.xcor(),
            tkTurtle.ycor(),
            tkTurtle.heading(),
            tkTurtle.isvisible(),
            tkTurtle.isdown(),
        ])

    def restoreState(self):

        tkTurtle = self.tkTurtle
        assert isinstance(tkTurtle, RawTurtle)
        if len(self.lSaveStack) == 0:
            raise Exception("restoreState(): No saved state to restore")
        lState = self.lSaveStack.pop()
        saved_x = lState[0]
        saved_y = lState[1]

        cur_x = tkTurtle.xcor()
        cur_y = tkTurtle.ycor()

        # --- determine whether we need to hide the turtle
        if tkTurtle.isvisible():
            dist = hypot(saved_x - cur_x, saved_y - cur_y)
            mustHide = (dist > 1)
        else:
            mustHide = False

        if mustHide:
            tkTurtle.hideturtle()

        tkTurtle.penup()
        tkTurtle.setposition(saved_x, saved_y)
        tkTurtle.setheading(lState[2])

        if lState[3] and mustHide:
            tkTurtle.showturtle()
        if lState[4]:
            tkTurtle.pendown()

    def moveTo(self, x, y):
        tkTurtle = self.tkTurtle
        tkTurtle.penup()
        tkTurtle.hideturtle()
        tkTurtle.setposition(x, y)
        tkTurtle.setheading(90)
        tkTurtle.pendown()
        tkTurtle.showturtle()

    def drawAt(self, x, y, func):

        # --- Must not draw or show movement
        tkTurtle = self.tkTurtle

        self.saveState()
        self.moveTo(x, y)
        func(self)
        self.restoreState()