A hand
- #include "OL.h"
- extern class Hand;
- extern void defclassHand();
- #define NOTHING 0
- #define ONEPAIR 1
- #define TWOPAIRS 2
- #define THREEOFKIND 3
- #define STRAIGHT 4
- #define FLUSH 5
- #define FULLHOUSE 6
- #define FOUROFKIND 7
- #define STRAIGHTFLUSH 8
Includes the definitions of the data types and the signatures of the functions of the Object Layer.
Declares the class Hand and the function defclassHand
which builds it.
Defines constants for the different possible values of a hand.
- #include "So-o.h"
- #include "Hand.h"
- #include <string.h>
- class Hand;
Includes the signatures of the So-o functions. Includes the declarations of the class Hand. Defines the class Hand.
- static int cardcmp(instance card1, instance card2) {
- return sendmsg(card1, "compare", card2).i;
- }
The function cardcmp
compares 2 cards with the compare
method of a Card
.
It's used by the reorder
method.
- static instance i_init(instance self, va_list va) {
- instance card1 = va_arg(va, instance);
- instance card2 = va_arg(va, instance);
- instance card3 = va_arg(va, instance);
- instance card4 = va_arg(va, instance);
- instance card5 = va_arg(va, instance);
- supersend(Hand, self, "init");
- list cards = list_new();
- list_put(cards, 0, card1);
- list_put(cards, 1, card2);
- list_put(cards, 2, card3);
- list_put(cards, 3, card4);
- list_put(cards, 4, card5);
- sendmsg(self, "set", "cards", cards);
- return self;
- }
init
takes 5 arguments, the 5 cards of the hand.
It allocates a container of type list
, fills it with the cards and initializes the cards property of self
with it.
- static void i_free(instance self) {
- list cards = sendmsg(self, "get", "cards").p;
- list_free(cards);
- supersend(Hand, self, "free");
- }
code>free frees the list of cards of self
.
It doesn't free the cards.
- static instance i_copy(instance self) {
- instance copy = supersend(Hand, self, "copy").p;
- sendmsg(copy, "set", "cards", list_copy(sendmsg(self, "get", "cards").p));
- return copy;
- }
copy
returns a copy of self
.
It sets the cards
property of copy
with a copy of the list of cards of self
.
- static instance i_reorder(instance self) {
- list cards = sendmsg(self, "get", "cards").p;
- list_sort(cards, (int (*)(void *, void *))cardcmp, 1);
- return self;
- }
reorder
sorts the list of cards of self
from the weakest value to the strongest.
2 cards are compared with the function cardcmp
by sending the compare message to a card with another card in argument
- static instance i_reset(instance self, va_list va) {
- instance card1 = va_arg(va, instance);
- instance card2 = va_arg(va, instance);
- instance card3 = va_arg(va, instance);
- instance card4 = va_arg(va, instance);
- instance card5 = va_arg(va, instance);
- list cards = sendmsg(self, "get", "cards").p;
- list_put(cards, 0, card1);
- list_put(cards, 1, card2);
- list_put(cards, 2, card3);
- list_put(cards, 3, card4);
- list_put(cards, 4, card5);
- return self;
- }
reset
set the list of cards of self
with the 5 cards passed in argument.
- static instance i_card(instance self, va_list va) {
- int n = va_arg(va, int);
- if (n < 1 || n > 5) {
- return sendmsg(self, "invalidArgument", "card").p;
- }
- list cards = sendmsg(self, "get", "cards").p;
- return (instance)list_get(cards, n-1);
- }
card
returns the n
card of self
.
If n
is < 1 or > 5, an InvalidArgument
error is triggered.
- static instance i_setCard(instance self, va_list va) {
- int n = va_arg(va, int);
- instance card = va_arg(va, instance);
- if (n < 1 || n > 5) {
- return sendmsg(self, "invalidArgument", "setCard").p;
- }
- list cards = sendmsg(self, "get", "cards").p;
- list_put(cards, n-1, card);
- return self;
- }
setCard
sets the n
card of self
with card
.
If n
is < 1 or > 5, an InvalidArgument
error is triggered.
- static char *i_toString(instance self) {
- static char *handnames[] = { "NOTHING", "ONEPAIR", "TWOPAIRS", "THREEOFKIND", "STRAIGHT", "FLUSH", "FULLHOUSE", "FOUROFKIND", "STRAIGHTFLUSH" };
- static char s[5*2+4+4+13+1];
- char *p = s;
- int eval = sendmsg(self, "evaluate").i;
- list cards = sendmsg(self, "get", "cards").p;
- for (int i = 0; i < list_length(cards); i++) {
- if (i > 0)
- *p++ = ',';
- strcpy(p, (char *)sendmsg((instance)list_get(cards, i), "toString").p);
- p += 2;
- }
- sprintf(p, " -> %s", handnames[eval]);
- return s;
- }
toString
returns a string containing the rank and the suit of the 5 cards of self
and the value of the hand.
This string is formatted in a static area. It must be used before this method is called again.
- static int i_evaluate(instance self) {
- // sort or nothing works but don't reoder the hand!
- list cards = list_sort(list_copy(sendmsg(self, "get", "cards").p), (int (*)(void *, void *))cardcmp, 1);
- instance card1 = list_get(cards, 0);
- instance card2 = list_get(cards, 1);
- instance card3 = list_get(cards, 2);
- instance card4 = list_get(cards, 3);
- instance card5 = list_get(cards, 4);
- int r1 = sendmsg(card1, "rank").i;
- int r2 = sendmsg(card2, "rank").i;
- int r3 = sendmsg(card3, "rank").i;
- int r4 = sendmsg(card4, "rank").i;
- int r5 = sendmsg(card5, "rank").i;
- int s1 = sendmsg(card1, "suit").i;
- int s2 = sendmsg(card2, "suit").i;
- int s3 = sendmsg(card3, "suit").i;
- int s4 = sendmsg(card4, "suit").i;
- int s5 = sendmsg(card5, "suit").i;
- int ret = NOTHING;
- // STRAIGHTFLUSH - a(a+1)(a+2)(a+3)(a+4)
- if (r5 == r4+1 && r4 == r3+1 && r3 == r2+1 && r2 == r1+1 &&
- s1 == s2 && s2 == s3 && s3 == s4 && s4 == s5)
- ret = STRAIGHTFLUSH;
- // FOUROFKIND - aaaab abbbb
- else if (r1 == r2 && r2 == r3 && r3 == r4)
- ret = FOUROFKIND;
- else if (r2 == r3 && r3 == r4 && r4 == r5)
- ret = FOUROFKIND;
- // FULLHOUSE - aaabb aabbb
- else if (r1 == r2 && r2 == r3 && r3 != r4 && r4 == r5)
- ret = FULLHOUSE;
- else if (r1 == r2 && r2 != r3 && r3 == r4 && r4 == r5)
- ret = FULLHOUSE;
- // FLUSH
- else if (s1 == s2 && s2 == s3 && s3 == s4 && s4 == s5)
- ret = FLUSH; // could be a straight flush
- // STRAIGHT - a(a+1)(a+2)(a+3)(a+4)
- else if (r5 == r4+1 && r4 == r3+1 && r3 == r2+1 && r2 == r1+1)
- ret = STRAIGHT; // could be a straight flush
- // THREEOFKIND - aaabc abbbc abccc
- else if (r1 == r2 && r2 == r3 && r3 != r4 && r4 != r5)
- ret = THREEOFKIND;
- else if (r1 != r2 && r2 == r3 && r3 == r4 && r4 != r5)
- ret = THREEOFKIND;
- else if (r1 != r2 && r2 != r3 && r3 == r4 && r4 == r5)
- ret = THREEOFKIND;
- // TWOPAIRS - aabbc aabcc abbcc
- else if (r1 == r2 && r2 != r3 && r3 == r4 && r4 != r5)
- ret = TWOPAIRS;
- else if (r1 == r2 && r2 != r3 && r3 != r4 && r4 == r5)
- ret = TWOPAIRS;
- else if (r1 != r2 && r2 == r3 && r3 != r4 && r4 == r5)
- ret = TWOPAIRS;
- // ONEPAIR - aabcd abbcd abccd abcdd
- else if (r1 == r2 && r2 != r3 && r3 != r4 && r4 != r5)
- ret = ONEPAIR;
- else if (r1 != r2 && r2 == r3 && r3 != r4 && r4 != r5)
- ret = ONEPAIR;
- else if (r1 != r2 && r2 != r3 && r3 == r4 && r4 != r5)
- ret = ONEPAIR;
- else if (r1 != r2 && r2 != r3 && r3 != r4 && r4 == r5)
- ret = ONEPAIR;
- list_free(cards);
- return ret;
- }
evaluate
returns the value of self
.
- void defclassHand() {
- property _i_properties[] = {
- "cards",
- 0, 0
- };
- selector _i_messages[] = {
- "init", METHOD(i_init),
- "free", METHOD(i_free),
- "copy", METHOD(i_copy),
- "reorder", METHOD(i_reorder),
- "reset", METHOD(i_reset),
- "card", METHOD(i_card),
- "setCard", METHOD(i_setCard),
- "evaluate", METHOD(i_evaluate),
- "toString", METHOD(i_toString),
- 0, 0
- };
- Hand = defclass("Hand", 0, 1, 0, _i_properties, 0, _i_messages);
- }
Initializes the class Hand. The class Hand inherits from the class Object. An instance has 1 property: cards, the cards it contains. An instance redefines the messages init, free, copy and toString. It implements the messages reorder, reset, card, card, setCard and evaluate.
TEST
Compile and run the unitary test:
$ make test-Hand
gcc -g -I.. -Wno-missing-braces -O -fstrength-reduce -finline-functions -fomit-frame-pointer -c test-Hand.c
gcc -g -I.. -Wno-missing-braces -O -fstrength-reduce -finline-functions -fomit-frame-pointer -c Hand.c
gcc -g test-Hand.o Hand.o Card.o ../libso-o.a -o test-Hand
$ test-Hand
As,3c,Ad,Jh,6s -> ONEPAIR
3c,6s,Jh,As,Ad -> ONEPAIR
3c
3c,Ah,Jh,As,Ad -> THREEOFKIND
Js,Kd,8d,4h,Tc -> NOTHING
As,3c,4d,3h,6s -> ONEPAIR
7s,Kh,7d,Jc,Js -> TWOPAIRS
4s,9h,9d,8c,9s -> THREEOFKIND
Kh,Jd,Qc,Ts,Ad -> STRAIGHT
4h,9h,Ah,7h,Qh -> FLUSH
4s,Th,Td,4c,Ts -> FULLHOUSE
5s,5h,5d,Qc,5c -> FOUROFKIND
Kd,Jd,Qd,Td,Ad -> STRAIGHTFLUSH
Comments