Skip to content

Commit

Permalink
Merge pull request #8 from georgelid06/data-storage-&-analysis
Browse files Browse the repository at this point in the history
Data storage & analysis
  • Loading branch information
georgelid06 authored Apr 20, 2023
2 parents f410000 + 8652be4 commit 69e6d87
Show file tree
Hide file tree
Showing 5 changed files with 117 additions and 13 deletions.
3 changes: 3 additions & 0 deletions ai.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import random
from location import Location
import copy


class AIPlayer:
def __init__(self, game, player_number, all_cards):
Expand All @@ -9,6 +11,7 @@ def __init__(self, game, player_number, all_cards):
self.turn_energy_spent = 0
self.energy = 1
self.deck = self.draw_starting_deck(all_cards)
self.starting_deck = copy.deepcopy(self.deck)
self.hand = self.draw_starting_hand(self.deck)
self.played_cards=[]

Expand Down
69 changes: 69 additions & 0 deletions data.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import json
import hashlib

def deck_hash(deck):
deck_str = ''.join(sorted([card.name for card in deck], key=str.lower)) # Sort card names before hashing
return hashlib.sha1(deck_str.encode()).hexdigest()

def update_deck_data(deck, result, total_power, decks_data):
deck_id = deck_hash(deck)

if deck_id in decks_data:
decks_data[deck_id]["total_power"] += total_power
decks_data[deck_id]["games_played"] += 1

if result == "win":
decks_data[deck_id]["wins"] += 1
elif result == "loss":
decks_data[deck_id]["losses"] += 1
else:
decks_data[deck_id] = {
"cards": [card.name for card in deck],
"wins": 1 if result == "win" else 0,
"losses": 1 if result == "loss" else 0,
"total_power": total_power,
"games_played": 1
}

def save_deck_data(decks_data, file_name):
with open(file_name, 'w') as file:
file.write("{\n")
for idx, (key, value) in enumerate(decks_data.items()):
file.write(f'"{key}": {json.dumps(value)}')
if idx < len(decks_data) - 1:
file.write(",\n")
else:
file.write("\n")
file.write("}")

def load_deck_data(file_name):
try:
with open(file_name, 'r') as file:
return json.load(file)
except FileNotFoundError:
# If the file doesn't exist, create it with an empty dictionary and return it
with open(file_name, 'w') as file:
json.dump({}, file)
return {}


def get_average_power(deck_id, decks_data):
total_power = decks_data[deck_id]["total_power"]
games_played = decks_data[deck_id]["games_played"]
return total_power / games_played

def winrate(decks_data):
return decks_data["wins"] / (decks_data["wins"] + decks_data["losses"])

def printwinrate(decks_data):
ranked_decks = sorted(decks_data.items(), key=lambda x: winrate(x[1]), reverse=True)

for idx, (deck_id, deck_data) in enumerate(ranked_decks, 1):
print(f"{idx}. Deck ID: {deck_id}")
print(f" Winrate: {winrate(deck_data) * 100:.2f}%")
print(f" Wins: {deck_data['wins']}")
print(f" Losses: {deck_data['losses']}")
print(f" Total Power: {deck_data['total_power']}")
print(f" Average Power: {deck_data['total_power'] / deck_data['games_played']}")
print(f" Games Played: {deck_data['games_played']}")
print()
15 changes: 15 additions & 0 deletions decks_data.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"e5fca0112973e69bc7402bd7319c53d88aa5f755": {"cards": ["Sentinel", "The Punisher", "Abomination", "Shocker", "Hulk", "The Thing", "Cyclops", "Iron Man", "Hawkeye", "Misty Knight", "Quicksilver", "Star Lord"], "wins": 125, "losses": 134, "total_power": 5411, "games_played": 259},
"f9a7f666b90e4974008ef32b4974442cb776504b": {"cards": ["Hulk", "Sentinel", "Iron Man", "Medusa", "Misty Knight", "Cyclops", "Star Lord", "Quicksilver", "Hawkeye", "Abomination", "Shocker", "The Punisher"], "wins": 121, "losses": 146, "total_power": 5406, "games_played": 267},
"eb39800df6a0b9faa278eb5b3adbc2576f641c76": {"cards": ["Hulk", "The Punisher", "Misty Knight", "Medusa", "Star Lord", "Iron Man", "The Thing", "Abomination", "Hawkeye", "Sentinel", "Quicksilver", "Cyclops"], "wins": 147, "losses": 144, "total_power": 6176, "games_played": 291},
"e8a2b0720bd929be139dd82d7878f72a3d803dee": {"cards": ["Sentinel", "Quicksilver", "Shocker", "Iron Man", "The Punisher", "Cyclops", "Hawkeye", "The Thing", "Hulk", "Medusa", "Misty Knight", "Abomination"], "wins": 134, "losses": 122, "total_power": 5543, "games_played": 256},
"bf4e2ce13ddbe0a52f9e06f91a534c102050ea3b": {"cards": ["Hawkeye", "Misty Knight", "Cyclops", "Abomination", "The Thing", "Medusa", "Hulk", "Iron Man", "Sentinel", "Star Lord", "Quicksilver", "Shocker"], "wins": 150, "losses": 164, "total_power": 6560, "games_played": 314},
"a4fd260d8d291f5683c167f00f8b873106172e75": {"cards": ["Hulk", "Cyclops", "Sentinel", "Quicksilver", "Iron Man", "The Thing", "Medusa", "Abomination", "The Punisher", "Star Lord", "Shocker", "Hawkeye"], "wins": 134, "losses": 136, "total_power": 5777, "games_played": 270},
"07b58e21fdf36c0a0d0c66e63b2810137a8d04b3": {"cards": ["Medusa", "Star Lord", "Hawkeye", "Misty Knight", "The Punisher", "Sentinel", "Abomination", "Hulk", "Shocker", "Cyclops", "The Thing", "Quicksilver"], "wins": 108, "losses": 122, "total_power": 4804, "games_played": 230},
"8547382b7d2056f64b68181f50405770729f0031": {"cards": ["Sentinel", "The Punisher", "Misty Knight", "Medusa", "Quicksilver", "Star Lord", "Shocker", "Hawkeye", "The Thing", "Cyclops", "Hulk", "Iron Man"], "wins": 126, "losses": 145, "total_power": 5246, "games_played": 271},
"ec3360ef2a55f6f3bb6103121352232a96fa569d": {"cards": ["Cyclops", "Shocker", "Quicksilver", "Sentinel", "Abomination", "Hawkeye", "The Thing", "Misty Knight", "The Punisher", "Medusa", "Star Lord", "Iron Man"], "wins": 131, "losses": 126, "total_power": 5089, "games_played": 257},
"36318860d633a9605ac4e3abe0212196c06607f2": {"cards": ["Medusa", "Hulk", "Iron Man", "Star Lord", "Cyclops", "Misty Knight", "The Thing", "Hawkeye", "The Punisher", "Shocker", "Sentinel", "Abomination"], "wins": 141, "losses": 109, "total_power": 5380, "games_played": 250},
"a57f3fdb8fe85a4cfa0b56c0b523f904a3de0af6": {"cards": ["Abomination", "Hulk", "Hawkeye", "Sentinel", "The Punisher", "Medusa", "The Thing", "Iron Man", "Quicksilver", "Star Lord", "Shocker", "Misty Knight"], "wins": 128, "losses": 133, "total_power": 5437, "games_played": 261},
"07ff7fd3924cf934a185dad837619352f3aa76c9": {"cards": ["Star Lord", "Abomination", "Quicksilver", "Hulk", "Shocker", "Iron Man", "The Thing", "Misty Knight", "Cyclops", "Sentinel", "The Punisher", "Medusa"], "wins": 144, "losses": 117, "total_power": 5705, "games_played": 261},
"b2371c11552e25f46eb59f5192a7a643e254aee5": {"cards": ["Medusa", "Quicksilver", "Shocker", "Hawkeye", "Cyclops", "The Thing", "The Punisher", "Misty Knight", "Star Lord", "Iron Man", "Hulk", "Abomination"], "wins": 155, "losses": 146, "total_power": 6526, "games_played": 301}
}
35 changes: 24 additions & 11 deletions game.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
from card import Card, generate_all_cards
from location import Location, generate_all_locations
from ai import AIPlayer

from data import update_deck_data, save_deck_data, load_deck_data, get_average_power
import json

class Game:
def __init__(self):
Expand All @@ -15,6 +16,7 @@ def __init__(self):
self.current_turn = 0
self.current_location = 0
self.prepare_game()
self.winner=2

def play_card(self, card, player_number, location_number):
player = self.players[player_number - 1]
Expand All @@ -26,7 +28,7 @@ def play_card(self, card, player_number, location_number):

# Ensuring the location does not already have 4 cards from the player.
if sum(1 for card in location.cards if card.owner == player_number - 1) >= 4:
print(f"Player {player_number} cannot play {card.name} at this location. It already has 4 cards from the player.")
#print(f"Player {player_number} cannot play {card.name} at this location. It already has 4 cards from the player.")
return

if card.energy_cost <= player.energy:
Expand Down Expand Up @@ -56,7 +58,8 @@ def play_card(self, card, player_number, location_number):
hawkeye_card.power += 2 # Apply the effect
hawkeye_card.hawkeye_effect_applied = True # Set the flag after applying the effect
else:
print(f"Player {player_number} cannot play {card.name} yet. It costs more energy than the current turn.")
#print(f"Player {player_number} cannot play {card.name} yet. It costs more energy than the current turn.")
return

def reveal_location(self):
if self.current_location >= len(self.locations):
Expand Down Expand Up @@ -90,7 +93,7 @@ def play_turn(self):
player.played_cards.append(card)
player.played_card_locations.append(location_index)
else:
print(f"Player {player_number} cannot play {card.name} yet. It costs more energy than the current turn.")
#print(f"Player {player_number} cannot play {card.name} yet. It costs more energy than the current turn.")
break
else:
break
Expand Down Expand Up @@ -134,7 +137,7 @@ def reveal_cards(self, player_number):
# Update the location card's power value as well
if location_card is not None:
location_card.power = card.power # Update the power of the card in location.cards
print("Card: ", card.name, "Has increased from ", card.base_power, "to ", card.power)
#print("Card: ", card.name, "Has increased from ", card.base_power, "to ", card.power)

def apply_ongoing_abilities(self):
for player_number in range(1, 3):
Expand Down Expand Up @@ -228,8 +231,8 @@ def display_game_state(self):
def determine_winner(self):
player1_score = sum(location.calculate_total_power(0) for location in self.locations)
player2_score = sum(location.calculate_total_power(1) for location in self.locations)
print("Player 1 had a total power of:", player1_score)
print("Player 2 had a total power of:", player2_score)
#print("Player 1 had a total power of:", player1_score)
#print("Player 2 had a total power of:", player2_score)
player1_wins = 0
player2_wins = 0
for location in self.locations:
Expand All @@ -238,20 +241,30 @@ def determine_winner(self):
elif location.calculate_total_power(0) < location.calculate_total_power(1):
player2_wins += 1

decks_data = load_deck_data('decks_data.json')
if player1_wins > player2_wins:
print("Player 1 Wins!")
#print("Player 1 Wins!")
update_deck_data(self.players[0].starting_deck, "win", player1_score, decks_data)
update_deck_data(self.players[1].starting_deck, "loss", player2_score, decks_data)

elif player1_wins < player2_wins:
print("Player 2 Wins!")
#print("Player 2 Wins!")
update_deck_data(self.players[0].starting_deck, "loss", player1_score, decks_data)
update_deck_data(self.players[1].starting_deck, "win", player2_score, decks_data)

save_deck_data(decks_data, 'decks_data.json')


def play_game(self):
for turn in range(6): # Loop through the 6 turns
self.current_turn = turn + 1
print(f"Turn {self.current_turn}")
#print(f"Turn {self.current_turn}")
if 4 > self.current_turn > 1:
self.reveal_location()
self.play_turn()
self.apply_ongoing_abilities()
self.end_of_turn()
self.display_game_state()
#self.display_game_state()

self.determine_winner()

8 changes: 6 additions & 2 deletions main.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
from card import generate_all_cards
from location import generate_all_locations
from game import Game
from data import load_deck_data, printwinrate

all_cards = generate_all_cards()
all_locations = generate_all_locations()
for i in range (1,20):
for i in range (1,1):
game = Game()
game.play_game()
game.play_game()

decks_data = load_deck_data('decks_data.json')
printwinrate(decks_data)

0 comments on commit 69e6d87

Please sign in to comment.