Author Topic: Reversi / Othello Game (play against computer AI)  (Read 5095 times)

0 Members and 1 Guest are viewing this topic.

Offline qbguy

  • Newbie
  • Posts: 11
    • View Profile
Reversi / Othello Game (play against computer AI)
« on: October 06, 2018, 09:18:20 pm »
Mouse code is for QBASIC and uses CALL ABSOLUTE to call interrupt 33 and put the results in global variables named AX, BX, CX, DX.  Should still work in QB64; otherwise alter it to use CALL ITERRUPT or QB64 mouse codes.  When this was on the [abandoned, outdated and now likely malicious qb64 dot net website - don’t go there] forum there was a bug in QB64 that caused it not to compile the constants.  I think I had already put alternative mouse routines for QB64 or FreeBASIC.

Code: QB64: [Select]
  1. DECLARE FUNCTION AlphaBeta% (player%, board%(), achievable%, cutoff%, ply%)
  2. DECLARE FUNCTION FinalValue% (player%, board%())
  3. DECLARE FUNCTION WeightedSquares% (player%, board%())
  4. DECLARE FUNCTION MaximizeDifference% (player%, board%())
  5. DECLARE FUNCTION CountDifference% (player%, board%())
  6. DECLARE SUB MakeMove (move%, player%, board%())
  7. DECLARE SUB InitBoard ()
  8. DECLARE FUNCTION LegalP% (move%, player%, board%())
  9. DECLARE FUNCTION WouldFlip% (move%, player%, board%(), dir%)
  10. DECLARE FUNCTION FindBracketingPiece% (square%, player%, board%(), dir%)
  11. DECLARE FUNCTION NextToPlay% (board%(), PreviousPlayer%)
  12. DECLARE FUNCTION AnyLegalMove% (player%, board%())
  13. DECLARE FUNCTION Opponent% (player%)
  14. DECLARE SUB MakeFlips (move%, player%, board%(), dir%)
  15. DEFINT A-Z
  16. DECLARE SUB Mouse (ax AS INTEGER)
  17. DECLARE FUNCTION GetMove% ()
  18. DECLARE FUNCTION Colour (i)
  19. DECLARE SUB ShowBd ()
  20. DIM SHARED board(100) AS INTEGER
  21. DIM SHARED AllDirections(8) AS INTEGER
  22. DIM SHARED weights(100) AS INTEGER
  23. CLEAR , , 9999
  24. FOR i = 1 TO 8
  25.   READ AllDirections(i)
  26. DATA -11, -10, -9, -1, 1, 9, 10, 11
  27.  
  28. FOR i = 0 TO 99
  29.   READ weights(i)
  30. DATA 0,0,0,0,0,0,0,0,0,0
  31. DATA 0,120,-20,20,5,5,20,-20,120,0
  32. DATA 0,-20,-0,-5,-5,-5,-5,-40,-20,0
  33. DATA 0,20,-5,15,3,3,15,-5,20,0
  34. DATA 0,5,-5,3,3,3,3,-5,5,0
  35. DATA 0,5,-5,3,3,3,3,-5,5,0
  36. DATA 0,20,-5,15,3,3,15,-5,20,0
  37. DATA 0,-20,-0,-5,-5,-5,-5,-40,-20,0
  38. DATA 0,120,-20,20,5,5,20,-20,120,0
  39. DATA 0,0,0,0,0,0,0,0,0,0
  40.  
  41. CONST ScreenWidth = 640
  42. CONST ScreenHeight = 480
  43. CONST SquareWidth = ScreenHeight / 8
  44. CONST tlx = (ScreenWidth - ScreenHeight) / 2
  45. CONST tly = 0
  46. CONST brx = ScreenWidth - (ScreenWidth - ScreenHeight) / 2
  47. CONST bry = ScreenHeight
  48. CONST PieceRadius = SquareWidth / 2 - 5
  49. CONST EMPTY = 0
  50. CONST BLACK = 1
  51. CONST WHITE = 2
  52. CONST OUTER = 3
  53. CONST WinningValue = 32767
  54. CONST LosingValue = -32767
  55. CONST nply = 5
  56.  
  57. DIM SHARED bestm(nply) AS INTEGER
  58. ax = 0
  59. bx = 0
  60. cx = 0
  61. dx = 0
  62.  
  63.  
  64.  
  65. CALL InitBoard
  66. CALL Mouse(0)
  67. CALL Mouse(1)
  68. player = BLACK
  69. human = BLACK
  70. computer = Opponent(human)
  71.   CALL ShowBd
  72.   IF player = human THEN
  73.     n = GetMove
  74.     IF LegalP(n, player, board()) THEN
  75.       CALL MakeMove(n, player, board())
  76.       player = NextToPlay(board(), player)
  77.     END IF
  78.   END IF
  79.   CALL ShowBd
  80.   IF player = computer THEN
  81.     n = AlphaBeta(player, board(), LosingValue, WinningValue, nply)
  82.     move = bestm(nply)
  83.     CALL MakeMove(move, player, board())
  84.     player = NextToPlay(board(), player)
  85.   END IF
  86. LOOP UNTIL player = 0
  87.  
  88. FUNCTION AlphaBeta (player, board(), achievable, cutoff, ply)
  89.   DIM board2(100)
  90.   FOR i = 0 TO 99
  91.     board2(i) = board(i)
  92.   NEXT
  93.   IF ply = 0 THEN
  94.     AlphaBeta = WeightedSquares(player, board())
  95.   END IF
  96.   nlegal = 0
  97.   FOR move = 0 TO 99
  98.     IF LegalP(move, player, board()) THEN
  99.       nlegal = nlegal + 1
  100.       CALL MakeMove(move, player, board2())
  101.       value = -AlphaBeta(Opponent(player), board2(), -cutoff, -achievable, ply - 1)
  102.       IF value > achievable THEN
  103.         achievable = value
  104.         bestmove = move
  105.       END IF
  106.     END IF
  107.   NEXT
  108.   IF nlegal = 0 THEN
  109.     IF AnyLegalMove(Opponent(player), board()) THEN
  110.       AlphaBeta = -AlphaBeta(Opponent(player), board(), -cutoff, -achievable, ply - 1)
  111.     ELSE
  112.       AlphaBeta = FinalValue(player, board())
  113.     END IF
  114.   END IF
  115.   bestm(ply) = bestmove
  116.  
  117. FUNCTION AnyLegalMove (player, board())
  118.   FOR i = 0 TO 99
  119.     IF LegalP(i, player, board()) THEN AnyLegalMove = -1: EXIT FUNCTION
  120.   NEXT
  121.  
  122. FUNCTION Colour (i)
  123.   IF i = BLACK THEN
  124.     Colour = 0
  125.   ELSE
  126.     Colour = 15
  127.   END IF
  128.  
  129. FUNCTION CountDifference (player, board())
  130.   c = 0
  131.   FOR y = 1 TO 8
  132.     FOR x = 1 TO 8
  133.       IF board(10 * y + x) = player THEN c = c + 1
  134.       IF board(10 * y + x) = Opponent(player) THEN c = c - 1
  135.     NEXT
  136.   NEXT
  137.   CountDifference = c
  138.  
  139. FUNCTION FinalValue (player, board())
  140.   SELECT CASE SGN(CountDifference(player, board()))
  141.     CASE -1
  142.       FinalValue = LosingValue
  143.     CASE 0
  144.       FinalValue = 0
  145.     CASE 1
  146.       FinalValue = WinningValue
  147.  
  148. FUNCTION FindBracketingPiece (square, player, board(), dir)
  149.   IF board(square) = player THEN
  150.     FindBracketingPiece = square
  151.   ELSEIF board(square) = Opponent(player) THEN
  152.     FindBracketingPiece = FindBracketingPiece(square + dir, player, board(), dir)
  153.   END IF
  154.  
  155. FUNCTION GetMove
  156.   DO
  157.     CALL Mouse(3)
  158.     IF bx AND 1 THEN
  159.       y = (dx - tly) \ SquareWidth + 1
  160.       x = (cx - tlx) \ SquareWidth + 1
  161.     END IF
  162.     IF 1 <= y AND y <= 8 AND 1 <= x AND x <= 8 THEN EXIT DO
  163.   LOOP
  164.   GetMove = 10 * y + x
  165.  
  166. SUB InitBoard
  167.   FOR i = 0 TO 9
  168.     board(i) = OUTER
  169.     board(90 + i) = OUTER
  170.     board(i * 10) = OUTER
  171.     board(i * 10 + 9) = OUTER
  172.   NEXT
  173.   board(44) = 1
  174.   board(45) = 2
  175.   board(54) = 2
  176.   board(55) = 1
  177.  
  178. FUNCTION LegalP (move, player, board())
  179.   IF board(move) <> EMPTY THEN LegalP = 0: EXIT FUNCTION
  180.   FOR i = 1 TO 8
  181.     x = WouldFlip(move, player, board(), AllDirections(i))
  182.     IF x THEN LegalP = -1: EXIT FUNCTION
  183.   NEXT
  184.  
  185. SUB MakeFlips (move, player, board(), dir)
  186.   bracketer = WouldFlip(move, player, board(), dir)
  187.   IF bracketer THEN
  188.     FOR c = move + dir TO bracketer STEP dir
  189.       board(c) = player
  190.     NEXT
  191.   END IF
  192.  
  193. SUB MakeMove (move, player, board())
  194.   board(move) = player
  195.   FOR i = 1 TO 8
  196.     CALL MakeFlips(move, player, board(), AllDirections(i))
  197.   NEXT
  198.  
  199. FUNCTION MaximizeDifference (player, board())
  200.   DIM board2(100)
  201.   best = -9999
  202.   FOR y = 1 TO 8
  203.     FOR x = 1 TO 8
  204.       move = 10 * y + x
  205.       IF LegalP(move, player, board()) THEN
  206.         FOR i = 0 TO 99
  207.           board2(i) = board(i)
  208.         NEXT
  209.         CALL MakeMove(move, player, board2())
  210.         score = WeightedSquares(player, board2())
  211.         IF score > best THEN best = score: bestmove = move
  212.       END IF
  213.     NEXT
  214.   NEXT
  215.   MaximizeDifference = bestmove
  216.  
  217. SUB Mouse (ax AS INTEGER)
  218.  
  219.   ml$ = "" ' -=<( Mouse Code )>=-
  220.   ml$ = ml$ + CHR$(&H55) ' push bp               ; preserve BP register
  221.   ml$ = ml$ + CHR$(&H89) + CHR$(&HE5) ' mov  bp, sp           ; copy SP to BP
  222.   ml$ = ml$ + CHR$(&HB8) + CHR$(ax) + CHR$(&H0) '   mov  ax, #          ;   copy SUBFUNCTION to AX
  223.   ml$ = ml$ + CHR$(&HCD) + CHR$(&H33) '   int  33             ;   call mouse interrupt
  224.   ml$ = ml$ + CHR$(&H53) '   push bx             ;   preserve BX (again)
  225.   ml$ = ml$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&H6) '   mov  bx, [bp+6]     ;   copy location of dx (last variable) to BX
  226.   ml$ = ml$ + CHR$(&H89) + CHR$(&H17) '   mov  [bx], dx       ;   copy DX to dx location in BX
  227.   ml$ = ml$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&H8) '   mov  bx, [bp+8]     ;   copy location of cx to BX
  228.   ml$ = ml$ + CHR$(&H89) + CHR$(&HF) '   mov  [bx], cx       ;   copy CX to cx location in BX
  229.   ml$ = ml$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&HC) '   mov  bx, [bp+C]     ;   copy location of ax to BX
  230.   ml$ = ml$ + CHR$(&H89) + CHR$(&HF7) '   mov  [bx], ax       ;   copy AX to ax location in BX
  231.   ml$ = ml$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&HA) '   mov  bx, [bp+A]     ;   copy location of bx to BX
  232.   ml$ = ml$ + CHR$(&H58) '   pop  ax             ;   restore int 33's BX value to AX
  233.   ml$ = ml$ + CHR$(&H89) + CHR$(&H7) '   mov  [bx], ax       ;   copy AX to bx location in BX
  234.   ml$ = ml$ + CHR$(&H5D) ' pop  bp               ; restore BP
  235.   ml$ = ml$ + CHR$(&HCA) + CHR$(&H8) + CHR$(&H0) ' retf 8                ; Return Far and skip 8 bytes of variables
  236.   DEF SEG = SSEG(ml$) ' Set current segment this machine code segment
  237.   offset% = SADD(ml$) ' Set offset to this machine code location
  238.   CALL absolute(ax, bx, cx, dx, offset%) ' The actual call to this machine code
  239.   DEF SEG ' Restore the default segment
  240.  
  241.  
  242. FUNCTION NextToPlay (board(), PreviousPlayer)
  243.   opp = Opponent(PreviousPlayer)
  244.   IF AnyLegalMove(opp, board()) THEN NextToPlay = opp: EXIT FUNCTION
  245.   IF AnyLegalMove(PreviousPlayer, board()) THEN NextToPlay = PreviousPlayer
  246.  
  247. FUNCTION Opponent (player)
  248.   IF player = WHITE THEN Opponent = BLACK
  249.   IF player = BLACK THEN Opponent = WHITE
  250.  
  251. SUB ShowBd
  252.   LINE (tlx, tly)-(brx, bry), 8, BF
  253.   FOR i = 0 TO 8
  254.     LINE (tlx + SquareWidth * i, tly)-(tlx + SquareWidth * i, bry)
  255.     LINE (tlx, tly + SquareWidth * i)-(brx, tly + SquareWidth * i)
  256.   NEXT
  257.   FOR y = 1 TO 8
  258.     FOR x = 1 TO 8
  259.       IF board(10 * y + x) <> EMPTY THEN
  260.         CIRCLE (tlx + SquareWidth * x - SquareWidth / 2, tly + SquareWidth * y - SquareWidth / 2), PieceRadius, Colour(board(10 * y + x))
  261.         PAINT (tlx + SquareWidth * x - SquareWidth / 2, tly + SquareWidth * y - SquareWidth / 2), Colour(board(10 * y + x))
  262.       END IF
  263.     NEXT
  264.   NEXT
  265.  
  266. FUNCTION WeightedSquares (player, board())
  267.   opp = Opponent(player)
  268.   sum = 0
  269.   FOR i = 0 TO 99
  270.     IF board(i) = player THEN sum = sum + weights(i)
  271.     IF board(i) = opp THEN sum = sum - weights(i)
  272.   NEXT
  273.   WeightedSquares = sum
  274.  
  275. FUNCTION WouldFlip (move, player, board(), dir)
  276.   c = move + dir
  277.   IF board(c) <> Opponent(player) THEN WouldFlip = 0: EXIT FUNCTION
  278.   WouldFlip = FindBracketingPiece(c + dir, player, board(), dir)
  279.  
  280.  
« Last Edit: October 06, 2018, 09:19:57 pm by qbguy »

Offline TempodiBasic

  • Forum Resident
  • Posts: 1792
    • View Profile
Re: Reversi / Othello Game (play against computer AI)
« Reply #1 on: October 13, 2018, 10:45:38 am »
Hi Codeguy

Thanks to share your code here.

I copy and paste it in QB64dev and I have got two errors....

1. at line 48 QB64 doesn't accept the formula to define brx so I convert brx to a shared variable
2. at line 258 I find a SSEG(ml$), but looking at wiki about DEF SEG  I see that if we use a variable address we must use VARSEG and so I correct the code

here the code that works in my machine (TOSHIBA) with 4GB ram and QB64dev
Code: QB64: [Select]
  1. DECLARE FUNCTION AlphaBeta% (player%, board%(), achievable%, cutoff%, ply%)
  2. DECLARE FUNCTION FinalValue% (player%, board%())
  3. DECLARE FUNCTION WeightedSquares% (player%, board%())
  4. DECLARE FUNCTION MaximizeDifference% (player%, board%())
  5. DECLARE FUNCTION CountDifference% (player%, board%())
  6. DECLARE SUB MakeMove (move%, player%, board%())
  7. DECLARE SUB InitBoard ()
  8. DECLARE FUNCTION LegalP% (move%, player%, board%())
  9. DECLARE FUNCTION WouldFlip% (move%, player%, board%(), dir%)
  10. DECLARE FUNCTION FindBracketingPiece% (square%, player%, board%(), dir%)
  11. DECLARE FUNCTION NextToPlay% (board%(), PreviousPlayer%)
  12. DECLARE FUNCTION AnyLegalMove% (player%, board%())
  13. DECLARE FUNCTION Opponent% (player%)
  14. DECLARE SUB MakeFlips (move%, player%, board%(), dir%)
  15. DEFINT A-Z
  16. DECLARE SUB Mouse (ax AS INTEGER)
  17. DECLARE FUNCTION GetMove% ()
  18. DECLARE FUNCTION Colour (i)
  19. DECLARE SUB ShowBd ()
  20. DIM SHARED board(100) AS INTEGER
  21. DIM SHARED AllDirections(8) AS INTEGER
  22. DIM SHARED weights(100) AS INTEGER
  23. CLEAR , , 9999
  24. FOR i = 1 TO 8
  25.     READ AllDirections(i)
  26. DATA -11,-10,-9,-1,1,9,10,11
  27.  
  28. FOR i = 0 TO 99
  29.     READ weights(i)
  30. DATA 0,0,0,0,0,0,0,0,0,0
  31. DATA 0,120,-20,20,5,5,20,-20,120,0
  32. DATA 0,-20,-0,-5,-5,-5,-5,-40,-20,0
  33. DATA 0,20,-5,15,3,3,15,-5,20,0
  34. DATA 0,5,-5,3,3,3,3,-5,5,0
  35. DATA 0,5,-5,3,3,3,3,-5,5,0
  36. DATA 0,20,-5,15,3,3,15,-5,20,0
  37. DATA 0,-20,-0,-5,-5,-5,-5,-40,-20,0
  38. DATA 0,120,-20,20,5,5,20,-20,120,0
  39. DATA 0,0,0,0,0,0,0,0,0,0
  40.  
  41. CONST ScreenWidth = 640
  42. CONST ScreenHeight = 480
  43. CONST SquareWidth = ScreenHeight / 8
  44. CONST tlx = (ScreenWidth - ScreenHeight) / 2
  45. CONST tly = 0
  46. DIM SHARED brx: brx = ScreenWidth - (ScreenWidth - ScreenHeight) / 2 'here CONST doesn't like to compiler
  47. CONST bry = ScreenHeight
  48. CONST PieceRadius = SquareWidth / 2 - 5
  49. CONST EMPTY = 0
  50. CONST BLACK = 1
  51. CONST WHITE = 2
  52. CONST OUTER = 3
  53. CONST WinningValue = 32767
  54. CONST LosingValue = -32767
  55. CONST nply = 5
  56.  
  57. DIM SHARED bestm(nply) AS INTEGER
  58. ax = 0
  59. bx = 0
  60. cx = 0
  61. dx = 0
  62.  
  63.  
  64.  
  65. CALL InitBoard
  66. CALL Mouse(0)
  67. CALL Mouse(1)
  68. player = BLACK
  69. human = BLACK
  70. computer = Opponent(human)
  71.     CALL ShowBd
  72.     IF player = human THEN
  73.         n = GetMove
  74.         IF LegalP(n, player, board()) THEN
  75.             CALL MakeMove(n, player, board())
  76.             player = NextToPlay(board(), player)
  77.         END IF
  78.     END IF
  79.     CALL ShowBd
  80.     IF player = computer THEN
  81.         n = AlphaBeta(player, board(), LosingValue, WinningValue, nply)
  82.         move = bestm(nply)
  83.         CALL MakeMove(move, player, board())
  84.         player = NextToPlay(board(), player)
  85.     END IF
  86. LOOP UNTIL player = 0
  87.  
  88. FUNCTION AlphaBeta (player, board(), achievable, cutoff, ply)
  89.     DIM board2(100)
  90.     FOR i = 0 TO 99
  91.         board2(i) = board(i)
  92.     NEXT
  93.     IF ply = 0 THEN
  94.         AlphaBeta = WeightedSquares(player, board())
  95.         EXIT FUNCTION
  96.     END IF
  97.     nlegal = 0
  98.     FOR move = 0 TO 99
  99.         IF LegalP(move, player, board()) THEN
  100.             nlegal = nlegal + 1
  101.             CALL MakeMove(move, player, board2())
  102.             value = -AlphaBeta(Opponent(player), board2(), -cutoff, -achievable, ply - 1)
  103.             IF value > achievable THEN
  104.                 achievable = value
  105.                 bestmove = move
  106.             END IF
  107.         END IF
  108.     NEXT
  109.     IF nlegal = 0 THEN
  110.         IF AnyLegalMove(Opponent(player), board()) THEN
  111.             AlphaBeta = -AlphaBeta(Opponent(player), board(), -cutoff, -achievable, ply - 1)
  112.         ELSE
  113.             AlphaBeta = FinalValue(player, board())
  114.         END IF
  115.     END IF
  116.     bestm(ply) = bestmove
  117.  
  118. FUNCTION AnyLegalMove (player, board())
  119.     FOR i = 0 TO 99
  120.         IF LegalP(i, player, board()) THEN AnyLegalMove = -1: EXIT FUNCTION
  121.     NEXT
  122.  
  123. FUNCTION Colour (i)
  124.     IF i = BLACK THEN
  125.         Colour = 0
  126.     ELSE
  127.         Colour = 15
  128.     END IF
  129.  
  130. FUNCTION CountDifference (player, board())
  131.     c = 0
  132.     FOR y = 1 TO 8
  133.         FOR x = 1 TO 8
  134.             IF board(10 * y + x) = player THEN c = c + 1
  135.             IF board(10 * y + x) = Opponent(player) THEN c = c - 1
  136.         NEXT
  137.     NEXT
  138.     CountDifference = c
  139.  
  140. FUNCTION FinalValue (player, board())
  141.     SELECT CASE SGN(CountDifference(player, board()))
  142.         CASE -1
  143.             FinalValue = LosingValue
  144.         CASE 0
  145.             FinalValue = 0
  146.         CASE 1
  147.             FinalValue = WinningValue
  148.     END SELECT
  149.  
  150. FUNCTION FindBracketingPiece (square, player, board(), dir)
  151.     IF board(square) = player THEN
  152.         FindBracketingPiece = square
  153.     ELSEIF board(square) = Opponent(player) THEN
  154.         FindBracketingPiece = FindBracketingPiece(square + dir, player, board(), dir)
  155.     END IF
  156.  
  157. FUNCTION GetMove
  158.     DO
  159.         CALL Mouse(3)
  160.         IF bx AND 1 THEN
  161.             y = (dx - tly) \ SquareWidth + 1
  162.             x = (cx - tlx) \ SquareWidth + 1
  163.         END IF
  164.         IF 1 <= y AND y <= 8 AND 1 <= x AND x <= 8 THEN EXIT DO
  165.     LOOP
  166.     GetMove = 10 * y + x
  167.  
  168. SUB InitBoard
  169.     FOR i = 0 TO 9
  170.         board(i) = OUTER
  171.         board(90 + i) = OUTER
  172.         board(i * 10) = OUTER
  173.         board(i * 10 + 9) = OUTER
  174.     NEXT
  175.     board(44) = 1
  176.     board(45) = 2
  177.     board(54) = 2
  178.     board(55) = 1
  179.  
  180. FUNCTION LegalP (move, player, board())
  181.     IF board(move) <> EMPTY THEN LegalP = 0: EXIT FUNCTION
  182.     FOR i = 1 TO 8
  183.         x = WouldFlip(move, player, board(), AllDirections(i))
  184.         IF x THEN LegalP = -1: EXIT FUNCTION
  185.     NEXT
  186.  
  187. SUB MakeFlips (move, player, board(), dir)
  188.     bracketer = WouldFlip(move, player, board(), dir)
  189.     IF bracketer THEN
  190.         FOR c = move + dir TO bracketer STEP dir
  191.             board(c) = player
  192.         NEXT
  193.     END IF
  194.  
  195. SUB MakeMove (move, player, board())
  196.     board(move) = player
  197.     FOR i = 1 TO 8
  198.         CALL MakeFlips(move, player, board(), AllDirections(i))
  199.     NEXT
  200.  
  201. FUNCTION MaximizeDifference (player, board())
  202.     DIM board2(100)
  203.     best = -9999
  204.     FOR y = 1 TO 8
  205.         FOR x = 1 TO 8
  206.             move = 10 * y + x
  207.             IF LegalP(move, player, board()) THEN
  208.                 FOR i = 0 TO 99
  209.                     board2(i) = board(i)
  210.                 NEXT
  211.                 CALL MakeMove(move, player, board2())
  212.                 score = WeightedSquares(player, board2())
  213.                 IF score > best THEN best = score: bestmove = move
  214.             END IF
  215.         NEXT
  216.     NEXT
  217.     MaximizeDifference = bestmove
  218.  
  219. SUB Mouse (ax AS INTEGER)
  220.  
  221.     ml$ = "" ' -=<( Mouse Code )>=-
  222.     ml$ = ml$ + CHR$(&H55) ' push bp               ; preserve BP register
  223.     ml$ = ml$ + CHR$(&H89) + CHR$(&HE5) ' mov  bp, sp           ; copy SP to BP
  224.     ml$ = ml$ + CHR$(&HB8) + CHR$(ax) + CHR$(&H0) '   mov  ax, #          ;   copy SUBFUNCTION to AX
  225.     ml$ = ml$ + CHR$(&HCD) + CHR$(&H33) '   int  33             ;   call mouse interrupt
  226.     ml$ = ml$ + CHR$(&H53) '   push bx             ;   preserve BX (again)
  227.     ml$ = ml$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&H6) '   mov  bx, [bp+6]     ;   copy location of dx (last variable) to BX
  228.     ml$ = ml$ + CHR$(&H89) + CHR$(&H17) '   mov  [bx], dx       ;   copy DX to dx location in BX
  229.     ml$ = ml$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&H8) '   mov  bx, [bp+8]     ;   copy location of cx to BX
  230.     ml$ = ml$ + CHR$(&H89) + CHR$(&HF) '   mov  [bx], cx       ;   copy CX to cx location in BX
  231.     ml$ = ml$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&HC) '   mov  bx, [bp+C]     ;   copy location of ax to BX
  232.     ml$ = ml$ + CHR$(&H89) + CHR$(&HF7) '   mov  [bx], ax       ;   copy AX to ax location in BX
  233.     ml$ = ml$ + CHR$(&H8B) + CHR$(&H5E) + CHR$(&HA) '   mov  bx, [bp+A]     ;   copy location of bx to BX
  234.     ml$ = ml$ + CHR$(&H58) '   pop  ax             ;   restore int 33's BX value to AX
  235.     ml$ = ml$ + CHR$(&H89) + CHR$(&H7) '   mov  [bx], ax       ;   copy AX to bx location in BX
  236.     ml$ = ml$ + CHR$(&H5D) ' pop  bp               ; restore BP
  237.     ml$ = ml$ + CHR$(&HCA) + CHR$(&H8) + CHR$(&H0) ' retf 8                ; Return Far and skip 8 bytes of variables
  238.     DEF SEG = VARSEG(ml$) ' Set current segment this machine code segment  'here is SSEG
  239.     offset% = SADD(ml$) ' Set offset to this machine code location
  240.     CALL ABSOLUTE(ax, bx, cx, dx, offset%) ' The actual call to this machine code
  241.     DEF SEG ' Restore the default segment
  242.  
  243.  
  244. FUNCTION NextToPlay (board(), PreviousPlayer)
  245.     opp = Opponent(PreviousPlayer)
  246.     IF AnyLegalMove(opp, board()) THEN NextToPlay = opp: EXIT FUNCTION
  247.     IF AnyLegalMove(PreviousPlayer, board()) THEN NextToPlay = PreviousPlayer
  248.  
  249. FUNCTION Opponent (player)
  250.     IF player = WHITE THEN Opponent = BLACK
  251.     IF player = BLACK THEN Opponent = WHITE
  252.  
  253. SUB ShowBd
  254.     LINE (tlx, tly)-(brx, bry), 8, BF
  255.     FOR i = 0 TO 8
  256.         LINE (tlx + SquareWidth * i, tly)-(tlx + SquareWidth * i, bry)
  257.         LINE (tlx, tly + SquareWidth * i)-(brx, tly + SquareWidth * i)
  258.     NEXT
  259.     FOR y = 1 TO 8
  260.         FOR x = 1 TO 8
  261.             IF board(10 * y + x) <> EMPTY THEN
  262.                 CIRCLE (tlx + SquareWidth * x - SquareWidth / 2, tly + SquareWidth * y - SquareWidth / 2), PieceRadius, Colour(board(10 * y + x))
  263.                 PAINT (tlx + SquareWidth * x - SquareWidth / 2, tly + SquareWidth * y - SquareWidth / 2), Colour(board(10 * y + x))
  264.             END IF
  265.         NEXT
  266.     NEXT
  267.  
  268. FUNCTION WeightedSquares (player, board())
  269.     opp = Opponent(player)
  270.     sum = 0
  271.     FOR i = 0 TO 99
  272.         IF board(i) = player THEN sum = sum + weights(i)
  273.         IF board(i) = opp THEN sum = sum - weights(i)
  274.     NEXT
  275.     WeightedSquares = sum
  276.  
  277. FUNCTION WouldFlip (move, player, board(), dir)
  278.     c = move + dir
  279.     IF board(c) <> Opponent(player) THEN WouldFlip = 0: EXIT FUNCTION
  280.     WouldFlip = FindBracketingPiece(c + dir, player, board(), dir)
  281.  

see attachment for screenshot
reverso QBGuy.jpg
* reverso QBGuy.jpg (Filesize: 270.07 KB, Dimensions: 1366x768, Views: 376)
Programming isn't difficult, only it's  consuming time and coffee

Offline johnno56

  • Forum Resident
  • Posts: 1270
  • Live long and prosper.
    • View Profile
Re: Reversi / Othello Game (play against computer AI)
« Reply #2 on: October 14, 2018, 04:51:35 pm »
qbguy,

Thank you for the cool game. I was totally "cleaned up" but still a good game.

TempodiBasic.

Thank you for the corrections.

J
Logic is the beginning of wisdom.