|
import numpy as np |
|
import pytest |
|
from easydict import EasyDict |
|
|
|
from connect4_env import Connect4Env |
|
from zoo.board_games.connect4.envs.rule_bot import Connect4RuleBot |
|
|
|
|
|
@pytest.mark.unittest |
|
class TestConnect4RuleBot(): |
|
""" |
|
Overview: |
|
This class is used to test the Connect4RuleBot class methods. |
|
""" |
|
|
|
def setup(self) -> None: |
|
""" |
|
Overview: |
|
This method is responsible for setting up the initial configurations required for the game environment. |
|
It creates an instance of the Connect4Env class and Connect4RuleBot class. |
|
""" |
|
cfg = EasyDict( |
|
battle_mode='self_play_mode', |
|
battle_mode_in_simulation_env='self_play_mode', |
|
render_mode='state_realtime_mode', |
|
channel_last=False, |
|
scale=True, |
|
agent_vs_human=False, |
|
prob_random_agent=0, |
|
prob_expert_agent=0, |
|
bot_action_type='rule', |
|
screen_scaling=9, |
|
save_replay=False, |
|
prob_random_action_in_bot=0 |
|
) |
|
self.env = Connect4Env(cfg) |
|
self.player = 1 |
|
self.bot = Connect4RuleBot(self.env, self.player) |
|
|
|
def test_is_winning_move(self) -> None: |
|
""" |
|
Overview: |
|
This test method creates a game situation where the bot has three consecutive pieces in the board. |
|
It tests the `is_winning_move` method of the Connect4RuleBot class by asserting that the method returns True |
|
when a winning move is possible for the bot. |
|
""" |
|
|
|
board = np.zeros((6, 7)) |
|
board[5][3] = self.player |
|
board[5][4] = self.player |
|
board[5][5] = self.player |
|
self.bot.board = board |
|
assert self.bot.is_winning_move(2) is True |
|
|
|
def test_is_winning_move_in_two_steps(self) -> None: |
|
board = np.zeros((6, 7)) |
|
board[5][3] = self.player |
|
board[5][4] = self.player |
|
self.bot.board = board |
|
assert self.bot.is_winning_move_in_two_steps(2) is True |
|
board = np.zeros((6, 7)) |
|
board[5][3] = self.player |
|
board[5][4] = self.player |
|
board[5][0] = 3 - self.player |
|
board[4][0] = 3 - self.player |
|
board[3][0] = 3 - self.player |
|
self.bot.board = board |
|
assert self.bot.is_winning_move_in_two_steps(2) is False |
|
|
|
def test_is_blocking_move(self) -> None: |
|
""" |
|
Overview: |
|
This test method creates a game situation where the opponent has three consecutive pieces in the board. |
|
It tests the `is_blocking_move` method of the Connect4RuleBot class by asserting that the method returns True |
|
when a blocking move is necessary to prevent the opponent from winning. |
|
""" |
|
""" |
|
# Create a chessboard with three consecutive pieces. |
|
board = np.zeros((6, 7)) |
|
opponent = 2 if self.player == 1 else 1 |
|
board[5][3] = opponent |
|
board[5][4] = opponent |
|
board[5][5] = opponent |
|
self.bot.board = board |
|
assert self.bot.is_blocking_move(2) is True # Placing a piece in the second column is a move to prevent the opponent from winning. |
|
""" |
|
|
|
|
|
self.bot.current_player = 2 |
|
board = np.array([[1, 0, 0, 0, 0, 0, 0], |
|
[1, 0, 1, 0, 0, 0, 0], |
|
[2, 0, 2, 0, 0, 0, 0], |
|
[1, 1, 1, 0, 0, 0, 0], |
|
[1, 2, 2, 1, 0, 0, 2], |
|
[1, 2, 2, 2, 1, 0, 0]]) |
|
self.bot.board = board |
|
assert self.bot.is_blocking_move(3) is True |
|
|
|
def test_is_sequence_3_move(self) -> None: |
|
""" |
|
Overview: |
|
This test method creates a game situation where the bot has two consecutive pieces in the board. |
|
It tests the `is_sequence_3_move` method of the Connect4RuleBot class by asserting that the method returns True |
|
when placing a piece next to these two consecutive pieces will create a sequence of 3 pieces. |
|
""" |
|
|
|
board = np.zeros((6, 7)) |
|
board[5][4] = self.player |
|
board[5][5] = self.player |
|
self.bot.board = board |
|
assert self.bot.is_sequence_3_move(3) is True |
|
|
|
def test_is_sequence_2_move(self) -> None: |
|
""" |
|
Overview: |
|
This test method creates a game situation where the bot has a single piece in the board. |
|
It tests the `is_sequence_2_move` method of the Connect4RuleBot class by asserting that the method returns True |
|
when placing a piece next to the single piece will create a sequence of 2 pieces. |
|
It also tests for situations where placing a piece will not result in a sequence of 2 pieces. |
|
""" |
|
|
|
board = np.zeros((6, 7)) |
|
board[5][5] = self.player |
|
self.bot.board = board |
|
assert self.bot.is_sequence_2_move(4) is True |
|
|
|
|
|
board = np.array([[0, 0, 0, 0, 0, 0, 0], |
|
[0, 0, 0, 0, 0, 0, 0], |
|
[0, 0, 0, 0, 2, 0, 0], |
|
[0, 0, 0, 0, 1, 0, 0], |
|
[0, 0, 0, 0, 1, 0, 0], |
|
[0, 0, 0, 2, 2, 0, 0]]) |
|
self.bot.board = board |
|
assert self.bot.is_sequence_2_move(5) is True |
|
assert self.bot.is_sequence_2_move(4) is False |
|
assert self.bot.is_sequence_2_move(6) is False |
|
|
|
def test_get_action(self) -> None: |
|
""" |
|
Overview: |
|
This test method creates a game situation with an empty board. |
|
It tests the `get_rule_bot_action` method of the Connect4RuleBot class by asserting that the method returns an action |
|
that is within the set of legal actions. |
|
""" |
|
board = np.zeros((6, 7)) |
|
self.bot.board = board |
|
action = self.bot.get_rule_bot_action(board, self.player) |
|
assert action in self.env.legal_actions |
|
|
|
def test_remove_actions(self) -> None: |
|
self.bot.next_player = 3 - self.player |
|
board = np.zeros((6, 7)) |
|
board[5][0] = self.player |
|
board[5][3] = self.player |
|
board[5][4] = self.player |
|
board[5][5] = 3 - self.player |
|
board[4][3] = 3 - self.player |
|
board[4][4] = 3 - self.player |
|
board[4][5] = 3 - self.player |
|
self.bot.board = board |
|
self.bot.legal_actions = [i for i in range(7) if board[0][i] == 0] |
|
self.bot.remove_actions() |
|
assert self.bot.legal_actions == [0, 1, 3, 4, 5] |
|
board = np.zeros((6, 7)) |
|
board[5][0] = self.player |
|
board[4][0] = self.player |
|
board[5][3] = 3 - self.player |
|
board[5][4] = 3 - self.player |
|
self.bot.board = board |
|
self.bot.legal_actions = [i for i in range(7) if board[0][i] == 0] |
|
self.bot.remove_actions() |
|
assert self.bot.legal_actions == [0, 2, 5] |