summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorantirez <antirez@gmail.com>2019-10-07 12:35:05 +0200
committerantirez <antirez@gmail.com>2019-10-07 12:35:17 +0200
commitf019f28e7b9f05205c02261bb3af8261869d600a (patch)
treee0eed01839907fb6ea74d99a7b0e2104fb15f327
parentbd6044706641fa6370a90dc5347e6cd37f5930eb (diff)
downloadredis-f019f28e7b9f05205c02261bb3af8261869d600a.tar.gz
LOLWUT: version 6 initial concept.
-rw-r--r--src/lolwut5.c4
-rw-r--r--src/lolwut6.c96
2 files changed, 95 insertions, 5 deletions
diff --git a/src/lolwut5.c b/src/lolwut5.c
index 4e9828145..0200fece6 100644
--- a/src/lolwut5.c
+++ b/src/lolwut5.c
@@ -106,7 +106,7 @@ lwCanvas *lwDrawSchotter(int console_cols, int squares_per_row, int squares_per_
* logical canvas. The actual returned string will require a terminal that is
* width/2 large and height/4 tall in order to hold the whole image without
* overflowing or scrolling, since each Barille character is 2x4. */
-sds lwRenderCanvas(lwCanvas *canvas) {
+static sds renderCanvas(lwCanvas *canvas) {
sds text = sdsempty();
for (int y = 0; y < canvas->height; y += 4) {
for (int x = 0; x < canvas->width; x += 2) {
@@ -166,7 +166,7 @@ void lolwut5Command(client *c) {
/* Generate some computer art and reply. */
lwCanvas *canvas = lwDrawSchotter(cols,squares_per_row,squares_per_col);
- sds rendered = lwRenderCanvas(canvas);
+ sds rendered = renderCanvas(canvas);
rendered = sdscat(rendered,
"\nGeorg Nees - schotter, plotter on paper, 1968. Redis ver. ");
rendered = sdscat(rendered,REDIS_VERSION);
diff --git a/src/lolwut6.c b/src/lolwut6.c
index 68f09036a..8cc8d6e04 100644
--- a/src/lolwut6.c
+++ b/src/lolwut6.c
@@ -36,6 +36,94 @@
#include "server.h"
#include "lolwut.h"
+/* Render the canvas using the four gray levels of the standard color
+ * terminal: they match very well to the grayscale display of the gameboy. */
+static sds renderCanvas(lwCanvas *canvas) {
+ sds text = sdsempty();
+ for (int y = 0; y < canvas->height; y++) {
+ for (int x = 0; x < canvas->width; x++) {
+ int color = lwGetPixel(canvas,x,y);
+ char *ce; /* Color escape sequence. */
+
+ /* Note that we set both the foreground and background color.
+ * This way we are able to get a more consistent result among
+ * different terminals implementations. */
+ switch(color) {
+ case 0: ce = "0;30;40m"; break; /* Black */
+ case 1: ce = "0;90;100m"; break; /* Gray 1 */
+ case 2: ce = "0;37;47m"; break; /* Gray 2 */
+ case 3: ce = "0;97;107m"; break; /* White */
+ }
+ text = sdscatprintf(text,"\033[%s \033[0m",ce);
+ }
+ if (y != canvas->height-1) text = sdscatlen(text,"\n",1);
+ }
+ return text;
+}
+
+/* Draw a skyscraper on the canvas, according to the parameters in the
+ * 'skyscraper' structure. Window colors are random and are always selected
+ * to be different than the color of the skyscraper itsefl. */
+struct skyscraper {
+ int xoff; /* X offset. */
+ int width; /* Pixels width. */
+ int height; /* Pixels height. */
+ int windows; /* Draw windows if true. */
+ int color; /* Color of the skyscraper. */
+};
+
+void generateSkyscraper(lwCanvas *canvas, struct skyscraper *si) {
+ int starty = canvas->height-1;
+ int endy = starty - si->height + 1;
+ for (int y = starty; y >= endy; y--) {
+ for (int x = si->xoff; x < si->xoff+si->width; x++) {
+ /* The roof is four pixels less wide. */
+ if (y == endy && (x <= si->xoff+1 || x >= si->xoff+si->width-2))
+ continue;
+ int color = si->color;
+ /* Alter the color if this is a place where we want to
+ * draw a window. We check that we are in the inner part of the
+ * skyscraper, so that windows are far from the borders. */
+ if (si->windows &&
+ x > si->xoff+1 &&
+ x < si->xoff+si->width-2 &&
+ y > endy+1 &&
+ y < starty-1)
+ {
+ /* Calculate the x,y position relative to the start of
+ * the window area. */
+ int relx = x - (si->xoff+1);
+ int rely = y - (endy+1);
+
+ /* Note that we want the windows to be two pixels wide
+ * but just one pixel tall, because terminal "pixels"
+ * (characters) are not square. */
+ if (relx/2 % 2 && rely % 2) {
+ do {
+ color = rand() % 4;
+ } while (color == si->color);
+ /* Except we want adjacent pixels creating the same
+ * window to be the same color. */
+ if (relx % 2) color = lwGetPixel(canvas,x-1,y);
+ }
+ }
+ lwDrawPixel(canvas,x,y,color);
+ }
+ }
+}
+
+/* Generate a skyline inspired by the parallax backgrounds of 8 bit games. */
+void generateSkyline(lwCanvas *canvas) {
+ struct skyscraper si = {
+ .xoff = 4,
+ .width = 13,
+ .height = 15,
+ .windows = 1,
+ .color = 1
+ };
+ generateSkyscraper(canvas, &si);
+}
+
/* The LOLWUT 6 command:
*
* LOLWUT [columns] [rows]
@@ -45,7 +133,7 @@
*/
void lolwut6Command(client *c) {
long cols = 80;
- long rows = 40;
+ long rows = 20;
/* Parse the optional arguments if any. */
if (c->argc > 1 &&
@@ -64,12 +152,14 @@ void lolwut6Command(client *c) {
if (rows > 1000) rows = 1000;
/* Generate the city skyline and reply. */
- sds rendered = sdsempty();
+ lwCanvas *canvas = lwCreateCanvas(cols,rows);
+ generateSkyline(canvas);
+ sds rendered = renderCanvas(canvas);
rendered = sdscat(rendered,
"\nDedicated to the 8 bit game developers of the past. Redis ver. ");
rendered = sdscat(rendered,REDIS_VERSION);
rendered = sdscatlen(rendered,"\n",1);
addReplyVerbatim(c,rendered,sdslen(rendered),"txt");
sdsfree(rendered);
- // lwFreeCanvas(canvas);
+ lwFreeCanvas(canvas);
}