Rogue Clone III の腹の減り具合がバグだったことを今日知った

ITMediaの「1000回遊べるRPGを4000回遊んだ男」って記事をすげーなと読んでたんだけど
http://nlab.itmedia.co.jp/nl/articles/1712/08/news117.html

「普段はかわのたて、戦闘時はもっと防御力の高い盾」と使い分けて腹減りを抑えると、食糧面で楽になります。その余力で経験値稼ぎ、アイテム集めに注力できると楽になるんです。

そもそもこういうやり方があることを今まで知らなかった。

Rogueでも似たようなことできるんじゃないのか。というかRogueにハマっていた当時はそういう攻略をしてたけど、最近忘れちゃってたのか、どっちだろう?


で、そもそも腹の減り具合ってどうなってんだろ→ちょうど自分のMacで昔RogueDarwinをコンパイルしていてソースがSSDの中にあるのでちょっと見てみるか、と思って見たところ、

        switch(e_rings) {
        /*case -2:                                                              
                Subtract 0, i.e. do nothing.                                    
                break;*/
        case -1:
                rogue.moves_left -= (rogue.moves_left % 2);
                break;
        case 0:
                rogue.moves_left--;
                break;
        case 1:
                rogue.moves_left--;
                (void) check_hunger(1);
                rogue.moves_left -= (rogue.moves_left % 2);
                break;
        case 2:
                rogue.moves_left--;
                (void) check_hunger(1);
                rogue.moves_left--;
                break;
        }

どう見てもバグですありがとうございました。

  • moves_left がプレイヤーキャラの腹の満たされ度合いを示していてこれが0未満だと1歩あるくごとにランダムに死ぬ
  • e_rings は指輪を身につけている数で、腹の減らない指輪はe_ringsが2減少する効果がある
  • ソースの意図としては、1歩あるくごとに
    ・指輪を装備していないときは1ずつmoves_leftが減る
    ・指輪を1個装備しているときは1.5ずつ、2個装備しているときは2ずつ減る
    ・腹の減らない指輪だけを装備していると減らない
    ・腹の減らない指輪と別の指輪を同時に装備しているときは0.5ずつ減る
    というようにしたかったと思われる
  • しかし上記のソースだと
    ・指輪を1装備しているときも2つ装備しているときも2ずつ減る
    ・腹の減らない指輪と別の指輪を装備しているときも全然腹が減らない
    という動きになる(一応moves_leftの奇遇で動作がかわるように作ってあるのだが、e_rings==1のとき「moves_leftが偶数のときはmoves_leftが1減り、奇数のときは2減る」という動作なのでずっと奇数が継続してしまうのだ)


Rogue Clone IVのソースを調べにいったところ( http://rogueclone.cvs.sourceforge.net/viewvc/rogueclone/rogue/src/move.c?revision=1.7.2.1&view=markup )、さすがに直されていました(しかも腹の減らない指輪だけを付けてるときも腹が減るようになってた)

        switch(e_rings) {
        /*case -2:
                Subtract 0, i.e. do nothing.
                break;*/                                                        
        case -2:
                rogue.moves_left -= (get_rand(1,4) == 1);                       
                break;                                                          
        case -1:
                /* NS: The original bug is funny enough to leave here for posterity. :-)
                 * rogue.moves_left -= (rogue.moves_left % 2); */               
                rogue.moves_left -= get_rand(0,1);                              
                break;                                                          
        case 0:
                rogue.moves_left--;                                             
                break;                                                          
        case 1:
                rogue.moves_left--;                                             
                (void) check_hunger(1);                                         
                /* rogue.moves_left -= (rogue.moves_left % 2); */               
                rogue.moves_left -= get_rand(0,1);                              
                break;                                                          
        case 2:
                rogue.moves_left--;                                             
                (void) check_hunger(1);                                         
                rogue.moves_left--;                                             
                break;                                                          
        }