commit 01b214f53b9b62637fb2adaf00667867f9473d01 Author: Daniel Date: Wed Mar 1 16:43:37 2017 +0100 initial diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..84a500a --- /dev/null +++ b/Makefile @@ -0,0 +1,17 @@ +CC=gcc +CFLAG= -O -g -o +objects=main.o\ + playfield.o\ + input_output.o + +all:main + +%.o:%.c + $(CC) -c $(CFLAG) $@ $< + + +main: clean $(objects) + $(CC) $(objects) $(CFLAG) main + +clean: + rm $(objects) || true diff --git a/conf.h b/conf.h new file mode 100644 index 0000000..9ad470c --- /dev/null +++ b/conf.h @@ -0,0 +1,21 @@ + +#ifndef __conf__h_ +#define __conf__h_ + +#define WIDTH 50 +#define LINES 20 + + +#define KEY_DEFAULT '_' +#define KEY_RIGHT 'd' +#define KEY_LEFT 'a' +#define KEY_EXIT 'q' +#define CHAR_ME '#' +#define CHAR_ENEMY '*' +#define ESCAPE_RED "\033[31m" +#define ESCAPE_GREEN "\033[32m" +#define ESCAPE_RESET "\033[0m" + +#define CHRS_TO_CLEAR_ESCAPE 7 + +#endif diff --git a/input_output.c b/input_output.c new file mode 100644 index 0000000..0c85233 --- /dev/null +++ b/input_output.c @@ -0,0 +1,71 @@ +#include +#include +#include +#include +#include +static volatile char EOF_received = 0; + +#include "conf.h" +void put_line(char * line) +{ + int i; + putc('|', stdout); + for(i = 0; i < WIDTH; i++) + { + // FIXME: add colors + if(line[i] == CHAR_ME) + { + printf(ESCAPE_GREEN); + } + if(line[i] == CHAR_ENEMY) + { + printf(ESCAPE_RED); + } + putc(line[i], stdout); + if(line[i] == CHAR_ME || line[i] == CHAR_ENEMY) + { + printf(ESCAPE_RESET); + } + } + putc('|', stdout); + putc('\n', stdout); +} + +void clear_screen(void) +{ + int i, j; + // clear the screen + for(i = 0; i < LINES + 3; i++) + { + for(j = 0; j < WIDTH + 3 + CHRS_TO_CLEAR_ESCAPE; j++) + { + putc('\b', stdout); + } + printf("\r\033[A"); + } + +} + +char kb_hit(void) +{ + struct timeval tv = { 0L, 0L }; + fd_set fds; + FD_ZERO(&fds); + FD_SET(0, &fds); + return select(1, &fds, NULL, NULL, &tv); +} + + +char get_last_key_or_default(void) +{ + int key = KEY_DEFAULT; + while(kb_hit()) + { + key = getc(stdin); + } + if(key == EOF) + { + EOF_received = 1; + } + return key; +} diff --git a/input_output.h b/input_output.h new file mode 100644 index 0000000..f24bcba --- /dev/null +++ b/input_output.h @@ -0,0 +1,16 @@ +#ifndef __input_output_h_ +#define __input_output_h_ +#include +#include +#include +#include +#include + +#include "conf.h" +void put_line(char * line); +void clear_screen(void); +char kb_hit(void); +char get_last_key_or_default(void); +static volatile char EOF_received = 0; + +#endif diff --git a/main.c b/main.c new file mode 100644 index 0000000..ddf610b --- /dev/null +++ b/main.c @@ -0,0 +1,148 @@ +#include +#include +#include +#include +#include +#include + +#include"input_output.h" +#include"playfield.h" + + +int difficulty = 200; +static struct termios oldt, newt; +char * playfield; +char ** horizon; + +static volatile char sigint_received = 0; + +int main(void) +{ + + // set up the terminal for our hacky game.... + + static struct termios oldt, newt; + tcgetattr(STDIN_FILENO, &oldt); + newt = oldt; + newt.c_lflag &= ~(ICANON | ECHO); + tcsetattr(STDIN_FILENO, TCSANOW, &newt); + + // ok done + + int pos = 0; + + + unsigned long long int score = 0; + + char input = KEY_DEFAULT; + int to_place = 0; + printf("q: end; d: right; a: left\n\n\n"); + + while(input != KEY_EXIT && !(EOF_received || sigint_received)) + { + horizon_drop_one_line(horizon); + // clear both the cursor and + // the last enemy + playfield[pos] = ' '; + horizon[0][to_place] = ' '; + + if(input == KEY_RIGHT) + { + pos++; + if(pos >= WIDTH) + { + pos = 0; + } + } + if(input == KEY_LEFT) + { + pos--; + if(pos < 0) + { + pos = WIDTH - 1; + } + } + if(input == KEY_EXIT) + { + break; + } + clear_screen(); + + print_horizon(horizon); + + playfield[pos] = CHAR_ME; + to_place = (random() & 0xff) % WIDTH; + horizon[0][to_place] = CHAR_ENEMY; + put_line(playfield); + + if(horizon[LINES - 1][pos] == CHAR_ENEMY) + { + printf("GAME OVER!\nYour score was: %llu\n", score); + break; + } + usleep(difficulty * 1000); + score++; + + if(!(score % 50)) + { + difficulty--; + } + if(score == 0) + { + printf("Congrats. You won the game.\nAnd you have absolutely no life.\nat all.\n"); + break; + } + + printf("SCORE: %llu\n", score); + + // check this to prevent blocking + if(EOF_received || sigint_received) + { + break; + } + input = get_last_key_or_default(); + } + + tcsetattr(STDIN_FILENO, TCSANOW, &oldt); + return 0; +} + +void __attribute__((cold)) handle_sigint(int signum) +{ + sigint_received = 1; +} +void __attribute__((cold)) handle_sigterm(int signum) +{ + printf("\n\nTERMINATED!\n"); + exit(1); + +} + +/* +Constructor: Add a sighandler for SIGINT and SIGTERM + */ +void __attribute__((constructor)) add_signal_handlers(void) +{ + signal(SIGINT, handle_sigint); + signal(SIGTERM, handle_sigterm); +} + +/* +Destructor: Free memory + */ +void __attribute__((destructor)) clean(void) +{ + free(playfield); + delete_horizon(horizon); + printf("\n"); +} + +/* +Constructor: create all the data we need + */ +void __attribute__((constructor)) build_playfield(void) +{ + playfield = allocate_playfield(WIDTH); + build_horizon(&horizon); +} + diff --git a/playfield.c b/playfield.c new file mode 100644 index 0000000..3769ca4 --- /dev/null +++ b/playfield.c @@ -0,0 +1,76 @@ +#include +#include +#include"conf.h" +#include"input_output.h" + + +void build_horizon(char *** horizon) +{ + char ** h = calloc(sizeof(char * ), LINES); + int i, j; + for(i = 0; i < LINES; i++) + { + h[i] = calloc(sizeof(char), WIDTH); + for(j = 0; j < WIDTH; j++) + { + h[i][j] = ' '; + } + putc('\n', stdout); // make space for the game + } + *horizon = h; +} + +void horizon_drop_one_line(char ** horizon) +{ + + int i, j; + for(i = LINES - 1; i >= 1; i--) + { + for(j = 0; j < WIDTH; j++) + { + horizon[i][j] = horizon[i - 1][j]; + } + } +} + +void print_horizon(char ** horizon) +{ + int i; + putc('+', stdout); + for(i = 0; i < WIDTH ; i++) + { + putc('-', stdout); + } + putc('+', stdout); + putc('\n', stdout); + + for(i = 0; i < LINES; i++) + { + put_line(horizon[i]); + } +} + +void delete_horizon(char ** horizon) +{ + int i; + for(i = 0; i < LINES; i++) + { + free(horizon[i]); + } + free(horizon); +} + + + +char * allocate_playfield(size_t width) +{ + char * field = calloc(sizeof(char), width); + + size_t i; + for(i = 0; i < width; i++) + { + field[i] = ' '; + } + return field; +} + diff --git a/playfield.h b/playfield.h new file mode 100644 index 0000000..4957209 --- /dev/null +++ b/playfield.h @@ -0,0 +1,10 @@ +#ifndef __playfield_h_ +#define __playfield_h_ + +void build_horizon(char *** horizon); +void horizon_drop_one_line(char ** horizon); +void print_horizon(char ** horizon); +void delete_horizon(char ** horizon); +char * allocate_playfield(size_t width); + +#endif