# 魷魚遊戲 [toc] ## 環境安裝 ### 已有前測環境 ```bash #找到前測環境的資料夾 cd MLGame git clone https://github.com/ocar1053/swimming_squid_funai25.git # 進入虛擬環境 # 如果出現了「這個系統上已停用程式碼執行」的錯誤,請在設定->系統->開發人員專用->Powershell # 將「...允許本機Powershell指令碼...」選項開啟,詳情請看環境介紹影片1:10處 (windows) .\funai\Scripts\Activate.ps1 (mac) source funai/bin/activate cd ./swimming_squid_funai25 #手動玩遊戲指令,遊戲正常啟動代表安裝成功 python -m mlgame -i ./ml/ml_play_manual.py ./ --level 1 ``` ### Windows 環境建置 ```bash # python 要是 3.10 !!!!!!! git clone https://github.com/ocar1053/swimming_squid_funai25.git cd .\swimming_squid_funai25\ # 建立虛擬環境 python -m venv funai # 進入虛擬環境 (todo cmd version) # 如果出現了「這個系統上已停用程式碼執行」的錯誤,請在設定->系統->開發人員專用->Powershell # 將「...允許本機Powershell指令碼...」選項開啟,詳情請看環境介紹影片1:10處 https://www.youtube.com/watch?v=VHBVYl70tp4 # 進入虛擬環境安裝套件 .\funai\Scripts\Activate.ps1 # 安裝需要的套件 pip install -r .\requirements.txt #手動玩遊戲指令,遊戲正常啟動代表安裝成功 python -m mlgame -i .\ml\ml_play_manual.py ./ --level 1 ``` ### Mac 環境建置 ```bash # python 要是 3.10 !!!!!!! git clone https://github.com/ocar1053/swimming_squid_funai25.git cd ./swimming_squid_funai25 # 建立虛擬環境 python3 -m venv funai # 進入虛擬環境 source funai/bin/activate # 安裝需要的套件 pip install -r ./requirements.txt #手動玩遊戲指令,遊戲正常啟動代表安裝成功 python -m mlgame -i ./mlml_play_manual.py ./ --level 1 ``` ## 遊戲介紹 ![image](https://hackmd.io/_uploads/r1LP5VYPkx.png) * pygame座標 * 原點在左上方 * 關卡 * 1~15關 * 遊戲物件 * 魷魚 * 動作 * UP:向上移動 * DOWN:向下移動 * LEFT:向左移動 * RIGHT:向右移動 * NONE:原地不動 * 食物(有三個等級) * 垃圾(有三個等級) * 升級 * 吃食物會讓魷魚升級,跑得更快 * 目標 * 在遊戲停止前,用 AI 模型操控魷魚,得到最多分數 ## 遊戲破關介紹 ### 破關三階段 ![FUNAI 破關 (1)](https://hackmd.io/_uploads/BkN7B7erJl.png) ### 策略參考 ![FUNAI 魷魚遊戲 (2)](https://hackmd.io/_uploads/BkCT47gBkg.png) #### 策略說明 以魷魚為中心,對其半徑 R 內的範圍進行搜索,計算 4 個方位的分數,各方位的分數為區域內的食物和海洋垃圾分數的總和。而在每一個幀數,會基於上述的分數決定魷魚該往哪個方向移動。 舉例來說,以上畫面的上區域有大量垃圾,分數總和會是最差,而下區域有大量食物,分數總和會是最高,因此魷魚會選擇往下移動。 #### Hint: 1. 如果發現魷魚很常跑到角落,可以嘗試將總和分數為 0 的區域分數設為 -999 。 2. 若要將物體與魷魚的距離納入考量,可嘗試將食物和垃圾的原始分數乘上權重。 ## 程式碼提示 方便學員實作,在 ml 資料夾中,可以找到破關三階段對應的 .py 檔案,同學可以直接對其進行修改來完成階段任務。 ### 收集訓練 AI 的資料 (ml_play_collect_data.py) * function update ```python def update(self, scene_info: dict, *args, **kwargs): """ Generate the command according to the received scene information """ ``` function update 每一個 frame 會被呼叫一次,可以利用每次傳入的 scene_info,撰寫對應的移動策略 (魷魚的動作)。 - scene_info 的資料格式如下 ```json { "frame": 15, "score": 8, "score_to_pass": 10, "self_x": 350, "self_y": 300, "self_h": 60, "self_w": 40, "self_lv": 1, "self_vel": 10, "status": "GAME_ALIVE", "foods": [ { "h": 30, "score": 1, "type": "FOOD_1", "w": 30, "x": 40, "y": 134 }, { "h": 40, "score": 2, "type": "FOOD_2", "w": 40, "x": 422, "y": 192 }, { "h": 50, "score": 4, "type": "FOOD_3", "w": 50, "x": 264, "y": 476 }, { "h": 30, "score": -1, "type": "GARBAGE_1", "w": 30, "x": 100, "y": 496 }, { "h": 40, "score": -4, "type": "GARBAGE_2", "w": 40, "x": 633, "y": 432 }, { "h": 50, "score": -10, "type": "GARBAGE_3", "w": 50, "x": 54, "y": 194 } ] } ``` * function get_distance ```python def get_distance(self, x1, y1, x2, y2): """ Calculate the distance between two points """ return ((x1-x2)**2 + (y1-y2)**2)**0.5 ``` 此函數可以幫助你計算魷魚和其他物體的距離 魷魚的動作。 * 變數 row ```python # collect the data row = [score_vector[0], score_vector[1], score_vector[2], score_vector[3], command[0]] ``` 可以利用變數 row 存儲紀錄訓練資料,score_vector 的索引 0 到 3 對應 [up, down, left, right] 區域的分數,command[0] 則為魷魚的動作。 * function reset ```python def reset(self): """ Reset the status """ print("reset ml script") if self.last_status == "GAME_PASS": self.all_data.extend(self.data) with open("dataset/training_data.pkl", "wb") as f: pickle.dump(self.all_data, f) print(f"Data appended, total {len(self.all_data)} entries saved.") self.data.clear() ``` 遊戲每結束一回合,reset 會被呼叫,如果此回合通過的話會將訓練資料儲存起來。沒過則不會儲存。 - 資料會存放在 dataset 資料夾中的 training_data.pkl 檔案內 - 若 training_data.pkl 中已存在資料,新通關的資料會接續在原有資料之後。 - 若需清除所有資料,請直接刪除 dataset 資料夾中的 training_data.pkl 檔案。 ### 訓練 AI 模型 (knn_train.py) * 變數 FEATURES_NUM 可以修改此變數,定義特徵長度。 * 變數 DATA_PATH 可以修改此變數,定義資料集的路徑。 ### 使用訓練好的 AI 模型破關 (ml_play_knn.py) * 變數 X ```python X = [score_vector[0], score_vector[1], score_vector[2], score_vector[3]] ``` 此變數為 4 個方向的分數,會輸入給 KNN 模型。 * 變數 pred_label ```python pred_label = self.model.predict([X])[0] ``` 此變數為 AI 模型預測的結果。 ## 遊戲指令運行方式 ### 手動操控魷魚 ``` # 於/swimming_squid_funai25 下執行 python -m mlgame -i .\ml\ml_play_manual.py ./ --level 1 ``` ### 收集魷魚移動資料 ``` # 於/swimming_squid_funai25 下執行 python -m mlgame -i .\ml\ml_play_collect_data.py ./ --level 1 ``` ### 訓練 KNN 模型 ``` # 於/swimming_squid_funai25 下執行 python .\ml\knn_train.py ``` ### 使用 KNN 模型操控魷魚 ``` # 於/swimming_squid_funai25 下執行 python -m mlgame -i .\ml\ml_play_knn.py ./ --level 1 ``` ### 執行自定義模板 ``` # 於/swimming_squid_funai25 下執行 python -m mlgame -i .\ml\ml_play_template.py ./ --level 1 ``` ### 加速遊戲 ``` python -m mlgame -f 120 -i .\ml\ml_play_knn.py ./ --level 1 ``` * -f 為設定 fps 的參數,數值越大,fps 越高。 ## 環境資訊格式 - scene_info 的資料格式如下 ```json { "frame": 15, "score": 8, "score_to_pass": 10, "self_x": 350, "self_y": 300, "self_h": 60, "self_w": 40, "self_lv": 1, "self_vel": 10, "status": "GAME_ALIVE", "foods": [ { "h": 30, "score": 1, "type": "FOOD_1", "w": 30, "x": 40, "y": 134 }, { "h": 40, "score": 2, "type": "FOOD_2", "w": 40, "x": 422, "y": 192 }, { "h": 50, "score": 4, "type": "FOOD_3", "w": 50, "x": 264, "y": 476 }, { "h": 30, "score": -1, "type": "GARBAGE_1", "w": 30, "x": 100, "y": 496 }, { "h": 40, "score": -4, "type": "GARBAGE_2", "w": 40, "x": 633, "y": 432 }, { "h": 50, "score": -10, "type": "GARBAGE_3", "w": 50, "x": 54, "y": 194 } ] } ``` ## 競賽說明 * [說明](https://hackmd.io/@IsFp8R6yRX-i3vPPttlq5Q/Hyne7EbBJe)