> Programming
Since version 2.49, besides LeekScript, you can write your leeks' artificial intelligences on Leek Wars in Python (or in JavaScript / TypeScript). 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:
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, and keeps its camelCase names in Python: me.setWeapon(...), Fight.getNearestEnemy(). 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: isinstance(enemy, Leek), isinstance(enemy, 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 is 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, with live type checking (Pyright).
Split your AI into modules with the classic Python import:
Only your own files are accessible. Module names follow the Python rules: no dashes, use underscores. Circular imports are not allowed.
The Python 3.12 standard library is available: math, itertools, collections, heapq, functools, random… However, there are no external packages (pip), and modules accessing the system (files, network, processes) are unavailable.
random module is seeded from the fight seed and the clock (time, datetime) is frozen, so that fights can be replayed identically.print() 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.