Example #1
0
 def test_init_fail(self):
     """ Test that non-board locations raises an exception."""
     with self.assertRaises(ValueError):
         KnightsState([(-1, 0)])
     with self.assertRaises(ValueError):
         KnightsState([(0, 8)])
     with self.assertRaises(TypeError):
         KnightsState([(0, 1.1)])
Example #2
0
    def test_equality(self):
        """ Test that two objects are equal if they represent the same board,
        otherwise not.
        """
        occ1 = [(4, 5), (2, 2)]
        occ2 = [(5, 4), (2, 2)]

        ks1a = KnightsState(occ1)
        ks1b = KnightsState(occ1)
        self.assertEqual(ks1a, ks1b)

        ks2 = KnightsState(occ2)
        self.assertNotEqual(ks2, ks1a)
Example #3
0
 def test_6_only_one_move(self):
     """Only a single move should be made between a start state an each of its successors."""
     occ = [(5, 7), (0, 1), (4, 2)]
     ks = KnightsState(occ)
     _, succ = zip(
         *ks.successors())  # Transpose the answer to get list of states.
     # Go over each successor state
     for ss in succ:
         # The set intersection of occupied spaces should be one less than
         # the total number of pieces in the board, meaning that only one
         # piece has been moved from one place to another.
         self.assertEqual(
             len(ks.occupied.intersection(ss.occupied)),
             len(occ) - 1,
             "Hint: Only one piece on the board may move in a single action."
         )
Example #4
0
 def test_4_no_move_outside(self):
     """Successors are only made up from moves within the board."""
     ks = KnightsState([(0, 0)])
     sas = list(ks.successors())  # Get a list of successors
     _, succ = zip(*sas)  # Transpose the answer to get list of states.
     # These are the possible successors.
     truth = [KnightsState([(1, 2)]), KnightsState([(2, 1)])]
     hint = "Hint: Are you making sure that a move does not end up outside the board?"
     # Check for same number of successors
     self.assertEqual(len(truth), len(list(succ)), hint)
     # Then check that all of the successors are present in result.
     for t in truth:
         self.assertIn(t, succ, hint)
     # Finally check the actions.
     self.assertTrue(all(a.source in ks.occupied and a.target in s.occupied \
                         for a,s in sas), "Actions do not match.")
Example #5
0
    def test_init(self):
        """Just test that the occupied parameter is copied."""
        # Couple of locations
        occ1 = [(3, 3), (1, 2)]
        # KnightsState
        ks1 = KnightsState(occ1)
        # Should have the same locations as when created.
        self.assertEqual(frozenset(occ1), ks1.occupied)

        # Add a repeated location
        occ2 = occ1 + [(3, 3)]
        # New knights state
        ks2 = KnightsState(occ2)
        # The repeated location should be removed, and
        # the occupied locations of ks2 should be the same
        # as the set of locations in occ1.
        self.assertEqual(frozenset(occ1), ks2.occupied)
Example #6
0
 def test_5_no_moves_to_occupied(self):
     """Successors are only made up from moves to unoccupied locations."""
     ks = KnightsState([(5, 6), (7, 7)])
     sas = list(ks.successors())  # Get a list of successors
     _, succ = zip(*sas)  # Transpose the answer to get list of states.
     # These are the possible successors.
     truth = [
         KnightsState([(5, 6), (6, 5)]),
         KnightsState([(3, 7), (7, 7)]),
         KnightsState([(4, 4), (7, 7)]),
         KnightsState([(6, 4), (7, 7)]),
         KnightsState([(3, 5), (7, 7)]),
         KnightsState([(7, 5), (7, 7)])
     ]
     hint = "Hint: Are you making sure that a move does not end up in an already occupied location?"
     # Check for same number of successors
     self.assertEqual(len(truth), len(list(succ)), hint)
     # Then check that all of the successors are present in result.
     for t in truth:
         self.assertIn(t, succ, hint)
     # Finally check the actions.
     self.assertTrue(all(a.source in ks.occupied and a.target in s.occupied \
                         for a,s in sas), "Actions do not match.")
Example #7
0
    def test_3_all_legal(self):
        """One piece with no obstructed moves will have all eight possible successors present."""
        ks = KnightsState([(4, 4)])
        sas = list(ks.successors())  # Get a list of successors
        _, succ = zip(*sas)  # Transpose the answer to get list of states.
        # These are the eight possible successor states.
        truth = [
            KnightsState([(3, 6)]),
            KnightsState([(5, 6)]),
            KnightsState([(2, 5)]),
            KnightsState([(6, 5)]),
            KnightsState([(3, 2)]),
            KnightsState([(5, 2)]),
            KnightsState([(2, 3)]),
            KnightsState([(6, 3)])
        ]

        # Check for same number of successors
        self.assertEqual(len(truth), len(list(succ)))
        # Then check that all of the successors are present in result.
        for t in truth:
            self.assertIn(t, succ)
        # Finally check the actions.
        self.assertTrue(all(a.source in ks.occupied and a.target in s.occupied \
                            for a,s in sas), "Actions do not match.")
Example #8
0
 def test_2_full(self):
     """There should be no successor states from a filled board."""
     ks = KnightsState([(r, c) for r in range(8) for c in range(8)])
     succ = list(ks.successors())
     self.assertEqual(0, len(list(succ)))
Example #9
0
 def test_1_empty(self):
     """There should be no successor states from the empty board."""
     ks = KnightsState([])
     succ = list(ks.successors())
     self.assertEqual(0, len(list(succ)))
Example #10
0
 def test_0_return(self):
     """Successors should return something."""
     ks = KnightsState([])
     succ = list(ks.successors())
     self.assertNotEqual(succ, None,
                         "Hint: Did you remember the return statement?")
Example #11
0
if __name__ == "__main__":
    from knightsstate import KnightsState

    # Example 1
    #
    # KK......  ........
    # KK......  ........
    # ........  ..KK....
    # ........  ..KK....
    # ........  ........
    # ........  ........
    # ........  ........
    # ........  ........
    print("Move four knights in a 2 by 2 formation 2 steps diagonally.")
    print("This will take about a second to solve.")
    ks1 = KnightsState([(0, 0), (0, 1), (1, 0), (1, 1)])
    ks2 = KnightsState([(2, 2), (2, 3), (3, 2), (3, 3)])
    print("Start state:")
    print(ks1)
    print("Target state:")
    print(ks2)
    pi = bfs(ks1, lambda s: s == ks2)
    print(f"Policy: {', '.join(str(a) for a in pi)}")
    print("---------------------------------------------------")

    # Example 2
    # KKK.....  ........
    # KK......  ........
    # ........  ..KKK...
    # ........  ..KK....
    # ........  ........