前回作成したドラクエ1風のシミュレーターを改造して
ドラクエ2風のチーム戦が出来るようにしました。
解説動画はこちら
さて前回のプログラムを改造して行きましょう。
前回は1vs1だったので
複数vs複数に対応するように改造します。
前回の奴をそのまま使用するのと改造するもの
新規のものといろいろ出てきますが
まずは前回の流用。
キャラクタークラスはそのまま流用できますが
チーム戦になると生存フラグが必要になってきますので
フラグを追加します、1が生存0が死亡。
ダメージ計算や素早さ計算はそのまま流用します。
チーム戦を行うために、キャラを複数格納できる
チームクラスを作ります。
前回は2キャラの対戦なのでチームでの複数対戦だと
行動の順番を決める必要があります。
行動順番は素早さを元に計算し
数値が大きい順に行動するようにします。
その際生存フラグが1のものだけにします。
戦闘順番が決まったらその順番通りに攻撃開始です。
相手チームの中で狙う相手を決めるために
相手チームの生存者を探してインデックス値で返します。
ターン中の攻撃は攻撃者からターゲットへの
一方的なやりとりだけにします。
お互いのステータスからダメージ計算し
相手のHPから引き、HPが0になったら倒れます。
チームの全員の生存フラグが0になったら試合終了です。
全員の生存フラグをチェックします。
ターンが終わったら全員のステータスを出すように
ログ出力します。
ここから戦闘中のアルゴリズムです。
順番を決めて
攻撃対象を決めて
ダメージ計算して
HP0なら生存フラグを0にして
全員生存フラグ0なら勝負ありです。
さて、シミュレーションしてみましょう。
結果は
見事に勇者チーム勝利wwwwwwww
お互いに殴り合うだけの
単純なシミュレーションです。
ドラクエ2風になったんじゃないかと思います。
そう考えると
ドラクエ3以降は複雑怪奇ですねーー
すぐ作れる気がしないので
この先どうなることやら・・・
今回はここまでです。
それでは。
ドラクエ2風のチーム戦が出来るようにしました。
解説動画はこちら
さて前回のプログラムを改造して行きましょう。
前回は1vs1だったので
複数vs複数に対応するように改造します。
前回の奴をそのまま使用するのと改造するもの
新規のものといろいろ出てきますが
まずは前回の流用。
キャラクタークラスはそのまま流用できますが
チーム戦になると生存フラグが必要になってきますので
フラグを追加します、1が生存0が死亡。
ダメージ計算や素早さ計算はそのまま流用します。
import numpy as np
# キャラクタークラス
class character():
def __init__(self,name,hp,attack,defence,agility):
self.name = name
self.hp = hp
self.attack = attack
self.defence = defence
self.agility = agility
self.survive = 1
# ダメージ計算
def damage_calc(c1,c2):
base = c1.attack //2 - c2.defence//4
rand = base//16+1
tmp = np.random.randint(0,rand*2+1)-rand
damage = base + tmp
return damage
# 素早さ計算
def agility_calc(c):
base = c.agility
tmp = base//10
result = np.random.randint(base-tmp,base+tmp+1)
return result
チーム戦を行うために、キャラを複数格納できる
チームクラスを作ります。
# チームクラス
class Team():
def __init__(self,name,teams):
self.name = name
self.team = teams
def append(self,chara):
self.team.append(chara)
def delete(self,index):
del self.team[index]
前回は2キャラの対戦なのでチームでの複数対戦だと
行動の順番を決める必要があります。
行動順番は素早さを元に計算し
数値が大きい順に行動するようにします。
その際生存フラグが1のものだけにします。
# 先頭順序の計算
def turn_calc(t1,t2):
result = {}
for i,c in enumerate(t1.team):
ag = agility_calc(c)
if c.survive==1:
result['{0}:{1}'.format(t1.name,i)] = ag
for i,c in enumerate(t2.team):
ag = agility_calc(c)
if c.survive==1:
result['{0}:{1}'.format(t2.name,i)] = ag
return [k for k,v in sorted(result.items(),reverse=True,key=lambda x:x[1])]
戦闘順番が決まったらその順番通りに攻撃開始です。
相手チームの中で狙う相手を決めるために
相手チームの生存者を探してインデックス値で返します。
ターン中の攻撃は攻撃者からターゲットへの
一方的なやりとりだけにします。
お互いのステータスからダメージ計算し
相手のHPから引き、HPが0になったら倒れます。
# 狙う相手を計算
def target(teams):
index = [i for i ,c in enumerate(teams.team) if c.survive==1]
return np.random.choice(index)
# ターン中の攻撃
def attack(c1,c2):
damage = damage_calc(c1,c2)
c2.hp = c2.hp - damage if c2.hp - damage>=0 else 0
print('{0}の攻撃 : {1}に{2}のダメージ'.format(c1.name,c2.name,damage))
print('{0}のHP : {1}'.format(c2.name,c2.hp))
if c2.hp<=0:
print('{0}は力尽きた!!!'.format(c2.name))
return (c2,0)
return (c2,9)
チームの全員の生存フラグが0になったら試合終了です。
全員の生存フラグをチェックします。
ターンが終わったら全員のステータスを出すように
ログ出力します。
# 生存チェック
def check_survived(teams):
res = 0
for c in teams.team:
if c.survive==1:
res+=1
if res > 0:
return True
else:
return False
# ログ出力
def print_log(t1,t2):
print()
result = ''
for c in t1.team + t2.team:
result += '{0} , HP : {1}\t'.format(c.name , c.hp )
print(result)
print()
ここから戦闘中のアルゴリズムです。
順番を決めて
攻撃対象を決めて
ダメージ計算して
HP0なら生存フラグを0にして
全員生存フラグ0なら勝負ありです。
# 戦闘
def battle(t1,t2):
print('戦闘開始')
print_log(t1,t2)
while True:
# ターン内の処理
for m in turn_calc(t1,t2):
tm , i , flg= m.split(':')[0] , int(m.split(':')[1]),9
# 攻撃チームの設定
attack_team = t1 if t1.name==tm else t2
# ターゲットチームとターゲットの指定
target_team = t2 if t1.name==tm else t1
t_num = target(target_team)
# 戦闘結果
target_team.team[t_num],flg = attack(attack_team.team[i],target_team.team[t_num])
if flg==0:
target_team.team[t_num].survive=0
if not check_survived(t1):
print('\n{0}チームの勝ち'.format(t2.name))
break
elif not check_survived(t2):
print('\n{0}チームの勝ち'.format(t1.name))
break
# ターン後
if not check_survived(t1) or not check_survived(t2):
break
print_log(t1,t2)
print('戦闘終了')
さて、シミュレーションしてみましょう。
c1 = character('勇者1',100,80,40,66)
c2 = character('勇者2',100,80,40,66)
c3 = character('勇者3',100,80,40,66)
c4 = character('勇者4',200,100,50,66)
s1 = character('スライム1',180,80,30,66)
s2 = character('スライム2',180,80,30,66)
s3 = character('スライム3',180,80,30,66)
s4 = character('スライム4',380,70,40,56)
team1 = Team('勇者チーム',[c1,c2,c3,c4])
team2 = Team('スライムチーム',[s1,s2,s3])
battle(team1,team2)
結果は
戦闘開始
勇者1 , HP : 100 勇者2 , HP : 100 勇者3 , HP : 100 勇者4 , HP : 200
スライム1 , HP : 180 スライム2 , HP : 180 スライム3 , HP : 180
スライム1 , HP : 180 スライム2 , HP : 180 スライム3 , HP : 180
勇者1の攻撃 : スライム2に36のダメージ
スライム2のHP : 144
勇者2の攻撃 : スライム3に34のダメージ
スライム3のHP : 146
スライム3の攻撃 : 勇者3に29のダメージ
勇者3のHP : 71
スライム1の攻撃 : 勇者3に28のダメージ
勇者3のHP : 43
勇者4の攻撃 : スライム2に41のダメージ
スライム2のHP : 103
勇者3の攻撃 : スライム3に36のダメージ
スライム3のHP : 110
スライム2の攻撃 : 勇者4に30のダメージ
勇者4のHP : 170
勇者1 , HP : 100 勇者2 , HP : 100 勇者3 , HP : 43 勇者4 , HP : 170
スライム1 , HP : 180 スライム2 , HP : 103 スライム3 , HP : 110
スライム1 , HP : 180 スライム2 , HP : 103 スライム3 , HP : 110
スライム1の攻撃 : 勇者4に29のダメージ
勇者4のHP : 141
勇者4の攻撃 : スライム2に43のダメージ
スライム2のHP : 60
勇者1の攻撃 : スライム2に32のダメージ
スライム2のHP : 28
勇者2の攻撃 : スライム2に31のダメージ
スライム2のHP : 0
スライム2は力尽きた!!!
スライム3の攻撃 : 勇者4に27のダメージ
勇者4のHP : 114
勇者3の攻撃 : スライム3に30のダメージ
スライム3のHP : 80
スライム2の攻撃 : 勇者4に26のダメージ
勇者4のHP : 88
勇者1 , HP : 100 勇者2 , HP : 100 勇者3 , HP : 43 勇者4 , HP : 88
スライム1 , HP : 180 スライム2 , HP : 0 スライム3 , HP : 80
スライム1 , HP : 180 スライム2 , HP : 0 スライム3 , HP : 80
勇者3の攻撃 : スライム3に35のダメージ
スライム3のHP : 45
勇者1の攻撃 : スライム3に36のダメージ
スライム3のHP : 9
スライム3の攻撃 : 勇者2に31のダメージ
勇者2のHP : 69
スライム1の攻撃 : 勇者3に28のダメージ
勇者3のHP : 15
勇者2の攻撃 : スライム3に34のダメージ
スライム3のHP : 0
スライム3は力尽きた!!!
勇者4の攻撃 : スライム1に43のダメージ
スライム1のHP : 137
勇者1 , HP : 100 勇者2 , HP : 69 勇者3 , HP : 15 勇者4 , HP : 88
スライム1 , HP : 137 スライム2 , HP : 0 スライム3 , HP : 0
スライム1 , HP : 137 スライム2 , HP : 0 スライム3 , HP : 0
勇者1の攻撃 : スライム1に33のダメージ
スライム1のHP : 104
勇者4の攻撃 : スライム1に41のダメージ
スライム1のHP : 63
勇者2の攻撃 : スライム1に34のダメージ
スライム1のHP : 29
勇者3の攻撃 : スライム1に36のダメージ
スライム1のHP : 0
スライム1は力尽きた!!!
勇者チームチームの勝ち
戦闘終了
見事に勇者チーム勝利wwwwwwww
お互いに殴り合うだけの
単純なシミュレーションです。
ドラクエ2風になったんじゃないかと思います。
そう考えると
ドラクエ3以降は複雑怪奇ですねーー
すぐ作れる気がしないので
この先どうなることやら・・・
今回はここまでです。
それでは。

コメントする