Civilization7 が楽しい
92 時間遊びました
そしてこんな感じ。
難易度神で勝利直前のターンの様子。
イブン・バットゥータでマヤ→アッバース→アメリカの流れ。
いろいろ分かってきたので、つらつらと書いていこうかなと。
UI が終わっている
本当に終わっている。いくつかの方向性でそれぞれ終わっているが、改善するって分かってることに文句言っても不毛なのでスルー。 当座の個人の対処法としては UI MOD 入れようという話か。
スタート直後の外交と戦争
相変わらずの運ゲー。近所の狂犬に因縁を付けられたら終わる。徴側お前のことやぞ。
難易度によるAI補正は立ち上がりが一番強くて、それをプレイヤーが頑張って追い抜くという流れ。時代が進むと色々リセットされるので、この追い抜きを3回繰り返すことになる。つまりスタートしてから内政が軌道に乗るまでの期間はAI文明に対してかなりのビハインド(特に太古はデカい)を背負うことになる。ということは軍事力でも劣るワケなので、舐められて宣戦布告されて戦闘力+8の暴力で終わるパターンになりがち。じゃあそもそも戦争にならないように外交で乗り切ろうっていう話になるのだけど、いうて最序盤なので出来ることも限られている。ていうか、舐められると非難が飛んできて関係が冷え切ったところで正規戦争ということになりがち。関係改善のために交易路を…って思っても、大抵は交易路がアンロックされる前に戦端が開かれる。
関係悪化のパターンには、「アジェンダ違反」「相手文明の近くに都市」もあるのだけど、これらは割と対処のしようがない。特に後者は判定範囲がかなり広い上、相手が寄せてきても発生するのがなかなかに最悪(関係値が双方向なのでしょうがなくはある)。思うに、「高難易度で容赦なく拡張してくるので関係悪化しやすい」「戦闘力+8の補正ボコられる」のせいで、最序盤のアンコントローラブルな部分が悪目立ちしているのだろう。
外交関係に補正を持っている文明・指導者やら、記念品の「リヴィウス論」やらでケア出来るかもしれない? 時代がうつりかわるタイミングで記念品を付け替えられるので、最序盤の安定化に特化した記念品構成が良さそう? このあたりは要研究。
今のところの結論は「最序盤で宣戦布告されたら殺意を胸に秘めてさっさと次のシド星へ行くヨロシ」
それ以降の外交と戦争
同大陸のトップ文明と仲良くできるかに全てがかかっている。
戦争が発生するとその同盟国がぞろぞろと参戦してくるシステムなので、「連合国」に入れず「枢軸」になってしまうと端的に言って終わる。枢軸側で戦争に突入すると消耗戦に引きずり込まれてAIの補正にすり潰され、内政に集中できないので文明の発展が遅れてどんどん不利な状況に追い込まれ、仮に損失を出さずに和平までこぎつけたとしても一度戦争した文明とは関係が劇的に悪化するので結局不利な戦争は再燃する。また、連合国側に外交志向の指導者(主に卑弥呼)が居ると、勝手に敵が増えていって最終的には世界の敵になってしまうこともある。
AI文明は勝利条件の達成が下手くそなので、どんなに出力の高い文明でも勝利条件の障害にはなりにくい。よって、トップ文明を早期に始末しようなどと考えない方が良い。それよりも、トップ文明との同盟は安全保障上の爆アドで、それだけで様々なコストをカットすることが出来る(もしくは戦争を1方面に集中出来る)と考えて、関係改善のために惜しみなく影響力を投入すると良いだろう。トップ文明なら都市数も多いはずで、であれば交易商もいっぱい出せるはずなので、理にかなった選択なはず。
イデオロギー
一番重要な同盟国と合わせるのが無難。なんなら取らなくても良い。実際、冒頭のスクショのケースでは同盟国がいつまでたってもイデオロギーを確定させなかったので、自文明もイデオロギーツリーを取らずにクリアしている。
イデオロギーツリーを進めると強い政策カードがアンロックされたりもするが、無いと勝てないようなものでもない。安全保障(≒内政集中出来る環境)と天秤にかけたら、そりゃあ安全保障を取るべきだろう。
難易度補正
今作の難易度補正は「AIの出力最低保証」だと思えば良さそう。つまり「指導者・文明を使いこなせてないバカなAIでも最低でもこのくらいの出力は出ますよ」のラインが難易度で決まる感じ。逆にピーク出力は、ほぼほぼ文明・指導者能力の影響で決まる(実際、難易度副王でAI卑弥呼に文化2000を出された事がある)。
で、この「最低ライン」は「人間がバニラ文明でちゃんと内政やったら、時代の終わりでこのくらい」じゃないかと思う(時代の開始時は相変わらずAI有利)。だから、基本的な内政をちゃんとやれてる上で、文明・指導者の能力をちゃんと活かせればAIに対してリードを築くことが出来るはず(だと思いたい)。
文化・科学力
出力をちゃんとだそうと思うと、かなり計画的に内政を進める必要がある。
今作で文化力・科学力を出すために最も重要なのは専門家。専門家1人ごとに「配置先タイルが受け取る隣接ボーナスを +0.5 する」効果がもらえるから、隣接ボーナスに気にして都市計画を立てる必要がある。
隣接ボーナスは、建造物の種類ごとに「海・航行可能な河川沿い」「資源の隣」「山岳の隣」「自然遺産の隣」あたりが設定されている。また、全ての建造物共通で遺産からボーナスを受け取ることが出来る。専門家を集中配置した場合2~3タイルくらいが埋まるので、専門家を集中配置する予定のタイルを上述の要素+世界遺産で囲えば良い。そして、世界遺産は古代がアツいし、「時代を問わない」系の建造物は一度建てたら解体できないし、市街タイルは更地に戻せない。そう、どのタイルに何を立てるかは、綿密に計画する必要がある…。
ただし、近代最初の「社会問題」でアンロックされる政策カードで専門家の出力が上がるので、近代では隣接ボーナスの重要度がちょっとだけ小さくなる。
専門家によって高出力化したタイルは探索の時代の化学レガシーパスの条件でもあるので、実質的には都市計画必須。また、専門家を活用できてないと高難易度AIの発展には追いつけない。多分これ初心者の最初の壁だと思う。
生産力
「文化力・科学力の高い都市」とは別に「生産力の高い都市」を作る方法もある。
前述の通り、文化力・科学力を狙う場合はそれなりの数の遺産(タイル出力が決まっているし大抵は生産力を持っていない)が建つことになるし、(隣接ボーナス無いから)倉庫建造物もできるだけ建てたくないので、郊外タイルはほぼ使えない(ていうか最終的には資源タイル以外全部市街で埋まる)。専門家で生産力をカバーしたければ生産力系の建造物を頼るしかないが、よりによって隣接ボーナスを科学力系建造物と食い合うので、あまり現実的ではない。
なので、生産力特化の都市を作りたければ、専門家による高出力を諦めて、倉庫タイルで伐採所(樹草)・鉱山(荒地)を強化して生産力を絞り出すと良い。最終的には鉱山から生産力が+5か+7くらいは出るので、専門家を配置して+2を受け取るのより圧倒的に効率が良い。最終的な出力で言っても、遺産・専門家と無縁な生産力特化都市の方が1.2~1.5倍位の生産力を出せる。
専門家都市をツメツメでやると全タイルすでに埋まっちゃってたりするし、そうでなくても勝利条件遺産の建造のために生産力が必要なはずなので、近代の最後の詰めで生産力都市を作るのはあり得る。
食料・人口
前述の専門家都市にしろ生産力都市にしろ、実現には人口が必要で、人口を増やすには食料が必要。それらをどこから持ってくるかというと、町から輸出するのが良い。
このゲームの基本的システムとして、町が「成長に専念」している間は食料は地産地消されるが、それ以外(例えば農業の町)に専念させると、「その町の余剰食料」が「接続されている都市」に輸出される(等分される)。つまり、都市の食料収入は各町に外部化可能。前述の通り、都市は食料にかまけてる余裕なんて無いので、食料は町任せで良いだろう。
町をいつ専業化すべきかは…まだなんとも言えない。全ての資源を取った上で、次の人口成長までのターン数が 7~8 ターンに差し掛かったら専業化か?
世界遺産
前述の通り、貴重な隣接ボーナス供給源なので、計画的に建てていきたい。
太古はまぁまぁ競争率が高い(文化レガシーパスの条件にもなってるし)が、都市が発展すればするほど場所がなくなっていく関係か、時代が進むほど競争率が下がる傾向にある…ような気がする。
過去作と比べると遺産レースがあんまり苛烈じゃないような気も? というか、遺産からの隣接ボーナスありきで難易度設計されてるので、プレイヤーが遺産を立てる余地を残してくれていると考えるべきか?
レガシー
文化・化学の黄金時代レガシーの「隣接ボーナスが残る」効果が超重要。これの有無で、時代開始直後の立ち上がりが大きく変わる。しっかりやれば、近代1ターン目で神AIのインチキ補正を超えることも可能。
それ以外の強いか弱いかわからないようなレガシーを取るくらいなら、属性ポイントを取ったほうが良いように思う。
軍事ユニット
歩兵があまりにも弱すぎて、今のところコストが安い以外のメリットが無い。AI相手に消耗戦になったらオシマイなので、歩兵を選ぶ理由が全くない。特に、戦闘力的に厳しい高難易度であればなおさら。ここは今後のアプデに期待か。
Windows 10 で謎の暗転がしばしば発生する問題が解決した
# 症状
- ツクールMZ製のゲームを起動した時、1秒程度の画面暗転が何回か発生する
- 動画再生中のブラウザ(chrome)をウィンドウをメインウィンドウ・サブウィンドウ間で移動させた時、1秒程度の画面暗転が発生する
- 画面暗転というのは、ゲームのウィンドウ・フルスクリーンを切り替えた時のアレに近い感じ
# 問題点
- フルスクリーンに切り替えてないのに、フルスクリーンに切り替えた時みたいな暗転が発生してキモい
- 操作不能な時間が発生してウザい
- 原因が意味不明でつらい
# 解決方法
# 詳細
## ディスプレイ > 解像度の変更
- 「NVIDIAのカラー設定を使用」にチェック入れる
- グループ内の設定は「最高(32 ビット)」「RGB」「8 bpc」「限定」
## ディスプレイ > デスクトップ カラー設定の調整
- 「リファレンスモードに上書き」にチェックを入れる
- 多分これが効いた(その1)
## ディスプレイ > デスクトップのサイズと位置の調整 > スケーリング
- 「縦横比(S)」にチェックを入れる
- 「ゲームとプログラムによって設定されているスケーリングモードを上書きする(O)」にチェックを入れる
## ディスプレイ > デスクトップのサイズと位置の調整 > サイズ
- 「デスクトップのサイズ変更を有効にする(N)」のチェックを外す(元々チェックされてないはず)
## ビデオ > ビデオカラー設定の調整
- 「NVIDIA の設定を使用(N)」にチェックを入れる
- 多分これが効いた(その2)
## ビデオ > ビデオイメージ設定の調整
# なぜ直るのか?
- 多分 windows 側でロクでもないこと(ユーザーが注視しているコンテンツに合わせてディスプレイの色モード変えるとか)をしている
- nVidia 側の設定を変更することで、そうういったロクでもないフローに入らなくなる
- 証拠ないから、ただの推測だけどね
# 参考
Eigen3 の eulerAngles の値域
eulerAngles
使い方
- 回転行列からオイラー角に変換できる。
- 0, 1, 2 を渡した場合、回転順序は X <-- Y <-- Z になる
using namespace Eigen;
const Vector3f originalInEuler= { 0.2f, 0.4f, 0.6f };
const AngleAxisf originalInAa =
AngleAxisf( originalInEuler(0), Vector3f::UnitX() ) *
AngleAxisf( originalInEuler(1), Vector3f::UnitY() ) *
AngleAxisf( originalInEuler(2), Vector3f::UnitZ() );
const Vector3f resultInEuler = Quaternionf(originalInAa).toRotationMatrix().eulerAngles(0, 1, 2);
オイラー角の値域
ドキュメントより
- X : [0, +180] deg
- Y : [-180, +180] deg
- Z : [-180, +180] deg
問題点
- X 回転が 0 <--> 180 deg で不連続になる
- -180 <--> 180 deg なら ±360 deg の補正をかけることで連続扱いできるが、 0 <--> 180 deg だとどうあがいても不連続
- そのため、真の X 回転がほぼ 0 deg ちょうどの場合でも、数値誤差で 0 deg がでたり 180 deg が出たりする
- ±180 deg で不連続なのは想定内として、 0 deg で不連続なのは場合によっては不便
じゃあどうするのか?
※以下は引数に 0, 1, 2 を渡した場合の話
- X 回転を求めるのに atan2 を使っているので、直接得られるのは [-180, +180] の値
- それを [-180, 0] に収まるように、 atan2 で得られた値が 0 deg 以上なら -180 deg の補正を行っている (最後にオイラー角の符号を反転させているので、計算途中の値は符号が反転している)
- この -180 deg 補正のフローに入る分岐を削除したオレオレ eulerAngles を作ればいい (幸い、 Eigen3 はヘッダオンリーだからソースは見れるし、 eulerAngles は実装自体は結構簡素)
感想
- なんで [0, +180] に限定したんだろうか?
Satisfactory サーバーの立て方
# この記事は
GCP で VM インスタンスを立てて、そこで Satisfactory サーバーを動かす方法を書いた手順書です。
# 方針
- とにかく手を抜く
# 最低限ワールドに入れるようになる所まで
## プロジェクトの作成まで
- GCP のコンソールから、新しいプロジェクトを作成する。
- プロジェクト名は Satisfactory にしておく。
## インスタンスの作成まで
- GCP のコンソールから VM インスタンスを有効化
- 「VM インスタンス」から「インスタンスを作成」
- 「名前」を「game-server」に変更
- 「リージョン」を「asia-northeast1(東京)」に変更
- 「マシンタイプ」を「e2-standard-4 (4 vCPU、 16 GB メモリ)」に変更
- 「ブートディスク」の「変更」をクリック
- 「ネットワークタグ」を「satisfactory」に変更
- 「作成」をクリック
## SSH ログインまで
## Satisfactory サーバーのインストールまで
- まずはパッケージ更新
sudo apt update sudo apt -y upgrade
- multiverse リポジトリを有効化
sudo add-apt-repository multiverse sudo dpkg --add-architecture i386 sudo apt update
- steamcmd を入れる
sudo apt install -y lib32gcc-s1 steamcmd
- steamcmd プロンプトに入る
steamcmd
- 匿名ユーザーでログイン
login anonymous
- Satisfactory サーバーをインストール
app_update 1690800 validate
- steamcmd プロンプトを抜ける
exit
## Satisfactory サーバーを起動するところまで
- tmux をインストール
sudo apt -y install tmux
- tmux セッションに入る
tmux
- Satisfactory サーバーを起動
Steam/steamapps/common/SatisfactoryDedicatedServer/FactoryServer.sh
## 必要なポートを開けるところまで
## 動作確認取るところまで
- CGP コンソールの「VM インスタンス」で「外部 IP」をコピー
- satisfactory を起動
- メインメニューで「サーバー管理」を選択
- 「サーバー追加」を選択
- さっきコピーした「外部 IP」を「アドレス」に入力して「確認」をクリック
# 終盤も快適にプレイできるように設定する所まで
## チューニング要る?
- 少なくとも、オートセーブだけは絶対にやったほうが良い
- オートセーブ中の移動や作業はロールバックされてしまう
- 高頻度のオートセーブ=高頻度の作業中断
- ウザくならない程度にオートセーブ頻度は下げたほうが良い
- 設定ファイルを書き換えてのチューニングは終盤までにはやりたい
- ゲーム終盤(100h~)までいくと、プレイに支障が出るレベルで重たい
## オートセーブの間隔を 30 分に変更
- インゲームのサーバー管理メニューから「コンソール」タブを開く
FG.AutosaveInterval 1800を入力
## クライアントのネットワーク帯域制限を撤廃
- クライアント PC の
%localappdata%\FactoryGame\Saved\Config\WindowsNoEditor\
の各設定ファイルを書き換える - ※同名の変数が最初からある場合は上書き、ない場合は追記 - Engine.ini ``` [/Script/Engine.Player] ConfiguredInternetSpeed=104857600 ConfiguredLanSpeed=104857600
[/Script/OnlineSubsystemUtils.IpNetDriver]
MaxClientRate=104857600
MaxInternetClientRate=104857600
[/Script/SocketSubsystemEpic.EpicNetDriver]
MaxClientRate=104857600
MaxInternetClientRate=104857600
```
- Game.ini
```
[/Script/Engine.GameNetworkManager]
TotalNetBandwidth=104857600
MaxDynamicBandwidth=104857600
MinDynamicBandwidth=10485760
```
- Scalability.ini
```
[NetworkQuality@3]
TotalNetBandwidth=104857600
MaxDynamicBandwidth=104857600
MinDynamicBandwidth=10485760
```
- 書き換えた各ファイルを「読み取り専用」にする
## サーバーのチューニング
- サーバーインスタンスの
~/Steam/steamapps/common/SatisfactoryDedicatedServer/FactoryGame/Saved/Config/
の各設定ファイルを書き換える - ※同名の変数が最初からある場合は上書き、ない場合は追記 - Game.ini ``` [/script/engine.gamenetworkmanager] TotalNetBandwidth=104857600 MaxDynamicBandwidth=104857600 MinDynamicBandwidth=104857600 MAXPOSITIONERRORSQUARED=32.00f MoveRepSize=512.0f CLIENTADJUSTUPDATECOST=512.0f bMovementTimeDiscrepancyDetection=false bMovementTimeDiscrepancyResolution=false bMovementTimeDiscrepancyForceCorrectionsDuringResolution=false MAXCLIENTUPDATEINTERVAL=2.20f MaxMoveDeltaTime=0.700f MaxClientSmoothingDeltaTime=2.20f MaxClientForcedUpdateDuration=1.0f ClientNetSendMoveDeltaTime=0.0332 ClientNetSendMoveDeltaTimeStationary=0.0664 ClientNetSendMoveThrottleOverPlayerCount=99 ServerForcedUpdateHitchThreshold=2.800f
[/script/engine.gamesession]
MaxPlayers=10
```
- Engine.ini
```
[CrashReportClient]
bAgreeToCrashUpload=false
bImplicitSend=False
[Engine.ErrorHandling]
bPromptForRemoteDebugging=False
bPromptForRemoteDebugOnEnsure=False
[/script/onlinesubsystemutils.ipnetdriver]
MaxInternetClientRate=104857600
MinInternetClientRate=104857600
MaxClientRate=104857600
MinClientRate=104857600
LanServerMaxTickRate=15
NetServerMaxTickRate=15
ConnectionTimeout=100.0
InitialConnectTimeout=200.0
[SystemSettings]
t.MaxFPS=15
AllowAsyncRenderThreadUpdates=1
AllowAsyncRenderThreadUpdatesDuringGamethreadUpdates=1
net.UseRecvMulti=0
net.RecvMultiCapacity=8192
net.IpNetDriverUseReceiveThread=0
net.IpConnectionUseSendTasks=1
net.IpNetDriverReceiveThreadQueueMaxPackets=8192
net.MaxNetStringSize=67108864
net.MaxRPCPerNetUpdate=8
tick.AllowAsyncComponentTicks=1
tick.AllowConcurrentTickQueue=1
tick.AllowAsyncTickDispatch=1
tick.AllowAsyncTickCleanup=1
[/script/engine.player]
ConfiguredInternetSpeed=104857600
ConfiguredLanSpeed=104857600
[/script/socketsubsystemepic.epicnetdriver]
MaxClientRate=104857600
MaxInternetClientRate=104857600
[/script/engine.engine]
bSmoothFrameRate=true
bUseFixedFrameRate=false
SmoothedFrameRateRange=(LowerBound=(Type=Inclusive,Value=5.000000),UpperBound=(Type=Exclusive,Value=15.000000))
MinDesiredFrameRate=8.000000
FixedFrameRate=15.000000
NetClientTicksPerSecond=15
[/script/engine.garbagecollectionsettings]
gc.MaxObjectsNotConsideredByGC=476499
gc.SizeOfPermanentObjectPool=100378488
gc.ActorClusteringEnabled=True
gc.BlueprintClusteringEnabled=True
[/script/engine.streamingsettings]
s.EventDrivenLoaderEnabled=True
s.AsyncLoadingThreadEnabled=True
[Core.System]
+Suppress=Scriptwarning
+Suppress=Error
+Suppress=Scriptlog
+Suppress=Warning
[Core.Log]
LogPluginManager=all off
LogOnlineIdentity=all off
LogOnlineSession=all off
LogMemory=all off
LogPakFile=all off
LogTemp=all off
LogLinker=all off
LogOnline=all off
LogOnlineGame=all off
LogAnalytics=all off
LogConfig=all off
LogInteractiveProcess=all off
LogInput=all off
LogOnlineEntitlement=all off
LogOnlineEvents=all off
LogOnlineFriend=all off
LogOnlinePresence=all off
LogOnlineTitleFile=all off
LogOnlineUser=all off
Global=off
```
- 書き換えた各ファイルを「読み取り専用」にする
chmod -w Game.ini chmod -w Engine.ini
参考
Civilization 6 のオンラインマルチをやってる時に接続が怪しくなった
ことの起こり
- オンラインマルチでフレンドと civ6 をやっていた
- ゲーム中盤入ったくらいから
- 毎ターン同期ずれが発生するようになった
- 2ターン進めるのに数十秒待たされるようになった
- ゲーム終盤入ったくらいから
- クライアント側がクラッシュするようになった
- クライントがゲームに参加できなくなった
解決方法
以下の手順を、マルチの参加者全員が行う。
- "%USERPROFILE%\Documents\My Games\Sid Meier's Civilization VI" の直下にある、
- logs
- dumps
- cache
- moduserdata
- packageddumps を削除。
- PC を再起動
- Stream で civ6 の「ゲームファイルの整合性を確認…」を実行
- 問題がある場合、修正します的なメッセージが出る
- その場合、2回目を実行して問題ありません的なメッセージが出なくなることを確認する
これを実行したあと、快適にターンが進むようになった(快適性+5)。
考察
- ゲームファイルに問題があったのは間違いない
- 整合性の確認で問題が出ていた
- ホスト側のログでエラーが出ていた
- キャッシュが不正だったかどうかは不明
- そもそもゲームファイルに問題があったのだから、キャッシュにも波及してそう
- 再起動は意味があったかわからない
- 一応やっとこうか、という程度
参考
Linux でユーザーの所属グループを編集する方法いろいろ
なんでまとめた?
やらかし(後述)たので
主グループを変更
# usermod -g <group name> <user name>
補助グループを変更(上書き)
こちらは「上書き」なので、変更前の補助グループリストは全部吹き飛ぶ。
# usermod -G <group name1>,<group name2>,... <user name>
補助グループを変更(追記)
こちらは「追記」なので、変更前の補助グループリストは残る。
# usermod -aG <group name1>,<group name2>,... <user name>
主グループと補助グループ
- 主グループは
- 1つだけ設定可能
- ファイル・ディレクトリ新規作成時に「所有グループ」として使われる
- 補助グループは
- 2つ以上設定可能
- 「グループに所属=権限がある」みたいなケースはこちらを使う
やらかしって?
- ubuntu で補助グループをオリジナルのグループで「上書きした」
- ところで ubuntu は「sudo グループに所属するユーザー=soder」という仕様になっている
- つまり、補助グループの上書きにより sudo 権限を吹き飛ばしてしまった!
- ちなみにその後は、リカバリーモードから root ログインして sudo グループを再設定することで復帰できた