Coder Social home page Coder Social logo

tribes's Introduction

Tribes

GitHub release (latest by date) Tribes Java 93.5% GitHub All Releases GitHub stars

About

A turn-based strategy game framework. Tribes is a multi-player, multi-agent, stochastic and partially observable game that involves strategic and tactical combat decisions. A good playing strategy requires the management of a technology tree, build orders and economy. The framework provides a Forward Model, which can be used by Statistical Forward Planning methods.

Requirements

Java 8 or later is required to run the project. Download Java here.

Getting started

In order to run the code, you must either download the repository, or clone it. If you are looking for a particular release, you can find all listed here.

Tribes Download

The simplest way to run the code is to create a new project in IntelliJ IDEA or a similar IDE. In IntelliJ, create a new project from existing sources, pointing to the code downloaded or cloned. This process should automatically set up the environment and add any project libraries as well (JSON library only required for version 1.0).

Alternatively, open the code directly in your IDE of choice and add libraries included in the download from the lib/ package. Make sure src/ is marked as sources root.

Running the framework

The main class for running the framework is Play.java found in the sources root directory. The main method in this class contains 3 ways of running the code. The parameters for all these execution modes can be found in the configuration file play.json.

  1. Play one game with visuals, using the level generator. Call the play method with the following possible settings:

    • tribes: array of type Types.TRIBE containing the tribes that will be assigned to the players.
    • level seed: random seed for the level generator
    • players: array of type PlayerType containing the players taking part in the game; the tribe they receive depends on the order, mapping directly to the tribes array (thus the two arrays must also be of the same length).
    • game mode: variable of type Types.GAME_MODE, which can take either Capitals or Score values in version 1.0, to change the mode of the game played.
  2. Play one game with visuals, with level loaded from a file. Call the alternative play method with the following possible settings:

    • file name: path to file containing the level to be loaded.
    • players: array of type PlayerType containing the players taking part in the game; the tribe they receive depends on the order, mapping directly to the tribes defined in the level; read order of tribes in level files is top-left to bottom-right (the player array must contain exactly enough players for the loaded level).
    • game mode: variable of type Types.GAME_MODE, which can take either Capitals or Score values in version 1.0, to change the mode of the game played.
  3. Play one game with visuals, with whole game loaded from a file. Call the load method with the following possible settings:

    • players: array of type PlayerType containing the players taking part in the game; the tribe they receive depends on the order, mapping directly to the tribes array saved in the file (thus the two arrays must also be of the same length).
    • file name: path to file containing the JSON saved game to be loaded.

Additionally, other variables can be modified for an effect with all methods of running the framework in this file:

  • AGENT_SEED: this variable defined at the top of the file can be given a new value, to set the random seed used by the AI agents.
  • GAME_SEED: this variable defined at the top of the file can be given a new value, to set the random seed used by the game (e.g. for deciding random bonuses when exploring ruins).
  • RUN_VERBOSE: this variable defined at the top of the file can be set to true (producing detailed output while running the game) or false.

The _getAgent method and the PlayerType enum can be used to set which AI players are available to run in the framework, and new ones can be defined by including both a type, and a corresponding constructor. Currently defined players have parameter options set as well, which can be modified for different behaviours.

No visuals

To run without visuals, set the following variable in the core.Constants.java class to false:

    public static boolean VISUALS = true;

Other intersting variables in the core.Constants.java class for running games include:

    static final int MAX_TURNS = 30;  // Maximum number of turns when playing in Score mode
    static final int MAX_TURNS_CAPITALS = 50; // Maximum number of turns when playing in Capitals mode
    public static final boolean PLAY_WITH_FULL_OBS = true; // If false, agents receive game states with information hidden for areas covered by fog of war
    public static boolean GUI_FORCE_FULL_OBS = false; // If true, display still shows full observable game states even if players play with partial observability
    public static boolean WRITE_SAVEGAMES = false;  // If true, all games played are saved to files
    public static boolean DISABLE_NON_HUMAN_ACTION_HIGHLIGHT = true;  // If true, human observing/playing doesn't have access to actions of non-human players
    public static int FRAME_DELAY = 500; // The display delay between frames
    public static boolean TURN_LIMITED = false;  // Limits games to maximum number of turns
    public static long TURN_TIME_MILLIS = 10000000; // Limits a player's thinking time to this many milliseconds
    public static boolean GUI_PAN_TO_TRIBE = false;  // Pans to a tribe's capital when turn changes
    public static boolean GUI_DRAW_EFFECTS = false;  // Draws animations for unit actions

Tournaments

To run round-robin tournaments between multiple AI players, run class Tournament.java. Running a tourament requires some parameters, which are indicated in the file tournament.json. Among these parameters, you may determine:

  • game mode: Int, 0 for Capitals, 1 for Score
  • # repetitions: Int, number of repetitions per match-up
  • max length: Int, maximum number of turns per game
  • force turn end: Int, 1 if true, 0 if false, forces players to end their turn after 5 moves if true.
  • MCTS rollouts: Int, 1 if true, 0 if false, decides if MCTS is using rollouts or not
  • population size: Int, for population-based algorithms, e.g. RHEA
  • players: String x N, N player types taking part in the game
  • tribes: String x N, N tribes for the game, same number as players
  • Level Seeds: A series of random seeds for the game levels.

Tournament results indicate number of games played (N), number of wins (W) and win rate, score (S), number of technologies researched (T), number of cities (C) and star production (P) for each player.

Game configuration

The game itself can be modified by changing its configuration (e.g. attack power of certain units) in the core.TribesConfig.java file.

Associated research

  • Diego Perez Liebana, Yu-Jhen Hsu, Stavros Emmanouilidis, Bobby Khaleque, Raluca Gaina, "Tribes: A New Turn-Based Strategy Game for AI", in Sixteenth AAAI Conference on Artificial Intelligence and Interactive Digital Entertainment (AIIDE), 2020.

Acknowledgements

This work is supported by UK EPSRC research grants EP/T008962/1 and IGGI CDT EP/L015846/1

tribes's People

Contributors

amrit-code avatar bkhaleque avatar diegopliebana avatar gaigresearch avatar owenstanley avatar rdgain avatar rovenr12 avatar stevemman avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

tribes's Issues

Resources that can't be resourced

  • Ore can't be gathered. Instead, a mine can be built when there's an Ore resource.
  • Crops can't be gathered. Instead, a farm can be built when there's a Crops resource.

I've removed these options from the ResourceGathering.execute() methods, but I wonder if the mine and farm building are taking the added production into account.

Converted units

Units that join a tribe via the Convert action do not count as population for any city. That also means that we're not adding them to any city, so they're lost in time and space - we can't access them from a Tribe. We need to hold those unit ids somewhere (maybe Tribe)?

GUI Tooltips

Actions should describe effects & requirements.

+5 points for each tile discovered

also, +20 points for every non-city tile added to the tribe's territory. This means that converting village into city means 180 points (100 for city level 1 + 8x20 tiles around for borders). Level Up - Border_growth also adds +20 for all the new tiles.

Savegames

We need functionality to saving/loading gamestates. Ideally in a human readable format (i.e. JSON).

Monuments

Tribes should manage monuments counters. Actions should be created accordingly.

Handle Unit Status

  • analyze transition code
  • init at start of turn
  • call from all appropriate actions

Attack action

The attacking unit gets damage back from the target if the target is not killed. This is not happening now in the Attack action.

Also, in some cases (when the attacker is not a ranged unit), the attacker takes the position of the target if the target is killed.

Meeting a tribe

Meeting a tribe for the first time grants knowledge of a technology. I'm not sure if the fandom says how does this happen...

Board.getCityTiles() performace

At the moment, this method runs through the whole board to check tiles that rarely change. Add a list of tiles to City.java (ArrayList, order doesn't matter) that is updated with the calls to Board.setBorderHelper() and access through that list instead.

Preferred: same method, different limits (not size, but position+-RANGE)

Actions Coordinates Bounds Check

All actions should be checking bounds on any positions (e.g. neighbours) they're considering and querying the grid for (>=0 and <gridSize). Currently some crash if units move to the edges.

E.g. AttackFactory.computeActionVariants() method has a loop that checks neighbouring cells, but those coordinates are not validated to be within the grid. Likely to be the case in others as well.

// Loop through unit range, check if tile observable and action feasible, if so add action
        for(int i = position.x - unit.RANGE; i <= position.x + unit.RANGE; i++) {
            for (int j = position.y - unit.RANGE; j <= position.y + unit.RANGE; j++) {
                //Not attacking itself
                if(i != position.x || j != position.y) {

                    Attack a = new Attack(unit.getActorId());
                    Unit other = b.getUnitAt(i, j);
                    if (other != null) {  // Check if there is actually a unit there
                        a.setTargetId(other.getActorId());
                        if (a.isFeasible(gs)) {
                            attacks.add(a);
                        }
                    }
                }
            }
        }

Handle turn change

Needs two parts:

  • Move the current turn (GameState.activeTribeID) to the next tribe.
  • Compute the starting turn events: star provision and score update

Note that, if enemy unit is in an owned city, that city does not generate stars that turn.

Uses of Random

All random events in the game must come from a common Random object (which uses a determined random seed).

Board.occupy(...)

This function needs changing. A village is not a City object, but a terrain type.
Needs to manage two cases:

  • When the city belongs to another player.
  • When it's occupying a village, not a city.

Boats, Ships and Battleships

We've somehow forgotten about naval units (Boat, Ship and Battleship). They were missing in the Types enum, sprites and we don't have classes for them.

I added them to Types and found the sprite sets for them. Stavros, can you please add the classes to the corresponding package? (there are no dependencies, they can be added to the refactor-2 branch). Sprites and types are now merged into master.

Action Pack A

  • Attack (unit action)
  • Capture (unit action)
  • Convert (unit action)
  • Resource Gathering (city action)

Action lists copied in GameState.copy()

GameState.copy() missing a deep copy on the actions lists, otherwise they're not actually received by the players/GUI. Those lists are possibly affected by the actions refactor too?

Destroying a Custom House

Destry.java, execute()

When destroying a CUSTOM HOUSE building, see:

//TODO: Is this correct? The production of a custom house depends on the number of Ports around it,
// so I'm not sure this should be a constant value.

city.subtractProduction(removedBuilding.getPRODUCTION());

City.java using clone()

One thing we need to avoid using is clone() - I may have forgotten mentioning this.

We need to create our own copy method for the objects, as clone() has shown unstable behaviour. This is specially true for objects contained in data structures.

Building checks

BUILDING

  • Check if types are actually assigned to building classes
  • Use constants from Types.BUILDING (instead of TribesConfig)
  • Make sure all the side effects for Buildings are counted.

CUSTOM HOUSE

  • isBuildable(): it must check if there's at least 1 port adjacent to it. Otherwise it can't be built.

  • New method in CustomHouse: computeProduction(c, gs) -> computes and returns the production of this custom house.

Custom House will have its own production that is not added to the city. That way it's easier to ignore this production when destroyed.

FORGE, SAWMIMLL

  • Check adjacency conditions for these buildings

Action Pack C

  • Examine (unit action)
  • Spawn (city action)
  • Clear Forest (city action)
  • Grow Forest (city action)
  • Burn Forest (city action)
  • Destroy (city action)

Points for spawning units

Spawning units gives points to the tribe. I haven't seen when in the wiki is this reflected, but it does happen. Also Disband removes these points from the tribe.

Action Pack D

  • Actions upgrade level 2
  • Actions upgrade level 3
  • Actions upgrade level 4
  • Actions upgrade level 5+
  • End Turn Action

Converted Units #2

Move from objects to unit ids
Also another name for the variable. It contains converted units, but also those derived from unit shifts.

Star generation

Star generation at the beginning of each turn needs to be computed.
Note that, if enemy unit is in an owned city, that city does not generate stars that turn.

Negative populations

Populations can be negative in cities, which happens when losing connection to the capital. But I'm not 100% sure how it happens, so needs investigating.

One clear effect is that a city with -X population generates -X stars.

Action Pack B

  • Move (unit action)
  • Heal Others (unit action)
  • Upgrade (unit action)
  • Build (city action)

Refactoring in buildings

There are two main things that can be refactored in the buildings hierarchy:

  1. There are some variables that are common to many buildings (example: cost) that can be in the upper class (Building) and not in the derivate. In fact, probably most of them are (production, type, even the constraints). We can set void values (null, or 0) to those units that do not have production, for instance. The same is true with the accessor functions (getType(), for instance, but also others).

  2. The actual (constant) values for different properties of buildings should be extracted to a common file. I've created TribesConfig.java for this (check this in the branch refactor-2). The best way would be to pass this values in the class constructor - I've made an example of this for Warrior.java, in refactor-2 branch).

And two extra things that may help simplify things:

  1. All monuments (TowerOfWisdom, ParkOfFortune, etc.) are essentially the same, so we could probably converge them all in a single class Monument.java and remove the other ones.

  2. Doesn't the same concept above in (3) applies to the different types of Temples in the game.

Overall, the concept is to move to a more data-driven approach. Less classes/code and more reliance on parameter values.

Note that in the branch refactor-2 I've also made a refactoring of files and packages below 'units' (now called 'actors', to reflect its meaning better).

[UPDATE] UNITS shifts

When a new city is captured (from a village to city), one UNIT moves there from the capital.

If capital has UNIT == 0, then it's taken from another city (at random?)

City Issues

If an enemy unit or Nature Bunny moves into one of your cities, star production from that city will stop entirely and you will gain 0 stars from it the next turn. City Class

Units in their tribe's city get a +50% (ร—1.5) defence buff, which increases to +300% (ร—4) if the city has city walls. Defense Action

It is also important to note that the amount of cities you own influences the prices of tech on the Technology Tree. 1 star per extra city for Tier 1, 2 stars per extra city on Tier 2 and 3 stars on Tier 3 techs. Technology Action

Actor ID errors

Current codebase version gives a lot of exceptions everywhere where a list of actors and actor IDs are used, and possibly more - it seems a lot of these IDs are lost at some point, maybe not copied?

Also, do tribes need actor IDs? I can't think of a case where the tribe would be retrieved by actor ID instead of tribe ID.

E.g.

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -1
at core.game.Game.initTurn(Game.java:273)
at core.game.Game.processTurn(Game.java:211)
at core.game.Game.tick(Game.java:189)
at core.game.Game.run(Game.java:164)
at Run.runGame(Run.java:28)
at Play.main(Play.java:46)

Exception in thread "main" java.lang.NullPointerException
at core.actions.cityactions.LevelUp.isFeasible(LevelUp.java:34)
at core.actions.cityactions.factory.LevelUpFactory.computeActionVariants(LevelUpFactory.java:24)
at core.actions.cityactions.factory.CityActionBuilder.getActions(CityActionBuilder.java:23)
at core.game.GameState.computePlayerActions(GameState.java:160)
at core.game.Game.initTurn(Game.java:315)
at core.game.Game.processTurn(Game.java:211)
at core.game.Game.tick(Game.java:189)
at core.game.Game.run(Game.java:164)
at Run.runGame(Run.java:28)
at Play.main(Play.java:46)

Constants extraction from Units

All constant values (properties of units) should be extracted to a common file: TribesConfig.java

  • I've made this with Warrior.java as an example.

Check this in the branch refactor-2
Note that in this branch there's also a refactoring of files and packages below 'units' (now 'actors', to reflect its meaning better).

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.