/* Poetry Evolver */

/* Math Functions */
function log10(x) {
return Math.LOG10E * Math.log(x);
}

function randomCap(num) {
var dice = Math.round(Math.random() * Math.pow(10, Math.floor(log10(num) + 1)));
if (num <= dice)
return randomCap(num);
else
return dice;
}

/* Word Banks */
var TheTruthAboutSanchoPanza = list("he", "marveled", "at", "himself", "Razumikhin", "was", "one", "of", "his", "former", "university", "friends", "it", "was", "remarkable", "that", "Raskolnikov", "had", "almost", "no", "friends", "while", "he", "was", "at", "the", "university", "kept", "aloof", "from", "everyone", "visited", "no", "one", "and", "had", "difficulty", "recieving", "visitors", "soon", "however", "everyone", "also", "turned", "away", "from", "him", "general", "gatherings", "conversations", "merrymarking", "he", "somehow", "did", "not", "participate", "in", "any", "of", "it", "he", "was", "a", "zealous", "student", "unsparing", "of", "himself", "and", "was", "respected", "for", "it", "but", "no", "one", "loved", "him", "he", "was", "very", "poor", "and", "somehow", "haughtily", "proud", "and", "unsociable", "as", "though", "he", "were", "keeping", "something", "to", "himself", "it", "seemed", "to", "some", "of", "his", "friends", "that", "he", "looked", "upon", "them", "all", "as", "children", "from", "above", "as", "though", "he", "were", "ahead", "of", "them", "all", "in", "development", "in", "knowledge", "and", "in", "convictions", "and", "that", "he", "regarded", "their", "convictions", "and", "interests", "as", "something", "inferior");

/* Initializers */
function makeInitialMemes() {
return initialMemesMakerA();
}

function reproduce(meme1, meme2) {
return reproducerA(meme1, meme2);
}

function mutate(meme, r) {
return mutatorA(meme, r);
}

var litterSize = 6;

var wordBank = TheTruthAboutSanchoPanza;

var wordBankSize = length(wordBank);

/* Text-Working Functions */
function prepMemePart(memepart) {
if (memepart == null)
return "\n";
else 
return car(memepart) + " " + prepMemePart(cdr(memepart));
}

function prepMeme(meme) {
if (meme == null)
return "";
else
return prepMemePart(car(meme)) + prepMeme(cdr(meme));
}

function prepMemes(memes, c) {
if (memes == null)
return "\n";
else
return c + ".  " + prepMeme(car(memes)) + prepMemes(cdr(memes), c + 1);
}

function writeForms(memes) {
document.write(prepMemes(memes, 1));
}

/* Driver Loop Function */
function loopHelper(memes) {
writeForms(map(growForm, memes));
var input = prompt("what?");
if (input == "exit")
return null;
var input2 = prompt("'what else?");
if (input2 == "exit")
return null;
else
loopHelper(reproduce(item(parseInt(input) - 1 , memes), item(parseInt(input2) -1 , memes)));
}

function evolverLoop() {
loopHelper(makeInitialMemes());
}

/* Memes to Word Forms Function */
function growFormhelper(lst) {
if (lst == null)
return null;
else
return cons(item(car(lst), wordBank), growFormhelper(cdr(lst)));
}

function growForm(meme) {
function helper(meme) {
if (meme == null)
return null;
else
return cons(growFormhelper(car(meme)), helper(cdr(meme)));
}
return helper(cdr(meme));
}

/* Reproduction Functions */
function litterMaker(num) {
if (num == 0)
return null;
else
return cons(1, litterMaker(num - 1));
}

function reproducerAhelper(lst1, lst2) {
var dice =  randomCap(2);
if (lst1 == null)
return lst2;
else {
if (lst2 == null)
return lst1;
else {
if  (dice ==  0)
return cons(car(lst1), reproducerAhelper(cdr(lst2), cdr(lst1)));
else
return cons(car(lst2), reproducerAhelper(cdr(lst2), cdr(lst1)));
}
}
}

function reproducerAhelper2(meme1, meme2) {
if (meme1 == null || meme2 == null)
return null;
else
return cons(reproducerAhelper(car(meme1), car(meme2)), reproducerAhelper2(cdr(meme1), cdr(meme2)));
}

function reproducerA(meme1, meme2) {
var memeA = append(mutate(list(car(meme1)), 8), mutate(cdr(meme1), wordBankSize));
var memeB = append(mutate(list(car(meme2)), 8), mutate(cdr(meme2), wordBankSize));
var nextGen = null;
var c = litterSize;
while (c > 0) {
nextGen = cons(alignForm(reproducerAhelper2(memeA, memeB)), nextGen);
--c;
}
return nextGen;
}

/*Higher Level Memes */
function addRandomWords(num) {
if (num == 0)
return null;
else
return cons(randomCap(wordBankSize), addRandomWords(num - 1));
}

function addRandomSection(lst) {
if (lst == null)
return null;
else
return cons(addRandomWords(car(lst)), addRandomSection(cdr(lst)));
}

function alignForm(meme) {
function helper(formPart, wordPart) {
if (formPart == null) {
if (length(form) < length(word))
return helper(form, wordPart);
else
return null;
}
else {
if (wordPart == null) {
if (length(form) < length(word))
return null;
else
return helper(formPart, addRandomSection(formPart));
}
else {
if (car(formPart) > length(car(wordPart)))
return helper(formPart, cons( append(car(wordPart), addRandomWords(car(formPart) - length(car(wordPart)))), cdr(wordPart)));
else
return cons(filter(function (x) {return position(x, car(wordPart)) < car(formPart);}, car(wordPart)), helper(cdr(formPart), cdr(wordPart)));
}}}
var form = car(meme);
var word = cdr(meme);
return cons(form, helper(form, word));
}

/* Mutator Functions */
function partMutator(part, r) {
var dice = randomCap(6);
if (part == null)
return null;
else {
if (dice == 4)
return cons(randomCap(r), partMutator(cdr(part), r));
else {
if (dice == 3)
return partMutator(cdr(part), r);
else {
if (dice == 2)
return cons(randomCap(r), cons(randomCap(r), partMutator(cdr(part), r)));
else
return cons(car(part), partMutator(cdr(part), r));
}
}
}
}

function mutatorA(meme, r) {
return map(function(x) {return partMutator(x, r);}, meme);
}

/* Initial Meme Makers */
function memeMakerA() {
var x = wordBankSize;
var theList = list(list(3 + randomCap(8), 3 + randomCap(8), 3 + randomCap(8)),
list(randomCap(x), randomCap(x), randomCap(x), randomCap(x), randomCap(x), randomCap(x), randomCap(x)), list(randomCap(x), randomCap(x), randomCap(x), randomCap(x), randomCap(x), randomCap(x), randomCap(x)), list(randomCap(x), randomCap(x), randomCap(x), randomCap(x), randomCap(x), randomCap(x), randomCap(x)), list(randomCap(x), randomCap(x), randomCap(x), randomCap(x), randomCap(x), randomCap(x), randomCap(x)),
list(randomCap(x), randomCap(x), randomCap(x), randomCap(x), randomCap(x)));
return theList;
}


function initialMemesMakerA() {
var c = 6;
var theList = null;
while (c > 0) {
theList = cons(memeMakerA(), theList);
--c;
}
return theList;
}

