60fps and updating list. What to do? - python

I want to append a score to my "last_Score" list at the end of the game but it adds 60 items per second. I only want to have one item per game_over. Any ideas?
def __init__(self, **kwargs):
super(Game, self).__init__(**kwargs)
self.start_sound.play()
self.init_vertical_line()
self.init_horizontal_line()
self.init_quad()
self.init_hero()
self.start_quads()
self.quad_generation()
if self.is_desktop():
self.keyboard = Window.request_keyboard(self.keyboard_hidden, self)
self.keyboard.bind(on_key_down=self.on_keyboard_down)
self.keyboard.bind(on_key_up=self.on_keyboard_up)
Clock.schedule_interval(self.update, 1/60)
def update(self, dt):
time_factor = dt*60
self.update_vertical_lines()
self.update_horizontal_line()
self.quad_update()
self.quad_generation()
self.update_hero()
self.score_board()
def score_board(self):
if self.game_over:
self.end_score = self.score
self.last_Score.append((self.end_score))
if len(self.last_Score) > 10:
del self.last_Score[:-2]
print(self.last_Score)

I did it! My code down here.
def score_board(self):
if self.game_over:
self.end_score = self.score
self.last_Score.append((self.end_score))
if len(self.last_Score) > self.game_number:
del self.last_Score[-1]
try:
self.last_Score_Label = "Your last score is" + str(self.last_Score[-2])
except:
self.last_Score_Label = "Your last score is " + str(self.last_Score[-1])
print(self.last_Score)

A heavy-handed way to ensure score_board is only executed once:
Set self.update_score = True in __init__.
Redefine score_board as
def score_board(self):
if self.game_over:
self.update_score = False
self.end_score = self.score
self.last_Score.append((self.end_score))
if len(self.last_Score) > 10:
del self.last_Score[:-2]
print(self.last_Score)
Reset self.update_score = True when appropriate (when the game restarts?).

Related

how's i can calling to int from def in class?

i have this code:
class PLAYER:
def player_move(self):
if self.new_block == True:
body_copy = self.body[:]
body_copy.insert(0,body_copy[0] + self.direction)
self.body = body_copy[:]
self.new_block = False
self.score += 1
#print(self.score)
i want to calling self.score from outside the PLAYER class
You need to add a constructor (the init method) as done below, and within the constructor you must define self.score, as well as all the other fields you want your PLAYER class to have. In the code below I am assuming that when you are initializing a PLAYER object that you are providing the new_block, direction, and body information, however you defined these fields, which is unclear from the question.
class PLAYER:
def __init__(self, new_block,direction,body):
self.score = 0
self.new_block = new_block
self.direction = direction
self.body = body
def player_move(self):
if self.new_block == True:
body_copy = self.body[:]
body_copy.insert(0,body_copy[0] + self.direction)
self.body = body_copy[:]
self.new_block = False
self.score += 1

How to alter a variable defined in a parent class in the child class without altering the parent class variable itself?

I'm trying to create two subclasses based on the same parent class, so that they each have their own versions of the same variables defined in the parent object. However I realized that changing these variables in one of these subclasses will cause the versions in the other subclass to change as well. I know I am probably not fully understanding the idea of Inheritance. Please help!
import random
class PlayerParent():
id = 1
# Cooperate: True; Betrayal: False
opponent_moves_history = {}
self_moves_history = {}
def append_opponent_history(self, round_num, c_true, misunderstand=0.0):
# randomly change the result based on probability given in misunderstand
random_num = random.uniform(0, 1)
if random_num <= misunderstand:
c_true = not c_true
self.opponent_moves_history[round_num] = c_true
def append_self_history(self, round_num, c_true, misunderstand=0.0):
# randomly change the result based on probability given in misunderstand
random_num = random.uniform(0, 1)
if random_num <= misunderstand:
c_true = not c_true
self.self_moves_history[round_num] = c_true
score = int(0)
def score_keeper(self, round_num):
if (self.opponent_moves_history[round_num] == True) and (self.self_moves_history[round_num] == False):
self.score += 7
if (self.opponent_moves_history[round_num] == True) and (self.self_moves_history[round_num] == True):
self.score += 5
if (self.opponent_moves_history[round_num] == False) and (self.self_moves_history[round_num] == True):
self.score += 1
if (self.opponent_moves_history[round_num] == False) and (self.self_moves_history[round_num] == False):
self.score += 2
def get_score(self):
return self.score
class TitForTat(PlayerParent):
def rule(self, round_num):
if len(self.opponent_moves_history) == 0:
return True
else:
return self.opponent_moves_history[round_num - 1]
class Random(PlayerParent):
def rule(self, round_num):
random_num = random.uniform(0, 1)
if random_num >= 0.5:
return True
else:
return False
Random = Random()
Random.id = 1
TitForTat = TitForTat()
TitForTat.id = 2
def match(a, b):
game_counter = 1
# while game_counter <= 10:
#a_result = a.rule(game_counter)
# b_result = b.rule(game_counter)
# print(a_result, b_result)
# a.append_self_history(game_counter, a_result)
# b.append_opponent_history(game_counter, a_result)
# b.append_self_history(game_counter, b_result)
# a.append_opponent_history(game_counter, b_result)
# a.score_keeper(game_counter)
# b.score_keeper(game_counter)
# game_counter += 1
# print(a.get_score(), b.get_score())
a.self_moves_history[1] = True
print(a.self_moves_history, '\n', b.self_moves_history)
match(Random, TitForTat)
Resulting a.self_moves_history and b.self_moves_history is identical even though no alteration has been done to the b class variable.
I commented out chunks of the codes just to test where went wrong.
You are making opponent_moves_history a class variable, so naturally any change to it is class-wide.
In your case you should make opponent_moves_history, along with self_moves_history and id instance variables instead, so that changes made to them are specific to the instances.
class PlayerParent():
def __init__(self):
self.id = 1
self.opponent_moves_history = {}
self.self_moves_history = {}

Initializing Class instance within a class

the entire counter list of methods in side counter class do not work. I want setcap to set of cap, and check cap to see if each counter have reached their limit as hr min sec are what a clock should know i would like to initialize them inside the clock.
import time
class counter():
count = 0
cap = 0
def _init_(self):pass
def reset(self):
self.count = 0
def increment(self):
self.count += 1
def setcap(self,x):
print x
self.cap = x
def checkcap(self):
if self.cap > self.count:
return False
else:
return True
class clock():
_hr = counter()
_min = counter()
_sec = counter()
def _init_(self):
self._hr.setcap(23)
self._min.setcap(59)
self._sec.setcap(59)
def manualreset(self):
self._hr.reset()
self._min.reset()
self_sec.reset()
def tick(self):
if self._sec.checkcap():
self._sec.reset()
self._min.increment()
if self._min.checkcap():
self._min.reset()
self._hr.increment()
if self._hr.checkcap():
self._hr.reset()
else:
self._sec.increment()
newClock = clock()
raw_input("Press enter to start clock")
while newClock._hr != 24:
newClock.tick()
print str(newClock._hr.count).zfill(2) + str(newClock._min.count).zfill(2) + str(newClock._sec.count).zfill(2)
One of the problems in your code is that your init functions are init.
Try using
def __init__(self):
pass
This should solve one of your problems

Ping Pong simulation not correctly triggering function

I'm new to OOP and am practicing putting together a little bit more complex programs using various classes and implementing principles like Inheritance. I've created a Ping-Pong simulation that has a Player class which contains the probability that the player will win their serve. Then I have a PingPong class which is a subclass of the super class RacquetSports. Each instance is a single game, with the ability to change server, and record who won, and whether or not it was a shut-out. Finally, I have a SimStats class whose purpose is to record the stats across "n" number of games.
My problem is that it seems like my play_game function is not correctly firing, when I place a print statement in there it never triggers. My current result when running the whole program is that Player1 has 10 wins no shutouts, and Player2 has zero of both.
Finally, any suggestions on better OO practice would also be appreciated. Here is my player class:
from random import random
class Player(object):
def __init__(self, prob_win):
self.prob = prob_win
self.points = 0
def wins_serve(self):
return self.prob >= random()
def add_point(self):
self.points += 1
def get_score(self):
return self.points
My RacquetSports class:
from abc import ABCMeta, abstractmethod
from player import Player
class RacquetSport(object):
__metaclass__ = ABCMeta
def __init__(self, prob1, prob2):
self.player1 = Player(prob1)
self.player2 = Player(prob2)
self.server = self.player1
def play_game(self):
while not self.game_over():
self.sim_point()
#abstractmethod
def type(self):
pass
def chg_server(self):
if self.server == self.player1:
self.server = self.player2
else:
self.server = self.player1
def sim_point(self):
if self.server.wins_serve():
self.server.add_point()
else:
self.chg_server()
#abstractmethod
def game_over(self):
pass
def get_scores(self):
return self.player1.get_score(), \
self.player2.get_score()
def return_stats(self):
p1_score, p2_score = self.get_scores()
print(p1_score, p2_score)
won = 'p1'
if p2_score > p1_score:
won = 'p2'
return won, self.__shutout(p1_score, p2_score)
#staticmethod
#abstractmethod
def __shutout(score1, score2):
pass
My PingPong and SimStats classes, as well as my calling code:
from racquet import RacquetSport
class PingPong(RacquetSport):
def type(self):
return 'Ping Pong'
def game_over(self):
return self.player1.get_score == 11 or \
self.player2.get_score == 11
#staticmethod
def __shutout(score1, score2):
return abs(score1 - score2) == 11
class SimStats(object):
def __init__(self):
# First field is games won, second is shutouts.
self.gms_won_p1 = [0] * 2
self.gms_won_p2 = [0] * 2
def update(self, game):
won, shutout = game.return_stats()
if won == 'p1':
self.gms_won_p1[0] += 1
if shutout:
self.gms_won_p1[1] += 1
else:
self.gms_won_p2[0] += 1
if shutout:
self.gms_won_p2[1] += 1
def print_results(self):
tot_games = self.gms_won_p1 + self.gms_won_p2
print('Wins for Player 1 = {} Shutouts = {}\n'
'Wins for Player 2 = {} Shutouts = {}'.format(*tot_games))
if __name__ == '__main__':
stats = SimStats()
for x in range(1, 11):
game = PingPong(.5, .5)
stats.update(game)
stats.print_results()
Your first problem is that you never call play_game. My guess is that you intend it to work like this:
if __name__ == '__main__':
stats = SimStats()
for x in range(1, 11):
game = PingPong(.5, .5)
game.play_game()
stats.update(game)
stats.print_results()
Next, you have a bug that will cause the entire game to last forever. Take a look at these lines:
def game_over(self):
return self.player1.get_score == 11 or \
self.player2.get_score == 11
get_score is a function, so you need to call it:
def game_over(self):
return self.player1.get_score() == 11 or \
self.player2.get_score() == 11

Simpy: don't understand why my simulation never ends

I'm trying to simulate a game of Counter Strike. Basically I have two teams with different players (all the players are identical for now) and I want them to "fight" and when all the players on one team are dead, the simulation should end.
I'm trying to understand why the simulation I'm running never ends. I feel like I'm misunderstanding some core element of simpy but I don't really know what.
All of the process and simpy related code are in main.py and player.py.
I'm trying to get my simulation to end once every player has "died".
Basically I want every player to be a process that constantly checks their surrounding area (the node they are in which is represented by the Hotspot class) to see if there are any enemies. If there are any enemies they will choose one at random and "attack" them. Once all of the players from any team have health below 0 the simulation should end and the team that won should increment their win count by 1.
EDIT: Also of note, when I ran it through pdb it seemed like none of the player's health were decreasing and that the play method wasn't being run.
EDIT 2: I don't think all of the code needs to be read to find the problem, I think it's mostly in the main and player files but I'm not 100% sure because the code loops infinitely without error
Here is my code
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()
sides.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__
requirements.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
Your round() function is the culprit:
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()
The function contains an infinite loop without any yields. This means it never returns and env.run() isn’t even executed.
I have a feeling this might be an infinite loop:
while(self.is_alive):
target = self.choose_target()
if target == -1:
continue
yield env.timeout(5)
You probably want to yield before the continue (which is unneeded anyway).

Categories

Resources