############################################################################ # # File: verse.icn # # Subject: Program to generate bizarre verses # # Author: Chris Tenaglia # # Date: May 26, 1992 # ############################################################################ # # This file is in the public domain. # ############################################################################ # # This verse maker was initially published in an early 1980s Byte magazine in # TRS80 Basic. In 1985 I translated it to BASICA, and in 1987 I translated it # to Icon. Recently, I've polished it to fetch the vocabulary all from one # file. # # A vocabulary file can be specified on the command line; otherwise # file it looks for verse.dat by default. See that file for examples # of form. # ############################################################################ # # Links: random # ############################################################################ link random global nouns,nounp,adjt,advb,more,most,ivpre,ivpas,tvpre,tvpas,prep global being,art,ques,cond,nompro,punc,noun1,noun2,tv,iv,adjv,prpo global be,pun,pron,con,ar,tnnum,tadjno,ttvnum,tprnum,cls,name,watch procedure main(param) local in, part, line, tmp, reply, Out, In, t randomize() nouns := [] #singular nouns nounp := [] #plural nouns adjt := [] #adjectives advb := [] #adverbized more := [] #more adjective most := [] #most adjective tvpas := [] #transitive verb past tvpre := [] #transitive verb present ivpas := [] #intransitive verb past ivpre := [] #intransitive verb present prep := [] #prepositions punc := [] #punctuations art := [] #articles of speech ques := [] #question words being := [] #being verbs cls := "\e[H\e[2J" #clear screen string (or system("clear")) ############################################################################ # # # load the vocabulary arrays # # # ############################################################################ name := param[1] | "verse.dat" (in := open(name)) | stop("Can't open vocabulary file (",name,")") part := "?" ; watch := "?" write(cls,"VERSE : AI Mysterious Poetry Generator\n\nInitializing\n\n") while line := read(in) do { if match("%",line) then { part := map(trim(line[2:0])) write("Loading words of type ",part) next } tmp := parse(line,'|@#') case part of { "noun" : { put(nouns,tmp[1]) put(nounp,tmp[2]) } "adjt" : { put(adjt,tmp[1]) put(advb,tmp[2]) put(more,tmp[3]) put(most,tmp[4]) } "ivrb" : { put(ivpre,tmp[1]) put(ivpas,tmp[2]) } "tvrb" : { put(tvpre,tmp[1]) put(tvpas,tmp[2]) } "prep" : put(prep,line) "been" : put(being,line) default: write("Such Language!") } loadrest() } close(in) reply := "" while map(reply) ~== "q" do { # # output the title # (Out := open("a.out","w")) | stop ("can't open a.out for some reason!") t := ?7 tnnum := ?*(nouns) #title noun selector tadjno:= ?*(adjt) #title adjective selector ttvnum:= ?*(tvpre) #title transitive verb selector tprnum:= ?*(prep) #title preposition selector clrvdu() write(title(t)) write(Out,title(t)) write() write(Out) # # output the lines # every 1 to (12+?6) do { noun1 := ?*(nouns) noun2 := ?*(nouns) tv := ?*(tvpre) iv := ?*(ivpre) adjv := ?*(adjt) prpo := ?*(prep) be := ?*(being) pun := ?*(punc) pron := ?*(nompro) con := ?*(cond) ar := ?*(art) case ?19 of { 1 : {write(form1()) ; write(Out,form1())} 2 : {write(form2()) ; write(Out,form2())} 3 : {write(form3()) ; write(Out,form3())} 4 : {write(form4()) ; write(Out,form4())} 5 : {write(form5()) ; write(Out,form5())} 6 : {write(form6()) ; write(Out,form6())} 7 : {write(form7()) ; write(Out,form7())} 8 : {write(form8()) ; write(Out,form8())} 9 : {write(form9()) ; write(Out,form9())} 10 : {write(form10()) ; write(Out,form10())} 11 : {write(form11()) ; write(Out,form11())} 12 : {write(form12()) ; write(Out,form12())} 13 : {write(form13()) ; write(Out,form13())} 14 : {write(form14()) ; write(Out,form14())} 15 : {write(form15()) ; write(Out,form15())} 16 : {write(form16()) ; write(Out,form16())} 17 : {write(form17()) ; write(Out,form17())} 18 : {write(form18()) ; write(Out,form18())} 19 : {write(form19()) ; write(Out,form19())} } } # last line case ?2 of { 1 : { write(nounp[tnnum]," ",prep[prpo]," THE ",nouns[noun1], " ",being[be]," ",adjt[tadjno],".") write(Out,nounp[tnnum]," ",prep[prpo]," THE ",nouns[noun1], " ",being[be]," ",adjt[tadjno],".") } 2 : { write("THE ",nounp[tnnum]," OR ",nouns[noun1]," ", adjt[adjv]," ",being[be],".") write(Out,"THE ",nounp[tnnum]," OR ",nouns[noun1]," ", adjt[adjv]," ",being[be],".") } } close(Out) write() writes("Press for another, Q to quit, or a name to save it>") reply := read() if (reply ~== "Q") & (trim(reply) ~== "") then { (In := open("a.out")) | stop ("can't open a.out for some reason!") (Out := open(reply,"w")) | stop ("can't open ",reply) while write(Out,read(In)) close(In) ; close(Out) } } end ############################################################################ procedure aoran(word) local vowels vowels := 'AEIOU' if any(vowels,word) then return ("AN " || word) else return ("A " || word) end ############################################################################ procedure clrvdu() writes(cls) end ############################################################################ procedure gerund(word) static vowel initial vowel := 'AEIOU' if word[-1] == "E" then word[-1] := "" return(word || "ING") end ############################################################################ procedure title(a) local text case a of { 1 : text := aoran(adjt[tadjno]) || " " || nouns[tnnum] 2 : text := "TO " || tvpre[ttvnum] || " SOME " || nouns[tnnum] 3 : text := prep[tprnum] || " " || nounp[tnnum] 4 : text := "THE " || nouns[tnnum] 5 : text := prep[tprnum] || " " || aoran(nouns[tnnum]) || " " || advb[tadjno] 6 : text := "THE " || more[tadjno] || " " || nouns[tnnum] 7 : text := "THE " || most[tadjno] || " " || nouns[tnnum] } return(text) end ############################################################################ procedure form1() local text, n, prefix n := 1 if watch=="true" then prefix := "(" || n || ") " else prefix := "" text := prefix || nounp[noun1] || " " || tvpre[tv] || " THE " text ||:= more[adjv] || " " || nouns[noun2] || punc[pun] return(text) end procedure form2() local text, n, prefix n := 2 if watch=="true" then prefix := "(" || n || ") " else prefix := "" text := prefix || nounp[noun1] || " " || tvpre[tv] || " THE " text ||:= most[adjv] || " " || nouns[noun2] || punc[pun] return(text) end procedure form3() local text, n, prefix n := 3 if watch=="true" then prefix := "(" || n || ") " else prefix := "" text := prefix || adjt[adjv] || " " || nounp[noun1] || " " || being[be] text ||:= " " || gerund(ivpre[iv]) || " " || punc[pun] return(text) end procedure form4() local text, n, prefix n := 4 if watch=="true" then prefix := "(" || n || ") " else prefix := "" text := prefix || adjt[adjv] || " " || nounp[noun1] || " " || ivpre[iv] text ||:= " " || punc[pun] return(text) end procedure form5() local text, n, prefix n := 5 if watch=="true" then prefix := "(" || n || ") " else prefix := "" text := prefix || ques[?*ques] || " " || adjt[adjv] || " " text ||:= nounp[noun1] || " " || ivpre[iv] || "?" return(text) end procedure form6() local text, n, prefix n := 6 if watch=="true" then prefix := "(" || n || ") " else prefix := "" text := prefix || art[ar] || " " || adjt[adjv] || " " || nouns[noun1] text ||:= " " || tvpas[tv] || " THE " || nouns[noun2] || punc[pun] return(text) end procedure form7() local text, n, prefix n := 7 if watch=="true" then prefix := "(" || n || ") " else prefix := "" text := prefix || "THE " || nounp[tnnum] || " " || ivpas[iv] text ||:= " " || prep[prpo] || " THE " || more[tadjno] || " " text ||:= nounp[noun1] || " " || punc[pun] return(text) end procedure form8() local text, n, prefix n := 8 if watch=="true" then prefix := "(" || n || ") " else prefix := "" text := prefix || "THE " || nounp[tnnum] || " " || ivpas[iv] || " " text ||:= prep[prpo] || " THE " || most[tadjno] || " " || nounp[noun1] text ||:= " " || punc[pun] return(text) end procedure form9() local text, n, prefix n := 9 if watch=="true" then prefix := "(" || n || ") " else prefix := "" text := prefix || ques[?*ques] || " " || nounp[tnnum] || " " || ivpre[iv] text ||:= " " || prep[prpo] || " " || aoran(adjt[adjv]) || " " text ||:= nouns[noun2] || "?" return(text) end procedure form10() local text, n, prefix n := 10 if watch=="true" then prefix := "(" || n || ") " else prefix := "" text := prefix || nounp[noun1] || " " || ivpre[iv] || " " || advb[adjv] text ||:= " " || prep[prpo] || " " || nompro[pron] || punc[pun] return(text) end procedure form11() local text, n, prefix n := 11 if watch=="true" then prefix := "(" || n || ") " else prefix := "" text := prefix || adjt[adjv] || " " || nounp[noun1] || " " || being[be] text ||:= " " || adjt[tadjno] || " " || cond[con] return(text) end procedure form12() local text, n, prefix n := 12 if watch=="true" then prefix := "(" || n || ") " else prefix := "" text := prefix || art[ar] || " " || nouns[noun1] || " " || ivpas[iv] text ||:= " " || advb[adjv] || punc[pun] return(text) end procedure form13() local text, n, prefix n := 13 if watch=="true" then prefix := "(" || n || ") " else prefix := "" text := prefix || cond[con] || " " || nounp[noun1] || " " || being[be] text ||:= " " || gerund(tvpre[ttvnum]) || " " || prep[prpo] || " " text ||:= gerund(ivpre[iv]) || " " || nounp[noun2] || punc[pun] return(text) end procedure form14() local text, n, prefix n := 14 if watch=="true" then prefix := "(" || n || ") " else prefix := "" text := prefix || art[ar] || " " || adjt[adjv] || " " || gerund(tvpre[tv]) text ||:= " OF THE " || nouns[tnnum] || " AND " || nouns[noun1] || punc[pun] return(text) end procedure form15() local text, n, prefix n := 15 if watch=="true" then prefix := "(" || n || ") " else prefix := "" text := prefix || gerund(tvpre[ttvnum]) || " " || nouns[noun1] text ||:= " AND " || nouns[noun2] return(text) end procedure form16() local text, n, prefix n := 16 if watch=="true" then prefix := "(" || n || ") " else prefix := "" text := prefix || "THE " || nounp[tnnum] || " " || ivpre[iv] || punc[pun] return(text) end procedure form17() local text, n, prefix n := 17 if watch=="true" then prefix := "(" || n || ") " else prefix := "" text := prefix || nompro[pron] || " " || tvpas[ttvnum] || " THE " text ||:= adjt[adjv] || " " || nouns[noun1] || punc[pun] return(text) end procedure form18() local text, n, prefix n := 18 if watch=="true" then prefix := "(" || n || ") " else prefix := "" text := prefix || adjt[adjv] || " " || nounp[noun2] || " " || being[be] text ||:= " " || nounp[noun1] || punc[pun] return(text) end procedure form19() local text, n, prefix n := 19 if watch=="true" then prefix := "(" || n || ") " else prefix := "" text := prefix || "THE " || nounp[tnnum] || "'S " || nounp[noun1] || " " text ||:= adjt[adjv] || " " || being[be] || punc[pun] return(text) end ############################################################################ procedure parse(line,delims) static chars local tokens chars := &cset -- delims tokens := [] line ? while tab(upto(chars)) do put(tokens,tab(many(chars))) return tokens end procedure loadrest() art := ["ITS" , "THIS" , "SOME", "ANY" , "ONE" , "THAT" , "ITS" , "MY" , "YOUR" , "OUR"] ques := ["WHY DO" , "WHEN DO" , "WHERE DO" , "HOW DO" , "CANNOT" , "HOW COME" , "WHY DON'T"] nompro := ["SOMETHING" , "ANYTHING" , "IT" , "THAT" , "ONE" , "YOU" , "THIS"] cond := ["SINCE" , "BECAUSE" , "UNTIL" , "IF" , "THEN" , "OR" , "UNLESS" , "THEREFORE" , "AND THEN" , "OR ELSE" , "ELSE IF"] punc := ["." , "," , "?" , "!" , "," , "-" , ";"] end