⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 smartagentbase.java

📁 good project for programmer,,
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
package com.sillysoft.lux.agent;import com.sillysoft.lux.*;import com.sillysoft.lux.util.*;////  SmartAgentBase.java//	Lux////  Copyright (c) 2002-2007 Sillysoft Games. //	http://sillysoft.net//	lux@sillysoft.net////	This source code is licensed free for non-profit purposes. //	For other uses please contact lux@sillysoft.net//////  An abstract agent class containing a variety of utility methods for//	subclasses to use//import java.util.Random;import java.util.List;import java.util.ArrayList;public abstract class SmartAgentBase implements LuxAgent {// This agent's ownerCode:protected int ID;// We store some refs to commonly used board objectsprotected Board board;protected Country[] countries;protected int numCountries;protected int numContinents;// Sometimes in the attack phase we know if we want to move in armies or not.// Store the value in this var. It will be used as long as it is not equal to -1.protected int moveInMemory;// Sometimes it is useful to remember which continent we are spending our efforts on.// When not in use set to -1.protected int goalCont;// Since all subclasses need a random number generator (for you-won strings) we keep one. protected Random rand;public SmartAgentBase()	{	rand = new Random();	goalCont = -1;	moveInMemory = -1;	}public void setPrefs( int newID, Board theboard )	{	ID = newID;	board = theboard;	countries = board.getCountries();	numCountries = countries.length;	numContinents = board.getNumberOfContinents();	}// SmartAgentBase leaves it up to subclasses to implement the following methods:public abstract String name();public abstract int pickCountry();public abstract void placeArmies( int numberOfArmies );public abstract void attackPhase();public abstract int moveArmiesIn( int cca, int ccd);public abstract void fortifyPhase();public abstract String youWon();// I have yet to develope any card-smarts. The game-world will automatically cash in our best set if we return from this method and still have five or more cards.public void cardsPhase( Card[] cards )	{	mustKillPlayer = -1;	// just in case it was set last turn.	// xxagentxx SmartAgentBase cards phase	}public void cashCardsIfPossible(Card[] cards)	{	if (Card.containsASet(cards))		{		Card[] set = Card.getBestSet( cards, ID, countries );		board.cashCards(set[0], set[1], set[2]);		}	}// This method sets the class-variable goalCont to the continent with the least number of borders.// First all totally non-occupied conts will be searched, then partially ocupied ones.// Conts worth 0 or less are not considered.protected void setGoalToLeastBordersCont()	{	goalCont = -1;	int[] borderSizes = new int[numContinents];	int smallBorders = 1000000;	// the size of the smallest borders cont	// first loop through and find the smallest totally empty cont	for (int i = 0; i < numContinents; i++)		{		if (board.getContinentBonus(i) > 0)			{			borderSizes[i] = BoardHelper.getContinentSize(i, countries);			if (borderSizes[i] < smallBorders && BoardHelper.playerOwnsContinent(-1, i, countries))				{				smallBorders = borderSizes[i];				goalCont = i;				}			}		}	// if there were no empty conts then next we would like the cont with the least # of borders that is partially empty	if (goalCont == -1)		{		smallBorders = 1000000;		for (int i = 0; i < numContinents; i++)			{			if (board.getContinentBonus(i) > 0)				{				if (borderSizes[i] < smallBorders && BoardHelper.playerOwnsContinentCountry(-1, i, countries))					{					smallBorders = borderSizes[i];					goalCont = i;					}				}			}		}	// There is the possibility that no cont will be chosen, if all the continents with	// open countries are worth 0 or less income	}// If goalCont is set then return a country-code of the country we should choose in that cont. If goalCont is unset then set it to the smallest empty/open cont.protected int pickCountryInSmallContinent()	{	if (goalCont == -1 || ! BoardHelper.playerOwnsContinentCountry(-1, goalCont, countries))	// then we don't have a target cont yet		{		goalCont = -1;		goalCont = BoardHelper.getSmallestPositiveEmptyCont(countries, board);		if (goalCont == -1) // oops, there are no unowned conts			goalCont = BoardHelper.getSmallestPositiveOpenCont(countries, board);		}	// if we are here then we DO have a target cont.	return pickCountryInContinent( goalCont );	}// return an unowned country-code in <continent>, preferably near others we own// If there are no countries left in the given continent then pick a country touching us.protected int pickCountryInContinent(int continent)	{	CountryIterator continentIter = new ContinentIterator(continent, countries);	while (continentIter.hasNext())		{		Country c = continentIter.next();		if (c.getOwner() == -1 && c.getNumberPlayerNeighbors(ID) > 0)			return c.getCode();		}	// we neighbor none of them, so pick the open country with the fewest neighbors	continentIter = new ContinentIterator(continent, countries);	int bestCode = -1;	int fewestNeib = 1000000;	while (continentIter.hasNext())		{		Country c = continentIter.next();		if (c.getOwner() == -1 && c.getNumberNeighbors() < fewestNeib)			{			bestCode = c.getCode();			fewestNeib = c.getNumberNeighbors();			}		}	if (bestCode == -1)		{		// There are no unowned countries in this continent.		return pickCountryTouchingUs();		}	return bestCode;	}/** Pick the open country that touches us the most. */protected int pickCountryTouchingUs()	{	int maxTouches = -1;	int maxCode = -1;	// the country code of the best place so far	// Loop through all the unowned countries	CountryIterator ci = new PlayerIterator(-1, countries);	while (ci.hasNext())		{		Country open = ci.next();		if (open.getNumberPlayerNeighbors(ID) > maxTouches && board.getContinentBonus(open.getContinent()) >= 0)			{			maxTouches = open.getNumberPlayerNeighbors(ID);			maxCode = open.getCode();			}		}			if (maxTouches < 1)		{		// Then no open countries touch any of our countries directly.		// Do a search outwards to find the closest unowned country to us.				List ourBorderCountries = new ArrayList();		ci = new PlayerIterator(ID, countries);		while (ci.hasNext())			{			Country open = ci.next();			if (open.getNumberNotPlayerNeighbors(ID) > 0)				{				ourBorderCountries.add(open);				}			}		return BoardHelper.closestCountryWithOwner(ourBorderCountries, -1, countries);				}	return maxCode;	}// returns the country-code of the nearest unowned country to the cluster starting at <root>// NOTE, this method is inferior to pickCountryTouchingUs().protected int pickCountryNearCluster( Country root )	{	// do a breadth first search outwards starting with this cluster's borders	// return as soon as we find an unowned country	CountryIterator borders = new ClusterBorderIterator( root );	List cluster = new ArrayList();	while (borders.hasNext())		{		cluster.add(borders.next());		}	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() == -1 )				return neighbor.getCode();			else if( !cluster.contains(neighbor))				{				// Then we add it to the List. in time its neighbors will get expanded				cluster.add(neighbor);				}			}		}	// we should never get here.	System.out.println("ERROR in smartbase.pickCountryNearCluster() 65465477");	return -1;	}public void placeInitialArmies( int numberOfArmies )	{	placeArmies( numberOfArmies );	}// a simplistic method to get the easiest continent for us to take overprotected int getEasiestContToTake()	{	// For each continent we calculate the ratio of (our armies):(enemy armies)	// The biggest one wins.	float easiestContRatio = -1;	int easiestCont = -1;	for (int cont = 0; cont < numContinents; cont++) {		int enemies = BoardHelper.getEnemyArmiesInContinent( ID, cont, countries );		int ours = BoardHelper.getPlayerArmiesInContinent( ID, cont, countries );		float newratio = (float)ours/(float)enemies;		if (newratio > easiestContRatio && board.getContinentBonus(cont) > 0) {			easiestCont = cont;			easiestContRatio = newratio;			}		}	return easiestCont;	}// Do we own all of the continents that this country borders?// NOTE: This will not check countries that are in the same continent as 'center'protected boolean weOwnContsArround(Country center)	{	int cont = center.getContinent();	CountryIterator n = new NeighborIterator(center);	while (n.hasNext())		{		Country neib = n.next();		if (neib.getContinent() != cont && ! BoardHelper.playerOwnsContinent(ID, neib.getContinent(), countries))			{			return false;			}		}	return true;	}// should be called within placeArmies()// will place them at the start of the cheapest path to <wantCont>protected void placeArmiesToTakeCont( int numberOfArmies, int wantCont )	{	if (wantCont == -1)		{ // we weren't given a continent index. maybe there is only 1 continent. fallback to another method		placeArmiesOnClusterBorder( numberOfArmies, BoardHelper.getPlayersBiggestArmy(ID, countries) );		return;		}			// we want to place our armies strategically, in order to conquer <wantCont>	if (BoardHelper.playerOwnsContinent( ID, wantCont, countries))		{		// then we already own it, place on the weakest borders that we don't envelope		int[] borders = BoardHelper.getContinentBorders(wantCont, countries);		int placed = 0;		while ( placed < numberOfArmies )			{			int leastArmies = 1000000, leastID = -1;			for (int i = 0; i < borders.length; i++)				{				if (countries[borders[i]].getArmies() < leastArmies && ! weOwnContsArround(countries[borders[i]]))					{					leastArmies = countries[borders[i]].getArmies();					leastID = borders[i];					}				}			if (leastID == -1)				{	// this can happen when the entire map is one continent. thus it has no borders				leastID = borders[rand.nextInt(borders.length)];				}			board.placeArmies(1, leastID);			placed++;			}		return;		}	// if we own any countries in <wantCont>, then place the armies on the one with the most enemies inside the continent.	CountryIterator want = new ContinentIterator(wantCont, countries);	Country bestPlace = null;	int mostEnemies = 0;	while (want.hasNext())		{		Country us = want.next();		if (us.getOwner() == ID)			{			// count its enemy neighbors inside wantCont:			int enemyNeighbors = 0;			CountryIterator neighbors = new NeighborIterator(us);			while (neighbors.hasNext())				{				Country neighbor = neighbors.next();				if (neighbor.getOwner() != ID && neighbor.getContinent() == wantCont)					enemyNeighbors++;				}			if (enemyNeighbors > mostEnemies)				{				mostEnemies = enemyNeighbors;				bestPlace = us;				}			}		}	// if we found anyplace at all, do it	if (bestPlace != null)		{		board.placeArmies(numberOfArmies, bestPlace);		return;		}	// If we got here then we own zero countries inside <wantCont>	// we place our armies in the country we own with the cheapest route to <wantCont>	int[] route = BoardHelper.cheapestRouteFromOwnerToCont( ID, wantCont, countries );	debug("BoardHelper.cheapestRouteFromOwnerToCont("+ID+", "+wantCont+") = "+new CountryRoute(route, countries));	int placer = route[0];	board.placeArmies(numberOfArmies, placer);	}// this method places armies one at a time on the weakest border surrounding <root>// it will call itself untill all armies have been placed.protected void placeArmiesOnClusterBorder( int numberOfArmies, Country root )	{	if (root==null)		System.out.println("SmartBase.placeArmiesOnClusterBorder() -> the cluster root==null. 654213465");	CountryIterator borders = new ClusterBorderIterator( root );	// Find the weakest of the cluster borders:	Country weakest = null;	int weakestArmies = 1000000;	while (borders.hasNext())		{		Country border = borders.next();		if (border.getArmies() < weakestArmies)			{			weakestArmies = border.getArmies();			weakest = border;			}		}	if (weakest == null)		System.out.println("SmartBase.placeArmiesOnClusterBorder() -> weakest==null. 7404524");			int numberToPlace = Math.min(numberOfArmies, Math.max(1, numberOfArmies/100));		board.placeArmies( numberToPlace, weakest );	if (numberOfArmies > numberToPlace)		placeArmiesOnClusterBorder( numberOfArmies-numberToPlace, root );	}	/***********	The actual attack methods are below.	Different skill level of agents can use different combinations of them.	************/// If any of our border countries around <root>'s cluster have only one enemy then attack it // (if they have some chance of winning)// return true if we won at least one attack protected boolean attackEasyExpand(Country root)	{	// get the borders of the cluster centered on <root>:	CountryIterator borders = new ClusterBorderIterator( root );	boolean wonAttack = false;	while (borders.hasNext()) {		Country border = borders.next();		CountryIterator neighbors = new NeighborIterator(border);		int enemies = 0;		Country enemy = null;		while (neighbors.hasNext()) {			Country neighbor = neighbors.next();			if (neighbor.getOwner() != ID) {				enemies++;				enemy = neighbor;				}			}		if (enemies == 1 && border.getArmies() > enemy.getArmies()) {			// then we will attack that one country and move everything in, thus expanding our borders.			moveInMemory = 1000000;			if (board.attack( border, enemy, true) > 0)				wonAttack = true;			moveInMemory = -1;			}		}	return wonAttack;	}// Attack any countries next to <root>'s cluster that has zero not-owned-by-us neighbors// This kills little islands to fill out our territory.// return true if we won at least one attack protected boolean attackFillOut(Country root )	{	boolean wonAttack = false;	CountryIterator borders = new ClusterBorderIterator( root );	while (borders.hasNext()) {		Country border = borders.next();		CountryIterator neighbors = new NeighborIterator(border);		while (neighbors.hasNext()) {			Country neighbor = neighbors.next();			if (neighbor.getOwner() != ID && neighbor.getNumberNotPlayerNeighbors(ID) == 0) {				// attack it				if (neighbor.getArmies() < border.getArmies()) {					moveInMemory = 0; // since we are attacking from a border we remember to move zero armies in					if (board.attack( border, neighbor, true) == 7)						wonAttack = true;					moveInMemory = -1;					}				}			}		}	return wonAttack;	}// If we can, we consolidate our borders, by attacking from two or more borderCountries into a common enemy// return true if we won at least one attackprotected boolean attackConsolidate( Country root)	{	CountryIterator borders = new ClusterBorderIterator( root );	boolean wonAttack = false;	while (borders.hasNext())		{		Country border = borders.next();		CountryIterator neighbors = new NeighborIterator(border);		int enemies = 0;		Country enemy = null;		while (neighbors.hasNext())			{			Country neighbor = neighbors.next();			if (neighbor.getOwner() != ID)				{				enemies++;				enemy = neighbor;				}			}		if (enemies == 1 && enemy.getNumberPlayerNeighbors(ID) > 1)			{			// then this enemy could be a good point to consolidate.			// look for other border countries to consolidate into enemy...			List ours = new ArrayList(); // this will store all the countries that will participate in the attack.			CountryIterator possibles = new NeighborIterator(enemy);			while (possibles.hasNext() )

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -