hanafuda/dialog.c
2025-02-26 20:16:04 -05:00

298 lines
11 KiB
C

// Copyright 2025 Bill Rossi
//
// This file is part of Hanafuda Hachi-Hachi.
//
// Hanafuda Hachi-Hachi is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
//
// Hanafuda Hachi-Hachi is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along with Hanafuda Hachi-Hachi. If not, see <https://www.gnu.org/licenses/>.
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <raylib.h>
#include "dialog.h"
Dialog dialogs[8];
void handle_click_cancel_yes(Game *g) {
g->player.dekiyaku_action = DEKIYAKU_ACTION_CANCEL;
g->state = GAME_STATE_CALCULATING_DEKIYAKU_SCORE;
}
void handle_click_cancel_no(Game *g) {
g->state = GAME_STATE_CHOOSING_FROM_HAND;
}
void handle_click_shoubu(Game *g) {
g->player.dekiyaku_action = DEKIYAKU_ACTION_SHOUBU;
g->state = GAME_STATE_CALCULATING_DEKIYAKU_SCORE;
}
void handle_click_sage(Game *g) {
if (!g->first_sage) g->first_sage = &g->player;
g->player.dekiyaku_action = DEKIYAKU_ACTION_SAGE;
g->turn_number++;
g->state = GAME_STATE_CHOOSING_FROM_HAND;
}
void handle_click_ok_end_of_round(Game *g) {
g->state = GAME_STATE_END_OF_ROUND;
}
void handle_click_ok_end_of_game(Game *g) {
g->state = GAME_STATE_TITLE_SCREEN;
}
void handle_click_play_again(Game *g) {
g->state = GAME_STATE_NEW_GAME;
}
void handle_click_quit(Game *g) {
g->should_close = true;
}
void handle_click_claim_set_teyaku(Game *g) {
g->player.teyaku.chaff = CHAFF_TEYAKU_NONE;
teyaku_to_string(&g->player.teyaku, g->player.teyaku_string);
g->state = GAME_STATE_START_OF_TURN;
}
void handle_click_claim_chaff_teyaku(Game *g) {
g->player.teyaku.set = SET_TEYAKU_NONE;
teyaku_to_string(&g->player.teyaku, g->player.teyaku_string);
g->state = GAME_STATE_START_OF_TURN;
}
void handle_click_claim_both_teyaku(Game *g) {
g->state = GAME_STATE_START_OF_TURN;
}
void handle_click_dont_claim_teyaku(Game *g) {
(&g->player.teyaku)->chaff = CHAFF_TEYAKU_NONE;
g->player.teyaku.set = SET_TEYAKU_NONE;
teyaku_to_string(&g->player.teyaku, g->player.teyaku_string);
g->state = GAME_STATE_START_OF_TURN;
}
void handle_click_no_action(Game *g) {
}
void init_dialogs(Game *g) {
Dialog *cancel_dialog = &dialogs[0];
cancel_dialog->text_count = 1;
cancel_dialog->text[0] = malloc(200);
strcpy(cancel_dialog->text[0], "Would you like to cancel?");
cancel_dialog->text_size = 60;
cancel_dialog->options_count = 2;
cancel_dialog->game = g;
cancel_dialog->options[0].text = malloc(50);
strcpy(cancel_dialog->options[0].text, "Yes");
cancel_dialog->options[0].color = GREEN;
cancel_dialog->options[0].handle = &handle_click_cancel_yes;
cancel_dialog->options[1].text = malloc(50);
strcpy(cancel_dialog->options[1].text, "No");
cancel_dialog->options[1].color = RED;
cancel_dialog->options[1].handle = &handle_click_cancel_no;
Dialog *shoubu_dialog = &dialogs[1];
shoubu_dialog->text_count = 2;
shoubu_dialog->text[0] = malloc(200);
shoubu_dialog->text[1] = malloc(200);
strcpy(shoubu_dialog->text[0], "You have dekiyaku!");
strcpy(shoubu_dialog->text[1], "Sage or shoubu?");
shoubu_dialog->text_size = 60;
shoubu_dialog->options_count = 2;
shoubu_dialog->game = g;
shoubu_dialog->options[0].text = malloc(50);
strcpy(shoubu_dialog->options[0].text, "Sage");
shoubu_dialog->options[0].color = GREEN;
shoubu_dialog->options[0].handle = &handle_click_sage;
shoubu_dialog->options[1].text = malloc(50);
strcpy(shoubu_dialog->options[1].text, "Shoubu");
shoubu_dialog->options[1].color = RED;
shoubu_dialog->options[1].handle = &handle_click_shoubu;
Dialog *no_dekiyaku_end_of_round_dialog = &dialogs[2];
no_dekiyaku_end_of_round_dialog->text_count = 3;
no_dekiyaku_end_of_round_dialog->text[0] = malloc(200);
no_dekiyaku_end_of_round_dialog->text[1] = malloc(200);
no_dekiyaku_end_of_round_dialog->text[2] = malloc(200);
strcpy(no_dekiyaku_end_of_round_dialog->text[0], "Player score");
strcpy(no_dekiyaku_end_of_round_dialog->text[1], "Right score");
strcpy(no_dekiyaku_end_of_round_dialog->text[2], "Left score");
no_dekiyaku_end_of_round_dialog->text_size = 40;
no_dekiyaku_end_of_round_dialog->options_count = 1;
no_dekiyaku_end_of_round_dialog->game = g;
no_dekiyaku_end_of_round_dialog->options[0].text = malloc(50);
strcpy(no_dekiyaku_end_of_round_dialog->options[0].text, "Okay");
no_dekiyaku_end_of_round_dialog->options[0].color = GREEN;
no_dekiyaku_end_of_round_dialog->options[0].handle = &handle_click_ok_end_of_round;
Dialog *end_of_game_dialog = &dialogs[3];
end_of_game_dialog->text_count = 4;
end_of_game_dialog->text[0] = malloc(200);
end_of_game_dialog->text[1] = malloc(200);
end_of_game_dialog->text[2] = malloc(200);
end_of_game_dialog->text[3] = malloc(200);
end_of_game_dialog->text_size = 30;
end_of_game_dialog->options_count = 2;
end_of_game_dialog->game = g;
end_of_game_dialog->options[0].text = malloc(50);
strcpy(end_of_game_dialog->options[0].text, "Play Again");
end_of_game_dialog->options[0].color = GREEN;
end_of_game_dialog->options[0].handle = &handle_click_play_again;
end_of_game_dialog->options[1].text = malloc(50);
strcpy(end_of_game_dialog->options[1].text, "Quit");
end_of_game_dialog->options[1].color = GREEN;
end_of_game_dialog->options[1].handle = &handle_click_quit;
Dialog *dekiyaku_end_of_round_dialog = &dialogs[4];
dekiyaku_end_of_round_dialog->text_count = 4;
dekiyaku_end_of_round_dialog->text[0] = malloc(200);
dekiyaku_end_of_round_dialog->text[1] = malloc(200);
dekiyaku_end_of_round_dialog->text[2] = malloc(200);
dekiyaku_end_of_round_dialog->text[3] = malloc(200);
strcpy(dekiyaku_end_of_round_dialog->text[0], "Player score");
strcpy(dekiyaku_end_of_round_dialog->text[1], "Right score");
strcpy(dekiyaku_end_of_round_dialog->text[2], "Left score");
strcpy(dekiyaku_end_of_round_dialog->text[3], "");
dekiyaku_end_of_round_dialog->text_size = 50;
dekiyaku_end_of_round_dialog->options_count = 1;
dekiyaku_end_of_round_dialog->game = g;
dekiyaku_end_of_round_dialog->options[0].text = malloc(50);
strcpy(dekiyaku_end_of_round_dialog->options[0].text, "Okay");
dekiyaku_end_of_round_dialog->options[0].color = GREEN;
dekiyaku_end_of_round_dialog->options[0].handle = &handle_click_ok_end_of_round;
Dialog *teyaku_dialog = &dialogs[5];
teyaku_dialog->text_count = 4;
teyaku_dialog->text[0] = malloc(200);
teyaku_dialog->text[1] = malloc(200);
teyaku_dialog->text[2] = malloc(200);
teyaku_dialog->text[3] = malloc(200);
strcpy(teyaku_dialog->text[0], "You can claim some teyaku");
strcpy(teyaku_dialog->text[3], "(There is no reason not to claim both)");
teyaku_dialog->text_size = 40;
teyaku_dialog->options_count = 4;
teyaku_dialog->game = g;
teyaku_dialog->options[0].text = malloc(50);
strcpy(teyaku_dialog->options[0].text, "Claim Set Teyaku");
teyaku_dialog->options[0].color = SKYBLUE;
teyaku_dialog->options[0].handle = &handle_click_claim_set_teyaku;
teyaku_dialog->options[1].text = malloc(50);
strcpy(teyaku_dialog->options[1].text, "Claim Chaff Teyaku");
teyaku_dialog->options[1].color = SKYBLUE;
teyaku_dialog->options[1].handle = &handle_click_claim_chaff_teyaku;
teyaku_dialog->options[2].text = malloc(50);
strcpy(teyaku_dialog->options[2].text, "Claim Both Teyaku");
teyaku_dialog->options[2].color = GREEN;
teyaku_dialog->options[2].handle = &handle_click_claim_both_teyaku;
teyaku_dialog->options[3].text = malloc(50);
strcpy(teyaku_dialog->options[3].text, "Don't Claim");
teyaku_dialog->options[3].color = RED;
teyaku_dialog->options[3].handle = &handle_click_dont_claim_teyaku;
Dialog *end_of_round_dialog = &dialogs[6];
end_of_round_dialog->text_count = 3;
end_of_round_dialog->text[0] = malloc(200);
end_of_round_dialog->text[1] = malloc(200);
end_of_round_dialog->text[2] = malloc(200);
end_of_round_dialog->text_size = 40;
end_of_round_dialog->options_count = 1;
end_of_round_dialog->game = g;
end_of_round_dialog->options[0].text = "Okay";
end_of_round_dialog->options[0].color = GREEN;
end_of_round_dialog->options[0].handle = &handle_click_no_action;
}
void cancel_dialog(Game *g) { g->dialog = &dialogs[0]; }
void shoubu_dialog(Game *g) { g->dialog = &dialogs[1]; }
void no_dekiyaku_end_of_round_dialog(Game *g) { g->dialog = &dialogs[2]; }
void end_of_game_dialog(Game *g) { g->dialog = &dialogs[3]; }
void dekiyaku_end_of_round_dialog(Game *g) { g->dialog = &dialogs[4]; }
void teyaku_dialog(Game *g) { g->dialog = &dialogs[5]; }
void end_of_round_dialog(Game *g) { g->dialog = &dialogs[6]; }
Rectangle dialog_option_outer_rectangle(Dialog *d, int i) {
if (d->options_count < 4) {
return (Rectangle) {
((960 * (i + 1)) / (d->options_count + 1)) - 10 + 200,
500,
MeasureText(d->options[i].text, DIALOG_OPTION_FONT_SIZE) + 20,
40,
};
} else {
return (Rectangle) {
((960 * (i % 2)) / ((d->options_count / 2) + 1)) - 10 + 250,
500 + ((i / 2) * 50),
MeasureText(d->options[i].text, DIALOG_OPTION_FONT_SIZE) + 20,
40,
};
}
}
Rectangle dialog_option_inner_rectangle(Dialog *d, int i) {
Rectangle outer = dialog_option_outer_rectangle(d, i);
return (Rectangle) {
outer.x + 3,
outer.y + 3,
outer.width - 6,
outer.height - 6,
};
}
void dialog_draw(Dialog *d) {
Vector2 mouse_pos = GetMousePosition();
DrawText("Hide Dialog", 1225, 870, 20, BLACK);
if (mouse_pos.x > 1225 && mouse_pos.y > 850) return;
int text_width;
DrawRectangleRec(DIALOG_OUTER_RECTANGLE, BLACK);
DrawRectangleRec(DIALOG_INNER_RECTANGLE, WHITE);
for (int i = 0; i < d->text_count; i++) {
text_width = MeasureText(d->text[i], d->text_size);
DrawText(d->text[i], 700 - (text_width / 2), 300 + (70 * (i - 1)), d->text_size, BLACK);
}
for (int i = 0; i < d->options_count; i++) {
DialogOption *o = &d->options[i];
Rectangle outer = dialog_option_outer_rectangle(d, i);
Rectangle inner = dialog_option_inner_rectangle(d, i);
DrawRectangleRec(outer, BLACK);
DrawRectangleRec(inner, o->color);
DrawText(o->text, inner.x + 3, inner.y + 3, DIALOG_OPTION_FONT_SIZE, BLACK);
}
}
void dialog_handle_input(Dialog *d) {
Vector2 mouse_pos = GetMousePosition();
if (IsMouseButtonPressed(0)) {
for (int i = 0; i < d->options_count; i++) {
DialogOption *o = &d->options[i];
Rectangle outer = dialog_option_outer_rectangle(d, i);
if (CheckCollisionPointRec(mouse_pos, outer)) {
o->handle(d->game);
d->game->dialog = NULL;
break;
}
}
}
}