% FILE: melds.pl % LINE: Defines rules for finding melds in a player's hand % DATE: March 14, 2021 % checks if a hand has N of one card in it find_same_card([], _, [], []). find_same_card([card(Face1, Suit1, Rank1)|RestHand], card(Face1, _, _), [card(Face1, Suit1, Rank1)|Move], NewHand) :- find_same_card(RestHand, card(Face1, _, _), Move, NewHand). find_same_card([card(Face1, Suit1, Rank1)|RestHand], card(Face2, Suit2, Rank2), Move, [card(Face1, Suit1, Rank1)|NewHand]) :- find_same_card(RestHand, card(Face2, Suit2, Rank2), Move, NewHand). % finds three of a kind in a player's hand % Original Hand, Hand to iterate through, find_set(OrigHand, [], OldMelds, OldMelds, OrigHand). find_set(OrigHand, [card(Face1, Suit1, Rank1)|_], OldMelds, [Move|OldMelds], NewHand) :- find_same_card(OrigHand, card(Face1, Suit1, Rank1), Move, NewHand), length(Move, L), L>=2. find_set(OrigHand, [_|RestHand], OldMelds, NewMelds, NewHand) :- find_set(OrigHand, RestHand, OldMelds, NewMelds, NewHand). % finds three of a kind in a player's hand % Original Hand, Hand to iterate through, find_four_of_a_kind(OrigHand, [], OldMelds, OldMelds, OrigHand). find_four_of_a_kind(OrigHand, [card(Face1, Suit1, Rank1)|_], OldMelds, [Move|OldMelds], NewHand) :- find_same_card(OrigHand, card(Face1, Suit1, Rank1), Move, NewHand), length(Move, L), L=4. find_four_of_a_kind(OrigHand, [_|RestHand], OldMelds, NewMelds, NewHand) :- find_four_of_a_kind(OrigHand, RestHand, OldMelds, NewMelds, NewHand). % finds a run of any length greater than or equal to three in a player's hand % Hand must be sorted before calling this method % try with suit, if move is found, add it to melds, repeat until no more suits find_run(Hand, Hand, [], Melds, Melds). find_run(Hand, NewHand, [FirstSuit|_], Melds, [CardsFound|Melds]) :- find_run_suit(Hand, NewHand, 1, FirstSuit, CardsFound), length(CardsFound, L), L >= 2 ; find_run_suit(Hand, NewHand, 2, FirstSuit, CardsFound), length(CardsFound, L), L >= 2 ; find_run_suit(Hand, NewHand, 3, FirstSuit, CardsFound), length(CardsFound, L), L >= 2 ; find_run_suit(Hand, NewHand, 4, FirstSuit, CardsFound), length(CardsFound, L), L >= 2 ; find_run_suit(Hand, NewHand, 5, FirstSuit, CardsFound), length(CardsFound, L), L >= 2 ; find_run_suit(Hand, NewHand, 6, FirstSuit, CardsFound), length(CardsFound, L), L >= 2 ; find_run_suit(Hand, NewHand, 7, FirstSuit, CardsFound), length(CardsFound, L), L >= 2 ; find_run_suit(Hand, NewHand, 8, FirstSuit, CardsFound), length(CardsFound, L), L >= 2 ; find_run_suit(Hand, NewHand, 9, FirstSuit, CardsFound), length(CardsFound, L), L >= 2 ; find_run_suit(Hand, NewHand, 10, FirstSuit, CardsFound), length(CardsFound, L), L >= 2 ; find_run_suit(Hand, NewHand, 11, FirstSuit, CardsFound), length(CardsFound, L), L >= 2. find_run(Hand, NewHand, [_|RestSuits], Melds, NewMelds) :- find_run(Hand, NewHand, RestSuits, Melds, NewMelds). % finds a run in the suit provided starting at rank NextRank find_run_suit([], [], _, _,[]). find_run_suit([card(Face, Suit, Rank)|Hand], NewHand, Rank, Suit, [card(Face, Suit, Rank)|CardsFound]) :- NewRank is Rank +1, find_run_suit(Hand, NewHand, NewRank, Suit, CardsFound). find_run_suit([card(Face, Suit, Rank)|Hand], [card(Face, Suit, Rank)|NewHand], AnotherRank, Suit2, CardsFound) :- find_run_suit(Hand, NewHand, AnotherRank, Suit2, CardsFound). % Sorts hand in order by the following rule % A - K with suit order being Diamonds, Clubs, Hearts, Spade merge_sort([], []). merge_sort([Item], [Item]). merge_sort(List,Sorted):- List=[_,_|_], split(List, L1, L2), merge_sort(L1,Sorted1), merge_sort(L2,Sorted2), merge(Sorted1,Sorted2,Sorted). % merges two lists together, sorting them on the way up merge([], L, L). merge(L, [], L) :- L \= []. merge([card(Face1, Suit1, Rank1)|T1], [card(Face2, Suit2, Rank2)|T2], [card(Face1, Suit1, Rank1)|T]) :- less_than(card(Face1, Suit1, Rank1), card(Face2, Suit2, Rank2)), merge(T1, [card(Face2, Suit2, Rank2)|T2], T). merge([X|T1],[Y|T2],[Y|T]) :- merge([X|T1],T2,T). % true if card 1 is less than card 2 less_than(card(_, _, Rank1), card(_, _, Rank2)) :- Rank1 < Rank2. less_than(card(_, Suit1, Rank1), card(_, _, Rank2)) :- Rank1 = Rank2, Suit1 = diamonds. less_than(card(_, Suit1, Rank1), card(_, Suit2, Rank2)) :- Rank1 = Rank2, Suit1 = clubs, Suit2 = hearts. less_than(card(_, Suit1, Rank1), card(_, Suit2, Rank2)) :- Rank1 = Rank2, Suit1 = clubs, Suit2 = spades. less_than(card(_, Suit1, Rank1), card(_, Suit2, Rank2)) :- Rank1 = Rank2, Suit1 = hearts, Suit2 = spades. split([], [], []). split([Card], [Card|[]], []). split([Card1, Card2|RestCards], [Card1|RestCards1], [Card2|RestCards2]) :- split(RestCards, RestCards1, RestCards2).