############################################################################### ### ### File : blocks.soar ### Original author(s): John E. Laird ### Organization : University of Michigan AI Lab ### Created on : 15 Mar 1995, 13:53:46 ### Last Modified By : Clare Bates Congdon ### Last Modified On : 17 Jul 1996, 16:35:14 ### Soar Version : 7 ### ### Description : A new, simpler implementation of the blocks world ### with just three blocks being moved at random. ### ### Notes: ### CBC, 6/27: Converted to Tcl syntax ### CBC, 6/27: Added extensive comments ############################################################################### ############################################################################### # Create the initial state with blocks A, B, and C on the table. # # This is the first production that will fire; Soar creates the initial state # as an architectural function (in the 'zeroth' decision cycle), which will # match against this production. # This production does a lot of work because it is creating (preferences for) # all the structure for the initial state: # 1. The state has a problem-space named 'blocks'. The problem-space limits # the operators that will be selected for a task. In this simple problem, # it isn't really necessary (there is only one operator), but it's a # programming convention that you should get used to. # 2. The state has four 'things' -- three blocks and the table. # 3. The state has three 'ontop' relations # 4. Each of the things has substructure: their type and their names. Note that # the fourth thing is actually a 'table'. # 5. Each of the ontop relations has substructure: the top thing and the # bottom thing. # Finally, the production writes a message for the user. # # Note that this production will fire exactly once and will never retract. sp {blocks-world*elaborate*initial-state (state ^superstate nil) --> ( ^problem-space blocks ^thing ^ontop ) ( ^type block ^name A) ( ^type block ^name B) ( ^type block ^name C) (
^type table ^name TABLE) ( ^top-block ^bottom-block
) ( ^top-block ^bottom-block
) ( ^top-block ^bottom-block
) (write (crlf) |Initial state has A, B, and C on the table.|)} ############################################################################### # State elaborations - keep track of which objects are clear # There are two productions - one for blocks and one for the table. ############################################################################### ############################################################################### # Assert table always clear # # The conditions establish that: # 1. The state has a problem-space named 'blocks'. # 2. The state has a thing of type table. # The action: # 1. creates an acceptable preference for an attribute-value pair asserting # the table is clear. # # This production will also fire once and never retract. sp {elaborate*table*clear (state ^problem-space blocks ^thing
) (
^type table) --> (
^clear yes)} ############################################################################### # Calculate whether a block is clear # # The conditions establish that: # 1. The state has a problem-space named 'blocks'. # 2. The state has a thing of type block. # 3. There is no 'ontop' relation having the block as its 'bottom-block'. # The action: # 1. create an acceptable preference for an attribute-value pair asserting # the block is clear. # # This production will retract whenever an 'ontop' relation for the given block # is created. Since the ( ^clear yes) wme only has i-support, it will # be removed from working memory automatically when the production retracts. sp {elaborate*block*clear (state ^problem-space blocks ^thing ) ( ^type block) -( ^bottom-block ) --> ( ^clear yes)} ############################################################################### # Suggest MOVE-BLOCK operators # # This production proposes operators that move one block ontop of another block. # The conditions establish that: # 1. The state has a problem-space named 'blocks' # 2. The block moved and the block moved TO must be both be clear. # 3. The block moved is different from the block moved to. # 4. The block moved must be type block. # 5. The block moved must not already be ontop the block being moved to. # The actions: # 1. create an acceptable preference for an operator. # 2. create acceptable preferences for the substructure of the operator (its # name, its 'moving-block' and the 'destination). sp {blocks-world*propose*move-block (state ^problem-space blocks ^thing {<> } ^ontop ) ( ^type block ^clear yes) ( ^clear yes) ( ^top-block ^bottom-block <> ) --> ( ^operator +) ( ^name move-block ^moving-block ^destination )} ############################################################################### # Make all acceptable move-block operators also indifferent # # The conditions establish that: # 1. the state has an acceptable preference for an operator # 2. the operator is named move-block # The actions: # 1. create an indifferent prefererence for the operator sp {blocks-world*compare*move-block*indifferent (state ^operator +) ( ^name move-block) --> ( ^operator =)} ############################################################################### # Apply a MOVE-BLOCK operator # # There are two productions that are part of applying the operator. # Both will fire in parallel. ############################################################################### ############################################################################### # Apply a MOVE-BLOCK operator # (the block is no longer ontop of the thing it used to be ontop of) # # This production is part of the application of a move-block operator. # The conditions establish that: # 1. An operator has been selected for the current state # a. the operator is named move-block # b. the operator has a 'moving-block' and a 'destination' # 2. The state has an ontop relation # a. the ontop relation has a 'top-block' that is the same as the # 'moving-block' of the operator # b. the ontop relation has a 'bottom-block' that is different from the # 'destination' of the operator # The actions: # 1. create a reject preference for the ontop relation sp {blocks-world*apply*move-block*remove-old-ontop (state ^operator ^ontop ) ( ^name move-block ^moving-block ^destination ) ( ^top-block ^bottom-block { <> }) --> ( ^ontop -)} ############################################################################### # Apply a MOVE-BLOCK operator # (the block is now ontop of the destination) # # This production is part of the application of a move-block operator. # The conditions establish that: # 1. An operator has been selected for the current state # a. the operator is named move-block # b. the operator has a 'moving-block' and a 'destination' # The actions: # 1. create an acceptable preference for a new ontop relation # 2. create (acceptable preferences for) the substructure of the ontop # relation: the top block and the bottom block sp {blocks-world*apply*move-block*add-new-ontop (state ^operator ) ( ^name move-block ^moving-block ^destination ) --> ( ^ontop ) ( ^top-block ^bottom-block )} ############################################################################### ############################################################################### # Detect that the goal has been achieved # # The conditions establish that: # 1. The state has a problem-space named 'blocks' # 2. The state has three ontop relations # a. a block named A is ontop a block named B # b. a block named B is ontop a block named C # c. a block named C is ontop a block named TABLE # The actions: # 1. print a message for the user that the A,B,C tower has been built # 2. halt Soar sp {blocks-world*detect*goal (state ^problem-space blocks ^ontop { <> } { <> <> } ) ( ^top-block ^bottom-block ) ( ^top-block ^bottom-block ) ( ^top-block ^bottom-block ) ( ^type block ^name A) ( ^type block ^name B) ( ^type block ^name C) ( ^type table ^name TABLE) --> (write (crlf) |Achieved A, B, C|) (halt)} ############################################################################### ############################################################################### # Monitor the state: Print a message every time a block is moved # # The conditions establish that: # 1. An operator has been selected for the current state # a. the operator is named move-block # b. the operator has a 'moving-block' and a 'destination' # 2. each block has a name # The actions: # 1. print a message for the user that the block has been moved to the # destination. sp {blocks-world*monitor*move-block (state ^operator ) ( ^name move-block ^moving-block ^destination ) ( ^name ) ( ^name ) --> (write (crlf) |Moving Block: | | to: | ) }