From 6e881bc0c88ca5e1411f0e0270d0a84c3e9566b3 Mon Sep 17 00:00:00 2001 From: Curtis McEnroe Date: Tue, 21 Aug 2018 13:29:51 -0400 Subject: Remove spawns This reverts 66761cd30ee1da5b820c89c38fac6caf42fbe715 and commits after it. --- torus.h | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) (limited to 'torus.h') diff --git a/torus.h b/torus.h index 775df3c..26204f3 100644 --- a/torus.h +++ b/torus.h @@ -75,19 +75,8 @@ enum { }; static const size_t TILES_SIZE = sizeof(struct Tile[TILE_ROWS][TILE_COLS]); -static const uint32_t TILE_VOID_X = UINT32_MAX; -static const uint32_t TILE_VOID_Y = UINT32_MAX; - -static const struct { - uint32_t tileX; - uint32_t tileY; -} SPAWNS[] = { - { 0, 0 }, - { TILE_COLS * 3 / 4, TILE_ROWS * 3 / 4 }, // NW - { TILE_COLS * 1 / 4, TILE_ROWS * 3 / 4 }, // NE - { TILE_COLS * 1 / 4, TILE_ROWS * 1 / 4 }, // SE - { TILE_COLS * 3 / 4, TILE_ROWS * 1 / 4 }, // SW -}; +static const uint32_t TILE_INIT_X = TILE_COLS / 2; +static const uint32_t TILE_INIT_Y = TILE_ROWS / 2; enum { MAP_ROWS = 11, @@ -138,7 +127,6 @@ struct ClientMessage { enum PACKED { CLIENT_MOVE, CLIENT_PUT, - CLIENT_SPAWN, CLIENT_MAP, } type; union { @@ -150,6 +138,5 @@ struct ClientMessage { uint8_t color; char cell; } put; - uint8_t spawn; }; }; -- cgit 1.4.1 From 9bd49e16c9f41b12887a314c6c0317b0c8e8f852 Mon Sep 17 00:00:00 2001 From: Curtis McEnroe Date: Tue, 21 Aug 2018 14:00:15 -0400 Subject: Shrink the torus and rearrange struct Tile --- client.c | 18 +++++++++--------- merge.c | 4 ++-- meta.c | 10 +++++----- server.c | 22 +++++++--------------- torus.h | 28 ++++++++++++---------------- 5 files changed, 35 insertions(+), 47 deletions(-) (limited to 'torus.h') diff --git a/client.c b/client.c index 6fb2483..37cc7ce 100644 --- a/client.c +++ b/client.c @@ -346,23 +346,23 @@ static void serverMap(void) { time_t timeMin = timeNow; for (int y = 0; y < MAP_ROWS; ++y) { for (int x = 0; x < MAP_COLS; ++x) { - struct MapTile tile = map.tiles[y][x]; - if (countMax < tile.modifyCount) countMax = tile.modifyCount; - if (tile.modifyTime && timeMin > tile.modifyTime) { - timeMin = tile.modifyTime; + struct Meta meta = map.meta[y][x]; + if (countMax < meta.modifyCount) countMax = meta.modifyCount; + if (meta.modifyTime && timeMin > meta.modifyTime) { + timeMin = meta.modifyTime; } } } for (int y = 0; y < MAP_ROWS; ++y) { for (int x = 0; x < MAP_COLS; ++x) { - struct MapTile tile = map.tiles[y][x]; + struct Meta meta = map.meta[y][x]; - double count = (tile.modifyCount && countMax > 1) - ? log(tile.modifyCount) / log(countMax) + double count = (meta.modifyCount && countMax > 1) + ? log(meta.modifyCount) / log(countMax) : 0.0; - double time = (tile.modifyTime && timeNow - timeMin) - ? (double)(tile.modifyTime - timeMin) / (double)(timeNow - timeMin) + double time = (meta.modifyTime && timeNow - timeMin) + ? (double)(meta.modifyTime - timeMin) / (double)(timeNow - timeMin) : 0.0; count *= ARRAY_LEN(MAP_CELLS) - 2; time *= ARRAY_LEN(MAP_COLORS) - 1; diff --git a/merge.c b/merge.c index 276d071..ea1326e 100644 --- a/merge.c +++ b/merge.c @@ -93,11 +93,11 @@ int main(int argc, char *argv[]) { if (!countA && !countB) break; if (!countA || !countB) errx(EX_DATAERR, "different size inputs"); - const struct Tile *tileC = (tileA.accessTime > tileB.accessTime) + const struct Tile *tileC = (tileA.meta.accessTime > tileB.meta.accessTime) ? &tileA : &tileB; - if (tileA.modifyTime != tileB.modifyTime) { + if (tileA.meta.modifyTime != tileB.meta.modifyTime) { drawTile(0, &tileA); drawTile(CELL_ROWS + 1, &tileB); move(CELL_ROWS * 2 + 2, 0); diff --git a/meta.c b/meta.c index 14a0930..ed55a8d 100644 --- a/meta.c +++ b/meta.c @@ -32,11 +32,11 @@ int main() { "%d,%d,%jd,%u,%jd,%u,%jd\n", i % TILE_COLS, i / TILE_COLS, - tile.createTime, - tile.modifyCount, - tile.modifyTime, - tile.accessCount, - tile.accessTime + tile.meta.createTime, + tile.meta.modifyCount, + tile.meta.modifyTime, + tile.meta.accessCount, + tile.meta.accessTime ); } } diff --git a/server.c b/server.c index 5b502ef..e565816 100644 --- a/server.c +++ b/server.c @@ -58,25 +58,25 @@ static void tilesMap(void) { static struct Tile *tileGet(uint32_t tileX, uint32_t tileY) { struct Tile *tile = &tiles[tileY * TILE_ROWS + tileX]; - if (!tile->createTime) { + if (!tile->meta.createTime) { memset(tile->cells, ' ', CELLS_SIZE); memset(tile->colors, COLOR_WHITE, CELLS_SIZE); - tile->createTime = time(NULL); + tile->meta.createTime = time(NULL); } return tile; } static struct Tile *tileAccess(uint32_t tileX, uint32_t tileY) { struct Tile *tile = tileGet(tileX, tileY); - tile->accessTime = time(NULL); - tile->accessCount++; + tile->meta.accessTime = time(NULL); + tile->meta.accessCount++; return tile; } static struct Tile *tileModify(uint32_t tileX, uint32_t tileY) { struct Tile *tile = tileGet(tileX, tileY); - tile->modifyTime = time(NULL); - tile->modifyCount++; + tile->meta.modifyTime = time(NULL); + tile->meta.modifyCount++; return tile; } @@ -282,15 +282,7 @@ static bool clientMap(const struct Client *client) { for (int32_t x = 0; x < MAP_COLS; ++x) { uint32_t tileY = ((mapY + y) % TILE_ROWS + TILE_ROWS) % TILE_ROWS; uint32_t tileX = ((mapX + x) % TILE_COLS + TILE_COLS) % TILE_COLS; - - const struct Tile *tile = &tiles[tileY * TILE_ROWS + tileX]; - map.tiles[y][x] = (struct MapTile) { - .createTime = tile->createTime, - .modifyTime = tile->modifyTime, - .accessTime = tile->accessTime, - .modifyCount = tile->modifyCount, - .accessCount = tile->accessCount, - }; + map.meta[y][x] = tiles[tileY * TILE_ROWS + tileX].meta; } } diff --git a/torus.h b/torus.h index 26204f3..9c047b9 100644 --- a/torus.h +++ b/torus.h @@ -48,7 +48,7 @@ enum { }; enum { - CELL_ROWS = 25, + CELL_ROWS = 24, CELL_COLS = 80, }; static const size_t CELLS_SIZE = sizeof(char[CELL_ROWS][CELL_COLS]); @@ -56,22 +56,24 @@ static const size_t CELLS_SIZE = sizeof(char[CELL_ROWS][CELL_COLS]); static const uint8_t CELL_INIT_X = CELL_COLS / 2; static const uint8_t CELL_INIT_Y = CELL_ROWS / 2; -struct ALIGNED(4096) Tile { +struct Meta { time_t createTime; time_t modifyTime; - char ALIGNED(16) cells[CELL_ROWS][CELL_COLS]; - uint8_t ALIGNED(16) colors[CELL_ROWS][CELL_COLS]; + time_t accessTime; uint32_t modifyCount; uint32_t accessCount; - time_t accessTime; +}; + +struct ALIGNED(4096) Tile { + char cells[CELL_ROWS][CELL_COLS]; + uint8_t colors[CELL_ROWS][CELL_COLS]; + struct Meta meta; }; static_assert(4096 == sizeof(struct Tile), "struct Tile is page-sized"); -static_assert(16 == offsetof(struct Tile, cells), "stable cells offset"); -static_assert(2016 == offsetof(struct Tile, colors), "stable colors offset"); enum { - TILE_ROWS = 512, - TILE_COLS = 512, + TILE_ROWS = 64, + TILE_COLS = 64, }; static const size_t TILES_SIZE = sizeof(struct Tile[TILE_ROWS][TILE_COLS]); @@ -84,13 +86,7 @@ enum { }; struct Map { - struct MapTile { - time_t createTime; - time_t modifyTime; - time_t accessTime; - uint32_t modifyCount; - uint32_t accessCount; - } tiles[MAP_ROWS][MAP_COLS]; + struct Meta meta[MAP_ROWS][MAP_COLS]; }; struct ServerMessage { -- cgit 1.4.1 From a2353335a28e5b3d185a2dfbe5380f134fe59725 Mon Sep 17 00:00:00 2001 From: Curtis McEnroe Date: Tue, 21 Aug 2018 15:38:38 -0400 Subject: Use alignas rather than attributes --- torus.h | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'torus.h') diff --git a/torus.h b/torus.h index 9c047b9..775670c 100644 --- a/torus.h +++ b/torus.h @@ -15,15 +15,13 @@ */ #include +#include #include #include #include #include #include -#define PACKED __attribute__((packed)) -#define ALIGNED(x) __attribute__((aligned(x))) - #define ARRAY_LEN(a) (sizeof(a) / sizeof((a)[0])) #undef COLOR_BLACK @@ -64,8 +62,8 @@ struct Meta { uint32_t accessCount; }; -struct ALIGNED(4096) Tile { - char cells[CELL_ROWS][CELL_COLS]; +struct Tile { + alignas(4096) char cells[CELL_ROWS][CELL_COLS]; uint8_t colors[CELL_ROWS][CELL_COLS]; struct Meta meta; }; @@ -90,7 +88,7 @@ struct Map { }; struct ServerMessage { - enum PACKED { + enum { SERVER_TILE, SERVER_MOVE, SERVER_PUT, @@ -120,7 +118,7 @@ struct ServerMessage { static const uint8_t CURSOR_NONE = UINT8_MAX; struct ClientMessage { - enum PACKED { + enum { CLIENT_MOVE, CLIENT_PUT, CLIENT_MAP, -- cgit 1.4.1 From 0c8fb2b9fe779bdb7ba85c8458d4efc0034fb77b Mon Sep 17 00:00:00 2001 From: Curtis McEnroe Date: Tue, 21 Aug 2018 22:46:18 -0400 Subject: Replace client with rudimentary CP437 support --- Makefile | 3 +- client.c | 614 +++++++++++++++++++++++---------------------------------------- server.c | 2 +- torus.h | 28 ++- 4 files changed, 246 insertions(+), 401 deletions(-) (limited to 'torus.h') diff --git a/Makefile b/Makefile index 4091276..f2b2ca0 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ CHROOT_USER = torus CHROOT_GROUP = $(CHROOT_USER) CFLAGS += -Wall -Wextra -Wpedantic -LDLIBS = -lm -lcurses +LDLIBS = -lm -lcursesw BINS = server client help meta merge OBJS = $(BINS:%=%.o) @@ -32,6 +32,7 @@ chroot.tar: server client help /lib/libncurses.so.8 \ /lib/libncursesw.so.8 \ root/lib + cp -a -f /usr/share/locale root/usr/share cp -p -f /usr/share/misc/termcap.db root/usr/share/misc cp -p -f /bin/sh root/bin install -o root -g wheel -m 555 server client help root/bin diff --git a/client.c b/client.c index 37cc7ce..ad0bc8e 100644 --- a/client.c +++ b/client.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2017 Curtis McEnroe +/* Copyright (C) 2018 Curtis McEnroe * * 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 @@ -14,12 +14,14 @@ * along with this program. If not, see . */ -#include +#define _XOPEN_SOURCE_EXTENDED + #include #include #include -#include +#include #include +#include #include #include #include @@ -27,43 +29,42 @@ #include #include #include +#include +#include #include "torus.h" +#define err(...) do { endwin(); err(__VA_ARGS__); } while(0) +#define errx(...) do { endwin(); errx(__VA_ARGS__); } while (0) + +#define CTRL(ch) ((ch) ^ 0x40) enum { ESC = 0x1B, DEL = 0x7F, }; -static int client; - -static void clientMessage(struct ClientMessage msg) { - ssize_t size = send(client, &msg, sizeof(msg), 0); - if (size < 0) err(EX_IOERR, "send"); -} - -static void clientMove(int8_t dx, int8_t dy) { - struct ClientMessage msg = { - .type = CLIENT_MOVE, - .move = { .dx = dx, .dy = dy }, - }; - clientMessage(msg); -} - -static void clientPut(uint8_t color, char cell) { - struct ClientMessage msg = { - .type = CLIENT_PUT, - .put = { .color = color, .cell = cell }, - }; - clientMessage(msg); -} +static void curse(void) { + setlocale(LC_CTYPE, ""); -static void clientMap(void) { - struct ClientMessage msg = { .type = CLIENT_MAP }; - clientMessage(msg); -} + initscr(); + start_color(); + if (!has_colors() || COLOR_PAIRS < 64) { + endwin(); + fprintf(stderr, "Sorry, your terminal doesn't support colors!\n"); + fprintf(stderr, "If you think it should, check TERM.\n"); + exit(EX_CONFIG); + } + if (LINES < CELL_ROWS || COLS < CELL_COLS) { + endwin(); + fprintf( + stderr, + "Sorry, your terminal is too small!\n" + "It must be at least %ux%u characters.\n", + CELL_COLS, CELL_ROWS + ); + exit(EX_CONFIG); + } -static void colorPairs(void) { assume_default_colors(0, 0); if (COLORS >= 16) { for (short pair = 1; pair < 0x80; ++pair) { @@ -74,421 +75,243 @@ static void colorPairs(void) { init_pair(pair, pair & 007, (pair & 070) >> 3); } } -} -static chtype colorAttr(uint8_t color) { - if (COLORS >= 16) return COLOR_PAIR(color); - chtype bold = (color & COLOR_BRIGHT) ? A_BOLD : A_NORMAL; - short pair = (color & 0x70) >> 1 | (color & 0x07); - return bold | COLOR_PAIR(pair); -} + color_set(COLOR_WHITE, NULL); + bool hline = (LINES > CELL_ROWS); + bool vline = (COLS > CELL_COLS); + if (hline) mvhline(CELL_ROWS, 0, 0, CELL_COLS); + if (vline) mvvline(0, CELL_COLS, 0, CELL_ROWS); + if (hline && vline) mvaddch(CELL_ROWS, CELL_COLS, ACS_LRCORNER); -static uint8_t attrColor(chtype attr) { - if (COLORS >= 16) return PAIR_NUMBER(attr); - uint8_t bright = (attr & A_BOLD) ? COLOR_BRIGHT : 0; - short pair = PAIR_NUMBER(attr); - return (pair & 070) << 1 | bright | (pair & 007); + cbreak(); + noecho(); + keypad(stdscr, true); + set_escdelay(100); } -static struct { - int8_t speed; - uint8_t color; - enum { - MODE_NORMAL, - MODE_MAP, - MODE_INSERT, - MODE_REPLACE, - MODE_PUT, - MODE_DRAW, - } mode; - int8_t dx; - int8_t dy; - uint8_t len; - char draw; -} input = { - .speed = 1, - .color = COLOR_WHITE, - .dx = 1, -}; - -static void colorFg(uint8_t fg) { - input.color = (input.color & 0xF8) | fg; +static attr_t colorAttr(uint8_t color) { + if (COLORS >= 16) return A_NORMAL; + return (color & COLOR_BRIGHT) ? A_BOLD : A_NORMAL; } - -static void colorBg(uint8_t bg) { - input.color = (input.color & 0x0F) | (bg << 4); +static short colorPair(uint8_t color) { + if (COLORS >= 16) return color; + return (color & 0x70) >> 1 | (color & 0x07); } -static void colorInvert(void) { - input.color = - (input.color & 0x08) | - ((input.color & 0x07) << 4) | - ((input.color & 0x70) >> 4); +static void put(uint8_t cellX, uint8_t cellY, uint8_t color, uint8_t cell) { + cchar_t cch; + wchar_t wch[] = { CP437[cell], L'\0' }; + setcchar(&cch, wch, colorAttr(color), colorPair(color), NULL); + mvadd_wch(cellY, cellX, &cch); } -static void insertMode(int8_t dx, int8_t dy) { - input.mode = MODE_INSERT; - input.dx = dx; - input.dy = dy; - input.len = 0; -} +static int client; -static void swapCell(int8_t dx, int8_t dy) { - uint8_t aColor = attrColor(inch()); - char aCell = inch() & A_CHARTEXT; +static void serverTile(void) { + struct Tile tile; + ssize_t size = recv(client, &tile, sizeof(tile), 0); + if (size < 0) err(EX_IOERR, "recv"); + if ((size_t)size < sizeof(tile)) errx(EX_PROTOCOL, "truncated tile"); - int sy, sx; - getyx(stdscr, sy, sx); - move(sy + dy, sx + dx); - uint8_t bColor = attrColor(inch()); - char bCell = inch() & A_CHARTEXT; - move(sy, sx); + for (uint8_t cellY = 0; cellY < CELL_ROWS; ++cellY) { + for (uint8_t cellX = 0; cellX < CELL_COLS; ++cellX) { + put(cellX, cellY, tile.colors[cellY][cellX], tile.cells[cellY][cellX]); + } + } +} - clientPut(bColor, bCell); - clientMove(dx, dy); - clientPut(aColor, aCell); +static void serverPut(struct ServerMessage msg) { + put(msg.put.cellX, msg.put.cellY, msg.put.color, msg.put.cell); } -static void inputNormal(int c) { - switch (c) { - break; case ESC: input.mode = MODE_NORMAL; +static void serverCursor(struct ServerMessage msg) { +} - break; case 'q': endwin(); exit(EX_OK); - break; case 'm': clientMap(); +static void serverMap(void) { +} - break; case 'i': insertMode(1, 0); - break; case 'a': clientMove(1, 0); insertMode(1, 0); - break; case 'I': insertMode(0, 0); - break; case 'r': input.mode = MODE_REPLACE; - break; case 'p': input.mode = MODE_PUT; - break; case 'R': input.mode = MODE_DRAW; input.draw = 0; - break; case 'x': clientPut(attrColor(inch()), ' '); - - break; case '~': { - clientPut(input.color, inch() & A_CHARTEXT); - clientMove(input.dx, input.dy); - } +static void readMessage(void) { + struct ServerMessage msg; + ssize_t size = recv(client, &msg, sizeof(msg), 0); + if (size < 0) err(EX_IOERR, "recv"); + if ((size_t)size < sizeof(msg)) errx(EX_PROTOCOL, "truncated message"); - break; case '[': if (input.speed > 1) input.speed--; - break; case ']': if (input.speed < 4) input.speed++; - - break; case 'h': clientMove(-input.speed, 0); - break; case 'j': clientMove( 0, input.speed); - break; case 'k': clientMove( 0, -input.speed); - break; case 'l': clientMove( input.speed, 0); - break; case 'y': clientMove(-input.speed, -input.speed); - break; case 'u': clientMove( input.speed, -input.speed); - break; case 'b': clientMove(-input.speed, input.speed); - break; case 'n': clientMove( input.speed, input.speed); - - break; case 'H': swapCell(-1, 0); - break; case 'J': swapCell( 0, 1); - break; case 'K': swapCell( 0, -1); - break; case 'L': swapCell( 1, 0); - break; case 'Y': swapCell(-1, -1); - break; case 'U': swapCell( 1, -1); - break; case 'B': swapCell(-1, 1); - break; case 'N': swapCell( 1, 1); - - break; case '`': input.color = attrColor(inch()); - - break; case '0': colorFg(COLOR_BLACK); - break; case '1': colorFg(COLOR_RED); - break; case '2': colorFg(COLOR_GREEN); - break; case '3': colorFg(COLOR_YELLOW); - break; case '4': colorFg(COLOR_BLUE); - break; case '5': colorFg(COLOR_MAGENTA); - break; case '6': colorFg(COLOR_CYAN); - break; case '7': colorFg(COLOR_WHITE); - - break; case ')': colorBg(COLOR_BLACK); - break; case '!': colorBg(COLOR_RED); - break; case '@': colorBg(COLOR_GREEN); - break; case '#': colorBg(COLOR_YELLOW); - break; case '$': colorBg(COLOR_BLUE); - break; case '%': colorBg(COLOR_MAGENTA); - break; case '^': colorBg(COLOR_CYAN); - break; case '&': colorBg(COLOR_WHITE); - - break; case '*': case '8': input.color ^= COLOR_BRIGHT; - - break; case '(': case '9': colorInvert(); - - break; case KEY_LEFT: clientMove(-1, 0); - break; case KEY_DOWN: clientMove( 0, 1); - break; case KEY_UP: clientMove( 0, -1); - break; case KEY_RIGHT: clientMove( 1, 0); + int y, x; + getyx(stdscr, y, x); + switch (msg.type) { + break; case SERVER_TILE: serverTile(); + break; case SERVER_MOVE: y = msg.move.cellY; x = msg.move.cellX; + break; case SERVER_PUT: serverPut(msg); + break; case SERVER_CURSOR: serverCursor(msg); + break; case SERVER_MAP: serverMap(); + break; default: errx(EX_PROTOCOL, "unknown message type %d", msg.type); } + move(y, x); } -static void inputMap(void) { - input.mode = MODE_NORMAL; - curs_set(1); - touchwin(stdscr); +static void clientMessage(struct ClientMessage msg) { + ssize_t size = send(client, &msg, sizeof(msg), 0); + if (size < 0) err(EX_IOERR, "send"); } -static void inputInsert(int c) { - if (c == ESC) { - input.mode = MODE_NORMAL; - clientMove(-input.dx, -input.dy); - } else if (!input.dx && !input.dy) { - switch (c) { - break; case 'h': insertMode(-1, 0); - break; case 'j': insertMode( 0, 1); - break; case 'k': insertMode( 0, -1); - break; case 'l': insertMode( 1, 0); - break; case 'y': insertMode(-1, -1); - break; case 'u': insertMode( 1, -1); - break; case 'b': insertMode(-1, 1); - break; case 'n': insertMode( 1, 1); - } - } else if (c == '\b' || c == DEL) { - clientMove(-input.dx, -input.dy); - clientPut(input.color, ' '); - input.len--; - } else if (c == '\n') { - clientMove(input.dy, input.dx); - clientMove(-input.dx * input.len, -input.dy * input.len); - input.len = 0; - } else if (isprint(c)) { - clientPut(input.color, c); - clientMove(input.dx, input.dy); - input.len++; - } +static void clientMove(int8_t dx, int8_t dy) { + struct ClientMessage msg = { + .type = CLIENT_MOVE, + .move = { .dx = dx, .dy = dy }, + }; + clientMessage(msg); } -static void inputReplace(int c) { - if (isprint(c)) clientPut(attrColor(inch()), c); - input.mode = MODE_NORMAL; +static void clientPut(uint8_t color, uint8_t cell) { + struct ClientMessage msg = { + .type = CLIENT_PUT, + .put = { .color = color, .cell = cell }, + }; + clientMessage(msg); } -static void inputPut(int c) { - if (isprint(c)) clientPut(input.color, c); - input.mode = MODE_NORMAL; +static void clientMap(void) { + struct ClientMessage msg = { .type = CLIENT_MAP }; + clientMessage(msg); } -static void inputDraw(int c) { - if (input.draw) { - inputNormal(c); - clientPut(input.color, input.draw); - } else if (isprint(c)) { - input.draw = c; - clientPut(input.color, c); - } else if (c == ESC) { - input.mode = MODE_NORMAL; - } -} +static struct { + enum { + MODE_NORMAL, + MODE_INSERT, + } mode; + uint8_t color; + uint8_t shift; +} input; -static void readInput(void) { - int c = getch(); - switch (input.mode) { - break; case MODE_NORMAL: inputNormal(c); - break; case MODE_MAP: inputMap(); - break; case MODE_INSERT: inputInsert(c); - break; case MODE_REPLACE: inputReplace(c); - break; case MODE_PUT: inputPut(c); - break; case MODE_DRAW: inputDraw(c); - } -} +static struct { + int8_t dx; + int8_t dy; + uint8_t len; +} insert; -static void serverPut(uint8_t x, uint8_t y, uint8_t color, char cell) { - mvaddch(y, x, colorAttr(color) | cell); +static void insertMode(int8_t dx, int8_t dy) { + input.mode = MODE_INSERT; + insert.dx = dx; + insert.dy = dy; + insert.len = 0; } -static void serverTile(void) { - struct Tile tile; - ssize_t size = recv(client, &tile, sizeof(tile), 0); - if (size < 0) err(EX_IOERR, "recv"); - if ((size_t)size < sizeof(tile)) { - errx(EX_PROTOCOL, "This tile isn't big enough..."); - } - - for (int y = 0; y < CELL_ROWS; ++y) { - for (int x = 0; x < CELL_COLS; ++x) { - serverPut(x, y, tile.colors[y][x], tile.cells[y][x]); - } - } +static void inputFg(uint8_t fg) { + input.color = (input.color & 0x78) | (fg & 0x07); +} +static void inputBg(uint8_t bg) { + input.color = (input.color & 0x0F) | (bg & 0x07) << 4; +} +static void inputInvert(void) { + input.color = (input.color & 0x08) + | (input.color & 0x70) >> 4 + | (input.color & 0x07) << 4; } -static void serverCursor(uint8_t oldX, uint8_t oldY, uint8_t newX, uint8_t newY) { - if (oldX != CURSOR_NONE) { - move(oldY, oldX); - addch(inch() & ~A_REVERSE); - } - if (newX != CURSOR_NONE) { - move(newY, newX); - addch(inch() | A_REVERSE); +static uint8_t inputCell(wchar_t ch) { + if (ch < 0x7F) return (uint8_t)ch + input.shift; + for (size_t i = 0; i < ARRAY_LEN(CP437); ++i) { + if (ch == CP437[i]) return i; } + return 0; } -static WINDOW *mapFrame; -static WINDOW *mapWindow; - -static const char MAP_CELLS[] = " -~=+:$%#"; -static const uint8_t MAP_COLORS[] = { - COLOR_BLUE, COLOR_BRIGHT | COLOR_BLUE, - COLOR_CYAN, COLOR_BRIGHT | COLOR_CYAN, - COLOR_GREEN, COLOR_BRIGHT | COLOR_GREEN, - COLOR_YELLOW, COLOR_BRIGHT | COLOR_YELLOW, - COLOR_RED, COLOR_BRIGHT | COLOR_RED, - COLOR_MAGENTA, COLOR_BRIGHT | COLOR_MAGENTA, - COLOR_WHITE, COLOR_BRIGHT | COLOR_WHITE, -}; - -static void serverMap(void) { - struct Map map; - ssize_t size = recv(client, &map, sizeof(map), 0); - if (size < 0) err(EX_IOERR, "recv"); - if ((size_t)size < sizeof(map)) errx(EX_PROTOCOL, "This map is incomplete..."); - - uint32_t countMax = 0; - time_t timeNow = time(NULL); - time_t timeMin = timeNow; - for (int y = 0; y < MAP_ROWS; ++y) { - for (int x = 0; x < MAP_COLS; ++x) { - struct Meta meta = map.meta[y][x]; - if (countMax < meta.modifyCount) countMax = meta.modifyCount; - if (meta.modifyTime && timeMin > meta.modifyTime) { - timeMin = meta.modifyTime; - } +static void inputNormal(bool keyCode, wchar_t ch) { + if (keyCode) { + switch (ch) { + break; case KEY_LEFT: clientMove(-1, 0); + break; case KEY_RIGHT: clientMove( 1, 0); + break; case KEY_UP: clientMove( 0, -1); + break; case KEY_DOWN: clientMove( 0, 1); } + return; } - for (int y = 0; y < MAP_ROWS; ++y) { - for (int x = 0; x < MAP_COLS; ++x) { - struct Meta meta = map.meta[y][x]; - - double count = (meta.modifyCount && countMax > 1) - ? log(meta.modifyCount) / log(countMax) - : 0.0; - double time = (meta.modifyTime && timeNow - timeMin) - ? (double)(meta.modifyTime - timeMin) / (double)(timeNow - timeMin) - : 0.0; - count *= ARRAY_LEN(MAP_CELLS) - 2; - time *= ARRAY_LEN(MAP_COLORS) - 1; - - char cell = MAP_CELLS[(int)round(count)]; - chtype attr = colorAttr(MAP_COLORS[(int)round(time)]); - if (y == MAP_ROWS / 2 && x == MAP_COLS / 2) { - attr |= A_REVERSE; - } + switch (ch) { + break; case ESC: input.mode = MODE_NORMAL; + break; case 'q': endwin(); exit(EX_OK); - wmove(mapWindow, y, 3 * x); - waddch(mapWindow, attr | cell); - waddch(mapWindow, attr | cell); - waddch(mapWindow, attr | cell); - } - } + break; case 'h': clientMove(-1, 0); + break; case 'l': clientMove( 1, 0); + break; case 'k': clientMove( 0, -1); + break; case 'j': clientMove( 0, 1); + break; case 'y': clientMove(-1, -1); + break; case 'u': clientMove( 1, -1); + break; case 'b': clientMove(-1, 1); + break; case 'n': clientMove( 1, 1); + + break; case '0': inputFg(COLOR_BLACK); + break; case '1': inputFg(COLOR_RED); + break; case '2': inputFg(COLOR_GREEN); + break; case '3': inputFg(COLOR_YELLOW); + break; case '4': inputFg(COLOR_BLUE); + break; case '5': inputFg(COLOR_MAGENTA); + break; case '6': inputFg(COLOR_CYAN); + break; case '7': inputFg(COLOR_WHITE); + + break; case ')': inputBg(COLOR_BLACK); + break; case '!': inputBg(COLOR_RED); + break; case '@': inputBg(COLOR_GREEN); + break; case '#': inputBg(COLOR_YELLOW); + break; case '$': inputBg(COLOR_BLUE); + break; case '%': inputBg(COLOR_MAGENTA); + break; case '^': inputBg(COLOR_CYAN); + break; case '&': inputBg(COLOR_WHITE); + + break; case '8': case '*': input.color ^= COLOR_BRIGHT; + break; case '9': case '(': inputInvert(); + + break; case CTRL('P'): input.shift -= 0x20; + break; case CTRL('N'): input.shift += 0x20; - input.mode = MODE_MAP; - curs_set(0); + break; case 'i': insertMode(1, 0); + break; case 'a': clientMove(1, 0); insertMode(1, 0); + } } -static void readMessage(void) { - struct ServerMessage msg; - ssize_t size = recv(client, &msg, sizeof(msg), 0); - if (size < 0) err(EX_IOERR, "recv"); - if ((size_t)size < sizeof(msg)) errx(EX_PROTOCOL, "A message was cut short."); - - int sy, sx; - getyx(stdscr, sy, sx); - switch (msg.type) { - break; case SERVER_TILE: serverTile(); - break; case SERVER_MOVE: move(msg.move.cellY, msg.move.cellX); return; - break; case SERVER_PUT: { - serverPut( - msg.put.cellX, - msg.put.cellY, - msg.put.color, - msg.put.cell - ); +static void inputInsert(bool keyCode, wchar_t ch) { + if (keyCode) { + inputNormal(keyCode, ch); + return; + } + switch (ch) { + break; case ESC: { + input.mode = MODE_NORMAL; + clientMove(-insert.dx, -insert.dy); } - break; case SERVER_CURSOR: { - serverCursor( - msg.cursor.oldCellX, - msg.cursor.oldCellY, - msg.cursor.newCellX, - msg.cursor.newCellY - ); + break; case '\b': case DEL: { + clientMove(-insert.dx, -insert.dy); + clientPut(input.color, ' '); + insert.len--; } - break; case SERVER_MAP: serverMap(); - break; default: errx(EX_PROTOCOL, "I don't know what %d means!", msg.type); - } - move(sy, sx); -} + break; case '\n': { + clientMove(insert.dy, insert.dx); + clientMove(insert.len * -insert.dx, insert.len * -insert.dy); + insert.len = 0; + } + break; default: { + if (iswcntrl(ch)) { + inputNormal(false, ch); + break; + } -static void draw(void) { - wnoutrefresh(stdscr); - if (input.mode == MODE_MAP) { - touchwin(mapFrame); - touchwin(mapWindow); - wnoutrefresh(mapFrame); - wnoutrefresh(mapWindow); + uint8_t cell = inputCell(ch); + if (!cell) break; + clientPut(input.color, cell); + clientMove(insert.dx, insert.dy); + insert.len++; + } } - doupdate(); } -static void curse(void) { - initscr(); - cbreak(); - noecho(); - keypad(stdscr, true); - set_escdelay(100); - - if (!has_colors()) { - endwin(); - fprintf( - stderr, - "Sorry, your terminal doesn't support colors!\n" - "If you think it does, check TERM.\n" - ); - exit(EX_CONFIG); - } - start_color(); - if (COLOR_PAIRS < 64) { - endwin(); - fprintf( - stderr, - "Sorry, your terminal doesn't support enough color pairs!\n" - "If you think it does, check TERM.\n" - ); - exit(EX_CONFIG); - } - colorPairs(); - - if (LINES < CELL_ROWS || COLS < CELL_COLS) { - endwin(); - fprintf(stderr, "Sorry, your terminal is too small!\n"); - fprintf(stderr, "It needs to be at least 80x25 characters.\n"); - exit(EX_CONFIG); - } - - attrset(colorAttr(COLOR_WHITE)); - if (LINES > CELL_ROWS) { - mvhline(CELL_ROWS, 0, 0, CELL_COLS); - } - if (COLS > CELL_COLS) { - mvvline(0, CELL_COLS, 0, CELL_ROWS); - } - if (LINES > CELL_ROWS && COLS > CELL_COLS) { - mvaddch(CELL_ROWS, CELL_COLS, ACS_LRCORNER); +static void readInput(void) { + wint_t ch; + bool keyCode = (KEY_CODE_YES == get_wch(&ch)); + switch (input.mode) { + break; case MODE_NORMAL: inputNormal(keyCode, ch); + break; case MODE_INSERT: inputInsert(keyCode, ch); } - attrset(A_NORMAL); - - mapFrame = newwin( - MAP_ROWS + 2, - 3 * MAP_COLS + 2, - CELL_INIT_Y - MAP_ROWS / 2 - 1, - CELL_INIT_X - 3 * MAP_COLS / 2 - 1 - ); - mapWindow = newwin( - MAP_ROWS, - 3 * MAP_COLS, - CELL_INIT_Y - MAP_ROWS / 2, - CELL_INIT_X - 3 * MAP_COLS / 2 - ); - wattrset(mapFrame, colorAttr(COLOR_WHITE)); - box(mapFrame, 0, 0); } int main() { @@ -515,6 +338,7 @@ int main() { if (fds[0].revents) readInput(); if (fds[1].revents) readMessage(); - draw(); + + refresh(); } } diff --git a/server.c b/server.c index e565816..9486fcd 100644 --- a/server.c +++ b/server.c @@ -254,7 +254,7 @@ static bool clientMove(struct Client *client, int8_t dx, int8_t dy) { return true; } -static bool clientPut(const struct Client *client, uint8_t color, char cell) { +static bool clientPut(const struct Client *client, uint8_t color, uint8_t cell) { struct Tile *tile = tileModify(client->tileX, client->tileY); tile->colors[client->cellY][client->cellX] = color; tile->cells[client->cellY][client->cellX] = cell; diff --git a/torus.h b/torus.h index 775670c..53e469c 100644 --- a/torus.h +++ b/torus.h @@ -21,6 +21,7 @@ #include #include #include +#include #define ARRAY_LEN(a) (sizeof(a) / sizeof((a)[0])) @@ -45,11 +46,30 @@ enum { COLOR_BRIGHT, }; +static const wchar_t CP437[256] = ( + L" ☺☻♥♦♣♠•◘○◙♂♀♪♫☼" + L"►◄↕‼¶§▬↨↑↓→←∟↔▲▼" + L" !\"#$%&'()*+,-./" + L"0123456789:;<=>?" + L"@ABCDEFGHIJKLMNO" + L"PQRSTUVWXYZ[\\]^_" + L"`abcdefghijklmno" + L"pqrstuvwxyz{|}~⌂" + L"ÇüéâäàåçêëèïîìÄÅ" + L"ÉæÆôöòûùÿÖÜ¢£¥₧ƒ" + L"áíóúñѪº¿⌐¬½¼¡«»" + L"░▒▓│┤╡╢╖╕╣║╗╝╜╛┐" + L"└┴┬├─┼╞╟╚╔╩╦╠═╬╧" + L"╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀" + L"αßΓπΣσµτΦΘΩδ∞φε∩" + L"≡±≥≤⌠⌡÷≈°∙·√ⁿ²■ " +); + enum { CELL_ROWS = 24, CELL_COLS = 80, }; -static const size_t CELLS_SIZE = sizeof(char[CELL_ROWS][CELL_COLS]); +static const size_t CELLS_SIZE = sizeof(uint8_t[CELL_ROWS][CELL_COLS]); static const uint8_t CELL_INIT_X = CELL_COLS / 2; static const uint8_t CELL_INIT_Y = CELL_ROWS / 2; @@ -63,7 +83,7 @@ struct Meta { }; struct Tile { - alignas(4096) char cells[CELL_ROWS][CELL_COLS]; + alignas(4096) uint8_t cells[CELL_ROWS][CELL_COLS]; uint8_t colors[CELL_ROWS][CELL_COLS]; struct Meta meta; }; @@ -104,7 +124,7 @@ struct ServerMessage { uint8_t cellX; uint8_t cellY; uint8_t color; - char cell; + uint8_t cell; } put; struct { uint8_t oldCellX; @@ -130,7 +150,7 @@ struct ClientMessage { } move; struct { uint8_t color; - char cell; + uint8_t cell; } put; }; }; -- cgit 1.4.1 From 97216e7486e887e640f3c3a1b713278d7e97e15c Mon Sep 17 00:00:00 2001 From: Curtis McEnroe Date: Thu, 23 Aug 2018 15:33:56 -0400 Subject: Add g for flip --- client.c | 6 ++++ server.c | 96 +++++++++++++++++++++++++++++++++++++--------------------------- torus.h | 1 + 3 files changed, 62 insertions(+), 41 deletions(-) (limited to 'torus.h') diff --git a/client.c b/client.c index 28ccc4e..e0286eb 100644 --- a/client.c +++ b/client.c @@ -179,6 +179,11 @@ static void clientMove(int8_t dx, int8_t dy) { clientMessage(msg); } +static void clientFlip(void) { + struct ClientMessage msg = { .type = CLIENT_FLIP }; + clientMessage(msg); +} + static void clientPut(uint8_t color, uint8_t cell) { struct ClientMessage msg = { .type = CLIENT_PUT, @@ -277,6 +282,7 @@ static void inputNormal(wchar_t ch) { break; case ESC: input.mode = MODE_NORMAL; input.shift = 0; break; case 'q': endwin(); exit(EX_OK); + break; case 'g': clientFlip(); break; case 'h': clientMove(-1, 0); break; case 'l': clientMove( 1, 0); break; case 'k': clientMove( 0, -1); diff --git a/server.c b/server.c index 9486fcd..73cd9f1 100644 --- a/server.c +++ b/server.c @@ -172,6 +172,51 @@ static bool clientCursors(const struct Client *client) { return true; } +static bool clientUpdate(struct Client *client, const struct Client *old) { + struct ServerMessage msg = { + .type = SERVER_MOVE, + .move = { .cellX = client->cellX, .cellY = client->cellY }, + }; + if (!clientSend(client, msg)) return false; + + if (client->tileX != old->tileX || client->tileY != old->tileY) { + msg.type = SERVER_TILE; + if (!clientSend(client, msg)) return false; + + if (!clientCursors(client)) return false; + + msg = (struct ServerMessage) { + .type = SERVER_CURSOR, + .cursor = { + .oldCellX = old->cellX, .oldCellY = old->cellY, + .newCellX = CURSOR_NONE, .newCellY = CURSOR_NONE, + }, + }; + clientCast(old, msg); + + msg = (struct ServerMessage) { + .type = SERVER_CURSOR, + .cursor = { + .oldCellX = CURSOR_NONE, .oldCellY = CURSOR_NONE, + .newCellX = client->cellX, .newCellY = client->cellY, + }, + }; + clientCast(client, msg); + + } else { + msg = (struct ServerMessage) { + .type = SERVER_CURSOR, + .cursor = { + .oldCellX = old->cellX, .oldCellY = old->cellY, + .newCellX = client->cellX, .newCellY = client->cellY, + }, + }; + clientCast(client, msg); + } + + return true; +} + static bool clientMove(struct Client *client, int8_t dx, int8_t dy) { struct Client old = *client; @@ -210,48 +255,14 @@ static bool clientMove(struct Client *client, int8_t dx, int8_t dy) { assert(client->tileX < TILE_COLS); assert(client->tileY < TILE_ROWS); - struct ServerMessage msg = { - .type = SERVER_MOVE, - .move = { .cellX = client->cellX, .cellY = client->cellY }, - }; - if (!clientSend(client, msg)) return false; - - if (client->tileX != old.tileX || client->tileY != old.tileY) { - msg.type = SERVER_TILE; - if (!clientSend(client, msg)) return false; - - if (!clientCursors(client)) return false; - - msg = (struct ServerMessage) { - .type = SERVER_CURSOR, - .cursor = { - .oldCellX = old.cellX, .oldCellY = old.cellY, - .newCellX = CURSOR_NONE, .newCellY = CURSOR_NONE, - }, - }; - clientCast(&old, msg); - - msg = (struct ServerMessage) { - .type = SERVER_CURSOR, - .cursor = { - .oldCellX = CURSOR_NONE, .oldCellY = CURSOR_NONE, - .newCellX = client->cellX, .newCellY = client->cellY, - }, - }; - clientCast(client, msg); - - } else { - msg = (struct ServerMessage) { - .type = SERVER_CURSOR, - .cursor = { - .oldCellX = old.cellX, .oldCellY = old.cellY, - .newCellX = client->cellX, .newCellY = client->cellY, - }, - }; - clientCast(client, msg); - } + return clientUpdate(client, &old); +} - return true; +static bool clientFlip(struct Client *client) { + struct Client old = *client; + client->tileX = (client->tileX + TILE_COLS / 2) % TILE_COLS; + client->tileY = (client->tileY + TILE_ROWS / 2) % TILE_ROWS; + return clientUpdate(client, &old); } static bool clientPut(const struct Client *client, uint8_t color, uint8_t cell) { @@ -371,6 +382,9 @@ int main() { break; case CLIENT_MOVE: { success = clientMove(client, msg.move.dx, msg.move.dy); } + break; case CLIENT_FLIP: { + success = clientFlip(client); + } break; case CLIENT_PUT: { success = clientPut(client, msg.put.color, msg.put.cell); } diff --git a/torus.h b/torus.h index 53e469c..818f009 100644 --- a/torus.h +++ b/torus.h @@ -140,6 +140,7 @@ static const uint8_t CURSOR_NONE = UINT8_MAX; struct ClientMessage { enum { CLIENT_MOVE, + CLIENT_FLIP, CLIENT_PUT, CLIENT_MAP, } type; -- cgit 1.4.1 From a015f73a754ae6cbfb267a050770c94374fc908c Mon Sep 17 00:00:00 2001 From: Curtis McEnroe Date: Sat, 25 Aug 2018 00:39:43 -0400 Subject: Calculate min and max meta for map server-side --- server.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++-- torus.h | 2 ++ 2 files changed, 53 insertions(+), 2 deletions(-) (limited to 'torus.h') diff --git a/server.c b/server.c index 73cd9f1..d01332f 100644 --- a/server.c +++ b/server.c @@ -288,12 +288,61 @@ static bool clientMap(const struct Client *client) { int32_t mapY = (int32_t)client->tileY - MAP_ROWS / 2; int32_t mapX = (int32_t)client->tileX - MAP_COLS / 2; - struct Map map; + time_t now = time(NULL); + struct Map map = { + .min = { + .createTime = now, + .modifyTime = now, + .accessTime = now, + .modifyCount = UINT32_MAX, + .accessCount = UINT32_MAX, + }, + }; + for (int32_t y = 0; y < MAP_ROWS; ++y) { for (int32_t x = 0; x < MAP_COLS; ++x) { uint32_t tileY = ((mapY + y) % TILE_ROWS + TILE_ROWS) % TILE_ROWS; uint32_t tileX = ((mapX + x) % TILE_COLS + TILE_COLS) % TILE_COLS; - map.meta[y][x] = tiles[tileY * TILE_ROWS + tileX].meta; + struct Meta meta = tiles[tileY * TILE_ROWS + tileX].meta; + + if (meta.createTime) { + if (meta.createTime < map.min.createTime) { + map.min.createTime = meta.createTime; + } + if (meta.createTime > map.max.createTime) { + map.max.createTime = meta.createTime; + } + } + if (meta.modifyTime) { + if (meta.modifyTime < map.min.modifyTime) { + map.min.modifyTime = meta.modifyTime; + } + if (meta.modifyTime > map.max.modifyTime) { + map.max.modifyTime = meta.modifyTime; + } + } + if (meta.accessTime) { + if (meta.accessTime < map.min.accessTime) { + map.min.accessTime = meta.accessTime; + } + if (meta.accessTime > map.max.accessTime) { + map.max.accessTime = meta.accessTime; + } + } + if (meta.modifyCount < map.min.modifyCount) { + map.min.modifyCount = meta.modifyCount; + } + if (meta.modifyCount > map.max.modifyCount) { + map.max.modifyCount = meta.modifyCount; + } + if (meta.accessCount < map.min.accessCount) { + map.min.accessCount = meta.accessCount; + } + if (meta.accessCount > map.max.accessCount) { + map.max.accessCount = meta.accessCount; + } + + map.meta[y][x] = meta; } } diff --git a/torus.h b/torus.h index 818f009..a83cac0 100644 --- a/torus.h +++ b/torus.h @@ -104,6 +104,8 @@ enum { }; struct Map { + struct Meta min; + struct Meta max; struct Meta meta[MAP_ROWS][MAP_COLS]; }; -- cgit 1.4.1 From c92e9c288a8e4c6faad54daec07d7ac9aff43a86 Mon Sep 17 00:00:00 2001 From: Curtis McEnroe Date: Sat, 25 Aug 2018 00:44:51 -0400 Subject: Send now in map --- server.c | 1 + torus.h | 1 + 2 files changed, 2 insertions(+) (limited to 'torus.h') diff --git a/server.c b/server.c index d01332f..08b8dd1 100644 --- a/server.c +++ b/server.c @@ -290,6 +290,7 @@ static bool clientMap(const struct Client *client) { time_t now = time(NULL); struct Map map = { + .now = now, .min = { .createTime = now, .modifyTime = now, diff --git a/torus.h b/torus.h index a83cac0..ad7953d 100644 --- a/torus.h +++ b/torus.h @@ -104,6 +104,7 @@ enum { }; struct Map { + time_t now; struct Meta min; struct Meta max; struct Meta meta[MAP_ROWS][MAP_COLS]; -- cgit 1.4.1 From 4e98681f34befccf16af73a29dc154365b9d282e Mon Sep 17 00:00:00 2001 From: Curtis McEnroe Date: Sat, 25 Aug 2018 01:03:20 -0400 Subject: Shrink map --- torus.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'torus.h') diff --git a/torus.h b/torus.h index ad7953d..62994b9 100644 --- a/torus.h +++ b/torus.h @@ -99,8 +99,8 @@ static const uint32_t TILE_INIT_X = TILE_COLS / 2; static const uint32_t TILE_INIT_Y = TILE_ROWS / 2; enum { - MAP_ROWS = 11, - MAP_COLS = 11, + MAP_ROWS = 7, + MAP_COLS = 7, }; struct Map { -- cgit 1.4.1