mjx-project / mjx

Mjx: A framework for Mahjong AI research
https://colab.research.google.com/drive/1m1wOT_K2YFtuV6IO7VgWk4ilVhTKqRFU?usp=sharing
MIT License
171 stars 19 forks source link

CUIでのState・Observationの可視化 #665

Closed sotetsuk closed 2 years ago

sotetsuk commented 3 years ago

方針

データの形式

いったん Observation を想定

データの例

データのロードの仕方

例: main.py

import mjxproto
import json
from google.protobuf import json_format

d = json.loads(line)  # line は文字列
state = json_format.ParseDict(d, mjxproto.State())
print(state)

仕様

image

リンク

OkanoShinri commented 3 years ago
sotetsuk commented 3 years ago

betterproto を使うようになったので、 from_jsonto_json とかが使える

https://github.com/danielgtaylor/python-betterproto

@OkanoShinri

sotetsuk commented 3 years ago

イメージ図

12006C34-8835-4E67-A764-E120863CB437

sotetsuk commented 3 years ago

ユニコードの表示のされ方の実験

to_unicode = {
    0: "\U0001F007",
    1: "\U0001F008",
    2: "\U0001F009",
    3: "\U0001F00A",
    4: "\U0001F00B",
    5: "\U0001F00C",
    6: "\U0001F00D",
    7: "\U0001F00E",
    8: "\U0001F00F",
    9: "\U0001F019",
    10: "\U0001F01A",
    11: "\U0001F01B",
    12: "\U0001F01C",
    13: "\U0001F01D",
    14: "\U0001F01E",
    15: "\U0001F01F",
    16: "\U0001F020",
    17: "\U0001F021",
    18: "\U0001F010",
    19: "\U0001F011",
    20: "\U0001F012",
    21: "\U0001F013",
    22: "\U0001F014",
    23: "\U0001F015",
    24: "\U0001F016",
    25: "\U0001F017",
    26: "\U0001F018",
    27: "\U0001F000",
    28: "\U0001F001",
    29: "\U0001F002",
    30: "\U0001F003",
    31: "\U0001F006",
    32: "\U0001F005",
    33: "\U0001F004",
}

for k, v in to_unicode.items():
    print(v)

print("🀄")
print("🀄︎")
sotetsuk commented 3 years ago

Mac

iterm

image

Terminal

image

Notes

image

PyCharm

image

sotetsuk commented 3 years ago

異文字セレクタを使うことでだいたいの場合うまいこといった

to_unicode = {
    0: "\U0001F007",
    1: "\U0001F008",
    2: "\U0001F009",
    3: "\U0001F00A",
    4: "\U0001F00B",
    5: "\U0001F00C",
    6: "\U0001F00D",
    7: "\U0001F00E",
    8: "\U0001F00F",
    9: "\U0001F019",
    10: "\U0001F01A",
    11: "\U0001F01B",
    12: "\U0001F01C",
    13: "\U0001F01D",
    14: "\U0001F01E",
    15: "\U0001F01F",
    16: "\U0001F020",
    17: "\U0001F021",
    18: "\U0001F010",
    19: "\U0001F011",
    20: "\U0001F012",
    21: "\U0001F013",
    22: "\U0001F014",
    23: "\U0001F015",
    24: "\U0001F016",
    25: "\U0001F017",
    26: "\U0001F018",
    27: "\U0001F000",
    28: "\U0001F001",
    29: "\U0001F002",
    30: "\U0001F003",
    31: "\U0001F006",
    32: "\U0001F005",
    33: "\U0001F004\uFE0E",
}

for k, v in to_unicode.items():
    print(v)

image

sotetsuk commented 3 years ago
from rich.table import Table
from rich.console import Console
from rich import print

to_unicode = {
    0: "\U0001F007",
    1: "\U0001F008",
    2: "\U0001F009",
    3: "\U0001F00A",
    4: "\U0001F00B",
    5: "\U0001F00C",
    6: "\U0001F00D",
    7: "\U0001F00E",
    8: "\U0001F00F",
    9: "\U0001F019",
    10: "\U0001F01A",
    11: "\U0001F01B",
    12: "\U0001F01C",
    13: "\U0001F01D",
    14: "\U0001F01E",
    15: "\U0001F01F",
    16: "\U0001F020",
    17: "\U0001F021",
    18: "\U0001F010",
    19: "\U0001F011",
    20: "\U0001F012",
    21: "\U0001F013",
    22: "\U0001F014",
    23: "\U0001F015",
    24: "\U0001F016",
    25: "\U0001F017",
    26: "\U0001F018",
    27: "\U0001F000",
    28: "\U0001F001",
    29: "\U0001F002",
    30: "\U0001F003",
    31: "\U0001F006",
    32: "\U0001F005",
    33: "\U0001F004\uFE0E",
}

all_tiles = [v for k, v in to_unicode.items()]

console = Console()

table = Table(show_header=True, header_style="bold magenta")
table.add_column("East", justify="center")
table.add_column("South", justify="center")
table.add_column("West", justify="center")
table.add_column("North", justify="center")
table.add_row(
    " ".join(all_tiles[:6]),
    " ".join(all_tiles[6:12]),
    " ".join(all_tiles[12:18]),
    " ".join(all_tiles[18:24]),
)
table.add_row(
    " ".join(all_tiles[:6]),
    " ".join(all_tiles[6:12]),
    " ".join(all_tiles[12:18]),
    " ".join(all_tiles[18:24]),
)
table.add_row(
    " ".join(all_tiles[:6]),
    " ".join(all_tiles[6:12]),
    " ".join(all_tiles[12:18]),
    " ".join(all_tiles[18:24]),
)
table.add_row(
    " ".join(all_tiles[:6]),
    " ".join(all_tiles[6:12]),
    " ".join(all_tiles[12:18]),
    " ".join(all_tiles[18:24]),
)
console.print(table)

image

sotetsuk commented 3 years ago

方向性

From #667

全体の設計方針として次の2つのパートを用意する

  • [1] mjxproto.Observation (or State )から表示しやすく加工されたオブジェクト(例えば Board とする)にパースをするパート

    • e.g., board = Board.from_proto()
  • [2] 上記の Board オブジェクトを(キレイに)表示するパート

    • e.g., board.show() or board.print()

このPRでは [2] だけに集中してください。データ例としてjsonのデータも提供しましたが、Board オブジェトのデータはダミーで適当に用意してもらう形が好ましいです。 [1] は後でテストを用意しつつ書きます

ちょっと方向性が混乱してきている気がするので、方向性を決めます。

[2] も、次のパターンを考えます

  • richを使う[w/ rich]/使わない[w/o rich]
  • unicodeを使う[w/ unicode]/使わない[u/o unicode]

よって次の4パターンが存在

  • [A: w/rich, w/ unicode]: 一番重要。これに時間を使う予定。
  • [B: w rich, w/o unicode] : 重要でない。
  • [C: w/o rich, w/ unicode] : 重要でない。
  • [D: w/o rich, w/o unicode] : 二番目に重要。ただし時間を使う必要はない。テスト用途で雑な可視化を確認すれば良い。

ちょっとタスクの切り分けが大きくなりすぎてしまったので、 まず、このPRでDだけ実装して、僕のレビューを経てマージするようにしましょう。

まとめると、このPRで実装するパートは

  1. [ ] 可視化用にパースされたデータを保持するBoardクラス(名前は何でもよい)
  2. [ ] Boardクラスを可視化するメソッド(上記のDパターンのみ実装)
sotetsuk commented 3 years ago
OkanoShinri commented 3 years ago

https://github.com/mjx-project/mjx/pull/667 と同じ例を用いて手牌、捨て牌部分を実装しています。

スクリーンショット 2021-04-27 211018

このコード辺りからPRを作っていくべきでしょうか?

OkanoShinri commented 3 years ago