遊戲設置 - LanKuDot/MLGame GitHub Wiki
本章節介紹遊戲在 MLGame 的擺放位置與如何設置遊戲與參數。
在 MLGame 中,遊戲皆放在 games 資料夾底下,一個遊戲存放於一個資料夾,該資料夾的名稱就是 MLGame 啟動遊戲的名稱。每個遊戲資料夾內有三個子資料夾:
- game:存放遊戲程式碼的資料夾。關於如何將一個現有遊戲導入到 MLGame 可以參考 將遊戲導入 MLGame 與 遊戲與
MLPlay
類別; - log:存放產生的紀錄檔的資料夾。未建立的話,在第一次執行遊戲時,MLGame 會自動產生;
- ml:存放玩家程式碼的資料夾。可以包含一個
ml_play_template.py
檔案作為玩家的範例程式。
在遊戲資料夾、game、ml 這三個資料夾中,需要有 __init__.py
檔案,使這些資料夾成為 python package。此外,在遊戲資料夾下需要幾個檔案:
-
config.py
:告知 MLGame 如何啟動遊戲。格式參考下方的遊戲設定章節; -
README.md
:介紹遊戲的檔案,包含遊戲規則、場景資訊格式、遊戲物件、遊戲指令等。
資料夾結構的樹狀圖如下,假如有一個遊戲 "snake" 要放在 MLGame 中:
games/
└── snake/
├── __init__.py
├── config.py
├── README.md
├── game/
│ ├── __init__.py
│ └── 遊戲程式碼
├── log/
└── ml/
├── __init__.py
├── ml_play_template.py
└── 玩家程式碼
以此為例,啟動遊戲的指令就是 python MLGame.py -i ml_play_template.py snake
。
遊戲開發者可以將一個遊戲資料夾設成一個專案,如此一來,玩家只要將整個資料夾放入 games 資料夾底下,就可以透過 MLGame 遊玩。
在遊戲資料夾中的 config.py
檔案負責設定遊戲,每個遊戲都必須提供這個檔案,否則 MLGame 無法執行。以下介紹 config.py
中的參數。
遊戲版本,為一個字串。可不指定,預設為空字串 ""
。
透過 python MLGame.py --list
列出所有遊戲時,也會一同列出遊戲版本。
遊戲參數,為一個 dict。可不指定,預設為:
GAME_PARAMS = {
"()": {
"prog": 遊戲資料夾名稱,
"game_usage": "%(prog)s"
}
}
MLGame 利用 argparse
模組來幫助解析使用者在命令列下的遊戲參數的有效性,而 GAME_PARAMS
就是用來幫助產生 argparse.ArgumentParser
物件的資訊。命令列中所有指定在遊戲名稱後面的參數,都會傳給產生的 argparse.ArgumentParser
解析。以下介紹 GAME_PARAMS
的格式:
在 GAME_PARAMS
中的鍵為 "()"
,其值為一個 dict。dict 中的每個鍵值對應代表要呼叫 argparse.ArgumentParser()
的參數。例如:
GAME_PARAMS = {
"()": {
"prog": "snake",
"description": "A simple snake game",
"usage": "python MLGame.py [options] %(prog)s"
}
}
等同於
argparse.ArgumentParser(
prog = "snake",
description = "A simple snake game",
usage = "python MLGame.py [options] %(prog)s")
而在 MLGame 中可以指定 "game_usage"
。MLGame 會在 "game_usage"
前面加上 "python MLGame.py [options] "
的前綴,並取代 "usage"
,所以 "usage"
跟 "game_usage"
只能擇一存在。例如上面的例子也可以寫成:
GAME_PARAMS = {
"()": {
"prog": "snake",
"description": "A simple snake game",
"game_usage": "%(prog)s"
}
}
在 GAME_PARAMS
中除了 "()"
以外的鍵都是參數,該鍵的值即為參數名稱,其值亦為一個 dict。而 dict 中的每個鍵值對應代表要呼叫 ArgumentParser.add_argument()
的參數。例如:
GAME_PARAMS = {
"()": {
"prog": "snake",
"description": "A simple snake game",
"game_usage": "%(prog)s <difficulty>"
},
"difficulty": {
"choices": ("EASY", "NORMAL", "HARD"),
"metavar": "difficulty",
"help": "Specify the game style. Choices: %(choices)s"
}
}
等同於
parser = argparse.ArgumentParser(
prog = "snake",
description = "A simple snake game",
usage = "python MLGame.py [options] %(prog)s <difficulty>")
parser.add_argument("difficulty",
choices = ("EASY", "NORMAL", "HARD"),
metavar = "difficulty",
help = "Specify the game style. Choices: %(choices)s")
而在 GAME_PARAMS
所指定的參數順序會等同於傳入給遊戲類別的參數順序。
如果在 config.py
中有指定 GAME_VERSION
的話,MLGame 會在 GAME_PARAMS
中增加 "--version"
的參數,就可以透過 python MLGame.py snake --version
來看遊戲版本:
"--version": {
"action": "version",
"version": GAME_VERSION
}
使用 python MLGame.py snake -h
就可以看到由 argparse.ArgumentParser
產生的幫助訊息。
遊戲的啟動設定,為一個 dict。以下介紹鍵值對應:
"game"
指定要執行的遊戲類別。遊戲類別必須含有指定的函式供 MLGame 呼叫。
"dynamic_ml_clients"
遊戲是否為動態玩家數量,為一布林值。可不指定,預設為 False
。
如果為 True
,MLGame 會依照玩家指定的程式碼數量來生成對應數量的機器學習端,但不會超過 "ml_clients"
指定的數量。
"ml_clients"
指定機器學習端的名稱與傳入的參數,為一個 list。list 內的每一個元素都是 dict,內容如下:
-
"name"
:機器學習端的名稱,為字串。 -
"args"
:要傳給MLPlay
類別的位置參數(positional arguments),為 tuple,可不指定。 -
"kwargs"
:要傳給MLPlay
類別的關鍵字參數(keyword arguments),為 dict,可不指定。
GAME_SETUP
的範例:
from .game.pingpong import PingPong
GAME_SETUP = {
"game": PingPong,
"ml_clients": [
{ "name": "ml_1P", "args": ("1P",) },
{ "name": "ml_2P", "args": ("2P",) }
]
}