[RULE CHANGE] "NO_MOVE" is no longer a legal
authorSam Moore <[email protected]>
Fri, 6 Jan 2012 05:39:24 +0000 (13:39 +0800)
committerSam Moore <[email protected]>
Fri, 6 Jan 2012 05:39:24 +0000 (13:39 +0800)
Previously AIs could respond with "NO_MOVE" whenever they felt like.
Officially, now they can only respond with "NO_MOVE" when they have no mobile pieces left.
(That is, only Bombs and the Flag are left).

However the game should end by a VICTORY_ATTRITION condition as soon as either player loses its last mobile piece.
So technically, "NO_MOVE" can't ever be legally printed, because the game should have ended. If it doesn't, there is a bug.

Updated webpage, updated manual, updated README

Going to email the list later today.

Goodluck!

PS: The rule change is due to a mean initial setup, for example:

**********
**********
**********
BB**BB**BB
..++..++..
..++..++..
etc

Here, Red has placed Bombs in all three "lanes". Red is unable to move.
However, as long as Red can use "NO_MOVE", an unsuspecting Blue will lose most of its pieces on the Bombs.
(Unless Blue puts a miner up the front...) But anyway, being able to not move is silly and not allowed in the real game.

README
judge/manager/controller.cpp
judge/manager/game.cpp
judge/manager/game.h
judge/manager/stratego.cpp
judge/manager/stratego.h
judge/simulator/simulate.py
web/doc/manager_manual.txt
web/index.html

diff --git a/README b/README
index 042882b..9cdb4d1 100644 (file)
--- a/README
+++ b/README
@@ -51,10 +51,6 @@ description
 
 Please do not allow paths such as "../../" etc - but that is common sense!
 
-=== TODO ===
-Add a user for each submission for extra security
-Web upload?
-
 [SZM] (matches) 22/12/2011
 
 
index f5c99ce..5691406 100644 (file)
@@ -80,6 +80,8 @@ MovementResult Controller::MakeMove(string & buffer)
        if (query != MovementResult::OK)
                return query;
 
+       /* 
+       //Removed 3/01/12 NO_MOVE now not allowed, SURRENDER is undocumented and not necessary
        if (buffer == "NO_MOVE")
        {
                buffer += " OK";
@@ -90,6 +92,7 @@ MovementResult Controller::MakeMove(string & buffer)
                buffer += " OK";
                return MovementResult::SURRENDER;
        }
+       */
        
        int x; int y; string direction="";
        stringstream s(buffer);
index 3df968c..486920d 100644 (file)
@@ -442,9 +442,24 @@ void Game::PrintEndMessage(const MovementResult & result)
        }
 
 }
+/** Checks for victory by attrition (destroying all mobile pieces)
+ *
+ *  @returns OK for no victory, 
+ *     DRAW if both players have no pieces, or 
+ *     VICTORY_ATTRITION  if the current player has won by attrition
+ */
+MovementResult Game::CheckVictoryAttrition()
+{
+        if (theBoard.MobilePieces(Piece::OppositeColour(turn)) == 0)
+       {
+               if (theBoard.MobilePieces(turn) == 0)
+                       return MovementResult::DRAW;
+               else
+                       return MovementResult::VICTORY_ATTRITION;
+       }
+       return MovementResult::OK;
 
-
-
+}
 MovementResult Game::Play()
 {
 
@@ -483,22 +498,26 @@ MovementResult Game::Play()
                #endif //BUILD_GRAPHICS
                
                turn = Piece::RED;
+
+               if (!Board::HaltResult(result))
+               {
+                       result = CheckVictoryAttrition();
+               }
+               if (Board::HaltResult(result))
+                       break;
+
                logMessage( "%d RED: ", turnCount);
                result = red->MakeMove(buffer);
                red->Message(buffer);
                blue->Message(buffer);
                logMessage( "%s\n", buffer.c_str());
-               if (Board::HaltResult(result))
-                       break;
 
-               if (theBoard.MobilePieces(Piece::BLUE) == 0)
+               if (!Board::HaltResult(result))
                {
-                       if (theBoard.MobilePieces(Piece::RED) == 0)
-                               result = MovementResult::DRAW;
-                       else
-                               result = MovementResult::VICTORY_ATTRITION;
-                       break;                  
+                       result = CheckVictoryAttrition();
                }
+               if (Board::HaltResult(result))
+                       break;
 
                if (stallTime >= 0)
                        Wait(stallTime);
@@ -523,12 +542,24 @@ MovementResult Game::Play()
                
                
                turn = Piece::BLUE;
+
+               if (!Board::HaltResult(result))
+               {
+                       result = CheckVictoryAttrition();
+               }
+               if (Board::HaltResult(result))
+                       break;
+
                logMessage( "%d BLU: ", turnCount);
                result = blue->MakeMove(buffer);
                blue->Message(buffer);
                red->Message(buffer);
                logMessage( "%s\n", buffer.c_str());
 
+               if (!Board::HaltResult(result))
+               {
+                       result = CheckVictoryAttrition();
+               }
                if (Board::HaltResult(result))
                        break;
 
index aebda9d..2ed35f6 100644 (file)
@@ -23,6 +23,7 @@ class Game
                void Wait(double wait); 
 
                Piece::Colour Setup(const char * redName, const char * blueName);
+               MovementResult CheckVictoryAttrition();
                MovementResult Play();
                void PrintEndMessage(const MovementResult & result);
                
index 5acfaa3..e142a4b 100644 (file)
@@ -57,6 +57,27 @@ Piece::Type Piece::GetType(char fromToken)
        return Piece::BOULDER;
 }
 
+/**
+ * Gets the opposite to the indicated colour
+ */
+Piece::Colour Piece::OppositeColour(const Colour & colour)
+{
+       switch (colour)
+       {
+               case Piece::RED:
+                       return Piece::BLUE;
+                       break;
+               case Piece::BLUE:
+                       return Piece::RED;
+                       break;
+               case Piece::BOTH:
+                       return Piece::BOTH;
+                       break;
+               case Piece::NONE:
+                       return Piece::NONE;
+       }
+}
+
 /**
  * Construct a new, empty board
  * @param newWidth - the width of the board
index d2e667f..098540c 100644 (file)
@@ -28,6 +28,9 @@ class Piece
        
                typedef enum {RED=0, BLUE=1, NONE=2, BOTH=3} Colour; //Used for the allegiance of the pieces - terrain counts as NONE.
 
+               static Colour OppositeColour(const Colour & compare);
+       
+
                Piece(const Type & newType, const Colour & newColour) : type(newType), colour(newColour), beenRevealed(false) {}
                virtual ~Piece() {}
 
index b44012b..5daafb7 100755 (executable)
@@ -328,10 +328,10 @@ for roundNumber in range(totalRounds, totalRounds + nRounds):
                print "RESULTS FOR ROUND " + str(roundNumber)
 
        #totalFile = open(resultsDirectory+"total.scores", "w") #Recreate the file
-               for agent in agents:    
+               #for agent in agents:   
                #totalFile.write(agent["name"] + " " + str(agent["totalScore"]) +"\n") #Write the total scores in descending order
                #if verbose:
-                               print "Agent: " + str(agent)
+               #               print "Agent: " + str(agent)
        
 
        if verbose:
@@ -356,9 +356,9 @@ for roundNumber in range(totalRounds, totalRounds + nRounds):
 
                for index in range(0, len(agent["ALL"])):
                        if agent["ALL"][index][4] == "RED":
-                               logFile = logDirectory + "round"+str(roundNumber) + "/"+agent["name"]+".vs."+agent["ALL"][index][0]+"."+str(agent["ALL"][index][1])
+                               logFile = "log/round"+str(roundNumber) + "/"+agent["name"]+".vs."+agent["ALL"][index][0]+"."+str(agent["ALL"][index][1])
                        else:
-                               logFile = logDirectory + "round"+str(roundNumber) + "/"+agent["ALL"][index][0]+".vs."+agent["name"]+"."+str(agent["ALL"][index][1])
+                               logFile = "log/round"+str(roundNumber) + "/"+agent["ALL"][index][0]+".vs."+agent["name"]+"."+str(agent["ALL"][index][1])
                        agentFile.write("<tr> <td> <a href="+logFile+">" + str(agent["ALL"][index][1]) + " </a> </td> <td> <a href="+agent["ALL"][index][0]+".html>"+agent["ALL"][index][0] + " </a> </td> <td> " + agent["ALL"][index][4] + " </td> <td> " + agent["ALL"][index][3] + " </td> <td> " + str(agent["ALL"][index][2]) + "</td> <td> " + str(agent["score"][len(agent["score"])-index -2]) + " </td> </tr> </th>\n")
                agentFile.write("</table>\n")
                
index bd9f0e1..d8b7a68 100644 (file)
@@ -157,16 +157,14 @@ PROTOCOL
                        as described in the GAME_RULES section. Each line ends with the newline character.
                        
 
-               RESPONSE: X Y DIRECTION [MULTIPLIER=1] | NO_MOVE
+               RESPONSE: X Y DIRECTION [MULTIPLIER=1] 
                        X and Y are the coords (starting from 0) of the piece to move
                        DIRECTION is either UP, DOWN, LEFT or RIGHT
                        MULTIPLIER is optional and only valid for units of type Scout. Scouts may move through any number of unblocked squares
                        in one direction.
 
-                       The AI program should print "NO_MOVE" if it is unable to determine a move.
-                       This will typically occur when the only pieces belonging to the AI program are Bombs and the Flag.
 
-               CONFIRMATION: X Y DIRECTION [MULTIPLIER=1] OUTCOME | NO_MOVE {OK | ILLEGAL} | QUIT [RESULT]
+               CONFIRMATION: X Y DIRECTION [MULTIPLIER=1] OUTCOME | QUIT [RESULT]
 
                        OUTCOME may be either OK, ILLEGAL, KILLS or DIES
                                OK - Move was successful
@@ -174,14 +172,7 @@ PROTOCOL
                                KILLS ATTACKER_RANK DEFENDER_RANK - The piece moved into an occupied square and killed the defender.
                                DIES ATTACKER_RANK DEFENDER_RANK - The piece moved into an occupied square and was killed by the defender.
 
-                       Most turns will be confirmed with: "X Y DIRECTION [MULTIPLIER=1] OUTCOME"
-
-                       A confirmation of "NO_MOVE OK" occurs when the AI program made no move for a legitimate reason.
-                       "NO_MOVE ILLEGAL" is printed if the AI program made no move for an illegitimate reason.
-
-                       If both AI programs successively make a "NO_MOVE" response, then the game will end.
-                       The player with the highest piece value will win, or a draw will be declared if the values are equal.
-
+                       QUIT will only be sent when the game is about to end.
        3. END GAME
                If the CONFIRMATION line is of the form:
                        QUIT [RESULT]
@@ -277,5 +268,5 @@ NOTES
           irc://irc.ucc.asn.au #progcomp
 
 THIS PAGE LAST UPDATED
-       23/12/11 by Sam Moore
+       3/01/12 by Sam Moore
        
index 8563b14..9cf4c0f 100644 (file)
 <h3> Protocol </h3>
 <p> For the sake of simplicity and keeping things in one place, the protocol is now entirely described in the <a href="doc/manager_manual.txt"/>manual page</a> of the manager program. All updates to the protocol will be reflected in that file. </p>
 
+<p> Major updates to the manager program or protocol will be accompanied by an email to the mailing list. However, it is probably a good idea to clone the git repository, and regularly pull from it. </p>
 
-<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 "web/doc/manager_manual.txt" in the <a href="http://git.ucc.asn.au/?p=progcomp2012.git;a=summary"/>git repository</a> </p>
+<p> <b> 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>
 
-<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> Scoring and Results </h2>
+<p> The competition will be a round robin, with every AI playing three (3) games against each possible opponent. A points system is used to score each AI, 3 points for a Win, 2 for a Draw, 1 for a Loss or -1 for an Illegal response (counts as a Win for the opponent). Scores accumulate between rounds. </p>
+<p> The winning AI will be the AI with the highest score after all games have been played. In the event of a tied score, the two highest scoring AI's will play one more round consisting of three games. If the scores are still tied, the official outcome will be a Draw. </p>
+<p> When the competition officially runs, results will appear <a href="results"/>here</a>. There may (or may not) be test results there now. </p> <p> 
 
-<h2> Long Term Scoring </h2>
-<p> Several rounds will be played (depending on the number of entries), with contestants given time to improve their entries between rounds. </p>
-<p> Each round is a round robin, with every AI playing several games against each possible opponent. A points system is used to score each AI, 3 points for a Win, 2 for a Draw, 1 for a Loss or -1 for an Illegal response (counts as a Win for the opponent). Scores accumulate between rounds. </p>
-<p> The winning AI will be the AI with the highest score after all rounds have been played. In the event of a tied score, the two highest scoring AI's will play one more round consisting of three games. If the scores are still tied, the official outcome will be a Draw. </p>
-<p> When the competition officially runs, results will appear <a href="results"/>here</a>. Preliminary test results might occasionally appear there for the next few weeks. </p> <p> 
-
-<h2> Sample AI Programs </h2>>
-<p> The following sample programs are currently available (and in a semi-working state - refer to the git repository): </p>
-<table border="0">
-<tr> <th>Name</th> <th>Language</th> <th> Moves </th> <th> Considers... </th> </tr>
-<tr> <td>basic_python</td> <td>Python</td> <td>Randomised</td> </tr>
-<tr> <td>basic_cpp</td> <td>C++</td> <td>Randomised</td> </tr>
-<tr> <td>asmodeus</td> <td>Python</td> <td>Scored</td> <td>Path finding, known combat results, piece values</td> </th> 
-<tr> <td>vixen</td> <td>Python</td> <td>Scored</td> <td>Asmodeus + Probabilities for unknown combat results </td> </th>
-</table> 
-<p> It is planned to implement the equivelants of these samples in C++ and Python at least, possibly other languages later. </p>
+<h2> Sample AI Programs </h2>
+<p> Several sample AI programs are currently available. No guarantees are provided about the functioning of these programs. The sample programs can be downloaded from the <a href="http://git.ucc.asn.au/?p=progcomp2012.git;a=summary"/>git repository </a>
 
 <h2> Submissions </h2>
 <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>
-<p> <b> Code which attempts to comprimise the host machine, or interfere directly with the functioning of other programs will be disqualified. </b> </p>
+<p> <b> Code which attempts to comprimise the host machine, or interfere interfere either directly or indirectly with the functioning of other programs will be disqualified. </b> </p>
 
 <h2> Dates </h2>
-<p> The competition will run in 2012. The exact dates have not been determined. An email will be sent to the list and messages sent to the irc channel. </p>
-
-<h2> Involvement </h2>
-<p> If you want to help set up the competition, email matches@ </p>
+<p> The competition is now officially open. Submissions will be accepted until midday, Saturday the 10th of March, 2012. Results will be announced as soon as they are available (depending on the number of entries it may take several days to simulate the competition). </p>
 
+<h2> FAQ </h2>
+<p> No one has asked any questions yet. If there is anything not covered or vague on this page, please email matches@ </p>
 
-<p> <b>Last webpage update: 22/12/11</b></p>
+<p> <b>Last webpage update: 06/01/12</b></p>
 </body>
 
 </html>

UCC git Repository :: git.ucc.asn.au