# gcc noise
*.o
*.a
+*.dSYM
# old skool
.svn
-agents/
!agents/*.c
+agents/*
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)
$(AGENTS): $(AGENTSRCS) $(LINKLIB)
@echo Building $@
.c.o: c_link.h
- $(CC) -c $(CFLAGS) $< -o $@
+ $(CC) -c $(myCFLAGS) $< -o $@
.PHONY : clean
clean:
--- /dev/null
+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]
+
+++ /dev/null
-/*
- * 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
--- /dev/null
+/*
+ * 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
attack.promisedAttack = paper;
break;
}
- attack.promisedAttack = attack.realAttack; /* Tells the truth for its bluff */
return attack;
}
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 */
08FB7794FE84155DC02AAC07 /* c-link-lib */ = {
isa = PBXGroup;
children = (
+ 22CAFECF11D48750001ECDEF /* README */,
2208AFE7118F28F400770C92 /* c_agents.py */,
2291A1BC117EE3FD00854CBE /* agents */,
22F652F6117C6C9500A3793D /* c_link.h */,
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) {
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];
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)
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)
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! #