Skip to content

Instantly share code, notes, and snippets.

@luckytyphlosion
Created May 22, 2019 14:58
Show Gist options
  • Save luckytyphlosion/0926e801c551fe30442e42f1d27646e0 to your computer and use it in GitHub Desktop.
Save luckytyphlosion/0926e801c551fe30442e42f1d27646e0 to your computer and use it in GitHub Desktop.
Abstract Pokemon Simulator
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