private void MakeArtificialMouseHoverLine(string first, string second)
        {
            LineBetweenCircles line = new LineBetweenCircles();

            int tmp1, tmp2;

            if (Int32.TryParse(first, out tmp1))                // horizontal line
            {
                tmp2 = Miscellaneous.TranslateLetterToAxis(second[0]);

                line.CoordinateFrom = new VTuple <int, int>(tmp1, tmp2);
                line.CoordinateTo   = new VTuple <int, int>(tmp1, tmp2 + 1);
            }
            else                                                // vertical line
            {
                tmp1 = Miscellaneous.TranslateLetterToAxis(first[0]);
                tmp2 = Int32.Parse(second);

                line.CoordinateFrom = new VTuple <int, int>(tmp1, tmp2);
                line.CoordinateTo   = new VTuple <int, int>(tmp1 + 1, tmp2);
            }

            line.From    = (Point)circleCenters[line.CoordinateFrom];
            line.To      = (Point)circleCenters[line.CoordinateTo];
            line.WhoDrew = currentGame.Turn;

            FinishTurn(line);
        }
Example #2
0
        private void MinimaxTree_AfterSelect(object sender, TreeViewEventArgs e)
        {
            if (e.Node != null)
            {
                ModifiedTreeNode node = (ModifiedTreeNode)e.Node;
                selectedNode = node.MinimaxTreeNode;

                deltaLine = selectedNode.DeltaMove;

                canvas.Refresh();
            }
        }
        private bool TransferFromNonExistingToExisting(LineBetweenCircles line)
        {
            for (int i = 0; i < nonExistingLines.Count; i++)
            {
                if ((nonExistingLines[i].CoordinateFrom == line.CoordinateFrom && nonExistingLines[i].CoordinateTo == line.CoordinateTo) ||
                    (nonExistingLines[i].CoordinateTo == line.CoordinateFrom && nonExistingLines[i].CoordinateFrom == line.CoordinateTo))
                {
                    LineBetweenCircles trueLine = nonExistingLines[i];

                    nonExistingLines.RemoveAt(i);
                    existingCanvasLines.Add(trueLine);

                    return(true);
                }
            }

            return(false);
        }
        private void Canvas_MouseClick(object sender, MouseEventArgs e)
        {
            if (currentGame == null)
            {
                MessageBox.Show("Igra nije započeta!");
                return;
            }
            else if (currentGame.Opponent != null && currentGame.Opponent2 != null)
            {
                return;
            }

            if (mouseHoverLine != null && !currentGame.GameOver)
            {
                FinishTurn(mouseHoverLine);

                mouseHoverLine = null;
                // refreshing done inside FinishTurn(...)
            }
        }
        private void CreateNonExistingMovesList()
        {
            nonExistingLines.Clear();

            // horizontal lines
            for (int i = 0; i < currentGame.TableSizeX; i++)            // rows
            {
                for (int j = 0; j < currentGame.TableSizeY - 1; j++)    // columns
                {
                    LineBetweenCircles newLine = new LineBetweenCircles();
                    newLine.CoordinateFrom = new VTuple <int, int>(i, j);
                    newLine.CoordinateTo   = new VTuple <int, int>(i, j + 1);

                    newLine.From = (Point)circleCenters[newLine.CoordinateFrom];
                    newLine.To   = (Point)circleCenters[newLine.CoordinateTo];

                    nonExistingLines.Add(newLine);
                }
            }

            // vertical lines
            for (int j = 0; j < currentGame.TableSizeY; j++)            // rows
            {
                for (int i = 0; i < currentGame.TableSizeX - 1; i++)    // columns
                {
                    LineBetweenCircles newLine = new LineBetweenCircles();
                    newLine.CoordinateFrom = new VTuple <int, int>(i, j);
                    newLine.CoordinateTo   = new VTuple <int, int>(i + 1, j);

                    newLine.From = (Point)circleCenters[newLine.CoordinateFrom];
                    newLine.To   = (Point)circleCenters[newLine.CoordinateTo];

                    nonExistingLines.Add(newLine);
                }
            }

            Miscellaneous.ShuffleList(nonExistingLines);
        }
Example #6
0
        public static List <Box> TryClosingBoxes(List <LineBetweenCircles> existingCanvasLines,
                                                 Player player,
                                                 LineBetweenCircles line,
                                                 out int[] surroundingEdges)
        {
            List <Box> result = new List <Box>();

            surroundingEdges    = new int[2];
            surroundingEdges[0] = surroundingEdges[1] = 0;

            int coordinateFromX = line.CoordinateFrom.Item1;
            int coordinateFromY = line.CoordinateFrom.Item2;
            int coordinateToX   = line.CoordinateTo.Item1;
            int coordinateToY   = line.CoordinateTo.Item2;

            if (coordinateFromX == coordinateToX)
            {
                // horizontal line

                for (int direction = 0; direction < 2; direction++)
                {
                    // DIRECTION(0) -> ABOVE
                    // DIRECTION(1) -> BELOW

                    // (line where x = 0 doesn't have upper element
                    if (coordinateFromX == 0 && direction == 0)
                    {
                        continue;
                    }

                    int dx = (direction == 0 ? -1 : 1); // check for clojure both above and below the line

                    Box box = new Box();

                    bool upperLeft  = false;
                    bool upperUpper = false;
                    bool upperRight = false;

                    for (int i = 0; i < existingCanvasLines.Count; i++)
                    {
                        // looking for left and right
                        if (coordinateFromY < coordinateToY)
                        {
                            if (direction == 0)
                            {
                                box.BottomLeft  = line.From;
                                box.BottomRight = line.To;
                            }
                            else
                            {
                                box.TopLeft  = line.From;
                                box.TopRight = line.To;
                            }

                            // 'from' is left edge
                            if (!upperLeft &&
                                ((existingCanvasLines[i].CoordinateFrom == new VTuple <int, int>(coordinateFromX, coordinateFromY) && existingCanvasLines[i].CoordinateTo == new VTuple <int, int>(coordinateFromX + dx, coordinateFromY)) ||
                                 (existingCanvasLines[i].CoordinateTo == new VTuple <int, int>(coordinateFromX, coordinateFromY) && existingCanvasLines[i].CoordinateFrom == new VTuple <int, int>(coordinateFromX + dx, coordinateFromY))))
                            {
                                upperLeft    = true;
                                box.LeftEdge = existingCanvasLines[i];

                                surroundingEdges[direction]++;

                                continue;
                            }

                            // 'to' is right edge
                            if (!upperRight &&
                                ((existingCanvasLines[i].CoordinateFrom == new VTuple <int, int>(coordinateToX, coordinateToY) && existingCanvasLines[i].CoordinateTo == new VTuple <int, int>(coordinateToX + dx, coordinateToY)) ||
                                 (existingCanvasLines[i].CoordinateTo == new VTuple <int, int>(coordinateToX, coordinateToY) && existingCanvasLines[i].CoordinateFrom == new VTuple <int, int>(coordinateToX + dx, coordinateToY))))
                            {
                                upperRight    = true;
                                box.RightEdge = existingCanvasLines[i];

                                surroundingEdges[direction]++;

                                continue;
                            }

                            if (!upperUpper &&
                                ((existingCanvasLines[i].CoordinateFrom == new VTuple <int, int>(coordinateFromX + dx, coordinateFromY) && existingCanvasLines[i].CoordinateTo == new VTuple <int, int>(coordinateFromX + dx, coordinateFromY + 1)) ||
                                 (existingCanvasLines[i].CoordinateTo == new VTuple <int, int>(coordinateFromX + dx, coordinateFromY) && existingCanvasLines[i].CoordinateFrom == new VTuple <int, int>(coordinateFromX + dx, coordinateFromY + 1))))
                            {
                                upperUpper = true;
                                if (direction == 0)
                                {
                                    box.UpperEdge = existingCanvasLines[i];
                                }
                                else
                                {
                                    box.BottomEdge = existingCanvasLines[i];
                                }

                                surroundingEdges[direction]++;

                                continue;
                            }
                        }
                        else
                        {
                            if (direction == 0)
                            {
                                box.BottomLeft  = line.To;
                                box.BottomRight = line.From;
                            }
                            else
                            {
                                box.TopLeft  = line.To;
                                box.TopRight = line.From;
                            }

                            // 'from' is right edge
                            if (!upperRight &&
                                ((existingCanvasLines[i].CoordinateFrom == new VTuple <int, int>(coordinateFromX, coordinateFromY) && existingCanvasLines[i].CoordinateTo == new VTuple <int, int>(coordinateFromX + dx, coordinateFromY)) ||
                                 (existingCanvasLines[i].CoordinateTo == new VTuple <int, int>(coordinateFromX, coordinateFromY) && existingCanvasLines[i].CoordinateFrom == new VTuple <int, int>(coordinateFromX + dx, coordinateFromY))))
                            {
                                upperRight    = true;
                                box.RightEdge = existingCanvasLines[i];

                                surroundingEdges[direction]++;

                                continue;
                            }

                            // 'to' is left edge
                            if (!upperLeft &&
                                ((existingCanvasLines[i].CoordinateFrom == new VTuple <int, int>(coordinateToX, coordinateToY) && existingCanvasLines[i].CoordinateTo == new VTuple <int, int>(coordinateToX + dx, coordinateToY)) ||
                                 (existingCanvasLines[i].CoordinateTo == new VTuple <int, int>(coordinateToX, coordinateToY) && existingCanvasLines[i].CoordinateFrom == new VTuple <int, int>(coordinateToX + dx, coordinateToY))))
                            {
                                upperLeft    = true;
                                box.LeftEdge = existingCanvasLines[i];

                                surroundingEdges[direction]++;

                                continue;
                            }

                            if (!upperUpper &&
                                ((existingCanvasLines[i].CoordinateFrom == new VTuple <int, int>(coordinateToX + dx, coordinateToY) && existingCanvasLines[i].CoordinateTo == new VTuple <int, int>(coordinateFromX + dx, coordinateFromY)) ||
                                 (existingCanvasLines[i].CoordinateTo == new VTuple <int, int>(coordinateToX + dx, coordinateToY) && existingCanvasLines[i].CoordinateFrom == new VTuple <int, int>(coordinateFromX + dx, coordinateFromY))))
                            {
                                upperUpper = true;
                                if (direction == 0)
                                {
                                    box.UpperEdge = existingCanvasLines[i];
                                }
                                else
                                {
                                    box.BottomEdge = existingCanvasLines[i];
                                }

                                surroundingEdges[direction]++;

                                continue;
                            }
                        }

                        if (upperLeft && upperUpper && upperRight)
                        {
                            break;
                        }
                    }

                    // add to list of boxes
                    if (upperLeft && upperUpper && upperRight)
                    {
                        box.ClosingPlayer = player;

                        if (direction == 0)
                        {
                            box.BottomEdge = line;

                            box.TopLeft  = (box.UpperEdge.From.X < box.UpperEdge.To.X ? box.UpperEdge.From : box.UpperEdge.To);
                            box.TopRight = (box.UpperEdge.From.X > box.UpperEdge.To.X ? box.UpperEdge.From : box.UpperEdge.To);
                        }
                        else
                        {
                            box.UpperEdge   = line;
                            box.BottomLeft  = (box.BottomEdge.From.X < box.BottomEdge.To.X ? box.BottomEdge.From : box.BottomEdge.To);
                            box.BottomRight = (box.BottomEdge.From.X > box.BottomEdge.To.X ? box.BottomEdge.From : box.BottomEdge.To);
                        }

                        result.Add(box);
                    }
                }
            }
            else if (coordinateFromY == coordinateToY)
            {
                // vectical line

                for (int direction = 0; direction < 2; direction++)
                {
                    // DIRECTION(0) -> LEFT
                    // DIRECTION(1) -> RIGHT

                    if (coordinateFromY == 0 && direction == 0)
                    {
                        continue;
                    }

                    int dy = (direction == 0 ? -1 : 1);

                    Box box = new Box();

                    bool upper  = false;
                    bool left   = false;
                    bool bottom = false;

                    for (int i = 0; i < existingCanvasLines.Count; i++)
                    {
                        if (coordinateFromX < coordinateToX)
                        {
                            if (direction == 0)
                            {
                                box.TopRight    = line.From;
                                box.BottomRight = line.To;
                            }
                            else
                            {
                                box.TopLeft    = line.From;
                                box.BottomLeft = line.To;
                            }

                            // 'from' is up
                            // 'to' is down
                            if (!bottom &&
                                ((existingCanvasLines[i].CoordinateFrom == new VTuple <int, int>(coordinateToX, coordinateToY + dy) && existingCanvasLines[i].CoordinateTo == new VTuple <int, int>(coordinateToX, coordinateToY)) ||
                                 (existingCanvasLines[i].CoordinateTo == new VTuple <int, int>(coordinateToX, coordinateToY + dy) && existingCanvasLines[i].CoordinateFrom == new VTuple <int, int>(coordinateToX, coordinateToY))))
                            {
                                bottom         = true;
                                box.BottomEdge = existingCanvasLines[i];

                                surroundingEdges[direction]++;

                                continue;
                            }

                            if (!upper &&
                                ((existingCanvasLines[i].CoordinateFrom == new VTuple <int, int>(coordinateFromX, coordinateFromY + dy) && existingCanvasLines[i].CoordinateTo == new VTuple <int, int>(coordinateFromX, coordinateFromY)) ||
                                 (existingCanvasLines[i].CoordinateTo == new VTuple <int, int>(coordinateFromX, coordinateFromY + dy) && existingCanvasLines[i].CoordinateFrom == new VTuple <int, int>(coordinateFromX, coordinateFromY))))
                            {
                                upper         = true;
                                box.UpperEdge = existingCanvasLines[i];

                                surroundingEdges[direction]++;

                                continue;
                            }

                            if (!left &&
                                ((existingCanvasLines[i].CoordinateFrom == new VTuple <int, int>(coordinateToX, coordinateToY + dy) && existingCanvasLines[i].CoordinateTo == new VTuple <int, int>(coordinateFromX, coordinateFromY + dy)) ||
                                 (existingCanvasLines[i].CoordinateTo == new VTuple <int, int>(coordinateToX, coordinateToY + dy) && existingCanvasLines[i].CoordinateFrom == new VTuple <int, int>(coordinateFromX, coordinateFromY + dy))))
                            {
                                left = true;
                                if (direction == 0)
                                {
                                    box.LeftEdge = existingCanvasLines[i];
                                }
                                else
                                {
                                    box.RightEdge = existingCanvasLines[i];
                                }

                                surroundingEdges[direction]++;

                                continue;
                            }
                        }
                        else
                        {
                            if (direction == 0)
                            {
                                box.TopRight    = line.To;
                                box.BottomRight = line.From;
                            }
                            else
                            {
                                box.TopLeft    = line.To;
                                box.BottomLeft = line.From;
                            }

                            // 'from' is down
                            // 'to' is up
                            if (!bottom &&
                                ((existingCanvasLines[i].CoordinateFrom == new VTuple <int, int>(coordinateFromX, coordinateFromY + dy) && existingCanvasLines[i].CoordinateTo == new VTuple <int, int>(coordinateFromX, coordinateFromY)) ||
                                 (existingCanvasLines[i].CoordinateTo == new VTuple <int, int>(coordinateFromX, coordinateFromY + dy) && existingCanvasLines[i].CoordinateFrom == new VTuple <int, int>(coordinateFromX, coordinateFromY))))
                            {
                                bottom         = true;
                                box.BottomEdge = existingCanvasLines[i];

                                surroundingEdges[direction]++;

                                continue;
                            }

                            if (!upper &&
                                ((existingCanvasLines[i].CoordinateFrom == new VTuple <int, int>(coordinateToX, coordinateToY + dy) && existingCanvasLines[i].CoordinateTo == new VTuple <int, int>(coordinateToX, coordinateToY)) ||
                                 (existingCanvasLines[i].CoordinateTo == new VTuple <int, int>(coordinateToX, coordinateToY + dy) && existingCanvasLines[i].CoordinateFrom == new VTuple <int, int>(coordinateToX, coordinateToY))))
                            {
                                upper         = true;
                                box.UpperEdge = existingCanvasLines[i];

                                surroundingEdges[direction]++;

                                continue;
                            }

                            if (!left &&
                                ((existingCanvasLines[i].CoordinateFrom == new VTuple <int, int>(coordinateFromX, coordinateFromY + dy) && existingCanvasLines[i].CoordinateTo == new VTuple <int, int>(coordinateToX, coordinateToY + dy)) ||
                                 (existingCanvasLines[i].CoordinateTo == new VTuple <int, int>(coordinateFromX, coordinateFromY + dy) && existingCanvasLines[i].CoordinateFrom == new VTuple <int, int>(coordinateToX, coordinateToY + dy))))
                            {
                                left = true;
                                if (direction == 0)
                                {
                                    box.LeftEdge = existingCanvasLines[i];
                                }
                                else
                                {
                                    box.RightEdge = existingCanvasLines[i];
                                }

                                surroundingEdges[direction]++;

                                continue;
                            }
                        }
                    }

                    if (upper && left && bottom)
                    {
                        box.ClosingPlayer = player;

                        if (direction == 0)
                        {
                            box.RightEdge = line;

                            box.TopLeft    = (box.UpperEdge.From.X < box.UpperEdge.To.X ? box.UpperEdge.From : box.UpperEdge.To);
                            box.BottomLeft = (box.BottomEdge.From.X < box.BottomEdge.To.X ? box.BottomEdge.From : box.BottomEdge.To);
                        }
                        else
                        {
                            box.LeftEdge = line;

                            box.TopRight    = (box.UpperEdge.From.X > box.UpperEdge.To.X ? box.UpperEdge.From : box.UpperEdge.To);
                            box.BottomRight = (box.BottomEdge.From.X > box.BottomEdge.To.X ? box.BottomEdge.From : box.BottomEdge.To);
                        }

                        result.Add(box);
                    }
                }
            }
            else
            {
                throw new Exception("Diagonal connections now allowed.");
            }

            return(result);
        }
        private void FinishTurn(LineBetweenCircles line)
        {
            if (line == null)
            {
                throw new Exception("AI returned null for the next move.");
            }

            // will return false if clicked on line that had already been drawn on the canvas
            if (!TransferFromNonExistingToExisting(line))
            {
                return;
            }

            ///////////////////////////////////
            string log = line.ToString();

            int    startPosition = turnRichTextBox.Text.Length;
            string textToAppend  = log + Environment.NewLine;

            turnRichTextBox.AppendText(textToAppend);
            turnRichTextBox.SelectionStart  = startPosition;
            turnRichTextBox.SelectionLength = log.Length;
            turnRichTextBox.SelectionColor  = (currentGame.Turn == Player.BLUE ? Color.Blue : Color.Red);
            turnRichTextBox.ScrollToCaret();
            ///////////////////////////////////

            List <Box> newBoxes = AICommon.TryClosingBoxes(existingCanvasLines, currentGame.Turn, line, out int[] notUsed);

            boxes.AddRange(newBoxes);
            currentGame.Score[(int)currentGame.Turn] += newBoxes.Count;

            if (newBoxes.Count > 0)
            {
                canvas.Refresh();
                UpdateGUI();
            }

            if (boxes.Count == (currentGame.TableSizeX - 1) * (currentGame.TableSizeY - 1))
            {
                currentGame.GameOver = true;
            }

            if (currentGame.GameOver)
            {
                UpdateGUI();
                GUI_GameSettingChanged(null, null);
                MessageBox.Show("Igra je završena");
            }
            else if (currentGame.Opponent2 == null) // pc vs pc will be handled in other method -> PcNextStep
            {
                if (currentGame.Turn == Player.BLUE)
                {
                    if (newBoxes.Count == 0)
                    {
                        SwitchTurn();

                        if (currentGame.Opponent != null)
                        {
                            FinishTurn(currentGame.Opponent.MakeTurn());
                        }
                    }

                    UpdateGUI();
                }
                else
                {
                    if (newBoxes.Count == 0)
                    {
                        SwitchTurn();
                    }
                    else if (newBoxes.Count > 0 && currentGame.Opponent != null)
                    {
                        UpdateGUI();
                        Thread.Sleep(1000);

                        FinishTurn(currentGame.Opponent.MakeTurn());
                    }

                    UpdateGUI();
                }
            }
            else if (currentGame.Opponent != null && currentGame.Opponent2 != null)
            {
                if (newBoxes.Count == 0)
                {
                    SwitchTurn();
                }

                UpdateGUI();
                canvas.Refresh();
            }
        }
        private void NewGame_Click(object sender, EventArgs e)
        {
            BasePlayer opponent  = null;
            BasePlayer opponent2 = null;

            pcNextStep.Enabled = false;

            if (humanVsHumanRadio.Checked)
            {
                opponent = null;
            }
            else if (humanVsPcRadio.Checked)
            {
                opponent = CreateOpponent(aiDifficulty.SelectedIndex, Player.RED);
                if (opponent == null)
                {
                    return;
                }
            }
            else
            {
                opponent  = CreateOpponent(aiDifficulty.SelectedIndex, Player.BLUE);
                opponent2 = CreateOpponent(aiDifficulty.SelectedIndex, Player.RED);
                if (opponent == null || opponent2 == null)
                {
                    return;
                }

                pcNextStep.Enabled = true;
            }

            // creating new game
            currentGame = new CurrentGame((int)tableSizeX.Value, (int)tableSizeY.Value, opponent, opponent2);

            // this cannot be moved to constructor of current game because object reference can be
            // retrieved once the constructor has finished
            if (currentGame.Opponent != null)
            {
                currentGame.Opponent.SetCurrentGame(currentGame);
            }
            if (currentGame.Opponent2 != null)
            {
                currentGame.Opponent2.SetCurrentGame(currentGame);
            }

            Logic.CalculateCanvasParameters(currentGame.TableSizeX,
                                            currentGame.TableSizeY,
                                            canvas.Width,
                                            canvas.Height,
                                            out horizontalSpacingBetweenCircles,
                                            out verticalSpacingBetweenCircles,
                                            out circleDiameter);

            // clearing existing data structures
            mouseHoverLine = null;
            existingCanvasLines.Clear();
            boxes.Clear();
            circleCenters.Clear();
            turnRichTextBox.Clear();

            UpdateGUI();
            canvas.Refresh();

            CreateNonExistingMovesList();
        }
        private void Canvas_MouseMove(object sender, MouseEventArgs e)
        {
            // finding the closes circle
            object min = null;

            foreach (DictionaryEntry pair in circleCenters)
            {
                Point p = (Point)pair.Value;

                if (min == null)
                {
                    min = pair;
                }
                else if ((Math.Abs(e.X - p.X) <= (horizontalSpacingBetweenCircles + circleDiameter) / 2) &&
                         (Math.Abs(e.Y - p.Y) <= (verticalSpacingBetweenCircles + circleDiameter) / 2))
                {
                    min = pair;
                }
                else
                {
                    continue;
                }
            }

            if (min != null)
            {
                // closest circle found
                Point minPoint     = (Point)(((DictionaryEntry)min).Value);
                Point?coordinateTo = null;

                // if in designated line area
                if ((Math.Abs(e.X - minPoint.X) <= (horizontalSpacingBetweenCircles + circleDiameter) / 2) &&
                    (Math.Abs(e.Y - minPoint.Y) <= (verticalSpacingBetweenCircles + circleDiameter) / 2))
                {
                    VTuple <int, int> coordinatesFrom = (VTuple <int, int>)((DictionaryEntry)min).Key;
                    //Debug.WriteLine("min coordinates (" + coordinatesFrom.Item1 + ", " + coordinatesFrom.Item2 + ")");

                    int  dx = 0, dy = 0;
                    bool valid = false;

                    if ((e.Y >= (minPoint.Y - verticalSpacingBetweenCircles / 2 - circleDiameter / 2)) && (e.Y <= minPoint.Y - circleDiameter / 2) &&
                        (Math.Abs(e.X - minPoint.X) <= LINE_WIDTH))
                    {
                        // up
                        if (coordinatesFrom.Item1 != 0)
                        {
                            valid = true;
                            dx    = -1;
                        }
                    }
                    else if ((e.Y >= minPoint.Y + circleDiameter / 2) && (e.Y <= (minPoint.Y + verticalSpacingBetweenCircles / 2 + circleDiameter / 2)) &&
                             (Math.Abs(e.X - minPoint.X) <= LINE_WIDTH))
                    {
                        // down
                        if (coordinatesFrom.Item1 != currentGame.TableSizeX - 1)
                        {
                            valid = true;
                            dx    = 1;
                        }
                    }
                    else if ((e.X >= (minPoint.X - horizontalSpacingBetweenCircles / 2 - circleDiameter / 2)) && (e.X <= minPoint.X - circleDiameter / 2) &&
                             (Math.Abs(e.Y - minPoint.Y) <= LINE_WIDTH))
                    {
                        // left
                        if (coordinatesFrom.Item2 != 0)
                        {
                            valid = true;
                            dy    = -1;
                        }
                    }
                    else if ((e.X >= minPoint.X + circleDiameter / 2) && (e.X <= (minPoint.X + horizontalSpacingBetweenCircles / 2 + circleDiameter / 2)) &&
                             (Math.Abs(e.Y - minPoint.Y) <= LINE_WIDTH))
                    {
                        // right
                        if (coordinatesFrom.Item2 != currentGame.TableSizeY - 1)
                        {
                            valid = true;
                            dy    = 1;
                        }
                    }
                    else
                    {
                        valid = false;
                    }

                    // signal drawing of temporary line
                    if (valid)
                    {
                        VTuple <int, int> lookingFor = new VTuple <int, int>(coordinatesFrom.Item1 + dx, coordinatesFrom.Item2 + dy);

                        //Debug.WriteLine("Looking for (" + (coordinatesFrom.Item1 + dx) + ", " + (coordinatesFrom.Item2 + dy) + ")");

                        if (circleCenters[lookingFor] != null)
                        {
                            coordinateTo = (Point)circleCenters[lookingFor];

                            LineBetweenCircles line = new LineBetweenCircles();
                            line.From           = minPoint;
                            line.To             = (Point)coordinateTo;
                            line.CoordinateFrom = coordinatesFrom;
                            line.CoordinateTo   = lookingFor;
                            line.WhoDrew        = currentGame.Turn;

                            if (mouseHoverLine != null && mouseHoverLine.From == line.From && mouseHoverLine.To == line.To)
                            {
                                return;
                            }
                            else
                            {
                                mouseHoverLine = line;
                                canvas.Refresh();
                            }
                        }
                    }
                    else
                    {
                        // clear non-existing hover line because user has exited the area
                        if (mouseHoverLine != null)
                        {
                            mouseHoverLine = null;
                            canvas.Refresh();
                        }
                    }
                }
            }
        }