なでしこを明後日の方向に

日本語プログラム言語なでしこを応援しています

なでしこ3でMTGのカードを検索する

※ MTGマジック・ザ・ギャザリング(カードゲーム)

なでしこ3貯蔵庫にプログラムを投稿してきました。

投稿ページ(プログラムソース)
MTGカードまとめて検索

アプリページ
n3s.nadesi.com

アプリページくん、中央揃えにしないで?

何をするためのもの?

意識高いMTG記事では、カード名を《  》でくくって書かれる事が多いです。
コンボ紹介記事では複数のカードが入り乱れるのですが、これを1枚1枚検索するのはけっこう大変。

そこで複数のカード名を含む文章をコピペするとカードの部分だけ拾って検索してくれるものを作りました。

たとえば、こういう文章をそのまま検索の入力欄にいれます。

2022年1月25日改定
以下のカードはスタンダード・フォーマットにおいて禁止されています。
・《アールンドの天啓》
・《ゼロ除算》
・《不詳の安息地》
・《創造の座、オムナス》

この文章を入れて検索ボタンを押すと《アールンドの天啓》《ゼロ除算》《不詳の安息地》《創造の座、オムナス》の4枚のカードを検索します。

検索結果は


《アールンドの天啓/Alrund's Epiphany
{5}{U}{U}
ソーサリー
飛行を持つ青の1/1の鳥・クリーチャー・トークン2体を生成する。このターンに続いて追加の1ターンを行う。アールンドの天啓を追放する。
予顕{4}{U}{U}(あなたのターンの間、あなたは{2}を支払って、あなたの手札からこのカードを裏向きに追放してもよい。後のターンに、これの予顕コストでこれを唱えてもよい。)


《ゼロ除算/Divide by Zero》
{2}{U}
インスタント
マナ総量が1以上の、呪文1つかパーマネント1つを対象とする。それをオーナーの手札に戻す。
履修を行う。(あなたは、ゲームの外部からあなたがオーナーである講義・カード1枚を公開しあなたの手札に加えるか、カード1枚を捨てカード1枚を引くか、どちらかを行ってもよい。)


《不詳の安息地/Faceless Haven》
氷雪土地
{T}:{C}を加える。
{S}{S}{S}:ターン終了時まで、不詳の安息地は警戒とすべてのクリーチャー・タイプを持つ4/3のクリーチャーになる。これは土地でもある。({S}は氷雪である発生源からのマナ1点で支払える。)


《創造の座、オムナス/Omnath, Locus of Creation》
{R}{G}{W}{U}
伝説のクリーチャー — エレメンタル
創造の座、オムナスが戦場に出たとき、カードを1枚引く。
上陸 ― 土地が1つあなたのコントロール下で戦場に出るたび、このターンで初めてこの能力が解決されるなら、あなたは4点のライフを得る。2度目なら、{R}{G}{W}{U}を加える。3度目なら、創造の座、オムナスは各対戦相手とあなたがコントロールしていない各プレインズウォーカーに、それぞれ4点のダメージを与える。
4/4


こんな感じ。

APIの仕様は

https://api.magicthegathering.io/v1/cards?name={カード名}
これをAJAX送信で送るとjsonデータが返ってくる。
日本語のカード名で検索するときは
https://api.magicthegathering.io/v1/cards?language=japanese&name={カード名をURLエンコード}

詳しいことはプログラムのコメントに書いた!

なでしこ3で《カード名》を取り出す

文字列処理で《カード名》の内側をとりだして配列にする部分がこちら。

 もし(txt「》」出現回数)>0ならば
   ex=「.*《(.*)》」(txt「》」出現回数)リフレイン
   txt = txt改行「」置換
   txt「/{ex}/」正規表現マッチ
   戻値 = 抽出文字列配列複製

カード1枚なら正規表現でいうと《(.*)》で取り出せます。

文に含まれる《カード名》をすべて取りたいので、まず「》」の出現回数を調べます。
たとえば3個の「》」が文章中にあるならばtxtが「/.*《(.*)》.*《(.*)》.*《(.*)》/」に正規表現マッチとなるようにします。
正規表現マッチでは(  )にマッチした部分が変数抽出文字列に入るのでカード名だけが配列にして取り出せます。

少々、方法が雑なのは認めます

カード名は日本語?英語?

APIにカード名を送るとき、日本語の場合はURLパラメータlanguage=japaneseを付けたうえで、カード名をURLエンコードする必要があります。

日本語か英語かを判定する関数がこちら

●多バイト文字含む(txtに|txtが)
 txt文字列分解して反復
   もし255<ASC(対象)ならば1戻す
 0戻す

もしカード名多バイト文字含むならば で呼び出します。

文字列分解で1文字ごとに文字にASCをかけていきます。
256以上だったらアルファベット以外だな…日本語に違いない、日本語として処理しよう、という感じです。

少々、方法が雑なのは認めます