Counter Strike のゲームをシミュレートしようとしています。基本的に、私は異なるプレイヤーを持つ 2 つのチームを持っており (今のところすべてのプレイヤーは同一です)、それらを「戦わせ」、1 つのチームのすべてのプレイヤーが死んだらシミュレーションを終了する必要があります。
実行中のシミュレーションが終わらない理由を理解しようとしています。simpy のコア要素を誤解しているように感じますが、実際には何がわかりません。
すべてのプロセスと simpy 関連のコードは、main.py と player.py にあります。すべてのプレイヤーが「死亡」したら、シミュレーションを終了させようとしています。
基本的に、私はすべてのプレイヤーが周囲の領域 (Hotspot クラスによって表されるノード) を常にチェックして、敵がいるかどうかを確認するプロセスであることを望んでいます。敵がいる場合、敵はランダムに 1 つを選択して「攻撃」します。いずれかのチームのすべてのプレイヤーのヘルスが 0 未満になると、シミュレーションが終了し、勝ったチームの勝数が 1 増えます。
編集: また、pdb で実行したところ、プレイヤーのヘルスが減少しているようには見えず、play メソッドが実行されていないようでした。
編集 2: 問題を見つけるためにすべてのコードを読む必要はないと思います。主にメイン ファイルとプレーヤー ファイルにあると思いますが、コードがエラーなしで無限にループするため、100% 確信が持てません。
これが私のコードです
main.py
from player import Player
from game_map import Game_Map
from team import Team
from sides import Sides
import simpy
import pdb
def main():
team_a = Team("Team_A", Sides.CT)
team_b = Team("Team_B", Sides.T)
gmap = Game_Map()
gmap.spawn_team(team_a)
gmap.spawn_team(team_b)
env = simpy.Environment()
for team in (team_a, team_b):
for player in team.players:
env.process(player.play(env))
env.run(until=round(team_a, team_b, env))
def round(team_a, team_b, env):
while True:
if team_a.all_dead():
team_b.round_wins += 1
print team_b
env.exit()
if team_b.all_dead():
team_a.round_wins += 1
print team_a
env.exit()
if __name__ == "__main__":
main()
player.py
import simpy
from sides import Sides
import numpy as np
import pdb
class Player(object):
""" Class that represents a CSGO player"""
def __init__(self, steam_id, team, acc, hs_percentage):
# the player's id
self.steam_id = steam_id
# percentage of shots that hit, accuracy
self.acc = acc
# percentage of hits that hit the head
self.hs_percentage = hs_percentage
# the team
self.team = team
# the player's health, this changes when the teams "fight"
self.health = 100
# the current hotspot that the player is in
self.current_location = 0
# if the player is alive or dead
self.is_alive = True
def play(self, env):
"""Process that simulates the player's actions. This is run once every round until
the round is over"""
while(self.is_alive):
target = self.choose_target()
if target == -1:
continue
yield env.timeout(5)
else:
target.inflict_self(self.determine_damage())
yield env.timeout(5)
def determine_damage(self):
"""The amount of damage the player will inflict on the enemy"""
return 27
def choose_target(self):
"""Choose a target to attack from the enemies in the hotspot"""
# 1 - side converts 0 to 1 and 1 to 0
enemy_list = self.current_location.players[1 - self.team.side]
num_enemies = len(enemy_list)
# if there are no enemies currently in the same location of the player
# simply return 0
if num_enemies == 0:
return -1
# pick an enemy randomly from the list of enemies and return their object
return enemy_list[np.random.random_integers(0, num_enemies - 1)]
def get_side(self):
return self.team.side
def inflict_self(self, damage):
"""Inflict damage onto own class. If damage moves health below 0, mark the
player as "Dead" and remove them from the map"""
self.health = self.health - damage
if self.health <= 0:
self.current_location.players[self.team.side].remove(self)
self.is_alive = False
def __str__(self):
return "Steam id: {0}\tIs Alive: {1}\tCurrent Location: {2}".format(self.steam_id, self.is_alive, self.current_location)
def tests():
return
if __name__ == "__main__":
tests()
game_map.py
import networkx as nx
from hotspot import Hotspot
import matplotlib.pyplot as plt
class Game_Map(object):
""" Generic map that represents general outline of all counter strike maps"""
def __init__(self):
self.graph = nx.Graph()
self.spawns = [Hotspot()]
self.graph.add_node(self.spawns[0])
def add_team(team):
#side = team.side
# side is 0 because for testing the simulation
# we are only using one node
side = 0
for player in team.players:
self.spawns[side].move_into(player)
def spawn_team(self, team):
for player in team.players:
self.spawns[0].move_into(player)
def draw(self):
nx.draw(self.graph)
plt.show()
def tests():
"""Tests to see that Game_Map class works properly"""
# initialize the map
gmap = Game_Map()
gmap.draw()
# if this module is being run explicitly from the command line
# run tests to assure that this module is working properly
if __name__ == "__main__":
tests()
hotspot.py
import simpy
from player import Player
from team import Team
from sides import Sides
class Hotspot(object):
"""Hotspots are the representation for different areas of the map. This is where players 'fight'."""
def __init__(self):
self.players = [[], []]
def move_into(self, player):
side = player.get_side()
self.players[side].append(player)
player.current_location = self
return 1
def __eq__(self, other):
return id(self) == id(other)
def __hash__(self):
return id(self)
def tests():
"""Tests to see that hotspot works properly"""
hotspot_list = []
for i in range(5):
hotspot_list.append(Hotspot())
for spot in hotspot_list:
team_a = Team("team_a", Sides.CT)
team_b = Team("team_b", Sides.T)
spot.move_into(Player(1, team_a, .5, .5))
spot.move_into(Player(1, team_b, .5, .5))
print "Hotspot id = {0}".format(id(spot))
for team in spot.players:
for player in team:
print "player = {0} in team {1}".format(player, player.team)
if __name__ == "__main__":
tests()
側面.py
class Sides(object):
"""Enum object, simply represents CT (Counter Terrorists) as 0 and
T (Terrorists) as 1"""
CT, T = range(2)
team.py
from player import Player
class Team(object):
"""Class that holds critical team information"""
def __init__(self, name, side):
self.round_wins = 0
self.players = []
self.name = name
self.side = side
self.generate_team()
def all_dead(self):
count = 0
for player in self.players:
if player.is_alive == False:
count += 1
if count == 5:
return True
else:
return False
def __str__(self):
rep = "Team: {0}, Round Wins: {1}\n".format(self.name, self.round_wins)
for player in self.players:
rep += player.__str__() + '\n'
return rep
def generate_team(self):
for i in range(5):
self.players.append(Player(1, self, .5, .2))
__rep__ = __str__
要件.txt
decorator==3.4.2
matplotlib==1.4.3
mock==1.0.1
networkx==1.9.1
nose==1.3.6
numpy==1.9.2
pyparsing==2.0.3
python-dateutil==2.4.2
pytz==2015.2
scipy==0.15.1
simpy==3.0.7
six==1.9.0