読者です 読者をやめる 読者になる 読者になる

YAMAGUCHI::weblog

太めの女性の軍団が、本部をグルリと囲んでます。 現在恋人募集中! ポンコツミニチュア三等兵、中井です。

「逆引きGolang」で気になったところ

Go

はじめに

こんにちは、タゾチャイティーラテです。最近急に蒸し暑くなったり、寒かったり中途半端な天気が多いですね。逆引きGolang というサイトが公開されてて面白いなあと思って見てたんですが、僕だったらこう書くなというものがいくつかあったので覚書きです。

文字列

部分文字列を置き換える

これは無理に strings 使わないほうが楽なんじゃないかと思いますがどうでしょう。自分で関数定義するのは面倒かもしれませんが。

package main

import "fmt"

func main() {
    s := "Apple Banana Orange"
    r1 := replace(0, 5, []rune(s), []rune("Vine"))
    fmt.Println(string(r1))
    r2 := replace(5, 6, r1, []rune("Lemon"))
    fmt.Println(string(r2))
}

func replace(start, length int, orig, target []rune) []rune {
    ret := make([]rune, len(orig)+len(target)-length)
    copy(ret, orig[0:start])
    copy(ret[start:], target)
    copy(ret[start+len(target):], orig[start+length:])
    return ret
}

16進文字列を整数に変換する

コメントに "0xを含んではいけない" とありますが、含んでも大丈夫です。その場合はbaseを0にします。baseを0にした場合は文字列の見て0が先頭にあれば8進数、0xであれば16進数と判断します。

package main

import (
    "fmt"
    "strconv"
)

func main() {
    s := "0xff"
    sh, _ := strconv.ParseInt(s, 0, 64)
    fmt.Println(sh)
}

漢字コードを変換する

たぶん書きかけなんだろうけど、直接 EUCJP は呼べないので japanese.EUCJP.NewEncoder() としないと動かない。

日付と時刻

これは別に本文と関係ないけど、 time パッケージにはRFCとかで定義されてるフォーマットは定数で事前定義されてるっていうのをFYI。

const (
        ANSIC       = "Mon Jan _2 15:04:05 2006"
        UnixDate    = "Mon Jan _2 15:04:05 MST 2006"
        RubyDate    = "Mon Jan 02 15:04:05 -0700 2006"
        RFC822      = "02 Jan 06 15:04 MST"
        RFC822Z     = "02 Jan 06 15:04 -0700" // RFC822 with numeric zone
        RFC850      = "Monday, 02-Jan-06 15:04:05 MST"
        RFC1123     = "Mon, 02 Jan 2006 15:04:05 MST"
        RFC1123Z    = "Mon, 02 Jan 2006 15:04:05 -0700" // RFC1123 with numeric zone
        RFC3339     = "2006-01-02T15:04:05Z07:00"
        RFC3339Nano = "2006-01-02T15:04:05.999999999Z07:00"
        Kitchen     = "3:04PM"
        // Handy time stamps.
        Stamp      = "Jan _2 15:04:05"
        StampMilli = "Jan _2 15:04:05.000"
        StampMicro = "Jan _2 15:04:05.000000"
        StampNano  = "Jan _2 15:04:05.000000000"
)

配列

配列に要素を追加する

append 使えばいいんですが、あんまり回数が多いと効率が悪いので、長さがわかってるならばバッファを確保したほうがよいと思う。

一致する要素を全て取り除く

まず全然関係ないけど、全体的にアンダースコア区切りの関数名がよく見られるけど、Goの慣習的には変数名も関数名もキャメルケースです。詳しくは ここ 参照。あと複数パッケージimportするときは括弧で囲ったほうが読みやすいかなあ。

deleteStrings()はまっすぐ書いたほうがスッキリ書けそう。

package main

import "fmt"

func main() {
    a := []string{"apple", "orange", "lemon", "apple", "vine"}

    str, a, err := deleteStrings(a, "apple")
    fmt.Println(str) // => "apple"
    fmt.Println(a)   // => "[orange lemon vine]"
    fmt.Println(err) // => "<nil>"

    str, a, err = deleteStrings(a, "apple")
    fmt.Println(str) // => ""
    fmt.Println(a)   // => "[orange lemon vine]"
    fmt.Println(err) // => "Couldn't find"
}

func deleteStrings(slice []string, s string) (string, []string, error) {
    ret := make([]string, len(slice))
    i := 0
    for _, x := range slice {
        if s != x {
            ret[i] = x
            i++
        }
    }
    if len(ret[:i]) == len(slice) {
        return "", slice, fmt.Errorf("Couldn't find")
    }
    return s, ret[:i], nil
}

おわりに

公式ドキュメントでは文法などはわかりやすく書いてあって、あのサイトだけひと通り読んでれば普通に書けるようになるのですが、やはり逆引き的にスニペットがあると便利ですね。これからも更新頑張ってください。

Ubuntu 15.04のサーバをWake on LANできるようにした

はじめに

最近、とある用途のために眠ってたマシンを引っ張り出してきた。こいつがまたいい働きをしてるんだけど、いくらファンが静か目とはいえうるさい。ということでWoLの設定をして、いい感じに必要なときだけ起動できる下地を作っておこうと思った。

BIOSの設定

まずBIOSの設定だけど当然使ってるマザーボードによって設定は違う。俺のおんぼろマザボ785GM-P45) の設定だと Power Management Setup → Wake Up Event Setup → Resume By PCI-E Device で Enable の設定をするだけ。

OSの設定

Ubuntu 15.04の方での設定は ethtool で実施。apt-getしようと思ったらすでに入ってた。

% sudo ethtool -s p5p1 wol g
% sudo ethtool p5p1
Settings for p5p1:
    Supported ports: [ TP ]
    Supported link modes:   10baseT/Half 10baseT/Full
                            100baseT/Half 100baseT/Full
                            1000baseT/Full
    Supported pause frame use: No
    Supports auto-negotiation: Yes
    Advertised link modes:  Not reported
    Advertised pause frame use: No
    Advertised auto-negotiation: Yes
    Speed: 1000Mb/s
    Duplex: Full
    Port: Twisted Pair
    PHYAD: 0
    Transceiver: internal
    Auto-negotiation: on
    MDI-X: Unknown
    Supports Wake-on: pg
    Wake-on: g
    Current message level: 0x0000003f (63)
                   drv probe link timer ifdown ifup

Wake-onが g になってるのを確認。このままだと再起動したら設定消えちゃうので、initスクリプトを新規作成。

% sudo vim /etc/init.d/wakeonlanconfig
#!/bin/bash
### BEGIN INIT INFO
# Provides:          wakeonlanconfig
# Required-Start:    $local_fs
# Required-Stop:     $local_fs
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: wakeonlanconfig
### END INIT INFO
ethtool -s p5p1 wol g
exit
% sudo chmod +x /etc/init.d/wakeonlanconfig

これで再起動して起動後にちゃんとWake on LANが有効になってるか確認。

% sudo reboot
% sudo ethtool p5p1
Settings for p5p1:
...
    Wake-on: g
...

テストのために終了する。

% sudo shutdown -h now

MacWake on LANのクライアントの設定

MacPortsを使ってるんで探してみると便利なパッケージがあった。

% port info wol
wol @0.7.1 (net)
Variants:             universal

Description:          wol can send a Wake-On-Lan magic packet to a target ethernet address
Homepage:             http://wake-on-lan.sourceforge.net

Build Dependencies:   autoconf, automake, libtool
Platforms:            darwin, freebsd
License:              GPL-2+
Maintainers:          jeremyhu@macports.org, openmaintainer@macports.org

これをインストールして、試してみる。

% sudo port install wol
% wol <UbuntuマシンのMACアドレス>
Waking up XX:XX:XX:XX:XX:XX....

Ubuntuのマシンが起動した。便利。

Raspberry PiのWake on LANのクライアントの設定

Raspbianを使ってるんでaptで探してみると発見。

$ apt-cache show wakeonlan
Package: wakeonlan
Version: 0.41-11
Installed-Size: 56
Maintainer: Thijs Kinkhorst <thijs@debian.org>
Architecture: all
Depends: perl, perl-modules
Size: 11510
SHA256: d93c21fe7023fd98ec9461047a67f1099addae6a46278e2fb0aea97d55d73f60
SHA1: 988ce3c2f1c6d04f715da153b8a7bfc74dac895a
MD5sum: 6d4c609468083aeedc329a2df9b77079
Description: Sends 'magic packets' to wake-on-LAN enabled ethernet adapters
Homepage: http://gsd.di.uminho.pt/jpo/software/wakeonlan/
Description-md5: 1f4cb6ce85d821307a46719513c54d04
Tag: admin::boot, implemented-in::perl, interface::commandline,
 network::configuration, protocol::ethernet, protocol::udp,
 role::program, scope::utility, use::transmission
Section: net
Priority: optional
Filename: pool/main/w/wakeonlan/wakeonlan_0.41-11_all.deb

これをインストールして試してみる。

% sudo apt-get install wakeonlan
% wakeonlan <UbuntuマシンのMACアドレス>
Sending magic packet to 255.255.255.255:9 with XX:XX:XX:XX:XX:XX

起動した。

結論

便利なのでWoLをもっと気軽に使えるシステムを作りたい。

Goで再帰使うと遅くなりますがそれが何だ

Go

はじめに

こんにちは、Go界のうまい棒です。昼間にTwitter眺めてたら次のような記事を見かけました。

結果はあくまでフィボナッチ数列をナイーブに実装した場合なんで、まあ明らかに遅くなるよなあと予想通りの実行結果でした。

件のプログラム

ナイーブにフィボナッチ数列を実装してますね。

package main

import "fmt"

func fib(n int) int {
    if n < 2 {
        return n
    }
    return fib(n-2) + fib(n-1)
}

func main() {
    fmt.Println(fib(42))
}

これを実際にビルドして実行するとどれくらいかかるかというと、だいたい手元で2.5秒以上かかってますね。

% time go run fib1.go
267914296
go run fib1.go  2.55s user 0.06s system 94% cpu 2.763 total

なんで遅いのか

先のコードは最後が末尾再帰でない再帰呼び出しなので、コールスタックがめっちゃ積まれそうです。Goが再帰呼び出しが得意でないのは、Goランタイムのスタックサイズがデフォルトが小さく、かつスタックサイズの大きさを最小にするような最適化を行わないからです。さらにいうと、Goでは末尾再帰ですら最適化されません。

困ったらgo toolを使ってアセンブリを見てみると良いです。

$ go tool 6g -S fib.go > fib.asm

再帰の場合、途中のいろいろは抜かして関係しそうなところだけ抜粋。

"".fib t=1 size=128 value=0 args=0x10 locals=0x18
        0x0000 00000 (fib1.go:5)        TEXT    "".fib+0(SB),$24-16
        ...
        0x000f 00015 (fib1.go:5)        CALL    ,runtime.morestack_noctxt(SB)
        ...
        0x001f 00031 (fib1.go:6)        CMPQ    AX,$2
        ...
        0x002e 00046 (fib1.go:7)        RET     ,
        ...
        0x003a 00058 (fib1.go:9)        CALL    ,"".fib(SB)
        ...
        0x0055 00085 (fib1.go:9)        CALL    ,"".fib(SB)
        ...
        0x0070 00112 (fib1.go:9)        RET     ,

今回のコードは普通の再帰ですが、見ての通りfibがどんどん呼ばれてコールスタックが深くなっていきます。これは末尾再帰のコード書いても同様のアセンブリになります。階乗の計算をするコードを書いてみます。

package main

import "fmt"

func fact(n, p int) int {
        p = p * n
        if n == 1 {
                return p
        }
        return fact(n-1, p)
}

func main() {
        fmt.Println(fact(10, 1))
}

このアセンブリを見てみます。

"".fact t=1 size=96 value=0 args=0x18 locals=0x18
        0x0000 00000 (tailrec.go:5)     TEXT    "".fact+0(SB),$24-24
        ...
        0x000f 00015 (tailrec.go:5)     CALL    ,runtime.morestack_noctxt(SB)
        ...
        0x0024 00036 (tailrec.go:6)     IMULQ   AX,CX
        0x0028 00040 (tailrec.go:7)     CMPQ    AX,$1
        ...
        0x0037 00055 (tailrec.go:8)     RET     ,
        ...
        0x004c 00076 (tailrec.go:10)    CALL    ,"".fact(SB)
        ... 
        0x005f 00095 (tailrec.go:10)    RET     ,

fibと同様のアセンブリコードになってますね。

Goという言語

@mayahjp さんとも話してましたが、そもそも「Goが速い」というのが間違いで、たとえば「Goはビルドは遅くない」「普通にやってもまあ遅くないしLLよりは速く書けがち」「並行プログラミングが楽にできる」というところがいいのであって、システムプログラミングなどには向いてますが、数値計算などには向いてませんし、そういったものをするために開発された言語ではありません。(ただ先のエントリのベンチマークを見ても最適化を掛けないCよりは実行速度速くなってますよ。)

今回のフィボナッチ数列でのベンチマークはやってる処理自体はごくごく小さな演算で、パフォーマンスに寄与するのは

  1. 関数呼び出し自体のパフォーマンス
  2. コールスタックの最適化

です。そういった意味でGoは

  1. 関数呼び出し自体はgoroutineの管理などもあり、そもそもがgoroutineを大量に呼べるようにスタックサイズがデフォルトで小さく設定されていて、かつ自動で管理するようにランタイムで調整が入る。
  2. Goではスタックトレースで表示されることが大事なので、敢えて最適化していない*1 (2015.02.23 訂正。鵜飼さんご指摘ありがとうございます。)

という状況なので仕方ないかなと思います。

アルゴリズムでの最適化

もし今回のプログラムをアルゴリズムで最適化するのであればメモ化をするのが手っ取り早いでしょう。O(n)になります。

package main

import "fmt"

var mem = make(map[int]int, 100)

func fib(n int) int {
        if n < 2 {
                return n
        }
        if m, ok := mem[n]; ok {
                return m
        }
        m := fib(n-2) + fib(n-1)
        mem[n] = m
        return m
}

func main() {
        fmt.Println(fib(42))
}

これを実行すると0.12秒になりました。

% time go run fib4.go
267914296
go run fib4.go  0.12s user 0.04s system 89% cpu 0.178 total

ちなみにPythonで適当に書いても速いです。

def fib(n, mem):
    if n < 2:
        return n
    if n in mem:
        return mem[n]
    m = fib(n-2, mem) + fib(n-1, mem)
    mem[n] = m
    return m

if __name__ == "__main__":
    print(fib(42,{}))

実行すると0.01秒ですよ。十分速い。

% time python fib.py
267914296
python fib.py  0.01s user 0.01s system 92% cpu 0.024 total

おわりに

先のエントリの最後にもちょろっと書いてますが、マイクロベンチマークはそのベンチマークに特化した結果しか出ないので、あくまでマイクロベンチマークはマイクロベンチマークです。何が言いたいかというと、Nim使いたくなるようにその言語が得意とする領域のもっと良いサンプルで比較してほしいな、ということでした。おわり。

参考

YAMAGUCHI::weblogの2014年を振り返る

はじめに

こんにちは、Go界のアラン・アーキンです。今日、また1歳年齢を重ねてしまいました。例のやつ貼っときます。

関連エントリ

1年の振り返りも8年目になりました。

ブログに関して

とにかくエントリの数が減ったなあという印象。書けないことが多いというより、社内でいろんな人と話をしているうちに満足してしまうということが多いのが原因だと思います。

Qiitaなどに書く記事などもあるけれど、もうちょっと自分の整理のために、初心に帰って、アウトプットの量を増やしていこう。

ymotongpooの2014年

昨年立てた目標

まず昨年末に立てた2014年の目標を振り返ります。

  • YouTube(のAPI)の人として認知してもらえるようになる
  • Go言語の更なる普及
  • 翻訳本出すぞ
  • カメラの機能をひと通り使いこなす

YouTube(のAPI)の人として認知してもらえるようになる

昨年10月にDeveloper Relationsチームに異動して、YouTube APIのDeveloper Advocateになりましたが、その後今年3月に組織再編があり全サービス・製品の担当となりました。 そのため、YouTube APIのみに割く時間というのはだいぶ減りましたが、それでもずっと継続してYouTube APIのサポートなどは続けているため、社内外からの問い合わせなどもずいぶんと多くいただいた一年でした。

特に今年一番大きかったのはYouTube APIWii U SDKへのインテグレーションです。任天堂社のご協力により、Wii Uでのゲームプレイ動画をパソコンを介することなく、直接YouTubeへとアップロードできるようになりました。

YouTube APIでは動画のアップロードの際、手元に動画ファイルが用意されていることが前提となります。ここで動画アップロード機能をゲーム本体あるいはゲーム用SDKに組み込むとなると、ゲームプレイ動画を「作成」する必要があります。 したがってYouTube APIWii U SDKに組み込むには次のような課題がありました。

  1. 通常は画面にレンダリングされるだけのゲームプレイ映像をキャプチャし、動画ファイルの形にエンコードする
  2. エンコード時間を短くしつつ、アップロードを行う
  3. ネットワークがトラブルにより切断された場合レジュームアップロードを行う

1と2に関してはYouTube APIおよびそのクライアントライブラリで提供しているものではなく、独自実装を行っていただく必要がありました。 しかしそこは任天堂社。白川さんを始めとする社の技術者の方々の技術力により見事に実現され、YouTube APIを用いたゲームプレイ動画アップロード機構のすばらしい参照実装となりました。

3に関してはブログエントリにあるとおり、YouTube APIで提供しているレジュームアップロード機能を利用しています。 Wii Uですので、携帯と違い、安定した帯域を持つ有線ネットワーク環境からアップロードされることを想定していますが、スムーズなレジュームアップロード機能により、よりユーザビリティが向上したと思います。

YouTube APIにはアップロード以外の機能がたくさんあり、Wii U SDKではそれらも多くの場所で利用されています。

また、カヤック社のLobi REC SDKでもYouTube連携の機能が加わり、モバイルゲームのゲームプレイ動画を簡単にYouTubeへとアップロードができるようになっています。これまで国外でもちらほらと聞いていた事例も日本国内で見られるようになったことは自分としても嬉しいものです。

今年はそういった意味ではYouTube APIは少なからずの広がりを見せていると思いますし、来年はゲームプレイ動画を活かした収益的な成功事例を少しでもお手伝いできればなと思っています。

Go言語のさらなる普及

上のトレンドは2013年1月からの"golang"というキーワードの検索ボリュームですが、順調に右肩上がりにボリュームが増えていることが見て取れます。

今年も昨年と同様に2回のGo Conferenceの運営に関わりました。 またカンファレンスだけでなく、その運営者周辺でカート大会をするという、ファンイベントにも参加して、非常に充実した1年でした。

とくに先月末に開催されたGo Conference 2014 autumnはこの会のターニングポイントになったと感じています。まずGoの生みの親であるRob Pikeがキーノートをしてくれたこと、そして僕が運営の表に立たなくなったことです。

前者に関しては、(Goに限らない)レジェンドが自らの言葉で、その設計思想を語ったことに大きな意味があると思っていて、キーノートや口頭でのQ&Aではフォーラムやメーリングリストで文字で読むよりも説得力がありました。 また後者に関しては、Go Conferenceがこれからも継続可能な形として存続できるように僕は今回を機に支援役に回ることにしました。結果@tenntennさんや@Jxck_さん、会場を提供してくれた@deeeetさん、Tシャツを用意してくださった@nuki_ponさん、そして当日運営を快く引き受けてくださった運営の方々みなさんのおかげで過去最大規模のイベントとなりました。

またGoConにかぎらず多くのGo関連イベントも開催されました。Go関連の日本語情報はGoogle+のコミュニティで数多く共有されているので、ぜひ参加&書き込んでください!

翻訳本出すぞ

出版することが出来ました。

すごいErlangゆかいに学ぼう!

すごいErlangゆかいに学ぼう!

英文翻訳をするという行為は自分の英語力と翻訳対象に対する理解を求められる、高度な技能だと思います。 この翻訳を通じて、自分の技術力を思い知らされると同時に、多くの方々のレビューを通じて非常に勉強させていただきました。

出版に至るまでの苦労などは、上にリンクされているエントリに任せるとして、今後も淡々と英語や技術系の勉強を行いつつ、より良い品質の翻訳ができるように努めていきます。

カメラの機能をひと通り使いこなす

昨年末にNikon D610を購入して以来、旅行やイベントのたびに一眼レフカメラを持ち歩いて、カメラの練習を続けています。その中で多くの機能を知り、状況に合わせた利用というものもできるようになってきました。ところが、今度は現像やクロップの技術がまだまだ未熟すぎて、もどかしい思いをすることも増えました。来年は現像も色々と試して、より深みのある写真を撮れるようにしたいなあ。

非常に奥が深い趣味なので、これからもこのカメラを使い続けて、いい写真撮るぞ。

来年に向けて

今年は変化が多い年だったけれど、来年は腰を据えて何かに取り組みたいと思う。

  • Go関連情報の継続的なアウトプット
    • なかなか出てない情報があるなあと思うのでその辺の情報を共有していきたい
  • Android開発の技術力の向上
    • 課長に質問する回数は減らしていきたい
  • 「通知」に関する研究
    • 最近は「通知」に興味があるので、いろいろな方に意見を聞いてまとめたい。
  • 英語力の向上
    • 最近英語記事読んでてわからない単語や表現が増えた気がする。良くない。
  • 仏教について学ぶ
    • 仏教おもしろい
  • 経済について学ぶ
    • 経済おもしろい
  • RAWデータの現像技術の向上

これまでのIngressとDarsanaの思い出 #ingress

このエントリはIngress Advent Calendar 2014の23日目の記事です。

f:id:ymotongpoo:20141213103215j:plain

はじめに

こんにちは、RES A15です。Ingressを本格的に初めてから1年ちょっとが過ぎました。あとちょいでA16なので頑張っています。*1

f:id:ymotongpoo:20141223111117p:plain

先日のDarsana Tokyoに参加してきました。過去最大規模のアノマリーに参加するというだけでもテンションが上がりますが、それ以上に今回クラスターが指定された場所が、どこもまだポータルがすくないころに自分がレベル上げをしたエリアばかりだったので、とても思い出深いものになりました。そこで、普段文字にすることのないIngress自体のこれまでの思い出とDarsanaの感想を、少し長いですがここに残そうと思います。

自分がIngressを始めた頃

自分がスキャナを毎日起動するようになったころは、まだ自分の活動エリアはポータルが少なく、ポータル間も常に100m以上はあったきがします。ポータルが密集しているエリアを探しては、自転車や電車で数十分かけてファーミングをしにいったり、CFを敷き詰めてレベリングをしたりしていました。

自分がいちばん活動していたエリアはちょうど僕と同じくらいのレベルの緑の方が頑張っていて、密かにどちらが先にA8になるか競い合っていました。当時は取り返す先から壊されていたので「この野郎!」と思ったりもしていましたが、あの方のおかげでだいぶレベル上げのモチベーションも高く維持出来ていたと思います。おかげで年末の2週間ちょっとでLv3からLv8まで一気にレベルを上げることができました。*2

コミュニティへの参加と戦略的活動

「Lv8になるまではコミュニティに参加しない」と決めていたので、Lv8になってすぐにIngress Resistance TokyoのGoogle+コミュニティに参加しました。これまで活動しているなかでポータルオーナーやレゾネータ、あるいはCOMMで名前を見かけていた方々とのやりとりをしながら、ソロプレイとは違った戦略的な活動に新たな楽しみを覚えはじめたのもこの時期です。

それから半年程はポータルの数もエージェントの数との比率がちょうどよく、青も緑もガチガチのファームをお互いに攻めつ守りつしながら、新エージェントの加入により形成を逆転させたりといったドラマが毎日のように繰り広げられていました。いまの混戦模様はそれはそれで面白いのですが、Ingressのゲーム本来の目的であるMUの競い合いという意味では、この頃のゲームバランスが自分にとってはちょうどよかったのではと思っています。

Guardian 150日への道のり

話が前後しますが、僕がLv8になった頃はまだレベルキャップが開放されておらず、Lv8が最高レベルでした。そのため、Lv8になってしばらくして、すべてのメダルをUnlockすること、そして大きな目標としてGuardian 150日の達成を心に誓いました。ここからアラート通知に苛まされる日々が始まったのです。

ユーザ数が爆発的に増えたいまではGuardianメダルはGold(20日)ですら難しくなってしまいましたが、当時でもOnyx(150日)は相当厳しいものでした。当時はIntel Mapにポータルをキャプチャした日付が記載されていたので、エージェント活動を終えて家に帰ってから、ガーディアンが取れそうなポータルをスプレッドシートに記録・管理していました。

f:id:ymotongpoo:20141223120023p:plain

攻撃アラートが来たらポータル名を横目で確認し、Guardian候補への攻撃が来れば可能な限りリチャージ応戦をしていました。自分が行ける距離であれば壊されたレゾネータやmodを補強しに行ったりと、一番Ingressに時間をかけていた時期もこのころでした。夜の1時にアラートが鳴り、嫌な予感がして見てみるとGuardianポータルへの攻撃で、なんとかリチャージ応戦で勝った、ということもありました。

Platinum(90日)を達成してからなかなか150日まで生かすことができない日々が続き、心が折れそうになったこともありましたが、夏頃にようやく達成ができ、一区切りが付きました。通知の設定をオフにした時の安堵感はいまでも忘れられません。150日の間に2回もあった2週間の海外出張の間も、僕の代わりにリチャージをしてくれていた友人に感謝です。

レベルキャップ開放とLv10+の壁

Guardian 150日という目標にまい進しているなか、ゴールデンウィーク明けにレベルキャップがLv16まで開放され、同時にLv9以降のレベルアップにはメダルの色と数が条件として付与されるようになりました。

幸いあらゆるアクションを均等に行うことを心がけていた結果、レベルキャップ開放の日に一気にLv8からLv10まで上がっていましたが、ここからのレベル上げはみなさんもご承知の通りで、たんたんと日々のエージェント活動を行い地道に稼ぎ、なんとかLv15までやって来ました。*3

以前、@takano32が「Ingress道に則って活動していれば、自ずとレベル達成のためのメダルが取得できる」と言っていたけれど、まさにそのとおりだと思うので、レベル上げを目指している方はできるアクションはできるだけ行ったほうがよいでしょう。

iOS版リリース、ポータルLive祭り、AP2倍・アイテム3倍祭り、混戦

Guardian 150日を達成した10日後にiOS版がリリースされ、一気にユーザが増えました。「ユーザ数の増加でこれほどゲームバランスが変わるのか」と面白く観察していた時期です。地元にも新たな味方が増え、コミュニティ参加者の数も一気に増えていました。

この頃、iOSから始めたエージェントの底上げや、エージェント数に対してのポータル数の割合を増やすことを意図したのかわかりませんが、ポータルLive祭り、AP2倍・アイテム3倍祭りなどが起き、いままで割と平和だった地域も、あっという間に激戦区に様変わりしたり、設定一つでこれほどまでに様相が変わるものかと、驚きました。と、同時にiOS版から始めた人がどんどんレベルを上げているのに触発され、自分もやるぞと奮起してかなり活動量を戻しました。

Darsana Tokyo

東京がAnomalyのPrimary Siteになるという連絡を受けたのがちょうどポータルLive祭りの前でした。「東京」と指定している以上、都内のどこがクラスターに指定されるのか、コミュニティ内で盛り上がっていたなか、ついに発表されたエリアがなんと自分がいちばん慣れ親しんだエリア。「ここで5000人がAnomalyやるのか...」と期待が高ぶるとともに、地域の方々に御迷惑がかからないかどうか、心配でなりませんでした。*4とはいえ、同じエリアで活動しているRES陣営の方々と一緒にチーム分けを考えたり、当日までの動きを考えたりするのは、遠足の準備をするようですごく楽しかったですね。

当日は受付でRESの方々の手首にスタンプを押しまくる係をしてました。普段FFなどでお会いする方々と改めてイベントで会うと、部活の試合前にチームメイトに会うような、懐かしい高揚感を覚えました。その後、計測に向けて担当のクラスターに同じグループの人たちと移動して、慣れ親しんだ場所でAnomalyが開始。普段見慣れたエリアも、これほどまでにエージェントにあふれると違って見えます。

途中、「Dead Dropがあのポータルに!」という情報がくると、「ああ、あのポータルにあるのかぁ。隠すとしたらあのへんかなあ。」と思いを馳せたり、「あのポータルがVolatileだ!」という連絡を受ければ「あのポータルで初めてリアルタイムのポータルの取り合いをしたなあ」とか、自分の思い入れがあるポータルが特別な扱いを受けていることに、妙に嬉しくなり、計測の時にも妙に力を入れていたのを覚えています。

特に自分の申請したポータルがVolatileになったという報告を受けた時は、自分が申請したポータルが勝敗に少なからずの影響を与えるということで、達成感すら覚えていました。

結果はRESは勝てませんでしたが、あの一日は普段同じエリアで活動している人と目の前のポータルを取るために一緒に頑張り、また計測の間は顔を合わせて普段できない会話を楽しむことができた、そういった意味でDarsanaは貴重なイベントでした。

これから

前々から「年内にまたレベルキャップを上げる」という噂が出ています。Lv24を目指すかはわかりませんが、新しいメダルも増えて、またIngressの新しい楽しみ方ができるようになってきました。これからも、外にでて、青いエリアを拡大するための活動に勤しみたいと思います。外でお会いした時には、ぜひ声をかけてください。

次は @usaturn さんです。

*1:もっとも新規メダルで勝手にレベルが上ってしまったので、自力であと2つプラチナ取らないと気分的に先達に恥ずかしい。

*2:今年の1月5日にLv8になった。

*3:新メダルが立て続けに付与されたおかげで次のレベルまでAPが800万足りない。

*4:事実ご迷惑をお掛けしてしまったようで、この辺はNianticは真剣に反省すべきだと思います。