{"id":22542534,"url":"https://github.com/maumagnaguagno/locus","last_synced_at":"2025-10-12T21:16:03.101Z","repository":{"id":28251979,"uuid":"31760576","full_name":"Maumagnaguagno/Locus","owner":"Maumagnaguagno","description":":memo: Environment description language for Jason","archived":false,"fork":false,"pushed_at":"2024-12-26T00:46:17.000Z","size":633,"stargazers_count":4,"open_issues_count":0,"forks_count":1,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-04-09T22:51:22.794Z","etag":null,"topics":["agent","agentspeak","environment","ruby"],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Maumagnaguagno.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2015-03-06T08:50:33.000Z","updated_at":"2024-12-26T00:46:20.000Z","dependencies_parsed_at":"2024-08-01T13:15:23.871Z","dependency_job_id":null,"html_url":"https://github.com/Maumagnaguagno/Locus","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Maumagnaguagno%2FLocus","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Maumagnaguagno%2FLocus/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Maumagnaguagno%2FLocus/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Maumagnaguagno%2FLocus/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Maumagnaguagno","download_url":"https://codeload.github.com/Maumagnaguagno/Locus/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248125643,"owners_count":21051766,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["agent","agentspeak","environment","ruby"],"created_at":"2024-12-07T13:10:49.088Z","updated_at":"2025-10-12T21:15:58.082Z","avatar_url":"https://github.com/Maumagnaguagno.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"![Locus](Logo.png) [![Actions Status](https://github.com/Maumagnaguagno/Locus/workflows/build/badge.svg)](https://github.com/Maumagnaguagno/Locus/actions)\n\n\u003e [Jason](http://jason.sourceforge.net/) is an AgentSpeak interpreter for multi-agent system development.\nThe agents are describbed in AgentSpeak, but the environment requires a Java description of how the actions and perceptions happen.\nWe aim to close the gap between the descriptions with an AgentSpeak-like description of the environment, targeting new users and simpler examples.\nLocus generates the Java source required by Jason, giving the user an easier starting point to create complex environments without limiting the user to the tool.\nThe Java output can be further modified if required.\n\n## The Language\n\nAgentSpeak uses plans to describe agent behavior.\nThose plans are made of a triggering event, a new perception or belief, happening at a given context, current state, is enough to execute the action in the body of the plan.\nThis is a simple way to define which, when and what happens for an agent.\n\n```\ntriggeringEvent : context \u003c- body.\n```\n\nWith this in mind we created a tool to parse an environment description in this form and output the Java expected environment of Jason.\nWith this we hope to make the system easier for new users while being able to keep environment descriptions safe from the revisions of Jason's API.\nIn order to achieve this we created some constructs to affect the environment at specific points in time. **init** is triggered at the initialization of the environment.\n**stop** is triggered at the end of the simulation. **beforeActions** and **afterActions** can be used to clear and add perceptions dependending of the current state.\nEach action added to the environment has a name and N terms, can be applied every time it is called with a context evaluating to true.\n\n```\ninit                             \u003c- body.\n\nbeforeActions                    \u003c- body.\n+action(name[, terms]) : context \u003c- body.\nafterActions                     \u003c- body.\n\nstop                             \u003c- body.\n```\n\nThe body of these constructs can be used to add or remove perceptions, add, remove or overwrite the current state.\n\n```\n+percept(agent|all, predicate[, terms]) : context.\n-percept(agent|all, predicate[, terms]) : context.\n-percept(all).\n-percept(bob).\n\n+state(predicate[, terms]).\n-state(predicate[, terms]).\n-+state(predicate[, terms]).\n```\n\nFor the context you can check state and agent definition, but the system currently does not parse complex operations (with and/or/not, only an atom):\n\n```\n+percept(bob, danger) : agentClass(human).\n+percept(bob, danger) : agentName(bobs_friend).\n+percept(bob, danger) : state(on, bob, fire).\n```\n\nPerhaps the most interesting feature is to easily handle the terms of an action.\nSo far we are supporting only strings, but we will add more as required.\nBeware that free-variables can only be used inside an action context in the current version.\n\n```\n+action(bake, C) : agentClass(cooker) \u003c- -+state(have, C).\n```\n\nIn case you need to do something in Java to describe the behavior of your environment we are exposing **include** and any command inside of the main constructs that can not be parsed by our tool.\nTherefore you can include any Java library required and use inline Java as normal code.\nWe do not have tests for this feature and recommend you to find a generic abstraction for your case and request support instead of using this last resort.\n\n## [Examples](examples)\n\nWe hope the next examples show the power of the description.\nThe room example is part of the Jason set of examples and is maintained without modifications to show compatibility while the others were created by us to explore what we considered important without adding complex behaviors.\n\n### [Room](examples/Room)\n\nIn the room application we have 3 agents sharing the same room with a door:\n- a porter, the only agent who controls the door\n- a claustrophobe, an agent who wants the door to be open\n- a paranoid, an agent who wants the door to be closed\n\nThe environment's door starts either closed or opened.\nAll agents perceive the state of the door.\nThe claustrophobe or paranoid agent perceive the door in the correct position and does nothing, the other will ask the porter to fix the situation.\nThe porter simply obeys, having no desire for any particular door state.\nOnce the porter finishes the action the process restarts. A Prometheus design shows the room application:\n\n![Prometheus design of Room](examples/Room/Prometheus_Room.svg)  \n\nWe can follow the specification to build the agents and the environment:\n- [Porter](examples/Room/porter.asl)\n  ```\n  +!locked(door)[ source(paranoid)     ] : ~locked(door) \u003c-   lock.\n  +!~locked(door)[source(claustrophobe)] :  locked(door) \u003c- unlock.\n  ```\n\n- [Paranoid](examples/Room/paranoid.asl)\n  ```\n  +~locked(door) : true \u003c- .send(porter, achieve, locked(door)).\n  +locked(door)  : true \u003c- .print(\"Thanks for locking the door!\").\n  ```\n\n- [Claustrophobe](examples/Room/claustrophobe.asl)\n  ```\n  +locked(door) : true \u003c- .send(porter, achieve, ~locked(door)).\n  -locked(door) : true \u003c- .print(\"Thanks for unlocking the door!\").\n  ```\n\n- [Room Environment](examples/Room/RoomEnv.esl) ([see Java output](examples/Room/RoomEnv.java))\n  ```\n  init \u003c-\n    +state(doorLocked);\n    +percept(all, locked, door).\n  \n  beforeActions \u003c-\n    -percept(all).\n  \n  +action(lock) : agentClass(porter) \u003c-\n    -+state(doorLocked).\n  \n  +action(unlock) : agentClass(porter) \u003c-\n    -+state(~doorLocked).\n  \n  afterActions \u003c-\n    +percept(all, locked, door) : state(doorLocked);\n    +percept(all, ~locked, door) : state(~doorLocked).\n  ```\n\n### [Bakery React](examples/BakeryReact)\n\nIn the bakery react application we have 2 agents:\n- a boss, an agent that perceives and reacts to the lack of the items to sell in the bakery\n- a baker, the agent responsible to make the items in the bakery\n\nThe environment starts without some items, the boss perceives the lack of them.\nAnd every time an item is not in the shelf a client can not buy it, the boss pins a task to do more of this item in a board, the baker will perceive this task and bake.\nThe baker simply obeys the boss. Both agents simply react to perceptions from the environment. A Prometheus design shows the bakery react application:\n\n![Prometheus design of Bakery react](examples/BakeryReact/Prometheus_Bakery.svg)\n\nWe can follow the specification to build the agents and the environment:\n- [Boss](examples/BakeryReact/boss.asl)\n  ```\n  +~have(C) \u003c- pinTask(C).\n  +have(C) \u003c- .print(\"Done \", C).\n  ```\n\n- [Baker](examples/BakeryReact/baker.asl)\n  ```\n  +newTask(X) \u003c- bake(X).\n  ```\n\n- [Bakery Environment](examples/BakeryReact/Bakery.esl) ([see Java output](examples/BakeryReact/Bakery.java))\n  ```\n  init \u003c-\n    +state(~have(pie));\n    +state(~have(cake));\n    +state(~have(donut));\n    +percept(boss, ~have, pie);\n    +percept(boss, ~have, cake);\n    +percept(boss, ~have, donut).\n\n  beforeActions \u003c-\n    -percept(all).\n\n  +action(pinTask, C) : agentName(boss) \u003c-\n    +percept(all, newTask, C).\n    \n  +action(bake, C) : agentClass(cooker) \u003c-\n    -+state(have, C).\n    \n  afterActions \u003c-\n    +percept(boss, ~have, pie) : state(~have(pie));\n    +percept(boss, ~have, cake) : state(~have(cake));\n    +percept(boss, ~have, donut) : state(~have(donut));\n    +percept(boss, have, pie) : state(have(pie));\n    +percept(boss, have, cake) : state(have(cake));\n    +percept(boss, have, donut) : state(have(donut)).\n  ```\n\n## How it works\n\nA [Ruby script](Locus.rb) works as a [source-to-source compiler](http://en.wikipedia.org/wiki/Source-to-source_compiler), parsing the environment description, optimizing and converting to Java, the core language of Jason.\nInstead of creating the file from scratch, the script only fill the [template file](locus_env.java).\nThe blanks filled match the constructs like init, helper functions and internal variables required to work.\nThe current version already uses a few optimization tricks to avoid redundancy, the **Literals** are stored in variables to be reused as required.\nWe hope to add more optimizations (if-else), and make the Literals more readable using a better name convention for the variables.\n\n## Execution\n\nWith your **.esl** file ready you can launch Ruby to make the conversion to Java, the output is a file in the same folder of the file provided as input.\n\n```\nruby Locus.rb MyEnvironment.esl\n```\nor\n```\nruby Locus.rb projects\\thisproject\\MyEnvironment.esl\n```\n\nNote that a file named ``RoomEnv.esl`` will generate ``RoomEnv.java`` and **RoomEnv** must be present in your setup file (**.mas2j**) to be used as your environment.\nSince we rely on the setup file to obtain the agent's class during run-time we expect to [receive the setup filename in the arguments of the environment](http://jason.sourceforge.net/faq/faq.html#SECTION00042000000000000000), like this:\n\n```\nMAS room {\n    infrastructure: Centralised\n    environment: RoomEnv(\"Room.mas2j\")\n    executionControl: jason.control.ExecutionControl\n    agents: porter; claustrophobe; paranoid;\n}\n```\n\n## Contribution\n\nTo cite Locus, please cite this [paper](http://www2.ic.uff.br/~wesaac2015/Proceedings-WESAAC-2015.pdf#page=27):\n\n\u003e Ramon Fraga Pereira, Mauricio Magnaguagno, Anibal Solon Heinsfeld and Felipe Meneguzzi (2015). LOCUS: An environment description language for JASON, In WESAAC 2015. pp. 21-32.\n\n## ToDo's\n\n- Add more tests\n- Check version of Jason jar being used here\n- Optional condition block for actions\n- Optional condition block for afterActions and beforeActions\n- Arity check for actions\n- Complex formulas in conditions (\u0026/|/~/not/())\n- Unifications\n- Integer support for non string terms\n- Add perception checks (context)\n- Add belief check (context)\n- Add different term type support\n- Separate parser from output generator methods, being able to generate other outputs\n  - This would makes Locus output language agnostic and easy to extend.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmaumagnaguagno%2Flocus","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmaumagnaguagno%2Flocus","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmaumagnaguagno%2Flocus/lists"}