XS Scripting for AI Tournaments

Updated September 8, 2026

XS scripting functionality was extended to AI scripting in AoE2:DE, with many different features. These are documented in the community-based UGC XS Scripting Reference, and this article is designed to be used alongside that guide. For learning how to use the various XS functions, use the UGC website. This article will focus on which XS functions can be safely used in AI scripting without cheating so that tournament hosts can be confident about allowing AI scripts to enter that use XS code. A list provided without commentary is included at the top, and the rest of the article will explain the commands in more detail. Click on the links in the cheating list to jump to commentary for each function category.

Cheating List

These XS functions should not be used in AI scripts:

Non-FunctionsXS rules shouldn't be used
All Rules FunctionsxsDisableRule, xsDisableSelf, xsEnableRule, xsIsRuleEnabled, xsSetRulePriority, xsSetRulePrioritySelf, sSetRuleMinInterval, xsSetRuleMinIntervalSelf, xsSetRuleMaxInterval, xsSetRuleMaxIntervalSelf, xsEnableRuleGroup, xsDisableRuleGroup, xsIsRuleGroupEnabled
Techs FunctionsxsResearchTechnology
Player FunctionsxsEffectAmount, xsSetPlayerAttribute, xsDeclareVictory
Tasks FunctionsxsTaskAmount, xsResetTaskAmount, xsModifyObjectTasks, xsModifyUnitTasks, xsTask, xsRemoveTask
Units & Objects FunctionsxsCreateUnit, xsRemoveUnit, xsGetUnitOwner, xsSetUnitPosition, xsSetUnitHitpoints, xsSetUnitBuildPoints, xsSetUnitAttributeHeld, xsSetUnitCharge
Map FunctionsxsSetColorMood
UI Functions xsPlaySound, xsDisplayInstructions, xsClearInstructions, xsDisplayTimer, xsClearTimer, xsGetTimerRemaining

Cheating List if Used for Other Players

Many XS functions have full access to info about every single player. Such functions are obviously cheating if used on enemy players, and may also be considered cheating by some tournament hosts if used on ally players. Unfortunately, XS doesn't have a way to automatically get the playerId of the current AI player, like my-player-number, so you can't dynamically reference the AI's player number by default. A workaround is to store my-player-number in a goal, then call an XS function with xs-script-call which uses xsGetGoal to read this goal value and set a global XS myPlayerNumber variable to that value. Then, you can use myPlayerNumber as the playerId parameter for each of these functions to prevent cheating.

Global variables (variables outside of XS functions, like those in /xs/Constants.xs) are separately created for each player that loads the .xs file that creates them, so you don't have to worry about other AI players overwriting this variable with their own XS code.

Techs FunctionsxsGetTechState, xsGetTechAttribute
Player FunctionsxsGetPlayerUnitIds, xsPlayerAttribute
Tasks FunctionsxsGetObjectTaskCount, xsObjectTaskCount, xsGetUnitTaskCount, xsUnitTaskAmount
Units & Objects FunctionsxsGetObjectAttribute, xsGetUnitAttribute, xsDoesUnitExist, xsGetUnitPosition, xsGetUnitName, xsGetObjectName, xsGetUnitTargetUnitId, xsGetUnitMoveTarget, xsGetUnitGroupId, xsGetGroupMoveTarget, xsIsObjectAvailable, xsGetUnitHitpoints, xsGetUnitBuildPoints, xsGetUnitObjectId, xsGetUnitCopyId, xsGetObjectCopyId, xsGetUnitClass, xsGetObjectClass, xsGetUnitType, xsGetUnitAttributeTypesHeld, xsGetUnitAttributeHeld, xsGetUnitCharge, xsGetGarrisonedInUnitId, xsGetGarrisonedUnitIds, xsGetObjectCount, xsGetObjectCountTotal, xsObjectHasAction, xsIsObjectValid, xsGetPlayerNumberOfObjects

Use With Care

These functions are allowed to be used, but should be used carefully.

Array Functions(can use excessive memory if not managed properly) xsArrayCreateInt, xsArrayCreateFloat, xsArrayCreateBool, xsArrayCreateString, xsArrayCreateVector, xsArrayResizeInt, xsArrayResizeFloat, xsArrayResizeBool, xsArrayResizeString, xsArrayResizeVector
Map Functions(these functions only work in custom scenarios) xsTriggerVariable, xsSetTriggerVariable
UI Functions(can cause a desync in some situations because of language localization differences) xsGetLocale, xsGetString, xsGetPlayerAttributeName, xsGetDamageClassName, xsGetLocalPlayerId, xsSendChat
Miscellaneous Functions(these apparently do nothing or are of little use to anyone besides devs) xsDumpArrays, xsGetFunctionId, xsBreakPoint, xsAddRuntimeEvent

Permitted Functions

Here is a list of functions which can be used without cheating concerns.

All Vector FunctionsxsVectorGetX, xsVectorGetY, xsVectorGetZ, xsVectorSetX, xsVectorSetY, xsVectorSetZ, xsVectorSet, xsVectorLength, xsVectorNormalize
All Array FunctionsxsArrayCreateInt, xsArrayCreateFloat, xsArrayCreateBool, xsArrayCreateString, xsArrayCreateVector, xsArraySetInt, xsArraySetFloat, xsArraySetBool, xsArraySetString, xsArraySetVector, xsArrayGetInt, xsArrayGetFloat, xsArrayGetBool, xsArrayGetString, xsArrayGetVector, xsArrayResizeInt, xsArrayResizeFloat, xsArrayResizeBool, xsArrayResizeString, xsArrayResizeVector, xsArrayGetSize
All Maths Functionsabs, sqrt, pow, sin, cos, tan, asin, acos, atan, atan2, atan2v, exp, ceil, floor, bitCastToFloat, bitCastToInt, xsCeilToInt, ln, log2, log10, round, radians, degrees, dist, bitAnd, bitOr, bitXor, bitNot
All Randomization FunctionsxsGetRandomNumber, xsGetRandomNumberLH, xsGetRandomNumberMax
Techs FunctionsxsGetTechName
Player FunctionsxsGetHandicapMultiplier, xsGetWorldPlayerId, xsGetPlayerCivilization, xsGetPlayerInGame, xsGetPlayerNumberOfTechs, xsGetPlayerName, xsGetPlayerType, xsGetDiplomacy, xsSetDiplomacy, xsGetDifficulty
Tasks FunctionsxsGetTaskAmount (if the stored task struct doesn't belong to another player)
Map FunctionsxsGetMapName, xsGetMapId, xsGetMapHeight, xsGetMapWidth, xsGetColorMood, xsGetMapSeed,
All Game Info FunctionsxsGetNumPlayers, xsGetTime, xsGetGameTime, xsGetTurn, xsGetVictoryType, xsGetVictoryPlayer, xsGetVictoryPlayerForSecondaryGameMode, xsGetVictoryTime, xsGetVictoryTimeForSecondaryGameMode, xsGetVictoryCondition, xsGetVictoryConditionForSecondaryGameMode
UI FunctionsxsChatData, xsGetPlayerColorTag
All File I/O FunctionsxsOpenFile, xsWriteString, xsWriteInt, xsWriteFloat, xsWriteVector, xsReadString, xsReadInt, xsReadFloat, xsReadVector, xsOffsetFilePosition, xsCloseFile, xsGetFilePosition, xsGetDataTypeSize, xsGetFileSize
All AI Scripting FunctionsxsGetGoal, xsGetStrategicNumber, xsSetGoal, xsSetStrategicNumber
Miscellaneous Functions xsGetContextPlayer, xsSetContextPlayer

Commentary

Here are explanations why these XS functions should or should not be allowed in AI tournaments. This section covers every function category, according to how functions are categorized on the UGC XS Scripting Reference.

Non-Functions

XS rules shouldn't be used because they do not operate independently for each AI player. Instead, XS rules seem to function globally, independent of AI players, which can easily throw off any player-specific code the rules contain, such as xsGetGoal. The only code that exists outside of XS function calls should be code that creates variables. XS variables, thankfully, are created and managed separately for each AI player.

Rules Functions

See the section above about how XS rules shouldn't be used. Since rules shouldn't be used for AIs, XS functions that affect rules shouldn't be used either.

Vector Functions

None of these functions are cheating. All they do is modify or get information about existing vector variables, which store 3-dimensional points.

Array Functions

Arrays are purely ways to store data, and therefore they don't cheat. Arrays are perhaps the most useful tool that XS scripts provide for AI scripters. However, be careful about when creating new arrays or increasing their size to make sure that your script doesn't repeatedly create new arrays or increase their size over and over again, causing massive memory usage. If XS code repeatedly creates new arrays throughout the game, the game can eventually crash after using up all of the computer's memory. Instead, make sure that you only create your arrays once. To be able to reference your created arrays outside of a called function, you can create a global XS variable at the start of the game which stores the array ID when it's created so that it can be referenced later.

Maths Functions

All math functions are available to be used. The sqrt and trig functions can be especially useful to AI scripters since these calculations are difficult to replicate in AI .per code.

Randomization Functions

Non cheating. These functions just generate a random number.

Techs Functions

xsResearchTechnology researches the tech immediately, so it is a cheating command. xsGetTechState and xsGetTechAttribute allow you to get tech info about other players, even enemies. Some tournament hosts may allow getting tech info about allies, but it's probably best to only use these functions for the AI player itself. xsGetTechAttribute can be particularly effective to get the research time or location of certain techs, because there are no .per equivalents.

Player Functions

xsEffectAmount is basically the same as fe-cc-effect-amount, which is almost always cheating. To make things simple and transparent for tournament hosts, please use fe-cc-effect-amount instead to implement any permitted non-cheating cosmetic changes. xsGetPlayerUnitIds is essentially a DUC search, but it works on any given player regardless of exploration. xsPlayerAttribute is basically a resource-amount check on any given player. xsSetPlayerAttribute modifies a player's given resource-amount, which is obviously cheating. xsDeclareVictory force declares victory for a player and is obviously cheating. All other player functions are permitted since they get information about players that every player has access to.

Tasks Functions

These functions are mostly for scenario designers. Tasks in this case refers to the particular tasks or action abilities that a particular unit can do, such as converting, garrisoning, guarding, combat, etc. These functions don't check a unit's current action, but check which tasks an object can potentially do. Most Tasks functions allow you to change the default task abilities available to a unit, which is obviously cheating, but some merely check what task types a unit type currently has, which is permitted if used on objects the AI owns.

Units & Objects Functions

These functions are basically XS' version of checking object data. The xsCreateUnit function immediately places a unit on the map at a given location, which is obviously cheating. xsRemoveUnit and the various function that set/change unit attributes are obviously cheating. The rest of the commands can be used as long as the units are owned by the AI itself, but the .per commands are probably easier to use. However, of particular interest are the xsGetGroupMoveTarget, xsGetGarrisonedInUnitId, and xsGetGarrisonedUnitIds functions, which don't have .per equivalents. They might be useful to AI scripters.

Map Functions

AIs shouldn't use xsSetColorMood since it affects all players, but it's just a cosmetic change. All other map functions are permissible since they get map info that is known from the start of the game, but xsTriggerVariable and xsSetTriggerVariable only work in custom scenarios.

Game Info Functions

All game info functions get global information about the game, so all of these functions are permitted.

UI Functions

Many of these functions can cause desync issues if different players use different languages, such as in a multiplayer game. Really, the only function that should be used in this category is xsChatData, which is essentially up-chat-data-to-self and is the only debugging chat command available in XS.

File I/O Functions

These functions allow you to create, read, and write external hex files. These functions are all permitted because each file is unique for each player. However, these files are hex files and require more data manipulation to write and read data at the correct position. They are also overwritten each game, and you can't specify a file name or save location. up-log-data is much easier to use, and it's likely a better alternative to these functions.

AI Scripting Functions

These functions are all permitted. If used from a function called by xs-script-call, they will only get and set values for the current AI player.

Miscellaneous Functions

The only functions in this category that are useful are xsGetContextPlayer and xsSetContextPlayer. xsSetContextPlayer must be used before using any of the File I/O functions. The context player also affects xsEffectAmount. It's possible that xsBreakPoint might be useful, but it probably has the same effect as fe-break-point.