UNPKG

dimensions-ai

Version:

A generalized AI Competition framework that allows you to create any competition you want in any language you want with no hassle.

345 lines (344 loc) 12.8 kB
/// <reference types="node" /> import { DeepPartial } from '../utils/DeepPartial'; import { MatchEngine } from '../MatchEngine'; import { Agent } from '../Agent'; import { Logger } from '../Logger'; import { Design } from '../Design'; import { Tournament } from '../Tournament'; import EngineOptions = MatchEngine.EngineOptions; import Command = MatchEngine.Command; import { ChildProcess } from 'child_process'; import { NanoID, Dimension } from '../Dimension'; /** * An match created using a {@link Design} and a list of Agents. The match can be stopped and resumed with * {@link stop}, {@link resume}, and state and configurations can be retrieved at any point in time with the * {@link state} and {@link configs} fields * * @see {@link Design} for Design information * @see {@link Agent} for Agent information */ export declare class Match { design: Design; /** * agent meta data regarding files, ids, etc. */ agentFiles: Agent.GenerationMetaData; private dimension; /** * When the match was created (called with new) */ creationDate: Date; /** * When the match finished */ finishDate: Date; /** * Name of the match */ name: string; /** * Match ID. It's always a 12 character NanoID */ id: NanoID; /** * The state field. This can be used to store anything by the user when this `match` is passed to the {@link Design} * life cycle functions {@link Design.initialize}, {@link Design.update}, and {@link Design.getResults} * * This is also used by the {@link CustomDesign} class to store all standard outputted match output for * matches running using a custom design and passing in {@link Design.OverrideOptions}. */ state: any; /** * List of the agents currently involved in the match. * @See {@link Agent} for details on the agents. */ agents: Array<Agent>; /** * Map from an {@link Agent.ID} ID to the {@link Agent} */ idToAgentsMap: Map<Agent.ID, Agent>; /** * The current time step of the Match. This time step is independent of any {@link Design} and agents are coordianted * against this timeStep */ timeStep: number; /** * The associated {@link MatchEngine} that is running this match and serves as the backend for this match. */ matchEngine: MatchEngine; /** * The match logger. * @see {@link Logger} for details on how to use this */ log: Logger; /** * The results field meant to store any results retrieved with {@link Design.getResults} * @default `null` */ results: any; /** * The current match status */ matchStatus: Match.Status; /** * A mapping from {@link Agent} IDs to the tournament id of the {@link Player} in a tournament that generated the * {@link Agent} */ mapAgentIDtoTournamentID: Map<Agent.ID, Tournament.ID>; /** * Match Configurations. See {@link Match.Configs} for configuration options */ configs: Match.Configs; /** Match process used to store the process governing a match running on a custom design */ matchProcess: ChildProcess; /** The timer set for the match process */ matchProcessTimer: any; /** Signal to stop at next time step */ private shouldStop; /** Promise for resuming */ private resumePromise; /** Resolver for the above promise */ private resumeResolve; /** Resolver for stop Promise */ private resolveStopPromise; /** Rejecter for the run promise */ private runReject; /** * Path to the replay file for this match */ replayFile: string; /** * Key used to retrieve the replay file from a storage plugin */ replayFileKey: string; /** * Non local files that should be removed as they are stored somewhere else. Typically bot files are non local if * using a backing storage service */ private nonLocalFiles; /** * Match Constructor * @param design - The {@link Design} used * @param agents - List of agents used to create Match. * @param configs - Configurations that are passed to every run through {@link Design.initialize}, {@link Design.update}, and {@link Design.getResults} functioon in the * given {@link Design} */ constructor(design: Design, /** * agent meta data regarding files, ids, etc. */ agentFiles: Agent.GenerationMetaData, configs: DeepPartial<Match.Configs>, dimension: Dimension); /** * Initializes this match using its configurations and using the {@link Design.initialize} function. This can * throw error with agent generation, design initialization, or with engine initialization. In engine initialization, * errors that can be thrown can be {@link AgentCompileError | AgentCompileErrors}, * {@link AgentInstallError | AgentInstallErrors}, etc. * * * @returns a promise that resolves true if initialized correctly */ initialize(): Promise<boolean>; /** * Retrieves a bot through its key and downloads it to a random generated folder. Returns the new file's path * @param botkey * @param file * @param useCached - if true, storage plugin will avoid redownloading data. If false, storage plugin will always * redownload data */ private retrieveBot; /** * Runs this match to completion. Sets this.results to match results and resolves with the match results when done */ run(): Promise<any>; /** * Handles log files and stores / uploads / deletes them as necessary */ private handleLogFiles; /** * Step forward the match by one timestep by sending commands individually. */ step(commands: Array<Command>): Promise<Match.Status>; /** * Next function. Moves match forward by one timestep. Resolves with the match status * This function should always used to advance forward a match unless a custom design is provided * * Gathers commands from agents via the {@link MatchEngine} * * Should not be called by user */ next(): Promise<Match.Status>; /** * Stops the match. For non-custom designs, stops at the next nearest timestep possible. Otherwise attempts to stop * the match using the {@link MatchEngine} stopCustom function. * * Notes: * - If design uses a PARALLEL match engine, stopping behavior can be a little unpredictable * - If design uses a SEQUENTIAL match engine, a stop will result in ensuring all agents complete all their actions up * to a coordinated stopping `timeStep` */ stop(): Promise<void>; /** * Resume the match if it was in the stopped state * @returns true if succesfully resumed */ resume(): Promise<void>; /** * Stop all agents through the match engine and clean up any other files and processes * * Used by custom and dimensions based designs */ private killAndCleanUp; /** * Terminate an {@link Agent}, kill the process. Note, the agent is still stored in the Match, but you can't send or * receive messages from it anymore * * @param agent - id of agent or the Agent object to kill * @param reason - an optional reason string to provide for logging purposes */ kill(agent: Agent.ID | Agent, reason?: string): Promise<void>; /** * Retrieve results through delegating the task to {@link Design.getResults} */ getResults(): Promise<any>; /** * Sends a message to the standard input of all agents in this match * @param message - the message to send to all agents available * @returns a promise resolving true/false if it was succesfully sent */ sendAll(message: string): Promise<boolean>; /** * Functional method for sending a message string to a particular {@link Agent}. Returns a promise that resolves true * if succesfully sent. Returns false if could not send message, meaning agent was also killed. * @param message - the string message to send * @param receiver - receiver of message can be specified by the {@link Agent} or it's {@link Agent.ID} (a number) */ send(message: string, receiver: Agent | Agent.ID): Promise<boolean>; /** * Throw an {@link FatalError}, {@link MatchError}, or {@link MatchWarn} within the Match. Indicates that the * {@link Agent} with id agentID caused this error/warning. * * Throwing MatchWarn will just log a warning level message and throwing a MatchError will just log it as an error * level message. * * Throwing FatalError will cause the match to automatically be destroyed. This is highly not recommended and it is * suggested to have some internal logic to handle moments when the match cannot continue. * * * Examples are misuse of an existing command or using incorrect commands or sending too many commands * @param agentID - the misbehaving agent's ID * @param error - The error */ throw(agentID: Agent.ID, error: Error): Promise<void>; /** * Destroys this match and makes sure to remove any leftover processes */ destroy(): Promise<void>; /** * Generates a 12 character nanoID string for identifying matches */ static genMatchID(): string; getMatchErrorLogDirectory(): string; } export declare namespace Match { /** * Match Configurations. Has 5 specified fields. All other fields are up to user discretion */ interface Configs { /** * Name of the match */ name: string; /** * Logging level for this match. * @see {@link Logger} */ loggingLevel: Logger.LEVEL; /** * The engine options to use in this match. */ engineOptions: DeepPartial<EngineOptions>; /** * Whether to run match in secure mode or not * @default true */ secureMode: boolean; /** * Default Agent options to use for all agents in a match. Commonly used for setting resource use boundaries */ agentOptions: DeepPartial<Agent.Options>; /** * Agent options to override with depending on extension of file * @default `{}` - an empty object */ languageSpecificAgentOptions: Agent.LanguageSpecificOptions; /** * Agent options to lastly overridde with depending on agent index * @default `[]` - empty array meaning no more overrides */ agentSpecificOptions: Array<DeepPartial<Agent.Options>>; /** * Whether or not to store a replay file if match results indicate a replay file was stored * * @default `true` */ storeReplay: boolean; /** * Used only when a {@link Storage} plugin is used. Indicates the directory to use to store onto the storage. * (Typically some path in the bucket). * * @default `replays` */ storeReplayDirectory: string; /** * Whether to store error output for each {@link Match} * * @default true */ storeErrorLogs: boolean; /** * Whether to store error and warnings outputted by match from calling match.throw * * @default false */ storeMatchErrorLogs: boolean; /** * Directory to store error logs locally. When a {@link Storage} plugin is used, this indicates the path in the * bucket to store the log in, and removes the local copy. * * @default `errorlogs` */ storeErrorDirectory: string; /** * Whether to run in detached mode. When in detached mode (true), the match can initialize within dimensions using the {@link Design} but will now * instead update step by step * * @default `false` */ detached: boolean; [key: string]: any; } enum Status { /** Match was created with new but initialize was not called */ UNINITIALIZED = "uninitialized", /** * If the match has been initialized and checks have been passed, the match is ready to run using {@link Match.run} */ READY = "ready", /** * If the match is running at the moment */ RUNNING = "running", /** * If the match is stopped */ STOPPED = "stopped", /** * If the match is completed */ FINISHED = "finished", /** * If fatal error occurs in Match, appears when match stops itself */ ERROR = "error" } }