第18話「パッチ適用の日々」
ロジカ王都に戻って一週間が経った。
俺たちは「魔法システム修正請負班」として、非公式に活動を開始している。名前はガルドが「かっこ悪い」と言ったが、代案も出なかったので定着した。
正式な依頼ルートは特務調査官経由、非公式な依頼はギルドや直接の口コミ。気づいたら毎朝、宿の前に依頼者が並ぶようになっていた。
それが——現状だ。
---
朝一番の依頼は、商業区の大手雑貨商・ポロスからだった。
「た、助けてください! 商売が終わりです! えっと、その、品物の値段が全部マイナスになってしまって、買い物に来たお客さんにこっちからお金を払う羽目になってるんです! もう昨日から三十七人来て、合計四千ゴールド以上出ていって——!」
四十代くらいの商人が、目の下に隈を作り、青白い顔で懇願してきた。服はよれているし、髪は乱れている。昨夜は眠れなかったのだろう。
「スキルは?」俺が聞く。
「は、はい、私の持っているスキルは『値引き交渉』です。交渉の度に価格を自動的に下げる——それが特技だったんですが、昨日の朝から急に暴走して……」
「デバッガーズ・アイで確認するので、少し待っていてください」
俺はスキルのコードにアクセスした。ポロスのスキル「値引き交渉」の内部ロジックが見える。
```
// Skill: price_negotiation
// 値引き交渉スキル
function negotiate(item_price, buyer_loyalty) {
let discount = calculate_discount(item_price, buyer_loyalty);
item_price -= discount;
return item_price;
// ← 問題はここ: 戻り値にバリデーションなし
}
```
見た瞬間、原因がわかった。
「変数の型が問題だ」俺は言った。「このスキルで使われている価格の変数、`int`型——整数型を使ってる。整数型は扱える範囲の下限がある。大量の値引きを積み重ねて、その下限を突き破ると、符号が反転してマイナスに飛ぶ。整数アンダーフローって言う」
「あ、あの——日本語で、じゃなかった、人間語でお願いします」
「水桶があると思ってください。水をどんどん出すと、最終的にカラになる。でもこのスキルの桶は設計ミスがあって、カラになった後も水を出し続けようとすると、どこからか水が逆流してくる——価格がマイナスになるのは、その逆流と同じことです」
「な、なるほど……?」
「修正します」
俺はコードに手を入れた。価格変数の型を`int`から`long`——より大きな範囲を扱える整数型に変換する。さらに、戻り値がゼロ以下にならないよう条件チェックを追加する。
```
// 修正後
function negotiate(item_price, buyer_loyalty) {
let discount = calculate_discount(item_price, buyer_loyalty);
item_price -= discount;
if (item_price < 1) item_price = 1; // 最低価格は1ゴールド
return item_price;
}
```
シンプルな修正だ。作業時間、約三分。
「直りました」
「ほ、本当ですか!?」ポロスが目を輝かせる。「なんか難しいことを言ってましたが……本当に直りましたか? お客さんに値段が表示されて、それが正しい数字に——?」
「確認してみてください」
ポロスが自分の商品棚を見て——「直ってる! 三十ゴールド! ちゃんと三十ゴールド!」と叫んだ。
アリアが俺の横でメモを取りながら、目を輝かせていた。
「変数の『型』によって扱える数値の範囲が変わる——なるほど、論理魔法の『係数宣言』と同じ概念ですね。係数を宣言する際に精度を指定しないと、小数点以下が切り捨てられる」
「正確にはそれとは少し違うが——方向性は合ってる」
ガルドが商人からもらった礼の菓子を頬張りながら首をかしげた。「型ってなんだ? 剣みたいなもんか? 大剣と小剣で斬れるものが違うみたいな?」
「……ある意味そう」
苦笑いしながら答えると、ガルドが「なるほどな」と真剣な顔で頷いた。本当に理解しているのか怪しいが、それで本人が満足しているならいい。
---
午後の依頼は鍛冶師区のベテラン職人・ドワンからだった。
「先生、こっちの方が緊急です!」
ギルドのカウンターで依頼書を受け取った瞬間、ドワンの弟子——まだ十代の、すすで顔を黒くした少年——が飛び込んでくる。
「師匠の炎魔法が暴走して、工房が火事になりそうで——!」
四人で急行した。
鍛冶師区のドワンの工房からは、遠目にも異常が見えた。煙突から普通じゃない量の煙が出ている。熱気が建物全体から漂っており、近づくだけで肌がじりじりする。
扉を開けた。
熱波が来た。
炉の前で職人のドワン——六十代の、肩幅の広い男——が必死に制御しようとしているが、炎は言うことを聞かない。石造りの壁の一部が赤く染まり始めている。本来の鍛冶炉の温度ではありえない色だ。
「離れていてください」俺はドワンに言い、デバッガーズ・アイで炎魔法「ヴァルカン・フォージ」のコードを展開した。
熱気の中でも、コードは見える。
```
// Skill: vulcan_forge
// 鍛冶炉の炎魔法
function vulcan_forge(target_temp) {
let current_temp = get_current_temp();
while (current_temp < target_temp) {
add_fuel();
current_temp = get_current_temp();
// ← 上限チェックが存在しない
}
}
```
「温度パラメータに上限値が設定されていない」俺は状況を声に出した。「温度の増加処理はある。でも`if temperature > MAX_TEMP`の条件チェックが存在しない。無限ループで加熱し続ける設計だ」
「修正できますか!?」弟子の少年が叫ぶ。
「今やる」
バリデーション処理を追加する。温度が一定の上限——鍛冶炉として安全な範囲の最大値——を超えた場合、自動で燃料供給を遮断する条件分岐だ。
```
// 修正後
const MAX_FORGE_TEMP = 1500; // 安全上限値
function vulcan_forge(target_temp) {
let current_temp = get_current_temp();
while (current_temp < target_temp) {
if (current_temp >= MAX_FORGE_TEMP) {
stop_fuel_supply(); // 燃料遮断
break;
}
add_fuel();
current_temp = get_current_temp();
}
}
```
炉の炎が、数秒後に落ち着いた。
赤かった壁の色が、ゆっくりと元に戻っていく。熱気が引いていく。
「……おおっ」ドワンが、信じられないという顔で炉を見た。「炎が、制御できてる。ちゃんと言うことを聞いてる」
「魔法学院の先生でも原因すら分からなかったのに!」弟子が目を丸くして言う。
ドワンが俺の前に来た。六十年以上生きてきたであろう皺の刻まれた顔が、深々と頭を下げた。「ありがとうございます。本当に……危うく工房ごと終わるところでした」
「設計の問題です。今後また起きるようなら連絡してください」
俺が淡々と答えると、アリアが横で小さく肩をすくめた。「もう少し優しく言える?」と目で言っていた。
俺は何も言わなかった。事実を言っただけだ。
---
帰り道、四人で宿へ向かいながら、メモリがぽつりと言った。
「マスター、今日の二つの修正——どちらも『想定外の状態になることを防ぐ』作業でしたね」
「そうだな」
「想定外というのは……悪いことですか?」
俺は少し考えた。
「システムにとっては悪いことだ。想定外の状態はクラッシュを引き起こす。だから防ぐ必要がある」
「では——悪いことですね」
「システムにとってはな。でも人間にとっては——想定外こそが面白いことになる場合もある」
メモリが俺を見た。
「……面白い、とは?」
「思いがけない出会い。予想しなかった展開。計算通りにいかないこと。それを人間は『面白い』と言う場合がある」
メモリは少しの間、その言葉を処理していた。
「……面白い」
小さな声で繰り返した。瞳の回路模様が、かすかに明滅した。光が、どこか弾んでいるように見えた。
「マスターも、想定外が好きですか?」
「嫌いじゃない」俺は答えた。「ただし、俺が対処できる範囲の想定外に限る」
「ガルドとアリアと私のことは……想定外でしたか?」
「最大級の想定外だ」
メモリが、くすっと笑った——笑ったように見えた。人工精霊が笑うと、瞳の光が一瞬強くなる。それだけのことだが、俺にはその違いがわかるようになっていた。
---
夕食の席で、ガルドが豪快に肉を頬張りながら言った。
「お前ら難しいことばっか言ってるけど、今日も人が助かったんだろ。それで十分じゃねえか」
アリアが苦笑する。「まあ、そうは言っても——」
「そうなんだよ。世界規模の陰謀とか、謎の存在とか、難しいことは難しいことで考えりゃいい。でも今日の仕事は、今日終わった。それを喜んどけ」
俺は黙って頷いた。
ガルドの言葉は、時々バグ修正の指針よりも正確に現実を捉える。
四人の間に、自然な空気が生まれつつあった。会話が弾む、というよりは——沈黙が苦痛じゃなくなっていた。それが「仲間」の定義だとしたら、俺たちはすでにそこにいるのかもしれない。
食後、俺が酒を頼もうとした——その瞬間、宿の窓から何かが飛び込んできた。
小さな鳥だった。足に、細い紙を括り付けている。
「伝書鳥だ」アリアが受け取り、素早く紐を解いた。
紙を開く。アリアの顔が引き締まる。
「——緊急依頼」アリアが読み上げた。「ネットワーク連合の主要通商路にて、転送魔法——テレポートゲートが連続暴走。物資が行方不明、旅人が見知らぬ土地に飛ばされる被害が続出。至急調査されたし」
ガルドが苦い顔をした。
「ネットワーク連合か……あそこは縄張り意識が強くてよそ者を嫌う。一筋縄じゃいかないぞ」
「行ったことがあるのか」
「昔、仕事で通ったことがある。連中、外から来た奴の言うことはまず聞かねえ」
「だから王家の紋章がある」アリアが静かに言った。「いつでも使う」
「……嫌いじゃないですかね、権威で押し切るの」俺が指摘する。
「嫌いです。でも必要なら使います」
潔かった。
俺は酒を飲むのをやめた。「明朝出発か」
「できれば今夜にでも」
「ガルド、荷造りできるか」
「三分で終わる」
「メモリ、転送魔法のシステムについて事前に調べてくれ」
「了解しました、マスター。すでに処理開始しています」
テキパキと動き始める三人を見ながら、俺は伝書鳥を窓の外に逃がした。
テレポートゲートの暴走。ルーティングが狂えば、物と人が正しい場所に届かなくなる。それはシステム的には——パケットロスと同じ問題だ。
やれやれ、夕食が台無しだ。
——まあ、仕事だから仕方ない。
次回、第19話「パケット・ロス」——ネットワーク連合の中枢都市「ポート・ハブ」。転送魔法の連続暴走、その裏に見えてきたヴァイラスの影。そしてコードの最深部に、謎の暗号が眠っていた。




