juegos

Juegos de terminal de Pancho: Catan (TUI, GUI, web, servidor, PicoCalc), ajedrez, calculadora y minijuegos
git clone https://git.lu3dhn.xyz/juegos.git
Log | Files | Refs

mini.c (4885B)


      1 /* mini.c - ver mini.h */
      2 #include <string.h>
      3 #include "mini.h"
      4 
      5 Rng mini_rng;
      6 void (*mini_art)(Surface *s);
      7 int mini_menu_top = 84;
      8 
      9 static const char *g_title;
     10 static Color g_accent;
     11 
     12 /* ------------------------------------------------------------ azar */
     13 
     14 int mini_rand(int n) { return n > 0 ? (int)rng_below(&mini_rng, (uint32_t)n) : 0; }
     15 
     16 void mini_shuffle(uint8_t *a, int n)
     17 {
     18     for (int i = n - 1; i > 0; i--) {
     19         int j = mini_rand(i + 1);
     20         uint8_t t = a[i]; a[i] = a[j]; a[j] = t;
     21     }
     22 }
     23 
     24 /* ------------------------------------------------------------ texto grande */
     25 
     26 int mini_big_text(Surface *s, const Font *f, int x, int y, int scale, const char *t, Color c)
     27 {
     28     int x0 = x, ch;
     29     while ((ch = utf8_next(&t)) != 0) {
     30         if (ch < 32 || ch > 255) ch = '?';
     31         const uint8_t *g = f->bits + (ch - 32) * f->h;
     32         for (int row = 0; row < f->h; row++)
     33             for (int col = 0; col < 8; col++)
     34                 if (g[row] & (0x80 >> col)) gfx_rect(s, x + col * scale, y + row * scale, scale, scale, c);
     35         x += f->w * scale;
     36     }
     37     return x - x0;
     38 }
     39 
     40 int mini_big_w(const Font *f, int scale, const char *t) { return gfx_text_w(f, t) * scale; }
     41 
     42 void mini_big_center(Surface *s, const Font *f, int y, int scale, const char *t, Color c)
     43 {
     44     int x = (s->w - mini_big_w(f, scale, t)) / 2;
     45     mini_big_text(s, f, x + scale / 2 + 1, y + scale / 2 + 1, scale, t, C_BLACK);   /* sombra */
     46     mini_big_text(s, f, x, y, scale, t, c);
     47 }
     48 
     49 int str_time(char *buf, int n, int pos, uint32_t ms)
     50 {
     51     uint32_t sec = ms / 1000;
     52     pos = str_int(buf, n, pos, (long)(sec / 60));
     53     pos = str_put(buf, n, pos, sec % 60 < 10 ? ":0" : ":");
     54     return str_int(buf, n, pos, (long)(sec % 60));
     55 }
     56 
     57 /* ------------------------------------------------------------ menus */
     58 
     59 static int backdrop(Surface *s, bool compact)
     60 {
     61     (void)compact;
     62     gfx_rect(s, 0, 0, s->w, s->h, RGB(16, 20, 30));
     63     for (int y = 0; y < s->h; y += 8) gfx_rect(s, 0, y, s->w, 1, RGB(22, 27, 40));
     64     mini_big_center(s, &font_bold, 14, 3, g_title, g_accent);
     65     if (mini_art) mini_art(s);
     66     return mini_menu_top;
     67 }
     68 
     69 static void paint_form(Surface *s, void *ctx) { gfx_form(s, ctx, 0); }
     70 
     71 int mini_form(Form *f)
     72 {
     73     bool dirty = true;
     74     for (;;) {
     75         if (dirty) { hal_draw(paint_form, f); dirty = false; }
     76         int k = hal_key();
     77         if (k < 0) { hal_sleep(10); continue; }
     78         dirty = true;
     79         if (k == 0) continue;
     80         int r = form_key(f, k);
     81         if (r != FORM_NONE) return r;
     82     }
     83 }
     84 
     85 void mini_notice(const char *title, const char *text)
     86 {
     87     Form f;
     88     form_begin(&f, title);
     89     form_label(&f, text);
     90     form_button(&f, 1, "OK");
     91     f.cur = 1;
     92     mini_form(&f);
     93 }
     94 
     95 /* ------------------------------------------------------------ guardado */
     96 
     97 static char store[2048];
     98 
     99 static char *find(const char *key)
    100 {
    101     int kl = (int)strlen(key);
    102     for (char *p = store; *p; ) {
    103         if (!strncmp(p, key, (size_t)kl) && p[kl] == ' ') return p;
    104         char *e = strchr(p, '\n');
    105         if (!e) break;
    106         p = e + 1;
    107     }
    108     return 0;
    109 }
    110 
    111 const char *mini_get_str(const char *key)
    112 {
    113     static char val[256];
    114     char *p = find(key);
    115     if (!p) return 0;
    116     p += strlen(key) + 1;
    117     int i = 0;
    118     while (p[i] && p[i] != '\n' && i < (int)sizeof val - 1) { val[i] = p[i]; i++; }
    119     val[i] = 0;
    120     return val;
    121 }
    122 
    123 long mini_get(const char *key, long def)
    124 {
    125     const char *v = mini_get_str(key);
    126     long x;
    127     return v && str_scan_int(v, &x) ? x : def;
    128 }
    129 
    130 void mini_set_str(const char *key, const char *v)
    131 {
    132     char *p = find(key);
    133     if (p) {                                   /* sacar la linea vieja */
    134         char *e = strchr(p, '\n');
    135         if (e) memmove(p, e + 1, strlen(e + 1) + 1);
    136         else *p = 0;
    137     }
    138     int n = (int)strlen(store);
    139     if (n + (int)strlen(key) + (int)strlen(v) + 3 > (int)sizeof store) return;
    140     n = str_put(store, sizeof store, n, key);
    141     n = str_put(store, sizeof store, n, " ");
    142     n = str_put(store, sizeof store, n, v);
    143     str_put(store, sizeof store, n, "\n");
    144 }
    145 
    146 void mini_set(const char *key, long v)
    147 {
    148     char b[24];
    149     str_int(b, sizeof b, 0, v);
    150     mini_set_str(key, b);
    151 }
    152 
    153 bool mini_save(void) { return hal_store_save(store, (int)strlen(store)); }
    154 
    155 /* ------------------------------------------------------------ arranque */
    156 
    157 void mini_start(const char *title, Color accent)
    158 {
    159     hal_init();
    160     g_title = title;
    161     g_accent = accent;
    162     gfx_form_backdrop = backdrop;
    163     rng_seed(&mini_rng, ((uint64_t)hal_random() << 32) | hal_random(), hal_random() | 1);
    164     int n = hal_store_load(store, sizeof store - 1);
    165     store[n > 0 ? n : 0] = 0;
    166     /* un .SAV nuevo esta lleno de ceros o basura: quedarse solo con texto */
    167     for (int i = 0; store[i]; i++)
    168         if ((store[i] < 32 && store[i] != '\n') || (unsigned char)store[i] > 126) { store[0] = 0; break; }
    169 }