1 #include "AntSimulatorFast.hpp"
2 
AntSimulatorFast(unsigned int inMaxMoves)3 AntSimulatorFast::AntSimulatorFast(unsigned int inMaxMoves) :
4         mMaxMoves(inMaxMoves),
5         mNbPiecesAvail(0),
6         mRowStart(0),
7         mColStart(0),
8         mDirectionStart(AntSimulatorFast::eAntEast),
9         mNbMovesAnt(0),
10         mNbPiecesEaten(0),
11         mRowAnt(0),
12         mColAnt(0),
13         mDirectionAnt(AntSimulatorFast::eAntEast)
14     { }
15 
16 
parseMatrix(char * inFileStr)17 void AntSimulatorFast::parseMatrix(char* inFileStr){
18     std::fstream lFileHandle;
19 
20     lFileHandle.open(inFileStr, std::fstream::in);
21 
22     mOrigTrail.resize(ROWS_NBR);
23     mExecTrail.resize(ROWS_NBR);
24     for(unsigned int i = 0; i < ROWS_NBR; i++){
25         mOrigTrail[i].resize(COLS_NBR);
26         mExecTrail[i].resize(COLS_NBR);
27     }
28 
29     char lBuffer;
30     for(unsigned int i=0; i<mOrigTrail.size(); ++i) {
31         for(unsigned int j=0; j<mOrigTrail[i].size(); ++j) {
32             lFileHandle >> lBuffer;
33             switch(lBuffer) {
34             case eStart: {
35                 mOrigTrail[i][j] = eStart;
36                 mRowStart = i;
37                 mColStart = j;
38                 mExecTrail[i][j] = eStart;
39                 break;
40             }
41             case eEmpty:
42             case eFoodPiece: {
43                 mOrigTrail[i][j] = lBuffer;
44                 mExecTrail[i][j] = lBuffer;
45                 break;
46             }
47             case ePassed: {
48                 mOrigTrail[i][j] = eEmpty;
49                 mExecTrail[i][j] = ePassed;
50                 break;
51             }
52             case eEatenPiece: {
53                 mOrigTrail[i][j] = eFoodPiece;
54                 mExecTrail[i][j] = eEatenPiece;
55                 break;
56             }
57             case eAntNorth:
58             case eAntEast:
59             case eAntSouth:
60             case eAntWest: {
61                 mOrigTrail[i][j] = eEmpty;
62                 mExecTrail[i][j] = lBuffer;
63                 break;
64             }
65             default: { }
66             }
67         }
68     }
69     lFileHandle.close();
70 }
71 
72 
turnLeft(void)73 void AntSimulatorFast::turnLeft(void){
74     if(mNbMovesAnt >= mMaxMoves) return;
75     ++mNbMovesAnt;
76     switch(mDirectionAnt) {
77     case eAntNorth: {
78         mDirectionAnt = eAntWest;
79         break;
80     }
81     case eAntEast: {
82         mDirectionAnt = eAntNorth;
83         break;
84     }
85     case eAntSouth: {
86         mDirectionAnt = eAntEast;
87         break;
88     }
89     case eAntWest: {
90         mDirectionAnt = eAntSouth;
91         break;
92     }
93     default: { }
94     }
95 }
96 
turnRight(void)97 void AntSimulatorFast::turnRight(void){
98     if(mNbMovesAnt >= mMaxMoves) return;
99     ++mNbMovesAnt;
100     switch(mDirectionAnt) {
101     case eAntNorth: {
102         mDirectionAnt = eAntEast;
103         break;
104     }
105     case eAntEast: {
106         mDirectionAnt = eAntSouth;
107         break;
108     }
109     case eAntSouth: {
110         mDirectionAnt = eAntWest;
111         break;
112     }
113     case eAntWest: {
114         mDirectionAnt = eAntNorth;
115         break;
116     }
117     default: { }
118     }
119 }
120 
121 
moveForward(void)122 void AntSimulatorFast::moveForward(void){
123     if(mNbMovesAnt >= mMaxMoves) return;
124     ++mNbMovesAnt;
125 
126     switch(mDirectionAnt) {
127     case eAntNorth: {
128         if(mRowAnt == 0) mRowAnt = (mExecTrail.size()-1);
129         else --mRowAnt;
130         break;
131     }
132     case eAntEast: {
133         ++mColAnt;
134         if(mColAnt >= mExecTrail.front().size()) mColAnt = 0;
135         break;
136     }
137     case eAntSouth: {
138         ++mRowAnt;
139         if(mRowAnt >= mExecTrail.size()) mRowAnt = 0;
140         break;
141     }
142     case eAntWest: {
143         if(mColAnt == 0) mColAnt = (mExecTrail.front().size()-1);
144         else --mColAnt;
145         break;
146     }
147     default: { }
148     }
149     switch(mExecTrail[mRowAnt][mColAnt]) {
150     case eStart:
151     case ePassed:
152     case eEatenPiece:
153         break;
154     case eEmpty: {
155         mExecTrail[mRowAnt][mColAnt] = ePassed;
156         break;
157     }
158     case eFoodPiece: {
159         mExecTrail[mRowAnt][mColAnt] = eEatenPiece;
160         ++mNbPiecesEaten;
161         break;
162     }
163     default: { }
164     }
165 }
166 
ifFoodAhead(PyObject * inIfTrue,PyObject * inIfFalse)167 void AntSimulatorFast::ifFoodAhead(PyObject* inIfTrue, PyObject* inIfFalse){
168     unsigned int lAheadRow = mRowAnt;
169     unsigned int lAheadCol = mColAnt;
170     switch(mDirectionAnt) {
171     case eAntNorth: {
172         if(lAheadRow == 0) lAheadRow = (mExecTrail.size()-1);
173         else --lAheadRow;
174         break;
175     }
176     case eAntEast: {
177         ++lAheadCol;
178         if(lAheadCol >= mExecTrail.front().size()) lAheadCol = 0;
179         break;
180     }
181     case eAntSouth: {
182         ++lAheadRow;
183         if(lAheadRow >= mExecTrail.size()) lAheadRow = 0;
184         break;
185     }
186     case eAntWest: {
187         if(lAheadCol == 0) lAheadCol = (mExecTrail.front().size()-1);
188         else --lAheadCol;
189         break;
190     }
191     default: { }
192     }
193 
194     PyObject_CallFunctionObjArgs((mExecTrail[lAheadRow][lAheadCol] == eFoodPiece) ? inIfTrue : inIfFalse, NULL);
195 }
196 
run(PyObject * inWrappedFunc)197 void AntSimulatorFast::run(PyObject* inWrappedFunc){
198     this->reset();
199     while(mNbMovesAnt < mMaxMoves)
200         PyObject_CallFunctionObjArgs(inWrappedFunc, NULL);
201 }
202 
reset(void)203 void AntSimulatorFast::reset(void){
204     mExecTrail = mOrigTrail;
205     mNbMovesAnt = 0;
206     mNbPiecesEaten = 0;
207     mRowAnt = mRowStart;
208     mColAnt = mColStart;
209     mDirectionAnt = mDirectionStart;
210 }
211 
212 
213 /*
214  *
215  * Python wrappers
216  *
217  *
218  */
219 
220 typedef struct {
221     PyObject_HEAD
222     AntSimulatorFast *mInnerClass;
223 } AntSimulatorWrapper;
224 
225 
wrapAntSimulatorConstructor(AntSimulatorWrapper * self,PyObject * args,PyObject * kwargs)226 static int wrapAntSimulatorConstructor(AntSimulatorWrapper *self, PyObject *args, PyObject *kwargs){
227     int lMaxMoves;
228     const char *keywords[] = {"max_moves", NULL};
229 
230     if (!PyArg_ParseTupleAndKeywords(args, kwargs, (char *) "i", (char **) keywords, &lMaxMoves)) {
231         return -1;
232     }
233     self->mInnerClass = new AntSimulatorFast(lMaxMoves);
234     return 0;
235 }
236 
wrapTurnLeft(AntSimulatorWrapper * self)237 static PyObject* wrapTurnLeft(AntSimulatorWrapper *self){
238     self->mInnerClass->turnLeft();
239     Py_INCREF(Py_None);
240     return Py_None;
241 }
242 
wrapTurnRight(AntSimulatorWrapper * self)243 static PyObject* wrapTurnRight(AntSimulatorWrapper *self){
244     self->mInnerClass->turnRight();
245     Py_INCREF(Py_None);
246     return Py_None;
247 }
248 
wrapMoveForward(AntSimulatorWrapper * self)249 static PyObject* wrapMoveForward(AntSimulatorWrapper *self){
250     self->mInnerClass->moveForward();
251     Py_INCREF(Py_None);
252     return Py_None;
253 }
254 
wrapIfFoodAhead(AntSimulatorWrapper * self,PyObject * args)255 static PyObject* wrapIfFoodAhead(AntSimulatorWrapper *self, PyObject *args){
256     self->mInnerClass->ifFoodAhead(PyTuple_GET_ITEM(args, 0),
257                                     PyTuple_GET_ITEM(args, 1));
258     Py_INCREF(Py_None);
259     return Py_None;
260 }
261 
wrapRun(AntSimulatorWrapper * self,PyObject * args)262 static PyObject* wrapRun(AntSimulatorWrapper *self, PyObject *args){
263     PyObject* func = PyTuple_GetItem(args, 0);
264     self->mInnerClass->run(func);
265     Py_INCREF(Py_None);
266     return Py_None;
267 }
268 
wrapParseMatrix(AntSimulatorWrapper * self,PyObject * args)269 static PyObject* wrapParseMatrix(AntSimulatorWrapper *self, PyObject *args){
270     self->mInnerClass->parseMatrix(PyString_AsString(PyFile_Name(PyTuple_GetItem(args, 0))));
271     Py_INCREF(Py_None);
272     return Py_None;
273 }
274 
wrapGetEaten(AntSimulatorWrapper * self,void * closure)275 static PyObject* wrapGetEaten(AntSimulatorWrapper *self, void *closure){
276     PyObject *py_retval;
277 
278     py_retval = Py_BuildValue((char *) "i", self->mInnerClass->mNbPiecesEaten);
279     return py_retval;
280 }
281 
282 // Getters and setters (here only for the 'eaten' attribute)
283 static PyGetSetDef AntSimulatorWrapper_getsets[] = {
284     {
285         (char*) "eaten", /* attribute name */
286         (getter) wrapGetEaten, /* C function to get the attribute */
287         NULL, /* C function to set the attribute */
288         NULL, /* optional doc string */
289         NULL /* optional additional data for getter and setter */
290     },
291     { NULL, NULL, NULL, NULL, NULL }
292 };
293 
294 // Class method declarations
295 static PyMethodDef AntSimulatorWrapper_methods[] = {
296     {(char *) "turn_left", (PyCFunction) wrapTurnLeft, METH_NOARGS, NULL },
297     {(char *) "turn_right", (PyCFunction) wrapTurnRight, METH_NOARGS, NULL },
298     {(char *) "move_forward", (PyCFunction) wrapMoveForward, METH_NOARGS, NULL },
299     {(char *) "if_food_ahead", (PyCFunction) wrapIfFoodAhead, METH_VARARGS, NULL },
300     {(char *) "parse_matrix", (PyCFunction) wrapParseMatrix, METH_VARARGS, NULL },
301     {(char *) "run", (PyCFunction) wrapRun, METH_VARARGS, NULL },
302     {NULL, NULL, 0, NULL}
303 };
304 
AntSimulatorWrapperDealloc(AntSimulatorWrapper * self)305 static void AntSimulatorWrapperDealloc(AntSimulatorWrapper *self){
306     delete self->mInnerClass;
307     self->ob_type->tp_free((PyObject*)self);
308 }
309 
AntSimulatorWrapperRichcompare(AntSimulatorWrapper * self,AntSimulatorWrapper * other,int opid)310 static PyObject* AntSimulatorWrapperRichcompare(AntSimulatorWrapper *self, AntSimulatorWrapper *other, int opid){
311     Py_INCREF(Py_NotImplemented);
312     return Py_NotImplemented;
313 }
314 
315 
316 PyTypeObject AntSimulatorWrapper_Type = {
317     PyObject_HEAD_INIT(NULL)
318     0,                                 /* ob_size */
319     (char *) "AntC.AntSimulatorFast",            /* tp_name */
320     sizeof(AntSimulatorWrapper),                  /* tp_basicsize */
321     0,                                 /* tp_itemsize */
322     /* methods */
323     (destructor)AntSimulatorWrapperDealloc,        /* tp_dealloc */
324     (printfunc)0,                      /* tp_print */
325     (getattrfunc)NULL,       /* tp_getattr */
326     (setattrfunc)NULL,       /* tp_setattr */
327     (cmpfunc)NULL,           /* tp_compare */
328     (reprfunc)NULL,             /* tp_repr */
329     (PyNumberMethods*)NULL,     /* tp_as_number */
330     (PySequenceMethods*)NULL, /* tp_as_sequence */
331     (PyMappingMethods*)NULL,   /* tp_as_mapping */
332     (hashfunc)NULL,             /* tp_hash */
333     (ternaryfunc)NULL,          /* tp_call */
334     (reprfunc)NULL,              /* tp_str */
335     (getattrofunc)NULL,     /* tp_getattro */
336     (setattrofunc)NULL,     /* tp_setattro */
337     (PyBufferProcs*)NULL,  /* tp_as_buffer */
338     Py_TPFLAGS_DEFAULT,                      /* tp_flags */
339     NULL,                        /* Documentation string */
340     (traverseproc)NULL,     /* tp_traverse */
341     (inquiry)NULL,             /* tp_clear */
342     (richcmpfunc)AntSimulatorWrapperRichcompare,   /* tp_richcompare */
343     0,             /* tp_weaklistoffset */
344     (getiterfunc)NULL,          /* tp_iter */
345     (iternextfunc)NULL,     /* tp_iternext */
346     (struct PyMethodDef*)AntSimulatorWrapper_methods, /* tp_methods */
347     (struct PyMemberDef*)0,              /* tp_members */
348     AntSimulatorWrapper_getsets,                     /* tp_getset */
349     NULL,                              /* tp_base */
350     NULL,                              /* tp_dict */
351     (descrgetfunc)NULL,    /* tp_descr_get */
352     (descrsetfunc)NULL,    /* tp_descr_set */
353     0,                 /* tp_dictoffset */
354     (initproc)wrapAntSimulatorConstructor,             /* tp_init */
355     (allocfunc)PyType_GenericAlloc,           /* tp_alloc */
356     (newfunc)PyType_GenericNew,               /* tp_new */
357     (freefunc)0,             /* tp_free */
358     (inquiry)NULL,             /* tp_is_gc */
359     NULL,                              /* tp_bases */
360     NULL,                              /* tp_mro */
361     NULL,                              /* tp_cache */
362     NULL,                              /* tp_subclasses */
363     NULL,                              /* tp_weaklist */
364     (destructor) NULL                  /* tp_del */
365 };
366 
progn(PyObject * self,PyObject * args)367 PyObject* progn(PyObject *self, PyObject *args){
368     for(Py_ssize_t i = 0; i < PyTuple_Size(args); i++)
369         PyObject_CallFunctionObjArgs(PyTuple_GET_ITEM(args, i), NULL);
370     Py_INCREF(Py_None);
371     return Py_None;
372 }
373 
374 static PyMethodDef AntC_functions[] = {
375     {"progn", progn, METH_VARARGS, "Boum"},
376     {NULL, NULL, 0, NULL}
377 };
378 
379 PyMODINIT_FUNC
initAntC(void)380 initAntC(void)
381 {
382     PyObject *m;
383     m = Py_InitModule3((char *) "AntC", AntC_functions, NULL);
384     if (m == NULL) {
385         return;
386     }
387     /* Register the 'AntSimulatorWrapper' class */
388     if (PyType_Ready(&AntSimulatorWrapper_Type)) {
389         return;
390     }
391     PyModule_AddObject(m, (char *) "AntSimulatorFast", (PyObject *) &AntSimulatorWrapper_Type);
392 }
393