Fumofumotris/source/fumotris/fumotris.c

177 lines
4 KiB
C
Raw Normal View History

2024-05-07 22:10:15 +00:00
#include "fumotris.h"
2024-05-15 05:44:13 +00:00
#include <stdlib.h>
2024-05-19 06:56:14 +00:00
#include <string.h>
2024-05-02 22:17:37 +00:00
2024-05-08 12:47:46 +00:00
struct Fumotris {
2024-05-15 22:10:47 +00:00
struct Terminal term;
struct TetraTemplate *bag[7];
usize bag_i;
2024-05-14 04:20:20 +00:00
struct Tetra board;
struct Tetra piece;
2024-05-15 05:44:13 +00:00
2024-05-14 04:20:20 +00:00
bool is_ground;
2024-05-15 05:44:13 +00:00
2024-05-15 22:10:47 +00:00
nsec last_moved;
nsec last_dropped;
};
2024-05-15 05:44:13 +00:00
2024-05-15 22:10:47 +00:00
void shuffle(struct Fumotris *fumo)
2024-05-15 05:44:13 +00:00
{
2024-05-15 22:10:47 +00:00
for (usize i = 6; i > 0; i--) {
2024-05-15 05:44:13 +00:00
usize swap = rand() % i;
2024-05-15 22:10:47 +00:00
struct TetraTemplate *tmp = fumo->bag[swap];
fumo->bag[swap] = fumo->bag[i];
fumo->bag[i] = tmp;
2024-05-15 05:44:13 +00:00
}
}
2024-05-19 06:56:14 +00:00
bool check_clear(struct Tetra *board, usize y)
2024-05-15 22:10:47 +00:00
{
2024-05-19 06:56:14 +00:00
for (usize x = 0; x < board->wid; x++) {
if (board->blks[board->wid * y + x] == 0)
return false;
}
return true;
}
void shift_down(struct Tetra *board, usize y)
{
memmove(board->blks + board->wid, board->blks, board->wid * y);
2024-05-15 22:10:47 +00:00
}
void place(struct Fumotris *fumo)
2024-05-15 05:44:13 +00:00
{
TetraOverlay(&fumo->piece, &fumo->board);
2024-05-19 06:56:14 +00:00
usize lines_cleared = 0;
2024-05-15 22:10:47 +00:00
for (usize y = fumo->piece.y; y < fumo->piece.y + fumo->piece.hgt; y++) {
2024-05-19 06:56:14 +00:00
if (check_clear(&fumo->board, y)) {
lines_cleared += 1;
shift_down(&fumo->board, y);
2024-05-15 22:10:47 +00:00
}
2024-05-15 05:44:13 +00:00
}
2024-05-15 22:10:47 +00:00
TetraSet(&fumo->piece, fumo->bag[fumo->bag_i++]);
if (fumo->bag_i == 7) {
shuffle(fumo);
fumo->bag_i = 0;
}
2024-05-15 05:44:13 +00:00
}
i16 get_horizontal(struct Controller *ctrl)
{
2024-05-15 22:10:47 +00:00
return (-(i16)ctrl->axes[LEFT].is_held) + ctrl->axes[RIGHT].is_held;
2024-05-15 05:44:13 +00:00
}
2024-05-15 22:10:47 +00:00
void FumotrisStart(struct Instance *inst, struct Fumotris *fumo)
2024-05-02 22:17:37 +00:00
{
2024-05-15 22:10:47 +00:00
ControllerBindMulti(&inst->ctrl, BINDS_N, CONTROLS, CODES, TYPES);
2024-05-15 05:44:13 +00:00
2024-05-19 06:56:14 +00:00
CreateTerminal(&fumo->term, 64, 26);
FILE *file;
file = fopen("fumo.txt", "r");
if (file) {
signed char ch;
usize x = 0;
usize y = 0;
while ((ch = getc(file)) != EOF) {
if (ch == '\n') {
x = 0;
y += 1;
continue;
}
fumo->term.buf[fumo->term.wid * y + x++] = (struct Char4) { .ch = ch, .color.fg = 15 };
}
fclose(file);
}
2024-05-15 05:44:13 +00:00
2024-05-15 22:10:47 +00:00
for (usize i = 0; i < 7; i++)
fumo->bag[i] = templates[i];
fumo->bag_i = 1;
2024-05-15 05:44:13 +00:00
2024-05-15 22:10:47 +00:00
CreateTetra(&fumo->board, 10, 20);
TetraSet(&fumo->piece, fumo->bag[0]);
2024-05-15 05:44:13 +00:00
2024-05-15 22:10:47 +00:00
fumo->is_ground = false;
fumo->last_moved = 0;
fumo->last_dropped = 0;
2024-05-07 22:10:15 +00:00
}
2024-05-07 03:29:10 +00:00
2024-05-15 22:10:47 +00:00
void FumotrisUpdate(struct Instance *inst, struct Fumotris *fumo)
2024-05-07 22:10:15 +00:00
{
2024-05-15 22:10:47 +00:00
i16 horizontal = get_horizontal(&inst->ctrl);
2024-05-14 04:20:20 +00:00
2024-05-15 22:10:47 +00:00
if (horizontal != 0 and fumo->last_moved < inst->time) {
2024-05-16 06:08:15 +00:00
fumo->last_moved = inst->time + 1e8;
2024-05-15 22:10:47 +00:00
TetraMove(&fumo->piece, &fumo->board, horizontal, 0);
}
if (inst->ctrl.axes[ROTATE_CCW].is_down)
TetraRotate(&fumo->piece, &fumo->board, 1);
if (inst->ctrl.axes[ROTATE_CW].is_down)
TetraRotate(&fumo->piece, &fumo->board, -1);
if (inst->ctrl.axes[SOFT_DROP].is_held and fumo->last_dropped < inst->time) {
2024-05-16 06:08:15 +00:00
fumo->last_dropped = inst->time + 1e8;
2024-05-14 04:20:20 +00:00
TetraMove(&fumo->piece, &fumo->board, 0, 1);
2024-05-15 05:44:13 +00:00
}
2024-05-14 04:20:20 +00:00
if (inst->ctrl.axes[HARD_DROP].is_down) {
while (TetraMove(&fumo->piece, &fumo->board, 0, 1));
2024-05-15 22:10:47 +00:00
place(fumo);
2024-05-14 04:20:20 +00:00
}
2024-05-15 05:44:13 +00:00
}
2024-05-14 04:20:20 +00:00
2024-05-15 22:10:47 +00:00
nsec FumotrisFall(struct Instance *inst, struct Fumotris *fumo)
2024-05-15 05:44:13 +00:00
{
if (!TetraMove(&fumo->piece, &fumo->board, 0, 1)) {
if (!fumo->is_ground)
fumo->is_ground = true;
else
2024-05-15 22:10:47 +00:00
place(fumo);
2024-05-14 04:20:20 +00:00
}
2024-05-15 22:10:47 +00:00
return 5e8;
2024-05-14 04:20:20 +00:00
}
2024-05-15 22:10:47 +00:00
void FumotrisDraw(struct Instance *inst, struct Fumotris *fumo)
2024-05-14 04:20:20 +00:00
{
2024-05-19 06:56:14 +00:00
TetraTerminalClear(&fumo->board, &fumo->term, 3, 5);
TetraTerminalDraw(&fumo->board, &fumo->term, 3, 5);
TetraTerminalDrawGhost(&fumo->piece, &fumo->board, &fumo->term, 3, 5);
TetraTerminalDraw(&fumo->piece, &fumo->term, 3, 5);
2024-05-15 22:10:47 +00:00
TerminalPrint(&fumo->term);
puts(fumo->term.str);
2024-05-02 22:17:37 +00:00
}
int main()
{
2024-05-19 06:56:14 +00:00
system("color");
2024-05-15 22:10:47 +00:00
struct Instance inst;
2024-05-08 12:47:46 +00:00
CreateFumoInstance(&inst);
2024-05-02 22:17:37 +00:00
2024-05-07 22:10:15 +00:00
struct Fumotris game;
2024-05-15 05:44:13 +00:00
2024-05-15 22:10:47 +00:00
EventAdd(&inst.on_start, &game, FumotrisStart);
EventAdd(&inst.on_update, &game, FumotrisUpdate);
EventAdd(&inst.on_draw, &game, FumotrisDraw);
2024-05-15 05:44:13 +00:00
2024-05-15 22:10:47 +00:00
CoroutineAdd(&inst, &game, FumotrisFall);
2024-05-02 22:17:37 +00:00
2024-05-08 12:47:46 +00:00
FumoInstanceRun(&inst);
2024-05-02 22:17:37 +00:00
2024-05-07 22:10:15 +00:00
return 0;
2024-05-19 06:56:14 +00:00
}