ぷよぷよプログラミングAI学習システムは、中高生の自己調整学習に向けて開発されました。
どうやって、Chromebookで、10分で、素敵な人工知能を作れるのでしょうか?
秘密は、3つ。
1 jupyter liteで、webクライアントがpythonコードを実行
2 超軽量な機械学習フレームワークdezeroを採用
3 ぷよぷよのstageとactionがコンパクト
Github&X
ぷよぷよプログラミングAI学習用まとめ
チュートリアルまとめ
Step3 Action選択肢と衝突判定
3 衝突判定をして、Action選択肢を探る。
どこにpuyoを移動させて、回転させるかという選択肢は、幅6 x 回転4 -2 = 22 の可能性があるようにも見えますが、他のpuyoと衝突するかもしれないので、衝突判定が必要です。
step2で作った、set_puyo_to_boardを改造して、衝突判定の関数を作ります。
def check_collision(board, puyo):
rot = puyo.rotation
if rot == 0 and puyo.x == 5:
return True
if rot == 2 and puyo.x == 0:
return True
if puyo.y >= 12:
return True
if puyo.y == 11 and rot == 3 :
return True
if board[puyo.y, puyo.x] > 0 :
return True
if not( rot == 1) and board[puyo.y + puyo.dy[rot], puyo.x + puyo.dx[rot]] > 0:
return True
return False
この関数は、そのブロックがboardの中に入っているか、逆に言えば、はみ出ていないか判定もしています。
check_collisionを使って、actionの選択肢をリスト化します。
actionの選択肢は、スタートする列の位置と回転数をリストとして出力します。
import numpy as np
from puyo_utils import *
def create_action_list(board):
puyo2 = Puyopuyo()
res = []
for rot in range(4):
for pos1 in range(6):
puyo2.x = pos1
puyo2.rotation = rot
if not check_collision(board, puyo2):
res.append([pos1, rot])
return res
action_list は、numpyではないので、少し注意が必要です。
それでは、使ってみましょう。
board = utils.create_sample_board()
action_list=create_action_list(board)
print(action_list)
[[0, 0], [1, 0], [2, 0], [3, 0], [4, 0], [0, 1], [1, 1], [2, 1], [3, 1], [4, 1], [5, 1], [1, 2], [2, 2], [3, 2], [4, 2], [5, 2], [0, 3], [1, 3], [2, 3], [3, 3], [4, 3], [5, 3]]
action_listは厳密には、ぷよの横移動と回転可能性が完全には保証されていません。実ゲームでどこまで応用可能かはやってみてからの調整が必要です。
これらの関数も使いたいので、puyo_utilsに保存しておきます。
%%writefile puyo_utils.py
import numpy as np
import random
class CFG:
Height = 12
Width = 6
class Puyopuyo:
def __init__(self):
self.x = 2
self.y = 0
self.dx = [1, 0, -1, 0]
self.dy = [0, -1, 0, 1]
self.centerPuyo = random.randint(1,4)
self.movablePuyo = random.randint(1,4)
self.rotation = 1
class utils:
def create_sample_board(height=CFG.Height, width=CFG.Width):
sample_list = np.arange(width)
random.shuffle(sample_list)
board = np.zeros(height * width, dtype = np.int32).reshape(height, width)
for j in range(width):
if sample_list[j]:
for i in range(sample_list[j]):
board[height - 1 - i, j] = random.randint(1, 4)
return board
def create_new_puyo(board):
new_puyo = Puyopuyo()
done = False
if board[2, 0] > 0:
done = True
return new_puyo, done
def set_puyo_to_board(board, puyo):
new_board = np.copy(board)
new_board[puyo.y, puyo.x ] = puyo.centerPuyo
puyo_dy = puyo.y + puyo.dy[puyo.rotation]
puyo_dx = puyo.x + puyo.dx[puyo.rotation]
if puyo_dy >= 0:
new_board[puyo_dy, puyo_dx ] = puyo.movablePuyo
return new_board
def check_collision(board, puyo):
rot = puyo.rotation
if rot == 0 and puyo.x == 5:
return True
if rot == 2 and puyo.x == 0:
return True
if puyo.y >= 12:
return True
if puyo.y == 11 and rot == 3 :
return True
if board[puyo.y, puyo.x] > 0 :
return True
if not( rot == 1) and board[puyo.y + puyo.dy[rot], puyo.x + puyo.dx[rot]] > 0:
return True
return False
def create_action_list(board):
puyo2 = Puyopuyo()
res = []
for rot in range(4):
for pos1 in range(6):
puyo2.x = pos1
puyo2.rotation = rot
if not utils.check_collision(board, puyo2):
res.append([pos1, rot])
return res
Overwriting puyo_utils.py
- class utils : 関数をまとめて、utilsにしました。名前がぶつからないようにします。