// 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); }
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); }