# Glitch City Laboratories Archives

Glitch City Laboratories closed on 1 September 2020 (announcement). This is an archived copy of a thread from Glitch City Laboratories Forums.

You can join Glitch City Research Institute to ask questions or discuss current developments.

You may also download the archive of this forum in .tar.gz, .sql.gz, or .sqlite.gz formats.

## Programming/Scripting/Development/Web Design

### Pokemon Battle Simulator (WIP) - Page 1

Previous Page

- 1

Next Page

#### Pokemon Battle Simulator (WIP)

Posted by: OldNewComputers
Date: 2019-11-07 19:17:24
As a programming project, I'm writing a Pokemon battle simulator in Python. It still lacks status conditions and most move effects (I am using the pret disassembly and some data extraction tools I wrote to get most of this info, plus some diagrams on Bulbapedia), but I wanted your guys opinion on the code. Keep in mind that, to run it, you need a Pokemon Red/Blue ROM with the name "pokeblue.gb" in the same directory as this file, and I wanted the opinion of you guys on the code. I'm not sure if I'm targeting bug compatibility with anything (including Stadium or RB/Y), but I am targeting Generation 1 functionality. Beware that it is pretty long, and liable only to get longer. Most of the code is in the "mainBattle" function, but that calls several utility functions, and several other functions serve to datamine or create monsters for use in the game. Summary printing works too.
`#pokemon battle simulator - gen 1
import random
import math
file = open('pokeblue.gb','rb')
file_contents = file.read()
file.close()
typeMatchups = {0: {5: 0.5, 8: 0.0}, 1: {0: 2.0, 3: 0.5, 2: 0.5, 24: 0.5, 7: 0.5, 5: 2.0, 25: 2.0, 8: 0.0}, 2: {23: 0.5, 1: 2.0, 7: 2.0, 22: 2.0, 5: 0.5}, 3: {22: 2.0, 3: 0.5, 4: 0.5, 7: 2.0, 5: 0.5, 8: 0.5}, 4: {2: 0.0, 20: 2.0, 23: 2.0, 22: 0.5, 7: 0.5, 5: 2.0, 3: 2.0}, 5: {20: 2.0, 1: 0.5, 4: 0.5, 2: 2.0, 7: 2.0, 25: 2.0}, 6: {}, 7: {20: 0.5, 22: 2.0, 1: 0.5, 2: 0.5, 24: 2.0, 8: 0.5, 3: 2.0}, 8: {8: 2.0, 0: 0.0, 24: 0.0}, 9: {}, 10: {}, 11: {}, 12: {}, 13: {}, 14: {}, 15: {}, 16: {}, 17: {}, 18: {}, 19: {}, 20: {22: 2.0, 25: 2.0, 20: 0.5, 21: 0.5, 7: 2.0, 5: 0.5, 26: 0.5}, 21: {20: 2.0, 5: 2.0, 21: 0.5, 22: 0.5, 4: 2.0, 26: 0.5}, 22: {21: 2.0, 22: 0.5, 20: 0.5, 4: 2.0, 7: 0.5, 3: 0.5, 5: 2.0, 2: 0.5, 26: 0.5}, 23: {21: 2.0, 23: 0.5, 22: 0.5, 4: 0.0, 2: 2.0, 26: 0.5}, 24: {24: 0.5, 1: 2.0, 3: 2.0}, 25: {25: 0.5, 21: 0.5, 22: 2.0, 4: 2.0, 2: 2.0, 26: 2.0}, 26: {26: 2.0}}
typeNames = {0: 'NORMAL', 1: "FIGHTING", 2: "FLYING", 3: "POISON", 4: 'GROUND',
5: "ROCK", 6: "BIRD", 7: "BUG", 8: "GHOST", 0x14: "FIRE",
0x15: 'WATER', 0x16: "GRASS", 0x17: 'ELECTRIC', 0x18: "PSYCHIC",
0x19: 'ICE', 0x1A: 'DRAGON'}
volatileStatus0 = [0]*8 #confusion, recharge, wrap, leechseed, flinch
volatileStatus1 = [0]*8
statChanges0 = [0, 0, 0, 0, 0, 0] #attack, defense, speed, special, accuracy, evasion
statChanges1 = [0, 0, 0, 0, 0, 0]
statChangeList = {-6: 0.25, -5: 0.28, -4: 1/3, -3: 0.4, -2: 0.5, -1: 2/3, 0: 1,
1: 1.5, 2: 2, 3: 2.5, 4: 3, 5: 3.5, 6: 4}
indexToDex = []
dexToIndex = [112, 115, 32, 35, 21, 100, 34, 80, 2, 103, 108, 102, 88, 94, 29, 31, 104, 111, 131, 59, 151, 130, 90, 72, 92, 123, 120, 9, 127, 114, 0, 0, 58, 95, 22, 16, 79, 64, 75, 113, 67, 122, 106, 107, 24, 47, 54, 96, 76, 0, 126, 0, 125, 82, 109, 0, 56, 86, 50, 128, 0, 0, 0, 83, 48, 149, 0, 0, 0, 84, 60, 124, 146, 144, 145, 132, 52, 98, 0, 0, 0, 37, 38, 25, 26, 0, 0, 147, 148, 140, 141, 116, 117, 0, 0, 27, 28, 138, 139, 39, 40, 133, 136, 135, 134, 66, 41, 23, 46, 61, 62, 13, 14, 15, 0, 85, 57, 51, 49, 87, 0, 0, 10, 11, 12, 68, 0, 55, 97, 42, 150, 143, 129, 0, 0, 89, 0, 99, 91, 0, 101, 36, 110, 53, 105, 0, 93, 63, 65, 17, 18, 121, 1, 3, 73, 0, 118, 119, 0, 0, 0, 0, 77, 78, 19, 20, 33, 30, 74, 137, 142, 0, 81, 0, 0, 4, 7, 5, 8, 6, 0, 0, 0, 0, 43, 44, 45, 69, 70, 71]###
a = [21, 54, 1, 100, 0, 24, 24, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 0, 0, 0, 0, 54, 1, 205, 0, 205, 0, 205, 0, 205, 0]
b = [126, 34, 1, 100, 0, 1, 1, 0, 1, 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 0, 0, 0, 0, 34, 1, 9, 1, 165, 0, 115, 0, 135, 0]
c = [21, 147, 1, 100, 0, 24, 24, 0, 94, 1, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 35, 0, 0, 0, 147, 1, 42, 1, 42, 1, 42, 1, 42, 1]
#10 35
player_old = [c,b,a]
enemy_old = ['ROCKET',[a,b]]
currentPkmn = 0
currentEMon = 0
pidgeot_gary = [151, 228, 0, 61, 0, 0, 2, 0, 17, 119, 143, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 20, 5, 20, 0, 228, 0, 159, 0, 153, 0, 172, 0, 147, 0]
alakazam_gary = [149, 188, 0, 59, 0, 24, 24, 0, 60, 94, 115, 105, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 10, 20, 20, 0, 188, 0, 118, 0, 112, 0, 201, 0, 219, 0]
rhydon_gary = [1, 255, 0, 61, 0, 4, 5, 0, 43, 39, 31, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 30, 20, 5, 0, 255, 0, 220, 0, 208, 0, 110, 0, 116, 0]
arcanine_gary = [20, 237, 0, 61, 0, 20, 20, 0, 46, 43, 52, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 30, 25, 20, 0, 237, 0, 195, 0, 159, 0, 177, 0, 159, 0]
exeggutor_gary = [10, 251, 0, 63, 0, 22, 24, 0, 95, 140, 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 20, 20, 0, 0, 251, 0, 183, 0, 170, 0, 132, 0, 221, 0]
blastoise_gary = [28, 238, 0, 65, 0, 21, 21, 0, 56, 59, 44, 110, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 25, 40, 0, 238, 0, 173, 0, 195, 0, 166, 0, 175, 0]
test_charizard = [180, 233, 0, 64, 0, 20, 2, 0, 99, 163, 53, 83, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 20, 15, 15, 0, 233, 0, 172, 0, 164, 0, 192, 0, 173, 0]
test_raichu = [85, 210, 0, 64, 0, 23, 23, 0, 85, 86, 97, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 20, 30, 20, 0, 210, 0, 179, 0, 134, 0, 192, 0, 179, 0]
test_tauros = [60, 229, 0, 64, 0, 0, 0, 0, 36, 43, 99, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 30, 20, 30, 0, 229, 0, 192, 0, 186, 0, 205, 0, 154, 0]
test_gyarados = [22, 255, 0, 64, 0, 21, 2, 0, 56, 82, 43, 63, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 10, 30, 5, 0, 255, 0, 224, 0, 165, 0, 168, 0, 192, 0]
player_test = [test_charizard, test_raichu, test_tauros, test_gyarados] #add mons
enemy_gary = ["BLUE",[pidgeot_gary, alakazam_gary, rhydon_gary, arcanine_gary, exeggutor_gary, blastoise_gary]] #add mons
moveNames = """POUND
KARATE CHOP
DOUBLESLAP
COMET PUNCH
MEGA PUNCH
PAY DAY
FIRE PUNCH
ICE PUNCH
THUNDERPUNCH
SCRATCH
VICEGRIP
GUILLOTINE
RAZOR WIND
SWORDS DANCE
CUT
GUST
WING ATTACK
WHIRLWIND
FLY
BIND
SLAM
VINE WHIP
STOMP
DOUBLE KICK
MEGA KICK
JUMP KICK
ROLLING KICK
SAND-ATTACK
HEADBUTT
HORN ATTACK
FURY ATTACK
HORN DRILL
TACKLE
BODY SLAM
WRAP
TAKE DOWN
THRASH
DOUBLE-EDGE
TAIL WHIP
POISON STING
TWINEEDLE
PIN MISSILE
LEER
BITE
GROWL
ROAR
SING
SUPERSONIC
SONICBOOM
DISABLE
ACID
EMBER
FLAMETHROWER
MIST
WATER GUN
HYDRO PUMP
SURF
ICE BEAM
BLIZZARD
PSYBEAM
BUBBLEBEAM
AURORA BEAM
HYPER BEAM
PECK
DRILL PECK
SUBMISSION
LOW KICK
COUNTER
SEISMIC TOSS
STRENGTH
ABSORB
MEGA DRAIN
LEECH SEED
GROWTH
RAZOR LEAF
SOLARBEAM
POISONPOWDER
STUN SPORE
SLEEP POWDER
PETAL DANCE
STRING SHOT
DRAGON RAGE
FIRE SPIN
THUNDERSHOCK
THUNDERBOLT
THUNDER WAVE
THUNDER
ROCK THROW
EARTHQUAKE
FISSURE
DIG
TOXIC
CONFUSION
PSYCHIC
HYPNOSIS
MEDITATE
AGILITY
QUICK ATTACK
RAGE
TELEPORT
NIGHT SHADE
MIMIC
SCREECH
DOUBLE TEAM
RECOVER
HARDEN
MINIMIZE
SMOKESCREEN
CONFUSE RAY
WITHDRAW
DEFENSE CURL
BARRIER
LIGHT SCREEN
HAZE
REFLECT
FOCUS ENERGY
BIDE
METRONOME
MIRROR MOVE
SELFDESTRUCT
EGG BOMB
LICK
SMOG
SLUDGE
BONE CLUB
FIRE BLAST
WATERFALL
CLAMP
SWIFT
SKULL BASH
SPIKE CANNON
CONSTRICT
AMNESIA
KINESIS
SOFTBOILED
HI JUMP KICK
GLARE
DREAM EATER
POISON GAS
BARRAGE
LEECH LIFE
LOVELY KISS
SKY ATTACK
TRANSFORM
BUBBLE
DIZZY PUNCH
SPORE
FLASH
PSYWAVE
SPLASH
ACID ARMOR
CRABHAMMER
EXPLOSION
FURY SWIPES
BONEMERANG
REST
ROCK SLIDE
HYPER FANG
SHARPEN
CONVERSION
TRI ATTACK
SUPER FANG
SLASH
SUBSTITUTE
STRUGGLE"""
pokeNames = ['RHYDON', 'KANGASKHAN', 'NIDORAN', 'CLEFAIRY', 'SPEAROW', 'VOLTORB', 'NIDOKING', 'SLOWBRO', 'IVYSAUR', 'EXEGGUTOR', 'LICKITUNG', 'EXEGGCUTE', 'GRIMER', 'GENGAR', 'NIDORAN', 'NIDOQUEEN', 'CUBONE', 'RHYHORN', 'LAPRAS', 'ARCANINE', 'MEW', 'GYARADOS', 'SHELLDER', 'TENTACOOL', 'GASTLY', 'SCYTHER', 'STARYU', 'BLASTOISE', 'PINSIR', 'TANGELA', 'MISSINGNO.', 'MISSINGNO.', 'GROWLITHE', 'ONIX', 'FEAROW', 'PIDGEY', 'SLOWPOKE', 'KADABRA', 'GRAVELER', 'CHANSEY', 'MACHOKE', 'MR.MIME', 'HITMONLEE', 'HITMONCHAN', 'ARBOK', 'PARASECT', 'PSYDUCK', 'DROWZEE', 'GOLEM', 'MISSINGNO.', 'MAGMAR', 'MISSINGNO.', 'ELECTABUZZ', 'MAGNETON', 'KOFFING', 'MISSINGNO.', 'MANKEY', 'SEEL', 'DIGLETT', 'TAUROS', 'MISSINGNO.', 'MISSINGNO.', 'MISSINGNO.', "FARFETCH'D", 'VENONAT', 'DRAGONITE', 'MISSINGNO.', 'MISSINGNO.', 'MISSINGNO.', 'DODUO', 'POLIWAG', 'JYNX', 'MOLTRES', 'ARTICUNO', 'ZAPDOS', 'DITTO', 'MEOWTH', 'KRABBY', 'MISSINGNO.', 'MISSINGNO.', 'MISSINGNO.', 'VULPIX', 'NINETALES', 'PIKACHU', 'RAICHU', 'MISSINGNO.', 'MISSINGNO.', 'DRATINI', 'DRAGONAIR', 'KABUTO', 'KABUTOPS', 'HORSEA', 'SEADRA', 'MISSINGNO.', 'MISSINGNO.', 'SANDSHREW', 'SANDSLASH', 'OMANYTE', 'OMASTAR', 'JIGGLYPUFF', 'WIGGLYTUFF', 'EEVEE', 'FLAREON', 'JOLTEON', 'VAPOREON', 'MACHOP', 'ZUBAT', 'EKANS', 'PARAS', 'POLIWHIRL', 'POLIWRATH', 'WEEDLE', 'KAKUNA', 'BEEDRILL', 'MISSINGNO.', 'DODRIO', 'PRIMEAPE', 'DUGTRIO', 'VENOMOTH', 'DEWGONG', 'MISSINGNO.', 'MISSINGNO.', 'CATERPIE', 'METAPOD', 'BUTTERFREE', 'MACHAMP', 'MISSINGNO.', 'GOLDUCK', 'HYPNO', 'GOLBAT', 'MEWTWO', 'SNORLAX', 'MAGIKARP', 'MISSINGNO.', 'MISSINGNO.', 'MUK', 'MISSINGNO.', 'KINGLER', 'CLOYSTER', 'MISSINGNO.', 'ELECTRODE', 'CLEFABLE', 'WEEZING', 'PERSIAN', 'MAROWAK', 'MISSINGNO.', 'HAUNTER', 'ABRA', 'ALAKAZAM', 'PIDGEOTTO', 'PIDGEOT', 'STARMIE', 'BULBASAUR', 'VENUSAUR', 'TENTACRUEL', 'MISSINGNO.', 'GOLDEEN', 'SEAKING', 'MISSINGNO.', 'MISSINGNO.', 'MISSINGNO.', 'MISSINGNO.', 'PONYTA', 'RAPIDASH', 'RATTATA', 'RATICATE', 'NIDORINO', 'NIDORINA', 'GEODUDE', 'PORYGON', 'AERODACTYL', 'MISSINGNO.', 'MAGNEMITE', 'MISSINGNO.', 'MISSINGNO.', 'CHARMANDER', 'SQUIRTLE', 'CHARMELEON', 'WARTORTLE', 'CHARIZARD', 'MISSINGNO.', 'MISSINGNO.', 'MISSINGNO.', 'MISSINGNO.', 'ODDISH', 'GLOOM', 'VILEPLUME', 'BELLSPROUT', 'WEEPINBELL', 'VICTREEBEL']
def createReverseList(lst):
dict = {}
for i in range(len(pokeNames)):
dict[pokeNames[i]] = i+1
return dict
revPN = createReverseList(pokeNames)
def findTable():
address = 0
for i in file_contents:
if file_contents[address] == 112 and file_contents[address+1] == 115 and file_contents[address+2] == 32 and file_contents[address+3] == 35: return address
address += 1
def grabTable(address):
table = []
for i in range(0, 190):
table.append(file_contents[address + i])
return table
def convertNameToIndex(moveName):
string = moveNames.split("\n")
index = 0
for i in string:
if i == moveName: return index + 1
index += 1
def physOrSpcl(type):
if type > 16:
return 1
else:
return 0
def getTE(type0, type1):
try: return typeMatchups[type0][type1]
except: return 1
def readBaseStats(pokedex):
if pokedex in range(1, 151):
offset = 0x383de + 28*(pokedex-1)
else:
offset = 0x425b
species = []
for i in range(0, 28):
species.append(file_contents[offset + i])
return species
def readMoveData(moveID, po=0):
offset = 0x38000 + 6*(moveID-1)
if po:
print("Index Number: {}".format(file_contents[offset]))
print("Effect ID: {}".format(file_contents[offset+1]))
print('Attack Power: {}'.format(file_contents[offset+2]))
print("Move Type: {}".format(file_contents[offset+3]))
print("Accuracy: {}".format(file_contents[offset+4]))
print("PP: {}".format(file_contents[offset+5]))
return (file_contents[offset], file_contents[offset+1], file_contents[offset+2],
file_contents[offset+3], file_contents[offset+4], file_contents[offset+5])
def indvCalc(B, E, I, L):
return int(int((2 * B + (I*2) + E) * L / 100 + 5))
def statCalc(evs, ivs, dex, level): #evs = [0,0,0,0,0], ivs = [0,0,0,0]
stats = [0] * 5
#generate hp iv
hp_dv = 0
add = 8
for i in ivs:
if not (i % 2 == 0): hp_dv += add
add /= 2
#calculate E value in format E_HP, E_A
E = [0] * 5
for i in range(0, 5):
E[i] = int(min(255, int(math.sqrt(max(0, evs[i] - 1)) + 1)) / 4)
#calculate all stats
for i in range(1, 5):
stats[i] = indvCalc(readBaseStats(dex)[i+1], E[i], ivs[i-1], level)
#calculate hp
stats[0] = int((2 * readBaseStats(dex)[1] + (hp_dv*2) + E[0]) * level / 100 + level + 10)
return stats
def monsterCreator(species):
pokemon = [species] + ([0] * 43)
#get base stats
basestats = readBaseStats(dexToIndex[species - 1])
#enter level, evs, ivs
pokemon[3] = int(input("Enter level: "))
evs = [int(input("Enter HP EV: ")), int(input("Enter Attack EV: ")), int(input("Enter Defense EV: ")), int(input("Enter Speed EV: ")), int(input("Enter Special EV: "))]
ivs = [int(input("Enter Attack IV: ")), int(input("Enter Defense IV: ")), int(input("Enter Speed IV: ")), int(input("Enter Special IV: ")), ]
#enter moves
num = int(input('Enter number of moves: '))
for i in range(num):
move = input("Enter move name: ").upper()
move = convertNameToIndex(move)
pokemon[8+i] = move
pokemon[0x1d+i] = readMoveData(move)[5]
#calculate stats
stats = statCalc(evs, ivs, dexToIndex[species - 1], pokemon[3])
for i in range(0, 5):
upper = stats[i] >> 8
lower = stats[i] & 255
pokemon[0x22+(2*i)] = lower
pokemon[0x23+(2*i)] = upper
pokemon[1] = pokemon[0x22]
pokemon[2] = pokemon[0x23]
#assign type 1, type 2
pokemon[5] = basestats[6]
pokemon[6] = basestats[7]
#return value
return pokemon
def getMoves(pokemon):
moveList = ["-"] + moveNames.split("\n")
list = []
empty = []
#print("1. {} | {} | {}/{} PP".format(moveList[pokemon[8]], typeNames[readMoveData(pokemon[8])[3]], pokemon[0x1d], readMoveData(pokemon[8])[5]))
if pokemon[0x1d] == 0: empty.append("1")
else: list.append("1")
if pokemon[9] != 0:
#print("2. {} | {} | {}/{} PP".format(moveList[pokemon[9]], typeNames[readMoveData(pokemon[9])[3]], pokemon[0x1e], readMoveData(pokemon[9])[5]))
if pokemon[0x1e] == 0: empty.append("2")
else: list.append("2")
if pokemon[10] != 0:
#print("3. {} | {} | {}/{} PP".format(moveList[pokemon[10]], typeNames[readMoveData(pokemon[10])[3]], pokemon[0x1f], readMoveData(pokemon[10])[5]))
if pokemon[0x1f] == 0: empty.append("3")
else: list.append("3")
if pokemon[11] != 0:
#("4. {} | {} | {}/{} PP".format(moveList[pokemon[11]], typeNames[readMoveData(pokemon[11])[3]], pokemon[0x20], readMoveData(pokemon[11])[5]))
if pokemon[0x20] == 0: empty.append("4")
else: list.append("4")
return list, empty
def printMoves(pokemon):
moveList = ["-"] + moveNames.split("\n")
list = []
empty = []
print("1. {} | {} | {}/{} PP".format(moveList[pokemon[8]], typeNames[readMoveData(pokemon[8])[3]], pokemon[0x1d], readMoveData(pokemon[8])[5]))
if pokemon[0x1d] == 0: empty.append("1")
else: list.append("1")
if pokemon[9] != 0:
print("2. {} | {} | {}/{} PP".format(moveList[pokemon[9]], typeNames[readMoveData(pokemon[9])[3]], pokemon[0x1e], readMoveData(pokemon[9])[5]))
if pokemon[0x1e] == 0: empty.append("2")
else: list.append("2")
if pokemon[10] != 0:
print("3. {} | {} | {}/{} PP".format(moveList[pokemon[10]], typeNames[readMoveData(pokemon[10])[3]], pokemon[0x1f], readMoveData(pokemon[10])[5]))
if pokemon[0x1f] == 0: empty.append("3")
else: list.append("3")
if pokemon[11] != 0:
print("4. {} | {} | {}/{} PP".format(moveList[pokemon[11]], typeNames[readMoveData(pokemon[11])[3]], pokemon[0x20], readMoveData(pokemon[11])[5]))
if pokemon[0x20] == 0: empty.append("4")
else: list.append("4")
return list, empty
def retStatus(pokemon):
statString = ''
status = pokemon[4]
hp = pokemon[1] + (pokemon[2] * 256)
if status == 0 and hp == 0:
statString = 'FNT'
if status == 0 and hp > 0:
statString = 'OK'
if status == 4:
statString = 'SLP'
if status == 8:
statString = 'PSN'
if status == 16:
statString = 'BRN'
if status == 32:
statString = 'FRZ'
if status == 64:
statString = 'PRZ'
return statString
def printSummary(pokemon):
#what we need to print - stats, types, species, moves
print("Species: {} | Level {}".format(pokeNames[pokemon[0] - 1], pokemon[3]))
print("HP: {}/{}".format(pokemon[0x1] + (pokemon[0x2] * 256), pokemon[0x22] + (pokemon[0x23] * 256)))
print("Attack: {}".format(pokemon[0x24] + (pokemon[0x25] * 256)))
print("Defense: {}".format(pokemon[0x26] + (pokemon[0x27] * 256)))
print("Speed: {}".format(pokemon[0x28] + (pokemon[0x29] * 256)))
print("Special: {}".format(pokemon[0x2A] + (pokemon[0x2B] * 256)))
print('Status: {}'.format(retStatus(pokemon)))
if pokemon[5] != pokemon[6]: print("Type: {}/{}".format(typeNames[pokemon[5]], typeNames[pokemon[6]])) #add check for single/dual type
else: print ('Type: {}'.format(typeNames[pokemon[5]]))
#add attacks
printMoves(pokemon)
return
def accuracyTest(moveID):
result = random.randint(0, 256)
accuracy = readMoveData(moveID)[4] * statChangeList[statChanges0[4]] * statChangeList[0-(statChanges1[5])]
if accuracy >= result: return 0
return 1
def printParty(party,p=1):
counter = 1
valids = []
fainted = []
for i in party:
stat = retStatus(i)
if p: print("{}. {} | {} | Level {} | {}/{}HP".format(counter, pokeNames[i[0]-1], stat, i[3], i[0x1] + (i[0x2] * 256), i[0x22] + (i[0x23] * 256))) #add level
if stat == "FNT":
fainted.append(str(counter))
else:
valids.append(str(counter))
counter += 1
return valids,fainted
def damageCalculator(attacker, target, moveID):
global random
stab = 1
#modifier = random * stab * type
#damage = ( ( ( ( ( (2*level) / 5 ) + 2 ) * power * a/d )/50 ) + 2 ) * modifier
###assign vars - attacker level, power, acting attack/defense
level = attacker[3] #implement critical hits, doubles level, based on speed
power = readMoveData(moveID)[2]
result = physOrSpcl(readMoveData(moveID)[3])
if result:
a = (attacker[0x2a] + (attacker[0x2b] * 256)) * statChangeList[statChanges0[3]]
d = (target[0x2a] + (target[0x2b] * 256)) * statChangeList[statChanges1[3]]
if not result:
if attacker[4] == 16: a = (attacker[0x24] + (attacker[0x25] * 256)) * statChangeList[statChanges0[0]] * 0.25 #* (0.25*int(attacker[4]==16))
else: a = (attacker[0x24] + (attacker[0x25] * 256)) * statChangeList[statChanges0[0]]
d = (target[0x26] + (target[0x27] * 256)) * statChangeList[statChanges1[1]]
###calculate modifier
#calculate random
rnd = random.randint(217,255) / 255
#calculate stab
if readMoveData(moveID)[3] in (attacker[5], attacker[6]):
stab = 1.5
#calculate type effectiveness
if target[5] == target[6]:
#type = typeMatchups[readMoveData(moveID)[3]][target[5]]
type = getTE(readMoveData(moveID)[3], target[5])
if target[5] != target[6]:
type = getTE(readMoveData(moveID)[3], target[5]) * getTE(readMoveData(moveID)[3], target[6])
#type = typeMatchups[readMoveData(moveID)[3]][target[5]] * typeMatchups[readMoveData(moveID)[3]][target[6]]
if type == 0:
print("It had no effect!")
if type < 1 and type != 0:
print("It's not very effective...")
if type > 1:
print("It's super effective!")
modifier = rnd * stab * type
damage = ( ( ( ( ( (2*level) / 5 ) + 2 ) * power * a/d )/50 ) + 2 ) * modifier
#print("Level:{},Power:{},A:{},D:{}".format(level,power,a,d))
return int(damage)
def resolveMove(attacker, target, move, entry, who=0): #48=recoil, 29=2to5hits
#add checks for 0 basepower, non-damaging effects
ret_value = [0, 0] #value 0 = target fainted, value 1 = attacker fainted
acc = accuracyTest(move)
if not acc and readMoveData(move)[2] != 0 and readMoveData(move)[1] != 29 and readMoveData(move)[1] != 38:
damage = damageCalculator(attacker, target, move)
enemyHP = target[1] + (target[2] * 256)
#print("{} damage!".format(damage)) #inflict damage, add faint check
enemyHP -= damage
if enemyHP < 0: enemyHP = 0
upper = enemyHP >> 8
lower = enemyHP & 255
target[1] = lower
target[2] = upper
elif not acc and readMoveData(move)[1] == 38:
print("It's a one-hit-KO!")
target[1] = 0; target[2] = 0
else:
print("The attack missed...")
if readMoveData(move)[1] == 48:
playerHP = attacker[1] + (attacker[2] * 256)
recoil = int(damage/4)
print("{} recoil!".format(recoil))
playerHP -= recoil
if playerHP < 0: playerHP = 0
upper = playerHP >> 8
lower = playerHP & 255
attacker[1] = lower
attacker[2] = upper
if readMoveData(move)[1] == 71: #special down
down = random.randint(1,10)
if down == 10:
if not who:
statChanges1[3] -= 1
print("Enemy {}'s SPECIAL stat went down!".format(pokeNames[target[0]-1]))
if who: #enemy using attack
statChanges0[3] -= 1
print("{}'s SPECIAL stat went down!".format(pokeNames[target[0]-1]))
#print("{}'s SPECIAL stat went down!".format(pokeNames[target[0]-1]))
if entry != -1:
attacker[0x1c+entry] -= 1
if target[1] == 0 and target[2] == 0:
ret_value[(not who)] = 1
if attacker[1] == 0 and attacker[2] == 0:
ret_value[(who)] = 1
return ret_value
def mainBattle(playerParty, enemy): #list of pokes
global currentPkmn
global currentEMon
global volatileStatus0
global volatileStatus1
global statChanges0
global statChanges1
moveNameList = [""] + moveNames.split("\n")
attacking = 0 #0=not,1=attacking,2=struggle
enemyAttacking = 0
attack = [0,0]
enemyAttack = [0,0]
print("{} WANTS TO FIGHT!".format(enemy[0]))
enemyParty = enemy[1]
print("GO, {}!".format(pokeNames[playerParty[0][0]-1]))
print("{} SENT OUT {}!".format(enemy[0], pokeNames[enemy[1][0][0]-1] ))
while True: #mainbattle loop, add flinch, do speedtest
enemy_maxhp = enemyParty[currentEMon][0x22] + (enemyParty[currentEMon][0x23] * 256)
enemy_chp = enemyParty[currentEMon][0x1] + (enemyParty[currentEMon][0x2] * 256)
enemy_php = (enemy_chp / enemy_maxhp) * 100
enemy_php = round(enemy_php, 0)
player_maxhp = playerParty[currentPkmn][0x22] + (playerParty[currentPkmn][0x23] * 256)
player_chp = playerParty[currentPkmn][0x1] + (playerParty[currentPkmn][0x2] * 256)
stat = retStatus(playerParty[currentPkmn])
enemyStat = retStatus(enemyParty[currentEMon])
print("{} | {} | Level {} | {}/{}HP".format(pokeNames[playerParty[currentPkmn][0]-1], stat, playerParty[currentPkmn][3], player_chp, player_maxhp)) #add hp, level
print('Enemy: {} | {} | Level {} | {}% HP'.format(pokeNames[enemy[1][currentEMon][0]-1], enemyStat, enemyParty[currentEMon][3], enemy_php)) #add hp, level
print("")
if volatileStatus0[1] == 0: #add wrap check
while True:
attacking = 0
attack = [0,0]
choice = input('''Please choice an option
1.) Fight (Choose an attack)
2.) Switch Pokemon
? ''')
if choice == "1":
options = getMoves(playerParty[currentPkmn])
if options[0] == []:
print("{} ran out of moves! {} used STRUGGLE!".format(pokeNames[playerParty[currentPkmn][0]-1], pokeNames[playerParty[currentPkmn][0]-1]))
#resolveMove(playerParty[currentPkmn], enemyParty[currentEMon], 165, -1)
attacking = 2
break
else: #add freeze, sleep, confusion checks
options = printMoves(playerParty[currentPkmn])
print("C. Cancel")
pkmn = input("? ")
while pkmn not in options[0]:
#print(options[0])
if pkmn in options[1]: print("The move is out of PP!")
elif pkmn == "C": break
else: print("Out of range. Re-enter move number to use.")
pkmn = input('? ').upper()
if pkmn in options[0]:
#resolveMove(playerParty[currentPkmn], enemyParty[currentEMon], playerParty[currentPkmn][int(pkmn)+7], int(pkmn))
attacking = 1
attack = (playerParty[currentPkmn][int(pkmn)+7],int(pkmn))
break
continue
if choice == "2": #add summary
options = printParty(playerParty)
print("C. Cancel")
pkmn = input("? ").upper()
while pkmn not in options[0]:
if pkmn in options[1]: print("There's no energy left to battle!")
elif pkmn == "C": break
else: print("Out of range. Re-enter Pokemon number to switch.")
pkmn = input('? ').upper()
if pkmn in options[0]:
volatileStatus0 = [0]*8
statChanges0 = [0]*6
print("Enough, {}!".format(pokeNames[playerParty[currentPkmn][0]-1]))
currentPkmn = int(pkmn)-1
print("Go, {}!".format(pokeNames[playerParty[currentPkmn][0]-1]))
break
continue
else:
print("{} needs to recharge!".format(pokeNames[playerParty[currentPkmn][0]-1]))
#do enemy input
if volatileStatus1[1] == 0: #add wrap check
while True:
options = printParty(enemyParty,0)
enemyAttacking = 0
enemyAttack = [0,0]
if len(options[0]) > 1: choice = random.choice(["1", "2"])
else: choice = "1"
if choice == "1":
options = getMoves(enemyParty[currentEMon])
if options[0] == []:
print("{} ran out of moves! {} used STRUGGLE!".format(pokeNames[enemyParty[currentEMon][0]-1], pokeNames[enemyParty[currentEMon][0]-1]))
#resolveMove(playerParty[currentPkmn], enemyParty[currentEMon], 165, -1)
enemyAttacking = 2
break
else: #add freeze, sleep, confusion checks
#options = printMoves(playerParty[currentPkmn])
#print("C. Cancel")
ekmn = random.choice(options[0])
while ekmn not in options[0]:
#print(options[0])
if ekmn in options[1]: pass
elif ekmn == "C": break
else: pass#rint("Out of range. Re-enter move number to use.")
ekmn = random.choice(options[0])
if ekmn in options[0]:
#resolveMove(playerParty[currentPkmn], enemyParty[currentEMon], playerParty[currentPkmn][int(pkmn)+7], int(pkmn))
enemyAttacking = 1
attack = (enemyParty[currentEMon][int(ekmn)+7],int(ekmn))
break
continue
if choice == "2": #add summary
#print("C. Cancel")
ekmn = random.choice(options[0])
while ekmn not in options[0]:
if ekmn in options[1]: pass#rint("There's no energy left to battle!")
elif ekmn == "C": break
else: pass#rint("Out of range. Re-enter Pokemon number to switch.")
ekmn = input('? ').upper()
if ekmn in options[0]:
volatileStatus1 = [0]*8
statChanges1 = [0]*6
print("{} withdrew {}!".format(enemy[0], pokeNames[enemy[1][currentEMon][0]-1]))
currentEMon = int(ekmn)-1
print("{} sent out {}!".format(enemy[0], pokeNames[enemy[1][currentEMon][0]-1]))
break
continue
else:
print("{} needs to recharge!".format(pokeNames[enemyParty[currentEMon][0]-1]))
#add burn checks
if playerParty[currentPkmn][4] == 16: #player burned
print("{}'s hurt by the burn!")
playerMaxHP = playerParty[currentPkmn][22] + (playerParty[currentPkmn][23] * 256)
playerHP = playerParty[currentPkmn][1] + (playerParty[currentPkmn][2] * 256)
playerHP -= int(playerMaxHP * (1/16))
upper = playerHP >> 8
lower = playerHP & 255
playerParty[currentPkmn][1] = lower
playerParty[currentPkmn][2] = upper
###faint check for burn check
#input resolving time - add confusion, wrap tests
result = [0,0]
playerSpeed = (playerParty[currentPkmn][0x28] + (playerParty[currentPkmn][0x29] * 256)) * statChangeList[statChanges0[2]]
enemySpeed = (enemyParty[currentEMon][0x28] + (enemyParty[currentEMon][0x29] * 256)) * statChangeList[statChanges1[2]]
if playerSpeed == enemySpeed:
rand = random.randint(1,2)
if rand == 1: playerSpeed += 1
if rand == 2: enemySpeed += 1
if playerSpeed > enemySpeed: #player outspeeds enemy, include faint check
if attacking == 1:
print("{} used {}!".format(pokeNames[playerParty[currentPkmn][0]-1], moveNameList[playerParty[currentPkmn][int(pkmn)+7]]))
result = resolveMove(playerParty[currentPkmn], enemyParty[currentEMon], playerParty[currentPkmn][int(pkmn)+7], int(pkmn), 1)
if attacking == 2:
print("{} is out of PP! {} used STRUGGLE!")
result = resolveMove(playerParty[currentPkmn], enemyParty[currentEMon], 165, -1, 1)
#faint check for enemy, player here
if result[1] == 1: #player fainted
print("{} fainted!".format(pokeNames[playerParty[currentPkmn][0]-1]))
options = printParty(playerParty,1)
#print(options)
if options[0] == []:
print('You are out of usable Pokemon! Cradling your exchausted Pokemon, you scurry to a Pokemon Center. {} whited out!')
break
else:
currentPkmn = 400000000000000000
attacking = 0
while str(currentPkmn) not in options[0]:
currentPkmn = int(input("? "))
if currentPkmn in options[1]: print("There's no energy left to battle!")
currentPkmn -= 1
volatileStatus0 = [0]*8
statChanges0 = [0]*6
print("Go, {}!".format(pokeNames[playerParty[currentPkmn][0]-1]))
if result[0] == 1: #enemy fainted
print("Enemy {} fainted!".format(pokeNames[enemy[1][currentEMon][0]-1]))
options = printParty(enemyParty,0)
#print(options)
if options[0] == []:
print('{} is all out of usable Pokemon! {} has been defeated! You win!'.format(enemy[0], enemy[0]))
break
else:
enemyAttacking = 0
currentEMon = int(random.choice(options[0]))-1
volatileStatus1 = [0]*8
statChanges1 = [0]*6
print("{} sent out {}!".format(enemy[0], pokeNames[enemy[1][currentEMon][0]-1]))
result = [0,0]
#execute enemy attack
if enemyAttacking == 1:
print("Enemy {} used {}!".format(pokeNames[enemy[1][currentEMon][0]-1], moveNameList[enemyParty[currentEMon][int(ekmn)+7]]))
result = resolveMove(enemyParty[currentEMon], playerParty[currentPkmn], enemyParty[currentEMon][int(ekmn)+7], int(ekmn))
#print(result)
if enemyAttacking == 2: result = resolveMove(enemyParty[currentEMon], playerParty[currentPkmn], 165, -1)
if result[0] == 1: #enemy fainted
print("Enemy {} fainted!".format(pokeNames[enemy[1][currentEMon][0]-1]))
options = printParty(enemyParty,0)
#print(options)
if options[0] == []:
print('{} is all out of usable Pokemon! {} has been defeated! You win!'.format(enemy[0], enemy[0]))
break
else:
enemyAttacking = 0
currentEMon = int(random.choice(options[0]))-1
volatileStatus1 = [0]*8
statChanges1 = [0]*6
print("{} sent out {}!".format(enemy[0], pokeNames[enemy[1][currentEMon][0]-1]))
if result[1] == 1: #player fainted
print("{} fainted!".format(pokeNames[playerParty[currentPkmn][0]-1]))
options = printParty(playerParty,1)
#print(options)
if options[0] == []:
print('You are out of usable Pokemon! Cradling your exchausted Pokemon, you scurry to a Pokemon Center. {} whited out!')
break
else:
currentPkmn = 400000000000000000
attacking = 0
while str(currentPkmn) not in options[0]:
currentPkmn = int(input("? "))
if currentPkmn in options[1]: print("There's no energy left to battle!")
currentPkmn -= 1
volatileStatus0 = [0]*8
statChanges0 = [0]*6
print("Go, {}!".format(pokeNames[playerParty[currentPkmn][0]-1]))
#faint check for enemy, player here
if enemySpeed > playerSpeed: #enemy outspeeds player, include faint check
if enemyAttacking == 1:
print("Enemy {} used {}!".format(pokeNames[enemy[1][currentEMon][0]-1], moveNameList[enemyParty[currentEMon][int(ekmn)+7]]))
result = resolveMove(enemyParty[currentEMon], playerParty[currentPkmn], enemyParty[currentEMon][int(ekmn)+7], int(ekmn))
if enemyAttacking == 2: result = resolveMove(enemyParty[currentEMon], playerParty[currentPkmn], 165, -1)
#faint check for enemy, player here
if result[1] == 1: #player fainted
print("{} fainted!".format(pokeNames[playerParty[currentPkmn][0]-1]))
options = printParty(playerParty,1)
#print(options)
if options[0] == []:
print('You are out of usable Pokemon! Cradling your exchausted Pokemon, you scurry to a Pokemon Center. {} whited out!')
break
else:
currentPkmn = 400000000000000000
attacking = 0
while str(currentPkmn) not in options[0]:
currentPkmn = int(input("? "))
if currentPkmn in options[1]: print("There's no energy left to battle!")
currentPkmn -= 1
volatileStatus0 = [0]*8
statChanges0 = [0]*6
print("Go, {}!".format(pokeNames[playerParty[currentPkmn][0]-1]))
if result[0] == 1: #enemy fainted
print("Enemy {} fainted!".format(pokeNames[enemy[1][currentEMon][0]-1]))
options = printParty(enemyParty,0)
#print(options)
if options[0] == []:
print('{} is all out of usable Pokemon! {} has been defeated! You win!'.format(enemy[0], enemy[0]))
break
else:
enemyAttacking = 0
currentEMon = int(random.choice(options[0]))-1
volatileStatus1 = [0]*8
statChanges1 = [0]*6
print("{} sent out {}!".format(enemy[0], pokeNames[enemy[1][currentEMon][0]-1]))
result = [0,0]
#execute player attack
if attacking == 1:
print("{} used {}!".format(pokeNames[playerParty[currentPkmn][0]-1], moveNameList[playerParty[currentPkmn][int(pkmn)+7]]))
result = resolveMove(playerParty[currentPkmn], enemyParty[currentEMon], playerParty[currentPkmn][int(pkmn)+7], int(pkmn), 1)
if attacking == 2: result = resolveMove(playerParty[currentPkmn], enemyParty[currentEMon], 165, -1, 1)
#faint check for enemy, player here
if result[1] == 1: #player fainted
print("{} fainted!".format(pokeNames[playerParty[currentPkmn][0]-1]))
options = printParty(playerParty,1)
#print(options)
if options[0] == []:
print('You are out of usable Pokemon! Cradling your exchausted Pokemon, you scurry to a Pokemon Center. {} whited out!')
break
else:
currentPkmn = 400000000000000000
attacking = 0
while str(currentPkmn) not in options[0]:
currentPkmn = int(input("? "))
if currentPkmn in options[1]: print("There's no energy left to battle!")
currentPkmn -= 1
volatileStatus0 = [0]*8
statChanges0 = [0]*6
print("Go, {}!".format(pokeNames[playerParty[currentPkmn][0]-1]))
if result[0] == 1: #enemy fainted
print("Enemy {} fainted!".format(pokeNames[enemy[1][currentEMon][0]-1]))
options = printParty(enemyParty,0)
#print(options)
if options[0] == []:
print('{} is all out of usable Pokemon! {} has been defeated! You win!'.format(enemy[0], enemy[0]))
break
else:
enemyAttacking = 0
currentEMon = int(random.choice(options[0]))-1
volatileStatus1 = [0]*8
statChanges1 = [0]*6
print("{} sent out {}!".format(enemy[0], pokeNames[enemy[1][currentEMon][0]-1]))
volatileStatus0[4] = 0 #reset flinch chance
volatileStatus1[4] = 0
#add leech seed, burn, poison check
return
`
Previous Page

- 1

Next Page