The goal of this project is to allow you to explore artificial intelligence by creating a bot in the Python programming language that plays the game Connect 4:
Connect Four (also known as Captain's Mistress, Four Up, Plot Four, Find Four, Fourplay, Four in a Row, Four in a Line and Gravitrips (in Soviet Union) ) is a two-player connection game in which the players first choose a color and then take turns dropping colored discs from the top into a seven-column, six-row vertically suspended grid. The pieces fall straight down, occupying the next available space within the column. The objective of the game is to be the first to form a horizontal, vertical, or diagonal line of four of one's own discs. -- Wikipedia
In class, we will explore how to represent the Connect 4 board and how to simulate a game between two opponents. For the project, you will need to create a bot that plays as one of the players in the game.
To develop your bot, create a new Jupyter Notebook titled
Project01.ipynb
and use this notebook to program and test your bot.
This Project assignment is due in class Tuesday, November 22, 2016 and is to be done in pairs.
The following is an overview of the code skeleton provided below.
As we will discuss in class, a Connect 4 board can be represented as a two dimensional list:
Board = create_board()
print Board
[[' ', ' ', ' ', ' ', ' ', ' ', ' '],
[' ', ' ', ' ', ' ', ' ', ' ', ' '],
[' ', ' ', ' ', ' ', ' ', ' ', ' '],
[' ', ' ', ' ', ' ', ' ', ' ', ' '],
[' ', ' ', ' ', ' ', ' ', ' ', ' '],
[' ', ' ', ' ', ' ', ' ', ' ', ' ']]
The create_board
function below initializes a board of size ROWS
(i.e.
6
) and COLUMNS
(i.e. 7
) with PIECE_NONE
(i.e. ' ') in each cell.
We can place a piece on the board by doing:
drop_piece(Board, 3, PIECE_ONE)
print_board(Board)
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| | | |x| | | |
This calls the drop_piece
function to place PIECE_ONE
(i.e. x
) into
the column 3
of the board.
To check if there is a winner on the board, we can use the find_winner
function:
winner = find_winner(Board)
if winner:
print 'The winner is {}'.format(winner)
Finally, to display the board using SVG graphics, we can use the create_board_svg
function:
display_html(create_board_svg(Board, 40))
All of these functions are combined into a game simulator given below.
The following is the support code provided to you in class:
# Imports
from IPython.display import display, HTML, clear_output
import random
import time
# Game Constants
ROWS = 6
COLUMNS = 7
PIECE_NONE = ' '
PIECE_ONE = 'x'
PIECE_TWO = 'o'
PIECE_COLOR_MAP = {
PIECE_NONE : 'white',
PIECE_ONE : 'black',
PIECE_TWO : 'red',
}
DIRECTIONS = (
(-1, -1), (-1, 0), (-1, 1),
( 0, -1), ( 0, 1),
( 1, -1), ( 1, 0), ( 1, 1),
)
# Board Functions
def create_board(rows=ROWS, columns=COLUMNS):
''' Creates empty Connect 4 board '''
board = []
for row in range(rows):
board_row = []
for column in range(columns):
board_row.append(PIECE_NONE)
board.append(board_row)
return board
# Copy board
def copy_board(board):
''' Return a copy of the board '''
rows = len(board)
columns = len(board[0])
copied = create_board(rows, columns)
for row in range(rows):
for column in range(columns):
copied[row][column] = board[row][column]
return copied
def print_board(board):
''' Prints Connect 4 board '''
for row in board:
print '|' + '|'.join(row) + '|'
def drop_piece(board, column, piece):
''' Attempts to drop specified piece into the board at the
specified column
If this succeeds, return True, otherwise return False.
'''
for row in reversed(board):
if row[column] == PIECE_NONE:
row[column] = piece
return True
return False
def find_winner(board, length=4):
''' Return whether or not the board has a winner '''
rows = len(board)
columns = len(board[0])
for row in range(rows):
for column in range(columns):
if board[row][column] == PIECE_NONE:
continue
if check_piece(board, row, column, length):
return board[row][column]
return None
def check_piece(board, row, column, length):
''' Return whether or not there is a winning sequence starting from
this piece
'''
rows = len(board)
columns = len(board[0])
for dr, dc in DIRECTIONS:
found_winner = True
for i in range(1, length):
r = row + dr*i
c = column + dc*i
if r not in range(rows) or c not in range(columns):
found_winner = False
break
if board[r][c] != board[row][column]:
found_winner = False
break
if found_winner:
return True
return False
# HTML/SVG Functions
def display_html(s):
''' Display string as HTML '''
display(HTML(s))
def create_board_svg(board, radius):
''' Return SVG string containing graphical representation of board '''
rows = len(board)
columns = len(board[0])
diameter = 2*radius
svg = '<svg height="{}" width="{}">'.format(rows*diameter, columns*diameter)
svg += '<rect width="100%" height="100%" fill="blue"/>'
for row in range(rows):
for column in range(columns):
piece = board[row][column]
color = PIECE_COLOR_MAP[piece]
cx = column*diameter + radius
cy = row*diameter + radius
svg += '<circle cx="{}" cy="{}" r="{}" fill="{}"/>'.format(cx, cy, radius*.75, color)
svg += '</svg>'
return svg
Here are two initial players you can use to test your bot:
def HumanPlayer(board, history, players):
''' Read move from human player '''
columns = len(board[0])
column = -1
while column not in range(0, columns):
column = input('Which column? ')
return column
def RandomPlayer(board, history, players):
''' Randomly select a column '''
columns = len(board[0])
return random.randint(0, columns - 1)
To simulate a game of Connect 4, you may use the following code:
# Globals
Players = (PIECE_ONE, PIECE_TWO)
History = []
Board = create_board()
Radius = 40
Winner = None
Tries = 0
# Game Loop
while not Winner:
turn = len(History)
if turn % 2 == 0:
move = HumanPlayer(Board, History, Players) # Player One
else:
move = RandomPlayer(Board, History, Players) # Player Two
if drop_piece(Board, move, Players[turn % 2]):
Tries = 0
History.append(move)
if Tries > 3:
print 'Player {} is stuck!'.format((turn % 2) + 1)
break
clear_output()
display_html(create_board_svg(Board, Radius))
time.sleep(1)
Winner = find_winner(Board)
print 'The Winner is {}'.format(PIECE_COLOR_MAP[Winner])
Your objective for this project is to create an artificial intelligence agent that can successfully play Connect 4 against humans and other bots. To do so, you will need to define a function:
def BotPlayer(board, history, players):
'''
This is your AI bot player. It is given the following arguments:
Board: This is the current board.
History: This is the history of the previous moves (columns).
Players: This is the list of players.
Your function must not modify any of these objects.
After analyzing the inputs, your bot should return the column that
represents the best possible move.
'''
An example of an artificial intelligence agent is given above in
RandomPlayer
, which simply chooses a random column.
Note: Feel free to rename BotPlayer
to another creative name.
Your bot needs to be better than random placement. In order to get full credit, your bot must do at least the following:
It must select a winning move if it exists.
It must select a blocking move (i.e. prevent opponent from winning) if it exists.
When there is neither a winning move or a blocking move is where your creativity and your bot's intelligence manifests yourself.
One possible strategy is to simulate moves and see which moves gives you the most two-in-a-rows, three-in-a-rows, etc. That is simulate placing a piece in a column and see what the possible outcomes are. You will then need to score and rank each move.
The rigorous way to solve Connect 4 is to implement the Minimax algorithm which would guarantee a win or a tie for your bot.
Use the copy_board
function to create a copy of the board before
simulating a move.
Use the drop_piece
function on the copied board to simulate a move.
Use the find_winner
function to check if there is a winner in the
simulated board.
Use the find_winner
or check_piece
function to test for lengths
other than 4
.
On November 22, we will have a Connect 4 tournament during class where your bot will compete against bots written by other students. The winner of the tournament will face a bot written by the instructional staff and be given extra credit.
To facilitate this tournament, please make sure you submit your Notebook on time and that you have at least one group member present.
To submit your notebook, follow the same directions for Notebook 01.