Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cards representation in Prolog

Tags:

prolog

poker

I'm trying to learn Prolog. This are my first steps with this language. As exercise I want to write program which can recognize some poker hands (Straight flush, Four of a kind, Full house etc.).

I'm looking for good card representation in Prolog. I need to have possibility to check if one card is bigger than other, if cards are suited and so one.

I have started with code:

rank(2).
rank(3).
rank(4).
rank(5).
rank(6).
rank(7).
rank(8).
rank(9).
rank(t).
rank(j).
rank(q).
rank(k).
rank(a).

value(2, 2).
value(3, 3).
value(4, 4).
value(5, 5).
value(6, 6).
value(7, 7).
value(8, 8).
value(9, 9).
value(t, 10).
value(j, 11).
value(q, 12).
value(k, 13).
value(a, 14).
%value(a, 1).

suite(d).
suite(h).
suite(c).
suite(s).

rank_bigger(X, Y) :-
               value(X, A),
               value(Y, B),
               A > B.

That give mi possibility to check if rank A is bigger than for example J.

But I'm not sure how to represent single card. This representation should contains rank of card and also suit. There is also some issue with Ace because Ace have rank 14 but it can be also 1 in straight.

So my question is how to represents cards if I want to make rules like:

isStraight(C1, C2, C3, C4, C5) :- 
                                  [...]

or

isStraightFlush(C1, C2, C3, C4, C5) :- 
                                       [...]

I'm sure that this is kind of simple question if you know language, but it is not so easy to 'switch' thinking from languages like C or python. :-)

like image 954
Adam Avatar asked Jan 12 '11 19:01

Adam


2 Answers

You can use unicode and SWI to make pretty programs...

:- op(200, xf, ♥).
:- op(200, xf, ♦).
:- op(200, xf, ♣).
:- op(200, xf, ♠).
:- op(200, xf, ♡).
:- op(200, xf, ♢).
:- op(200, xf, ♧).
:- op(200, xf, ♤).

main :- print([2♠,3♦,'K'♥,10♠,3♣]),
        isFlush(2♠,3♦,'K'♥,10♠,3♣).

isFlush(♥(_),♥(_),♥(_),♥(_),♥(_)).
isFlush(♦(_),♦(_),♦(_),♦(_),♦(_)).
isFlush(♣(_),♣(_),♣(_),♣(_),♣(_)).
isFlush(♠(_),♠(_),♠(_),♠(_),♠(_)).
like image 71
Greg Buchholz Avatar answered Sep 30 '22 04:09

Greg Buchholz


You could represent cards as terms with the form Rank-Suite.

In order to check if the cards come from the same suite define a predicate:

same_suit(_-S, _-S).

You can use this predicate to check if you have a flush:

?- Cards = [1-d, 2-d, 3-d, 4-d, 5-d], maplist(same_suit(_-S), Cards).
Cards = [1-d, 2-d, 3-d, 4-d, 5-d],
S = d.

In order to detect if you have a pair, two pairs, three of a kind, full house, or four of a kind you can just count the number of pairs in the hand and then map the result to the name of the hand.

% Count the number of pairs in the given list of cards.
count_pairs([], 0).

count_pairs([R-_ | Cs], Pairs) :-
    count_rank(R, Cs, RankCount),
    count_pairs(Cs, Pairs0),
    Pairs is RankCount + Pairs0.


% Count the number of cards with the given rank
count_rank(R, Cs, RankCount) :-
    count_rank(R, Cs, 0, RankCount).


count_rank(_, [], RankCount, RankCount) :- !.

count_rank(R, [R-_ | Cs], RankCount0, RankCount) :-
    !,
    RankCount1 is RankCount0 + 1,
    count_rank(R, Cs, RankCount1, RankCount).

count_rank(R, [_ | Cs], RankCount0, RankCount) :-
    count_rank(R, Cs, RankCount0, RankCount).


% Map the number of pairs to the name of the hand
pairs_hand(1, one_pair).
pairs_hand(2, two_pair).
pairs_hand(3, three_of_a_kind).
pairs_hand(4, full_house).
%pairs_hand(5, 'NOT POSSIBLE').
pairs_hand(6, four_of_a_kind).

Usage examples:

?- count_pairs([q-c, q-d, q-s, j-s, q-h], PairsCount), pairs_hand(PairsCount, Hand).
PairsCount = 6,
Hand = four_of_a_kind.

?- count_pairs([j-c, q-d, q-s, j-s, q-h], PairsCount), pairs_hand(PairsCount, Hand).
PairsCount = 4,
Hand = full_house.

?- count_pairs([j-c, q-d, q-s, j-s, 7-h], PairsCount), pairs_hand(PairsCount, Hand).
PairsCount = 2,
Hand = two_pair.
like image 40
Kaarel Avatar answered Sep 30 '22 02:09

Kaarel