Гра міст


34

Вступ

Гра відбувається в маленькому світі з різними містами. Правителі міст ненавидять один одного і хотіли б керувати світом. Люди поділяються на дві групи, воїнів і малонароджених. Однак малолітні можуть піднести до воїнів. Ви правитель трьох цих міст.

Ігровий процес

Коли гра починається, ви правите над трьома містами. У кожному місті є 100 чоловік. Ви повинні розділити їх на лицарів і малонародних.

Потім починається власне гра, яка покрокова. Поворот виглядає приблизно так: "Produce" knights=> execute command of first town=> execute command of next town(повторити для всіх міст) => try a rebellion.

  • Щоразу, ваша програма буде викликатись для кожного міста, яке належить вам . Можна або напасти на місто , підтримати місто або просто почекати . Ці дії виконуватимуться послідовно, а не одночасно.
  • Кожен третій хід, ви отримуєте одного лицаря на 2 малонароджених (23 низьких народження => 11 лицарів). Кількість малозабезпечених дітей залишається однаковою.
  • Лицарі всередині міста мають бонус за оборону 1,2. Якщо ви нападете, ваші лицарі будуть помножені на це число (наприклад 78 knights, у вас є 93 knightsпід час нападу). Після нападу зайві лицарі будуть вилучені (якщо 82 knightsвиживуть, ви все одно будете мати 78 knights).
  • В атаці кожен лицар вбиває ворога, перш ніж він помре. Наприклад: 30 knightsатака 100 knights(без бонусу за захист) => 70 рицарів виживають.
  • Ви можете захопити місто, убивши всіх лицарів всередині нього . Усі малолітні належать вам зараз, а ваші вцілілі лицарі розміщені в місті. У наступному турі ви можете керувати цим містом на додаток до всіх інших міст .
  • Після захоплення міста у нього не буде бонусу за оборону протягом 2 повних оборотів (бо ворота зламані). На третьому ходу ворота будуть відремонтовані.
  • Щоб запобігти повстанству малозабезпеченим, вам потрібно принаймні вдвічі більше рицарів, ніж малозабезпечених (23 низькорослих у місті потребують принаймні 12 лицарів у тому ж місті). Інакше маломовні вбивають усіх лицарів, і місто стає «нейтральним» (без лідера, вказаного PlayerId -1).
  • Нейтральні міста будуть "виробляти" лицарів, але не атакуватимуть і не підтримуватимуть жодне інше місто.

Синтаксис

Контролер надає вам введення через аргументи команд, ваша програма повинна виводити через stdout.

Вихідні дані (підготовка)
Перед початком гри контролер викликає ваше подання без аргументів. Це означає, що ви повинні розподілити своїх 100 людей (для кожного міста) на лицарів і малонароджених. Вам потрібно вивести KnightCount KnightCount KnightCount, наприклад 95 80 95.

Вхідні дані
Round;YourPlayerId;YourTownId;PlayerId_TownId_knights_lowborns;PlayerId_TownId_knights_lowborns;...
На першому раунді це буде щось подібне 1;2;2;0_0_100_0;1_1_50_50;2_2_80_20. Ось, ви бачите, що це перший тур, ви гравець 2 у місті 2. У вас є 80 лицарів і 20 малолітніх.

Пізніше в грі це могло бути щось на кшталт 20;2;1;0_0_100_0;2_1_30_50;2_2_40_20. Ви все ще гравець 2 (це ніколи не змінюється), але ви захопили місто 1 (яким ви зараз керуєте).

Вихід
A TownId NumberOfKnights або S TownId NumberOfKnightsабо W(для очікування).
Приклад: A 2 100(атакувати місто 2 зі 100 лицарів) або S 3 2(місто підтримки 3 з 2 лицарями).

Правила

  • Ботів не слід писати, щоб бити або підтримувати конкретних інших ботів.
  • Запис у файли дозволяється. Будь ласка, напишіть на " tvojeubmissionname .txt", папка буде видалена перед початком гри. Інші зовнішні ресурси заборонені.
  • На ваш запит є 1 секунда для відповіді (за місто).
  • Укажіть команди для складання та запуску подань.

Перемога

Переможець - той, у кого найбільше міст після 100 турів. Якщо гравець захоплює всі міста, гра зупиняється і він виграє. Якщо кілька гравців мають однакову кількість міст, то кількість рицарів буде підрахована, то кількість малих дітей.

Контролер

Ви можете знайти контролер на github. Він також містить 2 вибірки, написані на Java. Відкрийте його в Eclipse, помістіть складені боти в кореневу папку і додайте клас до керуючої програми (як і зразок).

Результати

Для остаточних результатів я провів 10 ігор. Це середнє значення:

    Міста гравців 
 1. Визволювач 37.5
 2. Сехтіміанер 8.2
 3. Суперпродуктор 5.4
 4. Спальний 1.4
 5. Франкенштейн 1.2
 6. Вершкове масло 0,8 (більше лицарів)
 7. TheKing 0.8 (менше лицарів)
 8. Вихід 0,6
 9. Черепаха 0,5 (більше лицарів)
10. AttackOn3 0,5 (менше рицарів)
11. Демократія 0,3
12. Розрахованофайл 0,2
13. Революціоніст 0,1

Ви можете прочитати зразкову гру тут: зразок гри на github


Я припускаю , що коли місто Aпідтримує інше місто B, дане число лицарів просто передається від Aдо B, після чого вони знаходяться під контролем власника B, правильно?
Згарб

@Zgarb Correct :)
CommonGuy

Чи будете проводити матчі та показувати таблицю лідерів?
Логічний лицар

@CarpetPython Звичайно, я публікую його, як тільки
встигну

1
@ Ману, я повинен сказати, що я люблю ваші КОТИ. Це мій тип Codegolf.SE питань. Доки ви приймаєте матеріали? Я зараз почну продуму алгоритм. Також, я думаю, вам слід додати ще одне правило - максимальна кількість подань на користувача.
Марк Габріель

Відповіді:


14

Python3, Визволитель

from sys import argv
from math import ceil, floor

class OppressedTown:
    def __init__(self, owner_id, id, oppressors, oppressed):
        self.owner_id = owner_id
        self.id = id
        self.oppressors = oppressors
        self.oppressed = oppressed

    def get_free_oppressors(self):
        return self.oppressors - ceil(self.oppressed / 2)

    def get_needed_liberators(self):
        return ceil(self.oppressed / 2)

class LiberatedTown:
    def __init__(self, owner_id, id, liberators, liberated):
        self.owner_id = owner_id
        self.id = id
        self.liberators = liberators
        self.liberated = liberated

    def get_free_liberators(self):
        return self.liberators - ceil(self.liberated / 2)

    def get_needed_liberators(self):
        return ceil(self.liberated / 2)

    def is_safe(self):
        return self.liberators >= self.liberated * 2

    def get_unneeded_liberators(self):
        return self.liberators - self.liberated * 2

def safe_div(a, b):
    try:
        c = a / b
    except ZeroDivisionError:
        if a == 0:
            c = 0
        else:
            c = float("inf")
    return c

def main():
    if len(argv) == 1:
        print ("100 100 100")
    else:
        decision = decide()
        print (decision)

def decide():
    def needs_urgent_support(town):
        return town.get_needed_liberators() >= town.liberators and town.liberated > 0

    def can_beat(free_liberators, town):
        return free_liberators > town.oppressors * 1.2 + town.get_needed_liberators()

    def can_damage(free_liberators, town):
        return free_liberators > town.oppressors * 0.2

    args = argv[1].split(";")
    round = int(args[0])
    me = int(args[1])
    current_id = int(args[2])
    liberated_towns = []
    oppressed_towns = []

    for i in range(3, len(args)):
        infos = list(map(int, args[i].split("_")))
        if infos[0] != me:
            oppressed_towns.append(OppressedTown(infos[0], infos[1], infos[2], infos[3]))
        else:
            liberated_towns.append(LiberatedTown(infos[0], infos[1], infos[2], infos[3]))

    current_town = [town for town in liberated_towns if town.id == current_id][0]
    free_liberators = current_town.get_free_liberators()

    total_oppressors = sum(town.liberators for town in liberated_towns)
    total_oppressors = sum(town.oppressors for town in oppressed_towns)
    total_liberated = sum(town.liberated for town in liberated_towns)
    total_oppressed = sum(town.oppressed for town in oppressed_towns)

    oppressed_towns.sort(key=lambda town: safe_div(town.oppressed, town.oppressors), reverse=True)

    most_oppressed = oppressed_towns[-1]

    if free_liberators > 0:
        for town in liberated_towns:
            if town.id != current_id and needs_urgent_support(town):
                return "S {0} {1}".format(town.id, free_liberators // 2)

        if current_town.is_safe():
            free_liberators = current_town.get_unneeded_liberators()

            if free_liberators > 0:
                for town in oppressed_towns:
                    if can_beat(free_liberators, town):
                        if total_liberated <= total_oppressed or town.owner_id != -1 or not any(town.owner_id != -1 for town in oppressed_towns):
                            return "A {0} {1}".format(town.id, free_liberators)
                        else:
                            continue
                    else:
                        break

                for town in liberated_towns:
                    if not town.is_safe():
                        return "S {0} {1}".format(town.id, free_liberators)

                liberated_towns.sort(key=lambda town: (town.liberated, town.liberators), reverse=True)

##                if current_id == liberated_towns[0].id and total_oppressors > total_oppressors and can_damage(free_liberators, most_oppressed):
##                    return "A {0} {1}".format(most_oppressed.id, free_liberators)

                if current_id != liberated_towns[0].id:
                    return "S {0} {1}".format(liberated_towns[0].id, free_liberators)

    return "W"

main()

Єдина мета цього бота - звільнити найпоширеніших людей від гнітючого ярма тиранії.


1
Я повинен сказати, що цей Визволювач - це чума: сильна, швидка та смертельна. Він вигравав майже кожен симулятор, який я запускав, навіть побив нейтрального гравця ... Все ж Масло є сильним претендентом.
Thrax

Ви звільнили хліб від свавілля Масла. :( Мені подобається масло.
TheNumberOne

Данг! Визволителю важко перемогти! У мене був запис, який я збирався подати ще до того, як додати учасників, які не входять в Java, до контролера ... але тепер ця запис не зможе перемогти, як і решта не-визволителів! У мене є ще одна ідея спробувати, щоб все не було втрачено ...: P + 1 для виклику!
Moogie

молодець! твоя була заслуженою перемогою!
Moogie

11

Пітон 2, Король

Король керує найвищим містечком своєї імперії і вимагає, щоб усі зайві лицарі були відправлені до нього з інших підконтрольних йому міст. Коли у нього буде достатньо лицарів, він нападе на вороже місто. Він не дуже розумний Король, тому не вивчав історії або не розуміє наслідків своїх дій.

import sys
from random import *

PLAYER, TOWN, KNIGHTS, SERFS = range(4)

if len(sys.argv) < 2:
    print randint(20,100), randint(50,100), randint(70,100)
else:
    parts = sys.argv[1].split(';')
    turn, me, thistown = [int(parts.pop(0)) for i in range(3)]
    towns = [[int(v) for v in town.split('_')] for town in parts]
    enemy = [t for t in towns if t[PLAYER] != me]
    mytowns = [t for t in towns if t[PLAYER] == me]
    here = [t for t in mytowns if t[TOWN] == thistown][0]

    avgfree = sum(t[KNIGHTS]-t[SERFS]/2 for t in towns) / len(towns)
    free = here[KNIGHTS] - here[SERFS]/2
    last = mytowns[-1]
    if here == last:
        needed, target = min([(t[KNIGHTS]*1.2+t[SERFS]/2, t) for t in enemy])
        if free > needed+5:
            print 'A', target[TOWN], int(free+needed)/2 + 1
        else:
            print 'W'
    else:
        spare = max(0, free - avgfree)
        if spare:
            print 'S', last[TOWN], spare
        else:
            print 'W'

Це не перевірено з контролером або іншими ботами.


+1 заHe is not a very smart King, so has not studied history or understands the consequences of his actions.
Марк Габріель

8

Javascript (Вузол), Empire

Починає сильно, щоб відлякати інші міста. Міста намагаються працювати разом, щоб захопити інших. Визначає пріоритетність захоплення міст з великою кількістю дітей.

/*jshint node:true*/
'use strict';

function startGame() {
  console.log('80 70 60');
}

function parseArgs(args) {
  var state = {
    players: [],
    towns: []
  };
  var argArray = args.split(';');
  state.currentTurn = parseInt(argArray.splice(0, 1)[0], 10);
  var myId = argArray.splice(0, 1)[0];
  var myTownId = parseInt(argArray.splice(0, 1)[0], 10);

  for(var townIndex = 0; townIndex < argArray.length; townIndex++) {
    var townArgs = argArray[townIndex].split('_');
    var playerId = townArgs[0];
    var townId = parseInt(townArgs[1], 10);
    var player = state.players[playerId];

    if(!player) {
      player = {
        towns: []
      };
      state.players[playerId] = player;
    }

    var town = {
      id: townId,
      knights: parseInt(townArgs[2], 10),
      lowborns: parseInt(townArgs[3], 10),
      player: player
    };

    state.towns[townId] = town;
    player.towns.push(town);
  }

  state.me = state.players[myId];
  state.currentTown = state.towns[myTownId];

  return state;
}

function getDefense(town) {
  return Math.floor(town.knights * 1.2) + Math.ceil(town.lowborns / 2) + 1;
}

function getAttackers(town) {
  return Math.max(town.knights - Math.ceil(town.lowborns / 2), 0);
}

function attackTown(town, strength) {
  console.log('A ' + town.id + ' ' + strength);
}

function supportTown(town, strength) {
  console.log('S ' + town.id + ' ' + strength);
}

function wait() {
  console.log('W');
}

function processTurn(gameState) {
  var attackers = getAttackers(gameState.currentTown);

  if(attackers > 0) {
    var totalAttackers = attackers;

    var helperIndex = (gameState.currentTown.id + 1) % gameState.towns.length;
    while(gameState.towns[helperIndex].player === gameState.me) {
      totalAttackers += getAttackers(gameState.towns[helperIndex]);
      helperIndex = (helperIndex + 1) % gameState.towns.length;
    }

    var bestTarget;

    for(var targetIndex = 0; targetIndex < gameState.towns.length; targetIndex++) {
      var targetTown = gameState.towns[targetIndex];
      if(targetTown.player !== gameState.me) {
        var defense = getDefense(targetTown);

        if(defense < totalAttackers) {
          if(!bestTarget) {
            bestTarget = targetTown;
          }
          else if(targetTown.lowborns > bestTarget.lowborns) {
            bestTarget = targetTown;
          }
          else if(getDefense(bestTarget) < defense) {
            bestTarget = targetTown;
          }
        }
      }
    }

    if(bestTarget) {
      return attackTown(bestTarget, Math.min(attackers, getDefense(bestTarget)));
    }

    var smallestTown;
    var smallestSize = gameState.currentTown.knights;

    for(var myTownIndex = 0; myTownIndex < gameState.me.towns.length; myTownIndex++) {
      var myTown = gameState.me.towns[myTownIndex];
      if(myTown.knights < smallestSize) {
        smallestTown = myTown;
        smallestSize = smallestTown.knights;
      }
    }

    if(smallestTown) {
      var supporters = Math.floor((smallestSize - gameState.currentTown.knights) / 2);
      supporters = Math.min(supporters, attackers);
      if(supporters > 0) {
        return supportTown(smallestTown, supporters);
      }
    }
  }

  wait();
}

if(process.argv.length <= 2) {
  startGame();
}
else {
  var gameState = parseArgs(process.argv[2]);  
  processTurn(gameState);
}

Запуск: імперія вузла


1
Ваше подання іноді посилає більше рицарів, ніж насправді в місті, і тому втрачає на даний момент ...
CommonGuy

@ Ману, на жаль, я якось ніколи не стикався (або принаймні помічав), що в своїх тестах, можливо, тому, що я не мав можливості створити всіх ботів противника для тестування. Саме цю помилку слід виправити зараз.
Спенсер

Це все ще не виправлено ... іноді ви нападаєте з 0 або з негативною кількістю лицарів ... Це тому, що ви підраховуєте knights - lowborns/2, але якщо у вас є 30 лицарів і 90 малонароджених, це не працює. Виправте свою getAttackers()функцію.
CommonGuy

Також іноді ви надсилаєте опори з негативною кількістю лицарів.
CommonGuy

@ Ману добре, я відчуваю себе дурним, я нарешті помітив DEBUGпрапор у контролері, який змусив його проковтнути помилки, навіть якщо GAME_MESSAGESпрапор встановлено на істинне. Я відчуваю, що я все-таки міг би скористатися деякою роботою над моєю стратегією, особливо з Liberator, який зараз на сцені, але при останньому редагуванні я не бачу помилок, коли запускаю тести DEBUGна
Спенсер

8

Ява, Франкенштейн

Прагнучи знайти спосіб знищити Визволителя, у мій код проскочила невеличка помилка. Код тоді почав знищувати конкуренцію. Після додавання Демократії та перестановки гравців вона почала провалюватися. Вивчаючи код, я намагався знайти його стратегію. Отже, був зроблений наступний код. Він схильний атакувати та знищувати найкращого гравця. Після знищення найкращих гравців це легко знищує решту.

import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Frankenstein {

    int round;
    int playerID;
    int thisTownID;

    List<Town> towns;
    List<Town> myTowns;
    List<Town> otherTowns;

    private static final boolean DEBUG = true;

    Town thisTown;

    int scariestPlayerId = -1;
    int scariestPlayerRecord = -1;

    private static final String LOG_FILE_NAME = "EmperorLog.txt";

    private static final String DATA_FILE_NAME = "Emperor.txt";

    public static void main(String[] args){
        try {
            if (args.length == 0) {
                System.out.println("100 100 100");
                return;
            }
            Frankenstein frankenstein = new Frankenstein();
            String result = frankenstein.destroy(args[0].split(";"));
            frankenstein.saveScariestPlayer();
            System.out.println(result);
            if (DEBUG) {
                new PrintStream(new FileOutputStream(LOG_FILE_NAME, true)).print(args[0] + "\n" + result + "\n");
            }
        } catch (Exception e){
            if (DEBUG) {
                try {
                    e.printStackTrace(new PrintStream(new FileOutputStream(LOG_FILE_NAME, true)));
                } catch (FileNotFoundException e1) {
                    e1.printStackTrace();
                }
            }
        }
    }

    private void saveScariestPlayer() throws FileNotFoundException {
        PrintStream out = new PrintStream(DATA_FILE_NAME);
        out.println(round);
        out.println(scariestPlayerId);
        out.println(scariestPlayerRecord);
    }

    private static int divide(int a, int b){
        if (a == 0){
            return 0;
        }
        if (b == 0){
            return 1000;
        }
        return a/b;
    }

    private String destroy(String[] args) {

        round = Integer.parseInt(args[0]);
        playerID = Integer.parseInt(args[1]);
        thisTownID = Integer.parseInt(args[2]);
        towns = new ArrayList<>();
        myTowns = new ArrayList<>();
        otherTowns = new ArrayList<>();


        for (int i = 3; i < args.length; i++) {
            towns.add(new Town(args[i]));
        }

        for (Town town : towns) {
            if (town.isMine()) {
                myTowns.add(town);
                if (town.isThisTown()) {
                    thisTown = town;
                }
            } else {
                otherTowns.add(town);
            }
        }

        loadScariestPlayer();
        updateScariestPlayer();

        if (thisTown.getFreeKnights() > 0){

            for (Town town : myTowns){
                if (town.needsHelp() && town.getFreeKnights() + thisTown.getFreeKnights() >= 0){
                    return "S " + town.getId() + " " + thisTown.getFreeKnights();
                }
            }

            Town bestTown = otherTowns.stream().max((a, b) -> divide(a.lowbornCount() * (scariestPlayerId == -1 || scariestPlayerId == a.ownerId ? a.lowbornCount() : 1), a.knightCount()) -
                    divide(b.lowbornCount() * (scariestPlayerId == -1 || scariestPlayerId == b.ownerId ? b.lowbornCount() : 1), b.knightCount())).get();

            if (bestTown.numberOfKnightsToConquer() <= thisTown.getFreeKnights()){
                return "A " + bestTown.getId() + " " + thisTown.getFreeKnights();
            }

            myTowns.sort((a,b) -> b.knightCount() - a.knightCount());
            myTowns.sort((a,b) -> b.lowbornCount() - a.lowbornCount());
            if (!myTowns.get(0).isThisTown()){
                return "S " + myTowns.get(0).getId() + " " + thisTown.getFreeKnights();
            }

        }

        return "W";

    }

    private void updateScariestPlayer() {
        Map<Integer, Integer> playerMap = new HashMap<>();
        int biggestPlayerId = -1;
        for (Town town : otherTowns){
            if (playerMap.containsKey(town.ownerId)){
                playerMap.put(town.ownerId, town.lowbornCount() + playerMap.get(town.ownerId));
            } else {
                playerMap.put(town.ownerId, town.lowbornCount());
            }
            if (biggestPlayerId == -1 || playerMap.get(town.ownerId) > playerMap.get(biggestPlayerId)){
                biggestPlayerId = town.ownerId;
            }
        }
        if (scariestPlayerId == -1 || scariestPlayerRecord == -1 || !playerMap.containsKey(scariestPlayerId) || playerMap.get(biggestPlayerId) > scariestPlayerRecord){
            scariestPlayerId = biggestPlayerId;
            scariestPlayerRecord = playerMap.get(biggestPlayerId);
        }
    }

    private void loadScariestPlayer() {
        try {
            BufferedReader in = new BufferedReader(new FileReader(DATA_FILE_NAME));
            int turn = Integer.parseInt(in.readLine());
            if (turn != round || turn != round + 1){
                throw new Exception();
            }
            scariestPlayerId = Integer.parseInt(in.readLine());
            scariestPlayerRecord = Integer.parseInt(in.readLine());
        } catch (Exception e) {
            scariestPlayerId = -1;
            scariestPlayerRecord = -1;
        }
    }


    private class Town {
        final int ownerId;
        final int id;
        final int knights;
        final int lowborns;
        boolean defenseBonus;

        Town(String string) {
            String[] args = string.split("_");
            ownerId = Integer.parseInt(args[0]);
            id = Integer.parseInt(args[1]);
            knights = Integer.parseInt(args[2]);
            lowborns = Integer.parseInt(args[3]);
            defenseBonus = true;
        }

        int getId() {
            return id;
        }

        int knightCount() {
            return knights;
        }

        int lowbornCount() {
            return lowborns;
        }

        boolean isMine() {
            return ownerId == playerID;
        }

        boolean isThisTown() {
            return id == thisTownID;
        }

        int getFreeKnights() {
            return knights - lowborns / 2 - 1;
        }

        int numberOfKnightsToConquer() {
            if (defenseBonus) {
                return ((knights * 6) / 5) + (lowborns / 2) + 1;
            } else {
                return knights + lowborns/2 + 1;
            }
        }

        int numberOfKnightsToOverthrow(){
            if (defenseBonus) {
                return (((knights * 6) / 5) - (lowborns / 2)) + 1;
            } else {
                return knights - lowborns / 2 + 1;
            }
        }

        boolean needsHelp() {
            return getFreeKnights() < 0;
        }

        public boolean isNeutural() {
            return ownerId == -1;
        }
    }
}

Ось оригінальний програвач:

import java.util.ArrayList;
import java.util.List;

public class Frankenstein {

    int round;
    int playerID;
    int thisTownID;

    List<Town> towns;
    List<Town> myTowns;
    List<Town> otherTowns;

    Town thisTown;

    Player me;

    public static void main(String[] args) {
        if (args.length == 0) {
            System.out.println("100 100 100");
            return;
        }
        new Frankenstein().destroy(args[0].split(";"));
    }

    private static int divide(int a, int b){
        if (a == 0){
            return 0;
        }
        if (b == 0){
            return 1000000;
        }
        return a/b;
    }

    private void destroy(String[] args) {
        round = Integer.parseInt(args[0]);
        playerID = Integer.parseInt(args[1]);
        thisTownID = Integer.parseInt(args[2]);
        towns = new ArrayList<>();
        myTowns = new ArrayList<>();
        otherTowns = new ArrayList<>();


        for (int i = 3; i < args.length; i++) {
            towns.add(new Town(args[i]));
        }

        for (Town town : towns) {
            if (town.isMine()) {
                myTowns.add(town);
                if (town.isThisTown()) {
                    thisTown = town;
                }
            } else {
                otherTowns.add(town);
            }
        }

        players.stream().filter(player -> player.id == playerID).forEach(player -> me = player);

        if (thisTown.getFreeKnights() > 0){

            for (Town town : myTowns){
                if (town.needsHelp()){
                    System.out.println("S " + town.getId() + " " + thisTown.getFreeKnights() / 2);
                    return;
                }
            }

            Town richestTown = otherTowns.stream().max((a, b) -> divide(a.lowbornCount(), a.knightCount()) -
                    divide(b.lowbornCount(), b.knightCount())).get();

            if (richestTown.numberOfKnightsToConquer() < thisTown.getFreeKnights()){
                System.out.println("A " + richestTown.getId() + " " + thisTown.getFreeKnights());
                return;
            }

            otherTowns.sort((a,b) -> divide(b.lowbornCount() * b.owner.richness(), b.getFreeKnights()) -
                    divide(a.lowbornCount() * a.owner.richness(), a.getFreeKnights()));

            if (thisTown.getFreeKnights() >= otherTowns.get(0).numberOfKnightsToOverthrow() && !otherTowns.get(0).isNeutral()){
                System.out.println("A " + otherTowns.get(0).getId() + " " + otherTowns.get(0).numberOfKnightsToOverthrow());
                return;
            }

            myTowns.sort((a,b) -> b.knightCount() - a.knightCount());
            myTowns.sort((a,b) -> b.lowbornCount() - a.lowbornCount());
            if (!myTowns.get(0).isThisTown()){
                System.out.println("S " + myTowns.get(0).getId() + " " + thisTown.getFreeKnights());
                return;
            }

        }

        System.out.println("W");

    }


    private class Town {
        private final int ownerId;
        private final int id;
        private final int knights;
        private final int lowborns;
        private final Player owner;

        private Town(String string) {
            String[] args = string.split("_");
            ownerId = Integer.parseInt(args[0]);
            id = Integer.parseInt(args[1]);
            knights = Integer.parseInt(args[2]);
            lowborns = Integer.parseInt(args[3]);
            for (Player player : players){
                if (player.id == ownerId){
                    player.addTown(this);
                    owner = player;
                    return;
                }
            }
            owner = new Player(id);//This mistake makes my player perform really good for some reason.
            owner.towns.add(this);
        }

        private int getId() {
            return id;
        }

        private int knightCount() {
            return knights;
        }

        private int lowbornCount() {
            return lowborns;
        }

        private boolean isMine() {
            return ownerId == playerID;
        }

        private boolean isThisTown() {
            return id == thisTownID;
        }

        private int getFreeKnights() {
            return knights - lowborns / 2 - 1;
        }

        private int numberOfKnightsToConquer() {
            return ((knights * 6) / 5) + (lowborns / 2) + 1;
        }

        private int numberOfKnightsToOverthrow(){
            return (((knights * 6) / 5) - (lowborns / 2)) + 1;
        }

        private boolean needsHelp() {
            return getFreeKnights() < 0;
        }

        private boolean isNeutral() {
            return owner.id == -1;
        }

    }

    List<Player> players = new ArrayList<>();

    private class Player{

        int id;

        List<Town> towns;

        int richness = 0;

        Player(int id){
            this.id = id;
            this.towns = new ArrayList<>();
            players.add(this);
        }

        void addTown(Town t){
            towns.add(t);
            richness += t.lowbornCount();
        }

        int richness(){
            return id == -1 ? (towns.size() > 0 ? 1 : 0) : richness;
        }

    }
}

Я провів 20 ігор, мені сумно сказати, що Франкенштейн вигравав лише 2 рази, тоді як Лібератор виграв 17 разів (так, Революціоністу вдалося один раз виграти нейтрального гравця, отримавши 2 місце).
Фракс

@Thrax Виправлено !!!!!
TheNumberOne

7

Ява, Черепаха

Завдяки TheBestOne для основних методів я просто змінив алгоритм (сподіваюся, що це нормально). Цей бот в основному модернізує своє найкраще захищене місто, щоб конкурувати з найнебезпечнішим ворожим містом, зберігаючи при цьому достатньо рицарів, щоб запобігти повстанню в інших містах.

import java.util.ArrayList;
import java.util.List;


public class Turtle {


    int round;
    int playerID;
    int thisTownID;

    List<Town> towns;
    List<Town> myTowns;
    List<Town> otherTowns;

    Town thisTown;

    public static void main(String[] args){
        if (args.length == 0){
            System.out.println("34 34 34");
            return;
        }
        new Turtle().defend(args[0].split(";"));
    }

    private void defend(String[] args) {
        round = Integer.parseInt(args[0]);
        playerID = Integer.parseInt(args[1]);
        thisTownID = Integer.parseInt(args[2]);
        towns = new ArrayList<>();
        myTowns = new ArrayList<>();
        otherTowns = new ArrayList<>();

        for (int i = 3; i < args.length; i++){
            towns.add(new Town(args[i]));
        }

        for (Town town : towns){
            if (town.isMine()){
                myTowns.add(town);
                if (town.isThisTown()){
                    thisTown = town;
                }
            } else {
                otherTowns.add(town);
            }
        }

        Town bestDefendedTown = null;
        for (Town town : myTowns) {
            if (bestDefendedTown == null)
                bestDefendedTown = town;

            bestDefendedTown = bestDefendedTown.knightCount() >= town.knightCount() ? bestDefendedTown : town;
        }

        Town dangerousEnemyTown = null;
        for (Town town : otherTowns) {
            if (dangerousEnemyTown == null)
                dangerousEnemyTown = town;

            dangerousEnemyTown = dangerousEnemyTown.knightCount() >= town.knightCount() ? dangerousEnemyTown : town;
        }

        int missingKnights = dangerousEnemyTown.knightCount() - bestDefendedTown.knightCount() > 0 ? dangerousEnemyTown.knightCount() - bestDefendedTown.knightCount() : 0;
        int reinforcements = thisTown.getFreeKnights() - (missingKnights + 1) > 0 ? thisTown.getFreeKnights() - (missingKnights + 1) : thisTown.getFreeKnights(); 


        if (reinforcements > 0) {
            System.out.println("S " + bestDefendedTown.getId() + " " + reinforcements);
        } else {
            System.out.println("W");
        }
    }



    private class Town {
        private final int ownerId;
        private final int id;
        private final int knights;
        private final int lowborns;

        public Town(String string){
            String[] args = string.split("_");
            ownerId = Integer.parseInt(args[0]);
            id = Integer.parseInt(args[1]);
            knights = Integer.parseInt(args[2]);
            lowborns = Integer.parseInt(args[3]);
        }

        public int getId() {
            return id;
        }

        public int getOwner() {
            return ownerId;
        }

        public int knightCount() {
            return knights;
        }

        public int lowbornCount() {
            return lowborns;
        }

        public boolean isMine(){
            return ownerId == playerID;
        }

        public boolean isThisTown(){
            return id == thisTownID;
        }

        private int getFreeKnights() {
            return knights - lowborns / 2 - 1;
        }
    }
}

Збірка: javac Turtle.java

Виконати: java Turtle


Я думаю, ти це dangerousEnemyTown = dangerousEnemyTown.knightCount() >= town.knightCount() ? dangerousEnemyTown : town;не мав на увазіdangerousEnemyTown = bestDefendedTown.knightCount() >= town.knightCount() ? bestDefendedTown : town;
TheNumberOne

@TheBestOne Дякую, що вказали на це! Оновлення моєї публікації.
Thrax

Я також виправив NPE, змусивши мою Черепаху чекати кожного повороту. Насправді ця маленька Черепаха до цього часу була Сном ...
Thrax

7

Ява 8, політик

Діє як справжній політик. Шкода, що Крашер все ще його вбиває.

import java.util.ArrayList;
import java.util.List;

public class Politician {

    int round;
    int playerID;
    int thisTownID;

    List<Town> towns;
    List<Town> myTowns;
    List<Town> otherTowns;

    Town thisTown;

    public static void main(String[] args){
        if (args.length == 0){
            System.out.println("34 34 34");
            return;
        }
        new Politician().bribe(args[0].split(";"));
    }

    private void bribe(String[] args) {
        round = Integer.parseInt(args[0]);
        playerID = Integer.parseInt(args[1]);
        thisTownID = Integer.parseInt(args[2]);
        towns = new ArrayList<>();
        myTowns = new ArrayList<>();
        otherTowns = new ArrayList<>();


        for (int i = 3; i < args.length; i++){
            towns.add(new Town(args[i]));
        }

        for (Town town : towns){
            if (town.isMine()){
                myTowns.add(town);
                if (town.isThisTown()){
                    thisTown = town;
                }
            } else {
                otherTowns.add(town);
            }
        }

        Town biggestTown = otherTowns.stream().max((a,b) -> a.knights - b.knights).get();

        if (thisTown.getFreeKnights() <= 0){//Out of knights.
            System.out.println("W");//Waiting for taxes so can hire more knights.
        }

        System.out.println("S " + biggestTown.getId() + " " + thisTown.getFreeKnights());
    }


    private class Town {
        private final int ownerId;
        private final int id;
        private final int knights;
        private final int lowborns;

        public Town(String string){
            String[] args = string.split("_");
            ownerId = Integer.parseInt(args[0]);
            id = Integer.parseInt(args[1]);
            knights = Integer.parseInt(args[2]);
            lowborns = Integer.parseInt(args[3]);
        }

        public int getId() {
            return id;
        }

        public int getOwner() {
            return ownerId;
        }

        public int knightCount() {
            return knights;
        }

        public int lowbornCount() {
            return lowborns;
        }

        public boolean isMine(){
            return ownerId == playerID;
        }

        public boolean isThisTown(){
            return id == thisTownID;
        }

        private int getFreeKnights() {
            return knights - lowborns / 2 - 1;
        }

    }
}

Збірка: javac Politician.java

Виконати: java Politician


1
+1 за хабар, але я думаю, ви пропустили занадто поширений lieметод
глобі

6

Java 8, Масло

Розтікається максимально рівномірно. Смучує місто, якщо місто достатньо невелике.

import java.util.ArrayList;
import java.util.List;

public class Butter {

    int round;
    int playerID;
    int thisTownID;

    List<Town> towns;
    List<Town> myTowns;
    List<Town> otherTowns;

    Town thisTown;

    public static void main(String[] args){
        if (args.length == 0){
            System.out.println("34 34 34");
            return;
        }
        new Butter().spread(args[0].split(";"));
    }

    private void spread(String[] args) {
        round = Integer.parseInt(args[0]);
        playerID = Integer.parseInt(args[1]);
        thisTownID = Integer.parseInt(args[2]);
        towns = new ArrayList<>();
        myTowns = new ArrayList<>();
        otherTowns = new ArrayList<>();


        for (int i = 3; i < args.length; i++){
            towns.add(new Town(args[i]));
        }

        for (Town town : towns){
            if (town.isMine()){
                myTowns.add(town);
                if (town.isThisTown()){
                    thisTown = town;
                }
            } else {
                otherTowns.add(town);
            }
        }

        Town mySmallestTown = myTowns.stream().min((a, b) -> a.getFreeKnights() - b.getFreeKnights()).get();

        Town smallestEnemyTown = otherTowns.stream().min((a,b) -> a.knights - b.knights).get();

        if ((thisTown.getFreeKnights() - mySmallestTown.getFreeKnights())/2 > 0) {
            System.out.println("S " + mySmallestTown.getId() + " " + (thisTown.getFreeKnights() - mySmallestTown.getFreeKnights()) / 2);
        } else if (thisTown.getFreeKnights() / 2 > smallestEnemyTown.numberOfKnightsToConquer()){
            System.out.println("A " + smallestEnemyTown.getId() + " " + smallestEnemyTown.numberOfKnightsToConquer());
        } else {
            System.out.println("W");
        }
    }


    private class Town {
        private final int ownerId;
        private final int id;
        private final int knights;
        private final int lowborns;

        private Town(String string){
            String[] args = string.split("_");
            ownerId = Integer.parseInt(args[0]);
            id = Integer.parseInt(args[1]);
            knights = Integer.parseInt(args[2]);
            lowborns = Integer.parseInt(args[3]);
        }

        private int getId() {
            return id;
        }

        private int getOwner() {
            return ownerId;
        }

        private int knightCount() {
            return knights;
        }

        private int lowbornCount() {
            return lowborns;
        }

        private boolean isMine(){
            return ownerId == playerID;
        }

        private boolean isThisTown(){
            return id == thisTownID;
        }

        private int getFreeKnights() {
            return knights - lowborns / 2 - 1;
        }

        private int numberOfKnightsToConquer(){
            return ((knights * 6) / 5) + (lowborns / 2) + 1;
        }

    }
}

Збірка: javac Butter.java

Виконати: java Butter


6

Ява, революціонер

Останній, все ще заснований на основних методах TheBestOne. Цей бот намагається підбурювати заколоти у кожному місті, оскільки нейтральний гравець не ображає, вбиваючи певну кількість лицарів відносно малонародженого населення. Звичайно, це не буде атакувати нейтрального гравця.

import java.util.ArrayList;
import java.util.List;


public class Revolutionist {


    int round;
    int playerID;
    int thisTownID;

    List<Town> towns;
    List<Town> myTowns;
    List<Town> otherTowns;

    Town thisTown;

    public static void main(String[] args){
        if (args.length == 0){
            System.out.println("80 80 80");
            return;
        }
        new Revolutionist().inciteRebellion(args[0].split(";"));
    }

    private void inciteRebellion(String[] args) {
        round = Integer.parseInt(args[0]);
        playerID = Integer.parseInt(args[1]);
        thisTownID = Integer.parseInt(args[2]);
        towns = new ArrayList<>();
        myTowns = new ArrayList<>();
        otherTowns = new ArrayList<>();

        for (int i = 3; i < args.length; i++){
            towns.add(new Town(args[i]));
        }

        for (Town town : towns){
            if (town.isMine()){
                myTowns.add(town);
                if (town.isThisTown()){
                    thisTown = town;
                }
            } else {
                otherTowns.add(town);
            }
        }

        Town onEdgeTown = null;
        int edgeCounter = 100;
        for (Town town : otherTowns) {
            if (onEdgeTown == null)
                onEdgeTown = town;

            if (town.getFreeKnights() >= 0 && town.getFreeKnights() <= edgeCounter && town.getOwner() >= 0) {
                onEdgeTown = town;
                edgeCounter = town.getFreeKnights();
            }
        }

        int minimumRequiredKnights = (int) ((onEdgeTown.knightCount() * 1.2 - onEdgeTown.getMinimumKnights() + 2) * 1.2) ;


        if (thisTown.getFreeKnights() > minimumRequiredKnights && onEdgeTown.getOwner() >= 0)
            System.out.println("A " + onEdgeTown.getId() + " " + minimumRequiredKnights);
        else
            System.out.println("W");

    }



    private class Town {
        private final int ownerId;
        private final int id;
        private final int knights;
        private final int lowborns;

        public Town(String string){
            String[] args = string.split("_");
            ownerId = Integer.parseInt(args[0]);
            id = Integer.parseInt(args[1]);
            knights = Integer.parseInt(args[2]);
            lowborns = Integer.parseInt(args[3]);
        }

        public int getId() {
            return id;
        }

        public int getOwner() {
            return ownerId;
        }

        public int knightCount() {
            return knights;
        }

        public int lowbornCount() {
            return lowborns;
        }

        public boolean isMine(){
            return ownerId == playerID;
        }

        public boolean isThisTown(){
            return id == thisTownID;
        }

        private int getFreeKnights() {
            return knights - lowborns / 2 - 1;
        }

        private int getMinimumKnights() {
            return lowborns / 2 + 1;
        }
    }
}

Збірка: javac Revolutionist.java

Виконати: java Revolutionist


6

JAVA, Sehtimianer

Ще раз завдяки TheBestOne, я скопіював його основні методи; ) Це вперше я граю KingOfTheHill-CodeGame, тож сподіваюся, що я все зробив правильно. Я з гордістю представляю сехтиміанерів: D

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Sehtimianer {

private static final String FILENAME = "Sehtimianer.txt";
private static final int AGGRESSIVE_ROUND_BORDER = 80;

int round;
int playerID;
int thisTownID;

List<Town> towns = new ArrayList<Town>();
List<Town> myTowns = new ArrayList<Town>();
List<Town> playerTowns = new ArrayList<Town>();
List<Town> neutralTowns = new ArrayList<Town>();
Map<Integer, Integer> townToPlayerMapping = new HashMap<Integer, Integer>();
boolean isAllowedToWriteMapping = true;

Town thisTown;

public static void main(String[] args) {
    if (args.length == 0) {
        // new File(FILENAME).delete();
        System.out.println("100 100 100");
        return;
    }
    new Sehtimianer().decide(args[0].split(";"));
}

private void decide(String[] args) {
    // final long start = System.currentTimeMillis();

    round = Integer.parseInt(args[0]);
    playerID = Integer.parseInt(args[1]);
    thisTownID = Integer.parseInt(args[2]);

    for (int i = 3; i < args.length; i++) {
        towns.add(new Town(args[i]));
    }

    for (Town town : towns) {
        if (town.isMine()) {
            myTowns.add(town);
            if (town.isThisTown()) {
                thisTown = town;
            }
        } else {
            if (town.getOwner() == -1) {
                neutralTowns.add(town);
            } else {
                playerTowns.add(town);
            }
        }
    }

    if (new File(FILENAME).exists()) {
        try {
            BufferedReader reader = new BufferedReader(new FileReader(FILENAME));
            String inputLine;
            String[] ids;
            while ((inputLine = reader.readLine()) != null) {
                ids = inputLine.split(";");
                if (ids.length == 1) {
                    Integer writingTownID = Integer.valueOf(ids[0]);
                    boolean townIsLost = true;
                    for (Town town : myTowns) {
                        if (town.getId() == writingTownID) {
                            townIsLost = false;
                            break;
                        }
                    }
                    isAllowedToWriteMapping = townIsLost || thisTownID == writingTownID;
                    continue;
                }
                townToPlayerMapping.put(Integer.valueOf(ids[0]), Integer.valueOf(ids[1]));
            }
            reader.close();

            for (Town town : towns) {
                if (!townToPlayerMapping.get(town.getId()).equals(town.getOwner())) {
                    town.setDefenseBonus(false);
                }
            }
        } catch (IOException e) {
            // Dont worry : )
        }
    }

    if (round == 1) {
        int maxKnights = 0;
        int maxKnightTownID = thisTownID;
        for (Town town : myTowns) {
            if (town == thisTown) {
                continue;
            }
            if (town.knightCount() > maxKnights) {
                maxKnights = town.knightCount();
                maxKnightTownID = town.getId();
            }
        }
        if (maxKnightTownID != thisTownID) {
            System.out.println("S " + maxKnightTownID + " " + thisTown.knightCount());
        }
    } else if (round % 3 == 2) {
        int myKnightIncome = 0;
        for (Town town : myTowns) {
            myKnightIncome += town.lowbornCount() / 2;
        }

        Map<Integer, Integer> playerKnightIncomeMap = new HashMap<Integer, Integer>();
        Map<Integer, Integer> playerTownCountMap = new HashMap<Integer, Integer>();
        List<Integer> nextRoundKnights = new ArrayList<Integer>();
        Map<Integer, Town> nextRoundKnightsToTownMapping = new HashMap<Integer, Town>();

        for (Town town : playerTowns) {
            fillDescisionMaps(town, nextRoundKnights, nextRoundKnightsToTownMapping, playerKnightIncomeMap, playerTownCountMap);
        }
        for (Town town : neutralTowns) {
            fillDescisionMaps(town, nextRoundKnights, nextRoundKnightsToTownMapping, playerKnightIncomeMap, playerTownCountMap);
        }

        Integer maxEnemyKnightIncome = 0;
        for (Integer knightIncome : playerKnightIncomeMap.values()) {
            if (knightIncome > maxEnemyKnightIncome) {
                maxEnemyKnightIncome = knightIncome;
            }
        }
        Integer maxEnemyTownCount = 0;
        for (Integer townCount : playerTownCountMap.values()) {
            if (townCount > maxEnemyTownCount) {
                maxEnemyTownCount = townCount;
            }
        }

        if (maxEnemyKnightIncome > myKnightIncome || (round > AGGRESSIVE_ROUND_BORDER && maxEnemyTownCount >= myTowns.size())) {
            Collections.sort(nextRoundKnights);
            int possibleHighest = 0;
            Town enemyTown;
            int enemyTownUpkeep;
            for (int i = nextRoundKnights.size() - 1; i >= 0; i--) {
                possibleHighest = nextRoundKnights.get(i);
                enemyTown = nextRoundKnightsToTownMapping.get(possibleHighest);
                enemyTownUpkeep = enemyTown.lowbornCount() / 2;
                if (enemyTownUpkeep > (possibleHighest - enemyTownUpkeep)) { // Substract the calculated Income for the next Turn
                    // Town will be lost because of revolution after captured -> Bad target
                    possibleHighest = 0;
                    continue;
                }
                if (round > AGGRESSIVE_ROUND_BORDER || enemyTown.lowbornCount() > 0) {
                    break;
                }
            }
            if (possibleHighest > 0) {
                Town attackedTown = nextRoundKnightsToTownMapping.get(possibleHighest);
                System.out.println("A " + attackedTown.getId() + " " + calcHowMuchKnightsShouldAttack(attackedTown, possibleHighest));
            }
        }
    }

    if (isAllowedToWriteMapping) {
        try {
            BufferedWriter writer = new BufferedWriter(new FileWriter(FILENAME));
            writer.write(thisTownID + "\n");
            for (Town town : towns) {
                writer.write(town.getId() + ";" + town.getOwner() + "\n");
            }
            writer.close();
        } catch (IOException e) {
            // Dont worry : )
        }
    }

    System.out.println("W");

    // long duration = System.currentTimeMillis() - start;
    // if (duration > 1000) {
    // throw new RuntimeException();
    // }
}

private void fillDescisionMaps(Town town, List<Integer> nextRoundKnights, Map<Integer, Town> nextRoundKnightsToTownMapping, Map<Integer, Integer> playerKnightIncomeMap,
        Map<Integer, Integer> playerTownCountMap) {
    int calculatedKnights = calcKnightsInNextRound(town);
    nextRoundKnights.add(calculatedKnights);
    nextRoundKnightsToTownMapping.put(calculatedKnights, town);

    Integer enemyKnightIncome = playerKnightIncomeMap.get(town.getOwner());
    if (enemyKnightIncome == null) {
        enemyKnightIncome = town.lowbornCount() / 2;
    } else {
        enemyKnightIncome = enemyKnightIncome + (town.lowbornCount() / 2);
    }
    playerKnightIncomeMap.put(town.getOwner(), enemyKnightIncome);

    Integer enemyTownCount = playerTownCountMap.get(town.getOwner());
    if (enemyTownCount == null) {
        enemyTownCount = Integer.valueOf(1);
    } else {
        enemyTownCount = enemyTownCount + 1;
    }
    playerTownCountMap.put(town.getOwner(), enemyTownCount);
}

private int calcKnightsInNextRound(Town enemyTown) {
    int knights = (int) ((double) enemyTown.knightCount() * (enemyTown.isDefenseBonus() ? 1.2 : 1));
    knights = thisTown.getFreeKnights() - knights;
    if (knights > 0) {
        knights += enemyTown.lowbornCount() / 2;
    } else {
        knights = 0;
    }
    return knights;
}

private int calcHowMuchKnightsShouldAttack(Town enemyTown, int possibleHighest) {
    if (round < AGGRESSIVE_ROUND_BORDER && thisTown.lowbornCount() == 0) {
        return thisTown.knightCount();
    }

    int spareKnights = possibleHighest - enemyTown.lowbornCount(); // Correct -> div 2 and mul 2
    int minShouldSend = thisTown.getFreeKnights() - (spareKnights / 2);

    return Math.max(minShouldSend, thisTown.knightCount() / 2);
}

private class Town {
    private final int ownerId;
    private final int id;
    private final int knights;
    private final int lowborns;
    private boolean defenseBonus;

    public Town(String string) {
        String[] args = string.split("_");
        ownerId = Integer.parseInt(args[0]);
        id = Integer.parseInt(args[1]);
        knights = Integer.parseInt(args[2]);
        lowborns = Integer.parseInt(args[3]);
        defenseBonus = true;
    }

    public boolean isDefenseBonus() {
        return defenseBonus;
    }

    public void setDefenseBonus(boolean defenseBonus) {
        this.defenseBonus = defenseBonus;
    }

    public int getId() {
        return id;
    }

    public int getOwner() {
        return ownerId;
    }

    public int knightCount() {
        return knights;
    }

    public int lowbornCount() {
        return lowborns;
    }

    public boolean isMine() {
        return ownerId == playerID;
    }

    public boolean isThisTown() {
        return id == thisTownID;
    }

    private int getFreeKnights() {
        return knights - lowborns / 2 - 1;
    }
}
}

Сехтиміанери намагаються перевершити всю гру і закінчити її в кінці. Сподіваюся, мій бот не зробить занадто поганого:)


5

Ява, Вихід

Ще раз на основі основних методів TheBestOne. Цей бот мігрує з міста в місто, коли він досяг певного рівня лицарської популяції, без розбору свого власника, і повторює цей процес, поки не перетворив увесь світ.

import java.util.ArrayList;
import java.util.List;


public class Exodus {


    int round;
    int playerID;
    int thisTownID;

    List<Town> towns;
    List<Town> myTowns;
    List<Town> otherTowns;

    Town thisTown;

    public static void main(String[] args){
        if (args.length == 0){
            System.out.println("100 100 100");
            return;
        }
        new Exodus().migrate(args[0].split(";"));
    }

    private void migrate(String[] args) {
        round = Integer.parseInt(args[0]);
        playerID = Integer.parseInt(args[1]);
        thisTownID = Integer.parseInt(args[2]);
        towns = new ArrayList<>();
        myTowns = new ArrayList<>();
        otherTowns = new ArrayList<>();

        for (int i = 3; i < args.length; i++){
            towns.add(new Town(args[i]));
        }

        for (Town town : towns){
            if (town.isMine()){
                myTowns.add(town);
                if (town.isThisTown()){
                    thisTown = town;
                }
            } else {
                otherTowns.add(town);
            }
        }

       if (thisTown.knightCount() >= 100) {
           int nextTownId = thisTown.getId() + 1 > towns.size() - 1 ? 0 : thisTown.getId() + 1;
           Town nextTown = towns.get(nextTownId);
          if (nextTown.isMine()){
              System.out.println("S " + nextTown.getId() + " " + thisTown.knightCount()) ;
          } else {
              System.out.println("A " + nextTown.getId() + " " + thisTown.knightCount()) ;
          }
       } else {
           System.out.println("W") ;
       }
    }



    private class Town {
        private final int ownerId;
        private final int id;
        private final int knights;
        private final int lowborns;

        public Town(String string){
            String[] args = string.split("_");
            ownerId = Integer.parseInt(args[0]);
            id = Integer.parseInt(args[1]);
            knights = Integer.parseInt(args[2]);
            lowborns = Integer.parseInt(args[3]);
        }

        public int getId() {
            return id;
        }

        public int getOwner() {
            return ownerId;
        }

        public int knightCount() {
            return knights;
        }

        public int lowbornCount() {
            return lowborns;
        }

        public boolean isMine(){
            return ownerId == playerID;
        }

        public boolean isThisTown(){
            return id == thisTownID;
        }

        private int getFreeKnights() {
            return knights - lowborns / 2 - 1;
        }
    }
}

Збірка: javac Exodus.java

Виконати: java Exodus


5

Пітон 2, демократія

Цей король не король. Це щось сучасне. Це цар людей . Це демократія. Це повільно, неефективно, а коли щось робить, то робить це неправильно.

import sys
from math import sqrt, ceil

class Town:
    def __init__(self, owner, ID, military, civilian):
        self.owner=owner
        self.id=ID
        self.isEnemy=(self.owner!=PlayerId)
        self.isCurrent=(self.id!=TownId)
        self.mil=military
        self.civ=civilian
        self.freeK=self.mil-self.civ/2
    def canBeat(self, other):
        otherPower    = int(ceil(other.mil*1.2))
        otherMinPower = int(ceil(other.freeK*1.2))
        selfPower     = self.freeK
        if selfPower<otherMinPower:
            return 0
        elif selfPower<otherPower or (selfPower-otherPower)*2-1<other.civ:
            return 1
        else:
            return 2
    def canMove(self, other):
        otherPower    = int(ceil(other.mil*1.2))
        otherMinPower = int(ceil(other.freeK*1.2))
        if otherPower<self.mil:
            return 2
        elif otherMinPower<=self.mil:
            return 1
        else:
            return 0

    def canDefend(self, other):
        return self.freeK>other.mil

def attack_weak():

    for town in EnemyTowns:
        if curr.canMove(town)==2:
            print "A", town.id, curr.mil
            exit()
    for town in EnemyTowns:
        if curr.canMove(town)==1:
            print "A", town.id, curr.mil
            exit()

    target=EnemyTowns[0]
    for et in EnemyTowns:
        if et.mil<target.mil and et.id!=-1:
            target=et
    print "A", target.id, curr.mil-1
    exit()


if len(sys.argv) < 2:
    print 96, 96, 96
else:
    Round, PlayerId, TownId, Towns = sys.argv[1].split(";", 3)
    Round=int(Round)
    PlayerId=int(PlayerId)
    TownId=int(TownId)
    Towns=[[int(i) for i in town.split("_")] for town in Towns.split(";")]
    Towns=[Town(i[0], i[1], i[2], i[3]) for i in Towns]
    MyTowns=[t for t in Towns if t.isEnemy==False]
    EnemyTowns=[t for t in Towns if t.isEnemy]
    GameStateEnd = [t for t in EnemyTowns if t.id!=-1]==[]
    curr=[town for town in MyTowns if town.isCurrent][0]

    support=[town for town in MyTowns if town.freeK<1]
    if support!=[]:
        for town in support:
            if town.id==curr.id:
                missing=town.freeK-int(ceil(town.civ/2))
                if town.civ<5:
                    attack_weak()
                elif town.freeK<-10:
                    attack_weak()
                else:
                    print "W"
                    exit()
        for town in support:
            if abs(town.freeK-2)<curr.freeK-2:
                print "S", town.id, abs(town.freeK-2)
                exit()
            else:
                if curr.freeK>10:
                    print "S", town.id, int(abs(town.freeK-2)*0.2)
                    exit()
    if GameStateEnd:
        attack_end()
    else:
        selection=EnemyTowns[:]
        selection.sort(key=(lambda x: (x.mil-x.civ) if x.civ>3 else x.mil/4))
        for s in selection:
            if curr.canBeat(s)==2 and s.civ>s.mil/2:
                NF=(int(ceil(s.mil*1.2))+s.civ/2+1)
                if curr.mil>NF:
                    print "A", s.id, NF+(curr.mil-NF)/3
                    exit()
    if curr.freeK>10:
        MyTowns.sort(key=lambda x: x.mil)
        print "S", MyTowns[-1].id, (curr.freeK-5)/5*3
        exit()
    print "W"
    exit()

Біжи python2 democracy.py. Зауважте, що для демократії потрібен Python 2 .

Редагувати: Виправлена ​​помилка щодо друку об’єкта міста


Це іноді виводить <__main__.Town.
TheNumberOne

Доведеться виправити це ...
Ханнес Карппіла,

4

C ++ 11, обчислена файл

після того, як я спробував кілька речей з маленькою Java, яку я знаю, і не був у змозі досягти того, що я хотів, я вирішив переписати це на C ++ і додати обробку файлів. Проблема полягала в тому, що мій C ++ досить іржавий і не набагато кращий, тому деякі частини збиті разом і просто перше рішення в Google, тому не дуже якісний код ...

все-таки я зміг отримати принаймні робочий результат, який не смокче так сильно, він виграє принаймні час від часу, але я не можу це перевірити на відмінно, бо я не в змозі запустити всі інші подання на цьому ПК. Я, мабуть, перепишу націлювання взагалі і додам його як іншу відповідь пізніше сьогодні чи завтра.

#include <iostream>
#include <string>
#include <vector>
#include <sstream>
#include <cmath>
#include <ratio>
#include <fstream>
#include <algorithm>

using namespace std;


class Town {
public:
    Town(int owner, int townId, int knights, int population, int roundToDefBonus);
    int getOwner();
    int getId();
    int getKnights();
    int getPopulation();

    int getFreeKnights();
    int neededConquer();
    int getKnightsStable();
    int getRoundToDef();

    bool operator< (const Town &other) const  {
        return townId < other.townId;
    }
private:
    int owner;
    int townId;
    int knights;
    int population;
    int roundToDefBonus;
    double defBonus;
};

Town::Town(int inOwner, int inTownId, int inKnights, int inPopulation, int inRoundToDefBonus) {
    owner = inOwner;
    townId = inTownId;
    knights = inKnights;
    population = inPopulation;
    roundToDefBonus = inRoundToDefBonus;
    if(roundToDefBonus > 0) {
        defBonus = 1;
    }
    else{
        defBonus = 1.2;
    }
}

int Town::getOwner() {
    return owner;
}
int Town::getId() {
    return townId;
}
int Town::getKnights() {
    return knights;
}
int Town::getPopulation() {
    return population;
}
int Town::getFreeKnights() {
    return knights - population / 2;
}
int Town::neededConquer() {
    return max(static_cast<int>(ceil(knights * defBonus + population / 2)), 1);
}
int Town::getKnightsStable() {
    return population / 2;
}
int Town::getRoundToDef() {
    return roundToDefBonus;
}


int gameRound;
int myId;
int thisTownId;
Town* thisTown;

vector <Town> myTowns;
vector <Town> enemyTowns;

vector <Town> lastTime;

string turn();
Town* bestTarget(int knights);
Town* bestSafe(int knights);
Town* biggestTarget(int knights);
Town* biggestSafe(int knights);


string out(string, int, int);
string attack(Town*);
string safe(Town*);

bool sortTowns(const Town & t1, const Town & t2);

vector <string> stringSplit(string input, string delimeter);

int main(int argc, char* argv[]) {
    if(argc < 2){
        cout << "100 100 100";
        ofstream myFile;
        myFile.open("CalculatedFail.txt");
        myFile << "0\n";
        myFile.close();
    }
    else{
        if(argc == 2){

            string input = argv[1];
            vector <string> params = stringSplit(input, ";");

            gameRound = atoi(params.at(0).c_str());
            myId = atoi((params.at(1)).c_str());
            thisTownId = atoi(params.at(2).c_str());

            ifstream myfile("CalculatedFail.txt");
            if(myfile.is_open()){
                string line;

                getline(myfile, line);
                bool newRound = false;
                if(atoi(line.c_str()) > gameRound) {
                    newRound = true;
                }

                vector <string> oldVals;
                if(!newRound) {
                    while (getline(myfile, line)) {
                        oldVals = stringSplit(line, "_");

                        int playerId = atoi(oldVals.at(0).c_str());
                        int townId = atoi(oldVals.at(1).c_str());
                        int knights = atoi(oldVals.at(2).c_str());
                        int population = atoi(oldVals.at(3).c_str());
                        int roundToDefBonus = atoi(oldVals.at(4).c_str());

                        lastTime.push_back(Town(playerId, townId, knights, population, roundToDefBonus));
                        oldVals.clear();
                    }
                }
                else {
                    while (getline(myfile, line)) {
                        oldVals = stringSplit(line, "_");

                        int playerId = atoi(oldVals.at(0).c_str());
                        int townId = atoi(oldVals.at(1).c_str());
                        int knights = atoi(oldVals.at(2).c_str());
                        int population = atoi(oldVals.at(3).c_str());
                        int roundToDefBonus = atoi(oldVals.at(4).c_str());
                        if(roundToDefBonus) {   //if round def bonus > 0, decrement because new round
                            roundToDefBonus --;
                        }

                        lastTime.push_back(Town(playerId, townId, knights, population, roundToDefBonus));
                        oldVals.clear();
                    }

                }
                std::sort(lastTime.begin(), lastTime.end());
            }

            if(lastTime.size() > 0) {
                vector <string> values;
                for(int i = 3; i < params.size(); i++) {

                    values = stringSplit(params.at(i), "_");

                    int playerId = atoi(values.at(0).c_str());
                    int townId = atoi(values.at(1).c_str());
                    int knights = atoi(values.at(2).c_str());
                    int population = atoi(values.at(3).c_str());

                    int roundsToDef = lastTime.at(townId).getRoundToDef();
                    if(playerId != lastTime.at(townId).getOwner()) {
                        roundsToDef = 2;
                    }
                    if(playerId == myId){
                        if(thisTownId != townId)
                            myTowns.push_back(Town(playerId, townId, knights, population, roundsToDef));
                        else{
                            thisTown = new Town(playerId, townId, knights, population, roundsToDef);
                        }
                    }
                    else{
                        enemyTowns.push_back(Town(playerId, townId, knights, population, roundsToDef));
                    }
                    values.clear();
                }
            }
            else {
                vector <string> values;
                for(int i = 3; i < params.size(); i++) {

                    values = stringSplit(params.at(i), "_");

                    int playerId = atoi(values.at(0).c_str());
                    int townId = atoi(values.at(1).c_str());
                    int knights = atoi(values.at(2).c_str());
                    int population = atoi(values.at(3).c_str());

                    if(playerId == myId){
                        if(thisTownId != townId)
                            myTowns.push_back(Town(playerId, townId, knights, population, 0));
                        else{
                            thisTown = new Town(playerId, townId, knights, population, 0);
                        }
                    }
                    else{
                        enemyTowns.push_back(Town(playerId, townId, knights, population, 0));
                    }
                    values.clear();
                }
            }

            string tmp = turn();
            cout << tmp;

            ofstream writeFile("CalculatedFail.txt");
            if(writeFile.is_open()) {
                writeFile << gameRound <<"\n";

                writeFile << thisTown->getOwner() <<"_"<<thisTown->getId()<<"_"<<thisTown->getKnights()<<"_"<< thisTown->getPopulation()<<"_"<<thisTown->getRoundToDef()<<"\n";

                for(vector<Town>::size_type i = 0; i != myTowns.size(); i++) {
                    writeFile << myTowns[i].getOwner() <<"_"<<myTowns[i].getId()<<"_"<<myTowns[i].getKnights()<<"_"<< myTowns[i].getPopulation()<<"_"<<myTowns[i].getRoundToDef()<<"\n";
                }
                for(vector<Town>::size_type i = 0; i != enemyTowns.size(); i++) {
                    writeFile << enemyTowns[i].getOwner() <<"_"<<enemyTowns[i].getId()<<"_"<<enemyTowns[i].getKnights()<<"_"<< enemyTowns[i].getPopulation()<<"_"<<enemyTowns[i].getRoundToDef()<<"\n";
                }
            }

        }
        else{
            cout<<"error, wrong parameter";
        }

    }

    delete thisTown;

    return 0;
}




string turn() {
    Town* safeTarget;
    Town* attackTarget;
    if(thisTown->getFreeKnights() < 0) {    //evacuate
        safeTarget = biggestSafe(thisTown->getKnights());
        attackTarget = biggestTarget(thisTown->getKnights());

        if(safeTarget != nullptr && attackTarget != nullptr){
            if(safeTarget->getPopulation() > attackTarget->getPopulation()) {
                return out("S", safeTarget->getId(), thisTown->getKnights());
            }
            else {
                return out("A", attackTarget->getId(), thisTown->getKnights());
            }
        }
        if(safeTarget){
            return out("S", safeTarget->getId(), thisTown->getKnights());
        }
        if(attackTarget){
            return out("A", attackTarget->getId(), thisTown->getKnights());
        }
        Town* target = &myTowns.at(0);
        for(vector<Town>::size_type i = 1; i != myTowns.size(); i++) {
            if(target->getPopulation() < myTowns[i].getPopulation())
                target = &myTowns[i];
        }
        return out("S", target->getId(), thisTown->getKnights());

    }

    safeTarget = biggestSafe(thisTown->getFreeKnights());
    attackTarget = bestTarget(thisTown->getFreeKnights());


    if(safeTarget != nullptr && attackTarget != nullptr){
        if(safeTarget->getPopulation() > attackTarget->getPopulation()) {
            return safe(safeTarget);
        }
        else {
            return attack(attackTarget);
        }
    }
    if(safeTarget){
        return safe(safeTarget);
    }
    if(attackTarget){
        return attack(attackTarget);
    }

    return "W";
}

Town* bestTarget(int knights) {
    Town* target = nullptr;
    double ratio = -1;
    for(vector<Town>::size_type i = 0; i != enemyTowns.size(); i++) {
        if(enemyTowns[i].neededConquer() < knights) {
            if(enemyTowns[i].getPopulation() / enemyTowns[i].neededConquer() > ratio) {
                target = &enemyTowns[i];
                ratio = enemyTowns[i].getPopulation() / enemyTowns[i].neededConquer();
            }
        }
    }
    return target;
}

Town* biggestTarget(int knights) {
    Town* target = nullptr;
    int population = -1;
    for(vector<Town>::size_type i = 0; i != enemyTowns.size(); i++) {
        if(enemyTowns[i].neededConquer() < knights) {
            if(enemyTowns[i].getPopulation() > population) {
                target = &enemyTowns[i];
                population = target->getPopulation();
            }
        }
    }
    return target;
}

Town* biggestSafe(int knights) {
    Town* target = nullptr;
    int population = -1;
    for(vector<Town>::size_type i = 0; i != myTowns.size(); i++) {
        if(myTowns[i].getFreeKnights() < 0 && myTowns[i].getFreeKnights() + knights >= 0){
            if(myTowns[i].getPopulation() > population) {
                target = &myTowns[i];
                population = target->getPopulation();
            }
        }
    }
    return target;
}

string attack(Town* target){
    int knights;
    if(thisTown->getPopulation() > target->getPopulation()) {
        knights = target->neededConquer();
    }
    else{
        knights = thisTown->getFreeKnights();
    }
    return out("A", target->getId(), knights);
}
string safe(Town* target){
    int knights;
    if(thisTown->getPopulation() > target->getPopulation()) {
        knights = target->getFreeKnights() * -1;
    }
    else{
        knights = thisTown->getFreeKnights();
    }
    return out("S", target->getId(), knights);
}
string out(string order, int targedId, int knights) {
    stringstream tmp;
    tmp << order << " " << targedId << " " << knights;
    return tmp.str();
}

vector <string> stringSplit(string input, string delimeter) {
    stringstream tmp(input);
    vector <string> splitted;
    string pushThis;
    while (getline(tmp, pushThis, delimeter.at(0))){
        splitted.push_back(pushThis);
    }

    return splitted;
}

компілювати з: g++ -std=c++11 CalculatedFail.cpp -o CalculatedFail.exe

google каже на Linux, що це CalculatedFail.out замість .exe, але я не можу це перевірити.

і біжи CalculatedFail.exe

оскільки він використовує файл для перевірки бонусу def, запуск гри одночасно кілька разів може призвести до помилок ...

сподіваємось, що вона працює належним чином без особливих проблем


Я майже впевнений, що в Linux не було б розширення файлу.
TheNumberOne

Я не можу змусити це запуститись з контролера Java в Windows. Я склав це, як ви сказали. Працює правильно з командного рядка.
TheNumberOne

нормально, що я був дурним, забув змінити ім'я текстового файлу на початку гри, я думаю, це повинно зараз
бити

Я думаю, це проблема з контролером.
TheNumberOne

mh, ви спробували оновлену версію? Вчора у мене було аварійно 2 різних імені. версія napadOn3 рідко має помилки повороту, якщо вона вже в основному виграла, але вони обидва працюють відмінно з контролером на моїй системі.
sthrandom

3

Ява, ілюмінати

Я читав це і знав, що мені ніколи не вдасться придумати життєздатну стратегію, тому вирішив зіграти на жахливо недостатньо представлених ящірок, які можуть чи не можуть нам керувати. Замість того, щоб битися з іншими ботами, цей примушує їх до співпраці, лише відмовляючись від них у самому кінці. Фактично цей бот не залишає постійних пошкоджень.

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;

import javax.tools.JavaCompiler;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;

public class Illuminati
{
    private static final String template = 
            "import java.io.File;import java.util.Scanner;import java.io.IOException;\n" +
            "public class <<NAME>> \n" +
            "{public static void main(String[] args) throws IOException {if(args.length == 0) {\n" +
            "System.out.println(\"35 35 35\");} else { File ill_data = new File(\"Illuminati.txt\");\n" + 
            "String order = new String();Scanner sc = new Scanner(ill_data);\n" +
            "while(sc.hasNextLine()){order = sc.nextLine();} sc.close(); int city = Integer.parseInt(order);" +
            "Illuminati.TurnDescriptor desc = new Illuminati.TurnDescriptor(args[0]);" +
            "int amt = desc.thistown.getFreeKnights(); System.out.println(\"S \" + city + \" \" + amt); }}}";

    private static final File datafile = new File("Illuminati.txt");

    private static final JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();

    public static void main(String[] args) throws IOException
    {
        if(args.length == 0)
        {
            if(compiler != null)
            {
                if(!datafile.exists())
                {
                    datafile.createNewFile();
                }

                File parentdir = datafile.getAbsoluteFile().getParentFile();
                List<File> torecompile = new ArrayList<File>();

                for(File f : parentdir.listFiles())
                {
                    if(!f.isDirectory())
                    {
                        if(f.getName().endsWith(".class") && !f.getName().contains("$") && !f.getName().equals("Illuminati.class"))
                        {
                            torecompile.add(f);
                        }
                    }
                }

                for(File f : torecompile)
                {
                    File newfile = new File(f.getName() + ".temp");
                    FileInputStream fis = new FileInputStream(f);
                    FileOutputStream fos = new FileOutputStream(newfile);
                    int val;
                    while((val = fis.read()) != -1)
                    {
                        fos.write(val);
                    }
                    fis.close();
                    fos.close();
                }

                List<File> tocompile = new ArrayList<File>();

                for(File f : torecompile)
                {
                    String classname = f.getName().substring(0, f.getName().length() - 6);
                    String code = template.replace("<<NAME>>", classname);
                    File temp = new File(classname + ".java");
                    FileOutputStream fos = new FileOutputStream(temp);
                    fos.write(code.getBytes());
                    fos.close();
                    tocompile.add(temp);
                }

                StandardJavaFileManager manager = compiler.getStandardFileManager(null, null, null);
                compiler.getTask(null, manager, null, null, null, manager.getJavaFileObjectsFromFiles(tocompile)).call();

                tocompile.forEach(file -> file.delete());

                System.out.println("34 34 34");
            }
            else
            {
                System.out.println("85 85 85");
            }
        }
        else
        {
            if(datafile.exists())
            {
                TurnDescriptor descriptor = new TurnDescriptor(args[0]);
                int knights = descriptor.thistown.getFreeKnights();
                int stockpile = descriptor.towns.stream()
                .filter(town -> town.owner == descriptor.thistown.owner)
                .mapToInt(town -> town.id)
                .max().getAsInt();
                PrintWriter pw = new PrintWriter(datafile);
                pw.println("" + stockpile);
                pw.close();
                if(descriptor.thistown.id != stockpile)
                {
                    System.out.println("S " + stockpile + " " + knights);
                }
                if(descriptor.round > 80 && (descriptor.round & 1) == 1) //If the round is greater than 80 and is odd
                {
                    if(descriptor.thistown.id == stockpile)
                    {
                        Town target = descriptor.towns.stream()
                        .filter(town -> town.owner != descriptor.playerid)
                        .findAny().get();

                        System.out.println("A " + target.id + " " + descriptor.thistown.getFreeKnights());
                    }
                }
                if(descriptor.round == 99) //Resume normal AI practices
                {
                    resetClassesFromCache();
                }
            }
            else //Man, now we have to actually do stuff
            {
                System.out.println("W"); //Just kidding! Suicide!
            }
        }
    }

    private static void resetClassesFromCache() throws IOException
    {
        File parentdir = datafile.getAbsoluteFile().getParentFile();

        for(File f : parentdir.listFiles())
        {
            if(!f.isDirectory())
            {
                if(f.getName().endsWith(".class.temp") && !f.getName().contains("$"))
                {
                    FileInputStream fis = new FileInputStream(f);
                    File out = new File(f.getName().substring(0, f.getName().length() - 5));
                    FileOutputStream fos = new FileOutputStream(out, false);

                    int val;
                    while((val = fis.read()) != -1)
                    {
                        fos.write(val);
                    }

                    fis.close();
                    fos.close();
                    f.delete();
                }
            }
        }
    }

    public static class Town
    {
        public final int owner;
        public final int id;
        public final int knights;
        public final int lowborns;

        public Town(String chunk)
        {
            String[] vals = chunk.split("_");
            owner = Integer.parseInt(vals[0]);
            id = Integer.parseInt(vals[1]);
            knights = Integer.parseInt(vals[2]);
            lowborns = Integer.parseInt(vals[3]);
        }

        public int getFreeKnights()
        {
            return knights - (lowborns/2) - 1;
        }
    }

    public static class TurnDescriptor
    {
        public final List<Town> towns;
        public final int round;
        public final int playerid;
        public final Town thistown;

        public TurnDescriptor(String s)
        {
            String[] info = s.split(";");
            round = Integer.parseInt(info[0]);
            playerid = Integer.parseInt(info[1]);
            final int townid = Integer.parseInt(info[2]);

            towns = new ArrayList<Town>();
            for(int i = 3; i < info.length; i++)
            {
                Town t = new Town(info[i]);
                towns.add(t);
            }

            thistown = towns.stream()
            .filter(town -> {return town.id == townid;})
            .findFirst().get();
        }
    }
}

2
Хоча це цікава відповідь, " Інші зовнішні ресурси заборонені ". Таким чином, ваше вилучення виключається з судових процесів, але я все-таки підтверджую це рішення;)
CommonGuy

3

Java, SuperProducer

У моїй частині світу вже пізно, тому я не маю достатньо часу, щоб детально розглянути свої подання. Я буду планувати детальніше про те, як це працює згодом.

Продуктивність роботи бота здається сильно залежною від стартового порядку, який він виграє якийсь час ...

У мене були деякі ідеї, які допоможуть збільшити виграшні раунди ..., але не вистачає часу: P

package moogiesoft;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.IntSummaryStatistics;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;



public class SuperProducer implements Serializable
{
    private static final int MAX_POSSIBLE_LOWBORNS_IN_TOWN = 50;
    /**
     * 
     */
    private static final long serialVersionUID = 8652887937499233654L;
    public final String FILE = this.getClass().getSimpleName()+".txt";
    int round;
    int playerID;
    int thisTownID;

    List<Town> towns;
    List<Town> myTowns;
    List<Town> otherTowns;

    Map<Integer, Conquest> townOwnerShipMap = new HashMap<Integer, Conquest>();

    Town thisTown;
    private int targetOpponent = -1; // the id of the opponent that out towns will endevour to direct their attacks 
    private int maxOpponentTownSize; // the number of knights of the opponent town with the most knights
    private int avgOpponentTownSize; // the average number of knights in an opponent town
    private int midAvgMaxOpponentTownSize; // value 1/2 between average and max knights in an opponent town

    public static void main(String[] args){
        if (args.length == 0){
            new SuperProducer().sendStartingKnights();
        }
        else
        {
            new SuperProducer().letsDoIt(args[0].split(";"));
        }
    }

    private void sendStartingKnights()
    {
        // delete any stale state information
        File file = new File(FILE);
        file.delete();

        System.out.println("100 100 0");
    }

    private void letsDoIt(String[] args)
    {
        round = Integer.parseInt(args[0]);
        playerID = Integer.parseInt(args[1]);
        thisTownID = Integer.parseInt(args[2]);
        towns = new ArrayList<>();
        myTowns = new ArrayList<>();
        otherTowns = new ArrayList<>();

        for (int i = 3; i < args.length; i++)
        {
            towns.add(new Town(args[i]));
        }

        // load in stored state information
        File file = new File(FILE);
        if (file.exists())
        {
            try
            {
                ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
                townOwnerShipMap = (Map<Integer, Conquest>) ois.readObject();
                targetOpponent  = ois.readInt();
                ois.close();
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
        }

        for (Town town : towns)
        {

            // update town conquest map
            Conquest conquest = townOwnerShipMap.remove(town.getId());
            if (conquest==null)
            {
                conquest = new Conquest(town.ownerId, -1);
                townOwnerShipMap.put(town.getId(),conquest);
            }
            else if (town.getOwner()!=conquest.getOwner())
            {
                conquest.setOwner(town.ownerId);
                conquest.setConquestRound(round-1);
            }
            town.setDefenceBonus(round-conquest.getConquestRound()>2);

            if (town.isMine()){
                myTowns.add(town);
                if (town.isThisTown()){
                    thisTown = town;
                }
            } else {
                otherTowns.add(town);
            }
        }

        String response = "W";

        // this town has some knights to potentially command...
        if (thisTown.getKnightCount()>0)
        {
            // first round... consolidate into 1 super town
            if (round==1)
            {
                int thisTownIndex=myTowns.indexOf(thisTown);
                switch (thisTownIndex)
                {
                    case 1:
                    case 0:
                        // if we are the first town then move all knights into second town
                        if (myTowns.size()>1 && thisTown.getKnightCount()<200)
                        {
                            response = "S " + myTowns.get(thisTownIndex+1).getId() + " " + thisTown.getKnightCount();
                            break;
                        }
                    default:
                        // the third town does nothing!
                }
            }
            else 
            {
                // second round... go find some good starting towns to conquer
                if (round==2)
                {
                    // this town is a town able to attack
                    if (thisTown.getKnightCount()>100)
                    {
                        // If by some miracle we still own the town with no knights then re-inforce it.
                        Town superTown = myTowns.stream().filter(a->a.getKnightCount()==200).findFirst().get();
                        if (superTown!=null && superTown.getId()!=thisTown.getId())
                        {
                            response = "S " + superTown.getId() + " " + thisTown.getKnightCount();
                        }
                        else
                        {
                            // find the next most productive Town...
                            Town townToAttack = otherTowns.get(0);
                            for (Town town : otherTowns)
                            {
                                if (town.getLowbornCount()>townToAttack.getLowbornCount())
                                {
                                    townToAttack=town;
                                    if (townToAttack.getOwner()!=playerID)
                                    {
                                        targetOpponent=townToAttack.getOwner();
                                    }
                                }
                            }

                            // the town to attack is most likely the own we lost due to having no knights to begin with...
                            response = "A " + townToAttack.getId() + " " + thisTown.getKnightCount();
                        }
                    }
                    // else this is a conquered town so lets not do anything!
                }
                else if (round>97)
                {
                    int attackForce = thisTown.getFreeKnights()/4;
                    if (thisTown.getFreeKnights()>attackForce && attackForce>0)
                    {

                        boolean goFlag=false;
                        Town townToAttack = null;
                        for (Town town : towns)
                        {
                            // 
                            if (town==thisTown) goFlag=true;
                            else if (goFlag && town.getOwner()!=thisTown.getOwner())
                            {
                                if (town.getLowbornCount()==0)
                                {
                                    townToAttack=town;
                                    break;
                                }
                            }
                        }

                        if (townToAttack==null)
                        {
                            for (Town town : otherTowns)
                            {
                                if (town.getLowbornCount()==0)
                                {
                                    townToAttack=town;
                                    break;
                                }
                            }
                        }

                        if (round > 98 && townToAttack==null)
                        {
                            for (Town town : otherTowns)
                            {
                                attackForce = thisTown.getKnightCount()-town.getKnightCount()-town.getMinimumKnights()-1-thisTown.getMinimumKnights()-1;
                                if (attackForce>0)
                                {
                                    townToAttack=town;
                                    break;
                                }
                            }
                        }

                        if (townToAttack!=null)
                        {
                            response = "A " + townToAttack.getId() + " " + attackForce;
                        }
                        else
                        {
                            int thisTownIndex = myTowns.indexOf(thisTown);
                            int supportSize = Math.min(thisTown.getKnightCount()/4, thisTown.getFreeKnights());

                            if (supportSize>thisTown.getMinimumKnights() && thisTownIndex<myTowns.size()-1)
                            {
                                Town townToSupport = myTowns.get(thisTownIndex+1);
                                response = "S " + townToSupport.getId() + " " + (thisTown.getKnightCount()-thisTown.getKnightCount()/4);
                            }
                        }
                    }

                }

                // we are on non-beginning non-ending round...
                else
                {
                    // calculate statistics
                    IntSummaryStatistics statistics = otherTowns.stream().collect(Collectors.summarizingInt(Town::getKnightCount));
                    maxOpponentTownSize = statistics.getMax();
                    avgOpponentTownSize = (int) statistics.getAverage();
                    midAvgMaxOpponentTownSize = (maxOpponentTownSize+avgOpponentTownSize)/2;

                    if ((round-1)%3==1)
                    {
                        // find the next strongest town of our target Opponent that produces knights...
                        Town townToAttack = null;
                        for (Town town : otherTowns)
                        {
                            if (town.getLowbornCount() > 0 && town.getOwner() == targetOpponent && (townToAttack == null || town.getKnightCount()>townToAttack.getKnightCount()))
                            {
                                townToAttack=town;
                            }
                        } 


                        // target opponent cannot grow so choose another opponent...
                        // favour the weakest opponent that has has some towns that produces towns..
                        // otherwise favour the weakest opponent
                        if (townToAttack==null)
                        {
                            townToAttack=chooseNewOpponentToAttack();
                        }
                        targetOpponent=townToAttack.getOwner();

                        int minKnightsToLeaveAtThisTown = calculateDesiredKnightsAtTown(thisTown);
                        int minKnightsToLeftAtAttackedTownAfterBattle = calculateDesiredKnightsAtTown(townToAttack);

                        double defenceBonus = townToAttack.hasDefenceBonus()?1.2:1;
                        double defenderAttackStrength = townToAttack.getKnightCount() * defenceBonus;
                        int knightsNeededToWinAndEnsureNotAttackedNextRound =  minKnightsToLeftAtAttackedTownAfterBattle + (int) (defenderAttackStrength);
                        knightsNeededToWinAndEnsureNotAttackedNextRound = knightsNeededToWinAndEnsureNotAttackedNextRound + ((knightsNeededToWinAndEnsureNotAttackedNextRound-defenderAttackStrength - townToAttack.getMinimumKnights() < 0) ?townToAttack.getMinimumKnights():0);
                        int knightsLeftAtSortieingTownAfterAttacking = thisTown.getKnightCount()-knightsNeededToWinAndEnsureNotAttackedNextRound;

                        // if the sortieing town is sufficiently safe from another attack after it attempts to attack the other town will it try to attack  
                        if (knightsLeftAtSortieingTownAfterAttacking > thisTown.getMinimumKnights()*2 &&
                            knightsLeftAtSortieingTownAfterAttacking>minKnightsToLeaveAtThisTown &&
                            thisTown.getFreeKnights()>knightsNeededToWinAndEnsureNotAttackedNextRound)
                        {
                            response = "A " + townToAttack.getId() + " " + knightsNeededToWinAndEnsureNotAttackedNextRound;
                        }
                        // not safe... so lets support our other towns
                        else
                        {
                            int surplusKnights = thisTown.getKnightCount()-minKnightsToLeaveAtThisTown;

                            // this town has surplusKnights
                            if (surplusKnights>0)
                            {
                                int knightsAvailable = Math.min(surplusKnights, thisTown.getFreeKnights());

                                // find our weakest and strongest towns
                                Town myWeakestTown=null;
                                Town myStrongestTown=null;
                                for (Town town : myTowns)
                                {
                                    if (!(town.getKnightCount()==0 && round<50) && (myWeakestTown == null || town.getKnightCount()<myWeakestTown.getKnightCount()))
                                    {
                                        myWeakestTown=town;
                                    }
                                    if (!(town.getKnightCount()==0 && round<50) && ( myStrongestTown == null || town.getKnightCount()>myStrongestTown.getKnightCount()))
                                    {
                                        myStrongestTown=town;
                                    }
                                }

                                // see if my Weakest Town needs support
                                Town townToSupport = null;
                                int knightsToSend=0;
                                if (thisTown!=myWeakestTown)
                                {
                                    int desiredKnightsAtTown = calculateDesiredKnightsAtTown(myWeakestTown);

                                    if (myWeakestTown.getKnightCount()<desiredKnightsAtTown)
                                    {
                                        int deltaDesiredKnights = desiredKnightsAtTown-myWeakestTown.getKnightCount();
                                        knightsToSend = Math.min(knightsAvailable, deltaDesiredKnights);
                                        townToSupport=myWeakestTown;
                                    }
                                }

                                // no towns needed support so we will attempt to support the strongest town
                                if (townToSupport == null)
                                {
                                    if (thisTown!=myStrongestTown)
                                    {
                                        int desiredKnightsAtTown = calculateDesiredKnightsAtTown(myStrongestTown);
                                        if (myStrongestTown.getKnightCount()<desiredKnightsAtTown)
                                        {
                                            int deltaDesiredKnights = desiredKnightsAtTown-myStrongestTown.getKnightCount();
                                            knightsToSend = Math.min(knightsAvailable, deltaDesiredKnights);

                                            knightsToSend = knightsAvailable;
                                            townToSupport=myStrongestTown;
                                        }
                                    }
                                }

                                // support the chosen town if possible
                                if (townToSupport != null)
                                {
                                    response = "S " + townToSupport.getId() + " " + knightsToSend;
                                }
                            }
                        }
                    }
                }
            }
        }

        // save state information
        try
        {
            ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file));
            oos.writeObject(townOwnerShipMap);
            oos.writeInt(targetOpponent);
            oos.close();
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }

        System.out.println(response);
    }

    // returns a town of the opponent that is deemed to be the most worthy
    private final Town chooseNewOpponentToAttack()
    {
        Town townToAttack=null;

        // calculate opponent sizes
        HashMap<Integer,Opponent> opponentMap = new HashMap<Integer, Opponent>();
        for (Town town : otherTowns)
        {
            Opponent opponent = opponentMap.get(town.getOwner());
            if (opponent == null)
            {
                opponent = new Opponent(town.getOwner());
                opponentMap.put(town.getOwner(), opponent);
            }
            opponent.addTown(town);
        }


        // create sorted list of opponents based on strength. 
        List<Integer> opponentsByStrength = new ArrayList<Integer>(opponentMap.keySet());
        opponentsByStrength.sort(new Comparator<Integer>()
        {
            public int compare(Integer o1, Integer o2)
            {
                Opponent left = opponentMap.get(o1);
                Opponent right = opponentMap.get(o2);

                return left.getTotalKnights()-right.getTotalKnights();
            }
        });

        // attempt to choose the weakest opponent's weakest town that has some ability to generate knights...
        out:
        for (Integer opponent : opponentsByStrength)
        {
            for (Town town : opponentMap.get(opponent).getTowns())
            {
                if (town.getOwner() !=-1 && town.getLowbornCount() > 0 && (townToAttack == null || town.getKnightCount()<townToAttack.getKnightCount()))
                {
                    townToAttack=town;
                    break out;
                }
            } 
        }

        // no opponents left with knights producing towns... just go for the weakest town.
        if (townToAttack == null)
        {
            for (Town town : otherTowns)
            {
                if (townToAttack == null || town.getKnightCount()<townToAttack.getKnightCount())
                {
                    townToAttack=town;
                }
            } 
        }

        return townToAttack;
    }

    // returns the number of knights that should make this town safe from attack
    final private int calculateDesiredKnightsAtTown(Town town)
    {
        int minimumKnightsWeWantInATown = avgOpponentTownSize;
        return minimumKnightsWeWantInATown + town.getLowbornCount()==0?0:(minimumKnightsWeWantInATown +(int) (((double) town.getLowbornCount() / MAX_POSSIBLE_LOWBORNS_IN_TOWN) * (midAvgMaxOpponentTownSize-minimumKnightsWeWantInATown)));
    }

    /** represents a conquest of a Town by a player */
    class Conquest implements Serializable
    {
        private static final long serialVersionUID = -1120109012356785962L;
        private int owner;
        private int conquestRound;
        public int getOwner()
        {
            return owner;
        }
        public void setOwner(int owner)
        {
            this.owner = owner;
        }
        public int getConquestRound()
        {
            return conquestRound;
        }
        public void setConquestRound(int conquestRound)
        {
            this.conquestRound = conquestRound;
        }
        public Conquest(int owner, int conquestRound)
        {
            super();
            this.owner = owner;
            this.conquestRound = conquestRound;
        }

    }

    /** represents an opponent in the simulation */
     private class Opponent implements Serializable
     {
         private int ownerId;
         private int totalKnights;
         private List<Town> towns = new ArrayList<SuperProducer.Town>();

         public void addTown(Town town)
         {
             totalKnights+=town.getKnightCount();
             towns.add(town);
         }

        public int getOwnerId()
        {
            return ownerId;
        }

        public int getTotalKnights()
        {
            return totalKnights;
        }

        public List<Town> getTowns()
        {
            return towns;
        }

        public Opponent(int ownerId)
        {
            super();
            this.ownerId = ownerId;
        }
     }

     /** represents a Town in the simulation */
     private class Town implements Serializable
    {
        private static final long serialVersionUID = 5011668142883502165L;
        private final int ownerId;
        private final int id;
        private final int knights;
        private final int lowborns;
        private boolean defenceFlag =true;

        public Town(String string){
            String[] args = string.split("_");
            ownerId = Integer.parseInt(args[0]);
            id = Integer.parseInt(args[1]);
            knights = Integer.parseInt(args[2]);
            lowborns = Integer.parseInt(args[3]);
        }

        public boolean hasDefenceBonus()
        {
            return defenceFlag;
        }

        public void setDefenceBonus(boolean defenceFlag)
        {
            this.defenceFlag = defenceFlag;
        }

        public int getId() {
            return id;
        }

        public int getOwner() {
            return ownerId;
        }

        public int getKnightCount() {
            return knights;
        }

        public int getLowbornCount() {
            return lowborns;
        }

        public boolean isMine(){
            return ownerId == playerID;
        }

        public boolean isThisTown(){
            return id == thisTownID;
        }

        private int getFreeKnights() {
            return knights - lowborns / 2 - 1;
        }

        private int getMinimumKnights() {
            return lowborns / 2 + 1;
        }
    }
 }

Компілювати: javac SuperProducer.java

Виконати: java moogiesoft.SuperProducer


2

C ++ 11, атакаOn3

сам код не став набагато красивішим, але тепер я використовую інший спосіб націлювання, можливо, додаватимуть коментарі до коду пізніше.

начебто все добре з ботами, які я бігаю, хоча це все ще важко проти Франкенштейна та визволителя і не може виграти послідовно.

#include <iostream>
#include <string>
#include <vector>
#include <sstream>
#include <cmath>
#include <ratio>
#include <fstream>
#include <algorithm>

using namespace std;


class Town {
public:
    Town(int owner, int townId, int knights, int population, int roundToDefBonus);

    int getOwner();

    int getId();

    int getKnights();

    int getPopulation();

    int getFreeKnights();

    int neededConquer();

    int needRevolt();

    int getRoundToDef();

    bool operator<(const Town &other) const {
        return townId < other.townId;
    }

private:
    int owner;
    int townId;
    int knights;
    int population;
    int roundToDefBonus;
    double defBonus;
};

Town::Town(int inOwner, int inTownId, int inKnights, int inPopulation, int inRoundToDefBonus) {
    owner = inOwner;
    townId = inTownId;
    knights = inKnights;
    population = inPopulation;
    roundToDefBonus = inRoundToDefBonus;
    if (roundToDefBonus > 0) {
        defBonus = 1;
    }
    else {
        defBonus = 1.2;
    }
}

int Town::getOwner() {
    return owner;
}

int Town::getId() {
    return townId;
}

int Town::getKnights() {
    return knights;
}

int Town::getPopulation() {
    return population;
}

int Town::getFreeKnights() {
    return knights - population / 2;
}

int Town::neededConquer() {
    return max(static_cast<int>(ceil(knights * defBonus + population / 2)), 1);
}

int Town::needRevolt() {
    return knights * defBonus - population / 2;
}

int Town::getRoundToDef() {
    return roundToDefBonus;
}

#define maxRounds 100
#define newKnights 3

const int attackround = newKnights - 1;
const int getEmptyTowns = maxRounds - 5;

int gameRound;
int myId;
int thisTownId;
Town *thisTown;

vector<Town> myTowns;
vector<Town> enemyTowns;

vector<Town> lastTime;

string turn();

Town *bestGainTarget(int knights);

Town *bestSafe(int knights);

Town *biggestTarget(int knights);

Town *biggestSafe(int knights);

Town *weakTarget(int knights);


string out(string, int, int);

string attack(Town *);

string safe(Town *);

bool sortTowns(const Town &t1, const Town &t2);

vector<string> stringSplit(string input, string delimeter);

int getBiggestEnemyId();

int main(int argc, char *argv[]) {
    if (argc < 2) {
        cout << "100 100 100";
        ofstream myFile;
        myFile.open("attackOn3.txt");
        myFile << "0\n";
        myFile.close();
    }
    else {
        if (argc == 2) {

            string input = argv[1];
            vector<string> params = stringSplit(input, ";");

            gameRound = atoi(params.at(0).c_str());
            myId = atoi((params.at(1)).c_str());
            thisTownId = atoi(params.at(2).c_str());

            ifstream myfile("attackOn3.txt");
            if (myfile.is_open()) {
                string line;

                getline(myfile, line);
                bool newRound = false;
                if (atoi(line.c_str()) > gameRound) {
                    newRound = true;
                }

                vector<string> oldVals;
                if (!newRound) {
                    while (getline(myfile, line)) {
                        oldVals = stringSplit(line, "_");

                        int playerId = atoi(oldVals.at(0).c_str());
                        int townId = atoi(oldVals.at(1).c_str());
                        int knights = atoi(oldVals.at(2).c_str());
                        int population = atoi(oldVals.at(3).c_str());
                        int roundToDefBonus = atoi(oldVals.at(4).c_str());

                        lastTime.push_back(Town(playerId, townId, knights, population, roundToDefBonus));
                        oldVals.clear();
                    }
                }
                else {
                    while (getline(myfile, line)) {
                        oldVals = stringSplit(line, "_");

                        int playerId = atoi(oldVals.at(0).c_str());
                        int townId = atoi(oldVals.at(1).c_str());
                        int knights = atoi(oldVals.at(2).c_str());
                        int population = atoi(oldVals.at(3).c_str());
                        int roundToDefBonus = atoi(oldVals.at(4).c_str());
                        if (roundToDefBonus) {   //if round def bonus > 0, decrement because new round
                            roundToDefBonus--;
                        }

                        lastTime.push_back(Town(playerId, townId, knights, population, roundToDefBonus));
                        oldVals.clear();
                    }

                }
                std::sort(lastTime.begin(), lastTime.end());
            }

            if (lastTime.size() > 0) {
                vector<string> values;
                for (int i = 3; i < params.size(); i++) {

                    values = stringSplit(params.at(i), "_");

                    int playerId = atoi(values.at(0).c_str());
                    int townId = atoi(values.at(1).c_str());
                    int knights = atoi(values.at(2).c_str());
                    int population = atoi(values.at(3).c_str());

                    int roundsToDef = lastTime.at(townId).getRoundToDef();
                    if (playerId != lastTime.at(townId).getOwner()) {
                        roundsToDef = 2;
                    }
                    if (playerId == myId) {
                        if (thisTownId != townId)
                            myTowns.push_back(Town(playerId, townId, knights, population, roundsToDef));
                        else {
                            thisTown = new Town(playerId, townId, knights, population, roundsToDef);
                        }
                    }
                    else {
                        enemyTowns.push_back(Town(playerId, townId, knights, population, roundsToDef));
                    }
                    values.clear();
                }
            }
            else {
                vector<string> values;
                for (int i = 3; i < params.size(); i++) {

                    values = stringSplit(params.at(i), "_");

                    int playerId = atoi(values.at(0).c_str());
                    int townId = atoi(values.at(1).c_str());
                    int knights = atoi(values.at(2).c_str());
                    int population = atoi(values.at(3).c_str());

                    if (playerId == myId) {
                        if (thisTownId != townId)
                            myTowns.push_back(Town(playerId, townId, knights, population, 0));
                        else {
                            thisTown = new Town(playerId, townId, knights, population, 0);
                        }
                    }
                    else {
                        enemyTowns.push_back(Town(playerId, townId, knights, population, 0));
                    }
                    values.clear();
                }
            }

            string tmp = turn();
            cout << tmp;

            ofstream writeFile("attackOn3.txt");
            if (writeFile.is_open()) {
                writeFile << gameRound << "\n";

                writeFile << thisTown->getOwner() << "_" << thisTown->getId() << "_" << thisTown->getKnights() << "_" << thisTown->getPopulation() << "_" << thisTown->getRoundToDef() << "\n";

                for (vector<Town>::size_type i = 0; i != myTowns.size(); i++) {
                    writeFile << myTowns[i].getOwner() << "_" << myTowns[i].getId() << "_" << myTowns[i].getKnights() << "_" << myTowns[i].getPopulation() << "_" << myTowns[i].getRoundToDef() << "\n";
                }
                for (vector<Town>::size_type i = 0; i != enemyTowns.size(); i++) {
                    writeFile << enemyTowns[i].getOwner() << "_" << enemyTowns[i].getId() << "_" << enemyTowns[i].getKnights() << "_" << enemyTowns[i].getPopulation() << "_" << enemyTowns[i].getRoundToDef() << "\n";
                }
            }
        }
        else {
            cout << "error, wrong parameter";
        }
    }

    delete thisTown;

    return 0;
}


string turn() {
    Town *safeTarget;
    Town *attackTarget;
    if (thisTown->getFreeKnights() < 0) {    //evacuate
        safeTarget = biggestSafe(thisTown->getKnights());
        attackTarget = biggestTarget(thisTown->getKnights());

        if (safeTarget != nullptr && attackTarget != nullptr) {
            if (safeTarget->getPopulation() > attackTarget->getPopulation()) {
                return out("S", safeTarget->getId(), thisTown->getKnights());
            }
            else {
                return out("A", attackTarget->getId(), thisTown->getKnights());
            }
        }
        if (safeTarget) {
            return out("S", safeTarget->getId(), thisTown->getKnights());
        }
        if (attackTarget) {
            return out("A", attackTarget->getId(), thisTown->getKnights());
        }
        Town *target = &myTowns.at(0);
        for (vector<Town>::size_type i = 1; i != myTowns.size(); i++) {
            if (target->getPopulation() < myTowns[i].getPopulation())
                target = &myTowns[i];
        }
        return out("S", target->getId(), thisTown->getKnights());

    }

    safeTarget = biggestSafe(thisTown->getFreeKnights());
    if (gameRound % newKnights == attackround) {      //knights only get produced every 3 town, i want to conquer the best towns just before that so i get more reinforments and dont need to fight quite that much
        attackTarget = bestGainTarget(thisTown->getFreeKnights());
    }
    else {       //but if a town is easy to aquiere i still want it, e. g. because of revolution or someone weakened it so that it will revolte
        attackTarget = weakTarget(thisTown->getFreeKnights());
    }

    if (safeTarget != nullptr && attackTarget != nullptr) {
        if (safeTarget->getPopulation() > attackTarget->getPopulation()) {
            return safe(safeTarget);
        }
        else {
            return attack(attackTarget);
        }
    }
    if (safeTarget) {
        return safe(safeTarget);
    }
    if (attackTarget) {
        return attack(attackTarget);
    }

    if (gameRound > getEmptyTowns) {     //empty towns dont matter early on but still count to win score
        for (vector<Town>::size_type i = 0; i != enemyTowns.size(); i++) {
            if (enemyTowns[i].getPopulation() < 2) {
                if (enemyTowns[i].neededConquer() < thisTown->getFreeKnights()) {
                    return attack(&enemyTowns[i]);
                }
            }
        }
    }

    int biggestEnemy = getBiggestEnemyId();
    //if last round attack possible biggest other guy
    if (gameRound == maxRounds) {
        int targetKnights = -1;
        Town *target;
        for (vector<Town>::size_type i = 0; i != enemyTowns.size(); i++) {
            if (enemyTowns[i].getOwner() == biggestEnemy) {
                if (enemyTowns[i].neededConquer() < thisTown->getFreeKnights()) {
                    if (enemyTowns[i].getFreeKnights() > targetKnights) {
                        target = &enemyTowns[i];
                        targetKnights = target->getFreeKnights();
                    }
                }
            }
        }
        if (targetKnights > -1) {
            attack(target);
        }
    }
    //revolt from biggest other guy
    if (gameRound > 10) {        //most bots need a bit of time
        int targetPop = 0;
        Town *target;
        for (vector<Town>::size_type i = 0; i != enemyTowns.size(); i++) {
            if (enemyTowns[i].getOwner() == biggestEnemy) {
                if (enemyTowns[i].needRevolt() < thisTown->getFreeKnights()) {
                    if (enemyTowns[i].getPopulation() > targetPop) {
                        target = &enemyTowns[i];
                        targetPop = target->getPopulation();
                    }
                }
            }
        }
        if (targetPop != 0) {
            return attack(target);
        }
    }

    return "W";
}

Town *bestGainTarget(int knights) {
    Town *target = nullptr;
    int gain = -thisTown->getFreeKnights();
    int now = -thisTown->getFreeKnights();
    //int loses = thisTown->getFreeKnights();
    for (vector<Town>::size_type i = 0; i != enemyTowns.size(); i++) {
        int conquer = enemyTowns[i].neededConquer();
        if (conquer < knights && enemyTowns[i].getPopulation() > 0) {
            if (enemyTowns[i].getPopulation() * 2 *1.2 - conquer > gain) {
                if(enemyTowns[i].getPopulation() - conquer > now){
                    target = &enemyTowns[i];
                    now = target->getPopulation() - conquer;
                    gain = target->getPopulation() * 2 - conquer;
                }
            }
        }
    }
    return target;
}

Town *weakTarget(int knights) {     //maybe change it that it prefers targets with 0/40 over 24/50
    Town *target = nullptr;
    double population = 1;
    for (vector<Town>::size_type i = 0; i != enemyTowns.size(); i++) {
        if (enemyTowns[i].neededConquer() < knights) {
            if (enemyTowns[i].getKnights() < enemyTowns[i].getPopulation() / 2) {
                if (enemyTowns[i].getPopulation() > population) {
                    target = &enemyTowns[i];
                    population = target->getPopulation();
                }
            }
        }
    }
    return target;
}

Town *biggestTarget(int knights) {
    Town *target = nullptr;
    int population = -1;
    for (vector<Town>::size_type i = 0; i != enemyTowns.size(); i++) {
        if (enemyTowns[i].neededConquer() < knights) {
            if (enemyTowns[i].getPopulation() > population) {
                target = &enemyTowns[i];
                population = target->getPopulation();
            }
        }
    }
    return target;
}

Town *biggestSafe(int knights) {
    Town *target = nullptr;
    int population = -1;
    for (vector<Town>::size_type i = 0; i != myTowns.size(); i++) {
        if (myTowns[i].getFreeKnights() < 0 && myTowns[i].getFreeKnights() + knights >= 0) {
            if (myTowns[i].getPopulation() > population) {
                target = &myTowns[i];
                population = target->getPopulation();
            }
        }
    }
    return target;
}

int getBiggestEnemyId() {
    int players[enemyTowns.size() / 3 + 1];
    for (vector<Town>::size_type i = 0; i != enemyTowns.size(); i++) {
        if (enemyTowns[i].getOwner() != -1) {
            players[enemyTowns[i].getOwner()] = enemyTowns[i].getPopulation();
        }
    }
    int max = 0;
    for (int i = 1; i < enemyTowns.size() / 3 + 1; i++) {
        if (players[i] > players[max]) {
            max = i;
        }
    }
}

string attack(Town *target) {
    int knights;
    if (thisTown->getPopulation() > target->getPopulation()) {
        knights = target->neededConquer();
    }
    else {
        knights = thisTown->getFreeKnights();
    }
    return out("A", target->getId(), knights);
}

string safe(Town *target) {
    int knights;
    if (thisTown->getPopulation() > target->getPopulation()) {
        knights = target->getFreeKnights() * -1;
    }
    else {
        knights = thisTown->getFreeKnights();
    }
    return out("S", target->getId(), knights);
}

string out(string order, int targedId, int knights) {
    stringstream tmp;
    tmp << order << " " << targedId << " " << knights;
    return tmp.str();
}

vector<string> stringSplit(string input, string delimeter) {
    stringstream tmp(input);
    vector<string> splitted;
    string pushThis;
    while (getline(tmp, pushThis, delimeter.at(0))) {
        splitted.push_back(pushThis);
    }
    return splitted;
}

компілюйте з: g++ -std=c++11 attackOn3.cpp -o attackOn3.exe
і запустітьattackOn3.exe

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.