From 839093e3f15c0f0ee37a44d06a02ca128504cf19 Mon Sep 17 00:00:00 2001 From: Philipp Horstenkamp Date: Sun, 12 Feb 2023 16:35:53 +0100 Subject: [PATCH] Added a text implementing the search for possible turns. --- main.ipynb | 48 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 41 insertions(+), 7 deletions(-) diff --git a/main.ipynb b/main.ipynb index 5b76f0e..31c7575 100644 --- a/main.ipynb +++ b/main.ipynb @@ -391,6 +391,27 @@ " plt.show()" ] }, + { + "cell_type": "markdown", + "source": [ + "## Find possible actions to take\n", + "\n", + "The frist step in the implementation of an AI like this is to get an overview over the possible actions that can be taken in a situation.\n", + "Here was the design choice taken to first find fields that are empty and have at least one neighbouring enemy stone.\n", + "This was implemented with element wise check for a stone and a binary dilation marking all fields neighboring an enemy stone.\n", + "For that the `SURROUNDING` mask was used. Both aries are then element wise combined using and.\n", + "The resulting array contains all filed where a turn could potentially be made. Those are then check in detail.\n", + "The previous element wise operations on the numpy array increase the spead for this operation dramatically.\n", + "\n", + "The check for a possible turn is done in detail by following each direction step by step as long as there are enemy stones in that direction.\n", + "If the board end is reached or en empty filed before reaching a field occupied by the player that direction does not surround enemy stones.\n", + "If one direction surrounds enemy stone a turn is possible.\n", + "This detailed step is implemented as a recursion and need to go at leas one step to return True." + ], + "metadata": { + "collapsed": false + } + }, { "cell_type": "code", "execution_count": 10, @@ -408,7 +429,9 @@ } ], "source": [ - "SURROUNDING: Final = np.array([[[1, 1, 1], [1, 0, 1], [1, 1, 1]]])\n", + "SURROUNDING: Final = np.array(\n", + " [[[1, 1, 1], [1, 0, 1], [1, 1, 1]]]\n", + ") # defines the binary dilation mask to check if a field is next to an enemy stones\n", "SURROUNDING" ] }, @@ -427,15 +450,26 @@ } ], "source": [ - "def recursive_steps(_array, rec_direction, rec_position, step_one=True) -> bool:\n", + "def _recursive_steps(board, rec_direction, rec_position, step_one=True) -> bool:\n", + " \"\"\"Check if a player can place a stone on the board specified in the direction specified and direction specified.\n", + "\n", + " Args:\n", + " board: The board that should be checked for a playable action.\n", + " rec_direction: The direction that should be checked.\n", + " rec_position: The position that should be checked.\n", + " step_one:\n", + "\n", + " Returns:\n", + "\n", + " \"\"\"\n", " rec_position = rec_position + rec_direction\n", " if np.any((rec_position >= BOARD_SIZE) | (rec_position < 0)):\n", " return False\n", - " next_field = _array[tuple(rec_position.tolist())]\n", + " next_field = board[tuple(rec_position.tolist())]\n", " if next_field == 0:\n", " return False\n", " if next_field == -1:\n", - " return recursive_steps(_array, rec_direction, rec_position, step_one=False)\n", + " return _recursive_steps(board, rec_direction, rec_position, step_one=False)\n", " if next_field == 1:\n", " return not step_one\n", "\n", @@ -456,7 +490,7 @@ " position = idx, idy\n", " if _poss_turns[game, idx, idy]:\n", " _poss_turns[game, idx, idy] = any(\n", - " recursive_steps(boards[game, :, :], direction, position)\n", + " _recursive_steps(boards[game, :, :], direction, position)\n", " for direction in DIRECTIONS\n", " )\n", " return _poss_turns\n", @@ -512,7 +546,7 @@ " if np.all(move == -1):\n", " return not np.any(get_possible_turns(np.reshape(board, (1, 8, 8))))\n", " return any(\n", - " recursive_steps(board[:, :], direction, move) for direction in DIRECTIONS\n", + " _recursive_steps(board[:, :], direction, move) for direction in DIRECTIONS\n", " )\n", "\n", "\n", @@ -540,7 +574,7 @@ " )\n", " else:\n", " arr_moves_possible[game] = any(\n", - " recursive_steps(boards[game, :, :], direction, moves[game])\n", + " _recursive_steps(boards[game, :, :], direction, moves[game])\n", " for direction in DIRECTIONS\n", " )\n", " return arr_moves_possible\n",