update beer-knowledge.clp

update beer-knowledge.clp

;;************************
;;* BEER KNOWLEDGE RULES *
;;************************

; determine best beer attributes for user type and scenario recognized

(defrule determine-best-beer-attributes-if-preferred-carbonation-is-any
   (declare (salience ?*medium-low-priority*))
   (preferred-carbonation ?carbonation)
   =>
   (assert (attribute (name best-carbonation) (value ?carbonation) (certainty 20))))

(defrule determine-best-beer-attributes-if-regular-beer-drinker-is-no
   (declare (salience ?*medium-low-priority*))
   (regular-beer-drinker no)
   =>
   (assert (attribute (name best-name) (value "American Cream Ale") (certainty 20)))
   (assert (attribute (name best-name) (value "Blonde Ale") (certainty 20)))
   (assert (attribute (name best-name) (value "German-Style Helles") (certainty 20)))
   (assert (attribute (name best-name) (value "German-Style Kölsch") (certainty 20)))
   (assert (attribute (name best-name) (value "Belgian-Style Witbier") (certainty 10)))
   (assert (attribute (name best-name) (value "American Amber Ale") (certainty 10)))
   (assert (attribute (name best-name) (value "Irish-Style Red") (certainty 10)))
   (assert (attribute (name best-name) (value "American Brown Ale") (certainty 10)))
   (assert (attribute (name best-name) (value "English-Style Brown Porter") (certainty 10))))

(defrule determine-best-beer-attributes-if-fermented-foods-eater-is-yes
   (declare (salience ?*medium-low-priority*))
   (fermented-foods-eater yes)
   =>
   (assert (attribute (name best-fermentation) (value wild) (certainty 20))))

(defrule determine-best-beer-attributes-if-driver-is-yes
   (declare (salience ?*medium-low-priority*))
   (driver yes)
   =>
   (assert (attribute (name best-alcohol) (value not-detectable) (certainty 20)))
   (assert (attribute (name best-alcohol) (value mild) (certainty 10))))

(defrule determine-best-beer-attributes-if-preferred-flavor-is-clean
   (declare (salience ?*medium-low-priority*))
   (preferred-flavor clean)
   =>
   (assert (attribute (name best-flavor) (value crisp-clean) (certainty 20))))

(defrule determine-best-beer-attributes-if-preferred-flavor-is-sweet
   (declare (salience ?*medium-low-priority*))
   (preferred-flavor sweet)
   =>
   (assert (attribute (name best-flavor) (value malty-sweet) (certainty 20))))

(defrule determine-best-beer-attributes-if-preferred-flavor-is-roasty
   (declare (salience ?*medium-low-priority*))
   (preferred-flavor roasty)
   =>
   (assert (attribute (name best-flavor) (value dark-roasty) (certainty 20))))

(defrule determine-best-beer-attributes-if-preferred-flavor-is-bitter
   (declare (salience ?*medium-low-priority*))
   (preferred-flavor bitter)
   =>
   (assert (attribute (name best-flavor) (value hoppy-bitter) (certainty 20))))

(defrule determine-best-beer-attributes-if-preferred-flavor-is-fruity
   (declare (salience ?*medium-low-priority*))
   (preferred-flavor fruity)
   =>
   (assert (attribute (name best-flavor) (value fruity-spicy) (certainty 20))))

; determine best beer attributes for meal type recognized...

(defrule determine-best-beer-attributes-if-which-pizza-topping-is-classic
   (declare (salience ?*medium-low-priority*))
   (or (pizza-topping-for-omnivorous classic)
       (pizza-topping-for-vegetarian classic)
       (pizza-topping-for-vegan classic))
   =>
   (assert (attribute (name best-flavor) (value crisp-clean) (certainty 50))))

(defrule determine-best-beer-attributes-if-which-pizza-topping-for-omnivorous-is-meat
   (declare (salience ?*medium-low-priority*))
   (meat-topping-is-spicy no)
   =>
   (assert (attribute (name best-flavor) (value hoppy-bitter) (certainty 50))))

(defrule determine-best-beer-attributes-if-which-pizza-topping-for-omnivorous-is-spicy-meat
   (declare (salience ?*medium-low-priority*))
   (meat-topping-is-spicy yes)
   =>
   (assert (attribute (name best-flavor) (value malty-sweet) (certainty 50))))

(defrule determine-best-beer-attributes-if-which-pizza-topping-are-vegetables
  (declare (salience ?*medium-low-priority*))
  (vegetables-topping-are-roasted no)
  =>
  (assert (attribute (name best-flavor) (value sour-tart-funky) (certainty 50))))

(defrule determine-best-beer-attributes-if-which-pizza-topping-are-roasted-vegetables
   (declare (salience ?*medium-low-priority*))
   (vegetables-topping-are-roasted yes)
   =>
   (assert (attribute (name best-flavor) (value dark-roasty) (certainty 50))))

(defrule determine-best-beer-attributes-if-which-pizza-topping-for-omnivorous-or-vegetarian-is-cheese
   (declare (salience ?*medium-low-priority*))
   (or (pizza-topping-for-omnivorous cheese)
       (pizza-topping-for-vegetarian cheese))
   =>
   (assert (attribute (name best-flavor) (value fruity-spicy) (certainty 50))))

(defrule determine-best-beer-attributes-if-which-cheese-style-is-fresh
   (declare (salience ?*medium-low-priority*))
   (which-cheese-style fresh)
   =>
   (assert (attribute (name best-style) (value "Wheat Beer") (certainty 80)))
   (assert (attribute (name best-name) (value "Belgian-Style Fruit Lambic") (certainty 80)))
   (assert (attribute (name best-name) (value "Belgian-Style Lambic/Gueuze") (certainty 80))))

(defrule determine-best-beer-attributes-if-which-fresh-cheese-is-Mascarpone
   (declare (salience ?*medium-low-priority*))
   (which-fresh-cheese Mascarpone)
   =>
   (assert (attribute (name best-name) (value "Belgian-Style Witbier") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-fresh-cheese-is-Ricotta-or-which-grain-is-bruschetta
   (declare (salience ?*medium-low-priority*))
   (or (which-fresh-cheese Ricotta)
       (which-grain-is-bruschetta))
   =>
   (assert (attribute (name best-name) (value "Honey Beer") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-fresh-cheese-is-Chevre
   (declare (salience ?*medium-low-priority*))
   (which-fresh-cheese Chèvre)
   =>
   (assert (attribute (name best-name) (value "American Wheat") (certainty 90)))
   (assert (attribute (name best-name) (value "German-Style Hefeweizen") (certainty 90)))
   (assert (attribute (name best-name) (value "Belgian-Style Fruit Lambic") (certainty 90)))
   (assert (attribute (name best-name) (value "European-Style Export") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-fresh-cheese-is-Feta-or-which-pork-is-loin
   (declare (salience ?*medium-low-priority*))
   (or (which-fresh-cheese Feta)
       (which-pork loin))
   =>
   (assert (attribute (name best-name) (value "California Common") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-fresh-cheese-is-Cream-Cheese
   (declare (salience ?*medium-low-priority*))
   (which-fresh-cheese "Cream Cheese")
   =>
   (assert (attribute (name best-name) (value "Fruit and Field Beer") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-cheese-style-is-semi-soft
   (declare (salience ?*medium-low-priority*))
   (which-cheese-style semi-soft)
   =>
   (assert (attribute (name best-style) (value "Pale Ale") (certainty 80)))
   (assert (attribute (name best-name) (value "German-Style Bock") (certainty 80)))
   (assert (attribute (name best-name) (value "German-Style Kölsch") (certainty 80))))

(defrule determine-best-beer-attributes-if-which-semi-soft-cheese-is-Mozzarella
   (declare (salience ?*medium-low-priority*))
   (which-semi-soft-cheese Mozzarella)
   =>
   (assert (attribute (name best-flavor) (value crisp-clean) (certainty 50)))
   (assert (attribute (name best-name) (value "American Imperial Red Ale") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-semi-soft-cheese-is-Colby
   (declare (salience ?*medium-low-priority*))
   (which-semi-soft-cheese Colby)
   =>
   (assert (attribute (name best-name) (value "German-Style Helles") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-semi-soft-cheese-is-Havarti
   (declare (salience ?*medium-low-priority*))
   (which-semi-soft-cheese Havarti)
   =>
   (assert (attribute (name best-name) (value "Berliner-Style Weisse") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-semi-soft-cheese-is-Monterey-Jack-or-shellfish-is-mild
   (declare (salience ?*medium-low-priority*))
   (or (which-semi-soft-cheese "Monterey Jack")
       (shellfish-is-mild yes))
   =>
   (assert (attribute (name best-name) (value "American Cream Ale") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-cheese-style-is-firm-hard
   (declare (salience ?*medium-low-priority*))
   (which-cheese-style firm/hard)
   =>
   (assert (attribute (name best-style) (value "Bock") (certainty 80)))
   (assert (attribute (name best-style) (value "Brown Ale") (certainty 80)))
   (assert (attribute (name best-name) (value "Bohemian-Style Pilsener") (certainty 80)))
   (assert (attribute (name best-name) (value "German-Style Pilsener") (certainty 80)))
   (assert (attribute (name best-name) (value "American Imperial Stout") (certainty 80))))

(defrule determine-best-beer-attributes-if-which-firm/hard-cheese-is-Swiss
   (declare (salience ?*medium-low-priority*))
   (which-firm/hard-cheese Swiss)
   =>
   (assert (attribute (name best-name) (value "German-Style Maibock") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-firm/hard-cheese-is-Gouda
   (declare (salience ?*medium-low-priority*))
   (which-firm/hard-cheese Gouda)
   =>
   (assert (attribute (name best-flavor) (value malty-sweet) (certainty 50)))
   (assert (attribute (name best-name) (value "German-Style Dunkelweizen") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-type-of-Gouda-is-aged
   (declare (salience ?*medium-low-priority*))
   (which-type-of-Gouda aged)
   =>
   (assert (attribute (name best-name) (value "American Brown Ale") (certainty 90)))
   (assert (attribute (name best-name) (value "English-Style Brown Ale") (certainty 90)))
   (assert (attribute (name best-name) (value "Belgian-Style Quadrupel") (certainty 90)))
   (assert (attribute (name best-name) (value "Baltic-Style Porter") (certainty 90)))
   (assert (attribute (name best-name) (value "American Black Ale") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-type-of-Gouda-is-smoked
   (declare (salience ?*medium-low-priority*))
   (which-type-of-Gouda smoked)
   =>
   (assert (attribute (name best-name) (value "American Imperial Porter") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-firm/hard-cheese-is-Cheddar
   (declare (salience ?*medium-low-priority*))
   (which-firm/hard-cheese Cheddar)
   =>
   (assert (attribute (name best-name) (value "Irish-Style Red") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-color-of-Cheddar-is-white
   (declare (salience ?*medium-low-priority*))
   (which-color-of-Cheddar white)
   =>
   (assert (attribute (name best-name) (value "American Amber Lager") (certainty 90)))
   (assert (attribute (name best-name) (value "German-Style Pilsener") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-Cheddar-seasoning-is-mild
   (declare (salience ?*medium-low-priority*))
   (which-Cheddar-seasoning mild)
   =>
   (assert (attribute (name best-name) (value "American Pale Ale") (certainty 90)))
   (assert (attribute (name best-name) (value "English-Style Mild") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-Cheddar-seasoning-is-medium
   (declare (salience ?*medium-low-priority*))
   (which-Cheddar-seasoning medium)
   =>
   (assert (attribute (name best-name) (value "American Amber Ale") (certainty 90)))
   (assert (attribute (name best-name) (value "American Pale Ale") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-Cheddar-seasoning-is-aged
   (declare (salience ?*medium-low-priority*))
   (which-Cheddar-seasoning aged)
   =>
   (assert (attribute (name best-flavor) (value hoppy-bitter) (certainty 50)))
   (assert (attribute (name best-name) (value "English-Style IPA") (certainty 90)))
   (assert (attribute (name best-name) (value "English-Style Oatmeal Stout") (certainty 90))))

(defrule determine-best-beer-attributes-if-Cheddar-is-sharp-or-which-rich-is-grilled-lamb
   (declare (salience ?*medium-low-priority*))
   (or (Cheddar-is-sharp yes)
       (and (meat-cooking-method grilled)
            (which-rich lamb)))
   =>
   (assert (attribute (name best-name) (value "American Stout") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-color-of-Cheddar-is-white-and-which-Cheddar-seasoning-is-mild
   (declare (salience ?*medium-low-priority*))
   (which-color-of-Cheddar white)
   (which-Cheddar-seasoning mild)
   =>
   (assert (attribute (name best-name) (value "Bohemian-Style Pilsener") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-type-of-Swiss-is-Emmental-or-which-bluefish-is-grilled-salmon
   (declare (salience ?*medium-low-priority*))
   (or (which-type-of-Swiss Emmental)
       (and (fish-cooking-method grilled)
            (which-bluefish salmon)))
   =>
   (assert (attribute (name best-name) (value "German-Style Brown/Altbier") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-type-of-Swiss-is-Gruyere
   (declare (salience ?*medium-low-priority*))
   (which-type-of-Swiss Gruyère)
   =>
   (assert (attribute (name best-name) (value "English-Style Brown Porter") (certainty 90)))
   (assert (attribute (name best-name) (value "Robust Porter") (certainty 90))))

(defrule determine-best-beer-attributes-if-Swiss-is-aged
   (declare (salience ?*medium-low-priority*))
   (Swiss-is-aged yes)
   =>
   (assert (attribute (name best-name) (value "German-Style Bock") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-firm/hard-cheese-is-Parmesan
   (declare (salience ?*medium-low-priority*))
   (which-firm/hard-cheese Parmesan)
   =>
   (assert (attribute (name best-name) (value "Smoke Beer") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-cheese-style-is-is-blue
   (declare (salience ?*medium-low-priority*))
   (which-cheese-style blue)
   =>
   (assert (attribute (name best-flavor) (value dark-roasty) (certainty 50)))
   (assert (attribute (name best-style) (value "India Pale Ale") (certainty 80)))
   (assert (attribute (name best-name) (value "American Black Ale") (certainty 80))))

(defrule determine-best-beer-attributes-if-which-blue-or-natural-rind-cheese-is-Stilton
   (declare (salience ?*medium-low-priority*))
   (or (which-blue-cheese Stilton)
       (which-natural-rind-cheese Stilton))
   =>
   (assert (attribute (name best-name) (value "British-Style Barley Wine Ale") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-cheese-style-is-natural-rind
   (declare (salience ?*medium-low-priority*))
   (which-cheese-style "natural rind")
   =>
   (assert (attribute (name best-style) (value "Pale Ale") (certainty 80)))
   (assert (attribute (name best-name) (value "Belgian-Style Golden Strong Ale") (certainty 80)))
   (assert (attribute (name best-name) (value "Belgian-Style Blonde Ale") (certainty 80)))
   (assert (attribute (name best-name) (value "Blonde Ale") (certainty 80)))
   (assert (attribute (name best-name) (value "American Barley Wine") (certainty 80)))
   (assert (attribute (name best-name) (value "British-Style Barley Wine Ale") (certainty 80))))

(defrule determine-best-beer-attributes-if-which-natural-rind-cheese-is-Brie
   (declare (salience ?*medium-low-priority*))
   (which-natural-rind-cheese Brie)
   =>
   (assert (attribute (name best-flavor) (value fruity-spicy) (certainty 50)))
   (assert (attribute (name best-name) (value "Belgian-Style Blonde Ale") (certainty 90)))
   (assert (attribute (name best-name) (value "Belgian-Style Saison") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-natural-rind-cheese-is-Camembert
   (declare (salience ?*medium-low-priority*))
   (which-natural-rind-cheese Camembert)
   =>
   (assert (attribute (name best-name) (value "Pumpkin Beer") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-natural-rind-cheese-is-Triple-Crème
   (declare (salience ?*medium-low-priority*))
   (which-natural-rind-cheese "Triple Crème")
   =>
   (assert (attribute (name best-name) (value "Belgian-Style Golden Strong Ale") (certainty 90)))
   (assert (attribute (name best-name) (value "Belgian-Style Tripel") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-natural-rind-cheese-is-Mimolette
   (declare (salience ?*medium-low-priority*))
   (which-natural-rind-cheese Mimolette)
   =>
   (assert (attribute (name best-name) (value "Belgian-Style Flanders") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-cheese-style-is-washed-rind
   (declare (salience ?*medium-low-priority*))
   (which-cheese-style "washed rind")
   =>
   (assert (attribute (name best-name) (value "Belgian-Style Blonde Ale") (certainty 80)))
   (assert (attribute (name best-name) (value "Belgian-Style Golden Strong Ale") (certainty 80)))
   (assert (attribute (name best-name) (value "Belgian-Style Pale Ale") (certainty 80)))
   (assert (attribute (name best-name) (value "Belgian-Style Dubbel") (certainty 80)))
   (assert (attribute (name best-name) (value "French-Style Biére de Garde") (certainty 80))))

(defrule determine-best-beer-attributes-if-which-washed-rind-cheese-is-Taleggio
   (declare (salience ?*medium-low-priority*))
   (which-washed-rind-cheese Taleggio)
   =>
   (assert (attribute (name best-name) (value "Belgian-Style Pale Ale") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-entree-is-grain
   (declare (salience ?*medium-low-priority*))
   (or (which-entrée-omnivorous grain)
       (which-entrée-vegetarian grain)
       (which-entrée-vegan grain))
   =>
   (assert (attribute (name best-flavor) (value crisp-clean) (certainty 50))))

(defrule determine-best-beer-attributes-if-which-grain-are-chips
   (declare (salience ?*medium-low-priority*))
   (which-grain chips)
   =>
   (assert (attribute (name best-name) (value "English-Style Bitter") (certainty 90)))
   (assert (attribute (name best-name) (value "English-Style Pale Ale (ESB)") (certainty 90)))
   (assert (attribute (name best-name) (value "Belgian-Style Pale Ale") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-grain-is-spaghetti
   (declare (salience ?*medium-low-priority*))
   (which-grain spaghetti)
   =>
   (assert (attribute (name best-name) (value "Blonde Ale") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-grain-are-grits-or-which-shellfish-are-grilled-shrimps
   (declare (salience ?*medium-low-priority*))
   (or (which-grain grits)
       (and (fish-cooking-method grilled)
            (which-shellfish shrimps)))
   =>
   (assert (attribute (name best-name) (value "American Black Ale") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-entree-is-legumes
   (declare (salience ?*medium-low-priority*))
   (or (which-entrée-omnivorous legumes)
       (which-entrée-vegetarian legumes)
       (which-entrée-vegan legumes))
   =>
   (assert (attribute (name best-flavor) (value malty-sweet) (certainty 50))))

(defrule determine-best-beer-attributes-if-which-which-entree-omnivorous-is-fish
   (declare (salience ?*medium-low-priority*))
   (which-entrée-omnivorous fish)
   =>
   (assert (attribute (name best-name) (value "English-Style Bitter") (certainty 80)))
   (assert (attribute (name best-name) (value "English-Style Pale Ale (ESB)") (certainty 80))))

(defrule determine-best-beer-attributes-if-which-fish-is-shellfish
   (declare (salience ?*medium-low-priority*))
   (which-fish shellfish)
   =>
   (assert (attribute (name best-flavor) (value fruity-spicy) (certainty 50)))
   (assert (attribute (name best-name) (value "Bohemian-Style Pilsener") (certainty 90)))
   (assert (attribute (name best-name) (value "German-Style Pilsener") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-shellfish-are-mussels
   (declare (salience ?*medium-low-priority*))
   (which-shellfish mussels)
   =>
   (assert (attribute (name best-name) (value "Belgian-Style Saison") (certainty 90)))
   (assert (attribute (name best-name) (value "Belgian-Style Lambic/Gueuze") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-shellfish-are-oysters
   (declare (salience ?*medium-low-priority*))
   (which-shellfish oysters)
   =>
   (assert (attribute (name best-name) (value "Irish-Style Dry Stout") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-which-entree-omnivorous-is-meat
   (declare (salience ?*medium-low-priority*))
   (which-entrée-omnivorous meat)
   =>
   (assert (attribute (name best-name) (value "Scotch Ale/Wee Heavy") (certainty 80)))
   (assert (attribute (name best-name) (value "Scottish-Style Ale") (certainty 80))))

(defrule determine-best-beer-attributes-if-meat-cooking-method-is-barbecue
   (declare (salience ?*medium-low-priority*))
   (meat-cooking-method barbecue)
   =>
   (assert (attribute (name best-name) (value "American Amber Ale") (certainty 90))))

(defrule determine-best-beer-attributes-if-meat-cooking-method-is-braised-or-which-dessert-is-chocolate
   (declare (salience ?*medium-low-priority*))
   (or (meat-cooking-method braised)
       (which-dessert chocolate))
   =>
   (assert (attribute (name best-flavor) (value malty-sweet) (certainty 50)))
   (assert (attribute (name best-flavor) (value dark-roasty) (certainty 50))))

(defrule determine-best-beer-attributes-if-meat-cooking-method-is-grilled
   (declare (salience ?*medium-low-priority*))
   (meat-cooking-method grilled)
   =>
   (assert (attribute (name best-name) (value "American Pale Ale") (certainty 90)))
   (assert (attribute (name best-name) (value "American Amber Lager") (certainty 90)))
   (assert (attribute (name best-name) (value "Vienna-Style Lager") (certainty 90)))
   (assert (attribute (name best-name) (value "American Brown Ale") (certainty 90)))
   (assert (attribute (name best-name) (value "English-Style Brown Porter") (certainty 90)))
   (assert (attribute (name best-name) (value "Robust Porter") (certainty 90))))

(defrule determine-best-beer-attributes-if-meat-cooking-method-is-roasted
   (declare (salience ?*medium-low-priority*))
   (meat-cooking-method roasted)
   =>
   (assert (attribute (name best-name) (value "American Pale Ale") (certainty 90)))
   (assert (attribute (name best-name) (value "English-Style Brown Porter") (certainty 90)))
   (assert (attribute (name best-name) (value "Robust Porter") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-meat-is-rich-meats
   (declare (salience ?*medium-low-priority*))
   (which-meat rich)
   =>
   (assert (attribute (name best-flavor) (value sour-tart-funky) (certainty 50))))

(defrule determine-best-beer-attributes-if-which-rich-is-roasted-beef-or-which-rich-is-lamb
   (declare (salience ?*medium-low-priority*))
   (or (and (meat-cooking-method roasted)
            (which-rich beef))
       (which-rich lamb))
   =>
   (assert (attribute (name best-name) (value "English-Style Old Ale") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-beef-is-bresola
   (declare (salience ?*medium-low-priority*))
   (which-beef bresola)
   =>
   (assert (attribute (name best-name) (value "American Brown Ale") (certainty 90)))
   (assert (attribute (name best-name) (value "Rye Beer") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-rich-is-roasted-lamb
   (declare (salience ?*medium-low-priority*))
   (meat-cooking-method roasted)
   (which-rich lamb)
   =>
   (assert (attribute (name best-name) (value "French-Style Biére de Garde") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-rich-is-pork
   (declare (salience ?*medium-low-priority*))
   (which-rich pork)
   =>
   (assert (attribute (name best-flavor) (value hoppy-bitter) (certainty 50)))
   (assert (attribute (name best-flavor) (value fruity-spicy) (certainty 50)))
   (assert (attribute (name best-name) (value "German-Style Doppelbock") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-rich-is-roasted-pork-or-which-meat-is-steak
   (declare (salience ?*medium-low-priority*))
   (or (and (meat-cooking-method roasted)
            (which-rich pork))
       (which-meat steak))
   =>
   (assert (attribute (name best-name) (value "English-Style Brown Ale") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-pork-is-tenderloin
   (declare (salience ?*medium-low-priority*))
   (which-pork tenderloin)
   =>
   (assert (attribute (name best-name) (value "Coffee Beer") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-pork-is-prosciutto
   (declare (salience ?*medium-low-priority*))
   (which-pork prosciutto)
   =>
   (assert (attribute (name best-name) (value "Bohemian-Style Pilsener") (certainty 90)))
   (assert (attribute (name best-name) (value "German-Style Doppelbock") (certainty 90)))
   (assert (attribute (name best-name) (value "Belgian-Style Saison") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-pork-is-speck
   (declare (salience ?*medium-low-priority*))
   (which-pork speck)
   =>
   (assert (attribute (name best-name) (value "Smoke Beer") (certainty 90)))
   (assert (attribute (name best-name) (value "American Pale Ale") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-pork-is-mortadella
   (declare (salience ?*medium-low-priority*))
   (which-pork mortadella)
   =>
   (assert (attribute (name best-name) (value "German-Style Märzen/Oktoberfest") (certainty 90)))
   (assert (attribute (name best-name) (value "Belgian-Style Tripel") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-pork-is-sausage
   (declare (salience ?*medium-low-priority*))
   (which-pork sausage)
   =>
   (assert (attribute (name best-name) (value "German-Style Dunkel") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-pork-is-grilled-sausage
   (declare (salience ?*medium-low-priority*))
   (meat-cooking-method grilled)
   (which-pork sausage)
   =>
   (assert (attribute (name best-name) (value "Smoke Porter") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-sausage-is-capocollo
   (declare (salience ?*medium-low-priority*))
   (which-sausage capocollo)
   =>
   (assert (attribute (name best-name) (value "American Amber Lager") (certainty 90)))
   (assert (attribute (name best-name) (value "English-Style Pale Ale (ESB)") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-sausage-is-soppressata
   (declare (salience ?*medium-low-priority*))
   (which-sausage soppressata)
   =>
   (assert (attribute (name best-name) (value "American Brown Ale") (certainty 90)))
   (assert (attribute (name best-name) (value "Belgian-Style Dubbel") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-sausage-is-salame-piccante
   (declare (salience ?*medium-low-priority*))
   (which-sausage "salame piccante")
   =>
   (assert (attribute (name best-name) (value "Imperial IPA") (certainty 90)))
   (assert (attribute (name best-name) (value "Rye Beer") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-poultry-is-chicken
   (declare (salience ?*medium-low-priority*))
   (which-poultry chicken)
   =>
   (assert (attribute (name best-name) (value "German-Style Weizenbock") (certainty 90)))
   (assert (attribute (name best-name) (value "Bohemian-Style Pilsener") (certainty 90)))
   (assert (attribute (name best-name) (value "German-Style Pilsener") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-poultry-is-roasted-chicken
   (declare (salience ?*medium-low-priority*))
   (meat-cooking-method roasted)
   (which-poultry chicken)
   =>
   (assert (attribute (name best-name) (value "English-Style Bitter") (certainty 90)))
   (assert (attribute (name best-name) (value "English-Style Pale Ale (ESB)") (certainty 90)))
   (assert (attribute (name best-name) (value "German-Style Dunkelweizen") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-poultry-is-roasted-turkey
   (declare (salience ?*medium-low-priority*))
   (meat-cooking-method roasted)
   (which-poultry turkey)
   =>
   (assert (attribute (name best-name) (value "Belgian-Style Tripel") (certainty 90)))
   (assert (attribute (name best-name) (value "Pumpkin Beer") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-meat-is-game
   (declare (salience ?*medium-low-priority*))
   (which-meat game)
   =>
   (assert (attribute (name best-name) (value "Scotch Ale/Wee Heavy") (certainty 90)))
   (assert (attribute (name best-name) (value "Scottish-Style Ale") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-meat-is-grilled-or-roasted-game
   (declare (salience ?*medium-low-priority*))
   (or (meat-cooking-method grilled)
       (meat-cooking-method roasted))
   (which-meat game)
   =>
   (assert (attribute (name best-name) (value "American Brett") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-game-is-wild-or-which-other-vegetables-are-mushrooms
   (declare (salience ?*medium-low-priority*))
   (or (which-game wild)
       (which-other-vegetables mushrooms))
   =>
   (assert (attribute (name best-name) (value "English-Style Mild") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-game-is-birds
   (declare (salience ?*medium-low-priority*))
   (which-game birds)
   =>
   (assert (attribute (name best-flavor) (value hoppy-bitter) (certainty 50))))

(defrule determine-best-beer-attributes-if-which-game-birds-is-roasted-duck
   (declare (salience ?*medium-low-priority*))
   (meat-cooking-method roasted)
   (which-game-birds duck)
   =>
   (assert (attribute (name best-name) (value "Belgian-Style Quadrupel") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-meat-is-grilled-steak
   (declare (salience ?*medium-low-priority*))
   (meat-cooking-method grilled)
   (which-meat steak)
   =>
   (assert (attribute (name best-name) (value "European-Style Export") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-entree-is-vegetables
   (declare (salience ?*medium-low-priority*))
   (or (which-entrée-omnivorous vegetables)
       (which-entrée-vegetarian vegetables)
       (which-entrée-vegan vegetables))
   =>
   (assert (attribute (name best-name) (value "American Amber Lager") (certainty 80)))
   (assert (attribute (name best-name) (value "Vienna-Style Lager") (certainty 80)))
   (assert (attribute (name best-name) (value "American Brown Ale") (certainty 80))))

(defrule determine-best-beer-attributes-if-which-vegetables-is-root
   (declare (salience ?*medium-low-priority*))
   (which-vegetables root)
   =>
   (assert (attribute (name best-flavor) (value sour-tart-funky) (certainty 50))))

(defrule determine-best-beer-attributes-if-which-vegetables-is-salad
   (declare (salience ?*medium-low-priority*))
   (which-vegetables salad)
   =>
   (assert (attribute (name best-name) (value "American Wheat") (certainty 90)))
   (assert (attribute (name best-name) (value "American Cream Ale") (certainty 90)))
   (assert (attribute (name best-name) (value "Bohemian-Style Pilsener") (certainty 90)))
   (assert (attribute (name best-name) (value "German-Style Pilsener") (certainty 90)))
   (assert (attribute (name best-name) (value "Fruit and Field Beer") (certainty 90))))

(defrule determine-best-beer-attributes-if-vegetables-cooking-method-is-grilled
   (declare (salience ?*medium-low-priority*))
   (vegetables-cooking-method grilled)
   =>
   (assert (attribute (name best-flavor) (value dark-roasty) (certainty 50)))
   (assert (attribute (name best-name) (value "Smoke Beer") (certainty 90))))

(defrule determine-best-beer-attributes-if-vegetables-cooking-method-is-roasted
   (declare (salience ?*medium-low-priority*))
   (vegetables-cooking-method roasted)
   =>
   (assert (attribute (name best-name) (value "German-Style Dunkel") (certainty 90)))
   (assert (attribute (name best-name) (value "Irish-Style Red") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-entree-is-fats
   (declare (salience ?*medium-low-priority*))
   (or (which-entrée-omnivorous fats)
       (which-entrée-vegetarian "vegetable fats")
       (which-entrée-vegan "vegetable fats"))
   =>
   (assert (attribute (name best-flavor) (value hoppy-bitter) (certainty 50)))
   (assert (attribute (name best-flavor) (value dark-roasty) (certainty 50))))

(defrule determine-best-beer-attributes-if-which-fats-is-vegetable
   (declare (salience ?*medium-low-priority*))
   (or (which-fats vegetable)
       (which-entrée-vegetarian "vegetables fats")
       (which-entrée-vegan "vegetables fats"))
   =>
   (assert (attribute (name best-carbonation) (value high) (certainty 50)))
   (assert (attribute (name best-carbonation) (value medium) (certainty 25))))

(defrule determine-best-beer-attributes-if-which-chocolate-is-white
   (declare (salience ?*medium-low-priority*))
   (which-chocolate white)
   =>
   (assert (attribute (name best-name) (value "Belgian-Style Witbier") (certainty 90)))
   (assert (attribute (name best-name) (value "American Brown Ale") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-chocolate-is-milk
   (declare (salience ?*medium-low-priority*))
   (which-chocolate milk)
   =>
   (assert (attribute (name best-name) (value "American Pale Ale") (certainty 90)))
   (assert (attribute (name best-name) (value "German-Style Doppelbock") (certainty 90)))
   (assert (attribute (name best-name) (value "English-Style Pale Ale (ESB)") (certainty 90)))
   (assert (attribute (name best-name) (value "American Amber Lager") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-chocolate-is-semisweet
   (declare (salience ?*medium-low-priority*))
   (which-chocolate semisweet)
   =>
   (assert (attribute (name best-name) (value "American Stout") (certainty 90)))
   (assert (attribute (name best-name) (value "Robust Porter") (certainty 90)))
   (assert (attribute (name best-name) (value "Belgian-Style Dubbel") (certainty 90)))
   (assert (attribute (name best-name) (value "American IPA") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-chocolate-is-bittersweet
   (declare (salience ?*medium-low-priority*))
   (which-chocolate bittersweet)
   =>
   (assert (attribute (name best-name) (value "American Imperial Stout") (certainty 90)))
   (assert (attribute (name best-name) (value "Belgian-Style Dubbel") (certainty 90)))
   (assert (attribute (name best-name) (value "Belgian-Style Quadrupel") (certainty 90)))
   (assert (attribute (name best-name) (value "Belgian-Style Fruit Lambic") (certainty 90)))
   (assert (attribute (name best-name) (value "Belgian-Style Lambic/Gueuze") (certainty 90)))
   (assert (attribute (name best-name) (value "Robust Porter") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-chocolate-is-unsweetened-bitter-or-which-entree-vegan-is-chocolate
   (declare (salience ?*medium-low-priority*))
   (or (which-chocolate unsweetened/bitter)
       (which-entrée-vegan chocolate))
   =>
   (assert (attribute (name best-name) (value "Belgian-Style Flanders") (certainty 90)))
   (assert (attribute (name best-name) (value "Belgian-Style Fruit Lambic") (certainty 90)))
   (assert (attribute (name best-name) (value "American Sour") (certainty 90))))

;;************************
;;* BEER KNOWLEDGE RULES *
;;************************

; determine best beer attributes for user type and scenario recognized

(defrule determine-best-beer-attributes-if-preferred-carbonation-is-any
   (declare (salience ?*medium-low-priority*))
   (preferred-carbonation ?carbonation)
   =>
   (assert (attribute (name best-carbonation) (value ?carbonation) (certainty 20))))

(defrule determine-best-beer-attributes-if-regular-beer-drinker-is-no
   (declare (salience ?*medium-low-priority*))
   (regular-beer-drinker no)
   =>
   (assert (attribute (name best-name) (value "American Cream Ale") (certainty 20)))
   (assert (attribute (name best-name) (value "Blonde Ale") (certainty 20)))
   (assert (attribute (name best-name) (value "German-Style Helles") (certainty 20)))
   (assert (attribute (name best-name) (value "German-Style Kölsch") (certainty 20)))
   (assert (attribute (name best-name) (value "Belgian-Style Witbier") (certainty 10)))
   (assert (attribute (name best-name) (value "American Amber Ale") (certainty 10)))
   (assert (attribute (name best-name) (value "Irish-Style Red") (certainty 10)))
   (assert (attribute (name best-name) (value "American Brown Ale") (certainty 10)))
   (assert (attribute (name best-name) (value "English-Style Brown Porter") (certainty 10))))

(defrule determine-best-beer-attributes-if-fermented-foods-eater-is-yes
   (declare (salience ?*medium-low-priority*))
   (fermented-foods-eater yes)
   =>
   (assert (attribute (name best-fermentation) (value wild) (certainty 20))))

(defrule determine-best-beer-attributes-if-driver-is-yes
   (declare (salience ?*medium-low-priority*))
   (driver yes)
   =>
   (assert (attribute (name best-alcohol) (value not-detectable) (certainty 20)))
   (assert (attribute (name best-alcohol) (value mild) (certainty 10))))

(defrule determine-best-beer-attributes-if-preferred-flavor-is-clean
   (declare (salience ?*medium-low-priority*))
   (preferred-flavor clean)
   =>
   (assert (attribute (name best-flavor) (value crisp-clean) (certainty 20))))

(defrule determine-best-beer-attributes-if-preferred-flavor-is-sweet
   (declare (salience ?*medium-low-priority*))
   (preferred-flavor sweet)
   =>
   (assert (attribute (name best-flavor) (value malty-sweet) (certainty 20))))

(defrule determine-best-beer-attributes-if-preferred-flavor-is-roasty
   (declare (salience ?*medium-low-priority*))
   (preferred-flavor roasty)
   =>
   (assert (attribute (name best-flavor) (value dark-roasty) (certainty 20))))

(defrule determine-best-beer-attributes-if-preferred-flavor-is-bitter
   (declare (salience ?*medium-low-priority*))
   (preferred-flavor bitter)
   =>
   (assert (attribute (name best-flavor) (value hoppy-bitter) (certainty 20))))

(defrule determine-best-beer-attributes-if-preferred-flavor-is-fruity
   (declare (salience ?*medium-low-priority*))
   (preferred-flavor fruity)
   =>
   (assert (attribute (name best-flavor) (value fruity-spicy) (certainty 20))))

; determine best beer attributes for meal type recognized...

(defrule determine-best-beer-attributes-if-which-pizza-topping-is-classic
   (declare (salience ?*medium-low-priority*))
   (or (pizza-topping-for-omnivorous classic)
       (pizza-topping-for-vegetarian classic)
       (pizza-topping-for-vegan classic))
   =>
   (assert (attribute (name best-flavor) (value crisp-clean) (certainty 50))))

(defrule determine-best-beer-attributes-if-which-pizza-topping-for-omnivorous-is-meat
   (declare (salience ?*medium-low-priority*))
   (meat-topping-is-spicy no)
   =>
   (assert (attribute (name best-flavor) (value hoppy-bitter) (certainty 50))))

(defrule determine-best-beer-attributes-if-which-pizza-topping-for-omnivorous-is-spicy-meat
   (declare (salience ?*medium-low-priority*))
   (meat-topping-is-spicy yes)
   =>
   (assert (attribute (name best-flavor) (value malty-sweet) (certainty 50))))

(defrule determine-best-beer-attributes-if-which-pizza-topping-are-vegetables
  (declare (salience ?*medium-low-priority*))
  (vegetables-topping-are-roasted no)
  =>
  (assert (attribute (name best-flavor) (value sour-tart-funky) (certainty 50))))

(defrule determine-best-beer-attributes-if-which-pizza-topping-are-roasted-vegetables
   (declare (salience ?*medium-low-priority*))
   (vegetables-topping-are-roasted yes)
   =>
   (assert (attribute (name best-flavor) (value dark-roasty) (certainty 50))))

(defrule determine-best-beer-attributes-if-which-pizza-topping-for-omnivorous-or-vegetarian-is-cheese
   (declare (salience ?*medium-low-priority*))
   (or (pizza-topping-for-omnivorous cheese)
       (pizza-topping-for-vegetarian cheese))
   =>
   (assert (attribute (name best-flavor) (value fruity-spicy) (certainty 50))))

(defrule determine-best-beer-attributes-if-which-cheese-style-is-fresh
   (declare (salience ?*medium-low-priority*))
   (which-cheese-style fresh)
   =>
   (assert (attribute (name best-style) (value "Wheat Beer") (certainty 80)))
   (assert (attribute (name best-name) (value "Belgian-Style Fruit Lambic") (certainty 80)))
   (assert (attribute (name best-name) (value "Belgian-Style Lambic/Gueuze") (certainty 80))))

(defrule determine-best-beer-attributes-if-which-fresh-cheese-is-Mascarpone
   (declare (salience ?*medium-low-priority*))
   (which-fresh-cheese Mascarpone)
   =>
   (assert (attribute (name best-name) (value "Belgian-Style Witbier") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-fresh-cheese-is-Ricotta-or-which-grain-is-bruschetta
   (declare (salience ?*medium-low-priority*))
   (or (which-fresh-cheese Ricotta)
       (which-grain-is-bruschetta))
   =>
   (assert (attribute (name best-name) (value "Honey Beer") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-fresh-cheese-is-Chèvre
   (declare (salience ?*medium-low-priority*))
   (which-fresh-cheese Chèvre)
   =>
   (assert (attribute (name best-name) (value "American Wheat") (certainty 90)))
   (assert (attribute (name best-name) (value "German-Style Hefeweizen") (certainty 90)))
   (assert (attribute (name best-name) (value "Belgian-Style Fruit Lambic") (certainty 90)))
   (assert (attribute (name best-name) (value "European-Style Export") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-fresh-cheese-is-Feta-or-which-pork-is-loin
   (declare (salience ?*medium-low-priority*))
   (or (which-fresh-cheese Feta)
       (which-pork loin))
   =>
   (assert (attribute (name best-name) (value "California Common") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-fresh-cheese-is-Cream-Cheese
   (declare (salience ?*medium-low-priority*))
   (which-fresh-cheese "Cream Cheese")
   =>
   (assert (attribute (name best-name) (value "Fruit and Field Beer") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-cheese-style-is-semi-soft
   (declare (salience ?*medium-low-priority*))
   (which-cheese-style semi-soft)
   =>
   (assert (attribute (name best-style) (value "Pale Ale") (certainty 80)))
   (assert (attribute (name best-name) (value "German-Style Bock") (certainty 80)))
   (assert (attribute (name best-name) (value "German-Style Kölsch") (certainty 80))))

(defrule determine-best-beer-attributes-if-which-semi-soft-cheese-is-Mozzarella
   (declare (salience ?*medium-low-priority*))
   (which-semi-soft-cheese Mozzarella)
   =>
   (assert (attribute (name best-flavor) (value crisp-clean) (certainty 50)))
   (assert (attribute (name best-name) (value "American Imperial Red Ale") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-semi-soft-cheese-is-Colby
   (declare (salience ?*medium-low-priority*))
   (which-semi-soft-cheese Colby)
   =>
   (assert (attribute (name best-name) (value "German-Style Helles") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-semi-soft-cheese-is-Havarti
   (declare (salience ?*medium-low-priority*))
   (which-semi-soft-cheese Havarti)
   =>
   (assert (attribute (name best-name) (value "Berliner-Style Weisse") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-semi-soft-cheese-is-Monterey-Jack-or-shellfish-is-mild
   (declare (salience ?*medium-low-priority*))
   (or (which-semi-soft-cheese "Monterey Jack")
       (shellfish-is-mild yes))
   =>
   (assert (attribute (name best-name) (value "American Cream Ale") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-cheese-style-is-firm/hard
   (declare (salience ?*medium-low-priority*))
   (which-cheese-style firm/hard)
   =>
   (assert (attribute (name best-style) (value "Bock") (certainty 80)))
   (assert (attribute (name best-style) (value "Brown Ale") (certainty 80)))
   (assert (attribute (name best-name) (value "Bohemian-Style Pilsener") (certainty 80)))
   (assert (attribute (name best-name) (value "German-Style Pilsener") (certainty 80)))
   (assert (attribute (name best-name) (value "American Imperial Stout") (certainty 80))))

(defrule determine-best-beer-attributes-if-which-firm/hard-cheese-is-Swiss
   (declare (salience ?*medium-low-priority*))
   (which-firm/hard-cheese Swiss)
   =>
   (assert (attribute (name best-name) (value "German-Style Maibock") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-firm/hard-cheese-is-Gouda
   (declare (salience ?*medium-low-priority*))
   (which-firm/hard-cheese Gouda)
   =>
   (assert (attribute (name best-flavor) (value malty-sweet) (certainty 50)))
   (assert (attribute (name best-name) (value "German-Style Dunkelweizen") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-type-of-Gouda-is-aged
   (declare (salience ?*medium-low-priority*))
   (which-type-of-Gouda aged)
   =>
   (assert (attribute (name best-name) (value "American Brown Ale") (certainty 90)))
   (assert (attribute (name best-name) (value "English-Style Brown Ale") (certainty 90)))
   (assert (attribute (name best-name) (value "Belgian-Style Quadrupel") (certainty 90)))
   (assert (attribute (name best-name) (value "Baltic-Style Porter") (certainty 90)))
   (assert (attribute (name best-name) (value "American Black Ale") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-type-of-Gouda-is-smoked
   (declare (salience ?*medium-low-priority*))
   (which-type-of-Gouda smoked)
   =>
   (assert (attribute (name best-name) (value "American Imperial Porter") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-firm/hard-cheese-is-Cheddar
   (declare (salience ?*medium-low-priority*))
   (which-firm/hard-cheese Cheddar)
   =>
   (assert (attribute (name best-name) (value "Irish-Style Red") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-color-of-Cheddar-is-white
   (declare (salience ?*medium-low-priority*))
   (which-color-of-Cheddar white)
   =>
   (assert (attribute (name best-name) (value "American Amber Lager") (certainty 90)))
   (assert (attribute (name best-name) (value "German-Style Pilsener") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-Cheddar-seasoning-is-mild
   (declare (salience ?*medium-low-priority*))
   (which-Cheddar-seasoning mild)
   =>
   (assert (attribute (name best-name) (value "American Pale Ale") (certainty 90)))
   (assert (attribute (name best-name) (value "English-Style Mild") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-Cheddar-seasoning-is-medium
   (declare (salience ?*medium-low-priority*))
   (which-Cheddar-seasoning medium)
   =>
   (assert (attribute (name best-name) (value "American Amber Ale") (certainty 90)))
   (assert (attribute (name best-name) (value "American Pale Ale") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-Cheddar-seasoning-is-aged
   (declare (salience ?*medium-low-priority*))
   (which-Cheddar-seasoning aged)
   =>
   (assert (attribute (name best-flavor) (value hoppy-bitter) (certainty 50)))
   (assert (attribute (name best-name) (value "English-Style IPA") (certainty 90)))
   (assert (attribute (name best-name) (value "English-Style Oatmeal Stout") (certainty 90))))

(defrule determine-best-beer-attributes-if-Cheddar-is-sharp-or-which-rich-is-grilled-lamb
   (declare (salience ?*medium-low-priority*))
   (or (Cheddar-is-sharp yes)
       (and (meat-cooking-method grilled)
            (which-rich lamb)))
   =>
   (assert (attribute (name best-name) (value "American Stout") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-color-of-Cheddar-is-white-and-which-Cheddar-seasoning-is-mild
   (declare (salience ?*medium-low-priority*))
   (which-color-of-Cheddar white)
   (which-Cheddar-seasoning mild)
   =>
   (assert (attribute (name best-name) (value "Bohemian-Style Pilsener") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-type-of-Swiss-is-Emmental-or-which-bluefish-is-grilled-salmon
   (declare (salience ?*medium-low-priority*))
   (or (which-type-of-Swiss Emmental)
       (and (fish-cooking-method grilled)
            (which-bluefish salmon)))
   =>
   (assert (attribute (name best-name) (value "German-Style Brown/Altbier") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-type-of-Swiss-is-Gruyère
   (declare (salience ?*medium-low-priority*))
   (which-type-of-Swiss Gruyère)
   =>
   (assert (attribute (name best-name) (value "English-Style Brown Porter") (certainty 90)))
   (assert (attribute (name best-name) (value "Robust Porter") (certainty 90))))

(defrule determine-best-beer-attributes-if-Swiss-is-aged
   (declare (salience ?*medium-low-priority*))
   (Swiss-is-aged yes)
   =>
   (assert (attribute (name best-name) (value "German-Style Bock") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-firm/hard-cheese-is-Parmesan
   (declare (salience ?*medium-low-priority*))
   (which-firm/hard-cheese Parmesan)
   =>
   (assert (attribute (name best-name) (value "Smoke Beer") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-cheese-style-is-is-blue
   (declare (salience ?*medium-low-priority*))
   (which-cheese-style blue)
   =>
   (assert (attribute (name best-flavor) (value dark-roasty) (certainty 50)))
   (assert (attribute (name best-style) (value "India Pale Ale") (certainty 80)))
   (assert (attribute (name best-name) (value "American Black Ale") (certainty 80))))

(defrule determine-best-beer-attributes-if-which-blue-or-natural-rind-cheese-is-Stilton
   (declare (salience ?*medium-low-priority*))
   (or (which-blue-cheese Stilton)
       (which-natural-rind-cheese Stilton))
   =>
   (assert (attribute (name best-name) (value "British-Style Barley Wine Ale") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-cheese-style-is-natural-rind
   (declare (salience ?*medium-low-priority*))
   (which-cheese-style "natural rind")
   =>
   (assert (attribute (name best-style) (value "Pale Ale") (certainty 80)))
   (assert (attribute (name best-name) (value "Belgian-Style Golden Strong Ale") (certainty 80)))
   (assert (attribute (name best-name) (value "Belgian-Style Blonde Ale") (certainty 80)))
   (assert (attribute (name best-name) (value "Blonde Ale") (certainty 80)))
   (assert (attribute (name best-name) (value "American Barley Wine") (certainty 80)))
   (assert (attribute (name best-name) (value "British-Style Barley Wine Ale") (certainty 80))))

(defrule determine-best-beer-attributes-if-which-natural-rind-cheese-is-Brie
   (declare (salience ?*medium-low-priority*))
   (which-natural-rind-cheese Brie)
   =>
   (assert (attribute (name best-flavor) (value fruity-spicy) (certainty 50)))
   (assert (attribute (name best-name) (value "Belgian-Style Blonde Ale") (certainty 90)))
   (assert (attribute (name best-name) (value "Belgian-Style Saison") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-natural-rind-cheese-is-Camembert
   (declare (salience ?*medium-low-priority*))
   (which-natural-rind-cheese Camembert)
   =>
   (assert (attribute (name best-name) (value "Pumpkin Beer") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-natural-rind-cheese-is-Triple-Crème
   (declare (salience ?*medium-low-priority*))
   (which-natural-rind-cheese "Triple Crème")
   =>
   (assert (attribute (name best-name) (value "Belgian-Style Golden Strong Ale") (certainty 90)))
   (assert (attribute (name best-name) (value "Belgian-Style Tripel") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-natural-rind-cheese-is-Mimolette
   (declare (salience ?*medium-low-priority*))
   (which-natural-rind-cheese Mimolette)
   =>
   (assert (attribute (name best-name) (value "Belgian-Style Flanders") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-cheese-style-is-washed-rind
   (declare (salience ?*medium-low-priority*))
   (which-cheese-style "washed rind")
   =>
   (assert (attribute (name best-name) (value "Belgian-Style Blonde Ale") (certainty 80)))
   (assert (attribute (name best-name) (value "Belgian-Style Golden Strong Ale") (certainty 80)))
   (assert (attribute (name best-name) (value "Belgian-Style Pale Ale") (certainty 80)))
   (assert (attribute (name best-name) (value "Belgian-Style Dubbel") (certainty 80)))
   (assert (attribute (name best-name) (value "French-Style Biére de Garde") (certainty 80))))

(defrule determine-best-beer-attributes-if-which-washed-rind-cheese-is-Taleggio
   (declare (salience ?*medium-low-priority*))
   (which-washed-rind-cheese Taleggio)
   =>
   (assert (attribute (name best-name) (value "Belgian-Style Pale Ale") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-entrée-is-grain
   (declare (salience ?*medium-low-priority*))
   (or (which-entrée-omnivorous grain)
       (which-entrée-vegetarian grain)
       (which-entrée-vegan grain))
   =>
   (assert (attribute (name best-flavor) (value crisp-clean) (certainty 50))))

(defrule determine-best-beer-attributes-if-which-grain-are-chips
   (declare (salience ?*medium-low-priority*))
   (which-grain chips)
   =>
   (assert (attribute (name best-name) (value "English-Style Bitter") (certainty 90)))
   (assert (attribute (name best-name) (value "English-Style Pale Ale (ESB)") (certainty 90)))
   (assert (attribute (name best-name) (value "Belgian-Style Pale Ale") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-grain-is-spaghetti
   (declare (salience ?*medium-low-priority*))
   (which-grain spaghetti)
   =>
   (assert (attribute (name best-name) (value "Blonde Ale") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-grain-are-grits-or-which-shellfish-are-grilled-shrimps
   (declare (salience ?*medium-low-priority*))
   (or (which-grain grits)
       (and (fish-cooking-method grilled)
            (which-shellfish shrimps)))
   =>
   (assert (attribute (name best-name) (value "American Black Ale") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-entrée-is-legumes
   (declare (salience ?*medium-low-priority*))
   (or (which-entrée-omnivorous legumes)
       (which-entrée-vegetarian legumes)
       (which-entrée-vegan legumes))
   =>
   (assert (attribute (name best-flavor) (value malty-sweet) (certainty 50))))

(defrule determine-best-beer-attributes-if-which-which-entrée-omnivorous-is-fish
   (declare (salience ?*medium-low-priority*))
   (which-entrée-omnivorous fish)
   =>
   (assert (attribute (name best-name) (value "English-Style Bitter") (certainty 80)))
   (assert (attribute (name best-name) (value "English-Style Pale Ale (ESB)") (certainty 80))))

(defrule determine-best-beer-attributes-if-which-fish-is-shellfish
   (declare (salience ?*medium-low-priority*))
   (which-fish shellfish)
   =>
   (assert (attribute (name best-flavor) (value fruity-spicy) (certainty 50)))
   (assert (attribute (name best-name) (value "Bohemian-Style Pilsener") (certainty 90)))
   (assert (attribute (name best-name) (value "German-Style Pilsener") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-shellfish-are-mussels
   (declare (salience ?*medium-low-priority*))
   (which-shellfish mussels)
   =>
   (assert (attribute (name best-name) (value "Belgian-Style Saison") (certainty 90)))
   (assert (attribute (name best-name) (value "Belgian-Style Lambic/Gueuze") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-shellfish-are-oysters
   (declare (salience ?*medium-low-priority*))
   (which-shellfish oysters)
   =>
   (assert (attribute (name best-name) (value "Irish-Style Dry Stout") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-which-entrée-omnivorous-is-meat
   (declare (salience ?*medium-low-priority*))
   (which-entrée-omnivorous meat)
   =>
   (assert (attribute (name best-name) (value "Scotch Ale/Wee Heavy") (certainty 80)))
   (assert (attribute (name best-name) (value "Scottish-Style Ale") (certainty 80))))

(defrule determine-best-beer-attributes-if-meat-cooking-method-is-barbecue
   (declare (salience ?*medium-low-priority*))
   (meat-cooking-method barbecue)
   =>
   (assert (attribute (name best-name) (value "American Amber Ale") (certainty 90))))

(defrule determine-best-beer-attributes-if-meat-cooking-method-is-braised-or-which-dessert-is-chocolate
   (declare (salience ?*medium-low-priority*))
   (or (meat-cooking-method braised)
       (which-dessert chocolate))
   =>
   (assert (attribute (name best-flavor) (value malty-sweet) (certainty 50)))
   (assert (attribute (name best-flavor) (value dark-roasty) (certainty 50))))

(defrule determine-best-beer-attributes-if-meat-cooking-method-is-grilled
   (declare (salience ?*medium-low-priority*))
   (meat-cooking-method grilled)
   =>
   (assert (attribute (name best-name) (value "American Pale Ale") (certainty 90)))
   (assert (attribute (name best-name) (value "American Amber Lager") (certainty 90)))
   (assert (attribute (name best-name) (value "Vienna-Style Lager") (certainty 90)))
   (assert (attribute (name best-name) (value "American Brown Ale") (certainty 90)))
   (assert (attribute (name best-name) (value "English-Style Brown Porter") (certainty 90)))
   (assert (attribute (name best-name) (value "Robust Porter") (certainty 90))))

(defrule determine-best-beer-attributes-if-meat-cooking-method-is-roasted
   (declare (salience ?*medium-low-priority*))
   (meat-cooking-method roasted)
   =>
   (assert (attribute (name best-name) (value "American Pale Ale") (certainty 90)))
   (assert (attribute (name best-name) (value "English-Style Brown Porter") (certainty 90)))
   (assert (attribute (name best-name) (value "Robust Porter") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-meat-is-rich-meats
   (declare (salience ?*medium-low-priority*))
   (which-meat rich)
   =>
   (assert (attribute (name best-flavor) (value sour-tart-funky) (certainty 50))))

(defrule determine-best-beer-attributes-if-which-rich-is-roasted-beef-or-which-rich-is-lamb
   (declare (salience ?*medium-low-priority*))
   (or (and (meat-cooking-method roasted)
            (which-rich beef))
       (which-rich lamb))
   =>
   (assert (attribute (name best-name) (value "English-Style Old Ale") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-beef-is-bresola
   (declare (salience ?*medium-low-priority*))
   (which-beef bresola)
   =>
   (assert (attribute (name best-name) (value "American Brown Ale") (certainty 90)))
   (assert (attribute (name best-name) (value "Rye Beer") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-rich-is-roasted-lamb
   (declare (salience ?*medium-low-priority*))
   (meat-cooking-method roasted)
   (which-rich lamb)
   =>
   (assert (attribute (name best-name) (value "French-Style Biére de Garde") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-rich-is-pork
   (declare (salience ?*medium-low-priority*))
   (which-rich pork)
   =>
   (assert (attribute (name best-flavor) (value hoppy-bitter) (certainty 50)))
   (assert (attribute (name best-flavor) (value fruity-spicy) (certainty 50)))
   (assert (attribute (name best-name) (value "German-Style Doppelbock") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-rich-is-roasted-pork-or-which-meat-is-steak
   (declare (salience ?*medium-low-priority*))
   (or (and (meat-cooking-method roasted)
            (which-rich pork))
       (which-meat steak))
   =>
   (assert (attribute (name best-name) (value "English-Style Brown Ale") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-pork-is-tenderloin
   (declare (salience ?*medium-low-priority*))
   (which-pork tenderloin)
   =>
   (assert (attribute (name best-name) (value "Coffee Beer") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-pork-is-prosciutto
   (declare (salience ?*medium-low-priority*))
   (which-pork prosciutto)
   =>
   (assert (attribute (name best-name) (value "Bohemian-Style Pilsener") (certainty 90)))
   (assert (attribute (name best-name) (value "German-Style Doppelbock") (certainty 90)))
   (assert (attribute (name best-name) (value "Belgian-Style Saison") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-pork-is-speck
   (declare (salience ?*medium-low-priority*))
   (which-pork speck)
   =>
   (assert (attribute (name best-name) (value "Smoke Beer") (certainty 90)))
   (assert (attribute (name best-name) (value "American Pale Ale") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-pork-is-mortadella
   (declare (salience ?*medium-low-priority*))
   (which-pork mortadella)
   =>
   (assert (attribute (name best-name) (value "German-Style Märzen/Oktoberfest") (certainty 90)))
   (assert (attribute (name best-name) (value "Belgian-Style Tripel") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-pork-is-sausage
   (declare (salience ?*medium-low-priority*))
   (which-pork sausage)
   =>
   (assert (attribute (name best-name) (value "German-Style Dunkel") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-pork-is-grilled-sausage
   (declare (salience ?*medium-low-priority*))
   (meat-cooking-method grilled)
   (which-pork sausage)
   =>
   (assert (attribute (name best-name) (value "Smoke Porter") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-sausage-is-capocollo
   (declare (salience ?*medium-low-priority*))
   (which-sausage capocollo)
   =>
   (assert (attribute (name best-name) (value "American Amber Lager") (certainty 90)))
   (assert (attribute (name best-name) (value "English-Style Pale Ale (ESB)") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-sausage-is-soppressata
   (declare (salience ?*medium-low-priority*))
   (which-sausage soppressata)
   =>
   (assert (attribute (name best-name) (value "American Brown Ale") (certainty 90)))
   (assert (attribute (name best-name) (value "Belgian-Style Dubbel") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-sausage-is-salame-piccante
   (declare (salience ?*medium-low-priority*))
   (which-sausage "salame piccante")
   =>
   (assert (attribute (name best-name) (value "Imperial IPA") (certainty 90)))
   (assert (attribute (name best-name) (value "Rye Beer") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-poultry-is-chicken
   (declare (salience ?*medium-low-priority*))
   (which-poultry chicken)
   =>
   (assert (attribute (name best-name) (value "German-Style Weizenbock") (certainty 90)))
   (assert (attribute (name best-name) (value "Bohemian-Style Pilsener") (certainty 90)))
   (assert (attribute (name best-name) (value "German-Style Pilsener") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-poultry-is-roasted-chicken
   (declare (salience ?*medium-low-priority*))
   (meat-cooking-method roasted)
   (which-poultry chicken)
   =>
   (assert (attribute (name best-name) (value "English-Style Bitter") (certainty 90)))
   (assert (attribute (name best-name) (value "English-Style Pale Ale (ESB)") (certainty 90)))
   (assert (attribute (name best-name) (value "German-Style Dunkelweizen") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-poultry-is-roasted-turkey
   (declare (salience ?*medium-low-priority*))
   (meat-cooking-method roasted)
   (which-poultry turkey)
   =>
   (assert (attribute (name best-name) (value "Belgian-Style Tripel") (certainty 90)))
   (assert (attribute (name best-name) (value "Pumpkin Beer") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-meat-is-game
   (declare (salience ?*medium-low-priority*))
   (which-meat game)
   =>
   (assert (attribute (name best-name) (value "Scotch Ale/Wee Heavy") (certainty 90)))
   (assert (attribute (name best-name) (value "Scottish-Style Ale") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-meat-is-grilled-or-roasted-game
   (declare (salience ?*medium-low-priority*))
   (or (meat-cooking-method grilled)
       (meat-cooking-method roasted))
   (which-meat game)
   =>
   (assert (attribute (name best-name) (value "American Brett") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-game-is-wild-or-which-other-vegetables-are-mushrooms
   (declare (salience ?*medium-low-priority*))
   (or (which-game wild)
       (which-other-vegetables mushrooms))
   =>
   (assert (attribute (name best-name) (value "English-Style Mild") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-game-is-birds
   (declare (salience ?*medium-low-priority*))
   (which-game birds)
   =>
   (assert (attribute (name best-flavor) (value hoppy-bitter) (certainty 50))))

(defrule determine-best-beer-attributes-if-which-game-birds-is-roasted-duck
   (declare (salience ?*medium-low-priority*))
   (meat-cooking-method roasted)
   (which-game-birds duck)
   =>
   (assert (attribute (name best-name) (value "Belgian-Style Quadrupel") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-meat-is-grilled-steak
   (declare (salience ?*medium-low-priority*))
   (meat-cooking-method grilled)
   (which-meat steak)
   =>
   (assert (attribute (name best-name) (value "European-Style Export") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-entrée-is-vegetables
   (declare (salience ?*medium-low-priority*))
   (or (which-entrée-omnivorous vegetables)
       (which-entrée-vegetarian vegetables)
       (which-entrée-vegan vegetables))
   =>
   (assert (attribute (name best-name) (value "American Amber Lager") (certainty 80)))
   (assert (attribute (name best-name) (value "Vienna-Style Lager") (certainty 80)))
   (assert (attribute (name best-name) (value "American Brown Ale") (certainty 80))))

(defrule determine-best-beer-attributes-if-which-vegetables-is-root
   (declare (salience ?*medium-low-priority*))
   (which-vegetables root)
   =>
   (assert (attribute (name best-flavor) (value sour-tart-funky) (certainty 50))))

(defrule determine-best-beer-attributes-if-which-vegetables-is-salad
   (declare (salience ?*medium-low-priority*))
   (which-vegetables salad)
   =>
   (assert (attribute (name best-name) (value "American Wheat") (certainty 90)))
   (assert (attribute (name best-name) (value "American Cream Ale") (certainty 90)))
   (assert (attribute (name best-name) (value "Bohemian-Style Pilsener") (certainty 90)))
   (assert (attribute (name best-name) (value "German-Style Pilsener") (certainty 90)))
   (assert (attribute (name best-name) (value "Fruit and Field Beer") (certainty 90))))

(defrule determine-best-beer-attributes-if-vegetables-cooking-method-is-grilled
   (declare (salience ?*medium-low-priority*))
   (vegetables-cooking-method grilled)
   =>
   (assert (attribute (name best-flavor) (value dark-roasty) (certainty 50)))
   (assert (attribute (name best-name) (value "Smoke Beer") (certainty 90))))

(defrule determine-best-beer-attributes-if-vegetables-cooking-method-is-roasted
   (declare (salience ?*medium-low-priority*))
   (vegetables-cooking-method roasted)
   =>
   (assert (attribute (name best-name) (value "German-Style Dunkel") (certainty 90)))
   (assert (attribute (name best-name) (value "Irish-Style Red") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-entrée-is-fats
   (declare (salience ?*medium-low-priority*))
   (or (which-entrée-omnivorous fats)
       (which-entrée-vegetarian "vegetable fats")
       (which-entrée-vegan "vegetable fats"))
   =>
   (assert (attribute (name best-flavor) (value hoppy-bitter) (certainty 50)))
   (assert (attribute (name best-flavor) (value dark-roasty) (certainty 50))))

(defrule determine-best-beer-attributes-if-which-fats-is-vegetable
   (declare (salience ?*medium-low-priority*))
   (or (which-fats vegetable)
       (which-entrée-vegetarian "vegetables fats")
       (which-entrée-vegan "vegetables fats"))
   =>
   (assert (attribute (name best-carbonation) (value high) (certainty 50)))
   (assert (attribute (name best-carbonation) (value medium) (certainty 25))))

(defrule determine-best-beer-attributes-if-which-chocolate-is-white
   (declare (salience ?*medium-low-priority*))
   (which-chocolate white)
   =>
   (assert (attribute (name best-name) (value "Belgian-Style Witbier") (certainty 90)))
   (assert (attribute (name best-name) (value "American Brown Ale") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-chocolate-is-milk
   (declare (salience ?*medium-low-priority*))
   (which-chocolate milk)
   =>
   (assert (attribute (name best-name) (value "American Pale Ale") (certainty 90)))
   (assert (attribute (name best-name) (value "German-Style Doppelbock") (certainty 90)))
   (assert (attribute (name best-name) (value "English-Style Pale Ale (ESB)") (certainty 90)))
   (assert (attribute (name best-name) (value "American Amber Lager") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-chocolate-is-semisweet
   (declare (salience ?*medium-low-priority*))
   (which-chocolate semisweet)
   =>
   (assert (attribute (name best-name) (value "American Stout") (certainty 90)))
   (assert (attribute (name best-name) (value "Robust Porter") (certainty 90)))
   (assert (attribute (name best-name) (value "Belgian-Style Dubbel") (certainty 90)))
   (assert (attribute (name best-name) (value "American IPA") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-chocolate-is-bittersweet
   (declare (salience ?*medium-low-priority*))
   (which-chocolate bittersweet)
   =>
   (assert (attribute (name best-name) (value "American Imperial Stout") (certainty 90)))
   (assert (attribute (name best-name) (value "Belgian-Style Dubbel") (certainty 90)))
   (assert (attribute (name best-name) (value "Belgian-Style Quadrupel") (certainty 90)))
   (assert (attribute (name best-name) (value "Belgian-Style Fruit Lambic") (certainty 90)))
   (assert (attribute (name best-name) (value "Belgian-Style Lambic/Gueuze") (certainty 90)))
   (assert (attribute (name best-name) (value "Robust Porter") (certainty 90))))

(defrule determine-best-beer-attributes-if-which-chocolate-is-unsweetened/bitter-or-which-entrée-vegan-is-chocolate
   (declare (salience ?*medium-low-priority*))
   (or (which-chocolate unsweetened/bitter)
       (which-entrée-vegan chocolate))
   =>
   (assert (attribute (name best-name) (value "Belgian-Style Flanders") (certainty 90)))
   (assert (attribute (name best-name) (value "Belgian-Style Fruit Lambic") (certainty 90)))
   (assert (attribute (name best-name) (value "American Sour") (certainty 90))))


Added basic support for loading programs in memory.

I am in the process of implementing operations that are actually objects in the
system. I am deciding whether the initial implementation should be
message-based (requires a subclass for each operation and a general pain in the
ass with the upside being that its easy to write "microcode" if I want to get
that low level) or using a common operation class that asserts facts which
contain the actual operation logic. I'm not sure which one to do at this point.
I'm leaning towards the more "pain-in-the-ass" method because its easier to
understand and I can rearrange encodings without having to change execution
rules. The only downside is that the "overhead" of message passing could come
into play. However, this is not a safety-critical or performance tool so who
cares....hmmmmmm

Anyway, I have also implemented a cacheless design for the processor due to the
way that the knowledge base works combined with the fact that it is dead
fucking simple to implement. Caches add a lot of complexity that really is not
necessary at this point.

;------------------------------------------------------------------------------
;electron
;Copyright (c) 2012-2013, Joshua Scoggins
;All rights reserved.
;
;Redistribution and use in source and binary forms, with or without
;modification, are permitted provided that the following conditions are met:
;    * Redistributions of source code must retain the above copyright
;      notice, this list of conditions and the following disclaimer.
;    * Redistributions in binary form must reproduce the above copyright
;      notice, this list of conditions and the following disclaimer in the
;      documentation and/or other materials provided with the distribution.
;    * Neither the name of The Adventure Engine nor the
;      names of its contributors may be used to endorse or promote products
;      derived from this software without specific prior written permission.
;
;THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
;ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
;WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
;DISCLAIMED. IN NO EVENT SHALL Joshua Scoggins BE LIABLE FOR ANY
;DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
;(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
;LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
;ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
;(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
;SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
;-------------------------------------------------------------------------------
; Simulator.clp - Defines a simple computer to be executed through an expert
;                 system. This computer is unique in that instructions declare
;                 actions instead of perform actions directly.
;
;                 The Theoretical Architecture is an 8-bit declarative
;                 processor architecture. It has an 8-bit direct address space
;                 that can be extended through the use of jump instructions.
;-------------------------------------------------------------------------------
(defclass operation
 "Represents an instruction to execute"
 (is-a USER)
 (role abstract)
 (slot address
  (type INTEGER)
  (visibility public)
  (storage local)
  (range 0 ?VARIABLE)
  (default ?NONE))
 (slot name
  (type SYMBOL)
  (visibility public)
  (storage local)
  (default ?NONE)))
(defclass cell
  (is-a USER)
  (role abstract)
  (slot cell-type
        (type SYMBOL)
        (storage shared)
        (access read-only)
        (default unknown))
  (slot address
        (type INTEGER)
        (visibility public)
        (storage local)
        (range 0 ?VARIABLE))
  (slot value
        (type INTEGER)
        (range 0 255)
        (visibility public)
        (default-dynamic 0)))
(defclass memory-cell
  (is-a cell)
  (role concrete)
  (slot cell-type
        (source composite)
        (default memory)))

(defclass cache-cell
  (is-a cell)
  (role concrete)
  (slot address
        (source composite)
        (storage shared)
        (access initialize-only)
        (default 0))
  (slot cell-type
        (source composite)
        (default cache)))

(defclass register
  "Represents a storage location that is \"close\" to the procesor"
  (is-a USER)
  (slot offset
        (type INTEGER)
        (storage local)
        (default ?NONE))
  (slot value
        (type INTEGER)))

(defclass machine
  (is-a USER)
  (multislot registers
             (type INSTANCE)
             (allowed-classes register)))
;TODO: automate the generation of the register set
(defrule setup-machine
         (initial-fact)
         =>
         (bind ?registers (instance-name (make-instance pc of register (offset 256))))
         (loop-for-count (?i 0 255) do
                         (bind ?registers (create$ ?registers (instance-name (make-instance (sym-cat r ?i) of register (offset ?i))))))
         (make-instance proc of machine
                        (registers ?registers))
         (assert (Machine setup)))
(defrule load-program-into-memory
         ?s <- (Machine setup)
         ?f <- (load ?program-path into memory)
         =>
         ; the encoding of this processor can change from time to time but my
         ; current idea is to have a 255 byte window that represents a set of
         ; actions to be performed by the machine itself.
         (retract ?s ?f)
         ;build the memory cells right now
         (if (open ?program-path file "r") then
           (bind ?this (get-char file))
           (bind ?i 0)
           (while (!= ?this -1) do
                  (make-instance of memory-cell
                                 (address ?i)
                                 (value ?this))
                  (bind ?this (get-char file))
                  (bind ?i (+ ?i 1)))
           (close ?file)
           (assert (stage decode execute restart))
           else
           (printout t "ERROR: Couldn't load program" crlf)
           (halt)))
(defrule next-stage
         (declare (salience -10000))
         ?f <- (stage ? $?rest)
         =>
         (retract ?f)
         (if (> (length$ ?rest) 0) then
           (assert (stage $?rest))))
(defrule decode-instruction
         (stage decode $?)
         (object (is-a register)
                 (name [pc])
                 (value ?location))
         (object (is-a memory-cell)
          (address ?location)
          (value ?operation))

;------------------------------------------------------------------------------
;electron
;Copyright (c) 2012-2013, Joshua Scoggins
;All rights reserved.
;
;Redistribution and use in source and binary forms, with or without
;modification, are permitted provided that the following conditions are met:
;    * Redistributions of source code must retain the above copyright
;      notice, this list of conditions and the following disclaimer.
;    * Redistributions in binary form must reproduce the above copyright
;      notice, this list of conditions and the following disclaimer in the
;      documentation and/or other materials provided with the distribution.
;    * Neither the name of The Adventure Engine nor the
;      names of its contributors may be used to endorse or promote products
;      derived from this software without specific prior written permission.
;
;THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
;ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
;WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
;DISCLAIMED. IN NO EVENT SHALL Joshua Scoggins BE LIABLE FOR ANY
;DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
;(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
;LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
;ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
;(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
;SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
;-------------------------------------------------------------------------------
; Simulator.clp - Defines a simple computer to be executed through an expert
;                 system. This computer is unique in that instructions declare
;                 actions instead of perform actions directly.
;
;                 The Theoretical Architecture is an 8-bit declarative
;                 processor architecture. It has an 8-bit direct address space
;                 that can be extended through the use of jump instructions.
;-------------------------------------------------------------------------------
(defclass memory-cell
  (is-a USER)
  (slot address
        (type INTEGER)
        (range 0 ?VARIABLE))
  (slot value
        (type INTEGER)
        (range 0 255)
        (default-dynamic 0)))

(defclass register
 "Represents a storage location that is \"close\" to the procesor"
  (is-a USER)
  (slot offset
        (type INTEGER)
        (range 0 255)
        (storage local)
        (default ?NONE))
  (slot value
        (type INTEGER)
        (range 0 255)
        (default-dynamic 0)))
;TODO: automate the generation of the register set


Added the automation to the bottom of Simulator.clp

;------------------------------------------------------------------------------
;electron
;Copyright (c) 2012-2013, Joshua Scoggins
;All rights reserved.
;
;Redistribution and use in source and binary forms, with or without
;modification, are permitted provided that the following conditions are met:
;    * Redistributions of source code must retain the above copyright
;      notice, this list of conditions and the following disclaimer.
;    * Redistributions in binary form must reproduce the above copyright
;      notice, this list of conditions and the following disclaimer in the
;      documentation and/or other materials provided with the distribution.
;    * Neither the name of The Adventure Engine nor the
;      names of its contributors may be used to endorse or promote products
;      derived from this software without specific prior written permission.
;
;THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
;ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
;WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
;DISCLAIMED. IN NO EVENT SHALL Joshua Scoggins BE LIABLE FOR ANY
;DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
;(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
;LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
;ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
;(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
;SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
;-------------------------------------------------------------------------------
; Simulator.clp - Defines a simple computer to be executed through an expert
;                 system. This computer is unique in that instructions declare
;                 actions instead of perform actions directly.
;
;                 The Theoretical Architecture is an 8-bit declarative
;                 processor architecture. It has an 8-bit direct address space
;                 that can be extended through the use of jump instructions.
;-------------------------------------------------------------------------------
(load* MachineCommon.clp)
(defclass cell
  (is-a USER)
  (role abstract)
  (slot cell-type
        (type SYMBOL)
        (storage shared)
        (access read-only)
        (default unknown))
  (slot address
        (type INTEGER)
        (visibility public)
        (storage local)
        (range 0 ?VARIABLE))
  (slot value
        (type INTEGER)
        (range 0 255)
        (visibility public)
        (default-dynamic 0)))
(defclass memory-cell
  (is-a cell)
  (role concrete)
  (pattern-match reactive)
  (slot cell-type
        (source composite)
        (default memory)))

(defclass cache-cell
  (is-a cell)
  (role concrete)
  (pattern-match reactive)
  (slot address
        (source composite)
        (storage shared)
        (access initialize-only)
        (default 0))
  (slot cell-type
        (source composite)
        (default cache)))

(defclass register
  "Represents a storage location that is \"close\" to the procesor"
  (is-a USER)
  (slot offset
        (type INTEGER)
        (storage local)
        (default ?NONE))
  (slot value
        (type INTEGER)))

(defclass machine
  (is-a USER)
  (multislot registers
             (type INSTANCE)
             (allowed-classes register)))

(defgeneric next)
(defgeneric next-one)
(defgeneric next-two)
(defgeneric next-three)
(defmethod next
  ((?value NUMBER)
   (?count NUMBER (> ?count 3))
   (?inc NUMBER (!= ?inc 1)))
  (bind ?out (create$))
  (loop-for-count (?i 1 ?count) do
                  (bind ?out (create$ ?out (+ ?value (* ?i ?inc)))))
  (return ?out))

(defmethod next
  ((?value NUMBER)
   (?count NUMBER (> ?count 3))
   (?inc NUMBER (= ?inc 1)))
  (bind ?out (create$))
  (loop-for-count (?i 1 ?count) do
                  (bind ?out (create$ ?out (+ ?value ?i))))
  (return ?out))
(defmethod next
  ((?value NUMBER)
   (?count NUMBER (= ?count 1))
   (?inc NUMBER))
  (create$ (+ ?value ?inc)))
(defmethod next
  ((?value NUMBER)
   (?count NUMBER (= ?count 2))
   (?inc NUMBER (!= ?count 1)))
  (create$ (+ ?value ?inc)
           (+ ?value ?inc ?inc)))
(defmethod next
  ((?value NUMBER)
   (?count NUMBER (= ?count 2))
   (?inc NUMBER (= ?count 1)))
  (create$ (+ ?value 1)
           (+ ?value 2)))

(defmethod next
  ((?value NUMBER)
   (?count NUMBER (= ?count 3))
   (?inc NUMBER (!= ?count 1)))
  (create$ (+ ?value ?inc)
           (+ ?value ?inc ?inc)
           (+ ?value ?inc ?inc ?inc)))

(defmethod next
  ((?value NUMBER)
   (?count NUMBER (= ?count 3))
   (?inc NUMBER (= ?count 1)))
  (create$ (+ ?value 1)
           (+ ?value 2)
           (+ ?value 3)))

(defmethod next
  ((?value NUMBER)
   (?count NUMBER))
  (next ?value ?count 1))

(defmethod next-one
  ((?value NUMBER)
   (?inc NUMBER))
  (next ?value 1 ?inc))

(defmethod next-one
  ((?value NUMBER))
  (next ?value 1 1))

(defmethod next-two
  ((?value NUMBER)
   (?inc NUMBER))
  (next ?value 2 ?inc))

(defmethod next-two
  ((?value NUMBER))
  (next ?value 2 1))

(defmethod next-three
  ((?value NUMBER)
   (?inc NUMBER))
  (next ?value 3 ?inc))

(defmethod next-three
  ((?value NUMBER))
  (next ?value 3 1))

(defrule setup-machine
         (initial-fact)
         =>
         (bind ?registers (instance-name (make-instance pc of register (offset 256))))
         (loop-for-count (?i 0 255) do
                         (bind ?registers (create$ ?registers (instance-name (make-instance (sym-cat r ?i) of register (offset ?i))))))
         (make-instance proc of machine
                        (registers ?registers))
         (assert (Machine setup)))
(defrule load-program-into-memory
         ?s <- (Machine setup)
         ?f <- (load ?program-path into memory)
         =>
         (retract ?s ?f)
         ;build the memory cells right now
         (if (open ?program-path file "r") then
           (bind ?this (get-char file))
           (bind ?i 0)
           (while (!= ?this -1) do
                  (make-instance of memory-cell
                                 (address ?i)
                                 (value ?this))
                  (bind ?this (get-char file))
                  (bind ?i (+ ?i 1)))
           (close file)
           (assert (stage decode execute restart))
           else
           (printout t "ERROR: Couldn't load program" crlf)
           (halt)))
(defrule next-stage
         (declare (salience -10000))
         ?f <- (stage ? $?rest)
         =>
         (retract ?f)
         (if (> (length$ ?rest) 0) then
           (assert (stage $?rest))))
(defrule load-instruction-into-decoder
         (stage decode $?)
         (object (is-a register)
                 (name [pc])
                 (value ?location))
         (object (is-a memory-cell)
                 (address ?location)
                 (value ?operation))
         =>
         ;tee hee, silly computer scientist, it's not a fixed
         ;decoder location :D. But it will serve our purposes
         ;well.
         (assert (invoke operation ?operation at ?location)))

(defrule decode:invalid
         (declare (salience -1))
         (stage decode $?)
         ?f <- (invoke operation ? at ?)
         =>
         (retract ?f)
         (printout t "ERROR: Target operation is not valid" crlf)
         (halt))

; MACHINE SPECIFIC DESCRIPTION CODE FOLLOWS:
; With the exception of one instruction, the rest of the instruction
; set operates on available registers (which is why there are 255 of
; them). This only applies to the externally visible instruction set
; which is transformed internally to provide on the fly optimizations.
;
; This is the basis of the procedurally declarative processor design
; I'm implementing. Eventually, this will have more features but at
; this point it is important to get a basic implementation.
;
; TODO: Modify the instruction set to define the program counter
(defrule decode:nop
         "defines a nop instruction"
         (stage decode $?)
         ?f <- (invoke operation ?x&:(= ?x ?*nop-instruction*) at ?)
         =>
         (retract ?f)
         (assert (nop)))

(defrule decode:load
         (stage decode $?)
         ?f <- (invoke operation ?x&:(= ?*load-instruction* ?x) at ?loc)
         =>
         (retract ?f)
         (assert (load (next-two ?loc))))

(defrule decode:store
         (stage decode $?)
         ?f <- (invoke operation ?x&:(= ?x ?*store-instruction*) at ?loc)
         =>
         (retract ?f)
         (assert (store (next-two ?loc))))

(defrule decode:add
         (stage decode $?)
         ?f <- (invoke operation ?x&:(= ?x ?*add-instruction*) at ?loc)
         =>
         (retract ?f)
         (assert (add (next-three ?loc))))

(defrule decode:subtract
         (stage decode $?)
         ?f <- (invoke operation ?x&:(= ?x ?*subtract-instruction*) at ?loc)
         =>
         (retract ?f)
         (assert (subtract (next-three ?loc))))

(defrule decode:multiply
         (stage decode $?)
         ?f <- (invoke operation ?x&:(= ?x ?*multiply-instruction*) at ?loc)
         =>
         (retract ?f)
         (assert (multiply (next-three ?loc))))

(defrule decode:divide
         (stage decode $?)
         ?f <- (invoke operation ?x&:(= ?x ?*divide-instruction*) at ?loc)
         =>
         (retract ?f)
         (assert (divide (next-three ?loc))))

(defrule decode:equal
         (stage decode $?)
         ?f <- (invoke operation ?x&:(= ?x ?*equal-instruction*) at ?loc)
         =>
         (retract ?f)
         (assert (equal (next-three ?loc))))

; NOTES
; the encoding of this processor can change from time to time but my
; current idea is to have a 255 byte window that represents a set of
; actions to be performed by the machine itself. This isn't valid at
; this point but I may come back to this at another point

(reset)
(run)
(exit)