reversi_board's People
reversi_board's Issues
処理結果に矛盾がある
例えば以下の条件を満たすレコードは存在していないはずだが、(depth = 8 くらいになると)実際にはある:
select count(*) from reversi where ( depth + 4 < player0_count + player1_count ) or ( depth + next_choices_num > 12 );
bot.js と analytics.js の統合
どちらの機能を使うべきか、も自動判断する
サーバーは next_processed_num != 1
のレコードが存在していたら旧 bot.js の、存在していなかったら analytics.js の処理を行うためのレコードを返す。
クライアントは返されたレコードの next_processed_num
の値を見て、1 以外だったら旧 bot.js の、1 だったら analytics の処理を行う。
CORS 対応
bot はブラウザを使うわけではない(REST API を使うだけ)ので、CORS 対応自体が不要?
全読み結果を使う AI(?) ゲーム画面
ステータス画面とは別に作りたい
reversi テーブル変更
create table reversi(
id bigserial not null,
parent_id bigint default -1, //. 1つ前の board の id
next_id bigint default -1, //. 1つ先の節が既存している場合の行先 id
next_idx int default -1, //. next_id が存在している場合、boards の何番目にリンクするか
board_size int default -1,
depth int default -1,
//choice_idx int default -1,
//choice_x int default -1,
//choice_y int default -1,
board text default '', //. 現在のボード状態を1次配列で表したものを文字列化したもの
boards text default '', //. 現在のボード状態を1次配列で表した複数の状態(上下左右回転を考慮)を昇順に並べて文字列化して ":" でつないだもの
next_choices text default '',
next_choices_num int default -1,
process_status int default 0, //. これまで next_processed_num として使っていたものの列名を変更
player0_count int default -1,
player1_count int default -1,
next_player int default 0, //. -1 or 1。0 の場合は終了
value int default 0,
value_status default 0,
created bigint default 0,
updated bigint default 0,
primary key (id)
);
create index on reversi ( board_size, next_choices_num, process_status, updated );
alter table reversi add unique( boards, next_player );
ステータスが -1 のものを対象とするかしないかを分けて処理可能な bot
-1 のものは(別の誰かが処理中、ということを意味するので)対象外としないと、分散処理時の効率が悪くなる。
一方で対象外にして処理を先に進めてしまうと、親が未処理なのに子を実施することになりかねない。この事態を避けるにはどういうアルゴリズムとするべきか?
分岐は環境変数を使う?
bot.js の BASE_URL を環境変数化
同じ盤面かどうかの判断は「自分の boards の中に過去に記録された board があるかどうか」とする
こんな感じ
var found_id = null;
for( var i = 0; i < this.boards.length && !found_id; i ++ ){
//. できればループではなく、1回の DB アクセスで見つけたい
found_id = findIdByBoard( this.boards[i] );
}
if( found_id ){
//. 過去に同じボードが見つかった
this.next_id = found_id;
save( this );
}else{
//. *
}
でも初手はこれだと見つからない。* で工夫する必要がある。
6x6 、depth = 8 の処理が終わりかけている中で、bot の実行結果が全て { status: true, result: null } になり、それ以上実行されない
ステータス確認用 UI
ウェブクライアント画面が 4x4 固定になっている?
- ai.ejs は board が 4x4 固定
- status.ejs は一見大丈夫だけど、動いていないように見える
Docker イメージ化
両方とも個別に用意すると便利
- API サーバー
- クライアント
バックアップファイル名 (3x3 -> 4x4)
何故か間違いにずっと気づけなかった・・・
bot.js : next_choices_num = 0 のレコードは next_processed_num = 1 にして保存する
New Web UI
- コンシューマー向け UI
- Web UI からもボタンクリック後に連続実行させる
- 明示的に止める手段を用意
BOARD_SIZE=6 の環境変数を与えて実行しているのに、いつの間にか BOARD_SIZE=4 の結果が紛れ込む
原因不明。どういうこと??
reversi.id だけから履歴画面を再現する
デバッグ用に URL パラメータなどで reversi.id を入力すると、該当レコードの履歴画面が表示される(そこから Back もできる)ようにする
#14 のウェブクライアント化
board 配列や boards 配列内の順序は縦方向
例えば、
0 0 0 0
0 1 1 1
0 1 -1 0
0 0 0 0
の board は
[ 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, -1, 0, 0, 1, 0, 0 ]
とする。
こうしておくと ( x, y ) の駒は board[board_size * x + y]
で求めることができるようになる。
先手・後手を入れ替えてのミニマックス解析
現状は「先手」番のみのロジックで value 値を求めている。「後手」番のロジックも必要。
value -> value0 にして、value 1 列を加えて、両方同時に求めて更新するようにするべき。
深読みと解析の切り替え
#14 実装後に、bot (深読み)機能から analytics(解析)機能に正しく切り替わることを確認する。そのためには bot 処理終了直前の DB データが必要。
現在の DB 状態を Web 画面に表示
GET /
内で以下の結果を表示できるように API を追加した上で status.ejs を改良する:
select depth,value_status,count(*) from reversi group by depth, value_status order by depth, value_status;
docker コンテナイメージのバージョン管理
ローリングアップデートを可能にするため
HTTP を使わない bot
REST API ではなく、スタンドアロンで直接関数を実行するようなイメージ。高速化のため。
自分一人で調査する時のためだけにしか使わないので、需要については疑問。
next_status の値が -1 のまま処理が進んでしまっているケースが稀にある
select * from reversi where depth < ( select max(depth) from reversi ) and next_status like '%-1%';
で分かる
DBバックアップ/リストア確認
分散処理でも深読みが正しく動くことを確認する
ミニマックス戦略で先手(後手)の最適解を求める
アルゴリズム(先手の最適手を求める)
-
max(depth)
が偶数であることを(後手が最後の手を選択していることを)確認する -
reversi
から全レコードを以下の条件で取得- 取り出すのは
id
,parent_id
, (board_size
, )depth
,choice_idx
,player0_count
,next_player
-
board_size
は指定の固定値 -
depth
の大きい順,parent_id
の小さい順,choice_idx
の小さい順
- 取り出すのは
- (*) 同じ
depth
を持ち、同じparent_id
を持つレコードカテゴリごとにplayer0_count
の最小値を求めて、このparent_id
をid
として持つレコードのplayer0_count
とする -
depth
を1つ減らして、(*) と同じ計算を行う。ただし求めるのはplayer0_count
の最小値ではなく最大値 -
depth
を1つ減らして、(*) と同じ計算を行う。ただし求めるのはplayer0_count
の最大値ではなく最小値 -
depth = 0
になるまで (*) を繰りかえす -
depth = 0
の時に求めたplayer0_count
がboard_size * board_size / 2
よりも小さい場合は後手必勝、大きい場合は先手必勝
6x6 ボードで深読み&解析
ID 自動連番
k8s 対応
IBM Cloud の 30 日間無料 k8s でも動くようにする
reversi オブジェクトを変更
var reversi = class{
//. コンストラクタの引数は整数または文字列(JSON オブジェクトは使わない)
constructor( id, parent_id, next_id, next_idx, board_size, depth, board, boards, next_player ){
this.id = id;
this.parent_id = parent_id;
this.next_id = next_id;
this.next_idx = this.next_idx;
this.board_size = board_size;
this.depth = depth;
this.board = JSON.parse( board );
this.boards = JSON.parse( boards.split( ":" ) );
this.next_player = next_player;
//. ここから下はすべて計算で求める
this.next_choices = [];
this.next_choices_num = 0;
this.process_status = 0;
this.player0_count = 0;
this.player1_count = 0;
this.value = 0;
this.value_status = 0;
};
SQL だけで analytics できないか?
SQL の update 文で analytics.js の機能を実装できないか?できれば(分散処理ではないが)かなり早いはず
#22 の問題を解決する現実的なアイデア
1手目を4つではなく(どうせ同じなので)1つだけ選んで進めた場合でも、depth = 9 は4分の1になるが depth = 10, 11, .. と進めていくとすぐに非現実的な数字になってしまいそう。思っていたよりも限界が早かった。。
bot.js は候補手を全てまとめて処理&更新するよう改良すべき
更新オーバーヘッドが大きすぎるため
その場合のステータス管理をどうするべきか・・・
POST /api/reversi/next_process
や POST /api/reversi/update_process
も変更の必要あり
分散処理でも解析が正しく動くことを確認する
分散環境下で動かしながら select depth,value_status,count(*) from reversi group by depth,value_status order by depth,value_status;
で確認する
候補選択肢の [ y, x ] が [ x, y ] になってしまっている
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.