Giter Site home page Giter Site logo

heroquest's Introduction

HeroQuest

This project development was part of the MC322 Object-Oriented Programming subject activities.

The proposal was to develop a virtual version of the board game HeroQuest. For doing so, a reduced number of game rules has been used.

Game mechanics

In a nutshell, the developed game consists in a hero who finds herself lost on an unknown place, and needs to kill all monsters nearby. In order to do so, she might use weapons or spells to attack the enemies, armors to protect herself and even use cure potions to restore health points.

There are also chests spread all over the map, which contains the items which can be used during the adventure. Moreover, you can find some hidden rooms, which are accessible by hidden doors, that might contain treasures, as well as monsters. An extra care must be taken while wandering around, since hidden traps might be found quite often.

Therefore, your final goal is to kill all monsters on the map, even those hidden in secret rooms!

For more information about the original game, see Hasbro HeroQuest manual.

Game interfaces

Two different interfaces have been developed in this project: a Command Line Interface (CLI) and a Graphical User Interface (GUI).

CLI

The command line interface uses only the text input and output to control the game actions. This was the proposed user interaction method to the OOP subject project. Therefore, an extra attention has been given to its development.

This game interface can be selected by passing the --cli argument when running the game. More details on how to do this is given in the running section.

Map interpretation

In order to represent the map objects, a codification has been followed. The map below illustrates most of the characters used in the representation.

################
#  C t   # TC  #
#c    E  # TT C#
#  W     # TC  #
###D############
#  F t S    G  #
#  B   Ŝ   C   #
################

The map uses the following mapping:

  • Map structure:
    • # - Walls;
    • - Floor;
    • C - Closed chest;
    • c - Opened chest;
    • D - Closed door;
    • T - Armed trap (when detected);
    • t - Unarmed trap;
  • Heroes:
    • B - Barbarian;
    • F - Dwarf;
    • E - Elf;
    • W - Wizard;
  • Monsters:
    • S - Common skeleton;
    • Ŝ - Wizard skeleton;
    • G - Goblin;
  • View:
    • ? - Unknown (not visible) objects;

Moreover, for object location reference, a coordinate system is displayed on the top and on the left side of the map. The coordinate follows the web screen coordinate pattern, i.e. x-coordinate is from left to right, and the y-coordinate is from top to bottom. The (x,y) coordinate is always used when a location reference is shown or asked the player.

GUI

This is the default interface. It runs in a fix-sized window, which renders the game configuration menu, and the game itself.

In the current game version, the graphical interface has the same command interface as the command line. In other words, the turn actions are displayed at the side text panel, and have the same input interface (numbered choices selected by their index). Some differences still exists, though. For instance, in order to select a destination for the teleport spell, a mouse click is used to get to the desired location.

Installing

In order to run the game, you'll have to first install the Java Runtime Environment (JRE) for Java 14. We strongly recommend installing it following the OpenJDK platform instructions.

The game installation itself is as simple as downloading the latest game version. To do so, use the GitHub release tab to find the latest released version, and download its JAR attached file.

It is possible to place the file on a system installation folder. In a Linux system, for instance, you may place it on the /usr/local/bin folder. However, this is not required to execute the game.

Running

After installing the game, to run it using the Graphical Interface, simply double-click the downloaded JAR file, or execute on the command line with:

$ java -jar heroquest.jar

In order to run the CLI version, just add the --cli argument:

$ java -jar heroquest.jar --cli

Modifying the game

Some game modification does not require to change the source code, such as adding new maps. We'll present this change first, and then introduce to how recompile the source code after any modification.

Creating your own map

As we have shown previously, a codification has been used to display the map object during the game. The same codification is used on the pre-defined maps on the disk. However, some differences exists. First, on the pre-defined maps, the secret object must be represented. In the current game version, only secret door can be specified on the map. In order to do so, use the P character instead of D. Other hidden objects, such as traps, are added in different locations regardless of the map being pre-defined. The same happens for monsters. Therefore, only the map structure (wall, doors) and fixed objects (closed chests) can be arranged on the map when creating your own.

In order to include the created file into an existing JAR game file, just extract the JAR file, include the created map on the maps folder, and zip it once again (alternatively, it is possible to include the file to the folder without extracting the files). This will make the game automatically list the map when running.

Recompiling

First you will need to have Maven installed, which is used for compiling the source code, and generating the JAR file. To do so, please refer to the Maven installation guide. This step also includes installing the Java Development Kit (JDK). Here we use the Java 14 version, provided by OpenJDK.

Once Maven is installed, you just need to run the following command:

$ mvn clean compile assembly:single

Here we first clear eventual previous builds with the clean routine, then compile the source code, and finally assembly the project into a jar file with all dependencies.

Troubleshooting

If you get an issue with some of the Maven plugins, you can force them to be updated, which will also install any missing dependencies listed in the pom.xml file. For doing so, use the following command:

$ mvn clean install -U

If this does not work, consider creating an issue.

Contributing

If you find any improvement you are willing work on, please fork the project, and create a pull request with the updates.

Contributors

Acknowledgements

We'd like to thank our OOP teacher Leonardo Montecchi for our useful discussions on online meetings, which helped to improve our approaches and offered some insights on how to better organize the project. In addition, we thank him for the great classes, which made this project possible to be done following mostly good practices.

heroquest's People

Contributors

henriquesimoes avatar matheuss1 avatar renanffernando avatar

Stargazers

 avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

heroquest's Issues

Monitor sujo

Embora seja um trocadilho, é de fato o que está acontecendo no jogo. Quando um jogo termina, o antigo GameLoop e Map continuam inscritos para receber notificações sobre os walkers.

Generalização do pacote objects

Estava vendo que não tem necessidade do pacote map.objects ter esse namespace "map", ou seja, não muda nada em termos de dependência a mudança dele para a raiz do projeto. Tenho a impressão de que ele ficaria mais ou menos no mesmo sentido dos pacotes skills e item.

Faz essa mudança para tentar deixar mais coerente a organização dos pacotes ou vocês veem como algo mais relacionado com o mapa mesmo?

Monstros pulando do baú

Falta incluir monstros que saem do baú durante interação do jogador.

Vamos fazer isso dando o mapa ao baú realmente?

Habilidades especiais nos itens

Tem algumas armaduras com descrições que diz que elas aumentam o números de dados de um tipo diferente do defesa. Acham que de fato vale a pena fazer isso? Porque vai dar um trabalhinho viu.

Incompatibilidade da PlayerInterface

Estou criando esse issue para documentarmos que essa modificação faz-se necessária. No caso, essa incompatibilidade que descrevo é mais precisamente a utilização sempre de formas de exibição pelo terminal na classe PlayerInterface, o que impossiblita a utilização de uma forma gráfica (GUI).

Aliado a isso, tem a questão de já ter sido incluída uma classe para interação com o usuário (inspirada na própria PlayerInterface) no pacote heroquest.terminal.

Não realizei essa mudança já no pull request #15, pois há a necessidade de mudança em mais classes, como a WalkerPlayer, para poder eliminar essa incompatibilidade.

Sugiro de utilizarmos a classe heroquest.view.IOInterface no lugar da PlayerInterface. Nesse caso, o próprio pacote util.playerInterface poderia ser excluído. Pode haver a necessidade de alterar a interface IOInterface ao realizar a refatoração. Caso isso ocorra, seria interessante manter nomes e métodos coerentes com ambas as possilidades de interface: terminal e gráfica.

Caso tenham algo a acrescentar sobre as mudanças e possiblidades existentes, podemos discutir por aqui também.

Ah, aproveitando, caso alguém de vocês pegue para realizar as modificações necessárias, ao criar o pull request, tem como realizar um link entre o pull request e este issue (de forma que o issue é automaticamente fechado caso o pull request seja aceito e incorporado).

Input mismatch exceptions

No momento não fizermos o tratamento de entradas equivocadas em alguns casos. Por exemplo, na seleção das ações a serem executadas no turno, ao digitar uma letra, é lançada a exceção InputMismatchException que não é capturada, causando o término abrupto do jogo.

Uma revisão completa desse tipo de entrada inesperada faz-se interessante, dado o estágio que estamos de desenvolvimento e do prazo de entrega.

Seleção do destino no teletransporte

Percebi que para mapas gerados automaticamente, é comum ter muitas posições visíveis. Isso leva a existir na ordem de centenas de coordenadas possíveis para serem escolhidas (um testamento na tela). Estou começando a achar que possibilitar a inserção do usuário das coordenadas e na sequência validar pode ser mais interessante do que a abordagem atual.

Alguma outra sugestão de como lidar com isso?

Potencial loop infinito

O loop de inserção em uma posição aleatória do mapa pode rodar pra sempre quando não tem mais posição disponível. Sei que é improvável de acontecer num mapa grande, mas é uma situação possível.

Agora teria que pensar numa forma de incluir uma checagem dessa impossibilidade. Talvez pegar todos as Units que estão livres e depois selecionar aleatoriamente dentre elas seja melhor nesse sentido, embora utilize mais memória. Com essa abordagem que mencionei, acho que há uma melhora do caso médio também (quando o mapa está bem cheio, pode acontecer muitos chutes para posições ocupadas com a implementação atual).

Originally posted by @henriquesimoes in #23

Inserir mais mapas prontos.

Atualmente só tem 1 mapa como padrão, seria bom inserir ter pelo menos 3 tamanhos diferentes e inserir uns 2 de cada tamanho.

Herança de heróis e monstros

Estava reparando que não parece ser necessária a herança para heróis e monstros. A única coisa que a herança está fazendo é setar o time e definir o valor da face do CombatDice que é favorável ao Walker. Acho que dá para remover as classes Heroe Monster e utilizar somente a definição do Team para decidir as coisas. Ficaria algo como:

public enum Team {
    HEROES {
        @Override
        public CombatDiceFace getFavorableDiceFace() {
            return CombatDiceFace.HERO_SHIELD;
        }
    },
    MORCAR {
        @Override
        public CombatDiceFace getFavorableDiceFace() {
            return CombatDiceFace.MONSTER_SHIELD;
        }
    };

    public abstract CombatDiceFace getFavorableDiceFace();
}

e com a alteração no Walker.getDefenceIntensity para:

protected int getDefenseIntensity(int numberOfDices) {
    int intensity = 0;

    for (int times = 0; times < numberOfDices; times++)
        if (combatDice.roll() == getTeam().getFavorableDiceFace())
            intensity++;

    return intensity;
}

O que vocês acham?

Tratamento de exceções

Embora tenhamos utilizado poucas exceções, em algumas partes incluímos o lançamento, mas não realizamos o tratamento em local algum. Em alguns casos, o código é esperado funcionar sem ocorrer a exceção, mas poderia ocorrer o lançamento. Um exemplo é o estado inválido do mapa ao estar cheio e se tentar inserir uma nova armadilha ou walker. Acho que deveríamos tratar isso mesmo que seja impossível de ocorrer com a configuração atual.

Adição de outros heróis como jogáveis

Um aspecto importante que ainda está faltando ser incorporado ao jogo é a possibilidade de escolha dos outros heróis para serem jogáveis também. Lembro de ter algo sobre a escolha de skills de magia também. Agora fiquei em dúvida se também é algo a escolha do usuário ou se é dada pelo personagem escollhido justamente. De qualquer maneira, essa é uma feature faltante no jogo.

Mensagem de fim de jogo equivocada

Ao fazer alguns testes em outra parte que estou desenvolvendo, percebi que ao morrer, o GameLoop está exibindo a mensagem your team wins quando na verdade o jogador perdeu.

@renanffernando, se você puder pegar para tentar reproduzir o erro, identificar a causa e corrigir, ficaria grato.

Opção de desistir do jogo

Acham que vale a pena criar uma opção para se desistir do jogo e voltar ao menu inicial?

Muitas vezes aproveito que não tem o tratamento de NoSuchElementException lançada pelo Scanner (quando insiro o caractere EOF com Ctrl+D) para parar o jogo na hora de testes.

Remoção da PlacementStrategy

Realizar a remoção da PlacementStrategy e passar a utilizar os métodos canPlaceWalkerOn (ou algum método alternativo) para a decisão da disposição dos objetos do mapa.

Para mais informações sobre essa decisão, vide discussão pull request #23.

Jogador nunca perde

Ou pelo menos nunca é avisado explicitamente disso. Como o WalkerManager do jogador é removido quando ele morre, o time dele fica sempre sem manager quando é executada a notifyEndGame, ou seja, ele nunca é avisado que perdeu (nem que ganhou).

Informações sobre interpretação do mapa

Um aspecto que estamos levando em consideração que seja totalmente intuitiva é a forma como o jogador interpreta mapa. Acham que seria importante incluirmos uma opção para a visualização do mapeamento dos símbolos utilizados?

Descrição das habilidades

Reparei que temos a descrição das habilidades no código, mas não utilizamos em momento algum. Alguma sugestão de como incorporar isso?

Novo validador para inserção de armadilhas.

Vi que em #41, foi tratado erro no qual o mapa está tentando colocar uma armadilha aonde já existe uma. Sugiro implementar um novo validador para solucionar problema (de preferência após ser aceito o pull request dos validadores que está aberto).

Duplicidade de classes

Existem duas classe Weapon implementadas, uma dentro do pacote item.baseitems e outra no pacote item.weapons. A classe que está dentro do package de Weapons é a completa, mas a de dentro do baseitems também está sendo utilizada em partes do código.

Mudança da forma de visualização das regiões ocultas

Modificar a forma como são representadas as regiões que não estão sob a visão do jogador. Atualmente se tem a mesma configuração das paredes, o que torna mais confusa a interpretação do mapa.

Agora entra um ponto de decisão sobre o que seria mais interessante: um caracter visível diferente ou espaço em branco?

Feedback ao buscar por itens ocultos

Adicionar alguma forma de mensagem ao se buscar por itens que estejam eventualmente ocultos. Atualmente nenhuma mensagem indicando a existência de itens é exibida. Isso pode trazer dúvidas ao jogador se realmente fora efetuado o comando.

Reaproveitamento de código na região visível

Notei que existe o praticamente o mesmo código para a criação (método build) das regiões visível e limitada. Acham que faria sentido fazer um reaproveitamento nesse caso criando alguma relação entre elas?

Novo pacote engine

Estava pensando se não compensa colocar a GameEngine no pacote loop e renomear para engine.

Uma outra reflexão que estava fazendo é se não compensaria também jogar o pacote terminal (e também o pacote da GUI) para esse novo pacote. Acho que acaba aumentando a profundidade da hierarquia, mas parece ficar mais organizado.

Opiniões?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.