> Programming
Since version 2.49, besides LeekScript, you can write your leeks' artificial intelligences on Leek Wars in JavaScript, TypeScript or Python. AIs run in a secure and deterministic environment, with access to the whole combat API of the game, and can fight AIs written in any other language.
The language of an AI is determined by its file extension:
| Language | Extension | |----------|-----------| | LeekScript | (none) | | JavaScript | .js or .mjs | | TypeScript | .ts or .mts | | Python | .py |
You pick the language when creating a file ("New AI" button in the editor) or as the default language of your first AI when signing up. Renaming a file with a different extension changes its language.
Each turn, the engine runs your AI. Two ways to write it:
Simple AI: write your code directly, it runs every turn (in a fresh scope, no state is kept):
Stateful AI: define a turn() function. The file body runs only once (declare your classes and persistent variables there), then turn() runs every turn:
The game API is exposed in an object-oriented form. There is no global me variable: get your entity via Fight.me.
Unlike LeekScript, there are no global functions and no "flat" constants (getNearestEnemy(), WEAPON_PISTOL…): the whole API goes through the objects below.
Entities returned by the API are typed: enemy instanceof Leek, enemy instanceof Bulb…
| Class | Main members | |-------|--------------| | Entity | life, maxLife, tp, mp, strength, agility, wisdom, resistance, science, magic, level, name, cell, weapon, weapons, chips, effects, states, summons, alive, dead, isAlly(), isEnemy(), distance(target) | | Me | everything from Entity, plus the actions: moveToward(target), moveAwayFrom(target), useWeapon(target), useChip(chip, target), setWeapon(weapon), say(message), summon(chip, cell, ai), canUseWeapon(target), weaponCell(target), chipCells(chip, target), weaponTargets(cell)… | | Cell | x, y, empty, obstacle, entity, distance(target), pathLength(target), lineOfSight(target), path(target) | | Weapon / Chip | cost, minRange, maxRange, area, launchType, maxUses, needsLos, features (plus cooldown and currentCooldown for Chip) | | Effect | type, value, caster, turns, critical, item, target | | Feature | type, minValue, maxValue, turns, targets |
Alongside the classes, four singletons:
| Singleton | Role | Main members | |-----------|------|--------------| | Fight | the fight | me, turn, getNearestEnemy(), getFarthestEnemy(), getEnemies(), getAliveEnemies(), getAllies(), getAlliedTurret()… | | Field | the field | cellFromXY(x, y), getObstacles(), distance(a, b), pathLength(a, b), lineOfSight(a, b), path(a, b) | | Registers | storage persisted between fights | get(key), set(key, value), delete(key), all() | | Debug | field visualization | mark(cells, color), markText(cells, text), show(cell), clearMarks(), pause() |
Constants are grouped by family, in two forms:
Weapon.pistol, Chip.bandage, me.weapon === Weapon.pistol.Effect.DAMAGE, State.UNHEALABLE, Entity.Stat.STRENGTH, Entity.Type.LEEK, Cell.Type.EMPTY, Item.Area.CIRCLE_1, Item.LaunchType.LINE, Fight.Type.SOLO, Fight.Context.GARDEN, Field.NEXUS…The editor's autocompletion (Weapon., Effect., Entity.Stat.…) lists all available members.
Split your AI into ES modules (import / export):
Only your own files are accessible: no disk, network or system access.
In .ts files, the editor checks your types live: the whole combat API is typed (classes, methods, constants), with full autocompletion. At fight time, TypeScript is transpiled to JavaScript by the official tsc compiler, then run by the same engine. A type error makes the AI invalid, just like a LeekScript compilation error.
Math.random() is seeded from the fight seed and the clock (Date.now(), performance.now()) is frozen, so that fights can be replayed identically.console.log() is redirected to the fight log, like debug() in LeekScript: its output shows up in the report.Impossible de charger les données du jeu.
Vérifiez votre connexion et réessayez.