## Creature Project ## CSC323 ## 4/17/10 ## species.py: Contains methods associated with the class Species. from Instruction import Instruction from Rule import Rule import Direction import re class Species (): """A type of unit in the game. It has * a kind (a string such as student or squirrel); * a color, which is the color it is displayed as on the board; * a list of rules that describe what changes it causes under certain conditions. Ideally there should only be one object of each species made, with it being referenced from multiple places. An actual species should not change during gameplay.""" id_count = 0 def __init__(self, kind, color, rules=None): self.kind = kind self.color = color self.id_count = Species.id_count Species.id_count += 1 if isinstance(rules, list): self.rules = rules else: self.rules = [] if (kind.find("Dead") == -1): self.alive = True else: self.alive = False def addRule(self, rule, index=None): """Places a rule in the list in a user selected place. This is given as an index. Note that index does not mean absolute priority: Example: If rules A then B then C then D are given with indices 1,0,0,2, they will be listed C,B,D,A in rules, even though A's index was lower than B's (aka the order they are added matters somewhat).""" if index != None: while self.rules.__len__() < index: self.rules.append(None) self.rules.insert(index, rule) else: self.rules.append(rule) def countRules(self): '''Creates a species based count of the rules. Used in the GUI to help revert a database after a cancel action''' return len(self.rules) def removeRule(self, rule): """Removes a rule from the list. I don't think this is ever actually used at any part of the game though, so its purpose is debatable.""" try: self.rules.remove(rule) except Exception as e: pass def next(self, world, coordinates): """Examines each rule in sequence and returns the instruction for the first one that evaluates to true. If no rule evaluates to true, a stay instruction is returned.""" for r in self.rules: if r != None and r.holds(world, coordinates): return r.getInstructions(coordinates) """Returns a stay instruction, which just tells the cell at the coords it was called from to change its species to the species that's already there.""" return [Instruction(Direction.C, self, coordinates)] def rulePop(self): """Removes and returns the last element of the rulesList""" if len(self.rules) > 0: return self.rules.pop() else: return None def isLive(self): return self.alive def __str__(self): """Returns a string representation of this Species""" s = "(" + self.kind + ": " + self.color + ")" return s @staticmethod def loadFromString(string): """Given the canonical string representation for a Species, returns the Species""" #First, try to match Species with a color result = re.match(r"^\((\w+): (\w+)\)$",string) if result: return Species(result.group(1),result.group(2)) else: #Nothing matched. This evidently wasn't a Species. raise Error("String format error") def save_the_species(self): speciesString ="("+ str(self.kind) +":"+ self.color for r in self.rules: speciesString += " \n"+ r.save_the_rule() + "" speciesString += ")" return speciesString def __eq__(self, other): """Overrides equality. Possibly not necessary since each species should only have one instance, so the default eq should work.""" if isinstance(other,Species): if self.kind == other.kind: if self.color == other.color: return True return False def __ne__(self, other): """Overrides !=. Possibly not necessary since each species should only have one instance, so the default ne should work.""" result = self.__eq__(other) if result is NotImplemented: return result return not result def __hash__(self): """Implement a sane hashcode for Species. Needed in order to overwrite equality methods.""" return hash(str(self))