dimanche 12 avril 2020

Polymorphic implementation of a board game with MVC (Java)

I'm developing a board game called Santorini using Java and I'm having some troubles in figuring out the correct way/pattern to implement the polymorphic aspects of it.

For the ones that don't know the rules, I will briefly summarize part of them: The basic Turn is made of a Move phase where you move your "character" followed by a Build phase where you build a block on the board. In the advanced version of the game every player chooses a God card at the start of the game and the card gives the player some special powers that modify radically his turn, both in the order of his actions and in the modifications of them. For example the God Card could alter the order in which you perform these actions, giving you an extra move or build action (ex. you can build before and after moving), or change the possible spaces available for an action (ex. you can move your character in spaces that are already occupied by other opponents, which normally you cannot). So I changed the game logic making it a four phase turn (Move,Build,Optional Move, Optional Build).

The problem I'm having is that, following a typical MVC pattern design, I want to have only one Controller that deals with every type of God available, but I'm not sure on how to achieve that. My first idea was to create an abstract class called God, with an ArrayList of availableActions and abstract methods like getAvailableMove(), getAvailableBuild() that would return a list of spaces available for the user for that particular Action. Then there is a class for every God which extends the God abstract class and overrides the methods, plus adding extra methods for the optional phases. Every God would instantiate the availableActions list in their constructor following their turn logic, so that the controller just has to go through every action in the ArrayList to "play" the turn.

public abstract class God {
    protected ArrayList<Phase> availableActions= new ArrayList<>();
    protected GodsNames name;

    public abstract ArrayList<Space> getAvailableMove(Player player);

    public abstract ArrayList<Space> getAvailableBuild(Player player);}


public class Artemis extends God {

    Artemis(){
        this.name = GodsNames.ARTEMIS;
        availableSteps.add(Phase.MOVE);
        availableSteps.add(Phase.BUILD);
        availableSteps.add(Phase.OPTIONALMOVE);

    }

    @Override
    public ArrayList<Space> getAvailableMove(Player player) {...}
 @Override
    public ArrayList<Space> getAvailableBuild(Player player) {...}

    public ArrayList<Space> getAvailableOptionalMove(Player player) {...}
}

The problem is that a lot of Gods share a default implementation either of getAvailableMove or getAvailableBuild. But I cannot write the default implementation for both the methods in the God class of course, if not the class wouldn't be abstract. And because a "generic God" object doesn't exist in the game, I think it would be pointless to make "God" a non abstract class. But doing so, I'm writing loads for extra code for nothing (Gods are more than 30). Is there another design pattern that might fit more the dynamics of this board game? Do any of you have experienced a situation similar to this in terms of game logic implementation? I know the explanation of a game cannot be done precisely in a few words, but I tried to be as clear as possible. Thank you to everyone that will reply or just read the question.

Aucun commentaire:

Enregistrer un commentaire