---
# System prepended metadata

title: 魷魚遊戲

---

# 魷魚遊戲

[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)




