I'm coding an abstract strategy game with C# & XNA. As for the AI, I'm currently using Negascout and a depth of 5. The following is the description of the game:
The game consists of a board of 6x7 hexagonal locations, 42 hexagonal tiles, and 6 pieces (1 king & 5 pawns) for each player (max 2 players).
During the first phase of the game, the players alternately place a random tile on an empty location of the board. Each tile can have a maximum of 6 arrows pointing at the edges. Some arrows can be double-pointed. The arrows mean the direction/s of movement from that tile. A double-pointed arrow makes a piece move/jump 2 locations if there's a valid location. The players are not allowed to place tiles in their opponent's row if there are still empty locations left on the board.
Once this phase is complete, the next player in turn places his king on any one of the 6 tiles of the row nearest to him. Next, the movement of the pieces commences. Pieces are moved according to the arrows on the tiles. The game is won by capturing or blocking the king.
Ok, so now to my move generation function.
Tile placement stage
a) Place a tile on the nearest row. The tile is rotated to find the optimal rotation.
b) Once the nearest row is full, place a tile on an empty location that is surrounded by locations on all sides (ie no edge of board). Rotate the tile to find the optimal rotation.
c) If no locations are found, add all remaining empty locations, trying to find the optimal rotation.
King placement stage
a) Locate the location with the best tile and place the king there.
b) Place the remaining pawns on the remaining empty locations on the row.
Movement stage
a) If king is attacked, try to attack the attacking piece if that piece is not defended.
b) Add moves for all player's pieces that are being attacked.
c) Add all opponent pieces that the player can attack.
d) Add all locations player can move to.
Now to the evaluation function.
Tile placement stage
score = No. of tiles current player placed so far + current player's tiles on the nearest row - no. of tiles opponent placed so far - opponent's tiles on the furthest row (nearest to the opponent).
King placement stage
score = current player's tiles on the nearest row - opponent's tiles on the furthest row (nearest to the opponent).
Movement stage
score = current player's pieces' value - opponent's pieces' value.
The weighting of the tiles is 100 for every valid location an arrow points to. The weighting of the pieces is as follows:
piece value = piece type (king = 10000, pawn = 1000) + mobility + defended - attacked - enprise - blocked
where:
mobilty = no. of locations node can move to (free or occupied by the opponent) * 1000
defended = no. of current player pieces surrounding this piece that can actually move to this location * 1000
attacked = no. of opponent pieces surrounding this piece that can actually move to this location * 1000
blocked = (king = -10000, pawn = -1000) piece cannot move because all arrows point to invalid locations and the piece has no chance of moving again in this game.
Quite long, but here come my problems:
When placing tiles, the AI sometimes places a tile using the wrong rotation (ie. places a tile in location where the arrows point to no valid locations). Sometimes this occurs in his 'home' row.
When moving pieces, the AI is ignoring king safety. Moves mostly the king and is captured in about 4-6 moves.
Anybody, especially with chess AI experience, has ideas and suggestions on how to improve my AI, in particular my move generation and evaluation functions?
Thanks
Ivan
btw... If anyone is interested in trying out the mail, just let me know and I'll upload a setup on my website.
Quite long, but here come my problems:
Quite long, indeed.
When placing tiles, the AI sometimes places a tile using the wrong rotation (ie. places a tile in location where the arrows point to no valid locations). Sometimes this occurs in his 'home' row.
In other words, you have a bug in your code. There's no way to answer this question, even with all this extensive preamble. This question should be in a separate, concisely-phrased question that includes a copy of the relevant code.
When moving pieces, the AI is ignoring king safety. Moves mostly the king and is captured in about 4-6 moves.
Same as above. This question can't be answered based on even the extensive preamble you've written.
My advice to you is to be more concise with your questions, post only the details relevant to the problem, and not to combine multiple questions into a single post.
Anybody, especially with chess AI experience, has ideas and suggestions on how to improve my AI, in particular my move generation and evaluation functions?
This is an overly vague question that would normally get closed. If you want some advice about your code, you would have to provide that code in order for anyone to give you a helpful answer that goes beyond blind speculation!
Related
I'm trying to build a rubik's cube solver in C using the Thistlethwaite algorithm.
I'm storing a cube as an array of 6 uint64_t integers (Faces).
Each of this faces stores 8 colors as one byte.
This structure let's me easily rotate faces using bit manipulation but I wonder if I should use something else that would be more appropriate for the Thistlethwaite algorithm.
The issue I'm having is checking if a cube is contained in the sub group G1 <L, R, F, B, U2,D2>
From what I understand, a cube that has correctly orientated edges is contained in this subgroup.
(see https://www.jaapsch.net/puzzles/thistle.htm)
The paper at the end of the page clearly indicates how to check if an edge is good or not but I could not find a way to implement it.
The question I have is: How to check in code if an edge is correctly oriented given a scrambled cube ?
According to the article, page 1:
Getting into G1
An edge piece is BAD if in taking it home an odd
number of quarter-turns of U and D faces is needed; otherwise it is GOOD
A different way of putting this: if you can manage to bring an edge home without ever using a U or D turn (so only turning the L, F, R and B faces), then an edge is good, otherwise it is bad.
So let's say you have a scrambled cube and are looking at one particular edge piece. Identify the position where it should end up (obviously based on the centre pieces). Let's say that one of the two colours of this edge is red. Then identify where the current place of that red face is in the following image:
Do the same for the place where that red side should end up.
If both places have the same colour (yellow or blue) in the above image, then the edge is good. If they have different colours in the above image, then the edge is bad.
You can easily see that if you had taken the other colour side of the edge in question (the not-red one), you would arrive at the same conclusion with this method.
Up to you to translate this to your data structure.
I'm trying to build an AI agent for a specific zero-sum board game using alpha-beta pruning. The program will be depth limited because of certain time constraints and hence I need a good evaluation function to use. The game is as follows
It is a two-player game in which each player tries to maximize his/her
share from a batch of candies randomly placed in a box. The box is
divided into cells and each cell is either empty or filled with one
candy of a specific type. At the beginning of each game, all cells are
filled with candies. Players play in turn and can pick a cell of the
box in their own turn and claim all candies of the same type, in all
cells that are connected to the selected cell through horizontal and
vertical paths. For each selection or move the agent is rewarded a
numeric value which is the square of the number of candies claimed in
that move. Once an agent picks the candies from the cells, their empty
place will be filled with other candies on top of them(which fall down
due to gravity), if any. In this game, no candy is added during
gameplay. Hence, players play until all candies have been claimed.
Given the above gameplay, can someone help me get a good eval function for the game ? One thought that comes to my mind is to get the maximum number of fruits that can be claimed from the given board state as a heuristic/eval function. However, this is not a great eval function. What could be better ?
I am developing a snake game for iOS:
https://github.com/ScottBouloutian/Snake
My goal is to have the AI complete the game of snake optimally (have the snake fill the board).
I am using IDA* to find a path from a snake's current location to the food. This works. However, the algorithm doesn't take into account the fact that it may need to get more food in the future. As a result, sometimes it tends to box itself in.
i.e. The snake's goal at any given time is to find the food, whereas it's goal should be to fill the board (finding food along the way).
How can I add to or modify this approach to make the AI win the game of snake? Is there a better approach I should use instead? I'm just trying to come up with some ideas. Thanks!
If a board is a static rectangle (not torus - so no crossing though the borders) then the only optimal strategy is to find a set of longest closed paths through the board, such that each point in the board is in at least one path.
If a board is empty (there are no obstacles) then there exists an "ultimate" path in the form
16|.1|.6|.7
15|.2|.5|.8
14|.3|.4|.9
13|12|11|10
which goes through all tiles, snake following this pattern will eventually eat all food, and fill the whole board
If there are some obstacles, then such path does not have to exist, then you should find set of such longest paths, and switch between them, when food appears in the unreachable spot of a current path.
For example
#######
#.....#
#.#.#.#
#.....#
#######
Here you have two paths you have to consider, one-longest, going around the whole board, but missing the central spot, and one small loop going through it. As long as food does not appear in the center, you should use the outer loop. Hopefully, if food appears in the center when you fill all the remaining blocks - you will "win". If it appears there sooner - you have to eat it (switch to the other loop) and depending on your current length - you will get back to the best loop, or hit your tail and "lose". In each case, your score will be the best possible to achieve on the board with this locations of foods.
Non A* based approach will find the optimum, this is completely different problem, you should look for the longest closed path, not shortest.
I have an assigment to do a tron game with AI. Me an my team almost made it but we're trying to find a good heuristic. We taught about Voronoi, but it's kinda slow :
for yloop = 0 to height-1
for xloop = 0 to width-1
// Generate maximal value
closest_distance = width * height
for point = 0 to number_of_points-1
// calls function to calc distance
point_distance = distance(point, xloop, yloop)
if point_distance < closest_distance
closest_point = point
end if
next
// place result in array of point types
points[xloop, yloop] = point
next
next
We have 5 seconds to make a move and this algorithm doesn`t sound too good ! I don't need code ... we just need an ideea !
Thank you !
Later edit : Should we try Delaunay Triangulations ?
Have a look at the postmortem of Google's AI Challenge about this.
well i am considering redesigning my old Wurmeler game (AI including) so i stumped on your question while searching for new ideas so here is my insight from my old AI
Wurmeler is similar to tron but much slover and worms turn smoothly
game space is 2D bitmap
each AI is very simple ... stupid,...
but navigate better than me
unless they are closed by other player
or crush into local min/max
but still they are fun
OK now the AI algorithm in every decision move:
create few rays from Worm
one in movement direction
few turned to the left by some angle (5 degree step is fine)
few turned to the right
evaluate the ray length
from worm until it hit border
or another worm path curve
use the max rule to change heading
This old AI maintain only navigation but I want to implement more (this is not yet done):
divide map to square sections
each section will have the average density of already filled space
so if possible AI will choose less filled area
add strategies
navigate (already done)
flee (go away from near player if too close and behind)
attack (if on relative parallel course and too close and in the front)
may be conversion from raster to vector
should speed up the ray traceing and colision detection
but with growing length may be slower ... have to try it and see
possible use of field algorithms
Ok so, I'm making a 2d dungeon crawler and I want to randomize a map for it. Right now it's look like I'm going to use a Random Walk algoritm for the path, combined with a Perlin Noise for different the underworld enviroments (currently only 1, as I'm using my own shitty looking tile set consisting of only 1 rook image and 1 grass image, but whatever :D)
So in figuring out how random walks work, it looks like I'm supposed to do something along the lines of this:
*create two-dimensional array sized after the map.
*pick random start postion and end postiont (I chose to put these on opposite sides of the map, randomly distributed across its side.
*follow these steps until you hit your finish point:
*pick a direction to 'walk' at random (only up, down, left, right because you otherwise I'm left with diagonal passes which the player can't walk through)
*'walk' that direction for a random amount of steps (I randomize amount of steps first then walk one by one for bound checking later, rather than just drawing a line).
*Everytime you 'walk' on a tile, turn that tile to 1 from originally 0.
*repeat above steps until you hit your finish point.
This leaves me with too much open ground, and too much closed ground. What I'm looking for is a path covered with rooms, sort of, but I want to control how big the 'rooms' become. I don't want 'rooms' to get too big, which some become. So I want the feeling of being in an enclosed space, but also I want to use as much of the map grid as possible.
Is a random walk not suited for this? I was thinking about making every step have a certain width to it, maybe that could work.
Or maybe I'm just implementing it wrong! I'm not a math genious sadly ;P