このソースコードによる処理が行われた結果、特定のエリアで、プランナーの条件データでマッチする人と、ゲームサーバ側の条件データでマッチする人が完全に異なる状態になり、パーティーが成立しなくなった。なぜこのコードがゲームサーバに残っていたのか、青山氏は説明する。
「この不具合が起きる1年前の6月、邪神の宮殿に関するデータフォーマットを変更した。その際、移行するタイミングが不明瞭だったため、一時的に6月分の参加条件をソースコードで直接処理することでシームレスに移行できるようにした。そのソースコードを消し忘れて、1年後の6月10日に分岐処理が行われて不具合が発生したというオチだった。この失敗からは、暫定で対応する際は対応完了までをBTSのチケットで管理すべきだという教訓を得た」
最後に取り上げた不具合は「『釣り』において、『オウムガイ』の『ビッグサイズ』や『キングサイズ』を釣ったのに、『釣り老師』や『魚交換員』から、ビッグサイズはノーマルサイズ、キングサイズはビッグサイズとして扱われることがある」だ。
ドラゴンクエストXでは、釣りを行うことができる。魚は個々に大きさの数値データとサイズの定義があり、サイズとしては「キング」「ビッグ」「ノーマル」がある。魚を釣った後、「釣り老師」や「魚交換員」というキャラクターと話すと、サイズに対応した報酬を得られる。
不具合の対象となった「オウムガイ」という魚は「1023mm」(1.023m)以上でビッグサイズ、「1022mm」(1.02m)以下でノーマルサイズと定義されていたが、ビッグサイズのオウムガイがノーマルサイズと判定されていた。
「釣りの実装部分ではC++とLuaを併用しており、C++では魚の大きさをint型で扱っていた。一方、LuaにはC言語におけるdouble型しかないため、doubleで扱っていた。われわれはLuaにおけるdouble型の数値演算で浮動小数点の誤差による不具合が起きたのではないかと疑った」
浮動小数点の誤差とは、小数に関するプログラムの問題だ。コンピュータの内部では10進数を2進数として扱うが、0.1のような小数を2進数で表現しようとすると10進数における「3分の1 = 0.333……」のような循環小数になる。従って、数値演算で小数を扱う場合は、近似値計算が行われている。
今回の場合、1023mmから1.023mに変換する計算の中で、限りなく1023に近い値と、限りなく1.23に近い値を利用している。開発チームでは1023や1022という値に1000を掛けたり、割ったりして内部の値がどうなるか確認した。その結果「1023」という数値でも内部的には「1022.999……」になっていることが分かったという。
「開発チームは小数を利用した計算で誤差が起きることを加味して、誤差補正処理を追加して数式を組み立てていたので、この誤差は今回の不具合とは無関係だと考えていた。しかし別の不具合の検証時に、数式に問題があると分かった」
青山氏が紹介したのは以下の数式だ。
Copyright © ITmedia, Inc. All Rights Reserved.