Modified the assert-string message in Environment.clp

The assert-string message no longer uses format because it isn't necessary due
to the env-assert-string function

;------------------------------------------------------------------------------
;Copyright (c) 2012, 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 Joshua Scoggins 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.
;------------------------------------------------------------------------------
; Environment.clp - A wrapper over a CLIPS environment
;------------------------------------------------------------------------------
(defclass core::Environment (is-a Object InteropObject))

(defmessage-handler core::Environment destroy primary ()
                    (if (not (is-executing-environment ?self:pointer)) then
                      (env-destroy ?self:pointer)
                      (return (delete-instance))
                      else
                      (printout
                        werror
                        "ERROR: attempted to destroy the executing environment."
                        crlf)
                      (return FALSE)))

(defmessage-handler core::Environment is-executing-environment primary ()
                    (return (is-executing-environment ?self:pointer)))

(defmessage-handler core::Environment run ($?count)
                    (bind ?size (length$ $?count))
                    (if (= 0 ?size) then
                      (if (is-executing-environment ?self:pointer) then
                        (run)
                        else
                        (env-run ?self:pointer))
                      else
                      (bind ?num (nth$ 1 ?count))
                      (if (and (> ?num 0) (integerp ?num)) then
                        (if (is-executing-environment ?self:pointer) then
                          (run ?num)
                          else
                          (env-run ?self:pointer ?num))
                        else
                        (printout werror "ERROR: invalid count provided." crlf))))

(defmessage-handler core::Environment eval (?string)
                    (if (stringp ?string) then
                      (if (is-executing-environment ?self:pointer) then
                        (eval ?string)
                        else
                        (env-eval ?self:pointer ?string))
                      else
                      (printout werror "ERROR: string expected" crlf)))

(defmessage-handler core::Environment build (?string)
                    (if (stringp ?string) then
                      (if (is-executing-environment ?self:pointer) then
                        (build ?string)
                        else
                        (env-build ?self:pointer ?string))
                      else
                      (printout werror "ERROR: string expected" crlf)))

(defmessage-handler core::Environment facts ()
                    (if (is-executing-environment ?self:pointer) then
                      (facts)
                      else
                      (env-facts ?self:pointer)))
(defmessage-handler core::Environment instances ()
                    (if (is-executing-environment ?self:pointer) then
                      (instances)
                      else
                      (env-instances ?self:pointer)))

(defmessage-handler core::Environment rules ()
                    (if (is-executing-environment ?self:pointer) then
                      (rules)
                      else
                      (env-rules ?self:pointer)))

(defmessage-handler core::Environment assert ($?elements)
                    (bind ?length (length$ ?elements))
                    (if (= 0 ?length) then
                      (printout werror "ERROR: No arguments provided" crlf)
                      else
                      (env-assert-string ?self:pointer
							  (implode$ $?elements))))

;------------------------------------------------------------------------------
;Copyright (c) 2012, 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 Joshua Scoggins 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.
;------------------------------------------------------------------------------
; Environment.clp - A wrapper over a CLIPS environment
;------------------------------------------------------------------------------
(defclass core::Environment (is-a Object InteropObject))

(defmessage-handler core::Environment destroy primary ()
                    (if (not (is-executing-environment ?self:pointer)) then
                      (env-destroy ?self:pointer)
                      (return (delete-instance))
                      else
                      (printout
                        werror
                        "ERROR: attempted to destroy the executing environment."
                        crlf)
                      (return FALSE)))

(defmessage-handler core::Environment is-executing-environment primary ()
                    (return (is-executing-environment ?self:pointer)))

(defmessage-handler core::Environment run ($?count)
                    (bind ?size (length$ $?count))
                    (if (= 0 ?size) then
                      (if (is-executing-environment ?self:pointer) then
                        (run)
                        else
                        (env-run ?self:pointer))
                      else
                      (bind ?num (nth$ 1 ?count))
                      (if (and (> ?num 0) (integerp ?num)) then
                        (if (is-executing-environment ?self:pointer) then
                          (run ?num)
                          else
                          (env-run ?self:pointer ?num))
                        else
                        (printout werror "ERROR: invalid count provided." crlf))))

(defmessage-handler core::Environment eval (?string)
                    (if (stringp ?string) then
                      (if (is-executing-environment ?self:pointer) then
                        (eval ?string)
                        else
                        (env-eval ?self:pointer ?string))
                      else
                      (printout werror "ERROR: string expected" crlf)))

(defmessage-handler core::Environment build (?string)
                    (if (stringp ?string) then
                      (if (is-executing-environment ?self:pointer) then
                        (build ?string)
                        else
                        (env-build ?self:pointer ?string))
                      else
                      (printout werror "ERROR: string expected" crlf)))

(defmessage-handler core::Environment facts ()
                    (if (is-executing-environment ?self:pointer) then
                      (facts)
                      else
                      (env-facts ?self:pointer)))
(defmessage-handler core::Environment instances ()
                    (if (is-executing-environment ?self:pointer) then
                      (instances)
                      else
                      (env-instances ?self:pointer)))

(defmessage-handler core::Environment rules ()
                    (if (is-executing-environment ?self:pointer) then
                      (rules)
                      else
                      (env-rules ?self:pointer)))

(defmessage-handler core::Environment assert ($?elements)
                    (bind ?length (length$ ?elements))
                    (if (= 0 ?length) then
                      (printout werror "ERROR: No arguments provided" crlf)
                      else
                      (env-assert-string
                        ?self:pointer
                        (format nil
                                "(assert (%s))" (implode$ $?elements)))))


Simplified the thing type

Simplified the thing type

;------------------------------------------------------------------------------
;The Adventure Engine
;Copyright (c) 2012-2016, 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.
;------------------------------------------------------------------------------
; Core module
;------------------------------------------------------------------------------
(defmodule core
           (export defclass thing))

(defclass core::thing
          "Base class of everything"
          (is-a USER))

;------------------------------------------------------------------------------
;The Adventure Engine
;Copyright (c) 2012-2016, 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.
;------------------------------------------------------------------------------
; Core module
;------------------------------------------------------------------------------
(defmodule core
           (export defclass thing))
(defclass core::thing
          "Base class for all entities in the world, has a parent child relationship"
          (is-a USER)
          (slot parent
                (type INSTANCE
                      SYMBOL)
                (allowed-classes thing)
                (allowed-symbols FALSE)
                (default-dynamic FALSE))
          (multislot children
                     (type INSTANCE)
                     (allowed-classes thing))
          (message-handler parent-is primary))

(defmessage-handler thing parent-is primary
                    (?value)
                    (and ?self:parent
                         (or (eq ?self:parent
                                 ?value)
                             (send ?self:parent
                                   parent-is
                                   ?value))))


update beer-questions.clp

update beer-questions.clp

;;***********************
;;* BEER QUESTION RULES *
;;***********************

; random questions for user type and scenario recognition

(defrule random-question-to-determine-which-sex
   (start)
   (not (which-sex ?sex))
   =>
   (set-strategy random)
   (assert (UI-state (display "Are you male or female? 👨🏻👩🏻")
                     (why "Male or female persons tend to prefer more or less intense beers.")
                     (relation-asserted which-sex)
                     (valid-answers male female))))

(defrule random-question-to-determine-which-age
   (start)
   (not (which-age ?age))
   =>
   (set-strategy random)
   (assert (UI-state (display "How old are you? 🔞")
                     (why "Younger people tend to prefer less intense beers.")
                     (relation-asserted which-age)
                     (valid-answers 18-23 24-29 >=30))))

(defrule random-question-to-determine-which-season
   (start)
   (not (which-season ?season))
   =>
   (set-strategy random)
   (assert (UI-state (display "It is autumn, spring, summer or winter? 🍁🌱🏖❄")
                     (why "Weather conditions influence our perceptions and needs. The choice of a beer is among these.")
                     (relation-asserted which-season)
                     (valid-answers autumn spring summer winter))))

(defrule random-question-to-determine-whether-he-is-a-regular-beer-drinker
   (start)
   (not (regular-beer-drinker ?drinker))
   =>
   (set-strategy random)
   (assert (UI-state (display "Are you a regular beer drinker? 🍺")
                     (why "Better start with more standard beers. On the other hand, you may be surprised!")
                     (relation-asserted regular-beer-drinker)
                     (valid-answers yes no))))

(defrule random-question-to-determine-whether-he-is-going-to-smoke
   (start)
   (not (smoker ?smoker))
   =>
   (set-strategy random)
   (assert (UI-state (display "Are you going to smoke while you drink? 🚬")
   					 (why "Beer may alter the taste of tobacco. Also, stronger beers pair well with tobacco flavor.")
                     (relation-asserted smoker)
                     (valid-answers yes no))))

; depth questions for meal type recognition

(defrule determine-main-meal
   (smoker ?smoker)
   (which-sex ?sex)
   (which-age ?age)
   (which-season ?season)
   (regular-beer-drinker ?drinker)
   =>
   (set-strategy depth)
   (assert (UI-state (display "Is the main meal pizza, entrée, cheese or dessert?")
                     (relation-asserted main-meal)
                     (valid-answers pizza entrée cheese dessert other))))

(defrule determine-pizza-topping
   (main-meal pizza)
   =>
   (assert (UI-state (display "Is the pizza topping classic, meat, vegetables, cheese or other? 🍕🥓🍆🧀")
                     (why (format nil "%s %n%s %n%s %n%s"
                                      (str-cat "🍕 _Classic_ topping pizzas pair well with crisp and clean beers. "
                                               "Complementary grain and cheese flavors balance hop character while "
                                               "remaining light on the palate.")
                                      (str-cat "🍕🥓 _Meat_ topping pizzas pair well with hoppy and bitter beers, which "
                                               "stands up to strong flavors and cut through fat to deliver a complex "
                                               "finish.")
                                      (str-cat "🍕🍆 _Vegetables_ topping pizzas pair well with sour beers which "
                                               "increases the perception of savoriness or with beers which contrasts "
                                               "the char of the oven-roasted vegetables.")
                                      (str-cat "🍕🧀 _Cheese_ topping pizzas pair well with fruity and spicy beers, "
                                               "thanks to their high carbonation which works overtime to cleanse the "
                                               "palate from a strong flavor.")))
                     (relation-asserted pizza-topping)
                     (valid-answers classic meat vegetables cheese other))))

(defrule determine-if-meat-topping-is-spicy
   (pizza-topping meat)
   =>
   (assert (UI-state (display "Is the meat spicy? 🌶")
                     (why (str-cat "Malty flavors highlight the roasted qualities of the meat, while sweetness works to "
                                   "neutralize capsaicin, the active component in chili peppers."))
                     (relation-asserted meat-topping-is-spicy)
                     (valid-answers yes no))))

(defrule determine-if-vegetables-topping-are-roasted
   (pizza-topping vegetables)
   =>
   (assert (UI-state (display "Are the vegetables roasted?")
                     (why "The roasted character of the beer complements the char on oven-roasted vegetables.")
                     (relation-asserted vegetables-topping-are-roasted)
                     (valid-answers yes no))))

(defrule determine-which-entree
   (main-meal entrée)
   =>
   (assert (UI-state (display (str-cat "Is the main component of the entrée grain (farro, arborio, wild rice, polenta, "
                                       "etc.), legumes (lentils, fava, chickpea, green beans, etc.), fish, meat, "
                                       "vegetables, fats or other?"))
                     (why (format nil "%s %n%s %n%s %n%s %n%s %n%s"
                                      "🌾 Complementary _grain_ flavors balance hops while remaining light on the palate."
                                      "🌱 _Legumes_ add richness to the beer while balancing salt and acidity."
                                      (str-cat "🐟🦐 _Fish_ pair well with the bitterness of the English-Style Bitter and "
                                               "the sweetness of the English-Style Pale Ale.")
                                      "🥩🍖 _Meat_ pairs well with Scottish-Style Ales."
                                      "🍆🥦 _Vegetables_ pair well with clean Dark Lagers and American Brown Ale."
                                      "🥜 With _fats_ strong flavors, beer balances and allows for a complex finish."))
                     (relation-asserted which-entrée)
                     (valid-answers grain legumes fish meat vegetables fats other))))

(defrule determine-which-grain
   (which-entrée grain)
   =>
   (assert (UI-state (display "Are the grain chips, spaghetti, bruschetta, grits or other?")
                     (relation-asserted which-grain)
                     (valid-answers chips spaghetti bruschetta grits other))))

(defrule determine-which-fish
   (which-entrée fish)
   =>
   (assert (UI-state (display (str-cat "Is the fish shellfish (clams, scallops, lobster, crab, etc.), bluefish (salmon, "
                                       "trout, tuna, etc.) or other? 🐟🦐🦀🦑"))
                     (relation-asserted which-fish)
                     (valid-answers shellfish bluefish other))))

(defrule determine-which-fish-cooking-method
   (which-fish ?fish)
   =>
   (assert (UI-state (display "Is the fish cooking method grilled or other?")
                     (relation-asserted fish-cooking-method)
                     (valid-answers grilled other))))

(defrule determine-if-shellfish-is-mild
   (which-fish shellfish)
   =>
   (assert (UI-state (display "Is the shellfish mild (squid, cuttlefish, octopus, etc.)? 🐙🦑")
                     (relation-asserted shellfish-is-mild)
                     (valid-answers yes no))))

(defrule determine-which-shellfish
   (shellfish-is-mild no)
   =>
   (assert (UI-state (display "Are the fish shellfish shrimps, mussels, oysters or other? 🦐🦀🐚")
                     (relation-asserted which-shellfish)
                     (valid-answers shrimps mussels oysters other))))

(defrule determine-which-bluefish
   (which-fish bluefish)
   =>
   (assert (UI-state (display "Is the bluefish salmon or other? 🐠🐟")
                     (relation-asserted which-bluefish)
                     (valid-answers salmon other))))

(defrule determine-which-meat
   (which-entrée meat)
   =>
   (assert (UI-state (display "Is the meat rich (beef, lamb, pork, etc.), poultry, game or other? 🍖🥩🦆")
                     (relation-asserted which-meat)
                     (valid-answers rich poultry game other))))

(defrule determine-which-meat-cooking-method
   (which-meat ?meat)
   =>
   (assert (UI-state (display "Is the meat cooking method barbecue, braised, grilled, roasted or other?")
                     (relation-asserted meat-cooking-method)
                     (valid-answers barbecue braised grilled roasted other))))

(defrule determine-which-rich
   (which-meat rich)
   =>
   (assert (UI-state (display "Is the rich meat beef, lamb, pork or other?")
                     (relation-asserted which-rich)
                     (valid-answers beef lamb pork other))))

(defrule determine-which-beef
   (which-rich beef)
   =>
   (assert (UI-state (display "Is the beef bresaola or other?")
                     (relation-asserted which-beef)
                     (valid-answers bresaola other))))

(defrule determine-which-pork
   (which-rich pork)
   =>
   (assert (UI-state (display "Is the pork loin, tenderloin, prosciutto, speck, mortadella, sausage or other?")
                     (relation-asserted which-pork)
                     (valid-answers loin tenderloin prosciutto speck mortadella sausage other))))

(defrule determine-which-sausage
   (which-pork sausage)
   =>
   (assert (UI-state (display "Is the sausage capocollo, soppressata, salame piccante or other?")
                     (relation-asserted which-sausage)
                     (valid-answers capocollo soppressata "salame piccante" other))))

(defrule determine-which-poultry
   (which-meat poultry)
   =>
   (assert (UI-state (display "Is the poultry chicken or turkey? 🦃")
                     (relation-asserted which-poultry)
                     (valid-answers chicken turkey))))

(defrule determine-which-game
   (which-meat game)
   =>
   (assert (UI-state (display "Is the game wild or birds (duck, quail, quinoa, etc.)?")
                     (relation-asserted which-game)
                     (valid-answers wild birds))))

(defrule determine-which-game-birds
   (which-game birds)
   =>
   (assert (UI-state (display "Is the game birds duck or other? 🦆")
                     (relation-asserted which-game-birds)
                     (valid-answers duck other))))

(defrule determine-which-vegetables
   (which-entrée vegetables)
   =>
   (assert (UI-state (display "Is the vegetables root (parsnips, carrots, etc.), salad or other? 🥕🥗")
                     (relation-asserted which-vegetables)
                     (valid-answers root salad other))))

(defrule determine-which-vegetables-cooking-method
   (which-vegetables ?vegetable)
   =>
   (assert (UI-state (display "Is the vegetables cooking method grilled, roasted or other?")
                     (relation-asserted vegetables-cooking-method)
                     (valid-answers grilled roasted other))))

(defrule determine-which-other-vegetables
   (which-vegetables other)
   =>
   (assert (UI-state (display "Are the vegetables mushrooms or other? 🍄")
                     (relation-asserted which-other-vegetables)
                     (valid-answers mushrooms other))))

(defrule determine-which-fats
   (which-entrée fats)
   =>
   (assert (UI-state (display (str-cat "Is the fats vegetable (avocados, olive oil, peanut butter, nuts and seeds, etc.) "
                                       "or animal (duck/pork fat, dairy, etc.) 🥑🍖?"))
                     (why "Carbonation is an effective tool to cleanse vegetable fats.")
                     (relation-asserted which-fats)
                     (valid-answers vegetable animal other))))

(defrule determine-which-cheese-style
   (main-meal cheese)
   =>
   (assert (UI-state (display (str-cat "Is the cheese style fresh (Mascarpone, Ricotta, Chèvre, Feta, Cream Cheese, "
                                       "Quark, Cottage, etc.), semi-soft (Mozzarella, Colby, Fontina, Havarti, Monterey "
                                       "Jack, etc.), firm/hard (Gouda, Cheddar, Swiss, Parmesan, etc.), blue (Roquefort, "
                                       "Gorgonzola, Danish, etc.), natural rind (Brie, Camembert, Triple Crème, "
                                       "Mimolette, Stilton, Lancashire, Tomme de Savoie, etc.) or washed rind (Epoisses, "
                                       "Livarot, Taleggio, etc.)? 🧀"))
                     (help (format nil "%s %n%s %n%s %n%s %n%s %n%s"
                                       (str-cat "🧀 _Fresh_ cheeses have not been aged, or are very slightly cured. "
                                                "These cheeses have a high moisture content and are usually mild and "
                                                "have a very creamy taste and soft texture.")
                                       (str-cat "🧀 _Semi-soft_(www.goo.gl/izu1Bw) cheeses have a smooth, generally, "
                                                "creamy interior with little or no rind. These cheeses are generally "
                                                "high in moisture content and range from very mild in flavor to very "
                                                "pungent.")
                                       (str-cat "🧀 _Firm/hard_(www.goo.gl/yrfoJK) cheeses have a taste profiles range "
                                                "from very mild to sharp and pungent. They generally have a texture "
                                                "profile that ranges from elastic, at room temperature, to the hard "
                                                "cheeses that can be grated.")
                                       (str-cat "🧀 _Blue_(www.goo.gl/9KkNww) cheeses have a distinctive blue/green "
                                                "veining, created when the penicillium roqueforti mold, added during the "
                                                "make process, is exposed to air. This mold provides a distinct flavor "
                                                "to the cheese, which ranges from fairly mild to assertive and pungent.")
                                       (str-cat "🧀 _Natural rind_(www.goo.gl/ys8pkz) cheeses have rinds that are "
                                                "self-formed during the aging process. Generally, no molds or microflora "
                                                "are added, nor is washing used to create the exterior rinds, and those "
                                                "that do exhibit molds and microflora in their rinds get them naturally "
                                                "from the environment.")
                                       (str-cat "🧀 _Washed rind_(www.goo.gl/Kh3BwD) cheeses are surface-ripened by "
                                                "washing the cheese throughout the ripening/aging process with brine, "
                                                "beer, wine, brandy, or a mixture of ingredients, which encourages the "
                                                "growth of bacteria. The exterior rind of washed rind cheeses may vary "
                                                "from bright orange to brown, with flavor and aroma profiles that are "
                                                "quite pungent, yet the interior of these cheeses is most often "
                                                "semi-soft and, sometimes, very creamy.")))
                     (why (format nil "%s %n%s %n%s %n%s %n%s %n%s"
                                      (str-cat "🧀 _Fresh_ cheeses are light cheeses which pair excellently with the "
                                               "softer flavors of Wheat and Lambic beers.")
                                      (str-cat "🧀 _Semi-soft_ cheeses can be paired with many different craft beers, "
                                               "such as German Kölsch or Bock and Pale Ale beers.")
                                      (str-cat "🧀 _Firm/hard_ cheeses are easily paired with an equally broad range of "
                                               "craft beer styles, such as Pilsner, Bock, Brown Ale and Imperial Stout.")
                                      (str-cat "🧀 _Blue_ cheeses are stronger-flavored cheeses which are most "
                                               "successfully balanced with stonger-flavored bolder beers like IPAs or "
                                               "Imperial IPAs.")
                                      (str-cat "🧀 _Natural rind_ cheeses pair well with Golden, Blonde and traditional "
                                               "British-style ales.")
                                      (str-cat "🧀 _Washed rind_ cheeses, while potentially pungent, are often creamy "
                                               "and can be paired with Belgian-styles ales, like Triples and Golden "
                                               "Strong ales with these varieties.")))
                     (relation-asserted which-cheese-style)
                     (valid-answers fresh semi-soft firm/hard blue "natural rind" "washed rind" "don't know"))))

(defrule determine-which-fresh-cheese
   (which-cheese-style fresh)
   =>
   (assert (UI-state (display "Is the fresh cheese Mascarpone, Ricotta, Chèvre, Feta, Cream Cheese or other? 🧀")
                     (why (str-cat "🧀 Italian-Style Mascarpone, Ricotta and soft Chèvre will match the delicate notes "
                                   "of the beer and neither will overwhelm the palate in the beginning of a meal."))
                     (relation-asserted which-fresh-cheese)
                     (valid-answers Mascarpone Ricotta Chèvre Feta "Cream Cheese" other))))

(defrule determine-which-semi-soft-cheese
   (which-cheese-style semi-soft)
   =>
   (assert (UI-state (display "Is the semi-soft cheese Mozzarella, Colby, Havarti, Monterey Jack or other? 🧀")
                     (why (str-cat "🧀 Fontina, Havarti and milder blue cheeses can be enhanced by the carbonation of "
                                   "Kölsch style ales. The gentle notes of grass in the cheese can be brought out by "
                                   "using the malt of a Bock or the hops of a Pale Ale."))
                     (relation-asserted which-semi-soft-cheese)
                     (valid-answers Mozzarella Colby Havarti "Monterey Jack" other))))

(defrule determine-which-firm-hard-cheese
   (which-cheese-style firm/hard)
   =>
   (assert (UI-state (display "Is the firm/hard cheese Gouda, Cheddar, Swiss, Parmesan or other? 🧀")
                     (why (str-cat "🧀 Cheddar and Swiss cheeses can mimic the Maillard reaction when paired with a beer "
                                   "style, such as a Brown Ale. Roasty stouts can add a creaminess to the firm and hard "
                                   "cheeses on the palate."))
                     (relation-asserted which-firm/hard-cheese)
                     (valid-answers Gouda Cheddar Swiss Parmesan other))))

(defrule determine-which-type-of-Gouda
   (which-firm/hard-cheese Gouda)
   =>
   (assert (UI-state (display "Is the Gouda cheese aged, smoked or other? 🧀")
                     (relation-asserted which-type-of-Gouda)
                     (valid-answers aged smoked other))))

(defrule determine-which-color-of-Cheddar
   (which-firm/hard-cheese Cheddar)
   =>
   (assert (UI-state (display "Is the Cheddar cheese white or yellow? 🧀")
                     (relation-asserted which-color-of-Cheddar)
                     (valid-answers white yellow))))

(defrule determine-which-Cheddar-seasoning
   (which-firm/hard-cheese Cheddar)
   =>
   (assert (UI-state (display "Is the Cheddar cheese seasoning mild, medium, aged or other? 🧀")
                     (relation-asserted which-Cheddar-seasoning)
                     (valid-answers mild medium aged other))))

(defrule determine-if-Cheddar-is-sharp
   (or (which-Cheddar-seasoning medium)
       (which-Cheddar-seasoning aged))
   =>
   (assert (UI-state (display "Is the Cheddar cheese sharp? 🧀")
                     (relation-asserted Cheddar-is-sharp)
                     (valid-answers yes no "don't know"))))

(defrule determine-which-type-of-Swiss
   (which-firm/hard-cheese Swiss)
   =>
   (assert (UI-state (display "Is the Swiss cheese Emmental, Gruyère or other? 🧀")
                     (why (str-cat "🧀 Emmentaler-style cheeses can mimic the Maillard reaction when paired with a beer "
                                   "style, such as a Brown Ale."))
                     (relation-asserted which-type-of-Swiss)
                     (valid-answers Emmental Gruyère other))))

(defrule determine-if-Swiss-is-aged
   (which-type-of-Swiss other)
   =>
   (assert (UI-state (display "Is the Swiss aged? 🧀")
                     (relation-asserted Swiss-is-aged)
                     (valid-answers yes no "don't know"))))

(defrule determine-which-blue-cheese
   (which-cheese-style blue)
   =>
   (assert (UI-state (display "Is the blue cheese Stilton or other? 🧀")
                     (why "🧀 Stilton cheese can be intensified the sweetness on the palate with a Barley Wine.")
                     (relation-asserted which-blue-cheese)
                     (valid-answers Stilton other))))

(defrule determine-which-natural-rind-cheese
   (which-cheese-style "natural rind")
   =>
   (assert (UI-state (display (str-cat "Is the natural rind cheese Brie, Camembert, Triple Crème, Mimolette, Stilton, "
                                       "or other? 🧀"))
                     (why (str-cat "🧀 Lancashire, Stilton, Brie and Camembert all share a rich creamy base that can be "
                                   "refreshed with a Golden, Blond or Pale Ale or intensified the sweetness on the "
                                   "palate with a Barley Wine."))
                     (relation-asserted which-natural-rind-cheese)
                     (valid-answers Brie Camembert "Triple Crème" Mimolette Stilton other))))

(defrule determine-which-washed-rind-cheese
   (which-cheese-style "washed rind")
   =>
   (assert (UI-state (display "Is the washed rind cheese Taleggio or other? 🧀")
                     (why (str-cat "🧀 Classic Belgian yeast flavors spur a tighter carbonation as well as bring out "
                                   "delicate sweet notes that can cut through the funk of a washed rind cheeses."))
                     (relation-asserted which-washed-rind-cheese)
                     (valid-answers Taleggio other))))

(defrule determine-which-dessert
   (main-meal dessert)
   =>
   (assert (UI-state (display "Is the dessert creamy, fruit, chocolate or other? 🍮🥧🍪🍫")
                     (relation-asserted which-dessert)
                     (valid-answers creamy fruit chocolate other))))

(defrule determine-if-creamy-dessert-is-fruit
   (which-dessert creamy)
   =>
   (assert (UI-state (display "Is the creamy dessert with fruit?")
                     (relation-asserted creamy-dessert-with-fruit)
                     (valid-answers yes no))))

(defrule determine-which-chocolate-dessert
   (which-dessert chocolate)
   =>
   (assert (UI-state (display (str-cat "Is the chocolate white, milk (35% cacao ca.), semisweet (55% cacao ca.), "
                                       "bittersweet (70% cacao ca.) or unsweetened/bitter (100% cacao)? 🍫"))
                     (relation-asserted which-chocolate)
                     (valid-answers white milk semisweet bittersweet unsweetened/bitter "don't know"))))

;;***********************
;;* BEER QUESTION RULES *
;;***********************

; random questions for user type and scenario recognition

(defrule random-question-to-determine-which-sex
   (start)
   (not (which-sex ?sex))
   =>
   (set-strategy random)
   (assert (UI-state (display "Are you male or female? 👨🏻👩🏻")
                     (why "Male or female persons tend to prefer more or less intense beers.")
                     (relation-asserted which-sex)
                     (valid-answers male female))))

(defrule random-question-to-determine-which-age
   (start)
   (not (which-age ?age))
   =>
   (set-strategy random)
   (assert (UI-state (display "How old are you? 🔞")
                     (why "Younger people tend to prefer less intense beers.")
                     (relation-asserted which-age)
                     (valid-answers 18-23 24-29 >=30))))

(defrule random-question-to-determine-which-season
   (start)
   (not (which-season ?season))
   =>
   (set-strategy random)
   (assert (UI-state (display "It is autumn, spring, summer or winter? 🍁🌱🏖❄")
                     (why "Weather conditions influence our perceptions and needs. The choice of a beer is among these.")
                     (relation-asserted which-season)
                     (valid-answers autumn spring summer winter))))

(defrule random-question-to-determine-whether-he-is-a-regular-beer-drinker
   (start)
   (not (regular-beer-drinker ?drinker))
   =>
   (set-strategy random)
   (assert (UI-state (display "Are you a regular beer drinker? 🍺")
                     (why "Better start with more standard beers. On the other hand, you may be surprised!")
                     (relation-asserted regular-beer-drinker)
                     (valid-answers yes no))))

(defrule random-question-to-determine-whether-he-is-going-to-smoke
   (start)
   (not (smoker ?smoker))
   =>
   (set-strategy random)
   (assert (UI-state (display "Are you going to smoke while you drink? 🚬")
   					 (why "Beer may alter the taste of tobacco. Also, stronger beers pair well with tobacco flavor.")
                     (relation-asserted smoker)
                     (valid-answers yes no))))

; depth questions for meal type recognition

(defrule determine-main-meal
   (smoker ?smoker)
   (which-sex ?sex)
   (which-age ?age)
   (which-season ?season)
   (regular-beer-drinker ?drinker)
   =>
   (set-strategy depth)
   (assert (UI-state (display "Is the main meal pizza, entrée, cheese or dessert?")
                     (relation-asserted main-meal)
                     (valid-answers pizza entrée cheese dessert other))))

(defrule determine-pizza-topping
   (main-meal pizza)
   =>
   (assert (UI-state (display "Is the pizza topping classic, meat, vegetables, cheese or other? 🍕🥓🍆🧀")
                     (why (format nil "%s %n%s %n%s %n%s"
                                      (str-cat "🍕 _Classic_ topping pizzas pair well with crisp and clean beers. "
                                               "Complementary grain and cheese flavors balance hop character while "
                                               "remaining light on the palate.")
                                      (str-cat "🍕🥓 _Meat_ topping pizzas pair well with hoppy and bitter beers, which "
                                               "stands up to strong flavors and cut through fat to deliver a complex "
                                               "finish.")
                                      (str-cat "🍕🍆 _Vegetables_ topping pizzas pair well with sour beers which "
                                               "increases the perception of savoriness or with beers which contrasts "
                                               "the char of the oven-roasted vegetables.")
                                      (str-cat "🍕🧀 _Cheese_ topping pizzas pair well with fruity and spicy beers, "
                                               "thanks to their high carbonation which works overtime to cleanse the "
                                               "palate from a strong flavor.")))
                     (relation-asserted pizza-topping)
                     (valid-answers classic meat vegetables cheese other))))

(defrule determine-if-meat-topping-is-spicy
   (pizza-topping meat)
   =>
   (assert (UI-state (display "Is the meat spicy? 🌶")
                     (why (str-cat "Malty flavors highlight the roasted qualities of the meat, while sweetness works to "
                                   "neutralize capsaicin, the active component in chili peppers."))
                     (relation-asserted meat-topping-is-spicy)
                     (valid-answers yes no))))

(defrule determine-if-vegetables-topping-are-roasted
   (pizza-topping vegetables)
   =>
   (assert (UI-state (display "Are the vegetables roasted?")
                     (why "The roasted character of the beer complements the char on oven-roasted vegetables.")
                     (relation-asserted vegetables-topping-are-roasted)
                     (valid-answers yes no))))

(defrule determine-which-entree
   (main-meal entrée)
   =>
   (assert (UI-state (display (str-cat "Is the main component of the entrée grain (farro, arborio, wild rice, polenta, "
                                       "etc.), legumes (lentils, fava, chickpea, green beans, etc.), fish, meat, "
                                       "vegetables, fats or other?"))
                     (why (format nil "%s %n%s %n%s %n%s %n%s %n%s"
                                      "🌾 Complementary _grain_ flavors balance hops while remaining light on the palate."
                                      "🌱 _Legumes_ add richness to the beer while balancing salt and acidity."
                                      (str-cat "🐟🦐 _Fish_ pair well with the bitterness of the English-Style Bitter and "
                                               "the sweetness of the English-Style Pale Ale.")
                                      "🥩🍖 _Meat_ pairs well with Scottish-Style Ales."
                                      "🍆🥦 _Vegetables_ pair well with clean Dark Lagers and American Brown Ale."
                                      "🥜 With _fats_ strong flavors, beer balances and allows for a complex finish."))
                     (relation-asserted which-entrée)
                     (valid-answers grain legumes fish meat vegetables fats other))))

(defrule determine-which-grain
   (which-entrée grain)
   =>
   (assert (UI-state (display "Are the grain chips, spaghetti, bruschetta, grits or other?")
                     (relation-asserted which-grain)
                     (valid-answers chips spaghetti bruschetta grits other))))

(defrule determine-which-fish-cooking-method
   (which-entrée fish)
   =>
   (assert (UI-state (display "Is the fish cooking method grilled or other?")
                     (relation-asserted fish-cooking-method)
                     (valid-answers grilled other))))

(defrule determine-which-fish
   (which-entrée fish)
   =>
   (assert (UI-state (display (str-cat "Is the fish shellfish (clams, scallops, lobster, crab, etc.), bluefish (salmon, "
                                       "trout, tuna, etc.) or other? 🐟🦐🦀🦑"))
                     (relation-asserted which-fish)
                     (valid-answers shellfish bluefish other))))

(defrule determine-if-shellfish-is-mild
   (which-fish shellfish)
   =>
   (assert (UI-state (display "Is the shellfish mild (squid, cuttlefish, octopus, etc.)? 🐙🦑")
                     (relation-asserted shellfish-is-mild)
                     (valid-answers yes no))))

(defrule determine-which-shellfish
   (shellfish-is-mild no)
   =>
   (assert (UI-state (display "Are the fish shellfish shrimps, mussels, oysters or other? 🦐🦀🐚")
                     (relation-asserted which-shellfish)
                     (valid-answers shrimps mussels oysters other))))

(defrule determine-which-bluefish
   (which-fish bluefish)
   =>
   (assert (UI-state (display "Is the bluefish salmon or other? 🐠🐟")
                     (relation-asserted which-bluefish)
                     (valid-answers salmon other))))

(defrule determine-which-meat-cooking-method
   (which-entrée meat)
   =>
   (assert (UI-state (display "Is the meat cooking method barbecue, braised, grilled, roasted or other?")
                     (relation-asserted meat-cooking-method)
                     (valid-answers barbecue braised grilled roasted other))))

(defrule determine-which-meat
   (which-entrée meat)
   =>
   (assert (UI-state (display "Is the meat rich (beef, lamb, pork, etc.), poultry, game or other? 🍖🥩🦆")
                     (relation-asserted which-meat)
                     (valid-answers rich poultry game other))))

(defrule determine-which-rich
   (which-meat rich)
   =>
   (assert (UI-state (display "Is the rich meat beef, lamb, pork or other?")
                     (relation-asserted which-rich)
                     (valid-answers beef lamb pork other))))

(defrule determine-which-beef
   (which-rich beef)
   =>
   (assert (UI-state (display "Is the beef bresaola or other?")
                     (relation-asserted which-beef)
                     (valid-answers bresaola other))))

(defrule determine-which-pork
   (which-rich pork)
   =>
   (assert (UI-state (display "Is the pork loin, tenderloin, prosciutto, speck, mortadella, sausage or other?")
                     (relation-asserted which-pork)
                     (valid-answers loin tenderloin prosciutto speck mortadella sausage other))))

(defrule determine-which-sausage
   (which-pork sausage)
   =>
   (assert (UI-state (display "Is the sausage capocollo, soppressata, salame piccante or other?")
                     (relation-asserted which-sausage)
                     (valid-answers capocollo soppressata "salame piccante" other))))

(defrule determine-which-poultry
   (which-meat poultry)
   =>
   (assert (UI-state (display "Is the poultry chicken or turkey? 🦃")
                     (relation-asserted which-poultry)
                     (valid-answers chicken turkey))))

(defrule determine-which-game
   (which-meat game)
   =>
   (assert (UI-state (display "Is the game wild or birds (duck, quail, quinoa, etc.)?")
                     (relation-asserted which-game)
                     (valid-answers wild birds))))

(defrule determine-which-game-birds
   (which-game birds)
   =>
   (assert (UI-state (display "Is the game birds duck or other? 🦆")
                     (relation-asserted which-game-birds)
                     (valid-answers duck other))))

(defrule determine-which-vegetables-cooking-method
   (which-entrée vegetables)
   =>
   (assert (UI-state (display "Is the vegetables cooking method grilled, roasted or other?")
                     (relation-asserted vegetables-cooking-method)
                     (valid-answers grilled roasted other))))

(defrule determine-which-vegetables
   (which-entrée vegetables)
   =>
   (assert (UI-state (display "Is the vegetables root (parsnips, carrots, etc.), salad or other? 🥕🥗")
                     (relation-asserted which-vegetables)
                     (valid-answers root salad other))))

(defrule determine-which-other-vegetables
   (which-vegetables other)
   =>
   (assert (UI-state (display "Are the vegetables mushrooms or other? 🍄")
                     (relation-asserted which-other-vegetables)
                     (valid-answers mushrooms other))))

(defrule determine-which-fats
   (which-entrée fats)
   =>
   (assert (UI-state (display (str-cat "Is the fats vegetable (avocados, olive oil, peanut butter, nuts and seeds, etc.) "
                                       "or animal (duck/pork fat, dairy, etc.) 🥑🍖?"))
                     (why "Carbonation is an effective tool to cleanse vegetable fats.")
                     (relation-asserted which-fats)
                     (valid-answers vegetable animal other))))

(defrule determine-which-cheese-style
   (main-meal cheese)
   =>
   (assert (UI-state (display (str-cat "Is the cheese style fresh (Mascarpone, Ricotta, Chèvre, Feta, Cream Cheese, "
                                       "Quark, Cottage, etc.), semi-soft (Mozzarella, Colby, Fontina, Havarti, Monterey "
                                       "Jack, etc.), firm/hard (Gouda, Cheddar, Swiss, Parmesan, etc.), blue (Roquefort, "
                                       "Gorgonzola, Danish, etc.), natural rind (Brie, Camembert, Triple Crème, "
                                       "Mimolette, Stilton, Lancashire, Tomme de Savoie, etc.) or washed rind (Epoisses, "
                                       "Livarot, Taleggio, etc.)? 🧀"))
                     (help (format nil "%s %n%s %n%s %n%s %n%s %n%s"
                                       (str-cat "🧀 _Fresh_ cheeses have not been aged, or are very slightly cured. "
                                                "These cheeses have a high moisture content and are usually mild and "
                                                "have a very creamy taste and soft texture.")
                                       (str-cat "🧀 _Semi-soft_(www.goo.gl/izu1Bw) cheeses have a smooth, generally, "
                                                "creamy interior with little or no rind. These cheeses are generally "
                                                "high in moisture content and range from very mild in flavor to very "
                                                "pungent.")
                                       (str-cat "🧀 _Firm/hard_(www.goo.gl/yrfoJK) cheeses have a taste profiles range "
                                                "from very mild to sharp and pungent. They generally have a texture "
                                                "profile that ranges from elastic, at room temperature, to the hard "
                                                "cheeses that can be grated.")
                                       (str-cat "🧀 _Blue_(www.goo.gl/9KkNww) cheeses have a distinctive blue/green "
                                                "veining, created when the penicillium roqueforti mold, added during the "
                                                "make process, is exposed to air. This mold provides a distinct flavor "
                                                "to the cheese, which ranges from fairly mild to assertive and pungent.")
                                       (str-cat "🧀 _Natural rind_(www.goo.gl/ys8pkz) cheeses have rinds that are "
                                                "self-formed during the aging process. Generally, no molds or microflora "
                                                "are added, nor is washing used to create the exterior rinds, and those "
                                                "that do exhibit molds and microflora in their rinds get them naturally "
                                                "from the environment.")
                                       (str-cat "🧀 _Washed rind_(www.goo.gl/Kh3BwD) cheeses are surface-ripened by "
                                                "washing the cheese throughout the ripening/aging process with brine, "
                                                "beer, wine, brandy, or a mixture of ingredients, which encourages the "
                                                "growth of bacteria. The exterior rind of washed rind cheeses may vary "
                                                "from bright orange to brown, with flavor and aroma profiles that are "
                                                "quite pungent, yet the interior of these cheeses is most often "
                                                "semi-soft and, sometimes, very creamy.")))
                     (why (format nil "%s %n%s %n%s %n%s %n%s %n%s"
                                      (str-cat "🧀 _Fresh_ cheeses are light cheeses which pair excellently with the "
                                               "softer flavors of Wheat and Lambic beers.")
                                      (str-cat "🧀 _Semi-soft_ cheeses can be paired with many different craft beers, "
                                               "such as German Kölsch or Bock and Pale Ale beers.")
                                      (str-cat "🧀 _Firm/hard_ cheeses are easily paired with an equally broad range of "
                                               "craft beer styles, such as Pilsner, Bock, Brown Ale and Imperial Stout.")
                                      (str-cat "🧀 _Blue_ cheeses are stronger-flavored cheeses which are most "
                                               "successfully balanced with stonger-flavored bolder beers like IPAs or "
                                               "Imperial IPAs.")
                                      (str-cat "🧀 _Natural rind_ cheeses pair well with Golden, Blonde and traditional "
                                               "British-style ales.")
                                      (str-cat "🧀 _Washed rind_ cheeses, while potentially pungent, are often creamy "
                                               "and can be paired with Belgian-styles ales, like Triples and Golden "
                                               "Strong ales with these varieties.")))
                     (relation-asserted which-cheese-style)
                     (valid-answers fresh semi-soft firm/hard blue "natural rind" "washed rind" "don't know"))))

(defrule determine-which-fresh-cheese
   (which-cheese-style fresh)
   =>
   (assert (UI-state (display "Is the fresh cheese Mascarpone, Ricotta, Chèvre, Feta, Cream Cheese or other? 🧀")
                     (why (str-cat "🧀 Italian-Style Mascarpone, Ricotta and soft Chèvre will match the delicate notes "
                                   "of the beer and neither will overwhelm the palate in the beginning of a meal."))
                     (relation-asserted which-fresh-cheese)
                     (valid-answers Mascarpone Ricotta Chèvre Feta "Cream Cheese" other))))

(defrule determine-which-semi-soft-cheese
   (which-cheese-style semi-soft)
   =>
   (assert (UI-state (display "Is the semi-soft cheese Mozzarella, Colby, Havarti, Monterey Jack or other? 🧀")
                     (why (str-cat "🧀 Fontina, Havarti and milder blue cheeses can be enhanced by the carbonation of "
                                   "Kölsch style ales. The gentle notes of grass in the cheese can be brought out by "
                                   "using the malt of a Bock or the hops of a Pale Ale."))
                     (relation-asserted which-semi-soft-cheese)
                     (valid-answers Mozzarella Colby Havarti "Monterey Jack" other))))

(defrule determine-which-firm-hard-cheese
   (which-cheese-style firm/hard)
   =>
   (assert (UI-state (display "Is the firm/hard cheese Gouda, Cheddar, Swiss, Parmesan or other? 🧀")
                     (why (str-cat "🧀 Cheddar and Swiss cheeses can mimic the Maillard reaction when paired with a beer "
                                   "style, such as a Brown Ale. Roasty stouts can add a creaminess to the firm and hard "
                                   "cheeses on the palate."))
                     (relation-asserted which-firm/hard-cheese)
                     (valid-answers Gouda Cheddar Swiss Parmesan other))))

(defrule determine-which-type-of-Gouda
   (which-firm/hard-cheese Gouda)
   =>
   (assert (UI-state (display "Is the Gouda cheese aged, smoked or other? 🧀")
                     (relation-asserted which-type-of-Gouda)
                     (valid-answers aged smoked other))))

(defrule determine-which-color-of-Cheddar
   (which-firm/hard-cheese Cheddar)
   =>
   (assert (UI-state (display "Is the Cheddar cheese white or yellow? 🧀")
                     (relation-asserted which-color-of-Cheddar)
                     (valid-answers white yellow))))

(defrule determine-which-Cheddar-seasoning
   (which-firm/hard-cheese Cheddar)
   =>
   (assert (UI-state (display "Is the Cheddar cheese seasoning mild, medium, aged or other? 🧀")
                     (relation-asserted which-Cheddar-seasoning)
                     (valid-answers mild medium aged other))))

(defrule determine-if-Cheddar-is-sharp
   (or (which-Cheddar-seasoning medium)
       (which-Cheddar-seasoning aged))
   =>
   (assert (UI-state (display "Is the Cheddar cheese sharp? 🧀")
                     (relation-asserted Cheddar-is-sharp)
                     (valid-answers yes no "don't know"))))

(defrule determine-which-type-of-Swiss
   (which-firm/hard-cheese Swiss)
   =>
   (assert (UI-state (display "Is the Swiss cheese Emmental, Gruyère or other? 🧀")
                     (why (str-cat "🧀 Emmentaler-style cheeses can mimic the Maillard reaction when paired with a beer "
                                   "style, such as a Brown Ale."))
                     (relation-asserted which-type-of-Swiss)
                     (valid-answers Emmental Gruyère other))))

(defrule determine-if-Swiss-is-aged
   (which-type-of-Swiss other)
   =>
   (assert (UI-state (display "Is the Swiss aged? 🧀")
                     (relation-asserted Swiss-is-aged)
                     (valid-answers yes no "don't know"))))

(defrule determine-which-blue-cheese
   (which-cheese-style blue)
   =>
   (assert (UI-state (display "Is the blue cheese Stilton or other? 🧀")
                     (why "🧀 Stilton cheese can be intensified the sweetness on the palate with a Barley Wine.")
                     (relation-asserted which-blue-cheese)
                     (valid-answers Stilton other))))

(defrule determine-which-natural-rind-cheese
   (which-cheese-style "natural rind")
   =>
   (assert (UI-state (display (str-cat "Is the natural rind cheese Brie, Camembert, Triple Crème, Mimolette, Stilton, "
                                       "or other? 🧀"))
                     (why (str-cat "🧀 Lancashire, Stilton, Brie and Camembert all share a rich creamy base that can be "
                                   "refreshed with a Golden, Blond or Pale Ale or intensified the sweetness on the "
                                   "palate with a Barley Wine."))
                     (relation-asserted which-natural-rind-cheese)
                     (valid-answers Brie Camembert "Triple Crème" Mimolette Stilton other))))

(defrule determine-which-washed-rind-cheese
   (which-cheese-style "washed rind")
   =>
   (assert (UI-state (display "Is the washed rind cheese Taleggio or other? 🧀")
                     (why (str-cat "🧀 Classic Belgian yeast flavors spur a tighter carbonation as well as bring out "
                                   "delicate sweet notes that can cut through the funk of a washed rind cheeses."))
                     (relation-asserted which-washed-rind-cheese)
                     (valid-answers Taleggio other))))

(defrule determine-which-dessert
   (main-meal dessert)
   =>
   (assert (UI-state (display "Is the dessert creamy, fruit, chocolate or other? 🍮🥧🍪🍫")
                     (relation-asserted which-dessert)
                     (valid-answers creamy fruit chocolate other))))

(defrule determine-if-creamy-dessert-is-fruit
   (which-dessert creamy)
   =>
   (assert (UI-state (display "Is the creamy dessert with fruit?")
                     (relation-asserted creamy-dessert-with-fruit)
                     (valid-answers yes no))))

(defrule determine-which-chocolate-dessert
   (which-dessert chocolate)
   =>
   (assert (UI-state (display (str-cat "Is the chocolate white, milk (35% cacao ca.), semisweet (55% cacao ca.), "
                                       "bittersweet (70% cacao ca.) or unsweetened/bitter (100% cacao)? 🍫"))
                     (relation-asserted which-chocolate)
                     (valid-answers white milk semisweet bittersweet unsweetened/bitter "don't know"))))


Start second chapter for this

Start second chapter for this

// First task
(deffacts students
         (student LelyakinMA 4)
         (student ArutunyaAS 4)
         (student KefalicsAI 1)
         (student BelokobylskySA 2)
)

(facts)

(retract 2)
(retract 3)

(assert (student KefalicsAI 2))

(facts)

error: pathspec 'ssu-ai-level-2/chapter-2.clp' did not match any file(s) known to git


Added the target-symbol-is-special function.

This function automates the process of defining symbol splitting due to the
fact that the body of each rule assigned to symbol splitting is the same except
for the target symbol. By adding this function I make it easier to maintain the
code as I add new features. It also doesn't matter if I construct a binary
image of the expert system because the rules will have already been defined.

The only downside is that batch* must be used instead of load*. While this may
seem like an issue, it really isn't.

;------------------------------------------------------------------------------
;Copyright (c) 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 Joshua Scoggins 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.
;------------------------------------------------------------------------------
; GLCommonConversionRules.clp - Common rules that multiple expert systems use
; to do different kinds of conversion
;
; Written by Joshua Scoggins
;------------------------------------------------------------------------------
; INPUT FACT FORM: (parse constant file ?path)
;------------------------------------------------------------------------------
(deffunction types::get-input-form-factor ()
             (printout t "(parse constant file ?path)" crlf))
;------------------------------------------------------------------------------
(defrule MAIN::open-target-file
         "This rule takes a fact of the above INPUT FORM and attempts to open the file"
         ?fct <- (parse constant file ?path)
         =>
         (bind ?name (gensym*))
         (retract ?fct)
         (if (open ?path ?name "r") then
           (make-instance of opened-file
                          (file-id ?name)
                          (index 0))
           (assert (message (to identify-lines)
                            (action read-file)
                            (arguments ?name)))
           (focus read-input
                  modify-input
                  identify-lines
                  convert-templates
                  build-groups
                  grouping-update)
           else
           (printout t "ERROR: target file at " ?path " does not exist!" crlf
                     "Halting!" crlf)
           (halt)))
;------------------------------------------------------------------------------
(defrule read-input::build-file-line
         ?fct <- (message (to identify-lines)
                          (action read-file)
                          (arguments ?name))
         ?obj <- (object (is-a opened-file)
                         (file-id ?fid))
         =>
         (retract ?fct)
         (bind ?result (send ?obj read-line))
         (if (neq ?result EOF) then
           (duplicate ?fct)
           (if (neq ?result "") then
             (make-instance of file-line (index (send ?obj next-index))
                            (type UNKNOWN)
                            (parent ?fid)
                            (contents (explode$ ?result))))
           else
           (send ?obj close-file)
           (unmake-instance ?obj)))
;------------------------------------------------------------------------------
(deffunction modify-input::blank-on-empty-string (?str)
             (if (> (str-length ?str) 0) then ?str else (create$)))
;------------------------------------------------------------------------------
(deffunction modify-input::break-apart (?sp ?i)
             (bind ?str (if (stringp ?i) then ?i else (str-cat ?i)))
             (bind ?ind (str-index ?sp ?str))
             (bind ?p0 (sub-string 1 (- ?ind 1) ?str))
             (bind ?p1 (sub-string (+ ?ind 1) (str-length ?str) ?str))
             (create$ (blank-on-empty-string ?p0) ?sp
                      (blank-on-empty-string ?p1)))
;------------------------------------------------------------------------------
(deffunction modify-input::input-is-not-split-symbol (?sp ?input)
             (bind ?str (str-cat ?input))
             (and (neq 0 (str-compare ?str ?sp))
                  (str-index ?sp ?str)))
;------------------------------------------------------------------------------
(deffunction types::target-symbol-is-special (?symbol ?name ?docString)
             (build (format nil "(defrule modify-input::%s \"%s\"
?fct <- (object (is-a file-line) (contents $?b ?s $?a))
(test (input-is-not-split-symbol \"%s\" ?s))
=>
(modify-instance ?fct (contents $?b (break-apart \"%s\" ?s) $?a)))"
                     ?name ?docString ?symbol ?symbol)))
;------------------------------------------------------------------------------
;(defrule modify-input::identify-symbols-with-commas
;         ?fct <- (object (is-a file-line)
;                         (contents $?before ?symbol $?after))
;         (test (input-is-not-split-symbol "," ?symbol))
;         =>
;         (modify-instance ?fct (contents $?before (break-apart "," ?symbol)
;                                         $?after)))
(target-symbol-is-special "," identify-symbols-with-commas "")
;------------------------------------------------------------------------------
;(defrule modify-input::identify-symbols-with-open-parens
;         ?fct <- (object (is-a file-line)
;                         (contents $?b ?s $?a))
;         (test (input-is-not-split-symbol "(" ?s))
;         =>
;         (modify-instance ?fct (contents $?b (break-apart "(" ?s) $?a)))
(target-symbol-is-special "(" identify-symbols-with-open-parens "")
;------------------------------------------------------------------------------
;(defrule modify-input::identify-symbols-with-close-parens
;         ?fct <- (object (is-a file-line)
;                         (contents $?before ?symbol $?after))
;         (test (input-is-not-split-symbol ")" ?symbol))
;         =>
;         (modify-instance ?fct (contents $?before (break-apart ")" ?symbol)
;                                         $?after)))
(target-symbol-is-special ")" identify-symbols-with-close-parens "")
;------------------------------------------------------------------------------
(defrule identify-lines::mark-heading-groups
         "Tags lines that consist of /* $? */ as group headings"
         ?f <- (object (is-a file-line)
                       (type UNKNOWN)
                       (contents /* $? */))
         =>
         (modify-instance ?f (type heading)))
;------------------------------------------------------------------------------
(defrule identify-lines::mark-entry-line
         "Tags lines that are defines and modifies the associated contents"
         ?f <- (object (is-a file-line)
                       (type UNKNOWN)
                       (contents #define ?name ?))
         =>
         (modify-instance ?f (type #define)
                          (contents ?name)))
;------------------------------------------------------------------------------
(defrule identify-lines::merge-three-line-headers
         "Merges simple three line headings into one rule"
         ?f0 <- (object (is-a file-line)
                        (index ?i)
                        (type UNKNOWN)
                        (contents /*))
         ?f1 <- (object (is-a file-line)
                        (index ?i2&:(= ?i2 (+ ?i 1)))
                        (type UNKNOWN)
                        (contents * $?c))
         ?f2 <- (object (is-a file-line)
                        (index ?i3&:(= ?i3 (+ ?i 2)))
                        (type UNKNOWN)
                        (contents */))
         =>
         (unmake-instance ?f1 ?f2)
         (modify-instance ?f0 (contents /* $?c */)))
;------------------------------------------------------------------------------
(defrule identify-lines::mark-glapi-calls
         "marks glapi calls"
         ?f <- (object (is-a file-line)
                       (type UNKNOWN)
                       (contents GLAPI $? "(" $? ")"))
         =>
         (modify-instance ?f (type GLAPI-DEF)))
;------------------------------------------------------------------------------
(defrule identify-lines::merge-potential-glapi-calls
         "Merges the next line of a GLAPI call if the line doesn't end with )"
         (declare (salience -1))
         ?f <- (object (is-a file-line)
                       (type UNKNOWN)
                       (contents GLAPI $?vals "(" $?c)
                       (index ?i))
         (test (not (member$ ")" $?c)))
         ?f0 <- (object (is-a file-line)
                        (index ?i0&:(= ?i0 (+ ?i 1)))
                        (type UNKNOWN)
                        (contents $?contents))
         =>
         (unmake-instance ?f)
         (modify-instance ?f0 (contents GLAPI $?vals "(" $?c $?contents)))
;------------------------------------------------------------------------------
(defrule identify-lines::define-header-spans-initial
         "Defines spans between headers"
         (declare (salience -3))
         (object (is-a file-line)
                 (type heading)
                 (parent ?parent)
                 (index ?i)
                 (contents /* $?name */))
         (not (exists (object (is-a heading-span)
                              (from ?i)
                              (parent ?parent))))
         (object (is-a file-line)
                 (type heading)
                 (parent ?parent)
                 (index ?i2&:(> ?i2 ?i)))
         =>
         (if (> (- ?i2 ?i) 0) then
           (make-instance of heading-span
                          (header-name (implode$ $?name))
                          (from ?i)
                          (to ?i2)
                          (parent ?parent))))
;------------------------------------------------------------------------------
(defrule identify-lines::modify-header-spans-for-smaller-size
         "Retracts the heading-span in response to finding an earlier heading"
         ?f <- (object (is-a heading-span)
                       (from ?i)
                       (to ?j)
                       (parent ?parent))
         (object (is-a file-line)
                 (type heading)
                 (parent ?parent)
                 (index ?i2&:(> ?j ?i2 ?i)))
         =>
         (modify-instance ?f (to ?i2)))
;------------------------------------------------------------------------------
(defrule convert-templates::retract-unknowns
         ?f <- (object (is-a file-line)
                       (type UNKNOWN))
         =>
         (unmake-instance ?f))
;------------------------------------------------------------------------------
(defrule convert-templates::assert-build-groups
         ?f <- (object (is-a file-line)
                       (type ~UNKNOWN)
                       (id ?id))
         =>
         (assert (message (to build-groups)
                          (action add-to-span)
                          (arguments ?id))))
;------------------------------------------------------------------------------

;------------------------------------------------------------------------------
;Copyright (c) 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 Joshua Scoggins 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.
;------------------------------------------------------------------------------
; GLCommonConversionRules.clp - Common rules that multiple expert systems use
; to do different kinds of conversion
;
; Written by Joshua Scoggins
;------------------------------------------------------------------------------
; INPUT FACT FORM: (parse constant file ?path)
;------------------------------------------------------------------------------
(deffunction types::get-input-form-factor ()
             (printout t "(parse constant file ?path)" crlf))
;------------------------------------------------------------------------------
(defrule MAIN::open-target-file
         "This rule takes a fact of the above INPUT FORM and attempts to open the file"
         ?fct <- (parse constant file ?path)
         =>
         (bind ?name (gensym*))
         (retract ?fct)
         (if (open ?path ?name "r") then
           (make-instance of opened-file
                          (file-id ?name)
                          (index 0))
           (assert (message (to identify-lines)
                            (action read-file)
                            (arguments ?name)))
           (focus read-input
                  modify-input
                  identify-lines
                  convert-templates
                  build-groups
                  grouping-update)
           else
           (printout t "ERROR: target file at " ?path " does not exist!" crlf
                     "Halting!" crlf)
           (halt)))
;------------------------------------------------------------------------------
(defrule read-input::build-file-line
         ?fct <- (message (to identify-lines)
                          (action read-file)
                          (arguments ?name))
         ?obj <- (object (is-a opened-file)
                         (file-id ?fid))
         =>
         (retract ?fct)
         (bind ?result (send ?obj read-line))
         (if (neq ?result EOF) then
           (duplicate ?fct)
           (if (neq ?result "") then
             (make-instance of file-line (index (send ?obj next-index))
                            (type UNKNOWN)
                            (parent ?fid)
                            (contents (explode$ ?result))))
           else
           (send ?obj close-file)
           (unmake-instance ?obj)))
;------------------------------------------------------------------------------
(deffunction modify-input::blank-on-empty-string (?str)
             (if (> (str-length ?str) 0) then ?str else (create$)))
;------------------------------------------------------------------------------
(deffunction modify-input::break-apart (?sp ?i)
             (bind ?str (if (stringp ?i) then ?i else (str-cat ?i)))
             (bind ?ind (str-index ?sp ?str))
             (bind ?p0 (sub-string 1 (- ?ind 1) ?str))
             (bind ?p1 (sub-string (+ ?ind 1) (str-length ?str) ?str))
             (create$ (blank-on-empty-string ?p0) ?sp
                      (blank-on-empty-string ?p1)))
;------------------------------------------------------------------------------
(deffunction modify-input::input-is-not-split-symbol (?sp ?input)
             (bind ?str (str-cat ?input))
             (and (neq 0 (str-compare ?str ?sp))
                  (str-index ?sp ?str)))
;------------------------------------------------------------------------------
(defrule modify-input::identify-symbols-with-commas
         ?fct <- (object (is-a file-line)
                         (contents $?before ?symbol $?after))
         (test (input-is-not-split-symbol "," ?symbol))
         =>
         (modify-instance ?fct (contents $?before (break-apart "," ?symbol)
                                         $?after)))
;------------------------------------------------------------------------------
(defrule modify-input::identify-symbols-with-open-parens
         ?fct <- (object (is-a file-line)
                         (contents $?b ?s $?a))
         (test (input-is-not-split-symbol "(" ?s))
         =>
         (modify-instance ?fct (contents $?b (break-apart "(" ?s) $?a)))
;------------------------------------------------------------------------------
(defrule modify-input::identify-symbols-with-close-parens
         ?fct <- (object (is-a file-line)
                         (contents $?before ?symbol $?after))
         (test (input-is-not-split-symbol ")" ?symbol))
         =>
         (modify-instance ?fct (contents $?before (break-apart ")" ?symbol)
                                         $?after)))
;------------------------------------------------------------------------------
(defrule identify-lines::mark-heading-groups
         "Tags lines that consist of /* $? */ as group headings"
         ?f <- (object (is-a file-line)
                       (type UNKNOWN)
                       (contents /* $? */))
         =>
         (modify-instance ?f (type heading)))
;------------------------------------------------------------------------------
(defrule identify-lines::mark-entry-line
         "Tags lines that are defines and modifies the associated contents"
         ?f <- (object (is-a file-line)
                       (type UNKNOWN)
                       (contents #define ?name ?))
         =>
         (modify-instance ?f (type #define)
                          (contents ?name)))
;------------------------------------------------------------------------------
(defrule identify-lines::merge-three-line-headers
         "Merges simple three line headings into one rule"
         ?f0 <- (object (is-a file-line)
                        (index ?i)
                        (type UNKNOWN)
                        (contents /*))
         ?f1 <- (object (is-a file-line)
                        (index ?i2&:(= ?i2 (+ ?i 1)))
                        (type UNKNOWN)
                        (contents * $?c))
         ?f2 <- (object (is-a file-line)
                        (index ?i3&:(= ?i3 (+ ?i 2)))
                        (type UNKNOWN)
                        (contents */))
         =>
         (unmake-instance ?f1 ?f2)
         (modify-instance ?f0 (contents /* $?c */)))
;------------------------------------------------------------------------------
(defrule identify-lines::mark-glapi-calls
         "marks glapi calls"
         ?f <- (object (is-a file-line)
                       (type UNKNOWN)
                       (contents GLAPI $? "(" $? ")"))
         =>
         (modify-instance ?f (type GLAPI-DEF)))
;------------------------------------------------------------------------------
(defrule identify-lines::merge-potential-glapi-calls
         "Merges the next line of a GLAPI call if the line doesn't end with )"
         (declare (salience -1))
         ?f <- (object (is-a file-line)
                       (type UNKNOWN)
                       (contents GLAPI $?vals "(" $?c)
                       (index ?i))
         (test (not (member$ ")" $?c)))
         ?f0 <- (object (is-a file-line)
                        (index ?i0&:(= ?i0 (+ ?i 1)))
                        (type UNKNOWN)
                        (contents $?contents))
         =>
         (unmake-instance ?f)
         (modify-instance ?f0 (contents GLAPI $?vals "(" $?c $?contents)))
;------------------------------------------------------------------------------
(defrule identify-lines::define-header-spans-initial
         "Defines spans between headers"
         (declare (salience -3))
         (object (is-a file-line)
                 (type heading)
                 (parent ?parent)
                 (index ?i)
                 (contents /* $?name */))
         (not (exists (object (is-a heading-span)
                              (from ?i)
                              (parent ?parent))))
         (object (is-a file-line)
                 (type heading)
                 (parent ?parent)
                 (index ?i2&:(> ?i2 ?i)))
         =>
         (if (> (- ?i2 ?i) 0) then
           (make-instance of heading-span
                          (header-name (implode$ $?name))
                          (from ?i)
                          (to ?i2)
                          (parent ?parent))))
;------------------------------------------------------------------------------
(defrule identify-lines::modify-header-spans-for-smaller-size
         "Retracts the heading-span in response to finding an earlier heading"
         ?f <- (object (is-a heading-span)
                       (from ?i)
                       (to ?j)
                       (parent ?parent))
         (object (is-a file-line)
                 (type heading)
                 (parent ?parent)
                 (index ?i2&:(> ?j ?i2 ?i)))
         =>
         (modify-instance ?f (to ?i2)))
;------------------------------------------------------------------------------
(defrule convert-templates::retract-unknowns
         ?f <- (object (is-a file-line)
                       (type UNKNOWN))
         =>
         (unmake-instance ?f))
;------------------------------------------------------------------------------
(defrule convert-templates::assert-build-groups
         ?f <- (object (is-a file-line)
                       (type ~UNKNOWN)
                       (id ?id))
         =>
         (assert (message (to build-groups)
                          (action add-to-span)
                          (arguments ?id))))
;------------------------------------------------------------------------------


Deleted the id and class slots as well as the init message-handler

The slots consumed extra memory for no real benefit. In the case of id, the
name field already exists (it is an implicit field) and matches on
instance-name instead of symbol. This means that we store the instance-names in
a list instead of symbols. It also means that the name retrieved from an object
can be directly invoked without having to match against it (in the case where
that is all we were looking for).

The class slot is useless because we can just call (class ...) if it is
necessary. There is no need to waste space. Hell, for matching purposes we can
just use the (is-a ) field to do pattern matching as well.

The init message handler is no longer necessary because these fields no longer
exist.

I left the parent field in because I find it really useful in a wide number of
cases.

;------------------------------------------------------------------------------
;Copyright (c) 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 Joshua Scoggins 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.
;------------------------------------------------------------------------------
; Object.clp - Contains basic object classes
;------------------------------------------------------------------------------
(defclass cortex::Object
  "Base class of all objects"
  (is-a USER)
  (slot parent
        (type INSTANCE SYMBOL)
        (visibility public)))
;------------------------------------------------------------------------------

;------------------------------------------------------------------------------
;Copyright (c) 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 Joshua Scoggins 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.
;------------------------------------------------------------------------------
; Object.clp - Contains basic object classes
;------------------------------------------------------------------------------
(defclass cortex::Object
  "Base class of all objects"
  (is-a USER)
  (slot id (type SYMBOL) (visibility public) (access initialize-only))
  (slot class (type SYMBOL) (visibility public) (access initialize-only))
  (slot parent (type SYMBOL) (visibility public))
  (message-handler init around))
;------------------------------------------------------------------------------
(defmessage-handler cortex::Object init around
                    "Initializes the object, setting the id and class of the
                    object"
                    ()
                    (call-next-handler)
                    ;we want to set this information as the last thing before
                    ;we return
                    (bind ?self:id (instance-name-to-symbol
                                     (instance-name ?self)))
                    (bind ?self:class (class ?self)))
;------------------------------------------------------------------------------


adding a sample to test deffunction. it's not implemented yet, but it's good to have a sample.
this sample was copied from clips user guide
peter

git-svn-id: 9643e93313b82f5e4da82d8413267a0daa4b5472@448 2cd91b7d-3b21-0410-a5f4-f42db4f24360

error: pathspec 'samples/deffunction_test1.clp' did not match any file(s) known to git