5 * Created by Daniel Axtens on 22/04/10.
6 * Licensed under an MIT-style license: see the LICENSE file for details.
14 /* Implement the wash agent, that is by default nice but will
15 permanently turn against any agent that betrays it.
16 This is trickier in C than in any other language, for a number of reasons:
17 - there's no classes in C, so we can't just write a generic learning agent
19 - your agent has no idea how many agents it's going to battle, or how many
20 battles it is going to fight, so you've got to do dynamic memory allocation.
21 (anyone who tries to read the source of the supervisor to find out is liable
22 to have their program break unexpectedly)
25 /* To simplify things, we just look at whether we have lost to a particular agent.
26 Unlike in the Python version, we don't keep a generic list
27 This is also done in a inefficient (O(bot-cout)) way.
28 Implementing a faster version is left as an exercise to the DSA student. */
30 /* Our guess at the number of agents I'm going to fight in my lifetime
31 (note that this is only a guess, not an upper limit. Do *not* take it as
32 gospel on the number of agents you're going to see. */
33 #define NUMBEROFAGENTSGUESS 100
35 typedef char agentName[MAXAGENTNAMELEN];
37 /* data for each instance of my agent */
39 /* The name of the n-th foe who has beaten us */
40 agentName * defeatingFoes;
42 /* The length of the array, and how far we are along it */
44 unsigned int foesCount;
48 /* an internal function - have I lost to a given foe? */
49 int haveLostTo( wash_data * me, char * foeName ) {
53 /* check every foe we know to have defeated us */
54 for (foe=0; foe<me->foesCount; foe++) {
55 if (strncmp( me->defeatingFoes[foe], foeName, MAXAGENTNAMELEN) == 0) {
56 //debugmsg( "%d\thaveLostTo( %s ) -> Yes\n", me, foeName );
61 /* this foe not found */
66 void * Initialise( char * myName ) {
67 wash_data * me = malloc( sizeof( wash_data ) );
69 me->defeatingFoes = calloc( NUMBEROFAGENTSGUESS, sizeof( agentName ) );
70 me->foesLen = NUMBEROFAGENTSGUESS;
77 ATTACKTYPE Attack( void * this, char * foeName ) {
78 wash_data * me = (wash_data *)this;
82 attack.realAttack = RandomAttack();
84 /* have I lost to this foe? */
85 if ( haveLostTo(me, foeName) ) {
86 /* Assume they are lying */
87 switch (attack.realAttack) {
89 attack.promisedAttack = scissors;
92 attack.promisedAttack = rock;
94 default: /* attack = scissors */
95 attack.promisedAttack = paper;
100 attack.promisedAttack = attack.realAttack;
108 ITEMTYPE Defend( void * this, char * foeName, ITEMTYPE foePromisedAttack ) {
109 wash_data * me = (wash_data *)this;
113 if (haveLostTo(me, foeName)) {
114 /* They've screwed us in the past, assume they're lying and go for the
116 switch (foePromisedAttack) {
129 defence = foePromisedAttack;
135 /* This is so much less fun in C */
136 void Results( void * this, char * foeName, int isInstigatedByYou,
137 RESULTTYPE winner, ITEMTYPE attItem, ITEMTYPE defItem,
138 ITEMTYPE bluffItem, int pointDelta ) {
140 wash_data * me = (wash_data *)this;
144 /* figure out if we lost, which is the only thing we care about
145 if we didn't, move on. */
146 if ((winner == tie) ||
147 (winner==attacker && isInstigatedByYou) ||
148 (winner==defender && !isInstigatedByYou) ) return;
150 //fprintf( stderr, "%d\tsaving loss from %s\n", me, foeName );
152 /* if we've already lost the foe, don't store again */
153 for (foe=0; foe<me->foesCount; foe++) {
154 if (strncmp( me->defeatingFoes[foe], foeName, MAXAGENTNAMELEN ) == 0) {
155 /* we've found it! */
160 /* we haven't found the foe. add it, expanding the array if needed */
161 if (me->foesCount==me->foesLen) {
162 /* double the array size. This should error check, but doesn't */
163 me->defeatingFoes = realloc( me->defeatingFoes,
164 me->foesLen*2*sizeof( agentName ) );
168 strncpy( me->defeatingFoes[me->foesCount], foeName, MAXAGENTNAMELEN );
175 void Cleanup( void * this ) {
176 wash_data * me = (wash_data *) this;
177 free(me->defeatingFoes);