Created
November 27, 2012 17:47
-
-
Save stravant/4155826 to your computer and use it in GitHub Desktop.
Arduino Solitaire Logic
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
struct Card { | |
CardColor Color; | |
CardSuit Suit; | |
CardValue Value; | |
// | |
bool FaceUp; | |
// | |
Card* Next; | |
Card* Prev; | |
// | |
CardLocation Location; // Deck | Stack | | |
// | |
static Card* getCard(CardValue, CardSuit); | |
}; | |
struct BoardState { | |
Card* Stacks[4]; | |
Card* Board[7]; | |
// | |
Card* TopOfDeck; | |
Card* DeckCurrentPos; | |
// | |
Card* Disc; | |
} state; | |
//description of a move to do | |
struct SubMove { | |
Card* From; | |
Card* To; | |
}; | |
struct MoveDescription { | |
Card* From; | |
Card* To; | |
size_t SubmoveCount; | |
SubMove* SubmoveList; | |
}; | |
void hint_get_tomove(Card* dest[7], int* count) { | |
int put_inx = 0; | |
for (int i = 0; i < 7; ++i) { | |
Card* c = state.Board[i]; | |
while (c->Next && c->Next.FaceUp && c->Next.Value != 0) | |
c = c->Next; | |
if (c->Value != 0) | |
dest[put_inx++] = c; | |
} | |
*count = put_inx; | |
} | |
void hint_get_dest(Card* source[11], int* count) { | |
int put_inx = 0; | |
//places to put down a card on the board | |
for (int i = 0; i < 7; ++i) { | |
dest[put_inx++] = state.Board[i]; | |
} | |
//places to put down a card on the stacks | |
for (int i = 0; i < 7; ++i) { | |
dest[put_inx++] = state.Stacks[i]; | |
} | |
*count = put_inx; | |
} | |
//check if a given card is `available`, that is, if it is face up | |
//on the board, or in the stack. | |
Card* hint_isavailable(CardValue, CardColor) { | |
} | |
Card* hint_isavailable(CardValue, CardSuit) { | |
} | |
//can we "pull" a card from the deck onto some spot on the field | |
//(in order to make a get a card in the deck that we want into a | |
//position where we can take it.) | |
Card* can_pull_from_deck(Card*) { | |
} | |
//red => black, black => red | |
CardColor hint_otherColor(CardColor) { | |
} | |
void hint(Card** move_from, Card** move_to, bool do_move) { | |
//get cards to move and places to move them to | |
Card* toMove[7]; | |
int toMoveN; | |
hint_get_moves(toMove, &toMoveN); | |
// | |
Card* dest[11]; | |
int destN; | |
hint_get_dest(dest, &destN); | |
// | |
struct HintRecord { | |
Card* From; | |
Card* To; | |
int Difficulty; | |
bool Possible; | |
}; | |
int hintRecordComparator(const HintRecord* a, const HintRecord* b) { | |
if (a->Possible && !b->Possible) { | |
return 1; | |
} else if (!a->Possible && b->Possible) { | |
return -1; | |
} else if (a->Possible && b->Possible) { | |
return b->Difficulty - a->Difficulty; | |
} | |
} | |
HintRecord moveArray[toMoveN]; | |
moveArrayN = 0; | |
// | |
for (int i = 0; i < toMoveN; ++i) { | |
Card* cardToMove = toMove[i]; | |
//stats on the best move to do | |
Card* whereToMove = 0; | |
int moveDifficulty = 100; //large value to start | |
bool requiresUnrevealed = true; | |
// | |
for (int j = 0; j < destN; ++j) { | |
Card* cardDest = dest[j]; | |
// | |
int difficulty = 100; //intial difficulty, larger | |
bool reqUnrevealed = false; | |
// | |
if (cardDest.Location == LocationStack) { | |
//on the stacks, we need to be the same color and +n | |
if (cardToMove->Suit == cardDest->Suit || cardDest->Value == 0) { | |
difficulty = cardToMove->Value - cardDest->Value - 1 | |
//Search to see if the between cards are available | |
for (int value = cardDest->Value+1; value < cardToMove->Value; ++value) { | |
if (!hint_isavailable(i, cardDest->Suit)) | |
reqUnrevealed = true; | |
} | |
} | |
} else if (cardDest.Location == LocationBoard) { | |
//on the board, we need to have alternating colors per stack, which | |
//is a bit more complicated logic | |
int cardsBetween = cardToMove->Value - cardDest->Value - 1 | |
if (cardsBetween >= 0) { | |
if (cardDest->Value > 0) { | |
//normal placement on a stack | |
if ((cardsBetween%2 == 1) == (cardToMove->Color == cardDest->Color)) { | |
difficulty = cardsBetween; | |
//Search to see if the between cards are available | |
CardColor oddColor = hint_otherColor(cardToMove->Color); | |
CardColor evenColor = cardToMove->Color; | |
for (int ofs = 1; ofs <= cardsBetween; ++ofs) { | |
if (!hint_isavailable(cardToMove->Value+ofs, (i%2==0)?evenColor:oddColor)) | |
reqUnrevealed = true; | |
} | |
} | |
} else { | |
//placement of a king in an empty stack | |
if (cardToMove->Value == 13) { | |
//king, can move | |
difficulty = 0; | |
reqUnrevealed = false; | |
} | |
} | |
} | |
} else { | |
assert(false && "Unreachable"); | |
} | |
//update the best move if we are "better" than it with this move | |
if (difficulty < moveDifficulty && (!reqUnrevealed || requiresUnrevealed)) { | |
moveDifficulty = difficulty; | |
requiresUnrevealed = reqUnrevealed; | |
whereToMove = cardDest; | |
} | |
} | |
//update the hintRecord if we found a way to move this item | |
if (whereToMove) { | |
HintRecord& rec = moveArray[moveArrayN++]; | |
rec.From = cardToMove; | |
rec.To = whereToMove; | |
rec.Difficulty = moveDifficulty; | |
rec.Possible = !requiresUnrevealed; | |
} | |
} | |
//now sort the hintrecords by difficulty | |
qsort(moveArray, moveArrayN, sizeof(HintRecord), hintRecordComparator); | |
//sorted, see if we have a 0 difficulty item | |
if (moveArray[0].Difficulty == 0) { | |
//with a 0 difficult move we can just do it | |
*move_from = moveArray[0].From; | |
*move_to = moveArray[0].To; | |
return; | |
} else { | |
//otherwise, we need a more complex logic to test the constraints of the move. | |
//we can't just pull any old card out of the deck, so we may need to | |
//for each move, test if each of the constraints can be met | |
for (int i = 0; i < moveArrayN; ++i) { | |
HintRecord& rec = moveArrayN[i]; | |
//now, find the constraints, exactly which cards we need | |
if (rec.To->Location == LocationStack) { | |
//stack, constraints are on-suit | |
} else if (rec.To->Location == LocationBoard) { | |
//board, constraints are alternating color | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment