## Creature Project ## CSC323 ## 4/17/10 ## Predicate.py: All the predicates import Direction class Predicate: """the predicate interface""" def __init__(self): pass def holds(self, world, coordinates): pass def __str__(self): pass class TruePredicate(Predicate): """A nice constant predicate that always holds.""" def __init__(self): pass def holds(self, world, coordinates): return True def __str__(self): return '(TRUE)' class LogicPredicate(Predicate): """An abstract class for logic predicates like AND OR NOT. It implements a constructor that accepts a list of predicates.""" def __init__(self, predlist): self.predicateList = predlist class AndPredicate(LogicPredicate): """Performs an n-way boolean AND on the list of predicates.""" def holds(self, world, coordinates): for predicate in self.predicateList: if not predicate.holds(world, coordinates): return False return True def __str__(self): return ''.join(["(AND ",' '.join((str(pl) for pl in \ self.predicateList)), ")"]) class OrPredicate(LogicPredicate): """Performs an n-way boolean OR on the list of predicates.""" def holds(self, world, coordinates): for predicate in self.predicateList: if predicate.holds(world, coordinates): return True return False def __str__(self): return ''.join(["(OR ",' '.join((str(pl) for pl in \ self.predicateList)), ")"]) class NotPredicate(LogicPredicate): """Inverts the result of its child predicate.""" def __init__(self, pred): """Overwrites the inherited constructor to accept only one predicate.""" self.predicate = pred def holds(self, world, coordinates): return not self.predicate.holds(world, coordinates) def __str__(self): return ''.join(["(NOT ", str(self.predicate), ")"]) class DirectionalTestPredicate(Predicate): '''Compares the given species in the given direction with the actual species in that direction.''' def __init__(self, species, direction): self.species = species self.direction = direction def holds(self, world, coordinates): new_x = coordinates[0] + self.direction.x new_y = coordinates[1] + self.direction.y return world.getSpecies(new_x,new_y) == self.species def __str__(self): return "(DIRECTION " + str(self.direction) + " " + str(self.species) + ")" class LiveNeighbors(Predicate): """Examine some characteristic of the number of live neighbors of a creature. For example, if number is 5 and comparator is int.__gt__, the predicate is 'at most five live neighbors'.""" def __init__(self, number, comparator): self.number = number self.comparator = comparator def count(self, world, coordinates): statecount = 0 x = coordinates[0] y = coordinates[1] for j in (y-1,y,y+1): for i in (x-1,x,x+1): if not (x==i and y==j): if world.getSpecies(i,j).isLive(): statecount = statecount + 1 return statecount def holds(self, world, coordinates): neighbors = self.count(world, coordinates) return self.comparator(self.number, neighbors) def __str__(self): return "(LIVE " + str(self.number) + " " + str(self.comparator) + ")" class CountingPredicate(Predicate): """Checks if there are a certain (given) number of neighbors of a certain (given) species.""" def __init__(self, spec, number, comparator): '''pickle does not allow the pickling of int.__gt__ and its kin. Because we want to keep the HOP interface, we will pretend to store one of the integer comparators and act like we did even though we just represented them as strings ''' self.species = spec self.number = number if comparator == int.__gt__: self.comparator = ">" elif comparator == int.__lt__: self.comparator = "<" elif comparator == int.__eq__: self.comparator = "=" else: raise Exception("We don't actually allow HOP") def count(self, world, coordinates): statecount = 0 x = coordinates[0] y = coordinates[1] for j in (y-1,y,y+1): for i in (x-1,x,x+1): if not (x==i and y==j): if world.getSpecies(i,j) == self.species: statecount = statecount + 1 return statecount def holds(self, world, coordinates): neighbors = self.count(world, coordinates) '''use our awful hack about integer comparisons''' if self.comparator == ">": return self.number > neighbors elif self.comparator == "<": return self.number < neighbors elif self.comparator == "=": return self.number == neighbors else: raise Exception("I told you, we don't support HOP!") def __str__(self): return "(COUNTING " + str(self.species) + " " + str(self.number) + \ " " + str(self.comparator) + ")" class QuantityPredicate(CountingPredicate): """Checks if there are a certain (given) number of neighbors of a certain (given) species.""" def __init__(self, spec, number): CountingPredicate.__init__(self, spec, number, int.__eq__) def __str__(self): return "(QUANTITY " + str(self.species) + " " + str(self.number) + ")"