private void MakeSimpleMove(int from, int fromRow, int to) { if (fromRow < 0) { fromRow += Tableau[from].Count; } if (Diagnostics) { Utils.WriteLine(" MSM: {0}/{1} -> {2}", from, fromRow, to); } Debug.Assert(Tableau[from].Count != 0); Debug.Assert(fromRow < Tableau[from].Count); Debug.Assert(Tableau.CountSuits(from, fromRow) == 1); Debug.Assert(Tableau[to].Count == 0 || Tableau[from][fromRow].IsSourceFor(Tableau[to][Tableau[to].Count - 1])); MakeMove(new Move(from, fromRow, to, Tableau[to].Count)); }
private void UnloadToSpaces(int from, int fromRow, int to) { if (Diagnostics) { Utils.WriteLine("ULTS: {0}/{1} -> {2}", from, fromRow, to); } int numberOfSpaces = Tableau.NumberOfSpaces; int suits = Tableau.CountSuits(from, fromRow); if (suits > ExtraSuits(numberOfSpaces)) { throw new InvalidMoveException("insufficient spaces"); } Spaces.Copy(Tableau.Spaces); int totalSuits = Tableau.CountSuits(from, fromRow); int remainingSuits = totalSuits; int currrentFromRow = Tableau[from].Count; for (int n = 0; n < numberOfSpaces; n++) { int m = Math.Min(numberOfSpaces, n + remainingSuits); for (int i = m - 1; i >= n; i--) { int runLength = Tableau.GetRunUp(from, currrentFromRow); currrentFromRow -= runLength; currrentFromRow = Math.Max(currrentFromRow, fromRow); MakeSimpleMove(from, -runLength, Spaces[i]); MoveStack.Push(new Move(Spaces[i], -runLength, to)); remainingSuits--; } for (int i = n + 1; i < m; i++) { int runLength = Tableau[Spaces[i]].Count; MakeSimpleMove(Spaces[i], -runLength, Spaces[n]); MoveStack.Push(new Move(Spaces[n], -runLength, Spaces[i])); } if (remainingSuits == 0) { break; } } }
private string SafeMakeMoveUsingSpaces(int from, int fromRow, int to) { if (fromRow < 0) { fromRow += Tableau[from].Count; } if (Diagnostics) { Utils.WriteLine("MMUS: {0}/{1} -> {2}", from, fromRow, to); } int toRow = Tableau[to].Count; int extraSuits = Tableau.CountSuits(from, fromRow) - 1; if (extraSuits < 0) { return("not a single run"); } if (extraSuits == 0) { MakeSimpleMove(from, fromRow, to); return(null); } int numberOfSpaces = Tableau.NumberOfSpaces; Spaces.Copy(Tableau.Spaces); if (toRow == 0) { Spaces.Remove(to); numberOfSpaces--; } int maxExtraSuits = ExtraSuits(numberOfSpaces); if (extraSuits > maxExtraSuits) { return("insufficient spaces"); } int suits = 0; int currentFromRow = Tableau[from].Count; SpacesMoveStack.Clear(); for (int n = numberOfSpaces; n > 0; n--) { for (int i = 0; i < n; i++) { int runLength = Tableau.GetRunUp(from, currentFromRow); currentFromRow -= runLength; MakeSimpleMove(from, -runLength, Spaces[i]); SpacesMoveStack.Push(new Move(Spaces[i], -runLength, to)); suits++; if (suits == extraSuits) { break; } } if (suits == extraSuits) { break; } for (int i = n - 2; i >= 0; i--) { int runLength = Tableau[Spaces[i]].Count; MakeSimpleMove(Spaces[i], -runLength, Spaces[n - 1]); SpacesMoveStack.Push(new Move(Spaces[n - 1], -runLength, Spaces[i])); } } MakeSimpleMove(from, fromRow, to); while (SpacesMoveStack.Count != 0) { Move move = SpacesMoveStack.Pop(); MakeSimpleMove(move.From, move.FromRow, move.To); } return(null); }
private void SwapUsingSpaces(int from, int fromRow, int to, int toRow) { if (Diagnostics) { Utils.WriteLine("SWUS: {0}/{1} -> {2}/{3}", from, fromRow, to, toRow); } int fromSuits = Tableau.CountSuits(from, fromRow); int toSuits = Tableau.CountSuits(to, toRow); if (fromSuits == 0 && toSuits == 0) { return; } if (fromSuits == 0) { MakeMoveUsingSpaces(to, toRow, from); return; } if (toSuits == 0) { MakeMoveUsingSpaces(from, fromRow, to); return; } int numberOfSpaces = Tableau.NumberOfSpaces; Spaces.Copy(Tableau.Spaces); if (fromSuits + toSuits - 1 > ExtraSuits(numberOfSpaces)) { throw new InvalidMoveException("insufficient spaces"); } MoveStack.Clear(); for (int n = numberOfSpaces; n > 0 && fromSuits + toSuits > 1; n--) { if (fromSuits >= toSuits) { int moveSuits = toSuits != 0 ? fromSuits : fromSuits - 1; fromSuits -= MoveOffUsingSpaces(from, fromRow, to, moveSuits, n); } else { int moveSuits = fromSuits != 0 ? toSuits : toSuits - 1; toSuits -= MoveOffUsingSpaces(to, toRow, from, moveSuits, n); } } if (fromSuits + toSuits != 1 || fromSuits * toSuits != 0) { throw new Exception("bug: left over swap runs"); } if (fromSuits == 1) { MakeSimpleMove(from, fromRow, to); } else { MakeSimpleMove(to, toRow, from); } while (MoveStack.Count != 0) { Move move = MoveStack.Pop(); MakeSimpleMove(move.From, move.FromRow, move.To); } }