Direction dir = Helper::StrToDir(tokens[2]);
- string & outcome = tokens[3];
- int x2 = x; int y2 = y; Helper::MoveInDirection(x2,y2,dir);
+ //We might want to actually check for the multiplier in the sample agents! 20/12/11
+ unsigned int outIndex = 3;
+ int multiplier = atoi(tokens[outIndex].c_str());
+ if (multiplier == 0)
+ multiplier = 1;
+ else
+ outIndex += 1;
+
+
+
+ string & outcome = tokens[outIndex];
+
+
+ int x2 = x; int y2 = y; Helper::MoveInDirection(x2,y2,dir, multiplier);
Piece * attacker = board->Get(x,y);
if (attacker == NULL)
//cerr << "No defender!\n";
return false;
}
+ if (tokens.size() < outIndex+2)
+ return false;
+
board->Set(x2,y2, attacker);
board->Set(x,y,NULL);
attacker->x = x2; attacker->y = y2;
-
- attacker->rank = Piece::GetRank(tokens[4][0]);
+ attacker->rank = Piece::GetRank(tokens[outIndex+1][0]);
ForgetUnit(defender);
}
else if (outcome == "DIES")
//cerr << "No defender!\n";
return false;
}
-
+ if (tokens.size() < outIndex+3)
+ return false;
+
board->Set(x,y,NULL);
- defender->rank = Piece::GetRank(tokens[5][0]);
+ defender->rank = Piece::GetRank(tokens[outIndex+2][0]);
ForgetUnit(attacker);
ranks = ['B','1','2','3','4','5','6','7','8','9','s','F', '?', '+']
-def move(x, y, direction):
+def is_integer(s):
+ """ Using exceptions for this feels... wrong..."""
+ try:
+ int(s)
+ return True
+ except ValueError:
+ return False
+
+def move(x, y, direction, multiplier):
""" Moves point (x,y) in direction, returns a pair """
if direction == "UP":
return (x,y-1)
#sys.stderr.write(" Board position " + str(x) + " " + str(y) + " is OK!\n")
direction = result[2].strip()
+
+ multiplier = 1
outcome = result[3].strip()
+ outIndex = 3
+ if is_integer(outcome):
+ multiplier = int(outcome)
+ outcome = result[4].strip()
+ outIndex = 4
- p = move(x,y,direction)
+ p = move(x,y,direction, multiplier)
self.board[p[0]][p[1]] = self.board[x][y]
- self.board[x][y].rank = result[4].strip()
+ self.board[x][y].rank = result[outIndex+1].strip()
self.board[x][y] = None
elif self.board[x][y].colour == oppositeColour(self.colour):
self.enemyUnits.remove(self.board[x][y])
- self.board[p[0]][p[1]].rank = result[5].strip()
+ self.board[p[0]][p[1]].rank = result[outIndex+2].strip()
self.board[x][y] = None
elif outcome == "BOTHDIE":
if self.board[p[0]][p[1]] == None:
NOTES
1. There is no plan to support AI programs named "human". Deal with it.
2. The graphical interface for human players is... basic. Deal with it.
-
blue_player
As red_player, except for controlling the Blue player.
+
+A WARNING ABOUT BUFFERING
+ The AI programs must unbuffer their stdin and stdout streams, otherwise it will be seen to be non-responsive.
+ If you C and you know a way to force the process started by exec() to have unbuffered stdin/stdout, please email the author.
+
+ In C or C++, unbuffering is accomplished with the following lines, which should appear near the start of main()
+ setbuf(stdin, NULL);
+ setbuf(stdout, NULL);
+ In python, unbuffering is accomplished by passing the -u switch to the interpreter, ie: The first line of a script reads:
+ #!/usr/bin/python -u
+
OPTIONS
-g
GAME RULES
- Each player controls up to 40 pieces on the Board. The pieces consist of the following:
+ Each player controls up to 40 pieces on the Board. The pieces are represented by the following characters:
Piece Name Rank Number Abilities
1 Marshal 1 1 Dies if attacked by Spy
If possible, stratego will print the message "QUIT" to both AI programs, and they should exit as soon as possible.
-BUGS
- WARNING:
- stratego has been observed to segfault occassionally after the end of a game. It is not yet known what is causing these errors.
- They appear to occur most often when the result is a draw, however they have been observed to occur under all exit conditions except the Illegal case. The result is still printed to stdout. However this bug _must_ be fixed before stratego can be used by simulation scripts.
-
+BUGS
stratego is still a work in progress. Report another bug to the AUTHOR (see below).
AUTHORS
3. IRC Channel
irc://irc.ucc.asn.au #progcomp
+
+THIS PAGE LAST UPDATED
+ 20/12/11 by Sam Moore
/**
* Draw the board state to graphics
- * @param reveal - Pieces matching this colour will be revealed. All others will be shown as blank coloured squares.
+ * @param reveal - Pieces matching this colour will be revealed. If Piece::BOTH, all pieces will be revealed
+ * @param showRevealed - If true, then all pieces that have taken part in combat will be revealed, regardless of colour.
+ * If false, only pieces matching the colour reveal will be revealed
*/
void Board::Draw(const Piece::Colour & reveal, bool showRevealed)
{
}
/**
- * Moves a piece at a specified position in the specified direction, handles combat if necessary
+ * Moves a piece at a specified position in the specified direction, handles combat if necessary, updates state of the board
* @param x - x-coord of the piece
* @param y - y-coord of the piece
* @param direction - Direction in which to move (UP, DOWN, LEFT or RIGHT)
* @param colour - Colour which the piece must match for the move to be valid
- * @returns A MovementResult which indicates the result of the move - OK is good, VICTORY means that a flag was captured, anything else is an error
+ * @returns A MovementResult which indicates the result of the move
*/
MovementResult Board::MovePiece(int x, int y, const Direction & direction, int multiplier,const Piece::Colour & colour)
{
board[x2][y2] = target;
return MovementResult(MovementResult::KILLS, attackerType, defenderType);
}
- else if (target->operator==(*defender) && rand() % 2 == 0)
+ else if (target->operator==(*defender))// && rand() % 2 == 0)
{
RemovePiece(defender);
+ RemovePiece(target);
delete defender;
+ delete target;
board[x][y] = NULL;
- board[x2][y2] = target;
- return MovementResult(MovementResult::KILLS, attackerType, defenderType);
+ board[x2][y2] = NULL;
+ return MovementResult(MovementResult::BOTH_DIE, attackerType, defenderType);
}
else
{
if os.path.exists(resultsDirectory) == False:
os.mkdir(resultsDirectory) #Make the results directory if it didn't exist
+'''
+ Obselete older version doesn't work with new .html files
#Identify the round number by reading the results directory
totalRounds = len(os.listdir(resultsDirectory)) + 1
if totalRounds > 1:
totalRounds -= 1
+'''
+
+totalRounds = 1
+#TODO: Fix this bit!
if os.path.exists(logDirectory) == False:
os.mkdir(logDirectory) #Make the log directory if it didn't exist
os.mkdir(logDirectory + "round"+str(roundNumber)) #Check there is a directory for this round's logs
for agent in agents:
- agent.update({"name":agent["name"], "path":agent["path"], "score":[0], "VICTORY":[], "DEFEAT":[], "DRAW":[], "ILLEGAL":[], "DEFAULT":[], "INTERNAL_ERROR":[], "SURRENDER":[], "DRAW_DEFAULT":[], "BOTH_ILLEGAL":[], "BAD_SETUP":[], "ALL":[], "totalScore":0, "Wins":0, "Losses":0, "Draws":0, "Illegal":0, "Errors":0})
+ agent.update({"name":agent["name"], "path":agent["path"], "score":[0], "VICTORY":[], "DEFEAT":[], "DRAW":[], "ILLEGAL":[], "DEFAULT":[], "INTERNAL_ERROR":[], "SURRENDER":[], "DRAW_DEFAULT":[], "BOTH_ILLEGAL":[], "BAD_SETUP":[], "ALL":[]})
print "Commencing ROUND " + str(roundNumber) + " combat!"
agentFile.write("</table>\n")
agentFile.close()
-
+ #Update round file
+ roundFile = open(htmlDir + "round"+str(roundNumber)+".html", "w")
+ roundFile.write("<html>\n<head>\n <title> Round " +str(roundNumber)+ " Overview </title>\n</head>\n<body>\n")
+ roundFile.write("<h1> Round " +str(roundNumber)+ " Overview </h1>\n")
+ roundFile.write("<table border=\"0\" cellpadding=\"10\">\n")
+ roundFile.write("<tr> <th> Name </th> <th> Score </th> <th> Total Score </th> </tr>\n")
+ agents.sort(key = lambda e : e["score"][0], reverse=True)
+ for agent in agents:
+ roundFile.write("<tr> <td> <a href="+agent["name"]+".html>"+agent["name"] + " </a> </td> <td> " + str(agent["score"][0]) + " </td> <td> " + str(agent["totalScore"]) + " </td> </tr>\n")
+ roundFile.write("</table>\n</body>\n<!-- Results file for Round " + str(roundNumber) + " autogenerated by \"" + sys.argv[0] + "\" at time " + str(time()) + " -->\n</html>\n\n")
+ roundFile.close()
+
+
+
if verbose:
agentFile.write("</body>\n<!-- Results file for \"" + agent["name"] + "\" autogenerated by \"" + sys.argv[0] + "\" at time " + str(time()) + " -->\n</html>\n\n")
agentFile.close()
+ if os.path.exists(htmlDir + "total.html") == True:
+ os.remove(htmlDir + "total.html") #Delete the file
+
+totalFile = open(htmlDir + "total.html", "w")
+totalFile.write("<html>\n<head>\n <title> Total Overview </title>\n</head>\n<body>\n")
+totalFile.write("<h1> Total Overview </h1>\n")
+totalFile.write("<table border=\"0\" cellpadding=\"10\">\n")
+totalFile.write("<tr> <th> Name </th> <th> Total Score </th> </tr>\n")
+agents.sort(key = lambda e : e["totalScore"], reverse=True)
+for agent in agents:
+ totalFile.write("<tr> <td> <a href="+agent["name"]+".html>"+agent["name"] + " </a> </td> <td> " + str(agent["totalScore"]) + " </td> </tr>\n")
+totalFile.write("</table>\n</body>\n<!-- Total Results file autogenerated by \"" + sys.argv[0] + "\" at time " + str(time()) + " -->\n</html>\n\n")
+totalFile.close()
+
if verbose:
print "Done!"
<p> <b> Warning:</b> The accuracy of the above file depends on how recently I pulled it from git. To ensure you get the latest version, find it under "manager/manual.txt" in the <a href="http://git.ucc.asn.au/?p=progcomp2012.git;a=summary"/>git repository</a> </p>
+<p> <b> Another Warning:</b> AI programs <b>must</b> unbuffer stdin and stdout themselves. This is explained in the manual page, but I figured no one would read it. It is fairly simple to unbuffer stdin/stdout in C/C++ and python, I have not investigated other languages yet. </p>
+
<h2> Long Term Scoring </h2>
<p> <b> WARNING: Work in progress </b> </p>
<p> It is currently planned to store all the AIs on a virtual machine, and periodically run a script to play a round robin </p>
<h2> Submissions </h2>
<p> We (I?) are now accepting test submissions. </p>
-<p> Please email matches@ attaching your submission source code </p>
+<p> You must submit the full source code, and build instructions or makefile(s) for your program. </p>
+<p> Also include the name of the executable or script, the name of the AI, your name, and optionally a description of your AI and its tactics. </p>
+<p> Please email matches@ if you have a submission. </p>
+
+<h2> Dates </h2>
+<p> The competition will run in 2012. The exact dates have not been determined. I will consider whether it is worth waiting until freshers have a chance to make submissions March/April, or running the competition earlier in January/February. </p>
+
+<h2> Involvement </h2>
+<p> If you want to help set up the competition, email matches@ </p>
+<p> There isn't much left to do, but all help is appreciated. Maybe you can suggest something, and volunteer to implement it! </p>
+<p> The most useful thing you can do is actually write an AI, and test the manager program. Please report any bugs (in the manager program, not in your AI!) to matches@ (you can feel free to fix them, but won't be able to push unless you email matches). </p>
-<p> <b>Last webpage update: 12/12/11</b></p>
+<p> <b>Last webpage update: 20/12/11</b></p>
</body>
</html>