AI coding: how to simulate attacks

AI discussion, ideas, and SDK help.
Post Reply
User avatar
Bertrand
Reaper Creator
Posts: 568
Joined: Mon Nov 28, 2005 4:35 pm
Location: Montreal

AI coding: how to simulate attacks

Post by Bertrand » Wed Jan 04, 2006 3:19 pm

Reaper is already an efficient killer, but he sometimes misses a kill because of blocking. To get better, Reaper has to do what humans do without thinking: simulate a sequence of moves.

Is there a way to simulate a kill, without actually doing it? I could call the BoardHelper methods with a local copy of the countries array, but when I simulate an attack I need to reset the owner of a country, as well as the number of armies. There are no documented methods to do this.

User avatar
dustin
Lux Creator
Lux Creator
Posts: 10433
Joined: Thu May 15, 2003 2:01 am
Location: Cascadia
Contact:

Post by dustin » Wed Jan 04, 2006 6:22 pm

Take a look at the code in Shaft for a possible example. STarting with the startSweep method.

He does a simulation of an attack, before executing it. It didn't work out so well in practice (since the attacks he looks for are quite limited), but maybe you can use it as an example.

I haven't dealt with the code for awhile now, so I don't remember exactly what it does.

User avatar
Bertrand
Reaper Creator
Posts: 568
Joined: Mon Nov 28, 2005 4:35 pm
Location: Montreal

Post by Bertrand » Wed Jan 04, 2006 7:19 pm

I've looked at shaft's code, but what I really need is more basic:

a method to set armies - Country.setArmies(n)

a method to set the owner - Country.setOwner(player)

Now I realize that those methods must not be used on the real bord - that would be cheating. Is it possible to allow those methods only on a copy of the countries?

User avatar
dustin
Lux Creator
Lux Creator
Posts: 10433
Joined: Thu May 15, 2003 2:01 am
Location: Cascadia
Contact:

Post by dustin » Sat Jan 07, 2006 2:05 am

Add these methods to the Country.java stub class. It does what you need? A nice method could be made to duplicate a set of country objects I suppose...

Code: Select all

/** Create a new country. The passkey object must be suplied to make any changes to the object. So you can only change Country objects that you creats, and not the ones the Board sends you. */
public Country(int newCountryCode, int newContCode, Object passkey)
	{}

/** Sets the continent code of the Country, as long as the passkey object is the same as supplied in the constructor. */
public void setContinentCode(int newContinentCode, Object passkey)
	{}

/** Sets the owner code of the Country, as long as the passkey object is the same as supplied in the constructor. */
public void setOwner( int newOwner, Object passkey)
	{}

/** Sets the number of armies on the Country, as long as the passkey object is the same as supplied in the constructor. */
public void setArmies( int newArmies, Object passkey)
	{}
	
/** Adds one to the army count of the the Country, as long as the passkey object is the same as supplied in the constructor. */
public void addArmy(Object passkey)
	{}


/** Add a connection from this Country object to the destinationCountry object. To be traversable both ways, the connection should be added in reverse as well. */
public void addToAdjoiningList( Country destinationCountry, Object passkey )
	{}

/** Add a 2-way connection between this Country object and the otherCountry object. */	
public void addToAdjoiningListBoth( Country otherCountry, Object passkey )
	{}

/** Set the name of the Country. */		
public void setName(String name, Object passkey)
	{}

User avatar
Bertrand
Reaper Creator
Posts: 568
Joined: Mon Nov 28, 2005 4:35 pm
Location: Montreal

Post by Bertrand » Sat Jan 07, 2006 11:30 am

This is exactly what I was looking for. Excellent!

digit
Lux Newbie
Posts: 5
Joined: Tue May 23, 2006 8:06 pm

Simulating board actions

Post by digit » Tue May 23, 2006 8:19 pm

I am interested in developing an AI that can search and evaluate different actions of players.

Is it possible to clone the Board and Country classes for simulation purposes?

Specifically, I would like to play out the actions of players like trading in cards, attacking, fortifying, etc. without affecting the actual board.

User avatar
dustin
Lux Creator
Lux Creator
Posts: 10433
Joined: Thu May 15, 2003 2:01 am
Location: Cascadia
Contact:

Post by dustin » Tue May 23, 2006 8:36 pm

You can duplicate the countries and perform simulations using them. See the above post with code in it that I posted.

digit
Lux Newbie
Posts: 5
Joined: Tue May 23, 2006 8:06 pm

Income updates and Card actions

Post by digit » Tue May 23, 2006 9:34 pm

I see. So after calling a constructor for Country, the Board class is updated of the new country?

Is the income of players updated properly during simulation? I plan to perform search by playing out actions of multiple players. For example, after my player finishes his turn, I want to simulate the actions of opponents and do actions like cashing in cards, reinforcing (with the proper income such as continents and such), etc.

Also, how do I simulate card actions?
Add these methods to the Country.java stub class. It does what you need? A nice method could be made to duplicate a set of country objects I suppose...
Is it possible to include the ability to duplicate a set of country objects into the API?[/quote]

User avatar
GregM
Luxer
Posts: 252
Joined: Wed Jun 01, 2005 4:33 pm

Post by GregM » Tue May 23, 2006 9:58 pm

digit,

I think I understand what you want to do. I think the best way to go about it would be to create your own subclass of Board (e.g., OffscreenBoard) that you have complete control over. You will need to implement attack(), fortifyArmies(), etc. for this new class. On your agent's turn you can initialize an instance of your Board subclass to reflect the current state of the game and then create some offscreen agents, which you initialize with your Board through setPrefs. Then just go through the agents and call their cardsPhase, placeArmies, attackPhase and fortifyPhase in sequence to simulate a turn. This lets the agents use the API they are coded for but gives you access to the results.

This amounts to rewriting Lux's core game mechanism, which shouldn't be all that difficult, as the rules of the game are known. However, there might be an easier way if it is possible to gain greater access to the Board class.

digit
Lux Newbie
Posts: 5
Joined: Tue May 23, 2006 8:06 pm

cloning

Post by digit » Wed May 24, 2006 8:36 am

GregM,

Yes, you have the right idea of what I plan to do.

If I subclass Board to say, OffscreenBoard, how would I initialize or set the current state of Board to OffscreenBoard? I suppose it would just mean calling the the various Get methods of Board and Country. This works, but it is rather tedious. In addition, it does seem like I would be "reinventing the wheel" as I would have to re-implement some methods of the Board class. As you have stated, it would be easier (much easier) if there is greater access to the Board class.

The ability to clone the Board and Country class would also suffice for the purposes of simulation, and would not require any greater access to the implementation of the Board or Country classes.

Is it possible to add a clone method for Board or Country then?

User avatar
dustin
Lux Creator
Lux Creator
Posts: 10433
Joined: Thu May 15, 2003 2:01 am
Location: Cascadia
Contact:

Post by dustin » Wed May 24, 2006 3:49 pm

It's not really possible to add a simple clone method for Board. The Board class is really just a bridge that calls into one of Lux main engine classes.

The OffscreenBoard idea that Greg brings up seems like a doable answer. I could provide some of the code from the Lux methods so rewriting wouldn't be needed.

User avatar
Bertrand
Reaper Creator
Posts: 568
Joined: Mon Nov 28, 2005 4:35 pm
Location: Montreal

Post by Bertrand » Wed May 24, 2006 7:47 pm

digit,

I have successfully done simulations in Reaper, by making the countries array point to a copy of the real countries, and front-ending the board.attack method.

I have not gone as far as GregM suggests (simulating other players), so I did not have to implement a board.fortifyArmies front-end. My board.attack replacement modifies the simulated board, calls moveArmiesIn() if a simulated win occurs, and calls placeArmies() when a simulated card cash occurs. All the BoardHelper methods work just fine with the simulated countries array. When the simulation is finished, I simply switch back the countries array to the real version.

I found simulations very helpful when planning kills, sweeps and continent takeovers.

I wrote the following method to create a copy of the real countries array (Dustin, this would make a nice addition to the SDK, feel free to use it if you wish…)

Code: Select all

// Create a copy of the countries array, for simulation
public Country[] getCountriesCopy(Country[] countries)
{
    Country[] countriesCopy = new Country[countries.length];
    // pass 1: allocate the countries
    for (int i = 0; i < countries.length; i++)
    {
        countriesCopy[i] = new Country(i, countries[i].getContinent(), null);
        countriesCopy[i].setArmies(countries[i].getArmies(), null);
        countriesCopy[i].setName(countries[i].getName(), null);
        countriesCopy[i].setOwner(countries[i].getOwner(), null);
    }
    // pass 2: create the AdjoiningLists
    for (int i = 0; i < countries.length; i++)
    {
        Country[] around = countries[i].getAdjoiningList();
        for (int j = 0; j < around.length; j++)
            countriesCopy[i].addToAdjoiningList(countriesCopy[around[j].getCode()], null);
    }
    return countriesCopy;
}   
Anyway, welcome to the wonderful world of AI coding!

digit
Lux Newbie
Posts: 5
Joined: Tue May 23, 2006 8:06 pm

Post by digit » Sun May 28, 2006 9:16 am

dustin wrote:The OffscreenBoard idea that Greg brings up seems like a doable answer. I could provide some of the code from the Lux methods so rewriting wouldn't be needed.
Yes, that would be good. Simulating attacks and troop movement has been simple. But I would appreciate calls/methods that allow the calculations of troop income, and card actions.

digit
Lux Newbie
Posts: 5
Joined: Tue May 23, 2006 8:06 pm

Post by digit » Tue Jun 06, 2006 3:47 am

Thanks everyone for the help and advice! Much appreciated.

I am currently coding the attack simulations and evaluation function. I am going to add in some card simulations and was wondering if is it possible to add a method to the API

getCardSetValueAfterNCashes( int N )

public int getCardSetValueAfterNCashes( int N )
Returns the number of armies given by the card cash after N > 0 more cashes.

Thanks again!

User avatar
dustin
Lux Creator
Lux Creator
Posts: 10433
Joined: Thu May 15, 2003 2:01 am
Location: Cascadia
Contact:

Post by dustin » Tue Jun 06, 2006 5:38 am

I'll try to add such a function in the next Lux update (might not be for a little while though).
digit wrote:I would appreciate calls/methods that allow the calculations of troop income, and card actions.
Here's some code for calculating incomes for all players:

Code: Select all

// Count the number of countries each player owns:
int[] owned = new int[numPlayers];
for (int p = 0; p < numPlayers; p++)
	owned[p] = 0;

int owner;
for (int i = 0; i < countries.length; i++)
	{
	owner = countries[i].getOwner();
	if (owner != -1)
		{
		owned[owner]++;
		}
	}

// Now get an income for each player
int[] incomes = new int[numPlayers];
for (int p = 0; p < incomes.length; p++)
	{
	if (owned[p] < 1)
		incomes[p] = 0;
	else
		{
		// Divide by three (ditching any fraction):
		incomes[p] = owned[p]/3;

		// But there's a 3-army minimum from countries owned:
		incomes[p] = Math.max( incomes[p], 3);

		// Now we should see if this guy owns any continents:
		for (int i = 0; i < board.getNumberOfContinents(); i++)
			{
			if ( BoardHelper.playerOwnsContinent( p, i, countries ) )
				{
				incomes[p] += board.getContinentBonus(i);
				}
			}

		// there can be negative continent values. give a minimum of 3 income in all cases
		incomes[p] = Math.max( incomes[p], 3);
		}
	}

MrEnder
Lux Newbie
Posts: 6
Joined: Thu Feb 10, 2011 4:26 pm

Post by MrEnder » Wed Mar 09, 2011 3:00 am

Did these issues ever get resolved? I am actually interested in something similar now!

Post Reply