Compare commits

...

10 Commits

11 changed files with 305 additions and 103 deletions

50
README.md Normal file
View File

@@ -0,0 +1,50 @@
# Handleiding
Geachte speler,
Heb je wel eens rijk willen zijn?
Vast wel. Mensen met goede bedoelingen (zoals ik) hebben jouw
daarom meermaals geappt op Telegram om je te vragen of je bij een
bedrijf XYZ wilt werken. De werktijden zijn slechts 30 min per
week, en je verdient 500 euro per dag!
Misschien twijfel je nog. Geen probleem! Voor kleine spelers
zoals jij hebben we een spel genaamd 'gambling-curses'. In dit
spel zie je een live grafiek van de laatste Bitcoin-prijs, en heb
je 10.000 euro op je bankaccount. Je kunt gemakkelijk traden door
op 's' en 'b' te klikken. ('s' betekent SELL, 'b' betekent BUY).
Aangezien de cryptomarkt zeker NIET gamblen is, en er wel degelijk
een strategie achter zit, kun je zo gaan oefenen.
Met vriendelijke groet,
Crypto/Dropshipping Guru
## Notes aan de TA's
Beste TA,
Het is nu zaterdagavond, en ik heb besloten om de game te laten
voor wat het is. Ik had de functies nog beter commentaar moeten
geven, de code moeten refactoren, bugs moeten fixen, memory moeten
free()en, ...
Maar daar is nu geen tijd meer voor. Veel dingen in de code zijn
ronduit fout. Als ik nog tijd had, dan had ik de UI-framework
uitgebreid om textboxes te maken, buttonhovers en een betere
algoritme voor het tekenen van de boxes. Ook had ik dan de
pricechart anders geprogrammeerd zodat de prijzen altijd in zicht
blijven en niet buiten de box komen, wat momenteel weleens
gebeurt. (Overigens heb ik hier de NGINX-stijlgids gevolgt.)
Toch is het een geinig spelletje. Geniet ervan.
Met vriendelijke groet,
Artsiom
UvA-Informaticastudent
16141253

98
box.c
View File

@@ -17,10 +17,14 @@
#include "util.h" #include "util.h"
static void draw_rectangle(double x, double y, double width, double height); static void draw_rectangle(unsigned int x, unsigned int y, unsigned int width,
static void draw_chart(struct box *, double x, double y, double width, double height); unsigned int height);
static void draw_container(struct box *, double x, double y, double width, double height); static void draw_chart(struct box *, unsigned int x, unsigned int y,
static void draw_button(struct box *, double x, double y, double width, double height); unsigned int width, unsigned int height);
static void draw_container(struct box *, unsigned int x, unsigned int y,
unsigned int width, unsigned int height);
static void draw_button(struct box *, unsigned int x, unsigned int y,
unsigned int width, unsigned int height);
void void
@@ -31,46 +35,42 @@ append_box(struct box *parent, struct box *child)
static void static void
draw_rectangle(double fx, double fy, double fwidth, double fheight) draw_rectangle(unsigned int x, unsigned int y, unsigned int width,
unsigned int height)
{ {
size_t x = llround(fx);
size_t y = llround(fy);
size_t w = llround(fwidth) - 1;
size_t h = llround(fheight) - 1;
/* corners */ /* corners */
ui_char(x, y, '+'); ui_char(x, y, '+');
ui_char(x, y + h, '+'); ui_char(x, y + height, '+');
ui_char(x + w, y + h, '+'); ui_char(x + width, y + height, '+');
ui_char(x + w, y, '+'); ui_char(x + width, y, '+');
/* vertical borders */ /* vertical borders */
for (size_t i = 1; i < h; i++) { for (size_t i = 1; i < height; i++) {
ui_char(x, y + i, '|'); ui_char(x, y + i, '|');
} }
for (size_t i = 1; i < h; i++) { for (size_t i = 1; i < height; i++) {
ui_char(x + w, y + i, '|'); ui_char(x + width, y + i, '|');
} }
/* horizontal borders */ /* horizontal borders */
for (size_t i = 1; i < w; i++) { for (size_t i = 1; i < width; i++) {
ui_char(x + i, y, '-'); ui_char(x + i, y, '-');
} }
for (size_t i = 1; i < w; i++) { for (size_t i = 1; i < width; i++) {
ui_char(x + i, y + h, '-'); ui_char(x + i, y + height, '-');
} }
} }
static void static void
draw_chart(struct box *chart, double x, double y, double width, double height) draw_chart(struct box *chart, unsigned int x, unsigned int y,
unsigned int width, unsigned int height)
{ {
char c = '@';
long int actual_diff; long int actual_diff;
double diff, price; double diff, price;
enum ui_color color; enum ui_color color;
@@ -86,28 +86,18 @@ draw_chart(struct box *chart, double x, double y, double width, double height)
actual_diff = 0; actual_diff = 0;
for (size_t i = 0; i < width; i++) { for (size_t i = 0; i < width; i++) {
diff = (double)rand() / RAND_MAX - 0.6; price = chart->chart->prices[i];
actual_diff = (size_t)(height + y - price) - (size_t)(height + y - (price + diff));
if (actual_diff > 0) { ui_color_on(UI_BLUE);
color = UI_GREEN; ui_char(x + i, height + y - price, '@');
} else if (actual_diff == 0) { ui_color_off(UI_BLUE);
color = UI_NONE;
} else if (actual_diff < 0) {
color = UI_RED;
}
ui_color_on(color);
ui_char(x + i, height + y - price, c);
ui_color_off(color);
price += diff;
} }
} }
static void static void
draw_button(struct box *b, double x, double y, double width, double height) draw_button(struct box *b, unsigned int x, unsigned int y, unsigned int width,
unsigned int height)
{ {
ui_color_on(b->color); ui_color_on(b->color);
draw_rectangle(x, y, width, height); draw_rectangle(x, y, width, height);
@@ -117,9 +107,10 @@ draw_button(struct box *b, double x, double y, double width, double height)
static void static void
draw_container(struct box *b, double x, double y, double width, double height) draw_container(struct box *b, unsigned int x, unsigned int y,
unsigned int width, unsigned int height)
{ {
double current, length, total_fills, pixels_per_fill; unsigned int current, i, length, total_fills, pixels_per_fill;
struct box *child; struct box *child;
switch (b->type) { switch (b->type) {
@@ -134,19 +125,23 @@ draw_container(struct box *b, double x, double y, double width, double height)
} }
total_fills = 0; total_fills = 0;
for (size_t i = 0; i < b->length; i++) { for (i = 0; i < b->length; i++) {
total_fills += b->children[i]->fills; total_fills += b->children[i]->fills;
} }
pixels_per_fill = length / total_fills; pixels_per_fill = length / total_fills;
for (size_t i = 0; i < b->length; i++) { for (i = 0; i < b->length; i++) {
child = b->children[i]; child = b->children[i];
length = child->fills * pixels_per_fill; length = child->fills * pixels_per_fill;
switch (b->type) { switch (b->type) {
case BOX_VERTICAL: draw_box(child, x, current, width, length); break; case BOX_VERTICAL:
case BOX_HORIZONTAL: draw_box(child, current, y, length, height); break; draw_box(child, x, current, width, length);
break;
case BOX_HORIZONTAL:
draw_box(child, current, y, length, height);
break;
} }
current += length; current += length;
@@ -155,16 +150,16 @@ draw_container(struct box *b, double x, double y, double width, double height)
struct box * struct box *
new_chart_box(void) new_chart_box(struct chart *chart)
{ {
struct box *chart = malloc(sizeof(struct box)); struct box *box = malloc(sizeof(struct box));
chart->type = BOX_CHART; box->type = BOX_CHART;
chart->prices = emalloc(sizeof(double) * 100); box->chart = chart;
chart->fills = 1; box->fills = 1;
chart->color = UI_NONE; box->color = UI_NONE;
return chart; return box;
} }
@@ -211,7 +206,8 @@ new_vertical_box(void)
void void
draw_box(struct box *b, double x, double y, double width, double height) draw_box(struct box *b, unsigned int x, unsigned int y, unsigned int width,
unsigned int height)
{ {
switch (b->type) { switch (b->type) {
case BOX_BUTTON: case BOX_BUTTON:

25
box.h
View File

@@ -8,6 +8,7 @@
#pragma once #pragma once
#include "chart.h"
#include "ui.h" #include "ui.h"
@@ -21,24 +22,19 @@ enum box_type {
struct box { struct box {
enum box_type type; enum box_type type;
enum ui_color color; enum ui_color color;
double fills; unsigned int fills;
union { union {
/* button */ /* button */
char *name; char *name;
/* chart and vertical/horizontal box */
struct {
/* chart and vertical/horizontal box */
size_t length;
union {
/* vertical/horizontal box */
struct box **children;
/* chart */ /* chart */
double *prices; struct chart *chart;
};
/* vertical/horizontal */
struct {
size_t length;
struct box **children;
}; };
}; };
}; };
@@ -47,8 +43,9 @@ struct box {
struct box *new_button_box(char *name); struct box *new_button_box(char *name);
struct box *new_vertical_box(void); struct box *new_vertical_box(void);
struct box *new_horizontal_box(void); struct box *new_horizontal_box(void);
struct box *new_chart_box(void); struct box *new_chart_box(struct chart *);
void append_box(struct box *parent, struct box *child); void append_box(struct box *parent, struct box *child);
void draw_box(struct box *, double x, double y, double width, double height); void draw_box(struct box *, unsigned int x, unsigned int y, unsigned int width,
unsigned int height);

43
chart.c Normal file
View File

@@ -0,0 +1,43 @@
/*
* Copyright (C) Artsiom D.
* Copyright (C) shit-co.de
*/
#include <stdlib.h>
#include <string.h>
#include "chart.h"
#include "util.h"
struct chart
new_chart(unsigned int length)
{
unsigned int i;
double price;
struct chart chart;
chart.prices = emalloc(sizeof(double) * length);
chart.length = length;
/* populate with random prices */
price = 10;
for (i = 0; i < length; i++) {
chart.prices[i] = price;
price += (double)rand() / RAND_MAX * 4 - 2;
}
return chart;
}
void
update_chart(struct chart *chart)
{
memmove(chart->prices, chart->prices + 1, (chart->length - 1) * sizeof(double));
chart->prices[chart->length - 1] = chart->prices[chart->length - 2] + (double)rand() / RAND_MAX * 4 - 2;
}

18
chart.h Normal file
View File

@@ -0,0 +1,18 @@
/*
* Copyright (C) Artsiom D.
* Copyright (C) shit-co.de
*/
#pragma once
struct chart {
double *prices;
unsigned int length;
};
void update_chart(struct chart *);
struct chart new_chart(unsigned int length);

113
main.c
View File

@@ -5,20 +5,35 @@
*/ */
#include <curses.h>
#include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #include <unistd.h>
#include <curses.h> #include <time.h>
#include "box.h" #include "box.h"
#include "ui.h" #include "ui.h"
#include "util.h"
int enum game_state {
main(void) GAME_IDLE, /* can buy AND sell */
GAME_BOUGHT, /* cannot buy again */
GAME_SOLD, /* cannot sell again */
};
struct game {
unsigned int dollars;
struct chart chart;
enum game_state state;
};
struct box *
initialize_ui_from_game(struct game *game)
{ {
struct box *ui, *top, *bottom, *left, *right, *buy, *sell, *scam, *title, *desc; struct box *ui, *top, *bottom, *left, *right, *buy, *sell, *bank,
*title, *desc;
ui_init();
title = new_button_box("Bitcoin"); title = new_button_box("Bitcoin");
desc = new_button_box("A crypto-scam :-)"); desc = new_button_box("A crypto-scam :-)");
@@ -27,20 +42,25 @@ main(void)
append_box(top, title); append_box(top, title);
append_box(top, desc); append_box(top, desc);
left = new_chart_box(); left = new_chart_box(&game->chart);
left->fills = 5; left->fills = 5;
buy = new_button_box("buy"); buy = new_button_box("buy");
buy->color = UI_GREEN; buy->color = UI_GREEN;
sell = new_button_box("sell"); sell = new_button_box("sell");
sell->color = UI_RED; sell->color = UI_RED;
scam = new_button_box("scam");
char *bank_text = emalloc(500);
sprintf(bank_text, "YOU HAVE $%d.", game->dollars);
bank = new_button_box(bank_text);
sell->color = UI_BLUE; sell->color = UI_BLUE;
right = new_vertical_box(); right = new_vertical_box();
append_box(right, buy); append_box(right, buy);
append_box(right, sell); append_box(right, sell);
append_box(right, scam); append_box(right, bank);
bottom = new_horizontal_box(); bottom = new_horizontal_box();
bottom->fills = 3; bottom->fills = 3;
@@ -51,11 +71,82 @@ main(void)
append_box(ui, top); append_box(ui, top);
append_box(ui, bottom); append_box(ui, bottom);
draw_box(ui, 0, 0, ui_width()-1, ui_height()-1); return ui;
}
/*
* Buy 50 coins, price = last price in chart.
*/
void game_buy(struct game *game)
{
if (game->state != GAME_IDLE) {
return;
}
game->dollars -= game->chart.prices[game->chart.length - 1] * 50;
game->state = GAME_BOUGHT;
}
/*
* Sell 50 coins, price = last price in chart.
*/
void game_sell(struct game *game)
{
if (game->state != GAME_BOUGHT) {
return;
}
game->dollars += game->chart.prices[game->chart.length - 1] * 50;
game->state = GAME_IDLE;
}
int
main(void)
{
int framerate;
struct box *ui;
struct game game;
framerate = 10;
game.state = GAME_IDLE;
game.dollars = 10000;
game.chart = new_chart(200);
ui_init();
ui = initialize_ui_from_game(&game);
for (;;) {
draw_box(ui, 0, 0, ui_width(), ui_height());
ui_refresh(); ui_refresh();
sleep(300); clock_t current = clock();
clock_t max = current + CLOCKS_PER_SEC * (1.0/framerate);
for (;;) {
switch (getch()) {
case 'b':
game_buy(&game);
break;
case 's':
game_sell(&game);
break;
}
if (clock() >= max) {
break;
}
}
update_chart(&game.chart);
ui_clear();
ui = initialize_ui_from_game(&game);
}
ui_end(); ui_end();
} }

View File

@@ -1,14 +1,19 @@
CFLAGS = -std=c23 -Wextra -pedantic -Wall -pedantic CFLAGS = -std=c11 -Wextra -pedantic -Wall -O0 -g3 -fsanitize=address
LDFLAGS = -lncurses LDFLAGS = -lncurses -fsanitize=address
main: box.o main.o ui.o util.o main: box.o main.o ui.o util.o chart.o
.PHONY: clean .PHONY: clean
box.o: box.c box.o: box.c
chart.o: chart.c
main.o: main.c main.o: main.c
ui.o: ui.c ui.o: ui.c
util.o: util.c util.o: util.c
tarball2: deel2.tar.gz
deel2.tar.gz: box.c chart.c main.c ui.c util.c box.h chart.h util.h ui.h util.h README.md makefile
tar czf $@ $^
clean: clean:
rm *.o main rm -f *.o main

7
ui.c
View File

@@ -22,6 +22,7 @@ ui_init(void)
init_pair(UI_BLUE, COLOR_BLUE, COLOR_BLACK); init_pair(UI_BLUE, COLOR_BLUE, COLOR_BLACK);
cbreak(); cbreak();
noecho(); noecho();
nodelay(stdscr, TRUE);
nonl(); nonl();
intrflush(stdscr, FALSE); intrflush(stdscr, FALSE);
keypad(stdscr, TRUE); keypad(stdscr, TRUE);
@@ -29,17 +30,17 @@ ui_init(void)
refresh(); refresh();
} }
void ui_end() void ui_end(void)
{ {
endwin(); endwin();
} }
void ui_string(size_t x, size_t y, char *s) void ui_string(unsigned int x, unsigned int y, char *s)
{ {
mvaddstr(y, x, s); mvaddstr(y, x, s);
} }
void ui_char(size_t x, size_t y, char c) void ui_char(unsigned int x, unsigned int y, char c)
{ {
mvaddch(y, x, c); mvaddch(y, x, c);
} }

4
ui.h
View File

@@ -22,8 +22,8 @@ void ui_end(void);
void ui_color_on(enum ui_color); void ui_color_on(enum ui_color);
void ui_color_off(enum ui_color); void ui_color_off(enum ui_color);
void ui_char(size_t x, size_t y, char c); void ui_char(unsigned int x, unsigned int y, char c);
void ui_string(size_t x, size_t y, char *s); void ui_string(unsigned int x, unsigned int y, char *s);
size_t ui_width(void); size_t ui_width(void);
size_t ui_height(void); size_t ui_height(void);

2
util.c
View File

@@ -23,7 +23,7 @@ emalloc(size_t n)
} }
void noreturn void
die(char *fmt, ...) die(char *fmt, ...)
{ {
va_list va; va_list va;

3
util.h
View File

@@ -8,7 +8,8 @@
#pragma once #pragma once
#include <stddef.h> #include <stddef.h>
#include <stdnoreturn.h>
void *emalloc(size_t n); void *emalloc(size_t n);
void die(char *fmt, ...); noreturn void die(char *fmt, ...);