public bool RunFilter(int BoardsToSave)
        {
            bool bCanSpinMore = true;
            int  LastCount;

            cSC.CountLimit   = 0;
            BoardBeingWorked = 0;
            board tb, OldBoard;
            bool  bOnlyNotifyOnce = true;

            cSC.bSignalSpinDone        = false;
            cSC.bExceededCountLimit    = false;
            cSC.bExceededONEcolLimit   = false;
            cSC.bExceededTWOcolLimit   = false;
            cSC.bExceededThreecolLimit = false;
            cSC.bOutOfSpaceInSTLOOKUP  = false;
            cSC.bGotOneSuitAtLeast     = false;
            dtFirstBoard = DateTime.Now;
            cSC.SortedScores.Clear();
            cSC.BestScoreIndex.Clear();
            cSC.TimeDealStarted = TimeLastBest;
            NumOne             = 0;
            NumTwo             = 0;
            NumThreeOrBetter   = 0;
            Num3000            = 0;
            TimeLastBest       = DateTime.Now; // in event we never get a "best"
            TimeSinceFilterRan = TimeLastBest;
            OriginalCount      = cSC.ThisBoardSeries.Count;
            bool bAnyInShrink;

            //bool bAbleToReduce = false;
            ClearNumSuitedInSeries();
            while (BoardBeingWorked < cSC.ThisBoardSeries.Count)
            {
                OldBoard = cSC.ThisBoardSeries[BoardBeingWorked];
                tb       = new board(ref OldBoard);
                tb.from  = OldBoard.ID;
                //cSC.Strategy.ExposeOneTop(ref tb);
                tb.RunCounter = cSC.RunCounter++;

                if (tb.NotifySuitJustCompleted && bOnlyNotifyOnce)
                {
                    tb.NotifySuitJustCompleted = false;
                    bOnlyNotifyOnce            = tb.bIsCompletable; // once all are done then no need for hi values
                    utils.SetSuitableValues(ref cSC, ref tb);
                }

                // cSC.JoinSuited.JoinAllSuitedWhenRankable(ref tb);
                // 12november2012 had to comment out the above because makeing wrong moves
                int any = cSC.Strategy.FirstStrategy(ref tb);

                //if (BoardBeingWorked < OriginalCount)
                //{
                //    int any = cSC.Strategy.FirstStrategy(ref tb);
                //    bAbleToReduce = (any > 0);
                //    if (bAbleToReduce)
                //    {
                //        cSC.Strategy.GetBoards();
                //    }
                //}
                //else
                //{
                //    int any = cSC.Strategy.RunJoinables(ref tb, true);
                //    bAbleToReduce = (any > 0);
                //}



                LastCount    = cSC.ThisBoardSeries.Count;
                bCanSpinMore = SpinOff(ref tb);
                if (GlobalClass.bFoundFirstColunn)
                {
                    string strName = cSC.FormName(tb.DealCounter, eSavedType.eFIRST);
                    GlobalClass.bFoundFirstColunn = false;
                    cSC.cBD.SetCS(ref GlobalClass.FirstEmptyColumn);
                    cXmlFromBoard xtest = new cXmlFromBoard();
                    xtest.ReCreateBinFile(ref GlobalClass.FirstEmptyColumn, ref cSC, strName);
                    cSC.Deck.SaveBoardMoves(ref GlobalClass.FirstEmptyColumn, strName);
                }
                OldBoard.nchild = cSC.ThisBoardSeries.Count - LastCount;
                BoardBeingWorked++;
                if (cSC.bSignalSpinDone)
                {
                    Console.WriteLine("Spin Done");
                    break;
                }
            }
            if (LastDuplicateBoard != null)
            {
                int        LDB_ID = LastDuplicateBoard.ID;
                cBestScore cBS    = new cBestScore(LDB_ID,
                                                   LastDuplicateBoard.score,
                                                   LastDuplicateBoard.NumEmptyColumns,
                                                   LastDuplicateBoard.NumCompletedSuits,
                                                   LastDuplicateBoard.bOnLastDeal);
                cSC.SortedScores.Add(cBS);
                Debug.Assert(LastDuplicateBoard.score == cSC.ThisBoardSeries[LDB_ID].score);
                LastDuplicateBoard = null;
            }

            cSC.bSpinDidAllBoards = (BoardBeingWorked == cSC.ThisBoardSeries.Count);
            //if (cSC.bExceededONEcolLimit) cSC.bSpinDidAllBoards = true;
            cSC.bStopThisRun = cSC.Strategy.ConsiderStopRunning(ref RepeatDepth);
            if ((GlobalClass.TraceBits & 2) > 0)
            {
                Console.WriteLine("DidAllBoards:" + cSC.bSpinDidAllBoards + " SpinDone:" + cSC.bSignalSpinDone + " ScoresSaved:" + cSC.SortedScores.Count + " NumSeeds:" + cSC.ThisSeed.SeedIndex.Count);
            }
            bAnyInShrink = ShrinkThisBoardSeries(BoardsToSave);
            if (!bAnyInShrink)
            {
                int n = cSC.ThisSeed.SeedIndex.Count;
                Console.WriteLine("None in shrink but seed was:" + n.ToString());
                for (int i = 0; i < n; i++)
                {
                    cSC.ThisBoardSeries[cSC.ThisSeed.SeedIndex[i]].MyMoves.AddShrinkCode(ref cSC, n);
                }
            }
            return(bAnyInShrink);
        }
        // return true if was able to create a new board
        public bool SpinOneCard(ref board tb, int SrcCol, int SrcCard, int DesCol, int DesCard)
        {
            if (cSC.bTrigger)
            {
                Console.WriteLine(MethodBase.GetCurrentMethod().Name);
            }
            int      iSecs = 0;
            TimeSpan TimeSinceLastBest;

            tb.AssignCompletedID(GlobalClass.TypeCompletedBy.ID_BS);
            tb.moveto(SrcCol, SrcCard, DesCol);

            tb.ReScoreBoard();
            if (tb.NotifySuitJustCompleted)
            {
                NumSuitsWritten++;
                bool   WriteOnce        = true;
                string strJustCompleted = "_";
                int    j = 1;
                for (int i = 0; i < 4; i++)
                {
                    if ((j & tb.bitJustCompleted) > 0)
                    {
                        strJustCompleted += GlobalClass.cSuits[i] + "_";
                        SuitsCompleted[i]++;
                        if (SuitsCompleted[i] > 1)
                        {
                            WriteOnce = false;
                        }
                    }
                    j = j << 1;
                }

                if (WriteOnce)
                {
                    string strName = cSC.Deck.SaveBoardAsBin(ref tb, eSavedType.eSUIT);
                    cSC.Deck.SaveBoardMoves(ref tb, strName);
                }
            }
            if (tb.score >= cSC.BestScore)
            {
                if (tb.score == cSC.BestScore)
                {
                    LastDuplicateBoard = tb;
                }
                else
                {
                    cSC.BestScore = tb.score;
                    cBestScore cBS = new cBestScore(cSC.ThisBoardSeries.Count, tb.score, tb.NumEmptyColumns, tb.NumCompletedSuits, tb.bOnLastDeal);
                    if (tb.NotifySuitJustCompleted)
                    {
                        cBS.SuitJustCompleted |= tb.bitJustCompleted;
                    }
                    cSC.SortedScores.Add(cBS);
                    cSC.BestBoard      = tb;
                    LastDuplicateBoard = null;
                }
            }
            else
            {
                if (tb.bOnLastDeal && false)
                {
                    cBestScore cBS = new cBestScore(cSC.ThisBoardSeries.Count, tb.score, tb.NumEmptyColumns, tb.NumCompletedSuits, tb.bOnLastDeal);
                    if (tb.NotifySuitJustCompleted)
                    {
                        cBS.SuitJustCompleted |= tb.bitJustCompleted;
                    }
                    cSC.SortedScores.Add(cBS);
                }
            }

            tb.NotifySuitJustCompleted = false;
            //tb.from = tb.ID;  // board was not spun off here
            tb.ID = cSC.ThisBoardSeries.Count;
            tb.AssignCompletedID();

            if ((GlobalClass.TraceBits & 8) > 0 || cSC.bTrigger)
            {
                tb.ShowRawBoard();
            }
            cSC.ThisBoardSeries.Add(tb);

            cSC.CountLimit++;
            TimeSinceLastBest = DateTime.Now.Subtract(TimeLastBest);
            if (cSC.bSignalSpinDone)
            {
                return(false);
            }
            if (TimeSinceLastBest.TotalSeconds > cSC.MaxValues.TimeOutBest)
            {
                Console.WriteLine("Aborting due to timeing out");
                if ((GlobalClass.TraceBits & 2) > 0)
                {
                    Console.WriteLine("Best1: " + cSC.BestScore + " dups:" + cSC.NumberDuplicates + " BoardsScored:" + cSC.CountLimit + " LastBoardSpun:" + BoardBeingWorked);
                    Console.WriteLine("Suits made (dchs) " + SuitsCompleted[0].ToString() + " " +
                                      SuitsCompleted[1].ToString() + " " +
                                      SuitsCompleted[2].ToString() + " " +
                                      SuitsCompleted[3].ToString() + " StringSuits:" + tb.strSuitsRemoved);
                    if (OriginalCount > BoardBeingWorked)
                    {
                        Console.WriteLine("Did not visit " + (OriginalCount - BoardBeingWorked) + " boards from last deal");
                    }
                }
                cSC.bSpinTimedOut   = true;
                cSC.bSignalSpinDone = true;
                return(false);
            }
            if (tb.score > GlobalClass.SUIT_WEIGHT)
            {
                Num3000++;
                if (tb.NotifySuitJustCompleted)
                {
                    tb.NotifySuitJustCompleted = false;
                    utils.SetSuitableValues(ref cSC, ref tb);
                    //cSC.bSignalSpinDone = true;
                    cSC.bGotOneSuitAtLeast = true;
                    //Console.WriteLine("Completed Suit");
                    //return true;
                }
            }
            else if (tb.NumEmptyColumns > 2)
            {
                NumThreeOrBetter++;
                if (NumThreeOrBetter > 100 && Num3000 == 0)
                {
                    cSC.bSignalSpinDone        = true;
                    cSC.bExceededThreecolLimit = true;
                    Console.WriteLine("ABORT:  Too many Three Column events: " + NumThreeOrBetter);
                    return(false);
                }
            }
            else if (tb.NumEmptyColumns > 1)
            {
                NumTwo++;
//                if (NumTwo > (cSC.MaxValues.MaxInserts / (1000 - 198 * tb.DealCounter)) && NumThreeOrBetter == 0)
                if (NumTwo > (1 + tb.DealCounter) * 200 && NumThreeOrBetter == 0)
                {
                    cSC.bSignalSpinDone      = true;
                    cSC.bExceededTWOcolLimit = true;
                    Console.WriteLine("ABORT:  Too many Two Column events: " + NumTwo);
                    return(false);
                }
            }
            else if (tb.NumEmptyColumns > 0)
            {
                NumOne++;
                //if (NumOne > ((1 + tb.DealCounter) * 1000) && NumTwo == 0)
                if (NumTwo == 0)
                {
                    if (NumOne > (tb.DealCounter < 2 ? GlobalClass.SUIT_WEIGHT : (2 * GlobalClass.SUIT_WEIGHT)))
                    {
                        cSC.bSignalSpinDone      = true;
                        cSC.bExceededONEcolLimit = true;
                        Console.WriteLine("ABORT:  Too many One Column events: " + NumOne);
                        return(false);
                    }
                }
            }

            if (0 == (cSC.CountLimit % 5000) && ((GlobalClass.TraceBits & 4) > 0))
            {
                dtNow = DateTime.Now;
                TimeSpan tc         = dtNow.Subtract(tb.TimeOfLastDeal);
                string   strSinceLD = "";
                if (tc.TotalSeconds < 60)
                {
                    strSinceLD = Convert.ToInt32(tc.TotalSeconds).ToString("0") + "s";
                }
                else
                {
                    strSinceLD = Convert.ToInt32(tc.TotalMinutes).ToString("0") + "m";
                }

                dtDiff = dtNow.Subtract(dtLast);
                dtLast = dtNow;
                iSecs  = Convert.ToInt32(dtDiff.TotalSeconds);
                tb.ShowBoard();
                Console.WriteLine("Q(" + cSC.SortedScores.Count + ") " + cSC.BestScore + " dups:" + cSC.NumberDuplicates + " limit:" + cSC.CountLimit / 1000 + "k i:" + BoardBeingWorked + " et:" + strSinceLD + " dif:" + (cSC.CountLimit - BoardBeingWorked) + " 1c:" + NumOne + " 2c:" + NumTwo + " 3+" + NumThreeOrBetter + " " + strSpinType);
                cSC.stlookup.ShowBufferStats();
            }


            // if (MoveValue == board.DEALT_A_CARD) return bCreatedBoard;
            // no need to check timouts, etc as we just want to get this board into the system

            if (cSC.CountLimit >= cSC.MaxValues.MaxInserts)
            {
                cSC.bSignalSpinDone     = true;
                cSC.bExceededCountLimit = true;
                Console.WriteLine("Aborting!  Exceeded limit when counting");
            }

            if (cSC.bSignalSpinDone && (GlobalClass.TraceBits & 2) > 0)
            {
                dtNow  = DateTime.Now;
                dtDiff = dtNow.Subtract(dtLast);
                dtLast = dtNow;
                iSecs  = Convert.ToInt32(dtDiff.TotalSeconds);
                tb.ShowBoard();
                Console.WriteLine("SpinDone - Best: " + cSC.BestScore + " dups:" + cSC.NumberDuplicates + " limit:" + cSC.CountLimit / 1000 + "k i:" + BoardBeingWorked + " et:" + iSecs + " dif:" + (cSC.CountLimit - BoardBeingWorked) + " 1c:" + NumOne + " 2c:" + NumTwo + " 3+" + NumThreeOrBetter);
                return(false);
            }

            if (cSC.bSignalSpinDone)
            {
                return(false);
            }

            LastCount = cSC.ThisBoardSeries.Count;
            if (cSC.BestScore > GlobalClass.COL_WEIGHT)
            {
                if (cSC.BestScore > LastBest)
                {
                    if ((GlobalClass.TraceBits & 2) > 0)
                    {
                        Console.WriteLine(TraceBoard(LastCount - 1));
                        dtDiff = DateTime.Now.Subtract(dtFirstBoard);
                        tb.ShowBoard();
                        TimeSinceFilter = DateTime.Now.Subtract(TimeSinceFilterRan);
                        Console.WriteLine("Extra:(" + tb.ExtraPoints + ") " + cSC.BestScore + " dups:" + cSC.NumberDuplicates + " limit:" + cSC.CountLimit + " i:" + BoardBeingWorked + " TO: " + cSC.MaxValues.TimeOutBest + " (Sec) MaxIter:" + cSC.MaxValues.MaxInserts + " TimeSinceFilterRan(sec):" + TimeSinceFilter.TotalSeconds.ToString("0"));
                    }
                }
                LastBest = cSC.BestScore;
            }
            return(true); // bSignalSpinDone;
        }