Author Topic: One Key Connect 4 (8x8) Halloween Style  (Read 9694 times)

0 Members and 1 Guest are viewing this topic.

Offline Pete

  • Forum Resident
  • Posts: 2361
  • Cuz I sez so, varmint!
    • View Profile
Re: One Key Connect 4 (8x8) Halloween Style
« Reply #30 on: October 23, 2021, 01:17:00 am »
Ah, you did find a more recent picture of Steve. Thanks!

Pete
Want to learn how to write code on cave walls? https://www.tapatalk.com/groups/qbasic/qbasic-f1/

Offline Cobalt

  • QB64 Developer
  • Forum Resident
  • Posts: 878
  • At 60 I become highly radioactive!
    • View Profile
Re: One Key Connect 4 (8x8) Halloween Style
« Reply #31 on: October 23, 2021, 12:33:40 pm »
@Cobalt Did you insert resizable in code?

@bplus nope just the code straight from the zip, course the one where I added the  overlay.

not just the sides of the screen, but anything showing up on top of the game window too.

Granted after becoming radioactive I only have a half-life!

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: One Key Connect 4 (8x8) Halloween Style
« Reply #32 on: October 23, 2021, 12:45:31 pm »
Hi Cobalt, is that Windows or Linux? If Windows what version? Those icons look different (top right corner).

I image that would mess up with any QB64 window.

Marked as best answer by bplus on October 23, 2021, 09:01:16 am

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: One Key Connect 4 (8x8) Halloween Style
« Reply #33 on: October 23, 2021, 12:54:39 pm »
Here is version #3, here you can play any opponent you want by using a 600 X 680 pixel (or same ratio width X height for least distortion when stretching over screen)  .png file and naming it "Opponent.png". I have 3 sample scary faces in zip, just add digit to current Opponent and remove digit from 1 of the others to try it.

Code: QB64: [Select]
  1. Option _Explicit ' One Key Connect 4 (8x8) Halloween Style - bplus 2021-10-19
  2. Const SQ = 60 '       square or grid cell
  3. Const NumCols = 8 '   number of columns
  4. Const NumRows = 8 '   you guessed it
  5. Const NCM1 = NumCols - 1 ' NumCols minus 1
  6. Const NRM1 = NumRows - 1 ' you can guess surely
  7. Const SW = SQ * (NumCols + 2) '  screen width
  8. Const SH = SQ * (NumRows + 3) '  screen height
  9. Const P = 1 '       Player is 1 on grid
  10. Const AI = -1 '     AI is -1 on grid
  11. Const XO = SQ '     x offset for grid
  12. Const YO = 3 * SQ ' y offset for grid
  13.  
  14. ReDim Shared Grid(NCM1, NRM1) ' 0 = empty  P=1 for Player,  AI=-1  for AI so -4 is win for AI..
  15. ReDim Shared DX(7), DY(7) ' Directions
  16. DX(0) = 1: DY(0) = 0 ': DString$(0) = "East"
  17. DX(1) = 1: DY(1) = 1 ': DString$(1) = "South East"
  18. DX(2) = 0: DY(2) = 1 ': DString$(2) = "South"
  19. DX(3) = -1: DY(3) = 1 ': DString$(3) = "South West"
  20. DX(4) = -1: DY(4) = 0 ': DString$(4) = "West"
  21. DX(5) = -1: DY(5) = -1 ': DString$(5) = "North West"
  22. DX(6) = 0: DY(6) = -1 ': DString$(6) = "North"
  23. DX(7) = 1: DY(7) = -1 ' : DString$(7) = "North East"
  24. ReDim Shared Scores(NCM1) ' rating column for AI and displaying them
  25. ReDim Shared AIX, AIY ' last move of AI for highlighting in display
  26. ReDim Shared WinX, WinY, WinD ' display Winning Connect 4
  27. ReDim Shared GameOn, Turn, GoFirst, PlayerLastMoveCol, PlayerLastMoveRow, MoveNum ' game tracking
  28. ReDim Shared Record$(NCM1, NRM1)
  29. Dim Shared sx, pr ' for pumpkin recursion shifty eyes and pumkin radius
  30. Dim place, k$, t, r, s$, d, temp&, target, y, delaid
  31. Dim Shared Overlay& 'the board overlay
  32. Dim Shared BF& 'opponent's face
  33. Screen _NewImage(SW, SH, 32)
  34. _Delay .25
  35. _ScreenMove 360, 60
  36. Overlay& = _NewImage(SW, SH, 32)
  37. BF& = _LoadImage("Opponent.png")
  38. Create_Board
  39. _Title "One Key Connect 4 (8x8) Halloween Style #3"
  40. d = 1
  41. While _KeyDown(32) = 0
  42.     Cls
  43.     pumpkin 0, _Width / 2, _Height / 2, _Height / 2.3, 3
  44.     sx = sx + d
  45.     If sx > 10 Then d = -d: sx = 10
  46.     If sx < -10 Then d = -d: sx = -10
  47.     Color &HFFFFFFFF
  48.     Locate 40, 33: Print "Spacebar Only"
  49.     _Display
  50.     _Limit 20
  51. GameOn = -1: GoFirst = AI: Turn = AI: MoveNum = 0
  52. ShowGrid
  53. place = -1
  54. t = Timer
  55. pr = (SQ - 2) / 2
  56. While GameOn
  57.     Cls
  58.     If Turn = P Then
  59.         k$ = InKey$
  60.         If k$ = Chr$(27) Then System ' emergency exit
  61.         If k$ = " " Then
  62.             t = Timer: place = place + 1
  63.             If place >= NumCols Then place = -1
  64.         Else ' watch out for midnight!
  65.             If Timer - t < 0 Then 'midnight problem
  66.                 t = Timer ' wait a little longer
  67.             Else
  68.                 If Timer - t > 2 And place <> -1 Then ' col selected
  69.                     r = GetOpenRow(place)
  70.                     If r <> NumRows Then
  71.                         y = 2 * SQ + SQ / 2
  72.                         target = r * SQ + YO + SQ / 2
  73.                         delaid = 6
  74.                         While y < target
  75.                             y = y + 1
  76.                             Cls
  77.                             ShowGrid
  78.                             pumpkin 0, place * SQ + XO + SQ / 2, y, pr, 2
  79.                             sx = Rnd * 6 - 3
  80.                             _PutImage , Overlay&, _Display
  81.                             _Display
  82.                             _Limit delaid
  83.                             delaid = delaid * 2
  84.                         Wend
  85.                         Grid(place, r) = P: Turn = AI: PlayerLastMoveCol = place: PlayerLastMoveRow = r: MoveNum = MoveNum + 1
  86.                         place = -1 ' reset back to hold area
  87.                     Else
  88.                         Beep
  89.                     End If
  90.                 End If
  91.             End If
  92.         End If
  93.     Else
  94.         AIMove
  95.         Turn = P: MoveNum = MoveNum + 1: t = Timer
  96.     End If
  97.     ShowGrid
  98.     If Turn = P Then
  99.         If place = -1 Then
  100.             s$ = "Holding area, press spacebar until over column to play."
  101.         Else
  102.             s$ = "Press Spacebar, if don't want to play" + Str$(place) + " column."
  103.         End If
  104.         dp XO + 1, YO - SQ - 16 + 1, s$
  105.     End If
  106.     pumpkin 0, place * SQ + XO + SQ / 2, 2 * SQ + SQ / 2, pr, 2
  107.     sx = Rnd * 6 - 3
  108.     _PutImage , Overlay&, _Display
  109.     _Display
  110.     _Limit 15
  111.  
  112. Sub AIMove
  113.     ' What this sub does in English:
  114.     ' This sub assigns the value to playing each column, then plays the best value with following caveats:
  115.     ' + If it finds a winning move, it will play that immediately.
  116.     ' + If it finds a spoiler move, it will play that if no winning move was found.
  117.     ' + It will poisen the column's scoring, if opponent can play a winning move if AI plays this column,
  118.     '   but it might be the only legal move left.  We will have to play it if no better score was found.
  119.  
  120.     Dim c, r, d, cntA, cntP, bestScore, startR, startC, iStep, test, goodF, i
  121.     Dim openRow(NCM1) ' find open rows once
  122.     ReDim Scores(NCM1) ' evaluate each column's potential
  123.     AIX = -1: AIY = -1 ' set these when AI makes move, they are signal to display procedure AI's move.
  124.     For c = 0 To NCM1
  125.         openRow(c) = GetOpenRow(c)
  126.         r = openRow(c)
  127.         If r <> NumRows Then
  128.             For d = 0 To 3 ' 4 directions to build connect 4's that use cell c, r
  129.                 startC = c + -3 * DX(d): startR = r + -3 * DY(d)
  130.                 For i = 0 To 3 ' here we backup from the potential connect 4 in opposite build direction of c, r
  131.                     cntA = 0: cntP = 0: goodF = -1 ' reset counts and flag for good connect 4
  132.                     'from this start position run 4 steps forward to count all connects involving cell c, r
  133.                     For iStep = 0 To 3 ' process a potential connect 4
  134.                         test = GR(startC + i * DX(d) + iStep * DX(d), startR + i * DY(d) + iStep * DY(d))
  135.                         If test = NumRows Then goodF = 0: Exit For 'cant get connect4 from here
  136.                         If test = AI Then cntA = cntA + 1
  137.                         If test = P Then cntP = cntP + 1
  138.                     Next iStep
  139.                     If goodF Then 'evaluate the Legal Connect4 we could build with c, r
  140.                         If cntA = 3 Then ' we are done!  winner!
  141.                             AIX = c: AIY = r ' <<< this is the needed 4th cell to win tell ShowGrid last cell
  142.                             Grid(c, r) = AI '  <<< this is the needed 4th cell to win, add to grid this is AI move
  143.                             Scores(c) = 1000
  144.                             Exit Sub
  145.                         ElseIf cntP = 3 Then 'next best move spoiler!
  146.                             AIX = c: AIY = r 'set the move but don't exit there might be a winner
  147.                             Scores(c) = 900
  148.                         ElseIf cntA = 0 And cntP = 2 Then
  149.                             Scores(c) = Scores(c) + 8
  150.                         ElseIf cntA = 2 And cntP = 0 Then ' very good offense or defense
  151.                             Scores(c) = Scores(c) + 4 'play this to connect 3 or prevent player from Connect 3
  152.                         ElseIf cntA = 0 And cntP = 1 Then
  153.                             Scores(c) = Scores(c) + 4
  154.                         ElseIf (cntA = 1 And cntP = 0) Then 'good offense or defense
  155.                             Scores(c) = Scores(c) + 2 ' play this to connect 2 or prevent player from Connect 2
  156.                         ElseIf (cntA = 0 And cntP = 0) Then ' OK it's not a wasted move as it has potential for connect4
  157.                             Scores(c) = Scores(c) + 1 ' this is good move because this can still be a Connect 4
  158.                         End If
  159.                     End If ' in the board
  160.                 Next i
  161.             Next d
  162.             If Stupid(c, r) Then Scores(c) = -1000 + Scores(c) ' poison because if played the human can win
  163.         End If
  164.     Next
  165.     If AIX <> -1 Then ' we found a spoiler so move there since we haven't found a winner
  166.         Grid(AIX, AIY) = AI ' make move on grid and done!
  167.         Exit Sub
  168.     Else
  169.         If GetOpenRow(PlayerLastMoveCol) < NumRows Then 'all things being equal play on top of player's last move
  170.             bestScore = Scores(PlayerLastMoveCol): AIY = PlayerLastMoveRow - 1: AIX = PlayerLastMoveCol
  171.         Else
  172.             bestScore = -1000 ' a negative score indicates that the player can beat AI with their next move
  173.         End If
  174.         For c = 0 To NCM1
  175.             r = openRow(c)
  176.             If r <> NumRows Then
  177.                 If Scores(c) > bestScore Then bestScore = Scores(c): AIY = r: AIX = c
  178.             End If
  179.         Next
  180.         If AIX <> -1 Then
  181.             Grid(AIX, AIY) = AI ' make first best score move we found
  182.         Else 'We have trouble!  Oh but it could be there are no moves!!!
  183.             ' checkWin is run after every move by AI or Player if there were no legal moves left it should have caught that.
  184.             ' Just in case it didn't here is an error stop!
  185.             Beep
  186.             dp 2 * 8, 4 * 16, "AI has failed to find a proper move, press any to end..."
  187.             Sleep ' <<< pause until user presses a key
  188.             End
  189.         End If
  190.     End If
  191.  
  192. Function GetOpenRow (forCol)
  193.     Dim i
  194.     GetOpenRow = NumRows 'assume none open
  195.     If forCol < 0 Or forCol > NCM1 Then Exit Function
  196.     For i = NRM1 To 0 Step -1
  197.         If Grid(forCol, i) = 0 Then GetOpenRow = i: Exit Function
  198.     Next
  199.  
  200. Function Stupid (c, r)
  201.     Dim ppr
  202.     Grid(c, r) = AI
  203.     ppr = GetOpenRow(c)
  204.     If ppr <> NumRows Then
  205.         Grid(c, ppr) = P
  206.         If CheckWin = 4 Then Stupid = -1
  207.         Grid(c, ppr) = 0
  208.     End If
  209.     Grid(c, r) = 0
  210.  
  211. Function GR (c, r) ' if c, r are out of bounds returns N else returns grid(c, r)
  212.     ' need to check the grid(c, r) but only if c, r is on the board
  213.     If c < 0 Or c > NCM1 Or r < 0 Or r > NRM1 Then GR = NumRows Else GR = Grid(c, r)
  214.  
  215. Sub ShowGrid
  216.     Static lastMoveNum
  217.     Dim i, r, c, check, s$, k$
  218.     If MoveNum <> lastMoveNum Then ' file newest move
  219.         If MoveNum = 1 Then ReDim Record$(NCM1, NRM1)
  220.         If Turn = -1 Then
  221.             Record$(PlayerLastMoveCol, PlayerLastMoveRow) = _Trim$(Str$(MoveNum)) + " " + "P"
  222.         Else
  223.             Record$(AIX, AIY) = _Trim$(Str$(MoveNum)) + " " + "A"
  224.         End If
  225.         lastMoveNum = MoveNum
  226.     End If
  227.     Color _RGB32(255, 255, 255), _RGB32(0): Cls
  228.     _PutImage , BF&, 0, (10, 10)-(_Width(BF&) - 20, _Height(BF&) - 50)
  229.     'Line (XO, YO)-Step(NumCols * SQ, NumRows * SQ), &HFF004400, BF
  230.     For i = 0 To NumCols 'grid
  231.         Line (SQ * i + XO, YO)-Step(0, NumRows * SQ), &HFFFFFFFF
  232.     Next
  233.     For i = 0 To NumRows
  234.         Line (XO, SQ * i + YO)-Step(NumCols * SQ, 0), &HFFFFFFFF
  235.     Next
  236.     Color
  237.     For r = NRM1 To 0 Step -1 ''in grid rows are reversed 0 is top row
  238.         For c = 0 To NCM1
  239.             If Grid(c, r) = P Then
  240.                 'Line (c * SQ + XO + 3, r * SQ + YO + 3)-Step(SQ - 6, SQ - 6), &HFF000000, BF
  241.                 pumpkin 0, c * SQ + XO + SQ / 2, r * SQ + YO + SQ / 2, pr, 2
  242.  
  243.             ElseIf Grid(c, r) = AI Then
  244.                 If c = AIX And r = AIY Then 'highlite last AI move
  245.                     'Line (c * SQ + XO + 3, r * SQ + YO + 3)-Step(SQ - 6, SQ - 6), &HFF8888FF, BF  ' no overlay
  246.                     Line (c * SQ + XO, r * SQ + YO)-Step(SQ, SQ), &HFF8888FF, BF
  247.                 Else
  248.                     'Line (c * SQ + XO + 3, r * SQ + YO + 3)-Step(SQ - 6, SQ - 6), &HFF4444FF, BF  ' no overlay
  249.                     Line (c * SQ + XO, r * SQ + YO)-Step(SQ, SQ), &HFF4444FF, BF
  250.                 End If
  251.                 drawSpinner c * SQ + XO + SQ / 2, r * SQ + YO + SQ / 2, .4, _Pi(-c / 8), _RGB32(Rnd * 30 + 40, Rnd * 15 + 20, Rnd * 6 + 10)
  252.             End If
  253.             s$ = _Trim$(Str$(Scores(c)))
  254.             dp XO + c * SQ + (60 - Len(s$) * 8) / 2, YO + SQ * NumRows + 22, s$
  255.         Next
  256.     Next
  257.     '_Display
  258.     check = CheckWin
  259.     If check Then 'report end of round ad see if want to play again
  260.         If check = 4 Or check = -4 Then
  261.             For i = 0 To 3
  262.                 Line ((WinX + i * DX(WinD)) * SQ + XO + 10, (WinY + i * DY(WinD)) * SQ + YO + 10)-Step(SQ - 20, SQ - 20), &HFFFFFF00, B
  263.             Next
  264.         End If
  265.         For r = 0 To NRM1
  266.             For c = 0 To NCM1
  267.                 If Record$(c, r) <> "" Then
  268.                     s$ = Mid$(Record$(c, r), 1, InStr(Record$(c, r), " ") - 1)
  269.                     dp SQ * c + XO + (SQ - Len(s$) * 8) / 2, SQ * r + YO + 22, s$
  270.                 End If
  271.             Next
  272.         Next
  273.         If check = -4 Then
  274.             s$ = " AI is Winner!"
  275.         ElseIf check = 4 Then
  276.             s$ = " Human is Winner!"
  277.         ElseIf check = NumRows Then
  278.             s$ = " Board is full, no winner." ' keep Turn the same
  279.         End If
  280.         dp (SW - Len(s$) * 8) / 2, 2 * 16, s$
  281.         s$ = " Play again? press spacebar, escape to quit... "
  282.         dp (SW - Len(s$) * 8) / 2, 4 * 16, s$
  283.         _PutImage , Overlay&, _Display
  284.         _Display
  285.         keywait:
  286.         While Len(k$) = 0
  287.             k$ = InKey$
  288.             _Limit 200
  289.         Wend
  290.         If k$ = " " Then
  291.             ReDim Grid(NCM1, NRM1), Scores(NCM1)
  292.             If GoFirst = P Then GoFirst = AI Else GoFirst = P
  293.             Turn = GoFirst: MoveNum = 0
  294.         ElseIf Asc(k$) = 27 Then
  295.             System
  296.         Else
  297.             k$ = "": GoTo keywait:
  298.         End If
  299.     End If
  300.  
  301. Function CheckWin ' return WinX, WinY, WinD along with +/- 4, returns NumRows if grid full, 0 if no win and grid not full
  302.     Dim gridFull, r, c, s, i
  303.     gridFull = NumRows
  304.     For r = NRM1 To 0 Step -1 'bottom to top
  305.         For c = 0 To NCM1
  306.             If Grid(c, r) Then ' check if c starts a row
  307.                 If c < NCM1 - 2 Then
  308.                     s = 0
  309.                     For i = 0 To 3 ' east
  310.                         s = s + Grid(c + i, r)
  311.                     Next
  312.                     If s = 4 Or s = -4 Then WinX = c: WinY = r: WinD = 0: CheckWin = s: Exit Function
  313.                 End If
  314.                 If r > 2 Then ' check if c starts a col
  315.                     s = 0
  316.                     For i = 0 To 3 ' north
  317.                         s = s + Grid(c, r - i)
  318.                     Next
  319.                     If s = 4 Or s = -4 Then WinX = c: WinY = r: WinD = 6: CheckWin = s: Exit Function
  320.                 End If
  321.                 If r > 2 And c < NCM1 - 2 Then 'check if c starts diagonal up to right
  322.                     s = 0
  323.                     For i = 0 To 3 ' north  east
  324.                         s = s + Grid(c + i, r - i)
  325.                     Next
  326.                     If s = 4 Or s = -4 Then WinX = c: WinY = r: WinD = 7: CheckWin = s: Exit Function
  327.                 End If
  328.                 If r > 2 And c > 2 Then 'check if c starts a diagonal up to left
  329.                     s = 0
  330.                     For i = 0 To 3 ' north west
  331.                         s = s + Grid(c - i, r - i)
  332.                     Next
  333.                     If s = 4 Or s = -4 Then WinX = c: WinY = r: WinD = 5: CheckWin = s: Exit Function
  334.                 End If
  335.             Else
  336.                 gridFull = 0 ' at least one enpty cell left
  337.             End If 'grid is something
  338.         Next
  339.     Next
  340.     CheckWin = gridFull
  341.  
  342.  
  343. Sub pumpkin (dh&, cx, cy, pr, limit)
  344.     Dim lastr, u, dx, i, tx1, tx2, tx3, ty1, ty2, ty3, ty22, sxs
  345.     'carve this!
  346.     Color &HFFFF0000
  347.     fEllipse cx, cy, pr, 29 / 35 * pr
  348.     Color &HFF000000
  349.     lastr = 2 / 7 * pr
  350.     Do
  351.         ellipse cx, cy, lastr, 29 / 35 * pr
  352.         lastr = .5 * (pr - lastr) + lastr + 1 / 35 * pr
  353.         If pr - lastr < 1 / 80 * pr Then Exit Do
  354.     Loop
  355.  
  356.     ' 'flickering candle light
  357.     'Color _RGB(Rnd * 55 + 200, Rnd * 55 + 200, 120)
  358.  
  359.     ' eye sockets
  360.     ftri2 dh&, cx - 9 * pr / 12, cy - 2 * pr / 12, cx - 7 * pr / 12, cy - 6 * pr / 12, cx - 3 * pr / 12, cy - 0 * pr / 12, _RGB(Rnd * 55 + 200, Rnd * 55 + 200, 120)
  361.     ftri2 dh&, cx - 7 * pr / 12, cy - 6 * pr / 12, cx - 3 * pr / 12, cy - 0 * pr / 12, cx - 2 * pr / 12, cy - 3 * pr / 12, _RGB(Rnd * 55 + 200, Rnd * 55 + 200, 120)
  362.     ftri2 dh&, cx + 9 * pr / 12, cy - 2 * pr / 12, cx + 7 * pr / 12, cy - 6 * pr / 12, cx + 3 * pr / 12, cy - 0 * pr / 12, _RGB(Rnd * 55 + 200, Rnd * 55 + 200, 120)
  363.     ftri2 dh&, cx + 7 * pr / 12, cy - 6 * pr / 12, cx + 3 * pr / 12, cy - 0 * pr / 12, cx + 2 * pr / 12, cy - 3 * pr / 12, _RGB(Rnd * 55 + 200, Rnd * 55 + 200, 120)
  364.  
  365.     ' nose
  366.     ftri2 dh&, cx, cy - rand%(2, 5) * pr / 12, cx - 2 * pr / 12, cy + 2 * pr / 12, cx + rand%(1, 2) * pr / 12, cy + 2 * pr / 12, _RGB(Rnd * 55 + 200, Rnd * 55 + 200, 120)
  367.  
  368.     ' evil grin
  369.     ftri2 dh&, cx - 9 * pr / 12, cy + 1 * pr / 12, cx - 7 * pr / 12, cy + 7 * pr / 12, cx - 6 * pr / 12, cy + 5 * pr / 12, _RGB(Rnd * 55 + 200, Rnd * 55 + 200, 120)
  370.     ftri2 dh&, cx + 9 * pr / 12, cy + 1 * pr / 12, cx + 7 * pr / 12, cy + 7 * pr / 12, cx + 6 * pr / 12, cy + 5 * pr / 12, _RGB(Rnd * 55 + 200, Rnd * 55 + 200, 120)
  371.  
  372.     ' moving teeth/talk/grrrr..
  373.     u = rand%(4, 8)
  374.     dx = pr / u
  375.     For i = 1 To u
  376.         tx1 = cx - 6 * pr / 12 + (i - 1) * dx
  377.         tx2 = tx1 + .5 * dx
  378.         tx3 = tx1 + dx
  379.         ty1 = cy + 5 * pr / 12
  380.         ty3 = cy + 5 * pr / 12
  381.         ty2 = cy + (4 - Rnd) * pr / 12
  382.         ty22 = cy + (6 + Rnd) * pr / 12
  383.         ftri2 dh&, tx1, ty1, tx2, ty2, tx3, ty3, _RGB(Rnd * 55 + 200, Rnd * 55 + 200, 120)
  384.         ftri2 dh&, tx1 + .5 * dx, ty1, tx2 + .5 * dx, ty22, tx3 + .5 * dx, ty3, _RGB(Rnd * 55 + 200, Rnd * 55 + 200, 120)
  385.     Next
  386.     If limit Then
  387.         'shifty eyes
  388.         If limit = 3 Then sxs = sx Else sxs = .1 * limit * sx
  389.         pumpkin dh&, sxs + cx - 5 * pr / 12, cy - 2.5 * pr / 12, .15 * pr, Int(limit - 1)
  390.         pumpkin dh&, sxs + cx + 5 * pr / 12, cy - 2.5 * pr / 12, .15 * pr, Int(limit - 1)
  391.     End If
  392.  
  393. Sub fEllipse (CX As Long, CY As Long, xRadius As Long, yRadius As Long)
  394.     Dim scale As Single, x As Long, y As Long
  395.     scale = yRadius / xRadius
  396.     Line (CX, CY - yRadius)-(CX, CY + yRadius), , BF
  397.     For x = 1 To xRadius
  398.         y = scale * Sqr(xRadius * xRadius - x * x)
  399.         Line (CX + x, CY - y)-(CX + x, CY + y), , BF
  400.         Line (CX - x, CY - y)-(CX - x, CY + y), , BF
  401.     Next
  402.  
  403. Sub ellipse (CX As Long, CY As Long, xRadius As Long, yRadius As Long)
  404.     Dim scale As Single, xs As Long, x As Long, y As Long
  405.     Dim lastx As Long, lasty As Long
  406.     scale = yRadius / xRadius: xs = xRadius * xRadius
  407.     PSet (CX, CY - yRadius): PSet (CX, CY + yRadius)
  408.     lastx = 0: lasty = yRadius
  409.     For x = 1 To xRadius
  410.         y = scale * Sqr(xs - x * x)
  411.         Line (CX + lastx, CY - lasty)-(CX + x, CY - y)
  412.         Line (CX + lastx, CY + lasty)-(CX + x, CY + y)
  413.         Line (CX - lastx, CY - lasty)-(CX - x, CY - y)
  414.         Line (CX - lastx, CY + lasty)-(CX - x, CY + y)
  415.         lastx = x: lasty = y
  416.     Next
  417.  
  418. Sub ftri2 (returnDest&, x1, y1, x2, y2, x3, y3, K As _Unsigned Long)
  419.     Dim a&
  420.     a& = _NewImage(1, 1, 32)
  421.     _Dest a&
  422.     PSet (0, 0), K
  423.     _Dest returnDest&
  424.     _MapTriangle _Seamless(0, 0)-(0, 0)-(0, 0), a& To(x1, y1)-(x2, y2)-(x3, y3)
  425.     _FreeImage a& '<<< this is important!
  426.  
  427. Function rand% (lo%, hi%)
  428.     rand% = Int(Rnd * (hi% - lo% + 1)) + lo%
  429.  
  430.  
  431.  
  432. Sub drawLink (x1, y1, r1, x2, y2, r2, c As _Unsigned Long)
  433.     Dim a, a1, a2, x3, x4, x5, x6, y3, y4, y5, y6
  434.     a = _Atan2(y2 - y1, x2 - x1)
  435.     a1 = a + _Pi(1 / 2)
  436.     a2 = a - _Pi(1 / 2)
  437.     x3 = x1 + r1 * Cos(a1): y3 = y1 + r1 * Sin(a1)
  438.     x4 = x1 + r1 * Cos(a2): y4 = y1 + r1 * Sin(a2)
  439.     x5 = x2 + r2 * Cos(a1): y5 = y2 + r2 * Sin(a1)
  440.     x6 = x2 + r2 * Cos(a2): y6 = y2 + r2 * Sin(a2)
  441.     fquad x3, y3, x4, y4, x5, y5, x6, y6, c
  442.     Fcirc x1, y1, r1, c
  443.     Fcirc x2, y2, r2, c
  444.  
  445. 'need 4 non linear points (not all on 1 line) list them clockwise so x2, y2 is opposite of x4, y4
  446. Sub fquad (x1 As Integer, y1 As Integer, x2 As Integer, y2 As Integer, x3 As Integer, y3 As Integer, x4 As Integer, y4 As Integer, c As _Unsigned Long)
  447.     ftri x1, y1, x2, y2, x4, y4, c
  448.     ftri x3, y3, x4, y4, x1, y1, c
  449.  
  450. Sub ftri (x1, y1, x2, y2, x3, y3, K As _Unsigned Long)
  451.     Dim a&
  452.     a& = _NewImage(1, 1, 32)
  453.     _Dest a&
  454.     PSet (0, 0), K
  455.     _Dest 0
  456.     _MapTriangle _Seamless(0, 0)-(0, 0)-(0, 0), a& To(x1, y1)-(x2, y2)-(x3, y3)
  457.     _FreeImage a& '<<< this is important!
  458.  
  459. Sub TiltedEllipseFill (destHandle&, x0, y0, a, b, ang, c As _Unsigned Long)
  460.     Dim max As Integer, mx2 As Integer, i As Integer, j As Integer, k As Single, lasti As Single, lastj As Single
  461.     Dim prc As _Unsigned Long, tef As Long
  462.     prc = _RGB32(255, 255, 255, 255)
  463.     If a > b Then max = a + 1 Else max = b + 1
  464.     mx2 = max + max
  465.     tef = _NewImage(mx2, mx2)
  466.     _Dest tef
  467.     _Source tef 'point wont read without this!
  468.     For k = 0 To 6.2832 + .05 Step .1
  469.         i = max + a * Cos(k) * Cos(ang) + b * Sin(k) * Sin(ang)
  470.         j = max + a * Cos(k) * Sin(ang) - b * Sin(k) * Cos(ang)
  471.         If k <> 0 Then
  472.             Line (lasti, lastj)-(i, j), prc
  473.         Else
  474.             PSet (i, j), prc
  475.         End If
  476.         lasti = i: lastj = j
  477.     Next
  478.     Dim xleft(mx2) As Integer, xright(mx2) As Integer, x As Integer, y As Integer
  479.     For y = 0 To mx2
  480.         x = 0
  481.         While Point(x, y) <> prc And x < mx2
  482.             x = x + 1
  483.         Wend
  484.         xleft(y) = x
  485.         While Point(x, y) = prc And x < mx2
  486.             x = x + 1
  487.         Wend
  488.         While Point(x, y) <> prc And x < mx2
  489.             x = x + 1
  490.         Wend
  491.         If x = mx2 Then xright(y) = xleft(y) Else xright(y) = x
  492.     Next
  493.     _Dest destHandle&
  494.     For y = 0 To mx2
  495.         If xleft(y) <> mx2 Then Line (xleft(y) + x0 - max, y + y0 - max)-(xright(y) + x0 - max, y + y0 - max), c, BF
  496.     Next
  497.     _FreeImage tef
  498.  
  499. Sub Fcirc (CX As Long, CY As Long, R As Long, C As _Unsigned Long)
  500.     Dim Radius As Long, RadiusError As Long
  501.     Dim X As Long, Y As Long
  502.     Radius = Abs(R): RadiusError = -Radius: X = Radius: Y = 0
  503.     If Radius = 0 Then PSet (CX, CY), C: Exit Sub
  504.     Line (CX - X, CY)-(CX + X, CY), C, BF
  505.     While X > Y
  506.         RadiusError = RadiusError + Y * 2 + 1
  507.         If RadiusError >= 0 Then
  508.             If X <> Y + 1 Then
  509.                 Line (CX - Y, CY - X)-(CX + Y, CY - X), C, BF
  510.                 Line (CX - Y, CY + X)-(CX + Y, CY + X), C, BF
  511.             End If
  512.             X = X - 1
  513.             RadiusError = RadiusError - X * 2
  514.         End If
  515.         Y = Y + 1
  516.         Line (CX - X, CY - Y)-(CX + X, CY - Y), C, BF
  517.         Line (CX - X, CY + Y)-(CX + X, CY + Y), C, BF
  518.     Wend
  519.  
  520. Sub drawSpinner (x As Integer, y As Integer, scale As Single, heading As Single, c As _Unsigned Long)
  521.     Dim x1, x2, x3, x4, y1, y2, y3, y4, r, a, a1, a2, lg, d, rd
  522.     Dim rred, bblue, ggreen
  523.     Static switch As Integer
  524.     switch = switch + 2
  525.     switch = switch Mod 16 + 1
  526.     rred = _Red32(c): ggreen = _Green32(c): bblue = _Blue32(c)
  527.     r = 10 * scale
  528.     x1 = x + r * Cos(heading): y1 = y + r * Sin(heading)
  529.     r = 2 * r 'lg lengths
  530.     For lg = 1 To 8
  531.         If lg < 5 Then
  532.             a = heading + .9 * lg * _Pi(1 / 5) + (lg = switch) * _Pi(1 / 10)
  533.         Else
  534.             a = heading - .9 * (lg - 4) * _Pi(1 / 5) - (lg = switch) * _Pi(1 / 10)
  535.         End If
  536.         x2 = x1 + r * Cos(a): y2 = y1 + r * Sin(a)
  537.         drawLink x1, y1, 3 * scale, x2, y2, 2 * scale, _RGB32(rred + 20, ggreen + 10, bblue + 5)
  538.         If lg = 1 Or lg = 2 Or lg = 7 Or lg = 8 Then d = -1 Else d = 1
  539.         a1 = a + d * _Pi(1 / 12)
  540.         x3 = x2 + r * 1.5 * Cos(a1): y3 = y2 + r * 1.5 * Sin(a1)
  541.         drawLink x2, y2, 2 * scale, x3, y3, scale, _RGB32(rred + 35, ggreen + 17, bblue + 8)
  542.         rd = Int(Rnd * 8) + 1
  543.         a2 = a1 + d * _Pi(1 / 8) * rd / 8
  544.         x4 = x3 + r * 1.5 * Cos(a2): y4 = y3 + r * 1.5 * Sin(a2)
  545.         drawLink x3, y3, scale, x4, y4, scale, _RGB32(rred + 50, ggreen + 25, bblue + 12)
  546.     Next
  547.     r = r * .5
  548.     Fcirc x1, y1, r, _RGB32(rred - 20, ggreen - 10, bblue - 5)
  549.     x2 = x1 + (r + 1) * Cos(heading - _Pi(1 / 12)): y2 = y1 + (r + 1) * Sin(heading - _Pi(1 / 12))
  550.     Fcirc x2, y2, r * .2, &HFF000000
  551.     x2 = x1 + (r + 1) * Cos(heading + _Pi(1 / 12)): y2 = y1 + (r + 1) * Sin(heading + _Pi(1 / 12))
  552.     Fcirc x2, y2, r * .2, &HFF000000
  553.     r = r * 2
  554.     x1 = x + r * .9 * Cos(heading + _Pi): y1 = y + r * .9 * Sin(heading + _Pi)
  555.     TiltedEllipseFill 0, x1, y1, r, .7 * r, heading + _Pi, _RGB32(rred, ggreen, bblue)
  556.  
  557. Sub Create_Board
  558.     Dim As Integer x, y
  559.     _Dest Overlay&
  560.     Line (XO, YO)-Step(SQ * NumCols, SQ * NumRows), _RGB32(40, 20, 10), BF
  561.     For y = 0 To NRM1
  562.         For x = 0 To NCM1
  563.             Fcirc SQ * x + XO + SQ / 2, SQ * y + YO + SQ / 2, (SQ - 2) / 2, _RGB32(0)
  564.     Next x, y
  565.     _ClearColor _RGB32(0), Overlay&
  566.  
  567. Sub dp (x, y, s$) ' double print white over black to stand out over images
  568.     Color &HFF000000
  569.     _PrintString (x + 1, y + 1), s$
  570.     Color &HFFFFFFFF
  571.     _PrintString (x, y), s$
  572.  
  573.  

I have given spiders solid background so they may be seen wiggling better.

 
1Key Connect4 #3 Human Wins.PNG


That's probably my final version.
* 1 key Connect 4 Halloween #3.zip (Filesize: 2.98 MB, Downloads: 248)

Offline Pete

  • Forum Resident
  • Posts: 2361
  • Cuz I sez so, varmint!
    • View Profile
Re: One Key Connect 4 (8x8) Halloween Style
« Reply #34 on: October 23, 2021, 01:01:07 pm »
@bplus and @Cobalt

I'm using Windows 10, and I don't get the distortion effect when dragging the game to the edges, as depicted in the video. BTW @Cobalt What type of screen recorder are you using to produce the vids?

Pete
Want to learn how to write code on cave walls? https://www.tapatalk.com/groups/qbasic/qbasic-f1/

Offline Cobalt

  • QB64 Developer
  • Forum Resident
  • Posts: 878
  • At 60 I become highly radioactive!
    • View Profile
Re: One Key Connect 4 (8x8) Halloween Style
« Reply #35 on: October 23, 2021, 01:17:29 pm »
Hi Cobalt, is that Windows or Linux? If Windows what version? Those icons look different (top right corner).

I image that would mess up with any QB64 window.

Windows.
Typically only does that on programs using the _DISPLAY keyword. And on random occasion with the IDE.
Granted after becoming radioactive I only have a half-life!

Offline Cobalt

  • QB64 Developer
  • Forum Resident
  • Posts: 878
  • At 60 I become highly radioactive!
    • View Profile
Re: One Key Connect 4 (8x8) Halloween Style
« Reply #36 on: October 23, 2021, 01:18:41 pm »

I'm using Windows 10, and I don't get the distortion effect when dragging the game to the edges, as depicted in the video. BTW @Cobalt What type of screen recorder are you using to produce the vids?

Pete

@Pete its called Active Presenter.
Granted after becoming radioactive I only have a half-life!

Offline Pete

  • Forum Resident
  • Posts: 2361
  • Cuz I sez so, varmint!
    • View Profile
Re: One Key Connect 4 (8x8) Halloween Style
« Reply #37 on: October 23, 2021, 01:32:08 pm »
@Cobalt. Thanks, I bookmarked the download site.

@bplus

I combined Halloween with Easter and can someone tell me what month they celebrate gay pride?

 
Screenshot (304).png


Kidding aside, I did try it with a "straight" black background, and I really liked that rendition.
 
Pete

Want to learn how to write code on cave walls? https://www.tapatalk.com/groups/qbasic/qbasic-f1/

Offline Dav

  • Forum Resident
  • Posts: 792
    • View Profile
Re: One Key Connect 4 (8x8) Halloween Style
« Reply #38 on: October 25, 2021, 09:59:15 am »
@Dav you had it figured out some time ago, my guess your memory getting like mine. This is old Connect 4 posted almost year ago but now we see our opponent!

I remember playing it before, but couldn't remember a technique that worked, but I think I found it again.  I've found if I mirror the AI play, and divide the playing field, it's easier to out think it.  Like this image shows, it drops on one side, I drop one on the opposite side. I drew boxes around the pieces to show how I matched the pieces.  This way I can beat it pretty often.

Had fun playing this.

- Dav

 
connect4halloween.jpg

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: One Key Connect 4 (8x8) Halloween Style
« Reply #39 on: October 25, 2021, 12:26:46 pm »
@Dav you might be onto how to play a perfect game! Supposedly it's been proved that for 8x8 Connect 4 Boards the 2nd player always wins in perfect game.

DaiHard at Syntax Bomb pointed me to a link about proof
https://tromp.github.io/c4/c4.html

and code for 8x8 game, I think? :)
https://github.com/tromp/fhourstones88/commit/8378b3256e9dcb79d90b856820cbcc7cef31e66f

Offline Pete

  • Forum Resident
  • Posts: 2361
  • Cuz I sez so, varmint!
    • View Profile
Re: One Key Connect 4 (8x8) Halloween Style
« Reply #40 on: October 25, 2021, 01:38:12 pm »
Nice work, Dav!

I noticed the A.I. would almost always stack on top. I figured this was a vulnerability that could be exploited, but I wasn't willing to investigate it further. I also "felt" there was a distinct advantage to going second.

So if we use your strategy, maybe Mark should code in a "Screw you, I quit!" message from the A.I.? Hey, he already uses a variable named "Stupid" to track our mistakes. :D

Pete
Want to learn how to write code on cave walls? https://www.tapatalk.com/groups/qbasic/qbasic-f1/

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: One Key Connect 4 (8x8) Halloween Style
« Reply #41 on: October 25, 2021, 03:16:59 pm »
Or the Board could suddenly be overrun by spiders!

The Stupid subroutine is to avoid making a stupid move ie putting a piece upon which the opponent may place his piece and win, sometimes stupid moves can't be avoided, that's when board should be overrun by spiders LOL!

I wish the human could use the Stupid sub too, hey maybe another mod! ;-))