본문 바로가기

🏃‍♀️ 활동/프로젝트 작업일지

Project: Ants vs SomeBees(2)

Phase 1: Basic gameplay

Problem 0: 규칙 이해도 점검

Q1: What is the purpose of the food_cost attribute?
A1: Placing an ant into the colony will decrease the colony's total available food by that ant's food_cost

 

Q2: What type of attribute is food_cost?
A2: class, all Ants of the same subclass cost the same to place

 

Problem 1: HarvestAnt, ThrowerAnt 초기 설정하기

- Ant클래스의 클래스 변수인 food_cost를 override해서 각 개미 클래스에 새로 정의하기
- HarvesterAnt 클래스에서 food add하는 기능 구현: 이 종류의 개미는 action으로서 gamestate.food 합계에 1개의 food를 더한다.
- 참고: ant를 초기화하는 것 만으로는 food가 소비되지 않음(Food Cost 감소X). 오직 ant를 게임 레이아웃에 배치할 때만 food를소비함
그래서 harverster를 만들기만 하면 그 개미종류의 역할에 따라 gamestate.food가 1 증가함

class HarvesterAnt(Ant):
    """HarvesterAnt produces 1 additional food per turn for the colony."""

    name = 'Harvester'
    implemented = True
    # OVERRIDE CLASS ATTRIBUTES HERE
    food_cost = 2

    def action(self, gamestate):
        """Produce 1 additional food for the colony.

        gamestate -- The GameState, used to access game state information.
        """
        # BEGIN Problem 1
        "*** YOUR CODE HERE ***"
        gamestate.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
    # ADD/OVERRIDE CLASS ATTRIBUTES HERE
    food_cost = 3

Problem 2: Place.__init__ 완성하기

- entrance를 추적하는 코드를 추가하여 Place.__init__을 완성할 것이다.

- 지금 단계에서 Place는 계속 오직 이것의 exit만 추적할 것이다.

- 우리는 Place가 이것의 entrance를 또한 계속 추적하기를 원한다.

- Place는 오직 하나의 entrance를 추적해야 한다.

- entrance를 추적하는 것은 ant가 터널 안에서 자기 앞에 무슨 bee가 있는지 보려고 할 때 유용하다.

 

- 하지만, 그냥 entrance를 Place로 패스하는 것은 문제가 생길 수 있다.

- 우리는 exit이랑 entrance를 Place를 만들기 전에 가지고 있어야 한다. -> 닭이먼저냐 달걀이 먼저냐 문제이긴 함

- 이 문제를 해결하기 위해 우리는 다음과 같은 방식으로 entrance를 추적할 것이다.

  • 새로 생성된 Place는 항상 그것의 entrance 초깃값을 None으로 갖는다.
  • 만약 Place가 exit을 갖고 있다면, 그 exit의 entrance는 그 Place로 설정한다.

- 힌트

  • Remember that when the __init__ method is called, the first parameter, self, is bound to the newly created object
  • Try drawing out two Places next to each other if things get confusing. In the GUI, a place's entrance is to its right while the exit is to its left.
  • Remember that Places are not stored in a list, so you can't index into anything to access them. This means that you can't do something like colony[index + 1] to access an adjacent Place. How can you move from one place to another?

- 예시 시각화

- 문제 이해 테스트

Q1: What does a Place represent in the game?

A1: A single tile that an Ant can be placed on and that connects to other Places

 

Q2: p is a Place whose entrance is q and exit is r (q and r are not None). When is p.entrance first set to a non-None value?

A2: When q is constructed

 

Q3: p is a Place whose entrance is q and exit is r (q and r are not None). When is p.exit first set to a non-None value?

A3:  When p is constructed

 

Q4: 

>>> from ants import *
>>> from ants_plans import *
>>> #
>>> # Create a test layout where the gamestate is a single row with 3 tiles
>>> beehive, layout = Hive(make_test_assault_plan()), dry_layout
>>> dimensions = (1, 3)
>>> gamestate = GameState(None, beehive, ant_types(), layout, dimensions)
>>> #
>>> # Simple test for Place
>>> place0 = Place('place_0')
>>> print(place0.exit)

A4: 

None

>>> print(place0.entrance)

None

>>> place1 = Place('place_1', place0)
>>> place1.exit is place0

True

>>> place0.entrance is place1

True

 

- 코드

class Place:
    """A Place holds insects and has an exit to another Place."""
    is_hive = False
    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

Problem 3: implementation of the nearest_bee method

- ThrowerAnt가 leaf를 던지기 위해서, 어떤 벌을 hit할지 알아야 한다.

- ThrowerAnt 클래스에 제공되어 있는 nearest_bee method는 오직 같은 place에서만 bee를 hit하는걸 허락한다.

- 내가 할 일은 이 함수를 고쳐서 ThrowerAnt가 가장 가깝고, hive 안에 있지 않은 bee에 던지도록 한다.

이건 ThrowerAnt랑 같은 Place에 있는 bee도 포함한다.
==> Change nearest_bee so that it returns a random Bee from the nearest place that contains bees

 

- 힌트: 모든 Place들은 is_hive속성이 있다. 이 속성은 place가 Hive안에 있을 때 True이다.

 

- 너의 구현은 아래 로직을 따라야 한다.

  • ThrowerAnt의 현재 Place에서 시작해야 한다.
  • 각각의 place마다, 만약 bee가 남아있다면 랜덤 bee를 리턴한다. 만약 남아있지 않다면, 그 place의 바로 앞(place의 entrance로 저장되어있는 곳)을 조사한다.
  • 만약 공격할 bee가 더 이상 없다면 None을 리턴해라.

- 힌트

  • The random_bee function provided in ants.py returns a random bee from a list of bees or None if the list is empty.
  • As a reminder, if there are no bees present at a Place, then the bees attribute of that Place instance will be an empty list.
  • Having trouble visualizing the test cases? Try drawing them out on paper! The sample diagram provided in Game Layout shows the first test case for this problem.

- 문제 이해 테스트

Q1: What Bee should a ThrowerAnt throw at?

A1: The ThrowerAnt finds the nearest place including and in front of its own place that has Bees and throws at a random Bee in that place

 

Q2: How do you get the Place object in front of another Place object?

A2: The place's entrance instance attribute

 

Q3: What is the entrance of the first Place in a tunnel (i.e. where do the bees enter from)?

A3: The Hive

 

Q4: How can you determine if a given Place is the Hive?

A4: by using the is_hive attribute of the place instance

 

Q5: What should nearest_bee return if there is no Bee in front of the ThrowerAnt in the tunnel?

A5: None

 

Q6:

>>> from ants import *
>>> beehive, layout = Hive(AssaultPlan()), dry_layout
>>> dimensions = (1, 9)
>>> gamestate = GameState(None, beehive, ant_types(), layout, dimensions)
>>> thrower = ThrowerAnt()
>>> ant_place = gamestate.places["tunnel_0_0"]
>>> ant_place.add_insect(thrower)
>>> #
>>> # Testing nearest_bee
>>> near_bee = Bee(2) # A Bee with 2 health
>>> far_bee = Bee(3)  # A Bee with 3 health
>>> hive_bee = Bee(4) # A Bee with 4 health
>>> hive_place = gamestate.beehive
>>> hive_place.is_hive # Check if this place is the Hive

True

>>> hive_place.add_insect(hive_bee)
>>> thrower.nearest_bee() is hive_bee # Bees in the Hive can never be attacked

False

>>> near_place = gamestate.places['tunnel_0_3']
>>> far_place = gamestate.places['tunnel_0_6']
>>> near_place.is_hive # Check if this place is the Hive

False

>>> near_place.add_insect(near_bee)
>>> far_place.add_insect(far_bee)
>>> nearest_bee = thrower.nearest_bee()
>>> nearest_bee is far_bee

False

>>> nearest_bee is near_bee

True

>>> nearest_bee.health

2

>>> thrower.action(gamestate)    # Attack! ThrowerAnts do 1 damage
>>> near_bee.health

1

>>> far_bee.health
3

>>> thrower.place is ant_place    # Don't change self.place!4

True

 

- 코드