public bool SpinOff(ref board tb) { int i, j; if (cSC.bTrigger) { Console.WriteLine(MethodBase.GetCurrentMethod().Name); } int n = tb.ThisColumn[10].Cards.Count; for (i = 0; i < 10; i++) { j = i; // cCO[i].ptr; if (tb.ThisColumn[j].Cards.Count == 0) { continue; // column is empty: nothing to spin } if (tb.NumEmptyColumns > 2) // || tb.bOnLastDeal ||(n==10 && tb.NumEmptyColumns == 1 )) { strSpinType = "Spin by suit!"; if (SpinThisSuitedColumn(ref tb, j)) { continue; } return(false); } else { if (SpinThisColumn(ref tb, j)) { continue; } return(false); } } return(true); }
public int FirstStrategy(ref board oldb) { int TotalAny = 0, Any = 0; int NumSOS; board tb; OurLastBest = oldb.LastBest; if (oldb.NumEmptyColumns >= 1) { do { Any = ExposeTop(ref oldb); TotalAny += Any; } while (Any > 0); } if (!(oldb.RunEndgame())) { return(0); } Any = SOSExposeTop(ref oldb); TotalAny += Any; NumSOS = NewBoards.Count; // SOSexpose added this many if (oldb.bIsCompletable) { Any += RunJoinables(ref oldb, false); // process the original board for (int i = 0; i < NumSOS; i++) // process any that SOSexpose created { tb = NewBoards[i]; board nb = new board(ref tb); Any += RunJoinables(ref nb, false); TotalAny += Any; } } return(TotalAny); }
// this looks for available spots to stuff a card and if it cannot find one it suggests an empty stack // this is different than the one in strategy because it can use the default BottomMost. This is true // because we are leaving the list unchanged. private int GetBestMove(card c, ref board tb) { int i, n; int iSameSuit = -1; int iAnySuit = -1; int ToStack = -1; n = tb.BottomMost.Count; for (i = 0; i < n; i++) { if (tb.BottomMost[i].ExcludePlaceholder) { continue; // cannot use this } if (tb.BottomMost[i].rank - 1 == c.rank) { if (tb.BottomMost[i].suit == c.suit) { iSameSuit = i; ToStack = tb.BottomMost[i].iStack; break; } iAnySuit = i; } } if (iAnySuit < 0 && iSameSuit < 0) { return(-1); // signal to use an empty column } if (iSameSuit >= 0) { return(ToStack); } ToStack = tb.BottomMost[iAnySuit].iStack; return(ToStack); }
private string AssemblePatternFrom(ref board tb, ref series sCollapse, string strInxvars) { int i, j, n = sCollapse.size; card c; string strPattern = ""; column cCol = tb.ThisColumn[sCollapse.iStack]; for (i = 0; i < n; i++) { c = cCol.Cards[i + sCollapse.topCard.iCard]; cAssemblePattern cap = new cAssemblePattern(ref c, i); AssemblePattern.Add(cap); // the original pattern needs to be recovered when performing moves // ie: if the cards are 5h,3C,4C we move 4C then 3C then bring them back to the faceup 5H // We sort only to get the pattern } AssemblePattern.Sort(delegate(cAssemblePattern c1, cAssemblePattern c2) { return(Comparer <int> .Default.Compare(c1.c.rank, c2.c.rank)); }); for (i = 0; i < AssemblePattern.Count; i++) { AssemblePattern[i].PatLetter = strInxvars.Substring(i, 1); } for (i = 0; i < AssemblePattern.Count; i++) { j = AssemblePattern[i].index; string a = APLookup(ref AssemblePattern, i); dictLookup.Add(a, cCol.Cards[i + sCollapse.topCard.iCard]); strPattern += a; } return(strPattern); }
// this spins only a series of cards of same suit private bool SpinCardInto(ref board tb, int ColumnToFill) { int i; series s; Debug.Assert(tb.ThisColumn[ColumnToFill].Cards.Count == 0); // do not move a card into a column that contains something for (i = 0; i < 10; i++) { if (OEmpties.Contains(i)) { continue; } // do not move from empty column because it is either empty // or we just put something in it so as to make it not empty if (tb.ThisColumn[i].ThisSeries.Count == 1 && tb.ThisColumn[i].ThisSeries.Last().top == 0) { continue; } // do not create an empty column just to fill another one nb = new board(ref tb); nb.dead = false; s = nb.ThisColumn[i].ThisSeries.Last(); //stats[i]++; nb.moveto(i, s.top, ColumnToFill); //nb.ThisColumn[i].CalculateColumnValue(i); //nb.ThisColumn[ColumnToFill].CalculateColumnValue(ColumnToFill); nb.ReScoreBoard(); NewBoards.Add(nb); } return(false); }
public bool ReAssembleStackables(ref List <series> Unstackables, ref board tb, string strPattern) { int i, j, n = strPattern.Length; string strPossibles = "ABCDEFG".Substring(0, n); dictLookup.Clear(); j = n; for (i = 0; i < n; i++) { dictLookup.Add(strPossibles.Substring(--j, 1), Unstackables[i].topCard); } tb.CopyWorkingInts(ref xEmpties, GlobalClass.WorkingType.tEmpties); /* * the following was to go there, but we are doing a type of expose top and there is no SCard * as SCard is the breakup column, not another column. use the FILLDS type tools * SCard = new card(ref sCollapse.bottomCard, sCollapse.bottomCard.iStack, sCollapse.bottomCard.iCard); * dictLookup.Add("S", SCard); * * // check first to see if we can use our empty columns * for (i = 0; i < sosDisStrategy.Count; i++) * { * cds = sosDisStrategy[i]; * if (n == cds.NumCards && cds.NumEmptyColumns <= tb.NumEmptyColumns) * { * if (cds.Collapsible != null || strPattern != cds.Pattern) continue; // only want to use empties * sosUnstackE(ref tb, ref cds); * return true; * } * } * * */ return(false); }
//complete starts off with x 110 y 380 then x goes to 140 (increments by 30 private void MakeXmlFile(string strFullPathName, ref board tb, ref cSpinControl cSC) { bool bFaceUp; // deck: all are false except the last enabled bool bEnabled; // complete: all are faceup and all enabled are false sbXML = new StringBuilder(16384); XmlWriterSettings settings = new XmlWriterSettings(); settings.Indent = true; settings.IndentChars = (" "); settings.NewLineChars = "\n"; settings.OmitXmlDeclaration = true; using (XmlWriter writer = XmlWriter.Create(sbXML, settings)) //(strFullPathName + "_bin.xml", settings)) // using (XmlWriter writer = XmlWriter.Create(strFullPathName + "_bin.xml", settings)) { // Write XML data. writer.WriteStartElement("Root"); writer.WriteStartElement("GameState"); writer.WriteElementString("Version", "7"); writer.WriteElementString("GameSeed", cSC.GameSeed.ToString()); writer.WriteElementString("Score", tb.score.ToString()); // 2018 tb.score.ToString()); writer.WriteElementString("Moves", (1 + tb.DealCounter).ToString()); // (tb.NumMoves + tb.MyMoves.TheseMoves.Count).ToString()); writer.WriteEndElement(); // gamestate writer.WriteStartElement("CardTable"); writer.WriteStartElement("CardStacks"); cCardStack ccsPtr; int nCardStack = 0; int nDirection = 1; foreach (column col in tb.ThisColumn) { ccsPtr = col.CardStack; int ccsPtrX = ccsPtr.X; int ccsPtrY = ccsPtr.Y; int j = 0; // count cards as only last one is enabled int dX = 0, dY = 0; string stackName = ""; switch (nDirection) { case 1: stackName = "Stack" + (col.CardStack.stackid).ToString(); dY = 7; dX = -7; break; case 2: stackName = "Deck"; dX = -6; break; case 3: stackName = "Complete"; dX = 30; // origin of X was 110 dY = 0; // origin of Y was 380 break; } writer.WriteStartElement("CardStack"); writer.WriteElementString("NumEndCardsSpaced", ccsPtr.NumEndCardsSpaced.ToString()); writer.WriteElementString("X", ccsPtr.X.ToString()); writer.WriteElementString("Y", ccsPtr.Y.ToString()); writer.WriteElementString("Name", stackName); writer.WriteElementString("Direction", nDirection.ToString()); writer.WriteStartElement("Cards"); foreach (card crd in col.Cards) { writer.WriteStartElement("Card"); writer.WriteElementString("X", ccsPtrX.ToString()); writer.WriteElementString("Y", ccsPtrY.ToString()); bFaceUp = crd.bFaceUp; bEnabled = bFaceUp; if (nDirection == 3) { bFaceUp = true; bEnabled = false; } else if (nDirection == 2) { bFaceUp = false; bEnabled = (j == (col.Cards.Count - 1)); } if (nDirection == 1) { ccsPtrY += dY; } writer.WriteElementString("Name", GlobalClass.ProperName(crd)); writer.WriteElementString("Type", crd.type.ToString()); writer.WriteElementString("FaceUp", bFaceUp.ToString().ToLower()); writer.WriteElementString("Enabled", bEnabled.ToString()); if (bFaceUp && nDirection < 3) { dY = 23; } if (((1 + j) % 13) == 0) { ccsPtrX += dX; if (nDirection != 1) { ccsPtrY += dY; } } j++; writer.WriteEndElement(); // card } writer.WriteEndElement(); // cards writer.WriteEndElement(); //CardStack nCardStack++; if (nCardStack == 10) { nDirection = 2; } if (nCardStack == 11) { nDirection = 3; } // need to write out the completed stack eventually!! } writer.WriteEndElement(); // cardstacks writer.WriteEndElement(); // cardtable writer.WriteEndElement(); // root writer.Flush(); if (strFullPathName.Contains("SUIT")) { Console.WriteLine(" Wrote out a binary suit file: " + strFullPathName); } else if (strFullPathName.Contains("DEAL")) { Console.WriteLine(" Wrote out a binary deal file: " + strFullPathName); } else { Console.WriteLine(" replaced with a new binary deal file: " + strFullPathName); } foreach (cSuitedStatus cSS in tb.SuitStatus) { for (int i = 0; i < cSS.NumCompletedAndRemoved; i++) { Console.WriteLine("Removed suit:" + GlobalClass.SuitNames[cSS.index]); } } } }
static void SolveBoard(ref cSpinControl cSC, string strSpiderBin) { int m = GlobalClass.MAX_FILTERED_BOARDS; GlobalClass.StrategyType gcst = GlobalClass.StrategyType.CONTINUE_SPINNING; board InitialBoard = new board(); cSC.Deck = new cBuildDeck(strSpiderBin, XMLtoRead, ref cSC); MakeAllPossibleMoves = new cSpinAllMoves(ref cSC); cSC.Deck.GetBoardFromSpiderSave(ref InitialBoard); if (InitialBoard.NumEmptyColumns > 0) { GlobalClass.bFoundFirstColunn = false; // started with an empty column, no need to display it. } InitialBoard.ShowBoard(); cSC.cMXF = new cMergeXmlFile(); if (cSC.bJustReadXML) { Console.WriteLine(" Did you mean to read a pre-existing XML file?\n - close window to abort\n - or press N to delete the XML file and abort\n - or press Y to continue"); if (cSC.EventList.Count > 0) { Console.WriteLine(" There are " + cSC.EventList.Count + " events in the event list"); Console.WriteLine(cSC.Deck.strEventInfoPrompt); } ConsoleKeyInfo cki = Console.ReadKey(); Console.WriteLine(""); if (cki.Key.ToString().ToLower() == "n") { File.Delete(cSC.XML_Diag_filename); Environment.Exit(0); } else { string strA = cki.KeyChar.ToString(); int A = -1; int.TryParse(strA, out A); if (A >= 1 && A < 7) { int RequiredOffset = 0; int RequiredDeal = A; string strCmd = Console.ReadLine().ToLower(); strA = strCmd.Substring(0, 1); InitialBoard = null; if (strA == "m") //Format is 2m34 or 3M45 { strCmd = strCmd.Substring(1); RequiredOffset = Convert.ToInt32(strCmd); bool bResult = cSC.Deck.AdvanceToPosition(RequiredDeal, RequiredOffset, out InitialBoard); CallExit(); } else { if (strA == "s") // format is 2s 3S , etc .. show all best scores { bool bResult = cSC.Deck.ShowAllBestScores(RequiredDeal, out InitialBoard); CallExit(); } else if (strA == "t") // format is 2t45 3t9 , etc .. trace using stlookup { // deals 2, 3, and set breakpoint in debugger at the callout for the 45, 9, etc RequiredOffset = Convert.ToInt32(strCmd.Substring(1)); bool bResult = cSC.Deck.AddBoardsToLookup(RequiredDeal, RequiredOffset); CallExit(); } else { Console.WriteLine("Unknown key code. One of M,S,m,s only"); CallExit(); } } } else { bool bResult = cSC.Deck.AdvanceSaveBoard(cki.Key.ToString().ToLower(), out InitialBoard); Debug.Assert(false); } } } //Suitable.CheckSuitability(ref InitialBoard); // the above is not critical to the program as yet, just good info about unexposed cards //cSC.Suitable.CombineLikeSuits(ref InitialBoard); MakeAllPossibleMoves.AddInitialBoard(ref InitialBoard, GlobalClass.FIRST_CARD, ref Suitable); //cSC.JoinSuited.SpinSuitedJoinables(ref cSC.ThisBoardSeries); //if (InitialBoard.bIsCompletable) PerformReduceSuits(ref cSC, 20); //Console.CancelKeyPress += delegate(object sender, ConsoleCancelEventArgs e) //{ // e.Cancel = true; // Program.keepRunning = false; //}; while (true) // (Program.keepRunning) { RunAway--; if (RunAway < 0) { Console.WriteLine("hit any key except x: TBS:" + cSC.ThisBoardSeries.Count + " NBS:" + cSC.NextBoardSeries.Count); ConsoleKeyInfo cki = Console.ReadKey(); if (cki.KeyChar == 'x') { Environment.Exit(0); } } bool b1 = MakeAllPossibleMoves.RunFilter(m); // m is max to allow after applying filter bool bSameSeed = cSC.PrevSeed.bSameSeed(ref cSC.ThisSeed); if (cSC.bOutOfSpaceInSTLOOKUP) { Console.WriteLine("ran out of space and had to clear stlookup"); cSC.stlookup.Clear(); cSC.bOutOfSpaceInSTLOOKUP = false; } if (cSC.bSpinDidAllBoards) { int iAny = 0; for (int i = 0; i < cSC.ThisBoardSeries.Count; i++) { board nb = cSC.ThisBoardSeries[i]; if (cSC.Suitable.CombineLikeSuits(ref nb)) { iAny++; } } if (iAny > 0) { cSC.bSpinDidAllBoards = false; m = cSC.ThisBoardSeries.Count; Console.WriteLine("Cannot deal but found " + iAny.ToString() + " new boards using join suited" + cSC.bSpinDidAllBoards); } } if (cSC.bSpinDidAllBoards || bSameSeed || cSC.bStopThisRun) { m = HandleDeal(ref cSC, false); Console.WriteLine("Handled deal with m:" + m.ToString() + " bSpin:" + cSC.bSpinDidAllBoards + " SameSeed:" + bSameSeed, " StopRun:" + cSC.bStopThisRun); Console.WriteLine("TBS: " + cSC.ThisBoardSeries.Count + " NBS: " + cSC.NextBoardSeries.Count); cSC.bTrace = true; } else { // unable to finish all boards -or- didnt generate any boards other then the same seeds if (cSC.SortedScores.Count == 0) { // no larger scores were found during the last run: use ThisSeed m = HandleDeal(ref cSC, true); Console.WriteLine("Handled deal from SortedScores.count=0 m:" + m.ToString()); } else { gcst = utils.UseThisManyBoards(ref cSC, ref m); Console.WriteLine("HNS: " + m + " type " + gcst.ToString()); if (gcst != GlobalClass.StrategyType.CONTINUE_SPINNING) { Console.WriteLine("Seem we are to reduce:" + m); HandleNewStrategy(gcst, ref cSC, ref m); } } } } //if (!Program.keepRunning) //{ // cSC.BestBoard.ShowBoard(); // 11nov2012 added this ctrl-c stuff //} }
public static int HandleDeal(ref cSpinControl cSC, bool bDealThruSeed) { int m, n = cSC.ThisBoardSeries.Count; // utils.UseThisManyBoards(ref cSC); cDealStrategy DealStrategy = new cDealStrategy(ref cSC); board tb = null; int j, nNewBoards = 0; if (cSC.BestBoard != null) { SaveBestBoard(ref cSC); } if (bDealThruSeed) { n = cSC.ThisSeed.Seeds.Count; } if (n > GlobalClass.MAX_FILTERED_BOARDS) { n = GlobalClass.MAX_FILTERED_BOARDS; } cSC.BestBoard = null; // only want the one for the current deal for (int i = 0; i < n; i++) { if (bDealThruSeed) { if (i >= cSC.ThisSeed.SeedIndex.Count) { break; } j = cSC.ThisSeed.SeedIndex[i]; } else { j = i; } tb = cSC.ThisBoardSeries[j]; nNewBoards = DealStrategy.DealToBoard(ref tb, DateTime.Now, n); // nNewBoards mistakenly includes dead boards so dont check for n==m anymore cSC.LocalDealCounter++; tb.DealCountIndex = cSC.LocalDealCounter; // save only the first 12 boards of the deal. the deal is against the previous deck if (i < GlobalClass.MaxDealsToShow) { bool bOnLast = ((i == (n - 1)) || (i == (GlobalClass.MaxDealsToShow - 1))); cSC.Deck.SaveBoardAtDeal(bOnLast ? GlobalClass.eSBAD.eAllGathered : GlobalClass.eSBAD.eContinue, ref tb, i); if (tb.MyMoves.TheseMoves.Count() < 6) { int kk = 0; } } if (nNewBoards > GlobalClass.MinInserts) { break; } } m = DealStrategy.GetBoards(ref cSC); if (m <= 0) { if (tb.DealCounter < 5) { Debug.Assert(m > 0); Console.WriteLine("problem with handleing deal! m:" + m + " nNewBoards:" + nNewBoards); } else { Console.WriteLine("Game over\n"); } Environment.Exit(0); } tb = cSC.ThisBoardSeries[0]; utils.SetSuitableValues(ref cSC, ref tb); if (m > GlobalClass.MAX_FILTERED_BOARDS) { m = GlobalClass.MAX_FILTERED_BOARDS; } // all will be processed, just want at most 500 results after RunFilter if (m < GlobalClass.MIN_FILTERED_BOARDS) { m = GlobalClass.MIN_FILTERED_BOARDS; } // want to have at least this many from the filter if possible cSC.BestScore = 0; // this may get new boards into SortedScores at least on the next filter run cSC.stlookup.Clear(); //GlobalClass.bLookForFirstColumn = true; // ONLY WANT TO DO THIS ONCE FOR VERY FIRST TIME. //GlobalClass.bFoundFirstColunn = false; return(m); }
// same as above JSS but does not consume any empty columns // the ranks must be in order (rankable under the series) and the gap above both top cards must be 1 // this routine can be called at any time after building a sorted sequence (BuildSEQ) of any number of suits public bool JoinSuitedWhenRankable(ref board tb) { if (cSC.bTrigger) { Console.WriteLine(MethodBase.GetCurrentMethod().Name); } series sDes, sSrc; series uDes; // the unstacked part of the destination int PossibleCostReduction; int RankWanted, LowestRank, RankWantedLoc; PsuedoMoveList.Clear(); tb.BuildPlaceholders(ref PlaceHolder); //foreach (series s1 in tb.SortedSEQ) for (int i = 0; i < tb.SortedSEQ.Count - 1; i++) { sDes = tb.SortedSEQ[i]; // biggest is first in sorted order of ranks if (sDes.topCard.GapAbove != 1 || sDes.pattern == "") { continue; } // only want reversible moves for swapping purposes // and there must be a pattern of else the series is not rankable PossibleCostReduction = sDes.bRankable ? utils.hasPlaceholder(ref sDes.topCard, ref tb, ref PlaceHolder) : 0; //foreach (series s2 in tb.SortedSEQ) for (int j = i + 1; j < tb.SortedSEQ.Count; j++) { sSrc = tb.SortedSEQ[j]; if (sSrc.topCard.GapAbove != 1 || sSrc.pattern == "") { continue; } if (sSrc.sSuit != sDes.sSuit) { continue; // in event more then one suit is in the sorted list } PossibleCostReduction += sSrc.bRankable ? utils.hasPlaceholder(ref sSrc.topCard, ref tb, ref PlaceHolder) : 0; utils.FreeExcludedPlaceholders(ref PlaceHolder); // done with our PossibleCostReduction // the 0 below represents possibly a single available placeholder ie; we assume NONE here if (sDes.nEmptiesToUnstack + sSrc.nEmptiesToUnstack > (tb.NumEmptyColumns + PossibleCostReduction + 0)) { return(false); } if (sDes.iStack == sSrc.iStack) { continue; } // make s1 (bottom) the destination and s2 (top) the source (ranks must be different) if (sDes.topCard.rank == sSrc.topCard.rank) { continue; // nothing to join } // 9..6 could join to 6..3 by moveing only the 5..3 if it exists RankWanted = sDes.bottomCard.rank - 1; // find a card in source to be mvoed that is this rank LowestRank = sSrc.bottomCard.rank; if (!(RankWanted > LowestRank && sSrc.topCard.rank >= RankWanted)) { continue; } // figure out where that card is in the source to be moved RankWantedLoc = sSrc.top + (1 + sSrc.topCard.rank - sDes.bottomCard.rank); card cSrc = tb.ThisColumn[sSrc.iStack].Cards[RankWantedLoc]; Debug.Assert(RankWanted == cSrc.rank); sSrc.size -= (1 + sSrc.topCard.rank - sDes.bottomCard.rank); sSrc.topCard = cSrc; sSrc.top = cSrc.iCard; if (sSrc.nEmptiesToUnstack == 0 && sDes.nEmptiesToUnstack == 0) { tb.moveto(cSrc.iStack, cSrc.iCard, sDes.bottomCard.iStack); return(true); } //pseudoCard pCard = new pseudoCard(sDes.topCard.ID, sSrc.bottomCard.ID, true); //PsuedoMoveList.Insert(0, pCard); uDes = null; if (sDes.nEmptiesToUnstack > 0) { uDes = sDes.NextSeries; uDes.tag = sSrc.iStack; // after moveing sSrc put the unstack from Des where Src came from // the above works because the algorithm only moves rankables that are in order // so as to not consume a stack. the tag is not updated by any move card operation if (!MoveSeriesBelow(ref tb, ref sDes)) { return(false); } uDes.iStack = tb.tag; // series locations are NOT updated by any cards that are moved // uDes.iStack is where the unstacked stuff was stashed tb.tag = uDes.tag; // cannot use sSrc.iStack since Src was moved } tb.tag = sDes.iStack; bool bAny = cSC.Suitable.Disassemble.MoveCollapsible(ref sSrc, ref tb); if (!bAny) { return(false); } if (uDes == null) { return(true); } tb.tag = uDes.tag; bAny = cSC.Suitable.Disassemble.MoveCollapsible(ref uDes, ref tb); return(bAny); } } return(false); }
// dont call this unless it was sorted by rank // this does not handle card subsets that are in the same column public bool JoinAnyLikeSuits(ref board tb) { if (cSC.bTrigger) { Console.WriteLine(MethodBase.GetCurrentMethod().Name); } series sDes, sSrc; int PossibleCostReduction; int RankWanted, LowestRank, RankWantedLoc; PsuedoMoveList.Clear(); //foreach (series s1 in tb.SortedSEQ) for (int i = 0; i < tb.SortedSEQ.Count - 1; i++) { sDes = tb.SortedSEQ[i]; // biggest is first in sorted order of ranks PossibleCostReduction = sDes.bRankable ? 1 : 0; //foreach (series s2 in tb.SortedSEQ) for (int j = i + 1; j < tb.SortedSEQ.Count; j++) { sSrc = tb.SortedSEQ[j]; if (sSrc.sSuit != sDes.sSuit) { continue; // in event more then one suit is in the sorted list } PossibleCostReduction += sSrc.bRankable ? 1 : 0; // the 1 below represents possibly a single available placeholder if (sDes.nEmptiesToUnstack + sSrc.nEmptiesToUnstack > (tb.NumEmptyColumns + 1 + PossibleCostReduction)) { return(false); } if (sDes.iStack == sSrc.iStack) { continue; } // make s1 (bottom) the destination and s2 (top) the source (ranks must be different) if (sDes.topCard.rank == sSrc.topCard.rank) { continue; // nothing to join } // 9..6 could join to 6..3 by moveing only the 5..3 if it exists RankWanted = sDes.bottomCard.rank - 1; // find a card in source to be mvoed that is this rank LowestRank = sSrc.bottomCard.rank; if (!(RankWanted > LowestRank && sSrc.topCard.rank >= RankWanted)) { continue; } // figure out where that card is in the source to be moved RankWantedLoc = sSrc.top + (1 + sSrc.topCard.rank - sDes.bottomCard.rank); card cSrc = tb.ThisColumn[sSrc.iStack].Cards[RankWantedLoc]; Debug.Assert(RankWanted == cSrc.rank); sSrc.size -= (1 + sSrc.topCard.rank - sDes.bottomCard.rank); sSrc.topCard = cSrc; sSrc.top = cSrc.iCard; if (sSrc.nEmptiesToUnstack == 0 && sDes.nEmptiesToUnstack == 0) { tb.moveto(cSrc.iStack, cSrc.iCard, sSrc.bottomCard.iStack); return(true); } pseudoCard pCard = new pseudoCard(sDes.topCard.ID, sSrc.bottomCard.ID, true); PsuedoMoveList.Insert(0, pCard); if (sSrc.nEmptiesToUnstack > 0) { if (!UnstackBelow(ref sSrc)) { return(false); } } if (sDes.nEmptiesToUnstack > 0) { if (!UnstackBelow(ref sDes)) { return(false); } } return(JoinPsudos()); } } return(false); }
public bool ShrinkThisBoardSeries(int nToUse) { int tbsNum = cSC.ThisBoardSeries.Count; board tb; int nEmpties = 0; int i, j, n = GetBestScores(nToUse, ref nEmpties); if (n == 0) { return(false); } cSC.NextBoardSeries.Clear(); if (nEmpties < 3 || true) // jys !!!! { for (i = 0; i < n; i++) { tb = cSC.ThisBoardSeries[cSC.BestScoreIndex[i]]; //int beforeJSS = tb.score; //cSC.JoinSuited.JoinAllSuitedWhenRankable(ref tb); //cSC.BestScore = tb.score; //Debug.Assert(beforeJSS <= tb.score); cSC.NextBoardSeries.Add(tb); if ((GlobalClass.TraceBits & 1) > 0) { tb.ShowBoard(); } } } else { // get the one(s) with the fewest moves when the boards are about the same j = 0; // count "n" may be different tb = cSC.ThisBoardSeries[cSC.BestScoreIndex[0]]; cSC.NextBoardSeries.Add(tb); j++; for (i = 1; i < n; i++) { board nb = cSC.ThisBoardSeries[cSC.BestScoreIndex[i]]; if (tb.Comparable(ref nb) && nb.MyMoves.TheseMoves.Count < tb.MyMoves.TheseMoves.Count) { cSC.NextBoardSeries.RemoveAt(cSC.NextBoardSeries.Count - 1); cSC.NextBoardSeries.Add(nb); tb = nb; } else { cSC.NextBoardSeries.Add(nb); j++; tb = nb; } } n = j; } if ((GlobalClass.TraceBits & 2) > 0) { Console.WriteLine("++++++++Shrank from " + tbsNum + " to " + n + " and here is the best one..."); DumpSorted(1); // very little difference between any, no need to show "n" cSC.stlookup.ShowBufferStats(); } cSC.ThisBoardSeries.Clear(); cSC.CountLimit = 0; cSC.PrevSeed.CopySeeds(ref cSC.ThisSeed); cSC.ThisSeed.Clear(); for (i = 0; i < n; i++) { tb = cSC.NextBoardSeries[i]; tb.MyMoves.AddShrinkCode(ref cSC, n); tb.from = tb.ID; tb.ID = cSC.ThisBoardSeries.Count; cSC.ThisSeed.Add(ref tb); cSC.ThisBoardSeries.Add(tb); Debug.Assert(tb.ID == (cSC.ThisBoardSeries.Count - 1)); //if (i == 0) //{ // cBestScore cBS = new cBestScore(0, tb.score, tb.NumEmptyColumns, tb.NumCompletedSuits); // cSC.SortedScores.Add(cBS); //} } cSC.NextBoardSeries.Clear(); cSC.BestScore = cSC.ThisBoardSeries[0].score; cSC.stlookup.ShrinkPerformed(); return(true); }
public void Add(ref board tb) { Seeds.Add(tb.UniqueID); SeedIndex.Add(tb.ID); }
public void ReCreateBinFile(ref board tb, ref cSpinControl cSC, string strPrefix) { long nLen1, nLen = 1048576; int i, j, n; int DealID = cSC.LocalDealCounter; // this is the deals that are done to the "working deal" which is the board deal counter. string strFullpathname = ""; if (strPrefix == "") { strFullpathname = GlobalClass.strSpiderOutputBinary; } else { strFullpathname = GlobalClass.strSpiderDir + strPrefix + ".SpiderSolitaireSave-ms"; } //FileStream inStream = File.OpenRead(strFullpathname + ".hdr"); //BinaryReader br = new BinaryReader(inStream); //nLen = inStream.Length; //Debug.Assert(nLen == 0x2028); if (File.Exists(strFullpathname)) { Debug.Assert(false); } FileStream outStream = File.Create(strFullpathname); BinaryWriter bw = new BinaryWriter(outStream); // get the hdr byte[] outbuf = new byte[256000]; for (j = 0; j < 0x2028; j++) { outbuf[j] = cSC.Hdr[j]; } nLen = cSC.PngArray.Length; // get the png file #if SAVE_PNG inStream = File.OpenRead(strFullpathname + ".png"); nLen = inStream.Length; br = new BinaryReader(inStream); br.Read(outbuf, 0x2028, (int)nLen); nLen1 = nLen + 0x2028; #endif nLen1 = 0x2028; for (i = 0; i < nLen; i++) { outbuf[nLen1] = cSC.PngArray[i]; nLen1++; } MakeXmlFile(strFullpathname, ref tb, ref cSC); n = sbXML.Length; string sbTemp = sbXML.ToString(); j = (int)nLen1; // convert n into bytes and append ff fe so one could get "c6 18 01 00 ff fe" byte[] b6 = new byte[8]; GetUnk6(ref b6, 6 + n * 2); // added 2 to fix problem and added another 2 for two more nulls but 0xa is missing for (i = 0; i < 6; i++) { outbuf[j] = b6[i]; j++; } for (i = 0; i < n; i++) { outbuf[j] = (byte)sbTemp[i]; j++; outbuf[j] = 0; j++; } outbuf[j] = 0; j++; outbuf[j] = 0x0a; j++; bw.Write(outbuf, 0, j + 2); bw.Close(); }
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); }
public static GlobalClass.StrategyType UseThisManyBoards(ref cSpinControl cSC, ref int NumToUse) { int i, n = cSC.ThisBoardSeries.Count; int iBiggest = 0; int[] tsbEmptyDistribution = new int[11] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; int[] sedEmptyDistribution = new int[11] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; Debug.Assert(cSC.ThisBoardSeries.Count > 0); Debug.Assert(cSC.ThisSeed.SeedIndex.Count > 0); foreach (board tb in cSC.ThisBoardSeries) { tsbEmptyDistribution[tb.Empties.Count]++; } for (i = 0; i < cSC.ThisSeed.SeedIndex.Count; i++) { board tb = cSC.ThisBoardSeries[cSC.ThisSeed.SeedIndex[i]]; sedEmptyDistribution[tb.Empties.Count]++; } for (i = 10; i >= 1; i--) { if (sedEmptyDistribution[i] > 0) { iBiggest = i; break; } } if (iBiggest == 0) { NumToUse = GlobalClass.MAX_FILTERED_BOARDS; // if no empty columns run thru all boards return(GlobalClass.StrategyType.CONTINUE_SPINNING); } if (iBiggest <= 3) { NumToUse = GlobalClass.MIN_FILTERED_BOARDS; return(GlobalClass.StrategyType.CONTINUE_SPINNING); } if (iBiggest > 3 && cSC.ThisBoardSeries[0].bIsCompletable) { NumToUse = 0; return(GlobalClass.StrategyType.REDUCE_SUITS); // stop the spinning - switch to end game } // UNTIL I FIX JOINSUITS //if (iBiggest == 3) //{ // NumToUse = 10; // return GlobalClass.StrategyType.SPIN_JOINSUITS; //} //if (iBiggest == 2) //{ // NumToUse = GlobalClass.MIN_FILTERED_BOARDS; // return GlobalClass.StrategyType.RUN_JOINSUITS_INPLACE; //} //foreach (board tb in cSC.ThisBoardSeries) //{ // if (tb.NumEmptyColumns == 2) // Console.WriteLine(tb.ID + " " + tb.score + " "); //} NumToUse = GlobalClass.MIN_FILTERED_BOARDS; return(GlobalClass.StrategyType.CONTINUE_SPINNING); }
static void Main(string[] args) { bool bIsThere = false; string stExt = ".SpiderSolitaireSave-ms"; string stTemp, strSpiderBin0; string PathToDirectory; string stSrc = "", stDef = "Spider Solitaire.SpiderSolitaireSave-ms"; cSpinControl cSC; board InitialBoard; stTemp = System.Reflection.Assembly.GetEntryAssembly().Location; // path to executable if (args.Count() > 0) { stSrc = "\\" + args[0]; } else //stSrc = "\\" + stDef; - not searching for save file anymore { GiveHelp(); Environment.Exit(0); } strSpiderBin0 = System.IO.Path.GetDirectoryName(stTemp) + stSrc; bIsThere = File.Exists(strSpiderBin0); if (bIsThere) { PathToDirectory = Path.GetDirectoryName(strSpiderBin0) + "\\"; GlobalClass.strSpiderBin = strSpiderBin0; GlobalClass.strSpiderDir = PathToDirectory; GlobalClass.strSpiderName = PathToDirectory + Path.GetFileNameWithoutExtension(strSpiderBin0); GlobalClass.strSpiderExt = Path.GetExtension(strSpiderBin0); cSC = new cSpinControl(); // this created the default xml "filename" InitialBoard = new board(); cSC.Deck = new cBuildDeck(strSpiderBin0, XMLtoRead, ref cSC); if (args.Count() < 2) // just want to look at the xml { cSC.Deck.GetBoardFromSpiderSave(ref InitialBoard); } else { string stDes = stDef; if (args.Count() == 3) { stDes = args[2]; } if (!stDes.Contains(stExt)) { stDes += stExt; } if (args[0] == stDes) { Console.WriteLine("cannot have same output file name as the input saved game\n"); Environment.Exit(0); } stTemp = PathToDirectory + Path.GetFileNameWithoutExtension(args[1]); if (GlobalClass.strSpiderName == stTemp) { Console.WriteLine("should not have same input saved game name as the input xml filename\n"); Console.WriteLine("or input xml file will be over written as that filename used for temp storage\n"); Environment.Exit(0); } GlobalClass.strSpiderOutputBinary = cSC.BIN_Diag_filename = PathToDirectory + "\\" + stDes; cSC.Deck.GetBoardFromSpiderSave(ref InitialBoard); // read in the saved game and also create the matching xml cSC.XML_Diag_filename = PathToDirectory + args[1]; cSC.Deck.WriteBoardMergingXML(); } } }
public bool TrySpinOneCard(ref board tb, int SrcCol, int SrcCard, int DesCol, int DesCard) { if (cSC.bTrigger) { Console.WriteLine(MethodBase.GetCurrentMethod().Name); } board nb = null; int[] des = new int[112]; Int64 ChkWord = 0; int WouldGoHere = cSC.ThisBoardSeries.Count; bool bInsertFailed = false, bResult = false; #if AINT int[] des1 = new int[112]; Int64 ChkWord1 = 0, ChkWord2 = 0; int desptr1; bool bVerify = true; #endif int desptr = tb.FormDupList(SrcCol, SrcCard, DesCol, DesCard, ref des, ref ChkWord); // check for a duplicate move before creating a new board // note that the number of actual moves is 1 less since we have not yet moved anything if (cSC.stlookup.bIsNewBoard(ChkWord, desptr, ref des, tb.MyMoves.TheseMoves.Count + 1, ref WouldGoHere, ref bInsertFailed)) { if (bInsertFailed) { cSC.bSignalSpinDone = true; cSC.bOutOfSpaceInSTLOOKUP = true; return(false); } if (WouldGoHere != cSC.ThisBoardSeries.Count) { // this indicates the lookup program found an identical board that had more moves // replace that board with the moves from this one. //ThisBoardSeries[WouldGoHere].DoNotUse = true; cSC.ThisBoardSeries.RemoveAt(WouldGoHere); nb = new board(ref tb); bResult = SpinOneCard(ref nb, SrcCol, SrcCard, DesCol, DesCard); cSC.ThisBoardSeries.Insert(WouldGoHere, nb); cSC.ThisBoardSeries.RemoveAt(cSC.ThisBoardSeries.Count - 1); return(bResult); } // either it was not found or it was found but we cannot update the queue // because the pointer WouldGoHere is invalid (board was shrunk) nb = new board(ref tb); bResult = SpinOneCard(ref nb, SrcCol, SrcCard, DesCol, DesCard); #if AINT //bVerify = tbsCompare1(0, 12); //tbsDump(WouldGoHere, desptr, ref des); //if ((WouldGoHere == 12 && RunCounter == 2) || WouldGoHere == 0) //{ // tbsDump(WouldGoHere, desptr, ref des); //} //if (WouldGoHere == 13 || WouldGoHere == 102) //{ // tbsDump(WouldGoHere, desptr, ref des); // desptr = tb.FormDupList(SrcCol, SrcCard, DesCol, DesCard, ref des, ref ChkWord2); // desptr1 = nb.FormVerify(ref des1, ref ChkWord1); // Console.WriteLine("WGH: " + WouldGoHere + " " + ChkWord.ToString("x16") + " " + ChkWord1.ToString("x16") + " " + ChkWord2.ToString("x16")); //} if ((iTrace & 0x10) > 0) { ChkWord1 = 0; //desptr = tb.FormDupList(SrcCol, SrcCard, DesCol, DesCard, ref des, ref ChkWord); desptr1 = nb.FormVerify(ref des1, ref ChkWord1); bVerify = (desptr == desptr1); bVerify |= (ChkWord == ChkWord1); for (int ii = 0; ii < desptr; ii++) { bVerify |= (des[ii] == des1[ii]); } Debug.Assert(bVerify); } #endif return(bResult); } else { cSC.NumberDuplicates++; } return(true); }
/* * THIS DOES NOT WORK EXCEPT FOR VERY SIMPLE SEQ SERIES JYS !!!! need UnStack and to use patterns * This joins one SEQ series under another so as to concatanate the two series * */ /* * this just exposes the top card and check to see if it can be recovered * jys this needs to be able to expose all cards that are exposable * (8s,6h,7D) expose to 8S,7D,6H * * right now, the series underneath must be SEQ, use the SOS one for that, but it does not use placeholders * * */ public int ExposeOneTop(ref board tb) { int e, n; int LocAbove; // location of card just above the top card card CardAbove; int Any = 0; int OriginalSource; foreach (card cT in tb.TopMost) { LocAbove = cT.iCard - 1; if (LocAbove <= 0) { continue; // nothing to expose } CardAbove = tb.ThisColumn[cT.iStack].Cards[LocAbove]; if (CardAbove.bFaceUp) { continue; // already exposed } // we want only unexposed cards and the series underneath must be SEQ // we can expose this card by moving the one below it (our card cT) if (CardAbove.rank - 1 != cT.rank) { continue; // nope, wrong rank, we want to move it back } n = tb.ThisColumn[cT.iStack].Cards.Count - cT.iCard; // number of cards to move // the below does no error checking nor any statistics computation if (tb.NumEmptyColumns > 0) { e = tb.Empties[0]; OriginalSource = cT.iStack; tb.PerformMove(cT.iStack, cT.iCard, e, n); tb.PerformMove(e, 0, OriginalSource, n); Any++; } else { // we will have to find a card that can hold it temporarily foreach (card bC in tb.BottomMost) { if (bC.iStack == cT.iStack) { continue; } if (bC.rank - 1 == cT.rank) { OriginalSource = cT.iStack; n = tb.ThisColumn[cT.iStack].Cards.Count - cT.iCard; tb.PerformMove(cT.iStack, cT.iCard, bC.iStack, n); tb.PerformMove(bC.iStack, bC.iCard + 1, OriginalSource, n); Any++; } } } if (Any > 0) { tb.ThisColumn[cT.iStack].CalculateColumnValue(cT.iStack, tb.NumEmptyColumns, tb.BoardState()); } } if (Any > 0) { tb.ReScoreBoard(); // alternately CalcBoardScore and then GetSortedTops return(ExposeOneTop(ref tb)); } return(Any); }
public bool JoinSuitedJoinables(ref board tb) { return(false); }
private int UnstackOneSeries(ref board tb) { int Any = 0; cUnstackOrder[] cUO; column cCol; card CardExposed; PlaceHolder.Clear(); cUO = new cUnstackOrder[tb.NumFacedownColumns()]; int i = 0; tb.CopyWorkingCards(ref xBottomMost, GlobalClass.WorkingType.tBottomMost); tb.CopyWorkingInts(ref xEmpties, GlobalClass.WorkingType.tEmpties); tb.BuildPlaceholders(ref PlaceHolder); // get best unstack order in case we cannot unstack all of them i = 0; foreach (int e in tb.NonEmpties) { cCol = tb.ThisColumn[e]; if (cCol.top == 0) { continue; } int nSEQ = cCol.ThisSeries.Count; int nSOS = cCol.ThisSOS.Count; cUO[i++] = new cUnstackOrder(e, nSEQ); } Array.Sort(cUO, delegate(cUnstackOrder c1, cUnstackOrder c2) { return(c1.SizeSeries.CompareTo(c2.SizeSeries)); }); foreach (cUnstackOrder uo in cUO) { cCol = tb.ThisColumn[uo.e]; for (i = uo.SizeSeries - 1; i >= 0; i--) { series s = cCol.ThisSeries[i]; int iStack = utils.GetBestMove(s.topCard, ref tb, ref PlaceHolder); if (iStack < 0) { if (xEmpties.Count == 0) { return(Any); } iStack = xEmpties[0]; xEmpties.RemoveAt(0); } CardExposed = tb.PerformMove(s.iStack, s.top, iStack, s.size); RecoverPlaceholder(ref tb, ref CardExposed); Any++; } if (Any > 0) { return(Any); } } return(Any); }
public int SOSExposeTop(ref board tb) { bool bAnySameSuit = false; List <series> TopSeries = new List <series>(); List <cPossibleMoves> ActualMoves = new List <cPossibleMoves>(); NewBoards.Clear(); TryUnstackAll(ref tb); tb.CopyWorkingCards(ref xBottomMost, GlobalClass.WorkingType.tBottomMost); foreach (column cCol in tb.ThisColumn) { if (cCol.iStack > 9) { break; } if (cCol.ThisSOS.Count == 1) { TopSeries.Add(cCol.ThisSOS[0]); } } foreach (card bm in xBottomMost) { foreach (series s in TopSeries) { card tm = s.topCard; if ((tm.rank + 1) == bm.rank) { card bbm = bm; cPossibleMoves cpm = new cPossibleMoves(ref tm, ref bbm); ActualMoves.Add(cpm); } } } foreach (cPossibleMoves cpm in ActualMoves) { if (cpm.bSameSuit) { bAnySameSuit = true; break; } } foreach (cPossibleMoves cpm in ActualMoves) { column cCol; card cCrd; board nb; series SOS; bool bCan; List <series> ListSEQ; List <int> yEmpties = new List <int>(); List <card> yBottomMost = new List <card>(); if (bAnySameSuit && !cpm.bSameSuit) { continue; } nb = new board(ref tb); nb.AssignCompletedID(GlobalClass.TypeCompletedBy.ID_SOSET); CardsToMove.Clear(); cCol = nb.ThisColumn[cpm.From.iStack]; SOS = cCol.ThisSOS[0]; ListSEQ = cCol.ThisSeries; // the top cards in the SEQ are the ones to move in the SOS for (int i = 0; i < SOS.NumSubSeries; i++) { cCrd = ListSEQ[i].topCard; CardsToMove.Add(cCrd); } nb.tag = cpm.To.iStack; nb.CopyWorkingInts(ref yEmpties, GlobalClass.WorkingType.tEmpties); nb.CopyWorkingCards(ref yBottomMost, GlobalClass.WorkingType.tBottomMost); bCan = DisAssemble.bCanDisassembleSOS(SOS.NumSubSeries, ref nb, ref yEmpties, ref yBottomMost, ref CardsToMove); if (bCan) { NewBoards.Add(nb); nb.AssignCompletedID(); } } return(NewBoards.Count); }
public bool ReduceSuits(ref board oldtb) { bool bSuccess = true; card cNext = null; card ExposedCard = null; int e, CardID, LastID; card CardExposed; board tb = new board(ref oldtb); tb.AssignCompletedID(GlobalClass.TypeCompletedBy.ID_RSI); OnCounter++; InitializeReduction(ref tb, ref cNext); Debug.Assert(cNext.rank == 13); GetPlaceholders(ref tb, cNext.iStack); if (bStackablesAbove(ref tb, ref cNext)) { bSuccess = UnstackSeriesBelow(ref tb, ref cNext); if (bSuccess) { e = tb.Empties[0]; tb.Empties.RemoveAt(0); CardExposed = tb.moveto(cNext.iStack, cNext.iCard, e); // have to move the king RecoverPlaceholder(ref tb, ref CardExposed); tb.tag = e; InitializeReduction(ref tb, ref cNext); } else { tb.AssignCompletedID(); return(false); // jys !!! may want to try a second or lower ranked card } } else { tb.tag = cNext.iStack; GetPlaceholders(ref tb, tb.tag); } // unstack below the last card (cNext) and the next card while (bSuccess) { bSuccess = UnstackSeriesBelow(ref tb, ref cNext); if (bSuccess) { if (StackableIDs.Count > 0) { CardID = StackableIDs[0]; // next card to gather in StackableIDs.RemoveAt(0); LastID = cNext.ID; cNext = utils.FindCardFromID(ref tb, CardID); bSuccess = UnstackSeriesBelow(ref tb, ref cNext); if (bSuccess) { ExposedCard = tb.moveto(cNext.iStack, cNext.iCard, tb.tag); RecoverPlaceholder(ref tb, ref ExposedCard); } else { tb.AssignCompletedID(); return(false); } } else { tb.ReScoreBoard(); cSC.Suitable.PerformSuitabilityScreening(ref tb); if (tb.bIsCompletable) { cSC.NextBoardSeries.Add(tb); } else { cSC.ThisBoardSeries.Add(tb); } tb.AssignCompletedID(); return(true); } } else { tb.AssignCompletedID(); return(false); } } tb.AssignCompletedID(); return(false); }
public void AddNewBoard(ref board ThisBoard) { ThisBoard.ReScoreBoard(); ThisBoard.ID = cSC.ThisBoardSeries.Count; cSC.ThisBoardSeries.Add(ThisBoard); }
// 20nov2012 need to prevent too many boards from being created // problem arises when there are more then 1 empty column // Do not return more than NumWanted boards total // spread those number across the number of empty columns using decimation // by multipling by NumEmptys and then using only every 1 out of NumEmptys public int DealToBoard(ref board tb, DateTime TimeOfLastDeal, int NumBoardsTotal) { int i, n, NumEmpties, NonEmpties, nbPtr = NewBoards.Count; bool bMore = true; int lBest = tb.score; int NumWantedMax = 32; int NumWantedMin = 16; int NumWanted = tb.NumEmptyColumns * NumWantedMax * NumBoardsTotal; if (NumWanted < NumWantedMin) { NumWanted = NumWantedMin; } int NumGenerated = 0; int DecimationCnt = tb.NumEmptyColumns * NumBoardsTotal; int[] NumDealtTo; if (DecimationCnt == 0) { DecimationCnt = 1; } tb.bWasDealtTo = false; if (OutOfCardsOrDone(ref tb)) { return(0); } StartOfDealPtr = nbPtr; tb.CopyWorkingInts(ref OEmpties, GlobalClass.WorkingType.tEmpties); tb.score = lBest; NumGenerated += AddBoard(ref tb, TimeOfLastDeal); bMore = (NumGenerated < NumWanted); // we reduced this board to a series that have 1 column less (if it has an empty column) while (bMore) { while (nbPtr < NewBoards.Count) { if (!NewBoards[nbPtr].bWasDealtTo) { board nb = NewBoards[nbPtr]; nb.score = lBest; NumGenerated += AddBoard(ref nb, TimeOfLastDeal); } nbPtr++; if (NumGenerated >= NumWanted) { bMore = false; break; } } bMore = false; //NonEmpties = 0; //for (i = StartOfDealPtr; i < NewBoards.Count; i++) //{ // if (NewBoards[i].NumEmptyColumns == 0) // { // NonEmpties++; // } //} //bMore = bMore && (NonEmpties < NumWanted); //nbPtr = StartOfDealPtr; } NumDealtTo = new int[NumGenerated]; n = 0; for (i = StartOfDealPtr; i < NewBoards.Count; i++) { if (NewBoards[i].bWasDealtTo) { NumDealtTo[n] = i; NewBoards[i].bWasDealtTo = false; n++; } } for (i = 0; i < n; i += DecimationCnt) { NewBoards[NumDealtTo[i]].bWasDealtTo = true; NumCreated++; } //for(i=StartOfDealPtr;i<NewBoards.Count;i++) //{ // board nb = NewBoards[i]; // if (nb.NumEmptyColumns == 0) // { // //nb.dead = true; // finished with this one also // // deal does not add a board so it needs to be marked dead ...but... // // the check for empty columns is the same as check for dead // NumCreated++; // //GetBetterMoves(ref nb); // // 11nov2012 somehow we are dealing a 2nd time so dont deal to a dead board // if(!nb.bWasDealtTo) // { // Debug.Assert(false); // dead is not used anymore ??? // nb.deal(lBest, TimeOfLastDeal); // nb.bWasDealtTo = true; // } // } //} //Console.WriteLine("NW:" + NumWanted + " DC:" + DecimationCnt + " NC:" + NumCreated + " NG:" + NumGenerated + " ====\n"); return(NumCreated); }
// exchange cards that are under the wrong suit public bool CombineLikeSuits(ref board tb) { column cCol = null; int n = 0; bool ChangedAnyBoards = false; int OriginalSrcStack = 0; card bm, Src = null, Des = null; bool bFound = false, bAny = false; List <card> LastSEQ = new List <card>(); // this holds the top card of the last SEQ series card BelowBM, cAbove; // Below Bm rank + 1 must equal to cAbove rank to swap (unless one card is top) tb.AssignCompletedID(GlobalClass.TypeCompletedBy.ID_COMBN); do { bFound = false; LastSEQ.Clear(); bAny = FreeSuitedSuits(ref tb, ref LastSEQ); if (tb.NumEmptyColumns == 0) { return(bAny); } //tb.ExplainBoard("before"); // locate the bottom card of the upper series, if any foreach (int e in tb.NonEmpties) { cCol = tb.ThisColumn[e]; n = cCol.ThisSeries.Count; if (n < 2) { continue; } bm = cCol.ThisSeries[n - 2].bottomCard; foreach (card tm in LastSEQ) { if (tm.iStack == bm.iStack) { continue; } if ((bm.rank - 1) == tm.rank && bm.suit == tm.suit) { OriginalSrcStack = tm.iStack; int iCardAbove = tm.iCard - 1; // this card must either be null (top of column) // or it must be 1 greater in rank if (iCardAbove > -1) // there is at least one card above us. It can be facedown too { cAbove = tb.ThisColumn[tm.iStack].Cards[iCardAbove]; if (cAbove.rank != (tm.rank + 1)) { continue; } BelowBM = cCol.Cards[bm.iCard + 1]; if (BelowBM.rank != (cAbove.rank - 1)) { continue; } } bFound = true; Src = tm; Des = bm; break; } } if (bFound == true) { break; } } if (bFound) { card MustMove = cCol.ThisSeries[n - 1].topCard; int nDest = GetBestMove(Src, ref tb); if (nDest < 0) { nDest = tb.Empties[0]; } tb.moveto(MustMove.iStack, MustMove.iCard, nDest); tb.moveto(Src.iStack, Src.iCard, Des.iStack); // do not bother moving from one top to another top when doing a swap if (!(tb.ThisColumn[nDest].Cards.Count == 1 && tb.ThisColumn[OriginalSrcStack].Cards.Count == 0)) { tb.moveto(nDest, MustMove.iCard, OriginalSrcStack); } tb.ReScoreBoard(); if (tb.NotifySuitJustCompleted) { tb.ExplainNoRescoreBoard("Combine Like Suits succeeded"); tb.NotifySuitJustCompleted = false; } ChangedAnyBoards = true; } } while (bFound == true); tb.AssignCompletedID(); //tb.ExplainBoard("after2"); return(ChangedAnyBoards); }
public bool PerformSuitabiltyStudy(ref board tb, int isuit) { column tCol; card tCrd; List <int> DupList = new List <int>(); int cRankBits = ALL_AVAILABLE; int i, j, k, rBit; int DealCnt = 0; tb.BuildingThisSuit = 0; if (!tb.SuitStatus[isuit].bSuitsCompletable) { // calculate all missing ranks, keep a copy (dMissing) for (j = 1; j < 14; j++) { rBit = 1 << j; if ((rBit & tb.SuitStatus[isuit].SuitedRankBits) == 0) { eMissingRanks.Add(j); dMissingRanks.Add(j); } } // see if we can expose some cards so as to reduce the number of required (eMissing) for (i = 0; i < 10; i++) { tCol = tb.ThisColumn[i]; if (tCol.Cards.Count < 2) { continue; // there are no cards to expose } for (j = tCol.top - 1; j >= 0; j--) { tCrd = tCol.Cards[j]; if (isuit != tCrd.suit) { continue; } if (DupList.Contains(tCrd.rank)) // must have put it in earlier { for (k = j + 1; k < tCol.Cards.Count; k++) { if (tCol.Cards[k].rank == 13) { continue; } } int nUncover = tCol.NumUnstacksReq(tCrd); foreach (cExposeStack cES in ExposesRequired) { if (cES.Rank != tCrd.rank) { continue; } if (cES.NumToRemove > nUncover) { cES.NumToRemove = nUncover; cES.Stack = i; } } } if (eMissingRanks.Contains(tCrd.rank)) { eMissingRanks.Remove(tCrd.rank); DupList.Add(tCrd.rank); // if a king is below this face down card then assume it cannot be exposed for (k = j + 1; k < tCol.Cards.Count; k++) { if (tCol.Cards[k].rank == 13) { continue; } } cExposeStack ces = new cExposeStack(i, tCol.NumUnstacksReq(tCrd), tCrd.rank); ExposesRequired.Add(ces); } } } if (eMissingRanks.Count > 0) // seems cannot get a suit unless we deal { tCol = tb.ThisColumn[10]; // for each deal, go thru the available deck and see if we can form a complete suit // if a card from the deck duplicates one that is facedown then remove the facedown one // from the exposes required list for (i = 0; i < tCol.Cards.Count; i++) { tCrd = tCol.Cards[i]; if (0 == (i % 10)) { DealCnt++; if (eMissingRanks.Count > 0) { DealsRequired++; } if (eMissingRanks.Count > 0) { CardsReqAfterDeal.Add(eMissingRanks.Count); } } if (tCrd.suit != isuit) { continue; } if (eMissingRanks.Contains(tCrd.rank)) { eMissingRanks.Remove(tCrd.rank); // no need to expose any cards if they will be in the deal for (j = 0; j < ExposesRequired.Count; j++) { ces = ExposesRequired[j]; if (dMissingRanks.Contains(ces.Rank)) { //ExposesRequired.RemoveAt(j); ExposesRequired[j].AtDeal = DealCnt; } } } //if (eMissingRanks.Count == 0) break; } if (eMissingRanks.Count > 0) { CardsReqAfterDeal.Add(eMissingRanks.Count); } } } if (tb.SuitStatus[isuit].bSuitsCompletable) { NumberCompletable++; } return(tb.SuitStatus[isuit].bSuitsCompletable); }
public board(ref board nb) { int i, j; column cCol; init(); // jys !!! need to copy the suitability stuff NumCompletedSuits = nb.NumCompletedSuits; bitJustCompleted = nb.bitJustCompleted; // fixs problem with suits missing from deck? for (i = 0; i < nb.UnexposedTypes.Count; i++) { UnexposedTypes.Add(nb.UnexposedTypes[i]); } strSuitsRemoved = nb.strSuitsRemoved; DealString = nb.DealString; for (i = 0; i < 12; i++) //2018 should have copied the completed ones also { cCol = nb.ThisColumn[i]; for (j = 0; j < cCol.Cards.Count; j++) { card nc = new card(); nc.bFaceUp = cCol.Cards[j].bFaceUp; nc.ID = cCol.Cards[j].ID; ThisColumn[i].Cards.Add(nc); } } foreach (cSuitedStatus cSS in SuitStatus) { int ii = cSS.index; cSS.bSuitsCompletable = nb.SuitStatus[ii].bSuitsCompletable; cSS.bExposesRequired = nb.SuitStatus[ii].bExposesRequired; cSS.UnexposedRankBits = nb.SuitStatus[ii].UnexposedRankBits; cSS.SuitedRankBits = nb.SuitStatus[ii].SuitedRankBits; cSS.NumCompletedAndRemoved = nb.SuitStatus[ii].NumCompletedAndRemoved; } ExtraPoints = nb.ExtraPoints; bOnLastDeal = nb.bOnLastDeal; score = nb.score; dead = nb.dead; nchild = nb.nchild; from = nb.ID; NumEmptyColumns = nb.NumEmptyColumns; DealCounter = nb.DealCounter; bIsCompletable = nb.bIsCompletable; MyMoves.CopyMoves(ref nb.MyMoves); BuildingThisSuit = nb.BuildingThisSuit; for (i = 0; i < nb.SuitedSEQ.Count; i++) { SuitedSEQ.Add(nb.SuitedSEQ[i]); } TimeOfLastDeal = nb.TimeOfLastDeal; foreach (cSuitedStatus css in SuitStatus) { for (i = 0; i < nb.SuitStatus[css.index].BonusExposes.Count; i++) { css.BonusExposes.Add(nb.SuitStatus[css.index].BonusExposes[i]); } } ReScoreBoard(); }
public bool FormMovesFromRules(int fptr, ref board tb, ref List <int> Empties, ref List <card> CardsToMove) { int i, j, n; int r1, r2; int FromStack = 0, FromLoc = 0, ToStack = 0; string strOper1, strOper2; card TopCardToMove = CardsToMove[0]; int TopCardsDestination = tb.tag; int SrcColumn = TopCardToMove.iStack; string strSrc, strDes; List <cMoves> Moves = DisStrategy[fptr].Moves; n = Moves.Count; Debug.Assert(n % 2 == 0); // must be an even number tb.ClearStacks(); for (i = 0; i < n; i += 2) { strSrc = Moves[i].MoveID; r1 = GetOperands(strSrc, out strOper1); if (strOper1 == "SC") { FromStack = SrcColumn; FromLoc = CardsToMove.Last().iCard; CardsToMove.RemoveAt(CardsToMove.Count - 1); } else if (strOper1 == "E") { FromStack = Empties[r1]; FromLoc = tb.ThisColumn[FromStack].HoldMoves.Pop(); } else if (strOper1 == "C") { for (j = 0; j < WhereStored.Count; j++) { if (WhereStored[j].SeriesID == r1) { FromStack = WhereStored[j].StackNumber; FromLoc = tb.ThisColumn[FromStack].HoldMoves.Pop(); } } } else { Debug.Assert(false); return(false); } strDes = Moves[i + 1].MoveID; r2 = GetOperands(strDes, out strOper2); if (strOper2 == "DC") { ToStack = TopCardsDestination; } else if (strOper2 == "E") { ToStack = Empties[r2]; tb.ThisColumn[ToStack].HoldMoves.Push(tb.ThisColumn[ToStack].Cards.Count); } else if (strOper2 == "C") { for (j = 0; j < WhereStored.Count; j++) { if (WhereStored[j].SeriesID == r2) { ToStack = WhereStored[j].StackNumber; tb.ThisColumn[ToStack].HoldMoves.Push(tb.ThisColumn[ToStack].Cards.Count); } } } else { Debug.Assert(false); return(false); } tb.moveto(FromStack, FromLoc, ToStack); } return(true); }
// select only 1 card even if more than 1 in suit // if more then 1 in a suit then try both of those card // repeat until the entire suit has been spun from this column public bool SpinThisColumn(ref board tb, int iColumn) { if (cSC.bTrigger) { Console.WriteLine(MethodBase.GetCurrentMethod().Name); } int i, ThisSuit, ThisRank; series s = tb.ThisColumn[iColumn].ThisSeries.Last(); card CardAbove; column c = tb.ThisColumn[iColumn]; int n = c.Cards.Count; Debug.Assert(n > 0); n--; // point to bottom most card ThisSuit = c.Cards[n].suit; // this suit and this rank are being moved ThisRank = c.Cards[n].rank; while (n >= s.top) { if (ThisRank == 13) { if (tb.NumEmptyColumns == 0 || c.Cards[n].iCard == 0) { return(true); } // a king cannot be moved anywhere except an empty column // never move a king if it is already in an otherwise empty column // move it only if the card exposed can hold some other column CardAbove = tb.ThisColumn[iColumn].Cards[n - 1]; for (i = 0; i < 10; i++) { if (tb.ThisColumn[i].ThisSeries.Count == 1) // only 1 sequential series { s = tb.ThisColumn[i].ThisSeries[0]; if (s.topCard.rank == (CardAbove.rank - 1)) { //nb = new board(ref tb); if (!SpinTheseCards(ref tb, iColumn, n)) { return(false); } } } } } if (!SpinTheseCards(ref tb, iColumn, n)) { return(false); } n--; if (n < 0 || cSC.bSignalSpinDone) { break; } ThisRank++; // one above it must be 1 higher and same rank if (ThisSuit != c.Cards[n].suit || ThisRank != c.Cards[n].rank) { break; } } return(true); }