I’ve got a particular question to an architectural event sending / receiving problem for my mvc based card game code. To understand my question you only need to know that I’ve got a game logic component that is responsible for processing the logic of the card game. That is, determining the state of the game, deal particular cards to the hands / players, etc. But most importantly, since I decided to use an event-driven approach, the game logic does not only send Events like which hand has to receive cards but needs to receive events from the Controller (or in my specific case; the controllers of the players (ai or user interface)).
It is possible to “attack” and “defend” in the card game that I’m writing. So when the game logic arrives at the point that a hand / player needs to attack, it should send some kind of “AttackRequestEvent” with all information needed for the controller to process the event and the controller sends the result back to the game logic that continues its processing with the controller’s result. Like I said, this event happens for example when the deck has dealt all cards to the player’s and it is a player’s turn to attack.
Well, you can see an old version of the game here http://storytube.kilu.de/durak7/
Here I avoided my problem by (roughly said) implementing the controllers directly into the game logic and call their methods directly when needed. While this works obviously it couples the model and controller too much and doesn’t arrange with the fact that I want to redesign the game event-driven. Note that I don’t want to fix my problem “somehow” but appropriate so that I know how to deal with such problems in the future.
Enough of the introduction. My game logic class creates a thread when instantiated that has an infinite loop in which the logic is processed, i.e. the state transitions are evaluated and the corresponding functions / events are executed ( "deal_cards_to_hand_1() | sendEvent(“Hand 1 received Card X from Deck”) ). Everything works fine without external input until the logic thread arrives at the state “attacking”. At this point it sends some kind of “request event” with all information needed by the player controller to determine which card to use to attack. It’s stil all fine til here.
However, I’m stuck at how to properly implement the logic thread’s recipience of the controller’s result!
How would I make the logic thread wait / sleep until it receives the reply of a controller, wake it up and make it continue processing with the received result elegantly?
The logic thread is in an infinite loop. How to elegantly pause it?
For now I’ve got a “solution” that doesn’t work at all and is shit but maybe you’ll understand my structural problem better when you understand how I think (or not think ). I make the game logic class implement an interface that has the methods “attack” and “defend”. The game logic instance is registered to the controller through the interface and the controller can directly call the functions of the interface. Only problem is that these methods are not in the logic thread! Look at that pseudeo java code, maybe it’ll make it clear:
class Gamelogic {
Thread logithread {
while(true) {
evaluatelogic()
}
}
void evaluatelogic() {
if(attackstate) {
sendEvent(new AttackRequestEvent(...));
}
else {
dat
}
}
attack(Card card) {} // implented from interface
defend(Card card) {} // implemented from interface
My attempt at a solution would probably look like that:
class Gamelogic {
public Stack inputQueue = new Stack();
Thread logithread {
while(true) {
evaluatelogic()
}
}
void evaluatelogic() {
if(attackstate) {
sendEvent(new AttackRequestEvent(...));
while(inputqueue.isEmtpy()) {//nothing}
attack(inputqueue.pop().getCard());
}
else {
dat
}
}
attack(Card card) {} // without interface
defend(Card card) {} // without interface
The controller processes the “AttackRequestEvent” and sends its result to the input queue “inputQueue” of the Gamelogic class. The Gamelogic thread waits until there is an item in the queue and then pops the item which should be the controller’s result.
The controller can’t communicate with an interface but must use the direct instance of the Gamelogic class although it would only need to be able to send results to the inputqueue.
I can’t really say what I don’t like about it, but it seems ugly to me and not elegant. How can I achieve what I want, regardless how much I’d have to refactor?
This is my “ideal” imagination of how it should work in java (or maybe some other jvm language). Maybe you can show me how this would be done:
It would be cool if the thread could just compute everything until it reached the point where it needs input from the controller (controller of the player). So the thread sends a request and goes to sleep. Now it’s the controller’s task to send a message with the result to the logic thread. By doing this, the thread wakes up, considers the result for its further processing until it again reaches a point where it needs input from the controller and so on… This is actually what I want.
BTW: I’m open for totally different suggestions. I mean, maybe you say that the whole way of doing what I’m doing is doomed to fail from the beginning (although I don’t think so) and you’ve got a super secret solution of approaching my specific problem from a totally different standpoint. I’d be glad to hear that!