Created
May 22, 2019 14:58
-
-
Save luckytyphlosion/0926e801c551fe30442e42f1d27646e0 to your computer and use it in GitHub Desktop.
Abstract Pokemon Simulator
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import collections | |
import copy | |
import string | |
import random | |
import math | |
# switch by inputting in the mon to switch to | |
# use moves by inputting 1, 2, 3, 4 for each move respectively | |
""" | |
team A: | |
A: hp=140, speed=2 | |
B: hp=120, speed=10 | |
team B: | |
a: hp=180, speed=1 | |
b: hp=260, speed=5 | |
Aa - 100 | |
Ab - 100 | |
Ba - 80 | |
Bb - 60 | |
aA - 100 | |
aB - 80 | |
bA - 50, 90 | |
bB - 60, 50 | |
""" | |
TEAM_1_SIZE = 6 | |
TEAM_2_SIZE = 6 | |
MAX_SPEED = 10 | |
class Team: | |
__slots__ = ("mons", "cur_member") | |
def __init__(self, mons, cur_member): | |
self.mons = mons | |
self.cur_member = cur_member | |
@property | |
def cur_mon(self): | |
return self.mons[self.cur_member] | |
class Member: | |
__slots__ = ("hp", "speed") | |
def __init__(self, hp, speed): | |
self.hp = hp | |
self.speed = speed | |
""" | |
team_a_mons_original = collections.OrderedDict({ | |
"A": Member(hp=140, speed=2), | |
"B": Member(hp=120, speed=10), | |
}) | |
team_b_mons_original = collections.OrderedDict({ | |
"a": Member(hp=180, speed=1), | |
"b": Member(hp=260, speed=5), | |
}) | |
""" | |
# Aa: [60, 10, 100] | |
# Ab: [60, 100, 50] | |
# Ba: [70, 30] | |
# Bb: [70, 90] | |
# aA: [60, 90, 90, 100] | |
# aB: [20, 60, 70, 90] | |
# bA: [50, 30, 20, 70] | |
# bB: [80, 10, 80, 50] | |
def generate_random_teams(): | |
team_1_mons = collections.OrderedDict() | |
team_2_mons = collections.OrderedDict() | |
damages = collections.OrderedDict() | |
for team_1_member in string.ascii_uppercase[:TEAM_1_SIZE]: | |
for team_2_member in string.ascii_lowercase[:TEAM_2_SIZE]: | |
damages[team_1_member + team_2_member] = [] | |
damages[team_2_member + team_1_member] = [] | |
for move_index in range(4): | |
damages[team_1_member + team_2_member].append(random.randint(1, 10) * 10) | |
damages[team_2_member + team_1_member].append(random.randint(1, 10) * 10) | |
team_1_speeds = [] | |
team_2_speeds = [] | |
speeds = set(i for i in range(MAX_SPEED + 1)) | |
if random.randint(1, 2) == 1: | |
first_team_speeds = team_1_speeds | |
second_team_speeds = team_2_speeds | |
first_team_len = TEAM_1_SIZE | |
second_team_len = TEAM_2_SIZE | |
else: | |
first_team_speeds = team_2_speeds | |
second_team_speeds = team_1_speeds | |
first_team_len = TEAM_2_SIZE | |
second_team_len = TEAM_1_SIZE | |
for i in range(first_team_len): | |
speed = random.randint(1, MAX_SPEED) | |
speeds.discard(speed) | |
first_team_speeds.append(speed) | |
speeds = tuple(speeds) | |
for i in range(second_team_len): | |
speed = random.choice(speeds) | |
second_team_speeds.append(speed) | |
for team_1_member in string.ascii_uppercase[:TEAM_1_SIZE]: | |
team_1_speed = team_1_speeds.pop(0) | |
team_1_mons[team_1_member] = Member(hp=random.randint(10, 30) * 10, speed=team_1_speed) | |
for team_2_member in string.ascii_lowercase[:TEAM_2_SIZE]: | |
team_2_speed = team_2_speeds.pop(0) | |
team_2_mons[team_2_member] = Member(hp=random.randint(10, 30) * 10, speed=team_2_speed) | |
return Team(team_1_mons, "A"), Team(team_2_mons, "a"), damages | |
def print_damages(damages): | |
output = "" | |
for matchup, damage_values in damages.items(): | |
output += "%s: %s\n" % (matchup, damage_values) | |
print(output) | |
def print_team(team): | |
output = "cur member: %s\n" % team.cur_member | |
for team_member in team.mons: | |
output += "%s: hp=%s, speed=%s\n" % (team_member, team.mons[team_member].hp, team.mons[team_member].speed) | |
print(output) | |
def print_teams_info(team_1, team_2, damages): | |
print_damages(damages) | |
print("Team 1:") | |
print_team(team_1) | |
print("Team 2:") | |
print_team(team_2) | |
def can_switch(team, member): | |
if not member in team.mons: | |
return False | |
if member == team.cur_member: | |
return False | |
if team.mons[member].hp <= 0: | |
return False | |
return True | |
def decide_opponent_action(team_1, team_2, damages): | |
# greedy | |
damage_list = damages[team_2.cur_member + team_1.cur_member] | |
return "%s" % (damage_list.index(max(damage_list)) + 1) | |
def decide_player_action(team_1, team_2, damages): | |
move_actions = set(("1", "2", "3", "4")) | |
while True: | |
action = input("Choose move or switch: ") | |
if action in team_1.mons and can_switch(team_1, action): | |
return action | |
elif action in move_actions: | |
return action | |
elif action == "m" or action == "max": | |
damage_list = damages[team_1.cur_member + team_2.cur_member] | |
return "%s" % (damage_list.index(max(damage_list)) + 1) | |
else: | |
print("Invalid action!") | |
def get_opponent_switch_in(team_1, team_2, damages): | |
max_damage = 0 | |
max_damage_team_member = None | |
for team_member in team_2.mons: | |
this_max_damage = max(damages[team_member + team_1.cur_member]) | |
if this_max_damage > max_damage: | |
max_damage = this_max_damage | |
max_damage_team_member = team_member | |
return team_member | |
def get_player_switch_in(team_1): | |
while True: | |
action = input("Choose switch: ") | |
if action in team_1.mons and can_switch(team_1, action): | |
return action | |
else: | |
print("Invalid switch!") | |
def remove_cur_mon(team, damages): | |
del team.mons[team.cur_member] | |
new_damages = dict(damages) | |
for matchup, damage_value in damages.items(): | |
if team.cur_member in matchup: | |
del new_damages[matchup] | |
return new_damages | |
def do_attack_switch_matchups(damages, team_a, team_s, team_attacking_name, team_switching_name, team_switching_size): | |
output = "" | |
output += "%s attacks, %s switches:\n" % (team_attacking_name, team_switching_name) | |
output += " | ".join((" ",) + tuple(team_s.mons.keys())) + "\n" | |
output += "===" + ("====" * team_switching_size) + "\n" | |
for team_a_member, team_a_mon in team_a.mons.items(): | |
for damage_index in range(4): | |
output += "%s%s" % (team_a_member, damage_index + 1) | |
for team_s_member, team_s_mon in team_s.mons.items(): | |
team_a_damages = damages[team_a_member + team_s_member] | |
team_a_damage = team_a_damages[damage_index] | |
team_a_best_damage = max(team_a_damages) | |
team_s_best_damage = max(damages[team_s_member + team_a_member]) | |
team_s_mon_hp = team_s_mon.hp - team_a_damage | |
if team_s_mon_hp > 0: | |
team_a_nhko = int(math.ceil(team_s_mon_hp / team_a_best_damage)) | |
team_s_nhko = int(math.ceil(team_a_mon.hp / team_s_best_damage)) | |
team_a_wins = team_a_nhko < team_s_nhko or (team_a_nhko == team_s_nhko and team_a_mon.speed > team_s_mon.speed) | |
winning_member = (team_a_member if team_a_wins else team_s_member) | |
else: | |
winning_member = team_a_member | |
output += " | " + winning_member | |
output += "\n" | |
return output | |
def do_attack_attack_matchups(team_1, team_2, damages): | |
output = "" | |
output += "both teams attack:\n" | |
output += " | ".join((" ",) + tuple(team_2.mons.keys())) + "\n" | |
output += "===" + ("====" * len(team_2.mons)) + "\n" | |
for team_1_member, team_1_mon in team_1.mons.items(): | |
output += team_1_member | |
for team_2_member, team_2_mon in team_2.mons.items(): | |
team_1_best_damage = max(damages[team_1_member + team_2_member]) | |
team_2_best_damage = max(damages[team_2_member + team_1_member]) | |
team_1_nhko = int(math.ceil(team_2_mon.hp / team_1_best_damage)) | |
team_2_nhko = int(math.ceil(team_1_mon.hp / team_2_best_damage)) | |
team_1_wins = team_1_nhko < team_2_nhko or (team_1_nhko == team_2_nhko and team_1_mon.speed > team_2_mon.speed) | |
output += " | " + (team_1_member if team_1_wins else team_2_member) | |
output += "\n" | |
return output | |
def print_matchups_info(team_1, team_2, damages): | |
output = "" | |
output += do_attack_attack_matchups(team_1, team_2, damages) | |
output += "\n" | |
output += do_attack_switch_matchups(damages, team_1, team_2, "team 1", "team 2", len(team_2.mons)) | |
output += "\n" | |
output += do_attack_switch_matchups(damages, team_2, team_1, "team 2", "team 1", len(team_1.mons)) | |
print(output) | |
def do_battle_until_ko(): | |
team_1_original, team_2_original, damages_original = generate_random_teams() | |
while True: | |
damages = dict(damages_original) | |
team_1 = copy.deepcopy(team_1_original) | |
team_2 = copy.deepcopy(team_2_original) | |
while True: | |
print_matchups_info(team_1, team_2, damages) | |
print_teams_info(team_1, team_2, damages) | |
opponent_action = decide_opponent_action(team_1, team_2, damages) | |
player_action = decide_player_action(team_1, team_2, damages) | |
player_switched = False | |
opponent_switched = False | |
if player_action in team_1.mons: | |
team_1.cur_member = player_action | |
player_switched = True | |
if opponent_action in team_2.mons: | |
team_2.cur_member = opponent_action | |
opponent_switched = True | |
if not player_switched: | |
team_1_damage = damages[team_1.cur_member + team_2.cur_member][int(player_action) - 1] | |
if not opponent_switched: | |
team_2_damage = damages[team_2.cur_member + team_1.cur_member][int(opponent_action) - 1] | |
if not player_switched and not opponent_switched: | |
if team_1.cur_mon.speed > team_2.cur_mon.speed: | |
team_2.cur_mon.hp -= team_1_damage | |
if team_2.cur_mon.hp > 0: | |
team_1.cur_mon.hp -= team_2_damage | |
else: | |
team_1.cur_mon.hp -= team_2_damage | |
if team_1.cur_mon.hp > 0: | |
team_2.cur_mon.hp -= team_1_damage | |
else: | |
if not player_switched: | |
team_2.cur_mon.hp -= team_1_damage | |
if not opponent_switched: | |
team_1.cur_mon.hp -= team_2_damage | |
if team_1.cur_mon.hp <= 0: | |
damages = remove_cur_mon(team_1, damages) | |
if len(team_1.mons) == 0: | |
break | |
print_teams_info(team_1, team_2, damages) | |
print(do_attack_attack_matchups(team_1, team_2, damages)) | |
team_1.cur_member = get_player_switch_in(team_1) | |
elif team_2.cur_mon.hp <= 0: | |
damages = remove_cur_mon(team_2, damages) | |
if len(team_2.mons) == 0: | |
break | |
team_2.cur_member = get_opponent_switch_in(team_1, team_2, damages) | |
print_teams_info(team_1, team_2, damages) | |
continue_answer = input("Continue? ") | |
if continue_answer != "yes" and continue_answer != "y": | |
break | |
do_battle_until_ko() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment