From 4dd45c42e8977dfdc6755eef79b817fa4327e034 Mon Sep 17 00:00:00 2001
From: Bill Rossi <bassguitarbill@gmail.com>
Date: Sat, 1 Feb 2025 11:05:46 -0500
Subject: [PATCH] Dekiyaku

---
 card.h     |   2 +-
 dekiyaku.c | 110 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 dekiyaku.h |  30 +++++++++++++++
 main.c     |  21 +++++++---
 4 files changed, 157 insertions(+), 6 deletions(-)
 create mode 100644 dekiyaku.c
 create mode 100644 dekiyaku.h

diff --git a/card.h b/card.h
index 4a59314..86cb1ad 100644
--- a/card.h
+++ b/card.h
@@ -52,7 +52,7 @@ struct Card {
 };
 
 struct Hand {
-  Card cards[7];
+  Card cards[48];
   int count;
 };
 
diff --git a/dekiyaku.c b/dekiyaku.c
new file mode 100644
index 0000000..7c44241
--- /dev/null
+++ b/dekiyaku.c
@@ -0,0 +1,110 @@
+#include "dekiyaku.h"
+
+void calculate_dekiyaku(const Hand h, Dekiyaku *d) {
+  int brights = 0, ribbons = 0, ribbons_except_november = 0, blue_ribbons = 0, poetry_ribbons = 0, boar = 0, deer = 0, butterflies = 0;
+  for (int i = 0; i < h.count; i++) {
+    const Card card = h.cards[i];
+    switch (card.type) {
+    case BRIGHT: brights++; break;
+    case RIBBON:
+      ribbons++;
+      if (card.month != NOVEMBER) ribbons_except_november++;
+      switch (card.ribbon_type) {
+      case RIBBON_BLUE: blue_ribbons++; break;
+      case RIBBON_POETRY: poetry_ribbons++; break;
+      }
+      break;
+    case ANIMAL:
+      switch (card.month) {
+      case JUNE: butterflies++; break;
+      case JULY: boar++; break;
+      case OCTOBER: deer++; break;
+      }
+      break;
+    case CHAFF:
+      break;
+    }
+  }
+
+  d->count = 0;
+
+  if (brights == 5) {
+    d->meld[d->count].type = FIVE_BRIGHTS;
+    d->meld[d->count].value = 12;
+    d->count++;
+  }
+
+  if (brights == 4) {
+    d->meld[d->count].type = FOUR_BRIGHTS;
+    d->meld[d->count].value = 10;
+    d->count++;
+  }
+
+  if (ribbons_except_november >= 7) {
+    d->meld[d->count].type = SEVEN_RIBBONS;
+    d->meld[d->count].value = 3 + ribbons; // Include november ribbons in this count
+    d->count++;
+  }
+
+  if (poetry_ribbons == 3) {
+    d->meld[d->count].type = POETRY_RIBBONS;
+    d->meld[d->count].value = 7;
+    d->count++;
+  }
+
+  if (blue_ribbons == 3) {
+    d->meld[d->count].type = BLUE_RIBBONS;
+    d->meld[d->count].value = 7;
+    d->count++;
+  }
+
+  if (boar == 1 && deer == 1 && butterflies == 1) {
+    d->meld[d->count].type = BOAR_DEER_BUTTERFLIES;
+    d->meld[d->count].value = 7;
+    d->count++;
+  }
+}
+
+char *meld_name(DekiyakuMeldType d) {
+  switch (d) {
+  case NONE:
+    return "None";
+  case FIVE_BRIGHTS:
+    return "5B";
+  case FOUR_BRIGHTS:
+    return "4B";
+  case SEVEN_RIBBONS:
+    return "7R";
+  case POETRY_RIBBONS:
+    return "PS";
+  case BLUE_RIBBONS:
+    return "BS";
+  case BOAR_DEER_BUTTERFLIES:
+    return "ISK";
+  }
+}
+
+int dekiyaku_value(Dekiyaku *d) {
+  int value = 0;
+  for (int i = 0; i < d->count; i++) {
+    value += d->meld[i].value;
+  }
+  return value;
+}
+
+void dekiyaku_to_string(Dekiyaku *d, char *str) {
+  char meld_str[200];
+
+  strcpy(str, "Dekiyaku: ");
+  for (int i = 0; i < d->count; i++) {
+    sprintf(meld_str, "%s (%d) + ", meld_name(d->meld[i].type), d->meld[i].value);
+    strcat(str, meld_str);
+  }
+
+  if (d->count == 0) strcat(str, "none (0)");
+  else {
+    str[strlen(str) - 2] = '=';
+    sprintf(meld_str, "%d", dekiyaku_value(d));
+    strcat(str, meld_str);
+  }
+}
diff --git a/dekiyaku.h b/dekiyaku.h
new file mode 100644
index 0000000..bfd0fa7
--- /dev/null
+++ b/dekiyaku.h
@@ -0,0 +1,30 @@
+#ifndef _HF_DEKIYAKU_
+#define _HF_DEKIYAKU_
+
+#include "card.h"
+
+typedef enum DekiyakuMeldType {
+  NONE,
+  FIVE_BRIGHTS,
+  FOUR_BRIGHTS,
+  SEVEN_RIBBONS,
+  POETRY_RIBBONS,
+  BLUE_RIBBONS,
+  BOAR_DEER_BUTTERFLIES,
+} DekiyakuMeldType;
+
+typedef struct DekiyakuMeld {
+  DekiyakuMeldType type;
+  int value;
+} DekiyakuMeld;
+
+typedef struct Dekiyaku {
+  DekiyakuMeld meld[5];
+  int count;
+} Dekiyaku;
+
+void calculate_dekiyaku(const Hand h, Dekiyaku *d);
+char *meld_name(DekiyakuMeldType d);
+void dekiyaku_to_string(Dekiyaku *d, char *str);
+
+#endif
diff --git a/main.c b/main.c
index b87907a..81af2e7 100644
--- a/main.c
+++ b/main.c
@@ -8,6 +8,7 @@
 #include "card.h"
 #include "move.h"
 #include "teyaku.h"
+#include "dekiyaku.h"
 
 char *text = "こんにちわ、 世界!";
 
@@ -70,7 +71,8 @@ int main(int argc, char** argv) {
 
     float delta;
     Vector2 mouse_position;
-    char *calculation = "";
+    char *teyaku_calculation = "";
+    char dekiyaku_calculation[400];
 
     while (!WindowShouldClose()) {
       delta = GetFrameTime();
@@ -80,7 +82,7 @@ int main(int argc, char** argv) {
 	for (int i = 0; i < 48; i++) {
 	  if (point_within_card(&cards[i], mouse_pos)) {
 	    cards[i].selected = !cards[i].selected;
-	    calculation = "";
+	    teyaku_calculation = "";
 	    break;
 	  }
 	}
@@ -94,17 +96,26 @@ int main(int argc, char** argv) {
 	draw_card(&cards[i]);
       }
 
-      if (strlen(calculation) == 0 && num_selected == 7) {
+      if (strlen(teyaku_calculation) == 0) {
 	Hand h;
 	h.count = 0;
 	for (int i = 0; i < 48; i++) {
 	  if (cards[i].selected) memcpy(&h.cards[h.count++], &cards[i], sizeof(Card));
 	}
 
-	calculation = TextFormat("Set: %s(%d) / Chaff: %s(%d) / Total: %d", set_teyaku_english(h), set_teyaku_points(h), chaff_teyaku_english(h), chaff_teyaku_points(h), calculate_teyaku(h));
+	if (num_selected == 7) {
+	  teyaku_calculation = TextFormat("Set: %s(%d) / Chaff: %s(%d) / Total: %d", set_teyaku_english(h), set_teyaku_points(h), chaff_teyaku_english(h), chaff_teyaku_points(h), calculate_teyaku(h));
+	} else {
+	  teyaku_calculation = "";
+	}
+
+	Dekiyaku d;
+	calculate_dekiyaku(h, &d);
+	dekiyaku_to_string(&d, dekiyaku_calculation);
       }
 
-      DrawText(calculation, 10, 500, 25, BLACK);
+      DrawText(teyaku_calculation, 10, 450, 25, BLACK);
+      DrawText(dekiyaku_calculation, 10, 500, 25, BLACK);
       EndDrawing();
     }