Advertisement
Vermiculus

the ferrous chef

Apr 1st, 2012
113
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. def d(m, s):
  2.     print m.format(s)
  3.  
  4. class Kitchen:
  5.     """A facility for interpreting the esoteric language 'Chef'.
  6.     """
  7.    
  8.     def __init__(self, recipe="", master=None):
  9.         """Constructor
  10.        
  11.         Initializes lists for mixing bowls and baking dishes and
  12.             begins evaluating the recipe (taken in as a string).
  13.         """
  14.         if master is None:
  15.             from collections import deque
  16.             self.ingredients = dict()   # contains a dictionary of ingredients
  17.             self.mixing_bowls = list()  # list of mixing bowls, stack-style
  18.             self.baking_dishes = list() # list of baking dishes, stack-style
  19.             self.stdin = deque()        # Our very own stdin! So we *could* take in more than one character at a time from what the user sees
  20.             self.stdout = deque()       # Well, if we have an stdin, might as well have an stdout. May make life easier.
  21.             self.history = list()       # Contains a list (stack) of (func, arg) tuples, most-recent last. Useful for looping.
  22.        
  23.         #handles a copy constructor
  24.         elif hasattr(master, 'ingredients') and hasattr(master, 'mixing_bowls') and hasattr(master, 'baking_dishes') and hasattr(master, 'stdin') and hasattr(master, 'stdout') and hasattr(master, 'history'):
  25.             self.ingredients    = master.ingredients
  26.             self.mixing_bowls   = master.mixing_bowls
  27.             self.baking_dishes  = master.baking_dishes
  28.             self.stdin          = master.stdin
  29.             self.stdout         = master.stdout
  30.            
  31.             #self.history       = master.history
  32.             # This statement may interfere with correct looping.
  33.            
  34.             # Note that how we are storing the history right now allows me to say things like this:
  35.            
  36.             # >>> self.history.append(self.take, ['pizza', 'from', 'refrigerator'])
  37.             # >>> last_cmd = self.history[len(self.history)-1]
  38.             # (self.take, ['pizza', 'from', 'refrigerator'])
  39.             # >>> last_cmd[0](last_cmd[1])
  40.             # (does that last command again)
  41.            
  42.            
  43.    
  44.     class Bowl:
  45.         """One mixing bowl allowing for the basic operations.
  46.         """
  47.         def __init__(self):
  48.             self.items = list()
  49.        
  50.         def put(self, ingredient):
  51.             pass
  52.        
  53.         def fold(self, ingredient):
  54.             pass
  55.        
  56.         def add(self, ingredient):
  57.             pass
  58.        
  59.         def remove(self, ingredient):
  60.             pass
  61.        
  62.         def combine(self, ingredient):
  63.             pass
  64.        
  65.         def divide(self, ingredient):
  66.             pass
  67.        
  68.         def mix(self):
  69.             pass       
  70.        
  71.         def liquefy(self, ingredient):
  72.             pass
  73.        
  74.         # etc
  75.    
  76.     class Dish:
  77.         """One baking dish allowing for the basic operations.
  78.         """
  79.         def __init__(self):
  80.             self.items = list()
  81.        
  82.         def pour(self, other):
  83.             """Pours this baking dish into another.
  84.             """
  85.             pass
  86.    
  87.     def do(self, s):
  88.         """Does an arbitrary operation from a valid Chef string
  89.        
  90.         The command must be the first word, case sensitive.
  91.         If the command does not exist, None is returned.
  92.         The rest of the string is passed to the desired function as a list.
  93.         """
  94.         t = s.split()
  95.         if hasattr(self, t[0]):
  96.             return getattr(self, t[0])(t[1:])
  97.         else:
  98.             print "No such attribute."
  99.             return False
  100.    
  101.     def __repr__(self):
  102.         return "  Ingridients: {ing}\n Mixing Bowls: {mb}\nBaking Dishes: {bd}\n Input Buffer: {ip}\nOutput Buffer: {op}".format(ing=str(self.ingredients), mb=str(self.mixing_bowls), bd=str(self.baking_dishes), ip=str(self.stdin), op=str(self.stdout))
  103.    
  104.     # Have this function declare a multidimensional array of strings according to differing degrees of messiness
  105.     # so it can be called
  106.     # ...   return arr[len(mixing_bowls) // 5][len(baking_dishes) // 5]
  107.     # or something like that.
  108.     def __str__(self):
  109.         return "You see a mess of utensils; you have a lot of work yet to do."
  110.    
  111.     def _get_bowl(self, s):
  112.         """Returns the mixing bowl specified by this string.
  113.        
  114.         This method searches the string provided for the mixing bowl needed:
  115.         >>> getDish("Pour the 3rd mixing bowl into the 2nd baking dish.")
  116.         3
  117.        
  118.         If no ordinal for a mixing bowl is specified, it defaults to 1:
  119.         >>> getDish("Put zucchinis into the mixing bowl.")
  120.         1
  121.        
  122.         If there is no mention of any mixing bowls, this function returns None:
  123.         >>> getDish("I've got poop for brains.")
  124.         None
  125.         """
  126.         pass
  127.         return 0
  128.    
  129.     def _get_dish(self, s):
  130.         """Returns the baking dish specified by this string.
  131.        
  132.         This method searches the string provided for the baking dish needed:
  133.         >>> getDish("Pour the 3rd mixing bowl into the 2nd baking dish")
  134.         2
  135.        
  136.         If no ordinal for a baking dish is specified, it defaults to 1:
  137.         >>> getDish("Pour the 3rd mixing bowl into the baking dish")
  138.         1
  139.        
  140.         If there is no mention of any baking dishes, this function returns None:
  141.         >>> getDish("I've got poop for brains.")
  142.         None
  143.         """
  144.         pass
  145.         return 0
  146.    
  147.     def take(self, s):
  148.         """Take (ingredient) from refrigerator.
  149.        
  150.         This reads a numeric value from STDIN into
  151.             the ingredient named, overwriting any
  152.             previous value.
  153.         """
  154.        
  155.         def isFood(s):
  156.             return not s.isdigit()
  157.        
  158.         ingredient_name = ' '.join(s[:len(s)-2])
  159.        
  160.         if not isFood(ingredient_name):
  161.             print "Name Error! You can't eat {}".format(ingredient_name)
  162.             return False
  163.         elif s[len(s)-1] != "refrigerator." or s[len(s)-2] != "from":
  164.             print "Syntax Error! \"{}\"".format("Take "+' '.join(s))
  165.             return False
  166.        
  167.         elif len(self.stdin) is 0: # make a delegate method to take information into STDIN
  168.             _in = raw_input("Press enter after input: ")
  169.             if _in.isdigit(): # if the entire input can be parsed as a single number
  170.                 self.stdin.append(int(_in)) # append that number to the buffer
  171.                 self.ingredients[ingredient_name] = self.stdin.popleft()
  172.             else:
  173.                 for char in _in: # otherwise, append the integral value of each character entered to the buffer.
  174.                     self.stdin.append(ord(char))
  175.                 self.ingredients[ingredient_name] = self.stdin.popleft()
  176.        
  177.         else:
  178.             self.ingredients[ingredient_name] = self.stdin.popleft()
  179.        
  180.         self.history.append(self.take, s)
  181.        
  182.         return True
  183.    
  184.     def put(self, s):
  185.         """Put (ingredient) into the [nth] mixing bowl.
  186.        
  187.         This puts the ingredient into the nth mixing bowl.
  188.         """
  189.         pass
  190.         return True
  191.    
  192.     def fold(self, s):
  193.         """Fold (ingredient) into [nth] mixing bowl.
  194.        
  195.         This removes the top value from the nth mixing bowl and places it in the ingredient.
  196.         """
  197.         pass
  198.         return False
  199.    
  200.     def add(self, s):
  201.         """Two uses.
  202.        
  203.        
  204.         Add (ingredient) [to [nth] mixing bowl].
  205.             This adds the value of ingredient to the
  206.             value of the ingredient on top of the
  207.             nth mixing bowl and stores the result
  208.             in the nth mixing bowl.
  209.        
  210.         Add dry ingredients [to [nth] mixing bowl].
  211.             This adds the values of all the dry ingredients
  212.             together and places the result into the
  213.             nth mixing bowl.
  214.         """
  215.         pass
  216.         return False
  217.    
  218.     def remove(self, s):
  219.         """Remove ingredient [from [nth] mixing bowl].
  220.        
  221.         This subtracts the value of ingredient from
  222.             the value of the ingredient on top of the
  223.             nth mixing bowl and stores the result in
  224.             the nth mixing bowl.
  225.         """
  226.         pass
  227.         return False
  228.    
  229.     def combine(self, s):
  230.         """Combine ingredient [into [nth] mixing bowl].
  231.        
  232.         This multiplies the value of ingredient by
  233.             the value of the ingredient on top of
  234.             the nth mixing bowl and stores the result
  235.             in the nth mixing bowl.
  236.         """
  237.         pass
  238.         return False
  239.    
  240.     def divide(self, s):
  241.         """Divide ingredient [into [nth] mixing bowl].
  242.        
  243.         This divides the value of ingredient into
  244.             the value of the ingredient on top of
  245.             the nth mixing bowl and stores the result
  246.             in the nth mixing bowl.
  247.         """
  248.         pass
  249.         return False
  250.    
  251.     def liquefy(self, s):
  252.         """Two uses.
  253.        
  254.        
  255.         Liquefy | Liquify ingredient.
  256.             This turns the ingredient into a liquid,
  257.             i.e. a Unicode character for output purposes.
  258.            
  259.             (Note: The original specification used
  260.             the word "Liquify", which is a spelling
  261.             error. "Liquify" is deprecated.
  262.             Use "Liquefy" in all new code.)
  263.        
  264.         Liquefy | Liquify contents of the [nth] mixing bowl.
  265.             This turns all the ingredients in the nth mixing bowl
  266.             into a liquid, i.e. a Unicode characters for
  267.             output purposes.
  268.         """
  269.         pass
  270.         return False
  271.    
  272.     def stir(self, s):
  273.         """Two uses.
  274.        
  275.        
  276.         Stir [the [nth] mixing bowl] for number minutes.
  277.             This "rolls" the top number ingredients
  278.             in the nth mixing bowl, such that the
  279.             top ingredient goes down that number of
  280.             ingredients and all ingredients above it
  281.             rise one place. If there are not that many
  282.             ingredients in the bowl, the top ingredient
  283.             goes to tbe bottom of the bowl and all
  284.             the others rise one place.
  285.        
  286.         Stir ingredient into the [nth] mixing bowl.
  287.             This rolls the number of ingredients
  288.             in the nth mixing bowl equal to
  289.             the value of ingredient, such that
  290.             the top ingredient goes down that number
  291.             of ingredients and all ingredients above
  292.             it rise one place. If there are not that
  293.             many ingredients in the bowl, the top
  294.             ingredient goes to tbe bottom of the bowl
  295.             and all the others rise one place.
  296.         """
  297.         pass
  298.         return False
  299.    
  300.     def mix(self, s):
  301.         """Mix [the [nth] mixing bowl] well.
  302.        
  303.         This randomises the order of the
  304.             ingredients in the nth mixing bowl.
  305.         """
  306.         pass
  307.         return False
  308.    
  309.     def clean(self, s):
  310.         """Clean [nth] mixing bowl.
  311.        
  312.         This removes all the ingredients
  313.             from the nth mixing bowl.
  314.         """
  315.         if len(s) > 3 or s[1] != 'mixing' or s[2] != 'bowl.':
  316.             return False
  317.        
  318.         num = self._get_dish(' '.join(s))
  319.         if num == None:
  320.             return False
  321.         else:
  322.             self.mixing_bowls[num] = list()
  323.            
  324.         return True
  325.    
  326.     def pour(self, s):
  327.         """Pour contents of the [nth] mixing bowl into the [pth] baking dish.
  328.        
  329.         This copies all the ingredients from
  330.             the nth mixing bowl to the
  331.             pth baking dish, retaining the order
  332.             and putting them on top of anything
  333.             already in the baking dish.
  334.         """
  335.         pass
  336.         return False
  337.    
  338.     def set(self, s):
  339.         """Set aside.
  340.        
  341.         This causes execution of the innermost
  342.             loop in which it occurs to end
  343.             immediately and execution
  344.             to continue at the statement after
  345.             the "until".
  346.         """
  347.         pass
  348.         return False
  349.    
  350.     def serve(self, s):
  351.         """Two uses.
  352.        
  353.        
  354.         Serve with auxiliary-recipe.
  355.             This invokes a sous-chef to immediately
  356.             prepare the named auxiliary-recipe.
  357.             The calling chef waits until the sous-chef
  358.             is finished before continuing.
  359.            
  360.             See the section on auxiliary recipes below.
  361.        
  362.         Serves number-of-diners.
  363.             This statement writes to STDOUT the contents
  364.             of the first number-of-diners baking dishes.
  365.             It begins with the 1st baking dish,
  366.             removing values from the top one by one and
  367.             printing them until the dish is empty,
  368.             then progresses to the next dish, until all
  369.             the dishes have been printed.
  370.            
  371.             The serves statement is optional, but is
  372.             required if the recipe is to output anything!
  373.         """
  374.         pass
  375.         return False
  376.    
  377.     def refrigerate(self, s):
  378.         """Refrigerate [for number hours].
  379.        
  380.         This causes execution of the recipe
  381.             in which it appears to end immediately.
  382.             If in an auxiliary recipe, the auxiliary
  383.             recipe ends and the sous-chef's first
  384.             mixing bowl is passed back to the calling
  385.             chef as normal. If a number of hours is
  386.             specified, the recipe will print out its
  387.             first number baking dishes before ending.
  388.         """
  389.         pass
  390.         return False
  391.    
  392.     def _verb_(self, s):
  393.         """Takes care of VERB until VERBED.
  394.         Not a clue on how to do this yet.
  395.        
  396.         IDEA!
  397.          -- Create a new kitchen
  398.          -- keep reading in commands until verbed
  399.          -- pass commands to a new kitchen
  400.          -- once we reach 'until verbed', execute the history again
  401.          -- keep executing until condition is zero
  402.         """
  403.  
  404.         pass
  405.  
  406. def read_recipe(filepath):
  407.     """Loads the given *.chef file and does initial parsing.
  408.    
  409. This method will parse the given filename
  410.  
  411. See http://docs.python.org/library/doctest.html#module-doctest
  412. So much awesome.
  413.  
  414. Example output:
  415. >>> print read_recipe("/hw.chef")
  416. ["Hello World Souffle", "This recipe prints the immortal words "Hello world!", in a basically brute force way. It also makes a lot of food for one person.", "72 g haricot beans
  417. 101 eggs
  418. 108 g lard
  419. 111 cups oil
  420. 32 zucchinis
  421. 119 ml water
  422. 114 g red salmon
  423. 100 g dijon mustard
  424. 33 potatoes", "Put potatoes into the mixing bowl. Put dijon mustard into the mixing bowl. Put lard into the mixing bowl. Put red salmon into the mixing bowl. Put oil into the mixing bowl. Put water into the mixing bowl. Put zucchinis into the mixing bowl. Put oil into the mixing bowl. Put lard into the mixing bowl. Put lard into the mixing bowl. Put eggs into the mixing bowl. Put haricot beans into the mixing bowl. Liquefy contents of the mixing bowl. Pour contents of the mixing bowl into the baking dish.
  425.  
  426. Serves 1."]
  427.     """
  428.     pass
  429.  
  430. # takes the instruction string from earlier and splits it into statements
  431. def preheat(method):
  432.     """Takes all of the statements (as a single string) under Method and begins the parsing process.
  433.    
  434. This method returns a list of simple tuples where the first element is the command
  435. and the second element is the source string. The output of this method is intended
  436. for calling Mom.
  437.     """
  438.     pass
  439.  
  440. def gather(ingredients):
  441.     """Return a dictionary of ingredients from the given string.
  442.    
  443. The dictionary returned will contain the ingredient as a string
  444. mapped to a tuple, where the first element indicates if it is dry or wet
  445. and the second element denotes its numeric value.
  446.  
  447. Example:
  448.     {'apple':('dry', 96), 'oil':('wet', 59), etc.}
  449.     """
  450.     pass
  451.  
  452. # Because we all know her handwriting is horrid.
  453. # we may be able to make this fun by using advanced features of functions in Python
  454. def callMom(method):
  455.     """Takes a list of command-string tuples and returns a list of pure command-tuples.
  456.    
  457. Following is a list of commands and descriptions, following the pattern
  458. (<command>,  <arguments>)   - execute <command> with <arguments>
  459. where the default value of ## is exactly 1 (signifying the mixing bowl index
  460. and where # is a plain number
  461.  
  462. For overloaded commands, use hasattr() for type checking
  463.  
  464. ('take',     'ingredient')                 - get one character from the user and place its numeric value into ingredient
  465. ('put',      'ingredient', ##)             - push the ingredient onto the ##th mixing bowl
  466. ('fold',     'ingredient', ##)             - pop the ##th mixing bowl into the ingredient
  467. ('add',      'ingredient', ##)             - peek at the ##th mixing bowl and add (numerically) ingredient to it
  468. ('remove',   'ingredient', ##)             - peek at the ##th mixing bowl and subtract (numerically) ingredient from it
  469. ('combine',  'ingredient', ##)             - peek at the ##th mixing bowl and multiply (numerically) ingredient with it
  470. ('divide',   'ingredient', ##)             - peek at the ##th mixing bowl and divide (numerically) ingredient from it
  471. ('add', ##)                                - takes all of the dry ingredients and places the sum into the #th mixing bowl
  472. ('liquefy',  'ingredient')                 - transform the ingredient into its Unicode equivalent
  473. ('liquefy',   ##)                          - transform the contents of the ##th mixing bowl into their Unicode equivalents
  474. ('stir',      ##,           #)             -
  475. ('stir',     'ingredient',  ##)            -
  476. ('mix',        ##)                         - randomize the order of the ##th mixing bowl
  477. ('clean',      ##)                         - pop the ##th mixing bowl until empty
  478. ('loop',      'verb',      'ingredient')   - See after.
  479. ('next',      'verb',      'ingredient')   - See after.
  480. ('exit')                                   - Continues execution after the next 'next'
  481. ('serve',     'recipe')                    - Invokes the execution of another recipe
  482. ('fridge')                                 - Ends execution immediately and returns the first mixing bowl
  483. ('fridge, #)                               - Print out the first # baking dishes before calling ('fridge')
  484.  
  485. ('serves', #)                              - Pops and prints each baking dish in succession. This is the last command.
  486.  
  487. Note that everything that follows the 'serve' command is an auxiliary recipe.
  488.  
  489. Looping:
  490.   With the 'loop' command, if the ingredient is non-zero, continue execution until reaching the 'next' command. If the ingredient is zero, continue execution after a matching 'next'.
  491.   At the 'next' command, if an ingredient is given (defaulting to the ingredient given by 'loop'), continue execution at the previous 'loop' if the given ingredient is non-zero. If the ingredient is zero, simply continue.
  492.  
  493. The output of this method is intended for cooking.
  494.     """
  495.    
  496.     pass
  497.  
  498. def loadVerbs(path):
  499.     """Return a list verbs and their past-tense form read from a file with the given path.
  500.        
  501. The return will be a list of tuples containing two strings:
  502. the first being the infinite stem, the second being the simple past.
  503.  
  504. Example:
  505.    [("sift","sifted"),("boil","boiled"), ...]
  506.     """
  507.     pass
  508.  
  509. def loadFoods(path):
  510.     """ Returns a simple list of foods read from a file with the given path.
  511.     """
  512.     pass
  513.  
  514. # executes a list of commands
  515. def cook(ingredients, method):
  516.     """Execute the list of commands given using the ingredients provided.
  517.    
  518. Execute the given list of commands in the format given by calling Mom.
  519. It is an error if a given command does not exist.
  520.     """
  521.    
  522.     ###################################################
  523.    
  524.     # iterate through the commands with complete control over position
  525.     #   (python's for-each loop does not give you any control)
  526.     cmd_index = 0
  527.     while cmd_index < len(method):
  528.         cmd_index += 1
  529.         pass
  530.    
  531.     pass
  532.  
  533.  
  534.  
  535. ########################################
  536.  
  537.  
  538.  
  539. hat = 'c= '
  540.  
  541. kills = ["quit", "exit", "stop", "kill", "term"]
  542.  
  543. k = Kitchen()
  544.  
  545. cmd = raw_input(hat).lower()
  546. while cmd[:4] not in kills: # checks the first for letters
  547.     print k.do(cmd)
  548.     print repr(k)
  549.     cmd = raw_input(hat).lower()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement