home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 22 / AACD 22.iso / AACD / Games / Connect4 / source / computer_player.c next >
Encoding:
C/C++ Source or Header  |  2001-05-13  |  9.0 KB  |  341 lines

  1. #include "computer_player.h"
  2. #include "gameboardclass.h"
  3. #include <stdlib.h>
  4. #include <stdio.h>
  5. #include <resources/battclock.h>
  6. #include <clib/exec_protos.h>
  7. #include <clib/battclock_protos.h>
  8.  
  9. //#define THREE_S_DEBUG
  10. //#define THREE_WE_DEBUG
  11. //#define THREE_NWSE_DEBUG
  12. //#define THREE_NESW_DEBUG
  13.  
  14. /*
  15. **  Inputs:
  16. **          skill_level     1 being the lowest skill level
  17. **                          1 being the highest skill level
  18. **          filled          2D array describing gameboard contents
  19. **          columntop       array giving row number of topmost piece in each column
  20. **          current_player  see "gameboardclass.h" for details
  21. **          newgame         boolean switch to initialise player before each game
  22. **
  23. **  Result:
  24. **          Computer player's choice of column in which to place piece
  25. **          -1 on error
  26. */
  27. APTR BattClockBase=NULL;
  28.  
  29. int computer_player (int skill_level, char (*filled)[5], char *columntop, ULONG current_player, BOOL newgame)
  30. {
  31.     enum {ERROR=-1};
  32.  
  33.     if (BattClockBase=OpenResource(BATTCLOCKNAME))
  34.     {
  35.         if (newgame)
  36.             srand(ReadBattClock()); // Seed the random generator with the system clock
  37.                                     // to ensure the moves are different each time
  38.         switch (skill_level)
  39.         {
  40.             // just needs columntop
  41.             case 1:
  42.             {
  43.                 int result;
  44.                 BOOL badmove=TRUE;
  45.  
  46.                 while (badmove)
  47.                 {
  48.                     result=rand();
  49.                     result-=(result/7)*7;
  50.                     if (columntop[result]!=4)
  51.                         badmove=FALSE;
  52.                 }
  53.  
  54.                 return result;
  55.             }
  56.  
  57.             case 2:
  58.             {
  59.                 int result;
  60.                 ULONG opponent;
  61.  
  62.                 if (current_player=red_player)
  63.                     opponent=yellow_player;
  64.                 else
  65.                     opponent=red_player;
  66.  
  67.                 if ((result=capthree(filled, columntop, opponent))!=-1)
  68.                     return result;
  69.  
  70.                 {
  71.                     BOOL badmove=TRUE;
  72.  
  73.                     while (badmove)
  74.                     {
  75.                         result=rand();
  76.                         result-=(result/7)*7;
  77.                         if (columntop[result]!=4)
  78.                             badmove=FALSE;
  79.                     }
  80.  
  81.                     return result;
  82.                 }
  83.             }
  84.  
  85.             default:
  86.                 return ERROR;
  87.         }
  88.     }
  89.  
  90.     return ERROR;
  91. }
  92.  
  93.  
  94. // calls helper functions three[S|WE|NWSE|NESW] to try and stop an opponent's
  95. // line of three turning into *gulp* a line of four!
  96. int capthree (char (*filled)[5], char *columntop, ULONG opponent)
  97. {
  98.     int result;
  99.  
  100.     if ((result=threeS(filled, columntop, opponent))!=-1)
  101.     {
  102.         #ifdef THREE_S_DEBUG
  103.         printf("threeS=%d\n", result);
  104.         #endif
  105.         return result;
  106.     }
  107.  
  108.     if ((result=threeWE(filled, columntop, opponent))!=-1)
  109.     {
  110.         #ifdef THREE_WE_DEBUG
  111.         printf("threeWE=%d\n", result);
  112.         #endif
  113.         return result;
  114.     }
  115.  
  116.     if ((result=threeNWSE(filled, columntop, opponent))!=-1)
  117.     {
  118.         #ifdef THREE_NWSE_DEBUG
  119.         printf("threeNWSE=%d\n", result);
  120.         #endif
  121.         return result;
  122.     }
  123.  
  124.     if ((result=threeNESW(filled, columntop, opponent))!=-1)
  125.     {
  126.         #ifdef THREE_NESW_DEBUG
  127.         printf("threeNESW=%d\n", result);
  128.         #endif
  129.         return result;
  130.     }
  131.  
  132.     return -1;
  133. }
  134.  
  135. int threeS (char (*filled)[5], char *columntop, ULONG opponent)
  136. {
  137.     char column;
  138.  
  139.     for (column=0; column<7; column++)
  140.     {
  141.         #ifdef THREE_S_DEBUG
  142.         printf("column=%d\n", column);
  143.         #endif
  144.         if (columntop[column]!=4 && columntop[column]!=-1)   // Only examine the column if it isn't already full or isn't completely empty
  145.         {      
  146.             char row, oppcount=0;
  147.             #ifdef THREE_S_DEBUG
  148.             printf("  scanning...\n");
  149.             #endif
  150.             for (row=0; row<=columntop[column]; row++)
  151.             {
  152.                 #ifdef THREE_S_DEBUG
  153.                 printf("    row=%d\n", row);
  154.                 #endif
  155.                 if (filled[column][row]==opponent)
  156.                     oppcount++;
  157.                 else
  158.                     oppcount=0;
  159.                 #ifdef THREE_S_DEBUG
  160.                 printf("      oppcount=%d\n", oppcount);
  161.                 #endif
  162.             }
  163.  
  164.             if (oppcount==3)    // opponent has a vertical line of 3 pieces
  165.                 return column;
  166.         }
  167.         #ifdef THREE_S_DEBUG
  168.         else
  169.             puts("  skipped");
  170.         puts("");
  171.         #endif
  172.     }
  173.  
  174.     return -1;
  175. }
  176.  
  177.  
  178. int threeWE (char (*filled)[5], char *columntop, ULONG opponent)
  179. {
  180.     char column, row, potential, emptyhole;
  181.     enum {EMPTYHOLE=-1};
  182.  
  183.     for (row=0; row<5; row++)
  184.     {
  185.         #ifdef THREE_WE_DEBUG
  186.         printf("row=%d\n", row);
  187.         #endif
  188.         potential=0;
  189.         emptyhole=EMPTYHOLE;
  190.         for (column=0; column<7; column++)
  191.         {
  192.             if (filled[column][row]==EMPTYHOLE && emptyhole==EMPTYHOLE)
  193.             {
  194.                 emptyhole=column;   
  195.                 potential++;
  196.                 #ifdef THREE_WE_DEBUG
  197.                 printf("  emptyhole=%d  potential=%d\n", emptyhole, potential);
  198.                 #endif
  199.             }
  200.             else if (filled[column][row]==opponent)
  201.             {
  202.                 potential++;
  203.                 #ifdef THREE_WE_DEBUG
  204.                 printf("  potential=%d\n", potential);
  205.                 #endif
  206.             }
  207.             else
  208.             {
  209.                 potential=0;
  210.                 emptyhole=EMPTYHOLE;
  211.                 #ifdef THREE_WE_DEBUG
  212.                 puts("  potential reset");
  213.                 #endif
  214.             }
  215.  
  216.             if (potential==4)
  217.                 return emptyhole;
  218.         }
  219.  
  220.     }
  221.  
  222.     return -1;
  223. }
  224.  
  225.  
  226. int threeNWSE (char (*filled)[5], char *columntop, ULONG opponent)
  227. {
  228.     char diagrow, potential, diagcolumn, diagonal, emptyhole;
  229.     enum {EMPTYHOLE=-1};
  230.  
  231.     for (diagonal=7; diagonal>2; diagonal--)
  232.     {
  233.         potential=0;
  234.         diagrow=0;
  235.         emptyhole=EMPTYHOLE;
  236.         for (diagcolumn=diagonal; diagrow<5; diagcolumn--)
  237.         {
  238.             if (diagcolumn>=0 && diagcolumn<=6)
  239.             {
  240.                 #ifdef THREE_NWSE_DEBUG
  241.                 printf("[diagcolumn:%d][diagrow:%d]=%d\n", diagcolumn, diagrow, filled[diagcolumn][diagrow]);
  242.                 #endif
  243.                 if (filled[diagcolumn][diagrow]==EMPTYHOLE && emptyhole==EMPTYHOLE)
  244.                 {
  245.                     emptyhole=diagcolumn;
  246.                     potential++;
  247.                     #ifdef THREE_NWSE_DEBUG
  248.                     printf("  emptyhole=%d  potential=%d\n", emptyhole, potential);
  249.                     #endif
  250.                 }
  251.                 else if (filled[diagcolumn][diagrow]==opponent)
  252.                 {
  253.                     potential++;
  254.                     #ifdef THREE_NWSE_DEBUG
  255.                     printf("  potential=%d\n", potential);
  256.                     #endif
  257.                 }
  258.                 else
  259.                 {
  260.                     potential=0;
  261.                     emptyhole=EMPTYHOLE;
  262.                     #ifdef THREE_NWSE_DEBUG
  263.                     puts("  potential reset");
  264.                     #endif
  265.                 }
  266.  
  267.                 if (potential==4)
  268.                     return emptyhole;
  269.             }
  270.  
  271.             diagrow++;
  272.             #ifdef THREE_NWSE_DEBUG
  273.             puts("");
  274.             #endif
  275.         }
  276.         
  277.     }
  278.  
  279.     return -1;
  280. }
  281.  
  282.  
  283. int threeNESW (char (*filled)[5], char *columntop, ULONG opponent)
  284. {
  285.     char diagrow, potential, diagcolumn, diagonal, emptyhole;
  286.     enum {EMPTYHOLE=-1};
  287.  
  288.     for (diagonal=-1; diagonal<4; diagonal++)
  289.     {
  290.         potential=0;
  291.         diagrow=0;
  292.         emptyhole=EMPTYHOLE;
  293.         for (diagcolumn=diagonal; diagrow<5; diagcolumn++)
  294.         {
  295.             if (diagcolumn>=0 && diagcolumn<=6)
  296.             {
  297.                 #ifdef THREE_NESW_DEBUG
  298.                 printf("[diagcolumn:%d][diagrow:%d]=%d\n", diagcolumn, diagrow, filled[diagcolumn][diagrow]);
  299.                 #endif
  300.                 if (filled[diagcolumn][diagrow]==EMPTYHOLE && emptyhole==EMPTYHOLE)
  301.                 {
  302.                     emptyhole=diagcolumn;
  303.                     potential++;
  304.                     #ifdef THREE_NESW_DEBUG
  305.                     printf("  emptyhole=%d  potential=%d\n", emptyhole, potential);
  306.                     #endif
  307.                 }
  308.                 else if (filled[diagcolumn][diagrow]==opponent)
  309.                 {
  310.                     potential++;
  311.                     #ifdef THREE_NESW_DEBUG
  312.                     printf("  potential=%d\n", potential);
  313.                     #endif
  314.                 }
  315.                 else
  316.                 {
  317.                     potential=0;
  318.                     emptyhole=EMPTYHOLE;
  319.                     #ifdef THREE_NESW_DEBUG
  320.                     puts("  potential reset");
  321.                     #endif
  322.                 }
  323.  
  324.                 if (potential==4)
  325.                     return emptyhole;
  326.             }
  327.  
  328.             diagrow++;
  329.             #ifdef THREE_NWSE_DEBUG
  330.             puts("");
  331.             #endif
  332.         }
  333.         
  334.     }
  335.  
  336.     return -1;
  337. }
  338.  
  339.  
  340.  
  341.