Rare world structures in Erlang
I am thinking about how to the property port "w40> -farm simulator" from Erlang. Here is the main summary:
1) Define a world of "slots" of size 100 × 100
2) Ants occupy one slot
3) Ant colony takes place 50.50
4) Food is randomly placed around the map
5) Ants move one space at a time to search for food and return it to the colony
6) There can only be one object at a time.
The goal of this problem is to support as parallel a system as possible. In Clojure, the aforementioned problem is solved by agent threads, each of which runs an AI for one ant. Then these ants update the global state through a transaction.
This is a global state that I think about all the time. How do we build a "game world"?
My first thought is to have an Erlang process for each ant, and then a process for each slot on the map. To move a ant, do the following:
1) ant tells the current slot "I want to move north"
2) The slot calls the slot north and says: "Please update your contents to now contain ant" pid ""
3) If the northern slot already has ant, it sends a "denied" response, which seeps into the slot containing ant (and then ant). If the update works, then "granted" is sent along the chain, and ant updates its internal state.
The only thing I don’t like about this method is that during the process of moving ant, its slot and target slot are “locked” until the end of the whole transaction. Then it opens for dead ends. That is, two ants can try to swap at the same time, each slot will wait for the other.
Can anyone suggest a better solution?
--- EDIT ----
Let me solve the deadlock problem:
1) ant 1 requests slot A to “transfer north” to slot 2 2) ant 2 requests slot B to “transfer south” to slot 1 3) Slot 1 sends a transfer request to slot 2 and waits for a response 4) Slot 2 sends a transfer request in slot 1 and is waiting for an answer
From a code point of view, this would be simple to implement, but would also be deadlocked, since each slot only listened for responses from another slot. I believe that the “right way” could be to automatically reject all transfer requests during the transfer.
Ask ant to roll into the slot he is moving towards and ask for permission to move. ant then waits for a drop response, telling him whether the move was successful or not. If the move was successful, ant updates its own state to indicate that it is in the new slot. If this fails, it again executes its search logic. If you end up with A and B trying to swap slots, you won't have a dead end, but they will both think that they need to look for other options.
If your grid is very busy, you may need the slots to perform polling logic, passing permission to neighboring ants, telling them that if their logic leads them there, they can enter. (Imagine a grid with 50x50-2 ants on it, and you will understand why this would be a good change in logic.)
Never use challenges if you absolutely, without a doubt, can not survive without problems without them. And then, try very hard to get rid of them, if there is a possibility that processes of the same type will call each other or types that can make calls with each other.