ConnectFour is a simple game that involves two players taking turns to place tokens in a grid. When one player assembles a line of four tokens, they win! Compete with friends and see who can write the best ConnectFour algorithm.
The only pre-requisite needed to run ConnectFour is python3.
Once installed, navigate to the project directory and run a ConnectFour match by entering the following in the command line:
python connect_four_match.py
Next register the first player's name and you will be asked to select a strategy. Each strategy presented is loaded from a strategy subclass in the /strategies
directory. Strategies and how to implement them will be expanded upon further on but they are how a player determines which move they should make.
Repeat the process for the second player and the match should begin!
Select the StdInStrategy
when presented with the strategy list and that player will be driven by user input via the command line. This can be useful when testing strategies you are implementing.
A human vs human game can be set up by having both players select the StdInStrategy
.
In a best of 3 series, a maximum of 3 games will be played to determine the winner. After each game, the player going first will be alternated so one player is not given an advantage. Play a series by using the -n
argument when starting a match, for example:
python connect_four_match.py -n 3
Once multiple strategies have been implemented, you can run a round robin tournament to determine rankings by using the following command:
python connect_four_tournament.py
A tournament will play matches for each pair of players and then use the accumulated scores to determine a ranking. You can change the number of players by tweaking the number_of_players
variable in /connect_four_tournament.py
.
To write a new strategy, add a new subclass of the core.Strategy
class. It has a single responsibility, to determine which column the player should place their token in.
class Strategy:
def place_token(self, token, board):
raise NotImplementedError("Implement this method in your subclass.")
The token argument specifies which token the player is placing, either a 1
or a 2
. Use this to identify which tokens in the board are yours and plan accordingly.
The board argument is a 2D array that represents the current state of the game. Here is an example of how the board might be filled:
board = [
[0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0]
[0, 0, 1, 0, 0, 2, 0]
]
A 0
represents an empty spot, a 1
represents a token placed by the first player and a 2
represents a token placed by the second player. When a player chooses a column, their token will then be placed in the lowest empty spot for that column.
The output of the place_token
method should be the index of the column that you want to place your token in. Placing a token in a out-of-bounds index or into a column that is full will mean that you lose the game, so choose carefully!
To export your strategy there are two requirements:
- Place your strategy in the
/strategies
directory - Add a
export_strategy
function to your python script
Here is an example implementation of a Strategy with the export_strategy
function included:
class MyStrategy(Strategy):
def place_token(self, token, board):
return -1
def export_strategy():
return MyStrategy()
This function will return an instance of your strategy when needed. It is used when registering a player and selecting which strategy the player should use.
Once it is ready to be exported, test your strategy by selecting it at the start of a match. Try testing it against other algorithms to see how it fares and what its weaknesses are. Also try test it against yourself using the StdInStrategy
.
You can also test your strategy's decision making in a variety of single-move scenarios designed to cover fundamentals in attacking and defending. This is accomplished by running the fundamentals_tests.py
script and supplying the name of your strategy's module.
# Run the fundamentals tests for left_to_right_strategy
python fundamentals_tests.py left_to_right_strategy
# Run the fundamentals tests, printing the board state for each test
python fundamentals_tests.py left_to_right_strategy --visuals
You may find poor results if your strategy relies heavily on state as the board is pre-built.
For an easy example, try reading through /strategies/left_to_right_strategy.py
from .strategy import Strategy
class LeftToRightStrategy(Strategy):
def place_token(self, token, board):
top_row = board[0]
for x in range(len(top_row)):
if top_row[x] == 0:
return x
return -1
def export_strategy():
return LeftToRightStrategy()
If none of the top rows are empty then returning -1 essentially means giving up because it is not a valid column index.
Check out how your strategy considers the board by running the following command:
python training_dummy.py
Select the target strategy and then face off against it in a single match. When the selected strategy is selecting a column to place its token, a separate window will display how it is accessing the board. The red square denotes the token which indices (x,y) are being used. Serves no real purpose other than to look cool!