e0d0357cbb325740cca90c33ed1dd75ddb49905f
[progcomp10.git] / src / link / C / agents / c_wash.c
1 /*
2  *  c_wash.c
3  *  c-link-lib
4  *
5  *  Created by Daniel Axtens on 22/04/10.
6  *  Licensed under an MIT-style license: see the LICENSE file for details.
7  *
8  */
9
10 #include <c_link.h>
11 #include <stdlib.h>
12 #include <string.h>
13
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
18        and subclass it.
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)
23  */
24
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. */
29
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
34
35 /* data for each instance of my agent */
36 typedef struct {
37         /* The name of the n-th foe who has beaten us */
38         char (*defeatingFoes)[MAXAGENTNAMELEN];
39
40         /* The length of the array, and how far we are along it */
41         size_t foesLen;
42         unsigned int foesCount;
43 } wash_data;
44
45
46 /* an internal function - have I lost to a given foe? */
47 int haveLostTo( wash_data * me, char * foeName ) {
48     
49         int foe;
50     
51     /* check every foe we know to have defeated us */
52     for (foe=0; foe<me->foesCount; foe++) {
53         if (strncmp( me->defeatingFoes[foe], foeName, MAXAGENTNAMELEN) == 0) {
54             //debugmsg( "%d\thaveLostTo( %s ) -> Yes\n", me, foeName );
55             return 1;
56         }
57     }
58     
59     /* this foe not found */
60     return 0;
61 }
62
63 /* set up myself */
64 void * Initialise( char * myName ) {
65         wash_data * me = malloc( sizeof( wash_data ) );
66         
67         me->defeatingFoes = calloc( NUMBEROFAGENTSGUESS, sizeof( MAXAGENTNAMELEN*sizeof(char) ) );
68         me->foesLen = NUMBEROFAGENTSGUESS;
69     me->foesCount = 0;
70         
71         return (void *) me;
72 }
73
74 /* Attack */
75 ATTACKTYPE Attack( void * this, char * foeName ) {
76         wash_data * me = (wash_data *)this;
77     
78         ATTACKTYPE attack;
79         
80         attack.realAttack =  RandomAttack();
81         
82     /* have I lost to this foe? */
83     if ( haveLostTo(me, foeName) ) {
84         /* Assume they are lying  */
85         switch (attack.realAttack) {
86             case rock:
87                 attack.promisedAttack = scissors;
88                 break;
89             case paper:
90                 attack.promisedAttack = rock;
91                 break;
92             default: /* attack = scissors */
93                 attack.promisedAttack = paper;
94                 break;
95         }
96     } else {
97         /* be nice! */
98         attack.promisedAttack = attack.realAttack;
99     }
100
101         
102         return attack;
103 }
104
105 /* defend */
106 ITEMTYPE Defend( void * this, char * foeName, ITEMTYPE foePromisedAttack ) {
107         wash_data * me = (wash_data *)this;
108         
109         ITEMTYPE defence;
110         
111     if (haveLostTo(me, foeName)) {
112         /* They've screwed us in the past, assume they're lying and go for the
113            kill. */
114         switch (foePromisedAttack) {
115             case rock:
116                 defence = scissors;
117                 break;
118             case paper:
119                 defence = rock;
120                 break;
121             default:
122                 defence = paper;
123                 break;
124         }
125     } else {
126         /* be nice! */
127         defence = foePromisedAttack;
128     }
129
130     return defence;
131 }
132
133 /* This is so much less fun in C */
134 void Results( void * this, char * foeName, int isInstigatedByYou, 
135                          RESULTTYPE winner, ITEMTYPE attItem, ITEMTYPE defItem, 
136                          ITEMTYPE bluffItem, int pointDelta ) {
137         
138     wash_data * me = (wash_data *)this;
139         
140         int foe;
141     
142     /* figure out if we lost, which is the only thing we care about
143        if we didn't, move on. */
144     if ((winner == tie) || 
145         (winner==attacker && isInstigatedByYou) ||
146         (winner==defender && !isInstigatedByYou) ) return;
147     
148     //fprintf( stderr, "%d\tsaving loss from %s\n", me, foeName );
149     
150     /* if we've already lost the foe, don't store again */
151     for (foe=0; foe<me->foesCount; foe++) {
152         if (strncmp( me->defeatingFoes[foe], foeName, MAXAGENTNAMELEN ) == 0) {
153             /* we've found it! */
154             return;
155         }
156     }
157     
158     /* we haven't found the foe. add it, expanding the array if needed */
159     if (me->foesCount==me->foesLen) {
160         /* double the array size. This should error check, but doesn't */
161         me->defeatingFoes = realloc( me->defeatingFoes, 
162                                              me->foesLen*2*sizeof( MAXAGENTNAMELEN*sizeof(char) ) );
163         me->foesLen *= 2;
164     }
165     
166     strncpy( me->defeatingFoes[me->foesCount], foeName, MAXAGENTNAMELEN );
167     me->foesCount++;
168     
169     return;
170 }
171
172 /* Cleanup */
173 void Cleanup( void * this ) {
174         wash_data * me = (wash_data *) this;
175         free(me->defeatingFoes);
176         free(me);
177 }

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