#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="/Zenith/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);
}
