bleachworm replaces widechomper #177

This commit is contained in:
nick black 2019-12-22 00:27:43 -05:00
parent dbb74ea8c4
commit c3fa7ea664
No known key found for this signature in database
GPG Key ID: 5F43400C21CBFACC
5 changed files with 72 additions and 110 deletions

View File

@ -45,7 +45,7 @@ contains a set of text-based demonstrations of capabilities from the notcurses l
.P
(s)liders—a missing-piece puzzle made up of colorful blocks
.P
(w)idechomper—a gremlin feasts upon wide characters
(b)leachworm—a great Nothing slowly robs the world of color
.P
(v)iew—images and a video are rendered as text
.P

View File

@ -8,7 +8,7 @@
#include "demo.h"
// Fill up the screen with as much crazy Unicode as we can, and then set a
// gremlin loose, looking to eat up all the wide characters.
// gremlin loose, looking to brighten up the world.
// FIXME throw this in there somehow
// ∮ E⋅da = Q, n → ∞, ∑ f(i) = ∏ g(i), ⎧⎡⎛┌─────┐⎞⎤⎫
@ -25,6 +25,42 @@
// the upper left: 012
// 7 3
// 654
// 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;
}
// the closer the coordinate is (lower distance), the more we lighten the cell
static inline int
lighten(struct ncplane* n, cell* c, int distance){
if(c->gcluster == 0){ // don't blow away wide characters
return 0;
}
unsigned r, g, b;
cell_get_fg_rgb(c, &r, &g, &b);
r += rand() % (75 - distance * 25);
b += rand() % (75 - distance * 25);
g += rand() % (75 - distance * 25);
if(r > 255) r = 255;
if(g > 255) g = 255;
if(b > 255) b = 255;
if(cell_set_fg_rgb(c, r, g, b)){
return -1;
}
return ncplane_putc(n, c);
}
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){
@ -65,149 +101,74 @@ get_surrounding_cells(struct ncplane* n, cell* cells, int y, int x){
}
}
// 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_rgb(c, &r, &g, &b);
r += (255 - r) / 3;
g += (255 - g) / 3;
b += (255 - b) / 3;
cell_set_fg_rgb(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);
lighten(n, &c, 2);
}
if(ncplane_cursor_move_yx(n, y - 1, x) == 0){
cell_duplicate(n, &c, &cells[1]);
lighten(&c);
ncplane_putc(n, &c);
lighten(n, &c, 1);
}
if(ncplane_cursor_move_yx(n, y - 1, x + 1) == 0){
cell_duplicate(n, &c, &cells[2]);
lighten(&c);
ncplane_putc(n, &c);
lighten(n, &c, 2);
}
if(ncplane_cursor_move_yx(n, y, x - 1) == 0){
cell_duplicate(n, &c, &cells[7]);
lighten(&c);
ncplane_putc(n, &c);
lighten(n, &c, 1);
}
if(ncplane_cursor_move_yx(n, y, x + 1) == 0){
cell_duplicate(n, &c, &cells[3]);
lighten(&c);
ncplane_putc(n, &c);
lighten(n, &c, 1);
}
if(ncplane_cursor_move_yx(n, y + 1, x - 1) == 0){
cell_duplicate(n, &c, &cells[6]);
lighten(&c);
ncplane_putc(n, &c);
lighten(n, &c, 2);
}
if(ncplane_cursor_move_yx(n, y + 1, x) == 0){
cell_duplicate(n, &c, &cells[5]);
lighten(&c);
ncplane_putc(n, &c);
lighten(n, &c, 1);
}
if(ncplane_cursor_move_yx(n, y + 1, x + 1) == 0){
cell_duplicate(n, &c, &cells[4]);
lighten(&c);
ncplane_putc(n, &c);
lighten(n, &c, 2);
}
if(ncplane_cursor_move_yx(n, y - 2, x) == 0){
cell_duplicate(n, &c, &cells[8]);
lighten(&c);
ncplane_putc(n, &c);
lighten(n, &c, 2);
}
if(ncplane_cursor_move_yx(n, y + 2, x) == 0){
cell_duplicate(n, &c, &cells[9]);
lighten(&c);
ncplane_putc(n, &c);
lighten(n, &c, 2);
}
if(ncplane_cursor_move_yx(n, y, x - 2) == 0){
cell_duplicate(n, &c, &cells[10]);
lighten(&c);
ncplane_putc(n, &c);
lighten(n, &c, 2);
}
if(ncplane_cursor_move_yx(n, y, x + 2) == 0){
cell_duplicate(n, &c, &cells[11]);
lighten(&c);
ncplane_putc(n, &c);
lighten(n, &c, 2);
}
if(ncplane_cursor_move_yx(n, y, x) == 0){
cell_duplicate(n, &c, &cells[12]);
lighten(n, &c, 0);
}
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
// of 13 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];
cell lightup[13];
size_t i;
for(i = 0 ; i < sizeof(lightup) / sizeof(*lightup) ; ++i){
cell_init(&lightup[i]);
@ -225,24 +186,22 @@ snake_thread(void* vnc){
cell_prime(n, &head, "א", 0, channels);
cell c = CELL_TRIVIAL_INITIALIZER;
struct timespec iterdelay = { .tv_sec = 0, .tv_nsec = 1000000000ul / 20, };
int prevx = 0, prevy = 0;
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);
int oldy, oldx;
clock_nanosleep(CLOCK_MONOTONIC, 0, &iterdelay, NULL);
do{ // force a move
oldy = y;
oldx = x;
// FIXME he ought be weighted to avoid light; he's a snake after all
int direction = random() % 4;
switch(direction){
case 0: --y; break;
@ -268,10 +227,9 @@ snake_thread(void* vnc){
x = oldx;
y = oldy;
}
}while(oldx == x && oldy == y);
if(restore_surrounding_cells(n, lightup, oldy, oldx)){
return NULL;
}
}while((oldx == x && oldy == y) || (x == prevx && y == prevy));
prevy = oldy;
prevx = oldx;
}
cell_release(n, &head); // FIXME won't be released when cancelled
cell_release(n, &c); // FIXME won't be released when cancelled
@ -348,7 +306,7 @@ message(struct ncplane* n, int maxy, int maxx, int num, int total,
}
// Much of this text comes from http://kermitproject.org/utf8.html
int widechomper_demo(struct notcurses* nc){
int bleachworm_demo(struct notcurses* nc){
static const char* strs[] = {
"Война и мир",
"Бра́тья Карама́зовы",
@ -670,9 +628,12 @@ int widechomper_demo(struct notcurses* nc){
if(i){
uint64_t delay = demodelay.tv_sec * 1000000000 + demodelay.tv_nsec;
delay /= screens;
struct timespec tv = {
.tv_sec = delay / 1000000000, .tv_nsec = delay % 1000000000,
};
struct timespec tv;
if(delay > GIG){
ns_to_timespec(GIG, &tv);
}else{
ns_to_timespec(delay, &tv);
}
ncplane_fadein(n, &tv);
}
pthread_t tid;

View File

@ -63,7 +63,7 @@ usage(const char* exe, int status){
fprintf(out, " s: run shuffle\n");
fprintf(out, " u: run uniblock\n");
fprintf(out, " v: run view\n");
fprintf(out, " w: run widechomper\n");
fprintf(out, " w: run bleachworm\n");
exit(status);
}
@ -183,7 +183,7 @@ ext_demos(struct notcurses* nc, const char* demos){
case 'l': ret = luigi_demo(nc); break;
case 'v': ret = view_demo(nc); break;
case 'e': ret = eagle_demo(nc); break;
case 'w': ret = widechomper_demo(nc); break;
case 'w': ret = bleachworm_demo(nc); break;
case 'p': ret = panelreel_demo(nc); break;
default:
fprintf(stderr, "Unknown demo specification: %c\n", *demos);

View File

@ -16,7 +16,7 @@ extern struct timespec demodelay;
char* find_data(const char* datum);
int unicodeblocks_demo(struct notcurses* nc);
int widechomper_demo(struct notcurses* nc);
int bleachworm_demo(struct notcurses* nc);
int box_demo(struct notcurses* nc);
int maxcolor_demo(struct notcurses* nc);
int grid_demo(struct notcurses* nc);

View File

@ -1126,6 +1126,7 @@ int ncplane_putc(ncplane* n, const cell* c){
}
}
cell_set_wide(candidate);
cell_release(n, candidate);
}
}
n->damage[n->y] = true;