From cb5b0e2968dd1f3dd7968330ecc54f2f223a2d02 Mon Sep 17 00:00:00 2001 From: nick black Date: Thu, 5 Dec 2019 17:38:36 -0500 Subject: [PATCH] =?UTF-8?q?=D7=90=20guy=20#110?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/demo/widecolor.c | 211 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 201 insertions(+), 10 deletions(-) diff --git a/src/demo/widecolor.c b/src/demo/widecolor.c index 6b2efefe4..551021275 100644 --- a/src/demo/widecolor.c +++ b/src/demo/widecolor.c @@ -7,10 +7,197 @@ #include #include "demo.h" +// get the (up to) eight surrounding cells. they run clockwise, starting from +// the upper left: 012 +// 7 3 +// 654 +static void +get_surrounding_cells(struct ncplane* n, cell* cells, int y, int x){ + if(ncplane_cursor_move_yx(n, y - 1, x - 1) == 0){ + ncplane_at_cursor(n, &cells[0]); + } + if(ncplane_cursor_move_yx(n, y - 1, x) == 0){ + ncplane_at_cursor(n, &cells[1]); + } + if(ncplane_cursor_move_yx(n, y - 1, x + 1) == 0){ + ncplane_at_cursor(n, &cells[2]); + } + if(ncplane_cursor_move_yx(n, y, x - 1) == 0){ + ncplane_at_cursor(n, &cells[7]); + } + if(ncplane_cursor_move_yx(n, y, x + 1) == 0){ + ncplane_at_cursor(n, &cells[3]); + } + if(ncplane_cursor_move_yx(n, y + 1, x - 1) == 0){ + ncplane_at_cursor(n, &cells[6]); + } + if(ncplane_cursor_move_yx(n, y + 1, x) == 0){ + ncplane_at_cursor(n, &cells[5]); + } + if(ncplane_cursor_move_yx(n, y + 1, x + 1) == 0){ + ncplane_at_cursor(n, &cells[4]); + } + if(ncplane_cursor_move_yx(n, y - 2, x) == 0){ + ncplane_at_cursor(n, &cells[8]); + } + if(ncplane_cursor_move_yx(n, y + 2, x) == 0){ + ncplane_at_cursor(n, &cells[9]); + } + if(ncplane_cursor_move_yx(n, y, x - 2) == 0){ + ncplane_at_cursor(n, &cells[10]); + } + if(ncplane_cursor_move_yx(n, y, x + 2) == 0){ + ncplane_at_cursor(n, &cells[11]); + } +} + +// is the provided cell part of the wall (i.e. a box-drawing character)? +static bool +wall_p(const struct ncplane* n, const cell* c){ + if(cell_simple_p(c)){ // any simple cell is fine to consume + return false; + } + const char* egc = cell_extended_gcluster(n, c); + wchar_t w; + if(mbtowc(&w, egc, strlen(egc)) > 0){ + if(w >= 0x2500 && w <= 0x257f){ // no room in the inn, little snake! + return true; + } + } + return false; +} + +static inline void +lighten(cell* c){ + unsigned r, g, b; + cell_get_fg(c, &r, &g, &b); + r += (255 - r) / 3; + g += (255 - g) / 3; + b += (255 - b) / 3; + cell_set_fg(c, r, g, b); +} + +static int +lightup_surrounding_cells(struct ncplane* n, const cell* cells, int y, int x){ + cell c = CELL_TRIVIAL_INITIALIZER; + if(ncplane_cursor_move_yx(n, y - 1, x - 1) == 0){ + cell_duplicate(n, &c, &cells[0]); + lighten(&c); + ncplane_putc(n, &c); + } + if(ncplane_cursor_move_yx(n, y - 1, x) == 0){ + cell_duplicate(n, &c, &cells[1]); + lighten(&c); + ncplane_putc(n, &c); + } + if(ncplane_cursor_move_yx(n, y - 1, x + 1) == 0){ + cell_duplicate(n, &c, &cells[2]); + lighten(&c); + ncplane_putc(n, &c); + } + if(ncplane_cursor_move_yx(n, y, x - 1) == 0){ + cell_duplicate(n, &c, &cells[7]); + lighten(&c); + ncplane_putc(n, &c); + } + if(ncplane_cursor_move_yx(n, y, x + 1) == 0){ + cell_duplicate(n, &c, &cells[3]); + lighten(&c); + ncplane_putc(n, &c); + } + if(ncplane_cursor_move_yx(n, y + 1, x - 1) == 0){ + cell_duplicate(n, &c, &cells[6]); + lighten(&c); + ncplane_putc(n, &c); + } + if(ncplane_cursor_move_yx(n, y + 1, x) == 0){ + cell_duplicate(n, &c, &cells[5]); + lighten(&c); + ncplane_putc(n, &c); + } + if(ncplane_cursor_move_yx(n, y + 1, x + 1) == 0){ + cell_duplicate(n, &c, &cells[4]); + lighten(&c); + ncplane_putc(n, &c); + } + if(ncplane_cursor_move_yx(n, y - 2, x) == 0){ + cell_duplicate(n, &c, &cells[8]); + lighten(&c); + ncplane_putc(n, &c); + } + if(ncplane_cursor_move_yx(n, y + 2, x) == 0){ + cell_duplicate(n, &c, &cells[9]); + lighten(&c); + ncplane_putc(n, &c); + } + if(ncplane_cursor_move_yx(n, y, x - 2) == 0){ + cell_duplicate(n, &c, &cells[10]); + lighten(&c); + ncplane_putc(n, &c); + } + if(ncplane_cursor_move_yx(n, y, x + 2) == 0){ + cell_duplicate(n, &c, &cells[11]); + lighten(&c); + ncplane_putc(n, &c); + } + cell_release(n, &c); + return 0; +} + +static int +restore_surrounding_cells(struct ncplane* n, const cell* cells, int y, int x){ + if(ncplane_cursor_move_yx(n, y - 1, x - 1) == 0){ + ncplane_putc(n, &cells[0]); + } + if(ncplane_cursor_move_yx(n, y - 1, x) == 0){ + ncplane_putc(n, &cells[1]); + } + if(ncplane_cursor_move_yx(n, y - 1, x + 1) == 0){ + ncplane_putc(n, &cells[2]); + } + if(ncplane_cursor_move_yx(n, y, x - 1) == 0){ + ncplane_putc(n, &cells[7]); + } + if(ncplane_cursor_move_yx(n, y, x + 1) == 0){ + ncplane_putc(n, &cells[3]); + } + if(ncplane_cursor_move_yx(n, y + 1, x - 1) == 0){ + ncplane_putc(n, &cells[6]); + } + if(ncplane_cursor_move_yx(n, y + 1, x) == 0){ + ncplane_putc(n, &cells[5]); + } + if(ncplane_cursor_move_yx(n, y + 1, x + 1) == 0){ + ncplane_putc(n, &cells[4]); + } + if(ncplane_cursor_move_yx(n, y - 2, x) == 0){ + ncplane_putc(n, &cells[8]); + } + if(ncplane_cursor_move_yx(n, y + 2, x) == 0){ + ncplane_putc(n, &cells[9]); + } + if(ncplane_cursor_move_yx(n, y, x - 2) == 0){ + ncplane_putc(n, &cells[10]); + } + if(ncplane_cursor_move_yx(n, y, x + 2) == 0){ + ncplane_putc(n, &cells[11]); + } + return 0; +} + +// each snake wanders around aimlessly, prohibited from entering the summary +// section. it ought light up the cells around it; to do this, we keep an array +// of 12 cells with the original colors, which we tune up for the duration of +// our colocality (unless they're summary area walls). static void * snake_thread(void* vnc){ struct notcurses* nc = vnc; struct ncplane* n = notcurses_stdplane(nc); + cell lightup[12]; + size_t i; + for(i = 0 ; i < sizeof(lightup) / sizeof(*lightup) ; ++i){ + cell_init(&lightup[i]); + } int dimy, dimx; ncplane_dim_yx(n, &dimy, &dimx); int x, y; @@ -20,17 +207,21 @@ snake_thread(void* vnc){ cell head = CELL_TRIVIAL_INITIALIZER; uint64_t channels = 0; notcurses_fg_prep(&channels, 255, 255, 255); - cell_prime(n, &head, "🐍", 0, channels); + cell_prime(n, &head, "א", 0, channels); cell c = CELL_TRIVIAL_INITIALIZER; cell_bg_default(&head); struct timespec iterdelay; timespec_div(&demodelay, 10, &iterdelay); while(true){ pthread_testcancel(); + get_surrounding_cells(n, lightup, y, x); ncplane_cursor_move_yx(n, y, x); ncplane_at_cursor(n, &c); // FIXME should be a whole body ncplane_putc(n, &head); + if(lightup_surrounding_cells(n, lightup, y, x)){ + return NULL; + } notcurses_render(nc); ncplane_cursor_move_yx(n, y, x); ncplane_putc(n, &c); @@ -60,20 +251,20 @@ snake_thread(void* vnc){ ncplane_cursor_move_yx(n, y, x); ncplane_at_cursor(n, &c); // don't allow the snake into the summary zone (test for walls) - if(!cell_simple_p(&c)){ // any simple cell is fine to consume - const char* egc = cell_extended_gcluster(n, &c); - wchar_t w; - if(mbtowc(&w, egc, strlen(egc)) > 0){ - if(w >= 0x2500 && w <= 0x257f){ // no room in the inn, little snake! - x = oldx; - y = oldy; - } - } + if(wall_p(n, &c)){ + x = oldx; + y = oldy; } }while(oldx == x && oldy == y); + if(restore_surrounding_cells(n, lightup, oldy, oldx)){ + return NULL; + } } cell_release(n, &head); // FIXME won't be released when cancelled cell_release(n, &c); // FIXME won't be released when cancelled + for(i = 0 ; i < sizeof(lightup) / sizeof(*lightup) ; ++i){ + cell_release(n, &lightup[i]); + } return NULL; }