[PRELIMINARY ROUND 2]
[progcomp2012.git] / agents / ramen / src / main.c
diff --git a/agents/ramen/src/main.c b/agents/ramen/src/main.c
new file mode 100644 (file)
index 0000000..a9a2d71
--- /dev/null
@@ -0,0 +1,240 @@
+/*
+ * UCC 2012 Programming Competition Entry
+ * - "Ramen"
+ *
+ * By John Hodge [TPG]
+ */
+#define ENABLE_DEBUG   0
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <regex.h>
+#include "interface.h"
+
+// === CONSTANTS ===
+static const char *DIR_NAMES[] = {"INVL", "LEFT", "RIGHT", "UP", "DOWN"};
+
+// === PROTOTYPES ===
+ int   main(int argc, char *argv[]);
+void   GetMove(char *line, tMove *Move);
+void   ReadBoardState(FILE *stream, char *dest);
+ int   RunRegex(regex_t *regex, const char *string, int nMatches, regmatch_t *matches, const char *errorMessage);
+void   CompileRegex(regex_t *regex, const char *pattern, int flags);
+
+// === GLOBALS ===
+regex_t        gRegex_move;
+regex_t        gRegex_res;
+ int   giBoardWidth;
+ int   giBoardHeight;
+char   *gaBoardState;
+
+// === CODE ===
+int main(int argc, char *argv[])
+{
+       setbuf(stdin, NULL);
+       setbuf(stdout, NULL);
+
+       // $X $Y $DIRECTION [$MULTIPLIER=1] $OUTCOME
+       CompileRegex(&gRegex_move, "([0-9]+) ([0-9]+) ([A-Z]+)( [0-9]+)? (.*)", REG_EXTENDED);
+       // (KILLS|DIES|BOTHDIE) $ATTACKER_RANK $DEFENDER_RANK
+       CompileRegex(&gRegex_res, "([A-Z_]+) (.) (.)", REG_EXTENDED);
+
+       {
+                int    colour_id;
+               char    colour[6];
+               char    opponent[128];
+               fscanf(stdin, "%s %s %i %i", colour, opponent, &giBoardWidth, &giBoardHeight);
+
+               if( strcmp(colour, "RED") == 0 )
+                       colour_id = COLOUR_RED;
+               else if( strcmp(colour, "BLUE") == 0 )
+                       colour_id = COLOUR_BLUE;
+               else {
+                       fprintf(stderr, "Oops... nutty manager, colour = %s\n", colour);
+                       colour_id = COLOUR_RED;
+               }
+
+               DEBUG("colour=%i, opponent='%s', dims = %ix%i", colour_id, opponent, giBoardWidth, giBoardHeight);
+
+               AI_Initialise(colour_id, opponent);
+       }
+       
+       gaBoardState = malloc(giBoardWidth*giBoardHeight);
+
+       for( ;; )
+       {
+               tMove   mymove, opponent_move;
+               char    line[32];
+
+//             DEBUG("Waiting for move");
+               ASSERT( fgets(line, sizeof(line), stdin) != NULL );
+//             DEBUG("pm line = '%s'", line);
+
+               if( strcmp(line, "\n") == 0 )
+                       continue ;
+
+               if( strcmp(line, "START\n") == 0 )
+               {
+//                     DEBUG("New game");
+                       ReadBoardState(stdin, gaBoardState);
+                       // TODO: Check if this hasn't happened before
+                       opponent_move.x = 0;
+                       opponent_move.y = 0;
+                       opponent_move.dist = 0;
+                       opponent_move.dir = 0;
+               }
+               else if( strncmp(line, "QUIT", 4) == 0 )
+               {
+                       // TODO: Result?
+                       break ;
+               }
+               else if( strcmp(line, "VICTORY_FLAG\n") == 0 )
+               {
+                       // I win!
+                       break;
+               }
+               else
+               {
+//                     DEBUG("GetMove");
+                       GetMove(line, &opponent_move);
+//                     DEBUG("Read board state");
+                       ReadBoardState(stdin, gaBoardState);
+               }
+               DEBUG("Opposing move %i,%i dir %i dist %i",
+                       opponent_move.x, opponent_move.y, opponent_move.dir, opponent_move.dist);
+
+               // Silly opponent, you lost
+               if( opponent_move.result == RESULT_VICTORY )
+                       break;
+
+               // Determine move
+               AI_HandleMove(0, &opponent_move);
+               AI_DoMove(&mymove);
+               DEBUG("Chose move %i,%i %i %i", mymove.x, mymove.y, mymove.dir, mymove.dist);
+               printf("%i %i %s %i\n", mymove.x, mymove.y, DIR_NAMES[mymove.dir], mymove.dist);
+
+               // Get result of the move
+               ASSERT( fgets(line, sizeof(line), stdin) != NULL );
+//             DEBUG("res line = '%s'", line);
+//
+               GetMove(line, &mymove);
+               AI_HandleMove(1, &mymove);
+
+               // I WON!
+               if( mymove.result == RESULT_VICTORY )
+                       break;
+
+//             DEBUG("Move over");
+       }
+
+       return 0;
+}
+
+void GetMove(char *line, tMove *Move)
+{
+       regmatch_t      matches[1+5];
+
+       // regex (\d+) (\d+) ([A-Z]*)(?: (\d+))?
+       RunRegex(&gRegex_move, line, 1+5, matches, "Move line");
+
+       char *xstr = line + matches[1].rm_so;
+       char *ystr = line + matches[2].rm_so;
+       char *dirstr = line + matches[3].rm_so;
+
+       Move->x = atoi(xstr);
+       Move->y = atoi(ystr);
+//     DEBUG("(%i,%i)", Move->x, Move->y);
+       // Direction
+            if( strncmp(dirstr, "UP",    2) == 0 )
+               Move->dir = DIR_UP;
+       else if( strncmp(dirstr, "DOWN",  4) == 0 )
+               Move->dir = DIR_DOWN;
+       else if( strncmp(dirstr, "LEFT",  4) == 0 )
+               Move->dir = DIR_LEFT;
+       else if( strncmp(dirstr, "RIGHT", 5) == 0 )
+               Move->dir = DIR_RIGHT;
+       else {
+               fprintf(stderr, "Is the manager nuts? Dir = %.*s unk\n",
+                       matches[3].rm_eo + matches[3].rm_so, dirstr
+                       );
+               fprintf(stderr, "line = '%s'\n", line);
+               Move->dir = DIR_INVAL;
+       }
+       if( matches[4].rm_so >= 0 )
+               Move->dist = atoi(line + matches[4].rm_so + 1);
+       else
+               Move->dist = 1;
+       
+       // Outcome
+       char    *outcome = line + matches[5].rm_so;
+       if( strncmp(outcome, "OK", 2) == 0 )
+               Move->result = RESULT_OK;
+       else if( strncmp(outcome, "ILLEGAL", 7) == 0 )
+               Move->result = RESULT_ILLEGAL;
+       else if( strncmp(outcome, "VICTORY_FLAG", 12) == 0 )
+               Move->result = RESULT_VICTORY;
+       else if( strncmp(outcome, "VICTORY_ATTRITION", 17) == 0 )
+               Move->result = RESULT_VICTORY;
+       else
+       {
+               regmatch_t res_matches[3+1];
+               RunRegex(&gRegex_res, outcome, 3+1, res_matches, "Result portion");
+
+               char *res_str = outcome + res_matches[1].rm_so;
+                    if( strncmp(res_str, "KILLS ", 6) == 0 )
+                       Move->result = RESULT_KILL;
+               else if( strncmp(res_str, "DIES ", 5) == 0 )
+                       Move->result = RESULT_DIES;
+               else if( strncmp(res_str, "BOTHDIE ", 8) == 0 )
+                       Move->result = RESULT_BOTHDIE;
+               else {
+                       fprintf(stderr, "Is the manager nuts? Result = %.*s\n",
+                               res_matches[1].rm_eo + res_matches[1].rm_so, res_str
+                              );
+                       Move->result = RESULT_INVAL;
+               }
+
+               Move->attacker = *(outcome + res_matches[2].rm_so);
+               Move->defender = *(outcome + res_matches[3].rm_so);
+       }
+}
+
+void ReadBoardState(FILE *stream, char *dest)
+{
+       for( int i = 0; i < giBoardHeight; i ++ )
+       {
+               char    tmp[giBoardWidth+2];
+               fgets(tmp, sizeof(tmp), stream);
+               DEBUG("BS %.*s", giBoardWidth, tmp);
+               memcpy(dest+i*giBoardWidth, tmp, giBoardWidth);
+       }
+}
+
+int RunRegex(regex_t *regex, const char *string, int nMatches, regmatch_t *matches, const char *errorMessage)
+{
+        int    ret;
+       
+       ret = regexec(regex, string, nMatches, matches, 0);
+       if( ret ) {
+               size_t  len = regerror(ret, regex, NULL, 0);
+               char    errorStr[len];
+               regerror(ret, regex, errorStr, len);
+               fprintf(stderr, "string = '%s'\n", string);
+               fprintf(stderr, "%s\n%s", errorMessage, errorStr);
+               exit(-1);
+       }
+       
+       return ret;
+}
+
+void CompileRegex(regex_t *regex, const char *pattern, int flags)
+{
+        int    ret = regcomp(regex, pattern, flags);
+       if( ret ) {
+               size_t  len = regerror(ret, regex, NULL, 0);
+               char    errorStr[len];
+               regerror(ret, regex, errorStr, len);
+               fprintf(stderr, "Regex compilation failed - %s\n", errorStr);
+               exit(-1);
+       }
+}

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