using Ck_Objects;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data.Common;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Runtime.Serialization.Formatters.Binary;
using System.Windows.Forms;
using Wordinator;
using static System.Windows.Forms.VisualStyles.VisualStyleElement.Rebar;

namespace Solitaire
{
    public class pictureboxTable : PictureBox 
    {
        public static pictureboxTable instance = null;
        classSweepAndPrune cSP = new classSweepAndPrune();

        static List<classPlayingCard> lstCards_Stock = new List<classPlayingCard>();
        static List<classPlayingCard> lstCards_Bank = new List<classPlayingCard>();
        static List<classPlayingCard> lstDeck = new List<classPlayingCard>();
        static List<classPlayingCard> lstDeckReplay = new List<classPlayingCard>();

        static classEventController.classEventTicket cEventTicket_DealCards = null;
        static classEventController.classEventTicket cEventTicket_DrawTable = null;
        static classEventController.classEventTicket cEventTicket_CollectCards = null;

        static classEventController cEC { get { return formSolitaire.cEC; } }
        static bool _bolGameOver = false;
        public static bool bolGameOver
        {
            get { return _bolGameOver; }
            set { _bolGameOver = value; }
        }

        enuDrawTableMode _eDrawMode = enuDrawTableMode.Game;
        enuDrawTableMode eDrawMode
        {
            get { return _eDrawMode; }
            set 
            {
                _eDrawMode = value; 
            
            switch(eDrawMode)
                {
                    case enuDrawTableMode.About:
                        {
                            About_LoadRtf();
                            rtxDrawText_SetSize();
                        }
                        break;

                    case enuDrawTableMode.Strategy:
                        {
                            Strategy_LoadRtf();
                            rtxDrawText_SetSize();
                        }
                        break;

                    case enuDrawTableMode.Game:
                        {

                        }
                        break;
                }
            }
        }

        static void arrLstCards_ColumnsPiles_Clear()
        {

            if (_arrlstCards_Columns != null)
            {
                for (int intColumnCounter = 0; intColumnCounter < _arrlstCards_Columns.Length; intColumnCounter++)
                {
                    _arrlstCards_Columns[intColumnCounter].Clear();
                }
            }
            if (_arrlstCards_Piles != null)
            {
                for (int intPileCounter = 0; intPileCounter < _arrlstCards_Piles.Length; intPileCounter++)
                {
                    _arrlstCards_Piles[intPileCounter].Clear();
                }
            }
        }


        static List<classPlayingCard>[] _arrlstCards_Columns = null;
        static List<classPlayingCard>[] arrlstCards_Columns
        {
            get
            {
                if (_arrlstCards_Columns == null)
                {
                    _arrlstCards_Columns = new List<classPlayingCard>[7];
                    for (int intPileCounter = 0; intPileCounter < _arrlstCards_Columns.Length; intPileCounter++)
                    {
                        _arrlstCards_Columns[intPileCounter] = new List<classPlayingCard>();
                    }
                }
                return _arrlstCards_Columns;
            }
        }

        static List<classPlayingCard>[] _arrlstCards_Piles = null;
        static List<classPlayingCard>[] arrlstCards_Piles
        {
            get
            {
                if (_arrlstCards_Piles == null)
                {
                    _arrlstCards_Piles = new List<classPlayingCard>[4];
                    for (int intPileCounter = 0; intPileCounter < _arrlstCards_Piles.Length; intPileCounter++)
                    {
                        _arrlstCards_Piles[intPileCounter] = new List<classPlayingCard>();
                    }
                }
                return _arrlstCards_Piles;
            }
        }

        static void debug_SaveGame()
        {
            debug_arrlstCards_Piles = new List<classPlayingCard>[arrlstCards_Piles.Length];
            for (int intPilesCounter = 0; intPilesCounter < arrlstCards_Piles.Length; intPilesCounter++)
            {
                debug_arrlstCards_Piles[intPilesCounter] = new List<classPlayingCard>();
                debug_arrlstCards_Piles[intPilesCounter].AddRange(arrlstCards_Piles[intPilesCounter]);
            }

            debug_arrlstCards_Columns = new List<classPlayingCard>[arrlstCards_Columns.Length];
            for (int intColumnsCounter = 0; intColumnsCounter < arrlstCards_Columns.Length; intColumnsCounter++)
            {
                debug_arrlstCards_Columns[intColumnsCounter] = new List<classPlayingCard>();
                debug_arrlstCards_Columns[intColumnsCounter].AddRange(arrlstCards_Columns[intColumnsCounter]);
            }

            debuglstStock.Clear();
            debuglstStock.AddRange(lstCards_Stock);

            debuglstBank.Clear();
            debuglstBank.AddRange(lstCards_Bank);
        }


        static void debug_LoadGame()
        {
            _arrlstCards_Piles = new List<classPlayingCard>[debug_arrlstCards_Piles.Length];
            for (int intPilesCounter = 0; intPilesCounter < debug_arrlstCards_Piles.Length; intPilesCounter++)
            {
                arrlstCards_Piles[intPilesCounter] = new List<classPlayingCard>();
                arrlstCards_Piles[intPilesCounter].AddRange(debug_arrlstCards_Piles[intPilesCounter]);
            }

            _arrlstCards_Columns = new List<classPlayingCard>[arrlstCards_Columns.Length];
            for (int intColumnsCounter = 0; intColumnsCounter < debug_arrlstCards_Columns.Length; intColumnsCounter++)
            {
                arrlstCards_Columns[intColumnsCounter] = new List<classPlayingCard>();
                arrlstCards_Columns[intColumnsCounter].AddRange(debug_arrlstCards_Columns[intColumnsCounter]);
            }

            lstCards_Stock.Clear();
            lstCards_Stock.AddRange(debuglstStock);

            lstCards_Bank.Clear();
            lstCards_Bank.AddRange(debuglstBank);
        }

        static List<classPlayingCard> debuglstStock = new List<classPlayingCard>();
        static List<classPlayingCard> debuglstBank = new List<classPlayingCard>();
        static List<classPlayingCard>[] debug_arrlstCards_Columns = null;
        static List<classPlayingCard>[] debug_arrlstCards_Piles = null;
       
        public static Size szCard
        {
            get { return classPlayingCard.szCard; }
            set 
            {
                classPlayingCard.szCard = value;
                _intStockGap = 0; 
            }
        }
        static int _intStockGap = 0;
        static int intStockGap
        {
            get
            {
                if (_intStockGap == 0)
                {
                    _intStockGap = (int)((float)szCard.Height * .20);
                }
                return _intStockGap;
            }
        }

        static List<Point> lstCardLocations = new List<Point>();
        static List<Point> lstCards_ColumnsLocations
        {
            get
            {
                List<Point> lstRetVal = new List<Point>();
                lstRetVal.AddRange(lstCardLocations.GetRange((int)enuCardLocation.Col0, ((int)enuCardLocation.Col6 - (int)enuCardLocation.Col0 +1)));
                return lstRetVal;
            }
        }

        static List<Point> lstPiles_Location
        {
            get
            {
                List<Point> lstRetVal = new List<Point>();
                lstRetVal.AddRange(lstCardLocations.GetRange(0, 4));
                return lstRetVal;
            }
        }

        public pictureboxTable()
        {
            instance = this;
            cEventTicket_DealCards = cEC.Ticket("picTable_DealCards", 100, tmrDealCards_Tick);
            cEventTicket_DealCards.quit();

            cEventTicket_DrawTable = cEC.Ticket("picTable_DrawTable", 100, tmrDrawTable_Tick);
            DrawTable_AutoRepeat = true;

            cEventTicket_CollectCards = cEC.Ticket("picTable_CollectCards", 100, tmrCollectCards_Tick);
            cEventTicket_CollectCards.quit();
             
            this.ContextMenuStrip = new ContextMenuStrip();
            this.ContextMenuStrip.Opening += ContextMenuStrip_Opening;
            this.ContextMenuStrip.Closing += ContextMenuStrip_Closing;

            rtxDrawText.ScrollBars = RichTextBoxScrollBars.None;

            MouseDoubleClick += PictureboxTable_MouseDoubleClick;
            MouseDown += PictureboxTable_MouseDown;
            MouseUp += PictureboxTable_MouseUp;
            MouseMove += PictureboxTable_MouseMove;
            MouseWheel += PictureboxTable_MouseWheel;

            SizeChanged += PictureboxTable_SizeChanged;
        }

        public static void launch_Intro()
        {
            classAnimation_Intro_Item.Launch();
        }

        bool DrawTable_AutoRepeat
        {
            get { return cEventTicket_DrawTable.AutoRepeat; }
            set 
            {
                cEventTicket_DrawTable.AutoRepeat = value; 
            }
        }

     

        void tmrCollectCards_Tick(object sender,  EventArgs e)
        {
            bool bolFoundACardToMove = false;
            for(int intColumnCounter =0; intColumnCounter < arrlstCards_Columns.Length; intColumnCounter ++)
            {
                List<classPlayingCard> lstColumn = arrlstCards_Columns[intColumnCounter];
                if (lstColumn.Count > 0)
                {
                    bolFoundACardToMove = true;
                    classPlayingCard cCardInColumn = lstColumn[lstColumn.Count - 1];
                    classPlayingCard cCardOnPile = Pile_PlayingCardMostVisible(cCardInColumn.eSuit);
                    if ((cCardOnPile != null &&  cCardInColumn.eRank == cCardOnPile.eRank + 1)
                        || (cCardOnPile == null && cCardInColumn.eRank == enuRanks.Ace))
                    {
                        // send card and quit 
                        lstColumn.Remove(cCardInColumn);
                        arrlstCards_Piles[(int)cCardInColumn.eSuit].Add(cCardInColumn);
                        cCardInColumn.eCardLocation = (enuCardLocation)(int)enuCardLocation.PileSpade + (int)cCardInColumn.eSuit;
                        cCardInColumn.cCardMotion.MoveTo(lstCardLocations[(int)cCardInColumn.eCardLocation]);
                        break;
                    }
                }
            }

            bolCollectingCards = bolFoundACardToMove;
            cEventTicket_CollectCards.AutoRepeat = true;
            DrawTable_AutoRepeat = true;
            DrawTable_TicketAutoRepeatSet();
        }

        private void PictureboxTable_MouseWheel(object sender, MouseEventArgs e)
        {
            float fltStep = 0.1f;

            switch (eDrawMode)
            {
                case enuDrawTableMode.About:
                case enuDrawTableMode.Strategy:
                    {
                        switch(ModifierKeys)
                        {
                            case Keys.Control:
                                {
                                    float fltZoomShift = 0.1f;
                                    if (e.Delta <0)
                                    {
                                        if (rtxDrawText.ZoomFactor > fltZoomShift)
                                        {
                                            rtxDrawText.ZoomFactor -= fltZoomShift;
                                        }
                                    }
                                    else
                                    {
                                        rtxDrawText.ZoomFactor += fltZoomShift;
                                    }
                                }
                                break;

                            default:
                                {
                                    if (e.Delta < 0)
                                    {
                                        scroll_Down();
                                    }
                                    else
                                    {
                                        scroll_Up();
                                    }
                                }
                                break;
                        }
                    }
                    break;

                case enuDrawTableMode.Game:
                    {
                        if (e.Delta < 0)
                        {
                            if (Zoom > fltStep)
                                Zoom -= fltStep;
                        }
                        else
                        {
                            if (Zoom < 5)
                                Zoom += fltStep;
                        }
                    }
                    break;
            }
        }

        enuCardLocation _eLocationUnderMouse = enuCardLocation.Null;
        enuCardLocation eLocationUnderMouse
        {
            get { return _eLocationUnderMouse; }
            set 
            {
                if (_eLocationUnderMouse != value)
                {
                    _eLocationUnderMouse = value;
                    //formSolitaire.instance.Text = eLocationUnderMouse.ToString();
                    DrawTable();
                }
            }
        }

        Point _ptMouse = new Point();
        Point ptMouse
        {
            get { return _ptMouse; }
            set
            {
                _ptMouse = value;
                classSweepAndPrune.classElement cEleUnderMouse = cSP.Search(ptMouse);
                if (cEleUnderMouse != null)
                {
                    enuSP_EleType eEleType = (enuSP_EleType)cEleUnderMouse.obj;
                    switch(eEleType)
                    {
                        case enuSP_EleType.Card:
                            {
                                if (cEleUnderMouse.tag != null)
                                    cCardUnderMouse = (classPlayingCard)cEleUnderMouse.tag;
                            }
                            break;

                        case enuSP_EleType.Region:
                            {
                                eLocationUnderMouse = (enuCardLocation)cEleUnderMouse.tag;
                                cCardUnderMouse = null;
                            }
                            break;

                    }

                    
                }
                else
                {
                    cCardUnderMouse = null;
                    eLocationUnderMouse = enuCardLocation.Null;
                }
            }
        }

        private void PictureboxTable_MouseMove(object sender, MouseEventArgs e)
        {
            ptMouse = new Point(e.X, e.Y);
            //countCards();
        }

        private void PictureboxTable_MouseUp(object sender, MouseEventArgs e)
        {
            //enuCardLocation eLocationNew = enuCardLocation.Null;
            enuCardLocation eLocationOld = enuCardLocation.Null;
            //countCards();
            if (cCardPlayerIsMoving != null)
            {
                if (cCardUnderMouse != null)
                {
                    switch (cCardUnderMouse.eCardLocation)
                    {
                        case enuCardLocation.Col0:
                        case enuCardLocation.Col1:
                        case enuCardLocation.Col2:
                        case enuCardLocation.Col3:
                        case enuCardLocation.Col4:
                        case enuCardLocation.Col5:
                        case enuCardLocation.Col6:
                            {
                                if (cCardUnderMouse.bolFaceUp)
                                {
                                    if (((cCardUnderMouse.eSuit == enuSuits.Heart || cCardUnderMouse.eSuit == enuSuits.Diamond)
                                                && (cCardPlayerIsMoving.eSuit == enuSuits.Club || cCardPlayerIsMoving.eSuit == enuSuits.Spade))
                                        ||
                                         ((cCardUnderMouse.eSuit == enuSuits.Club || cCardUnderMouse.eSuit == enuSuits.Spade)
                                                && (cCardPlayerIsMoving.eSuit == enuSuits.Heart || cCardPlayerIsMoving.eSuit == enuSuits.Diamond)))
                                    {
                                        if (cCardPlayerIsMoving.eRank == cCardUnderMouse.eRank - 1)
                                        {
                                            int intColumnUnderMouse = (int)cCardUnderMouse.eCardLocation - (int)enuCardLocation.Col0;
                                            eLocationOld = cCardPlayerIsMoving.eCardLocation;
                                            for (int intCardMovingCounter = 0; intCardMovingCounter < lstCardsPlayerIsMoving_Count; intCardMovingCounter++)
                                            {
                                                //classPlayingCard cCard =  lstCardsPlayerIsMoving[intCardMovingCounter];
                                                classPlayingCard cCard = lstCardsPlayerIsMove_Get(intCardMovingCounter);
                                                arrlstCards_Columns[intColumnUnderMouse].Add(cCard);
                                                cCard.eCardLocation = cCardUnderMouse.eCardLocation;
                                            }
                                            goto TurnOldColumnTopCardFaceUp;
                                        }
                                    }
                                }
                                goto fail;
                            }

                        case enuCardLocation.PileHeart:
                        case enuCardLocation.PileSpade:
                        case enuCardLocation.PileClub:
                        case enuCardLocation.PileDiamond:
                            {
                                int intPileIndex = (int)cCardUnderMouse.eCardLocation - (int)enuCardLocation.PileSpade;
                                if (intPileIndex >= 0 && intPileIndex < arrlstCards_Piles.Length)
                                {
                                    List<classPlayingCard> lstPile = arrlstCards_Piles[intPileIndex];
                                    classPlayingCard cCardOnTopOfPile = lstPile[lstPile.Count - 1];
                                    if (cCardOnTopOfPile.eSuit == cCardPlayerIsMoving.eSuit)
                                    {
                                        int intMovingCardValue = (int)cCardPlayerIsMoving.eRank;
                                        int intPileCardValue = (int)cCardOnTopOfPile.eRank;
                                        if (cCardPlayerIsMoving.eRank == cCardOnTopOfPile.eRank + 1)
                                        {
                                            // drop card onto pile 
                                            lstPile.Add(cCardPlayerIsMoving);
                                            eLocationOld = cCardPlayerIsMoving.eCardLocation;
                                            cCardPlayerIsMoving.eCardLocation = cCardUnderMouse.eCardLocation;
                                            goto TurnOldColumnTopCardFaceUp;
                                        }
                                    }
                                }
                                else
                                {
                                    ;
                                }
                                goto fail;
                            }
                    }
                }
                else if (eLocationUnderMouse != enuCardLocation.Null)
                {
                    switch (eLocationUnderMouse)
                    {
                        case enuCardLocation.Col0:
                        case enuCardLocation.Col1:
                        case enuCardLocation.Col2:
                        case enuCardLocation.Col3:
                        case enuCardLocation.Col4:
                        case enuCardLocation.Col5:
                        case enuCardLocation.Col6:
                            {
                                if (cCardPlayerIsMoving.eRank == enuRanks.King)
                                {
                                    int intColumnUnderMouse = (int)eLocationUnderMouse - (int)enuCardLocation.Col0;

                                    eLocationOld = cCardPlayerIsMoving.eCardLocation;
                                    while (lstCardsPlayerIsMoving_Count > 0)
                                    {
                                        //classPlayingCard cCard = lstCardsPlayerIsMoving[0];
                                        classPlayingCard cCard = lstCardsPlayerIsMove_Get(0);
                                        arrlstCards_Columns[intColumnUnderMouse].Add(cCard);
                                        //lstCardsPlayerIsMoving.Remove(cCard);
                                        lstCardsPlayerIsMoving_Remove(ref cCard);
                                        cCard.eCardLocation = eLocationUnderMouse;
                                    }
                                    goto TurnOldColumnTopCardFaceUp;
                                }
                                else
                                    goto fail;
                            }

                        case enuCardLocation.PileSpade:
                        case enuCardLocation.PileHeart:
                        case enuCardLocation.PileClub:
                        case enuCardLocation.PileDiamond:
                            {
                                enuSuits eSuitPile = (enuSuits)((int)eLocationUnderMouse - (int)enuCardLocation.PileSpade);
                                if (cCardPlayerIsMoving.eSuit == eSuitPile)
                                {
                                    int intPileIndex = (int)eLocationUnderMouse - (int)enuCardLocation.PileSpade;
                                    List<classPlayingCard> lstPile = arrlstCards_Piles[intPileIndex];
                                    lstPile.Add(cCardPlayerIsMoving);
                                    eLocationOld = cCardPlayerIsMoving.eCardLocation;
                                    cCardPlayerIsMoving.eCardLocation = eLocationUnderMouse;
                                    goto TurnOldColumnTopCardFaceUp;
                                }
                                goto fail;
                            }
                    }
                }
                else
                    ;
            }
        fail:

            // fail - return to original position 
            while (lstCardsPlayerIsMoving_Count > 0)
            {
                classPlayingCard cCard = lstCardsPlayerIsMove_Get(0);
                lstCardsPlayerIsMoving_Remove(ref cCard);

                switch (cCard.eCardLocation)
                {
                    case enuCardLocation.Col0:
                    case enuCardLocation.Col1:
                    case enuCardLocation.Col2:
                    case enuCardLocation.Col3:
                    case enuCardLocation.Col4:
                    case enuCardLocation.Col5:
                    case enuCardLocation.Col6:
                        {
                            int intColumn = (int)cCard.eCardLocation - (int)enuCardLocation.Col0;
                            if (intColumn >= 0 && intColumn < arrlstCards_Columns.Length)
                            {
                                List<classPlayingCard> lstCardReturn = arrlstCards_Columns[intColumn];
                                lstCardReturn.Add(cCard);
                            }
                            else
                            {
                                ;
                            }
                        }
                        break;

                    case enuCardLocation.PileSpade:
                    case enuCardLocation.PileHeart:
                    case enuCardLocation.PileClub:
                    case enuCardLocation.PileDiamond:
                        {
                            int intPile = (int)cCard.eCardLocation - (int)enuCardLocation.PileSpade;
                            if (intPile >= 0 && intPile < arrlstCards_Piles.Length)
                            {
                                List<classPlayingCard> lstCardReturn = arrlstCards_Piles[intPile];
                                lstCardReturn.Add(cCard);
                            }
                        }
                        break;

                    case enuCardLocation.Bank:
                        {   
                            lstCards_Bank.Add(cCard);
                        }
                        break;

                    default:
                        ;
                        break;
                }

            }
            DrawTable();
            TestIfGameIsOver();
            if (!bolDealingCards)
                countCards(true);
            return;

        TurnOldColumnTopCardFaceUp:
            {
                TurnOldColumnTopCardFaceUp(eLocationOld); 
                lstCardsPlayerIsMoving_Clear();
                DrawTable();
                TestIfGameIsOver();
                if (!bolDealingCards)
                    countCards(true);
                return;
            }
        }

        void TurnOldColumnTopCardFaceUp(enuCardLocation eCardLocation)
        {
            switch (eCardLocation)
            {
                case enuCardLocation.Col0:
                case enuCardLocation.Col1:
                case enuCardLocation.Col2:
                case enuCardLocation.Col3:
                case enuCardLocation.Col4:
                case enuCardLocation.Col5:
                case enuCardLocation.Col6:
                    { // turn top card if needed 
                        int intColumnSource = (int)eCardLocation - (int)enuCardLocation.Col0;
                        List<classPlayingCard> lstColumnSource = arrlstCards_Columns[intColumnSource];
                        if (lstColumnSource.Count > 0)
                        {
                            classPlayingCard cCardTopOfSourceColumn = lstColumnSource[lstColumnSource.Count - 1];
                            cCardTopOfSourceColumn.bolFaceUp = true;
                        }
                    }
                    break;
            }
        }

        Point ptGrabCard = new Point();
        private void PictureboxTable_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            if (bolGameOver)
            {
                FillPiles();
                return;
            }

            if (classPlayingCard.lstCardsInMotion.Count > 0 && cCardUnderMouse == null)
            {
                classPlayingCard.SendCardsToFinalPosition();
                bolQuickDeal = true;
                tmrDealCards_Tick((object)cEventTicket_DealCards, new EventArgs());
                DrawTable();
                return;
            }

            classPlayingCard cCardBeingDoubleClicked = cCardUnderMouse == null
                                                                        ? cCardPlayerIsMoving
                                                                        : cCardUnderMouse;
            lstCardsPlayerIsMoving_.Clear();

            switch (e.Button)
            {
                case MouseButtons.Left:
                    {
                        if (cCardBeingDoubleClicked != null)
                        {
                            if (lstCardsPlayerIsMoving_Count == 1 || cCardUnderMouse == cCardBeingDoubleClicked)
                            {
                                if (cCardBeingDoubleClicked.bolFaceUp)
                                {
                                    List<classPlayingCard> lstPileSuit = arrlstCards_Piles[(int)cCardBeingDoubleClicked.eSuit];
                                    if (lstPileSuit.Count > 0)
                                    {
                                        classPlayingCard cCardPileVisible = lstPileSuit[lstPileSuit.Count - 1];
                                        if (cCardPileVisible.eRank == cCardBeingDoubleClicked.eRank - 1)
                                        {
                                            /// remove it from its current list 
                                            switch (cCardBeingDoubleClicked.eCardLocation)
                                            {
                                                case enuCardLocation.Bank:
                                                    {
                                                        lstCards_Bank.Remove(cCardBeingDoubleClicked);
                                                    }
                                                    break;

                                                case enuCardLocation.Col0:
                                                case enuCardLocation.Col1:
                                                case enuCardLocation.Col2:
                                                case enuCardLocation.Col3:
                                                case enuCardLocation.Col4:
                                                case enuCardLocation.Col5:
                                                case enuCardLocation.Col6:
                                                    {
                                                        List<classPlayingCard> lstColumn = arrlstCards_Columns[(int)cCardBeingDoubleClicked.eCardLocation - (int)enuCardLocation.Col0];
                                                        lstColumn.Remove(cCardBeingDoubleClicked);
                                                        if (lstColumn.Count > 0)
                                                        {
                                                            lstColumn[lstColumn.Count - 1].bolFaceUp = true;
                                                        }
                                                    }
                                                    break;

                                                default:
                                                    {// this should never happen
                                                        ;
                                                    }
                                                    break;
                                            }
                                            Point ptPile = lstCardLocations[(int)enuCardLocation.PileSpade + (int)cCardBeingDoubleClicked.eSuit];
                                            cCardBeingDoubleClicked.cCardMotion.MoveTo(ptPile, 5);
                                            cCardBeingDoubleClicked.eCardLocation = (enuCardLocation)((int)enuCardLocation.PileSpade + cCardBeingDoubleClicked.eSuit);

                                            /// add it to its destined pile 
                                            lstPileSuit.Add(cCardBeingDoubleClicked);
                                            lstCardsPlayerIsMoving_Clear();
                                        }
                                    }
                                    else
                                    {
                                        if (cCardBeingDoubleClicked.eRank == enuRanks.Ace)
                                        {
                                            switch (cCardBeingDoubleClicked.eCardLocation)
                                            {
                                                case enuCardLocation.Bank:
                                                    {
                                                        lstCards_Bank.Remove(cCardBeingDoubleClicked);
                                                    }
                                                    break;

                                                case enuCardLocation.Col0:
                                                case enuCardLocation.Col1:
                                                case enuCardLocation.Col2:
                                                case enuCardLocation.Col3:
                                                case enuCardLocation.Col4:
                                                case enuCardLocation.Col5:
                                                case enuCardLocation.Col6:
                                                    {
                                                        List<classPlayingCard> lstColumn = arrlstCards_Columns[(int)cCardBeingDoubleClicked.eCardLocation - (int)enuCardLocation.Col0];
                                                        lstColumn.Remove(cCardBeingDoubleClicked);
                                                        if (lstColumn.Count > 0)
                                                        {
                                                            lstColumn[lstColumn.Count - 1].bolFaceUp = true;
                                                        }
                                                    }
                                                    break;

                                                default:
                                                    {// this should never happen
                                                        ;
                                                    }
                                                    break;
                                            }
                                            Point ptPile = lstCardLocations[(int)enuCardLocation.PileSpade + (int)cCardBeingDoubleClicked.eSuit];
                                            cCardBeingDoubleClicked.cCardMotion.MoveTo(ptPile, 5);
                                            cCardBeingDoubleClicked.eCardLocation = (enuCardLocation)((int)enuCardLocation.PileSpade + cCardBeingDoubleClicked.eSuit);

                                            /// add it to its destined pile 
                                            lstPileSuit.Add(cCardBeingDoubleClicked);

                                            lstCardsPlayerIsMoving_Clear();
                                        }
                                    }
                                }
                            }
                        }
                    }
                    break;
            }
        }

        private void PictureboxTable_MouseDown(object sender, MouseEventArgs e)
        {

            //countCards(true);
                classPlayingCard cCardUnderMouseRef = cCardUnderMouse;

            
            switch (e.Button)
            {
                case MouseButtons.Left:
                    {
                        if (cCardPlayerIsMoving == null)
                        {
                            if (cCardUnderMouse != null)
                            {
                                ptGrabCard = new Point(ptMouse.X - cCardUnderMouse.ptLocation.X, ptMouse.Y - cCardUnderMouse.ptLocation.Y);
                                switch (cCardUnderMouse.eCardLocation)
                                {
                                    case enuCardLocation.Stock:
                                        {
                                            MoveStockCardsToBank();
                                            return;
                                        }

                                    default:
                                        {
                                            lstCardsPlayerIsMoving_Add(ref cCardUnderMouseRef);
                                            DrawTable_TicketAutoRepeatSet();
                                        }
                                        break;
                                }

                                cCardUnderMouse = null;
                                switch (cCardPlayerIsMoving.eCardLocation)
                                {
                                    case enuCardLocation.Col0:
                                    case enuCardLocation.Col1:
                                    case enuCardLocation.Col2:
                                    case enuCardLocation.Col3:
                                    case enuCardLocation.Col4:
                                    case enuCardLocation.Col5:
                                    case enuCardLocation.Col6:
                                        {
                                            int intColumn = (int)cCardPlayerIsMoving.eCardLocation - (int)enuCardLocation.Col0;
                                            if (intColumn >= 0 && intColumn < arrlstCards_Columns.Length)
                                            {
                                                List<classPlayingCard> lstColumn = arrlstCards_Columns[intColumn];
                                                int intIndexCardMoving = lstColumn.IndexOf(cCardPlayerIsMoving);
                                                while (lstColumn.Count > intIndexCardMoving && lstColumn.Count >0)
                                                {
                                                    classPlayingCard cCardRemoving = lstColumn[intIndexCardMoving];
                                                    lstColumn.Remove(cCardRemoving);
                                                    if (!lstCardsPlayerIsMoving_Contains(ref cCardRemoving))
                                                        lstCardsPlayerIsMoving_Add(ref cCardRemoving);
                                                }
                                            }
                                            else
                                            {
                                                ;
                                            }
                                        }
                                        break;

                                    case enuCardLocation.Bank:
                                        {
                                            if (!lstCardsPlayerIsMoving_Contains(ref cCardUnderMouseRef) && cCardUnderMouse != null)
                                                lstCardsPlayerIsMoving_Add(ref cCardUnderMouseRef);
                                            lstCards_Bank.Remove(cCardPlayerIsMoving);
                                        }
                                        break;

                                    case enuCardLocation.PileClub:
                                    case enuCardLocation.PileSpade:
                                    case enuCardLocation.PileHeart:
                                    case enuCardLocation.PileDiamond:
                                        {

                                            int intSuit = (int)cCardPlayerIsMoving.eCardLocation - (int)enuCardLocation.PileSpade;
                                            if (intSuit >= 0 && intSuit < arrlstCards_Piles.Length)
                                            {
                                                arrlstCards_Piles[intSuit].Remove(cCardPlayerIsMoving);
                                            }
                                            else
                                            {
                                                ;
                                            }
                                        }
                                        break;

                                    case enuCardLocation.Stock:
                                        {
                                            MoveStockCardsToBank();

                                        }
                                        break;
                                }
                            }
                            else
                            {
                                switch (eLocationUnderMouse)
                                {
                                    case enuCardLocation.rtxDrawText:
                                        {
                                            eDrawMode = enuDrawTableMode.Game;
                                        }
                                        break;

                                    case enuCardLocation.Stock:
                                        {
                                            MoveStockCardsToBank();
                                        }
                                        break;

                                    case enuCardLocation.StockButton:
                                        {
                                            while (lstCards_Stock.Count >= 3)
                                                MoveStockCardsToBank();
                                        }
                                        break;

                                    case enuCardLocation.Statistics:
                                        {
                                            bolDrawStatistics = !bolDrawStatistics;
                                        }
                                        break;
                                }
                            }
                        }
                    }
                    break;

                case MouseButtons.Right:
                    {
                        if (cCardPlayerIsMoving == null)
                        {
                            if (cCardUnderMouse != null && lstCardsPlayerIsMoving_Contains(ref cCardUnderMouseRef))
                            {
                                if (cCardUnderMouse.bolFaceUp)
                                {
                                    List<classPlayingCard> lstPileSuit = arrlstCards_Piles[(int)cCardUnderMouse.eSuit];
                                    if (lstPileSuit.Count > 0)
                                    {
                                        classPlayingCard cCardPileVisible = lstPileSuit[lstPileSuit.Count - 1];
                                        if (cCardPileVisible.eRank == cCardUnderMouse.eRank - 1)
                                        {
                                            Point ptPile = lstCardLocations[(int)enuCardLocation.PileSpade + (int)cCardUnderMouse.eSuit];
                                            cCardUnderMouse.cCardMotion.MoveTo(ptPile);
                                            cCardUnderMouse.eCardLocation = (enuCardLocation)((int)enuCardLocation.PileSpade + cCardUnderMouse.eSuit);

                                            /// remove it from its current list 
                                            switch(cCardUnderMouse.eCardLocation)
                                            {
                                                case enuCardLocation.Bank:
                                                    {
                                                        lstCards_Bank.Remove(cCardUnderMouse);
                                                    }
                                                    break;

                                                case enuCardLocation.Col0:
                                                case enuCardLocation.Col1:
                                                case enuCardLocation.Col2:
                                                case enuCardLocation.Col3:
                                                case enuCardLocation.Col4:
                                                case enuCardLocation.Col5:
                                                case enuCardLocation.Col6:
                                                    {
                                                        List<classPlayingCard> lstColumn = arrlstCards_Columns[(int)cCardUnderMouse.eCardLocation];
                                                        lstColumn.Remove(cCardUnderMouse);
                                                    }
                                                    break;

                                                default:
                                                    {// this should never happen
                                                        ;
                                                    }
                                                    break;
                                            }

                                            /// add it to its destined pile 
                                            lstPileSuit.Add(cCardUnderMouse);
                                        }
                                    }
                                }
                            }
                        }
                    }
                    break;
            }
            if (!bolDealingCards)
                countCards(true);
            TestIfGameIsOver();
        }

        
        void MoveStockCardsToBank()
        {
            //countCards(true);

            if (lstCards_Stock.Count >=3 ||(lstCards_Stock.Count <3 && lstCards_Bank.Count ==0) )
            { // move 3 cards to Bank 
                for (int intStockCounter = 0; intStockCounter < 3 && lstCards_Stock.Count >0; intStockCounter++)
                {
                    classPlayingCard cCardMovingToBank = lstCards_Stock[lstCards_Stock.Count - 1];
                    cCardMovingToBank.BankIndex = intStockCounter;
                    lstCards_Stock.Remove(cCardMovingToBank);
                    cCardMovingToBank.bolFaceUp = true;
                    cCardUnderMouse = null;
                    cCardMovingToBank.eCardLocation = enuCardLocation.Bank;
                    lstCards_Bank.Add(cCardMovingToBank);

                    //countCards(true);
                }
            }
            else
            {
                // gather Bank cards into stock 
                while (lstCards_Bank.Count > 0)
                {
                    classPlayingCard cCardMovingToStock = lstCards_Bank[0];
                    lstCards_Bank.Remove(cCardMovingToStock);
                    cCardMovingToStock.bolFaceUp = false;
                    cCardMovingToStock.eCardLocation = enuCardLocation.Stock;
                    lstCards_Stock.Insert(0, cCardMovingToStock);
                    //countCards(true);
                }
            }

            TestIfGameIsOver();

            //countCards(true);
        }
        int ColumnsCardsRemaining()
        {
            int intRetVal = 0;
            for (int intcolumnCounter = 0; intcolumnCounter < arrlstCards_Columns.Length; intcolumnCounter++)
            {
                intRetVal += arrlstCards_Columns[intcolumnCounter].Count;
            }
            return intRetVal;
        }

        bool TestIfGameIsOver()
        {
            if (bolGameOver) return false;

            if (lstCards_Stock.Count == 0
              && lstCards_Bank.Count == 0
              && CardsInColumns_NumFaceDown() == 0
              && cCardPlayerIsMoving == null
              && ColumnsCardsRemaining() >0)
            {
                lstDeckReplay.Clear();
                bolGameOver = true;
                CollectCards();
                return true;
            } 
            return false;
        }

        //bool CanPlayerMoveACard()
        //{
        //    // test columns
        //    for (int intColumnCounter =0; intColumnCounter < arrlstCards_Columns.Length; intColumnCounter++)
        //    {
        //        List<classPlayingCard> lstColumn = arrlstCards_Columns[intColumnCounter];
        //        if (lstColumn.Count >0)
        //        {
        //            classPlayingCard cCard = lstColumn[lstColumn.Count-1];
        //            if (canCardMoveAnywhere(cCard))
        //                return true;
        //        }
        //    }

        //    // test Stock 
        //    List<classPlayingCard> lstStockTest = new List<classPlayingCard>();
        //    lstStockTest.AddRange(lstCards_Stock);
        //    lstStockTest.AddRange(lstCards_Bank);

        //    if (lstStockTest.Count %3 ==0)
        //    {

        //    }



        //    return false;   
        //}

        bool SuitsAreOpposite(enuSuits eSuit1, enuSuits eSuit2)
        {
            switch (eSuit1)
            {
                case enuSuits.Diamond:
                case enuSuits.Heart:
                    return eSuit2 == enuSuits.Club || eSuit2 == enuSuits.Spade;

                default:
                case enuSuits.Club:
                case enuSuits.Spade:
                    return eSuit2 == enuSuits.Heart || eSuit2 == enuSuits.Diamond;
            }
        }


        //bool canCardMoveAnywhere(classPlayingCard cCard)
        //{
        //    for (int intColumnCounter = 0; intColumnCounter < arrlstCards_Columns.Length; intColumnCounter++)
        //    {
        //        List<classPlayingCard> lstColumn = arrlstCards_Columns[intColumnCounter];
        //        if (lstColumn.Count > 0)
        //        {
        //            classPlayingCard cCardOnColumn = lstColumn[lstColumn.Count-1];
        //            if (SuitsAreOpposite(cCard.eSuit, cCardOnColumn.eSuit))
        //            {
        //                if (cCard.eRank == cCardOnColumn.eRank + 1)
        //                    return true;
        //            }
        //        }
        //    }




        //    return false;

        //}


        public bool GameIsWon()
        {
            return lstCards_Stock.Count == 0
                && lstCards_Bank.Count == 0
                && CardsInColumns_NumFaceDown() == 0
                && cCardPlayerIsMoving == null
                && arrlstCards_Piles[0].Count
                    + arrlstCards_Piles[1].Count
                    + arrlstCards_Piles[2].Count
                    + arrlstCards_Piles[3].Count == 52;
        }

        int CardsInColumns_NumFaceDown()
        {
            int intRetVal = 0;
            for (int intColumnCounter = 0; intColumnCounter < arrlstCards_Columns.Length; intColumnCounter++)
            {
                List<classPlayingCard> lstPlayingCards = arrlstCards_Columns[intColumnCounter];
                for (int intCardCounter = 0; intCardCounter < lstPlayingCards.Count; intCardCounter++)
                {
                    classPlayingCard cCard = lstPlayingCards[intCardCounter];
                    if (!cCard.bolFaceUp)
                        intRetVal += 1;
                }
            }
            
            return intRetVal;
        }


        void CollectCards()
        {
            classStatistics.GamesPlayed++;
            classStatistics.Wins++;

            classStatistics.WinStreak++;

            bolDrawStatistics = true;
            cEventTicket_CollectCards.AutoRepeat = true;
            DrawTable_AutoRepeat = true;
        }

        List<classPlayingCard> _lstCardsPlayerIsMoving_ = new List<classPlayingCard>();
        List<classPlayingCard> lstCardsPlayerIsMoving_
        {
            get { return _lstCardsPlayerIsMoving_; }
        }

        void lstCardsPlayerIsMoving_AddRange(ref List<classPlayingCard> lstAdd)
        {
            lstCardsPlayerIsMoving_.AddRange(lstAdd);
            DrawTable_TicketAutoRepeatSet();
        }

        void lstCardsPlayerIsMoving_Add(ref classPlayingCard cCardAdd)
        {
            lstCardsPlayerIsMoving_.Add(cCardAdd);
            DrawTable_TicketAutoRepeatSet();
        }


        static void lstCardsPlayerIsMoving_Clear()
        {
            instance.lstCardsPlayerIsMoving_.Clear();
            instance.DrawTable_TicketAutoRepeatSet();
        }

        int lstCardsPlayerIsMoving_Count
        {
            get { return lstCardsPlayerIsMoving_.Count; }
        }

        bool lstCardsPlayerIsMoving_Contains(ref classPlayingCard cCard)
        {
            return lstCardsPlayerIsMoving_.Contains(cCard);
        }

        classPlayingCard  lstCardsPlayerIsMove_Get(int intIndex)
        {
            if (intIndex >= 0 && intIndex < lstCardsPlayerIsMoving_Count)
                return _lstCardsPlayerIsMoving_[intIndex];
            return null;
        }

        void lstCardsPlayerIsMoving_Remove(ref classPlayingCard cCardRemove)
        {
            lstCardsPlayerIsMoving_.Remove(cCardRemove);
            DrawTable_TicketAutoRepeatSet();
        }

        void DrawTable_TicketAutoRepeatSet()
        {
            DrawTable_AutoRepeat = classPlayingCard.lstCardsInMotion.Count >0 
                                                || bolDealingCards
                                                || bolCollectingCards
                                                || classAnimation_Intro_Item.lst.Count >0
                                                || lstCardsPlayerIsMoving_Count >0;
        }


        
        classPlayingCard cCardPlayerIsMoving
        {
            get 
            {
                if (lstCardsPlayerIsMoving_ == null || lstCardsPlayerIsMoving_.Count == 0)
                    return null;
                return lstCardsPlayerIsMoving_[0];
            }
        }

        classPlayingCard _cCardUnderMouse = null;
        classPlayingCard cCardUnderMouse
        {
            get { return _cCardUnderMouse; }
            set 
            {
                if (_cCardUnderMouse != value)
                {
                    _cCardUnderMouse = value;
                    DrawTable();
                }
            }
        }

        bool bolContextMenuVisible = false;

        private void ContextMenuStrip_Closing(object sender, ToolStripDropDownClosingEventArgs e)
        {
            bolContextMenuVisible = false;
        }

        private void ContextMenuStrip_Opening(object sender, System.ComponentModel.CancelEventArgs e)
        {
            bolContextMenuVisible = true;
            ContextMenuStrip.Items.Clear();
            if (formSolitaire.bolDebug)
            {
                ToolStripMenuItem tsiDebug = new ToolStripMenuItem("Debug");
                {
                    ToolStripItem tsiUpdate = new ToolStripMenuItem("Update");
                    tsiUpdate.Click += tsiUpdate_Click;
                    tsiDebug.DropDownItems.Add(tsiUpdate);

                    ToolStripItem tsiDebug_SetupCards = new ToolStripMenuItem("set up debug cards");
                    tsiDebug_SetupCards.Click += TsiDebug_SetupCards_Click;
                    tsiDebug.DropDownItems.Add(tsiDebug_SetupCards);

                    ToolStripItem tsiSaveGameState = new ToolStripMenuItem("Save Game State");
                    tsiSaveGameState.Click += tsiSaveGameSate_Click;
                    tsiDebug.DropDownItems.Add(tsiSaveGameState);

                    ToolStripItem tsiLoadGameState = new ToolStripMenuItem("Load Game State");
                    tsiLoadGameState.Click += tsiLoadGameSate_Click;
                    tsiDebug.DropDownItems.Add(tsiLoadGameState);

                }
                ContextMenuStrip.Items.Add(tsiDebug);
            }

            ToolStripItem tsiNewGame= new ToolStripMenuItem("NewGame");
            tsiNewGame.Click += tsiNewGame_Click;
            ContextMenuStrip.Items.Add(tsiNewGame);
            
            if (lstDeckReplay.Count == 52)
            {
                ToolStripItem tsiReplayGame = new ToolStripMenuItem("ReplayGame");
                tsiReplayGame.Click += tsiReplayGame_Click;
                ContextMenuStrip.Items.Add(tsiReplayGame);
            }

            ToolStripItem tsiStatistics = new ToolStripMenuItem("Statistics");
            tsiStatistics.Click += tsiStatistics_Click;
            ContextMenuStrip.Items.Add(tsiStatistics);
            
            ToolStripItem tsiAbout = new ToolStripMenuItem("About");
            tsiAbout.Click += tsiAbout_Click;
            ContextMenuStrip.Items.Add(tsiAbout);
            
            ToolStripItem tsiStrategy = new ToolStripMenuItem("Strategy");
            tsiStrategy.Click += tsiStrategy_Click;
            ContextMenuStrip.Items.Add(tsiStrategy);

            ToolStripItem tsiQuit = new ToolStripMenuItem("Quit");
            tsiQuit.Click += tsiQuit_Click;
            ContextMenuStrip.Items.Add(tsiQuit);
        }

        private void TsiDebug_SetupCards_Click(object sender, EventArgs e)
        {
            lstCards_Stock.Clear();
            lstCards_Bank.Clear();
            lstCardsPlayerIsMoving_Clear();
            arrLstCards_ColumnsPiles_Clear();

            for (int intSuitCounter = 0; intSuitCounter < 4; intSuitCounter ++)
            {
                if (intSuitCounter < 3)
                {
                    // add all cards to suit pile 
                    for (int intRankCounter = 0; intRankCounter < 13; intRankCounter++)
                    {
                        classPlayingCard cCard = classPlayingCard.arrCardSuits[intSuitCounter][intRankCounter];
                        cCard.bolFaceUp = true;
                        cCard.eCardLocation = (enuCardLocation)((int)enuCardLocation.PileSpade + intSuitCounter);
                        arrlstCards_Piles[intSuitCounter].Add(cCard);
                    }
                }
                else
                {
                    // spread all diamond cards across columns 
                    List<classPlayingCard> lstDiamonds = new List<classPlayingCard>();
                    lstDiamonds.AddRange(classPlayingCard.arrCardSuits[intSuitCounter]);
                    int intColumnCounter = 0;
                    classPlayingCard cKingDiamonds = lstDiamonds[lstDiamonds.Count -1];
                    lstDiamonds.Remove(cKingDiamonds);
                    lstCards_Bank.Add(cKingDiamonds);
                    cKingDiamonds.eCardLocation = enuCardLocation.Bank;

                    while (lstDiamonds.Count > 0)
                    {
                        classPlayingCard cCard = lstDiamonds[lstDiamonds.Count - 1];
                        cCard.bolFaceUp = true;
                        cCard.eCardLocation = (enuCardLocation)((int)enuCardLocation.Col0 + intColumnCounter);

                        lstDiamonds.Remove(cCard);
                        arrlstCards_Columns[intColumnCounter].Add(cCard);

                        intColumnCounter = (intColumnCounter + 1) % 6;
                    }
                }
            }
        }

        void tsiStatistics_Click(object sender, EventArgs e)
        {
            bolDrawStatistics = !bolDrawStatistics;
        }

        
        

        /// <summary>
        /// https://docs.microsoft.com/en-us/answers/questions/753327/send-mousescroll-from-picturebox-to-richtextbox.html
        /// this was used to let the mousewheel event on the WordMap picturebox simulate a MouseWheel event on RTX editor in use
        /// </summary>
        /// <param name="hWnd"></param>
        /// <param name="msg"></param>
        /// <param name="wParam"></param>
        /// <param name="lParam"></param>
        /// <returns></returns>
        [DllImport("User32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        public static extern int SendMessage(IntPtr hWnd, uint msg, int wParam, IntPtr lParam);

        public void scroll_Up()
        {
            SendMessage(rtxDrawText.Handle, WM_VSCROLL, (int)MakeWord(SB_LINEUP, 0), IntPtr.Zero);
        }
        public void scroll_Down()
        {
            SendMessage(rtxDrawText.Handle, WM_VSCROLL, (int)MakeWord(SB_LINEDOWN, 0), IntPtr.Zero);
        }

        public const int WM_VSCROLL = 0x0115;
        public const int SB_LINEUP = 0;
        public const int SB_LINEDOWN = 1;

        public static uint MakeWord(byte low, byte high)
        {
            return ((uint)high << 8) | low;
        }


        //string strAbout_Filename = "";
        //string About_Filename
        //{
        //    get
        //    {
        //        if (strAbout_Filename == null || strAbout_Filename.Length == 0)
        //            strAbout_Filename = System.IO.Directory.GetCurrentDirectory() + "\\Solitaire - About.rtf";
        //        return strAbout_Filename;
        //    }
        //}

        void About_LoadRtf()
        {
            float fltRtxZoom = rtxDrawText.ZoomFactor;

             /*
            if (System.IO.File.Exists(About_Filename))
            {
                rtxDrawText.LoadFile(About_Filename);

            }
            /*/
            rtxDrawText.Rtf = @"{\rtf1\ansi\deff3\adeflang1025
{\fonttbl{\f0\froman\fprq2\fcharset0 Times New Roman;}{\f1\froman\fprq2\fcharset2 Symbol;}{\f2\fswiss\fprq2\fcharset0 Arial;}{\f3\froman\fprq2\fcharset0 Liberation Serif{\*\falt Times New Roman};}{\f4\froman\fprq2\fcharset0 Liberation Sans{\*\falt Arial};}{\f5\froman\fprq2\fcharset0 Cascadia Mono;}{\f6\fnil\fprq2\fcharset0 0;}{\f7\fnil\fprq2\fcharset0 Microsoft YaHei;}{\f8\fnil\fprq2\fcharset0 Arial;}}
{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;}
{\stylesheet{\s0\snext0\rtlch\af8\afs24\alang1081 \ltrch\lang4105\langfe2052\hich\af3\loch\widctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang4105\kerning1\dbch\af6\langfe2052 Normal;}
{\s15\sbasedon0\snext16\rtlch\af8\afs28 \ltrch\hich\af4\loch\sb240\sa120\keepn\f4\fs28\dbch\af7 Heading;}
{\s16\sbasedon0\snext16\loch\sl276\slmult1\sb0\sa140 Body Text;}
{\s17\sbasedon16\snext17\rtlch\af8 \ltrch\loch\sl240\slmult1\sb0\sa0 List;}
{\s18\sbasedon0\snext18\rtlch\af8\afs24\ai \ltrch\loch\sb120\sa120\fs24\i caption;}
{\s19\sbasedon0\snext19\rtlch\af8 \ltrch Index;}
}{\*\generator LibreOffice/25.2.5.2$Windows_X86_64 LibreOffice_project/03d19516eb2e1dd5d4ccd751a0d6f35f35e08022}{\info{\creatim\yr2025\mo8\dy16\hr11\min37}{\revtim\yr2025\mo8\dy16\hr12\min23}{\printim\yr0\mo0\dy0\hr0\min0}}{\*\userprops}\deftab709
\hyphauto1\viewscale110\formshade\paperh15840\paperw12240\margl1134\margr1134\margt1134\margb1134\sectd\sbknone\sftnnar\saftnnrlc\sectunlocked1\pgwsxn12240\pghsxn15840\marglsxn1134\margrsxn1134\margtsxn1134\margbsxn1134\ftnbj\ftnstart1\ftnrstcont\ftnnar\fet\aftnrstcont\aftnstart1\aftnnrlc
{\*\ftnsep\chftnsep}\pgndec\pard\plain \s0\rtlch\af8\afs24\alang1081 \ltrch\lang4105\langfe2052\hich\af3\loch\widctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang4105\kerning1\dbch\af6\langfe2052\ql\fi420{\hich\af5\loch\cf7\fs19\lang1033\ul\ulc0\chcbpat8\f5\loch
About Solitaire}
\par \pard\plain \s0\rtlch\af8\afs24\alang1081 \ltrch\lang4105\langfe2052\hich\af3\loch\widctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang4105\kerning1\dbch\af6\langfe2052\ql\fi420{\hich\af5\loch\cf7\fs19\lang1033\chcbpat8\f5\loch
Solitaire, also known as Patience, evolved out of boredom, go Fish ennui and Old Maid apathy, competitive Patience never caught on, but petitions have been raised to convince the World Olympic Committee reappraise the game's solitary importance and finally include it in the games. }
\par \pard\plain \s0\rtlch\af8\afs24\alang1081 \ltrch\lang4105\langfe2052\hich\af3\loch\widctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang4105\kerning1\dbch\af6\langfe2052\ql\fi420{\hich\af5\loch\cf7\fs19\lang1033\chcbpat8\f5\loch
T}{\hich\af5\loch\cf7\fs19\lang1033\chcbpat8\f5\loch
he board is comprised of seven columns of face down cards, dealt with one card face up }{\hich\af5\loch\cf7\fs19\lang1033\chcbpat8\f5\loch
located}{\hich\af5\loch\cf7\fs19\lang1033\chcbpat8\f5\loch
 at the top of the screen, four suits of empty foundation piles, and the face down stock. }{\hich\af5\loch\cf7\fs19\lang1033\chcbpat8\f5\loch
T}{\hich\af5\loch\cf7\fs19\lang1033\chcbpat8\f5\loch
he }{\hich\af5\loch\cf7\fs19\lang1033\chcbpat8\f5\loch
player}{\hich\af5\loch\cf7\fs19\lang1033\chcbpat8\f5\loch
 will then turn three cards from the stock to the bank stack at the bottom right of the screen and, alternat}{\hich\af5\loch\cf7\fs19\lang1033\chcbpat8\f5\loch
ing}{\hich\af5\loch\cf7\fs19\lang1033\chcbpat8\f5\loch
 between red and black cards on the columns in descending order of value, }{\hich\af5\loch\cf7\fs19\lang1033\chcbpat8\f5\loch
attempt }{\hich\af5\loch\cf7\fs19\lang1033\chcbpat8\f5\loch
to gather all the cards of the same suit, in ascending order from Ace to King, onto the four foundation piles.}
\par \pard\plain \s0\rtlch\af8\afs24\alang1081 \ltrch\lang4105\langfe2052\hich\af3\loch\widctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang4105\kerning1\dbch\af6\langfe2052\ql\fi420{\hich\af5\loch\cf7\fs19\lang1033\chcbpat8\f5\loch
M}{\hich\af5\loch\cf7\fs19\lang1033\chcbpat8\f5\loch
ay you vanquish apathy's languid doldrums forevermore, }
\par \pard\plain \s0\rtlch\af8\afs24\alang1081 \ltrch\lang4105\langfe2052\hich\af3\loch\widctlpar\hyphpar0\ltrpar\cf0\f3\fs24\lang4105\kerning1\dbch\af6\langfe2052\qr\fi420{\hich\af5\loch\cf7\fs19\lang1033\chcbpat8\f5\loch
Christ King Kennedy}
\par }";


            while (rtxDrawText.ZoomFactor != fltZoom)
                rtxDrawText.ZoomFactor = fltZoom;
            rtxDrawText.Select(0, 0);
            rtxDrawText.ScrollToCaret();
            // */
        }

        void Strategy_LoadRtf()
        {
            float fltZoom = rtxDrawText.ZoomFactor;
             /*
            if (System.IO.File.Exists(Strategy_Filename))
            {
                rtxDrawText.LoadFile(Strategy_Filename);

            }
            /*/
            rtxDrawText.Rtf = @"{\rtf1\ansi\ansicpg1252\deff0\nouicompat{\fonttbl{\f0\fnil\fcharset0 Arial;}{\f1\fnil Arial;}}
{\colortbl ;\red255\green255\blue0;\red255\green255\blue255;}
{\*\generator Riched20 10.0.26100}\viewkind4\uc1 
\pard\hyphpar0\widctlpar\fi270\cf1\highlight2\kerning1\ul\fs20\lang1033 Solitaire Strategies\ulnone  \par
In order to solve the puzzle of Solitaire you must accomplish 3 objectives :\par
objective 1 - all the face down cards in the columns must be turned face up. \par
objective 2 - all stock/bank cards must be added to the columns \par
objective 3 - all column cards must move to suit piles \par
\ul\par
Objective 1\ulnone\par
The cards in your hands, the stock and bank piles on the screen, are your resources. These are assets. They are your tools and currency.  During the first objective of the game, you must consider the 'cost' of expending resources for the gained 'value' of turning column cards.  Your best move is to 'spend' the least amount of stock/bank resources in order to turn the most amount of hidden column cards face up.\par
Turning three stock cards onto the pile at a time, you can view the contents of your accounts and see the sequence in which the cards will appear. As a multiple of 3x cards in your stock and bank means you will not 'cycle' through all the cards,  having a multiple of three cards in your accounts means that you will lose access to two thirds of your resources.  \par
You should at all times avoid holding a multiple of three cards, and so, be certain to plan on being able to discard a second card in the upcoming sequence when you find yourself with only one spare card in your wealth of resources. For this reason then, it is best to keep bank cards where they are and refrain from wasting these assets because a spare card may be needed later on when trying to evade a multiple of 3, during any phase of the game.\par
As long as you avoid multiples of three you will be able to cycle through all your cards. In order to safely shun any crippling multiple of three, it is best to always refresh your accounts and display all of your resources, before making your next move.\par
\par
\ul Objective 2\ulnone\f1\par
\f0 During this phase, as all your column cards are now face up and available to you in ascending order, your objective here is to make certain you move your bank cards to either a pile or column without locking yourselve in a multiple of 3 cards situation, as described above.  This is usually most easily done by moving cards from your bank resources in ascending order. Starting with any Ace, two or three still found in your accounts, you gradually make your way up the ranks, until all the cards have been moved.\par
\par
\ul Objective 3\ulnone  \par
The game will collect the cards from here, you've already won.\par
\par

\pard\hyphpar0\widctlpar\fi270\qr Christ King Kennedy}
";
            // */

            while (rtxDrawText.ZoomFactor != fltZoom)
                rtxDrawText.ZoomFactor = fltZoom;
            rtxDrawText.Select(0, 0);
            rtxDrawText.ScrollToCaret();
        }

        RichTextBox rtxDrawText = new RichTextBox();
        Bitmap _bmpRtxDrawText = null;
        Bitmap bmpRtxDrawText
        {
            get
            {
                if (_bmpRtxDrawText != null)
                {
                    if (_bmpRtxDrawText.Width != rtxDrawText.Width
                        ||
                        _bmpRtxDrawText.Height != rtxDrawText.Height)
                    {
                        _bmpRtxDrawText.Dispose();
                        _bmpRtxDrawText = null;
                    }
                }
                if (_bmpRtxDrawText == null)
                {
                    _bmpRtxDrawText = new Bitmap(rtxDrawText.Width, rtxDrawText.Height);
                }

                rtxDrawText.DrawToBitmap(_bmpRtxDrawText, new Rectangle(0, 0, rtxDrawText.Width, rtxDrawText.Height));
                _bmpRtxDrawText.MakeTransparent(_bmpRtxDrawText.GetPixel(2, 2));
                //_bmpRtxDrawText.Save(@"c:\debug\bmpDrawText.png");
                return _bmpRtxDrawText;
            }
        }



        void tsiAbout_Click(object sender, EventArgs e)
        {
            switch (eDrawMode)
            {
                case enuDrawTableMode.About:
                    eDrawMode = enuDrawTableMode.Game;
                    break;

                default:
                    eDrawMode = enuDrawTableMode.About;
                    break;
            }
        }
         


        void tsiStrategy_Click(object sender, EventArgs e)
        {
            switch (eDrawMode)
            {
                case enuDrawTableMode.Strategy:
                    eDrawMode = enuDrawTableMode.Game;
                    break;

                default:
                    eDrawMode = enuDrawTableMode.Strategy;
                    break;
            }
        }
         

        void tsiSaveGameSate_Click(object sender, EventArgs e)
        {
            debug_SaveGame();
        }

        void tsiLoadGameSate_Click(object sender, EventArgs e)
        {
            debug_LoadGame();
            DrawTable();
        }

        void tsiReplayGame_Click(object sender,  EventArgs e)
        {
            if (MessageBox.Show("Quit game and replay?", "quit?", MessageBoxButtons.YesNo) == DialogResult.Yes)
                Replay();
        }

        void tsiNewGame_Click(object sender, EventArgs e)
        {
            if (!GameIsWon())
            {
                if (MessageBox.Show("Quit game?", "quit", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.No)
                    return;
                classStatistics.GamesPlayed++;
                classStatistics.WinStreak = 0;
            }

            NewGame();
        }

        private void tsiUpdate_Click(object sender, EventArgs e)
        {
            formCodeUpdateJournal.instance.Show();
        }

        private void tsiQuit_Click(object sender, EventArgs e)
        {
            formSolitaire.instance.Close();
        }

        void tmrDrawTable_Tick(object sender, EventArgs e)
        {
            DrawTable();
        }

        private void PictureboxTable_SizeChanged(object sender, EventArgs e)
        {
            ResetCardLocations();
            rtxDrawText_SetSize();
        }

        void rtxDrawText_SetSize()
        {
            rtxDrawText.Size = new Size((int)(Width * .4), (int)(Height * .8));
        }

        static float fltZoom = 1f;
        static public float Zoom
        {
            get { return fltZoom; }
            set 
            {
                fltZoom = value;
                if (instance != null)
                   instance.ResetCardLocations();
            }
        }

        void ResetCardLocations()
        {
            ///*
            int intCardWidth = (int)(Zoom * (float)Width / 10f);            
            float fltAR = (float)classPlayingCard.szCard_base.Height / (float)classPlayingCard.szCard_base.Width;
            int intCardHeight = (int)(fltAR * (float)intCardWidth);
            szCard = new Size(intCardWidth, intCardHeight);
            /*/
            int intCardHeight = (int)(fltZoom *(float) Height / 10f);
            float fltAR = (float)classPlayingCard.szCard_base.Height / (float)classPlayingCard.szCard_base.Width;
            int intCardWidth= (int)((float)intCardHeight/ fltAR);
            szCard = new Size(intCardWidth, intCardHeight);
            // */
            lstCardLocations.Clear();

            int intNumCardLocation = Enum.GetNames(typeof(enuCardLocation)).Length;
            int intGap = 5;
            for(int intCardLocationCounter =0; intCardLocationCounter < intNumCardLocation; intCardLocationCounter++)
            {
                enuCardLocation eCardLocation = (enuCardLocation)intCardLocationCounter;
                switch(eCardLocation)
                {
                    case enuCardLocation.PileSpade:
                        {
                            Point ptFSpade = new Point(intGap, Height - szCard.Height);
                            lstCardLocations.Add(ptFSpade);
                        }
                        break;

                    case enuCardLocation.PileHeart:
                        {
                            Point ptFHeart = new Point(lstCardLocations[(int)enuCardLocation.PileSpade].X + szCard.Width + intGap,
                                                       lstCardLocations[(int)enuCardLocation.PileSpade].Y);
                            lstCardLocations.Add(ptFHeart);
                        }
                        break;

                    case enuCardLocation.PileClub:
                        {
                            Point ptFClub= new Point(lstCardLocations[(int)enuCardLocation.PileHeart].X + szCard.Width + intGap,
                                                       lstCardLocations[(int)enuCardLocation.PileHeart].Y);
                            lstCardLocations.Add(ptFClub);
                        }
                        break;

                    case enuCardLocation.PileDiamond:
                        {
                            Point ptFDiamond = new Point(lstCardLocations[(int)enuCardLocation.PileClub].X + szCard.Width + intGap,
                                                       lstCardLocations[(int)enuCardLocation.PileClub].Y);
                            lstCardLocations.Add(ptFDiamond);
                        }
                        break;

                    case enuCardLocation.Col0:
                        {
                            Point ptCol0 = new Point(intGap, intGap);
                            lstCardLocations.Add(ptCol0);
                        }
                        break;

                    case enuCardLocation.Col1:
                        {
                            Point ptCol1 = new Point(lstCardLocations[(int)enuCardLocation.Col0].X + szCard.Width + intGap,
                                                     lstCardLocations[(int)enuCardLocation.Col0].Y);
                            lstCardLocations.Add(ptCol1);
                        }
                        break;

                    case enuCardLocation.Col2:
                        {
                            Point ptCol2 = new Point(lstCardLocations[(int)enuCardLocation.Col1].X + szCard.Width + intGap,
                                                     lstCardLocations[(int)enuCardLocation.Col1].Y);
                            lstCardLocations.Add(ptCol2);
                        }
                        break;

                    case enuCardLocation.Col3:
                        {
                            Point ptCol3 = new Point(lstCardLocations[(int)enuCardLocation.Col2].X + szCard.Width + intGap,
                                                     lstCardLocations[(int)enuCardLocation.Col2].Y);
                            lstCardLocations.Add(ptCol3);
                        }
                        break;

                    case enuCardLocation.Col4:
                        {
                            Point ptCol4 = new Point(lstCardLocations[(int)enuCardLocation.Col3].X + szCard.Width + intGap,
                                                     lstCardLocations[(int)enuCardLocation.Col3].Y);
                            lstCardLocations.Add(ptCol4);
                        }
                        break;

                    case enuCardLocation.Col5:
                        {
                            Point ptCol5 = new Point(lstCardLocations[(int)enuCardLocation.Col4].X + szCard.Width + intGap,
                                                     lstCardLocations[(int)enuCardLocation.Col4].Y);
                            lstCardLocations.Add(ptCol5);
                        }
                        break;

                    case enuCardLocation.Col6:
                        {
                            Point ptCol6 = new Point(lstCardLocations[(int)enuCardLocation.Col5].X + szCard.Width + intGap,
                                                     lstCardLocations[(int)enuCardLocation.Col5].Y);
                            lstCardLocations.Add(ptCol6);
                        }
                        break;

                    case enuCardLocation.Stock:
                        {
                            Point ptStock = new Point((int)(Width - 3.5*szCard.Width  - intGap),
                                                      Height - szCard.Height - intGap);
                            lstCardLocations.Add(ptStock);
                        }
                        break;

                    case enuCardLocation.Bank:
                        {
                            Point ptBank = new Point((int)(Width - 2.5* szCard.Width - intGap),  
                            //Point ptBank = new Point(Width - szCard.Width - intGap,  lstCardLocations[(int)enuCardLocation.Stock].X + szCard.Width + intGap,
                                                      lstCardLocations[(int)enuCardLocation.Stock].Y);
                            lstCardLocations.Add(ptBank);
                        }
                        break;
                }
            }

            DrawTable();
        }


        static Bitmap _bmpFoundationFrame = null;
        static Bitmap bmpFoundationFrame
        {
            get
            {
                if (_bmpFoundationFrame == null)
                {
                    _bmpFoundationFrame = new Bitmap(Properties.Resources.Foundation_frame);
                    _bmpFoundationFrame.MakeTransparent(_bmpFoundationFrame.GetPixel(0, 0));
                }
                return _bmpFoundationFrame;
            }
        }

        static Bitmap _bmpStockRemaining_x1 = null;
        static Bitmap bmpStockRemaining_x1
        {
            get
            {
                if (_bmpStockRemaining_x1 == null)
                {
                    _bmpStockRemaining_x1 = new Bitmap(Properties.Resources.StockRemaining_x1);
                    _bmpStockRemaining_x1.MakeTransparent(_bmpStockRemaining_x1.GetPixel(0, 0));
                }
                return _bmpStockRemaining_x1;
            }
        }

        static Bitmap _bmpStockRemaining_x2 = null;
        static Bitmap bmpStockRemaining_x2
        {
            get
            {
                if (_bmpStockRemaining_x2 == null)
                {
                    _bmpStockRemaining_x2 = new Bitmap(Properties.Resources.StockRemaining_x2);
                    _bmpStockRemaining_x2.MakeTransparent(_bmpStockRemaining_x2.GetPixel(0, 0));
                }
                return _bmpStockRemaining_x2;
            }
        }

        static Bitmap _bmpHighlightCardUnderMouse = null;
        static Bitmap bmpHighlightCardUnderMouse
        {
            get
            {
                if (_bmpHighlightCardUnderMouse == null)
                {
                    _bmpHighlightCardUnderMouse = new Bitmap(Properties.Resources.card_highlight);
                    _bmpHighlightCardUnderMouse.MakeTransparent(_bmpHighlightCardUnderMouse.GetPixel(0, 0));
                }
                return _bmpHighlightCardUnderMouse;
            }
        }

        static List<Bitmap> _lstBmpFoundationSuits = new List<Bitmap>();
        static List<Bitmap> lstBmpFoundationSuits
        {
            get
            {
                if (_lstBmpFoundationSuits.Count  == 0)
                {
                    string strDir = System.IO.Directory.GetCurrentDirectory() + "\\";
                    for (int intSuitCounter = 0; intSuitCounter < 4; intSuitCounter ++)
                    {
                        enuSuits eSuit = (enuSuits)intSuitCounter;
                        string strSuitFilename = strDir + "Foundation Image " + eSuit.ToString() + ".png";
                        Bitmap bmpSuit = new Bitmap(strSuitFilename);
                        bmpSuit.MakeTransparent(bmpSuit.GetPixel(0, 0));
                        _lstBmpFoundationSuits.Add(bmpSuit);
                    }
                }
                return _lstBmpFoundationSuits;
            }
        }        

        static Bitmap _bmpTable = null;
        static Bitmap bmpTable
        {
            get
            {
                if (_bmpTable == null || _bmpTable.Width != instance.Width || _bmpTable.Height != instance.Height)
                {
                    if (_bmpTable != null)
                    {
                        _bmpTable.Dispose();
                    }
                    _bmpTable = new Bitmap(instance.Width, instance.Height);
                }
                return _bmpTable;
            }
        }

        classPlayingCard Pile_PlayingCardMostVisible(enuSuits eSuit)
        {
            int intPile = (int)eSuit;
            
            List<classPlayingCard> lstPile = arrlstCards_Piles[intPile];
            for (int intCounter = lstPile.Count-1; intCounter >=0; intCounter --)
            {
                classPlayingCard cPlayingCard = lstPile[intCounter];
                if (!cPlayingCard.IAmMoving)
                    return cPlayingCard;
            }

            return null;
        }

        public static void FillPiles()
        {
            cEventTicket_DealCards.AutoRepeat = false;
            cEventTicket_DealCards.quit();
            lstCards_Stock.Clear();
            lstCards_Bank.Clear();
            lstCardsPlayerIsMoving_Clear();
            arrLstCards_ColumnsPiles_Clear();

            for (int intPileCounter =0; intPileCounter < 4; intPileCounter ++)
            {
                enuSuits eSuit = (enuSuits)intPileCounter;
                List<classPlayingCard> lstSuitCards = classPlayingCard.arrCardSuits[intPileCounter];

                for (int intCardCounter = 0; intCardCounter < lstSuitCards.Count; intCardCounter++)
                {
                    classPlayingCard cCard = lstSuitCards[intCardCounter];
                    cCard.bolFaceUp = true;
                    arrlstCards_Piles[intPileCounter].Add(cCard);
                }
            }

        }

        public void DrawTable()
        {
            //formSolitaire.instance.Text = "cards moving : "
            //                                + (cCardPlayerIsMoving != null
            //                                                       ? (cCardPlayerIsMoving.eRank.ToString() + " of " + cCardPlayerIsMoving.eSuit.ToString())
            //                                                       : " none");
            if (formSolitaire.instance.WindowState == FormWindowState.Minimized  ) return;
            cSP.Reset();
            cSP.lstElements.Clear();

            try
            {
                using (Graphics g = Graphics.FromImage(bmpTable))
                {
                    Bitmap bmpBaize = Properties.Resources.Baize;
                    Rectangle recSourceBaize = new Rectangle(0, 0, bmpBaize.Width, bmpBaize.Height);
                    Rectangle recDestBaize = new Rectangle(0, 0, Width, Height);
                    g.DrawImage(bmpBaize, recDestBaize, recSourceBaize, GraphicsUnit.Pixel);

                    switch (eDrawMode)
                    {
                        case enuDrawTableMode.About:
                        case enuDrawTableMode.Strategy:
                            {
                                Bitmap bmpDrawText = bmpRtxDrawText;
                                Rectangle recDrawText = new Rectangle((Width - bmpDrawText.Width) / 2, (Height - bmpDrawText.Height) / 2, bmpDrawText.Width, bmpDrawText.Height);
                                Rectangle recSource = new Rectangle(2, 2, bmpDrawText.Width - 4, bmpDrawText.Height - 4);

                                g.DrawImage(bmpDrawText, recDrawText, recSource, GraphicsUnit.Pixel);
                                g.DrawRectangle(Pens.Black, recDrawText);
                                classSweepAndPrune.classElement cEleDrawText = new classSweepAndPrune.classElement();
                                cEleDrawText.rec = recDrawText;
                                cEleDrawText.tag = (object)enuCardLocation.rtxDrawText;
                                cEleDrawText.obj = (object)enuSP_EleType.Region;
                                cSP.Add(ref cEleDrawText);
                            }
                            break;

                        default:
                            {
                                // draw Piles
                                for (int intPileCounter = 0; intPileCounter < 4; intPileCounter++)
                                {
                                    List<classPlayingCard> lstCards_Pile = arrlstCards_Piles[intPileCounter];
                                    if (lstCards_Pile.Count > 0)
                                    {
                                        classPlayingCard cCardOnPile = Pile_PlayingCardMostVisible((enuSuits)intPileCounter);
                                        if (cCardOnPile != null)
                                        {
                                            Point ptPile = lstPiles_Location[intPileCounter];
                                            Bitmap bmpCard = cCardOnPile.bmp;
                                            Rectangle recSourcePile = new Rectangle(0, 0, bmpCard.Width, bmpCard.Height);
                                            Rectangle recDestPile = new Rectangle(ptPile, szCard);

                                            g.DrawImage(bmpCard, recDestPile, recSourcePile, GraphicsUnit.Pixel);
                                            cCardOnPile.ptLocation = recDestPile.Location;
                                            classSweepAndPrune.classElement cSPEle = new classSweepAndPrune.classElement();
                                            cSPEle.rec = recDestPile;
                                            cSPEle.tag = (object)cCardOnPile;
                                            cSPEle.obj = (object)enuSP_EleType.Card;
                                            cSP.Add(ref cSPEle);
                                        }
                                    }
                                    else
                                    {
                                        // draw foundation base 
                                        Point ptPile = lstPiles_Location[intPileCounter];
                                        Rectangle recSourcePile = new Rectangle(0, 0, bmpFoundationFrame.Width, bmpFoundationFrame.Height);
                                        Rectangle recDestPile = new Rectangle(ptPile, szCard);

                                        classSweepAndPrune.classElement cSPEle = new classSweepAndPrune.classElement();
                                        cSPEle.rec = recDestPile;
                                        enuCardLocation eLocation = (enuCardLocation)((int)enuCardLocation.PileSpade + intPileCounter);
                                        cSPEle.tag = (object)eLocation;
                                        cSPEle.obj = (object)enuSP_EleType.Region;
                                        cSP.Add(ref cSPEle);

                                        g.DrawImage(bmpFoundationFrame, recDestPile, recSourcePile, GraphicsUnit.Pixel);

                                        Point ptCenterFrame = new Point(ptPile.X + recDestPile.Width / 2, ptPile.Y + recDestPile.Height / 2);
                                        Bitmap bmpSuit = lstBmpFoundationSuits[intPileCounter];
                                        Rectangle recSource = new Rectangle(0, 0, bmpSuit.Width, bmpSuit.Height);
                                        int intSuitCenterSize = recDestPile.Width / 3;
                                        Rectangle recDest = new Rectangle(ptCenterFrame.X - intSuitCenterSize / 2, ptCenterFrame.Y - intSuitCenterSize / 2, intSuitCenterSize, intSuitCenterSize);
                                        g.DrawImage(bmpSuit, recDest, recSource, GraphicsUnit.Pixel);
                                    }
                                }

                                // draw columns 
                                for (int intColumnCounter = 0; intColumnCounter < arrlstCards_Columns.Length; intColumnCounter++)
                                {
                                    Point ptColumn = lstCards_ColumnsLocations[intColumnCounter];
                                    List<classPlayingCard> lstCardsInColumn = arrlstCards_Columns[intColumnCounter];
                                    if (lstCardsInColumn.Count > 0)
                                    {
                                        if (lstCardsInColumn.Count > 0)
                                        {
                                            for (int intCardCounter = 0; intCardCounter < lstCardsInColumn.Count; intCardCounter++)
                                            {
                                                classPlayingCard cCardInColumn = lstCardsInColumn[intCardCounter];
                                                if (!cCardInColumn.IAmMoving)
                                                {
                                                    Bitmap bmp = cCardInColumn.bmp;
                                                    Point ptCard = new Point(ptColumn.X, ptColumn.Y + intCardCounter * intStockGap);
                                                    Rectangle recColumnCard_Dest = new Rectangle(ptCard, szCard);
                                                    Rectangle recColumnCard_Source = new Rectangle(0, 0, bmp.Width, bmp.Height);
                                                    g.DrawImage(bmp, recColumnCard_Dest, recColumnCard_Source, GraphicsUnit.Pixel);

                                                    cCardInColumn.ptLocation = recColumnCard_Dest.Location;

                                                    if (cCardInColumn.bolFaceUp)
                                                    {
                                                        classSweepAndPrune.classElement cSPEle = new classSweepAndPrune.classElement();
                                                        cSPEle.rec = recColumnCard_Dest;
                                                        cSPEle.obj = (object)enuSP_EleType.Card;
                                                        cSPEle.tag = (object)cCardInColumn;
                                                        cSP.Add(ref cSPEle);
                                                    }
                                                }
                                            }
                                        }
                                    }
                                    else
                                    {
                                        Bitmap bmpFrame = bmpHighlightCardUnderMouse;
                                        Rectangle recSource = new Rectangle(0, 0, bmpHighlightCardUnderMouse.Width, bmpHighlightCardUnderMouse.Height);
                                        Rectangle recDest = new Rectangle(ptColumn, szCard);
                                        g.DrawImage(bmpFrame, recDest, recSource, GraphicsUnit.Pixel);

                                        classSweepAndPrune.classElement cSPEle = new classSweepAndPrune.classElement();                                        
                                        cSPEle.rec = new Rectangle(ptColumn, szCard);
                                        cSPEle.obj = (object)enuSP_EleType.Region;
                                        enuCardLocation eColumnLocation = (enuCardLocation)((int)enuCardLocation.Col0 + intColumnCounter);
                                        cSPEle.tag = (object)eColumnLocation;
                                        cSPEle.obj = (object)enuSP_EleType.Region;
                                        cSP.Add(ref cSPEle);
                                    }
                                }

                                
                                // draw stock 
                                if (lstCards_Stock.Count > 0)
                                {
                                    Bitmap bmpStock = Properties.Resources.card_back;
                                    Point ptStock = lstCardLocations[(int)enuCardLocation.Stock];
                                    Rectangle recStock_Source = new Rectangle(0, 0, bmpStock.Width, bmpStock.Height);
                                    Rectangle recStock_Dest = new Rectangle(ptStock, szCard);
                                    g.DrawImage(bmpStock, recStock_Dest, recStock_Source, GraphicsUnit.Pixel);

                                    classPlayingCard cPlayCard_TopOfStock = lstCards_Stock[0];
                                    cPlayCard_TopOfStock.ptLocation = recStock_Dest.Location;
                                    if (lstCards_Stock.Count < 3)
                                    {
                                        Bitmap bmpStockRemaining = lstCards_Stock.Count == 1
                                                                                         ? bmpStockRemaining_x1
                                                                                         : bmpStockRemaining_x2;
                                        Rectangle recSource = new Rectangle(0, 0, bmpStockRemaining.Width, bmpStockRemaining.Height);
                                        int intStockWidth = (int)((float)szCard.Width * .8);
                                        Point ptStockCenter = new Point(recStock_Dest.Left + recStock_Dest.Width / 2, recStock_Dest.Top + recStock_Dest.Height / 2);
                                        Rectangle recDest = new Rectangle(ptStockCenter.X - intStockWidth / 2, ptStockCenter.Y - intStockWidth / 2, intStockWidth, intStockWidth);
                                        g.DrawImage(bmpStockRemaining, recDest, recSource, GraphicsUnit.Pixel);

                                    }

                                    classSweepAndPrune.classElement cSPEle = new classSweepAndPrune.classElement();
                                    cSPEle.rec = recStock_Dest;
                                    cSPEle.tag = (object)cPlayCard_TopOfStock;
                                    cSPEle.obj = (object)enuSP_EleType.Card;
                                    cSP.Add(ref cSPEle);
                                }
                                else
                                {
                                    Bitmap bmpFrame = bmpFoundationFrame;
                                    Rectangle recSourceFrame = new Rectangle(0, 0, bmpFrame.Width, bmpFrame.Height);
                                    Rectangle recDestFrame = new Rectangle(lstCardLocations[(int)enuCardLocation.Stock], szCard);
                                    g.DrawImage(bmpFrame, recDestFrame, recSourceFrame, GraphicsUnit.Pixel);

                                    if (eLocationUnderMouse == enuCardLocation.Stock)
                                    {
                                        Rectangle recHighlightSource = new Rectangle(0, 0, bmpHighlightCardUnderMouse.Width, bmpHighlightCardUnderMouse.Height);
                                        Rectangle recHighlightDest = new Rectangle(lstCardLocations[(int)enuCardLocation.Stock], szCard);
                                        g.DrawImage(bmpHighlightCardUnderMouse, recHighlightDest, recHighlightSource, GraphicsUnit.Pixel);
                                    }

                                    classSweepAndPrune.classElement cSPEle = new classSweepAndPrune.classElement();
                                    cSPEle.rec = new Rectangle(lstCardLocations[(int)enuCardLocation.Stock], szCard);
                                    cSPEle.tag = (object)enuCardLocation.Stock;
                                    cSPEle.obj = (object)enuSP_EleType.Region;
                                    cSP.Add(ref cSPEle);
                                }

                              
                                // draw stock button 
                                if (lstCards_Stock.Count > 2)
                                {
                                    int intStockButtonWidth = szCard.Width / 5;
                                    Point ptStockButton = new Point(lstCardLocations[(int)enuCardLocation.Stock].X + szCard.Width,
                                                                    lstCardLocations[(int)enuCardLocation.Stock].Y);
                                    Rectangle recStockButton = new Rectangle(ptStockButton, new Size(intStockButtonWidth, intStockButtonWidth));
                                    g.DrawRectangle(new Pen(eLocationUnderMouse == enuCardLocation.StockButton ? Color.Yellow : Color.Black, 2), recStockButton);

                                    classSweepAndPrune.classElement cSPEleStockButton = new classSweepAndPrune.classElement();
                                    cSPEleStockButton.obj = (object)enuSP_EleType.Region;
                                    cSPEleStockButton.tag = (object)enuCardLocation.StockButton;
                                    cSPEleStockButton.rec = recStockButton;
                                    cSP.Add(ref cSPEleStockButton);
                                }
                                // draw Bank 
                                {
                                    Point ptBank = lstCardLocations[(int)enuCardLocation.Bank];
                                    int intBankShift = (int)((float)szCard.Width * .4);
                                    int intBankIndexPrevious = -1;
                                    //int intStockCounter = 0;
                                    int intYIndexCounter = 0;
                                    for (int intBankCounter = 0; intBankCounter < lstCards_Bank.Count; intBankCounter++)
                                    {
                                        classPlayingCard cCardBank = lstCards_Bank[intBankCounter];
                                        //int intXIndex = 3- intBankCounter % 3;
                                        int intXIndex = 3 - cCardBank.BankIndex;
                                        //int intYIndex = (int)Math.Floor((double)(intBankCounter / 3));
                                        if (cCardBank.BankIndex < intBankIndexPrevious)
                                            intYIndexCounter++;
                                        int intYIndex = intYIndexCounter;

                                        intBankIndexPrevious = cCardBank.BankIndex;

                                        Point ptCardBank = new Point(ptBank.X + intXIndex * intBankShift,
                                                                      ptBank.Y - intYIndex * intStockGap);
                                        Bitmap bmpBank = cCardBank.bmp;
                                        Rectangle recSourceBank = new Rectangle(0, 0, bmpBank.Width, bmpBank.Height);
                                        Rectangle recDestBank = new Rectangle(ptCardBank, szCard);
                                        g.DrawImage(bmpBank, recDestBank, recSourceBank, GraphicsUnit.Pixel);
                                        cCardBank.ptLocation = recDestBank.Location;
                                        if (intBankCounter == lstCards_Bank.Count - 1)
                                        {
                                            classSweepAndPrune.classElement cSPEle = new classSweepAndPrune.classElement();
                                            cSPEle.rec = recDestBank;
                                            cSPEle.tag = (object)cCardBank;
                                            cSPEle.obj = (object)enuSP_EleType.Card;
                                            cSP.Add(ref cSPEle);
                                        }
                                    }
                                }

                                // draw cards moving - dealing cards 
                                {
                                    List<classPlayingCard> lstCardsMoving = classPlayingCard.lstCardsInMotion;
                                    for (int intCardsMovingCounter = 0; intCardsMovingCounter < lstCardsMoving.Count; intCardsMovingCounter++)
                                    {
                                        classPlayingCard cCardMoving = lstCardsMoving[intCardsMovingCounter];
                                        Bitmap bmpCardMoving = cCardMoving.bmp;
                                        Rectangle recDestMoving = new Rectangle(cCardMoving.ptLocation, szCard);
                                        Rectangle recSourceMoving = new Rectangle(0, 0, bmpCardMoving.Width, bmpCardMoving.Height);
                                        g.DrawImage(bmpCardMoving, recDestMoving, recSourceMoving, GraphicsUnit.Pixel);
                                    }
                                }

                            
                                // draw statistics 
                                if (bolDrawStatistics)
                                {
                                    System.Drawing.Font fnt = new Font("ms sans-serif", 12);
                                    Color clrField = Color.Black;
                                    Color clrNumeral = Color.Gray;

                                    bool bolStatisticsAreUnderMouse = eLocationUnderMouse == enuCardLocation.Statistics;
                                    int intFrameGap = 2;
                                    Size szFrame = new Size(200, 145);
                                    Point ptCenter = new Point(Width / 2, Height / 2);
                                    Rectangle recFrame = new Rectangle(ptCenter.X - szFrame.Width / 2, ptCenter.Y - szFrame.Height / 2, szFrame.Width, szFrame.Height);
                                    g.FillRectangle(bolStatisticsAreUnderMouse ? Brushes.Blue : Brushes.White, recFrame);
                                    g.DrawRectangle(bolStatisticsAreUnderMouse ? Pens.Yellow : Pens.Black,
                                                        new Rectangle(recFrame.X + intFrameGap,
                                                                      recFrame.Y + intFrameGap,
                                                                      recFrame.Width - 2 * intFrameGap,
                                                                      recFrame.Height - 2 * intFrameGap));

                                    classSweepAndPrune.classElement cSPEle_Statistics = new classSweepAndPrune.classElement();
                                    cSPEle_Statistics.obj = (object)enuSP_EleType.Region;
                                    cSPEle_Statistics.tag = (object)enuCardLocation.Statistics;
                                    cSPEle_Statistics.rec = recFrame;
                                    cSP.Add(ref cSPEle_Statistics);

                                    int intFieldsGap = 15;
                                    int intFontHeight = 20;
                                    int intGamesPlayedY = recFrame.Top + 10;
                                    int intWinsY = intGamesPlayedY + intFontHeight;
                                    int intLossesY = intWinsY + intFontHeight;
                                    int intAverage = intLossesY + intFontHeight;
                                    int intStreakY = intAverage + intFontHeight;
                                    int intBestStreakY = intStreakY + intFontHeight;
                                    Brush brFields = bolStatisticsAreUnderMouse ? Brushes.White : Brushes.Blue;
                                    g.DrawString("Games Played", fnt, brFields, new Point(recFrame.X + intFieldsGap, intGamesPlayedY));
                                    g.DrawString("Wins", fnt, brFields, new Point(recFrame.X + intFieldsGap, intWinsY));
                                    g.DrawString("losses", fnt, brFields, new Point(recFrame.X + intFieldsGap, intLossesY));
                                    g.DrawString("average", fnt, brFields, new Point(recFrame.X + intFieldsGap, intAverage));
                                    g.DrawString("Win streak", fnt, brFields, new Point(recFrame.X + intFieldsGap, intStreakY));
                                    Rectangle recBestWinningStreak = new Rectangle();
                                    recBestWinningStreak.Location = new Point(recFrame.X + intFieldsGap, intBestStreakY);
                                    g.DrawString("Best streak", fnt, brFields, recBestWinningStreak.Location);

                                    float fltAverage = classStatistics.Wins > 0
                                                                            ? (float)(classStatistics.Wins) / (float)(classStatistics.Losses + classStatistics.Wins) * 100f
                                                                            : 0;
                                    string strAverage = "%" + (fltAverage.ToString("00.00"));
                                    Size szAverage = TextRenderer.MeasureText(strAverage, fnt);

                                    int intNumeralsLeft = recFrame.Right - (int)((float)szAverage.Width * .6f);
                                    Brush brNumerals = bolStatisticsAreUnderMouse ? Brushes.Yellow : Brushes.Black;
                                    g.DrawString(classStatistics.GamesPlayed.ToString(), fnt, brNumerals, new Point(intNumeralsLeft, intGamesPlayedY));
                                    g.DrawString(classStatistics.Wins.ToString(), fnt, brNumerals, new Point(intNumeralsLeft, intWinsY));
                                    g.DrawString(classStatistics.Losses.ToString(), fnt, brNumerals, new Point(intNumeralsLeft, intLossesY));
                                    g.DrawString(strAverage, fnt, brNumerals, new Point(intNumeralsLeft - szAverage.Width / 2, intAverage));
                                    g.DrawString(classStatistics.WinStreak.ToString(), fnt, brNumerals, new Point(intNumeralsLeft, intStreakY));
                                    Point ptBestWinStreakText = new Point(intNumeralsLeft, intBestStreakY);
                                    string strBestWinStreakText = classStatistics.BestWinStreak.ToString();
                                    g.DrawString(strBestWinStreakText, fnt, brNumerals, ptBestWinStreakText);
                                    Size szBestWinStreakText = TextRenderer.MeasureText(strBestWinStreakText, fnt);
                                    Point ptBestWinStreak_BR = new Point(ptBestWinStreakText.X + szBestWinStreakText.Width, ptBestWinStreakText.Y + szBestWinStreakText.Height);
                                    recBestWinningStreak.Size = new Size(ptBestWinStreak_BR.X - recBestWinningStreak.Left,
                                                                         ptBestWinStreak_BR.Y - recBestWinningStreak.Top);
                                    
                                    classSweepAndPrune.classElement cEleBestWinStreak = new classSweepAndPrune.classElement();
                                    cEleBestWinStreak.rec = recBestWinningStreak;
                                    cEleBestWinStreak.obj = (object)enuSP_EleType.Region;
                                    cEleBestWinStreak.tag = (object)enuCardLocation.BestWinningStreak;
                                    cSP.Add(ref cEleBestWinStreak);


                                    switch (eLocationUnderMouse)
                                    {
                                        case enuCardLocation.BestWinningStreak:
                                            {
                                                // draw date time of Best Win Streak 
                                                DateTime dtBestWin = classStatistics.dtWinningStreak;
                                                string strBestWinDateTime = dtBestWin.Year.ToString() + "/" + dtBestWin.Month.ToString() + "/" + dtBestWin.Day.ToString() + " - " + dtBestWin.Hour.ToString("00") + ":" + dtBestWin.Minute.ToString("00");
                                                Size szBestWinDateTime = TextRenderer.MeasureText(strBestWinDateTime, fnt);
                                                int intBorder = 4;
                                                Rectangle recBestDateTime = new Rectangle(new Point( ptMouse.X + intBorder, ptMouse.Y + intBorder), new Size(szBestWinDateTime.Width + 2 * intBorder, szBestWinDateTime.Height + 2 * intBorder));
                                                g.FillRectangle(Brushes.Gold, recBestDateTime);
                                                g.DrawRectangle(new Pen(System.Drawing.Color.Black, 2), recBestDateTime);
                                                g.DrawString(strBestWinDateTime, fnt, Brushes.Black,new Point( recBestDateTime.Left + intBorder, recBestDateTime.Top + intBorder));
                                            }
                                            break;
                                    }
                                }

                                // highlight card under mouse 
                                if (cCardUnderMouse != null)
                                {
                                    Rectangle recCardUnderMouseSource = new Rectangle(0, 0, bmpHighlightCardUnderMouse.Width, bmpHighlightCardUnderMouse.Height);
                                    Rectangle recCardUnderMouseDest = new Rectangle(cCardUnderMouse.ptLocation, szCard);
                                    g.DrawImage(bmpHighlightCardUnderMouse, recCardUnderMouseDest, recCardUnderMouseSource, GraphicsUnit.Pixel);
                                }

                                //highlight region under mouse
                                {
                                    switch (eLocationUnderMouse)
                                    {
                                        case enuCardLocation.StockButton:
                                        case enuCardLocation.Statistics:
                                        case enuCardLocation.Null:
                                        case enuCardLocation.rtxDrawText:
                                        case enuCardLocation.BestWinningStreak:
                                            break;

                                        default:
                                            {
                                                Point ptLocation = lstCardLocations[(int)eLocationUnderMouse];
                                                Bitmap bmpFrame = bmpHighlightCardUnderMouse;
                                                Rectangle recSource = new Rectangle(0, 0, bmpHighlightCardUnderMouse.Width, bmpHighlightCardUnderMouse.Height);
                                                Rectangle recDest = new Rectangle(ptLocation, szCard);
                                                g.DrawImage(bmpFrame, recDest, recSource, GraphicsUnit.Pixel);
                                            }
                                            break;
                                    }
                                }

                                // draw card Player is moving 
                                if (cCardPlayerIsMoving != null)
                                {
                                    for (int intCardUserMovingCounter = 0; intCardUserMovingCounter < lstCardsPlayerIsMoving_Count; intCardUserMovingCounter++)
                                    {
                                        classPlayingCard cCardDrawn = lstCardsPlayerIsMove_Get(intCardUserMovingCounter);
                                        Bitmap bmpCard = cCardDrawn.bmp;
                                        Rectangle recSource = new Rectangle(0, 0, bmpCard.Width, bmpCard.Height);
                                        Rectangle recDest = new Rectangle(ptMouse.X - ptGrabCard.X, ptMouse.Y - ptGrabCard.Y + intCardUserMovingCounter * intStockGap, szCard.Width, szCard.Height);
                                        g.DrawImage(bmpCard, recDest, recSource, GraphicsUnit.Pixel);
                                    }
                                }

                                //// draw scrolling text 
                                //int intFormWidthByTwo = formSolitaire.instance.Width / 2;
                                //for (int intLineCounter = 0; intLineCounter < lstScrollingText.Count; intLineCounter++)
                                //{
                                //    classScrollingTextItem cScrollingItem = lstScrollingText[intLineCounter];
                                //    Bitmap bmp = cScrollingItem.bmp;
                                //    Rectangle recSource = new Rectangle(0, 0, bmp.Width, bmp.Height);
                                //    Size sz = cScrollingItem.sz;
                                //    Rectangle recDest = new Rectangle(intFormWidthByTwo - sz.Width / 2, cScrollingItem.pt.Y, sz.Width, sz.Height);
                                //    g.DrawImage(bmp, recDest, recSource, GraphicsUnit.Pixel);
                                //}

                                // draw animation intro 
                                if (classAnimation_Intro_Item.lst.Count > 0)
                                {
                                    for (int intAnimationItemCounter = 0; intAnimationItemCounter < classAnimation_Intro_Item.lst.Count; intAnimationItemCounter++)
                                    {
                                        classAnimation_Intro_Item cAniItem = classAnimation_Intro_Item.lst[intAnimationItemCounter];
                                        Point ptCenter = cAniItem.ptPosition;
                                        Size sz = cAniItem.size;
                                        Point ptDraw = new Point(ptCenter.X - sz.Width / 2, ptCenter.Y - sz.Height / 2);
                                        Rectangle recDest = new Rectangle(ptDraw, sz);
                                        Rectangle recSource = new Rectangle(0, 0, cAniItem.bmp.Width, cAniItem.bmp.Height);
                                        g.DrawImage(cAniItem.bmp, recDest, recSource, GraphicsUnit.Pixel);
                                    }
                                }
                            }
                            break;
                    }
                }
                Image = bmpTable;
                Refresh();
            }
            catch (Exception err)
            {
                ;
            }
            
        }


        //static List<classScrollingTextItem> lstScrollingText
        //{
        //    get { return classScrollingTextItem.lst; }
        //}

        bool _bolDealingCards = true;
        public bool bolDealingCards
        {
            get { return _bolDealingCards; }
            set 
            {
                _bolDealingCards = value;
                DrawTable_TicketAutoRepeatSet();
            }
        }

        bool _bolDrawStatistics = true;
        bool bolDrawStatistics
        {
            get { return _bolDrawStatistics; }
            set 
            {
                _bolDrawStatistics = value;
                DrawTable();
            }
        }
        
        bool _bolCollectingCards = true;
        bool bolCollectingCards
        {
            get { return _bolCollectingCards; }
            set 
            {
                _bolCollectingCards = value;
                cEventTicket_CollectCards.AutoRepeat = value;
                DrawTable_TicketAutoRepeatSet();
            }
        }

        

        bool countCards(bool bolDebug)
        {
            //if (bolDealingCards)
            //{
            //    return false;
            //}

            List<classPlayingCard> lstCountedCards = new List<classPlayingCard>();
            for (int intColCounter =0;intColCounter < arrlstCards_Columns.Length; intColCounter++)
            {
                lstCountedCards.AddRange(arrlstCards_Columns[intColCounter]);
            }

            for (int intPileCounter =0; intPileCounter < arrlstCards_Piles.Length; intPileCounter ++)
            {
                List<classPlayingCard> lstPile = arrlstCards_Piles[intPileCounter].OrderBy(card => card.eRank).ToList<classPlayingCard>();
                arrlstCards_Piles[intPileCounter] = lstPile;

                lstCountedCards.AddRange(lstPile);
            }

            lstCountedCards.AddRange(lstCards_Bank);
            lstCountedCards.AddRange(lstCards_Stock);
            lstCountedCards.AddRange(lstCardsPlayerIsMoving_);

            if (lstCountedCards.Count != 52)
            {
                if (bolDebug)
                {
                    lstCountedCards = (List<classPlayingCard>)lstCountedCards.OrderBy(card => card.eRank).ToList<classPlayingCard>();
                    lstCountedCards = (List<classPlayingCard>)lstCountedCards.OrderBy(card => card.eSuit).ToList<classPlayingCard>();

                    List<classPlayingCard> lstDeckCopy = classPlayingCard.NewDeck();
                    if (lstCountedCards.Count > lstDeckCopy.Count)
                    {
                        // too many cards 
                        List<classPlayingCard> lstCardDoubles = lstCountedCards.GroupBy(item => item)
                                                                               .Where(g => g.Count() > 1)
                                                                               .Select(g => g.Key)
                                                                               .ToList();
                        string strMsg = "doubles:";
                        foreach (classPlayingCard card in lstCardDoubles)
                            strMsg += "\n\t" + card.eRank.ToString() + " of " + card.eSuit.ToString();
                        MessageBox.Show(strMsg);
                    }
                    else
                    {
                        // missing a card 
                        List<classPlayingCard> lstCardMissing = lstDeckCopy.Except<classPlayingCard>(lstCountedCards).ToList<classPlayingCard>();
                        while(lstCardMissing.Count >0)
                        {
                            classPlayingCard cCardMissing = lstCardMissing[0];
                            lstCardMissing.RemoveAt(0);
                            
                            switch(cCardMissing.eCardLocation)
                            {
                                case enuCardLocation.Col0:
                                case enuCardLocation.Col1:
                                case enuCardLocation.Col2:
                                case enuCardLocation.Col3:
                                case enuCardLocation.Col4:
                                case enuCardLocation.Col5:
                                case enuCardLocation.Col6:
                                    arrlstCards_Columns[(int)cCardMissing.eCardLocation - (int)enuCardLocation.Col0].Add(cCardMissing);
                                    break;

                                case enuCardLocation.PileClub:
                                case enuCardLocation.PileHeart:
                                case enuCardLocation.PileSpade:
                                case enuCardLocation.PileDiamond:
                                    arrlstCards_Piles[(int)cCardMissing.eCardLocation - (int)enuCardLocation.PileSpade].Add(cCardMissing);
                                    break;

                                case enuCardLocation.Bank:
                                    lstCards_Bank.Add(cCardMissing);
                                    break;

                                default:
                                    ;
                                    break;
                            }
                        }

                        return true;
                        string strMsg = "missing:";
                        foreach (classPlayingCard card in lstCardMissing)
                            strMsg += "\n\t" + card.eRank.ToString() + " of " + card.eSuit.ToString();
                        MessageBox.Show(strMsg);
                    }
                }
                return false;
            }
            return true;
        }


        public void Replay()
        {
            if (lstDeckReplay.Count == 52)
            {
                lstDeck.Clear();
                for (int intCardCounter = 0; intCardCounter < lstDeckReplay.Count; intCardCounter++)
                {
                    classPlayingCard cCard = lstDeckReplay[intCardCounter];
                    cCard.bolFaceUp = false;
                    lstDeck.Add(cCard);
                }

                DealCards(ref lstDeck);
            }
        }

        public void NewGame()
        {
            bolQuickDeal = false;
            bolGameOver = false;
            classPlayingCard.lstCardsInMotion.Clear();
            lstDeck.AddRange(classPlayingCard.NewDeck());
            foreach (classPlayingCard cCard in lstDeck)
                cCard.bolFaceUp = false;

            lstDeckReplay.Clear();
            lstDeckReplay.AddRange(lstDeck);

            classPlayingCard.ShuffleDeck(ref lstDeck);
            DealCards(ref lstDeck);
        }


        void DealCards(ref List<classPlayingCard> lstCards)
        {
            cEventTicket_CollectCards.AutoRepeat = false;

            lstCards_Stock.Clear();
            lstCards_Bank.Clear();
            lstCardsPlayerIsMoving_Clear();
            arrLstCards_ColumnsPiles_Clear();


            lstDeckReplay.Clear();
            lstDeckReplay.AddRange(lstDeck);

            intDeal_PreviousNewColumn = 0;
            intColumnCounter = 0;
            bolDealingCards = true;
            cEventTicket_DealCards.AutoRepeat = true;
        }

        int intDeal_PreviousNewColumn= 0;
        int intColumnCounter = 0;

        bool bolQuickDeal = false;


        void tmrDealCards_Tick(object sender, EventArgs e)
        {
            if (lstDeck.Count == 0)
                                goto quit;

            do
            {
                classPlayingCard cCard = lstDeck[0];
                lstDeck.RemoveAt(0);

                cCard.ptLocation = new Point(0, Height);
                if (intColumnCounter == intDeal_PreviousNewColumn)
                    cCard.bolFaceUp = true;

                int intColumnCardLocationIndex = (int)enuCardLocation.Col0 + intColumnCounter;
                List<classPlayingCard> lstCardsInColumn = arrlstCards_Columns[intColumnCounter];
                lstCardsInColumn.Add(cCard);
                cCard.eCardLocation = (enuCardLocation)((int)enuCardLocation.Col0 + intColumnCounter);

                Point ptTarget = lstCardLocations[intColumnCardLocationIndex];
                ptTarget.Y += intStockGap * (lstCardsInColumn.Count - 1);
                cCard.cCardMotion.MoveTo(ptTarget);
                if (bolQuickDeal)
                {
                    cCard.cCardMotion.GotoEndPosition();
                }

                intColumnCounter++;
                if (intColumnCounter >= 7)
                {
                    // return to left Stock 
                    intColumnCounter = ++intDeal_PreviousNewColumn;
                    if (intDeal_PreviousNewColumn >= 7)
                    {
                        // stop dealing 
                        while (lstDeck.Count > 0)
                        {
                            cCard = lstDeck[0];
                            lstDeck.Remove(cCard);
                            cCard.eCardLocation = enuCardLocation.Stock;
                            lstCards_Stock.Add(cCard);
                        }
                        goto quit;
                    }
                }
            } while (bolQuickDeal);
        quit:
            cEventTicket_DealCards.AutoRepeat = lstDeck.Count > 0;
            bolDealingCards = lstDeck.Count > 0;
            bolQuickDeal = false;
        }

        public static BinaryFormatter formatter
        {
            get { return classStatistics.formatter; }
        }

        static public void fs_Game_Save(ref FileStream fs)
        {
            // save columns 
            for (int intColumnCounter = 0; intColumnCounter < arrlstCards_Columns.Length; intColumnCounter++)
            {
                List<classPlayingCard> lstCardsInColumn = arrlstCards_Columns[intColumnCounter];
                formatter.Serialize(fs, lstCardsInColumn.Count);
                for (int intCardCounter = 0; intCardCounter < lstCardsInColumn.Count; intCardCounter++)
                {
                    classPlayingCard cCard = lstCardsInColumn[intCardCounter];
                    fs_AppendCard(ref fs, cCard);
                }
            }

            // save piles
            for (int intPileCounter = 0; intPileCounter < arrlstCards_Piles.Length; intPileCounter++)
            {
                List<classPlayingCard> lstCardsInPile = arrlstCards_Piles[intPileCounter];
                formatter.Serialize(fs, lstCardsInPile.Count);

                for (int intCardCounter = 0; intCardCounter < lstCardsInPile.Count; intCardCounter++)
                {
                    classPlayingCard cCard = lstCardsInPile[intCardCounter];
                    fs_AppendCard(ref fs, cCard);
                }
            }

            // save stock 
            formatter.Serialize(fs, lstCards_Stock.Count);
            for (int intCardCounter = 0; intCardCounter < lstCards_Stock.Count; intCardCounter++)
            {
                classPlayingCard cCard = lstCards_Stock[intCardCounter];
                fs_AppendCard(ref fs, cCard);
            }

            // save  bank 
            formatter.Serialize(fs, lstCards_Bank.Count);
            for (int intCardCounter = 0; intCardCounter < lstCards_Bank.Count; intCardCounter++)
            {
                classPlayingCard cCard = lstCards_Bank[intCardCounter];
                fs_AppendCard(ref fs, cCard);
            }


            // save replay cards list 
            for (int intCardCounter =0; intCardCounter < lstDeckReplay.Count; intCardCounter++)
            {
                classPlayingCard cCard = lstDeckReplay[intCardCounter];
                fs_AppendCard(ref fs, cCard);
            }
        }

        public static bool fs_Game_Load(ref FileStream fs)
        {
            arrLstCards_ColumnsPiles_Clear();
            lstCards_Stock.Clear();
            lstCards_Bank.Clear();

            try
            {
                ///   read columns
                for (int intColumnCounter = 0; intColumnCounter < arrlstCards_Columns.Length; intColumnCounter++)
                {
                    int intNumCardsInColumn = (int)formatter.Deserialize(fs);
                    List<classPlayingCard> lstCardsColumn = arrlstCards_Columns[intColumnCounter];
                    for (int intCardCounter = 0; intCardCounter < intNumCardsInColumn; intCardCounter++)
                    {
                        classPlayingCard cCard = fs_GetCard(ref fs); 
                        cCard.eCardLocation = (enuCardLocation)((int)enuCardLocation.Col0 + intColumnCounter);
                        lstCardsColumn.Add(cCard);
                    }
                }


                ///   read Piles
                for (int intPileCounter = 0; intPileCounter < arrlstCards_Piles.Length; intPileCounter++)
                {
                    int intNumCardsInPile = (int)formatter.Deserialize(fs);
                    List<classPlayingCard> lstCardsPile = arrlstCards_Piles[intPileCounter];
                    for (int intCardCounter = 0; intCardCounter < intNumCardsInPile; intCardCounter++)
                    {
                        classPlayingCard cCard = fs_GetCard(ref fs);
                        cCard.eCardLocation = (enuCardLocation)((int)enuCardLocation.PileSpade + intPileCounter);
                        lstCardsPile.Add(cCard);
                    }
                }

                // read Stock 
                int intNumCardsInStock = (int)formatter.Deserialize(fs);
                for (int intCardCounter = 0; intCardCounter < intNumCardsInStock; intCardCounter++)
                {
                    classPlayingCard cCard = fs_GetCard(ref fs);
                    cCard.eCardLocation = enuCardLocation.Stock;
                    lstCards_Stock.Add(cCard);
                }

                // read Bank 
                int intNumCardsInBank = (int)formatter.Deserialize(fs);
                for (int intCardCounter = 0; intCardCounter < intNumCardsInBank; intCardCounter++)
                {
                    classPlayingCard cCard = fs_GetCard(ref fs);
                    cCard.eCardLocation = enuCardLocation.Bank;
                    lstCards_Bank.Add(cCard);
                }

                // read replay cards 
                lstDeckReplay.Clear();
                for (int intCardCounter =0; intCardCounter < 52; intCardCounter ++)
                {
                    classPlayingCard cCard = fs_GetCard(ref fs);
                    lstDeckReplay.Add(cCard);
                }

                return instance.countCards(false);
            }
            catch (Exception)
            {
                return false;
            }

            return false;

        }

        static classPlayingCard fs_GetCard(ref FileStream fs)
        {
            int intRank = (int)formatter.Deserialize(fs);
            int intSuit= (int)formatter.Deserialize(fs);
            bool bolFaceUp= (bool)formatter.Deserialize(fs);
            int intBankIndex = (int)formatter.Deserialize(fs);

            classPlayingCard cCardRetVal = arrCardSuits[intSuit][intRank];
            cCardRetVal.bolFaceUp = bolFaceUp;
            cCardRetVal.BankIndex = intBankIndex;
            return cCardRetVal;
        }

        static void fs_AppendCard(ref FileStream fs, classPlayingCard cCard)
        {
            formatter.Serialize(fs, ((int)cCard.eRank));
            formatter.Serialize(fs, ((int)cCard.eSuit));
            formatter.Serialize(fs, ((bool)cCard.bolFaceUp));
            formatter.Serialize(fs, ((int)cCard.BankIndex));
        }


        public static List<classPlayingCard>[] arrCardSuits
        {
            get
            {
                return classPlayingCard.arrCardSuits;
            }
        }
    }

    //public class classScrollingTextItem
    //{
    //    static List<string> lstStringNotScrolling = new List<string>();
    //    public static List<classScrollingTextItem> lst = new List<classScrollingTextItem>();
    //    static classEventController.classEventTicket _cEventTicket_Scroll = null;
    //    static classEventController.classEventTicket cEventTicket_Scroll
    //    {
    //        get
    //        {
    //            if (_cEventTicket_Scroll == null)
    //            {
    //                _cEventTicket_Scroll = formSolitaire.cEC.Ticket("scrollingText", 100, tmrScrollingText_Tick);
    //            }
    //            return _cEventTicket_Scroll;
    //        }
    //    }
    //    static classEventController.classEventTicket _cEventTicket_AddItem = null;
    //    static classEventController.classEventTicket cEventTicket_AddItem
    //    {
    //        get
    //        {
    //            if (_cEventTicket_AddItem == null)
    //            {
    //                _cEventTicket_AddItem = formSolitaire.cEC.Ticket("AddItemingText", 3000, tmrAddItemText_Tick);
    //            }
    //            return _cEventTicket_AddItem;
    //        }
    //    }

    //    static public void Scroll(List<string> lstText)
    //    {
    //        lstStringNotScrolling.AddRange(lstText);
    //        tmrAddItemText_Tick((object)null, new EventArgs());
    //        cEventTicket_AddItem.AutoRepeat = lstStringNotScrolling.Count > 0;
    //    }


    //    static void tmrAddItemText_Tick(object sender, EventArgs e)
    //    {
    //        if (lstStringNotScrolling.Count ==0)
    //        {
    //            cEventTicket_AddItem.AutoRepeat = false;
    //            return;
    //        }
    //        string strLine = lstStringNotScrolling[0];
    //        lstStringNotScrolling.RemoveAt(0);
    //        new classScrollingTextItem(strLine);
    //    }

    //    static void tmrScrollingText_Tick(object sender, EventArgs e)
    //    {
    //        if (lst.Count == 0)
    //        {
    //            cEventTicket_Scroll.AutoRepeat = false;
    //            return;
    //        }
    //        DateTime dtNow = DateTime.Now;
    //        int intFormHeight = formSolitaire.instance.Height;
    //        int intFormWidthByTwo = formSolitaire.instance.Width / 2;
    //        for (int intItemCounter=lst.Count -1; intItemCounter >=0; intItemCounter --)
    //        {
    //            classScrollingTextItem cTextItem = lst[intItemCounter];
    //            TimeSpan tsTimeElapsed = dtNow.Subtract(cTextItem.dtStart);
    //            float fltPCElapsedTravelTime = (float)tsTimeElapsed.TotalMilliseconds / (float)classScrollingTextItem.tsTravelTime.TotalMilliseconds;
    //            if (fltPCElapsedTravelTime >1f)
    //            {
    //                lst.Remove(cTextItem);
    //            }
    //            cTextItem.pt = new Point(intFormWidthByTwo - cTextItem.sz.Width/2,  (int)((float)intFormHeight *(1f- fltPCElapsedTravelTime)));
    //        }
            
    //    }

    //    Point _pt = new Point();
    //    public Point pt
    //    {
    //        get { return _pt; }
    //        set { _pt = value; }
    //    }

        

    //    Bitmap _bmp = null;
    //    public Bitmap bmp
    //    {
    //        get
    //        {
    //            return _bmp;
    //        }
    //    }

    //    public float fltSize
    //    {
    //        get
    //        {
    //            float fltPCUpScreen = (float)pt.Y / (float)formSolitaire.instance.Height;
    //            return fltPCUpScreen;
    //        }
    //    }
    //    public Size sz
    //    {
    //        get
    //        {
    //            Size szRetVal =  new Size((int)(fltSize * bmp.Width), (int)(fltSize * bmp.Height));
    //            return szRetVal;
    //        }
    //    }
    //    public DateTime dtStart = new DateTime();
    //    public static TimeSpan tsTravelTime = new TimeSpan(0, 0, 25);

    //    Font fnt = new Font("ms sans-serif", 72);
    //    public classScrollingTextItem(string strText)
    //    {
    //        strText = strText + "  ";
    //        Size sz = TextRenderer.MeasureText(strText, fnt);
    //        Bitmap bmpTempt = new Bitmap(sz.Width, sz.Height);
    //        Color clrTransparent = Color.AntiqueWhite;
    //        SolidBrush sbrTransparent = new SolidBrush(clrTransparent);
    //        using (Graphics g = Graphics.FromImage(bmpTempt))
    //        {
    //            g.FillRectangle(sbrTransparent, new Rectangle(0, 0, bmpTempt.Width, bmpTempt.Height));
    //            g.DrawString(strText, fnt, new SolidBrush(Color.Black), new Point());
    //        }

    //        _bmp = new Bitmap(bmpTempt.Width, bmpTempt.Height);
    //        using (Graphics g = Graphics.FromImage(_bmp))
    //        {
    //            g.FillRectangle(sbrTransparent, new RectangleF(0, 0, _bmp.Width, _bmp.Height));

    //            for (int intYCounter = bmpTempt.Height; intYCounter >= 0; intYCounter--)
    //            {
    //                Rectangle recSource = new Rectangle(0, intYCounter, bmpTempt.Width, 1);
    //                int intWidthOut = bmpTempt.Width - 2 * (bmpTempt.Height - intYCounter);
    //                int intSides = (bmpTempt.Width - intWidthOut) / 2;
    //                Rectangle recDest = new Rectangle(intSides, intYCounter, bmpTempt.Width - 2 * intSides, 1);
    //                g.DrawImage(bmpTempt, recDest, recSource, GraphicsUnit.Pixel);
    //            }
    //        }

    //        _bmp.MakeTransparent(clrTransparent);
    //        //_bmp.Save(@"c:\debug\bmp.png");
           
    //        lst.Add(this);
    //        dtStart = DateTime.Now;
    //        cEventTicket_Scroll.AutoRepeat = lst.Count > 0;
    //    }
    //}

    public class classAnimation_Intro_Item
    {
        public static List<classAnimation_Intro_Item> lst = new List<classAnimation_Intro_Item>();
        public static DateTime dtStartAnimation;
        static classEventController.classEventTicket _cEventTicket_QuitAnimation = null;
        static classEventController.classEventTicket cEventTicket_QuitAnimation
        {
            get
            {
                if (_cEventTicket_QuitAnimation ==null)
                {
                    _cEventTicket_QuitAnimation = formSolitaire.cEC.Ticket("animationIntro_Quit", 5500, tmrAnimationIntroQuit_Tick);
                    _cEventTicket_QuitAnimation.quit();
                }
                return _cEventTicket_QuitAnimation;
            }
        }
        static void tmrAnimationIntroQuit_Tick(object sender, EventArgs e)
        {
            lst.Clear();
        }

        public static formSolitaire frmSolitaire
        {
            get { return formSolitaire.instance; }
        }


        public static void Launch()
        {
            lst.Clear();
            int intNumItems = Enum.GetNames(typeof(enuAnimationItems)).Length;
            Point ptFormCenter = new Point(formSolitaire.instance.Width / 2, formSolitaire.instance.Height / 2);
            Point ptShiftFromCenter = new Point(ptFormCenter.X / 4, ptFormCenter.Y / 4);
            int intSuitSizes = formSolitaire.instance.Height /3;
            Size szSuit = new Size(intSuitSizes, intSuitSizes);
            float fltFractionSuitShift = 0.3f;
            
            for (int intItemCounter =0; intItemCounter < intNumItems; intItemCounter ++)
            {
                enuAnimationItems eItem = (enuAnimationItems)intItemCounter;
                switch(eItem)
                {
                    case enuAnimationItems.Spade:
                        {
                            classAnimation_Intro_Item cSpade = new classAnimation_Intro_Item();
                            cSpade._bmp = new Bitmap(Properties.Resources.Foundation_image_Spade);
                            cSpade._bmp.MakeTransparent(cSpade._bmp.GetPixel(0, 0));
                            cSpade.ptStart = new Point(formSolitaire.instance.Width, 0);
                            cSpade.ptEnd = new Point(ptFormCenter.X + (int)(cSpade._bmp.Width*fltFractionSuitShift) , ptFormCenter.Y - (int)(cSpade._bmp.Height *fltFractionSuitShift));
                            cSpade.szStart = new Size(4, 4);
                            cSpade.szEnd = szSuit;
                            lst.Add(cSpade);
                        }
                        break;

                    case enuAnimationItems.Heart:
                        {
                            classAnimation_Intro_Item cHeart = new classAnimation_Intro_Item();
                            cHeart._bmp = new Bitmap(Properties.Resources.Foundation_image_Heart);
                            cHeart._bmp.MakeTransparent(cHeart._bmp.GetPixel(0, 0));
                            cHeart.ptStart = new Point(0, 0);
                            cHeart.ptEnd = new Point(ptFormCenter.X - (int)(cHeart._bmp.Width *fltFractionSuitShift), ptFormCenter.Y - (int)(cHeart._bmp.Height *fltFractionSuitShift));
                            cHeart.szStart = new Size(4, 4);
                            cHeart.szEnd = szSuit;
                            lst.Add(cHeart);
                        }
                        break;

                    case enuAnimationItems.Club:
                        {
                            classAnimation_Intro_Item cClub = new classAnimation_Intro_Item();
                            cClub._bmp = new Bitmap(Properties.Resources.Foundation_image_Club);
                            cClub._bmp.MakeTransparent(cClub._bmp.GetPixel(0, 0));
                            cClub.ptStart = new Point(0, formSolitaire.instance.Height);
                            cClub.ptEnd = new Point(ptFormCenter.X - (int)(cClub._bmp.Width*fltFractionSuitShift), ptFormCenter.Y + (int)(cClub._bmp.Height*fltFractionSuitShift));
                            cClub.szStart = new Size(4, 4);
                            cClub.szEnd = szSuit;
                            lst.Add(cClub);
                        }
                        break;

                    case enuAnimationItems.Diamond:
                        {
                            classAnimation_Intro_Item cDiamond = new classAnimation_Intro_Item();
                            cDiamond._bmp = new Bitmap(Properties.Resources.Foundation_image_Diamond);
                            cDiamond._bmp.MakeTransparent(cDiamond._bmp.GetPixel(0, 0));
                            cDiamond.ptStart = new Point(formSolitaire.instance.Width, formSolitaire.instance.Height);
                            cDiamond.ptEnd = new Point(ptFormCenter.X + cDiamond._bmp.Width/2, ptFormCenter.Y + cDiamond._bmp.Height/2);
                            cDiamond.szStart = new Size(4, 4);
                            cDiamond.szEnd = szSuit;
                            lst.Add(cDiamond);
                        }
                        break;

                    case enuAnimationItems.Title:
                        {
                            classAnimation_Intro_Item cTitle = new classAnimation_Intro_Item();
                            cTitle._bmp = new Bitmap(Properties.Resources.Solitaire_title);
                            cTitle._bmp.MakeTransparent(cTitle._bmp.GetPixel(0, 0));
                            cTitle.ptStart = ptFormCenter;
                            cTitle.ptEnd = ptFormCenter;
                            float fltAR = (float)cTitle._bmp.Height / (float)cTitle._bmp.Width;
                            int intWidth = formSolitaire.instance.Width * 4;
                            int intHeight = (int)(fltAR * (float)intWidth);
                            cTitle.szStart = new Size(intWidth, intHeight);
                            int intWidth_End = (int)(frmSolitaire.Width * .8);
                            int intHeight_End = (int)(fltAR * (float)intWidth_End);
                            cTitle.szEnd = new Size(intWidth_End, intHeight_End);
                            lst.Add(cTitle);
                        }
                        break;

                    case enuAnimationItems.author:
                        {
                            classAnimation_Intro_Item cAuthor = new classAnimation_Intro_Item();
                            cAuthor._bmp = new Bitmap(Properties.Resources.Syntax_error_software);
                            cAuthor._bmp.MakeTransparent(cAuthor._bmp.GetPixel(0, 0));
                            cAuthor.ptStart = new Point(formSolitaire.instance.Width/2, formSolitaire.instance.Height);

                            float fltAR = (float)cAuthor._bmp.Height / (float)cAuthor._bmp.Width;
                            int intWidth = formSolitaire.instance.Width/8;
                            int intHeight = (int)(fltAR * (float)intWidth);
                            cAuthor.szStart = new Size(intWidth, intHeight);
                            cAuthor.szEnd = cAuthor._bmp.Size;
                            cAuthor.ptEnd = new Point((int)(frmSolitaire.Width - cAuthor.szEnd.Width/2 )-14, (int)(ptFormCenter.Y + 2.5 * ptShiftFromCenter.Y));
                            lst.Add(cAuthor);
                        }
                        break;
                }
            }

            dtStart = DateTime.Now;
            cEventTicket_QuitAnimation.Reschedule();
        }

        static TimeSpan tsAnimationLength = new TimeSpan(0, 0, 0, 0, 3500);

        Bitmap _bmp = null;
        public Bitmap bmp
        {
            get { return _bmp; }
        }

        Point ptStart = new Point(0, 0);
        Point ptEnd = new Point();
        Size szStart = new Size(4,4);
        Size szEnd = new Size(50,50);

        static DateTime dtStart = DateTime.Now;

        public Size size
        {
            get
            {
                DateTime dtNow = DateTime.Now;
                TimeSpan tsElapsed = dtNow - dtStart;
                float fltPCElapsed = (float)tsElapsed.TotalMilliseconds / (float)tsAnimationLength.TotalMilliseconds;
                if (fltPCElapsed > 1)fltPCElapsed = 1f;
                int intWidth = szStart.Width + (int)((float)(szEnd.Width - szStart.Width) * fltPCElapsed);
                int intHeight = szStart.Height + (int)((float)(szEnd.Height - szStart.Height) * fltPCElapsed);
                return new Size(intWidth, intHeight);
            }
        }

        public Point ptPosition
        {
            get
            {
                DateTime dtNow = DateTime.Now;
                TimeSpan tsElapsed = dtNow - dtStart;
                float fltPCElapsed = (float)tsElapsed.TotalMilliseconds / (float)tsAnimationLength.TotalMilliseconds;
                if (fltPCElapsed > 1) fltPCElapsed = 1f;
                int intX = ptStart.X + (int)((float)(ptEnd.X - ptStart.X) * fltPCElapsed);
                int intY = ptStart.Y + (int)((float)(ptEnd.Y - ptStart.Y) * fltPCElapsed);
                return new Point(intX, intY);
            }
        }
    }

}
