作者: 機械伯爵
日時: 2002/5/10(23:30)
「P は Python の P <実戦編>」
 〜やるぞ作るぞRPG!〜


NP-4 閉店・新装開店の時

 え〜新連載4回にして、もう挫折か?という話しでは、一応ありません(笑)

 これまで3回にわたって、試作品に手を入れてまいりましたが、これらは全
体の動作の様子と、本作品に必要なツールをそろえるためのものです。

 今回、コマンド関連をつかさどるcommand.pyを完成させて、ひとまずこの試
作品の改良は終了いたします。

 ゲーム内容はほとんど変わっていませんが、コマンドは数値だけでなく、文
字もうけつけるように改良されています(大文字、小文字を問いません)

 なお、ゲーム終了コマンドはひきつづき隠しコマンドとされていて、"quitgame"
ですので、ゲームに途中で飽きたらご利用ください。

--^ ebv4.py
#---ENDLESS BATTLE ver.4---
# 新しいコマンドクラスの動作確認のための
# テストモジュール
from dice    import *
from command import *
from display import *
from unit    import *
# 初期化作業
hero = Hero()

# コマンド作成
def hero_attack():
  dragon.hp - hero.attack()

# コマンド登録
hero_battle = CommandList({
  "attack" : hero_attack ,
  "heal"   : hero.heal
})
# お宝を装備するか捨てるかの選択コマンド
hero_weaponChange = CommandList({
  "change" : hero.changeWeapon,
  "drop"   : hero.dropTrophy
})
# ゲーム本体
next()
print 'WELCOME TO THE "ENDLESS BATTLE" FIELD!!'
next()
# メインループ
try:
  numberOfSlay = 0
  while numberOfSlay < 10 :
    print "Encounter!!"
    next()
    dragon = Dragon()
    while 1 :
      print "HERO'S WEAPON : ",hero.weapon.name
      print "HERO'S HP     : ",hero.hp
      print "HERO'S MP     : ",hero.mp
      print "DRAGON'S HP   : ",dragon.hp
      print "NO.OF SLAY    : ",numberOfSlay
      # 勇者の行動
      hero_battle()
      # ドラゴンの反撃
      print ""
      hero.hp -= dragon.attack()
      next()
      if hero.hp <= 0 : raise "HeroHPZero"
      elif dragon.hp <= 0 : break
    print "YOU WIN!"
    numberOfSlay += 1
    print "LEVEL UP!!"
    hero.levelUp()
    # ここから、お宝に関する処理
    print "YOU FIND A NEW WEAPON\nCHANGE?"
    hero.getTrophy(dragon.treasure())
    hero_weaponChange()
    next()
except "HeroHPZero":
  print "--HERO IS DEAD!--"
  print "--THE GAME OVER--"
  next()
else:
  print "--HERO SLAY 10 DRAGONS--"
  print "----CONGRATULATION!!----"
  print "--------GAME END--------"
  next()

--$ ebv4.py

 ebv4.pyは、FormalCommandに変わる、汎用のCommandListへのオブジェクトの
受け渡し方法が変更されたので、それに合わせてある以外、変更はありません。

 unit.py,item.py,display.py,dice.pyの4モジュールについては、全く変更
がありませんので、前回のものがそのまま使用できます。

--^ command.py
# command.pyモジュール[改定版]
# 定型、非定型に両対応

from sys import exit as sys_exit

class CommandList:
  def __init__(self,dict):
    self.dict = {"quitgame":sys_exit}
    self += dict
  def __add__(self,dict): # + は連結用
    for x in dict:
      self.dict[x.lower()] = dict[x]
    return self
  def __iadd__(self,dict): # +=は非連結用
    for x in dict:
      self.dict[x.lower()] = dict[x]
  def __sub__(self,key): # - は連結用
    del self.dict[key.lower()]
    return self
  def __isub__(self,key): # -= は非連結用
    del self.dict[key.lower()]
  def __delitem__(self,key):
    del self.dict[key.lower()]
  def __getitem__(self,key):
    return self.dict[key.lower()]
  def __setitem__(self,key,value):
    self.dict[key.lower()] = value
  def __call__(self,direct=0):#call(1)で、表示省略ダイレクト入力
    print "\n---COMMAND---\n"
    if direct:
      print "INPUT COMMAND AND HIT ENTER KEY!"
      while 1:
        c = raw_input("COMMAND >>> ").lower()
        if self.dict.has_key(c):
          self.dict[c]()
          break
        else :
          print "BAD COMMAND!\nPLEASE INPUT ONCE MORE"
    else :
      print "---SELECT NUMBER---"
      keyList = self.dict.keys()
      # quitgameを隠しコマンドにするため、リストから外す
      keyList = [x for x in keyList if x <> "quitgame"]
      keyList.sort()
      for x in range(len(keyList)):
        print x," : " , keyList[x].upper()
      print "INPUT COMMAND OR NUMBER\nAND HIT ENTER KEY!"
      while 1:
        c = raw_input("NUM/COM >>> ").lower()
        if c.isdigit(): # 番号入力の場合
          c = int(c)
          if 0 <= c < len(keyList):
            self.dict[keyList[c]]()
            break
          else:
            print "OUT OF RANGE!\nPLEASE INPUT ONCE MORE"
        else : # コマンド入力の場合
          if self.dict.has_key(c):
            self.dict[c]()
            break
          else :
            print "BAD COMMAND!\nPLEASE INPUT ONCE MORE"

--$ command.py

 今回の目玉であり、結果的には試作品の最大の結果となりました、コマンド
入力モジュールです。

 定型/非定型に分けるとメッセージの変更などが面倒になると考え、両対応
のクラスを作りました。

 ちなみに、ebv4.pyの一部を以下のように書き換えると、コマンドなどが表示
されず、ダイレクトにコマンドを入力しなければならなくなります。

    hero_battle()       -> hero_battle(1)
    hero_weaponChange() -> hero_weaponChange(1)

 魔法の入力や罠の解除なんかは、コレのほうが、Wizっぽくていいんじゃない
かな?と思うのは私だけでしょうか?(笑)

 さて、コマンドがしっかりできたところで、次回からは少しプログラミング
から外れて、ゲームデザインの話などを少しづつ進めていきたいと思います。

 最終的にどんなゲームにするかを決め、ゲームの骨格だけのものを作ります。

 それが終わったら、いよいよ各種データのフォーマットを考えるために、詳
細な戦闘ルールのデザインに入ります。

 戦闘ルールのデザインが終わったら、各種データ、そしてシナリオを書いて
完成。

 さて、完成までこぎつけるでしょうか?(笑)

   機械伯爵