💾 Archived View for thrig.me › blog › 2024 › 02 › 05 › some-random-things.gmi captured on 2024-05-10 at 11:10:00. Gemini links have been rewritten to link to archived content

View Raw

More Information

⬅️ Previous capture (2024-03-21)

-=-=-=-=-=-=-

Some Random Things

First, pick your algorithm well. Some are bad, especially old ones from when computers were not very powerful.

    #define RN_MAX 0x7fff
    #define RN (((seed = seed * 11109 + 13849) & RN_MAX) >> 1)

However, if all you have is an old (or small) computer, and you are writing a quick game in assembly, then it may make sense to use something terrible, provided you know the pitfalls involved.

    rand_seed:
            xor ax, ax
            int 0x1a                ; fn: system time
            mov [seed], dx
            ret

    ; the "RNG" from rogue 3.6.3
    rand_value:                     ; in=bx, out=dx (or dl)
            mov ax, [seed]
            mov cx, 11109
            mul cx
            add ax, 13849
            mov [seed], ax
            ror ax, 1
            xor dx, dx
            div bx
            ret

    seed: dw 0

Newer algorithms may be bad in that they may take up too much memory or CPU. If cryptography, the algorithm should be suited to that. If shooting Xorglaxian Crusaders or rolling some dice to see if the Hero falls in love with the Dragon, then something less expensive may do, unless you have competitive players who try to guess the game seed.

A small noncryptographic PRNG

https://www.pcg-random.org/posts/some-prng-implementations.html

SWAGGINZZZ with her RNG-predicting AWS-cluster of monster computers

On the other hand, those just starting out may want a language with "batteries included" and to use whatever RNG it ships with plus plenty of worked and hopefully tested examples. Or maybe you enjoy debugging why your custom code is only generating maces and not any other weapons?

Jenkins Small Fast 32-bit

Small, fast, not obviously broken, appears to be public domain code. Good enough for a smolgame? Probably this needs a few more functions such as "roll" for dice rolls and "one_in" for 1 in N odds of something happening, maybe also floating point, etc.

jsf.c

jsf.h

JSF for Common LISP

Seedy Things

A cryptographic RNG may be a good way to seed a faster RNG. Read some bytes from /dev/urandom, or on OpenBSD use arc4random(3). Or RDRAND if you trust the on-chip hardware. Higher level interfaces may use RDRAND among other sources of entropy.

For games where money and competition is less involved the seed may be derived from the current date (e.g. YYYYMMDD) so that different players using the same software can play the same seed and then discuss the results. Someone could practice such a seed in advance, so this is open to abuse.

    $ date +%Y%m%d
    20240205

For some games it may make sense to seed multiple generators so that level generation uses a distinct seed from the one for combat. Reasons for this include making the combat RNG impossible to guess from looking at what the level layout is doing, or so that the next level generated does not depend on the actions taken during the previous level. Some games will simply generate all the levels in advance.

Omake Interlude

Dragon Half Ending (with apologies to Beethoven)

Biased Noise

    static const char noise[] = "..,`':;~+=< _ij\"^\\l(amxvu04PYW";

    inline static char
    rndchar(void)
    {
        size_t index = 0;
        size_t len   = sizeof(noise) / sizeof(char);
        while (1) {
            size_t x = jsf_below(8);
            index += x;
            if (x < 5) break;
        }
        if (index >= len) index = 0;
        return noise[index];
    }

This code favors "less dense" characters early in the "noise" list, though will sometimes select "heavier" characters at the end. The characters are somewhat arbitrarily arranged. One should test these things; for visual noise in a game one wants something that looks good enough and isn't too expensive to calculate. It may also be good to tally up a lot of iterations to see what an average noise profile looks like, and from there to tune the cut-off points and list of noise characters as need be.

noisetally.c

    $ cc -c -o jsf.o jsf.c
    $ cc -o noisetally jsf.o noisetally.c
    $ ./noisetally | tally | sed 20q
    2565798 .
    1252794 ,
    1248885 '
    1247226 `
    468391 =
    468255 +
    467982 ~
    332502 <
    312736 ;
    214565
    176668 j
    158742 "
    156457 i
    156294 :
    126316 ^
    117453 _
    83264 \
    61350 a
    60450 l
    57877 m

A more formal way to do this would be to better characterize how many bits a character of a font turns on, and then to sort by that for character density. Probably this code has already been done somewhere in tools like chafa, which is what (indirectly) inspired all this noise. (The space or " " character is not early in the somewhat-sorted-by-character-density list as it is used to sometimes overwrite already existing characters on the screen, but not too often.)

character art facsimile generator

Another idea might be to use "heavier" characters more often more towards the bottom of the screen instead of placing the characters into random rows and columns.

noiseshow.c

    $ cc -o noiseshow jsf.o noiseshow.c -lncurses
    ...

And a random result.

    `   <          . ` _        ' ^        .  .                 ` ` ,
     '  0.                      (,          ,       .  .      +  '
    .     =  x         .  .` ,.,'    .         ,         `    (       `
      '   ;   :   j        < ^         .        `    , +       ^
               .            .j    `.              `     .   . ~.
      . +,                  ,            , ~        .   '      '.
               ,.    '    .=      `   , ,   ; .   j a '          .`l,=`
    .'        `            '     .         <                  ^.  .
    =  .            +'             .  `     . ,    j  . .     .
      `  `     .        `   .                    .              '
     .       =           `       .      '         ..                  ,
           (         = .   `,   .   . ^ +       j. `  =           =
                `   `,    '     _ + . = ;       a       `  .     ~
       .  ',      `   "    .               ~  '     _  `  =    `  '   :
       .  . ^      :       .          \       <            .    ;    ,
        :           ,     `u      +.     ~  +     .              .
              ~   m .`=   .`    '.  <   j  =           <           .
              .       . '  + ' ` `                          .l       `=
     ,           `=    <  ,  ~,.     `       .'  `  ~            i
    '       .   :   m'  .      <         . ` + `           ` , "
     , , +        .  + `      .    <   .  ,+         `     .   .
         .         . +                        .             `

And a different version where the index influences what line the character appears on, though with some randomization so that certain characters do not appear only on certain lines.

    .        .                                     .                 .
              .      .         .          .            ..  . .      .
                                   .   ..     ,    .     ..      .
        ,   ,  .    ` .      .                  . `.        . .   `
    `   .   ,.`       . ``   .. .'`   `       . `  .     `    .
      . .`.  `   `      '  .  .     . .  .   .    .        .
      `   ' , ,,'. ` '      , .   .      ,  '     ..  ,  . ,   '.
                ~   .           .    .    ,.           ;:  '`     ,  .
       '.   .  ` . '  ..       ~,`        '         ~  . ''`
    .   '=     '.   ` , . '; , ~.  ,.` ';    `    .~ '  .    .      `
      ~  ,  ,  ..    `   .   `         `   +  `'~     <     ``' ~  .
    '~   ,   '     =      +    ~         ~   , `  '      ,       ` ` ,
    `  +  '                ` ':`            `           ~_  `
         +~                       i                 +          +
         ~       =                     ~ <             _ <   = :
                  <       ;                      i                   <
         +<    +         =                  <  "          +          ^^
           +  "           =             ="           ^
                      =      i             "        <         =       <
                                    <     <   i      <  _
                    ^          (
      a            a                      j