A hand

  1. #include "OL.h"
  2.  
  3. extern class Hand;
  4.  
  5. extern void defclassHand();
  6.  
  7. #define NOTHING         0
  8. #define ONEPAIR         1
  9. #define TWOPAIRS        2
  10. #define THREEOFKIND     3
  11. #define STRAIGHT        4
  12. #define FLUSH           5
  13. #define FULLHOUSE       6
  14. #define FOUROFKIND      7
  15. #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.

  1. #include "So-o.h"
  2.  
  3. #include "Hand.h"
  4.  
  5. #include <string.h>
  6.  
  7. class Hand;

Includes the signatures of the So-o functions. Includes the declarations of the class Hand. Defines the class Hand.

  1. static int cardcmp(instance card1, instance card2) {
  2.     return sendmsg(card1, "compare", card2).i;
  3. }

The function cardcmp compares 2 cards with the compare method of a Card. It's used by the reorder method.

  1. static instance i_init(instance self, va_list va) {
  2.     instance card1 = va_arg(va, instance);
  3.     instance card2 = va_arg(va, instance);
  4.     instance card3 = va_arg(va, instance);
  5.     instance card4 = va_arg(va, instance);
  6.     instance card5 = va_arg(va, instance);
  7.  
  8.     supersend(Hand, self, "init");
  9.  
  10.     list cards = list_new();
  11.  
  12.     list_put(cards, 0, card1);
  13.     list_put(cards, 1, card2);
  14.     list_put(cards, 2, card3);
  15.     list_put(cards, 3, card4);
  16.     list_put(cards, 4, card5);
  17.  
  18.     sendmsg(self, "set", "cards", cards);
  19.  
  20.     return self;
  21. }

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.

  1. static void i_free(instance self) {
  2.     list cards = sendmsg(self, "get", "cards").p;
  3.  
  4.     list_free(cards);
  5.  
  6.     supersend(Hand, self, "free");
  7. }

code>free frees the list of cards of self. It doesn't free the cards.

  1. static instance i_copy(instance self) {
  2.     instance copy = supersend(Hand, self, "copy").p;
  3.  
  4.     sendmsg(copy, "set", "cards", list_copy(sendmsg(self, "get", "cards").p));
  5.  
  6.     return copy;
  7. }

copy returns a copy of self. It sets the cards property of copy with a copy of the list of cards of self.

  1. static instance i_reorder(instance self) {
  2.     list cards = sendmsg(self, "get", "cards").p;
  3.  
  4.     list_sort(cards, (int (*)(void *, void *))cardcmp, 1);
  5.  
  6.     return self;
  7. }

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

  1. static instance i_reset(instance self, va_list va) {
  2.     instance card1 = va_arg(va, instance);
  3.     instance card2 = va_arg(va, instance);
  4.     instance card3 = va_arg(va, instance);
  5.     instance card4 = va_arg(va, instance);
  6.     instance card5 = va_arg(va, instance);
  7.  
  8.     list cards = sendmsg(self, "get", "cards").p;
  9.  
  10.     list_put(cards, 0, card1);
  11.     list_put(cards, 1, card2);
  12.     list_put(cards, 2, card3);
  13.     list_put(cards, 3, card4);
  14.     list_put(cards, 4, card5);
  15.  
  16.     return self;
  17. }

reset set the list of cards of self with the 5 cards passed in argument.

  1. static instance i_card(instance self, va_list va) {
  2.     int n = va_arg(va, int);
  3.  
  4.     if (n < 1 || n > 5) {
  5.         return sendmsg(self, "invalidArgument", "card").p;
  6.     }
  7.  
  8.     list cards = sendmsg(self, "get", "cards").p;
  9.  
  10.     return (instance)list_get(cards, n-1);
  11. }

card returns the n card of self. If n is < 1 or > 5, an InvalidArgument error is triggered.

  1. static instance i_setCard(instance self, va_list va) {
  2.     int n = va_arg(va, int);
  3.     instance card = va_arg(va, instance);
  4.  
  5.     if (n < 1 || n > 5) {
  6.         return sendmsg(self, "invalidArgument", "setCard").p;
  7.     }
  8.  
  9.     list cards = sendmsg(self, "get", "cards").p;
  10.  
  11.     list_put(cards, n-1, card);
  12.  
  13.     return self;
  14. }

setCard sets the n card of self with card. If n is < 1 or > 5, an InvalidArgument error is triggered.

  1. static char *i_toString(instance self) {
  2.     static char *handnames[] = { "NOTHING", "ONEPAIR", "TWOPAIRS", "THREEOFKIND", "STRAIGHT", "FLUSH", "FULLHOUSE", "FOUROFKIND", "STRAIGHTFLUSH" };
  3.  
  4.     static char s[5*2+4+4+13+1];
  5.  
  6.     char *p = s;
  7.  
  8.     int eval = sendmsg(self, "evaluate").i;
  9.  
  10.     list cards = sendmsg(self, "get", "cards").p;
  11.  
  12.     for (int i = 0; i < list_length(cards); i++) {
  13.         if (i > 0)
  14.             *p++ = ',';
  15.         strcpy(p, (char *)sendmsg((instance)list_get(cards, i), "toString").p);
  16.         p += 2;
  17.     }
  18.  
  19.     sprintf(p, " -> %s", handnames[eval]);
  20.  
  21.     return s;
  22. }

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.

  1. static int i_evaluate(instance self) {
  2.     // sort or nothing works but don't reoder the hand!
  3.     list cards = list_sort(list_copy(sendmsg(self, "get", "cards").p), (int (*)(void *, void *))cardcmp, 1);
  4.  
  5.     instance card1 = list_get(cards, 0);
  6.     instance card2 = list_get(cards, 1);
  7.     instance card3 = list_get(cards, 2);
  8.     instance card4 = list_get(cards, 3);
  9.     instance card5 = list_get(cards, 4);
  10.  
  11.     int r1 = sendmsg(card1, "rank").i;
  12.     int r2 = sendmsg(card2, "rank").i;
  13.     int r3 = sendmsg(card3, "rank").i;
  14.     int r4 = sendmsg(card4, "rank").i;
  15.     int r5 = sendmsg(card5, "rank").i;
  16.  
  17.     int s1 = sendmsg(card1, "suit").i;
  18.     int s2 = sendmsg(card2, "suit").i;
  19.     int s3 = sendmsg(card3, "suit").i;
  20.     int s4 = sendmsg(card4, "suit").i;
  21.     int s5 = sendmsg(card5, "suit").i;
  22.  
  23.     int ret = NOTHING;
  24.  
  25.     // STRAIGHTFLUSH - a(a+1)(a+2)(a+3)(a+4)
  26.  
  27.     if (r5 == r4+1 && r4 == r3+1 && r3 == r2+1 && r2 == r1+1 &&
  28.         s1 == s2 && s2 == s3 && s3 == s4 && s4 == s5)
  29.         ret = STRAIGHTFLUSH;
  30.  
  31.     // FOUROFKIND - aaaab abbbb
  32.  
  33.     else if (r1 == r2 && r2 == r3 && r3 == r4)
  34.         ret = FOUROFKIND;
  35.  
  36.     else if (r2 == r3 && r3 == r4 && r4 == r5)
  37.         ret = FOUROFKIND;
  38.  
  39.     // FULLHOUSE - aaabb aabbb
  40.  
  41.     else if (r1 == r2 && r2 == r3 && r3 != r4 && r4 == r5)
  42.         ret = FULLHOUSE;
  43.  
  44.     else if (r1 == r2 && r2 != r3 && r3 == r4 && r4 == r5)
  45.         ret = FULLHOUSE;
  46.  
  47.     // FLUSH
  48.  
  49.     else if (s1 == s2 && s2 == s3 && s3 == s4 && s4 == s5)
  50.         ret = FLUSH;        // could be a straight flush
  51.  
  52.     // STRAIGHT - a(a+1)(a+2)(a+3)(a+4)
  53.  
  54.     else if (r5 == r4+1 && r4 == r3+1 && r3 == r2+1 && r2 == r1+1)
  55.         ret = STRAIGHT; // could be a straight flush
  56.  
  57.     // THREEOFKIND - aaabc abbbc abccc
  58.  
  59.     else if (r1 == r2 && r2 == r3 && r3 != r4 && r4 != r5)
  60.         ret = THREEOFKIND;
  61.  
  62.     else if (r1 != r2 && r2 == r3 && r3 == r4 && r4 != r5)
  63.         ret = THREEOFKIND;
  64.  
  65.     else if (r1 != r2 && r2 != r3 && r3 == r4 && r4 == r5)
  66.         ret = THREEOFKIND;
  67.  
  68.     // TWOPAIRS - aabbc aabcc abbcc
  69.  
  70.     else if (r1 == r2 && r2 != r3 && r3 == r4 && r4 != r5)
  71.         ret = TWOPAIRS;
  72.  
  73.     else if (r1 == r2 && r2 != r3 && r3 != r4 && r4 == r5)
  74.         ret = TWOPAIRS;
  75.  
  76.     else if (r1 != r2 && r2 == r3 && r3 != r4 && r4 == r5)
  77.         ret = TWOPAIRS;
  78.  
  79.     // ONEPAIR - aabcd abbcd abccd abcdd
  80.  
  81.     else if (r1 == r2 && r2 != r3 && r3 != r4 && r4 != r5)
  82.         ret = ONEPAIR;
  83.  
  84.     else if (r1 != r2 && r2 == r3 && r3 != r4 && r4 != r5)
  85.         ret = ONEPAIR;
  86.  
  87.     else if (r1 != r2 && r2 != r3 && r3 == r4 && r4 != r5)
  88.         ret = ONEPAIR;
  89.  
  90.     else if (r1 != r2 && r2 != r3 && r3 != r4 && r4 == r5)
  91.         ret = ONEPAIR;
  92.  
  93.     list_free(cards);
  94.  
  95.     return ret;
  96. }

evaluate returns the value of self.

  1. void defclassHand() {
  2.     property _i_properties[] = {
  3.         "cards",
  4.         0, 0
  5.     };
  6.     selector _i_messages[] = {
  7.         "init",             METHOD(i_init),
  8.         "free",             METHOD(i_free),
  9.         "copy",             METHOD(i_copy),
  10.         "reorder",          METHOD(i_reorder),
  11.         "reset",            METHOD(i_reset),
  12.         "card",             METHOD(i_card),
  13.         "setCard",          METHOD(i_setCard),
  14.         "evaluate",         METHOD(i_evaluate),
  15.         "toString",         METHOD(i_toString),
  16.         0, 0
  17.     };
  18.  
  19.     Hand = defclass("Hand", 0, 1, 0, _i_properties, 0, _i_messages);
  20. }

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
SEE ALSO

Card, Deck

Comments

Your comment:
[p] [b] [i] [u] [s] [quote] [pre] [br] [code] [url] [email] strip help 2000

Enter a maximum of 2000 characters.
Improve the presentation of your text with the following formatting tags:
[p]paragraph[/p], [b]bold[/b], [i]italics[/i], [u]underline[/u], [s]strike[/s], [quote]citation[/quote], [pre]as is[/pre], [br]line break,
[url]http://www.izend.org[/url], [url=http://www.izend.org]site[/url], [email]izend@izend.org[/email], [email=izend@izend.org]izend[/email],
[code]command[/code], [code=language]source code in c, java, php, html, javascript, xml, css, sql, bash, dos, make, etc.[/code].