Added a text implementing the search for possible turns.
This commit is contained in:
parent
bad719c8e6
commit
839093e3f1
48
main.ipynb
48
main.ipynb
@ -391,6 +391,27 @@
|
|||||||
" plt.show()"
|
" 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",
|
"cell_type": "code",
|
||||||
"execution_count": 10,
|
"execution_count": 10,
|
||||||
@ -408,7 +429,9 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"source": [
|
"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"
|
"SURROUNDING"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -427,15 +450,26 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"source": [
|
"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",
|
" rec_position = rec_position + rec_direction\n",
|
||||||
" if np.any((rec_position >= BOARD_SIZE) | (rec_position < 0)):\n",
|
" if np.any((rec_position >= BOARD_SIZE) | (rec_position < 0)):\n",
|
||||||
" return False\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",
|
" if next_field == 0:\n",
|
||||||
" return False\n",
|
" return False\n",
|
||||||
" if next_field == -1:\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",
|
" if next_field == 1:\n",
|
||||||
" return not step_one\n",
|
" return not step_one\n",
|
||||||
"\n",
|
"\n",
|
||||||
@ -456,7 +490,7 @@
|
|||||||
" position = idx, idy\n",
|
" position = idx, idy\n",
|
||||||
" if _poss_turns[game, idx, idy]:\n",
|
" if _poss_turns[game, idx, idy]:\n",
|
||||||
" _poss_turns[game, idx, idy] = any(\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",
|
" for direction in DIRECTIONS\n",
|
||||||
" )\n",
|
" )\n",
|
||||||
" return _poss_turns\n",
|
" return _poss_turns\n",
|
||||||
@ -512,7 +546,7 @@
|
|||||||
" if np.all(move == -1):\n",
|
" if np.all(move == -1):\n",
|
||||||
" return not np.any(get_possible_turns(np.reshape(board, (1, 8, 8))))\n",
|
" return not np.any(get_possible_turns(np.reshape(board, (1, 8, 8))))\n",
|
||||||
" return any(\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",
|
"\n",
|
||||||
"\n",
|
"\n",
|
||||||
@ -540,7 +574,7 @@
|
|||||||
" )\n",
|
" )\n",
|
||||||
" else:\n",
|
" else:\n",
|
||||||
" arr_moves_possible[game] = any(\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",
|
" for direction in DIRECTIONS\n",
|
||||||
" )\n",
|
" )\n",
|
||||||
" return arr_moves_possible\n",
|
" return arr_moves_possible\n",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user