見出し画像

オブジェクト指向で戦闘シミュレーション?(4)

前回は「艦これ」の戦闘のうち、砲撃戦の攻撃のみ計算させてみました。
今度は雷撃戦の攻撃も計算させてみます。

砲撃戦と雷撃戦の攻撃力計算の差

前回のプログラムのうち、PlayerクラスのGetOffenseメソッドで攻撃力計算をさせていました。
これをコピーして、与える値や計算の違うところを修正すれば、それでもプログラムは完成します。
しかし、大まかな計算の流れ()は同じなので、違う部分だけを書き直して、共通部分は再利用したほうがプログラムの見通しが良くなったり、デバッグが減ったりと利点があります。
今回はこれを、オブジェクト指向の「継承」を使って実現してみたいと思います。

砲撃戦と雷撃戦の計算のうち、変更が加わるのは下記になります。

・陣形補正
・損傷補正
・基本攻撃力計算式
・攻撃力キャップ
・クリティカル発生率

プログラム書き換え

攻撃力計算はPlayerクラスで行っていますが、今回は1人のPlayerで攻撃種類を切り替えたいので、継承で派生させるための(攻撃力計算用)Offense〜クラスを新たに作りたいと思います。

まずはもととなる、砲撃戦計算OffenseBombクラス。

class OffenseBomb():
   #昼・砲撃戦バージョン
   def __init__(self, player):
       self.Player= player
   
   def JinkeiHosei(self, Jinkei):
       #Jinkei 0:単縦/1:複縦/2:輪/3:梯/4:単横/5:警戒
       return [1.00, 0.80, 0.70, 0.75, 0.60, 0.5][Jinkei]

   def KousenKeitaiHosei(self, KousenKeitai):
       #KousenKeitai 0:同航戦/1:反航戦/2:T字有利/3:T字不利
       return [1.0, 0.8, 1.2, 0.6][KousenKeitai]
       
   def SonsyoHosei(self, Sonsyo):
       #Sonsyo 0:全快/1:小破/2:中破/3:大破/4:攻撃不能
       return [1.0, 1.0, 0.7, 0.4, 0.0][Sonsyo]
   
   def KihonKougeki(self, Player, KaisyuHou):
       #基本攻撃力
       return (Player.Karyoku +KaisyuHou +5)
   
   def Cap(self):
       #キャップ:昼戦砲撃戦
       return 180.0
       
   def ProbChritical(self, HitLev):
       #クリティカル発生率
       return (0.125 *math.sqrt(HitLev) +0.01)
   
   def Get(self, Player, Jinkei= 0, KousenKeitai= 0, KaisyuHou= 0.0):
       #各種パラメータ
       Sonsyo=0         #0:全快/1:小破/2:中破/3:大破/4:攻撃不能
       Chritical= 1.0   #クリティカル補正

       CapMaeHosei= self.KousenKeitaiHosei(KousenKeitai)  \
                    *self.JinkeiHosei(Jinkei)             \
                    *self.SonsyoHosei(Sonsyo)
       
       #命中・クリティカル判定
       HitLev= (self.Player.GetHit() -self.Player.GetAvoidance()) /100.0
       ChriticalDice= random.random()
       if ChriticalDice>=HitLev:                          #MISS
           return 0
       if ChriticalDice<self.ProbChritical(HitLev): #クリティカルヒット発生
           Chritical= 1.5

       #キャップ前攻撃力
       CapMae= self.KihonKougeki(Player, KaisyuHou) *CapMaeHosei
       
       #攻撃力キャップ
       if CapMae<=self.Cap():
           CapGo= CapMae
       else:
           CapGo= self.Cap() + math.sqrt(CapMae -self.Cap())

       #最終攻撃力算出
       A= int(CapGo)
       SaisyuKougeki= int(A *Chritical)    # クリティカル熟練度補正

       return SaisyuKougeki
       
       
class Player():
   #-- 中略 --#
   
   def GetOffense(self):
       OffenseAction= OffenseBomb(self) #上記のクラスを使う
       return OffenseAction.Get(self)   #攻撃力を返す

クラスの継承

次に、OffenseBombクラスを継承して、雷撃戦計算OffenseLightクラスを作ってみます。

#OffenseBombの後方に、下記の継承するクラスを書く

class OffenseLight(OffenseBomb):
   def JinkeiHosei(self, Jinkei):
       #Jinkei 0:単縦/1:複縦/2:輪/3:梯/4:単横/5:警戒
       return [1.0, 0.8, 0.7, 0.6, 0.6, 1.0][Jinkei]

   def SonsyoHosei(self, Sonsyo):
       #Sonsyo 0:全快/1:小破/2:中破/3:大破/4:攻撃不能
       return [1.0, 1.0, 0.8, 0.0, 0.0][Sonsyo]

   def KihonKougeki(self, Player, KaisyuRai):
       #基本攻撃力
       return (Player.Raisou +KaisyuRai +5)

   def Cap(self):
       #キャップ:昼戦砲撃戦以外
       return 150.0

   def ProbChritical(self, HitLev):
       #クリティカル発生率
       return (0.15 *math.sqrt(HitLev) +0.01)

class OffenseLight(OffenseBomb):と書くことで、OffenseBombクラスを継承することを指定します。
この中に継承元のメソッドと同名を書くことで、メソッドを上書きします。
上書きしなかったメソッドは、そのまま使うことができます。

なので、ここでの雷撃計算では、書き換えた5つのメソッドが書き換わり、OffenseBombクラスで用意したGetメソッドは同じように使うことができます。

意外と簡単に済んでしまいました。

ついでにポリモーフィズム

Playerクラスには、攻撃力を返すGetOffenseメソッドで、砲撃と雷撃を切り替えるプログラムを組みました。

class Player():
   #-- 中略 --#
   
   def GetOffense(self, action): #action= 雷撃:0、砲撃:1
       if action==0:
           OffenseAction= OffenseLight(self)
       elif action==1:
           OffenseAction= OffenseBomb(self)
       return OffenseAction.Get(self)
              #クラスが変わっても同名のメソッド(Get)を使うことができる

OffenseActionオブジェクトは、砲撃か雷撃かでクラス(OffenseBomb、OffenseLight)が変わります。
しかし、それらのクラスに同名のメソッドがあれば、それを使うことができます。(上記のreturnの所)

まあ当たり前なんじゃない?と思えたならば素晴らしい!
同じ名前のメソッドは同じように使えるように作れば、「return OffenseAction.Get(self)」はもう修正する必要がなくなります。
特に、継承を使うと、これが簡単にできることがオブジェクト指向の利点です。

昔からプログラムをしていると、違うメソッドを指しているのでエラーになるのではと直感で勘ぐってしまいますが、ポリモーフィズムならば大丈夫です、はい。

プログラムを試してみる

前回と同じように、paiza.ioにプログラムを用意しました。

エディタに用意されたプログラムは書き換えることができますし、ページを閉じれば元に戻りますので、自由に実行してみてください。

いいなと思ったら応援しよう!

この記事が参加している募集