Introduction
Introduction Statistics Contact Development Disclaimer Help
UI: Add pazz0's dungeon-crawler-like interface - sacc - sacc(omys), simple cons…
git clone git://bitreich.org/sacc/ git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65…
Log
Files
Refs
Tags
LICENSE
---
commit d16bb53db353da7b817b18809adf57b57c4f973e
parent 0fce134e1baa2ae47aeb0ee7c091e6c25651bcea
Author: Quentin Rameau <[email protected]>
Date: Thu, 28 Mar 2024 12:13:51 +0100
UI: Add pazz0's dungeon-crawler-like interface
This definitely looks fun and interesting
Diffstat:
A ui_rogue.c | 938 +++++++++++++++++++++++++++++…
1 file changed, 938 insertions(+), 0 deletions(-)
---
diff --git a/ui_rogue.c b/ui_rogue.c
@@ -0,0 +1,938 @@
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <term.h>
+#include <termios.h>
+#include <unistd.h>
+#include <sys/types.h>
+
+#include "common.h"
+#include "config.h"
+
+#define C(c) #c
+#define S(c) C(c)
+
+/* ncurses doesn't define those in term.h, where they're used */
+#ifndef OK
+#define OK (0)
+#endif
+#ifndef ERR
+#define ERR (-1)
+#endif
+
+static struct termios tsave;
+static struct termios tsacc;
+static Item *curentry;
+static int termset = ERR;
+static char bufout[256];
+static char bufout2[256];
+
+void drawscreen(void);
+
+uint32_t
+fnv1a(int n,...)
+{
+ int i;
+ char *s;
+ va_list l;
+ uint32_t h;
+
+ h = 0x811c9dc5;
+
+ va_start(l, n);
+ for (i = 0; i < n; i++) {
+ for (s = va_arg(l, char*); *s; s++) {
+ h ^= *s;
+ h *= 0x01000193;
+ }
+ }
+ va_end(l);
+
+ return h;
+}
+
+uint32_t
+xorshift(uint32_t *s)
+{
+ *s ^= *s << 13;
+ *s ^= *s >> 17;
+ *s ^= *s << 5;
+ return *s;
+}
+
+struct cell {
+ char c;
+ size_t nitems;
+ Item **items;
+};
+
+#define MAPHEIGHT (25)
+#define MAPWIDTH (80)
+struct cell map[MAPHEIGHT][MAPWIDTH];
+
+struct room {
+ struct room *p;
+ void *d;
+ size_t x, y;
+ size_t w, h;
+};
+
+struct rect {
+ struct rect *next, *next2;
+ struct room *room;
+ size_t x1, y1;
+ size_t x2, y2;
+ size_t d;
+};
+
+struct rect *
+randomneighbor(struct rect *x, struct rect *rs, uint32_t *prng)
+{
+ struct rect *r, *result;
+ size_t n;
+
+ n = 0;
+ result = NULL;
+ for (r = rs; r; r = r->next) {
+ if (r->y2 < x->y1 || r->y1 > x->y2 || r->x2 < x->x1 || r->x1 >…
+ continue;
+ if ((r->y2 == x->y1 || r->y1 == x->y2) && (r->x2 == x->x1 || r…
+ continue;
+ n++;
+ if (xorshift(prng) / (1. + UINT32_MAX) < 1. / n)
+ result = r;
+ }
+
+ return result;
+}
+
+#define ROOM_HEIGHT_MIN 3
+#define ROOM_WIDTH_MIN 5
+#define ROOM_MARGIN_MIN 1
+#define CELL_HEIGHT_MIN (ROOM_HEIGHT_MIN + ROOM_MARGIN_MIN + 3)
+#define CELL_WIDTH_MIN (ROOM_WIDTH_MIN + ROOM_MARGIN_MIN + 3)
+size_t
+generaterooms_gnarf(uint32_t prng, struct room *rs, size_t l)
+{
+ struct rect *queuehead, *queuetail;
+ struct rect *r, *t;
+ struct rect *rects, *walk;
+ size_t w, h, i, j, rl, n;
+ int vertical;
+ struct room *room;
+
+ r = malloc(sizeof(*r));
+ r->x1 = r->y1 = ROOM_MARGIN_MIN;
+ r->x2 = MAPWIDTH;
+ r->y2 = MAPHEIGHT;
+ r->d = 0;
+
+ queuetail = r;
+ queuetail->next = NULL;
+ queuehead = r;
+
+ rects = NULL;
+ rl = 0;
+
+ while (queuehead) {
+ r = queuehead;
+ if (queuetail == queuehead)
+ queuetail = NULL;
+ queuehead = queuehead->next;
+
+ if (r->x2 - r->x1 >= CELL_WIDTH_MIN * 2 && r->y2 - r->y1 >= CE…
+ vertical = xorshift(&prng) & 1;
+ } else if (r->x2 - r->x1 >= CELL_WIDTH_MIN * 2) {
+ vertical = 0;
+ } else if (r->y2 - r->y1 >= CELL_HEIGHT_MIN * 2) {
+ vertical = 1;
+ } else {
+ r->next = rects;
+ rects = r;
+ rl++;
+ continue;
+ }
+
+ if (vertical) {
+ w = r->x2 - r->x1;
+ h = CELL_HEIGHT_MIN + xorshift(&prng) % (1 + r->y2 - r…
+ } else {
+ w = CELL_WIDTH_MIN + xorshift(&prng) % (1 + r->x2 - r-…
+ h = r->y2 - r->y1;
+ }
+
+ t = malloc(sizeof(*t));
+ t->x1 = r->x1;
+ t->y1 = r->y1;
+ t->x2 = r->x1 + w;
+ t->y2 = r->y1 + h;
+ t->d = r->d + 1;
+ t->next = NULL;
+ t->room = NULL;
+
+ if (!queuetail) {
+ queuehead = t;
+ queuetail = t;
+ } else {
+ queuetail->next = t;
+ queuetail = t;
+ }
+
+ t = malloc(sizeof(*t));
+ if (vertical) {
+ t->x1 = r->x1;
+ t->y1 = r->y1 + h;
+ } else {
+ t->x1 = r->x1 + w;
+ t->y1 = r->y1;
+ }
+ t->x2 = r->x2;
+ t->y2 = r->y2;
+ t->d = r->d + 1;
+ t->next = NULL;
+ t->room = NULL;
+
+ queuetail->next = t;
+ queuetail = t;
+
+ free(r);
+ }
+
+ if (l > rl)
+ l = rl;
+
+ for (r = rects; r; r = r->next) {
+ if (MAPHEIGHT / 2 >= r->y1 && MAPHEIGHT / 2 < r->y2 &&
+ MAPWIDTH / 2 >= r->x1 && MAPWIDTH / 2 < r->x2)
+ break;
+ }
+
+ i = 0;
+ rs[i].w = ROOM_WIDTH_MIN + xorshift(&prng) % (1 + r->x2 - r->x1 - ROOM…
+ rs[i].h = ROOM_HEIGHT_MIN + xorshift(&prng) % (1 + r->y2 - r->y1 - ROO…
+ rs[i].x = r->x1 + xorshift(&prng) % (1 + r->x2 - r->x1 - ROOM_MARGIN_M…
+ rs[i].y = r->y1 + xorshift(&prng) % (1 + r->y2 - r->y1 - ROOM_MARGIN_M…
+ rs[i].p = NULL;
+ r->room = &rs[i];
+
+ walk = r;
+ walk->next2 = NULL;
+
+ i++;
+ for (; i < l;) {
+ t = randomneighbor(r, rects, &prng);
+ if (!t || t->room) {
+ n = 0;
+ for (t = walk; t; t = t->next2) {
+ n++;
+ if (xorshift(&prng) / (1. + UINT32_MAX) < 1. /…
+ r = t;
+
+ }
+ continue;
+ }
+ rs[i].w = ROOM_WIDTH_MIN + xorshift(&prng) % (1 + t->x2 - t->x…
+ rs[i].h = ROOM_HEIGHT_MIN + xorshift(&prng) % (1 + t->y2 - t->…
+ rs[i].x = t->x1 + xorshift(&prng) % (1 + t->x2 - t->x1 - ROOM_…
+ rs[i].y = t->y1 + xorshift(&prng) % (1 + t->y2 - t->y1 - ROOM_…
+ rs[i].p = r->room;
+ t->room = &rs[i];
+ i++;
+ r = t;
+ r->next2 = walk;
+ walk = r;
+ }
+
+ for (r = rects; r;) {
+ t = r->next;
+ free(r);
+ r = t;
+ }
+
+ return l;
+}
+
+size_t
+distance(size_t x1, size_t y1, size_t x2, size_t y2)
+{
+ size_t d;
+
+ if (y1 < y2)
+ d = y2 - y1;
+ else
+ d = y1 - y2;
+ if (x1 < x2)
+ d += x2 - x1;
+ else
+ d += x1 - x2;
+
+ return d;
+}
+
+void
+nearestpoints(struct room *a, struct room *b, size_t *ax, size_t *ay, size_t *…
+{
+ if (a->y >= b->y && a->y < b->y + b->h) {
+ *ay = *by = a->y;
+ } else if (b->y >= a->y && b->y < a->y + a->h) {
+ *ay = *by = b->y;
+ } else if (a->y >= b->y) {
+ *ay = a->y;
+ *by = b->y + b->h - 1;
+ } else if (b->y >= a->y) {
+ *ay = a->y + a->h - 1;
+ *by = b->y;
+ }
+
+ if (a->x >= b->x && a->x < b->x + b->w) {
+ *ax = *bx = a->x;
+ } else if (b->x >= a->x && b->x < a->x + a->w) {
+ *ax = *bx = b->x;
+ } else if (a->x >= b->x) {
+ *ax = a->x;
+ *bx = b->x + b->w - 1;
+ } else if (b->x >= a->x) {
+ *ax = a->x + a->w - 1;
+ *bx = b->x;
+ }
+}
+
+void
+connectrooms(struct room *a, struct room *b)
+{
+ size_t i, j;
+ ssize_t ii;
+ size_t x1, y1;
+ size_t x2, y2;
+
+ nearestpoints(a, b, &x1, &y1, &x2, &y2);
+
+ if (y1 > y2) {
+ ii = -1;
+ } else if (y2 > y1) {
+ ii = 1;
+ } else {
+ ii = 0;
+ }
+
+/*
+printf("%lu\t%lu\t%d\n", y1, y2, ii);
+*/
+ for (i = y1; i != y2; i += ii)
+ map[i][x1].c = '.';
+
+ if (x1 > x2) {
+ ii = -1;
+ } else if (x2 > x1) {
+ ii = 1;
+ } else {
+ ii = 0;
+ }
+
+ for (i = x1; i != x2; i += ii)
+ map[y2][i].c = '.';
+}
+
+void
+rendermap(void)
+{
+ size_t i, j;
+
+ for (i = 0; i < MAPHEIGHT; i++) {
+ for (j = 0; j < MAPWIDTH; j++)
+ putchar(map[i][j].c);
+ putchar('\n');
+ }
+}
+
+size_t
+placeitems_hash(Item *item, size_t *assocs, size_t k)
+{
+ Dir *dir;
+ Item *citem;
+ size_t i;
+
+ dir = item->dat;
+ for (i = 0; i < dir->nitems; i++) {
+ citem = &dir->items[i];
+ /* TODO Somewhere else */
+ if (!citem->host || !citem->port || !citem->selector)
+ continue;
+ assocs[i] = fnv1a(6, item->host, item->port, item->selector, c…
+ }
+
+ return k;
+}
+
+#define POSITIONS_LENGTH 4
+enum {
+ Portal,
+ StaircaseDown,
+ Bookshelf,
+ Back
+};
+
+size_t px, py;
+
+void
+generatemap(Item *item, int new)
+{
+ Dir *dir;
+ Item *citem;
+ size_t i, j, k, l, ir;
+ size_t x, y;
+ ssize_t n, m;
+ size_t *cassocs;
+ struct room *rooms, *r;
+ struct {
+ unsigned char x, y;
+ } positions[POSITIONS_LENGTH];
+ uint32_t prng;
+ char buffer[3];
+
+ for (i = 0; i < MAPHEIGHT; i++) {
+ for (j = 0; j < MAPWIDTH; j++) {
+ map[i][j].c = '#';
+ free(map[i][j].items);
+ map[i][j].items = NULL;
+ map[i][j].nitems = 0;
+ }
+ }
+
+ dir = item->dat;
+ for (j = l = 0; j < dir->nitems; j++) {
+ if (dir->items[j].type == '0' ||
+ dir->items[j].type == '1')
+ l++;
+ }
+
+ k = 1 + l / 10;
+ rooms = calloc(k, sizeof(*rooms));
+ if (!rooms)
+ return;
+ k = generaterooms_gnarf(fnv1a(3, item->host, item->port, item->selecto…
+
+ cassocs = calloc(dir->nitems, sizeof(*cassocs));
+ if (!cassocs)
+ goto cleanup;
+
+ k = placeitems_hash(item, cassocs, k);
+
+ /* Insert rooms */
+ for (i = 0; i < k; i++) {
+ for (y = rooms[i].y; y < rooms[i].y + rooms[i].h; y++) {
+ for (x = rooms[i].x; x < rooms[i].x + rooms[i].w; x++)
+ map[y][x].c = '.';
+ }
+ }
+
+ /* Insert connections */
+ for (i = 0; i < k; i++) {
+ if (rooms[i].p)
+ connectrooms(&rooms[i], rooms[i].p);
+ }
+
+ /*
+ Insert items
+ The placement of items affects the initial placement of the pl…
+ */
+ ir = fnv1a(4, item->host, item->port, item->selector, "initial_room") …
+
+ for (i = 0; i < k; i++) {
+ snprintf(buffer, sizeof(buffer), "%d", i);
+ prng = fnv1a(4, item->host, item->port, item->selector, buffer…
+ for (j = 0, n = 0, m = rooms[i].h * rooms[i].w; j < m; j++) {
+ if ((m - j) * (xorshift(&prng) / (double)UINT32_MAX) <…
+ positions[n].x = rooms[i].x + j % rooms[i].w;
+ positions[n].y = rooms[i].y + j / rooms[i].w;
+ n++;
+ }
+ if (n == POSITIONS_LENGTH)
+ break;
+ }
+ for (j = 0; j < dir->nitems; j++) {
+ if (cassocs[j] != i)
+ continue;
+
+ citem = &dir->items[j];
+ switch (citem->type) {
+ case '0':
+ x = positions[Bookshelf].x;
+ y = positions[Bookshelf].y;
+ if (map[y][x].nitems)
+ map[y][x].c = 'E';
+ else
+ map[y][x].c = '?';
+ break;
+ case '1':
+ if (strcmp(citem->host, item->host) || strcmp(…
+ x = positions[Portal].x;
+ y = positions[Portal].y;
+ if (map[y][x].nitems)
+ map[y][x].c = 'O';
+ else
+ map[y][x].c = '0';
+ } else {
+ x = positions[StaircaseDown].x;
+ y = positions[StaircaseDown].y;
+ if (map[y][x].nitems)
+ map[y][x].c = 'L';
+ else
+ map[y][x].c = '>';
+ }
+ break;
+ default:
+ continue;
+ }
+ map[y][x].nitems++;
+ map[y][x].items = realloc(map[y][x].items, map[y][x].n…
+ map[y][x].items[map[y][x].nitems-1] = citem;
+
+ if (new && j == dir->curline && citem->raw) {
+ px = x;
+ py = y;
+ }
+ }
+
+ if (i == ir && item->entry != item) {
+ y = positions[Back].y;
+ x = positions[Back].x;
+ if (strcmp(item->entry->host, item->host) || strcmp(it…
+ map[y][x].c = '0';
+ else
+ map[y][x].c = '<';
+ map[y][x].nitems++;
+ map[y][x].items = realloc(map[y][x].items, map[y][x].n…
+ map[y][x].items[map[y][x].nitems-1] = item->entry;
+ }
+
+ if (i == ir && new && !dir->items[dir->curline].raw) {
+ px = positions[Back].x;
+ py = positions[Back].y;
+ }
+ }
+ free(cassocs);
+
+cleanup:
+ free(rooms);
+}
+
+void
+uisetup(void)
+{
+ tcgetattr(0, &tsave);
+ tsacc = tsave;
+ tsacc.c_lflag &= ~(ECHO|ICANON);
+ tsacc.c_cc[VMIN] = 1;
+ tsacc.c_cc[VTIME] = 0;
+ tcsetattr(0, TCSANOW, &tsacc);
+
+ if (termset != OK)
+ /* setupterm call exits on error */
+ termset = setupterm(NULL, 1, NULL);
+ putp(tparm(clear_screen, 0, 0, 0, 0, 0, 0, 0, 0, 0));
+ fflush(stdout);
+}
+
+void
+uicleanup(void)
+{
+ tcsetattr(0, TCSANOW, &tsave);
+
+ if (termset != OK)
+ return;
+
+ putp(tparm(clear_screen, 0, 0, 0, 0, 0, 0, 0, 0, 0));
+ fflush(stdout);
+}
+
+char *
+uiprompt(char *fmt, ...)
+{
+ va_list ap;
+ char *input = NULL;
+ size_t n;
+ ssize_t r;
+
+ putp(tparm(save_cursor, 0, 0, 0, 0, 0, 0, 0, 0, 0));
+
+ putp(tparm(cursor_address, lines-1, 0, 0, 0, 0, 0, 0, 0, 0));
+ putp(tparm(clr_eol, 0, 0, 0, 0, 0, 0, 0, 0, 0));
+
+ va_start(ap, fmt);
+ vsnprintf(bufout, sizeof(bufout), fmt, ap);
+ va_end(ap);
+
+ n = mbsprint(bufout, columns);
+
+ putp(tparm(clr_eol, 0, 0, 0, 0, 0, 0, 0, 0, 0));
+
+ putp(tparm(cursor_address, lines-1, n, 0, 0, 0, 0, 0, 0, 0));
+
+ tsacc.c_lflag |= (ECHO|ICANON);
+ tcsetattr(0, TCSANOW, &tsacc);
+ fflush(stdout);
+
+ n = 0;
+ r = getline(&input, &n, stdin);
+
+ tsacc.c_lflag &= ~(ECHO|ICANON);
+ tcsetattr(0, TCSANOW, &tsacc);
+ putp(tparm(restore_cursor, 0, 0, 0, 0, 0, 0, 0, 0, 0));
+ fflush(stdout);
+
+ if (r == -1) {
+ clearerr(stdin);
+ clear(&input);
+ } else if (input[r - 1] == '\n') {
+ input[--r] = '\0';
+ }
+
+ return input;
+}
+
+void
+displaybar(char *s) {
+ size_t n;
+
+ putp(tparm(save_cursor, 0, 0, 0, 0, 0, 0, 0, 0, 0));
+
+ putp(tparm(cursor_address, lines-2, 0, 0, 0, 0, 0, 0, 0, 0));
+ putp(tparm(enter_standout_mode, 0, 0, 0, 0, 0, 0, 0, 0, 0));
+
+ n = mbsprint(s, columns);
+ for (n = columns - n; n; n--)
+ putchar(' ');
+
+ putp(tparm(exit_standout_mode, 0, 0, 0, 0, 0, 0, 0, 0, 0));
+
+ putp(tparm(restore_cursor, 0, 0, 0, 0, 0, 0, 0, 0, 0));
+ fflush(stdout);
+}
+
+void
+vdisplayinfoline(char *fmt, va_list ap)
+{
+ putp(tparm(save_cursor, 0, 0, 0, 0, 0, 0, 0, 0, 0));
+
+ putp(tparm(cursor_address, lines-1, 0, 0, 0, 0, 0, 0, 0, 0));
+
+ vsnprintf(bufout, sizeof(bufout), fmt, ap);
+
+ mbsprint(bufout, columns);
+
+ putp(tparm(clr_eol, 0, 0, 0, 0, 0, 0, 0, 0, 0));
+
+ putp(tparm(restore_cursor, 0, 0, 0, 0, 0, 0, 0, 0, 0));
+ fflush(stdout);
+}
+
+void
+uistatus(char *fmt, ...)
+{
+ va_list ap;
+ size_t n;
+
+ putp(tparm(save_cursor, 0, 0, 0, 0, 0, 0, 0, 0, 0));
+
+ putp(tparm(cursor_address, lines-1, 0, 0, 0, 0, 0, 0, 0, 0));
+
+ va_start(ap, fmt);
+ n = vsnprintf(bufout, sizeof(bufout), fmt, ap);
+ va_end(ap);
+
+ if (n < sizeof(bufout)-1) {
+ snprintf(bufout+n, sizeof(bufout)-n,
+ " [Press a key to continue \xe2\x98\x83]");
+ }
+
+ mbsprint(bufout, columns);
+
+ putp(tparm(clr_eol, 0, 0, 0, 0, 0, 0, 0, 0, 0));
+
+ putp(tparm(restore_cursor, 0, 0, 0, 0, 0, 0, 0, 0, 0));
+ fflush(stdout);
+
+ getchar();
+}
+
+void
+displayinfoline(char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ vdisplayinfoline(fmt, ap);
+ va_end(ap);
+}
+
+Item *
+showmenu(char *title, Item **item, size_t l)
+{
+ size_t i;
+
+ putp(tparm(clear_screen, 0, 0, 0, 0, 0, 0, 0, 0, 0));
+
+ putp(tparm(enter_standout_mode, 0, 0, 0, 0, 0, 0, 0, 0, 0));
+ printf("%s\n", title);
+ putp(tparm(exit_standout_mode, 0, 0, 0, 0, 0, 0, 0, 0, 0));
+ for (i = 0; i < l; i++)
+ printf("%lu\t%s\n", i, item[i]->username);
+
+ if (!scanf("%lu", &i) || i >= l)
+ return NULL;
+ fflush(stdout);
+
+ return item[i];
+}
+
+Item *
+prompt(char *text, Item *item)
+{
+ displayinfoline(text, item->username);
+ getchar();
+ return item;
+}
+
+Item *
+interact(Item *item)
+{
+ Item *selection;
+
+ selection = NULL;
+
+ switch (map[py][px].c) {
+ case '?':
+ case '0':
+ case '>':
+ case '<':
+ selection = map[py][px].items[0];
+ break;
+ case 'E':
+ selection = showmenu("Bookshelf", map[py][px].items, map[py][p…
+ break;
+ case 'O':
+ selection = showmenu("Portal machine", map[py][px].items, map[…
+ break;
+ case 'L':
+ selection = showmenu("Elevator", map[py][px].items, map[py][px…
+ break;
+ }
+
+ drawscreen();
+
+ if (selection) {
+ switch (map[py][px].c) {
+ case '?':
+ case 'E':
+ displayinfoline("A loading bar?! In a book?!");
+ break;
+ case 'O':
+ case '0':
+ displayinfoline("You are getting transported through t…
+ break;
+ case 'L':
+ displayinfoline("You hear elevator music...");
+ break;
+ case '<':
+ case '>':
+ displayinfoline("Too many stairs...");
+ break;
+ }
+ }
+
+ return selection;
+}
+
+void
+describe(size_t x, size_t y, int verbose)
+{
+ switch (map[y][x].c) {
+ case 'E':
+ displayinfoline("A bookshelf.");
+ break;
+ case 'O':
+ displayinfoline("A portal machine.");
+ break;
+ case 'L':
+ displayinfoline("An elevator.");
+ break;
+ case '?':
+ case '>':
+ case '<':
+ case '0':
+ if (*map[y][x].items[0]->username) {
+ displayinfoline("'%s'.", map[y][x].items[0]->username);
+ } else {
+ itemuri(map[y][x].items[0], bufout2, sizeof(bufout2));
+ displayinfoline("'%s'.", bufout2);
+ }
+ break;
+ default:
+ if (verbose) {
+ switch (map[y][x].c) {
+ case '.':
+ displayinfoline("Floor.");
+ break;
+ case '#':
+ displayinfoline("Wall.");
+ break;
+ }
+ } else {
+ displayinfoline("");
+ }
+ break;
+ }
+}
+
+void
+move(ssize_t dx, ssize_t dy)
+{
+ size_t x, y;
+
+ /* allow wraparound of the world for the lulz, even if it's not happen…
+ y = (MAPHEIGHT + py + dy) % MAPHEIGHT;
+ x = (MAPWIDTH + px + dx) % MAPWIDTH;
+
+ if (map[y][x].c == '#')
+ return;
+
+ putp(tparm(cursor_address, py, px, 0, 0, 0, 0, 0, 0, 0 ));
+ putchar(map[py][px].c);
+
+ py = y;
+ px = x;
+ putp(tparm(cursor_address, py, px, 0, 0, 0, 0, 0, 0, 0 ));
+ putchar('@');
+ putp(tparm(cursor_address, py, px, 0, 0, 0, 0, 0, 0, 0 ));
+
+ describe(x, y, 0);
+ putp(tparm(cursor_address, py, px, 0, 0, 0, 0, 0, 0, 0 ));
+}
+
+void
+drawscreen(void)
+{
+ Dir *dir;
+
+ putp(tparm(clear_screen, 0, 0, 0, 0, 0, 0, 0, 0, 0));
+ rendermap();
+
+ if (curentry->entry != curentry && (dir = curentry->entry->dat)) {
+ displaybar(dir->items[dir->curline].username);
+ } else {
+ itemuri(curentry, bufout, sizeof(bufout));
+ displaybar(bufout);
+ }
+
+ move(0, 0);
+
+}
+
+void
+uidisplay(Item *entry)
+{
+ if (!entry || entry->type != '1')
+ return;
+
+ generatemap(entry, curentry != entry);
+
+ curentry = entry;
+ drawscreen();
+}
+
+void
+lookmode(void)
+{
+ size_t x, y;
+
+ x = px;
+ y = py;
+
+ for (;;) {
+ switch (getchar()) {
+ case 0x1B:
+ case 'q':
+ putp(tparm(cursor_address, py, px, 0, 0, 0, 0, 0, 0, 0…
+ return;
+ case 'h':
+ x = (MAPWIDTH + x - 1) % MAPWIDTH;
+ break;
+ case 'j':
+ y = (y + 1) % MAPHEIGHT;
+ break;
+ case 'k':
+ y = (MAPHEIGHT + y - 1) % MAPHEIGHT;
+ break;
+ case 'l':
+ x = (x + 1) % MAPWIDTH;
+ break;
+ }
+ putp(tparm(cursor_address, y, x, 0, 0, 0, 0, 0, 0, 0));
+ describe(x, y, 1);
+ }
+}
+
+Item *
+uiselectitem(Item *entry)
+{
+ Dir *dir;
+ Item *e;
+ size_t i;
+
+ if (!entry || !(dir = entry->dat))
+ return NULL;
+
+ for (;;) {
+ switch (getchar()) {
+ case 'h':
+ move(-1, 0);
+ break;
+ case 'j':
+ move(0, 1);
+ break;
+ case 'k':
+ move(0, -1);
+ break;
+ case 'l':
+ move(1, 0);
+ break;
+ case 'L':
+ lookmode();
+ break;
+ case ' ':
+ /* Portals, stairs, bookshelfs */
+ if (e = interact(entry)) {
+ if (e->type == '1') {
+ for (i = 0; i < dir->nitems; i++) {
+ if (e == &dir->items[i]) {
+ dir->curline = i;
+ break;
+ }
+ }
+ }
+ return e;
+ }
+ break;
+ case 'q':
+ return NULL;
+ }
+ }
+}
+
+void
+uisigwinch(int signal)
+{
+ Dir *dir;
+
+ if (termset == OK)
+ del_curterm(cur_term);
+ termset = setupterm(NULL, 1, NULL);
+
+ if (!curentry || !(dir = curentry->dat))
+ return;
+
+ uidisplay(curentry);
+}
You are viewing proxied material from bitreich.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.