So the program works really well aside from some minor glitches. I was able to successfully produce words, produce sentences, and assemble words based on their assigned function in English syntax. This post is a bit late as I was having some last minute issues with the sentence constructor as well as issues with screen capturing as I was running it in fullscreen initially.
What is being shown is the program creates a set of words with random function being nouns or verbs. These are represented as the coloured dots on screen. The blue line shows which words are being used in the current sentence. If you select a positive response the words will then have a green line and recorded as complimentary so that the sentence constructor will attempt to add those words together in other sentences as they make sense in context (according to player response). If a negative response is selected the words will be given a red line to show a dead relation and the program will avoid using those words together in a sentence however new words may connect the two as a new word may change the context of the statement. The "I understand" and "pointless" options are there to increase the rate the words generate if the statements start becoming repetitious or aren't readable.
I wasn't able to touch any of the AI concepts since that would have been a project in itself but I think I'm happy having a networking language program that as far as I'm concerned shouldn't crash given the stress testing I've done. I was hoping to add some more graphics to the project like towers to show an archive of all the sentences as well as adding more sentences each cycle however at the current state I would have to move a lot of code around and Im unfortunately out of time. I'm struggling to go back and comment all of the code but I did leave some variables in that I wasnt able to utilize in the final build. Those however I left in so I had some room to expand if I did end up having the time.
//CODE
PVector[] snowFlakes = new PVector[2000];
float[] snowSpin = new float[2000];
Entity player = new Entity();
Entity stranger = new Entity();
Words useWords = new Words();
Central central = new Central();
int progress = 0;
void setup()
{
size(1600, 900, P3D);
//fullScreen(P3D);
snowSetup();
//pWords.makeWord();
//pWords.makeWord();
for (int a = 0; a < 5; a++)
{
central.addWord();
}
player.addDialogue("Yes");
player.addDialogue("No");
player.addDialogue("I think I understand");//pWords.wordList.get(0));
player.addDialogue("This is pointless");//pWords.wordList.get(1));
}
void draw()
{
lights();
translate(0, 0, 0);
background(200);
midGround();
snowing();
timeLine();
playerSpeak();
central.drawMe();
}
void snowSetup()
{
for (int a = 0; a < snowFlakes.length; a ++)
{
snowSpin[a] = random(-1, 1);
snowFlakes[a] = new PVector(random(-width, width*2), random(-height/2, height), random(-width*2, width*.75));
}
}
void snowing()
{
noStroke();
fill(255, 255, 255, 200);
for (int a = 0; a < snowFlakes.length; a ++)
{
pushMatrix();
translate(snowFlakes[a].x, snowFlakes[a].y, snowFlakes[a].z);
//ellipse(0, 0, 10, 5);
rect(0, 0, 20, 10);
popMatrix();
//random variation in snowing movement
snowSpin[a] += random(-.2, .1);
//wave movement with y set to always increase
snowFlakes[a].y += abs(sin(snowSpin[a]));//random(0.1,1);
snowFlakes[a].x += cos(snowSpin[a])/2;//random(-.5,.5);
snowFlakes[a].z += cos(snowSpin[a])/2;
//reset the snow position to the sky once it hits the ground
if (snowFlakes[a].y > height)
{
snowFlakes[a] = new PVector(random(-width, width*2), random(-height, -height/2), random(-width*2, width*.75));
}
}
}
void midGround()
{
stroke(100);
fill(150, 100, 100);
pushMatrix();
translate(width/2, height+100, -width/2);
box(width*10, 100, width*10);
popMatrix();
}
void playerSpeak()
{
if (stranger.doneTalking())
{
player.multipleText();
}
}
void timeLine()
{
switch(progress)
{
case 0:
//reset sentences
stranger.dialogue = new ArrayList();
//stranger.addDialogue("Busy working on the " + sWords.wordList.get(0) + "?");
stranger.addDialogue(central.makeSentence());
stranger.setupText();
progress++;
central.addWord();
break;
case 1:
stranger.textBox();
central.remember();
break;
}
}
//a String based Dictionary class for holding 1 string as a word and it's traits
class Dict
{
ArrayList <String> wordList = new ArrayList();
String word;
//other words that has made a positive response
ArrayList <Dict> siblings = new ArrayList();
//other words that has made a negative response
ArrayList <Dict> rejects = new ArrayList();
boolean isPronoun;
boolean isPropNoun;
boolean isNoun;
boolean isVerb;
boolean isAdjective;
boolean isAdverb;
boolean isSpecific;
boolean isGeneral;
//drawing
PVector dColour = new PVector();
PVector outPos = new PVector();
PVector moveRate = new PVector();
float rotation;
float orbitOff;
//
float orbitR;
Dict(String eWord)
{
word = eWord;
//
rotation = random(-2, 1);
//
orbitOff = random(-1, 1);
orbitR = central.definitions.size();
//
dColour = new PVector(random(0,255),random(0,255),random(0,255));
}
//use this to assign a word to either verb or noun randomly
void randomTraits()
{
//rolls a random float between 0 and 2 and rounds down to an int
//0 = false, anything above zero (1 or 2) is true;
if (boolean(floor(random(0, 2))))
{
println("noun");
isNoun = true;
if (boolean(floor(random(0, 2))))
{
isSpecific = true;
} else
{
isGeneral = true;
}
} else
{
println("verb");
isVerb = true;
}
}
//draw
void moveDot()
{
rotation += random(0, 0.005);
orbitOff += random(0, 0.012);
moveRate.x = sin(rotation);
moveRate.y = cos(orbitOff);
moveRate.z = cos(rotation);
moveRate = moveRate.normalize();
outPos.x = width/2 + moveRate.x * (orbitR + 200);
outPos.y = height/2 + moveRate.y * (orbitR + 200);
outPos.z = -width/2 + moveRate.z * (orbitR + 200);
}
}
class Central
{
int positive;
int negative;
PVector centerPos;
ArrayList <String> sentences = new ArrayList();
ArrayList <Dict> definitions = new ArrayList();
//Definite articles refer to the subject
String the = "the";
//Indefinite Articles refer to a subject
String aaa = "a";
ArrayList <Dict> phraseWords = new ArrayList();
String phrase;
int wordCountP;
int sentCount;
int hasSiblings;
//
Central()
{
}
//use to construct a new word with random traits
void addWord()
{
definitions.add(new Dict(useWords.makeWord()));
definitions.get(definitions.size()-1).randomTraits();
}
//Make a sentence
String makeSentence()
{
hasSiblings = 0;
//reset variables
wordCountP = int(random(2, 4));
phraseWords = new ArrayList();
phrase = new String();
//add a random word for the array size
for (phraseWords.size(); phraseWords.size() < wordCountP; )
{
phraseWords.add(definitions.get(int(random(0, definitions.size()))));
//add a sibling
if (phraseWords.get(phraseWords.size()-1).siblings.size()>0)
{
phraseWords.add(phraseWords.get(phraseWords.size()-1)
.siblings.get(int(random(0, phraseWords.get(phraseWords.size()-1).siblings.size()-1))));
}
//remove a reject
for (int a = 1; a < phraseWords.size(); a++)
{
//for (int b = 0; b < phraseWords.size(); b++)
{
if (phraseWords.get(a).rejects.size()>0)
{
for (int c = 0; c < phraseWords.get(a).rejects.size(); c++)
{
if (phraseWords.get(a).rejects.get(c) == phraseWords.get(a-1))
{
if (a >= phraseWords.size())
{
phraseWords.remove(a-1);
}
}
}
}
}
}
}
//Sentence construction
for (int a = 0; a < phraseWords.size(); a++)
{
//add a conjunction between subjects
if (a> 0 && a+1 < phraseWords.size())
{
if (phraseWords.get(a).isNoun && phraseWords.get(a+1).isNoun)
{
phrase += "and ";
}
}
//Add definite article before noun.
if (phraseWords.get(a).isNoun)
{
//use the construct method to add an Article
//add "the" to a known subject
phrase += article(phraseWords.get(a).isSpecific, the + " ", a);
//add "a" to a general subject
phrase += article(phraseWords.get(a).isGeneral, aaa + " ", a);
}
//add a new word.
phrase+= phraseWords.get(a).word;
//add space if there are still words to add.
if (a < phraseWords.size()-1)
{
phrase += " ";
}
}
//if there are 2 verbs together then the last becomes an adverb.
if (phraseWords.get(phraseWords.size()-1).isVerb && phraseWords.get(phraseWords.size()-2).isVerb)
{
phrase+= "ly";
}
phrase+= ".";
return phrase;
}
//recieve viewer feedback
void remember()
{
if (player.pInput[0])
{
positive++;
progress = 0;
for (int a = 1; a < phraseWords.size(); a++)
{
phraseWords.get(a).siblings.add(phraseWords.get(a-1));
}
}
if (player.pInput[1])
{
positive--;
progress = 0;
for (int a = 1; a < phraseWords.size(); a++)
{
phraseWords.get(a).rejects.add(phraseWords.get(a-1));
}
}
if (player.pInput[2])
{
positive+=2;
progress = 0;
for (int a = 1; a < phraseWords.size(); a++)
{
phraseWords.get(a).siblings.add(phraseWords.get(a-1));
}
addWord();
addWord();
}
if (player.pInput[3])
{
positive-=3;
progress = 0;
for (int a = 1; a < phraseWords.size(); a++)
{
phraseWords.get(a).rejects.add(phraseWords.get(a-1));
}
addWord();
addWord();
}
}
//returns a string that is a verb
String verb()
{
//only run loop if dictionary contains a word
if (definitions.size()>0)
{
//grab a random word from the dictionary
for (int a = 0; a < definitions.size(); a = int(random(0, definitions.size()))) //definitions.get(a).isVerb; a ++)
{
//check if the word is a verb to output
if (definitions.get(a).isVerb)
{
return definitions.get(a).word;
}
}
}
return "";
}
String article(boolean trait, String word, int wordPlace)
{
if (trait)
{
if (wordPlace == 0)
{
return word.substring(0, 1).toUpperCase() + word.substring(1, word.length());
} else
{
return word;
}
}
return "";
}
//Returns a Noun
String noun()
{
//only run if the dictionary contains a word
if (definitions.size()>0)
{
//grab a random word from the dictionary
for (int a = 0; a < definitions.size(); a = int(random(0, definitions.size()))) //definitions.get(a).isVerb; a ++)
{
//check if the word is a noun
if (definitions.get(a).isNoun)
{
return definitions.get(a).word;
}
}
}
return "";
}
String ranWord()
{
return definitions.get(int(random(0, definitions.size()))).word;
}
//display the words
void drawMe()
{
centerPos = new PVector(width/2, height/2, -width/2);
//draw center
pushMatrix();
translate(centerPos.x, centerPos.y, centerPos.z);
fill(250, 100, 200);
ellipse(0, 0, 100, 100);
popMatrix();
//draw orbits
fill(200, 150, 150);
for (int a = 0; a < definitions.size(); a ++)
{
fill(definitions.get(a).dColour.x, definitions.get(a).dColour.y, definitions.get(a).dColour.z);
pushMatrix();
definitions.get(a).moveDot();
translate(definitions.get(a).outPos.x, definitions.get(a).outPos.y, definitions.get(a).outPos.z);//a*50, defPos.get(a).y);
ellipse(0, 0, 50, 50);
popMatrix();
}
//active connections
strokeWeight(10);
stroke(100, 100, 200, 200);
for (int a = 1; a < phraseWords.size(); a++)
{
line(phraseWords.get(a).outPos.x, phraseWords.get(a).outPos.y, phraseWords.get(a).outPos.z - 5,
phraseWords.get(a-1).outPos.x, phraseWords.get(a-1).outPos.y, phraseWords.get(a-1).outPos.z - 5);
}
//sibling connections
strokeWeight(8);
stroke(150, 170, 50, 125);
for (int a = 1; a < definitions.size(); a++)
{
for (int b = 0; b < definitions.get(a).siblings.size(); b++)
{
line(definitions.get(a).outPos.x, definitions.get(a).outPos.y, definitions.get(a).outPos.z - 10,
definitions.get(a).siblings.get(b).outPos.x, definitions.get(a).siblings.get(b).outPos.y,
definitions.get(a).siblings.get(b).outPos.z - 10);
}
}
//reject connections
strokeWeight(8);
stroke(120, 50, 50, 125);
for (int a = 1; a < definitions.size(); a++)
{
for (int b = 0; b < definitions.get(a).rejects.size(); b++)
{
line(definitions.get(a).outPos.x, definitions.get(a).outPos.y, definitions.get(a).outPos.z - 10,
definitions.get(a).rejects.get(b).outPos.x, definitions.get(a).rejects.get(b).outPos.y,
definitions.get(a).rejects.get(b).outPos.z - 10);
}
}
}
}
//a String based Dictionary class for holding 1 string as a word and it's traits
class Dict
{
ArrayList <String> wordList = new ArrayList();
String word;
//other words that has made a positive response
ArrayList <Dict> siblings = new ArrayList();
//other words that has made a negative response
ArrayList <Dict> rejects = new ArrayList();
//boolean isPronoun;
//boolean isPropNoun;
boolean isNoun;
boolean isVerb;
//boolean isAdjective;
//boolean isAdverb;
boolean isSpecific;
boolean isGeneral;
//drawing
PVector dColour = new PVector();
PVector outPos = new PVector();
PVector moveRate = new PVector();
float rotation;
float orbitOff;
//
float orbitR;
Dict(String eWord)
{
word = eWord;
//
rotation = random(-2, 1);
//
orbitOff = random(-1, 1);
orbitR = central.definitions.size();
//
dColour = new PVector(random(0,255),random(0,255),random(0,255));
}
//use this to assign a word to either verb or noun randomly
void randomTraits()
{
//rolls a random float between 0 and 2 and rounds down to an int
//0 = false, anything above zero (1 or 2) is true;
if (boolean(floor(random(0, 2))))
{
println("noun");
isNoun = true;
if (boolean(floor(random(0, 2))))
{
isSpecific = true;
} else
{
isGeneral = true;
}
} else
{
println("verb");
isVerb = true;
}
}
//draw
void moveDot()
{
rotation += random(0, 0.005);
orbitOff += random(0, 0.012);
moveRate.x = sin(rotation);
moveRate.y = cos(orbitOff);
moveRate.z = cos(rotation);
moveRate = moveRate.normalize();
outPos.x = width/2 + moveRate.x * (orbitR + 200);
outPos.y = height/2 + moveRate.y * (orbitR + 200);
outPos.z = -width/2 + moveRate.z * (orbitR + 200);
}
}
class Entity
{
PVector position = new PVector();
//Text
//Speech list
ArrayList <String> dialogue = new ArrayList();
//
int dStep = 0;
//
float printSize = 30;
//Text box
PVector tbSize = new PVector(300, 100);
PVector tbPos = new PVector();
//printing speed
float textSpeed;
//print line
int step = 1;
//the width of each row
int lineLength = 30;
//the numbers of rows needed to print all the text
int textLineCount;
//counts up to print the text
int[] textCrawl = new int[4];
//the margins to start and stop the string segments
int[] textMargin = new int[5];
//locks each line of text to stop them from printing past the margins
boolean[] stepLocked = new boolean[4];
//
PVector tbButtonPos = new PVector();
PVector tbButtonSize = new PVector(50, 50);
//
boolean textDone;
boolean pressLock;
Entity()
{
}
void addDialogue(String enterText)
{
//enter dialogue string;
dialogue.add(enterText);
}
//sets up all the parameters for the dialogue box to display and print;
void setupText()
{
//measure the amount of rows needed to draw all the text
textLineCount = ceil(dialogue.get(dStep).length()/lineLength)+1;
//set Textbox position
tbPos = new PVector(width - lineLength*12 - 300, height/2 + 50);
//set the textbox size to encapsulate all the text
tbSize = new PVector(lineLength*12 + 100, textLineCount * (printSize));
//println(textLineCount);
//reinitialize all the arrays to the correct size to print all the dialogue
//text printing
textCrawl = new int[textLineCount];
//stop each row from going over
stepLocked = new boolean[textLineCount];
//set the margin to stop and start the text in
textMargin = new int[textLineCount+1];
//setup margins for the text
for (int a = 0; a < textMargin.length; a ++)
{
//set the markers for when to start and end the text scrawl
textMargin[a] = lineLength*a;//tbSize.x/11)*a;
}
//setup the text typing starting positions;
for (int a = 0; a < textCrawl.length; a ++)
{
//set up an int to print in each letter as it increases;
textCrawl[a] = textMargin[a];
}
step = 1;
textSpeed = 0;
}
boolean doneAll;
//prints and proceeds dialogue on screen
void textBox()
{
pushMatrix();
//draw textBox
translate(tbPos.x, tbPos.y);
fill(230);
rect(0, 0, tbSize.x + 100, tbSize.y+10);
//text box
fill(0);
textSize(printSize);
translate(0, 30, 0);
//speed that the text will display at
textSpeed += 10/frameRate;
//print all lines of text out in the current dialogue string
for (int a = 0; a < step; a ++)
{
//stop the text from going beyond the string length and crashing
if (textCrawl[a] < dialogue.get(dStep).length())
{
//print text by increasing text lines until it hits the margin and dont cut the word off
if (textCrawl[a] < textMargin[a+1] || dialogue.get(dStep).charAt(textCrawl[a]) != ' ')
{
//dont print over dialogue length and crash
if (textCrawl[a] < dialogue.get(dStep).length())
{
//extend text print by the print speed;
textCrawl[a] = int(textSpeed);
}
}
}
//stop the text from going beyond dialogue length
if (textCrawl[a] < dialogue.get(dStep).length())
{
//if the text length is larger than the margin length start the next line
if (textCrawl[a] >= textMargin[a+1] )//&& dialogue.get(0).charAt(textCrawl[a]) == ' ')
{
//only move to the next line once;
if (!stepLocked[a])
{
//only move down a line if there is another line and dont cut words off
if (step+1 <= textCrawl.length && (dialogue.get(dStep).charAt(textCrawl[a]) == ' ' || dialogue.get(dStep).charAt(textCrawl[a]) == '.'))
{
//move the starting marker to where the previous line ended
textMargin[a+1] = textCrawl[a];
//lock this line of text
stepLocked[a] = true;
//increase loop size to add the next text line;
step++;
}
}
}
}
//Text
fill(100, 100, 255);
//println(textMargin[a] + " " + textCrawl[a]);
text(dialogue.get(dStep).substring(textMargin[a], textCrawl[a]), 10, 25*a);
}
//textCrawl[0] = int(textSpeed);
popMatrix();
//Return true once all the text in the current line of dialogue is done printing
textDone = true;
if (textCrawl[textCrawl.length-1] < dialogue.get(dStep).length())
{
//println(dialogue.get(0).length());
textDone = false;
}
//load the button to proceed to the next dialogue;
if (textDone)
{
nextTextButton();
}
}
//proceeds text to next lines
void nextTextButton()
{
tbButtonPos = new PVector(tbPos.x, tbPos.y);
tbButtonPos.x = tbPos.x + tbSize.x - tbButtonSize.x;
tbButtonPos.y = tbPos.y + tbSize.y;
if (dStep+1 < dialogue.size()) {
//select to progress dialogue when first line is done.
if (mouseX > tbButtonPos.x && mouseX < tbButtonPos.x + tbButtonSize.x)
{
if (mouseY > tbButtonPos.y && mouseY < tbButtonPos.y + tbButtonSize.y)
{
if (mousePressed)
{
//dont proceed if it's the end of text list
if (pressLock)
{
dStep ++;
setupText();
pressLock = false;
}
//println(true);
} else
{
pressLock = true;
}
}
}
}
pushMatrix();
fill(50);
translate(tbButtonPos.x, tbButtonPos.y);
rect(0, 0, tbButtonSize.x, tbButtonSize.y);
popMatrix();
}
//tells the program when the current dialogue has run through
boolean doneTalking()
{
if (dStep+1 >= dialogue.size() && textDone)
{
return true;
}
return false;
}
PVector pPos = new PVector(100, 200);
boolean[] pInput = new boolean[4];
PVector rPos;
PVector rEnd;
void multipleText()
{
pushMatrix();
//make a return for each response option
pInput = new boolean[dialogue.size()];
//draw all the player choices
for (int a = 0; a < dialogue.size(); a++)
{
//positions and size
rPos = new PVector(100, 200 + 60*a);
rEnd = new PVector(20 + (printSize/2*dialogue.get(a).length()), 50);
//draw the rectangles
fill(150, 150, 50);
rect(rPos.x, rPos.y, 20 + rEnd.x, rEnd.y);
//draw the text
fill(50, 50, 50);
textSize(printSize);
text(dialogue.get(a), pPos.x + 10, pPos.y + 30 + 60*a);
//Player input when they select a dialogue
if (mouseX > rPos.x && mouseX < rPos.x + rEnd.x)
{
if (mouseY > rPos.y && mouseY < rPos.y + rEnd.y)
{
if (mousePressed)
{
if (dStep+1 < dialogue.size() && pressLock)
{
pInput[a] = true;
println(true);
pressLock = false;
}
//println(true);
} else
{
pressLock = true;
}
}
}
}
popMatrix();
}
}
class Words
{
//String[] vowels = {"a", "e", "i", "o", "u"};
char[] vowels = {'a', 'e', 'i', 'o', 'u'};
//String[] cons = {"b", "c", "d", "f", "g", "h", "j", "k", "l", "m", "n", "p", "q", "r", "s", "t", "v", "w", "x", "y", "z"};
char[] cons = {'b', 'c', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm', 'n', 'p', 'q', 'r', 's', 't', 'v', 'w', 'x', 'y', 'z'};
String[] anyLetter = {"a", "b", "c", "d", "e", "f", "g", "h", "i", "j",
"k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"};
//char[] anyLetter = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
//'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'};
ArrayList <String> wordList = new ArrayList();
String word;
ArrayList <String> siblings = new ArrayList();
ArrayList <String> rejects = new ArrayList();
Words(String eWord)
{
word = eWord;
}
Words()
{
}
//String word = new String();
int wordLength;
boolean addDone;
//THIS function generates new words and adds them to the stack whenever it's called
String makeWord()
{
wordLength = int(random(1, 8));
//wordLength = 8;
word = new String();
for (int a = 0; a < wordLength; a++)
{
addDone = false;
if (word.length() <= 0)
{
word += new String(anyLetter[int(random(0, anyLetter.length))]);
}
if (word.length() > 0)
{
//check if last letter is any vowel
for (int b = 0; b < vowels.length; b ++)
{
if (!addDone)
{
//add constinent if last letter is vowel
if (word.charAt(word.length()-1) == vowels[b])
{
word += cons[int(random(0, cons.length))];
addDone = true;
}
}
}
//check if last letter is a constinant
for (int b = 0; b < cons.length; b ++)
{
if (!addDone)
{
//add vowel if last letter is constinant
if (word.charAt(word.length()-1) == cons[b])
{
word += vowels[int(random(0, vowels.length))];
addDone = true;
}
}
}
}
}
wordList.add(word);
return word;
}
String lateWord()
{
return(wordList.get(wordList.size()-1));
}
}
No comments:
Post a Comment