Open8
Screepsプレイ用のOS制作
Screeps
It means "scripting creeps"
It's an open-source game for programmers, wherein the core mechanic is programming
your units' AI. You control your colony by writing JavaScript.
実装:https://github.com/mitsuyoshi-yamazaki/AntOS/pull/8
OS
OSの必要性
- 全体を統括する仕組みがなくともプレイは可能
- しかしCPU時間, メモリ容量に上限があるため、コードの複雑性が増すと身動きが取れなくなっていく
- また、ゲーム特有の構造があるため実装しにくい
- ~プレイヤーのスクリプトはtick毎に実行されるため、インスタンスとそれに紐づく全ての情報は永続化しない(永続化する際はゲームAPIから専用メモリに書き込む~
- コードがデプロイされるまでインスタンスは破棄されない
- イベントドリブンでないため、必要な情報はゲームAPIから毎tick取得する必要がある
- ~プレイヤーのスクリプトはtick毎に実行されるため、インスタンスとそれに紐づく全ての情報は永続化しない(永続化する際はゲームAPIから専用メモリに書き込む~
OSの機能
- デプロイやサーバー再起動で途切れるインスタンスのライフサイクルがあたかも途切れないかのように実装できるようにする
- 状態を永続化する
- 処理の単位を"プロセス"とする
- CPU, メモリの使用状況に応じてプロセスの実行密度を変更する
プロセス
基幹プロセス一覧
※ 基幹"プロセス"はOSの一部とする。Processではないため停止や遅滞実行させられない
- Root
- 他の基幹プロセス全てを起動、実行するブートストラップ
- EventDetector
- イベントドリブンなコーディングを実現する
- イベント監視を行い、オブザーバ登録をすれば通知されるようにする
- イベントドリブンなコーディングを実現する
- Logger
- ログ収集と出力を行う
- Launcher
- 手動でプロセスをstartさせる
- Quitter
- 手動でプロセスをkillする
- Messenger
- 実行中のプロセスに手動でメッセージを送る
プロセス仕様(OS側)
- Unixのようなプロセスの親子関係はつくらない(必要性が出たら考える
プロセス仕様
- プロセス単位の優先順位づけではなく、タスク単位で優先順位をつける
タスク仕様
- 優先順位情報と処理をまとめたもの
- 物理実体に貼り付けて使用する
- [条件達成]まで[行動]する という情報
- ❓ どのように永続化するか
prioritize仕様
priority
- always
- 常に実行
- normal
- CPU時間が逼迫したら実行間隔を落とされる
- if possible
- CPU時間が逼迫したら実行停止
prioritize
Standard IO
現状
- スクリプトに指令を与えるにはメモリを経由せねばならず冗長で危険
要件
- Screepsのコンソールから指令を与えられるようにする
実装仕様
- user-defined global variablesはアクセスできないのに対して、Gameオブジェクトに追加したメンバはアクセスできるため、Gameオブジェクトを経由させる
- 入力→
Game.io = (message: string): void
- 出力→
console.log
- 入力→
Objective
- 具体的に呼び出すAPIが定まっているtaskと抽象的なobjectiveにより行動を表現する
- 言葉の上では異なるがインターフェースは同じであるため同じ実装で表現する
Objective
- 未実行/実行中/停止中/成功/失敗の状態をとる
- Objective同士の親子関係
- 子の優先度は親の優先度で上限される
- すべてのObjectiveがProcessに準拠すると不都合があるため、Root Objectiveを実行するProcessを設ける
Problem Solver
- Objectiveが達成不能であるとき、どの子Objectiveを起動するか指定する
- 試行ができる
状態を保つObjectiveについて
- 部屋の安定
- Spawn, extensions, towersのチャージ
- Controllerのupgrade
- 一定期間動作していなければ警告を上げる
WrapperObjective
- 無理に共通化するのではなく、共通項のあるObjectiveをWrapするObjectiveをつくり、引数と返り値をそこで変換する
~状態の永続化~
- パースがめんどい
- mapperを用意する
- constructがめんどい
- 初期値を用意する
- 一箇所からinstantiateするようにする
Task
- Creepsに対するタスクを設定し、Creepに対するタスクと同様に扱えるようにする
- →harvester+haulerなど
- →creepの不足にどう対応する?