📄 smartagentbase.java
字号:
{ Country poss = possibles.next(); if (poss.getOwner()==ID && poss.getNumberEnemyNeighbors()==1) { // then <poss> will join in the merge into <enemy> ours.add(poss); } } // now we attack if the odds are good. int ourArmies = 0; for (int i = 0; i < ours.size(); i++) ourArmies += ((Country)ours.get(i)).getArmies(); if (ourArmies > enemy.getArmies()) { // AAaaaaaaaaaeeeeeeeeeiiiiiiiii! Attack him from all our countries for (int i = 0; i < ours.size() && enemy.getOwner() != ID; i++) { if (((Country)ours.get(i)).getArmies() > 1) { moveInMemory = 1000000; if (board.attack( (Country)ours.get(i), enemy, true) > 0) wonAttack = true; } } moveInMemory = -1; } } } return wonAttack; }// wherever we have a border that outnumbers an enemy, we attack the enemy.// let moveIn decide what to do if we win.// return true if we won at least one attack protected boolean attackSplitOff( Country root ) { moveInMemory = -1; CountryIterator borders = new ClusterBorderIterator(root ); boolean wonAttack = false; while (borders.hasNext()) { Country border = borders.next(); CountryIterator neighbors = new NeighborIterator(border); while (neighbors.hasNext()) { Country neighbor = neighbors.next(); if (neighbor.getOwner() != ID && neighbor.getArmies() < border.getArmies()) { if (board.attack( border, neighbor, true) > 0) wonAttack = true; } } } return wonAttack; }// for each border of <root>'s cluster, we split up our border country into its ememy countries.// but only when (our armies) > (enemy armies)*attackRatio.// An attack ratio of 1.0 is when we at least tie them// return true if we won at least one attack protected boolean attackSplitUp( Country root, float attackRatio ) { /**** STAGE 4 ATTACK ****/ // Now the third stage. If it leeds to a good chance of more land, we split our borders into two or more armie groups. CountryIterator borders = new ClusterBorderIterator(root ); boolean wonAttack = false; while (borders.hasNext()) { Country border = borders.next(); CountryIterator neighbors = new NeighborIterator(border); int enemies = 0; int enemiesArmies = 0; Country enemy = null; while (neighbors.hasNext()) { Country neighbor = neighbors.next(); if (neighbor.getOwner() != ID) { enemies++; enemiesArmies += neighbor.getArmies(); enemy = neighbor; } } // We only perform this operation when we far outnumber them. if (border.getArmies() > enemiesArmies*attackRatio) { int armiesPer = border.getArmies()/Math.max(enemies,1); // use the max function to avoid divide by zero // then we will attack from this border to all of its enemy neighbors. neighbors = new NeighborIterator(border); while (neighbors.hasNext() && border.getArmies() > 1) { Country neighbor = neighbors.next(); if (neighbor.getOwner() != ID) { // then we kill this enemy with 1/<enemies> moveInMemory = armiesPer; if (board.attack( border, neighbor, true) > 0) wonAttack = true; moveInMemory = -1; // xxagentxx: if we lose lots of armies in the first attacks, the last attacks might not happen because we are out of armies. This is a bug, but not very serious. wonAttack = true; } } } } return wonAttack; }// do a combonation of the three almost always helpful attacks// return true if we won at least one attack protected boolean tripleAttackPack(Country root) { boolean won = false; while ( attackEasyExpand(root) ) {won = true;} attackFillOut(root); while ( attackConsolidate(root) ) {won = true;} return won; }// This method calculates the total number of armies owned by each player.// If we outnumber all the other players combined then go HOGWILD!protected boolean hogWildCheck() { // calculate some stats about player armies: int numPlayers = board.getNumberOfPlayers(); int[] armies = new int[numPlayers]; int enemyArmies = 0; for (int i = 0; i < numPlayers; i++) { armies[i] = BoardHelper.getPlayerArmies(i, countries); if (i != ID) { enemyArmies += armies[i]; } } // done getting stats return (armies[ID] > enemyArmies); }// sets off as much attacking as possible if hogWild conditions are metprotected void attackHogWild() { if (hogWildCheck()) { attackAsMuchAsPossible(); } }// If we have tons of armies then the game has probably hit a stalemate.// Shake things upprotected void attackStalemate() { if (BoardHelper.getPlayerArmies(ID, countries) > 1500) attackAsMuchAsPossible(); }protected void attackAsMuchAsPossible() { boolean attacked = true; CountryIterator e; while (attacked) { attacked = false; e = new PlayerIterator(ID, countries); while (e.hasNext()) { Country c = e.next(); while ( tripleAttackPack(c) ) { attacked = true; } while ( attackSplitUp(c, 0.01f) ) { attacked = true; } } } }// This method first checks to see if we can still aquire a card by conquering a country.// If so, it compares all the possible attack match-ups we have and executes the best one // if (ourArmies > theirArmies*ratio). i.e. ratio of 1 is us > them. ratio of 2 is us double themprotected void attackForCard() { attackForCard(1); }protected void attackForCard(int outnumberTimes) { if (! board.useCards() || board.tookOverACountry()) { return; } // find the best matchup of all our enemies float bestRatio = 0; Country bestUs = null; Country bestThem = null; CountryIterator ours = new PlayerIterator(ID, countries); while (ours.hasNext()) { Country us = ours.next(); CountryIterator thems = new NeighborIterator(us); while (thems.hasNext()) { Country them = thems.next(); if (them.getOwner() != ID && (us.getArmies()*1.0/them.getArmies()) > bestRatio) { bestRatio = (us.getArmies()*1.0f/them.getArmies()); bestUs = us; bestThem = them; } } } // if we have a good matchup take it: if ( bestUs.getArmies() > bestThem.getArmies()*outnumberTimes ) { debug("executing an attackForCard attack"); setmoveInMemoryBeforeCardAttack(bestUs); // boscoe and Yakool implement this differently board.attack(bestUs, bestThem, true); moveInMemory = -1; } } // end of attackForCard()// to have rational behaviour when using attackForCard subclasses must imp thisprotected void setmoveInMemoryBeforeCardAttack(Country attacker) { }/** If either country only borders 1 country then stay away from that country.Return -1 if both countries have more then 1 neighbor, otherwise return the number that should be returned from moveArmiesIn(). */protected int obviousMoveArmiesInTest(int cca, int ccd) { if (countries[cca].getNumberNeighbors() == 1) { moveInMemory = -1; // just in case it was something return 1000000; } if (countries[ccd].getNumberNeighbors() == 1) { moveInMemory = -1; // just in case it was something return 0; } return -1; }/** Check to see if moveInMemory has been set and if so obey it.Return -1 if not set, otherwise return the number that should be returned from moveArmiesIn(). */protected int memoryMoveArmiesInTest(int cca, int ccd) { // Now see if the agent has set the memory if (moveInMemory != -1) { int temp; if (moveInMemory == -2) // then move in half temp = countries[cca].getArmies()/2; else temp = moveInMemory; moveInMemory = -1; return temp; } return -1; }// fortify armies outwards towards the borders of the clusterprotected void fortifyCluster( Country root ) { // We work from our borders back, fortifying closer. // Start out by getting a List of the cluster's borders: CountryIterator borders = new ClusterBorderIterator( root ); List cluster = new ArrayList(); while (borders.hasNext()) { cluster.add(borders.next()); } // So now the cluster borders are in <cluster>. fill it up while fortifying towards the borders. for (int i = 0; i < cluster.size(); i++) { CountryIterator neighbors = new NeighborIterator( (Country)cluster.get(i) ); while ( neighbors.hasNext()) { Country neighbor = neighbors.next(); if ( neighbor.getOwner() == ID && ! cluster.contains(neighbor)) { // Then <neighbor> is part of the cluster. fortify any armies back and add to the List if (neighbor.canGoto( (Country)cluster.get(i))) { // this if statement should only return false when their are single-way borders on the map board.fortifyArmies( neighbor.getMoveableArmies(), neighbor, (Country)cluster.get(i) ); } cluster.add(neighbor); } } } }/** Returns the contcode of the continent that we own with the most countries in it. */protected int getBiggestOwnedCont() { int bestCont = -1; int bestContSize = -1; for(int i = 0; i < numContinents; i++) if (BoardHelper.playerOwnsContinent(ID, i, countries) && BoardHelper.getContinentSize(i,countries) > bestContSize) { bestCont = i; bestContSize = BoardHelper.getContinentSize(i,countries); } return bestCont; }/** Returns the contcode of the continent that we own with the largest positive bonus. */protected int getMostValuablePositiveOwnedCont() { int bestCont = -1; int bestContBonus = -1; for(int i = 0; i < numContinents; i++) if (BoardHelper.playerOwnsContinent(ID, i, countries) && board.getContinentBonus(i) > bestContBonus) { bestCont = i; bestContBonus = board.getContinentBonus(i); } return bestCont; }// This method isn't used for anything, but it is part of the interface.public String message( String message, Object data ) { return null; }// These methods used to be part of Yakool, but they were moved here so EvilPixie could take advantage of themprotected int mustKillPlayer;protected boolean[] mustKillPlayerOwnsCont;protected boolean placeArmiesToKillDominantPlayer(int numberOfArmies) { // calculate some stats about player incomes and armies: int numPlayers = board.getNumberOfPlayers(); int[] incomes = new int[numPlayers]; int[] armies = new int[numPlayers]; int[] ownedCountries = new int[numPlayers]; int totalArmies = 0, totalIncome = 0; for (int i = 0; i < numPlayers; i++) { armies[i] = BoardHelper.getPlayerArmies(i, countries); incomes[i] = board.getPlayerIncome(i); ownedCountries[i] = BoardHelper.getPlayerCountries(i, countries); totalArmies += armies[i]; totalIncome += incomes[i]; } // done getting stats // if an enemy player has half of all armies or half of all income // then he MUST be stopped. int playerToAttack = -1; for (int i = 0; i < numPlayers; i++) { if (i != ID && (armies[i] >= totalArmies*0.5 || incomes[i] >= totalIncome*0.5 || ownedCountries[i] >= numCountries*0.5)) playerToAttack = i; } if (playerToAttack != -1) { mustKillPlayer = playerToAttack; if (placeArmiesToKillPlayer(numberOfArmies, playerToAttack)) return true; // cuz we successfully placed all the armies } return false; }protected boolean placeArmiesToKillPlayer(int numberOfArmies, int playerToAttack) { // try and take out his biggest continents: mustKillPlayerOwnsCont = new boolean[numContinents]; for (int i = 0; i < numContinents; i++) { mustKillPlayerOwnsCont[i] = false; if (BoardHelper.playerOwnsContinent(playerToAttack, i, countries)) mustKillPlayerOwnsCont[i] = true; } // now what? // place armies to take out the easiest continent // find the cost of taking out each one he owns int[] cost = new int[numContinents]; int smallestCost = 1000000; int placer = -1; for (int i = 0; i < numContinents; i++) { cost[i] = -1; if (mustKillPlayerOwnsCont[i]) { int[] path = BoardHelper.cheapestRouteFromOwnerToCont(ID, i, countries); if (path != null) { cost[i] = pathCost(path); if (cost[i] < smallestCost) { smallestCost = cost[i]; placer = path[0]; } } } } if (placer == -1) return false; board.placeArmies(numberOfArmies, placer); return true; }protected void attackToKillPlayer( int player ) {debug("starting attackToKillPlayer -> "+player); // get the bonus values of all the conts they own: int[] ownContValue = new int[numContinents]; for (int i = 0; i < numContinents; i++) { if (mustKillPlayerOwnsCont[i]) ownContValue[i] = board.getContinentBonus(i); else ownContValue[i] = -1; } // now try to kill the continents, starting with the biggest int biggestCont = 0; int biggestContValue = 0; while (biggestCont != -1) { biggestCont = -1; biggestContValue = 0; for (int i = 0; i < numContinents; i++) { if (ownContValue[i] > biggestContValue) { biggestContValue = ownContValue[i]; biggestCont = i; } } if (biggestCont != -1) { // kill it if possible attackToKillContinent(biggestCont); ownContValue[biggestCont] = -1; // so we don't try and attack it again } }debug("ending attackToKillPlayer -> "+player); }protected boolean attackToKillContinent(int cont) {debug("starting attackToKillContinent -> "+cont); CountryIterator armies = new ArmiesIterator( ID, 2, countries ); while (armies.hasNext()) { Country us = armies.next(); int[] path = BoardHelper.easyCostFromCountryToContinent(us.getCode(), cont, countries); if (path != null && pathCost(path) < us.getArmies()) { if (attackAlongPath( path )) { // we succeeded in killing the continent. our job is done. return true; } } } return false; }/** Calculate the sum of all enemy armies in <path> */protected int pathCost( int[] path ) { if (path==null) { System.out.println("SmartAgentBase.pathCost() -> the path was null!"); return 1000000; // return a high number so Yakool doesn't try to follow it } int cost = 0; for (int p = 0; p < path.length; p++) { if (countries[path[p]].getOwner() != ID) cost += countries[path[p]].getArmies(); } return cost; }// returns true if we successfully took over the whole path.// otherwise falseprotected boolean attackAlongPath( int[] path ) { for (int i = 1; i < path.length; i++) { moveInMemory = 1000000; if (countries[path[i-1]].getArmies() == 1 || board.attack(path[i-1], path[i], true) == 13) { // then we lost moveInMemory = -1; return false; } } moveInMemory = -1; return true; }public void debug(Object text) {// System.out.println(board.getPlayerName(ID)+" says: "+text);// System.out.flush(); }} // End of SmartAgentBase class
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -