makoto_ogaの日記

書ける時は技術系、それ以外は日常系・空想系のブログを書いていきます

ドッカンバトル不具合ソースコード解説

※11/17 9:30 追記
説明が不足しておりましたので、
『コインロッカーの0番目に悟空、1番目にクリリンが入っていて
2番目だけが空いている状態の場合』という文言を追記しました。


こんばんはogaです。

昨日公開された『ドッカンバトル』の不具合ソースコードの解説を私なりにしたいと思います。
なるべくプログラムを知らない方にも分かりやすいように書いていきます。

↓下記が公開された情報になります。

「ドラゴンボールZ ドッカンバトル」一部ガシャの「出現キャラ一覧」及び「出現キャラ提供割合」表示に関する不具合につきまして


公開されたソースコードはある機能のプログラムの一部です。
C++という言語で書かれています。

1行目に書かれている『〜getMasterCardDataByIds〜』というものを関数といいます。
この関数を呼ぶ事によって指定したIDのキャラクターカード情報を取得できるというものです。

まず、処理が書かれている3行目から見ていきます。
3行目〜5行目のソースコードです。

vector<CardDataPtr> results;
results.resize(masterCardIds.size());
size_t exists = 0;

3行目4行目は指定されたキャラクターカードID数分の配列作成し、メモリを確保しています。
配列というのは扉がたくさんある入れ物になります。
駅にあるコインロッカーをイメージしてください。

仮にここでは3個のキャラクターカードIDを指定したと仮定します。
そうするとコインロッカーの個数は3個用意することになります。
このコインロッカーは番号が0番から始まる規則になっているので
0番、1番、2番があることになります。
それがこのソースコードになります。

5行目はキャラクターカードの情報取得数をカウントするために使用します。

次に⓵の赤枠部分です。
1.スマホ内のメモリからデータ読み込み、コインロッカーに0番から順番に入れていきます。
2.コインロッカーに入れた数をカウントアップします。(exists++)

次に⓵の赤枠と⓶の赤枠の間の3行です。
指定されたキャラクターカードID数(3個)とコインロッカーに入れた
キャラクターカード情報の数を比較します。
数が一致したらメモリの状態が最新なので、コインロッカー情報を返却(return)して
関数を終了します。

件数が合わなければスマホ内のメモリが最新でないため、⓶の赤枠へ移行します。
この場合はコインロッカーのどこかに空きがある状態になります。

②の赤枠処理
ストレージからキャラクターカード情報を取得します。
空いているコインロッカーにキャラクターカードデータを
入れていきます。
最後にコインロッカー情報を返却(return)して関数を終了します。

不具合があったのは⓶の赤枠、キャラクターカード情報を取得する順番の部分です。

例えばキャラクターカード情報を下記のように仮定します。

カードID カード情報
0 悟空
1 クリリン
2 ピッコロ

②の赤枠で取得した順番がソートされていない下記のように取れた場合
2:ピッコロ
0:悟空
1:クリリン

コインロッカーの0番目に悟空、1番目にクリリンが入っていて
2番目だけが空いている状態の場合

上から順番にコインロッカーに入れていくので、コインロッカーの2番目に
クリリンが入ってしまい、1番目と2番目がクリリンとなってしまいます。(0番目は悟空)
また、ピッコロがコインロッカーに入らなくなります。
これが表示バグの原因です。

修正内容としては下記のようになるかと思います。

[修正前]

string sql = from(SELECT * FROM cache.cards where id IN (%s);", join(masterCardIds, ",").c_str());

[修正後]

string sql = from(SELECT * FROM cache.cards WHERE id IN (%s) ORDER BY id;", join(masterCardIds, ",").c_str());

修正後のソースコードが公開されていないのですが、おそらくこんな形だと思います。
これで昇順ソートされた順番で綺麗にコインロッカーに入れられます。

ただ、これだとソートされていないと不具合になるという危険を抱えたままなので
私がやる場合はIDがソートされていなくても問題無いように作ると思います。
(公開されていない部分の影響範囲は分かりませんが・・)

ソースコードの全文は割愛しますが、3行目のコインロッカーを作っている部分を変更します。

std::map<int, CardDataPtr> results;

これで配列が連想配列になります。
連想配列というのはラベル付きコインロッカーです。
普通のコインロッカーでは順番にキャラクターカード情報を入れていきましたが
このラベル付きロッカーにはラベルに対応したキャラクター情報しか入れられません。

0番目のロッカーにはID:0悟空、1番目のロッカーにはID:1クリリン、2番目のロッカーにはID:2ピッコロ
の情報しか入りません。
なので、取得したデータがソートされていなくても問題ないかと思います。

長くなってしまいましたが、
以上が公開されたソースコードの解説になります。

ガシャのソースコードは不具合が無いことを祈りつつ
詫び石300個でドッカンバトルを楽しんでいきましょう。

では、また。

シレーヌの日記9

私はシレーヌ

私とロミオの子供が生まれたわ。
名前はオーラ。
『時』を意味する言葉よ。
2人が時を越えて育んだ愛の結晶。

それがあなたよ - 。

あなたがこれを読んでいる時
私とロミオはもう死んでしまっているでしょう。

私たちはあなたをちゃんと愛せていたかしら?
限られた時間の中で精一杯やってきたつもりだけど
あなたに私たちの思いが伝わっていることを祈っているわ。

私たちの死期についてはあなたに話すかどうか
すごく迷っていたの。
でも、話さないことにしていたわ。
死期が分かってしまうことはすごく怖い事なの。
だから話せなかった。許してね。

それと、あなたには魔法の力が宿っているわ。
あなたがこれからの人生で大切な人を見つけた時
その人を守りたいと思った時
心の中で祈ってね。

きっと私があなたの元に現れて
魔法の事を教えてくれると思うから。

最後に、短い間だったけど
一緒に暮らせて楽しかったわ。
あなたの事をいつでも愛しています。
また会いましょう。

シレーヌより。


− オーラはそっと日記を机の上に置いた −

両親の突然の死の原因を探るため
オーラはシレーヌの残した日記を見た。
そして真実を知る事ができた。

オーラ15歳。
心に魔法の力を宿した少年は
大切な人を見つけるための旅に出るのであった。


おしまい。


makoto-oga.hatenablog.com

シレーヌの日記8

私はシレーヌ

ロミオの命がもうすぐ終わる - 。
そう知った私は何も考えずロミオの家の中で
寝込んでいた。

そのとき、聞こえてきたのはロミオの声。

シレーヌ!」

ロミオが帰ってきた - 。
ロミオに名前を呼ばれたのは、あの台風の日以来。
ロミオが帰ってきたの - 。

ロミオも私と同じく年齢を重ねていた。
でも何も変わっていなかった。
あの時のままの、やさしくてちょっと抜けている。
それがロミオ。

私たちは喜びを分かち合ったわ。
ロミオも旅の疲れがあったけれど、それを忘れて今までの事を
話し合った。
すごく長い時間、話したかった事を2人で話し合ったの。

でも、ロミオが私の記憶から事故の日の事を
消してくれたことを私が知っている事 - 。
それは言わなかったわ。
ロミオが守りたかったものを壊したくなかったの。

それから私達はロミオが働いている外国の地へ行く事にしたわ。
この場所にいては私の事を知る人達に迷惑が掛かってしまう - 。
後ろ髪を引かれる思いで私たちは
ロミオの家を後にした。

外国への移動中もずっと考えていたの。
ロミオはもうすぐ死んでしまう - 。
どうすればいいの。

私にできる事は - 。

私は決心した。
私ができることは1つしかない。
魔法の力を使ってロミオを救う事。
でも、もう次は2度とロミオに会えなくなるかもしれない。

私には移動の間の数日間がすごく怖かった。
ロミオと楽しく話をしていても常に頭を過る別れの気配 - 。

ついにロミオが働く外国の地へ着いたの。
そして私は願ったわ。
ロミオを救う事を - 。

目の前におばあさんが現れて
私は自分の祈りを伝えたわ。
そして - 、ロミオの命を20年延ばすことができた - 。

その魔法の代償は - 。
ロミオに与えた命と同じだけ私の命を差し出す事。
私とロミオはお互いあと約20年の命となったわ。

私は嬉しかった。
生きられる時間は減ったけれど、ロミオと一緒にいれる。
それは今までとは大きく違っていたの。

それから私たちは残された時間を共に生きていった。
そして、2人の間に子供を1人授かったの - 。

つづく。

makoto-oga.hatenablog.com

シレーヌの日記7

私はシレーヌ

今日は人生最良の日。
そして、最も悲しい日。

30年前の事故の真実を聞いた私は
ショックのあまり、しゃがみこんでしまったわ。

ロミオが死んでしまう。
私のせいで - 。

いつの間にかおばあさんはいなくなっていたわ。
私は埃を被ったロミオの庭の机を掃除し
椅子に座って空を眺めていた。

しばらく考えた後、私は自分の家を見に行こうと決めたわ。
30年 - 。
とても長い時間が過ぎていた。

自分の家への行き方はすぐに思い出せたわ。
以前見た風景とは変わってしまった道並みを横目に
自分の家を目指したの。

あった - 。

でも、なんて言って帰ったらいいのかしら。
私は30年前に死んだ身。
きっと、受け入れられることはない。

しばらく塀の外から様子を伺っていたわ。
そうしたら中から知らない女の人が出てきたの。
年齢は30歳から35歳くらいかしら。
庭で花に水をあげていた。
そして、家の中からもう一人出てきたわ。

お母さん - 。
昔とそれほど変わらない。
あの時のやさしいままの。
お母さん。

私はおもわず声を出そうとしてしまっていたわ。
でも、お母さんが女の人にやさしく語りかけている。
その雰囲気を見て、そっと声を落としたの。

すぐに理解できた。
私が死んだ後、心が悲しみに満ちてしまったおかあさん。
きっと、養子をとったのだわ。
2人の雰囲気はまさに親子のそれだった。

私は家に帰らず、その場を離れていった。
お母さんが元気でいてくれて本当に嬉しかった。
本当に。

でも、涙が止まらないのはなぜなのかしら。
もう、私には帰る場所は一切なかった - 。

あまり出歩くのも怪しまれてしまう - 。
そう思った私の行ける場所は1つしかなかった。

そう、ロミオの家。
いつも家の鍵は庭の机の裏につけていたわ。
もしかしたらと思い、机の裏を調べてみたわ。
鍵があった - 。

ごめんね、ロミオ。
少し家に入らせてもらうわ。
私は身を隠すためにロミオの家に入った。

電気も水も何も無いその場所で
ただ身を潜めていたわ。
木でいた頃はこんなに寂しいことはなかったかもしれない。
人間って寂しいのね。
とても - 。

それから何日か経ってからだった。
私は何も口にせず、体が衰弱していたわ。
こんなにもすぐに弱ってしまうのね。
このまま死んでしまってもいい - 。
そう思った時、その声は聞こえてきたの。

シレーヌ!」

忘れもしないその声は
ロミオの風音。

つづく。

makoto-oga.hatenablog.com

シレーヌの日記6

私はシレーヌ

人間の姿に戻った私に
おばあさんは真実を教えてくれた - 。

あの日、あの台風の日。
川に落ちたロミオを私が魔法で助けた日。

川に落ちたのはロミオではなかった - 。
あの日、川に落ちたのは私。

そして、その時に私は死んだの。

死んだ私を生き返らせようと、ロミオは必死に祈ってくれた。
そこでロミオは魔法の力を使ったの。
魔法の力を伝承していたのは私ではなく、ロミオの家系だった。
ロミオは5つのことを魔法に託したの。

シレーヌの魂を他の生き物に宿すこと。
シレーヌの記憶から事故の記憶を無くすこと。
シレーヌの記憶の一部を書き換えること。
シレーヌが蘇生したときにロミオに知らせること。
シレーヌに魔法の力を継承すること。

私の肉体は完全に死んでしまっていた。
でも、魂が肉体を蘇生させることが魔法により可能になったの。
そのための時間が10年。
私が猫になっていた時間。

ロミオは事故で私が体験した恐怖の記憶を無くしてくれた。

無くなった記憶の部分を
ロミオが溺れたという記憶に書き換えてくれた。

私がロミオの処刑を魔法で止めたとき
私は初めて魔法を使った。
20年間木になっていたのは
私の魔法の代償。

でも、ロミオは私の魂が何に宿っているかは知らなかった。
ロミオが外国へ旅立ったのも、どこかに宿る私を見つけるため
かもしれなかった。

そう語った後、おばあさんは話しを続けたわ。

ロミオが魔法の力を使ってまで
私の記憶を書き換えてくれたのに
なぜ、私に真実を教えたのか - 。

ロミオが私に使った魔法の代償 - 。
その代償はロミオの人生の半分を捧げることだった。
そう、ロミオは約40年の命を魔法の代償に差し出したの。

もう時間が残されていなかった。
ロミオの死期は迫っていた - 。

つづく。

makoto-oga.hatenablog.com

シレーヌの日記5

私はシレーヌ

今日は何か変な気分。
いつものように太陽の光で目を覚ましたわ。
でも、体がだるい - 。
うまく動かせないわ。

動かす - 。

何を考えているのかしら。

私は木。
動くことなんて - 。

手が動いた。
指も。
これは - 。

そう、私は人間の姿に戻っていたの。
もう、日を数えることもやめてしまっていた。
今日が魔法の代償から解放される日だった。

しばらくして体を動かす感覚を取り戻した私。
なんとか歩くことができた。
そして、ロミオの家の窓で自分の姿を確認したわ。

人間。そこにいたのは人間だった。
これは、誰なのかしら。
私はわからなかった。
その姿はあの日から
猫になったあの日から、30年経った私の姿だった。

それを教えてくれたのは、おばあさんだった。
魔法の力を使う時、いつも現れていたおばあさん。

私はようやく人間の姿になれたことが嬉しかった。
私の記憶している姿ではないけれど
面影は残っている気がする。

今日は人生最良の日 - 。
そう思えるくらい嬉しくて、私は自然と泣いていたわ。

そして、おばあさんは私に語りかけた。
真実を話す、と。
あの日の真実を - 。

つづく。

makoto-oga.hatenablog.com

シレーヌの日記4

私はシレーヌ

孤独な木。

ロミオは仕事で外国へ行ってしまったわ。
今までよりもはるかに悲しい。
そんな時間を過ごすことになってしまった - 。

しばらくは悲しみから立ち直れなかった。
でも、ロミオの頑張っている姿を思い出したわ。
私は何もできないけれど、時が来るまで耐えるしかないの。

もうこれ以上、魔法の力を使うわけにもいかない - 。
次はどんな姿になってしまうのか。
考えただけでも恐ろしいわ。

また月日は流れていった。

どれくらい経ったのかしら。
私はもう木としての自分を受け入れつつあった。

朝は太陽が力をくれる
昼は鳥たちが憩う
夜は月が鎮めてくれる

そんな日々が当たり前になった頃
私の前に1匹の猫が現れたの。

そう、それは私が木になる前の姿だった - 。
私は猫になった時、ロミオの家の窓で自分の姿を確認したの。
そして、首輪も付けていた。
間違いなく、その猫は私だった。

どういうことかしら。
私は今まで自分が姿を変えて生きていると思っていた。
でも、この猫は私じゃない。
ロミオが家を出る時に何かを探していた気がするわ。
それは、この猫かもしれない。

もし、私は生き物に憑依するような形で生きているのなら - 。
猫からロミオの家の木に憑依した私。
人間から猫に憑依した私。
じゃあ、人間だった私の体はどこへ行ってしまったの。
私は人間に戻れるの - 。

そんな不安と疑問は動けない私がいくら考えても
わからないまま、時は過ぎていった。

そして、途方もない時間の果て
遂にその時がやってきたの。

つづく。

makoto-oga.hatenablog.com