#help_index "God"

U8 *TimeStampCB(CDoc *, CDocEntry *, CTask *mem_task)
{
    U8 *st = MAlloc(64, mem_task);
    StrPrint(st, "%X", TSCGet >> GOD_BAD_BITS);
    return st;
}

U8 *KbdMouseTimeCB(CDoc *, CDocEntry *, CTask *mem_task)
{
    U8 *st = MAlloc(64, mem_task);
    StrPrint(st, "%X", KbdMouseEventTime >> GOD_BAD_BITS);
    return st;
}

I64 PopUpTimerOk(U8 *msg=NULL)
{
    I64          i;
    CDocEntry   *doc_e;
    CDoc        *doc = DocNew;

    if (msg)
        DocPrint(doc, "%s", msg);

    doc_e = DocPrint(doc, "\nTimer: $TX+TC,\" \"$");
    doc_e->tag_cb = &TimeStampCB;

    doc_e = DocPrint(doc, "\nLatch: $TX+TC,\" \"$");
    doc_e->tag_cb = &KbdMouseTimeCB;

    DocPrint(doc, "$CM+CX,0,4$$BT,\"OKAY\",LE=1$\n");
    i = PopUpMenu(doc);
    DocDel(doc);

    return i;
}

I64 GodPick(U8 *message=NULL)
{
    U8 *st = MStrPrint("%s\n\nPress $GREEN$OKAY$FG$ to generate a random number from the timer.\n"
                                    "The latch is the last timestamp from the keyboard.\n"
                                    "When you press $GREEN$OKAY$FG$, a new timestamp will be used.\n", message);
    PopUpTimerOk(st);
    Free(st);
    return KbdMouseEventTime >> GOD_BAD_BITS;
}

public U0 GodBitsInsert(I64 num_bits, I64 bitfield)
{//Insert bits into God bit FIFO.
    I64 i;

    for (i = 0; i < num_bits; i++)
    {
        FifoU8Insert(god.fifo, bitfield & 1);
        bitfield >>= 1;
    }
}

public U0 GodHexInsert(U8 *st)
{//Insert hex record into God bit FIFO.
    U8 buf[2];
    if (st)
    {
        buf[1] = 0;
        while (*buf = *st++)
            if (Bt(char_bmp_hex_numeric, *buf))
                GodBitsInsert(4, rev_bits_table[Str2I64(buf, 16)] >> 4);
    }
}

public I64 GodBitsRemove(I64 num_bits, U8 *message=NULL)
{//Return N bits. If low on entropy pop-up okay.
    U8  b;
    I64 res = 0;

    while (num_bits)
    {
        if (FifoU8Remove(god.fifo, &b))
        {
            res = res << 1 + b;
            num_bits--;
        }
        else
            GodBitsInsert(GOD_GOOD_BITS, GodPick(message));
    }

    return res;
}

I64 GodInit(U8 *files_find_mask="/System/God/Vocab.DD", U8 *fu_flags=NONE)
{//Read God's vocab file for picking words.
    I64          i, ch, fuf_flags = 0;;
    U8          *buf, *ptr, *ptr2;
    CDirEntry   *tmpde, *tmpde1;

    FlagsScan(&fuf_flags, Define("ST_FILE_UTIL_FLAGS"), "+r+f+F+T+O");
    FlagsScan(&fuf_flags, Define("ST_FILE_UTIL_FLAGS"), fu_flags);
    if (fuf_flags & ~FUG_FILES_FIND)
        throw('FUF');

    Free(god.word_file_mask);
    god.word_file_mask = StrNew(files_find_mask);
    god.word_fuf_flags = fuf_flags;

    tmpde = tmpde1 = FilesFind(files_find_mask, fuf_flags);

    i = 0;
    while (tmpde)
    {
        if (buf = ptr = FileRead(tmpde->full_name));
        {
            while (*ptr)
            {
                while (*ptr && !Bt(char_bmp_word, *ptr))
                    ptr++;
                if (*ptr)
                {
                    ptr2 = ptr;
                    while (*ptr && Bt(char_bmp_word, *ptr))
                        ptr++;
                    i++;
                }
            }
            Free(buf);
        }
        tmpde = tmpde->next;
    }

    Free(god.words);
    god.word_count = i;
    god.words = MAlloc(sizeof(U8 *) * i);

    tmpde = tmpde1;
    i = 0;
    while (tmpde)
    {
        if (buf = ptr = FileRead(tmpde->full_name))
        {
            while (*ptr)
            {
                while (*ptr && !Bt(char_bmp_word, *ptr))
                    ptr++;
                if (*ptr)
                {
                    ptr2 = ptr;
                    while (*ptr && Bt(char_bmp_word, *ptr))
                        ptr++;
                    ch = *ptr;
                    *ptr = '\0';
                    god.words[i++] = StrNew(ptr2);
                    *ptr = ch;
                }
            }
            Free(buf);
        }
        tmpde = tmpde->next;
    }
    DirTreeDel(tmpde1);

    return god.word_count;
}
GodInit;

public U8 *GodWordStr(I64 bits=17)
{//Make God pick a word.
    if (god.word_count)
        return god.words[GodBitsRemove(bits) % god.word_count];

    return NULL;
}

public U0 GodWord(I64 bits=17)
{//Make God pick a word.
    if (god.word_count)
        "%s ", god.words[GodBitsRemove(bits) % god.word_count];
}

public U0 GodBiblePassage(I64 num_lines=20)
{//Make God pick a Bible passage.
    I64 start = GodBitsRemove(21) % (ST_BIBLE_LINES - (num_lines - 1)) + 1;
    U8 *verse = BibleLine2Verse(start);
    "%s\n\n", verse;
    Free(verse);
    BookLines(, start, num_lines);
}