[강화시스터즈 1기/프로젝트/환경세미나] 폭탄제거부대 02팀

핵심 애트리뷰트

init()

class Environment:
    def __init__(self):
        self.grid_size = 9
        self.num_mines = 10

        # 실제 정답 minefield 초기화
        self.minefield = np.zeros((self.grid_size, self.grid_size), dtype=int)
        # 실제 화면 playerfield hidden 상태(9)로 초기화
        self.playerfield = np.full((self.grid_size, self.grid_size), 9, dtype=int)

        self.state_size = self.minefield.size # (81 반환됨)

        self.explode = False  # 폭발 여부
        self.done = False  # 게임 끝 여부
        self.first_move = True  # 처음 open하는지 여부

reset()

  def reset(self):
        self.minefield = np.zeros((self.grid_size, self.grid_size), dtype=int)
        self.playerfield = np.full((self.grid_size, self.grid_size), 9, dtype=int)

        self.explode = False
        self.done = False
        self.first_move = True

        self.place_mines()

        reset_state = self.get_state() // playerfield 를 flatten
        return reset_state

에피소드를 초기 상태로 되돌리는 역할

def count_adjacent_mines(self, x, y):
        count = 0
        # (x,y) 주변 지뢰 개수
        for i in range(max(0, x - 1), min(self.grid_size, x + 2)):  # 좌우 탐색 (경계 고려)
            for j in range(max(0, y - 1), min(self.grid_size, y + 2)):  # 상하 탐색 (경계 고려)
                if self.minefield[i, j] == -1:
                    count += 1
        return count

step()

def step(self, action):
        state = self.get_state()  # state은 (flatten된) playerfield
        minefield_state = self.minefield.flatten()

        reward = 0
        done = False

        if state[action] == 9:  # hidden 상태(9) 타일을 열면
            state[action] = minefield_state[action]  # 타일에 정답 복사

            # 지뢰를 선택하면 done
            if state[action] == -1:
                done = True
                self.explode = True
                reward = -10

            # 선택한 타일이 0인 경우
            elif state[action] == 0:
                x, y = divmod(action, self.grid_size)  # 1차원 인덱스를 2차원 좌표로 변환
                state = self.auto_reveal_tiles(x, y)  # 주변 타일 열기
                num_hidden_tiles = np.count_nonzero(state == 9)  # 남은 hidden tile 수
                if num_hidden_tiles == self.num_mines:  # 지뢰를 제외하고 전부 연 경우
                    done = True
                    reward = 100
                else:
                    done = False
                    reward = 10

            # 지뢰가 아닌 숫자(1~8) 타일을 선택한 경우
            else:
                num_hidden_tiles = np.count_nonzero(state == 9)  # 남은 hidden tile 수
                if num_hidden_tiles == self.num_mines:  # 지뢰를 제외하고 전부 연 경우
                    explode = False
                    done = True
                    reward = 100
                else:
                    explode = False
                    done = False
                    reward = 10

        self.playerfield = state
        self.playerfield = self.playerfield.reshape(self.grid_size, self.grid_size)
        self.done = done

        return state, reward, done

step 메소드: 에이전트가 환경에 한 단계(action)를 수행할 때 호출

주요 동작 방식

auto_reveal_tiles() : 타일 열기 함수

def auto_reveal_tiles(self, x, y):
        visited = set()  # 중복된 값 허용 X
        
        def reveal(x, y):
            if (x, y) in visited:
                return
            visited.add((x, y))
            self.playerfield[x, y] = self.minefield[x, y]

            # 주변 8개 타일 확인
            if self.minefield[x, y] == 0:
                for dx in [-1, 0, 1]:
                    for dy in [-1, 0, 1]:
                        nx, ny = x + dx, y + dy
                        # 인덱스가 게임판 범위 내에 있는지 확인
                        if self.check_boundary(nx, ny) and (nx, ny) not in visited:
                            reveal(nx, ny)

        reveal(x, y)
        return self.playerfield

render()




Comments