loop :: DeviceContext -> Map (Int, Int) XO -> XO -> IO ()
loop context board turn = do
        sz <- send context $ do
                clearRect (0,0,width context,height context)
                beginPath()

                let sz = min (width context) (height context)
                save()
                translate (width context / 2,height context / 2)
                sequence_ [ do bigLine (-sz * 0.45,n) (sz * 0.45,n)
                               bigLine (n,-sz * 0.45) (n,sz * 0.45)
                          | n <- [-sz * 0.15,sz * 0.15]
                          ]


                sequence_ [ do save()
                               translate (fromIntegral x * sz * 0.3,fromIntegral y * sz * 0.3)
                               case Map.lookup (x,y) board of
                                  Just X -> drawX (sz * 0.1)
                                  Just O -> drawO (sz * 0.1)
                                  Nothing -> return ()
                               restore()
                          | x <- [-1,0,1]
                          , y <- [-1,0,1]
                          ]
                restore()
                return sz

        let pointToSq :: (Double, Double) -> Maybe (Int, Int)
            pointToSq (x,y) = do
                    x' <- fd ((x - width context / 2) / sz)
                    y' <- fd ((y - height context / 2) / sz)
                    return (x',y')

            fd x = 
--                    trace (show ("fx",x,r)) $
                    if r `elem` [-1..1] then Just (signum r) else Nothing
                where r = round (x * 3.3333)

        let press = (width context / 2 + fromIntegral x * (sz / 4),height context / 2 + fromIntegral y * (sz / 4)) -- wiki $
                where (x,y) = head [ ix | (ix,Nothing)                                   -- wiki $
                                                 <- [ ((x',y'),Map.lookup (x',y') board) -- wiki $
                                                    | y' <- [-1,0,1]                     -- wiki $
                                                    , x' <- [-1,0,1]                     -- wiki $
                                                    ]]                                   -- wiki $

        _ <- wiki $ forkIO $ send context $ trigger $ Event {
              eMetaKey = False
            , ePageXY = return $ press
            , eType = "keypress"
            , eWhich = Nothing
        }
        event <- wait context

        file <- wiki $ anim_png "Tic_Tac_Toe"
        wiki $ snapShot context $ file
        wiki $ whenM (Map.size board == 7) $ do { build_anim "Tic_Tac_Toe" 100; close context ; quit }

        print event
        case ePageXY event of
           -- if no mouse location, ignore, and redraw
           Nothing -> loop context board turn
           Just (x',y') -> case pointToSq (x',y') of
                             Nothing -> loop context board turn
                             Just pos -> case Map.lookup pos board of
                                           Nothing -> loop context
                                                            (Map.insert pos turn board)
                                                            (swap turn)
                                                    -- already something here
                                           Just _ -> loop context board turn
loop :: DeviceContext -> Map (Int, Int) XO -> XO -> IO ()
loop context board turn = do
        sz <- send context $ do
                clearRect (0,0,width context,height context)
                beginPath()

                let sz = min (width context) (height context)
                save()
                translate (width context / 2,height context / 2)
                sequence_ [ do bigLine (-sz * 0.45,n) (sz * 0.45,n)
                               bigLine (n,-sz * 0.45) (n,sz * 0.45)
                          | n <- [-sz * 0.15,sz * 0.15]
                          ]


                sequence_ [ do save()
                               translate (fromIntegral x * sz * 0.3,fromIntegral y * sz * 0.3)
                               case Map.lookup (x,y) board of
                                  Just X -> drawX (sz * 0.1)
                                  Just O -> drawO (sz * 0.1)
                                  Nothing -> return ()
                               restore()
                          | x <- [-1,0,1]
                          , y <- [-1,0,1]
                          ]
                restore()
                return sz

        let pointToSq :: (Double, Double) -> Maybe (Int, Int)
            pointToSq (x,y) = do
                    x' <- fd ((x - width context / 2) / sz)
                    y' <- fd ((y - height context / 2) / sz)
                    return (x',y')

            fd x = 
--                    trace (show ("fx",x,r)) $
                    if r `elem` [-1..1] then Just (signum r) else Nothing
                where r = round (x * 3.3333)

        let press = (width context / 2 + fromIntegral x * (sz / 4),height context / 2 + fromIntegral y * (sz / 4)) -- wiki $
                where (x,y) = head [ ix | (ix,Nothing)                                   -- wiki $
                                                 <- [ ((x',y'),Map.lookup (x',y') board) -- wiki $
                                                    | y' <- [-1,0,1]                     -- wiki $
                                                    , x' <- [-1,0,1]                     -- wiki $
                                                    ]]                                   -- wiki $

        _ <- wiki $ forkIO $ send context $ trigger $ Event {
              eMetaKey = False
            , ePageXY = return $ press
            , eType = "keypress"
            , eWhich = Nothing
        }
        event <- wait context

        file <- wiki $ anim_png "Tic_Tac_Toe"
        wiki $ snapShot context $ file
        wiki $ whenM (Map.size board == 7) $ do { build_anim "Tic_Tac_Toe" 100; close context ; quit }

        print event
        case ePageXY event of
           -- if no mouse location, ignore, and redraw
           Nothing -> loop context board turn
           Just (x',y') -> case pointToSq (x',y') of
                             Nothing -> loop context board turn
                             Just pos -> case Map.lookup pos board of
                                           Nothing -> loop context
                                                            (Map.insert pos turn board)
                                                            (swap turn)
                                                    -- already something here
                                           Just _ -> loop context board turn
loop context board turn = do
        sz <- send context $ do
                clearRect (0,0,width context,height context)
                beginPath()

                let sz = min (width context) (height context)
                save()
                translate (width context / 2,height context / 2)
                sequence_ [ do bigLine (-sz * 0.45,n) (sz * 0.45,n)
                               bigLine (n,-sz * 0.45) (n,sz * 0.45)
                          | n <- [-sz * 0.15,sz * 0.15]
                          ]


                sequence_ [ do save()
                               translate (fromIntegral x * sz * 0.3,fromIntegral y * sz * 0.3)
                               case Map.lookup (x,y) board of
                                  Just X -> drawX (sz * 0.1)
                                  Just O -> drawO (sz * 0.1)
                                  Nothing -> return ()
                               restore()
                          | x <- [-1,0,1]
                          , y <- [-1,0,1]
                          ]
                restore()
                return sz

        let pointToSq :: (Double, Double) -> Maybe (Int, Int)
            pointToSq (x,y) = do
                    x' <- fd ((x - width context / 2) / sz)
                    y' <- fd ((y - height context / 2) / sz)
                    return (x',y')

            fd x = 
--                    trace (show ("fx",x,r)) $
                    if r `elem` [-1..1] then Just (signum r) else Nothing
                where r = round (x * 3.3333)

        let press = (width context / 2 + fromIntegral x * (sz / 4),height context / 2 + fromIntegral y * (sz / 4)) -- wiki $
                where (x,y) = head [ ix | (ix,Nothing)                                   -- wiki $
                                                 <- [ ((x',y'),Map.lookup (x',y') board) -- wiki $
                                                    | y' <- [-1,0,1]                     -- wiki $
                                                    , x' <- [-1,0,1]                     -- wiki $
                                                    ]]                                   -- wiki $

        _ <- wiki $ forkIO $ send context $ trigger $ Event {
              eMetaKey = False
            , ePageXY = return $ press
            , eType = "keypress"
            , eWhich = Nothing
        }
        event <- wait context

        file <- wiki $ anim_png "Tic_Tac_Toe"
        wiki $ snapShot context $ file
        wiki $ whenM (Map.size board == 7) $ do { build_anim "Tic_Tac_Toe" 100; close context ; quit }

        print event
        case ePageXY event of
           -- if no mouse location, ignore, and redraw
           Nothing -> loop context board turn
           Just (x',y') -> case pointToSq (x',y') of
                             Nothing -> loop context board turn
                             Just pos -> case Map.lookup pos board of
                                           Nothing -> loop context
                                                            (Map.insert pos turn board)
                                                            (swap turn)
                                                    -- already something here
                                           Just _ -> loop context board turn