中级农民
- 积分
- 104
- 大米
- 颗
- 鳄梨
- 个
- 水井
- 尺
- 蓝莓
- 颗
- 萝卜
- 根
- 小米
- 粒
- 学分
- 个
- 注册时间
- 2018-12-10
- 最后登录
- 1970-1-1
|
ants project
- """CS 61A presents Ants Vs. SomeBees."""
- import random
- from ucb import main, interact, trace
- from collections import OrderedDict
- ################
- # Core Classes #
- ################
- class Place(object):
- """A Place holds insects and has an exit to another Place."""
- def __init__(self, name, exit=None):
- """Create a Place with the given NAME and EXIT.
- name -- A string; the name of this Place.
- exit -- The Place reached by exiting this Place (may be None).
- """
- self.name = name
- self.exit = exit
- self.bees = [] # A list of Bees
- self.ant = None # An Ant
- self.entrance = None # A Place
- # Phase 1: Add an entrance to the exit
- # BEGIN Problem 2
- "*** YOUR CODE HERE ***"
- if self.exit:
- self.exit.entrance = self
- # END Problem 2
- def add_insect(self, insect):
- """Add an INSECT to this Place.
- There can be at most one Ant in a Place, unless exactly one of them is
- a BodyguardAnt (Phase 6), in which case there can be two. If add_insect
- tries to add more Ants than is allowed, an assertion error is raised.
- There can be any number of Bees in a Place.
- """
- if insect.is_ant:
- if self.ant is None:
- self.ant = insect
- else:
- # BEGIN Problem 9
- if self.ant.can_contain(insect):
- self.ant.ant = insect
- elif insect.can_contain(self.ant):
- self.ant,self.ant.ant = insect,self.ant
- else:
- assert self.ant is None, 'Two ants in {0}'.format(self)
- # END Problem 9
- else:
- self.bees.append(insect)
- insect.place = self
- def remove_insect(self, insect):
- """Remove an INSECT from this Place.
- A target Ant may either be directly in the Place, or be contained by a
- container Ant at this place. The true QueenAnt may not be removed. If
- remove_insect tries to remove an Ant that is not anywhere in this
- Place, an AssertionError is raised.
- A Bee is just removed from the list of Bees.
- """
- if insect.is_ant:
- # Special handling for QueenAnt
- # BEGIN Problem 13
- "*** YOUR CODE HERE ***"
- #什么都不做直接写return 就好
- if isinstance(insect,QueenAnt):#ant位置上是queen
- if insect.firstqueen:
- return
- # END Problem 13
- # Special handling for BodyguardAnt
- if self.ant is insect:
- if hasattr(self.ant, 'container') and self.ant.container:
- self.ant = self.ant.ant
- else:
- self.ant = None
- else:
- if hasattr(self.ant, 'container') and self.ant.container and self.ant.ant is insect:
- self.ant.ant = None
- else:
- assert False, '{0} is not in {1}'.format(insect, self)
- else:
- self.bees.remove(insect)
- insect.place = None
- def __str__(self):
- return self.name
- class Insect(object):
- """An Insect, the base class of Ant and Bee, has armor and a Place."""
- is_ant = False
- damage = 0
- watersafe = False
- def __init__(self, armor, place=None):
- """Create an Insect with an ARMOR amount and a starting PLACE."""
- self.armor = armor
- self.place = place # set by Place.add_insect and Place.remove_insect
- def reduce_armor(self, amount):
- """Reduce armor by AMOUNT, and remove the insect from its place if it
- has no armor remaining.
- >>> test_insect = Insect(5)
- >>> test_insect.reduce_armor(2)
- >>> test_insect.armor
- 3
- """
- self.armor -= amount
- if self.armor <= 0:
- self.place.remove_insect(self)
- def action(self, colony):
- """The action performed each turn.
- colony -- The AntColony, used to access game state information.
- """
- def __repr__(self):
- cname = type(self).__name__
- return '{0}({1}, {2})'.format(cname, self.armor, self.place)
- class Bee(Insect):
- """A Bee moves from place to place, following exits and stinging ants."""
- name = 'Bee'
- damage = 1
- watersafe = True
- def sting(self, ant):
- """Attack an ANT, reducing its armor by 1."""
- ant.reduce_armor(self.damage)
- def move_to(self, place):
- """Move from the Bee's current Place to a new PLACE."""
- self.place.remove_insect(self)
- place.add_insect(self)
- def blocked(self):
- """Return True if this Bee cannot advance to the next Place."""
- # Phase 4: Special handling for NinjaAnt
- # BEGIN Problem 7
- return self.place.ant is not None and self.place.ant.blocks_path
- # END Problem 7
- def action(self, colony):
- """A Bee's action stings the Ant that blocks its exit if it is blocked,
- or moves to the exit of its current place otherwise.
- colony -- The AntColony, used to access game state information.
- """
- if self.blocked():
- self.sting(self.place.ant)
- elif self.armor > 0 and self.place.exit is not None:
- self.move_to(self.place.exit)
- class Ant(Insect):
- """An Ant occupies a place and does work for the colony."""
- is_ant = True
- implemented = False # Only implemented Ant classes should be instantiated
- food_cost = 0
- blocks_path = True
- container = False
- def __init__(self, armor=1):
- """Create an Ant with an ARMOR quantity."""
- Insect.__init__(self, armor)
-
- def can_contain(self, other):
- # BEGIN Problem 9
- "*** YOUR CODE HERE ***"
- if self.container and not other.container and not self.ant:
- return True
- # END Problem 9
- class HarvesterAnt(Ant):
- """HarvesterAnt produces 1 additional food per turn for the colony."""
- name = 'Harvester'
- implemented = True
- food_cost = 2
- def action(self, colony):
- """Produce 1 additional food for the COLONY.
- colony -- The AntColony, used to access game state information.
- """
- # BEGIN Problem 1
- "*** YOUR CODE HERE ***"
- colony.food += 1
- # END Problem 1
- class ThrowerAnt(Ant):
- """ThrowerAnt throws a leaf each turn at the nearest Bee in its range."""
- name = 'Thrower'
- implemented = True
- damage = 1
- food_cost = 3
- min_range = 0
- max_range = float('inf')
- def nearest_bee(self, hive):
- """Return the nearest Bee in a Place that is not the HIVE, connected to
- the ThrowerAnt's Place by following entrances.
- This method returns None if there is no such Bee (or none in range).
- """
- # BEGIN Problem 3 and 4
- #好好复习和梳理这道题的逻辑,卡了我很久... = =
- Beerange = 0
- Beeplace = self.place
- while Beerange < self.min_range:
- Beeplace = Beeplace.entrance
- Beerange += 1
- while not Beeplace.bees and Beeplace != hive: #第一个有bee的place并且不是hive
- Beeplace = Beeplace.entrance
- Beerange += 1
- if Beerange > self.max_range or Beeplace == hive:
- return None
- elif Beerange >= self.min_range and Beerange <= self.max_range: #在满足了有bee的要求以后
- return random_or_none(Beeplace.bees)
- else:
- return None
- # END Problem 3 and 4
- def throw_at(self, target):
- """Throw a leaf at the TARGET Bee, reducing its armor."""
- if target is not None:
- target.reduce_armor(self.damage)
- def action(self, colony):
- """Throw a leaf at the nearest Bee in range."""
- self.throw_at(self.nearest_bee(colony.hive))
- def random_or_none(s):
- """Return a random element of sequence S, or return None if S is empty."""
- if s:
- return random.choice(s)
- ##############
- # Extensions #
- ##############
- class Water(Place):
- """Water is a place that can only hold 'watersafe' insects."""
- def add_insect(self, insect):
- """Add INSECT if it is watersafe, otherwise reduce its armor to 0."""
- # BEGIN Problem 11
- "*** YOUR CODE HERE ***"
- Place.add_insect(self,insect)
- if not insect.watersafe:
- insect.reduce_armor(insect.armor)
- # END Problem 11
- class FireAnt(Ant):
- """FireAnt cooks any Bee in its Place when it expires."""
- name = 'Fire'
- damage = 3
- # BEGIN Problem 5
- implemented = True # Change to True to view in the GUI
- food_cost = 5
- armor = 1
- # END Problem 5
- def reduce_armor(self, amount):
- """Reduce armor by AMOUNT, and remove the FireAnt from its place if it
- has no armor remaining. If the FireAnt dies, damage each of the bees in
- the current place.
- """
- # BEGIN Problem 5
- "*** YOUR CODE HERE ***"
- self.armor -= amount
- if not self.armor:
- beels = self.place.bees[:]
- for bee in beels:
- bee.armor -= self.damage
- if not bee.armor:
- self.place.bees.remove(bee)
- self.place.ant = None
- # END Problem 5
- class LongThrower(ThrowerAnt):
- """A ThrowerAnt that only throws leaves at Bees at least 5 places away."""
- name = 'Long'
- # BEGIN Problem 4
- implemented = True # Change to True to view in the GUI
- food_cost = 2
- min_range = 5
- max_range = float('inf')
- # END Problem 4
- class ShortThrower(ThrowerAnt):
- """A ThrowerAnt that only throws leaves at Bees at most 3 places away."""
- name = 'Short'
- # BEGIN Problem 4
- implemented = True # Change to True to view in the GUI
- food_cost = 2
- max_range = 3
- min_range = 0
- # END Problem 4
- # BEGIN Problem 8
- # The WallAnt class
- class WallAnt(Ant):
- name = 'Wall'
- implemented = True
- food_cost = 4
- armor = 4
- def __init__(self, armor=4):
- Insect.__init__(self,armor)
-
- # END Problem 8
- class NinjaAnt(Ant):
- """NinjaAnt does not block the path and damages all bees in its place."""
- name = 'Ninja'
- damage = 1
- # BEGIN Problem 7
- implemented = True # Change to True to view in the GUI
- blocks_path = False
- food_cost = 5
- # END Problem 7
- def action(self, colony):
- # BEGIN Problem 7
- "*** YOUR CODE HERE ***"
- for bee in self.place.bees[:]:
- bee.armor -= self.damage
- if bee.armor <= 0:
- self.place.bees.remove(bee)
- # END Problem 7
- # BEGIN Problem 12
- # The ScubaThrower class
- class ScubaThrower(ThrowerAnt):
- food_cost = 6
- armor = 1
- name = 'Scuba'
- implemented = True
- watersafe = True
- # END Problem 12
- class HungryAnt(Ant):
- """HungryAnt will take three turns to digest a Bee in its place.
- While digesting, the HungryAnt can't eat another Bee.
- """
- name = 'Hungry'
- # BEGIN Problem 6
- implemented = True # Change to True to view in the GUI
- food_cost = 4
- armor = 1
- left_time = 0
- # END Problem 6
- def __init__(self):
- # BEGIN Problem 6
- "*** YOUR CODE HERE ***"
- self.time_to_digest = 3
- self.digesting = 0
- # END Problem 6
- def eat_bee(self, bee):
- # BEGIN Problem 6
- "*** YOUR CODE HERE ***"
- if bee:
- self.digesting = 1
- bee.armor = 0
- self.place.bees.remove(bee)
- self.left_time = self.time_to_digest
- # END Problem 6
- def action(self, colony):
- # BEGIN Problem 6
- "*** YOUR CODE HERE ***"
- #注意这个if的层次,最后一个if必须执行
-
- if self.digesting == 0:
- self.eat_bee(random_or_none(self.place.bees))
- elif self.digesting:
- self.left_time -= 1
- if self.left_time == 0:
- self.digesting = 0
- self.left_time = self.time_to_digest
- # END Problem 6
- class BodyguardAnt(Ant):
- """BodyguardAnt provides protection to other Ants."""
- name = 'Bodyguard'
- # BEGIN Problem 9
- implemented = True # Change to True to view in the GUI
- container = True
- food_cost = 4
- armor = 2
- # END Problem 9
- def __init__(self):
- Ant.__init__(self, 2)
- self.ant = None # The Ant hidden in this bodyguard
- def contain_ant(self, ant):
- # BEGIN Problem 9
- "*** YOUR CODE HERE ***"
- self.ant = ant
- # END Problem 9
- def action(self, colony):
- # BEGIN Problem 9
- "*** YOUR CODE HERE ***"
- if self.ant:
- self.place.ant = self
- return self.ant.action(colony)
- # END Problem 9
- class TankAnt(BodyguardAnt):
- """TankAnt provides both offensive and defensive capabilities."""
- name = 'Tank'
- damage = 1
- # BEGIN Problem 10
- implemented = True # Change to True to view in the GUI
- food_cost = 6
- armor = 2
- # END Problem 10
- def action(self, colony):
- # BEGIN Problem 10
- "*** YOUR CODE HERE ***"
- if self.damage:
- for bee in self.place.bees[:]:
- bee.reduce_armor(self.damage)
- BodyguardAnt.action(self,colony)
- # END Problem 10
- # BEGIN Problem 13
- class QueenAnt(ScubaThrower): # You should change this line
- # END Problem 13
- """The Queen of the colony. The game is over if a bee enters her place."""
- name = 'Queen'
- # BEGIN Problem 13
- implemented = True # Change to True to view in the GUI
- food_cost = 7
- armor = 1
- firstqueen = True
- doubled_ls = []
- container = False
- # END Problem 13
- def __init__(self):
- # BEGIN Problem 13
- "*** YOUR CODE HERE ***"
- ScubaThrower.__init__(self)
- self.firstqueen = QueenAnt.firstqueen
- QueenAnt.firstqueen = False
- # END Problem 13
- def action(self, colony):
- """A queen ant throws a leaf, but also doubles the damage of ants
- in her tunnel.
- Impostor queens do only one thing: reduce their own armor to 0.
- """
- # BEGIN Problem 13
- "*** YOUR CODE HERE ***"
- db_place = self.place.exit
- if self.firstqueen:
- ThrowerAnt.action(self,colony)
- while db_place:#当没有走到tunnel尽头时
- if db_place.ant:
- if db_place.exit:
- if db_place.ant.container:
- if db_place.ant.ant and not db_place.ant.ant in self.doubled_ls:
- db_place.ant.ant.damage *= 2
- self.doubled_ls.append(db_place.ant.ant)
- if db_place.ant not in self.doubled_ls:#无论有没有两个ant都要执行
- db_place.ant.damage *= 2
- self.doubled_ls.append(db_place.ant)
- else:#前面有ant且在tunnel尽头
- bees_win()
- db_place = db_place.exit
- else:
- self.reduce_armor(self.armor)
- # END Problem 13
- def reduce_armor(self, amount):
- """Reduce armor by AMOUNT, and if the True QueenAnt has no armor
- remaining, signal the end of the game.
- """
- # BEGIN Problem 13
- "*** YOUR CODE HERE ***"
- self.armor -= amount
- if self.firstqueen and self.armor <= 0 :
- self.place.remove_insect(self)
- bees_win()
- else:
- self.place.remove_insect(self)
- # END Problem 13
- class AntRemover(Ant):
- """Allows the player to remove ants from the board in the GUI."""
- name = 'Remover'
- implemented = False
- def __init__(self):
- Ant.__init__(self, 0)
- ##################
- # Status Effects #
- ##################
- def make_slow(action):
- """Return a new action method that calls ACTION every other turn.
- action -- An action method of some Bee
- """
- # BEGIN Problem EC
- "*** YOUR CODE HERE ***"
- return lambda colony: None if colony.time % 2 else action(colony)
- # END Problem EC
- def make_stun(action):
- """Return a new action method that does nothing.
- action -- An action method of some Bee
- """
- # BEGIN Problem EC
- "*** YOUR CODE HERE ***"
- return lambda colony: None
- # END Problem EC
- def apply_effect(effect, bee, duration):
- """Apply a status effect to a BEE that lasts for DURATION turns."""
- # BEGIN Problem EC
- "*** YOUR CODE HERE ***"
- original_action = bee.action
- affected_action = effect(bee.action)
- def new_action(colony):
- nonlocal duration
- if duration:
- affected_action(colony)
- duration -= 1
- else:
- original_action(colony)
- bee.action = new_action
-
- # END Problem EC
- class SlowThrower(ThrowerAnt):
- """ThrowerAnt that causes Slow on Bees."""
- name = 'Slow'
- # BEGIN Problem EC
- implemented = True # Change to True to view in the GUI
- food_cost = 4
- armor = 1
- slow_time = 0
- # END Problem EC
- def throw_at(self, target):
- if target:
- apply_effect(make_slow, target, 3)
- class StunThrower(ThrowerAnt):
- """ThrowerAnt that causes Stun on Bees."""
- name = 'Stun'
- # BEGIN Problem EC
- implemented = True # Change to True to view in the GUI
- food_cost = 6
- armor = 1
- # END Problem EC
- def throw_at(self, target):
- if target:
- apply_effect(make_stun, target, 1)
- ##################
- # Bees Extension #
- ##################
- class Wasp(Bee):
- """Class of Bee that has higher damage."""
- name = 'Wasp'
- damage = 2
- class Hornet(Bee):
- """Class of bee that is capable of taking two actions per turn, although
- its overall damage output is lower. Immune to status effects.
- """
- name = 'Hornet'
- damage = 0.25
- def action(self, colony):
- for i in range(2):
- if self.armor > 0:
- super().action(colony)
- def __setattr__(self, name, value):
- if name != 'action':
- object.__setattr__(self, name, value)
- class NinjaBee(Bee):
- """A Bee that cannot be blocked. Is capable of moving past all defenses to
- assassinate the Queen.
- """
- name = 'NinjaBee'
- def blocked(self):
- return False
- class Boss(Wasp, Hornet):
- """The leader of the bees. Combines the high damage of the Wasp along with
- status effect immunity of Hornets. Damage to the boss is capped up to 8
- damage by a single attack.
- """
- name = 'Boss'
- damage_cap = 8
- action = Wasp.action
- def reduce_armor(self, amount):
- super().reduce_armor(self.damage_modifier(amount))
- def damage_modifier(self, amount):
- return amount * self.damage_cap/(self.damage_cap + amount)
- class Hive(Place):
- """The Place from which the Bees launch their assault.
- assault_plan -- An AssaultPlan; when & where bees enter the colony.
- """
- def __init__(self, assault_plan):
- self.name = 'Hive'
- self.assault_plan = assault_plan
- self.bees = []
- for bee in assault_plan.all_bees:
- self.add_insect(bee)
- # The following attributes are always None for a Hive
- self.entrance = None
- self.ant = None
- self.exit = None
- def strategy(self, colony):
- exits = [p for p in colony.places.values() if p.entrance is self]
- for bee in self.assault_plan.get(colony.time, []):
- bee.move_to(random.choice(exits))
- colony.active_bees.append(bee)
- class AntColony(object):
- """An ant collective that manages global game state and simulates time.
- Attributes:
- time -- elapsed time
- food -- the colony's available food total
- queen -- the place where the queen resides
- places -- A list of all places in the colony (including a Hive)
- bee_entrances -- A list of places that bees can enter
- """
- def __init__(self, strategy, hive, ant_types, create_places, dimensions, food=2):
- """Create an AntColony for simulating a game.
- Arguments:
- strategy -- a function to deploy ants to places
- hive -- a Hive full of bees
- ant_types -- a list of ant constructors
- create_places -- a function that creates the set of places
- dimensions -- a pair containing the dimensions of the game layout
- """
- self.time = 0
- self.food = food
- self.strategy = strategy
- self.hive = hive
- self.ant_types = OrderedDict((a.name, a) for a in ant_types)
- self.dimensions = dimensions
- self.active_bees = []
- self.configure(hive, create_places)
- def configure(self, hive, create_places):
- """Configure the places in the colony."""
- self.queen = QueenPlace('AntQueen')
- self.places = OrderedDict()
- self.bee_entrances = []
- def register_place(place, is_bee_entrance):
- self.places[place.name] = place
- if is_bee_entrance:
- place.entrance = hive
- self.bee_entrances.append(place)
- register_place(self.hive, False)
- create_places(self.queen, register_place, self.dimensions[0], self.dimensions[1])
- def simulate(self):
- """Simulate an attack on the ant colony (i.e., play the game)."""
- num_bees = len(self.bees)
- try:
- while True:
- self.hive.strategy(self) # Bees invade
- self.strategy(self) # Ants deploy
- for ant in self.ants: # Ants take actions
- if ant.armor > 0:
- ant.action(self)
- for bee in self.active_bees[:]: # Bees take actions
- if bee.armor > 0:
- bee.action(self)
- if bee.armor <= 0:
- num_bees -= 1
- self.active_bees.remove(bee)
- if num_bees == 0:
- raise AntsWinException()
- self.time += 1
- except AntsWinException:
- print('All bees are vanquished. You win!')
- return True
- except BeesWinException:
- print('The ant queen has perished. Please try again.')
- return False
- def deploy_ant(self, place_name, ant_type_name):
- """Place an ant if enough food is available.
- This method is called by the current strategy to deploy ants.
- """
- constructor = self.ant_types[ant_type_name]
- if self.food < constructor.food_cost:
- print('Not enough food remains to place ' + ant_type_name)
- else:
- ant = constructor()
- self.places[place_name].add_insect(ant)
- self.food -= constructor.food_cost
- return ant
- def remove_ant(self, place_name):
- """Remove an Ant from the Colony."""
- place = self.places[place_name]
- if place.ant is not None:
- place.remove_insect(place.ant)
- @property
- def ants(self):
- return [p.ant for p in self.places.values() if p.ant is not None]
- @property
- def bees(self):
- return [b for p in self.places.values() for b in p.bees]
- @property
- def insects(self):
- return self.ants + self.bees
- def __str__(self):
- status = ' (Food: {0}, Time: {1})'.format(self.food, self.time)
- return str([str(i) for i in self.ants + self.bees]) + status
- class QueenPlace(Place):
- """QueenPlace at the end of the tunnel, where the queen resides."""
- def add_insect(self, insect):
- """Add an Insect to this Place.
- Can't actually add Ants to a QueenPlace. However, if a Bee attempts to
- enter the QueenPlace, a BeesWinException is raised, signaling the end
- of a game.
- """
- assert not insect.is_ant, 'Cannot add {0} to QueenPlace'
- raise BeesWinException()
- def ants_win():
- """Signal that Ants win."""
- raise AntsWinException()
- def bees_win():
- """Signal that Bees win."""
- raise BeesWinException()
- def ant_types():
- """Return a list of all implemented Ant classes."""
- all_ant_types = []
- new_types = [Ant]
- while new_types:
- new_types = [t for c in new_types for t in c.__subclasses__()]
- all_ant_types.extend(new_types)
- return [t for t in all_ant_types if t.implemented]
- class GameOverException(Exception):
- """Base game over Exception."""
- pass
- class AntsWinException(GameOverException):
- """Exception to signal that the ants win."""
- pass
- class BeesWinException(GameOverException):
- """Exception to signal that the bees win."""
- pass
- def interactive_strategy(colony):
- """A strategy that starts an interactive session and lets the user make
- changes to the colony.
- For example, one might deploy a ThrowerAnt to the first tunnel by invoking
- colony.deploy_ant('tunnel_0_0', 'Thrower')
- """
- print('colony: ' + str(colony))
- msg = '<Control>-D (<Control>-Z <Enter> on Windows) completes a turn.\n'
- interact(msg)
- def start_with_strategy(args, strategy):
- """Reads command-line arguments and starts a game with those options."""
- import argparse
- parser = argparse.ArgumentParser(description="Play Ants vs. SomeBees")
- parser.add_argument('-d', type=str, metavar='DIFFICULTY',
- help='sets difficulty of game (test/easy/medium/hard/insane)')
- parser.add_argument('-w', '--water', action='store_true',
- help='loads a full layout with water')
- parser.add_argument('--food', type=int,
- help='number of food to start with when testing', default=2)
- args = parser.parse_args()
- assault_plan = make_normal_assault_plan()
- layout = dry_layout
- tunnel_length = 9
- num_tunnels = 3
- food = args.food
- if args.water:
- layout = wet_layout
- if args.d in ['t', 'test']:
- assault_plan = make_test_assault_plan()
- num_tunnels = 1
- elif args.d in ['e', 'easy']:
- assault_plan = make_easy_assault_plan()
- num_tunnels = 2
- elif args.d in ['n', 'normal']:
- assault_plan = make_normal_assault_plan()
- num_tunnels = 3
- elif args.d in ['h', 'hard']:
- assault_plan = make_hard_assault_plan()
- num_tunnels = 4
- elif args.d in ['i', 'insane']:
- assault_plan = make_insane_assault_plan()
- num_tunnels = 4
- hive = Hive(assault_plan)
- dimensions = (num_tunnels, tunnel_length)
- return AntColony(strategy, hive, ant_types(), layout, dimensions, food).simulate()
- ###########
- # Layouts #
- ###########
- def wet_layout(queen, register_place, tunnels=3, length=9, moat_frequency=3):
- """Register a mix of wet and and dry places."""
- for tunnel in range(tunnels):
- exit = queen
- for step in range(length):
- if moat_frequency != 0 and (step + 1) % moat_frequency == 0:
- exit = Water('water_{0}_{1}'.format(tunnel, step), exit)
- else:
- exit = Place('tunnel_{0}_{1}'.format(tunnel, step), exit)
- register_place(exit, step == length - 1)
- def dry_layout(queen, register_place, tunnels=3, length=9):
- """Register dry tunnels."""
- wet_layout(queen, register_place, tunnels, length, 0)
- #################
- # Assault Plans #
- #################
- class AssaultPlan(dict):
- """The Bees' plan of attack for the Colony. Attacks come in timed waves.
- An AssaultPlan is a dictionary from times (int) to waves (list of Bees).
- >>> AssaultPlan().add_wave(4, 2)
- {4: [Bee(3, None), Bee(3, None)]}
- """
- def add_wave(self, bee_type, bee_armor, time, count):
- """Add a wave at time with count Bees that have the specified armor."""
- bees = [bee_type(bee_armor) for _ in range(count)]
- self.setdefault(time, []).extend(bees)
- return self
- @property
- def all_bees(self):
- """Place all Bees in the hive and return the list of Bees."""
- return [bee for wave in self.values() for bee in wave]
- def make_test_assault_plan():
- return AssaultPlan().add_wave(Bee, 3, 2, 1).add_wave(Bee, 3, 3, 1)
- def make_easy_assault_plan():
- plan = AssaultPlan()
- for time in range(3, 16, 2):
- plan.add_wave(Bee, 3, time, 1)
- plan.add_wave(Wasp, 3, 4, 1)
- plan.add_wave(NinjaBee, 3, 8, 1)
- plan.add_wave(Hornet, 3, 12, 1)
- plan.add_wave(Boss, 15, 16, 1)
- return plan
- def make_normal_assault_plan():
- plan = AssaultPlan()
- for time in range(3, 16, 2):
- plan.add_wave(Bee, 3, time, 2)
- plan.add_wave(Wasp, 3, 4, 1)
- plan.add_wave(NinjaBee, 3, 8, 1)
- plan.add_wave(Hornet, 3, 12, 1)
- plan.add_wave(Wasp, 3, 16, 1)
- #Boss Stage
- for time in range(21, 30, 2):
- plan.add_wave(Bee, 3, time, 2)
- plan.add_wave(Wasp, 3, 22, 2)
- plan.add_wave(Hornet, 3, 24, 2)
- plan.add_wave(NinjaBee, 3, 26, 2)
- plan.add_wave(Hornet, 3, 28, 2)
- plan.add_wave(Boss, 20, 30, 1)
- return plan
- def make_hard_assault_plan():
- plan = AssaultPlan()
- for time in range(3, 16, 2):
- plan.add_wave(Bee, 4, time, 2)
- plan.add_wave(Hornet, 4, 4, 2)
- plan.add_wave(Wasp, 4, 8, 2)
- plan.add_wave(NinjaBee, 4, 12, 2)
- plan.add_wave(Wasp, 4, 16, 2)
- #Boss Stage
- for time in range(21, 30, 2):
- plan.add_wave(Bee, 4, time, 3)
- plan.add_wave(Wasp, 4, 22, 2)
- plan.add_wave(Hornet, 4, 24, 2)
- plan.add_wave(NinjaBee, 4, 26, 2)
- plan.add_wave(Hornet, 4, 28, 2)
- plan.add_wave(Boss, 30, 30, 1)
- return plan
- def make_insane_assault_plan():
- plan = AssaultPlan()
- plan.add_wave(Hornet, 5, 2, 2)
- for time in range(3, 16, 2):
- plan.add_wave(Bee, 5, time, 2)
- plan.add_wave(Hornet, 5, 4, 2)
- plan.add_wave(Wasp, 5, 8, 2)
- plan.add_wave(NinjaBee, 5, 12, 2)
- plan.add_wave(Wasp, 5, 16, 2)
- #Boss Stage
- for time in range(21, 30, 2):
- plan.add_wave(Bee, 5, time, 3)
- plan.add_wave(Wasp, 5, 22, 2)
- plan.add_wave(Hornet, 5, 24, 2)
- plan.add_wave(NinjaBee, 5, 26, 2)
- plan.add_wave(Hornet, 5, 28, 2)
- plan.add_wave(Boss, 30, 30, 2)
- return plan
- from utils import *
- @main
- def run(*args):
- Insect.reduce_armor = class_method_wrapper(Insect.reduce_armor,
- pre=print_expired_insects)
- start_with_strategy(args, interactive_strategy)
复制代码 |
|