Toto je dokumentácia k našej Špongia hre KSP. V tejto hre dokáže používateľ vytvárať vlastných botov v LuaScript ktorí následne fungujú ako agent v hre.

Cieľ hry

Krátkodobý cieľ

V hre hrajú proti sebe dvaja hráči. Každý z nich má na začiatku nejaké svoje planéty. Každá z planét v pravidelnom intervale generuje vesmírne lode. Hráči dokážu posielať vesmírne lode na iné planéty:

  1. Ak pošlem lode na svoju planétu, počet lodí na danej planéte bude súčtom poslaných a lodí, ktoré tam už boli.
  2. Ak pošlem lode na cudziu planétu, tak každá poslaná loď zníži počet tamojších lodí o 1. Akonáhle by počet mal ísť do záporu, vysielací hráč planétu získa.

Cieľom je takýmto spôsobom získať všetky planéty.

Dlhodobý cieľ

Hráči si vedia generovať botov. Boti sa píšu v jazyku Lua, nižšie je popísaná dokumentácia. Boti sa dajú pridávať na stránke

Pri vstupe do hry si hráč bude môcť z db vybrať, ktorých dvoch botov proti sebe pustí (alebo jedného z nich nahradí sebou). Každý zápas bude mať víťaza a porazeného.

Každý bot má svoje ELO. Po každom zápase sa mu ELO zmení vzorčekom rovnakým ako pri šachu. Na stránke ranking je vidieť aktuálne poradie všetkých botov. Cieľom každého bota je byť čo najlepší a mať čo najvyššie ELO.

Controls

Ked sa hráte ako player, tak hru kontrolujete nasledovne:

  1. Na poslanie lodí medzi dvoma planétami najskôr označíte svoju a potom planétu
  2. Ak pošlem lode na cudziu planétu, tak každá poslaná loď zníži počet tamojších lodí o 1. Akonáhle by počet mal ísť do záporu, vysielací hráč planétu získa.

Herný cyklus

Hra funguje takto (pri default settings, konštanty sa môžu meniť):

20 krát za sekundu sa odohrá kolo - aj keď hra možno vyzerá realtime, všetko beží na takéto kolá. V kole sa stane po rade toto:

  1. player1.Execute() - ak je tento hráč fyzický hráč, teda inštancia PhysicalPlayer tak toto neurobí nič. Ak je inštancia BotPlayer, tak to TOMTO BODE ZBEHNE VÁŠ LUA KÓD.
  2. player2.Execute() - to isté pre druhého hráča.
  3. Pridá každej planéte units podľa levelu. V pozadí má každá planéta hodnotu getsUnitInTurns, ktorá sa znižuje každým kolom, až kým nedosiahne 0, kedy pridá planéte unit a resetuje sa.
  4. Executnú sa všetky Action hráča 1.
  5. Executnú sa všetky Action hráča 2.
  6. Skontroluje sa, či niekto nevyhral.

Lua Globals

Ako botovi v Lua vám sú exposed základne funkcie a to:

Typy

Planet

using UnityEngine;

using UnityEngine;


namespace DefaultNamespace
{
    public class Planet
    {
        internal int level = 0;
        internal int units = 0;
        internal int getsUnitInTurns;
        internal Player owner;
        internal Vector2 position;
        internal int maxUnits;


        public int Level => level;


        public int Units => units;


        public int GetsUnitInTurns => getsUnitInTurns;


        public Player Owner => owner;


        public Vector2 Position => position;
    }
}

Constants

Tieto konštanty viete accessovať:


namespace DefaultNamespace
{
    public class Constants
    {
        public const int TURNS_PER_SECOND = 20;
        public const int MAX_LEVEL = 5;
        public const float TRAVEL_SPEED = 0.05f;
        public static readonly int[] PRODUCTION_PER_TURN_BY_LEVEL = new int[MAX_LEVEL] { 20, 15, 10, 8, 5 };
        public static readonly int[] MAX_CAPACITY_BY_LEVEL = new int[MAX_LEVEL] { 10, 20, 25, 35, 50 };
        public static readonly int[] UPGRADE_COST_PER_LEVEL = new int[MAX_LEVEL - 1] { 5, 10, 20, 30 };
    }
}

Player

Abstract class z ktorej dedia BotPlayer aj PhysicalPlayer. Tieto dve nemajú žiadnu ďalšiu funkcionalitu accessible cez bota.

using System.Collections.Generic;


namespace DefaultNamespace
{
    public abstract class Player
    {
        internal PlayerNumber playerNum;
        internal List<GameAction> actions;
        internal string humanReadableName;
        internal Player(PlayerNumber number)
        {
            playerNum = number;
            humanReadableName = "Physical";
            actions = new List<GameAction>();
        }


        internal abstract void Execute();


        public PlayerNumber PlayerNum => playerNum;


        public string HumanReadableName => humanReadableName;
    }
    public enum PlayerNumber{
        Player1,Player2,None
    }
}

Vector3

Každá planéta je definovaná ako Vector v Unity.

Funkcie

get_planets

get_planets syntax vyzerá takto:

allPlanets = get_planets()

Returns: Planet[]

upgrade

upgrade syntax vyzerá takto:

upgrade(myPlanet)

Pridá UpgradeAction(myPlanet) na koniec Player.actions

send_units

send_units syntax vyzerá takto:

send_units(origin, target, amount)

Pridá SendUnitsAction(origin, target, amount) na koniec Player.actions

log

log syntax vyzerá takto:

log("hello world")

Priamo sa logguje na obrazovku.

Príklady botov

Tu sú príklady jednoduchých botov:

Dumbbot

Tento bot posiela unity až kým nemôže, a skúša sa upgradovať.

function getMyPlanets(planets)
    myPlanets = {}
    index = 1
    for i = 1, #planets do
        if planets[i].Owner == bot then
            myPlanets[index] = planets[i]
            index = index +1
        end
    end
    return myPlanets
end
function getOpponentPlanets(planets)
    opponentPlanets = {}
    index = 1
    for i = 1, #planets do
        if planets[i].Owner ~= bot then
            opponentPlanets[index] = planets[i]
            index = index + 1
        end
    end
    return opponentPlanets
end

function turn()
    planets = get_planets()

    myPlanets = getMyPlanets(planets)
    opponentPlanets = getOpponentPlanets(planets)
    if #opponentPlanets == 0 then
        return
    end
    for i = 1, #myPlanets do
        planet = myPlanets[i]
        if planet.Level < 4 then
            if planet.Units >= Constants.UPGRADE_COST_PER_LEVEL[planet.Level+1] + 5 then
                upgrade(planet)
            end
        end
        send_units(myPlanets[i],opponentPlanets[1],1)
    end
end