krimchangのブログ

日々の発見を書き連ねるブログ

Startup Companyが面白すぎてハマった

store.steampowered.com

ウェブサイトを経営し、ウェブ広告やサブスク使用料により稼いでいく。

ウェブサイトのアップデート時はコンポーネントが必要で
コンポーネントは以下の2パターンで作成できる。

  1. 自社社員に作成させる。
  2. アウトソーシングし作ってもらう。

自社社員に作成させると、経費はトータル安く済むが。
アウトソーシングの方が早く完成する。

個人的には
初級者レベルのコンポーネントアウトソーシング
上級者レベルは自社作成するプレイスタイルがオススメ。
もしかすると、もっと良いスタイルが有るかもしれない。

ユーザ数1位目指してがんばるぞい。

セーブデータについて

セーブデータは超シンプルなjson形式なので
テキストエディタで所持金とか簡単に増やせてしまう。

実験やチートエンジョイしたいなら良いけど
通常プレイでは忘れてしまうのがオススメ

アンサイクロペディアのC++記事に有るHelloWorldは、C++11以降動かない

以下のソースコードです。

#include <iostream>

template<char O, bool =O == 'h'? '-' :O == 'w'? '=' :0>class _; 

template<char O>std::ostream&operator<<(std::ostream&lhs,_<O,0>*) {
    return lhs << O;
}

template<char O>std::ostream&operator<<(std::ostream&lhs, _<(O), 'o'>*) {
    return lhs<<(char)(O - '!' + '.' - '-' );
}

template<> std::ostream&operator<<<'~'>(std::ostream& m9,_<'~', 'o'>*) {
    return m9<<('m');
}

int main(int orz=3) {
    std::cout<<(_<'h'>*)0<<(_<'e'>*)0<<(_<'l'>*)0<<(_<'l'>*)0<<(_<'o'>*)0<<(_<'w',0>*)0<<(_<' '>*)0<<(_<'w'>*)0<<(_<'o'>*)0<<(_<'r'>*)0<<(_<'l'>*)0<<(_<'d'>*)0<<(_<'!'>*)0<<std::endl;
    return 0;
}

引用元(アンサイクロペディア C++)

C++11以降、このソースはコンパイルエラーとなります。

なぜ

結論から先に記載してしまうと

  1. 非型テンプレート引数は定数式(constant expression)であり
  2. 定数式は縮小変換(narrowing conversion)を行うことが出来ないため。

となります。

非型テンプレート引数(typename Tやclass Tでない)は
C++規格で言う定数式(constant expression)であり

定数式は縮小変換(narrowing conversion)を行うことが出来ません。

確認

エラーになる箇所を確認してみます。

template<char O, bool =O == 'h'? '-' :O == 'w'? '=' :0>class _; 

char Oが'h'または'w'の時
bool = '-' または '='として展開されますが。

'-'や'='は1を超過しているため(1 < '-')
bool代入は縮小変換に該当してしまい、エラーになります。

以下のソースコードも 同じ理由でエラーです。

template<char O>std::ostream&operator<<(std::ostream&lhs, _<(O), 'o'>*) {
    return lhs<<(char)(O - '!' + '.' - '-' );
}

template<> std::ostream&operator<<<'~'>(std::ostream& m9,_<'~', 'o'>*) {
    return m9<<('m');
}

第2テンプレート引数に'o'が渡っており
上記と同じ縮小変換に該当してしまいます。

解決方法

解決方法を幾つか考えてみましたが
正直言ってイマイチです。

class _のデフォルト引数を0or1にするとか

template<char O, bool =O == 'h'? 1 :O == 'w'? 1 :0>class _{}; 

引数指定部では!=を挟むとか

template<char O>std::ostream&operator<<(std::ostream&lhs, _<(O), 'o' != 0>*) { // != 0を挟む
    return lhs<<(char)(O - '!' + '.' - '-' );
}

明示キャストを挟むとか

template<> std::ostream&operator<<<'~'>(std::ostream& m9,_<'~', static_cast<bool>('o')>*) { // 定数式変換前に明示的キャストを行う
    return m9<<('m');
}

うーん

#include <iostream>

template<char O, bool =O == 'h'? 1 :O == 'w'? 1 :0>class _{}; 

template<char O>std::ostream&operator<<(std::ostream&lhs,_<O,0>*) {
    return lhs << O;
}

template<char O>std::ostream&operator<<(std::ostream&lhs, _<(O), 'o' != 0>*) { // != 0を挟む
    return lhs<<(char)(O - '!' + '.' - '-' );
}

template<> std::ostream&operator<<<'~'>(std::ostream& m9,_<'~', static_cast<bool>('o')>*) { // 定数式変換前に明示的キャストを行う
    return m9<<('m');
}

int main(int orz=3) {
    std::cout<<(_<'h'>*)0<<(_<'e'>*)0<<(_<'l'>*)0<<(_<'l'>*)0<<(_<'o'>*)0<<(_<'w',0>*)0<<(_<' '>*)0<<(_<'w'>*)0<<(_<'o'>*)0<<(_<'r'>*)0<<(_<'l'>*)0<<(_<'d'>*)0<<(_<'!'>*)0<<std::endl;
    return 0;
}

問題を解決したは良いものの
元記事にあるユーモア性が失われてしまいました。

ユーモアのあるソースコードを書くのは難しいですね

参考

超参考にしたstackoverflow質問。10割答え

Narrowing int to bool in SFINAE, different output between gcc and clang

また、上の質問には書かれていませんが。
仕様書には、定数式での文脈上bool変換(contextually converted to bool)は
[expr.const]に記載された変換しか受け付けてくれない

とご丁寧に記載されています。
(英検100級なので翻訳に自身がない)

[expr.const] A contextually converted constant expression of type bool is an expression, contextually converted to bool, where the converted expression is a constant expression and the conversion sequence contains only the conversions above. https://eel.is/c++draft/expr.const

しかし、普通に考えて
何もbool変換まで、縮小変換NGにする必要は無かったのではと
考えざるを得ません。

この辺りの経緯や意図については
今後の宿題ですね。

巡り廻る。V2.01をWineでプレイ

めぐめぐV2.01をwineでプレイしてみました。

環境

OS: Lubuntu 20.04 LTS
Wine: V5.0
巡り廻る。: V2.01

手順

躓きポイントや問題点等描き下ろしてから入りたいところですが
「いいからはよ手順教えろやボケェ!」と言われそうなので先に手順を書きます。

※1. 本手順は自分が成功した手順となります。公式で紹介されている手順等ではございません。
※2. 成功しなかった場合でも自己責任でお願いいたします。

1. 巡り廻るをダウンロード

めぐめぐ一式をダウンロードします。
https://wikiwiki.jp/guruguru/

f:id:krimchang:20201115195726p:plain
今回はV2.01(正規版)をダウンロード

2. ファイル一式を解凍

ターミナルを開いて、ダウンロード先のディレクトリまで移動したら
-Oオプション付きunzipで解凍します。

unzip -O sjis [巡り廻るファイル名(zip)]

※ ファイルマネージャやオプション無しunzipから解凍すると文字化けします。

(unzip sjis解凍参考: https://qiita.com/toyoshim/items/be4613fa373b4847196f)

3. グラフィック表示をソフトウェアモードにする(任意)

解凍出来たら、中にあるConfig.exeをwineで起動し
グラフィック表示モードをソフトウェアモードにします。
(理由は不明ですが、ハードウェアレンダリングだと正常に動かないケースが有るみたい?です)

f:id:krimchang:20201115195631p:plain

4.wineでGame.exeを起動

上手くプレイ出来れば成功です。

f:id:krimchang:20201115195808p:plain

f:id:krimchang:20201115195827p:plain

以下のような画面になった場合、解凍時に文字化けが発生したか
ファイルが欠損しているかもしれません。

f:id:krimchang:20201115195904p:plain

ファイルの状態や手順を確認し、もう一度試してみてください。

躓いたポイント

1.普通に解凍したらファイルが文字化けした

linux上の文字コード(UTF-8)と、めぐめぐが想定しているであろうwindows文字コード(SJIS)の不一致が多分原因です。
おのれSJIS SJIS死すべき慈悲はない。

なので、本記事で行ったような方法(unzip -O sjis)を使い
上手く文字化けしないように解凍する必要が有ります。

2.プレイしてたら強制終了エラーが頻発した。

ソフトウェアモードに切り替えた原因です。
3Dモードでプレイしていた所、戦闘時に高確率でエラー終了しました。

wineではウディタのハードウェアレンダリングが上手く動かないとの記載を見かけ
試しに切ってみた所、現象は発生しなくなりました。

とはいえ、環境による差異も有ると思いますので
動かなくなったら試す程度でも良いかも…

現状の問題点

BGMが出ない

BGMが一切出ません。(その他の音は出ます)
ターミナル上のエラーログに「err:winediag:MIDIMAP_drvOpen」とか出ているので
これが原因かなぁと思いつつ面倒で調べていません。
BGMが無いのはちょっと寂しいですが、代わりに作業用BGMでも流しておきましょ。

おわりに

V1.21時代はWindowsでプレイしていましたが、心機一転OSごと変え振り出しからスタートしました。
V1.21時代はストーリーはよはよで進めてしまったので、今回はのーんびり旅プレイでもしようかと思います。でもエターナルモードも気になりますね。
はてさて、世界の絶望を断ち切るのはいつになるのーやら。