Register

Author Topic: Theorycrafting! (Because I like competitive metagames too much)  (Read 109031 times)

dude789

  • Denizen
  • *
  • Posts: 1284
    • View Profile
Re: Theorycrafting! (Because I like competitive metagames too much)
« Reply #25 on: April 11, 2010, 01:10:21 AM »
This is a very good read and it's really interesting to read something like this about pokemon. As for new Gen 2 types. I think back when those two types were introduced the intention wasn't to have them be as redundant/overpowered defensively as they are now. I think both of them were created because psychic types really needed a counter of some sort and a new type or two seemed to be the best way to accomplish that. Ghost despite being hailed as the psychic counter was ineffective because they all had poison type as a secondary type and the only non fixed attack move they had was lick. Similarly, most of the bug types either sucked, had posion as a secondary typing, or didn't learn any bug moves.

As a result, dark was created as a type that could completely shut psychics down and steel was a type that could at least slow them up. Of course another thing that differentiated dark and ghost was that ghost was a physical type and dark was a special type back then. Steel is another type that I think started off as a good idea and became overpowered as more pokemon were introduced. In Gen 2 most of the steel types lost speed when they evolved and most of them had a glaring weakness to either ground or fire. However, I do agree with you that immuning posion is unnecessary. Heck if anything, they could make it so that steel was weak to poison. It makes sense (corrossion) and it would be a nice boost to a type that doesn't have a whole lot of good pokemon.

metroid composite

  • m_ACac
  • Administrator
  • Denizen
  • *
  • Posts: 4373
    • View Profile
Re: Theorycrafting! (Because I like competitive metagames too much)
« Reply #26 on: April 11, 2010, 01:25:23 AM »
I think both of them were created because psychic types really needed a counter of some sort and a new type or two seemed to be the best way to accomplish that.

Alternatively, they could have modified the type chart.  Which they...actually did!

Remember...

Poison used to be super effective against Bug (neutral now)
Bug used to be neutral against Poison (resisted now)
Ice used to deal neutral damage to Fire (resisted now)
Ghost used to be null damage against Psychic (super effective now)

(And no, I don't understand why Bug and Poison were nerfed as attacking types).

Ranmilia

  • Poetry Lover
  • DL
  • Denizen
  • *
  • Posts: 1687
  • Not a squid!!
    • View Profile
Re: Theorycrafting! (Because I like competitive metagames too much)
« Reply #27 on: April 11, 2010, 02:25:48 AM »
Those modifications have always seemed quite situational to me.  The type chart doesn't exist in a void, the designers were free to (and should!) consider the actual moves and pokes available in each type since... they control that too!

Poison resisting Bug, for example.  In RBY Bug really didn't exist as an offensive type and Poison was absolutely terrible on defense.  In GSC, Bug... still doesn't really exist  - except for Megahorn on Heracross, which is The Signature Offensive Move on The Signature Offensive Pokemon of the entire generation and was certainly expected to run amok.  Giving bug resistance to poison helped pull poison out of the hole of complete uselessness it was stuck in and let Gengar, Nidoqueen/King, Muk, Weezing, and the Grass/Poison crowd stand up to Hera.  (unless it had Earthquake, but... well.)  Increasing the defensive usefulness of those pokes seems like something Game Freak was quite interested in doing.  But they still wanted the Poison type to suck at direct offense in general (seems a clear case of "it's a status type, not an offense type"), so no SE against Hera and the complete walling by steel.

Dark is Ghost on offense, yeah, but it's Ghost that isn't tied to a Normal/Fighting immunity, which obviously shouldn't be given out too freely.

Steel... was a gimmick type in Gen 2 that was meant to make a select few pokes horribly defensively powerful while overemphasizing their weaknesses.  Definitely balanced by the pokes it was on rather than judging it in a void.  All the GSC steels are really bad at offense except MAYBE Magneton, and, indeed, steels aren't overrepresented at all in the Gen 2 metagame.  It worked well as a type then. 

Going on to make more and more steel pokes in gen 3+, with awesome stats and offensive capabilities without rebalancing the type chart to compensate - that I can't explain.

Cmdr_King

  • Strong and Full of Love
  • DL
  • Denizen
  • *
  • Posts: 5562
  • Is Gay
    • View Profile
    • CK Blog
Re: Theorycrafting! (Because I like competitive metagames too much)
« Reply #28 on: April 11, 2010, 02:39:26 AM »
My gutcheck there is that they had a large negative reaction from the type chart adjustments between Gen 1 and 2, and decided that adjusting it again wouldn't be worth it.  Why they still went ahead with making... 6 or 7? new Steels in Gen 3 after that decision of course is anyone's guess.
CK: She is the female you
Snow: Speaking of Sluts!

<NotMiki> I mean, we're talking life vs. liberty, with the pursuit of happiness providing color commentary.

metroid composite

  • m_ACac
  • Administrator
  • Denizen
  • *
  • Posts: 4373
    • View Profile
Re: Theorycrafting! (Because I like competitive metagames too much)
« Reply #29 on: April 14, 2010, 04:37:03 AM »
Formulae.

So...the basic stat formula that you'll use at level 100 is...

IV + EV/4 + 2*Base_Stat + 5

(Round down the final result)

Base_Stat is the number that gets thrown around all the time; 85 is probably about average.
IV is 0-31 (a random value in-game; fixed to 31 for internet ladders).
EV is 0-255 (but you can distribute at most 510 EVs.  Now, why this is 510 and not 511 is a little puzzling to me.  It's possible there's some really clever storage trick for storing numbers that sum to less than or equal to 510...but I'm not sure what such a storage technique would be, and honestly suspect that the game just dedicates the 6x8 bits for each pokemon.  No, the one place I can see 510 coming from is a designer deciding "I want this mechanic to let you max two stats.  255 to max one stat, 255x2 = 510.")

But the formula is a bit more complex than this--it's really (not counting Natures just yet):

(IV + EV/4 + 2*Base_Stat) * (Level/100) + 5

And for HP:
(IV + EV/4 + 2*Base_Stat) * (Level/100) + 10 + Level

Which has some interesting implications for levels not 100.  For one thing, at a certain point I was silly and assumed "if you get 4 EVs, I guess you get an extra stat", which is not true at all below level 100.  For another thing, it means that choosing EVs below level 100--notably, in the level 5 competitive metagame you get some interesting strategy around making round numbers:

http://www.smogon.com/dp/articles/little_cup_guide#EVs

In particular, you're multiplying the end result by (5/100) = (1/20) so you want the end result to be divisible by 20.  Only the final digit of Base_Stat matters, because for all higher digits, you have a number in the form of ??0, which you multiply by 2, and thus is divisible by 20.

So...taking the final digit of the base stat multiplied by 2, and added to 31 from the IV, you can see how many EVs you need to get a number divisible by 20.  For instance, if the Base_Stat ends in 4, then 31 + 2*4 = 39, so you only need EV/4 to be 1.  By comparison, if the base stat is 5, then 31 + 2*5 = 41, so if you want to bring this up to something divisible by 20, you need 19 stats, and thus 76 EVs.


This also has implications on, for instance, the world championships which are held at level 50.  The point is that it's better for EV/4 to be an odd number, since 2*Base_Stat is always even, and 31 from IVs is always odd.  Now...you can do the usual 252, 252, 4 to get three odd numbers (63, 63, and 1).  Or you could go for 5 odd numbers instead, by using (63, 61, 1, 1, 1).  This lets you exchange, for instance, -1 Atk for +1 Def +1 SDef.  Might be worthwhile.


Back to durability
Okay, so so far most of this post I'm assuming is well-known information.  One thing that's been interesting me...remember those durability calculations how nearly all pokemon wanted EVs in HP rather than defence?  Well...I started wondering, where's the cutoff point?

Let's say you're going for overall combined durability between physical and special, and get to distribute a total number of base stats to do this (or, more realistically, you get to distribute your EVs--for the purposes of this calculation I'm just going to merge base stat and EV into one controlled stat).  What's your ideal distribution.  Well...for starters your stats look like this at level 100:

HP = 2*Base_HP + 31 + 100 + 10 = 2*Base_HP + 141
Defs = 2*Base_Defs + 31 + 5 = 2*Base_Defs + 36

And the percentage damage that gets done is roughly damage/HP ~= (Constants/Def)/HP.  So...we just minimize HP*Def, which is a pretty classic minimization problem.  The one extra wrinkle is that we're generally choosing between +2 HP and +1 Def/+1 MDef.  So...basically, let Base_HP = x...

2*Base_HP = 2x
2*Base_Defs = 2( (Tot_Stat - x)/2 ) = Tot_Stat - x

So...we're trying to maximize:

(2x + 141) * (Tot_Stat - x + 36 ) = 2 * (x + 70.5) * (Tot_Stat - x + 36)

So...this is a really easy optimization--you don't even really benefit from calculus for this one, it's an x * (T-x) problem, and the answer is when x and (T-x) are closest to equal.

x + 70.5 = Tot_Stat - x + 36
2x = Tot_Stat - 34.5
Base_HP = (Tot_Stat - 34.5)/2

Or, to put this in a bit more of a table format, here's some optimal stat distributions:

Tot_StatHPDefSDef
3401717
102343434
2341006767
3021348484
3341509292
368168100100

At the bottom of the chart the HP to Def ratio heads to 0, at the top of the chart, the HP to Def ratio heads to 2:1.  In a more middle normal range, the best ratio is more like 3:2 in favour of HP.

The next interesting question is "when a pokemon has badly distributed defensive stats, just how bad is it?"  Like...Deoxys-D spends 390 base stats on durability.  Well...we plug in (Tot_Stat - 34.5)/2 into our formula to get...

(Tot_Stat + 106.5) * (Tot_Stat/2 + (34.5 + 72)/2) = 1/2 * (Tot_Stat + 106.5)^2

However, this formula is also the actual defence stat times the actual HP stat.  So...non-EVed Deoxys-D has...

HP*Def = 241*356 ~= 86,000
(optimal) HP*Def = (390+106.5)^2 * 1/2 ~= 123,000

So...70% efficiency (compared to what it would be with 180 base stat and 105 defences).  And...well, it's not even as bad as all that, because everyone maxes out HP EVs, which means the combined base HP is more like 81.  Plugging that back into the formula (453 base stats on durability, HP maxed, defs even) we get...

HP*Def = 304*388 ~= 118,000
(optimal) HP*Def = (453+106.5)^2 * 1/2 ~= 157,000

So...this brings Deoxys-D up to 75% optimum.

Hmm...for no good reason I wonder what the lowest base defensive stats a pokemon can have and match Deo-D.

(tot+106.5)^2 * 1/2 ~= 118,000
And so we multiply by 2 and square root and subtract 106.5...
tot = 379
Although of course: bear in mind that Deo-D with 453 total defensive investment is after EVs; So...removing EVs from 379 we're looking at 316.  Or more specifically, something like 142 HP, 88 Def, 88 SDef (doesn't have to be exactly this since EVs can take something with slightly worse HP/Defs balance and balance it).

Durability at lower levels
What's going to change?  Well...these:

HP = 2*Base_HP + 31 + 100 + 10 = 2*Base_HP + 141
Defs = 2*Base_Defs + 31 + 5 = 2*Base_Defs + 36

Notably, it becomes more like...

HP = 2*Base_HP + 31 + 100 + 10*(100/Level)
Defs = 2*Base_Defs + 31 + 5*(100/Level)

So, at, say, level 5, this is more like...

HP = 2*Base_HP + 331
Defs = 2*Base_Defs + 131

So...our maximization function looks like...

(2x + 331) * (Tot_Stat - x + 131 ) = 2 * (x + 165.5) * (Tot_Stat - x + 131)

Notice the real kicker yet?  The optimal x value is exactly the same as it is in the level 100 case.  (Tot_Stat - x) needs to be 34.5 less than (x).  It seems that the developers knew exactly what they were doing when they put a +10 in front of HP, and a +5 in front of all other stats.

There is, however, one behavioural difference: your base stats matter less.  Stat values are more homogeneous on the whole (which is exactly what you'd expect when you add constant values much larger than the stat).


Well...but I've been making an assumption that I don't think I can make at low levels.  Let's look at the actual damage formula:

Damage = ((((2 * Level / 5 + 2) * AttackStat * AttackPower / DefenseStat) / 50) + 2) * STAB * Weakness/Resistance * RandomNumber / 100

Particularly the +2 on the right is something I've left out completely (so far).  I played around with the optimization problem here (take the derivative, look for where it's 0) and it's...an ugly optimization.  I won't copy the notes I made on the plane.  I did some linear approximations and came to the conclusion that at level 100 you can pretty much ignore the +2 term for optimization purposes.  but at low levels such an assumption is probably wrong.  And high defences suffer the most--even if you had 300 defence at level 5 (a feat that would require 3000 base stat), you'd still take 1-2 damage from anything and go down in about 10-20 hits.  For medium-high defences it becomes more like "average damage is 12, and that attack gets reduced to 4" whereas at level 100 it's more like "average damage is 102, and that attack gets reduced to 22".  a 5:1 ratio at any reasonably high level becomes a 3:1 ratio at level 5, again devaluing defence.

Part of the problem with this one is that it's subject to just how strong the attack being used on you is, too.  I'm not sure of a great approach, but a decent approach is to say "if the goal is to survive 2 hits, then you'll need 4 extra HP for the +2s".  4 Extra HP at level 100 is 2 base stats (or 16 EVs).  4 Extra HP at level 5 is 40 base stats (or 320 EVs...more than the 255 max).  This allows us to use the simpler equation because we've already allowed for the +2 in our planned survival.

Of course, there's some potentially confusing points here.  If a move is super effective, then that +2 becomes +4.  If a move is STAB, then the +2 becomes +3.  If the move is STAB and hits 4xWeak, then that +2 becomes +12.  So...if your goal is surviving two hits from a common opponent who has a STAB on your W4, then you're going to need 24 extra HP for this, not 4 extra HP.  Realistically the goal is probably more like "survive two W2s from non-STAB opponents", in which case you need to set aside 8 HP, rather than 4 HP.

So...yeah, we can get a decent approximation of how to deal with the +2 part of the equation.  Factoring that back into the old equation for level 100 makes it like...Base_HP = (Tot_Stats - 30)/2.  (Not complaining about that; 30 makes for rounder numbers than 34.5).  And...for level 5, it's more like Base_HP = (Tot_Stats + 45)/2.  (Both of these numbers assuming setting aside 4 HP).  Okay, so let's do one that's kinda in-between and interesting and I'm not quite sure where it will land; setting aside 8 HP (survive two W2s) at level 50 (world championship levels) We end up looking like...Base_HP = (Tot_Stats - 18.5)/2.

Redoing the table from earlier for Base_HP = (Tot_Stats - 20)/2

Tot_StatHPDefSDef
2001010
60202020
2201006060
3001408080
380180100100

Notably, if you're using Giratina-O and only have 252 EVs to dedicate to defences, you can justify at least 244 of them in HP.  (Giratina-O being the one with high HP but not all that high defences...).  The level 50 quirk of "odd numbers better" means you want to put 4 Def, 4 SDef with the last 8, granted.

metroid composite

  • m_ACac
  • Administrator
  • Denizen
  • *
  • Posts: 4373
    • View Profile
Re: Theorycrafting! (Because I like competitive metagames too much)
« Reply #30 on: May 08, 2010, 06:08:05 AM »
Switching to Magic the Gathering for a bit...

So...for a bit of background, the most recent set, first card I saw I thought "huh, it looks like they're imitating Cthulu".  Of course, one of the nice things about MtG is you get to have a window into the designer's head:

http://www.wizards.com/Magic/Magazine/Article.aspx?x=mtg/daily/mm/84

(To paraphrase: "we decided to do Cthulu/Galactus".  Whee, it's fun to be proven right.)



Now, I'm going to focus on constructed magic here; not because what they're doing with Limited isn't interesting too (it is) but because I don't feel I understand Limited on a theoretical level.

So...constructed--it's certainly plausible for 9+ mana creatures to see constructed play--Iona, Shield of Emeria already does right now, for instance.

So what is the biggest obstacle to large creatures seeing play?  Simply put, removal.  You spend 10 mana, they spend 2 mana on a spell that says "destroy target creature" or "counter target spell" or whatever--10 mana vs 2 mana: you're behind.  What large creatures need, then, is to either have an immediate bonus effect so you don't care if it's killed (like Wall of Blossoms) or something that makes it hard to kill.

With that in mind, we can eliminate from the potential playability list the following monsters: It That Betrays, Pathrazer of Ulamog, Spawnsire of Ulamog, and Ulamog's Crusher.  And...well Hand of Emrakul is just in a totally different category, being a "small" creature that would only be considered in constructed if the Spawn Token cards are good enough on their own, which is an entirely different question (for another day, perhaps).  Okay, so eliminating those leaves us with...

CardMana  StatsExtrasWhen you cast
Artisan of Kozilek910/9 Annihilator 2return a creature from your graveyard to play
Kozilek, Butcher of Truth1012/12 Annihilator 4 draw 4 cards
Ulamog, the infinite Gyre1110/10 Annihilator 4indestructibledestroy target permanent
Emrakul, the Aeons Torn1515/15 flying Annihilator 6can't be countered, protection from coloured spellstake an extra turn after this one

Let's start by looking at the "when you cast" bonuses--as these are the bonuses that can't be stopped (counterspells don't even stop them, because you've already cast the card).  Most of these are actually 5 mana Sorceries that have seen competitive play in modern magic, actually.  Return creature from graveyard to play (slightly stronger being "any graveyard", but same idea).  Draw 4 CardsTake an extra turn.  The one sort of question mark is destroy target permanent--Desert Twister is bad, Mangara of Corondor is 3 mana, but takes a full turn to activate...and there's Vindicate at 3 mana, but the consensus is that said spell is very undercosted (and still used in type 1 style formats IIRC) and there's Confiscate which did see play, but is better than a destroy effect.  So...just how much is "destroy target permanent" as a monocolour sorcery worth?  I think we can safely say "at least 4" as Wrecking Ball seems to be interesting enough to consider in Extended (although granted: it's an instant, not a sorcery).  And...not 6.  So...4 or 5 mana (and probably 4 of those two, if it wants to see tournament play).

But the context of a large mana spell is more important here--for instance, they seem to no longer print land destruction below about 4 mana as it can be nasty early in the game, but on a 10 mana creature, "destroy target nonblack creature" would be of greater value than "destroy target land".  So...what are the contexts here...

Artisan of Kozilek: 9 mana for 2 creatures.  This has been powerful before.  But Artisan is more limited--you're stuck choosing Artisan's body as one of the two (not a bad body, but doesn't allow combos).  And you need creatures in the graveyard to get your two creatures (which would have been reasonable in some older blocks where the best turn 3/4 draw spells had you drawing and discarding cards, but is inconvenient in the current metagame).

Kozilek: 10 mana for uncounterable draw 4 cards.  Uncounterable but expensive card draw certainly has seen play.  The current metagame may value this less than the metagame in 2006, however, as counterspells are a bit out of favour right now (blue decks tend to run about four counterspells).

Ulamog: 11 mana for a big creature with destroy target permanent.  Last time I remember this being big was Angel of Despair which is 7 mana.  Mind you, the other comparison that could be made here is to Darksteel Colossus, which is 11 mana for an 11/11 indestructible trample, while this is 11 mana for a 10/10 indestructible annihilator 4.  Both have indestructible, and if you attack twice with them you probably win (22 trampling damage...or sacrifice 8 permanents and chump block with a 9th).  However, indestructible isn't fantastic in the metagame, what with strong bounce removal, strong exile removal (formerly known as "remove from game"), and some Mind Control running around.  Indestructible still helps, mind.

Emrakul: 15 mana for take an extra turn after this one...which in the context of Emrakul's other abilities means untap all lands, draw a card, your opponent sacrifices 6 permanents and is being attacked by a 15/15 flying that they can't stop using spells.  The usual weakness of time walk effects is that they're basically just draw a card...unless you have creatures or something like creatures that do things every turn...and Emrakul all but guarantees that you do make use of the extra turn.  Of course, the downside of Emrakul is the mana cost; people are already spending 9 mana, so a different 9 mana threat getting attention is reasonable, and 10 or 11 sound like "well...that's still somewhat close to 9 mana".  15 though?  Way off.  And if you have that kind of mana, arguably you're into "just fireball your opponent" range.  (Of course, if you're going to cheat your way around the mana cost somehow, Emrakul's the obvious one having the biggest body).



Anyhow, the first usage statistics are in, and the winner so-far seems to be...Ulamog.  I'm sure this has surprised some forum-goers I read some posts a while back expressing their disappointment with Ulamog (roughly to paraphrase: "Ulamog is smaller than Koziltek, and costs more, and destroy a permanent sounds less shiny than draw 4 cards.")  Only one of this poster's complaints was actually practical, however--10/10 vs 12/12...they're basically the same size, namely the size of "kill in two hits unless chump blocked."  Destroying having less bang than draw 4?  Not necessarily in practice--control decks have shifted more towards planeswalkers (cards that build up resources until they kaboom).  One permanent can actually have a very high resource value--higher than you'd think from just the mana and card spent.  Hence a lategame uncounterable "destroy target permanent" can be a significant resource swing.  And the final actually valid complaint: yes, Ulamog costs 1 more mana...although arguably that's more than worth-it for the added indestructability.

It's still early in the metagame, though; it'll be interesting to see if things shift--Kozilek getting more favour wouldn't surprise me in the right metagame.  And potentially Artisan if they print good "draw and discard" cards again, provided blue keeps running 9 mana creatures--since, y'know, Iona+Artisan > Iona on her own.  Also, doing it this way gives Iona that can't be countered, which is cool.

Emrakul's already seen play in decks designed to cheat him out, naturally.  I'm not holding my breath on decks that actually plan on hardcasting 15 mana, though.

metroid composite

  • m_ACac
  • Administrator
  • Denizen
  • *
  • Posts: 4373
    • View Profile
Re: Theorycrafting! (Because I like competitive metagames too much)
« Reply #31 on: May 16, 2010, 06:27:16 AM »
This post is well, not necessarily anything practical in any sense whatsoever, as just something I started thinking about and wanted to do some calculations.

What am I talking about, you might wonder?  Sweeps with terrible pokemon; example:

http://www.youtube.com/watch?v=ye7b3bOQ6lY

This is actually on the tame end of things--Magikarp has Flail and Swift Swim, so while it's ridiculous for it to solo a team, only four or so setup turns are used for it (Spore, Substitute, Belly Drum (triggering Salac Berry), Baton Pass).  People have taken this a fair bit further by trying to use considerably weaker pokemon and...buffing just about everything.

http://www.youtube.com/watch?v=jrOubH5lubE

Buffing everything, mind you, because Caterpie (who at the time could only learn Tackle) can't solo by OHKOing stuff, but needs to actually survive enemy hits and such.  So I was curious to check, just how powerful is one of these Karp-esque pokemon after buffs?  Like, what would be an equivalent unboosted pokemon?

Looking at Caterpie and comparing to Garchomp...

For starters, I'm going to have to disagree with the setup posted in the Youtube description.  Razor Claw or Scope Lens aren't the best item here--with Focus Energy baton passed, they take the critical hit rate from 25% to 33%.  By comparison, Choice Band multiplies the *whole* attack stat by 1.5 (including all the Swords Dances).  Even if he needs crit damage to break through specific problem setups, 25%*1.5 = 37.5%--so Choice Band actually means more critical damage (as well as more normal damage, obviously).

Adamant with max power EVs is obvious.  (In addition to being one of the best stats you can raise for a longer slugfest, making things take fewer turns = less time in which stuff can go wrong).  Some form of defence EVs after that are also obvious.  (You certainly don't need the speed--4x boost on speed is "enough").  Now, how exactly you split the defence EVs is an interesting question--before the substitute goes down, it's only Caterpie's defences that will matter, but after the sub goes down, it might be advantageous to raise HP to the next multiple of 16 to take full advantage of Aqua Ring/Ingrain.  (Heal 30 HP per turn instead of 28).

There's a reasonable question too--while he EV trained Caterpie entirely in defence, this does leave it very vulnerable to special attacks (and it nearly dies from two Tyranitar Fireblasts at the end...so, say, Heatran with Overheat would OHKO).  The probable logic behind this is probably one of "OU is more physical" "Flying and Rock are usually physical" or "you need to get lucky and face a stupid opponent anyway--maybe your opponent won't notice the low special stat."  However, balanced defences will make it easier to compare to other pokemon, and since this is purely a mathematical comparison exercise, let's go with the easy comparison...

100 HP EVs (reaches the "heal 32 HP per turn" mark) 20 Def EVs, 136 SDef EVs, (and 252 Atk EVs +Adamant, as mentioned earlier).  Stats are 256 HP, 174 Atk, 111 Def, 110 SDef, 126 Speed.  Boosts make this 256 HP, 696 Atk, 444 Def, 440 SDef, 504 Speed.  For our control case Garchomp we will similarly use EVs designed for damage then balanced durability.  So...EVs would be 252 Atk, 80 SDef, 176 HP.  This gives stats 401 HP, 394 Atk, 226 Def, 226 SDef, and 240 Speed.  To further parallel the setups, also give Garchomp a Choice Band.

Hmm...something I hadn't considered when I started this calculation: Earth deals half damage to Bug.  Well...for the purposes of comparison, I'll just pretend there exists a 100 power dragon move (I could use Outrage or Dragon Claw, but...meh; I'm aiming for generic).

So...with these numbers...Tackle does 127 average to Garchomp (with 25% crit and 95% hit) dealing 32% of the HP.  Garchomp's pretend 100 power dragon move deals...156 average to Caterpie, dealing 61% of the HP.  Before we factor in anything extra, looks like Caterpie looses the slugfest.

So...the extras.  Ingrain and Aqua Ring...don't actually prevent the 2HKO on average (they bring the two turn average down from 312 to 280, which is still more than the 256 HP).  Still losing the slugfest so far.  Really, what seems to make the above video possible is the Double Team, which reduces hit chances against Caterpie to 33%.  (Double Team is banned even in uber play as of right now so...yeah).

So...without DT, all stats boosted Caterpie with Choice Band loses to Garchomp with Choice Band.  But...that's only against each other; maybe Caterpie deals less damage but is tankier?  Let's see...damage against a 300 def opponent...Garchomp=231, Caterpie=96.  Defending against a 300 attack, 100 power opponent...Caterpie=21% taken, Garchomp=26% taken.  So...tankier, slightly, but not untouchably tanky (matched by a Cresselia with zero EVs).  So...backing up for a moment...what if we copied the Youtube guy and put the EVs specifically in defence?  Then it's 16% to physicals (and 34% to special hits).  This is solid physical durability (which is to say, with EVs some pokemon like Cresselia can be more durable to physicals, but they need supporting EVs).  Okay, so that's decent as a physical wall.

So...in conclusion...back when Caterpie could only learn Tackle and String Shot, it would have been NU even if it had an ability that gave it +6 attack, +6 Def, +6 SDef, +6 Speed, Focus Energy, and Aqua Ring at all times.  (And definitely NU if it had auto-Ingrain, due to Ingrain's no-switchout >_>)

SageAcrin

  • WATCH OUT! THAT'S HYDRO PUMP!
  • Moderator
  • Denizen
  • *
  • Posts: 944
  • ...Is it smiling...?
    • View Profile
Re: Theorycrafting! (Because I like competitive metagames too much)
« Reply #32 on: May 16, 2010, 04:59:06 PM »
That is an awesome assessment, although by this point I had enough of an intuitive feel for ze Pokeymons to not really be stunned by the outcome.

(Also read the Magic one but I'm so out of it on Magic, and never was in it for the metagame, so that I can't really comment.)
<RichardHawk> Waddle Dee looks broken.
<TranceHime> Waddle Dee does seem broken.

"Forget other people's feelings, this is fun and life is but a game and we nought but players in it.  CHECKMATE!  King me and that is Uno." - Grefter

AndrewRogue

  • Infinite
  • DL
  • Denizen
  • *
  • Posts: 3079
  • Sadness
    • View Profile
Re: Theorycrafting! (Because I like competitive metagames too much)
« Reply #33 on: May 17, 2010, 07:41:26 AM »
WoW TCG:

Prepping for NACC,  so I figured I might as well talk myself through the process of some decks here, rather then spoil my super secret tech on the correct forums. Please use WoWTCGDB.com to look up the cards if you desire.

HERO: Jonas the Red (Traitor)

Locations
3x The Darkmoon Faire

Quests
4x The Ring of Blood: Brokentoe
4x Darkness Calling
3x Junboxes Needed

Equipment
2x Vengeful Gladiator's Vestments

Master Hero
2x Illidan Stormrage

Abilities
3x Cloak of Shadows
3x Detect Traps
4x Thud
4x Gouge
3x Hateful Strike
3x Carnage
4x Deathblow
4x Surge of Adrenaline
4x Kidney Shot
4x Overkill
3x Gut Shot
3x Raze

A classic deck that didn't really gain much from Scourgewar, I feel. The biggest potential addition is Raze (which allows Jonas to counter rush much earlier, as well as handle Nathanos Blightcaller and Feral Spirit for a bargain), as well as its role as a finishing move, allowing it to further feed Overkill. The lack of it being Instant is a drag, but I think it definitely has a point. Might end up cutting one (since it and Carnage have some overlap), but I think its worth consideration.

Anyhow, the basic deck function is pretty simple. Survive to turn 4/5 (using a combination of Gouge/Thud/Hateful Strike/Raze/Carnage) and then cripple the opposition with Detect Traps (forces the opponent to discard all cards of a chosen type from their hand) or an Overkill (Remove X finishing moves from your graveyard, your opponent discards that many cards, you deal that much damage to opposing heroes and allies and destroy that many equipment). The swing this can generate is absolutely devastating (especially an Overkill landing on a busy board, where, realistically, you can generate a 5+ for one in a lot of circumstances). The quests and resources (minus Junkboxes Needed) allow you to feed Combo/Finishing Moves to the graveyard to make sure you're capable of landing the Overkill when you need it.

The win in the deck is pretty simple. Land a Vestments on Turn 7/8, accelerate out to Illidan (protecting the Vestments with its ability) and win from there.

Overall, the deck is quite solid, possessing a number of answers to a wide array of decktypes (Rush runs into issues with Raze/Carnage/Overkill, Control Decks without interrupts die terribly to Overkill/Detect Traps, Solo runs into massive problems with Thud/Gouge on critical turns). One of the biggest threats to the deck are decks with interrupts that can stop the Vestments or Illidan (such as Warrior or Mage), but neither is an assured loss. Sticking an Overkill or Detect Traps on an early turn can deplete their resources significantly, Junkboxes Needed can help you evaluate threats and an End of Turn Kidney Shot can exhaust their resources, leaving you free to actually play the Vesments, and once they land, things get a lot rougher for both classes). Another major danger, and one that Jonas, unfortunately, is ill-equipped to deal with, are Ongoing Abilities. With no real class based way to remove them, I'm actually wavering a bit on the appropriate answer to them. I'm currently running Cloak of Shadows, believing the Devouring Plague is probably the biggest threat to the deck, but including Shadala instead might be the wiser option. Adam Eternum is a threat as well, but, like Ongoing Abilitiess, is simply one that's very difficult to deal with in a practical manner. Your best bet is to simply keep him under control until later in the game.

All told, Jonas is a very dangerous deck, as the turn 4/5, although easy to identify and predict is, in practice, very difficult to actually deal with, and a landed Vestments/Illidan can often seal the game. Of course, as a classic deck, Jonas is likely to be among the decks to beat at NACC. Still, with its amazingly versatile toolbox of answers and several devastating plays available to it around midgame and lategame, Jonas appears to remain a relative powerhouse in the current field.

metroid composite

  • m_ACac
  • Administrator
  • Denizen
  • *
  • Posts: 4373
    • View Profile
Re: Theorycrafting! (Because I like competitive metagames too much)
« Reply #34 on: May 17, 2010, 07:31:56 PM »
So...an analysis I've been meaning to do for a while...

Scizor


The single most used pokemon in the OU metagame; as of the most recent statistics, used on 29% of OU teams (way ahead of the next highest pokemon), and 24% of Uber teams (though entertainingly, in January Scizor's Uber usage percentage was higher than its OU use percentage--24% is a drop).

And yet, this is a pokemon with a BST of 500.  What's going on?  I mean, yes, the typing is good (although there's plenty of Steel/x pokemon with 600 BST) and the stats are decently distributed, but there's obviously more going on here.  Let's investigate.

U-Turn
This can be argued as the best move in the game.  As I mentioned earlier in the topic, I've seen setups that run Baton Pass with no stat raising moves just to scout the opponent's switch-in.  U-Turn does that but with damage.  In fact 70 power isn't a joke (people use Hidden Power) and with typing that hits some notable weaknesses (one of two ways to hit Dark, and hitting Psychic is always good).  And of course, all sorts of random pokemon learn it...Articuno, Celebi, Infernape, Flygon, Raticate, and tons of others....  So...with all that, Scizor must have a fair bit of competition for best U-Turn user...right?

Nope.

U-Turn damage from Adamant with no item vs 250 defence
#1: Scizor: 130
#2: Scyther: 117
#3: Mothim: 106
#4: Ninjask: 101
#5: Vespiqueen: 94
#5: Beedrill: 94
#7: Yanmega: 92
#8: Volbeat: 90
#9: Beautifly: 87
#10: Azelf: 85

Why do I not bold the various bugs in the middle?  Because all except Beedrill and Volbeat take 50% damage from stealth rocks (compared to Scizor's 12.5%)--this doesn't make them unusable as pokemon necessarily, but makes U-Turn spam kinda impractical because it implies switching out.  (As for Beedrill and Volbeat, they have 385 BST and 400 BST respectively--they're not going to see use).  And as for abilities that might boost U-Turn, well...there's Yanmega's Tinted Lens, which admittedly is pretty cool (outdamages Scizor when the target resists bug) so...sure, physically based U-Turn Yanmega poses some damage competition if you're not worried about the 50% stealth rocks damage.... >_>

For all practical purposes, though, if you plan to switch in and U-Turn out a lot, then Scizor is way ahead of the competition in damage (by like...52% damage).

Priority Moves assuming Adamant no-item vs 250 Defence
Absol's Sucker Punch: 148 (NOTE: fails if the opponent doesn't use a damage move)
(Arceus ExtremeSpeed: 140)
Scizor Technician Bullet Punch: 112
(Rayquaza ExtremeSpeed: 110)
Dragonite ExtremeSpeed: 102
Ambipom's Technician Fake Out: 94 (Fake out can only be used the first turn on the battlefield, of course)
Hitmontop's Technician Mach Punch: 90
Azumarill Huge Power Aqua Jet: 83
Mammoswine's Ice Shard: 75
Staraptor's Quick Attack: 70
Banette's Shadow Sneak: 69
Lucario's Vacuum Wave: 69

That's the best damage available for each priority move, near as I can tell.  I'm inclined to treat Sucker Punch as a different style of move (requires proper prediction or it fails completely).  Which means...Scizor's Bullet Punch is the highest damage priority move in OU...and in fact the highest damage priority move in Ubers right now (last I checked they're still not allowing Arceus on Shoddy Ubers due to implementation issues).  And just for the fun of it...Swords Dance + priority moves is generally a strong strategy...and Scizor gets Swords Dance!

Other Stuff

Pursuit is another neat move that messes with switching (kills your opponent while they switch out).  While Scizor's not the best user of it (Tyranitar is) Scizor deals about the same damage as Tyranitar if the opponent stays in thanks to Technician.  (Deals less if the opponent switches, though...for all that switching out is still the more painful move for the opponent).

Roost.  Why not have fantastic healing too?

Swords Dance.  (Excellent stat boosting?  Sure).

Decent fighting moves (Superpower and Brick Break).

Technician Bug Bite (make fun of all those physical bugs using the 80 power X-Scissor.  Technician makes this a 90 power physical move that eats opposing berries).

10 resistances, and one weakness (4x weak, to be fair).

Reasonable stat distribution for what it does (focuses on just one attack stat.  Doesn't put too many stats in speed...which is quite acceptable on a priority user).

EDIT: And as Elfboy points out, Baton Pass (and a lot of durability for a pokemon that has Swords Dance, Agility, and Baton Pass).


To be honest, nothing in this "other stuff" section is all that gamebreaking (particularly on a 500 BST pokemon).  If you removed U-Turn and Bullet Punch from Scizor's list, it would...perhaps still get used due to the other perks outlined here, but I would expect the use percentage to be dramatically lower.  Still, though, perks are perks; they help.

Conclusion

Scizor, while all-around solid in other ways, is just made uniquely good at a couple of tools.  And bafflingly so--for U-Turn, it's not like there aren't high-power bugs that don't take 50% from Stealth Rocks--Armaldo, Heracross, and Pinsir all have almost the attack stat of Scizor, take 12.5%-25% from Stealth Rocks...and don't get U-Turn for some reason (when tons of non-bugs do).  Similarly, with Technician, Scizor has the highest attack stat and highest stat total among pokemon with Technician (the runner up being Scyther, who doesn't get STAB priority, followed by Ambipom who only gets Fake Out for priority, and finally Hitmontop who does get STAB priority, but whom Scizor beats by 37% in attack stat).  So...not the highest overall stats, but despite this the best by a good margin at two very relevant mechanics.
« Last Edit: May 18, 2010, 03:31:16 PM by metroid composite »

AndrewRogue

  • Infinite
  • DL
  • Denizen
  • *
  • Posts: 3079
  • Sadness
    • View Profile
Re: Theorycrafting! (Because I like competitive metagames too much)
« Reply #35 on: May 18, 2010, 12:23:07 AM »
Yeeeeeeeeeep. You pretty much hit the proverbial nail on the head with Scizor. Powerful U-Turn and Bullet Punch are stupid good, as is the ability to Swords Dance. I recently switched from using a banded one and even I was shocked at how stupid it was. On a related note, how decent is Scizor's coverage potential with the standard set? I'm blanking off-hand.

metroid composite

  • m_ACac
  • Administrator
  • Denizen
  • *
  • Posts: 4373
    • View Profile
Re: Theorycrafting! (Because I like competitive metagames too much)
« Reply #36 on: May 18, 2010, 03:51:53 AM »
On a related note, how decent is Scizor's coverage potential with the standard set? I'm blanking off-hand.

Standard being Choice Band with U-Turn, Bullet Punch, SuperPower, and Pursuit?

Going down the most used pokemon...

Scizor: 1x
Tyranitar: 4x (2x with priority)
Salamence: 1x
Heatran: 2x
Gyarados: 1x (only with Pursuit)
Latias: 2x
Rotom: 2x
Gengar: 2x
Metagross: 1x
Swampert: 1x
Jirachi: 1x
Infernape: 1x
Lucario: 2x
Starmie: 2x
Blissey: 2x
Skarmory: 1x
Machamp: 1x
Gliscor: 1x
Breloom: 1x
Azelf: 2x
Vaporeon: 1x
Magnezone: 2x
Suicune: 1x
Jolteon: 1x
Bronzong: 1x
Flygon: 1x
Celebi: 4x
Dragonite: 1x
Togekiss: 1x
Aerodactyl: 2x
Kingdra: 1x
Zapdos: 1x (only with Pursuit)
Forretress: 1x
Empoleon: 2x
Electivire: 1x
Weavile: 4x (2x with priority)
Dusknoir: 2x
(And those are all the pokemon above 5% usage)

So...can hit basically anything for neutral.  Would like to hit weakness a bit more often, though, especially on Flying.  (Flying in particular tends to stump Scizor, as it reduces both Fighting and Bug while not being weak to Dark or Steel, and there's lots of Flying pokemon).  A few other common types are just...1x to everything Scizor does (Dragon, Ground) or a mixture of 1x and a resistance or two (Fighting, Water, Electric, Fire, Bug, Poison).

So hmm...can't do better than neutral against 9/17 types.  That's actually not spectacular for four different moves of coverage (in fact, you can actually do better with just two types: Ice+Ground gives better coverage than that.  Go...Mamoswine?)

Dark Holy Elf

  • DL
  • Denizen
  • *
  • Posts: 8134
  • Well-behaved women seldom make history
    • View Profile
Re: Theorycrafting! (Because I like competitive metagames too much)
« Reply #37 on: May 18, 2010, 02:39:45 PM »
Don't forget Baton Pass in Scizor's other stuff. He's pretty tough by the standards of pokemon who get both Swords Dance and Baton Pass (Agility as well if you wish), and opponents have to respect what he can do on his own - bringing in a roarer doesn't do much good when it gets its face melted by a Swords Dance Bullet Punch instead of the expected BP. It's far from its best set, particularly in Gen4 (bad synergy with U-Turn), but still a pretty scary option for it to have.

Erwin Schrödinger will kill you like a cat in a box.
Maybe.

metroid composite

  • m_ACac
  • Administrator
  • Denizen
  • *
  • Posts: 4373
    • View Profile
Re: Theorycrafting! (Because I like competitive metagames too much)
« Reply #38 on: May 18, 2010, 06:28:08 PM »
So...type chart analysis.  I started wondering...let's say you want to hit weakness on as many mono-types as possible.  Given 1-4 move slots, what do you choose?

I should probably pause to note that this is mostly an academic exercise.  Say you're Rotom trying to hit weakness on Blissey--it's not really worthwhile to pull out Hidden Power Fighting...because STAB Thunderbolt deals the same damage.  (Granted, you might still use HP Fighting to hit 4x weak on Tyranitar, but dual types are more complicated).

So...let's hop into this.

Most type weaknesses hit with one move
5 types: Fighting
5 types: Ground
4 types: Fire
4 types: Ice
4 types: Rock

Most type weaknesses hit with two moves
9 types: Ice+Fighting
9 types: Ice+Ground
8 types: Ground+Fighting
8 types: Ground+Flying
8 types: Ground+Fire
8 types: Ground+Bug
8 types: Ground+Rock
8 types: Fighting+Flying
8 types: Fighting+Rock

Most type weaknesses hit with three moves
12 types: Ice+Ground+Fighting
11 types: Ice+Ground+Flying
11 types: Ice+Fighting+Flying
11 types: Ice+Ground+Fire
11 types: Ice+Ground+Bug
11 types: Ice+Ground+Rock
11 types: Ice+Fighting+Rock
11 types: Ice+Ground+Ghost
11 types: Ice+Fighting+Ghost
11 types: Ice+Ground+Dark
11 types: Ice+Fighting+Dark
11 types: Ice+Fighting+Psychic
11 types: Ground+Fighting+Flying
11 types: Ground+Bug+Rock

Most type weaknesses hit with four moves
14 types: Ice+Ground+Fighting+Flying
14 types: Ice+Ground+Fighting+Ghost
14 types: Ice+Ground+Fighting+Dark
13 types: Ice+Ground+Fighting+Fire
13 types: Ice+Ground+Fighting+Electric
13 types: Ice+Ground+Fighting+Grass
13 types: Ice+Ground+Fighting+Psychic
13 types: Ice+Ground+Fighting+Rock
13 types: Ice+Ground+Fighting+Bug
13 types: Ice+Ground+Flying+Bug
13 types: Ice+Ground+Flying+Ghost
13 types: Ice+Ground+Flying+Dark
13 types: Ice+Fighting+Flying+Ghost
13 types: Ice+Fighting+Flying+Dark
13 types: Ice+Ground+Fire+Bug
13 types: Ice+Ground+Fire+Ghost
13 types: Ice+Ground+Fire+Dark
13 types: Ice+Ground+Bug+Rock
13 types: Ice+Ground+Rock+Ghost
13 types: Ice+Ground+Rock+Dark
13 types: Ice+Fighting+Rock+Psychic
13 types: Ice+Fighting+Rock+Ghost
13 types: Ice+Fighting+Rock+Dark
13 types: Ice+Fighting+Psychic+Ghost
13 types: Ice+Fighting+Psychic+Dark
13 types: Ground+Fighting+Flying+Electric
13 types: Ground+Fighting+Flying+Grass
13 types: Ground+Fighting+Flying+Ghost
13 types: Ground+Fighting+Flying+Dark
13 types: Ground+Bug+Rock+Grass


Note: I did this all by hand, so I'm not 100% sure I've hit all the combinations.  Kinda want to go write some code to verify.

metroid composite

  • m_ACac
  • Administrator
  • Denizen
  • *
  • Posts: 4373
    • View Profile
Re: Theorycrafting! (Because I like competitive metagames too much)
« Reply #39 on: May 19, 2010, 12:39:56 AM »
Okay girls and boys, it's coding time!  As my thoughts no longer belong to Activision, I see no danger in just openly posting code.  This post won't be that exciting, mind you, as I'm just making sure that my basics are working (functional type chart, functional looping over the elements, etc).  Programming language chosen: Python--it's comfy and easy to wear...and besides I need practice with it as it's becoming relevant.

Code: [Select]
print "hello world"
#        [No,Fr,Wa,El,Gs,Ic,Ft,Po,Gd,Fl,Ps,Bu,Ro,Gh,Dr,Da,St]
Types = [[ 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1],
         [ 1,.5, 2, 1,.5,.5, 1, 1, 2, 1, 1,.5, 2, 1, 1, 1,.5],
         [ 1,.5,.5, 2, 2,.5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,.5],
         [ 1, 1, 1,.5, 1, 1, 1, 1, 2,.5, 1, 1, 1, 1, 1, 1,.5],
         [ 1, 2,.5,.5,.5, 2, 1, 2,.5, 2, 1, 2, 1, 1, 1, 1, 1],
         [ 1, 2, 1, 1, 1,.5, 2, 1, 1, 1, 1, 1, 2, 1, 1, 1, 2],
         [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2,.5,.5, 1, 1,.5, 1],
         [ 1, 1, 1, 1,.5, 1,.5,.5, 2, 1, 2,.5, 1, 1, 1, 1, 1],
         [ 1, 1, 2, 0, 2, 2, 1,.5, 1, 1, 1, 1,.5, 1, 1, 1, 1],
         [ 1, 1, 1, 2,.5, 2,.5, 1, 0, 1, 1,.5, 2, 1, 1, 1, 1],
         [ 1, 1, 1, 1, 1, 1,.5, 1, 1, 1,.5, 2, 1, 2, 1, 2, 1],
         [ 1, 2, 1, 1,.5, 1,.5, 1,.5, 2, 1, 1, 2, 1, 1, 1, 1],
         [.5,.5, 2, 1, 2, 1, 2,.5, 2,.5, 1, 1, 1, 1, 1, 1, 2],
         [ 0, 1, 1, 1, 1, 1, 0,.5, 1, 1, 1,.5, 1, 2, 1, 2, 1],
         [ 1,.5,.5,.5,.5, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1],
         [ 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 0, 2, 1,.5, 1,.5, 1],
         [.5, 2, 1, 1,.5,.5, 2, 0, 2,.5,.5,.5,.5,.5,.5,.5,.5]]
typenames = ["Normal","Fire","Water","Electric","Grass","Ice",
             "Fighting","Poison","Ground","Flying","Psychic","Bug",
             "Rock","Ghost","Dragon","Dark","Steel"]
print len(Types), "and"
for i in range(0,len(Types)):
    weak = 0
    strong = 0
    null = 0   
    for j in range(0,len(Types[i])):
        if( Types[i][j] == 2 ):
            weak = weak+1
        elif( Types[i][j] == 0.5 ):
            strong = strong+1
        elif( Types[i][j] == 0 ):
            null = null+1
        elif( Types[i][j] != 1 ):
            print "ERROR ", i, j, " fails"
    print typenames[i], " has ", weak, " weaknesses ", strong, " defences and ", null, " nulls."

In particular, I wrote out my little type chart by hand, and would be shocked if I didn't typo in the process.  Let's see if it holds up...

Quote
Normal  has  1  weaknesses  0  defences and  1  nulls.
Fire  has  3  weaknesses  5  defences and  0  nulls.
Water  has  2  weaknesses  4  defences and  0  nulls.
Electric  has  1  weaknesses  3  defences and  0  nulls.
Grass  has  5  weaknesses  4  defences and  0  nulls.
Ice  has  4  weaknesses  1  defences and  0  nulls.
Fighting  has  2  weaknesses  3  defences and  0  nulls.
Poison  has  2  weaknesses  4  defences and  0  nulls.
Ground  has  3  weaknesses  2  defences and  1  nulls.
Flying  has  3  weaknesses  3  defences and  1  nulls.
Psychic  has  3  weaknesses  2  defences and  0  nulls.
Bug  has  3  weaknesses  3  defences and  0  nulls.
Rock  has  5  weaknesses  4  defences and  0  nulls.
Ghost  has  2  weaknesses  2  defences and  2  nulls.
Dragon  has  2  weaknesses  4  defences and  0  nulls.
Dark  has  2  weaknesses  2  defences and  1  nulls.
Steel  has  3  weaknesses  11  defences and  1  nulls.

Crosschecking with my post on the previous page, it looks okay so far (and actually brings up an error with the previous post--Steel should be +10 on defence, not +8 >_>).  Let's check offence real quick.

Code: [Select]
    for j in range(0,len(Types[i])):
        if( Types[j][i] == 2 ):
            weak = weak+1
        elif( Types[j][i] == 0.5 ):
            strong = strong+1
        elif( Types[j][i] == 0 ):
            null = null+1
        elif( Types[j][i] != 1 ):
            print "ERROR ", i, j, " fails"
    print typenames[i], " hits ", weak, " weaknesses ", strong, " resistances and ", null, " nulls."

Changing a pretty minimal amount of code (which nevertheless proves to me I should have used a switch statement.  *smacks fingers* bad coding practices) we get...

Quote
Normal  hits  0  weaknesses  2  resistances and  1  nulls.
Fire  hits  4  weaknesses  4  resistances and  0  nulls.
Water  hits  3  weaknesses  3  resistances and  0  nulls.
Electric  hits  2  weaknesses  3  resistances and  1  nulls.
Grass  hits  3  weaknesses  7  resistances and  0  nulls.
Ice  hits  4  weaknesses  4  resistances and  0  nulls.
Fighting  hits  5  weaknesses  4  resistances and  1  nulls.
Poison  hits  1  weaknesses  4  resistances and  1  nulls.
Ground  hits  5  weaknesses  2  resistances and  1  nulls.
Flying  hits  3  weaknesses  3  resistances and  0  nulls.
Psychic  hits  2  weaknesses  2  resistances and  1  nulls.
Bug  hits  3  weaknesses  6  resistances and  0  nulls.
Rock  hits  4  weaknesses  3  resistances and  0  nulls.
Ghost  hits  2  weaknesses  2  resistances and  1  nulls.
Dragon  hits  1  weaknesses  1  resistances and  0  nulls.
Dark  hits  2  weaknesses  3  resistances and  0  nulls.
Steel  hits  2  weaknesses  4  resistances and  0  nulls.

Yeah, okay, I think this type chart is typo free, and ready for some analysis calculations.  (Wait, did I really make no typos?  Shocking!)

Dark Holy Elf

  • DL
  • Denizen
  • *
  • Posts: 8134
  • Well-behaved women seldom make history
    • View Profile
Re: Theorycrafting! (Because I like competitive metagames too much)
« Reply #40 on: May 19, 2010, 12:52:27 AM »
Quote
As my thoughts no longer belong to Activision

Yay!

Generally speaking I'd say it's more important to avoid resistances than hit weaknesses so you can't be forced to switch out, though it does vary on the pokemon (e.g. revenge killers). Also it might be more practical to count not types, but the typings (including any duals) of all OU pokemon (or uber, or whatever).

Erwin Schrödinger will kill you like a cat in a box.
Maybe.

metroid composite

  • m_ACac
  • Administrator
  • Denizen
  • *
  • Posts: 4373
    • View Profile
Re: Theorycrafting! (Because I like competitive metagames too much)
« Reply #41 on: May 19, 2010, 02:41:43 AM »
Quote
As my thoughts no longer belong to Activision

Yay!

Generally speaking I'd say it's more important to avoid resistances than hit weaknesses so you can't be forced to switch out, though it does vary on the pokemon (e.g. revenge killers). Also it might be more practical to count not types, but the typings (including any duals) of all OU pokemon (or uber, or whatever).

Yeah, I was thinking I'd do something like that as a second pass.  Like...average up the best multiplier (4, 2, 1, 0.5, 0.25, 0) for the highly frequent type combinations in OU.  And more specifically on the "avoid resistances" point, I was thinking take the reciprocal of the multiplier, so 2 for a resist, and 4 for an R4.  I do have a question on that note: any recommendations for defining 1/0?  Hypothetically there could be a move that hit 49/50 OU pokemon for at least neutral, and got nulled by the 50th pokemon...and offhand that doesn't feel like horrible coverage that averages to infinite resist.  I'm thinking setting 1/0 to 8 or something.

(Or alternatively, if you feel the reciprocal is not the ideal function for the job of "avoid resistances", what would you recommend?)

hinode

  • Enough expository banter! Now we fight like men!
  • DL
  • Denizen
  • *
  • Posts: 1352
  • And ladies! And ladies who dress like men!
    • View Profile
Re: Theorycrafting! (Because I like competitive metagames too much)
« Reply #42 on: May 19, 2010, 03:12:56 AM »
The general rule of thumb is that you want to maximize neutrality for STAB type(s) and super effective hits for non-STAB types, though with extra consideration for getting super-effective hits on stuff that resist your STABs. This is one reason why mono-Water types with Ice Beam are much more effective than any Ice type. Walls with sufficiently low offensive stats tend to go purely for type coverage since they can't do enough damage unless it's super-effective anyhow.

As far as metagame-specific numbers, X-Act has previously calculated which attacking types did best for each metagame based on the proportional usage for each ladder. The results from the last set of numbers are here:

http://www.smogon.com/smog/issue3/attacking_types

This was eight months ago, but I doubt the general results (i.e. special Fire being the best type in OU) will have changed much - especially in the standard metagame, which is pretty stable.

metroid composite

  • m_ACac
  • Administrator
  • Denizen
  • *
  • Posts: 4373
    • View Profile
Re: Theorycrafting! (Because I like competitive metagames too much)
« Reply #43 on: May 19, 2010, 04:42:44 AM »
As far as metagame-specific numbers, X-Act has previously calculated which attacking types did best for each metagame based on the proportional usage for each ladder. The results from the last set of numbers are here:

http://www.smogon.com/smog/issue3/attacking_types

This was eight months ago, but I doubt the general results (i.e. special Fire being the best type in OU) will have changed much - especially in the standard metagame, which is pretty stable.

Me calculating something that's already known in Pokemon?  Unpossible!!!!

(Also, what I'm calculating is more about how well multiple types overlap to cover each other, whereas X-Act's work looks to be calculating how well a single type does in the metagame).

Now, it's possible I want to use X-Act's formula...hmm...actually no, I doubt it.  Just skimming quickly, X-Act basically calculates "what percentage of this pokemon's HP do you deal?" and then averages those together weighted by usage statistics.  Problem is, let's say all the Grass pokemon in the format are super frail (hi Breloom) and all the water pokemon are jacked up on HP and defences (hi Suicune).  Fire moves get a big boost from the frail grass pokemon, whereas Grass moves still don't hit Suicune that hard because it's so tanky, so don't get much credit.  If anything, I feel like it should be the other way around (hitting a weakness on a tank should score you more points than horribly overkilling a frail Pokemon).  That said, one step at a time--I'm still a few iterations away from worrying about whether and how I want to factor stats into the equation.



Anyhow, managed to recreate my "how many mono-type weaknesses are available to X moves" scenario above.  Python arrays appear to be more C++ish than I initially expected from a scripting language (in that they basically work like pointers if you assign them to each other, for instance) so you get to see all my band-aid "wait, wtf?  Okay, let's hack around that" moments and some fairly ugly code as a result.  But it's a first pass and I just wanted to make sure the "take the best of X attack moves" calculations actually sorted properly and stuff.

Code: [Select]
print "hello world"
#        [No,Fr,Wa,El,Gs,Ic,Ft,Po,Gd,Fl,Ps,Bu,Ro,Gh,Dr,Da,St]
Types = [[ 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1],
         [ 1,.5, 2, 1,.5,.5, 1, 1, 2, 1, 1,.5, 2, 1, 1, 1,.5],
         [ 1,.5,.5, 2, 2,.5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,.5],
         [ 1, 1, 1,.5, 1, 1, 1, 1, 2,.5, 1, 1, 1, 1, 1, 1,.5],
         [ 1, 2,.5,.5,.5, 2, 1, 2,.5, 2, 1, 2, 1, 1, 1, 1, 1],
         [ 1, 2, 1, 1, 1,.5, 2, 1, 1, 1, 1, 1, 2, 1, 1, 1, 2],
         [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2,.5,.5, 1, 1,.5, 1],
         [ 1, 1, 1, 1,.5, 1,.5,.5, 2, 1, 2,.5, 1, 1, 1, 1, 1],
         [ 1, 1, 2, 0, 2, 2, 1,.5, 1, 1, 1, 1,.5, 1, 1, 1, 1],
         [ 1, 1, 1, 2,.5, 2,.5, 1, 0, 1, 1,.5, 2, 1, 1, 1, 1],
         [ 1, 1, 1, 1, 1, 1,.5, 1, 1, 1,.5, 2, 1, 2, 1, 2, 1],
         [ 1, 2, 1, 1,.5, 1,.5, 1,.5, 2, 1, 1, 2, 1, 1, 1, 1],
         [.5,.5, 2, 1, 2, 1, 2,.5, 2,.5, 1, 1, 1, 1, 1, 1, 2],
         [ 0, 1, 1, 1, 1, 1, 0,.5, 1, 1, 1,.5, 1, 2, 1, 2, 1],
         [ 1,.5,.5,.5,.5, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1],
         [ 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 0, 2, 1,.5, 1,.5, 1],
         [.5, 2, 1, 1,.5,.5, 2, 0, 2,.5,.5,.5,.5,.5,.5,.5,.5]]
typenames = ["Normal","Fire","Water","Electric","Grass","Ice",
             "Fighting","Poison","Ground","Flying","Psychic","Bug",
             "Rock","Ghost","Dragon","Dark","Steel"]
nummoves = 4
moves = []
for i in range(0,nummoves):
    moves.append(nummoves - i - 1)
print moves
tophitters = []
while True:

    total_hit = 0;
    for i in range(0,len(Types)):
        for j in range(0,len(moves)):
            if( Types[i][moves[j]] > 1 ):
                total_hit = total_hit + 1
                break
    #print moves, " deal ", total_hit

    #okay, this is hacky, but I haven't touched python in a while, so...
    #the first number in the array will be how well the moves perform (for
    #sorting purposes) and the next X numbers in the array will be the
    #moves.
    temparray = []
    temparray.append(total_hit)
    for i in range(0,len(moves)):
        temparray.append(moves[i])
    tophitters.append(temparray)
    if(len(tophitters) > 32):
        tophitters.sort()
        tophitters.pop(0)

    #increment the move list; this is a basic n choose r construction
    #we move the first variable all the way to the top, and then we
    #increment the second variable and reset the first variable to
    #be just to the right of the second (avoids repeats).
    shouldexit = True
    for i in range(0,len(moves)):
        if( moves[i] < 16-i ): #17 types, but array indexing means we don't want to increment if we're at 16
            moves[i] = moves[i]+1
            shouldexit = False;
            for j in range(0, i):
                moves[j] = moves[i]+(i-j)
            break
    if shouldexit:
        break
    #print moves
    #Right, remember there's nothing special going on in the above code,
    #just iterating over all possible combinations of X different moves,
    #where X is nummoves.  The above code is just dealing with the fact
    #that we don't know X, so can't just write 4 nested for loops.

print "WE MADE IT"
print tophitters

tophitters.sort()
for i in range(0,len(tophitters)):
    #translate from array indices into english.  Again, remember we don't
    #know the number of moves, hence the for loop.
    englishnames = []
    for j in range(1,len(tophitters[i])):
        englishnames.append(typenames[tophitters[i][j]])
        
    #remember the hacky I mentioned above?  The first number in the array
    #is how well this move combination did, and not actually a move.
    #Yeah, I know: cringeworthy code.
    print tophitters[i][0], ": ", englishnames
    

And confirming with my previous hand-calculations, it does work:

Code: [Select]
6 :  ['Dark', 'Fire']
6 :  ['Dark', 'Ice']
6 :  ['Dark', 'Rock']
6 :  ['Steel', 'Ice']
6 :  ['Steel', 'Ground']
7 :  ['Water', 'Fire']
7 :  ['Grass', 'Fire']
7 :  ['Ice', 'Fire']
7 :  ['Fighting', 'Fire']
7 :  ['Fighting', 'Water']
7 :  ['Fighting', 'Electric']
7 :  ['Fighting', 'Grass']
7 :  ['Ground', 'Electric']
7 :  ['Ground', 'Grass']
7 :  ['Psychic', 'Fighting']
7 :  ['Bug', 'Fighting']
7 :  ['Rock', 'Grass']
7 :  ['Rock', 'Ice']
7 :  ['Rock', 'Bug']
7 :  ['Ghost', 'Fighting']
7 :  ['Ghost', 'Ground']
7 :  ['Dark', 'Fighting']
7 :  ['Dark', 'Ground']
8 :  ['Ground', 'Fire']
8 :  ['Ground', 'Fighting']
8 :  ['Flying', 'Fighting']
8 :  ['Flying', 'Ground']
8 :  ['Bug', 'Ground']
8 :  ['Rock', 'Fighting']
8 :  ['Rock', 'Ground']
9 :  ['Fighting', 'Ice']
9 :  ['Ground', 'Ice']


10 :  ['Rock', 'Flying', 'Fighting']
10 :  ['Rock', 'Flying', 'Ground']
10 :  ['Rock', 'Psychic', 'Fighting']
10 :  ['Rock', 'Bug', 'Grass']
10 :  ['Rock', 'Bug', 'Fighting']
10 :  ['Ghost', 'Ground', 'Fire']
10 :  ['Ghost', 'Ground', 'Fighting']
10 :  ['Ghost', 'Flying', 'Fighting']
10 :  ['Ghost', 'Flying', 'Ground']
10 :  ['Ghost', 'Rock', 'Fighting']
10 :  ['Ghost', 'Rock', 'Ground']
10 :  ['Dark', 'Ground', 'Fire']
10 :  ['Dark', 'Ground', 'Fighting']
10 :  ['Dark', 'Flying', 'Fighting']
10 :  ['Dark', 'Flying', 'Ground']
10 :  ['Dark', 'Rock', 'Fighting']
10 :  ['Dark', 'Rock', 'Ground']
10 :  ['Steel', 'Ground', 'Ice']
11 :  ['Ground', 'Ice', 'Fire']
11 :  ['Flying', 'Fighting', 'Ice']
11 :  ['Flying', 'Ground', 'Ice']
11 :  ['Flying', 'Ground', 'Fighting']
11 :  ['Psychic', 'Fighting', 'Ice']
11 :  ['Bug', 'Ground', 'Ice']
11 :  ['Rock', 'Fighting', 'Ice']
11 :  ['Rock', 'Ground', 'Ice']
11 :  ['Rock', 'Bug', 'Ground']
11 :  ['Ghost', 'Fighting', 'Ice']
11 :  ['Ghost', 'Ground', 'Ice']
11 :  ['Dark', 'Fighting', 'Ice']
11 :  ['Dark', 'Ground', 'Ice']
12 :  ['Ground', 'Fighting', 'Ice']



12 :  ['Steel', 'Ghost', 'Ground', 'Ice']
12 :  ['Steel', 'Dark', 'Ground', 'Ice']
13 :  ['Ground', 'Fighting', 'Ice', 'Fire']
13 :  ['Ground', 'Fighting', 'Ice', 'Electric']
13 :  ['Ground', 'Fighting', 'Ice', 'Grass']
13 :  ['Flying', 'Ground', 'Fighting', 'Electric']
13 :  ['Flying', 'Ground', 'Fighting', 'Grass']
13 :  ['Psychic', 'Ground', 'Fighting', 'Ice']
13 :  ['Bug', 'Ground', 'Ice', 'Fire']
13 :  ['Bug', 'Ground', 'Fighting', 'Ice']
13 :  ['Bug', 'Flying', 'Ground', 'Ice']
13 :  ['Rock', 'Ground', 'Fighting', 'Ice']
13 :  ['Rock', 'Psychic', 'Fighting', 'Ice']
13 :  ['Rock', 'Bug', 'Ground', 'Grass']
13 :  ['Rock', 'Bug', 'Ground', 'Ice']
13 :  ['Ghost', 'Ground', 'Ice', 'Fire']
13 :  ['Ghost', 'Flying', 'Fighting', 'Ice']
13 :  ['Ghost', 'Flying', 'Ground', 'Ice']
13 :  ['Ghost', 'Flying', 'Ground', 'Fighting']
13 :  ['Ghost', 'Psychic', 'Fighting', 'Ice']
13 :  ['Ghost', 'Rock', 'Fighting', 'Ice']
13 :  ['Ghost', 'Rock', 'Ground', 'Ice']
13 :  ['Dark', 'Ground', 'Ice', 'Fire']
13 :  ['Dark', 'Flying', 'Fighting', 'Ice']
13 :  ['Dark', 'Flying', 'Ground', 'Ice']
13 :  ['Dark', 'Flying', 'Ground', 'Fighting']
13 :  ['Dark', 'Psychic', 'Fighting', 'Ice']
13 :  ['Dark', 'Rock', 'Fighting', 'Ice']
13 :  ['Dark', 'Rock', 'Ground', 'Ice']
14 :  ['Flying', 'Ground', 'Fighting', 'Ice']
14 :  ['Ghost', 'Ground', 'Fighting', 'Ice']
14 :  ['Dark', 'Ground', 'Fighting', 'Ice']

Next up, more sophisticated calculations than "got super effective?"
« Last Edit: May 19, 2010, 04:44:18 AM by metroid composite »

metroid composite

  • m_ACac
  • Administrator
  • Denizen
  • *
  • Posts: 4373
    • View Profile
Re: Theorycrafting! (Because I like competitive metagames too much)
« Reply #44 on: May 19, 2010, 10:39:58 PM »
Okay, first things first I need an OU typechart, and cleanest way to get it is just to calculate it.  Abilities like Flash Fire and Volt Absorb I treated the same way as levitate for type purposes (just nullify the move) seeing as walled is walled.  Usually there was an obvious most common ability in OU, so I used that, though for even usage splits, I just took an average.  Anyhow, the code to get the typechart (types and abilities entered by hand, so hypothetically could have errors).

Code: [Select]
#        [No,Fr,Wa,El,Gs,Ic,Ft,Po,Gd,Fl,Ps,Bu,Ro,Gh,Dr,Da,St]
Types = [[ 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1],
         [ 1,.5, 2, 1,.5,.5, 1, 1, 2, 1, 1,.5, 2, 1, 1, 1,.5],
         [ 1,.5,.5, 2, 2,.5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,.5],
         [ 1, 1, 1,.5, 1, 1, 1, 1, 2,.5, 1, 1, 1, 1, 1, 1,.5],
         [ 1, 2,.5,.5,.5, 2, 1, 2,.5, 2, 1, 2, 1, 1, 1, 1, 1],
         [ 1, 2, 1, 1, 1,.5, 2, 1, 1, 1, 1, 1, 2, 1, 1, 1, 2],
         [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2,.5,.5, 1, 1,.5, 1],
         [ 1, 1, 1, 1,.5, 1,.5,.5, 2, 1, 2,.5, 1, 1, 1, 1, 1],
         [ 1, 1, 2, 0, 2, 2, 1,.5, 1, 1, 1, 1,.5, 1, 1, 1, 1],
         [ 1, 1, 1, 2,.5, 2,.5, 1, 0, 1, 1,.5, 2, 1, 1, 1, 1],
         [ 1, 1, 1, 1, 1, 1,.5, 1, 1, 1,.5, 2, 1, 2, 1, 2, 1],
         [ 1, 2, 1, 1,.5, 1,.5, 1,.5, 2, 1, 1, 2, 1, 1, 1, 1],
         [.5,.5, 2, 1, 2, 1, 2,.5, 2,.5, 1, 1, 1, 1, 1, 1, 2],
         [ 0, 1, 1, 1, 1, 1, 0,.5, 1, 1, 1,.5, 1, 2, 1, 2, 1],
         [ 1,.5,.5,.5,.5, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1],
         [ 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 0, 2, 1,.5, 1,.5, 1],
         [.5, 2, 1, 1,.5,.5, 2, 0, 2,.5,.5,.5,.5,.5,.5,.5,.5]]

typenames = ["Normal","Fire","Water","Electric","Grass","Ice",
             "Fighting","Poison","Ground","Flying","Psychic","Bug",
             "Rock","Ghost","Dragon","Dark","Steel"]

OUPokedex = [["Scizor","Bug","Steel","",28.69],
["Tyranitar","Rock","Dark","",21.51],
["Salamence","Flying","Dragon","",20.91],
["Heatran","Fire","Steel","Flash Fire",19.49],
["Gyarados","Water","Flying","",17.35],
["Latias","Psychic","Dragon","Levitate",16.9],
["Gengar","Poison","Ghost","Levitate",15.97],
["Metagross","Psychic","Steel","",15.55],
["Swampert","Water","Ground","",15.27],
["Jirachi","Psychic","Steel","",15.2],
["Infernape","Fire","Fighting","",14.15],
["Lucario","Fighting","Steel","",13.47],
["Starmie","Water","Psychic","",12.51],
["Blissey","Normal","","",12.23],
["Skarmory","Flying","Steel","",11.13],
["Machamp","Fighting","","",10.49],
["Gliscor","Ground","Flying","",10.4],
["Breloom","Grass","Fighting","",10.33],
["Azelf","Psychic","","Levitate",9.89],
["Vaporeon","Water","","Water Absorb",9.76],
["Rotom-h","Electric","Ghost","Levitate",9.53],
["Magnezone","Electric","Steel","",9.1],
["Suicune","Water","","",8.11],
["Jolteon","Electric","","Volt Absorb",7.55],
["Bronzong","Psychic","Steel","Levitate",7.34],
["Flygon","Ground","Dragon","Levitate",7.31],
["Celebi","Grass","Psychic","",7.23],
["Dragonite","Flying","Dragon","",7.12],
["Togekiss","Normal","Flying","",7.11],
["Aerodactyl","Flying","Rock","",7.05],
["Kingdra","Water","Dragon","",6.91],
["Zapdos","Electric","Flying","",6.86],
["Forretress","Bug","Steel","",6.69],
["Empoleon","Water","Steel","",6.25],
["Electivire","Electric","","Motor Drive",6.14],
["Weavile","Ice","Dark","",5.69],
["Dusknoir","Ghost","","",5.22],
["Snorlax","Normal","","",4.93],
["Mamoswine","Ice","Ground","",4.93],
["Ninjask","Bug","Flying","",4.8],
["Hippowdon","Ground","","",4.49],
["Tentacruel","Water","Poison","",4.3],
["Roserade","Grass","Poison","",4.04],
["Smeargle","Normal","","",3.96],
["Heracross","Fighting","Bug","",3.79],
["Umbreon","Dark","","",3.6],
["Porygonz","Normal","","",3.16],
["Alakazam","Psychic","","",3.01],
["Rotom-w","Electric","Ghost","Levitate",2.86],
["Rotom-c","Electric","Ghost","Levitate",2.72],
["Abomasnow","Grass","Ice","",2.7],
["Ludicolo","Water","Grass","",2.58],
["Yanmega","Flying","Bug","",2.43],
["Cresselia","Psychic","","Levitate",2.35],
["Crobat","Poison","Flying","",2.33],
["Gallade","Fighting","Psychic","",2.29],
["Arcanine","Fire","","(50% usage) Flash Fire",2.27],
["Dugtrio","Ground","","",2.25],
["Rhyperior","Ground","Rock","Solid Rock",2.24],
["Ambipom","Normal","","",2.23],
["Milotic","Water","","",2.23],
["Froslass","Ice","Ghost","",2.13],
["Clefable","Normal","","",2.05],
["Porygon2","Normal","","",2.04],
["Charizard","Fire","Flying","",1.97],
["Uxie","Psychic","","Levitate",1.9],
["Kabutops","Water","Rock","",1.82],
["Donphan","Ground","","",1.79],
["Slowbro","Water","Psychic","",1.69],
["Honchkrow","Flying","Dark","",1.69],
["Walrein","Water","Ice","",1.63],
["Spiritomb","Ghost","Dark","",1.61],
["Registeel","Steel","","",1.57],
["Blastoise","Water","","",1.55],
["Venusaur","Grass","Poison","",1.49],
["Sceptile","Grass","","",1.47],
["Weezing","Poison","","Levitate",1.41],
["Mismagius","Ghost","","Levitate",1.37],
["Shuckle","Bug","Rock","",1.32],
["Hitmontop","Fighting","","",1.29],
["Claydol","Ground","Psychic","Levitate",1.28],
["Lanturn","Water","Electric","Volt Absorb",1.27],
["Feraligatr","Water","","",1.25],
["Cradily","Grass","Rock","",1.25],
["Electrode","Electric","","",1.23],
["Houndoom","Fire","Dark","Flash Fire",1.22],
["Shaymin","Grass","","",1.2],
["Typhlosion","Fire","","",1.18],
["Marowak","Ground","","",1.12],
["Blaziken","Fire","Fighting","",1.1],
["Raikou","Electric","","",1.1],
["Espeon","Psychic","","",1.05],
["Azumarill","Water","","",1.03],
["Staraptor","Normal","Flying","",1.02],
["Steelix","Ground","Steel","",1.01],
["Miltank","Normal","","",0.99],
["Absol","Dark","","",0.96],
["Aggron","Rock","Steel","",0.88],
["Rotom-f","Electric","Ghost","Levitate",0.88],
["Hariyama","Fighting","","(50% usage) Thick Fat",0.86],
["Tangrowth","Grass","","",0.85],
["Slowking","Water","Psychic","",0.84],
["Drapion","Poison","Dark","",0.84],
["Toxicroak","Poison","Fighting","Dry Skin",0.81],
["Ursaring","Normal","","",0.81],
["Gardevoir","Psychic","","",0.78],
["Drifblim","Flying","Ghost","",0.77],
["Torterra","Grass","Ground","",0.77],
["Cacturne","Grass","Dark","",0.77],
["Glaceon","Ice","","",0.76],
["Medicham","Fighting","Psychic","",0.75],
["Magmortar","Fire","","",0.75],
["Leafeon","Grass","","",0.74],
["Swellow","Normal","Flying","",0.73],
["Rampardos","Rock","","",0.72],
["Mr.Mime","Psychic","","",0.71],
["Ninetales","Fire","","Flash Fire",0.69],
["Nidoking","Poison","Ground","",0.69],
["Slaking","Normal","","",0.68],
["Lapras","Water","Ice","Water Absorb",0.68],
["Qwilfish","Water","Poison","",0.66],
["Exeggutor","Grass","Psychic","",0.65],
["Poliwrath","Water","Fighting","Water Absorb",0.62],
["Jumpluff","Grass","Flying","",0.62],
["Cloyster","Water","Ice","",0.6],
["Floatzel","Water","","",0.6],
["Shedinja","Bug","Ghost","Wonder Guard",0.6],
["Pikachu","Electric","","",0.58]]

def process_ability( ability, list ):
    if( ability == "" ):
        return list
    elif( ability == "Flash Fire" ):
        list[typenames.index("Fire")] = 0
    elif( ability == "Levitate" ):
        list[typenames.index("Ground")] = 0
    elif( ability == "Water Absorb" ):
        list[typenames.index("Water")] = 0
    elif( ability == "Volt Absorb" ):
        list[typenames.index("Electric")] = 0
    elif( ability == "Motor Drive" ):
        list[typenames.index("Electric")] = 0
    elif( ability == "(50% usage) Flash Fire" ):
        list[typenames.index("Fire")] *= 0.5
    elif( ability == "(50% usage) Thick Fat" ):
        list[typenames.index("Fire")] *= 0.75
        list[typenames.index("Ice")] *= 0.75
    elif( ability == "Dry Skin" ):
        list[typenames.index("Fire")] *= 1.25
        list[typenames.index("Water")] = 0
    elif( ability == "Solid Rock" ):
        for i in range(0,len(list)):
            if( list[i] > 1 ):
                list[i] = 0.75*list[i]
    elif( ability == "Wonder Guard" ):
        for i in range(0,len(list)):
            if( list[i] < 2 ):
                list[i] = 0
    else:
        print "ERROR, no such ability"
    return list


OUTypechart = []



for pok in range(0,len(OUPokedex)):
    thispokemon = []
    type1 = typenames.index(OUPokedex[pok][1])
    type2 = -1
    if( OUPokedex[pok][2] != "" ):
        type2 = typenames.index(OUPokedex[pok][2])
    for i in range(0,len(Types)):
        thispokemon.append(Types[type1][i])
        if( type2 != -1 ):
            thispokemon[i] *= Types[type2][i]
    thispokemon = process_ability( OUPokedex[pok][3], thispokemon )
   
    thispokemon.append(OUPokedex[pok][4])
    OUTypechart.append(thispokemon)
       
for i in range (0, len(OUTypechart) ):
    print OUPokedex[i][0], OUTypechart[i]

And checking that it works, here's the result:

Code: [Select]
Scizor [0.5, 4, 1, 1, 0.25, 0.5, 1.0, 0, 1.0, 1.0, 0.5, 0.5, 1.0, 0.5, 0.5, 0.5, 0.5, 28.690000000000001]
Tyranitar [0.5, 0.5, 2, 1, 2, 1, 4, 0.5, 2, 0.5, 0, 2, 1, 0.5, 1, 0.5, 2, 21.510000000000002]
Salamence [1, 0.5, 0.5, 1.0, 0.25, 4, 0.5, 1, 0, 1, 1, 0.5, 2, 1, 2, 1, 1, 20.91]
Heatran [0.5, 0, 2, 1, 0.25, 0.25, 2, 0, 4, 0.5, 0.5, 0.25, 1.0, 0.5, 0.5, 0.5, 0.25, 19.489999999999998]
Gyarados [1, 0.5, 0.5, 4, 1.0, 1.0, 0.5, 1, 0, 1, 1, 0.5, 2, 1, 1, 1, 0.5, 17.350000000000001]
Latias [1, 0.5, 0.5, 0.5, 0.5, 2, 0.5, 1, 0, 1, 0.5, 2, 1, 2, 2, 2, 1, 16.899999999999999]
Gengar [0, 1, 1, 1, 0.5, 1, 0.0, 0.25, 0, 1, 2, 0.25, 1, 2, 1, 2, 1, 15.970000000000001]
Metagross [0.5, 2, 1, 1, 0.5, 0.5, 1.0, 0, 2, 0.5, 0.25, 1.0, 0.5, 1.0, 0.5, 1.0, 0.5, 15.550000000000001]
Swampert [1, 0.5, 1.0, 0, 4, 1.0, 1, 0.5, 1, 1, 1, 1, 0.5, 1, 1, 1, 0.5, 15.27]
Jirachi [0.5, 2, 1, 1, 0.5, 0.5, 1.0, 0, 2, 0.5, 0.25, 1.0, 0.5, 1.0, 0.5, 1.0, 0.5, 15.199999999999999]
Infernape [1, 0.5, 2, 1, 0.5, 0.5, 1, 1, 2, 2, 2, 0.25, 1.0, 1, 1, 0.5, 0.5, 14.15]
Lucario [0.5, 2, 1, 1, 0.5, 0.5, 2, 0, 2, 1.0, 1.0, 0.25, 0.25, 0.5, 0.5, 0.25, 0.5, 13.470000000000001]
Starmie [1, 0.5, 0.5, 2, 2, 0.5, 0.5, 1, 1, 1, 0.5, 2, 1, 2, 1, 2, 0.5, 12.51]
Blissey [1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 12.23]
Skarmory [0.5, 2, 1, 2, 0.25, 1.0, 1.0, 0, 0, 0.5, 0.5, 0.25, 1.0, 0.5, 0.5, 0.5, 0.5, 11.130000000000001]
Machamp [1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 0.5, 0.5, 1, 1, 0.5, 1, 10.49]
Gliscor [1, 1, 2, 0, 1.0, 4, 0.5, 0.5, 0, 1, 1, 0.5, 1.0, 1, 1, 1, 1, 10.4]
Breloom [1, 2, 0.5, 0.5, 0.5, 2, 1, 2, 0.5, 4, 2, 1.0, 0.5, 1, 1, 0.5, 1, 10.33]
Azelf [1, 1, 1, 1, 1, 1, 0.5, 1, 0, 1, 0.5, 2, 1, 2, 1, 2, 1, 9.8900000000000006]
Vaporeon [1, 0.5, 0, 2, 2, 0.5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.5, 9.7599999999999998]
Rotom-h [0, 1, 1, 0.5, 1, 1, 0, 0.5, 0, 0.5, 1, 0.5, 1, 2, 1, 2, 0.5, 9.5299999999999994]
Magnezone [0.5, 2, 1, 0.5, 0.5, 0.5, 2, 0, 4, 0.25, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.25, 9.0999999999999996]
Suicune [1, 0.5, 0.5, 2, 2, 0.5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.5, 8.1099999999999994]
Jolteon [1, 1, 1, 0, 1, 1, 1, 1, 2, 0.5, 1, 1, 1, 1, 1, 1, 0.5, 7.5499999999999998]
Bronzong [0.5, 2, 1, 1, 0.5, 0.5, 1.0, 0, 0, 0.5, 0.25, 1.0, 0.5, 1.0, 0.5, 1.0, 0.5, 7.3399999999999999]
Flygon [1, 0.5, 1.0, 0.0, 1.0, 4, 1, 0.5, 0, 1, 1, 1, 0.5, 1, 2, 1, 1, 7.3099999999999996]
Celebi [1, 2, 0.5, 0.5, 0.5, 2, 0.5, 2, 0.5, 2, 0.5, 4, 1, 2, 1, 2, 1, 7.2300000000000004]
Dragonite [1, 0.5, 0.5, 1.0, 0.25, 4, 0.5, 1, 0, 1, 1, 0.5, 2, 1, 2, 1, 1, 7.1200000000000001]
Togekiss [1, 1, 1, 2, 0.5, 2, 1.0, 1, 0, 1, 1, 0.5, 2, 0, 1, 1, 1, 7.1100000000000003]
Aerodactyl [0.5, 0.5, 2, 2, 1.0, 2, 1.0, 0.5, 0, 0.5, 1, 0.5, 2, 1, 1, 1, 2, 7.0499999999999998]
Kingdra [1, 0.25, 0.25, 1.0, 1.0, 1.0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 0.5, 6.9100000000000001]
Zapdos [1, 1, 1, 1.0, 0.5, 2, 0.5, 1, 0, 0.5, 1, 0.5, 2, 1, 1, 1, 0.5, 6.8600000000000003]
Forretress [0.5, 4, 1, 1, 0.25, 0.5, 1.0, 0, 1.0, 1.0, 0.5, 0.5, 1.0, 0.5, 0.5, 0.5, 0.5, 6.6900000000000004]
Empoleon [0.5, 1.0, 0.5, 2, 1.0, 0.25, 2, 0, 2, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.25, 6.25]
Electivire [1, 1, 1, 0, 1, 1, 1, 1, 2, 0.5, 1, 1, 1, 1, 1, 1, 0.5, 6.1399999999999997]
Weavile [1, 2, 1, 1, 1, 0.5, 4, 1, 1, 1, 0, 2, 2, 0.5, 1, 0.5, 2, 5.6900000000000004]
Dusknoir [0, 1, 1, 1, 1, 1, 0, 0.5, 1, 1, 1, 0.5, 1, 2, 1, 2, 1, 5.2199999999999998]
Snorlax [1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 4.9299999999999997]
Mamoswine [1, 2, 2, 0, 2, 1.0, 2, 0.5, 1, 1, 1, 1, 1.0, 1, 1, 1, 2, 4.9299999999999997]
Ninjask [1, 2, 1, 2, 0.25, 2, 0.25, 1, 0.0, 2, 1, 0.5, 4, 1, 1, 1, 1, 4.7999999999999998]
Hippowdon [1, 1, 2, 0, 2, 2, 1, 0.5, 1, 1, 1, 1, 0.5, 1, 1, 1, 1, 4.4900000000000002]
Tentacruel [1, 0.5, 0.5, 2, 1.0, 0.5, 0.5, 0.5, 2, 1, 2, 0.5, 1, 1, 1, 1, 0.5, 4.2999999999999998]
Roserade [1, 2, 0.5, 0.5, 0.25, 2, 0.5, 1.0, 1.0, 2, 2, 1.0, 1, 1, 1, 1, 1, 4.04]
Smeargle [1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 3.96]
Heracross [1, 2, 1, 1, 0.5, 1, 0.5, 1, 0.5, 4, 2, 0.5, 1.0, 1, 1, 0.5, 1, 3.79]
Umbreon [1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 0, 2, 1, 0.5, 1, 0.5, 1, 3.6000000000000001]
Porygonz [1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 3.1600000000000001]
Alakazam [1, 1, 1, 1, 1, 1, 0.5, 1, 1, 1, 0.5, 2, 1, 2, 1, 2, 1, 3.0099999999999998]
Rotom-w [0, 1, 1, 0.5, 1, 1, 0, 0.5, 0, 0.5, 1, 0.5, 1, 2, 1, 2, 0.5, 2.8599999999999999]
Rotom-c [0, 1, 1, 0.5, 1, 1, 0, 0.5, 0, 0.5, 1, 0.5, 1, 2, 1, 2, 0.5, 2.7200000000000002]
Abomasnow [1, 4, 0.5, 0.5, 0.5, 1.0, 2, 2, 0.5, 2, 1, 2, 2, 1, 1, 1, 2, 2.7000000000000002]
Ludicolo [1, 1.0, 0.25, 1.0, 1.0, 1.0, 1, 2, 0.5, 2, 1, 2, 1, 1, 1, 1, 0.5, 2.5800000000000001]
Yanmega [1, 2, 1, 2, 0.25, 2, 0.25, 1, 0.0, 2, 1, 0.5, 4, 1, 1, 1, 1, 2.4300000000000002]
Cresselia [1, 1, 1, 1, 1, 1, 0.5, 1, 0, 1, 0.5, 2, 1, 2, 1, 2, 1, 2.3500000000000001]
Crobat [1, 1, 1, 2, 0.25, 2, 0.25, 0.5, 0, 1, 2, 0.25, 2, 1, 1, 1, 1, 2.3300000000000001]
Gallade [1, 1, 1, 1, 1, 1, 0.5, 1, 1, 2, 1.0, 1.0, 0.5, 2, 1, 1.0, 1, 2.29]
Arcanine [1, 0.25, 2, 1, 0.5, 0.5, 1, 1, 2, 1, 1, 0.5, 2, 1, 1, 1, 0.5, 2.27]
Dugtrio [1, 1, 2, 0, 2, 2, 1, 0.5, 1, 1, 1, 1, 0.5, 1, 1, 1, 1, 2.25]
Rhyperior [0.5, 0.5, 3.0, 0, 3.0, 1.5, 1.5, 0.25, 1.5, 0.5, 1, 1, 0.5, 1, 1, 1, 1.5, 2.2400000000000002]
Ambipom [1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 2.23]
Milotic [1, 0.5, 0.5, 2, 2, 0.5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.5, 2.23]
Froslass [0, 2, 1, 1, 1, 0.5, 0, 0.5, 1, 1, 1, 0.5, 2, 2, 1, 2, 2, 2.1299999999999999]
Clefable [1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 2.0499999999999998]
Porygon2 [1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 2.04]
Charizard [1, 0.5, 2, 2, 0.25, 1.0, 0.5, 1, 0, 1, 1, 0.25, 4, 1, 1, 1, 0.5, 1.97]
Uxie [1, 1, 1, 1, 1, 1, 0.5, 1, 0, 1, 0.5, 2, 1, 2, 1, 2, 1, 1.8999999999999999]
Kabutops [0.5, 0.25, 1.0, 2, 4, 0.5, 2, 0.5, 2, 0.5, 1, 1, 1, 1, 1, 1, 1.0, 1.8200000000000001]
Donphan [1, 1, 2, 0, 2, 2, 1, 0.5, 1, 1, 1, 1, 0.5, 1, 1, 1, 1, 1.79]
Slowbro [1, 0.5, 0.5, 2, 2, 0.5, 0.5, 1, 1, 1, 0.5, 2, 1, 2, 1, 2, 0.5, 1.6899999999999999]
Honchkrow [1, 1, 1, 2, 0.5, 2, 1.0, 1, 0, 1, 0, 1.0, 2, 0.5, 1, 0.5, 1, 1.6899999999999999]
Walrein [1, 1.0, 0.5, 2, 2, 0.25, 2, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1.0, 1.6299999999999999]
Spiritomb [0, 1, 1, 1, 1, 1, 0, 0.5, 1, 1, 0, 1.0, 1, 1.0, 1, 1.0, 1, 1.6100000000000001]
Registeel [0.5, 2, 1, 1, 0.5, 0.5, 2, 0, 2, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 1.5700000000000001]
Blastoise [1, 0.5, 0.5, 2, 2, 0.5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.5, 1.55]
Venusaur [1, 2, 0.5, 0.5, 0.25, 2, 0.5, 1.0, 1.0, 2, 2, 1.0, 1, 1, 1, 1, 1, 1.49]
Sceptile [1, 2, 0.5, 0.5, 0.5, 2, 1, 2, 0.5, 2, 1, 2, 1, 1, 1, 1, 1, 1.47]
Weezing [1, 1, 1, 1, 0.5, 1, 0.5, 0.5, 0, 1, 2, 0.5, 1, 1, 1, 1, 1, 1.4099999999999999]
Mismagius [0, 1, 1, 1, 1, 1, 0, 0.5, 0, 1, 1, 0.5, 1, 2, 1, 2, 1, 1.3700000000000001]
Shuckle [0.5, 1.0, 2, 1, 1.0, 1, 1.0, 0.5, 1.0, 1.0, 1, 1, 2, 1, 1, 1, 2, 1.3200000000000001]
Hitmontop [1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 0.5, 0.5, 1, 1, 0.5, 1, 1.29]
Claydol [1, 1, 2, 0, 2, 2, 0.5, 0.5, 0, 1, 0.5, 2, 0.5, 2, 1, 2, 1, 1.28]
Lanturn [1, 0.5, 0.5, 0, 2, 0.5, 1, 1, 2, 0.5, 1, 1, 1, 1, 1, 1, 0.25, 1.27]
Feraligatr [1, 0.5, 0.5, 2, 2, 0.5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.5, 1.25]
Cradily [0.5, 1.0, 1.0, 0.5, 1.0, 2, 2, 1.0, 1.0, 1.0, 1, 2, 1, 1, 1, 1, 2, 1.25]
Electrode [1, 1, 1, 0.5, 1, 1, 1, 1, 2, 0.5, 1, 1, 1, 1, 1, 1, 0.5, 1.23]
Houndoom [1, 0, 2, 1, 0.5, 0.5, 2, 1, 2, 1, 0, 1.0, 2, 0.5, 1, 0.5, 0.5, 1.22]
Shaymin [1, 2, 0.5, 0.5, 0.5, 2, 1, 2, 0.5, 2, 1, 2, 1, 1, 1, 1, 1, 1.2]
Typhlosion [1, 0.5, 2, 1, 0.5, 0.5, 1, 1, 2, 1, 1, 0.5, 2, 1, 1, 1, 0.5, 1.1799999999999999]
Marowak [1, 1, 2, 0, 2, 2, 1, 0.5, 1, 1, 1, 1, 0.5, 1, 1, 1, 1, 1.1200000000000001]
Blaziken [1, 0.5, 2, 1, 0.5, 0.5, 1, 1, 2, 2, 2, 0.25, 1.0, 1, 1, 0.5, 0.5, 1.1000000000000001]
Raikou [1, 1, 1, 0.5, 1, 1, 1, 1, 2, 0.5, 1, 1, 1, 1, 1, 1, 0.5, 1.1000000000000001]
Espeon [1, 1, 1, 1, 1, 1, 0.5, 1, 1, 1, 0.5, 2, 1, 2, 1, 2, 1, 1.05]
Azumarill [1, 0.5, 0.5, 2, 2, 0.5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.5, 1.03]
Staraptor [1, 1, 1, 2, 0.5, 2, 1.0, 1, 0, 1, 1, 0.5, 2, 0, 1, 1, 1, 1.02]
Steelix [0.5, 2, 2, 0, 1.0, 1.0, 2, 0.0, 2, 0.5, 0.5, 0.5, 0.25, 0.5, 0.5, 0.5, 0.5, 1.01]
Miltank [1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0.98999999999999999]
Absol [1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 0, 2, 1, 0.5, 1, 0.5, 1, 0.95999999999999996]
Aggron [0.25, 1.0, 2, 1, 1.0, 0.5, 4, 0.0, 4, 0.25, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 1.0, 0.88]
Rotom-f [0, 1, 1, 0.5, 1, 1, 0, 0.5, 0, 0.5, 1, 0.5, 1, 2, 1, 2, 0.5, 0.88]
Hariyama [1, 0.75, 1, 1, 1, 0.75, 1, 1, 1, 2, 2, 0.5, 0.5, 1, 1, 0.5, 1, 0.85999999999999999]
Tangrowth [1, 2, 0.5, 0.5, 0.5, 2, 1, 2, 0.5, 2, 1, 2, 1, 1, 1, 1, 1, 0.84999999999999998]
Slowking [1, 0.5, 0.5, 2, 2, 0.5, 0.5, 1, 1, 1, 0.5, 2, 1, 2, 1, 2, 0.5, 0.83999999999999997]
Drapion [1, 1, 1, 1, 0.5, 1, 1.0, 0.5, 2, 1, 0, 1.0, 1, 0.5, 1, 0.5, 1, 0.83999999999999997]
Toxicroak [1, 1.25, 0, 1, 0.5, 1, 0.5, 0.5, 2, 2, 4, 0.25, 0.5, 1, 1, 0.5, 1, 0.81000000000000005]
Ursaring [1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0.81000000000000005]
Gardevoir [1, 1, 1, 1, 1, 1, 0.5, 1, 1, 1, 0.5, 2, 1, 2, 1, 2, 1, 0.78000000000000003]
Drifblim [0, 1, 1, 2, 0.5, 2, 0.0, 0.5, 0, 1, 1, 0.25, 2, 2, 1, 2, 1, 0.77000000000000002]
Torterra [1, 2, 1.0, 0.0, 1.0, 4, 1, 1.0, 0.5, 2, 1, 2, 0.5, 1, 1, 1, 1, 0.77000000000000002]
Cacturne [1, 2, 0.5, 0.5, 0.5, 2, 2, 2, 0.5, 2, 0, 4, 1, 0.5, 1, 0.5, 1, 0.77000000000000002]
Glaceon [1, 2, 1, 1, 1, 0.5, 2, 1, 1, 1, 1, 1, 2, 1, 1, 1, 2, 0.76000000000000001]
Medicham [1, 1, 1, 1, 1, 1, 0.5, 1, 1, 2, 1.0, 1.0, 0.5, 2, 1, 1.0, 1, 0.75]
Magmortar [1, 0.5, 2, 1, 0.5, 0.5, 1, 1, 2, 1, 1, 0.5, 2, 1, 1, 1, 0.5, 0.75]
Leafeon [1, 2, 0.5, 0.5, 0.5, 2, 1, 2, 0.5, 2, 1, 2, 1, 1, 1, 1, 1, 0.73999999999999999]
Swellow [1, 1, 1, 2, 0.5, 2, 1.0, 1, 0, 1, 1, 0.5, 2, 0, 1, 1, 1, 0.72999999999999998]
Rampardos [0.5, 0.5, 2, 1, 2, 1, 2, 0.5, 2, 0.5, 1, 1, 1, 1, 1, 1, 2, 0.71999999999999997]
Mr.Mime [1, 1, 1, 1, 1, 1, 0.5, 1, 1, 1, 0.5, 2, 1, 2, 1, 2, 1, 0.70999999999999996]
Ninetales [1, 0, 2, 1, 0.5, 0.5, 1, 1, 2, 1, 1, 0.5, 2, 1, 1, 1, 0.5, 0.68999999999999995]
Nidoking [1, 1, 2, 0, 1.0, 2, 0.5, 0.25, 2, 1, 2, 0.5, 0.5, 1, 1, 1, 1, 0.68999999999999995]
Slaking [1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0.68000000000000005]
Lapras [1, 1.0, 0, 2, 2, 0.25, 2, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1.0, 0.68000000000000005]
Qwilfish [1, 0.5, 0.5, 2, 1.0, 0.5, 0.5, 0.5, 2, 1, 2, 0.5, 1, 1, 1, 1, 0.5, 0.66000000000000003]
Exeggutor [1, 2, 0.5, 0.5, 0.5, 2, 0.5, 2, 0.5, 2, 0.5, 4, 1, 2, 1, 2, 1, 0.65000000000000002]
Poliwrath [1, 0.5, 0, 2, 2, 0.5, 1, 1, 1, 2, 2, 0.5, 0.5, 1, 1, 0.5, 0.5, 0.62]
Jumpluff [1, 2, 0.5, 1.0, 0.25, 4, 0.5, 2, 0.0, 2, 1, 1.0, 2, 1, 1, 1, 1, 0.62]
Cloyster [1, 1.0, 0.5, 2, 2, 0.25, 2, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1.0, 0.59999999999999998]
Floatzel [1, 0.5, 0.5, 2, 2, 0.5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.5, 0.59999999999999998]
Shedinja [0, 2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 2, 2, 0, 2, 0, 0.59999999999999998]
Pikachu [1, 1, 1, 0.5, 1, 1, 1, 1, 2, 0.5, 1, 1, 1, 1, 1, 1, 0.5, 0.57999999999999996]

No mistakes jump out at me, anyhow.  So...on to actually calculating results....

metroid composite

  • m_ACac
  • Administrator
  • Denizen
  • *
  • Posts: 4373
    • View Profile
Re: Theorycrafting! (Because I like competitive metagames too much)
« Reply #45 on: May 20, 2010, 12:05:02 AM »
Okay, actual calculation time.  First, checking the results by doing something very close to what X-Act did.  (I.e. average the damage over all opponents, use only one move).  (Note if you're compiling, this continues precisely where the last python script left off, and uses the computed OUTypechart).

Code: [Select]
def attack_score( opponent, attacktype ):
    #this function references the global OUTypechart
    #
    #EDIT ME!  This function is designed to be edited.  Want to put more
    #weight on avoiding resistance than hitting weakness so that you don't?
    #get walled?  Try inverting the damage.  Want to do the calculation
    #assuming you have Ice STAB?
    #If( attacktype is ice ) multiply result by 1.5
    #Want to calculate assuming the Tinted Lens ability?  Just multiply the
    #appropriate moves by 2.
    #
    #This function returns a number.  Higher numbers will be chosen over
    #lower numbers when the pokemon picks its best damage.

    #Here's the simplest version of this function, just maximize your
    #damage (doesn't stop you from being walled, but will get a lot of
    #weaknesses).
    #
    return OUTypechart[opponent][attacktype]

nummoves = 1
moves = []
for i in range(0,nummoves):
    moves.append(nummoves - i - 1)
#print moves
tophitters = []
while True:

    total_percentage = 0;
    for i in range(0,len(OUTypechart)):
        max_output = -9999
        for j in range(0,len(moves)):
            max_output = max( max_output, attack_score( i, moves[j] ) )
        total_percentage += max_output * OUTypechart[i][len(Types)]
    #print moves, " deal ", total_hit

    #okay, this is hacky, but I haven't touched python in a while, so...
    #the first number in the array will be how well the moves perform (for
    #sorting purposes) and the next X numbers in the array will be the
    #moves.
    temparray = []
    temparray.append(total_percentage/575) #575 just because Shoddy percentages add up to 600% (6 pokes per team)
    for i in range(0,len(moves)):
        temparray.append(moves[i])
    tophitters.append(temparray)
    if(len(tophitters) > 32):
        tophitters.sort()
        tophitters.pop(0)

    #increment the move list; this is a basic n choose r construction
    #we move the first variable all the way to the top, and then we
    #increment the second variable and reset the first variable to
    #be just to the right of the second (avoids repeats).
    shouldexit = True
    for i in range(0,len(moves)):
        if( moves[i] < 16-i ): #17 types, but array indexing means we don't want to increment if we're at 16
            moves[i] = moves[i]+1
            shouldexit = False;
            for j in range(0, i):
                moves[j] = moves[i]+(i-j)
            break
    if shouldexit:
        break
    #print moves
    #Right, remember there's nothing special going on in the above code,
    #just iterating over all possible combinations of X different moves,
    #where X is nummoves.  The above code is just dealing with the fact
    #that we don't know X, so can't just write 4 nested for loops.

print "WE MADE IT"
print tophitters

tophitters.sort()
for i in range(0,len(tophitters)):
    #translate from array indices into english.  Again, remember we don't
    #know the number of moves, hence the for loop.
    englishnames = []
    for j in range(1,len(tophitters[i])):
        englishnames.append(typenames[tophitters[i][j]])
        
    #remember the hacky I mentioned above?  The first number in the array
    #is how well this move combination did, and not actually a move.
    #Yeah, I know: cringeworthy code.
    print tophitters[i][0], ": ", englishnames
    

And the results?

Code: [Select]
0.680495652174 :  ['Poison']
0.769773913043 :  ['Normal']
0.815291304348 :  ['Steel']
0.884752173913 :  ['Psychic']
0.93302173913 :  ['Bug']
0.943917391304 :  ['Grass']
0.979139130435 :  ['Dragon']
0.990086956522 :  ['Ghost']
1.01332173913 :  ['Ground']
1.01410869565 :  ['Dark']
1.02669130435 :  ['Water']
1.03828695652 :  ['Flying']
1.06770434783 :  ['Electric']
1.08676521739 :  ['Rock']
1.11244347826 :  ['Fighting']
1.21026521739 :  ['Fire']
1.21363913043 :  ['Ice']

Order is...definitely a few types have moved up or down by 1-3 places, but similar.  The gap between Poison and the best type is also about the same (gap's widened by 7%).  Yeah, looks like I'm functional.

Okay, let's start using this now.  Modifying the attack_score function for minimized walling...

Code: [Select]
   #This is a first pass at minimizing walling; just inverts the damage
    #taking 8 for a null damage result (worse than a W4)
    if( OUTypechart[opponent][attacktype] > 0 ):
        return ((-1)/float(OUTypechart[opponent][attacktype]))
    else:
        return (-8)

For one attack we get...

Quote
-3.17783623188 :  ['Ground']
-2.94306086957 :  ['Poison']
-1.86510869565 :  ['Electric']
-1.85143043478 :  ['Psychic']
-1.83008695652 :  ['Normal']
-1.78062463768 :  ['Grass']
-1.70187536232 :  ['Fighting']
-1.66867391304 :  ['Bug']
-1.6484173913 :  ['Ghost']
-1.58449275362 :  ['Steel']
-1.46804289855 :  ['Fire']
-1.34724637681 :  ['Water']
-1.3165 :  ['Ice']
-1.26288695652 :  ['Dark']
-1.2364173913 :  ['Flying']
-1.18893043478 :  ['Dragon']
-1.18579130435 :  ['Rock']

(Shocking pokemon strategy: if you're going to choose only one attack move and don't want to get walled, don't choose ground >_>).

Anyhow, moving on to the more interesting ones...minimizing walling on two moves:

Quote
-0.891043478261 :  ['Flying', 'Fire']
-0.888079710145 :  ['Ghost', 'Ground']
-0.884741449275 :  ['Fighting', 'Fire']
-0.87887826087 :  ['Bug', 'Electric']
-0.877905797101 :  ['Fighting', 'Electric']
-0.871557971014 :  ['Ground', 'Fire']
-0.87154057971 :  ['Flying', 'Ground']
-0.871115942029 :  ['Dragon', 'Water']
-0.86772173913 :  ['Ghost', 'Rock']
-0.862230434783 :  ['Dragon', 'Electric']
-0.855515942029 :  ['Flying', 'Water']
-0.854715942029 :  ['Rock', 'Water']
-0.85452115942 :  ['Dark', 'Fire']
-0.849986956522 :  ['Dark', 'Electric']
-0.848724637681 :  ['Dark', 'Water']
-0.836644927536 :  ['Dragon', 'Ground']
-0.833692753623 :  ['Flying', 'Fighting']
-0.82937826087 :  ['Ghost', 'Electric']
-0.825628985507 :  ['Ghost', 'Water']
-0.823779130435 :  ['Ghost', 'Fire']
-0.822005797101 :  ['Dragon', 'Fighting']
-0.816809565217 :  ['Electric', 'Fire']
-0.815657391304 :  ['Dragon', 'Fire']
-0.80741884058 :  ['Dark', 'Ground']
-0.805688405797 :  ['Rock', 'Ground']
-0.799808115942 :  ['Rock', 'Fire']
-0.794475362319 :  ['Ice', 'Electric']
-0.79251884058 :  ['Rock', 'Fighting']
-0.784710144928 :  ['Dark', 'Fighting']
-0.774066666667 :  ['Ghost', 'Fighting']
-0.771053623188 :  ['Fighting', 'Ice']
-0.726692753623 :  ['Ground', 'Ice']

Turns out the best way by far to be unwallable with two types (if this function is weighting things right), is to pick good offence (Mammoswine!)  Ghost combines nicely with Fighting seeing as fighting hits everything that resists Ghost.  And past that, there's a lot of "move that's not resisted by much like Dragon, Ghost, or Dark" combined with "move that hits Steel like Fighting, Fire, Ground, Water, or Electric."

Three types!

Quote
-0.684095072464 :  ['Rock', 'Water', 'Fire']
-0.683410144928 :  ['Dragon', 'Ground', 'Fire']
-0.680873333333 :  ['Rock', 'Bug', 'Fire']
-0.679353043478 :  ['Bug', 'Electric', 'Fire']
-0.677112463768 :  ['Dark', 'Rock', 'Fire']
-0.675884057971 :  ['Ghost', 'Ground', 'Electric']
-0.675592173913 :  ['Dark', 'Electric', 'Fire']
-0.67474057971 :  ['Rock', 'Ground', 'Fire']
-0.674507246377 :  ['Fighting', 'Ice', 'Grass']
-0.672948695652 :  ['Ghost', 'Electric', 'Fire']
-0.672892173913 :  ['Ghost', 'Rock', 'Fire']
-0.669653623188 :  ['Ghost', 'Rock', 'Ground']
-0.668834202899 :  ['Dark', 'Water', 'Fire']
-0.666462318841 :  ['Bug', 'Ground', 'Ice']
-0.665290724638 :  ['Rock', 'Grass', 'Fire']
-0.665112463768 :  ['Ghost', 'Water', 'Fire']
-0.663971884058 :  ['Fighting', 'Ice', 'Fire']
-0.66368057971 :  ['Rock', 'Fighting', 'Fire']
-0.662920289855 :  ['Ground', 'Ice', 'Grass']
-0.659284057971 :  ['Fighting', 'Ice', 'Electric']
-0.659166666667 :  ['Dark', 'Fighting', 'Ice']
-0.658019710145 :  ['Dark', 'Fighting', 'Fire']
-0.656523188406 :  ['Ghost', 'Fighting', 'Ice']
-0.655376231884 :  ['Ghost', 'Fighting', 'Fire']
-0.654644927536 :  ['Dark', 'Ground', 'Fire']
-0.654597101449 :  ['Ground', 'Fighting', 'Ice']
-0.652001449275 :  ['Ghost', 'Ground', 'Fire']
-0.650837101449 :  ['Ice', 'Electric', 'Fire']
-0.642427536232 :  ['Ground', 'Ice', 'Electric']
-0.640527536232 :  ['Dark', 'Ground', 'Ice']
-0.637884057971 :  ['Ghost', 'Ground', 'Ice']
-0.625327536232 :  ['Ground', 'Ice', 'Fire']

Suddenly there's a whole lot of Fire (where Fire did not stand out at two types).  I guess it's getting harder to ignore that W4 on the most-used pokemon.

Aand...four types:

Quote
-0.596116811594 :  ['Rock', 'Fighting', 'Grass', 'Fire']
-0.595638550725 :  ['Ghost', 'Ice', 'Water', 'Fire']
-0.595568115942 :  ['Rock', 'Ground', 'Grass', 'Fire']
-0.595551594203 :  ['Ghost', 'Electric', 'Water', 'Fire']
-0.595341449275 :  ['Ghost', 'Ice', 'Electric', 'Fire']
-0.592949275362 :  ['Flying', 'Fighting', 'Ice', 'Fire']
-0.592773333333 :  ['Ice', 'Electric', 'Water', 'Fire']
-0.590163188406 :  ['Dark', 'Fighting', 'Electric', 'Fire']
-0.589833333333 :  ['Dark', 'Ground', 'Ice', 'Grass']
-0.588571014493 :  ['Dark', 'Ground', 'Electric', 'Fire']
-0.587519710145 :  ['Ghost', 'Fighting', 'Electric', 'Fire']
-0.587189855072 :  ['Ghost', 'Ground', 'Ice', 'Grass']
-0.585927536232 :  ['Ghost', 'Ground', 'Electric', 'Fire']
-0.585627536232 :  ['Ground', 'Fighting', 'Ice', 'Electric']
-0.585157971014 :  ['Bug', 'Ground', 'Ice', 'Fire']
-0.584150144928 :  ['Dark', 'Rock', 'Fighting', 'Fire']
-0.582497101449 :  ['Dark', 'Rock', 'Ground', 'Fire']
-0.582105797101 :  ['Dark', 'Ground', 'Ice', 'Electric']
-0.581506666667 :  ['Ghost', 'Rock', 'Fighting', 'Fire']
-0.581197101449 :  ['Dark', 'Ground', 'Fighting', 'Ice']
-0.579853623188 :  ['Ghost', 'Rock', 'Ground', 'Fire']
-0.579462318841 :  ['Ghost', 'Ground', 'Ice', 'Electric']
-0.578553623188 :  ['Ghost', 'Ground', 'Fighting', 'Ice']
-0.57824057971 :  ['Ground', 'Fighting', 'Ice', 'Fire']
-0.571129855072 :  ['Fighting', 'Ice', 'Grass', 'Fire']
-0.565842028986 :  ['Ground', 'Ice', 'Grass', 'Fire']
-0.565584927536 :  ['Fighting', 'Ice', 'Electric', 'Fire']
-0.565467536232 :  ['Dark', 'Fighting', 'Ice', 'Fire']
-0.563505797101 :  ['Ground', 'Ice', 'Electric', 'Fire']
-0.562824057971 :  ['Ghost', 'Fighting', 'Ice', 'Fire']
-0.561605797101 :  ['Dark', 'Ground', 'Ice', 'Fire']
-0.558962318841 :  ['Ghost', 'Ground', 'Ice', 'Fire']

Hmm...well plausible stuff so far, anyhow.  I do wonder if the reciprocal is the best function to model "minimize walling" however.
« Last Edit: May 20, 2010, 12:09:19 AM by metroid composite »

metroid composite

  • m_ACac
  • Administrator
  • Denizen
  • *
  • Posts: 4373
    • View Profile
Re: Theorycrafting! (Because I like competitive metagames too much)
« Reply #46 on: May 20, 2010, 03:22:53 AM »
Okay, taking the "minimize weaknesses" statement utterly 100% literally to see how that changes things...

Code: [Select]
   #This is a more explicit "minimize weaknesses" calculation
    if( OUTypechart[opponent][attacktype] > 0.5 ):
        return 1
    else:
        return 0

One attack type:

Quote
0.496069565217 :  ['Steel']
0.509391304348 :  ['Grass']
0.516817391304 :  ['Bug']
0.518382608696 :  ['Poison']
0.609495652174 :  ['Psychic']
0.613843478261 :  ['Ground']
0.620347826087 :  ['Normal']
0.623113043478 :  ['Fire']
0.637773913043 :  ['Ice']
0.648991304348 :  ['Fighting']
0.686330434783 :  ['Dark']
0.688939130435 :  ['Ghost']
0.714886956522 :  ['Flying']
0.716156521739 :  ['Water']
0.740713043478 :  ['Electric']
0.757686956522 :  ['Dragon']
0.76107826087 :  ['Rock']

Rock and Dragon are still on top.  Types that were nulled tend to gain (Poison, Ground, Fighting, Water, Electric).

Two attack types:

Quote
0.915530434783 :  ['Flying', 'Electric']
0.919965217391 :  ['Fighting', 'Normal']
0.921130434783 :  ['Electric', 'Fire']
0.922469565217 :  ['Ghost', 'Fire']
0.930173913043 :  ['Bug', 'Electric']
0.930608695652 :  ['Psychic', 'Electric']
0.939756521739 :  ['Ghost', 'Rock']
0.943391304348 :  ['Electric', 'Normal']
0.947704347826 :  ['Dark', 'Ground']
0.948886956522 :  ['Rock', 'Ground']
0.951652173913 :  ['Rock', 'Fire']
0.956156521739 :  ['Flying', 'Fighting']
0.956365217391 :  ['Fighting', 'Ice']
0.956852173913 :  ['Ghost', 'Ground']
0.959008695652 :  ['Dark', 'Electric']
0.962 :  ['Dragon', 'Fire']
0.962730434783 :  ['Dragon', 'Ground']
0.963234782609 :  ['Dark', 'Water']
0.964573913043 :  ['Rock', 'Water']
0.973947826087 :  ['Poison', 'Water']
0.976817391304 :  ['Ice', 'Electric']
0.976973913043 :  ['Ghost', 'Electric']
0.977269565217 :  ['Dragon', 'Electric']
0.982086956522 :  ['Ground', 'Ice']
0.982817391304 :  ['Flying', 'Water']
0.983686956522 :  ['Ghost', 'Water']
0.983982608696 :  ['Water', 'Normal']
0.983982608696 :  ['Dragon', 'Water']
0.985773913043 :  ['Rock', 'Fighting']
0.987895652174 :  ['Dark', 'Fighting']
0.994852173913 :  ['Dragon', 'Fighting']
0.995895652174 :  ['Ghost', 'Fighting']

All of these combos hit 92% or more pokemon for at least neutral.  Ghost/Fighting actually hits everything for at least neutral (the only things ghost doesn't hit, fighting hits super effective, so even with a dual type that's at least neutral).  And if you're wondering "wait, doesn't the same apply to Dragon Fighting?" the answer is...it would have...except Shedinja'd.

(And there's not much point in going above two moves--with 3 moves it's actually quite easy to hit 100% of opponents for at least neutral).

metroid composite

  • m_ACac
  • Administrator
  • Denizen
  • *
  • Posts: 4373
    • View Profile
Re: Theorycrafting! (Because I like competitive metagames too much)
« Reply #47 on: May 21, 2010, 02:05:28 AM »
Okay, leaving behind for the moment the pokemon code (I expect I'll use it as an analysis tool to puzzle out movepool options for, say, Rotom), I'm going to switch gears for the moment, and talk about game design as pertaining to competitive metagames, and to some degree the current Magic metagame.




To start off, I'm going to paraphrase a talk I heard at GDC a few years back (by one of the Magic developers, as it happens.  I guess this was 2007 because Planar Chaos was the newest set).  I believe the talk ended up using more Starcraft examples than magic examples, though--it was talking about general game design.



The first thing he talked about was how important it was to get rock-paper-scissors interactions going on.  Your balance does not have to be perfect when you have rock-paper-scissors backing you up, since any imbalance will be corrected for by an appropriate shift in the metagame.  He further pointed out that it was important to recognize rock-paper-scissors interactions you didn't necessarily know you had in your game; like in magic, fast decks lose to midrange decks, because midrange decks have slightly more expensive cards that pack more punch.  Midrange decks lose to slow control decks for the same reason.  But slow control decks tend to lose to fast decks as they're dead before they can get set up.  You see the same kind of thing in Starcraft openers (fast strategies lose to medium strategies, but beat things like fast expand which leaves your early defences too minimal).



His next point was that there should be incentives to commit to a theme.  In Starcraft, you have upgrades that only upgrade certain units, which encourages you to make an army mostly of those units.  In Magic the Gathering you have 5 colours of mana, which encourage you to focus on only some pieces of the game.  The idea here is to maintain some real semblance of rock/paper/scissors.


Back to the Future

Okay, so let's gear back into modern MtG, flashing forward to 2009.  WotC has just done another multicolour block, this time focusing on 3-colour decks.  In parallel, they're trying to be a bit more creative about how different colours get card advantage; Blue would draw cards, for instance, while Green would have cards that made two creatures instead of one, and so on.  A "best deck" emerges (as sometimes happens) and people complain about it (people are always complaining, so this is nothing new).  Looking at things a bit closer, however, I feel like some of the design principles above were, most likely unintentionally, broken.

The deck in question is more of a "goodstuffs" deck than any particular theme; and on paper there's nothing wrong with that.  Except that it's a three colour deck, and many of the competing decks are also goodstuffs three colour decks that by definition must share at least one colour (everyone's playing Lightning Bolt!  ...Well almost).  Right there the commitment of one theme is partially gone.  But there's more to it than that.  Okay, so lots of different colours now have different ways to give card advantage...and as a result this deck is a fine mixture.  What's the best way to deal with Sprouting Thrinax?  Why, one of the variety of "remove target creature from the game" spells (or rather "exile target creature").  Great, but such spells don't help you against Broodmate Dragon, against whom...well I guess you counter him.  Great, but counterspells won't do well against Bloodbraid Elf.  And then there's Blightning...well they're always printing clever anti-discard tricks, although those won't save you against Maelstorm Pulse.

The funny thing is that it's not even that overwhelming as far as best decks in the format go.  It's not like the Mirrodin years of "you can be dead by turn 3", super-decks where the problem was that cards worked together a little too well.  It's more that the best deck happens to be a deck that has no real theme and does...well almost everything.  Would things be different if it had been another three-colour combination on top?  Probably not; white gets Ranger of Eos, Martial Coup, Stoneforge Mystic, and Knight of the White Orchid.  And Blue...draws cards.  It seems likely that if you group any three colours together in a deck that's not slow and not fast, the deck is going to have a tricky mixture of threatening cards.  And if one such deck's cards happens to be a little more threatening, well then you might just have a strongest deck that stays #1 for months on end because there's no clear way to get an advantage on it....like Jund.
« Last Edit: May 21, 2010, 02:07:19 AM by metroid composite »

metroid composite

  • m_ACac
  • Administrator
  • Denizen
  • *
  • Posts: 4373
    • View Profile
Re: Theorycrafting! (Because I like competitive metagames too much)
« Reply #48 on: June 08, 2010, 10:49:00 PM »
Okay, so...classic FFT debate.  Two Hands or Two Swords.  The classic answer has been that...outside of weapons that give you a bonus (like MA+2 or Auto-Haste) you should go for Two Hands.  This being for two flaws with Two Swords--first, if you are evaded on the first hit, then the second hit will face higher evasion because your opponent will turn-and-face you.  Second, because the first hit of a two swords attack can critical hit knocking the opponent backwards, and thus causing the second hit of the attack to miss.

This has been the conventional wisdom, anyhow.  Recently I did a quick calculation that ignored both of these factors, and ended up with this result:

Quote from: metroid composite on GameFAQs
If 1x physical is needed to kill target with 15% evade:
TS: 98% to kill in one round
TH: 85% to kill in one round

If 2x physical is needed to kill target with 15% evade:
TS: 72% to kill in one round, 99% to kill in two rounds
TH: 85% to kill in one round, 98% to kill in two rounds

If 3x physical is needed to kill target with 15% evade:
TS: 89% chance to kill in two rounds
TH: 72% chance to kill in two rounds

If 4x physical is needed to kill target with 15% evade:
TS: 52% chance to kill in two rounds, 95% chance to kill in three rounds
TH: 72% chance to kill in two rounds, 94% chance to kill in three rounds

So...at first glance this is pretty much what we'd expect--without those factors, Two Swords is better at killing things which take an odd number of physicals to kill, and Two Hands is better at killing things which take an even number of physicals to kill.  Except there's something else going on here as well--Two Swords has a greater level of consistency.  Which means that there's less chance of things going horribly wrong and missing over and over.  This actually makes "average number of turns needed to kill" slightly favour Two Swords.

In other words, without the turn-and-face mechanic and the knockback-out-of-second-hit mechanic, Two Swords would be at a mild advantage.  So...what happens when you factor all of those things in?

Code time!  (Sorry about the minimal commenting and inconsistent variable style; I did test each component as I was writing it).

Code: [Select]
print "hello world"
Hit = 0.75
Miss = 1-Hit
Crit = 0.05
DontCrit = 1-Crit
TFHit = Hit*0.9
TFMiss = 1-TFHit

def mult_arrays ( input, factor ):
    #we will need more space for the output
    return_value = []
    for i in range(0,len(input)+len(factor)-1):
        return_value.append(0.0)
    #now I make a messy loop
    for i in range(0, len(return_value)):
        for j in range(0,len(factor)):
            if( (i-j >= 0) and (i-j < len(input)) ):
                return_value[i] = return_value[i] + input[i-j]*factor[j]
    return return_value

def add_arrays ( input, addition ):
    #we will need more space for the output
    return_value = []
    for i in range(0,max(len(input),len(addition))):
        return_value.append(0.0)
    #and now we add.  Yes, there's more efficient ways of doing this than
    #constant if statements; inefficiency shouldn't be a problem today.
    for i in range(0,len(return_value)):
        if( i < len(input) ):
            return_value[i] = return_value[i] + input[i]
        if( i < len(addition) ):
            return_value[i] = return_value[i] + addition[i]
    return return_value


def get_TH_array():
    return_value = []
    for i in range(0,5):
        return_value.append(0.0)
    #miss
    miss = [Miss]

    hit = [0.0,0.0,Hit]
    
    #hit but don't crit
    justhit = mult_arrays(hit,[DontCrit])
    
    #crit
    critspread = [0.25,0.5,0.25]
    crit = mult_arrays(mult_arrays(critspread,hit),[Crit])

    return_value = add_arrays(return_value, miss)
    return_value = add_arrays(return_value, justhit)
    return_value = add_arrays(return_value, crit)
    return return_value

def get_one_hand_TS_array(CurrHit):
    CurrMiss = 1-CurrHit
    return_value = []
    for i in range(0,3):
        return_value.append(0.0)
    #miss
    miss = [CurrMiss]

    hit = [0.0,CurrHit]
    
    #hit but don't crit
    justhit = mult_arrays(hit,[DontCrit])
    
    #crit
    critspread = [0.5,0.5]
    crit = mult_arrays(mult_arrays(critspread,hit),[Crit])

    return_value = add_arrays(return_value, miss)
    return_value = add_arrays(return_value, justhit)
    return_value = add_arrays(return_value, crit)
    return return_value


def get_TS_array():
    return_value = []
    for i in range(0,3):
        return_value.append(0.0)
    #miss
    miss = [Miss]
    #if you miss, the second hit gets turn-faced
    miss = mult_arrays(miss,get_one_hand_TS_array(TFHit))

    hit = [0.0,Hit]
    
    #hit but don't crit
    justhit = mult_arrays(hit,[DontCrit])
    #if you just hit, then the next hit is normal propability spread
    justhit = mult_arrays(justhit,get_one_hand_TS_array(Hit))
    
    #crit
    critspread = [0.5,0.5]
    crit = mult_arrays(mult_arrays(critspread,hit),[Crit])
    #if you crit, you might knock back.  Technically knockback is 50%
    #although there's a number of cases where it can't happen, so I'll
    #take 40%
    knockbackfailure = [0.4]
    noknockback = mult_arrays([0.6],get_one_hand_TS_array(Hit))
    crit = mult_arrays(crit, add_arrays(knockbackfailure,noknockback))

    return_value = add_arrays(return_value, miss)
    return_value = add_arrays(return_value, justhit)
    return_value = add_arrays(return_value, crit)
    return return_value

TotalTurns = 20
def get_per_turn_probability(ThisTurn, killing_point):
    Spread = [1.0]
    prob_each_turn = []
    for i in range(0,TotalTurns):
        prob_each_turn.append(0.0)
    for turn in range(0,TotalTurns):
        total = 0.0
        for i in range (killing_point,len(Spread)):
            total = total + Spread[i]
    
        #now store this information for further use        
        if( turn > 0 ):
            prob_each_turn[turn] = total
            
        Spread = mult_arrays( Spread, ThisTurn )
    
    #print prob_each_turn
    #now isolate the each-turn probability
    non_cumul_prob = [prob_each_turn[0]]
    for i in range (1,len(prob_each_turn)):
        non_cumul_prob.append( prob_each_turn[i] - prob_each_turn[i-1] )
    return non_cumul_prob

def get_average_turn(ThisTurn, killing_point):
    per_turn_probability = get_per_turn_probability(ThisTurn, killing_point)
    average_turn = 0.0
    for i in range(0, len(per_turn_probability)):
        average_turn = average_turn + i*per_turn_probability[i]
    return average_turn

for durability in range(1,5):
    print "If ", durability, "x physicals kill, then Two Swords kills in ", get_average_turn(get_TS_array(), durability), " turns, and Two Hands kills in ", get_average_turn(get_TH_array(), durability), " turns."

And the results (for an enemy with 25% evade, plus an additional 10% front evade if they turn-and-face)

If  1 x physicals kill, then Two Swords kills in  1.08843537415  turns, and Two Hands kills in  1.33333333326  turns.
If  2 x physicals kill, then Two Swords kills in  1.50659447452  turns, and Two Hands kills in  1.33333333326  turns.
If  3 x physicals kill, then Two Swords kills in  2.31144817777  turns, and Two Hands kills in  2.61666666253  turns.
If  4 x physicals kill, then Two Swords kills in  2.89397498789  turns, and Two Hands kills in  2.64999999576  turns.
If  5 x physicals kill, then Two Swords kills in  3.6043053045  turns, and Two Hands kills in  3.90187488998  turns.
If  6 x physicals kill, then Two Swords kills in  4.24116898985  turns, and Two Hands kills in  3.96604155115  turns.

1x/3x/5x advantage: +0.25 turns, +0.30 turns, +0.30 turns
2x/4x/6x advantage: +0.17 turns, +0.25 turns, +0.28 turns

So...Two Swords is actually ahead in this case (although against an opponent with thousands of HP, Two Hands should eventually gain the advantage--it does deal more average damage, after all).  Furthermore, I would hazard a guess that something akin to Benford's Law will apply to enemy durability (probably more like a bell curve on a logarithmic scale than an even distribution on a logarithmic scale, to be fair) which...will likely tilt the durability distribution towards odd numbers, I'm guessing.

Not that there aren't cases where Two Hands are preferable--if you know your main target will be in the 2x range, for example, then go with Two Hands.  And of course, against an enemy with no evasion whatsoever (like attacking most enemies from the side) there's only two factors involved: knockback and crits (which gives Two Hands about a 0.01 turn advantage).  And if your strategy is "I have a good unevadeable move that I use to finish off enemies at low HP" then Two Hands is probably better.

Still, though, this is a lot less one-sided than originally thought, and may actually favour Two Swords in the abstract general case.
« Last Edit: June 08, 2010, 10:53:10 PM by metroid composite »

metroid composite

  • m_ACac
  • Administrator
  • Denizen
  • *
  • Posts: 4373
    • View Profile
Re: Theorycrafting! (Because I like competitive metagames too much)
« Reply #49 on: June 12, 2010, 06:20:23 AM »
I'm going to take a moment to talk about something fuzzy and not really math related.  That's because I'm looking at real-time stuff; and while yes, you can math out real-time games frame-by-frame, it tends to be a mess.

In particular, the question I'm looking at is how much real-time competitive games should be decided by twitch skill (as opposed to tactics).  Obviously this is a value judgement and there isn't one single right answer; nevertheless...let's start by looking at the Smash series.

Smash 64

The most breakable game in the series.  If you had frame by frame reflexes, you would be able to do completely ridiculous stuff.  Example:

http://www.youtube.com/watch?v=gLRzDQo4BPg

The competitive tournament scene for this game...involves Isai (one of the top Melee players, known for his reflexes) just...crushing everyone else.  A typical finals match looks something like this:

http://www.youtube.com/watch?v=4WNBOru3kdM

With...Isai being left with about 4 stock despite his opponent clearly being very good at Smash 64.

Melee

Melee is...a less breakable system than 64.  Picks up wavedashing (which is basically short-distance rolling) but loses some of 64's wacky movement exploits (like 64's short-distance teleporting).  The bigger deal, however, is that L-Canceling only cuts animation time in half (unlike 64 where it sets animation time to zero).  What you get is a system where flawless use of exploits maybe doubles the pace of matches, but several people have the reflexes to pull this off, so there's certainly competition at the top.

Example match:

http://www.youtube.com/watch?v=hm8KUKEE5Rk

Brawl

A few key things change in Brawl.
1. "Sekret timing trick/exploit to speed up your character" that Melee had is...mostly gone.  (There are some character-specific exploits, though).
2. Defencive abilities are powered up; shielding is better, air dodging is better, air dodging can break you out of combos now (except chaingrabs), ledge-grabbing is better.

Example match:

http://www.youtube.com/watch?v=M-19NssjjZQ

Two things I'd like to address here--I've seen people on the internet claim stuff like "anyone can win at Brawl, it takes no skill".  This is pretty clearly false (I'll note that a lot of the top Brawl players are also top Melee players; M2K, for instance).  Second, high-defence few-combos, while not typical of fighting games, is...not inherently good or bad; it puts more emphasis on certain skills (like positioning).  (To some degree this is personal preference; though I will note that I don't find defensive play as exciting to watch).

Brawl Hacks

There's three talked about ones that I know of.

* Melee 2.0: Introduces wavedashing and L-Cancelling into Brawl (and tries to tune other parameters like gravity to be more Melee-like).  Actually a more technical game than Melee (Brawl's more powerful airdodge mechanics lead to a much more powerful wavedash than Melee).  I'm not aware of any tournaments played on this hack.
* Brawl+: Tones down most of Brawl's defensive mechanics (to more normal fighting game levels for blocking/escaping combos).  Does not add any big exploits like wavedashing or L-Cancelling, and in fact removes a couple exploits. (example).
* Balanced Brawl: Only touches character balance, rather than game style.  (example).

Which of these has been successful?  The correct answer might be "none of them".  I don't see a lot of top players from other games migrating over to these (and why would they?  Brawl and Melee have tournaments for big money; the hack tournaments are...small money last I checked).  The most successful of the hacks is Brawl+...and there's two ways this could be read--the first interpretation being that low technical barrier to the learning curve and combos are both desirable.  The second interpretation would be that it fills a niche that hasn't been previously filled (although the problem with the niche argument is "where's the high technical barrier, low combo hack?")



-------------------------


OK, so within the Smash competitive community, we actually see some drifting towards games with a lower technical boundary.  (Not that there aren't elitists calling for a return to Smash 64--I've seen them on GameFAQs board 8, among other places).  What about other competitive communities?


My knowledge of first person shooters is even shakier than my knowledge of smash bros, but I do have some (particularly surrounding TF2), so I'll work with what I have at my fingertips.  I know TF2 was considered "lower skill" on the scale--which is to say that compared to some other games, where one clan member on a team of 6 can actually carry a team, that in TF2 teamwork is more important than having one spectacular player.  This is achieved in a few ways; for one, Bunny Hopping (an expoit where you trick gravity into making you fall sideways, and thus move faster than running) is removed from TF2.  For another thing (with three exceptions) there's no location-based damage (i.e. no "headshots") and most weapons decrease in damage over distance (and can be easily dodged).

I suppose if I'm going to write a paragraph about TF2 I should include a video; contains Otter & Sigma:

http://www.youtube.com/watch?v=nu6yilZIR-M

Now, have I seen elitists condemn TF2 for not being hardcore enough?  Sure.  Again, seems like a style of game issue (teamwork being more important than having a star player sounds reasonable for "Team" Fortress 2).  And...TF2 manages a pretty solid competitive scene in-spite of such criticisms (and has attracted some top skill players from other games; Carnage jumps to mind).

That said, popular versus games tend to develop tournament scenes; a quick search on the internet turns up tournament scenes for...just about every shooter that's been big in the past 3 years (Halo 3, CoD4, CoD5, CoD6, Left4Dead, Left4Dead2).  What about games that have a low mainstream visibility, but stand out in the tournament scene?  I want to say Painkiller falls into this category--it was chosen in 2005 to be the flagship tournament game of CPL (CPL had been the largest professional league since early in the Quake years).  And yet, I'm not sure if I know any Painkiller fans (if I do, they haven't been vocal).  So this...could be such an example.


------------------


It's also worth making a brief mention of RTSs...of which in the competitive scene there are...two (SC and WC3).  Starcraft focuses less on micromanagement of the two, and has the bigger tournament scene.  (Though with only two games a number of other factors could be contributing to this, from race balance, to the fact that PC gaming was more popular in 1998 than it was in 2002).  Certainly neither game is lacking in reflex use anyhow (some Starcraft players reaching 400 actions per minute).


------------------


Conclusion?
Here's the thing--as a competitive metagame voyeur, there's two things that I like watching.  First, I like watching strategy, and we know that games can show off strategy with or without twitch skill (and in fact, cranking the twitch skill factor up to 11 likely lowers how much strategy you will see in the metagame--if the fastest way to get better is to improve your reflexes rather than play smarter, that's what people will do).  Second, I like watching twitch skill if it is visible and dramatic--visible twitch skill would be something like blowing up a midair opponent in TF2 (which looks impressive) whereas invisible twitch skill would be something like L-Canceling in Smash games (which...you have to know the game very well to even spot while watching).

And I'll stop to point out as a tangent...what makes a game fun to play and fun to watch aren't always the same thing.  It's noteworthy that if I'm watching Starcraft for fun, I'll watch the battles, but if I'm trying to get better at the game then I'll watch the economy and build order and scouting.

Anyhow, back to voyerism.  I would venture a guess that being a fun game to spectate (due to visible strategy and/or visible skill) probably does factor into which games develop popular tournament scenes.  After all, people watching a tournament match and reacting "huh, I want to try that now" is a big part of how metagames develop.  This, in turn, puts a bit of a skill ceiling on twitchiness--if someone watches a top player, goes "I want to try that now" and...can't do something similar, not even 10% of the time, then said person will likely find the tournament scene less personally relevant, and not join up themselves.

And...actually, this is bringing me back to ye olde Flow Diagram--the same diagram that says "get your challenge right in one-player games" may well apply here too.  If someone watches a tournament player, says "let me try that" and finds that they have everything easily perfected, this player likely also would not stick around.  (I'm not sure how often this really comes up in-practice; most games are not so simple.  Although I will note that tournament tic-tac-toe is pretty non-existent).

I'll take a moment to reiterate, though--I could be wrong about a lot of this stuff.  Much of this is just speculation and guesswork, and not even necessarily perfectly informed.