The MesaLingua and MesaScript project is designed to help beginners learn agent-based modelling (ABM) using a simplified language called MesaScript. MesaScript commands are translated into Mesa/Python code by the MesaLingua Translator, and the generated code is implemented on the Mesa modeling framework.
MesaScript includes commands for creating, moving, and following objects, among other actions. Objects in the language include agents (individuals, resources, environmental factors, and other objects) and environments, with various attributes like location, health, and movement.
create 10 "predator" agents;
create 1 "prey" agent with .speed = 5;
create 20 "fast predator" agents based on "predator" agents but with .speed = 10 and with .health = 20;
create 10 "predator" agents at (R, R);
create 5 "prey" agents at (R, 3);
create 100 "water" agents at (5, R);
create 1 "predator" agent with .speed = R(3 & 12); create 3 "prey" agents with .strength = (R(0 & 1)[4] * 10);
create 10 "prey" agents with .scared = R(true);
create 5 "food" agents with .nutrition = R("low", "moderate", "high");
create 100 "dog" agents at (5, 10) and with .speed = 10 and with .health = 80;
# Commentary may be added to any line, following a hash ... create 1 "predator" agent at (R, R); # ... including here # ========================================= # # # # So, you can also do this kind of thing. # # # # ========================================= #
delete all "prey" agents at (10, 10);
create Moore non-toroidal grid with .size (50, 50);
move "salamander" agent to (5, 5);
"salamander" agent /bullies/ "insect" agent;
"salamander" agent reproduces;
{statement};
Multi-step actions are separated by semicolons (;) and are written on separate lines.
move "salamander" agent to (5, 5); "salamander" agent eats any "insect" agents in .range R(0 & 1);
define "objectAgent:agent_type:str" agent as:\n
\t[.attribute=value:{int, float, bool, str, 'R(expression[; seed:int])'} [...]];
Defines a new agent without creating an instance on the grid. The definition of the agent follows this line. Agents may be defined before they are used within MesaScript statements or at the time of creation with action:[create]. Agents (re)defined after creation overwrite attributes defined at creation.
define "prey" agent as: .hunger 20; .health 50; every tick: increase .hunger by 1; if .hunger is less than 10 or greater than 90: rest; otherwise: decrease .health by 1; /hunt/;
define /action:str/ action as:\n
\t{actions:list};
Defines a new action. The definition of the action follows this line. Actions must be defined before they may be used within MesaScript statements.
define /follows/ action as: move towards target agent; define /hunt/ or /hunts/ action as: move towards nearest "prey" agent; if any "prey" agent in .range 1: delete "prey" agent; decrease .hunger by 20; define /hungry/ action as: .health less than 10 or .hunger greater than 70; define /tired/ action as: .energy less than 10; define /rest/ or /rests/ action as: do not move; define /explore/ or /explores/ action as: move randomly; define /wake up/ or /wakes up/ action as: increase .energy by 20; .health * 1.005
Conditional actions are declared by using colons (:), are indented, and are written on separate lines.
if any agent is /hungry/: the agent /searches/ for "food" agents; but if the agent is /tired/: the agent rests; otherwise: the agent /explores/;
when any agent is /hungry/: the agent /searches/ for "food" agent; when the agent is /tired/: the agent rests; otherwise: the agent /explores/;
while any "predator" agent is /hungry/: the agent /hunts/ for "prey" agents; when successful: set the agent .hunger to 0; set the agent .health to 80; otherwise: increase the agent .hunger by 2; decrease the agent .health by 1;
before any agent eats: the agent /searches for food/; after any agent eats: the agent rests;
first the agent wakes up: then the agent /searches for food/; next the agent /explores/; finally the agent rests;
while any "prey" agent .energy is less than 50: increase "prey" agent .energy by 1;
every 10 ticks: decrease "predator" agent .energy by 1;
choose action based on .energy level: if .energy is greater than 50: "prey" agent /explores/; otherwise: "prey" agent rests;
In MesaScript, changing the state of an agent is a crucial part of modeling dynamic behaviors. This involves updating attributes based on certain conditions or events within the simulation. The following commands and syntax allow for defining and manipulating states of agents.
change "predator" agent .health to 50;
set "predator" agent .health to 50;
increase "prey" agent .energy by 10;
decrease "predator" agent .hunger by 5;
if any "predator" agent .hunger is greater than 20: change "predator" agent .health to 30;
when "predator" agent /hunts/ "prey" agent: change "predator" agent .hunger to 0;
change "prey" agent .speed to R(3 & 12); change "preditor" agent .strength to (R(0 & 1) * 5)
append "predator" agent .preyList with "rabbit";
update "predator" agent .stats to {"speed": 12, "strength": 15};
every 5 ticks: increase "prey" agent .health by 5;
every step "predator" agent moves: decrease "predator" agent .energy by 2;
"prey" agent "gathers" "food" agent: change "prey" agent .energy to 100; change "food" agent .quantity to 0;
if any "prey" agent .energy is greater than 80: "prey" agent reproduces; change "prey" agent .energy to 50;
if any "predator" agent .health is less than 20: "predator" agent rests; otherwise: "predator" agent /hunts/;
if any "prey" agent .energy is less than 10: change "prey" agent .speed to 2; otherwise: change "prey" agent .speed to 5;
State changes are integral to creating dynamic and realistic agent behaviors in simulations. By incorporating state changes, you can model complex interactions and adaptive behaviors.
create 10 "predator" agents with .hunger 20; create 50 "prey" agents with .energy 50; every tick: if any "predator" agent .hunger is greater than 15: "predator" agent /hunts/ "prey" agent: when successful: change "predator" agent .hunger to 0; change "prey" agent .health to 0; otherwise: "predator" agent rests; increase "prey" agent .energy by 5; if any "prey" agent .energy is greater than 80: "prey" agent reproduces; change "prey" agent .energy to 50;
This example shows how state changes can drive the behaviors of agents in a predator-prey model, creating a dynamic and evolving simulation.
MesaScript provides a set of foundational actions that can be used to define more complex behaviors. Actions are usable in any present form of a verb in any person (first, second, or third). Here are examples of each predefined action, organized by their category:
create 10 "predator" agents at (R, R);
delete "prey" agents at (5, 5);
"prey" agent reproduces;
"prey" agent dies;
"predator" agent rests;
"prey" agent wakes up;
"predator" agent prioritizes /hunt/ over rest;
"predator" agent moves to (10, 10);
move "predator" agent to (10, 10);
"prey" agent moves toward (0, -1); move "predator" agent toward northwest;
move "prey" agent toward (0, -1); move "predator" agent toward northwest;
"prey" agent moves randomly;
move "prey" agent randomly;
"predator" agent navigates toward nearest "prey" agent;
"prey" agent avoids "predator" agents;
"prey" agent avoids "predator" agents;
change "predator" agent .health to 50;
increase "prey" agent .energy by 10;
decrease "predator" agent .hunger by 5;
if any "predator" agent .hunger is greater than 20: change "predator" agent .health to 30;
while any "prey" agent .energy is less than 50: increase "prey" agent .energy by 1;
choose action based on .energy level: if .energy is greater than 50: "prey" agent /explores/; otherwise: "prey" agent rests;
"prey" agent gathers "food" agent;
"prey" agent drops "food" agent;
"prey" agent modifies environment;
"prey" agent forages;
"prey" agent seeks shelter;
"prey" agent communicates with "prey" agent;
"prey" agent broadcasts .danger;
"prey" agent sends .id and .height to "predator" agent .heightRecord;
"prey" agent receives data from "predator" agent;
"predator" agent waits 5 ticks;
schedule "prey" agent to /gather/ in 10 ticks;
"predator" agent eats "food" agent;
"prey" agent produces "food" agent;
"prey" agent metabolizes "food" agent into .energy 100;
"predator" agent /learns from hunt/ ;
This action can be used to simulate the improvement of an agent's attributes based on past experiences. For example, a predator might increase its hunting skill after each successful hunt.
In Python using Mesa, "learning" can be implemented as updating agent attributes based on experiences. For example, a predator might learn to improve its hunting efficiency after successful hunts.
class PredatorAgent(Agent): def __init__(self, unique_id, model): super().__init__(unique_id, model) self.hunting_skill = 1.0 def hunt(self): # Attempt to hunt prey prey = self.find_prey() if prey: self.hunting_skill += 0.1 # Improve hunting skill after a successful hunt def find_prey(self): # Logic to find prey pass
In MesaScript, this would be:
define action /learns from hunt/ as: increase .hunting_skill by 0.1;
"prey" agent adapts to "predator" agent presence;
This action can be used to adjust an agent's behavior or attributes based on external stimuli. For example, prey might increase its speed when predators are nearby.
Adapting to the presence of other agents can be modeled as changing behavior based on perceived threats. For instance, prey might increase their speed or change their movement pattern when predators are nearby.
class PreyAgent(Agent): def __init__(self, unique_id, model): super().__init__(unique_id, model) self.speed = 1.0 def step(self): if self.model.predators_nearby(self.pos): self.adapt() def adapt(self): self.speed *= 1.5 # Increase speed when predators are nearby
In MesaScript, this would be:
define action /adapts to predator presence/ as: change .speed to .speed * 1.5;
"predator" agent perceives "prey" agent;
Perception involves detecting other agents within the environment and updating internal state or attributes accordingly. For example, a predator might set a target prey after perceiving it in the environment.
This can be implemented as checking the agent's surroundings and updating internal state or attributes accordingly.
class PredatorAgent(Agent): def __init__(self, unique_id, model): super().__init__(unique_id, model) self.target_prey = None def perceive_prey(self): # Check for prey in the neighborhood neighbors = self.model.grid.get_neighbors(self.pos, moore=True, radius=2) prey = [agent for agent in neighbors if isinstance(agent, PreyAgent)] if prey: self.target_prey = prey[0] # Set the first prey found as the target
In MesaScript, this would be:
define action /perceives prey/ as: if any "prey" agent in range 2: set .target_prey to first "prey" agent in range 2;
"prey" agent senses "predator" presence;
Sensing can involve more complex perception mechanisms, such as detecting the presence of agents or environmental changes. For example, prey might update its safety status based on the presence of predators.
class PreyAgent(Agent): def __init__(self, unique_id, model): super().__init__(unique_id, model) self.is_safe = True def sense_predator_presence(self): neighbors = self.model.grid.get_neighbors(self.pos, moore=True, radius=3) predators = [agent for agent in neighbors if isinstance(agent, PredatorAgent)] self.is_safe = len(predators) == 0 # Update safety status based on predator presence
In MesaScript, this would be:
define action /senses predator presence/ as: if any "predator" agent in range 3: set .is_safe to false; otherwise: set .is_safe to true;
"prey" agent regenerates .health;
"prey" agent mutates .speed;
"prey" agent /evolves to adapt/ to "predator" agent;
"prey" agent metabolizes "food" agent to .energy;
"prey" agent trades .food with "predator" agent;
"prey" agent buys .food from "predator" agent;
"predator" agent sells .food to "prey" agent;
sets the price of .food to 5;
"prey" agent produces 3 .food;
"predator" agent consumes 2 .food;
"predator" agents interact with "prey" agents;
"prey" agents cooperate with "prey" agents;
"predator" agents compete with "predator" agents;
"positive node" agents connect with "negative node" agents;
"positive node" agents disconnect from "negative node" agents;
"predator" agents celebrate;
"prey" agents migrate to (10, 10);
The extensibility of MesaScript allows for the combination of foundational actions to define more complex behaviors. Extensible actions may be defined (and if so defined, must be) in multiple present forms of a verb in any number of persons (first, second, or third) through the use of "or". Prepositions (and other articles or modifiers) are required if they are to be expected and interpreted correctly by the MesaLingua lexer and parcer. The exception I don't know what "X" means. will be thrown by the parcer, and the process will fail, if the parcer encounters a new action that is not earlier defined. Here are some examples of new actions that can be defined using existing foundational actions:
Combining movement and interaction actions to create a complex behavior.
define action /hunt/ or /hunts/ as: move towards nearest "prey" agent; if any "prey" agent in .range 1: "predator" agent /attacks/ "prey" agent; change "predator" agent .hunger to 0; change "prey" agent .health to 0;
Combining movement and sensing actions to create a patrolling behavior.
define action /patrol/ or /patrols/ as: move randomly; if sense "predator" agent in .range 5: move away from "predator" agent;
Combining interaction and resource management actions to create a resource-sharing behavior.
define action /share resources with/ or /shares resources with/ as: if "prey" agent .energy is greater than 50: "prey" agent gives 10 .energy to "prey" agent;
Combining communication, movement, and interaction actions to create a cooperative defense behavior.
define action /cooperate in defense of/ or /cooperates in defense of/ or /cooperate in the defense of/ or /cooperates in the defense of/ as: if sense "predator" agent in .range 5: set .danger to true; broadcast .danger to all "prey" agents; move towards nearest "prey" agent; if within .range 1 of other "prey" agent: "prey" agent /defends against/ "predator" agent;
Combining movement, sensing, and state-based actions to create a migration behavior.
define action "migrate to" or "migrates to" as: if "prey" agent .energy is greater than 50: move towards (10, 10); if any "prey" agent in .range 5: move towards nearest "prey" agent;
One of the primary goals of MesaScript is to provide a flexible syntax that accommodates natural language elements. This allows users with little to no programming experience to define agent behaviors intuitively. Below are examples showcasing the flexibility of MesaScript:
create 10 "predator" agents; create "predator" agents with "hunger" 20; create "predator" agents; # Default number can be 1
if any "predator" agent's hunger is > 15: "predator" agent /hunts/ "prey" agent; otherwise: "predator" agent rests;
create 10 "predator" agents; # Correct create "predator" agents with hunger 20; # Missing quotes around "hunger"
MesaLingua is designed as a DSL to cater specifically to agent-based modeling. It focuses on providing simple, yet powerful, commands that directly translate to Mesa's Python API. This allows users to create and manipulate agents, define their interactions, and set up the environment without requiring deep programming knowledge.
The MesaLingua Workflow involves translating high-level commands written in MesaScript into executable Python code using the Mesa library. The workflow consists of the following steps:
import ply.lex as lex tokens = ( 'CREATE', 'SPAWN', 'AGENT', 'NUMBER', 'STRING', 'IF', 'HUNGER', 'HUNTS', 'INCREASE', 'DECREASE', 'ATTRIBUTE', 'IS', 'GREATER_THAN', 'THAN', 'BY', 'SEMICOLON', ) # Regular expression rules for simple tokens t_CREATE = r'create|spawn' t_IF = r'if' t_HUNTS = r'hunts' t_INCREASE = r'increase' t_DECREASE = r'decrease' t_IS = r'is' t_GREATER_THAN = r'greater than|>' # A regular expression rule with some action code def t_NUMBER(t): r'\d+' t.value = int(t.value) return t def t_STRING(t): r'\".*?\"' return t # Define a rule so we can track line numbers def t_newline(t): r'\n+' t.lexer.lineno += len(t.value) # A string containing ignored characters (spaces and tabs) t_ignore = ' \t' # Error handling rule def t_error(t): print(f"Illegal character '{t.value[0]}'") t.lexer.skip(1) # Build the lexer lexer = lex.lex() def lexer(input_text): lexer.input(input_text) tokens = [] while True: tok = lexer.token() if not tok: break tokens.append(tok) return tokens
import ply.yacc as yacc def p_command(p): '''command : create_command | conditional_command | action_command''' p[0] = p[1] def p_create_command(p): '''create_command : CREATE NUMBER STRING AGENT SEMICOLON | CREATE STRING AGENT SEMICOLON''' if len(p) == 5: p[0] = ('create', p[2], p[3]) else: p[0] = ('create', p[2]) def p_conditional_command(p): '''conditional_command : IF STRING AGENT ATTRIBUTE IS GREATER_THAN NUMBER COLON action_command''' p[0] = ('if', p[2], p[3], p[4], '>', p[6], p[8]) def p_action_command(p): '''action_command : STRING AGENT HUNTS STRING AGENT SEMICOLON | STRING HUNTS STRING SEMICOLON''' if len(p) == 7: p[0] = ('hunts', p[2], p[4]) else: p[0] = ('hunts', p[1], p[3]) # Error rule for syntax errors def p_error(p): print(f"Syntax error at '{p.value}'") # Build the parser parser = yacc.yacc() def parse(tokens): return parser.parse(tokens)
def interpret(parsed_command): if parsed_command[0] == "create": create_agent(parsed_command[2]) # where parsed_command[2] is the agent's name, e.g., "predator" elif parsed_command[0] == "if": # Implement the conditional logic here pass elif parsed_command[0] == /hunts/: # Implement the action logic here pass # ... among other actions def create_agent(agent_name): print(f"Creating agent: {agent_name}") # Add actual agent creation logic here # Example usage input_text = 'create 10 "predator" agents;' tokens = lexer(input_text) parsed_command = parse(tokens) interpret(parsed_command)
An Abstract Syntax Tree (AST) represents the hierarchical structure of source code, capturing its syntactic and semantic structure. ASTs are crucial for interpreting and translating high-level commands into executable code. Below are examples of ASTs for MesaScript commands:
CreateStatement ├── Number(10) ├── AgentType("predator") └── Action(agents)
IfStatement ├── Condition │ ├── AgentType("predator") │ └── Attribute("hunger") ├── ComparisonOperator(is greater than) ├── Value(15) └── Action ├── AgentType("predator") └── Command(/hunts/, "prey")
IfStatement ├── Condition │ ├── AgentType("predator") │ └── Attribute("hunger") ├── ComparisonOperator(is greater than) ├── Value(20) └── Actions ├── Action │ ├── AgentType("predator") │ └── Command(/hunts/, "prey") └── Action ├── AgentType("predator") └── Command("rests")
Using ASTs, MesaLingua can efficiently parse and interpret commands, making it easier to create complex agent-based models with intuitive syntax.
create 10 "predator" agents;
创建10个"捕食者"代理; # Chinese is typically written without word-spacing. # The efficacy of this within MesaScript is unexamined. 创建 10 个 "捕食者" 代理; # Word-spacing may be necessary to avoid ambiguities in MesaScript. # Examples used herein will employ word-spacing in natural languages where such is not always used.
أنشئ 10 "مفترس" وكلاء; # Italics are not used in RtL highlight-typing as results vary
10 "शिकारी" एजेंट बनाओ;
creu 10 "ysglyfaethwyr" asiantau;
vakaleweni "manumanu dau veilakoyaki" e tini na tamata;
if any "predator" agent .hunger is greater than 15: "predator" agent /hunts/ "prey" agent: change "predator" agent .hunger to 0; change "prey" agent .health to 0; otherwise: "predator" agent rests;
如果 任何 "捕食者" 代理 .饥饿 大于 15: "捕食者" 代理 /捕猎/ "猎物" 代理: 将 "捕食者" 代理 .饥饿 变为 0; 将 "猎物" 代理 .健康 变为 0; 否则: "捕食者" 代理 休息;
إذا كان أي "مفترس" عامل .جوع أكبر من 15: "مفترس" عامل \يصطاد\ "فريسة" عامل: غير "مفترس" عامل .جوع إلى 0; غير "فريسة" عامل .صحة إلى 0; وإلا: "مفترس" عامل يستريح;
यदि कोई "शिकारी" एजेंट .भूख 15 से अधिक है: "शिकारी" एजेंट "शिकार" एजेंट /का शिकार करता है/: "शिकारी" एजेंट की .भूख को 0 में बदलो; "शिकार" एजेंट की .स्वास्थ्य को 0 में बदलो; अन्यथा: "शिकारी" एजेंट आराम करता है;
os yw unrhyw asiant "ysglyfaethwr" .newyn yn fwy na 15: "ysglyfaethwr" asiant /yn hela/ "ysglyfaeth" asiant: newid "ysglyfaethwr" asiant .newyn i 0; newid "ysglyfaeth" asiant .iechyd i 0; os nad yw: "ysglyfaethwr" asiant yn gorffwys;
kevaka e dua na tamata "manumanu dau veilakoyaki" .viakana e sivia na tinikalima: /vakasigana/ na tamata "manumanu dau veilakoyaki" na tamata "manumanu vakadra": veisau na tamata "manumanu dau veilakoyaki" na .viakana ki na sero; veisau na tamata "manumanu vakadra" na .bula ki na sero; kevaka e sega: vakacegu na tamata "manumanu dau veilakoyaki";
Each component of the type hints structure plays a critical role in defining the syntax and semantics of MesaScript commands. Here is a detailed explanation:
The agent performing the action. This is the primary agent that initiates the command. In the following, this is represented by the "predator" agent:
"predator" agent
/hunts/ "prey" agent
The target agent of the action. This is the agent that is affected by the action performed by the subjectAgent. In the following, this is represented by the "prey" agent:
"predator" agent /hunts/"prey" agent
The type of agent or object involved. This specifies the kind or category of agents or objects. Examples include:
"predator", "prey", "food", "grid"
The action to be performed by the subjectAgent or performed upon the objectAgent involved. Actions define what the agents do in the simulation. Examples include:
create, eat, gather, move, rest, /learn from hunting/, /age/
A specific characteristic of an agent. Attributes define properties that agents possess and can be modified. Examples include:
.speed, .health, .energy, .position
Numerical values for attributes. Values define the magnitude or quantity of an attribute. Examples include:
10, 5.5, 100, random, randomly
Fixed values or strings. Literals are exact representations used within commands. Examples include:
Moore toroidal, grid
Optional elements in the command. Optional elements provide additional flexibility by allowing or omitting certain parts of a command. Examples include:
... and with .attribute[=]value:[int, float]
create value=1:literal[int, 'a':{'alias':1}] "type:str" subjectAgent:object based on "type:str" objectAgent:object but with .attribute[=]value:[int, float] [... and with .attribute[=]value:[int, float] ...];
create 5 "predator" agents based on "fast predator" agents but with .speed=10 and with .strength=15;
if value='any':literal[int, ['the', 'a', 'an']:self.conditionalAgent, ['any', 'all', 'each']:model.schedule.conditionalAgent] "type:str" conditionAgent:object .attribute comparisonOperator value:float: "type:str" subjectAgent:object action [...];
if any "predator" agent .hunger is greater than 20: "predator" agent /hunts/ "prey" agent;
action:['move'] "type:str" subjectAgent:object to (xValue:int, yValue:int);
move "predator" agent to (10, 10);
action:['move'] "type:str" subjectAgent:object randomly;
move "prey" agent randomly;
action:['change'] subjectAgent:object .attribute[=]value:[int, float];
action:['increase'] subjectAgent:object .attribute by value:[int, float];
action:['decrease'] subjectAgent:object .attribute by value:[int, float];
change "prey" agent .health=50;
subjectAgent:object action objectAgent:object;
"predator" agent /hunts/ "prey" agent;
if any "predator" agent .hunger > 15: "predator" agent /hunts/ "prey" agent: change "predator" agent .hunger=0; change "prey" agent .health=0; otherwise: "predator" agent rests;
"prey" agent gathers "food" agent: increase "prey" agent .energy by 20; decrease "food" agent .quantity by 1;
action:['create'] value=1:int "type:str" objectAgent:object;
create 10 "predator" agents;
action:['create'] value=1:int "type:str" objectAgent:object with .attribute[=]value:[int, float];
create 5 "prey" agents with .speed=3.5;
action:['create'] value=1:int "type:str" objectAgent:object based on "type:str" objectAgent:object but with .attribute[=]value:[int, float] [... and with .attribute[=]value:[int, float] ...];
create 20 "fast predator" agents based on "predator" agents but with .speed=10;
action:['create'] value=1:int "type:str" objectAgent:object at [.position=](RValue:int, RValue:int):tuple;
create 10 "predator" agents at (RValue:int, RValue:int);
action:['create'] value=1:int "type:str" objectAgent:object at [.position=](RValue:int, yValue:int):tuple;
create 5 "prey" agents at (R, 3);
action:['create'] value=1:int "type:str" objectAgent:object at [.position=](xValue:int, RValue:int):tuple;
create 100 "water" agents at (5, R);
action:['create'] value=1:int "type:str" objectAgent:object with .attribute[=]R(minValue:literal[int, float] & maxValue:literal[int, float]);
create 1 "predator" agent with .speed=R(3 & 12);
action:['create'] value=1:int "type:str" objectAgent:object at [.position=](xValue:int, yValue:int):tuple and with .attribute[=]value:[int, float] [... and with .attribute[=]value:[int, float] ...];
create 1 "predator" agent at (5, 5) and with .speed=4 and with .strength=7;
action:['delete'] X:literal[0<x<=len(model.schedule.agents):int, 'all'] "type:str" objectAgent:object at [.position=](xValue:int, yValue:int):tuple;
delete all "prey" agents at (10, 10);
action:['create'] [X=1] type:literal['Moore non-toroidal', 'Moore toroidal', 'von Neumann non-toroidal', 'von Neumann toroidal']='Moore toroidal' grid:literal['grid':object,'multigrid':object]='grid':object [with .size[=]](xValue=100:int, yValue=100:int):tuple;
create Moore toroidal grid with .size=(50, 50);
action:literal['move']='move' "type:str" objectAgent:object to [.position=](xValue:int, yValue:int):tuple;
move "predator" agent to (10, 10);
"type:str" subjectAgent:object action:literal[x, ... /z/] "type:str" objectAgent:object;
"predator" agent /hunts/ "prey" agent;
"type:str" objectAgent:object action:literal[x, ... /z/];
"predator" agent rests;
These type hints provide a clear and consistent way to define commands in MesaScript. The structure ensures that each element of the command is well-defined, allowing for both specific and flexible syntax that caters to various modeling needs.