試玩 GOWOG ,初探 OpenAI(使用 NeuroEvolution 神經進化)與 Golang 多人線上遊戲開發

為少發表於2021-01-27

GOWOG

GOWOG 是一款迷你的,使用 Golang 編寫的多人 Web 遊戲。

試玩遊戲

Demo:http://game.giongto35.com

在 Agent 上的 AI 實驗

由於伺服器,客戶端和訊息是分離的,因此很容易與後端進行通訊。
此專案是用 Python 編寫的 AI agent,可以學習與環境的互動。
這個實驗是利用 neuroevolution (神經進化)在迷宮中尋找一條路徑。

油管 Demo:https://www.youtube.com/watch?v=pWbb1m91mhU

本地 Docker 執行

run_local.sh

#!/bin/bash
docker build . --build-arg HOSTNAME=localhost:8080 -t gowog_local|| exit
docker stop gowog
docker rm gowog
docker run --privileged -d --name gowog -p 8080:8080 gowog_local server -prod client/build/

執行,我本地是 Mac

./run_local.sh

開啟 http://localhost:8080

本地開發

遊戲包含兩部分:伺服器和客戶端。伺服器使用 Golang,客戶端使用 Node.JSPhaser 遊戲引擎。

伺服器

為少調整過的專案:Kirk-Wang/gowog

我的本地環境是 go 1.14

本地啟動:

go run cmd/server/*

伺服器將監聽 8080

客戶端

npm install
npm run dev -- --env.HOST_IP=localhost:8080 # HOST_IP -> 伺服器地址

進入 http://localhost:3000

注意

在開發過程中,客戶端在埠 3000 上執行,伺服器端在埠 8080 上執行。

productiondocker環境中,已構建 Client,golang 伺服器將在同一埠 8080 上返回客戶端頁面。因此,如果我們執行 docker 環境,則遊戲將在瀏覽器中的 http://localhost:8080 執行。

通訊約定

伺服器和客戶端之間的通訊包基於 protobuf。 安裝 protoc 以生成 protobuf

每次你在 server/message.proto 中有更改(package singature)時。請執行:

cd server
./generate.sh

遊戲前端設計

這個前端專案是基於:

├── client
│   ├── index.html
│   ├── src
│   │   ├── config.js: javascript config
│   │   ├── index.html
│   │   ├── main.js
│   │   ├── sprites
│   │   │   ├── Leaderboard.js: Leaderboard object
│   │   │   ├── Map.js: Map object
│   │   │   ├── Player.js: Player object
│   │   │   └── Shoot.js: Shoot object
│   │   ├── states
│   │   │   ├── Boot.js Boot screen
│   │   │   ├── const.js
│   │   │   ├── Game.js: Game master
│   │   │   ├── message_pb.js: Protobuf Message
│   │   │   ├── Splash.js
│   │   │   └── utils.js
│   │   └── utils.js

每個物件都是從 Sprite 繼承的類。
玩家包含 shootManager,每次射擊時,shoot manager 都會生成新的 bullet

遊戲後端設計方案

Components(元件)

遊戲中主要有 5 個實體。他們的狀態是私有的

實體 私有狀態
Client websocket.Conn client hold 住 websocket 連線
Hub Client Hub 處理所有通訊, 包含所有 client 列表
ObjManager Player, Shoot, ... ObjManager 包含所有 Player 和 Shoot,處理遊戲邏輯
Game Master ObjManager, Hub Master object 由 ObjManager 和 Hub 組成

Architecture(架構圖)

不同的實體通過包裝在函式中的 channel 彼此呼叫。

Client 與 Server 互動設計方案

Player connect(玩家連線)

Player Disconnect(玩家斷開連線)

Client input(客戶端輸入)

Profile

Profile 是研究 Golang 效能並找出 slow components 的方法。執行伺服器時,可以使用標誌 --cpuprofile--memprofile 來配置 server。

cd server
go run cmd/server/* --cpuprofile --memprofile

程式碼結構

├── server
│   ├── cmd
│   │   └── server
│   │       └── server.go: Entrypoint running server
│   ├── game
│   │   ├── common
│   │   ├── config
│   │   │   └── 1.map: Map represented 0 and 1
│   │   ├── gameconst
│   │   ├── game.go: Game master objects, containing logic and communication
│   │   ├── mappkg
│   │   ├── objmanager
│   │   ├── playerpkg
│   │   ├── shape
│   │   ├── shootpkg
│   │   ├── types.go
│   │   └── ws
│   │       ├── wsclient.go
│   │       └── wshub.go
│   ├── generate.sh: Generate protobuf for server + client + AI environment
│   ├── message.proto
│   └── Message_proto
│       └── message.pb.go
├── Dockerfile
└── run_local.sh

AI 訓練設計方案

此倉庫包含遵循 openAI Gym 格式和訓練指令碼的 CS2D 環境。
訓練指令碼使用 NeuroEvolution(神經進化)在迷宮中找到到達目的地的最短路徑。

https://www.youtube.com/watch?v=pWbb1m91mhU

執行

按照的說明執行 gowog 環境。即本地 Docker 執行:

./run_local.sh

使用 virtualenv 設定 python3 虛擬環境(直接用 Docker 吧~)。

  • 安裝 requirements.txt 所包含的庫。

執行訓練指令碼

python train_ga.py -n save_file_name

save_fie_name 是儲存權重(weights)的地方。
在下一次,如果我們指定了一個現有的檔案,它將繼續從該檔案的最後一次執行中的權重(weights)進行訓練。

Genetic Algorithm(遺傳演算法)

_cs2denv_ga.py 的實現_

基於機器學習的目的,CS2D Agent 是在 CS2D 上構建的。
它遵循 openAI gym,支援 agent 的基本方法,包括:reset()step()observation_spaceaction_space

ObservationSpace 是一個一維陣列,它由來自伺服器的 update_player 訊息構造而成

  1. Player position(玩家位置), player size(玩家大小尺寸), number of columns(列數), number of rows(行數), block width(塊寬度), block height(塊高度
  2. 到左,右,上,下到最近 block()的距離。此輸入是為了避免碰撞
  3. 玩家在二進位制塊地圖(binary block map)中的位置。地圖是 012 維陣列(0 為空,1 為塊)
  4. binary block map

獎勵是 1 / distance(目標的距離)。如果 agent 接近目標 100 點,那麼獎勵就是 1,情節結束。

NeuroEvolution(神經進化)

_train_ga.py 的實現_

神經網路(Neural Network)通過使輸入(觀察空間)通過神經網路來獲得最佳動作。

NeuroEvolution(神經進化)是使用進化演算法不斷改進人工神經網路的AI。對於每次迭代(生成),程式將基於前一次迭代中的最佳設定生成一組新的神經網路權重。 由先前的 NN(神經網路) 生成一個 NN 的過程叫做 Mutate,它給神經網路中的每個引數新增隨機噪聲。

一個特別的改進是,我們只儲存應用於神經網路的噪聲種子列表,而不是儲存所有的代權值。因為在同一個種子下,所有的隨機化都是相同的,所以一個種子可以代表一個網路的突變運算元。我們不需要保留每一代的所有權值,我們只需要儲存一組從開始到當前一代的種子,然後從這組種子中重新構造權值來得到所有神經網路的權值。

程式碼是基於 Maxim Lapan"Deep Reinforcement Learning Hands-On"

我是為少。
微信:uuhells123。
公眾號:黑客下午茶。
謝謝點贊支援???!

相關文章