PHP Conference Japan 2019 に参加したので自分用メモを公開する #phpcon

はじめに

今回、12/1にPHP Conference Japan 2019 beyond.* に参加したので自分用にまとめます。 phpcon.php.gr.jp

実は、弊会社が協賛していて企業ブースに出展していて、自分も含めて3名ものLT登壇があり、普段の感覚とは大きく違いました。

発表者の話とTwitterをリアルタイムで見ていて今回はあまり有意義なメモが取れなかったのですが、共感した部分があったらTwitterで誰かが同じ思いを発言していることも多くTwitterっていいなと感じたことが多かった日でした。

続きを読む

Slack bot で bot 自身の発言は無視したい

Slack botへのメンションをトリガーとした何かしらを作るにあたって、とりあえずの練習として「botへのメンションがあったらその内容をオウム返しする」ものを作りました。
そのとき、無限ループに陥ってしまったので、それを回避する方法です。
Slack bot自体の作成の方法については述べません。

Slack bot自体の扱いはいくつかの他のブログを参考にさせていただきました。 teppay.hatenablog.com

これまで通り、SlackとGASの組み合わせです。
これまで ↓ ohshige.hatenablog.com

ささっと、オウム返しを行うGASを書いて公開しました。

function doPost(e) {
  var params = JSON.parse(e.postData.getDataAsString());

  // URL検証用
  if (params.type === 'url_verification') {
    var response = {'challenge': params.challenge};
    return ContentService.createTextOutput(JSON.stringify(response)).setMimeType(ContentService.MimeType.JSON);
  }

  // Webhookを使ってparamsをそのままオウム返しする処理
}

この状態で、 @bot名 こんにちは などとメンションを送ると、Slack Eventの様々な情報を含んだままポストされました。

{
  "token":"XXXXXXXXXX",
  "team_id":"XXXXXXXXXX",
  "api_app_id":"XXXXXXXXXX",
  "event":{
    "client_msg_id":"xxxxxxxxxxxxxxxxxxxxxxx",
    "type":"app_mention",
    "text":"@bot名 こんにちは",
    "user":"UXXXXXXXXXX",
    "ts":"0000000000000000",
    "team":"TXXXXXXXXXX",
    "channel":"CXXXXXXXXXX",
    "event_ts":"0000000000000000"
  },
  "type":"event_callback",
  "event_id":"EvXXXXXXXXXX",
  "event_time":0000000000000000,
  "authed_users":["UXXXXXXXXXX"]
}

これで成功したかに思えたのですが、直後またポストがあり、その直後にもポストがあり、...と無限ループに陥ってしまいました。
急遽連携を解除したことで止まりましたが、かなり焦りました。

2つ目のポストはこんな内容でした。

{
  "token":"XXXXXXXXXX",
  "team_id":"TXXXXXXXXXX",
  "api_app_id":"XXXXXXXXXX",
  "event":{
    "type":"app_mention",
    "subtype":"bot_message",
    "text":"{\"token\":\"XXXXXXXXXX\",\"team_id\":\"TXXXXXXXXXX\",\"api_app_id\":\"XXXXXXXXXX\",\"event\":{\"client_msg_id\":\"xxxxxxxxxxxxxxxxxxxxxxx\",\"type\":\"app_mention\",\"text\":\"@bot名 こんにちは\",\"user\":\"UXXXXXXXXXX\",\"ts\":\"0000000000000000\",\"team\":\"TXXXXXXXXXX\",\"channel\":\"CXXXXXXXXXX\",\"event_ts\":\"0000000000000000\"},\"type\":\"event_callback\",\"event_id\":\"EvXXXXXXXXXX\",\"event_time\":0000000000000000,\"authed_users\":[\"UXXXXXXXXXX\"]}",
    "ts":"0000000000000000",
    "bot_id":"BXXXXXXXXXX",
    "channel":"CXXXXXXXXXX",
    "event_ts":"0000000000000000"
  },
  "type":"event_callback",
  "event_id":"EvXXXXXXXXXX",
  "event_time":0000000000000000,
  "authed_users":["UXXXXXXXXXX"]
}

これでわかるように、botによってポストされた内容にも @bot名 こんにちは が含まれています。
オウム返しなのだから当然だろうという話ですが、実行するまで気づけなかったです。

というわけでbotによるポストは無視して、ユーザによるポストだけに反応させれば良さそうなので、そのポストがbotかどうかの判定を入れます。
その方法としては、eventのsubtypeがbot_messageかどうかを判定すれば良さそうです。

api.slack.com

function doPost(e) {
  var params = JSON.parse(e.postData.getDataAsString());

  // URL検証用
  if (params.type === 'url_verification') {
    var response = {'challenge': params.challenge};
    return ContentService.createTextOutput(JSON.stringify(response)).setMimeType(ContentService.MimeType.JSON);
  }

  // botによるポストの場合は何もしない
  if (params.event.subtype === 'bot_message') {
    return;
  }

  // Webhookを使ってparamsをそのままオウム返しする処理
}

bot_idもわかるので、自分自身だけは無視して他のbotとの会話は可能にしたい場合などはbot_idで判定すれば良さそうです。

無限ループって怖いですね。

Terraformでaws_security_groupとaws_security_group_ruleの両方でルールを設定すると競合する

前回はセキュリティグループIDをソースに指定してセキュリティグループを作成する方法について書きましたが、今回はその流れでルールを書いていたらハマった話です。

ohshige.hatenablog.com

セキュリティグループIDをソースに指定してセキュリティグループを作成するユースケースとして、AWSで踏み台サーバを用意してアプリケーションサーバにはその踏み台サーバ経由でしかsshできないようにする場合を想定していました。
例えば、そのうえで「アプリケーションサーバには特定のIPからの80番ポートでのHTTPを許可する」というルールを追加するということも考えられます。

CIDRブロックでのingressルールはaws_security_groupにそのまま記述できるので、例えば以下のように書けます。

provider "aws" {
  region = "ap-northeast-1"
}

resource "aws_security_group" "bastion" {
  (略)
}

resource "aws_security_group" "application" {
  name        = "application"
  description = "Security Group for application"

  // ここを新しく追加
  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}
resource "aws_security_group_rule" "application_from_bastion" {
  type                     = "ingress"
  to_port                  = 22
  protocol                 = "tcp"
  source_security_group_id = aws_security_group.bastion.id
  from_port                = 22
  security_group_id        = aws_security_group.application.id
}

これは問題なく実行でき、意図通りの設定になります。

問題はこれからで、上記のtfファイルを特に設定を書き換えることなく、 terraform plan を実行すると、変更があると言われてしまいます。

Terraform will perform the following actions:

  # aws_security_group.application will be updated in-place
  ~ resource "aws_security_group" "application" {
      (略)
    }

Plan: 0 to add, 1 to change, 0 to destroy.

そんなまさかと思いつつ、 terraform apply を実行すると、確かに変更が適用され、コンソールで確認するとaws_security_group_ruleで指定したSSHのルールが削除されています。

さらに、この状態で再度 terraform plan terraform apply を実行すると、もとに戻り、無限ループ(ずっと terraform plan で差分が出る)になります。

これを回避するためには、全てのルールをaws_security_group内かaws_security_group_ruleかどちらかに統一すれば良いです。
今回はセキュリティグループIDをソースに指定する指定方法をそのまま生かしたいので、aws_security_group_ruleに統一します。
ingressのルールを統一すれば良いので、egressはそのままでも良いです。

provider "aws" {
  region = "ap-northeast-1"
}

resource "aws_security_group" "bastion" {
  (略)
}

resource "aws_security_group" "application" {
  name        = "application"
  description = "Security Group for application"

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}
resource "aws_security_group_rule" "application_from_bastion" {
  type                     = "ingress"
  to_port                  = 22
  protocol                 = "tcp"
  source_security_group_id = aws_security_group.bastion.id
  from_port                = 22
  security_group_id        = aws_security_group.application.id
}
// aws_security_group_ruleとして新しく追加
resource "aws_security_group_rule" "application_from_http" {
  type              = "ingress"
  to_port           = 80
  protocol          = "tcp"
  cidr_blocks       = ["0.0.0.0/0"]
  from_port         = 80
  security_group_id = aws_security_group.application.id
}

これで何回 terraform plan を実行しても謎の差分が出ることはなくなります。

一件落着です。

--

という話は公式にしっかりと書かれていました。

www.terraform.io

NOTE on Security Groups and Security Group Rules: Terraform currently provides both a standalone Security Group Rule resource (a single ingress or egress rule), and a Security Group resource with ingress and egress rules defined in-line. At this time you cannot use a Security Group with in-line rules in conjunction with any Security Group Rule resources. Doing so will cause a conflict of rule settings and will overwrite rules.

aws_security_group_ruleを使う場合とaws_security_group内のingress/egressで定義する方法がありますが、同時に使うと競合するよ」みたいな感じでしょうか。

競合するので、どちらかに統一して書きましょうというお話でした。

TerraformでセキュリティグループIDをソースに指定したセキュリティグループを作成する

セキュリティグループを作成するときに、インバウンドのソースとして別のセキュリティグループIDを指定する方法はとても便利です。

よく使うのは、AWSで踏み台サーバを用意してアプリケーションサーバにはその踏み台サーバ経由でしかsshできないようにする場合です。
踏み台サーバには特定の(社内などの)IPからしsshできないようなセキュリティグループを設定し、アプリケーションサーバにはそのセキュリティグループIDがソースであるsshのみを許可するようにします。
CIDRブロック単位だと許可範囲が広いですし、IPだと変更があったときにセキュリティグループの設定も修正する必要があるので、セキュリティグループIDをソースに指定するやり方は便利です。

さて、この方法でセキュリティグループを作成するにあたってTerraformを使おうとした場合、少し悩みました。

以降のTerraformはv0.12.12で動作確認しています。

仮に踏み台サーバはどこからでもsshできて大丈夫だとして、そのようなセキュリティグループを作成する場合は以下のようなTerraformになります。

provider "aws" {
  region = "ap-northeast-1"
}

resource "aws_security_group" "bastion" {
  name        = "bastion"
  description = "Security Group for bastion"

  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

これはこれで問題ないのですが、今回作成したセキュリティグループをソースに指定してセキュリティグループを作成する方法に少し悩みました。

公式によると、aws_security_groupリソースのingressブロックで取りうる要素は以下の通りで、それっぽい指定箇所はありません。 www.terraform.io

要素 説明
cidr_blocks (Optional) List of CIDR blocks.
ipv6_cidr_blocks (Optional) List of IPv6 CIDR blocks.
prefix_list_ids (Optional) List of prefix list IDs.
from_port (Required) The start port (or ICMP type number if protocol is "icmp")
protocol (Required) The protocol. If you select a protocol of "-1" (semantically equivalent to "all", which is not a valid value here), you must specify a "from_port" and "to_port" equal to 0. If not icmp, tcp, udp, or "-1" use the protocol number
security_groups (Optional) List of security group Group Names if using EC2-Classic, or Group IDs if using a VPC.
self (Optional) If true, the security group itself will be added as a source to this ingress rule.
to_port (Required) The end range port (or ICMP code if protocol is "icmp").
description (Optional) Description of this ingress rule.

というわけで、よくよく調べると、aws_security_group_ruleリソースで指定ができるようです。 www.terraform.io

要素 説明
source_security_group_id (Optional) The security group id to allow access to/from, depending on the type. Cannot be specified with cidr_blocks and self.

最終的に、以下のようになります。

provider "aws" {
  region = "ap-northeast-1"
}

resource "aws_security_group" "bastion" {
  name        = "bastion"
  description = "Security Group for bastion"

  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

resource "aws_security_group" "application" {
  name        = "application"
  description = "Security Group for application"

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}
resource "aws_security_group_rule" "application_from_bastion" {
  type                     = "ingress"
  to_port                  = 22
  protocol                 = "tcp"
  source_security_group_id = aws_security_group.bastion.id
  from_port                = 22
  security_group_id        = aws_security_group.application.id
}

「プリンシプル オブ プログラミング」を読んで

はじめに

しばらく前に会社の同僚からすすめられて読んだので今更ながらまとめます。
「3年目までに身につけたい 一生役立つ101の原理原則」という副題がついているにもかかわらず、3年目どころではない私でも楽しめました。

プリンシプル オブ プログラミング

概要

タイトルにプリンシプル、副題に原理原則とあるように、本書は最初から最後まで徹底して「これはこういうものだ」というものが紹介されています。

「前提」「原則」「思想」「視点」「習慣」「手法」「法則」の7つで章立てされていて、各章でいくつかのプリンシプルが紹介されています。
すべてのプリンシプルは、どういうことなのか、どうして必要なのか、どうすれば実現できるのか、といったことが述べられていて、ただの押しつけにはなっていません。
また、コードは一切出て来ず、概念としての説明が主になっています。

感想

一番の感想は、よくこれだけの原理原則を集めたなということです。
リーダブルコードであればコーディングに関する内容ですし、各アンチパターン集であればその分野に特化したものになっていると思います。
その中で、プリンシプルに特化して101も紹介しているのは中々無いような気がします。

とは言え、コードは一切出て来ず概念的な説明が101回続くだけなので、たしかに一気にすべて読もうと思うと大変ですが、参考書的に必要な部分を掻い摘んで目を通していくような読み方をするなら、1冊もっておくのはアリだと思います。

実際読んでいると、DRY、カプセル化、3大美徳、車輪の再開発など、よく知られた聞いたことのあるプリンシプルが出てきます。
一方、なんだこの法則は!と思って読んでいると、ああこれはこういう名前なのか...と発見につながることも多々ありました。
例えば、ジョシュアツリーの法則やセカンドシステム症候群などがそうでした。

結局こういうプリンシプルは、カッコいい名前がついていて厨二感をくすぐられます*1が、名前自体に意味はなく、その内容をどれだけ理解しているかが重要だと思います。
ただ、共通認識として共通のワードがあれば意思疎通も効率的になるので、内容を理解している前提でチーム間で用語を共有できれば良さそうに思います。

本書で好きだった項目は、「1.1 プログラミングに銀の弾丸はない」「6.6 コンテキスト」です。

「プログラミングに銀の弾丸はない」に関しては、1.1という読者が一番最初に触れる部分にありながら、特効薬はないんだ難しいんだということを紹介しています。
内容自体はプログラミングに関することではあるのですが、言外に「だから本書で紹介するプリンシプルも銀の弾丸というわけではない」という主張が隠れているような気がして、構成の妙を感じました。

「コンテキスト」は、一番長く詳細に述べられている項です。
他の項目は長くても2〜3ページだけであるのに、この項目は10ページにも渡って紹介されています。
そのためなのか、それだからなのか、例示がたいへん多くしかもわかりやすくなっています。
達人と初心者の話として風呂掃除について、伝導能力のための背景の大事さの話として簡単なクイズとトイレについて、例え話があり、大変わかりやすいです。
コンテキストとドメイン駆動設計は切り離せないものなのか、ドメイン駆動設計への言及もあります。
さらには、西洋哲学、仏教哲学についても出てきます。
これだけ濃い項目は他には無く、背景や関係が大事だという話なのですが、とても印象深いです。

どのプリンシプルも、どうしてこれが必要なのかという点をしっかりと説明してあるので、よくある「べき論」で押し付け感があるということもありません。
逆に言うと、その説明に納得がいかなければ、そのプリンシプルは無視しても良いと思います。

全体的に、3年目までに身につけた方が良いかはよくわからなかったのですが、参考書的な読み方ができる良い本だと思います。
ただし、何度も言うようにコードは一切出てこないので、コードレベルでのサンプルがほしい場合はおすすめできません。

*1:これに名前がほしい

Terraformはどこで実行すれば良いのか教えてほしい

Terraformとは、多くのクラウドやその他のサービスを対象にInfrastructure as Codeを簡単に実現できる、便利なツールです。

その使い方は様々なところで紹介されているので良いとして、実際に実務として利用しようとした場合にTerraformをどこで実行するべきなのかということに悩みました。
ベストプラクティスがあるのか気になったのですがよくわからなかったので現状をまとめただけです。

どこで実行するべきか論は、Terraformに限らずAnsible等でも起こりえますが、今回はTerraformの話です。
また、Terraformを使って構築するのはAWS上の環境を想定しています。

Terraformを実行する環境の候補としては色々ありますが、今回は以下について考えました。

ローカルPCであれば、macなら brew install 等で環境を構築し、GitHub等で管理されている定義ファイルを使って、開発・実行することになります。
brew さえ使えれば良いのでイチ開発者のTerraform自体の環境構築は簡単です。
問題としては、ローカルに構築することになるのでどうしても環境を汚染してしまうことと、開発者間でTerraformのバージョンを揃えないといけないということがあります。*1

Docker on ローカルPCであれば、Dockerの環境とDockerfileを最初に用意できれば、以降は開発者間の差異を気にせずTerraformを実行できます。
普段からDockerを活用していて環境も用意されているなら、Terraform環境構築用のDockerfileがあれば良いので、特に手間もなく簡単です。
問題としては、メインであるTerraformの定義ファイルだけでなくDockerfile自体のメンテも必要になってしまうことと、当たり前ですがDockerに依存してしまうことがあります。

EC2インスタンスであれば、AWSのEC2上に共有のTerraform環境を用意して、開発者はそこにログインして実行します。
共有の環境なので開発者間の環境差異を気にする必要がなく、EC2へログインする方法され共有できれば個人で環境を構築する必要は基本的にありません。
問題としては、Terraformを使ってAWS上にInfrastructure as Codeで環境を構築しようとしているのに、Terraformを実行するための環境を手動で用意する必要があるということがあります。

それぞれのメリデメを考慮した上でより良い方法を選択するのが良いとは思うのですが、ベストプラクティスなりがあれば知りたいところです。

Terraformに関してはそこまで自動化する必要ないのではと思っていたのですが、このような方法もあるようなので紹介します。
medium.com

「Terraformをどこで実行するべきか」に関する情報もっとほしい...

*1:tfenvを使うという方法はあります

よく知られたボードゲームに似ているオススメのボードゲーム

はじめに

たまにはボードゲームの話でもしようと思います。

最近はボードゲームも人気になり、ボードゲームと言えば人生ゲームやUNOだけではないということも多少広まっている気がします。

そこで、よく知られたボードゲームと似ているが、それとは違うもしかしたらもっと面白い(一部では)ド定番でもあるボードゲームを紹介します。
どちらかがより面白いということで紹介しているわけではないので、悪しからず。

人生ゲーム ではなく ねことねずみの大レース

人生ゲームといえばすごろくです。
すごろくっぽい似たボードゲームとしてねことねずみの大レースがあります。
普通のすごろくと大きく違う点は、運だけではなく戦略も求められるという点です。

これは、サイコロを振って、その目の数だけ好きなように自分のねずみを進ませ、途中に落ちているチーズを取っていき、最終的に一番チーズを取った人の勝ちというゲームです。
ただし、サイコロにはねこの目があり、それが出るとねこが動き出します。ねこがねずみに追いついてしまうと自分のねずみを失ってしまいます。
チーズはスタート近くからゴール内まで数カ所に点在していますが、スタート近くほど点数が低くゴールに近いほど点数が高くなっています。そして、チーズを取ったねずみはねこに襲われることはありません。
つまり、ねこに襲われることを恐れてスタート近くの低い点数のチーズを取るのか、ねこに襲われるかもしれない中でゴール近くの高い点数のチーズに挑戦するかという、戦略も求められます。

子供とも一緒に楽しめますが、大人同士でも盛り上がります。
特にねこが追ってくる様は熱く緊迫感があります。

UNO ではなく NEU

UNOといえば、ある程度の人数で遊べるカードゲームです。
そんなカードゲームで似たボードゲームとしてNEUがあります。
大きな違いとしては、運要素がより大きくなり短時間で終わるようになっている点です。

ノイ (Neu) カードゲーム

ノイ (Neu) カードゲーム

これは、数字や特殊効果が書かれたカードを配り、順番に場に出していき、場の数字の合計が101を超えるようにカードを出してしまった人の負けというゲームです。
数字カードにはマイナスのカードや場の数を101に上書きするカードもあり、特殊効果のカードとしてパスやリバースなどがあります。
数字は0からスタートするので序盤は101はまだまだ先なのですが、50や101のカードが出されて急に熱い展開が繰り広げられることがよくあります。

足し算ができれば誰でも遊べ、1ゲームがとても短いので気軽にできます。
運要素がとても大きいので、ワイワイ楽しめるゲームです。

ジェンガ ではなく キャプテン・リノ

ジェンガといえば、崩した人が負けというような積み木のゲームです。
積み木っぽい似たボードゲームとしてキャプテン・リノがあります。 大きな違いとしては、何を積んでいくか戦略的に選べる点と、リノというキャラクターを登らせる独特な仕組みがある点です。

これは、屋根カードと呼ばれるカードを配り、その屋根カードと壁カードというカードを使い、積み木のようにタワーを作っていき、倒してしまった人の負けというゲームです*1
屋根カードにはスキップやリバースなどの特殊効果があったり、次の人が積むべきカードの形を指定できたり、戦略性があります。
さらに、リノというキャラクターのマークが書かれたカードを出すと、次の人はリノの人形をそのカードに置かなくてはいけません。リノがすでにどこかに置かれている場合はそこから回収した上で再度指定の場所に置く必要があります。
積み木というよりはトランプタワーに近いですが、ただ積んでいくだけでなく、積み方を指定される上に、人形も動かしていく必要があって、とても盛り上がります。

小さな子供がやると身長近くにもなり、巨大版で遊べば大人の身長でさえ優に超えてくる楽しさもあります。

キャプテン・リノ巨大版 第二版

キャプテン・リノ巨大版 第二版

将棋 ではなく ガイスター

将棋といえば、盤と駒を使う2人用のゲームです。
2人用の似たゲームとしてガイスターがあります。
大きな違いとしては、将棋ほどガチガチではなく運要素もあり気軽に楽しめる点です。

ガイスター (Geister) ボードゲーム

ガイスター (Geister) ボードゲーム

これは、良いおばけと悪いおばけを4体ずつ、どのおばけがどちらのおばけかは相手にわからないように自陣に設置し、将棋のように交互に動かして、相手のおばけを取ったりしながら、条件を満たした方の勝ちというゲームです。
勝つための条件として、①相手の自陣近くにある出口から良いおばけを外に出す、②相手の良いおばけを4体取る、③自分の悪いおばけを相手に4体取らせる、という3通りあります。
おばけはすべて前後左右の1マスしか進めることができず、ルールも簡単ではあるのですが、相手のおばけが良いのか悪いのかわからないために、とても悩ましくとても面白いゲームです。
相手の出口から出す必要があるのは良いおばけなので、良いおばけで相手陣地に進む必要があるのですが、単純に進むと相手に取られて相手が有利になってしまいます。そこで、良いおばけと見せかけて悪いおばけを進めて、悪いおばけを相手に取らせることを考え...と、裏の裏の裏まで考えることもある奥深いゲームです。

ルールが簡単であるので誰でも遊べるのですが、運要素もあるため将棋のように強い人が絶対に勝つということがなく気後れすることもなく楽しめます。

ビンゴ ではなく ストリームス

ビンゴといえば、大人数で余興として遊べるようなパーティーゲームです。
大人数で遊べるパーティーゲームとしてストリームスがあります。
どちらも数字を扱うのですが、大きな違いとしてただの運ではなく自分で戦略的に数字を配置していく点です。

リメイクとして、同じルールのパーティーキンゴ!というボードゲームもあります。

パーティーキンゴ!

パーティーキンゴ!

これは、参加者に書き込めるようなマスのあるシートを配り、数字の書かれたカードを代表者が順番に引き、参加者はその数字をマスに書き込んでいくゲームです。
参加者は引かれた数字を好きなようにマスに書き込んでいくのですが、できるだけ昇順になるように書き込んでいきます。
全てのマスを埋めた段階で、昇順になっている数字列の長さに応じて得点し、合計得点が一番大きい人の勝ちというゲームです。
基本的には昇順列が長いほど点数が大きくなるので、引かれたカードの数字と残っている数字を考慮し、確率をとるのかギャンブルをとるのか判断し、数字を書き込んでいきます。

大人数で遊べて、運要素ではなく多少意思を含んだ勝負にしたい場合にぴったりのゲームになっています。
良くない数字が出たときは阿鼻叫喚の図となるのも楽しめます。

さいごに

今度、会社の懇親会で上にあげたボードゲームの一部をやることになったので、ついでに色々と紹介しようと思い、書きました。

ボードゲームがとても好きなので、低頻度で紹介できたらと思います。

おまけ

今、放課後さいころ倶楽部というアニメが放送中です。
面白いボードゲームが紹介されて、途中の説明もとてもわかりやすいので、オススメです。

原作は、ボードゲームというニッチなテーマの漫画であるのに現時点で15巻も出ていて、追うのは大変かもしれないですが、こちらもとても面白いのでオススメです。

*1:正確には勝ちを決めるゲームです