/* * Copyright(c) 2017 Daniel Knüttel */ /* This program is free software. * Anyways if you think this program is worth it * and we meet shout a drink for me. */ /* This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program 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 Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . * * Dieses Programm ist Freie Software: Sie können es unter den Bedingungen * der GNU Affero General Public License, wie von der Free Software Foundation, * Version 3 der Lizenz oder (nach Ihrer Wahl) jeder neueren * veröffentlichten Version, weiterverbreiten und/oder modifizieren. * * Dieses Programm wird in der Hoffnung, dass es nützlich sein wird, aber * OHNE JEDE GEWÄHRLEISTUNG, bereitgestellt; sogar ohne die implizite * Gewährleistung der MARKTFÄHIGKEIT oder EIGNUNG FÜR EINEN BESTIMMTEN ZWECK. * Siehe die GNU Affero General Public License für weitere Details. * * Sie sollten eine Kopie der GNU Affero General Public License zusammen mit diesem * Programm erhalten haben. Wenn nicht, siehe . */ #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; // break the mainloop, if there was a SIGINT static volatile char sigint_received = 0; static struct termios oldt, newt; int main(void) { // set up the terminal for our hacky game.... 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] = ' '; // actually if...else produces // smaller objectcode than switch 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); // set the player cursor playfield[pos] = CHAR_ME; // add the next enemy to_place = (random() & 0xff) % WIDTH; horizon[0][to_place] = CHAR_ENEMY; put_line(playfield); // player got hit. 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.\n"); break; } printf("SCORE: %llu\n", score); // check this to prevent blocking if(EOF_received || sigint_received) { break; } input = get_last_key_or_default(); } return 0; } // We need those signal handlers to // free the memory properly. // If they do not get caught the // destructors will be skipped. // should not happen. void __attribute__((cold)) handle_sigint(int signum) { sigint_received = 1; } // should not happen. 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); tcsetattr(STDIN_FILENO, TCSANOW, &oldt); printf("\n"); } /* Constructor: create all the data we need */ void __attribute__((constructor)) build_playfield(void) { playfield = allocate_playfield(WIDTH); build_horizon(&horizon); }