#-quicklisp
(let ((quicklisp-init (merge-pathnames "quicklisp/setup.lisp"
                                      (user-homedir-pathname))))
 (when (probe-file quicklisp-init)
   (load quicklisp-init)))

(eval-when (:compile-toplevel :load-toplevel :execute)
 (defpackage #:horoscope))
(in-package #:cl-user)
(ql:quickload '#:tooter)

#+sbcl
(setf *random-state* (sb-ext:seed-random-state t))

(defparameter *client*
 (make-instance 'tooter:client
                :base "https://botsin.space"
                :name "Lisp horo"))

;; (tooter:make-status *client* "Totally nonesense fortune telling!")

(defparameter horoscope::paragraph
 '(("*sentence." "*sentence2." "*sentence." "*sentence2."
    "You'll" "*when" "be" "*state." "*luckynum.")
   ("*sentence." "*sentence2." "*sentence2." "You'll" "*when" "be" "*state.")
   ("*sentence2." "*sentence." "*sentence." "*sentence2."
    "You'll" "*when" "be" "*state.")))

(defparameter horoscope::sentence
 '(("!person" "will" "*personverb" "*attime")
   ("!attime" "is not a good time for" "*action")
   ("Your" "*noun" "will" "*verb" "soon")
   ("!thing" "is in the air")
   ("You will discover that" "*discovery")
   ("!attime" "will be a good time for" "*action")
   ("Be sure to" "*verb" "before you find out that" "*discovery")
   ("Your programs will start" "*action")
   ("Look for" "*person" "with one eye")
   ("Don't let" "*person" "*dothing" "with your" "*noun")
   ("Listen to your" "*noun" "*attime")
   ("Your" "*noun" "will be" "*change" "in the next" "*vaguenumber" "*time")
   ("!thingstodo")
   ("You might want to consider" "*action")
   ("!time" "from now" "*action" "may seem" "*likevalue")
   ("Do not" "*verb" "*attime")
   ("!person" "will be a" "*adjective" "*relationship")
   ("!attime" "*person" "will" "*thingstodo")
   ("Don't" "*thingstodo" "*attime")
   ("Put your" "*noun" "on hold" "*attime")
   ("Loaning money to your" "*relationship" "will bring dividends")
   ("*bullshit")))

(defparameter horoscope::sentence2
 '(("!person" "will eventually reveal itself to be" "*person")
   ("Your efforts at" "*action" "turn out to be" "*value")
   ("Many people will ask you for advice about" "*action")
   ("!person" "will think of you as" "*person")
   ("Beware of" "*person" "bearing" "*thing")
   ("Loving your" "*noun" "now will turn out to be"
    "*value" "after a few" "*time")
   ("Don't forget to" "*thingstodo")
   ("!thingstodo" "with the help of" "*person")
   ("Never" "*thingstodo" "without" "*action" "first")
   ("Do something nice for" "*person" "*attime")
   ("You will meet" "*person" "this week")
   ("Your" "*noun" "will need to be" "*thingverb" "*attime")
   ("!evilpeople" "will" "*verb" "*attime")
   ("!attime" "*thing" "would be a good thing to" "*consider")
   ("Stealing a" "*noun" "should not be" "*try")
   ("Your finances will become" "*moneystates"
    "in the next several" "*time")
   ("*bullshit")))

(defparameter horoscope::personverb
 '(("sit next to you on the bus")
   ("give you good advice")
   ("become pregnant")
   ("kiss you")
   ("make you feel warm and fuzzy")
   ("eat your mail")
   ("lift weights")
   ("hit you")
   ("give you pennies")
   ("share intimate feelings")
   ("throw up") ("splode")))

(defparameter horoscope::thingverb
 '(("replaced") ("repaired") ("opened up") ("rewired")
   ("burped") ("kicked") ("bathed") ("kissed") ("petted")
   ("scrubbed") ("rubbed") ("massaged") ("fondled")
   ("excommunicated") ("removed") ("destroyed")
   ("eaten") ("turned")))

(defparameter horoscope::bullshit
 '(("As" "*planet" "moves into" "*zodplace,"
    "be careful of your relationship with your" "*relationship")
   ("You will be in conflict with" "*zodiac"
    "since" "*planet" "has moved into" "*zodiac")))

(defparameter horoscope::planet
 '(("Mercury") ("Venus") ("Mars") ("Jupiter") ("Saturn")
   ("Uranus") ("Neptune") ("Pluto") ("the Moon")))

(defparameter horoscope::zodplace
 '(("*zodiac") ("the" "*number" "house of" "*zodiac")
   ("the" "*side" "of" "*zodiac")))

(defparameter horoscope::number
 '(("first") ("second") ("third") ("11th") ("392nd")))

(defparameter horoscope::side
 '(("left-hand quadrant") ("right-hand quadrant")
   ("upper half") ("lower half") ("middle")))

(defparameter horoscope::zodiac
 '(("Pisces") ("Sagitarius") ("Cancer") ("Leo") ("Gemini")
   ("Taurus") ("Scorpio") ("Aquarius") ("Capricorn") ("Virgo")))

(defparameter horoscope::luckynum
 '(("Your lucky number today is 29842924728.  Look for it everywhere")
   ("12 is your lucky number")
   ("Your lucky numbers are 20, 30, and 40")
   ("Don't forget, it's only 366 days at most until Christmas")))

(defparameter horoscope::person
 '(("a stranger") ("a friend") ("your" "*relationship")
   ("someone you" "*greeted" "*times" "at" "*event")
   ("your" "*animal") ("your teddy bear")
   ("your mom") ("the mailman") ("the man")
   ("your wonderful pet" "*animal") ("your child")
   ("your spouse") ("God") ("a wallflower") ("a lout")
   ("a warmonger") ("two other people put together")
   ("someone you know")))

(defparameter horoscope::animal
 '(("dog") ("cat") ("horse") ("elephant") ("piglet")
   ("mouse") ("rat") ("cheetah") ("giraffe") ("mutant shrimp")
   ("talking fish") ("crustacean") ("moose") ("algae") ("amoeba")))

(defparameter horoscope::action
 '(("moving") ("thinking") ("making love")
   ("straining in the toilet")
   ("washing clothes") ("becoming pregnant")
   ("doing something") ("asking for a raise")
   ("starting a revolution") ("becoming paranoid")
   ("reading mail") ("talking with piglet3")
   ("balancing a checkbook") ("talking")
   ("gossiping") ("stealing from the company")
   ("buying a new computer") ("sleeping")
   ("using a Torx #9 wrench") ("telephoning")
   ("not answering the phone")
   ("staying where you are") ("cleaning the fridge")
   ("wearing clothes")))

(defparameter horoscope::thingstodo
 '(("set your clock") ("get married" "*attime")
   ("dye your hair") ("move away") ("exercise")
   ("have your" "*noun" "spayed or neutered")
   ("watch Dr. Who") ("watch Wheel of Fortune")
   ("see your psychologist") ("talk to your plants")
   ("pet piglet") ("clean your apartment")
   ("think about financial concerns")
   ("discuss life with RMS") ("marry the milkperson")
   ("adjust your girdle") ("tune your stereo")
   ("tune your car") ("lift weights") ("paint") ("draw")
   ("play Sam and Max Hit the Road")
   ("play Car Bomb")))

(defparameter horoscope::time
 '(("months") ("days") ("years") ("seconds") ("minutes") ("hours")))

(defparameter horoscope::attime
 '(("today") ("tomorrow") ("this week") ("this month")))

(defparameter horoscope::try
 '(("attempted lightly")
   ("tried without the advice of a doctor")
   ("considered unusual")
   ("done under the influence of alcohol")
   ("achieved with the help of ZenIRC")
   ("done while wearing a girdle") ("stared at")
   ("questioned by" "*person")
   ("performed by a" "*relationship")
   ("shown on TV") ("demonstrated")
   ("shown to small children")))

(defparameter horoscope::value
 '(("worthless") ("futile") ("mysterious") ("quite worthwhile")
   ("costly") ("a good idea") ("unhealthy")
   ("a positive step in the right direction")))

(defparameter horoscope::likevalue
 '(("worthless") ("futile") ("mysterious")
   ("quite worthwhile") ("expensive")
   ("like a good idea") ("unhealthy")
   ("like a positive step in the right direction")))

(defparameter horoscope::noun
 '(("dog") ("cat") ("anteater") ("chicken") ("television")
   ("computer") ("telephone") ("abode") ("vehicle") ("sister")
   ("rhinocerous") ("piglet") ("alien") ("tetrodotoxin")
   ("dinoflagellate") ("endothermic therapsid")
   ("life insurance") ("child")))

(defparameter horoscope::dothing
 '(("brush its teeth") ("take a bath") ("make love")
   ("mow the lawn") ("go shopping") ("dig")
   ("rotate the TV antenna") ("eat worms")
   ("genetically engineer your plants")
   ("drink a bath")
   ("get life insurance from a TV ad")))

(defparameter horoscope::verb
 '(("become pregnant") ("eat holes in your carpet")
   ("piss on the bed") ("eat watermelon")
   ("sell your house")
   ("give away your" "*relationship" "to" "*evilpeople")
   ("talk to piglet") ("get a" "*noun")
   ("have financial problems")
   ("adjust your girdle") ("sit quietly") ("sleep")
   ("drive") ("put money in the bank") ("play games")))

(defparameter horoscope::evilpeople
 '(("Iranians") ("Iraquis") ("Americans")
   ("god-fearing Crustaceans") ("aliens") ("\"Bob\"")
   ("the Doctor") ("Frenchmen") ("Germans")
   ("piglet-haters") ("aliens from Mars")))

(defparameter horoscope::evilperson
 '(("Iranian") ("Iraqui") ("American")
   ("god-fearing Crustacean") ("alien") ("bobbie")
   ("loon") ("Frenchman") ("Germans") ("piglet-haters")
   ("alien from Mars") ("Republican") ("Democrat")
   ("Communist") ("Socialist") ("idiot") ("artist")))

(defparameter horoscope::thing
 '(("romance") ("nasty body odor")
   ("fortune (good or bad)") ("a gift")
   ("a small bomb") ("a flight recorder")
   ("a large dog") ("a piglet") ("a steering wheel")
   ("a toaster oven with a built-in clock radio")
   ("an egg") ("food") ("ice") ("bad weather")
   ("good weather") ("milk") ("a deadly disease")))

(defparameter horoscope::discovery
 '(("you are married") ("you have two left feet")
   ("Nazi Germany is your country of birth")
   ("you do not have a pet")
   ("several Conspiracy members are following you")
   ("the wives are catching colds")
   ("your" "*relationship" "is confused")
   ("your spouse is an alien")
   ("you lost your piglet")
   ("someone thinks of you as Liza Minelli")
   ("you are Murphy Brown's child")
   ("your long-lost brother is lost")
   ("Michael Jackson is abusing your" "*noun")
   ("*relationship" "was responsible for the overthrow of Communist Russia")
   ("your" "*relationship" "is a" "*evilperson")
   ("you're originally from" "*planet")
   ("using a" "*noun" "as a sex toy is" "*value")))

(defparameter horoscope::state
 '(("happy") ("unhappy") ("confused") ("sad")
   ("enlightened") ("a Borg") ("fulfilled") ("gay") ("tall")
   ("ill") ("shrunk") ("abused") ("tired") ("broke")))

(defparameter horoscope::statenoun
 '(("happiness") ("unhappiness") ("confusion") ("sadness")
   ("enlightenment") ("bogosity") ("fulfillment") ("gaiety") ("tallness")
   ("illness") ("lossage") ("bozosity") ("weariness")))

(defparameter horoscope::change
 '(("fluctuating") ("changing")
   ("turning" "*color")
   ("turning") ("*color")))

(defparameter horoscope::color
 '(("green") ("red") ("blue") ("black") ("brown")
   ("yellow") ("orange") ("fuscia") ("mauve") ("plaid")))

(defparameter horoscope::when
 '(("soon") ("eventually") ("later") ("never") ("someday") ("often")
   ("fall into a state of" "*statenoun," "but eventually")
   ("sometimes") ("perhaps in a few" "*time")
   ("once in a while")))

(defparameter horoscope::adjective
 '(("good") ("bad") ("indifferent") ("valuable")
   ("expensive") ("sick") ("unhappy")))

(defparameter horoscope::relationship
 '(("friend") ("enemy") ("relative") ("coworker")
   ("slave") ("mother") ("sister") ("spouse") ("owner")
   ("parent") ("child")))

(defparameter horoscope::moneystates
 '(("unstable") ("positive") ("financial") ("good")
   ("bad") ("important") ("unimportant") ("exposed")
   ("significant")))

(defparameter horoscope::vaguenumber
 '(("few") ("several") ("4 or 9") ("1 or 7")))

(defparameter horoscope::greeted
 '(("said hello to") ("shook hands with") ("met")
   ("talked to") ("screwed") ("kissed") ("fondled gently")
   ("blessed") ("gave an organ to")))

(defparameter horoscope::times
 '(("once") ("twice") ("a few times") ("5 or 11 times")
   ("3 to 6 times") ("thrice") ("988,122 times")))

(defparameter horoscope::event
 '(("a party") ("a gathering of some sort")
   ("a social reception") ("an intimate office party")
   ("Maria Shriver's wedding") ("Michael Jackson's trial")
   ("a bad""frat party") ("Underwear City")))

(defparameter horoscope::consider
 '(("ponder") ("think about") ("consider") ("try")
   ("make a stab at") ("meditate upon")
   ("look at deeply")))



(defun random-member (a)
 (and a
      (listp a)
      (nth (random (length a)) a)))

(defun getlist (listname restoflist)
 (let* ((lastchar (aref listname (1- (length listname))))
        (punct-char-p (member lastchar '(#\, #\.)))
        (period-p (char= lastchar #\.))
        (suffix (if punct-char-p
                    (subseq listname 0 (1- (length listname)))
                  listname)))
   (format nil "~A~A~A"
           (iterate-list
            (random-member
             (symbol-value (intern (string-upcase suffix)
                                   '#:horoscope))))
           (cond (period-p
                  (format nil "~A " lastchar))
                 (punct-char-p
                  lastchar)
                 (t ""))
           (if restoflist
               (format nil " ~A"
                       (iterate-list restoflist))
               ""))))

(defun capitalize (s)
 (let ((a (copy-seq s)))
   (setf (aref a 0) (char-upcase (aref s 0)))
   a))

(defun iterate-list (a)
 (cond ((null a) "")
       ((char= (aref (car a) 0) #\*)
        (getlist (subseq (car a) 1) (cdr a)))
       ((char= (aref (car a) 0) #\!)
        (capitalize
         (getlist (subseq (car a) 1) (cdr a))))
       (t
        (format nil "~A~:[~; ~]~A"
                (car a)
                (cdr a)
                (iterate-list (cdr a))))))

(defun horoscope ()
 (tooter:make-status *client*
                     (iterate-list (random-member horoscope::paragraph))))

(horoscope)