private void GetAdjacentStackables(ref card thisCard, ref column cCol, ref List <card> CardsAbove, ref List <card> CardsBelow) { int i, j; CardsBelow.Clear(); CardsAbove.Clear(); if (thisCard.iCard > cCol.top) { for (i = thisCard.iCard - 1; i >= cCol.top; i--) { for (j = 0; j < Stackables.Count; j++) { if (cCol.Cards[i] == Stackables[j]) { CardsAbove.Add(Stackables[j]); } } } } else if (thisCard.iCard != (cCol.Cards.Count - 1)) { for (i = thisCard.iCard + 1; i < cCol.Cards.Count; i++) { for (j = 0; j < Stackables.Count; j++) { if (cCol.Cards[i] == Stackables[j]) { CardsBelow.Add(Stackables[j]); } } } } }
public csosDisStrategy(int iNEC, int iNC, string strPattern, string strHoldCards, string strMoves) { string[] sSetMoves = strMoves.Split(','); string[] sOneMove; int i; NumEmptyColumns = Math.Abs(iNEC); NumCards = iNC; bMustBeTop = false; if (iNEC <= 0) { bMustBeTop = true; } Pattern = strPattern; if (strHoldCards != "") { nCollapse = Convert.ToInt32(strHoldCards.Substring(0, 1)); Collapsible = new column(); strCollapse = strHoldCards.Substring(1); } for (i = 0; i < sSetMoves.Length; i++) { sOneMove = sSetMoves[i].Split('-'); cDisMoves cdm = new cDisMoves(sOneMove[0], sOneMove[1]); UnstackMoves.Add(cdm); } }
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); }
public void InitializeReduction(ref board tb, ref card cNext) { int i, j = 13; tb.ReScoreBoard(); Stackables.Clear(); StackableIDs.Clear(); DoNotUse.Clear(); cNext = tb.SuitedSEQ[0].topCard; int suit = cNext.suit; foreach (series s in tb.SuitedSEQ) { DoNotUse.Add(s.iStack); // not a permanent placeholder till that card is moved (if it is moved) for (i = cNext.iCard; i <= s.bottom; i++) { column cCol = tb.ThisColumn[s.iStack]; Stackables.Add(cCol.Cards[i]); cCol.Cards[i].PartOfStackables = true; Debug.Assert(j == cCol.Cards[i].rank && suit == cCol.Cards[i].suit); j--; } cNext = s.AssemblyLink; // link to next card in "s" assembly if (cNext != null) { StackableIDs.Add(cNext.ID); } } cNext = tb.SuitedSEQ[0].topCard; }
/* * 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); }
// if there is a card above ThisCard that is a member of the series we are trying to stack, then // ThisCard must be moved. Only king has this problem when stacking private bool bStackablesAbove(ref board tb, ref card ThisCard) { column cCol = tb.ThisColumn[ThisCard.iStack]; for (int i = ThisCard.iCard - 1; i >= cCol.top; i++) { if (cCol.Cards[i].PartOfStackables) { return(true); } } return(false); }
// 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); }
public void init() { int i; score = 0; dead = false; nchild = 0; from = 0; bIsCompletable = false; NumEmptyColumns = 0; ThisColumn = new column[12]; // column 11 is the remaining deck and the 12th one is "complete" Empties = new List <int>(); NonEmpties = new List <int>(); Completed = new List <cCompleted>(); NewlyCompleted = false; bitJustCompleted = 0; strSuitsRemoved = ""; DealString = ""; bWasDealtTo = false; // not copied because it is used as a signaling variable for (i = 0; i < 12; i++) { ThisColumn[i] = new column(); ThisColumn[i].iStack = i; ThisColumn[i].init(); } bOnLastDeal = false; DealCounter = 0; // deal 0 is the initial board NumCompletedSuits = 0; tag = 0; TopMost = new List <card>(); BottomMost = new List <card>(); SuitedSEQ = new List <series>(); NotifySuitJustCompleted = false; SaveCompletedBy.Push((int)GlobalClass.TypeCompletedBy.ID_UNK); bSignalBoardComplete = false; UniqueID = BoardCounter++; SuitsLocked = false; BuildingThisSuit = 0; // we are building "all" suits for (i = 0; i < 4; i++) { SuitStatus[i] = new cSuitedStatus(); SuitStatus[i].MissingTypes = new List <int>(); SuitStatus[i].MustExpose = new List <int>(); SuitStatus[i].BonusExposes = new List <int>(); SuitStatus[i].index = i; SuitStatus[i].NumCompletedAndRemoved = 0; } UnexposedTypes = new List <int>(); }
public int NumFacedownColumns() { int n = 0; foreach (int e in NonEmpties) { column cCol = ThisColumn[e]; if (cCol.top == 0) { continue; } n++; } return(n); }
public List <int> PartOfMovables; // if a card is part of the movables then it cannot // be used as a placeholder until it has moved. After it has // has moved then fStack must be used, not iStack private bool IsTopMost(ref card thisCard, ref column cCol) { int i; if (thisCard.iCard == cCol.top) { return(true); } for (i = thisCard.iCard - 1; i >= cCol.top; i--) { foreach (card c in Stackables) { if (c == cCol.Cards[i]) { return(false); } } } return(true); }
// 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 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); }
public int RemoveCompletedSuit(int iCol) { column tc = ThisColumn[iCol]; int i, j, n = tc.ThisSeries.Count - 1; int suit = tc.ThisSeries[n].sSuit; Debug.Assert(n >= 0); j = tc.ThisSeries[n].bottom; // position of last card in last series Debug.Assert(j == tc.Cards.Count - 1); // should always be last card // instead of deleting 13 cards from location top // we will move 13 cards from the bottom of the stack to stack 11 (12th stack) for (i = 0; i < 13; i++) { card c = tc.Cards[j - i]; ThisColumn[11].Cards.Add(c); } tc.Cards.RemoveRange(tc.ThisSeries[n].top, 13); n = tc.Cards.Count - 1; if (n >= 0) { tc.Cards[n].bFaceUp = true; } return(suit); }
// 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)); }
// 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); }
// 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); }
// returns the card exposed by the move, if any public card PerformMove(int FromStack, int FromLoc, int ToStack, int NumMoved) { bool bWasFacedown = false; int i, suit; card NewCard, TopCardMoved; card CardExposed = null; column sCol = ThisColumn[FromStack]; TopCardMoved = sCol.Cards[FromLoc]; bool bWasUp = TopCardMoved.bFaceUp; int RankAbove, RankBelow, ToLoc; suit = TopCardMoved.suit; #if DEBUG Debug.Assert((FromLoc + NumMoved) == sCol.Cards.Count); for (int j = 0; j < NumMoved; j++) { Debug.Assert(suit == sCol.Cards[j + FromLoc].suit); } Debug.Assert(bWasUp); #endif ToLoc = ThisColumn[ToStack].Cards.Count; if (ToLoc > 0) { RankBelow = sCol.Cards[FromLoc].rank; RankAbove = ThisColumn[ToStack].Cards[ToLoc - 1].rank; Debug.Assert((RankAbove - RankBelow) == 1); if ((RankAbove - RankBelow) != 1) { ShowRawBoard(); return(null);// 0; } } for (i = 0; i < NumMoved; i++) { NewCard = sCol.Cards[FromLoc + i]; NewCard.iStack = ToStack; // the and the following are needed in case this card needs to be NewCard.iCard = i + ToLoc; // accessed before the ReScore is called ThisColumn[ToStack].Cards.Add(NewCard); } sCol.Cards.RemoveRange(FromLoc, NumMoved); i = (ThisColumn[FromStack].Cards.Count); if (i > 0) { card cCrd = sCol.Cards[i - 1]; if (!cCrd.bFaceUp) { int b = 1 << cCrd.rank; cSuitedStatus css = SuitStatus[cCrd.suit]; css.SuitedRankBits |= b; AreAnySuitsCompletable(); b = ~b; b = b & 0xffff; // keep to int size css.UnexposedRankBits &= b; // remove from unexposed "bits" and the list UnexposedTypes.Remove(cCrd.type); if (css.MustExpose.Contains(cCrd.type)) { SuitStatus[cCrd.suit].BonusExposes.Add(cCrd.type); } bWasFacedown = true; } cCrd.bFaceUp = true; CardExposed = cCrd; } MyMoves.AddMove(TopCardMoved.ID, FromStack, ToStack, score, bWasFacedown, NumMoved); return(CardExposed); }
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)); }