first ai implementation

This commit is contained in:
Tobias Christian Nauen
2026-03-05 17:36:08 +01:00
commit 89c3cd91c2
14 changed files with 2040 additions and 0 deletions

84
src/lib/types.ts Normal file
View File

@@ -0,0 +1,84 @@
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<TypeName, number> = Object.fromEntries(
TYPE_NAMES.map((name, i) => [name, i])
) as Record<TypeName, number>;
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;