This is a project dedicated to creating and training an AI to play pro level checkers/draughts for UAF CS 405/605.
PROJ2
- Create a neural network with random weights. (2/18, JH)
- Solve the neural network. (2/18, JH)
- Add a minimax search with a piece count evaluation function. (2/XX, JK)
PROJ3
- Modify random neural network to specified uniformly distributed range. (2/18, JH)
- Given neural network, create offspring. (2/18, JH)
- Test program to check correctly generated Gaussian pseudo-random values (non NN-related).
- Test program to check offspring lie on the Gaussian curve.
PROJ4
- Implement alpha-beta pruning.
- Generation manager (
OffspringProducer
). - Determine file storage structure.
- Testing (hand examine games played & test children in Gaussian curve).
- g++ compliant files added in
g++_timing_exes
. If the executables do not work for you, I have instructions also in that directory if you need it.
- Apply board evaluation function to mini-max/alpha-beta.
- Feed piece count into final board eval (can this be done with just two connectors?).
- Testing for
NeuralNetwork_PERF
(for result of layer 1 first node). - Modify draw condition.
- Calculate and record branch factor. (mini max or alpha beta)
- Calculate leaf nodes evaluated. (mini max or alpha beta)
- Record leaf nodes evaluated.
- Calculate and record expanded (but not evaluated) nodes. (mini max or alpha beta)
- Remove original
NeuralNetwork
. - Implement alpha-beta pruning. (JK)
- Implement iterative deepening search if time allows.
- Decide topology.
- Provide time per generation trained values. (IDEALLY 3 SEC/n-PLY-GAME FOR 100 GEN IN 12 HOURS -- n == optimal ply per device)
- JH: 80 minutes/4-ply-generation without alpha-beta pruning (surface pro 3).
- 40 s/4-ply-game without alpha-beta pruning (average over 8 games).
- 28 s/4-ply-game WITH alpha-beta pruning (average over 26 games).
- 26 s/4-ply-game WITH alpha-beta pruning but with dummy all 1 inputs (average over 16 games) (this also included time to construct each dummy input).
- JK:
- AM:
- JH: 80 minutes/4-ply-generation without alpha-beta pruning (surface pro 3).
- Examine children and provide proof for correct offspring production.
- Don't record unfinished games.
- OPTIMIZE FOR TRAINING SPEED.
- Here is the YouTube video that worked for me on getting SFML to work.
- Here is documentation for pragma optimize to get more accurate timing.
- 4-PLY TIMING RESULTS WITH ALPHA-BETA PRUNING
- Average number of moves per game: 57.5
- Average seconds per game: 28.6
- Average moves/sec: 2.2
- Global bool
GLOBAL_DO_WRITE
set as false (can change) so that unfinished games are not constantly recorded due to testing. REPLAY_SAVED_GAME
now handles replaying games consecutively.
- Using raw arrays when applicable.
- Fixed ambiguity of setting evaluated board as positive no matter whose turn (player ID handled outside) for
alpha_beta
. input
values inNeuralNetwork_PERF::set_input_layer
casted to double (not sure if this was truncating values).
- Class
NeuralNetwork_PERF
:- now requires player initialization so that
m_player_modifier
is initialized with constructor. - no longer has an issue where the piece count layer was not applying
m_player_modifier
. - has new function
get_player_modification
which returnsm_player_modifier
for tracking purposes (may not be useful).
- now requires player initialization so that
- Class
OffspringProducer
:- no longer has an issue with incorrect declaration of topology size (brought up by the piece count layer).
- Function
min_max_search
:- uses a raw array now in attempt to meet computation speed requirement.
- now does NOT handle player identity (as it is handled
NeuralNetwork_PERF
itself throughm_player_modifier
).- This seems to have fixed the issue of suicidal networks.
- New global int
call_count
to keep track ofmin_max_search
calls. Related calculations (leaf nodes, non-leaf nodes, etc) are presented inLNE.txt
(I forget what this stands for). - Cleaned up
main.cpp
's AI move chooser. - Watch
wtf.txt
inprevious_gen_data
for an interesting GEN0 game.
- Changed
min_max_search
: return value isdouble
, or else truncates to0
causing incorrect decision making. - Above is done to
alpha_beta
as well. - Fixed
NeuralNetwork_PERF
whereget_output
was returning the item one past the end. - Networks should be training correctly now; though through playing
GEN0 nn0
, I've noticed a "feed the king" behavior which may or may not be subjected to just that particular network. - I will run some training tonight (3/23, JH).
- Removed
NeuralNetwork
class. - New global int
eval_count
that will count leaf nodes evaluated and console print it. - New function
piece_count_search
for non-network pure-piece-count AI algorithm. - New
main_state
NNP_test
for testingNeuralNetwork_PERF
; tests successful: may delete soon. - New function
fn_play_checkers
to attempt to implement easier AI type switching, though may not be useful. - Discovered issue with
NNvNN
where networks recieved topologies with delimiters and used delimiters as play/evolutionary values.
main_state
NERUAL_NETWORK_OFFSPRING
renamed toGEN0_GENERATE
(call this to produce 30 random networks for GEN0).- Modified
REPLAY_SAVED_GAME
to allow for replaying drawed games. - New setting for
NNvNN
gens_to_train
. - Timing done for each generation and stored in
timing.txt
innn_topologies
. - New function
NeuralNetwork_PERF::set_player
to hopeufully fix the issue of both networks playing for the same side.
- With version 6.3, some network plays were very questionable and seemed like it did not consider piece count what-so-ever.
- I will provide all games of NN20 (best performing) of GEN9 for replay purposes.
- This is located in
previous_gen_folder
folder.
- This is located in
- Voiding
MAIN_STATE::PLAY_CHECKERS
because of interactivity with modifiedmin_max_search
. min_max_search
now takesNeuralNetwork_PERF
as an additional parameter and calculates each "leaf board" (at the end of the ply).- Increase modularity for
NeuralNetwork_PERF
to allow mutation to same object during runtime. - New function
NeuralNetwork_PERF::get_result
returns result (formin_max_search
to eat). - New function
temp_Board::get_board_as_vector
returnsm_board
. - New training method (ply = 2) takes ~35 minutes to train 10 generations.
- Created
results.txt
perNNvNN
generation.- Per line, the active network ID is followed by 5 networks played, then followed by results of the game, respectively (space delimited).
- Storage structure:
GEN#GENID#
directory contains:- all 30 network topologies
games_played_#GENID#
directory for games played- games played
- 150 games result file (
result.txt
) (this will allow easier determination for which networks survived)
- example access to generation 5 game results:
fin.open("ai-playing-checkers//nn_topologies//GEN5//games_played_5//result.txt", ifstream::in);
- QUES: Should the set of 5 games played by each network switch who starts first?
- QUES: Record lineage?
- Ply of evaluation is 4.
- Uses
NerualNetwork_PERF::calculate
formini_max_search
return values. - Fixed
OffspringProducer
issues with vector indicies. - More comments in
OffspringProducer.cpp
. NNvNN
now trains through 10 generations with 1 ply mini max (CURRENTLY NO BOARD EVALUATIONS!!!).- INSTRUCTIONS TO RECREATE:
- Delete all GENX directories (leave naming_status.txt).
- Run
NEURAL_NETWORK_OFFSPRING
to produce 0th generation randomly generated networks. - Run
NNvNN
and set desired generations (default to 10, at the moment) to train.- 10 generations with 1 ply is about 5~10 minutes, roughly.
- Produces offspring for the 10th generation but does not play itself on 10th generation.
- Interestingly, 1 ply mini max values kings as at least 2.0.
- INSTRUCTIONS TO RECREATE:
- New
OffspringProducer
functions:determine_survivors
: setsm_survived_parents
to all topologies that placed top 15 (in string form).produce_next_generation
: records survivors from previous generation and callsproduce_offspring
on it. Offspring topologies come right after parent topologies after GEN0.- TODO: Perhaps collapse
determine_survivors
into this function.
- TODO: Perhaps collapse
get_current_generation_id
: returns generation ID according to naming_status.txt.
- New
main_state
NNvNN
which handles network vs network play. main_state
sNEURAL_NETWORK_TESTING
andNEURAL_NETWORK_TIMING
removed due to irrelevance.- New generations generate new folder within directory to hold games played.
- Heuristics of network vs network:
- Active network is always red.
- Opposing network plays first move.
- 3 randomly generated moves will be made at the beginning.
- Networks will not play itself or a repeated network.
- Reaching move 100 indicates a draw.
- Networks use 4-ply for minimax iteration.
- 5 games per network with population of 30 networks: 150 games played.
- Games played stored in
games_played_#GENID#
folder found in respective generation directory where#GENID#
is replaced with the generation it is in.- Gameplay results will also be stored in that folder under
results.txt
. - Games played will be named
#ACTIVE#_#OPPO#.txt
.
- Gameplay results will also be stored in that folder under
- Completed saved games can now be replayed using the
REPLAY_SAVED_GAME
option for themain_state
. - The controls for this option are as follows:
Spacebar
: toggles automatic/manual stepping modes; manual stepping is the default stepping mode. When in automatic stepping mode, manual stepping mode can also be engaged by pressing either the left or right arrow key.Right Arrow Key
: steps forward in manual stepping mode.Left Arrow Key
: steps backward in manual stepping mode.- The
R
key: restarts the board when end of game has been reached in automatic stepping mode. - The
Q
key: to quit.
- New class
OffspringProducer
added. This class- generates random parent topology.
- records parent topology to specified directory.
- This currently only supports a single generation and a population of 30.
- King value and weights are delimited by
9999
while weights and sigma variables are delimited by8888
. ofstream::trunc
is used as an argument so previous topology text files will be overwritten permain
run.
- read and writes to
nn_topologies\naming_status.txt
to perform network naming. - does not produce offspring yet.
- New
main_state
NEURAL_NETWORK_OFFSPRING
. - Class
NeuralNetwork_PERF
topology generation moved toOffspringProducer
for reasons:- Declutter
NeuralNetwork_PERF
. - Array [] operations were somehow getting overwritten when transferring from
NeuralNetwork_PERF
toOffspringProducer
.
- Declutter
topo_proof_x.txt
files added as readable verification that the current version of topology generator works correctly.- Added separate Gaussian number generator with graphs. This can be found in
gnugraph
along with further documentation for the generator.- The main for the Gaussian number generator has been merged into
main.cpp
.
- The main for the Gaussian number generator has been merged into
- New class
NeuralNetwork_PERF
added. - New class provides about estimated 130% performance of
NeuralNetwork
. - For some reason,
NeuralNetwork
timing became about 30% slower with recent runs (crowdedmain.cpp
? new testing calculation functions added toNeuralNetwork
? just machine things?). - On my(JH) machine, it is currently consistent around 95,000 BEF/sec with the sigmoid function (slightly worse than
NeuralNetwork
, but better now withNeuralNetwork
slowing down). - New
main_state
NEURAL_NETWORK_TIMING_PERF
for timingNeuralNetwork_PERF
. - No current test cases for
NeuralNetwork_PERF
.
NeuralNetwork
now uses arrays for calculations instead. Uses hard coded values for sizes.- Both
std::vector
andstd::array
compute at least 10 (100? forgot the numbers) times slower than using arrays, thus array computation have been chosen.- I can provide the code for the tests if needed.
- Due to the nature of arrays, their size is statically allocated thus hard-coded global values are used for initialization.
- Hard-coded values apply to Blonde24 and simple test-case of 4-3-2-1 topology.
- Both
NeuralNetwork
BEF/sec is now roughly 150,000 WITHOUT applying sigmoid.NeuralNetwork
BEF/sec is around 100,000 with sigmoid on my machine.Main.cpp
now has new states forPLAY_CHECKERS
,NEURAL_NETWORK_TESTING
, andNEURAL_NETWORK_TIMING
for ease of switching betweenmain_modes
(thusNeuralNetwork_main.cpp
is now merged withmain.cpp
).- Testing mode implemented in
NEURAL_NETWORK_TESTING
.
- Classes
Connector
andNNNodes
removed for simplicity. - Class
NeuralNetwork
now computes the "board evaluation" (Now calledcalculate_output
). - Class
NeuralNetwork
now require more modular initialization. - King value, weights, and sigma are saved to a file.
- Class
NeuralNetwork
now applies sigmoid function (forgot about this in the previous commit). - Fixed an issue where
NeuralNetwork
would initialize new weights per board evaluation instead of using the previous ones. - Timing done in
NeuralNetwork_main.cpp
for average BEF/sec and BEF/15 sec: averaging around 700~900 BEF per second (that's OK??) NeuralNetwork_main.cpp
now also tests the timing for a six layer >10,000 weightsNeuralNetwork
and prints the related calculations (requirements 1 & 2 fulfilled for PROJ2 deliverables).NeuralNetwork
now writes its topology values to filebrunette26_topology_gen0.txt
within thenn_topologies
with first line as them_king_value
and the subsequent lines as a pair of weight and its corresponding sigma value.- User must use
NeuralNetwork::set_generate_file(true)
to write the topology, as it is set to false on default. - Topologies now have unique names in the same style as recorded games. Note that this name does not correlate the recorded game file to the topology file generated for it (would it be preferable to give topologies the same date/time as the recorded game that they are generated for?).
- User must use
- Live piece count displayed.
- AI player now prioritizes piece count when deciding its next move.
- New class
Connector
with randomized weights. - Each
NNNodes
in theNeuralNetwork
has the correct amount ofConnectors
to the next layer. Connectors
generate randomized values correctly.- Working on reading game data for function
NeuralNetwork::board_evaluation
. process_output
rewritten to do that, code has been added toboard_evaluation
to read in, parse, and store the data.
- New
temp_Board
functionwrite_board_to_file
that takes a file name and write the board status of all 32 positions for every single move made in a compressed binary style.
Playable | Red Soldier | Red King | Black Soldier | Black King | |
---|---|---|---|---|---|
Binary | 100 |
010 |
011 |
000 |
001 |
Hex | 0x4 |
0x2 |
0x3 |
0x0 |
0x1 |
- The data is stored by rows and each row is denoted by a unsigned short (16-bit) and the first 4 bits are not used. For example, the decimal value
1170
is0000010010010010
in binary, and is broken up into0000
010
010
010
010
where the 3-bit sections represent the piece type (in the table above). - I am unsure if storing them as binary/hex will cost less memory, please alter accordingly if you please.
- Integers are stored memory in binary format already.
NNNodes
objects now use a new sigmoid function for processing inputs. This allows for the range of inputs/output to be in the range of -1 and 1.
- New classes
NeuralNetwork
andNNNodes
for creating AI. - New classes are currently useless.
- Right arrow key now generates a random move for whosever turn it is.
- Resource files (
*.png
and*.ttf
files) are now stored in theres
directory.
- Identified issue causing crash where both players are to be random AI and only one piece is remaining on either side, it was because of attempted division by 0 when randomizing. Issue is now resolved.
- Added images and replaced
CircleShape piece
withSprite piece
. - Window does not auto-close at end of game and notes who the winner is.
- "The player who cannot move, because he has no pieces, or because all of his pieces are blocked, loses the game." http://www.chesslab.com/rules/CheckerComments.html
temp_Board
objects now allow either player to go first.- Allows (ish) for both players to be random AI (when
black_is_ai
andred_is_ai
are both set to true and there is only one piece remaining from either side, the game crashes). - Above seems to be resolved (?). Just did a game that ended with 0 black pieces.
- Added a delay between each move for viewing.
- Save the moves made and win status and output it to a text file.
- When the program is run, a game file (
.txt
) is created; the generated file name contains the current date and time. The file contents are space-delimited and each line containsr
orb
followed by the move it took, except for the last line which is eitherR
orB
depending on who won the game.
- Pieces are now displayed smaller allowing the top left corner of the playable slot to display slot id (for easier debugging and/or readability).
- Changed the white board base because it hurts my eyes a little.
- Now sports a classy dark brown board base.
- New class
temp_Board
is used to keep track of board status and pieces. - Deleted
piece.cpp
andpiece.h
files. - King moves and jumps correctly for single pieces.
- In order to perform a multi-jump, the user must override mouse-click mode by pressing the
M
key and choose a move ID. - Move IDs can be generated by pressing the
F
key. - Simple GUI implemented (with selection indication included).
- Right side of GUI to be implemented as move display, or something to the likes.
_RED_
player is by default and AI with random moves generated and_BLACK_
is user.
- Soft save so progress is not lost.
- Kings are now able to jump in opposite direction.
- Kings are not displayed correctly when they move from king spot.
- 3.2.1 hot fix(?) Kings are now displayed correctly at all times.
- Kings now update and print correctly when they reach the king spots.
- King are not able to jump in the opposite direction (can move in opposite direction).
- Soft save so progress is not lost.
- Player 1 and 2 are now renamed to Player BLACK and RED, respectively.
- Black pieces are now at the bottom (as required for assignment).
- Various new data members and functions to store and retrieve moves made, moves possible, and jumps possible.
valid_man_move
is renamed togenerate_valid_moves
with different functionality. The function now generates all possible moves and stores inm_all_possible_xxxxx_for_current_player
.- Fixed an issue where
m_alive == dead
Piece objects were still left on the board and considered in play. - Beginning stages of king transformation attempted to be implemented.
main.cpp
now allows for more interactive debugging with taking console input.move_piece
function now takes the location of a piece as its first parameter (as opposed topiece_id
). Invalid locations allow player to retry a different location.
- All files updated.
move_piece
allows both players to move to empty spaces and jump correctly.- New Board function
ownership_check
to make sure opposing player cannot move each other's pieces. - New Board function
valid_man_move
to check if move declared bymove_piece
is a valid move, and initiates jump events if needed (for man/men/non-king units only). - New Board function
get_piece_id
retrieves the ID of a Piece object located on a certain position on the board (kind of sketchy, but it seems to work ok and I don't know how else to retreive the piece's index). - Piece objects now keep track of their livelihood through
m_alive
.
- All files updated.
- Board function
move_piece
allows movement for player 1 (starting player). - New Board functions
init_board
,clear_board
,is_boarder
, andupdate_board
used to update Board object correctly forprint_board
. - Board construction now only initializes values.
- Various new data members for Board objects to keep track of Piece object owners and turn order.
- New Board function
pass_turn
and turn checking inmove_piece
not working properly (fixed: issue #1).
- All relevant current files added.
- Board object creates a 12 by 12 board with a boarder with width of 2.
- Board object correctly generates Piece objects according to playable positions.
- Board function
print_board
displays Board object for debugging purposes. - Piece objects display correct *true positions and directions (*numerical position starting at top left and incrementing right).
- Piece objects may become king, however no movements currently allow it.
main.cpp
draws the Board object and displays existing Piece values.
- Currently working on collision check/move piece functions. Feel free to make your own and/or put together a GUI! (1/24, JH)
-
Currently working on implementing king transformations/movements.(1/25, JH) - Currently working on all possible move generation. (1/25, JH)
- Currently working on implementing king movements and debugging transformation. (1/26, JH)
-
Currently working on implementing multijumping.(1/29, JH) - Currently working on implementing mouse click based GUI. (1/31, JH)
-
Currently contemplating if SFML related objects should be handled within a class.No for now. (2/1, JH) -
Devising a way to playback and store game info.Game info storing done by someone else. (2/6, JH) - Random move generated by using right arrow. (2/13, JH)
-
Left arrow should move backwards?I'm ok on that. (2/13, JH) - Figuring out how to implement the neural network. (2/14, JH)
-
NeuralNetwork
should iterate through all boards (currently only one). (2/17, JH) - Further optimize speed for
calculate_output
? (2/18, JH)- (below are timing results of
NeuralNetwork_PERF
) - 90,000 BEF/sec => compiled with Visual Studio on a Surface Pro 3 with -O2 turned on
- 120,000 BEF/sec => compiled with g++ on the desktop in the computer lab without -O2 turned on
- 290,000 BEF/sec => compiled with g++ on the desktop in the computer lab with -O2 turned on
- (below are timing results of
- Asexually reproducing
brunette26
. (2/18, JH) - Working on implementing
NeuralNetwork_PERF
'scalculate
function tomini_max_search
. (3/15, JH) - Here's a potentially helpful chart for all the playable positions:
P | L | A | Y | A | B | L | E |
---|---|---|---|---|---|---|---|
x | 0 | x | 1 | x | 2 | x | 3 |
4 | x | 5 | x | 6 | x | 7 | x |
x | 8 | x | 9 | x | 10 | x | 11 |
12 | x | 13 | x | 14 | x | 15 | x |
x | 16 | x | 17 | x | 18 | x | 19 |
20 | x | 21 | x | 22 | x | 23 | x |
x | 24 | x | 25 | x | 26 | x | 27 |
28 | x | 29 | x | 30 | x | 31 | x |