Work towards C SDK (#11). Frenchie is still broken.
[progcomp10.git] / src / link / C / agents / c_frenchie.c
1 /*
2  *  c_frechie.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 frenchie bot, 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 /* The name of the n-th foe who has beaten us */
36 char (*defeatingFoes)[MAXFOENAMELEN] = NULL;
37
38 /* The length of the array, and how far we are along it */
39 size_t foesLen = 0;
40 unsigned int foesCount = 0;
41
42 /* an internal function - have I lost to a given foe? */
43 int haveLostTo( char * foeName ) {
44     int foe;
45     
46     /* check every foe we know to have defeated us */
47     for (foe=0; foe<foesCount; foe++) {
48         if (strncmp( defeatingFoes[foe], foeName, MAXFOENAMELEN) == 0) {
49             debugmsg( "%d\thaveLostTo( %s ) -> Yes\n", me, foeName );
50             return 1;
51         }
52     }
53     
54     /* this foe not found */
55     return 0;
56 }
57
58
59 ATTACKTYPE Attack( char * foeName ) {
60         ATTACKTYPE attack;
61     
62         attack.realAttack =  RandomAttack();
63         
64     /* have I lost to this foe? */
65     if ( haveLostTo(foeName) ) {
66         /* Assume they are lying (FIXME: I'm not entirely sure why the python
67            does what it does: I'm just duplicating.) */
68         switch (attack.realAttack) {
69             case rock:
70                 attack.promisedAttack = scissors;
71                 break;
72             case paper:
73                 attack.promisedAttack = rock;
74                 break;
75             default: /* attack = scissors */
76                 attack.promisedAttack = paper;
77                 break;
78         }
79     } else {
80         /* be nice! */
81         attack.promisedAttack = attack.realAttack;
82     }
83
84         
85         return attack;
86 }
87
88
89 ITEMTYPE Defend( char * foeName, ITEMTYPE foePromisedAttack ) {
90         ITEMTYPE defence;
91         
92     if (haveLostTo(foeName)) {
93         /* They've screwed us in the past, assume they're lying and go for the
94            kill. */
95         switch (foePromisedAttack) {
96             case rock:
97                 defence = scissors;
98                 break;
99             case paper:
100                 defence = rock;
101                 break;
102             default:
103                 defence = paper;
104                 break;
105         }
106     } else {
107         /* be nice! */
108         defence = foePromisedAttack;
109     }
110
111     return defence;
112 }
113
114 /* This is so much less fun in C */
115 void Results( char * foeName, int isInstigatedByYou, ITEMTYPE yourItem, 
116                          ITEMTYPE theirItem, ITEMTYPE promisedItem) {
117         
118     int foe;
119     
120     /* check to see if we've initialised our arrays */
121         if (defeatingFoes == NULL) {
122         defeatingFoes = calloc( NUMBEROFAGENTSGUESS, sizeof( MAXFOENAMELEN*sizeof(char) ) );
123         foesLen = NUMBEROFAGENTSGUESS;
124     }
125     
126     /* figure out if we lost, which is the only thing we care about
127        if we didn't, move on. */
128     if (RESULTOF[yourItem][theirItem] != lose) return;
129     
130     fprintf( stderr, "%d\tsaving loss from %s\n", me, foeName );
131     
132     /* if we've already lost the foe, don't store again */
133     for (foe=0; foe<foesCount; foe++) {
134         if (strncmp( defeatingFoes[foe], foeName, MAXFOENAMELEN ) == 0) {
135             /* we've found it! */
136             return;
137         }
138     }
139     
140     /* we haven't found the foe. add it, expanding the array if needed */
141     if (foesCount==foesLen) {
142         /* double the array size */
143         defeatingFoes = realloc( defeatingFoes, foesLen*2*sizeof( MAXFOENAMELEN*sizeof(char) ) );
144         foesLen *= 2;
145     }
146     
147     strncpy( defeatingFoes[foesCount], foeName, MAXFOENAMELEN );
148     foesCount++;
149     
150     return;
151 }
152
153 /* same for Cleanup() */
154
155 void Cleanup() {
156         free(defeatingFoes);
157 }

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