Subversion Repositories Kolibri OS

Rev

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