Guest User

Battleship

a guest
Jun 2nd, 2022
185
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #NoEnv
  2. #SingleInstance, Force
  3. #Persistent
  4. Process, Priority,, High
  5. SetBatchLines, -1
  6. ListLines, Off
  7. SetWinDelay, -1
  8.  
  9. /*
  10. Options : an array of
  11.     - an array of ships length
  12.     - number of rows and columns of the grid
  13.     - the size of the cells (pixels)
  14. */
  15. small := [[2, 2, 2, 3, 3, 4], 8, 40]
  16. medium := [[2, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 5], 15, 30]
  17. large := [[2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 6, 6, 7], 25, 18]
  18.  
  19. Battleship := New Battleship(small)
  20.  
  21. OnMessage(0x200,"OnMouseMove")
  22. Return
  23.  
  24. OnMouseMove() {
  25.     Battleship.Hover(A_GuiControl)
  26. }
  27.  
  28. BattleshipGuiClose:
  29. ExitApp
  30.  
  31. class Battleship {
  32.     __New(options) {
  33.         this.ships := options[1]
  34.         this.grid := options[2]
  35.         this.size := options[3]
  36.         this.CurrentHover := 0
  37.         this.colors := {background: "969696", water:"122A5A", hover:"617298", ship:"135A12", hit:"6C1E15", miss:"414141", sank:"171A1F"}
  38.         this.human := new Player(this.ships, this.grid, "human", "computer")
  39.         this.computer := new Player(this.ships, this.grid, "computer", "human")
  40.         this.squares := {}
  41.         this.CreateGui()
  42.         for i, j in this.human.grid {
  43.             for k, l in j {
  44.                 if l.ship
  45.                     this.ChangeColor("h" "X" i "Y" k, this.colors.ship)
  46.             }
  47.         }
  48.         this.turn := "human"
  49.         this.winner := 0
  50.     }
  51.     CreateGui() {
  52.         Gui Battleship: Color, % this.colors.background
  53.         Gui Battleship: Show, % "w" this.size * this.grid " h" (this.size * this.grid * 2) + 30, Battleship
  54.         this.CreateGrid("c", 0)
  55.         this.CreateGrid("h", (this.grid * this.size) + 30)
  56.     }
  57.     Hover(btn) {
  58.         btn := StrReplace(btn, "b")
  59.         coord := StrSplit(btn, ["X","Y"])
  60.         x := coord[2]
  61.         y := coord[3]
  62.         NoHover := 0
  63.         if this.human.Egrid[x][y].revealed
  64.             NoHover := 1
  65.         if (!btn OR (SubStr(btn, 1, 1) != "c") OR NoHover) AND this.CurrentHover {
  66.             this.ChangeColor(this.CurrentHover, this.colors.water)
  67.             this.CurrentHover := 0
  68.         }
  69.         if (btn != 0) AND (SubStr(btn, 1, 1) = "c") AND (btn != this.CurrentHover) AND !NoHover {
  70.             this.ChangeColor(this.CurrentHover, this.colors.water)
  71.             this.CurrentHover := btn
  72.             this.ChangeColor(this.CurrentHover, this.colors.hover)
  73.         }
  74.     }
  75.     CreateGrid(player, offset) {
  76.         Global
  77.         if (offset = 0)
  78.             Gui Battleship: Add, Text, % "x10 y" (this.grid * this.size) + 7 " w" (this.grid * this.size) - 10 " h" 30 - 7 " vInfoText",
  79.         Loop, % this.grid
  80.             {
  81.             x := A_Index
  82.             Loop, % this.grid
  83.                 {
  84.                 y := A_Index
  85.                 Gui Battleship: Add, Progress, % "w" this.size - 2 " h" this.size - 2 " x" ((x - 1) * this.size) + 1 " y" ((y - 1) * this.size) + offset + 1 " Background" this.colors.water " Disabled -E0x0200 v" player "X" x "Y" y
  86.                 Gui Battleship: Add, Text, % "w" this.size - 2 " h" this.size - 2 " x" ((x - 1) * this.size) + 1 " y" ((y - 1) * this.size) + offset + 1 " BackgroundTrans v" player "bX" x "Y" y
  87.                 BindBtn := ObjBindMethod(this, "DropBomb", {p:player,x:x,y:y})
  88.                 GuiControl Battleship: +g, % player "bX" x "Y" y, % BindBtn
  89.             }
  90.         }
  91.     }
  92.     DropBomb(d) {
  93.         if this.winner
  94.             Return
  95.         if (d.p = "c") {
  96.             receiver := "computer"
  97.             attacker := "human"
  98.         }
  99.         else {
  100.             receiver := "human"
  101.             attacker := "computer"
  102.         }
  103.         if this[attacker].Click(d.x, d.y) {
  104.             hit := this[receiver].TakeHit(d.x, d.y)
  105.             this[attacker].GiveHit(d.x, d.y, hit.shipID)
  106.             if (hit.shipL < 0) {
  107.                 this.CurrentHover := 0
  108.                 this.ChangeColor(SubStr(receiver, 1, 1) "X" d.x "Y" d.y, this.colors.miss)
  109.             }
  110.             else if (hit.shipL = 0) {
  111.                 this.CurrentHover := 0
  112.                 this.Sink(attacker, receiver, hit.shipID)
  113.             }
  114.             else if (hit.shipL >= 0) {
  115.                 this.CurrentHover := 0
  116.                 this.ChangeColor(SubStr(receiver, 1, 1) "X" d.x "Y" d.y, this.colors.hit)
  117.             }
  118.             if (this.turn = "computer") AND (hit.shipL >= 0)
  119.                 this.computer.MadeDamage(d, hit)
  120.             if this.winner {
  121.                 this.turn := 0
  122.                 Return
  123.             }
  124.             this.ChangeTurn()
  125.             if (this.turn = "computer")
  126.                 this.DropBomb(this.computer.Play())
  127.         }
  128.     }
  129.     Sink(attacker, receiver, shipID) {
  130.         parts := this[receiver].GetParts(shipID)
  131.         this[attacker].Sink(parts)
  132.         for i, j in parts {
  133.             this.ChangeColor(SubStr(receiver, 1, 1) "X" j.x "Y" j.y, this.colors.sank)
  134.         }
  135.         if (this[receiver].GetTotalL() = 0) {
  136.             this.SetWinner(attacker)
  137.         }
  138.     }
  139.     SetWinner(player) {
  140.         Global
  141.         phrases := {}
  142.         phrases["computer"] := ["You lost again.","You should stick to tic-tac-toe.","Git Gud."]
  143.         phrases["human"] := ["I let you win.","90% luck.","No life."]
  144.         this.winner := player
  145.         Random, p, 1, 3
  146.         text := phrases[this.winner][p]
  147.         GuiControl Battleship: Text, InfoText, % text
  148.         if (this.winner = "computer") {
  149.             for i, j in this.computer.grid {
  150.                 for k, l in j {
  151.                     if l.ship {
  152.                         if !this.human.Egrid[i][k].hit
  153.                             this.ChangeColor("c" "X" i "Y" k, this.colors.ship)
  154.                             this.human.Egrid[i][k].revealed := 1
  155.                     }
  156.                 }
  157.             }
  158.         }
  159.     }
  160.     ChangeTurn() {
  161.         if (this.turn = "human")
  162.             this.turn := "computer"
  163.         else
  164.             this.turn := "human"
  165.     }
  166.     ChangeColor(btn, c) {
  167.         GuiControl Battleship: +Background%c%, % btn
  168.     }
  169. }
  170.  
  171. class Player {
  172.     __New(ships, grid, player, enemy) {
  173.         this.name := {long:player,short:SubStr(player,1,1)}
  174.         this.enemy := {long:enemy,short:SubStr(enemy,1,1)}
  175.         this.ships := []
  176.         this.ToDestroy := []
  177.         for i, l in ships {
  178.             this.ships.Push({l:l,parts:[]})
  179.         }
  180.         this.grid := []
  181.         this.Egrid := []
  182.         this.targets := {}
  183.         Random, fl, 0, 1
  184.         xt := 0
  185.         Loop, % grid
  186.             {
  187.             xt += 1
  188.             yt := 0
  189.             row := []
  190.             Erow := []
  191.             Loop, % grid
  192.                 {
  193.                 yt += 1
  194.                 row.Push({ship:0,avaible:1,shipID:0})
  195.                 Erow.Push({hit:0,ship:0,revealed:0,sank:0,nothing:0})
  196.                 if Mod(fl + xt + yt, 2)
  197.                     this.targets["X" xt "Y" yt] := {x:xt,y:yt}
  198.             }
  199.             this.grid.Push(row)
  200.             this.Egrid.Push(Erow)
  201.         }
  202.         validGrid := 0
  203.         while (validGrid = 0)
  204.             {
  205.             validGrid := this.RandomShips(this.grid, this.ships)
  206.             if (A_Index > 20)
  207.                 Break
  208.         }
  209.         this.grid := validGrid
  210.  
  211.         for i, j in this.grid {
  212.             for k, l in j {
  213.                 if l.ship {
  214.                     this.ships[l.shipID].parts.Push({x:i,y:k})
  215.                 }
  216.             }
  217.         }
  218.     }
  219.     Play() {
  220.         if (this.ToDestroy.Length() > 0) {
  221.             if (this.ToDestroy.Length() = 1) {
  222.                 candidates := []
  223.                 dirs := [["x","y"],["y","x"]]
  224.                 d := [1,-1]
  225.                 for i, dir in dirs[1] {
  226.                     for k, l in d {
  227.                         c%dir% := this.ToDestroy[1][dir] + l
  228.                         odir := dirs[2][i]
  229.                         c%odir% := this.ToDestroy[1][odir]
  230.                         if (this.Egrid[cx][cy].hit = "0") AND (this.Egrid[cx][cy].nothing = "0") AND (this.Egrid[cx][cy].revealed = "0") AND (cx > 0) AND (cy > 0) AND (cx <= this.Egrid.Length()) AND (cy <= this.Egrid.Length())
  231.                             candidates.Push({x:cx,y:cy})
  232.                     }
  233.                 }
  234.             }
  235.             else if (this.ToDestroy.Length() > 1) {
  236.                 candidates := []
  237.                 if (this.ToDestroy[1].x = this.ToDestroy[2].x) {
  238.                     dir := "y"
  239.                     odir := "x"
  240.                     cx := this.ToDestroy[1].x
  241.                 }
  242.                 else {
  243.                     dir := "x"
  244.                     odir := "y"
  245.                     cy := this.ToDestroy[1].y
  246.                 }
  247.                 max := 0
  248.                 min := this.Egrid.Length() + 1
  249.                 for i, j in this.ToDestroy {
  250.                     if (j[dir] > max)
  251.                         max := j[dir]
  252.                     if (j[dir] < min)
  253.                         min := j[dir]
  254.                 }
  255.                 min -= 1
  256.                 max += 1
  257.                 ds := [min,max]
  258.                 for i, d in ds {
  259.                     c%dir% := d
  260.                     if (this.Egrid[cx][cy].hit = "0") AND (this.Egrid[cx][cy].nothing = "0") AND (this.Egrid[cx][cy].revealed = "0") AND (cx > 0) AND (cy > 0) AND (cx <= this.Egrid.Length()) AND (cy <= this.Egrid.Length())
  261.                         candidates.Push({x:cx,y:cy})
  262.                 }
  263.             }
  264.             Random, rC, 1, candidates.Length()
  265.             Return {p:"h",x:candidates[rC].x,y:candidates[rC].y}
  266.         }
  267.  
  268.         Random, rID, 1, this.targets.Count()
  269.         a := 1
  270.         for i, j in this.targets {
  271.             if (a = rID) {
  272.                 tID := i
  273.                 Break
  274.             }
  275.             a += 1
  276.         }
  277.         targ := this.targets.Delete(tID)
  278.         Return {p:"h",x:targ.x,y:targ.y}
  279.     }
  280.     MadeDamage(d, hit) {
  281.         this.ToDestroy.Push({x:d.x,y:d.y})
  282.         if (hit.shipL = 0) {
  283.             candidates := []
  284.             if (this.ToDestroy[1].x = this.ToDestroy[2].x) {
  285.                 dir := "y"
  286.                 odir := "x"
  287.                 cx := this.ToDestroy[1].x
  288.             }
  289.             else {
  290.                 dir := "x"
  291.                 odir := "y"
  292.                 cy := this.ToDestroy[1].y
  293.             }
  294.             max := 0
  295.             min := this.Egrid.Length() + 1
  296.             for i, j in this.ToDestroy {
  297.                 if (j[dir] > max)
  298.                     max := j[dir]
  299.                 if (j[dir] < min)
  300.                     min := j[dir]
  301.             }
  302.             min -= 1
  303.             max += 1
  304.             ds := [min,max]
  305.             for i, d in ds {
  306.                 c%dir% := d
  307.                 candidates.Push({x:cx,y:cy})
  308.                 this.targets.Delete("X" cx "Y" cy)
  309.             }
  310.             this.ToDestroy := []
  311.         }
  312.     }
  313.     Click(x, y) {
  314.         if !this.Egrid[x][y].revealed
  315.             Return 1
  316.         Return 0
  317.     }
  318.     TakeHit(x, y) {
  319.         if this.grid[x][y].ship
  320.             this.ships[this.grid[x][y].shipID].l -= 1
  321.         if (this.ships[this.grid[x][y].shipID].l >= 0)
  322.             shipL := this.ships[this.grid[x][y].shipID].l
  323.         else
  324.             shipL := -1
  325.         return {shipID:this.grid[x][y].shipID,shipL:shipL}
  326.     }
  327.     GiveHit(x, y, shipID) {
  328.         this.Egrid[x][y].revealed := 1
  329.         this.Egrid[x][y].hit := 1
  330.         this.targets.Delete("X" x "Y" y)
  331.         if (shipID > 0)
  332.             {
  333.             this.Egrid[x][y].ship := 1
  334.             this.Egrid[x-1][y-1].nothing := 1
  335.             this.Egrid[x+1][y-1].nothing := 1
  336.             this.Egrid[x-1][y+1].nothing := 1
  337.             this.Egrid[x+1][y+1].nothing := 1
  338.             this.targets.Delete("X" x-1 "Y" y-1)
  339.             this.targets.Delete("X" x+1 "Y" y-1)
  340.             this.targets.Delete("X" x-1 "Y" y+1)
  341.             this.targets.Delete("X" x+1 "Y" y+1)
  342.         }
  343.     }
  344.     Sink(parts) {
  345.         for i, j in parts {
  346.             this.Egrid[j.x][j.y].sank := 1
  347.         }
  348.     }
  349.     GetTotalL() {
  350.         tL := 0
  351.         for i, j in this.ships {
  352.             tL += j.l
  353.         }
  354.         Return tL
  355.     }
  356.     GetParts(shipID) {
  357.         Return this.ships[shipID].parts
  358.     }
  359.     RandomShips(grid, ships) {
  360.         tships := this.ObjFullyClone(ships)
  361.         Tlen := ships.Length()
  362.         if (ships.Length() < 1)
  363.             Return grid
  364.         ship := tships.Pop()
  365.         Loop, 5
  366.             {
  367.             tgrid := this.ObjFullyClone(grid)
  368.             Random, x, 1, % grid.Length()
  369.             Random, y, 1, % grid.Length()
  370.             Random, o, 0, 1
  371.             tgrid := this.PlaceShip(tgrid, ship, x, y, o, Tlen)
  372.             if (tgrid != 0) {
  373.                 Return this.RandomShips(tgrid, tships)
  374.             }
  375.         }
  376.         Return 0
  377.     }
  378.     PlaceShip(grid, ship, x, y, o, Tlen) {
  379.         Loop, % ship.l
  380.             {
  381.             if !grid[x][y].avaible
  382.                 Return 0
  383.             else
  384.                 grid := this.PlacePart(grid, x, y, o, A_Index, ship.l, Tlen)
  385.             if o
  386.                 x += 1
  387.             else
  388.                 y += 1
  389.         }
  390.         Return grid
  391.     }
  392.     PlacePart(grid, x, y, o, ind, len, Tlen) {
  393.         grid[x][y].avaible := 0
  394.         grid[x][y].ship := 1
  395.         grid[x][y].shipID := Tlen
  396.         xs := []
  397.         if x > 1
  398.             xs.Push(x-1)
  399.         if x < grid.Length()
  400.             xs.Push(x+1)
  401.         ys := []
  402.         if y > 1
  403.             ys.Push(y-1)
  404.         if y < grid.Length()
  405.             ys.Push(y+1)
  406.        
  407.         for i, j in xs {
  408.             for k, l in ys {
  409.                 grid[j][l].avaible := 0
  410.             }
  411.         }
  412.         if (ind = 1) {
  413.             if o AND (x > 1)
  414.                 grid[x - 1][y].avaible := 0
  415.             if !o AND (y > 1)
  416.                 grid[x][y - 1].avaible := 0
  417.         }
  418.         if (ind = len) {
  419.             if o AND (x < grid.Length())
  420.                 grid[x + 1][y].avaible := 0
  421.             if !o AND (y < grid.Length())
  422.                 grid[x][y + 1].avaible := 0
  423.         }
  424.         Return grid
  425.     }
  426.     ObjFullyClone(obj) {
  427.         nobj := obj.Clone()
  428.         for k,v in nobj
  429.             if IsObject(v)
  430.                 nobj[k] := this.ObjFullyClone(v)
  431.         return nobj
  432.     }
  433. }
Add Comment
Please, Sign In to add comment