hanafuda/teyaku.c

96 lines
3.3 KiB
C

#include <stdio.h>
#include "teyaku.h"
#include "card.h"
SetTeyaku calculate_set_teyaku(const Hand h) {
int month_counts[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
int month_stands[12] = { 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1 };
for (int i = 0; i < h.count; i++) {
Card c = h.cards[i];
month_counts[c.month]++;
}
int triplets = 0, standing_triplets = 0, pairs = 0, four_of_a_kind = 0;
for (int i = 0; i < 12; i++) {
if (month_counts[i] == 4) {
four_of_a_kind++;
} else if (month_counts[i] == 3) {
if (month_stands[i]) standing_triplets++; // TODO Pawlonia is weird
else triplets++;
} else if (month_counts[i] == 2) {
pairs++;
}
}
int total_triplets = triplets + standing_triplets;
if (four_of_a_kind && total_triplets) return FOUR_THREE;
else if (four_of_a_kind && pairs) return ONE_TWO_FOUR;
else if (standing_triplets == 2) return TWO_STANDING_TRIPLETS;
else if (total_triplets && pairs == 2) return TRIPLET_AND_TWO_PAIRS;
else if (triplets == 1 && standing_triplets == 1) return TRIPLET_AND_STANDING_TRIPLET;
else if (four_of_a_kind) return FOUR_OF_A_KIND;
else if (triplets == 2) return TWO_TRIPLETS;
else if (pairs == 3) return THREE_PAIRS;
else if (standing_triplets) return STANDING_TRIPLET;
else if (triplets) return TRIPLET;
return SET_TEYAKU_NONE;
}
ChaffTeyaku calculate_chaff_teyaku(const Hand h) {
int ribbons = 0;
int animals = 0;
int brights = 0;
int chaff = 0;
for (int i = 0; i < h.count; i++) {
Card c = h.cards[i];
if (c.month == NOVEMBER) chaff++; // November cards are all counted as chaff here
else if (c.type == BRIGHT) brights++;
else if (c.type == RIBBON) ribbons++;
else if (c.type == ANIMAL) animals++;
else chaff++;
}
if (chaff == 7) return EMPTY_HAND;
else if (chaff == 6 && brights == 1) return ONE_BRIGHT;
else if (chaff == 6 && animals == 1) return ONE_ANIMAL;
else if (chaff == 6 && ribbons == 1) return ONE_RIBBON;
else if (ribbons >= 2 && chaff == 7 - ribbons) return CHAFF_TEYAKU_RED;
return CHAFF_TEYAKU_NONE;
}
static int set_teyaku_points_array[11] = { 0, 2, 3, 6, 7, 8, 4, 6, 7, 8, 20 };
static char *set_teyaku_english_array[11] = { "None", "Triplet", "Standing Triplet", "Two Triplets", "Triplet and Standing Triplet", "Two Standing Triplets", "Three Pairs", "Four of a Kind", "Triplet and Two Pairs", "One-Two-Four", "Four-Three" };
static int chaff_teyaku_points_array[6] = { 0, 2, 3, 3, 4, 4 };
static char *chaff_teyaku_english_array[6] = { "None", "Red", "One Ribbon", "One Animal", "One Bright", "Empty Hand" };
int set_teyaku_points(SetTeyaku st) {
return set_teyaku_points_array[st];
}
int chaff_teyaku_points(ChaffTeyaku ct) {
return chaff_teyaku_points_array[ct];
}
char *set_teyaku_english(SetTeyaku st) {
return set_teyaku_english_array[st];
}
char *chaff_teyaku_english(ChaffTeyaku ct) {
return chaff_teyaku_english_array[ct];
}
void calculate_teyaku(const Hand h, Teyaku *t) {
t->chaff = calculate_chaff_teyaku(h);
t->set = calculate_set_teyaku(h);
}
void teyaku_to_string(Teyaku *t, char *str) {
int set_points = set_teyaku_points(t->set);
int chaff_points = chaff_teyaku_points(t->chaff);
sprintf(str, "Set: %s(%d) / Chaff: %s(%d) / Total: %d", set_teyaku_english(t->set), set_points, chaff_teyaku_english(t->chaff), chaff_points, set_points + chaff_points);
}