[List.HybridLeet:new]
    int i, j;
	int c, p;
	int totrots;
	int length;

	/* Get the word length */
	length = 0; while (word[length++]) ; --length;

	/* Skip if this word length is out of bounds
	   This should not be necessary, but we'll leave it here to be defensive */
	if (req_minlen > length || (req_maxlen && req_maxlen < length ))
	{
		hybrid_total = 0;
		return;
	}

	/* Calculate word rotations */

	word_rot_count=0; 	/* Number of letter positions we are rotating for this word */
	totrots = 1; 		/* Number of total rotation iterations */

	i=0;
	while (i < length)
	{
		/* is this letter one of our rotators? a,A, b,B etc*/
		c = word[i];
		j = 0;
		while (j < rot_poslen)
		{
			p = rot_pos[j];
			if (c == rot_chars[p] || c == rot_chars[p+1]) 	/* Is 'a' or 'A' for example */
			{
				word_rot_idx[word_rot_count] = i;		/* Save off which letter position in the word we are rotating */
				word_rot_pos[word_rot_count] = j;		/* Save off the rotation position for this slot */
				word_rotchars_pos[word_rot_count] = p; 	/* Save off the first letter position in the rotation */
				word_rot_count++;

				/* Also, set the word to the first letter in the rotation so we ensure to go through all of them */
				word[i] = rot_chars[p];

				/* And multiple number of total rotations by the number of rotations for this position */
				totrots = totrots * rot_len[j];

				break;
			}
			j++;
		}
		i++;
	}

	hybrid_total = totrots;

	/* Reset or counter for THIS word. */
	word_rot_current = 0;

[List.External:HybridLeet]

/*
    Static context
    String lengths here are arbitrary, increase them if you increase the
    size of the stuff in the init() procedure
*/

int rot_chars[256];		/* All characters to rotate */
int rot_charslen;    	/* The length of the rot_chars buffer */

int rot_len[26];    	/* The number of characters to rotate through per letter */
int rot_pos[26];    	/* The starting position of each letter group in the rot_chars string */
int rot_poslen;			/* Length of rot_pos and rot_len arrays (both same size) */

int word_rot_idx[128];  		/* The positions in the current word that require rotations (index into word)*/
int word_rot_pos[128];  		/* The rot_pos index for each letter position in the current word that we are rotating (index into rot_pos)*/
int word_rotchars_pos[128];  	/* The current rot_chars index for each letter position in the current word that we are rotating (state of rotation, index into rot_chars)*/
int word_rot_count;     		/* The number of letters that we are rotating in the current word (size of word_rot_idx, word_rot_pos, and word_rotchars_pos) */

int word_rot_current;	/* The rotation number of the current word */

void init()
{
	int rci;
	int ri;

	rot_charslen=0;
	rci=0;
	ri=0;

	/* a */
	rot_pos[ri] = rci;
	rot_chars[rci++] = 'a'; /* The first two chars are always the lower */
	rot_chars[rci++] = 'A'; /* and upper case letters to rotate on */
	rot_chars[rci++] = '4';
	rot_chars[rci++] = '@';
	rot_chars[rci++] = '8';
	rot_len[ri] = (rci - rot_pos[ri]);
	ri++;

	/* b */
	rot_pos[ri] = rci;
	rot_chars[rci++] = 'b';
	rot_chars[rci++] = 'B';
	rot_chars[rci++] = '8';
	rot_len[ri] = (rci - rot_pos[ri]);
	ri++;

	rot_pos[ri] = rci;
	rot_chars[rci++] = 'c';
	rot_chars[rci++] = 'C';
	rot_len[ri] = (rci - rot_pos[ri]);
	ri++;

	rot_pos[ri] = rci;
	rot_chars[rci++] = 'd';
	rot_chars[rci++] = 'D';
	rot_len[ri] = (rci - rot_pos[ri]);
	ri++;

	/* e */
	rot_pos[ri] = rci;
	rot_chars[rci++] = 'e';
	rot_chars[rci++] = 'E';
	rot_chars[rci++] = '3';
	rot_len[ri] = (rci - rot_pos[ri]);
	ri++;

	rot_pos[ri] = rci;
	rot_chars[rci++] = 'f';
	rot_chars[rci++] = 'F';
	rot_len[ri] = (rci - rot_pos[ri]);
	ri++;

	rot_pos[ri] = rci;
	rot_chars[rci++] = 'g';
	rot_chars[rci++] = 'G';
	rot_len[ri] = (rci - rot_pos[ri]);
	ri++;

	/* h */
	rot_pos[ri] = rci;
	rot_chars[rci++] = 'h';
	rot_chars[rci++] = 'H';
	rot_chars[rci++] = '#';
	rot_len[ri] = (rci - rot_pos[ri]);
	ri++;

	/* i */
	rot_pos[ri] = rci;
	rot_chars[rci++] = 'i';
	rot_chars[rci++] = 'I';
	rot_chars[rci++] = '1';
	rot_chars[rci++] = '!';
	rot_len[ri] = (rci - rot_pos[ri]);
	ri++;

	rot_pos[ri] = rci;
	rot_chars[rci++] = 'j';
	rot_chars[rci++] = 'J';
	rot_len[ri] = (rci - rot_pos[ri]);
	ri++;

	rot_pos[ri] = rci;
	rot_chars[rci++] = 'k';
	rot_chars[rci++] = 'K';
	rot_len[ri] = (rci - rot_pos[ri]);
	ri++;

	/* l */
	rot_pos[ri] = rci;
	rot_chars[rci++] = 'l';
	rot_chars[rci++] = 'L';
	rot_chars[rci++] = '1';
	rot_len[ri] = (rci - rot_pos[ri]);
	ri++;

	rot_pos[ri] = rci;
	rot_chars[rci++] = 'm';
	rot_chars[rci++] = 'M';
	rot_len[ri] = (rci - rot_pos[ri]);
	ri++;

	rot_pos[ri] = rci;
	rot_chars[rci++] = 'n';
	rot_chars[rci++] = 'N';
	rot_len[ri] = (rci - rot_pos[ri]);
	ri++;

	/* o */
	rot_pos[ri] = rci;
	rot_chars[rci++] = 'o';
	rot_chars[rci++] = 'O';
	rot_chars[rci++] = '0';
	rot_len[ri] = (rci - rot_pos[ri]);
	ri++;

	rot_pos[ri] = rci;
	rot_chars[rci++] = 'p';
	rot_chars[rci++] = 'P';
	rot_len[ri] = (rci - rot_pos[ri]);
	ri++;

	rot_pos[ri] = rci;
	rot_chars[rci++] = 'q';
	rot_chars[rci++] = 'Q';
	rot_len[ri] = (rci - rot_pos[ri]);
	ri++;

	rot_pos[ri] = rci;
	rot_chars[rci++] = 'r';
	rot_chars[rci++] = 'R';
	rot_len[ri] = (rci - rot_pos[ri]);
	ri++;

	/* s */
	rot_pos[ri] = rci;
	rot_chars[rci++] = 's';
	rot_chars[rci++] = 'S';
	rot_chars[rci++] = '$';
	rot_chars[rci++] = '5';
	rot_len[ri] = (rci - rot_pos[ri]);
	ri++;

	/* t */
	rot_pos[ri] = rci;
	rot_chars[rci++] = 't';
	rot_chars[rci++] = 'T';
	rot_chars[rci++] = '+';
	rot_chars[rci++] = '7';
	rot_len[ri] = (rci - rot_pos[ri]);
	ri++;

	rot_pos[ri] = rci;
	rot_chars[rci++] = 'u';
	rot_chars[rci++] = 'U';
	rot_len[ri] = (rci - rot_pos[ri]);
	ri++;

	rot_pos[ri] = rci;
	rot_chars[rci++] = 'v';
	rot_chars[rci++] = 'V';
	rot_len[ri] = (rci - rot_pos[ri]);
	ri++;

	rot_pos[ri] = rci;
	rot_chars[rci++] = 'w';
	rot_chars[rci++] = 'W';
	rot_len[ri] = (rci - rot_pos[ri]);
	ri++;

	rot_pos[ri] = rci;
	rot_chars[rci++] = 'x';
	rot_chars[rci++] = 'X';
	rot_len[ri] = (rci - rot_pos[ri]);
	ri++;

	rot_pos[ri] = rci;
	rot_chars[rci++] = 'y';
	rot_chars[rci++] = 'Y';
	rot_len[ri] = (rci - rot_pos[ri]);
	ri++;

	rot_pos[ri] = rci;
	rot_chars[rci++] = 'z';
	rot_chars[rci++] = 'Z';
	rot_len[ri] = (rci - rot_pos[ri]);
	ri++;

	rot_charslen = rci;
	rot_poslen = ri;

}

/* new word */
void new()
{
.include [List.HybridLeet:new]
}

void next()
{
	int i, j;

	/* If we have reached the maximum number of rotations, we're done */
	if (word_rot_current == hybrid_total)
	{
		word[0] = 0;
		return;
	}

	/* set word[] to the next candidate */
	i=0;
	while (i < word_rot_count)
	{
		/* Replace letter in word with appropriate rotated letter fom rot_chars */
		word[word_rot_idx[i]] = rot_chars[word_rotchars_pos[i]];
		i++;
	}

	/* Rotate the word_rotchars_pos */
	i=0;
	while (i < word_rot_count)
	{
		word_rotchars_pos[i]++;

		j = word_rot_pos[i];
		if (word_rotchars_pos[i] != (rot_pos[j] + rot_len[j]))
		{
			/* No carry */
			break;
		}

		/* Rotation overflow, carry to next rotation */
		word_rotchars_pos[i] = rot_pos[j];

		i++;
	}

	word_rot_current++;
}

/* Called when restoring an interrupted session */
void restore()
{
	int wrc;

.include [List.HybridLeet:new]

	/* Pick up the current iteration */
	word_rot_current = hybrid_resume;

	/* Zoom the word_rotchars_pos to the hybrid_resume iteration */
	i=0;
	wrc = word_rot_current;

	while (i < word_rot_count)
	{
		j = word_rot_pos[i];

		/* Rotate this position */
		word_rotchars_pos[i] = rot_pos[j] + (wrc % rot_len[j]);
		wrc = wrc / rot_len[j];

		i++;
	}
}
