Upstream release 4.02a
[rice.git] / examples / game.c
blob11add4c5fcb350ade4cd6ebd4b67f32864ba7ead
1 /*
2 File: game.c
3 Author: Rene' Jager
4 Update: June 17, 1993
5 Info: game example for RICE
6 */
9 /* header files */
11 #include <stdlib.h>
12 #include <stdio.h>
13 #include <stdarg.h>
14 #include <time.h>
16 #include <rice.h>
19 /* global variables */
21 int stopGame = 0, autoGame = 0;
22 int myMark, yourMark, emptyMark = ' ';
23 int xTable[] = {0, 36, 40, 44}, yTable[] = {0, 10, 12, 14};
24 int fieldTable[3][3] = {{' ', ' ', ' '}, {' ', ' ', ' '}, {' ', ' ', ' '}};
25 int nrOfMoves = 0;
28 /* compiler dependent functions, for different compilers: adjust code */
30 #if defined(_MSC_VER) || defined(_QC)
31 # define __MICROSOFTC__
32 #endif
35 #if defined(__MICROSOFTC__)
37 /* this part is coded for use with Microsoft C(++) 7.00 compiler */
39 #include <graph.h>
42 /* hiding and showing cursor */
44 #define hideCursor() _displaycursor(_GCURSOROFF)
45 #define showCursor() _displaycursor(_GCURSORON)
48 /* goto position on screen */
50 #define gotoPos(x, y) _settextposition(y, x)
53 /* goto position and put character */
55 #define putChar(x, y, c) gotoPos(x, y); _putch(c)
58 /* write mark to screen */
60 void putMark(int x, int y, int c)
62 putChar(xTable[x], yTable[y], c);
63 fieldTable[x - 1][y - 1] = c;
67 /* clear screen */
69 #define clearScreen() _clearscreen(_GCLEARSCREEN)
72 #elif defined(__BORLANDC__)
75 /* this part is coded for use with Borland C(++) 3.1 compiler */
77 #include <conio.h>
80 /* hiding and showing cursor */
82 #define hideCursor() _setcursortype(_NOCURSOR)
83 #define showCursor() _setcursortype(_NORMALCURSOR)
86 /* goto position on screen */
88 #define gotoPos(x, y) gotoxy(x, y)
91 /* goto position and put character */
93 #define putChar(x, y, c) gotoPos(x, y); putchar(c)
96 /* write mark to screen */
98 void putMark(int x, int y, int c)
100 unsigned char buf[2];
101 gettext(xTable[x], yTable[y], xTable[x], yTable[y], buf);
102 fieldTable[x - 1][y - 1] = buf[0] = c;
103 puttext(xTable[x], yTable[y], xTable[x], yTable[y], buf);
107 /* clear screen */
109 #define clearScreen() clrscr()
112 /* increase stack length */
114 extern unsigned _stklen = 10000U;
116 #elif defined(__GNUC__) & defined(__MSDOS__)
119 /* this part is coded for use with Gnu C++ (DJGPP 2.4.1) compiler */
121 #include <conio.h> /* dummy header file including gppconio.h */
124 /* hiding and showing cursor */
126 #define hideCursor() _setcursortype(_NOCURSOR)
127 #define showCursor() _setcursortype(_NORMALCURSOR)
130 /* goto position on screen */
132 #define gotoPos(x, y) gotoxy(x, y)
135 /* goto position and put character */
137 #define putChar(x, y, c) gotoPos(x, y); putch(c)
140 /* write mark to screen */
142 void putMark(int x, int y, int c)
144 unsigned char buf[2];
145 gettext(xTable[x], yTable[y], xTable[x], yTable[y], buf);
146 fieldTable[x - 1][y - 1] = buf[0] = c;
147 puttext(xTable[x], yTable[y], xTable[x], yTable[y], buf);
151 /* clear screen */
153 #define clearScreen() clrscr()
156 #else
157 # error Compiler should be Microsoft C/C++ 7.0 or Borland C++ 3.1
158 #endif
161 /* prototypes */
163 void printMsg(char *, ...);
166 /* get mark from field */
168 int getMark(int x, int y)
170 return fieldTable[x - 1][y - 1];
174 /* sawp marks */
176 void SwapMark(int *m1, int *m2)
178 int m;
180 m = *m1;
181 *m1 = *m2;
182 *m2 = m;
186 /* do error */
188 void doError(char *msg)
190 gotoPos(1, 15);
191 printMsg(0);
192 gotoPos(1, 15);
193 printMsg("\x7Error: %s\n", msg);
196 void redirError(int kb, int type, char *msg)
198 doError(msg);
202 /* show message from kb */
204 void showInfo(char *msg)
206 if(autoGame) /* just play, don't talk */
207 return;
209 gotoPos(1, 15);
210 printMsg(0);
211 gotoPos(1, 15);
212 printMsg(msg);
215 void redirInfo(int kb, int argc, char *argv[], float *grade)
217 showInfo(argv[0]);
221 /* show field on screen */
223 void makeField(void)
225 int x, y;
227 x = xTable[2];
228 y = yTable[2];
230 putChar(x - 7, y - 2, 'a');
231 putChar(x - 7, y, 'b');
232 putChar(x - 7, y + 2, 'c');
234 putChar(x - 4, y - 3, '1');
235 putChar(x, y - 3, '2');
236 putChar(x + 4, y - 3, '3');
238 putChar(x - 2, y - 2, 179);
239 putChar(x - 2, y - 1, 179);
240 putChar(x - 2, y, 179);
241 putChar(x - 2, y + 1, 179);
242 putChar(x - 2, y + 2, 179);
243 putChar(x + 2, y - 2, 179);
244 putChar(x + 2, y - 1, 179);
245 putChar(x + 2, y , 179);
246 putChar(x + 2, y + 1, 179);
247 putChar(x + 2, y + 2, 179);
249 putChar(x - 5, y - 1, 196);
250 putChar(x - 4, y - 1, 196);
251 putChar(x - 3, y - 1, 196);
252 putChar(x - 3, y + 1, 196);
253 putChar(x - 4, y + 1, 196);
254 putChar(x - 5, y + 1, 196);
255 putChar(x - 1, y - 1, 196);
256 putChar(x, y - 1, 196);
257 putChar(x + 1, y + 1, 196);
258 putChar(x - 1, y + 1, 196);
259 putChar(x, y + 1, 196);
260 putChar(x + 1, y - 1, 196);
261 putChar(x + 5, y - 1, 196);
262 putChar(x + 4, y - 1, 196);
263 putChar(x + 3, y - 1, 196);
264 putChar(x + 3, y + 1, 196);
265 putChar(x + 4, y + 1, 196);
266 putChar(x + 5, y + 1, 196);
268 putChar(x - 2, y - 1, 197);
269 putChar(x - 2, y + 1, 197);
270 putChar(x + 2, y - 1, 197);
271 putChar(x + 2, y + 1, 197);
275 /* get position */
277 int getPos(int argc, char *argv[], int *x, int *y)
279 if(argc != 2)
281 doError("incomplete position");
282 return -1;
284 *x = argv[1][1] - '1' + 1;
285 *y = argv[1][0] - 'a' + 1;
286 if(*x < 1 || 3 < *x || *y < 1 || 3 < *y)
288 doError("incorrect position");
289 return -1;
291 return 0;
295 /* print a message */
297 void printMsg(char *msg, ...)
299 va_list arguments;
301 if(!msg) /* clear line: dirty, but working */
302 printf(" ");
303 else
305 va_start(arguments, msg);
306 vprintf(msg, arguments);
307 va_end(arguments);
309 fflush(stdout);
313 /* get your mark */
315 void getYourMark(void)
317 do {
318 gotoPos(1, 25);
319 printMsg(0);
320 gotoPos(1, 25);
321 showCursor();
322 printMsg("Put your mark (o/x): ");
323 yourMark = getche();
324 hideCursor();
325 } while(yourMark != 'o' && yourMark != 'x');
327 myMark = (yourMark == 'o') ? 'x' : 'o';
331 /* get your move */
333 void getMove(void)
335 int x, y;
336 do {
337 do {
338 gotoPos(1, 25);
339 printMsg(0);
340 gotoPos(1, 25);
341 showCursor();
342 printMsg("Your move [a..c][1..3]: ");
343 fflush(stdout);
344 y = getche();
345 y -= 'a' - 1;
346 x = getche();
347 x -= '1' - 1;
348 hideCursor();
349 } while(x < 1 || x > 3 || y < 1 || y > 3);
350 } while(getMark(x, y) != emptyMark);
352 putMark(x, y, yourMark);
353 nrOfMoves++;
354 gotoPos(1, 25);
355 printMsg(0);
359 /* linker function */
361 RICE_Linker(theLinkerFunction)
363 RICE_Link("put me on",
365 int x; int y;
366 if(getPos(rice_argc, rice_argv, &x, &y)) return;
367 putMark(x, y, myMark);
368 nrOfMoves++;
371 RICE_Link("I am on",
373 int x; int y;
374 if(getPos(rice_argc, rice_argv, &x, &y)) return;
375 *rice_grade = (getMark(x, y) == myMark) ? 1.0 : 0.0;
378 RICE_Link("you are on",
380 int x; int y;
381 if(getPos(rice_argc, rice_argv, &x, &y)) return;
382 *rice_grade = (getMark(x, y) == yourMark) ? 1.0 : 0.0;
385 RICE_Link("is empty",
387 int x; int y;
388 if(getPos(rice_argc, rice_argv, &x, &y)) return;
389 *rice_grade = (getMark(x, y) == emptyMark) ? 1.0 : 0.0;
392 RICE_Link("put me somewhere",
393 putMark(1 + rand()%3, 1 + rand()%3, myMark);
394 nrOfMoves++;
397 RICE_Link("stop the game", stopGame = 1);
400 RICE_LINKER theLinker = theLinkerFunction;
403 /* main function */
405 #define GAME_KB "game.kb"
407 int main(int argc, char *argv[])
409 int theES, theOtherES = 0;
411 /* init dice */
412 srand(time(0));
414 /* auto game */
415 autoGame = (argc > 1);
417 /* put field on screen */
418 hideCursor();
419 clearScreen();
420 makeField();
422 /* create and set up knowledge base */
423 theES = rice_CreateES();
424 rice_SetInteractive(theES, 0);
425 rice_RedirectReport(theES, redirError);
426 rice_RedirectInform(theES, redirInfo);
427 rice_UseLinker(theES, 1, &theLinker);
428 if(rice_CompileKB(theES, GAME_KB))
430 showCursor();
431 exit(1);
434 if(autoGame) /* if autonomous game */
436 theOtherES = rice_CopyES(0, theES);
437 if(argc > 1 && rice_CompileKB(theOtherES, (argc > 1) ? argv[1] : GAME_KB))
439 showCursor();
440 exit(1);
444 /* get your mark */
445 if(autoGame)
447 yourMark = 'x';
448 myMark = 'o';
450 else
451 getYourMark();
453 /* throw dice for starting */
454 if(rand() > RAND_MAX/2) /* other is first */
455 if(autoGame)
457 SwapMark(&yourMark, &myMark);
458 rice_InferKB(theOtherES);
459 SwapMark(&yourMark, &myMark);
461 else
462 getMove();
464 /* play game */
465 while(!stopGame && nrOfMoves < 9)
467 rice_ClearKB(theES);
468 rice_InferKB(theES);
470 if(!stopGame && nrOfMoves < 9)
471 if(autoGame)
473 SwapMark(&yourMark, &myMark);
474 rice_ClearKB(theOtherES);
475 rice_InferKB(theOtherES);
476 SwapMark(&yourMark, &myMark);
478 else
479 getMove();
482 /* goto bottom of screen */
483 gotoPos(1, 25);
485 /* clean up expert systems */
486 rice_DeleteES(theES);
487 if(theOtherES) rice_DeleteES(theOtherES);
489 showCursor();
491 return 0;