#include #include #include #include #include #include enum { COLOR_FONT, COLOR_SAND }; enum { ADD, UNDO }; struct SAND { int x; int y; }; WINDOW *win; struct winsize w_size; int px = 1, py = 1; struct SAND *sand_array; size_t array_index; void clear_scr(WINDOW *win) { clear(); refresh(); if (win != NULL) { wclear(win); wrefresh(win); } } void clean_up(int sig) { if (sig == SIGWINCH) { if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w_size) < 0) perror("TIOCGWINSZ"); if (px >= w_size.ws_col) px = w_size.ws_col - 2; if (py >= w_size.ws_row) py = w_size.ws_row - 2; endwin(); initscr(); delwin(win); win = newwin(w_size.ws_row, w_size.ws_col, 0, 0); } else { clear_scr(win); delwin(win); endwin(); if (sand_array != NULL) free(sand_array); exit((sig == -1) ? 1 : 0); } } int placed_on(int y, int x) { for (size_t i = 0; i < array_index; i++) if (sand_array[i].y == y && sand_array[i].x == x) return i; return -1; } void sand_ctl(char flag) { if (sand_array == NULL) { sand_array = malloc(sizeof(struct SAND)); if (sand_array == NULL) { perror("malloc"); clean_up(-1); } } if (flag == UNDO && array_index > 0) { array_index--; if (array_index == 0) { free(sand_array); sand_array = NULL; return; } } else if (flag == ADD) { for (size_t i = 0; i < array_index; i++) if (sand_array[i].x == px && sand_array[i].y == py) return; array_index++; } struct SAND *tmp = realloc(sand_array, array_index * sizeof(struct SAND)); if (tmp == NULL) { perror("realloc"); clean_up(-1); } if (flag == ADD) { tmp[array_index - 1].x = px; tmp[array_index - 1].y = py; } sand_array = tmp; } void move_sand(void) { for (size_t i = 0; i < array_index; i++) { if (placed_on(sand_array[i].y + 1, sand_array[i].x) == -1 && sand_array[i].y < w_size.ws_row - 2) sand_array[i].y++; else if (sand_array[i].y < w_size.ws_row - 3) { if (sand_array[i].x + 1 < w_size.ws_col - 1 && placed_on(sand_array[i].y + 1, sand_array[i].x + 1) == -1) sand_array[i].x++; else if (sand_array[i].x - 1 > 0 && placed_on(sand_array[i].y + 1, sand_array[i].x - 1) == -1) sand_array[i].x--; } } } void draw(void) { wattron(win, COLOR_PAIR(COLOR_FONT)); for (size_t y = 1; y < w_size.ws_row - 1; y++) for (size_t x = 1; x < w_size.ws_col - 1; x++) if (!(x % 2)) mvwprintw(win, y, x, "."); mvwprintw(win, py, px, "+"); wattroff(win, COLOR_PAIR(COLOR_FONT)); wattron(win, COLOR_PAIR(COLOR_SAND)); for (size_t i = 0; i < array_index; i++) mvwprintw(win, sand_array[i].y, sand_array[i].x, "#"); wattroff(win, COLOR_PAIR(COLOR_SAND)); box(win, 0, 0); wrefresh(win); } int main(void) { signal(SIGINT, clean_up); signal(SIGWINCH, clean_up); initscr(); noecho(); cbreak(); curs_set(0); timeout(1000); keypad(stdscr, TRUE); if (has_colors() == FALSE) { endwin(); fputs("Your terminal does not support color", stderr); exit(1); } start_color(); init_pair(COLOR_FONT, COLOR_RED, COLOR_BLACK); init_pair(COLOR_SAND, COLOR_YELLOW, COLOR_YELLOW); /* Init screen size */ clean_up(SIGWINCH); while (1) { clear_scr(win); move_sand(); draw(); int k = getch(); if (k == KEY_UP && py - 1 > 0) py--; else if (k == KEY_DOWN && py + 1 < w_size.ws_row - 1) py++; else if (k == KEY_RIGHT && px + 1 < w_size.ws_col - 1) px++; else if (k == KEY_LEFT && px - 1 > 0) px--; else if (k == ' ') sand_ctl(ADD); else if (k == 'u') sand_ctl(UNDO); } }