private void ClearAnyBlocking(ref board tb, ref series s) { card cAbove; card JustMoved = s.topCard; card BottomCard = s.bottomCard; column cCol = tb.ThisColumn[JustMoved.iStack]; // we moved from here so use iStack, not fStack int iAbove = JustMoved.iCard - 1; if (iAbove < 0) { xEmpties.Add(JustMoved.iStack); } if (!BottomCard.PartOfStackables) { PlaceHolders.Add(BottomCard); // this has the updated fStack } cAbove = cCol.Cards[iAbove]; if (cAbove.PartOfStackables) { return; } if (PartOfMovables.Contains(cAbove.ID)) { return; } PlaceHolders.Add(cAbove); }
// if the kings are in the same stack they will still be different SEQ and the lower king // will always have 1 better cost to unstack. If the size of K2 is the same (or greater than K1) // then K2 will be selected. If K1 is 1 or more greater in size then K2 must be discarded private series sGetKing(ref List <series> SortedSEQ, ref int cost) { series sKing = null; int rank = SortedSEQ[0].topCard.rank; Debug.Assert(rank == 13); bool bHaveTwoKings = (SortedSEQ[1].topCard.rank == 13); if (bHaveTwoKings) { int costK1 = SortedSEQ[0].nEmptiesToUnstack - SortedSEQ[0].size; int costK2 = SortedSEQ[1].nEmptiesToUnstack - SortedSEQ[1].size; if (costK2 <= costK1) { cost = SortedSEQ[1].nEmptiesToUnstack; sKing = SortedSEQ[1]; } else { cost = SortedSEQ[0].nEmptiesToUnstack; sKing = SortedSEQ[0]; } SortedSEQ.RemoveRange(0, 2); return(sKing); } sKing = SortedSEQ[0]; SortedSEQ.RemoveAt(0); return(sKing); }
private void GetRemainingSOS(int StartIndex, ref List <series> xThisSOS) { series ThisList; int PrevIndex = StartIndex; bool bStillDoingStackables; PrevIndex--; if (StartIndex == (Cards.Count)) { xThisSOS[xThisSOS.Count - 1].bottom = PrevIndex; xThisSOS[xThisSOS.Count - 1].bottomCard = Cards[PrevIndex]; return; } bStillDoingStackables = Cards[StartIndex].PartOfStackables; if ((Cards[StartIndex].rank + 1 == Cards[PrevIndex].rank) && (bStillDoingStackables == bDoingStackables)) { StartIndex++; GetRemainingSOS(StartIndex, ref xThisSOS); return; } else { bDoingStackables = bStillDoingStackables; xThisSOS[xThisSOS.Count - 1].bottomCard = Cards[PrevIndex]; xThisSOS[xThisSOS.Count - 1].bottom = PrevIndex; ThisList = new series(); ThisList.top = StartIndex; ThisList.topCard = Cards[StartIndex]; xThisSOS.Add(ThisList); StartIndex++; GetRemainingSOS(StartIndex, ref xThisSOS); } }
// find the sequence that contains the ExpectedRank. if more than one do the same analysis as the king private series sGetNext(ref board tb, ref List <series> SortedSEQ, int ExpectedRank, ref int cost) { series s1 = null, s2 = null; bool bFound1 = false, bFound2 = false; card c1 = null, c2 = null; column cCol; int cost1, cost2; foreach (series s in SortedSEQ) { if (s.topCard.rank >= ExpectedRank && ExpectedRank >= s.bottomCard.rank) { if (!bFound1) { s1 = s; bFound1 = true; cCol = tb.ThisColumn[s.iStack]; for (int i = s.top; i <= s.bottom; i++) { c1 = cCol.Cards[i]; if (c1.rank == ExpectedRank) { break; } } continue; } else { s2 = s; bFound2 = true; cCol = tb.ThisColumn[s.iStack]; for (int i = s.top; i <= s.bottom; i++) { c2 = cCol.Cards[i]; if (c2.rank == ExpectedRank) { break; } } break; } } } if (bFound1 && bFound2) { cost1 = s1.nEmptiesToUnstack - c1.next; cost2 = s2.nEmptiesToUnstack - c2.next; if (cost2 <= cost1) { s1 = s2; c1 = c2; } } cost = s1.nEmptiesToUnstack; s1.AssemblyLink = c1; return(s1); }
/* * This just moves the bottom most card to another stack that has the same suit. * The move is not made unless it can be reversed (if bReversible is set) */ public bool JoinSameSuits(ref board tb, bool bReversible) { int n = tb.BottomMost.Count; card tC, bC, aC; int i, j, k; int RankAbove; for (i = 0; i < n; i++) { bC = tb.BottomMost[i]; series s2 = tb.ThisColumn[bC.iStack].ThisSeries.Last(); for (j = 0; j < n; j++) { if (i == j) { continue; } tC = tb.TopMost[j]; if (tC.suit == bC.suit) { // we have a candidate to join srcCol = tb.ThisColumn[tC.iStack]; series s = srcCol.ThisSeries.Last(); // s is the series that might be moved under the bottom card if (s.topCard.rank >= (bC.rank - 1) && s.bottomCard.rank < bC.rank && s2.topCard.rank > s.topCard.rank) // size of destination must be //s2.size > s.size) { // we can move all or part of that series under that bottom card for (k = 0; k < s.size; k++) { aC = srcCol.Cards[k + tC.iCard]; if (aC.rank + 1 == bC.rank) { if (aC.iCard > 0) { // is not at top of stack // if Reversibility is required, then do not make the move // unless the the rank above allows reversing the move RankAbove = srcCol.Cards[aC.iCard - 1].rank; if ((RankAbove - 1) != aC.rank && bReversible) { return(false); } } tb.moveto(tC.iStack, aC.iCard, bC.iStack); return(true); } } } } } } return(false); }
//PsudoMoveList must have moves inserted in the "front" to keep the move order correct // board tag contains destination of series to be moved to public bool MoveCollapsible(ref series sCollapse, ref board tb) { List <card> BackupOfCardsToMove = new List <card>(); if (cSC.bTrigger) { Console.WriteLine(MethodBase.GetCurrentMethod().Name); } column cCol = tb.ThisColumn[sCollapse.iStack]; int n = sCollapse.pattern.Length; if (n > 7) { return(false); } tb.CopyWorkingInts(ref xEmpties, GlobalClass.WorkingType.tEmpties); if (tb.tag < 0) { tb.tag = xEmpties[0]; xEmpties.RemoveAt(0); } CollapsibleSEQCardsToMove.Clear(); series s = sCollapse; for (int i = 0; i < sCollapse.pattern.Length; i++) { string a = sCollapse.pattern.Substring(i, 1); CollapsibleSEQCardsToMove.Add(s.topCard); BackupOfCardsToMove.Add(s.topCard); s = s.NextSeries; } for (int i = DisStrategy.Count - 1; i >= 0; i--) { // going backwards we see the max empty columns before the ones requiring help if (DisStrategy[i].NumSeqSeries == n) { if (xEmpties.Count >= DisStrategy[i].nEmptyColumns) { if (DisStrategy[i].Ranks.Count > 0) { continue; // must use empty stack for now JYS !!! } // if a placeholder was available, it would have been assigned to tab.tag // since all series are rankable, they can all go under the top card // JYS !!! we could possibly have looked for another placeholder or two to make // complicated moves bool bAny = FormCollapsibleMoves(i, ref tb); return(bAny); } } } return(false); }
private bool MoveSeriesBelow(ref board tb, ref series sKeep) { series sCollapse = sKeep.NextSeries; tb.tag = utils.GetBestMove(sCollapse.topCard, ref tb, ref PlaceHolder); // note that tag could be negative: need to get an empty column bool bAny = cSC.Suitable.Disassemble.MoveCollapsible(ref sCollapse, ref tb); return(bAny); }
private void AddTopRanks(int sStart, ref List <cRankIndex> Ranks) { //int n = ThisSeries.Count; //for (int i = sStart; i < n; i++) { series s = ThisSeries[sStart]; cRankIndex cri = new cRankIndex(s.topCard.rank, sStart); Ranks.Add(cri); } Ranks.Sort(delegate(cRankIndex r1, cRankIndex r2) { return(r2.rank.CompareTo(r1.rank)); }); }
public static int CalcSOSSeriesValue(series s) { int v, n = s.bottom - s.top; s.sSuit = -1; v = 1; if (n > 0) { v += n; } s.nValue = (v); return(v); }
// this just checks empty columns for space right now // and only looks at SEQ public int ExposeTop(ref board tb) { int i, j, n, nT, nE; int sCost; // cost of all the series that need to be unstacked to expose the facedown card // is the sum of all the SEQ costs plus 1 int tlCount = 0; column cCol; series sCollapse = new series(); // out of sequence series we want to collapse to a series of series for (i = 0; i < 10; i++) { nE = tb.NumEmptyColumns; cCol = tb.ThisColumn[i]; n = cCol.Cards.Count; if (n < 2 || cCol.top == 0) { continue; } sCost = 1; for (j = 0; j < cCol.ThisSeries.Count; j++) { sCost += cCol.ThisSeries[j].nEmptiesToUnstack; } if (sCost <= nE) // series is moveable using empties { sCollapse.bottomCard = cCol.Cards[n - 1]; nT = cCol.top - 1; // point to first un-exposed card sCollapse.topCard = cCol.Cards[nT]; sCollapse.size = cCol.Cards.Count - nT; sCollapse.iStack = sCollapse.topCard.iStack; sCollapse.tag = nT; // this is destination if (utils.bRankable(ref sCollapse, ref tb)) { if (true) { if (!DisAssemble.TryExpose(ref sCollapse, ref tb)) { continue; } tlCount += 1; break; } } } } if (tlCount > 0) { tb.ReScoreBoard(); } return(tlCount); }
// remove cards in teh sCollapse series and put them all in one place, somewhere, if possible public bool TryExpose(ref series sCollapse, ref board tb) { int n = sCollapse.size; int i; card SCard = sCollapse.topCard; // this is the "S" Card with which we will be decrementing the iCard value as we move const string cstrInxVars = "ABCD"; // jys oct2012 added E string strInxvars, strPattern; column tCol = tb.ThisColumn[sCollapse.topCard.iStack]; if (n > 4) { return(false); } csosDisStrategy cds; strInxvars = cstrInxVars.Substring(0, n); AssemblePattern.Clear(); dictLookup.Clear(); //dictLookup.Add("S", SCard); // the above is not needed as we will unstack the pattern "BA" (B is actually S) to get A strPattern = AssemblePatternFrom(ref tb, ref sCollapse, strInxvars); n = strPattern.Length; if (n > 4) { return(false); // jys !!! have not created patterns bigger then 4 letters } // 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.Pattern != strPattern) { continue; } if (!cds.bMustBeTop) { continue; } if (cds.Collapsible != null) { continue; // only want to use empties } sosUnstackE(ref tb, ref cds); return(true); } } return(false); }
private bool UnstackSeriesBelow(ref board tb, ref card cNext) { bool bSuccess = true; series sCollapse; column cCol = tb.ThisColumn[cNext.iStack]; int n = cCol.Cards.Count; int LastSeries = cCol.ThisSeries.Count - 1; Debug.Assert(LastSeries >= 0); if (cNext.WhichSEQSeries == LastSeries) { return(true); } // if only one to unstack then use a simple unstack if (cNext.WhichSEQSeries == (LastSeries - 1)) { series ts = cCol.ThisSeries[cNext.WhichSEQSeries]; bSuccess = UnstackOne(ref tb, ref ts); return(bSuccess); } // if more then one to unstack then try to move all of them using a pattern match sCollapse = new series(); sCollapse.bottomCard = cCol.Cards[n - 1]; sCollapse.topCard = cNext; sCollapse.tag = cNext.tag; // this is destination sCollapse.size = cCol.Cards.Count - cNext.iCard; sCollapse.iStack = cNext.iStack; if (utils.bRankable(ref sCollapse, ref tb)) { bSuccess = Disassemble.bCanUnstackCollapseable(ref sCollapse, ref tb, ref PermanentPlaceHolders); return(bSuccess); } // hmm - not rankable JYS !!! could try a simple move SOS assumeing all are sequential // if that worked then mode the ABCD pattern counf of 4 max to account for simple sequential move // and use FillDS instead of SOS // the following will work but is not optimum int TopOfSeries = cNext.WhichSEQSeries + 1; // start at bottom series, work upward for (int i = LastSeries; i >= TopOfSeries && bSuccess; i--) { series ts = cCol.ThisSeries[i]; bSuccess = UnstackOne(ref tb, ref ts); } return(bSuccess); }
private bool UnstackOne(ref board tb, ref series ts) { int iStack = GetBestMove(ref ts.topCard, ref tb); if (iStack < 0) { if (tb.Empties.Count == 0) { return(false); } iStack = tb.Empties[0]; tb.Empties.RemoveAt(0); } tb.PerformMove(ts.iStack, ts.top, iStack, ts.size); return(true); }
public static int CalcSEQSeriesValue(series s, int BoardState) { double x, y = 2.33;// that gives 5 for two suited cards and 2.69 was for using only one series int v, n = s.bottom - s.top; if (n == 12) { s.nValue = 1000; s.sSuit = s.topCard.suit; return(1000); } if (n == 0) { v = 1; } else { x = n + 1; x = Math.Pow(x, y); v = Convert.ToInt32(x); } s.sSuit = s.topCard.suit; // 8nov2012 add value of top card and boost extra if rank was 12 if (s.topCard.rank == 13) { v += 20 * (n + 1); } v += s.topCard.rank; s.nValue = v; if (s.size == 1) { // there is only one card in the series. if ace or king give it 0 value int nOne = (s.topCard.rank == 13 || s.topCard.rank == 2) ? 0 : 1; // if the suit is buildable then use its rank as shown above if ((BoardState & 0xf & (1 << s.sSuit)) > 0) { return(v); } v = nOne; s.nValue = v; } return(v); }
public int FormSOSseries(int iFromColumn, int itop, ref List <series> xThisSOS) { series ThisList; int i; int SOSvalue = 0; int ThisTop = itop; xThisSOS.Clear(); if (Cards.Count == 0 || itop >= Cards.Count) { return(0); } ThisList = new series(); ThisList.top = ThisTop; ThisList.topCard = Cards[ThisTop]; bDoingStackables = ThisList.topCard.PartOfStackables; xThisSOS.Add(ThisList); ThisTop++; GetRemainingSOS(ThisTop, ref xThisSOS); for (i = 0; i < xThisSOS.Count; i++) { xThisSOS[i].iStack = iFromColumn; // xThisSOS[i].nEmptiesToUnstack = xThisSOS.Count - i - 1; // the above number would be true if the series was all one suit // the number of suit changes needs to be added to it. // for example: 10H,9H,8H,7D at the bottom of a column shows "0" to unstack // however, the 7D does need to be unstacked first. xThisSOS[i].nEmptiesToUnstack = xThisSOS.Count - i - 1 + xThisSOS[i].FormPatternSOS(ref Cards); } for (i = 0; i < xThisSOS.Count; i++) { utils.CalcSOSSeriesValue(xThisSOS[i]); xThisSOS[i].size = xThisSOS[i].bottom - xThisSOS[i].top + 1; } if (xThisSOS.Count == 0) { return(0); } SOSvalue = xThisSOS.Last().nValue; return(SOSvalue); }
// return true if an out of order series can be put into order // suit makes no difference public static bool bRankable(ref series s, ref board tb) { int i, d, r = s.topCard.rank; column tCol = tb.ThisColumn[s.iStack]; int n = s.size; int[] CardIndex = new int[n]; for (i = 0; i < n; i++) { CardIndex[i] = tCol.Cards[s.topCard.iCard + i].rank; } Array.Sort(CardIndex); for (i = 1; i < n; i++) { d = Math.Abs(CardIndex[i] - CardIndex[i - 1]); if (d != 1) { return(false); } } return(r == CardIndex[n - 1]); // the one to be exposed must be the biggest }
private void GetRemainingSEQ(int StartIndex) { series ThisList; int PrevIndex = StartIndex; card PrevCard; PrevIndex--; PrevCard = Cards[PrevIndex]; if (StartIndex == (Cards.Count)) { ThisSeries[ThisSeries.Count - 1].bottom = PrevIndex; ThisSeries[ThisSeries.Count - 1].bottomCard = PrevCard; return; } // is the card sequential with the previous one if (Cards[StartIndex].rank + 1 == PrevCard.rank && Cards[StartIndex].suit == PrevCard.suit) { StartIndex++; GetRemainingSEQ(StartIndex); return; } else { ThisSeries[ThisSeries.Count - 1].bottomCard = PrevCard; ThisSeries[ThisSeries.Count - 1].bottom = PrevIndex; ThisList = new series(); ThisList.top = StartIndex; ThisList.topCard = Cards[StartIndex]; ThisSeries.Add(ThisList); StartIndex++; GetRemainingSEQ(StartIndex); } }
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); }
// spin a suit at a time (causes problems, need to spin each card in turn) // do NOT move a king to an empty column unless the // exposed card frees up another column -OR- // there is a king above it that has a larger series value // nov2012 do not move king if suit is buildable ???? (maybe) // nov2012-1 king must be moved if it hides ALL others public bool SpinThisSuitedColumn(ref board tb, int iColumn) { if (cSC.bTrigger) { Console.WriteLine(MethodBase.GetCurrentMethod().Name); } column c = tb.ThisColumn[iColumn]; series s, ss; int i, cSeriesValue; int RankAbove; int n = c.ThisSeries.Count; int cntAbove; Debug.Assert(n > 0); s = c.ThisSeries.Last(); if (s.topCard.rank == 13 && s.top == 0) { return(true); // do not move a king from one empty to another } // nov2012 do not move king if that suit is buildable if (s.topCard.rank == 13) { if (tb.SuitStatus[s.topCard.suit].bSuitsCompletable) { return(true); } // must move a king if all (or any?) above it are required!!!! if (tb.bOnLastDeal) { cSC.Suitable.PerformSuitabiltyStudy(ref tb, s.topCard.suit); if (cSC.Suitable.ExposesRequired.Count > 0) { return(SpinTheseCards(ref tb, iColumn, s.top)); } } } if (!tb.SuitsLocked) { cntAbove = 1 + (c.ThisSeries[0].bottom - c.ThisSeries[0].top); if (s.topCard.rank == 13 && s.top > 0) // do not move a king unless ... { RankAbove = c.Cards[s.top - 1].rank; if (tb.NumEmptyColumns > 0) { for (i = 0; i < 10; i++) { if (tb.ThisColumn[i].Cards.Count == 0) { continue; } series t = tb.ThisColumn[i].ThisSeries.Last(); // bottom series if ((RankAbove - 1) == t.topCard.rank) { int ThisCnt = 1 + (s.bottom - s.top); if (((cntAbove + ThisCnt) > 7 && (s.topCard.suit == c.ThisSeries[0].topCard.suit)) || t.top == 0) { // spinning this king can result in swapping one empty column // for another or building a series that is probably close enough return(SpinTheseCards(ref tb, iColumn, s.top)); } } } } cSeriesValue = s.nValue; // current series value n--; // move up above the bottom series // n was is the count, if 0 then nothing more to process if (n == 0) { return(true); } while (n >= 0) { ss = c.ThisSeries[n]; n--; if (ss.topCard.rank == 13) { if (ss.nValue > cSeriesValue) { return(SpinTheseCards(ref tb, iColumn, s.top)); } } } return(true); } } return(SpinTheseCards(ref tb, iColumn, s.top)); }
// suits must be the same // pick the best series for the value of the entire series but subtract the // number of cards below the bottom public void FormSEQseries(int iFromColumn) { series ThisList, SaveSeries = null; int nValue; int NumToUnstack; int i, j = 0, iSEQ = 0; int ThisTop = top; ThisSeries.Clear(); if (Cards.Count == 0) { return; } ThisList = new series(); ThisList.top = ThisTop; ThisList.topCard = Cards[top]; ThisSeries.Add(ThisList); ThisTop++; GetRemainingSEQ(ThisTop); // when unstacking, the top card is never unstacked since we are trying to get to the top // if only 1 series, then takes nothing to unstack (it just gets moved to the destination // if 2 series the bottom one takes nothing to unstack, the one above it requires that // the one below it be unstacked first so it is = 1 and on up 2,3,etc // example: 4 series, K has 3, Q has 2, (J 10) has 1 and (6 5 4 3 2 1) has 0 for (i = 0; i < ThisSeries.Count; i++) { ThisSeries[i].iStack = iFromColumn; for (j = ThisSeries[i].top; j <= ThisSeries[i].bottom; j++) { Cards[j].WhichSEQSeries = i; } ThisSeries[i].nEmptiesToUnstack = ThisSeries.Count - i - 1; if (i == 0) { NumToUnstack = ThisSeries.Count - i - 1; } } SEQvalue = 0; if (ThisSeries.Count == 0) { return; } ThisList = null; series LastSeries = null; foreach (series s in ThisSeries) { if (LastSeries != null) { LastSeries.NextSeries = s; } #if USE_ALL_SERIES i = utils.CalcSEQSeriesValue(s); SEQvalue += i; #endif s.size = s.bottom - s.top + 1; s.topCard.next = s.size; for (i = 1; i < s.size; i++) { Cards[s.top + i].next = s.size - i; } ThisList = s; iSEQ++; LastSeries = s; } // new: if CLUBS are suitable and a CLUB series is sequential then we must not score // the column high if there is a non CLUB below the series. // the above was not implemented // instead we will NOT use the SEQ value if the suit is not completable. just use the count #if true j = 0; for (i = ThisSeries.Count - 1; i >= 0; i--) { series s = ThisSeries[i]; // jys the value is getting to 1000 and cannot do that // just use the largest value nValue = utils.CalcSEQSeriesValue(s, BoardState); if (j == 0) { SEQvalue = nValue; SaveSeries = s; } else { if ((nValue > SEQvalue) && !bSuitable) { SEQvalue = nValue; SaveSeries = s; } } j++; if (j > NumEmptyColumns) { break; } } #endif ThisSeries.Last().NextSeries = null; if (SEQvalue > 1000) { SEQvalue = 1000; } if (SaveSeries != null) { int b = (1 << SaveSeries.sSuit); // the following works at last deal ??? 17nov2012 // if (!((b & iSuitStatus) > 0)) SEQvalue = SaveSeries.size; if ((b & iSuitStatus) > 0) // we need this suit { return; } else { // we dont need that suit, but we are not in the last deal yet if (bLastDeal) { SEQvalue = SaveSeries.size; } } } }
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); }
// 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); }
// use a pattern if one is available else just unstack anyway possible private bool UnstackBelow(ref series sKeep) { return(true); }
public int FormDupList(int SrcCol, int SrcCard, int DesCol, int DesCard, ref int[] des, ref Int64 ChkValue) { int i, j, top, nCount, desptr = 0; int NumToMove; Int64 t; column tc = ThisColumn[SrcCol]; card dc; int WouldBeTop, WouldBeCount; int odesptr; int n = tc.Cards.Count; bool bCollapsible = (tc.Cards[n - 1].rank == 1); // must have an ace at the bottom of the move seq int suit = (int)tc.Cards[SrcCard].suit; // suit of each of the cards we are moving int NumAltSuits = 0; if (ThisColumn[DesCol].ThisSeries.Count > 0) { series lseq = ThisColumn[DesCol].ThisSeries.Last(); dc = ThisColumn[DesCol].Cards[DesCard - 1]; bCollapsible &= ((tc.Cards[SrcCard].rank + 1) == dc.rank); bCollapsible &= (suit == dc.suit); bCollapsible &= (suit == lseq.sSuit); bCollapsible &= (lseq.topCard.rank == 13); } else { bCollapsible = false; // would never have got this far as it would have already collapsed } // the above shows we can concat similar suits but we need to check the ones above the // destination card to see if they run up to king and also have the same suit NumToMove = ThisColumn[SrcCol].Cards.Count - SrcCard; Debug.Assert(NumToMove > 0); ChkValue = 0; for (i = 0; i < 10; i++) { tc = ThisColumn[i]; nCount = tc.Cards.Count; top = tc.top; if (i == SrcCol) { WouldBeCount = nCount - NumToMove; WouldBeTop = SrcCard - 1; if (WouldBeCount == 0) { des[desptr++] = 0; continue; //all were moved so column would be empty and nothing to shift for ChkWord } if (WouldBeTop < top) { Debug.Assert((top - WouldBeTop) == 1); // we would have exposed a new card: there are no leftovers des[desptr++] = 1; // only 1 card, the newly exposed one des[desptr++] = tc.Cards[top - 1].GetValue(); } else { if (WouldBeTop > top) { WouldBeTop = top; des[desptr++] = WouldBeCount - WouldBeTop; for (j = WouldBeTop; j < WouldBeCount; j++) { des[desptr++] = tc.Cards[j].GetValue(); } } else { des[desptr++] = 1; des[desptr++] = tc.Cards[top].GetValue(); } } } else if (i == DesCol) { WouldBeCount = nCount + NumToMove; WouldBeTop = nCount > 0 ? top : 0; // there are more cards in this column than the board shows so // we have to sequence it manually to avoid going beyond the actual count // we also need to see if the suit would have collapsed and the 13 cards removed odesptr = desptr; des[desptr++] = WouldBeCount - WouldBeTop; for (j = top; j < nCount; j++) { des[desptr++] = tc.Cards[j].GetValue(); } for (j = 0; j < NumToMove; j++) { des[desptr++] = ThisColumn[SrcCol].Cards[SrcCard + j].GetValue(); } // check the last 13 cards and see if they form a completed suit if (bCollapsible) { des[odesptr] -= 13; desptr -= 13; } } else { WouldBeTop = top; des[desptr++] = nCount - top; // number exposed boards for (j = top; j < nCount; j++) { des[desptr++] = tc.Cards[j].GetValue(); } } t = WouldBeTop; t = (t & 31) << (i * 5); ChkValue |= t; } NumAltSuits = CalcNumAltSuits(desptr, ref des); t = NumAltSuits; t = t << 50; ChkValue |= t; //return desptr; return(utils.ReOrderDups(desptr, ref des)); }