Skip to content

Instantly share code, notes, and snippets.

@pablo-meier
Created October 1, 2010 06:28
Show Gist options
  • Save pablo-meier/605834 to your computer and use it in GitHub Desktop.
Save pablo-meier/605834 to your computer and use it in GitHub Desktop.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Top Level
main(Num_Wins) :-
open(hands, read, Fb),
read(Fb, ListOfHands),
play(ListOfHands, Num_Wins).
play([],0).
play([[Hand1,Hand2]|Rst], Num_Wins) :-
winner(Hand1, Hand2, Winner),
(Winner = Hand1, play(Rst,Remaining), Num_Wins is 1 + Remaining ;
play(Rst, Num_Wins)).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Playing the game.
winner(H1, H2, Winner) :-
sort_hand(H1, Sorted_Hand1),
sort_hand(H2, Sorted_Hand2),
determine_hand(Sorted_Hand1, X1),
determine_hand(Sorted_Hand2, X2),
beats(X1, X2, Verdict),
(Verdict = X1, Winner = H1;
Verdict = X2, Winner = H2;
Verdict = tie, tiebreak(X1, Sorted_Hand1, Sorted_Hand2, SortedWinner),
(SortedWinner = left, Winner = H1 ;
SortedWinner = right, Winner = H2)).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Tiebreaks
tiebreak(straight_flush, H1, H2, Winner) :- higher_last_card(H1, H2, Winner).
tiebreak(four_of_a_kind, H1, H2, Winner) :- higher_middle_card(H1, H2, Winner).
tiebreak(full_house, H1, H2, Winner) :- higher_middle_card(H1, H2, Winner).
tiebreak(flush, H1, H2, Winner) :- tiebreak(high_card, H1, H2, Winner).
tiebreak(straight, H1, H2, Winner) :- higher_last_card(H1, H2, Winner).
tiebreak(three_of_a_kind, H1, H2, Winner) :- higher_middle_card(H1, H2, Winner).
tiebreak(two_pair, H1, H2, Winner) :-
isolate_pairs(H1, [HighCard1,_], [LowCard1,_], Last1),
isolate_pairs(H2, [HighCard2,_], [LowCard2,_], Last2),
(beats_with_hand(H1, HighCard1, H2, HighCard2, Winner),
Winner \= tie;
beats_with_hand(H1, LowCard1, H2, LowCard2, Winner),
Winner \= tie;
beats_with_hand(H1, Last1, H2, Last2, Winner)).
tiebreak(pair, H1, H2, Winner) :-
isolate_pair(H1, [PairCard1,_], Rst1),
isolate_pair(H2, [PairCard2,_], Rst2),
(beats_with_hand(H1, PairCard1, H2, PairCard2, Winner), Winner \= tie ;
tiebreak(high_card, Rst1, Rst2, Winner)).
tiebreak(high_card, H1, H2, X) :-
reverse(H1, RevH1),
reverse(H2, RevH2),
highest_card_chain(RevH1, RevH2, X).
beats_with_hand(H1, C1, H2, C2, X) :-
beats(C1, C2, C1), X = left ;
beats(C1, C2, C2), X = right ;
X = tie.
% Really ugly. How to better do this?
isolate_pairs(Hand, High_Pair, Low_Pair, Last) :-
[[V1,S1],[V2,S2],[V3,S3],[V4,S4],[V5,S5]] = Hand,
(V5 = V4, High_Pair = [[V4,S4],[V5,S5]],
(V3 = V2, Low_Pair = [[V3,S3],[V2,S2]], Last = [V1,S1] ;
V1 = V2, Low_Pair = [[V1,S1],[V2,S2]], Last = [V3,S3])) ;
(Low_Pair = [[V1,S1],[V2,S2]],
High_Pair = [[V3,S3],[V4,S4]],
Last = [V5,S5]).
isolate_pair(Hand, Pair, Rst) :-
[[V1,S1],[V2,S2],[V3,S3],[V4,S4],[V5,S5]] = Hand,
(V1 = V2, Pair = [[V1,S1],[V2,S2]], Rst = [[V3,S3],[V4,S4],[V5,S5]] ;
V2 = V3, Pair = [[V3,S3],[V2,S2]], Rst = [[V1,S1],[V4,S4],[V5,S5]] ;
V4 = V3, Pair = [[V3,S3],[V4,S4]], Rst = [[V1,S1],[V2,S2],[V5,S5]] ;
V4 = V5, Pair = [[V5,S5],[V4,S4]], Rst = [[V1,S1],[V2,S2],[V3,S3]]).
highest_card_chain([H1|T1], [H2|T2], X) :-
beats(H1,H2,Verdict),
(Verdict = H1, X = left ;
Verdict = H2, X = right ;
Verdict = tie, highest_card_chain(T1,T2,X)).
higher_last_card(H1,H2,Winner) :-
H1 = [_,_,_,_,[V1,_]],
H2 = [_,_,_,_,[V2,_]],
beats(V1,V2,Higher),
(Higher = V1, Winner = left ;
Higher = V2, Winner = right).
higher_middle_card(H1, H2, Winner) :-
H1 = [_,_,[V1,_],_,_],
H2 = [_,_,[V2,_],_,_],
beats(V1,V2,Higher),
(Higher = V1, Winner = left;
Higher = V2, Winner = right).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Hand determination
determine_hand([[10,X],[jack,X],[queen,X],[king,X],[ace,X]], royal_flush).
determine_hand([[A,X],[B,X],[C,X],[D,X],[E,X]], straight_flush) :-
successor(E,D), successor(D,C), successor(C,B), successor(B,A).
determine_hand([[C,_],[A,_],[A,_],[A,_],[B,_]], four_of_a_kind) :-
C = A ; B = A.
determine_hand([[A,_],[B,_],[C,_],[D,_],[E,_]], full_house) :-
A = B, D = E, (C = D ; C = B).
determine_hand([[_,X],[_,X],[_,X],[_,X],[_,X]], flush).
determine_hand([[A,_],[B,_],[C,_],[D,_],[E,_]], straight) :-
successor(E,D), successor(D,C), successor(C,B), successor(B,A).
determine_hand([[A,_],[B,_],[C,_],[D,_],[E,_]], three_of_a_kind) :-
(A = B, B = C); (B = C, C = D); (C = D, D = E).
determine_hand([[A,_],[A,_],[B,_],[B,_],[_,_]], two_pair).
determine_hand([[_,_],[A,_],[A,_],[B,_],[B,_]], two_pair).
determine_hand([[A,_],[A,_],[_,_],[B,_],[B,_]], two_pair).
determine_hand([[A,_],[B,_],[C,_],[D,_],[E,_]], pair) :-
A = B; B = C; C = D; D = E.
determine_hand(_,high_card).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Hand sorting (for easier pattern matching).
sort_hand([], []).
sort_hand([H|T], Sorted) :-
filter_by_high_card(H,T,Lower,Higher),
sort_hand(Lower,SortedLower),
sort_hand(Higher,SortedHigher),
append(SortedLower, [H|SortedHigher], Sorted).
filter_by_high_card(_, [], [], []).
filter_by_high_card(Pivot, [H|T], [H|Lower], Higher) :-
beats(Pivot,H,Z),
(Z = Pivot ; Z = tie),
filter_by_high_card(Pivot, T, Lower, Higher).
filter_by_high_card(Pivot, [H|T], Lower, [H|Higher]) :-
beats(Pivot,H,H),
filter_by_high_card(Pivot, T, Lower, Higher).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Card and Hand Precedence
beats([V,_],[V,_],tie).
beats([V1,S],[V2,_],[V1,S]) :- value_greater_than(V1,V2).
beats([V1,_],[V2,S],[V2,S]) :- value_greater_than(V2,V1).
beats(X,X,tie).
beats(X,Y,X) :- value_greater_than(X,Y).
beats(X,Y,Y) :- value_greater_than(Y,X).
successor(royal_flush, straight_flush). successor(straigh_flush, four_of_a_kind).
successor(four_of_a_kind, full_house). successor(full_house, flush).
successor(flush, straight). successor(straight, three_of_a_kind).
successor(three_of_a_kind, two_pair). successor(two_pair, pair).
successor(pair, high_card).
successor(ace,king). successor(king,queen). successor(queen,jack).
successor(jack,10). successor(10,9). successor(9,8).
successor(8,7). successor(7,6). successor(6,5).
successor(5,4). successor(4,3). successor(3,2).
value_greater_than(X,Y) :-
successor(X,P),
(Y = P;
value_greater_than(P,Y)).
@nikisix
Copy link

nikisix commented Oct 18, 2024

Prolog newb here, any tips on how to call/use this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment