Subversion Repositories Kolibri OS

Rev

Rev 2064 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. //
  2. //      KReversi.java
  3. //              The Othello Game, based on the algorithm of Muffy Barkocy
  4. //              (muffy@fish.com).
  5. //
  6. //              The strategy is very very simple.  The best move for the computer
  7. //              is the move that flip more pieces (preferring boards line and
  8. //              corners) and give less pieces to move to the opponent.
  9. //
  10. //      Author: Alex "Kazuma" Garbagnati (kazuma@energy.it)
  11. //      Date:           20 Jan 96
  12. //      L.R.:           26 Jan 96      
  13. //      Note:
  14. //
  15.  
  16.  
  17.  
  18. #include<menuet/os.h>
  19. #include<stdint.h>
  20. #include<stdlib.h>
  21. #include<stdio.h>
  22. #include<ctype.h>
  23. #include<string.h>
  24.  
  25. typedef unsigned int            u32;
  26.  
  27. int YSHIFT= 33;
  28.  
  29. int ENGLISH = 0;                                        //
  30. int ITALIAN = 1;                                        // Languages
  31. int EXTERNAL = 2;                               //
  32.  
  33. #define BLACK  0x000000;                        //
  34. #define BLACK_S  0x333333;              //
  35. #define WHITE  0xffffff;                        // Colors
  36. #define WHITE_S 0xaaaaaa;               //
  37.  
  38.  
  39. int NOMOVE = 0;                                 //
  40. int REALMOVE = 1;                               // Type of move
  41. int PSEUDOMOVE = 2;                             //
  42.  
  43. int Empty = 0;                                  //
  44. int User = 1;                                   // Board's owners
  45. int Computer = 2;                               //
  46.  
  47. #define true 1
  48. #define false 0
  49.  
  50. int UserMove = true;
  51. int GameOver = false;
  52. int CopyWinOn = false;
  53. int StillInitiated = false;                             // This solve a little
  54.                                                                                 // problem on reinit.
  55.  
  56. int TheBoard[8][8];                                                     // Board
  57. int Score[8][8];
  58. int OpponentScore[8][8];
  59.  
  60.  
  61.  
  62.         //
  63.         //      DrawBoard
  64.         //              (paint the Othello Board, a 8X8 green square table)
  65.         //
  66.         //      Input:  graphic (Graphics)
  67.         //      Output: none
  68.         //      Notes: 
  69.         //
  70.         void DrawBoard() {
  71.                 int i;
  72.                 for(i=0;i<=8;i++)  
  73.                 {
  74.                         __asm__ __volatile__("int $0x40"::"a"(38),"b"(320),"c"(YSHIFT+(YSHIFT+(40*i))*65536+40*i),"d"(0x555555));
  75.                         __menuet__line((40*i),YSHIFT,(40*i),353,0x555555);                              // horizontal
  76.  
  77.                 }
  78.  
  79.         }
  80.         // End of DrawBoard
  81.  
  82.  
  83.         //
  84.         //      DrawPiece
  85.         //              (paint a piece, black or white, I'm using an 8x8 array, so
  86.         //               from the input values for rows and cols must be
  87.         //               subtracted 1)
  88.         //
  89.         //      Input:  who (int),
  90.         //                      column (int),
  91.         //                      row (int)
  92.         //      Output: none
  93.         //      Notes:
  94.         //
  95.         void DrawPiece(int Who, int Col, int Row) {
  96.                 int pCol = (40*(Col-1)+1);
  97.                 int pRow = YSHIFT+(40*(Row-1)+1);
  98.                 u32 pColor,pShadow;
  99.  
  100.                 if (Who == User) {
  101.                         pColor = BLACK;
  102.                         pShadow = BLACK_S;
  103.                 } else {
  104.                         pColor = WHITE;
  105.                         pShadow = WHITE_S;
  106.                 }
  107.                 TheBoard[Col-1][Row-1] = Who;
  108.  
  109.                 __menuet__bar(pCol+9,pRow+9,19,19,pColor);
  110.         }
  111.         // End of DrawPiece
  112.  
  113.  
  114.         //
  115.         //      MsgWhoMove
  116.         //              (paint the message informing who's move)
  117.         //
  118.         //      Input:  is user ? (int)
  119.         //      Output: none
  120.         //      Notes:
  121.         //
  122.         void MsgWhoMove(int UM) {
  123.         }
  124.         // End of MsgWhoMove
  125.  
  126.  
  127.         //
  128.         //      FlipRow
  129.         //              (calculate number of pieces are flipped by a move
  130.         //               and return it. Eventually do the complete or pseudo
  131.         //               move)
  132.         //
  133.         //      Input:  who (int)
  134.         //                      which board (int[][])
  135.         //                      position col, row (int)
  136.         //                      direction col, row (int)
  137.         //                      make move ? (int)
  138.         //
  139.         int FlipRow(int Who, int WhichBoard[8][8] , int C, int R,
  140.                            int CInc, int RInc, int MakeMove) {
  141.                 int NewCol;
  142.                 int NewRow;
  143.                 int Opponent = User + Computer - Who;
  144.                 int CNT = 0;
  145.  
  146.                 NewCol = C - 1;
  147.                 NewRow = R - 1;
  148.                 while (true) {
  149.                         if (((NewCol+CInc) < 0) || ((NewCol+CInc) > 7) ||
  150.                             ((NewRow+RInc) < 0) || ((NewRow+RInc) > 7)) {
  151.                                 return 0;      
  152.                         }
  153.                         if (WhichBoard[NewCol+CInc][NewRow+RInc] == Opponent) {
  154.                                 CNT++;
  155.                                 NewCol += CInc;
  156.                                 NewRow += RInc;
  157.                         } else if (WhichBoard[NewCol+CInc][NewRow+RInc] == Empty) {
  158.                                 return 0;
  159.                         } else {
  160.                                 break;
  161.                         }
  162.                 }
  163.                 if (MakeMove != NOMOVE) {
  164.                         C--;
  165.                         R--;
  166.                         int v;
  167.                         for(v=0; v<=CNT; v++) {
  168.                                 if (MakeMove == REALMOVE) {
  169.                                         DrawPiece(Who, C+1, R+1);
  170.                                 } else {
  171.                                         WhichBoard[C][R] = Who;
  172.                                 }
  173.                                 C += CInc;
  174.                                 R += RInc;
  175.                         }
  176.                 }
  177.                 return CNT;
  178.         }
  179.         // End of FlipRow
  180.  
  181.  
  182.         //
  183.         //      IsLegalMove
  184.         //              (verify that the move is legal)
  185.         //
  186.         //      Input:  who (int)
  187.         //                      board (int[][])
  188.         //                      position col, row (int)
  189.         //      Output: is legal ? (int)
  190.         //      Notes:
  191.         //
  192.         int IsLegalMove(int Who, int WhichBoard[8][8] , int C, int R) {
  193.                 if (WhichBoard[C-1][R-1] != Empty) {
  194.                         return false;
  195.                 }
  196.                 int CInc,RInc;
  197.                 for (CInc=-1; CInc<2; CInc++) {
  198.                         for (RInc=-1; RInc<2; RInc++) {
  199.                                 if (FlipRow(Who, WhichBoard, C, R, CInc, RInc, NOMOVE) > 0) {
  200.                                         return true;
  201.                                 }
  202.                         }
  203.                 }
  204.                 return false;
  205.         }
  206.         // End of IsLegalMove
  207.  
  208.  
  209.         //
  210.         //      MakeMove
  211.         //              (make the move)
  212.         //
  213.         //      Input:  who (int)
  214.         //                      position col, row (int)
  215.         //      Output: false=EndGame, true=next player (int)
  216.         //      Notes:
  217.         //
  218.         int MakeMove(int Who, int C, int R) {
  219.                 int CInc,RInc;
  220.                 for (CInc=-1; CInc<2; CInc++) {
  221.                         for (RInc=-1; RInc<2; RInc++) {
  222.                                 FlipRow(Who, TheBoard, C, R, CInc, RInc, REALMOVE);
  223.                         }
  224.                 }
  225.                 if (IsBoardComplete() ||
  226.                 ((!ThereAreMoves(Computer, TheBoard)) && (!ThereAreMoves(User, TheBoard)))) {
  227.                         return false;
  228.                 }
  229.                 int Opponent = (User + Computer) - Who;
  230.                 if (ThereAreMoves(Opponent, TheBoard)) {
  231.                         UserMove = !UserMove;
  232.                 }
  233.                 return true;
  234.         }
  235.         // End of MakeMove
  236.  
  237.  
  238.         //
  239.         //      EndGame
  240.         //              (shows the winning message)
  241.         //
  242.         //      Input:  none
  243.         //      Output: none
  244.         //      Notes:
  245.         //
  246.         void EndGame() {
  247.                 int CompPieces = 0;
  248.                 int UserPieces = 0;
  249.                 char *WinMsg_W = "Computer Won";
  250.                 char *WinMsg_L = "User Won";
  251.                 char *WinMsg_T = "???";
  252.                 char *TheMsg;
  253.  
  254.                 int StrWidth;
  255.  
  256.                 int c,r;
  257.                 for (c=0; c<8; c++) {
  258.                         for (r=0; r<8; r++) {
  259.                                 if (TheBoard[c][r] == Computer) {
  260.                                         CompPieces++;
  261.                                 } else {
  262.                                         UserPieces++;
  263.                                 }
  264.                         }
  265.                 }
  266.                 if (CompPieces > UserPieces) {
  267.                         TheMsg = WinMsg_W;
  268.                 } else if (UserPieces > CompPieces) {
  269.                         TheMsg = WinMsg_L;
  270.                 } else {
  271.                         TheMsg = WinMsg_T;
  272.                 }
  273.  
  274.                 __menuet__write_text(100,8,0xff0000,TheMsg,strlen(TheMsg));
  275.  
  276.         }
  277.         // End of EndGame
  278.  
  279.  
  280.         //
  281.         //      IsBoardComplete
  282.         //              (checks if the board is complete)
  283.         //
  284.         //      Input:  none
  285.         //      Output: the board is complete ? (int)
  286.         //      Notes:
  287.         //
  288.         int IsBoardComplete() {
  289.                 int i,j;
  290.                 for (i=0; i<8; i++) {
  291.                         for (j=0; j<8; j++) {
  292.                                 if (TheBoard[i][j] == Empty) {
  293.                                         return false;
  294.                                 }
  295.                         }
  296.                 }
  297.                 return true;
  298.         }
  299.         // End of IsBoardComplete
  300.  
  301.  
  302.         //
  303.         //      ThereAreMoves
  304.         //              (checks if there are more valid moves for the
  305.         //               player)
  306.         //
  307.         //      Input:  player (int)
  308.         //                      board (int[][])
  309.         //      Output: there are moves ? (int)
  310.         //      Notes:
  311.         //
  312.         int ThereAreMoves(int Who, int WhichBoard[8][8] ) {
  313.                 int i,j;
  314.                 for (i=1; i<=8; i++) {
  315.                         for (j=1; j<=8; j++) {
  316.                                 if (IsLegalMove(Who, WhichBoard, i, j)) {
  317.                                         return true;
  318.                                 }
  319.                         }
  320.                 }
  321.                 return false;
  322.         }
  323.         // End of ThereAreMoves
  324.  
  325.  
  326.         //
  327.         //      CalcOpponentScore
  328.         //              (calculate the totalScore of opponent after
  329.         //               a move)
  330.         //
  331.         //      Input:  position x, y (int)
  332.         //      Output: score (int)
  333.         //      Notes:
  334.         //
  335.         int CalcOpponentScore(int CP, int RP) {
  336.                 int OpScore = 0;
  337.                 int tempBoard[8][8]; // = new int[8][8];
  338.                 int c,r;
  339.                 for (c=0; c<8; c++) {
  340.                         for (r=0; r<8; r++) {
  341.                                 tempBoard[c][r] = TheBoard[c][r];
  342.                         }
  343.                 }
  344.                 int CInc,RInc;
  345.                 for (CInc=-1; CInc<2; CInc++) {
  346.                         for (RInc=-1; RInc<2; RInc++) {
  347.                                 FlipRow(Computer, tempBoard, CP+1, RP+1, CInc, RInc, PSEUDOMOVE);
  348.                         }
  349.                 }
  350.                 if (ThereAreMoves(User, tempBoard)) {
  351.                         int C,R;
  352.                         for (C=0; C<8; C++) {
  353.                                 for (R=0; R<8; R++) {
  354.                                         OpScore += RankMove(User, tempBoard, C, R);
  355.                                 }
  356.                         }
  357.                 }
  358.                 return OpScore;
  359.         }
  360.         // End of CalcOpponentScore()
  361.  
  362.  
  363.         //
  364.         //      RankMoves
  365.         //              (rank all moves for the computer)
  366.         //
  367.         //      Input:  none
  368.         //      Output: none
  369.         //      Notes:
  370.         //
  371.         void RankMoves() {
  372.                 int C,R;
  373.                 for (C=0; C<8; C++) {
  374.                         for (R=0; R<8; R++) {
  375.                                 Score[C][R] = RankMove(Computer, TheBoard, C, R);
  376.                                 if (Score[C][R] != 0) {
  377.                                         OpponentScore[C][R] = CalcOpponentScore(C, R);
  378.                                 } else {
  379.                                         OpponentScore[C][R] = 0;
  380.                                 }
  381.                         }
  382.                 }
  383.         }
  384.         // End of RankMoves
  385.  
  386.  
  387.         //
  388.         //      RankMove
  389.         //              (rank a move for a player on a board)
  390.         //
  391.         //      Input:  who moves (int)
  392.         //                      on which board (int[][])
  393.         //                      position col, row (int)
  394.         //      Output: flipped pieces (int)
  395.         //      Notes:  best are corner, then border lines,
  396.         //                      worst are line near to border lines
  397.         //
  398.         int RankMove(int Who, int WhichBoard[8][8], int Col, int Row) {
  399.                 int CNT = 0;
  400.                 int MV = 0;
  401.  
  402.                 if (WhichBoard[Col][Row] != Empty) {
  403.                         return 0;
  404.                 }
  405.                 int CInc,RInc;
  406.                 for (CInc=-1; CInc<2; CInc++) {
  407.                         for (RInc=-1; RInc<2; RInc++) {
  408.                                 MV = FlipRow(Who, WhichBoard, Col+1, Row+1, CInc, RInc, NOMOVE);
  409.                                 CNT += MV;
  410.                         }
  411.                 }
  412.                 if (CNT > 0) {
  413.                         if (((Col == 0) || (Col == 7)) ||
  414.                             ((Row == 0) || (Row == 7))) {
  415.                                 CNT = 63;
  416.                         }
  417.                         if (((Col == 0) || (Col == 7)) &&
  418.                             ((Row == 0) || (Row == 7))) {
  419.                                 CNT = 64;
  420.                         }
  421.                         if ((((Col == 0) || (Col == 7)) && (Row == 1) || (Row == 6)) &&
  422.                             (((Col == 1) || (Col == 6)) && (Row == 0) || (Row == 7)) &&
  423.                             (((Col == 1) || (Col == 6)) && (Row == 1) || (Row == 6))) {
  424.                                 CNT = 1;
  425.                         }                      
  426.                 }
  427.                 return CNT;
  428.         }
  429.         // End of RankMove
  430.  
  431.  
  432.         //
  433.         //      BestMove
  434.         //              (calculate and execute the best move)
  435.         //
  436.         //      Input:  none
  437.         //      Output: value, col & row (int[3])
  438.         //      Notes:
  439.         //
  440.         void BestMove (int retval[3]) {
  441.  
  442.                 retval[0] = -998;       // move value;
  443.                 retval[1] = 0;  // column
  444.                 retval[2] = 0;  // row
  445.  
  446.                 RankMoves();
  447.                 int C,R;
  448.                 for (C=0; C<8; C++) {
  449.                         for (R=0; R<8; R++) {
  450.                                 if ((Score[C][R] == 0) && (OpponentScore[C][R] == 0)) {
  451.                                         Score[C][R] = -999;
  452.                                 } else if (Score[C][R] != 64) {
  453.                                         Score[C][R] = Score[C][R] - OpponentScore[C][R];
  454.                                 }
  455.                         }
  456.                 }
  457.                 for (C=0; C<8; C++) {
  458.                         for (R=0; R<8; R++) {
  459.                                 if (Score[C][R] > retval[0]) {
  460.                                         retval[1] = C;
  461.                                         retval[2] = R;
  462.                                         retval[0] = Score[C][R];
  463.                                 }
  464.                         }
  465.                 }
  466.                 retval[1]++;
  467.                 retval[2]++;
  468. //              return retval;
  469.         }
  470.         // End of BestMove
  471.  
  472.  
  473.  
  474.  
  475.         //
  476.         // paint
  477.         //
  478.         void paint() {
  479. //              MsgWhoMove(UserMove);
  480.                 if (!CopyWinOn) {
  481.                         int i,j;
  482.                         for (i=0; i<8; i++) {
  483.                                 for (j=0; j<8; j++) {
  484.                                         if (TheBoard[i][j] != Empty) {
  485.                                                 DrawPiece(TheBoard[i][j], i+1, j+1);
  486.                                         }
  487.                                 }
  488.                         }
  489. //              } else {
  490. //                      ShowAbout();
  491.                 }
  492.         }
  493.         // End of paint
  494.  
  495.  
  496.         //
  497.         // init
  498.         //
  499.         void init() {
  500.                         // This is the right size of the applet 321x387
  501. //              resize(321,387);
  502.                         // I set twice the language. That's because if anybody
  503.                         //      forget a string in an external language file, are
  504.                         //      used english strings.
  505.                 if (!StillInitiated) {
  506.                         StillInitiated = true;
  507.                 }
  508.                 int i,j;
  509.                 for (i=0; i<8; i++) {
  510.                         for (j=0; j<8; j++) {
  511.                                 TheBoard[i][j] = 0;
  512.                         }
  513.                 }
  514.                 TheBoard[3][3] = User;
  515.                 TheBoard[3][4] = Computer;
  516.                 TheBoard[4][3] = Computer;
  517.                 TheBoard[4][4] = User;
  518.                 UserMove = true;
  519. //              MsgWhoMove(true);
  520.         //      repaint();
  521.         }
  522.         // End of init
  523.  
  524.  
  525.  
  526.  
  527.  
  528. void paint_win(void)
  529. {
  530.  __menuet__window_redraw(1);
  531.  __menuet__define_window(100,100,330,400,0x33777777,0,"Reversi");
  532.  __menuet__make_button(2,2,40,20,3,0xe0e0e0);
  533.  __menuet__write_text(8,8,0x333333,"New",3);
  534.  __menuet__window_redraw(2);
  535. }
  536.  
  537. void app_main(void)
  538. {
  539.  int i;
  540.  u32 mouse_coord;
  541.  u32 mouse_butn;
  542.  int X,Y;
  543.  
  544.  int TheCol, TheRow;
  545.  int BMove[3];
  546.  int BX,  BY;
  547.  int retval = false;
  548.  
  549.  
  550.  __menuet__set_bitfield_for_wanted_events(EVENT_REDRAW + EVENT_KEY + EVENT_BUTTON + EVENT_MOUSE_CHANGE);
  551.  paint_win();
  552.  DrawBoard();
  553.  init();
  554.  paint();
  555.  
  556.  for(;;)
  557.  {
  558.   i=__menuet__wait_for_event();
  559.   switch(i)
  560.   {
  561.    case 1:
  562.     paint_win();
  563.     DrawBoard();
  564.     paint();
  565.     continue;
  566.    case 2:
  567.     __menuet__getkey();
  568.     continue;
  569.    case 3:
  570.     if(__menuet__get_button_id()==1) {
  571.                 __menuet__sys_exit();}
  572.     else
  573.         paint_win();
  574.         init();
  575.         DrawBoard();
  576.         paint();
  577.     continue;
  578.    case 4:
  579.     continue;
  580.    case 5:
  581.     continue;
  582.    case 6:
  583.         __asm__ __volatile__("int $0x40":"=a"(mouse_butn):"0"(37),"b"(2));
  584.         __asm__ __volatile__("int $0x40":"=a"(mouse_coord):"0"(37),"b"(1));
  585.         X = mouse_coord >> 16;
  586.         Y = mouse_coord & 0xffff;
  587.  
  588.                         // Process a normal click in the board
  589.                 BX = X;
  590.                 BY = Y - YSHIFT;
  591.  
  592.  
  593.                 if ((BY >= 0) && (BY <= 321) &&
  594.                     (mouse_butn !=0) && (UserMove)) {
  595.                         TheCol = (int)((BX/40)+1);
  596.                         TheRow = (int)((BY/40)+1);
  597.  
  598.                         if (IsLegalMove(User, TheBoard, TheCol, TheRow)) {
  599.                                 retval = MakeMove(User, TheCol, TheRow);
  600.                                 while (retval && (!UserMove)) {
  601.                                         //MsgWhoMove(UserMove);
  602.                                         BestMove(BMove);
  603.  
  604.                                         retval = MakeMove(Computer, BMove[1], BMove[2]);
  605.                                         //MsgWhoMove(UserMove);
  606.                                 }
  607.                                 if (!retval) {
  608.                                         EndGame();
  609.                                 }
  610.                         }                      
  611.                 paint();
  612.                 }
  613.         continue;
  614.  
  615.        
  616.   }
  617.  }
  618. }
  619.  
  620.