Work towards C SDK (#11). Frenchie is still broken.
authorDaniel Axtens <[email protected]>
Mon, 28 Jun 2010 02:23:45 +0000 (10:23 +0800)
committerDaniel Axtens <[email protected]>
Mon, 28 Jun 2010 02:23:45 +0000 (10:23 +0800)
12 files changed:
.gitignore
src/link/C/.gitignore
src/link/C/Makefile
src/link/C/README [new file with mode: 0644]
src/link/C/agents-broken/c_frenchie.c [deleted file]
src/link/C/agents/c_frenchie.c [new file with mode: 0644]
src/link/C/agents/c_lucifer.c
src/link/C/c-link-lib.xcodeproj/project.pbxproj
src/link/C/c_link.c
src/link/C/c_link.h
src/link/externAgent.py
src/simulate.py

index 047c57f..4baac77 100644 (file)
@@ -6,6 +6,7 @@ build/
 # gcc noise
 *.o
 *.a
+*.dSYM
 
 # old skool
 .svn
index fbde527..c51cee3 100644 (file)
@@ -1,2 +1,2 @@
-agents/
 !agents/*.c
+agents/*
index ccefb00..7d3e68c 100644 (file)
@@ -1,8 +1,8 @@
 CC=gcc
 AR=ar
 
-CFLAGS=-Wall -I.
-LDFLAGS=-lc_link -L.
+myCFLAGS=$(CFLAGS) -Wall -I.
+myLDFLAGS=-lc_link -L.
 
 LINKSRCS=c_link.c
 LINKOBJS=$(LINKSRCS:.c=.o)
@@ -18,10 +18,10 @@ $(LINKLIB): $(LINKOBJS)
        
 $(AGENTS): $(AGENTSRCS) $(LINKLIB)
        @echo Building $@
-       $(CC) $(CFLAGS) $(LDFLAGS) [email protected] -o $@
+       $(CC) $(myCFLAGS) $(myLDFLAGS) [email protected] -o $@
 
 .c.o: c_link.h
-       $(CC) -c $(CFLAGS) $< -o $@
+       $(CC) -c $(myCFLAGS) $< -o $@
 
 .PHONY : clean
 clean:
diff --git a/src/link/C/README b/src/link/C/README
new file mode 100644 (file)
index 0000000..7f0a970
--- /dev/null
@@ -0,0 +1,24 @@
+Welcome to the C SDK and link library.
+
+== Compiling and testing the sample bots ==
+
+Run "make" in this directory. To include them in the 
+
+== Making your own agent ==
+See wiki page.
+
+= Testing your own agent =
+Edit src/simulate.py.
+Your agents live in link.C.c_agents
+Add them to Agents to get them to do battle.
+
+For example, this code imports c_angel, c_lucifer, c_streetfighter and
+c_frenchie, as well as the python sample agents, and then battles c_lucifer, 
+python Frenchie, c_streetfighter and c_angel. It goes at the top of simulate.py.
+
+# Import and add your agents here:
+from link.C.c_agents import c_angel, c_lucifer, c_streetfighter, c_frenchie
+
+from SampleAgents import Angel, Lucifer, Dummy, Frenchie, Streetfighter
+Agents = [c_lucifer, Frenchie, c_streetfighter, c_angel]
+
diff --git a/src/link/C/agents-broken/c_frenchie.c b/src/link/C/agents-broken/c_frenchie.c
deleted file mode 100644 (file)
index 78866a6..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- *  c_frechie.c
- *  c-link-lib
- *
- *  Created by Daniel Axtens on 22/04/10.
- *  Licensed under an MIT-style license: see the LICENSE file for details.
- *
- */
-
-#include <c_link.h>
-#include <stdlib.h>
-
-/* Implement the frenchie bot, that is by default nice but will 
-   permanently turn against any agent that betrays it.
-   This is trickier in C than in any other language, for a number of reasons:
-     - there's no classes in C, so we can't just write a generic learning agent
-       and subclass it.
-     - your agent has no idea how many agents it's going to battle, or how many
-       battles it is going to fight, so you've got to do dynamic memory allocation.
-        (anyone who tries to read the source of the supervisor to find out is liable
-         to have their program break unexpectedly)
- */
-
-/* To simplify things, we just look at whether we have lost to a particular agent.
-   Unlike in the Python version, we don't keep a generic list
-   This is also done in a inefficient (O(bot-cout)) way.
-   Implementing a faster version is left as an exercise to the DSA student. */
-
-/* Our guess at the number of agents I'm going to fight in my lifetime */
-#define NUMBEROFAGENTSGUESS 100
-
-/* The name of the n-th foe we've seen, as well as a 0/1 have we lost to them */
-char foesNames[][MAXFOENAMELEN];
-int haveLostToFoe[];
-
-/* The length of the array, and how far we are along it */
-size_t foesLen = 0;
-unsigned int foesCount = 0;
-
-
-ATTACKTYPE Attack( char * foe_name ) {
-       ATTACKTYPE attack;
-       
-       attack.realAttack =  RandomAttack();
-       
-       /* Here we choose the thing that will hurt them if they go for the kill */
-       switch (attack.realAttack) {
-               case rock:
-                       attack.promisedAttack = paper;
-                       break;
-               case paper:
-                       attack.promisedAttack = scissors;
-                       break;
-               default: /* attack = scissors */
-                       attack.promisedAttack = rock;
-                       break;
-       }
-       return attack;
-}
-
-/* Here we assume they are lying, trying to kill us. And we try to kill them. */
-ITEMTYPE Defend( char * foeName, ITEMTYPE foePromisedAttack ) {
-       ITEMTYPE defence;
-       switch (foePromisedAttack) {
-               case rock:
-                       defence = scissors;
-                       break;
-               case paper:
-                       defence = rock;
-                       break;
-               default:
-                       defence = paper;
-                       break;
-       }
-    return defence;
-}
-
-/* This is so much less fun in C */
-void Results( char * foeName, int isInstigatedByYou, ITEMTYPE yourItem, 
-                        ITEMTYPE theirItem, ITEMTYPE promisedItem) {
-       
-    int foe;
-    
-    /* check to see if we've initialised our arrays */
-       if (foesNames == NULL) {
-        foesNames = calloc( NUMBEROFAGENTSGUESS, sizeof( foesNames[0] ) );
-        haveLostToFoe = calloc( NUMBEROFAGENTSGUESS, sizeof( haveLostToFoe[0] ) );
-        foesLen = NUMBEROFAGENTSGUESS;
-    }
-    
-    /* figure out if we lost, which is the only thing we care about
-       if we didn't, move on. */
-    if (RESULTOF[yourItem][theirItem] != lose) return;
-    
-    /* try and find existing foe */
-    
-    return;
-}
-
-/* same for Cleanup() */
-
-void Cleanup() {
-       free(foesNames);
-    free(haveLostToFoe);
-}
\ No newline at end of file
diff --git a/src/link/C/agents/c_frenchie.c b/src/link/C/agents/c_frenchie.c
new file mode 100644 (file)
index 0000000..a14ee92
--- /dev/null
@@ -0,0 +1,157 @@
+/*
+ *  c_frechie.c
+ *  c-link-lib
+ *
+ *  Created by Daniel Axtens on 22/04/10.
+ *  Licensed under an MIT-style license: see the LICENSE file for details.
+ *
+ */
+
+#include <c_link.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* Implement the frenchie bot, that is by default nice but will 
+   permanently turn against any agent that betrays it.
+   This is trickier in C than in any other language, for a number of reasons:
+     - there's no classes in C, so we can't just write a generic learning agent
+       and subclass it.
+     - your agent has no idea how many agents it's going to battle, or how many
+       battles it is going to fight, so you've got to do dynamic memory allocation.
+        (anyone who tries to read the source of the supervisor to find out is liable
+         to have their program break unexpectedly)
+ */
+
+/* To simplify things, we just look at whether we have lost to a particular agent.
+   Unlike in the Python version, we don't keep a generic list
+   This is also done in a inefficient (O(bot-cout)) way.
+   Implementing a faster version is left as an exercise to the DSA student. */
+
+/* Our guess at the number of agents I'm going to fight in my lifetime
+   (note that this is only a guess, not an upper limit. Do *not* take it as 
+   gospel on the number of agents you're going to see. */
+#define NUMBEROFAGENTSGUESS 100
+
+/* The name of the n-th foe who has beaten us */
+char (*defeatingFoes)[MAXFOENAMELEN] = NULL;
+
+/* The length of the array, and how far we are along it */
+size_t foesLen = 0;
+unsigned int foesCount = 0;
+
+/* an internal function - have I lost to a given foe? */
+int haveLostTo( char * foeName ) {
+    int foe;
+    
+    /* check every foe we know to have defeated us */
+    for (foe=0; foe<foesCount; foe++) {
+        if (strncmp( defeatingFoes[foe], foeName, MAXFOENAMELEN) == 0) {
+            debugmsg( "%d\thaveLostTo( %s ) -> Yes\n", me, foeName );
+            return 1;
+        }
+    }
+    
+    /* this foe not found */
+    return 0;
+}
+
+
+ATTACKTYPE Attack( char * foeName ) {
+       ATTACKTYPE attack;
+    
+       attack.realAttack =  RandomAttack();
+       
+    /* have I lost to this foe? */
+    if ( haveLostTo(foeName) ) {
+        /* Assume they are lying (FIXME: I'm not entirely sure why the python
+           does what it does: I'm just duplicating.) */
+        switch (attack.realAttack) {
+            case rock:
+                attack.promisedAttack = scissors;
+                break;
+            case paper:
+                attack.promisedAttack = rock;
+                break;
+            default: /* attack = scissors */
+                attack.promisedAttack = paper;
+                break;
+        }
+    } else {
+        /* be nice! */
+        attack.promisedAttack = attack.realAttack;
+    }
+
+       
+       return attack;
+}
+
+
+ITEMTYPE Defend( char * foeName, ITEMTYPE foePromisedAttack ) {
+       ITEMTYPE defence;
+       
+    if (haveLostTo(foeName)) {
+        /* They've screwed us in the past, assume they're lying and go for the
+           kill. */
+        switch (foePromisedAttack) {
+            case rock:
+                defence = scissors;
+                break;
+            case paper:
+                defence = rock;
+                break;
+            default:
+                defence = paper;
+                break;
+        }
+    } else {
+        /* be nice! */
+        defence = foePromisedAttack;
+    }
+
+    return defence;
+}
+
+/* This is so much less fun in C */
+void Results( char * foeName, int isInstigatedByYou, ITEMTYPE yourItem, 
+                        ITEMTYPE theirItem, ITEMTYPE promisedItem) {
+       
+    int foe;
+    
+    /* check to see if we've initialised our arrays */
+       if (defeatingFoes == NULL) {
+        defeatingFoes = calloc( NUMBEROFAGENTSGUESS, sizeof( MAXFOENAMELEN*sizeof(char) ) );
+        foesLen = NUMBEROFAGENTSGUESS;
+    }
+    
+    /* figure out if we lost, which is the only thing we care about
+       if we didn't, move on. */
+    if (RESULTOF[yourItem][theirItem] != lose) return;
+    
+    fprintf( stderr, "%d\tsaving loss from %s\n", me, foeName );
+    
+    /* if we've already lost the foe, don't store again */
+    for (foe=0; foe<foesCount; foe++) {
+        if (strncmp( defeatingFoes[foe], foeName, MAXFOENAMELEN ) == 0) {
+            /* we've found it! */
+            return;
+        }
+    }
+    
+    /* we haven't found the foe. add it, expanding the array if needed */
+    if (foesCount==foesLen) {
+        /* double the array size */
+        defeatingFoes = realloc( defeatingFoes, foesLen*2*sizeof( MAXFOENAMELEN*sizeof(char) ) );
+        foesLen *= 2;
+    }
+    
+    strncpy( defeatingFoes[foesCount], foeName, MAXFOENAMELEN );
+    foesCount++;
+    
+    return;
+}
+
+/* same for Cleanup() */
+
+void Cleanup() {
+       free(defeatingFoes);
+}
\ No newline at end of file
index 204e1dd..af4741f 100644 (file)
@@ -30,7 +30,6 @@ ATTACKTYPE Attack( char * foe_name ) {
                        attack.promisedAttack = paper;
                        break;
        }
-       attack.promisedAttack = attack.realAttack;      /* Tells the truth for its bluff */
        
        return attack;
 }
index c2f58fd..e5afa2b 100644 (file)
@@ -13,6 +13,7 @@
                2291A1BD117EE3FD00854CBE /* c_angel.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = c_angel.c; sourceTree = "<group>"; };
                2291A1BE117EE3FD00854CBE /* c_lucifer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = c_lucifer.c; sourceTree = "<group>"; };
                2291A1BF117EE3FD00854CBE /* c_streetfighter.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = c_streetfighter.c; sourceTree = "<group>"; };
+               22CAFECF11D48750001ECDEF /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
                22F652F5117C679300A3793D /* Makefile */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = "<group>"; };
                22F652F6117C6C9500A3793D /* c_link.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = c_link.h; sourceTree = "<group>"; };
 /* End PBXFileReference section */
@@ -21,6 +22,7 @@
                08FB7794FE84155DC02AAC07 /* c-link-lib */ = {
                        isa = PBXGroup;
                        children = (
+                               22CAFECF11D48750001ECDEF /* README */,
                                2208AFE7118F28F400770C92 /* c_agents.py */,
                                2291A1BC117EE3FD00854CBE /* agents */,
                                22F652F6117C6C9500A3793D /* c_link.h */,
index 680450e..40eee24 100644 (file)
@@ -56,6 +56,11 @@ int main( int argc, char * argv[] ) {
        ATTACKTYPE attack;
        ITEMTYPE defence;
        
+    /* generate a random id for this bot. Hopefully it's unique
+       I can't use the UUID, because python doesn't pass it to me! */
+    me = rand();
+    
+    
        scanf( "%s", command );
        
        while (strcasecmp("BYE",command) != 0) {
index 84e9bce..44922a3 100644 (file)
@@ -38,14 +38,19 @@ typedef struct {
     the agent and supervisor) 
  */
 
-#define debugmsg(x...) sprintf(stderr, x)
+#define debugmsg(x...) fprintf(stderr, x)
+
+/* A (hopefully) unique identifier for this particular instance of your agent,
+   to help with debugging */
+int me;
+
 
 /* Returns a random item */
 
 ITEMTYPE RandomAttack();
 
 /* A useful translation table
-   eg printf( "I use %s.\n", ITEMNAMES[rock] ); */
+   eg debugmsg( "I use %s.\n", ITEMNAMES[rock] ); */
 
 extern char ITEMNAMES[3][MAXITEMLEN];
 
index 10118c1..e75827c 100644 (file)
@@ -41,7 +41,7 @@ class externAgent (BaseAgent):
         
     def Attack (self, foe):
         self.process.sendline( "ATTACK %s" % foe )
-        self.process.expect( "ATTACKING (.+) (.+)\n" )
+        self.process.expect( "ATTACKING (.+) (.+)\r\n" )
         attack, bluff = self.process.match.groups()
         attack, bluff = attack.strip(), bluff.strip()
         return self.stringToItem(attack), self.stringToItem(bluff)
@@ -49,8 +49,10 @@ class externAgent (BaseAgent):
     def Defend( self, foe, bluff ):
         #print "DEFEND %s %s" % (foe, self.itemToString(bluff))
         self.process.sendline( "DEFEND %s %s" % (foe, self.itemToString(bluff) ) )
-        self.process.expect( "DEFENDING (.+)" )
+        self.process.expect( "DEFENDING (.+)\r\n" )
         #print '------------------ ', self.process.match.groups()[0].strip()
         defence = self.process.match.groups()[0].strip()
         return self.stringToItem(defence)
-        
\ No newline at end of file
+        
+    def __del__(self):
+        self.process.close(True)
index 7fa1bf2..e3f5eb5 100755 (executable)
@@ -9,7 +9,7 @@ Licensed under an MIT-style license: see the LICENSE file for details.
 from link.C.c_agents import c_angel, c_lucifer, c_streetfighter, c_frenchie
 
 from SampleAgents import Angel, Lucifer, Dummy, Frenchie, Streetfighter
-Agents = [c_lucifer, Frenchie, c_streetfighter, c_angel]
+Agents = [Lucifer, c_frenchie, c_streetfighter, c_angel]
 
 ####################################
 # Developers only past this point! #

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