Compare commits
7 Commits
3b6d384506
...
a40067ff8f
Author | SHA1 | Date | |
---|---|---|---|
a40067ff8f | |||
7b4847e165 | |||
ed32f6262d | |||
6375f1ec6f | |||
58859768f0 | |||
6fb770a0b8 | |||
65f36ae820 |
30
card.c
Normal file
30
card.c
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#include "card.h"
|
||||||
|
|
||||||
|
void draw_card(Card *c) {
|
||||||
|
DrawRectangleV(c->position, card_size, c->selected ? RED : BLACK);
|
||||||
|
DrawRectangle(c->position.x + CARD_BORDER, c->position.y + CARD_BORDER, card_size.x - (CARD_BORDER * 2), card_size.y - (CARD_BORDER * 2) , WHITE);
|
||||||
|
DrawText(month_english_abbr[c->month], c->position.x + CARD_BORDER + 2, c->position.y + CARD_BORDER + 2, 14, BLACK);
|
||||||
|
switch (c->type) {
|
||||||
|
case CHAFF:
|
||||||
|
break;
|
||||||
|
case RIBBON:
|
||||||
|
Color ribbon_color = RED;
|
||||||
|
if (c->ribbon_type == RIBBON_BLUE) ribbon_color = BLUE;
|
||||||
|
DrawRectangle(c->position.x + 26, c->position.y + 35, 10, 45 , ribbon_color);
|
||||||
|
if (c->ribbon_type == RIBBON_POETRY) {
|
||||||
|
DrawRectangle(c->position.x + 29, c->position.y + 38, 4, 39 , BLACK);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ANIMAL:
|
||||||
|
DrawRectangle(c->position.x + 10, c->position.y + 45, 40, 25 , BLACK);
|
||||||
|
break;
|
||||||
|
case BRIGHT:
|
||||||
|
DrawCircle(c->position.x + 31, c->position.y + 65, 25 , YELLOW);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool point_within_card(Card *c, Vector2 point) {
|
||||||
|
return point.x > c->position.x && point.x < c->position.x + card_size.x &&
|
||||||
|
point.y > c->position.y && point.y < c->position.y + card_size.y;
|
||||||
|
}
|
61
card.h
Normal file
61
card.h
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
#ifndef _HF_CARD_
|
||||||
|
#define _HF_CARD_
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <raylib.h>
|
||||||
|
|
||||||
|
typedef struct Card Card;
|
||||||
|
typedef struct Hand Hand;
|
||||||
|
#define CARD_WIDTH 63
|
||||||
|
#define CARD_HEIGHT 105
|
||||||
|
#define CARD_BORDER 5
|
||||||
|
static Vector2 card_size = (Vector2) { CARD_WIDTH, CARD_HEIGHT };
|
||||||
|
|
||||||
|
typedef enum CardType {
|
||||||
|
CHAFF,
|
||||||
|
RIBBON,
|
||||||
|
ANIMAL,
|
||||||
|
BRIGHT,
|
||||||
|
} CardType;
|
||||||
|
|
||||||
|
typedef enum RibbonType {
|
||||||
|
RIBBON_NONE,
|
||||||
|
RIBBON_PLAIN,
|
||||||
|
RIBBON_BLUE,
|
||||||
|
RIBBON_POETRY,
|
||||||
|
} RibbonType;
|
||||||
|
|
||||||
|
typedef enum Month {
|
||||||
|
JANUARY,
|
||||||
|
FEBRUARY,
|
||||||
|
MARCH,
|
||||||
|
APRIL,
|
||||||
|
MAY,
|
||||||
|
JUNE,
|
||||||
|
JULY,
|
||||||
|
AUGUST,
|
||||||
|
SEPTEMBER,
|
||||||
|
OCTOBER,
|
||||||
|
NOVEMBER,
|
||||||
|
DECEMBER
|
||||||
|
} Month;
|
||||||
|
|
||||||
|
static char *month_english_abbr[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
|
||||||
|
|
||||||
|
struct Card {
|
||||||
|
int index;
|
||||||
|
CardType type;
|
||||||
|
RibbonType ribbon_type;
|
||||||
|
Month month;
|
||||||
|
Vector2 position;
|
||||||
|
bool selected;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Hand {
|
||||||
|
Card cards[7];
|
||||||
|
int count;
|
||||||
|
};
|
||||||
|
|
||||||
|
void draw_card(Card *c);
|
||||||
|
|
||||||
|
#endif
|
102
main.c
102
main.c
@ -5,27 +5,103 @@
|
|||||||
|
|
||||||
#include <raylib.h>
|
#include <raylib.h>
|
||||||
|
|
||||||
|
#include "card.h"
|
||||||
|
#include "move.h"
|
||||||
|
#include "teyaku.h"
|
||||||
|
|
||||||
char *text = "こんにちわ、 世界!";
|
char *text = "こんにちわ、 世界!";
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
InitWindow(800, 450, "Hanafuda Hachi-Hachi");
|
InitWindow(800, 550, "Hanafuda Hachi-Hachi");
|
||||||
SetTargetFPS(60);
|
SetTargetFPS(60);
|
||||||
|
|
||||||
int codepoints_count;
|
/*
|
||||||
int *codepoints = LoadCodepoints(text, &codepoints_count);
|
Hand h;
|
||||||
Font font = LoadFontEx("font/DotGothic16/DotGothic16-Regular.ttf", 48, codepoints, codepoints_count);
|
h.cards[0] = (Card) { 1, BRIGHT, RIBBON_NONE, NOVEMBER, (Vector2) { 0, 0 } };
|
||||||
|
h.cards[1] = (Card) { 1, ANIMAL, RIBBON_NONE, NOVEMBER, (Vector2) { 0, 0 } };
|
||||||
|
h.cards[2] = (Card) { 1, RIBBON, RIBBON_PLAIN, NOVEMBER, (Vector2) { 0, 0 } };
|
||||||
|
h.cards[3] = (Card) { 1, CHAFF, RIBBON_NONE, NOVEMBER, (Vector2) { 0, 0 } };
|
||||||
|
h.cards[4] = (Card) { 1, CHAFF, RIBBON_NONE, DECEMBER, (Vector2) { 0, 0 } };
|
||||||
|
h.cards[5] = (Card) { 1, CHAFF, RIBBON_NONE, DECEMBER, (Vector2) { 0, 0 } };
|
||||||
|
h.cards[6] = (Card) { 1, CHAFF, RIBBON_NONE, DECEMBER, (Vector2) { 0, 0 } };
|
||||||
|
h.count = 7;
|
||||||
|
|
||||||
|
printf("Teyaku: %d\n", calculate_teyaku(h));
|
||||||
|
*/
|
||||||
|
|
||||||
|
Card cards[48];
|
||||||
|
for (int i = 0; i < 48; i++) {
|
||||||
|
CardType t = CHAFF;
|
||||||
|
RibbonType rt = RIBBON_NONE;
|
||||||
|
Month month = i / 4;
|
||||||
|
switch (i) {
|
||||||
|
case 0:
|
||||||
|
case 8:
|
||||||
|
case 28:
|
||||||
|
case 40:
|
||||||
|
case 44:
|
||||||
|
t = BRIGHT; break;
|
||||||
|
case 1:
|
||||||
|
case 5:
|
||||||
|
case 9:
|
||||||
|
t = RIBBON; rt = RIBBON_POETRY; break;
|
||||||
|
case 21:
|
||||||
|
case 33:
|
||||||
|
case 37:
|
||||||
|
t = RIBBON; rt = RIBBON_BLUE; break;
|
||||||
|
case 13:
|
||||||
|
case 17:
|
||||||
|
case 25:
|
||||||
|
case 42:
|
||||||
|
t = RIBBON; rt = RIBBON_PLAIN; break;
|
||||||
|
case 4:
|
||||||
|
case 12:
|
||||||
|
case 16:
|
||||||
|
case 20:
|
||||||
|
case 24:
|
||||||
|
case 29:
|
||||||
|
case 32:
|
||||||
|
case 36:
|
||||||
|
case 41:
|
||||||
|
t = ANIMAL; break;
|
||||||
|
}
|
||||||
|
cards[i] = (Card) { i, t, rt, month, (Vector2) { month * 65, (i % 4) * 110 }, false };
|
||||||
|
}
|
||||||
|
|
||||||
|
float delta;
|
||||||
|
Vector2 mouse_position;
|
||||||
|
|
||||||
while (!WindowShouldClose()) {
|
while (!WindowShouldClose()) {
|
||||||
|
delta = GetFrameTime();
|
||||||
|
|
||||||
|
if (IsMouseButtonPressed(0)) {
|
||||||
|
Vector2 mouse_pos = GetMousePosition();
|
||||||
|
for (int i = 0; i < 48; i++) {
|
||||||
|
if (point_within_card(&cards[i], mouse_pos)) {
|
||||||
|
cards[i].selected = !cards[i].selected;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
BeginDrawing();
|
BeginDrawing();
|
||||||
ClearBackground(BLACK);
|
ClearBackground(RAYWHITE);
|
||||||
DrawTextEx(
|
int num_selected = 0;
|
||||||
font,
|
for (int i = 0; i < 48; i++) {
|
||||||
text,
|
num_selected += cards[i].selected;
|
||||||
(Vector2) { 200, 200 },
|
draw_card(&cards[i]);
|
||||||
48,
|
}
|
||||||
5.,
|
|
||||||
RAYWHITE
|
if (num_selected == 7) {
|
||||||
);
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
|
char *s = 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));
|
||||||
|
DrawText(s, 10, 500, 25, BLACK);
|
||||||
|
}
|
||||||
EndDrawing();
|
EndDrawing();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
23
move.c
Normal file
23
move.c
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#include <math.h>
|
||||||
|
#include "move.h"
|
||||||
|
|
||||||
|
Vector2 move_position(Move *m, float delta) {
|
||||||
|
m->current_time += delta;
|
||||||
|
float percentage = m->current_time / m->end_time;
|
||||||
|
if (percentage < 0.0) percentage = 0.0;
|
||||||
|
else if (percentage > 1.0) percentage = 1.0;
|
||||||
|
|
||||||
|
switch (m->curve) {
|
||||||
|
case CURVE_LINEAR:
|
||||||
|
return (Vector2) {
|
||||||
|
((m->destination.x - m->origin.x) * percentage) + m->origin.x,
|
||||||
|
((m->destination.y - m->origin.y) * percentage) + m->origin.y
|
||||||
|
};
|
||||||
|
case CURVE_EASE_IN_OUT:
|
||||||
|
percentage = -(cos(PI * percentage) - 1) / 2;
|
||||||
|
return (Vector2) {
|
||||||
|
((m->destination.x - m->origin.x) * percentage) + m->origin.x,
|
||||||
|
((m->destination.y - m->origin.y) * percentage) + m->origin.y
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
23
move.h
Normal file
23
move.h
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#ifndef _HF_MOVE_
|
||||||
|
#define _HF_MOVE_
|
||||||
|
|
||||||
|
#include <raylib.h>
|
||||||
|
|
||||||
|
typedef enum Curve {
|
||||||
|
CURVE_LINEAR,
|
||||||
|
CURVE_EASE_IN_OUT,
|
||||||
|
} Curve;
|
||||||
|
|
||||||
|
typedef struct Move Move;
|
||||||
|
|
||||||
|
struct Move {
|
||||||
|
Vector2 origin;
|
||||||
|
Vector2 destination;
|
||||||
|
Curve curve;
|
||||||
|
float current_time;
|
||||||
|
float end_time;
|
||||||
|
};
|
||||||
|
|
||||||
|
Vector2 move_position(Move *m, float delta);
|
||||||
|
|
||||||
|
#endif
|
88
teyaku.c
Normal file
88
teyaku.c
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "teyaku.h"
|
||||||
|
#include "card.h"
|
||||||
|
|
||||||
|
SetTeyaku calculate_set_teyaku(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(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(Hand h) {
|
||||||
|
return set_teyaku_points_array[calculate_set_teyaku(h)];
|
||||||
|
}
|
||||||
|
|
||||||
|
int chaff_teyaku_points(Hand h) {
|
||||||
|
return chaff_teyaku_points_array[calculate_chaff_teyaku(h)];
|
||||||
|
}
|
||||||
|
|
||||||
|
char *set_teyaku_english(Hand h) {
|
||||||
|
return set_teyaku_english_array[calculate_set_teyaku(h)];
|
||||||
|
}
|
||||||
|
|
||||||
|
char *chaff_teyaku_english(Hand h) {
|
||||||
|
return chaff_teyaku_english_array[calculate_chaff_teyaku(h)];
|
||||||
|
}
|
||||||
|
|
||||||
|
int calculate_teyaku(Hand h) {
|
||||||
|
return chaff_teyaku_points(h) + set_teyaku_points(h);
|
||||||
|
}
|
37
teyaku.h
Normal file
37
teyaku.h
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
#ifndef _HF_TEYAKU_
|
||||||
|
#define _HF_TEYAKU_
|
||||||
|
|
||||||
|
#include "card.h"
|
||||||
|
|
||||||
|
typedef enum SetTeyaku {
|
||||||
|
SET_TEYAKU_NONE = 0,
|
||||||
|
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,
|
||||||
|
} SetTeyaku;
|
||||||
|
|
||||||
|
typedef enum ChaffTeyaku {
|
||||||
|
CHAFF_TEYAKU_NONE = 0,
|
||||||
|
CHAFF_TEYAKU_RED,
|
||||||
|
ONE_RIBBON,
|
||||||
|
ONE_ANIMAL,
|
||||||
|
ONE_BRIGHT,
|
||||||
|
EMPTY_HAND,
|
||||||
|
} ChaffTeyaku;
|
||||||
|
|
||||||
|
int calculate_teyaku(Hand h);
|
||||||
|
SetTeyaku calculate_set_teyaku(Hand h);
|
||||||
|
ChaffTeyaku calculate_chaff_teyaku(Hand h);
|
||||||
|
char *set_teyaku_english(Hand h);
|
||||||
|
char *chaff_teyaku_english(Hand h);
|
||||||
|
int set_teyaku_points(Hand h);
|
||||||
|
int chaff_teyaku_points(Hand h);
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue
Block a user