export type TypeName = | 'Normal' | 'Fire' | 'Water' | 'Electric' | 'Grass' | 'Ice' | 'Fighting' | 'Poison' | 'Ground' | 'Flying' | 'Psychic' | 'Bug' | 'Rock' | 'Ghost' | 'Dragon' | 'Dark' | 'Steel' | 'Fairy'; export interface TypeInfo { name: TypeName; backgroundColor: string; color: string; } export const TYPES: TypeInfo[] = [ { name: 'Normal', backgroundColor: '#a4acaf', color: '#212124' }, { name: 'Fire', backgroundColor: '#fd7d24', color: '#ffffff' }, { name: 'Water', backgroundColor: '#4792C4', color: '#ffffff' }, { name: 'Electric', backgroundColor: '#eed535', color: '#212121' }, { name: 'Grass', backgroundColor: '#9bcc50', color: '#212121' }, { name: 'Ice', backgroundColor: '#90d5d5', color: '#212121' }, { name: 'Fighting', backgroundColor: '#d56723', color: '#ffffff' }, { name: 'Poison', backgroundColor: '#b97fc9', color: '#ffffff' }, { name: 'Ground', backgroundColor: '#debb5c', color: '#212121' }, { name: 'Flying', backgroundColor: '#3dc7ef', color: '#212121' }, { name: 'Psychic', backgroundColor: '#f366b9', color: '#ffffff' }, { name: 'Bug', backgroundColor: '#7e9f56', color: '#ffffff' }, { name: 'Rock', backgroundColor: '#a38c21', color: '#ffffff' }, { name: 'Ghost', backgroundColor: '#7b62a3', color: '#ffffff' }, { name: 'Dragon', backgroundColor: '#53a4cf', color: '#ffffff' }, { name: 'Dark', backgroundColor: '#707070', color: '#ffffff' }, { name: 'Steel', backgroundColor: '#9eb7b8', color: '#212121' }, { name: 'Fairy', backgroundColor: '#fdb9e9', color: '#212121' }, ]; const TYPE_NAMES = TYPES.map(t => t.name); const EFFECTIVENESS_FLAT: number[] = [ // NOR FIR WAT ELE GRA ICE FIG POI GRO FLY PSY BUG ROC GHO DRA DAR STE FAI 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 0.50, 0.00, 1.00, 1.00, 0.50, 1.00, // NOR 1.00, 0.50, 0.50, 1.00, 2.00, 2.00, 1.00, 1.00, 1.00, 1.00, 1.00, 2.00, 0.50, 1.00, 0.50, 1.00, 2.00, 1.00, // FIR 1.00, 2.00, 0.50, 1.00, 0.50, 1.00, 1.00, 1.00, 2.00, 1.00, 1.00, 1.00, 2.00, 1.00, 0.50, 1.00, 1.00, 1.00, // WAT 1.00, 1.00, 2.00, 0.50, 0.50, 1.00, 1.00, 1.00, 0.00, 2.00, 1.00, 1.00, 1.00, 1.00, 0.50, 1.00, 1.00, 1.00, // ELE 1.00, 0.50, 2.00, 1.00, 0.50, 1.00, 1.00, 0.50, 2.00, 0.50, 1.00, 0.50, 2.00, 1.00, 0.50, 1.00, 0.50, 1.00, // GRA 1.00, 0.50, 0.50, 1.00, 2.00, 0.50, 1.00, 1.00, 2.00, 2.00, 1.00, 1.00, 1.00, 1.00, 2.00, 1.00, 0.50, 1.00, // ICE 2.00, 1.00, 1.00, 1.00, 1.00, 2.00, 1.00, 0.50, 1.00, 0.50, 0.50, 0.50, 2.00, 0.00, 1.00, 2.00, 2.00, 0.50, // FIG 1.00, 1.00, 1.00, 1.00, 2.00, 1.00, 1.00, 0.50, 0.50, 1.00, 1.00, 1.00, 0.50, 0.50, 1.00, 1.00, 0.00, 2.00, // POI 1.00, 2.00, 1.00, 2.00, 0.50, 1.00, 1.00, 2.00, 1.00, 0.00, 1.00, 0.50, 2.00, 1.00, 1.00, 1.00, 2.00, 1.00, // GRO 1.00, 1.00, 1.00, 0.50, 2.00, 1.00, 2.00, 1.00, 1.00, 1.00, 1.00, 2.00, 0.50, 1.00, 1.00, 1.00, 0.50, 1.00, // FLY 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 2.00, 2.00, 1.00, 1.00, 0.50, 1.00, 1.00, 1.00, 1.00, 0.00, 0.50, 1.00, // PSY 1.00, 0.50, 1.00, 1.00, 2.00, 1.00, 0.50, 0.50, 1.00, 0.50, 2.00, 1.00, 1.00, 0.50, 1.00, 2.00, 0.50, 0.50, // BUG 1.00, 2.00, 1.00, 1.00, 1.00, 2.00, 0.50, 1.00, 0.50, 2.00, 1.00, 2.00, 1.00, 1.00, 1.00, 1.00, 0.50, 1.00, // ROC 0.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 2.00, 1.00, 1.00, 2.00, 1.00, 0.50, 1.00, 1.00, // GHO 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 2.00, 1.00, 0.50, 0.00, // DRA 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 0.50, 1.00, 1.00, 1.00, 2.00, 1.00, 1.00, 2.00, 1.00, 0.50, 1.00, 0.50, // DAR 1.00, 0.50, 0.50, 0.50, 1.00, 2.00, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 2.00, 1.00, 1.00, 1.00, 0.50, 2.00, // STE 1.00, 0.50, 1.00, 1.00, 1.00, 1.00, 2.00, 0.50, 1.00, 1.00, 1.00, 1.00, 1.00, 1.00, 2.00, 2.00, 0.50, 1.00 // FAI ]; const TYPE_INDEX: Record = Object.fromEntries( TYPE_NAMES.map((name, i) => [name, i]) ) as Record; export const EFFECTIVENESS_MATRIX: number[][] = []; for (let i = 0; i < TYPE_NAMES.length; i++) { EFFECTIVENESS_MATRIX[i] = EFFECTIVENESS_FLAT.slice(i * 18, (i + 1) * 18); } export function getEffectiveness(attackType: TypeName, defenderTypes: TypeName[]): number { let result = 1; for (const defType of defenderTypes) { const attackIdx = TYPE_INDEX[attackType]; const defIdx = TYPE_INDEX[defType]; result *= EFFECTIVENESS_MATRIX[attackIdx][defIdx]; } return result; } export function getTypeInfo(name: TypeName): TypeInfo { return TYPES[findTypeIndex(name)]; } export function findTypeIndex(name: TypeName): number { return TYPE_INDEX[name]; } export const TYPE_COUNT = TYPES.length;