Commit f74c2985 authored by Sam Moore's avatar Sam Moore

[RULE CHANGE] *Changed rule for Bombs*, tweaking vixen agent

Previously, contact with a Bomb destroyed the Bomb even if the attacker was not a miner.
Now, the only way to destroy a Bomb (ever) is to attack it with a miner.

Yes, this means that if the enemy Flag is surrounded by Bombs and and AI has lost all its miners, it is impossible to win.

This reflects the rules of the original game. My version is now identical to the original game.
My original rule was intended to decrease the emphasis placed on Bombs and Miners.
Having played a few games, I think the traditional Bomb rule is more interesting, even if it makes things harder for the AI.

If there are any problems with this change, please email [email protected]
I will be happy to revert to the previous rules if there is demand. This also goes for the change to equivelant ranks combat (earlier commit today).

Updated vixen agent's scoring to take into account the change.
Yet to update asmodeus's scoring.

The AI's seem to have a much harder time now that they have to take out Bombs
Games often result in draws, because the Miners are easy targets and get killed whilst seeking out Bombs.
The AI should probably defend certain pieces with stronger piece combinations nearby. But this is all getting rather complex for a "sample" :P

TODO: Implement victory condition when opponent has no mobile pieces
	(Currently play continues until the player with mobile pieces ends up attacking Bombs because it has nothing else to do
		at which point the game is a draw because neither player has mobile pieces)
parent e063c97d
......@@ -62,6 +62,7 @@ class Piece:
self.y = y
self.lastMoved = -1
self.beenRevealed = False
self.positions = [(x, y)]
def mobile(self):
return self.rank != 'F' and self.rank != 'B' and self.rank != '?' and self.rank != '+'
......@@ -247,8 +248,10 @@ class BasicAI:
defender = self.board[p[0]][p[1]]
#Update attacker's position (Don't overwrite the board yet though)
attacker.x = p[0]
attacker.y = p[1]
attacker.positions.insert(0, (attacker.x, attacker.y))
#Determine ranks of pieces if supplied
......
......@@ -26,9 +26,10 @@ class Vixen(BasicAI):
BasicAI.__init__(self)
self.bombScores = {'1' : -0.9 , '2' : -0.8 , '3' : -0.5 , '4' : 0.1, '5' : 0.1, '6' : 0.3, '7' : 0.7, '8' : 1 , '9' : 0.6, 's' : 0}
self.suicideScores = {'1' : -0.5 , '2' : -0.4 , '3' : -0.35, '4' : -0.25, '5' : -0.2, '6' : 0.0, '7' : 0.1, '8' : -0.4 , '9' : 0.0, 's' : -0.4}
self.killScores = {'1' : 1.0 , '2' : 0.9 , '3' : 0.9 , '4' : 0.8, '5' : 0.8, '6' : 0.8, '7' : 0.8, '8' : 0.9 , '9' : 0.7, 's' : 0.9}
#self.bombScores = {'1' : -0.9 , '2' : -0.8 , '3' : -0.5 , '4' : 0.1, '5' : 0.1, '6' : 0.3, '7' : 0.7, '8' : 1 , '9' : 0.6, 's' : 0}
#self.bombScores = {'1' : -0.9 , '2' : -0.8 , '3' : -0.5 , '4' : -0.5, '5' : -0.4, '6' : -0.5, '7' : -0.2, '8' : 1.0 , '9' : -0.1, 's' : -0.2}
self.suicideScores = {'1' : -0.5 , '2' : -0.4 , '3' : -0.35, '4' : -0.25, '5' : -0.2, '6' : 0.0, '7' : 0.1, '8' : -1.0 , '9' : 0.0, 's' : -0.4}
self.killScores = {'1' : 1.0 , '2' : 0.9 , '3' : 0.9 , '4' : 0.8, '5' : 0.8, '6' : 0.8, '7' : 0.8, '8' : 0.9 , '9' : 0.7, 's' : 1.0}
self.riskScores = {'1' : 0.0, '2' : 0.1, '3' : 0.2, '4': 0.4, '5': 0.6, '6': 0.7, '7':0.8, '8': 0.0, '9' : 1.0, 's' : 0.1}
......@@ -53,11 +54,11 @@ class Vixen(BasicAI):
path = PathFinder().pathFind((unit.x, unit.y), (target.x, target.y), self.board)
if path == False or len(path) == 0:
continue
moveList.append({"unit":unit, "direction":path[0], "score":self.CalculateScore(unit, target, path)})
#scores[path[0]] += self.CalculateScore(unit, target, path)
#moveList.append({"unit":unit, "direction":path[0], "score":self.CalculateScore(unit, target, path)})
scores[path[0]] += self.CalculateScore(unit, target, path)
#bestScore = sorted(scores.items(), key = lambda e : e[1], reverse=True)[0]
#moveList.append({"unit":unit, "direction":bestScore[0], "score":bestScore[1]})
bestScore = sorted(scores.items(), key = lambda e : e[1], reverse=True)[0]
moveList.append({"unit":unit, "direction":bestScore[0], "score":bestScore[1]})
if len(moveList) == 0:
......@@ -65,7 +66,7 @@ class Vixen(BasicAI):
return True
moveList.sort(key = lambda e : e["score"], reverse=True)
sys.stderr.write("vixen - best move: " + str(moveList[0]["unit"].x) + " " + str(moveList[0]["unit"].y) + " " + moveList[0]["direction"] + " [ score = " + str(moveList[0]["score"]) + " ]\n")
#sys.stderr.write("vixen - best move: " + str(moveList[0]["unit"].x) + " " + str(moveList[0]["unit"].y) + " " + moveList[0]["direction"] + " [ score = " + str(moveList[0]["score"]) + " ]\n")
if moveList[0]["score"] == 0:
print "NO_MOVE"
return True
......@@ -84,6 +85,9 @@ class Vixen(BasicAI):
def CalculateScore(self, attacker, defender, path):
p = move(attacker.x, attacker.y, path[0], 1)
total = 0.0
count = 0.0
for rank in ranks:
......@@ -99,6 +103,9 @@ class Vixen(BasicAI):
total = total * self.tailFactor(len(path))
#HACK - Prevent "oscillating" by decreasing the value of backtracks
if len(path) > 1 and len(attacker.positions) > 1 and attacker.positions[1][0] == p[0] and attacker.positions[1][1] == p[1]:
total = total / 100
#sys.stderr.write("Total score for " + str(attacker) + " vs. " + str(defender) + " is " + str(total) + "\n")
return total
......@@ -122,7 +129,10 @@ class Vixen(BasicAI):
return self.killScores[defenderRank]
def bombScore(self, attackerRank):
return self.bombScores[attackerRank]
if attackerRank == '8':
return 1.0
else:
return 0.0
def suicideScore(self, attackerRank):
return self.suicideScores[attackerRank]
......@@ -152,12 +162,7 @@ class Vixen(BasicAI):
return 0.0
return float(float(self.hiddenEnemies[targetRank]) / float(total))
def InterpretResult(self):
""" Over-ride the basic AI interpret result so we can update probabilities """
if BasicAI.InterpretResult(self) == False:
return False
return True
......
......@@ -94,11 +94,11 @@ GAME RULES
5 Captain 5 4
6 Lieutenant 6 4
7 Sergeant 7 4
8 Miner 8 5 Destroys Bombs without being killed
8 Miner 8 5 Destroys Bombs
9 Scout 9 8 May move more through multiple empty squares
s Spy 10 1 If the Spy attacks the Marshal, the Marshal dies
B Bomb NA 6 Immobile. If any piece (except a Miner) encounters an enemy Bomb, both pieces are destroyed
F Flag NA 1 Immobile. If any piece encounters the enemy Flag, the controlling player wins.
B Bomb NA 6 Immobile. If any piece (except a Miner) attacks an enemy Bomb, that piece is destroyed.
F Flag NA 1 Immobile. If any piece attacks the enemy Flag, the controlling player wins.
Additional pieces, not controlled by the player:
Piece Name Number Notes
......@@ -115,6 +115,9 @@ GAME RULES
Each player's pieces are hidden from the other player. When two pieces encounter each other, the ranks will be revealed.
The objective is to destroy all Enemy Pieces (#) or capture the Enemy Flag (also #).
Since 20/12 Bombs reflect the traditional rules; they are only destroyed by Miners.
In previous versions contact of an attacker other than a Miner with a Bomb destroyed the Bomb as well as the attacking piece.
PROTOCOL
......@@ -216,8 +219,12 @@ EXIT/OUTPUT
BUGS
Occasionally the result is not printed at the end of the game.
So far this has only been observed to occur when RED wins the game by Flag capture.
stratego is still a work in progress. Report another bug to the AUTHOR (see below).
AUTHORS
Sam Moore (for the UCC Programming Competition 2012) <[email protected]>
......
......@@ -390,6 +390,14 @@ MovementResult Board::MovePiece(int x, int y, const Direction & direction, int m
}
else
{
//Use this to destroy only the attacking piece, and not the bomb
RemovePiece(target);
delete target;
board[x][y] = NULL;
return MovementResult(MovementResult::DIES, attackerType, defenderType);
/*
//Use this to destroy both the bomb and the attacking piece
RemovePiece(defender);
RemovePiece(target);
delete defender;
......@@ -397,6 +405,7 @@ MovementResult Board::MovePiece(int x, int y, const Direction & direction, int m
board[x][y] = NULL;
board[x2][y2] = NULL;
return MovementResult(MovementResult::BOTH_DIE, attackerType, defenderType);
*/
}
}
else if (defender->type == Piece::MARSHAL && target->type == Piece::SPY)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment