スピコラ考察

最近スピコラを全ルール全ステージで使ってS前後をウロウロしている。(A+は適当にやっても勝てるが、S+0にはボコボコにされる程度のウデマエ) スピコラの特徴を整理する。

立ち回り

最大の特徴は万能性にあると思う。 塗りをやらせても前衛をやらせても、そこそこ動けるので、ブキとしてはスシやZAPに近い立ち位置なると思う。 味方の構成と動きを見て、足りないポジションを補完できる。

射程と連射力が相まって塗りは強い。エリア塗りのような瞬間的な塗りが強く、スペシャルもそれなりに貯まる。 カーリングで強制的に塗れるのも塗り役として相性がいい。適当に後ろから流していてもラッキーキルが狙える。(カーリング強すぎだろ……。) 味方に前衛職が多ければ、ひたすら塗って裏方に徹するのもいいだろう。

対面も強くて、射程はスシ・ZAPより2キャラ分ぐらい長く、集弾性も悪くないので結構対面で打ち勝てる事が多い。ZAPなどと同じく確定4発なのでエイムは必要。 メインの射程はちょうどデボンエリアの味方屋根から敵屋根に届くぐらい。 カーリングを使って裏で暴れても結構いい感じ。後ろで暴れて雨も裏から打つと、敵ラインが前に出れなくなるので効果的だ。 味方に前衛職が少なければ、前に出るのもいいだろう。 しかし、どうしてもメインにタメが必要なのでインファイトや奇襲はあまり得意ではない。本職がいれば任すべきだろう。

苦手なこと

高低差が激しいステージだと、上にいる敵に対してほぼ為す術がない。 できるだけこちらが先に高台を取っていかなければならない。

また、スシより前衛力は低いし、わかば・モデよりは塗りが弱い。あくまで万能性を利用した柔軟な立ち回りを生かさなくては勝てない。

ほしいギア

ヒト速はデフォルトで1.3つけてる。 あとはメインインクがつくと動きやすく感じた。

スペ増積めばスペシャル型として立ち回れるが、その分前に出る意識が下がってしまうので特徴となる万能性が薄れてしまう。雨が打ちたければもみじがあるのでスピコラを持つ意味は薄まる。むしろスプスピに持ち替えてミサイル役に徹するのもいいかもしれない。 ホコやインクアーマー対策に対物積むのもいいし。エリアならサブインク積んでカーリング流しているだけでも現状維持・打開の援護射撃になる。(カーリング強すぎだろ……。)

https://twitter.com/_ksss_/status/984356619587764224

Shinjuku.rb #57で、"mrubykaigi"というタイトルの発表をした。

少し時間が立ってしまいましたが、Shinjuku.rb #57で話させていただきました。

shinjukurb.connpass.com

発端

弊社Repro, Inc.で定期開催している新宿.rbという地域コミュニティで、 「mrubyについて話しませんか」と人生初の登壇オファーを頂いたので快諾し、お話しさせていただくことになりました。

当日

本業がテンヤワンヤしていたので、予め資料を作っておいてよかった……。

発表した資料はこちら

https://gist.github.com/ksss/ff1dc20bcab3f7ab654cc40ce0df5aae

とはいえこの資料の内容は半分くらいしか喋っていません。

みんなどう思っているんだろうという所を知りたかったので、ディスカッションぽくトークできればいいなと思って、発表中もどんどん意見を求めました。

議題は「どうすればmrubyが流行るか?」と言うものだったのですが、様々な意見が飛び交い、思ったよりディスカッションぽくなったんじゃないかなと思います。

日頃から気になっていたmrubistの方々とも直接お話できて、思っていたよりmrubyへの関心が高まってるんじゃないかと手応えを得ました。

他の発表も非常に濃くて、自分では手が届いていない未知の世界を見せていただき、大変刺激になりました。

地味すぎて誰も気がついていないCRuby 2.5の新機能

did_you_mean gemがKeyErrorにも効くようになったよ

KeyErrorは指定したkeyに対するvalueが見つからなかったときに起こる例外で、IndexErrorから派生したものです。

KeyErrorが起こり得るのはHash#fetch Hash#fetch_values ENV.fetch Kernel.sprintf String#%の5つです。

このメソッド達で、探したkeyが見つからなかったときに近しい候補をサジェストしてくれるようになっています。

$ ruby
h = {foo: 1, bar: 2}
h.fetch(:bax)
Traceback (most recent call last):
    1: from -:2:in `<main>'
-:2:in `fetch': key not found: :bax (KeyError)
Did you mean?  :bar

実はCRuby 2.4でもrequire "did_you_mean/experimental/key_error_name_correction"と呪文を唱えると、Hash#fetchに対してdid_you_meanが効いていたのですが、やり方に気づかない上にHash#fetchprependでモンキーパッチする危ない実装だったので誰も使っていませんでした。*1

これはイカンと一念発起し、 KeyErrorに2つメソッドを追加しました。

bugs.ruby-lang.org

これで、NameErrorと同じく、エラーオブジェクトに原因となるオブジェクトを紐付けることができるので、モンキーパッチ無しでdid_you_meanを効かせることができます。

github.com

この辺で思いついた機能がついに実を結んだわけですね。

RubyでJSONをclassにmappingするやつと、2つの記法 - スペクトラム

ふるってご利用下さい。*2


*1:作者は私です

*2:本当はdid_you_mean作者のyuki24さんがRubyアドベントカレンダーに登録していたのを見て、ここで紹介されるだろうと思ってたけど、アドベントカレンダーの登録が消えたっぽいのでこのタイミングに。

mruby本体にmruby-methodを移管したよ

「mrubyにmethodメソッドはないのかな?」とおググりの皆さんに朗報です。

ksss/mruby-methodというライブラリでmethodメソッドは使えてはいたのですが、この度*1mruby本体にmergeしてもらいました。

github.com

理由としては、

ksss/mruby-methodを作ってからも「mrubyにはmethodメソッドないんですか」的なコメントがみられたり、

https://twitter.com/yukihiro_matz/status/788580277471711232 https://twitter.com/yukihiro_matz/status/777849074816995332 https://twitter.com/yukihiro_matz/status/938353972347146240

CRubyにも標準装備で環境依存の機能がないので入れやすかったり、

最近はmgemを本体に入れるのが流行ってたり *2

メソッドの持ち方が変わったときにメンテが面倒だったりしたからです。 *3

よりストレス無くmrubyを使ってほしいからです。

ふるってご利用下さい。

*1:と言っても去年

*2:偏見です

*3:一応直してからmergeした

今年買ってよかったもの

2017年に買ってよかったもの

Nintendo Switch & スプラトゥーン2

買ってよかったのか悪かったのか……、正直微妙ではあるが、ひたすらゲームが楽しかった。 ソフトはスプラトゥーン2しか持ってないのに5ヶ月遊べている。 スプラに飽きたらいったん休憩した方がいいと思う中毒性。

Nintendo Switch Proコントローラー

通称プロコン。これはスプラトゥーンを初めて2ヶ月後ぐらいに買った。 正直高いけど、使いやくはなっていると思う。ウデマエには全く影響しないと思う。 強いてあげるなら、スティックの感度が高いので無音移動しやすいとか、ある程度重みがあって、実際に武器を持っているかのような没入感がいいところだと思う。 電池はかなり持つ。充電は1週間に一度ぐらいに不安になって刺してるけどもっと持つかもしれない。 スティックの感度が高すぎて急に戻すと逆側に反応してしまうので、メニュー選択とかでは誤操作しやすいのがデメリットか。

ソファー

3万くらいで3人座れるソファーを買った。 ちょっとでかすぎたかもしれないけど、ほぼここが自分の居場所になってる。 自宅で仕事するときもだいたいソファーに座って作業している。 ポテンシャルはもっとあると思っていて、配置次第ではもっと活用できそう。

iPad

iPad miniを持っていたけど盛大に割れたので、2017モデルの無印iPad 64GB Wi-Fiモデルに買い替えた。 これまでiPad miniで十分と思っていたのは幻想で、どう考えてもiPadの方が満足感が高い。 理由は画面の大きさ。 iPad miniを使ってみてそれほど持ち出さないことがわかったし、なんなら持ち出したときに割れたのでもう持ち出したくない。。。 主に漫画(ジャンプ+とかkoboとか)と動画(YouTubeとかopenrec)に使っているので、大きい方が見やすくてうれしい。

2018年に欲しいもの

サイドテーブル

ソファーに座って仕事するときにコーヒー置き場がほしい

Razerのヘッドホン

これを使うとどこに誰がいるのか音でわかるようになるとかならないとか……!


来年もよろしくお願いします。

このブログは妻との相互企画でした。

shlyme.hatenablog.com

スプラトゥーン2ガチ初心者が5ヶ月かけてランクS+になるまでの軌跡

スプラトゥーン2を発売日の次の日ぐらいから初めて、ほぼ毎日プレイし続けて今日ようやく目標だったランクS+に到達した。

前作はプレイしていない。ゲームは好きだけど最近はポケモンとかだった。 FPSはほとんど経験ない。 こういう感じのゲームで近いのは、 GunZとかFEZとかはやったことあるぐらいか。

本当にスプラトゥーンばっかりしていたのでGitHubの草もわかりやすい感じになっている。

f:id:ksss9:20171222174803p:plain

うまくなるにはinputとoutputを等しく取るべし

大抵の物事はこの法則である程度上手くなれると思う。 inputとoutputをstream処理するのだ!

input == YouTube

スプラトゥーンにおけるinputとはYouTubeである。 YouTubeで上手いプレイヤーの動画を見まくるのだ。 僕はこれまでYouTuberなるものを見たことはなかったけど、YouTubeのサービス品質はすばらしい。 無料で高画質の動画を過去の分もライブも見れる。ライブ放送中もちょっと巻き戻したりできる。 openrec.tvなるサービスも初めて知ってすごいなあと思ったけど、課金しないと過去の分は見れないようだ。 ニコニコは見てない。

おすすめのYouTuberは

の3つである。(敬称略)

裏切りマンキーコング西澤さんは吉本のお笑い芸人であり、YouTuberであり、プロゲーマーでもある。 スプラトゥーン1の動画も大量にあげているのでおそらくスプラトゥーン業界では有名なんだと思う。 オールラウンダーを自称しているけど、わかば等の短射程ブキを使ったときのスピードが早すぎて理解が追いつかないほど。 環境毎に西澤さんの使うブキを参考に、自分の立ち回りも練習していた。 一番のおすすめ。

しをたんさんは正直そこまでめっちゃうまいわけではない(それでも自分よりはうまいんだけど)。 ネタで3.9系動画を上げることが多いので、このギアを付けるとこうなるみたいな知識が身につく。 検証や解説も丁寧でわかりやすい。

のわさんはプレイスキルが高いが西澤さんのように僕の理解を超えた上手さというよりは、僕でも理解できる上手さという感じで非常に参考になる。 戦略上の解説なんかも多めなので参考になることが多い。 淡々と勝つために必要なことを解説しつつ実践していく。

YouTuberを見る上で重要なのは、声の聞き取りやすさ、観ていて不快感がないかが重要になる。 紹介したYouTuberは、どれも声が聞き取りやすく、なんかいつも楽しそうだ。

他にもいくつかYouTuberを見ていたが、文句ばかり言うような人や、スプラトゥーンをプレイするモチベーションが下がってるなと感じると見るのをやめてしまった。

output == play

inputしたことをひたすら実戦で試してみる。 傘の動画を見たら傘を使い、スシの動画を見たらスシを使う。

さんぽもするし、試し打ちでの練習も重要だ。 上手いプレイヤーの動画では大体試し打ちでエイムを温めてから試合に望んでいた。

負けたらなんで負けたのか考えて、勝ったらなんで勝ったのか考える。 自分のプレイ動画を録画する機能がswitch本体にあるけど、30秒じゃよくわからない。

stream

inputとoutputを少しずつ処理して自分のものにしていく。 そう。stream処理である。 どちらか片方が多すぎるとバッファーが詰まったり、上達が頭打ちになってくる。

ひたすらreadしてwrite、readしてwriteだ。

よく使うブキ

わかばシューター/もみじシューター

機動力が高く、ちょこまか動いてひたすら塗ってスペシャル撒く役。 ブラスターやローラーやってると自陣の塗状況がいかに大切かよく分かる。 ボムが基本的な攻撃手段。あとはメインで塗って塗って塗りまくってスペシャルを吐きまくる。 いつの時代でも安定している。

スプラシューター/スプラシューターコラボ

ガチマッチは味方の武器構成が重要なので、オールラウンダー的なブキがやはり強い。 4人ブラスターはキツイけど、4人スシでも全然強い。 機動力もあるしキルも取れるし塗りもできる。 ひたすらスシを使ってこれが基礎だぞ!と練習していた時期があった。 今も強いと思う。

プライムシューター/プライムシューターコラボ

アップデートで強くなってから使うようになった。 撃ち合いになったときに勝ちやすい。 チームの守備要員という感じ。 バブルは使いどころが難しかったけどガチアサリで活躍できるようになった。

スプラローラー

Aランクから必要になるスキル「センプク」が習得できる。 単純に爽快感があるので楽しいブキ。 メインとイカニンとカーリングボムのシナジー効果が高い。

N-ZAP85

キューバンボムがつかえるスシという感じ。 オールラウンダー的なブキなのでどの試合でもそれなりに仕事ができる。 特にホコで勝率が高くて、対物をつけたZAPでA+〜S+まで一気に行けた。開幕でホコを割れる確率が高まる。

これまでの軌跡

とはいえ最終的になんでS+に行けたのかよくわからない

ガチホコを対物ZAPでやってたら何故か勝率が高く勝利が重なっただけなのかもしれない。 たまたまステージ・ブキ・ギアが自分にマッチしたのかもしれない。 この辺を分析すると、ガチホコ以外も勝率が上がるのかなあ。

うまくなりたい……。

mruby v1.3

mruby v1.3 がリリースされましたね。

趣味mrubyウォッチャーとしてv1.2からv1.3で何が変わったのかを、個人的にまとめてみたいと思います。

注目すべきは、やはりmatzのcommit数。

もちろんmerge commitも含みますが、約半数のcommitがmatzのcommitになっています。

なぜmatzがここまでmrubyに力を入れるのか聞いてみたいところですね。

それではmruby v1.2 からv1.3への変更で何が変わったのか、ザックリ見ていこうと思います。

リリースノート

http://mruby.org/releases/2017/07/04/mruby-1.3.0-released.html

1年以上あった割には、表向きにはそこまで変化はない感じ? わりと最新のCRubyの文法やメソッドも入っていたりしますね。

Contributions

https://github.com/mruby/mruby/graphs/contributors?from=2015-11-17&to=2017-07-04

v1.2が出た日からv1.3が出た日にしているので若干正確ではないのですが、やはりmatzのcommit数はダントツですね。

Many bug fixes

やはり注目すべきはShopifyからの大量のbug報告と、これら全てを丁寧に対応されたmatzの修正の応酬でしょう。

https://github.com/mruby/mruby/issues?q=is%3Aissue+author%3Aclayton-shopify

SEGVの報告。free後のメモリや、確保した領域外のメモリなど、触れてはいけないメモリを触れてしまっている部分の修正。GCのバグ修正。意図しない無限ループの修正。諸々含めて約200のissueが上げられ、閉じられています。

shopifyとmrubyの関係はbovi氏のblogが詳しい。

The 500.000$ release - mruby.sh

こちらからの目線での印象としては、正直「そんな重箱の隅まで……。」というケースもあったのですが、 ユーザーにコードを書いてもらって実行するようなシステムだと、「ユーザーにシステムを止められるようなコード書かれると困る」というのは分かる話。

おかげでmruby本体が原因でSEGVが起きるようなケースは、重箱の隅を含めてもそう滅多なことでは起こらないようになったんじゃないでしょうか。

mrb_yieldでbreakできない問題

折角なのでどういうbug fixがあったのかひとつ抜き出してみましょう。

この問題が修正されたのは1.3が出る直前のことでした。

v1.2では、実は以下のようなコードはうまく動きません。 breakしているのに、ループが終わらないのです。っていうかSEGVします。

$ mruby-1.2.0
"aaa\nbbb\nccc\n".lines do |line|
  p line
  break
end
#=> "aaa\n"
#=> "bbb\n"
#=> "ccc\n"
[2]    72458 segmentation fault  mruby-1.2.0

これは、Cで実装されたメソッドでmrb_yield系が使われていた場合にbreakを利用すると発生していました。

breakreturnとほぼ同じ扱いにしているので、rubyで書かれたブロックならbreakで以降のコードは飛ばせるのですが、 C側のコードは引き続き実行してしまうのでループを止められないという問題があったようです。

Rubyコード上はbreakしているのに、C側のコードは止められないので不整合が起こり、SEGVしているものと思われます。

この問題はbreakを例外扱いすることでlongjumpし、Cのレベルでもメソッドのコードを飛ばせるように修正されています。

Allow `break` from a block called by `mrb_yield`; close #3359 · mruby/mruby@d4d99dd · GitHub

パフォーマンス

「パフォーマンスは早くなったの?」

ということで、mrubyに添付されているbenchmarkスクリプトで計測してみました。

buildの設定はfull-coreにしただけでその他は初期値です。(OSX 10.12.5 clang v8.1.0)

$ time mruby-1.2.0 benchmark/bm_ao_render.rb > /dev/null
mruby-1.2.0 benchmark/bm_ao_render.rb > /dev/null  20.22s user 1.44s system 98% cpu 21.942 total

$ time mruby-1.3.0 benchmark/bm_ao_render.rb > /dev/null
mruby-1.3.0 benchmark/bm_ao_render.rb > /dev/null  19.74s user 0.11s system 98% cpu 20.134 total

$ time mruby-1.2.0 benchmark/bm_fib.rb > /dev/null
mruby-1.2.0 benchmark/bm_fib.rb > /dev/null  12.32s user 0.03s system 99% cpu 12.387 total

$ time mruby-1.3.0 benchmark/bm_fib.rb > /dev/null
mruby-1.3.0 benchmark/bm_fib.rb > /dev/null  13.33s user 0.05s system 98% cpu 13.529 total

$ time mruby-1.2.0 benchmark/bm_app_lc_fizzbuzz.rb > /dev/null
mruby-1.2.0 benchmark/bm_app_lc_fizzbuzz.rb > /dev/null  37.46s user 0.45s system 98% cpu 38.559 total

$ time mruby-1.3.0 benchmark/bm_app_lc_fizzbuzz.rb > /dev/null
mruby-1.3.0 benchmark/bm_app_lc_fizzbuzz.rb > /dev/null  41.14s user 0.37s system 99% cpu 41.850 total

$ time mruby-1.2.0 benchmark/bm_so_lists.rb > /dev/null
mruby-1.2.0 benchmark/bm_so_lists.rb > /dev/null  5.90s user 0.17s system 97% cpu 6.197 total

$ time mruby-1.3.0 benchmark/bm_so_lists.rb > /dev/null
mruby-1.3.0 benchmark/bm_so_lists.rb > /dev/null  48.57s user 0.53s system 99% cpu 49.492 total

うーん、そこまで劇的な変化はなさそうですね。

やはり、mruby v1.3の目玉は大量のbug fixということでしょうか。

bm_so_lists.rbはCRubyだと1sとかなのでこれは……見つけちゃったかもしれないですね……。

一応報告しておきましょう。

Performance regression for benchmark/bm_so_lists.rb · Issue #3737 · mruby/mruby · GitHub

[追記]なおしました。

Should only check frozen fix #3737 by ksss · Pull Request #3739 · mruby/mruby · GitHub

v1.4……?

keyword arguments

https://github.com/mruby/mruby/pull/3629

実はkeyword argumentsに対応するPRは既に来ています。

が、v1.3には取り込まれませんでした。

リリースノートにもRemaining Bugsとしてこっそり含まれているので、ゆくゆく対応されるのではないでしょうか。

※ここは個人のブログです

個人のブログなので、ここからは自分がやったことをまとめます。

Kernel#caller書いたのオレオレ

Cレベルではほぼ同じ機能があったので、これをRubyの世界でも使えるようにしただけ。

引数の扱いが意外とめんどくさかったりしました。

これでデバッグが楽になる場面が増えたはず……!

Proc#initialize消したのオレオレ

これまでは、Proc#initializeでProcオブジェクトの初期化を行っていたのですが、Proc.remove_method(:initialize)と凶悪なことをすると、Procオブジェクトに必要な値が準備されず、いろいろな部分でSEGVが発生するようになります。

これではCレベルのメソッドでProcオブジェクトを扱う際に、常にProc.remove_method(:initialize)されたことも考慮しないといけなくなってしまいます。

ところでCRubyを見てみると、なんとProc#initializeは定義されていないではありませんか。 つまりこういう問題は、CRubyではProc.remove_method(:initialize)にはProc#initializeを定義しないことによって対策していると判断。

mrubyでもProc#initializeを削除して、Proc.newメソッドを独自に定義するようにしました。*1

Proc.newで初期化するようにすれば、たとえProc.newが消されたとしてもProcオブジェクトが作れないのだけなので問題ありません。

Contributionsの二番目にいるのオレオレ

https://github.com/mruby/mruby/graphs/contributors?from=2015-11-17&to=2017-07-04

mruby-specを使って、mrubyとCRubyの挙動の不整合をひたすら直すということをしてました。 またその際にみつかったバグなども直したり、難しすぎて直せないものはissueで報告などの活動をしていました。

序盤の活動はブログに書いていましたね。

結構Rubyの細かい挙動を知れたりして勉強にもなりました。

shopifyのやつもちょこっとだけ手伝った

Make string embad from shared by ksss · Pull Request #3657 · mruby/mruby · GitHub

例えばこちらのエントリーでは、shopify issueの https://github.com/mruby/mruby/issues/3651 を解決しています。

前知識としてStringオブジェクトは、shared, no-free, embed, normalなどの状態が存在し、今どの状態かによって適切に処理を分岐しないと、最悪SEGVするケースがあります(大抵は破壊的な操作)。

sharedなStringを変更してsharedの関係をやめるときに、これまではnormalなStringとしていたのですが、 issueにあるような一部のコードでは文字列の長さでembedかどうか判断していました。

じゃあこれを適切に場合分けして……とも思ったのですが、normalなのに長さはembed可能な文字列が生成できてしまうせいで、問題が起こっていると判断。sharedなStringを変更するときに、長さが短い場合はembedなStringにしてしまえば、問題も治るしメモリ消費を若干抑えられるしで一石二鳥です。

bugを一つ埋め込んでしまった

MRB_DISABLE_STDIO: String#upto native's mrb_str_upto requires snprintf · Issue #3714 · mruby/mruby · GitHub

で報告されているとおり、mruby-string-ext gemをMRB_DISABLE_STDIOでbuildできなくしてしまいました。。。

MRB_DISABLE_STDIOはその名の通り標準入出力を行う関数を一切禁止するだいぶリソースが厳しい環境向けのオプション。

そんな厳しい環境では標準添付ライブラリなんて使わないよね……。う……これで困る人、許してくれ。。。

mruby v1.3

みんな使ってね!

*1:ちなみに実装は、渡されたブロックのコピーを作っているだけ。