文字列のフォーマットを使い分ける
戦闘時にモンスターへダメージを与えると、その旨が画面へ表示される。ソースコードを解析するまで知らなかったんだけど、ダメージ値に応じてメッセージが選ばれているわけではなく、なんと単純なランダムで選ばれていた。ローグを夢中で遊んでいた頃、「このメッセージが出ればモンスターを倒せるはず!」と思ったいたので、その幻想は儚くも打ち砕かれてしまった。
オリジナルのソースコードで攻撃が当たった場合に文字列を表示する処理は次の通り。
--- fight.c ---
446: hit(er, ee)
447: register char *er, *ee;
448: {
449: register char *s;
450:
451: addmsg(prname(er, TRUE));
452: if (terse)
453: s = " hit.";
454: else
455: switch (rnd(4))
456: {
457: when 0: s = " scored an excellent hit on ";
458: when 1: s = " hit ";
459: when 2: s = (er == 0 ? " have injured " : " has injured ");
460: when 3: s = (er == 0 ? " swing and hit " : " swings and hits ");
461: }
462: addmsg(s);
463: if (!terse)
464: addmsg(prname(ee, FALSE));
465: endmsg();
466: }
これをPythonに置き換えて、次のように実装した。f文字列とformatメソッドを使い分けてみた。
def hit(er, ee):
Io.addMsg(prname(er, True))
s = [
" scored an excellent hit on ",
" hit ",
f" {'have' if er == None else 'has'} injured ",
" swing{0} and hit{0} ".format('s' if er == None else '')
]
Io.addMsg(s[Rogue.rnd(4)])
Io.addMsg(prname(ee, False))
Io.endMsg()
f文字列はダブルクォートしてあれば、その中でシングルクォートを併用することができるだろうと思って試したらできた。なぜ「できる」と思ったのか?それは、ほかの多くのスクリプト言語でもそうだから。
同じように、波括弧の間には当然のように式を書くことができるだろうと思って試したらやはりできた。この辺りは各種プログラミング言語に共通なイディオムだと思っていいのかもしれない。
もうひとつは、formatメソッドを使う方法。こちらは複数形のsを2箇所につけるので採用した。同じ引数を複数箇所に埋め込めるのがformatメソッドの最大のメリットだと思う。
これをf文字列でやろうと思ったら、同じ式を2回書くか、一時変数に代入しなくちゃいけない。
同じ式を2回書く方法だとこうなる。
f" swing{'s' if er == None else ''} and hit{'s' if er == None else ''} "
一時変数に代入する方法だとこうなる。
s = 's' if er == None else ''
f" swing{s} and hit{s} "
こういう使い分けかたも、実際にプログラミングしていかないとなかなか学べないし、今回のことで「便利だからf文字列だけ」とか「使い慣れているからformatメソッドだけ」みたいな偏りもなくなった。
この記事が気に入ったらサポートをしてみませんか?