
속도, 정확도, 복잡성 등 요소를 고려해 가능한 이동 경로 중 최선의 경로를 찾음
게임의 승리 조건을 고려해 게임이 진행되는 일련의 과정 동안 상황에 맞는 최적의 이동 경로를 찾아 승리로 이끄는 전략을 제시함
2인용 게임에서, 기본적으로 자기 차례가 올 때마다 이동 경로를 다시 계산해야 함 <- 상대 플레이어의 방해로 인해 애초에 계획한 대로 이동하기 힘들기 때문
컴퓨터의 입장에서 게임
exhaustive search(철저한 검색) or brute force search(무차별 검색)
불필요한 노드 탐색 회피하도록 알고리즘 디자인하는 것을 의미
최적 경로에 포함되지 않은 서브트리 탐색 회피
가정: "합리적인 플레이어라면 상대방에게 가장 좋은 경로를 피할 것이다."
알파, 베타 매개변수:
각 노드에 점수 할당 시 (잠재적인 이동 경로로 간주) 노드 점수의 현재 추정치가 알파와 베타 사이에 있는지 판단하여 가지치기 할지 결정 -> 탐색 공간 줄어들음
미니맥스 알고리즘의 변형
실제 환경에서 자주 이용됨
2인용 게임은 일반적으로 제로섬 게임임 - 한 플레이어의 손실이 다른 플레이어의 이득이 됨
이 특징을 활용하여 게임에서 승리할 확률 높이는 전략 제시
게임 진행 시, 상대방의 점수는 최소화하고 내 점수는 최대화하는 방향으로 움직임
즉, 상대방에게 불리한 위치뿐만 아니라 동시에 나에게 가장 유리한 위치를 찾는 것
미니맥스 알고리즘보다 더 간결함
알파-베타 가지치기 사용할 수 있음
pip3 install easyAI
# This is a variant of the Game of Bones recipe given in the easyAI library
from easyAI import TwoPlayersGame, id_solve, Human_Player, AI_Player
from easyAI.AI import TT
class LastCoinStanding(TwoPlayersGame):
def __init__(self, players):
# Define the players. Necessary parameter.
self.players = players
# Define who starts the game. Necessary parameter.
self.nplayer = 1
# Overall number of coins in the pile
self.num_coins = 25
# Define max number of coins per move
self.max_coins = 4
# Define possible moves. 1 to 4 coins in the example
def possible_moves(self):
return [str(x) for x in range(1, self.max_coins + 1)]
# Remove coins
def make_move(self, move):
self.num_coins -= int(move)
# Did the opponent or I take the last coin?
def win(self):
return self.num_coins <= 0
# Stop the game when somebody wins
def is_over(self):
return self.win()
# Compute score
def scoring(self):
return 100 if self.win() else 0
# Show number of coins remaining in the pile
def show(self):
print(self.num_coins, 'coins left in the pile')
if __name__ == "__main__":
# Define the transposition(전치) table, saving the location and movement
tt = TT()
# Define the method returning the # of coins remaining
LastCoinStanding.ttentry = lambda self: self.num_coins
# Solve the game
result, depth, move = id_solve(LastCoinStanding,
range(2, 20), win_score=100, tt=tt)
print(result, depth, move)
# Start the game
game = LastCoinStanding([AI_Player(tt), Human_Player()])
game.play()
/Users/eunseo-ko/AIStudy/ESKAI/.venv/bin/python /Users/eunseo-ko/AIStudy/ESKAI/ch09/coins.py
d:2, a:0, m:1
d:3, a:0, m:1
d:4, a:0, m:1
d:5, a:0, m:1
d:6, a:0, m:1
d:7, a:0, m:1
d:8, a:0, m:1
d:9, a:0, m:1
d:10, a:100, m:4
1 10 4
25 coins left in the pile
Move #1: player 1 plays 4 :
21 coins left in the pile
Player 2 what do you play ? 1
Move #2: player 2 plays 1 :
20 coins left in the pile
Move #3: player 1 plays 4 :
16 coins left in the pile
Player 2 what do you play ? 4
Move #4: player 2 plays 4 :
12 coins left in the pile
Move #5: player 1 plays 1 :
11 coins left in the pile
Player 2 what do you play ? 1
Move #6: player 2 plays 1 :
10 coins left in the pile
Move #7: player 1 plays 4 :
6 coins left in the pile
Player 2 what do you play ? 1
Move #8: player 2 plays 1 :
5 coins left in the pile
Move #9: player 1 plays 4 :
1 coins left in the pile
Player 2 what do you play ? 1
Move #10: player 2 plays 1 :
0 coins left in the pile
Process finished with exit code 0
# This is a variant of the Tic Tac Toe recipe given in the easyAI library
from easyAI import TwoPlayersGame, AI_Player, Negamax
from easyAI.Player import Human_Player
class GameController(TwoPlayersGame):
def __init__(self, players):
# Define the players
self.players = players
# Define who starts the game
self.nplayer = 1
# Define the board - 3x3 board in this example
self.board = [0] * 9
# Define possible moves
def possible_moves(self):
return [a + 1 for a, b in enumerate(self.board) if b == 0]
# Make a move
def make_move(self, move):
self.board[int(move) - 1] = self.nplayer
# Does the opponent have three in a line?
def loss_condition(self):
possible_combinations = [[1, 2, 3], [4, 5, 6], [7, 8, 9],
[1, 4, 7], [2, 5, 8], [3, 6, 9], [1, 5, 9], [3, 5, 7]]
return any([all([(self.board[i - 1] == self.nopponent)
for i in combination]) for combination in possible_combinations])
# Check if the game is over
def is_over(self):
return (self.possible_moves() == []) or self.loss_condition()
# Show current position
def show(self):
print('\n' + '\n'.join([' '.join([['.', 'O', 'X'][self.board[3 * j + i]]
for i in range(3)]) for j in range(3)]))
# Compute the score
def scoring(self):
return -100 if self.loss_condition() else 0
if __name__ == "__main__":
# Define the algorithm - depth of tree = 7 in this example
algorithm = Negamax(7)
# Start the game
GameController([Human_Player(), AI_Player(algorithm)]).play()
/Users/eunseo-ko/AIStudy/ESKAI/.venv/bin/python /Users/eunseo-ko/AIStudy/ESKAI/ch09/tic_tac_toe.py
. . .
. . .
. . .
Player 1 what do you play ? 5
Move #1: player 1 plays 5 :
. . .
. O .
. . .
Move #2: player 2 plays 1 :
X . .
. O .
. . .
Player 1 what do you play ? 3
Move #3: player 1 plays 3 :
X . O
. O .
. . .
Move #4: player 2 plays 7 :
X . O
. O .
X . .
Player 1 what do you play ? 9
Move #5: player 1 plays 9 :
X . O
. O .
X . O
Move #6: player 2 plays 4 :
X . O
X O .
X . O
Process finished with exit code 0