Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ConnectFour = class()
- -- ConnectFour was the first game class i implemented, and has a few quirks due to that.
- -- the prefix on these params is for historical purposes and can be safely removed.
- -- "chain" represents the number in a row to win, and turns the game into Connect3, 4, 5, etc.
- function ConnectFour:setupParams()
- iparameter("ConnectColumns", 1, 7)
- iparameter("ConnectRows", 1, 7)
- iparameter("ConnectChain", 1, 7)
- ConnectColumns = readProjectData("connectCol", 4)
- ConnectRows = readProjectData("connectRows", 4)
- ConnectChain = readProjectData("connectChain", 3)
- end
- function ConnectFour:saveParams()
- saveProjectData("connectCol", ConnectColumns)
- saveProjectData("connectRows", ConnectRows)
- saveProjectData("connectChain", ConnectChain)
- end
- function ConnectFour:init()
- self.empty = -1
- self.player = 0
- self.ai = 1
- self.gameWon = nil
- -- this is to remind myself that i intend to have an 'undo' feature.
- -- self.moveHistory = {}
- self.turn = AIstarts
- self.numMoves = ConnectColumns
- self.columns = {}
- self.numberOfRows = ConnectRows
- self.numberOfColumns = ConnectColumns
- self.goal = ConnectChain
- for i = 1, self.numberOfColumns do
- local temp = {}
- for j = 1, self.numberOfRows do
- table.insert(temp, j, self.empty)
- end
- table.insert(self.columns, i, temp)
- end
- end
- function ConnectFour:copy(original)
- for i = 1, self.numberOfColumns do
- for j = 1, self.numberOfRows do
- self.columns[i][j] = original.columns[i][j]
- end
- end
- self.numMoves = original.numMoves
- self.turn = original.turn
- self.gameWon = original.gameWon
- end
- function ConnectFour:draw()
- local dx = WIDTH/(self.numberOfColumns)
- local dy = HEIGHT/(self.numberOfRows)
- ellipseMode(CORNER)
- for i,col in pairs(self.columns) do
- pushMatrix()
- for j,disc in pairs(col) do
- if disc == self.player then
- fill(red)
- elseif disc == self.ai then
- fill(blue)
- else
- fill(gray)
- end
- ellipse(0,0,math.min(dx, dy))
- translate(0, dy)
- end
- popMatrix()
- translate(dx, 0)
- end
- end
- -- only invalid if the column is filled.
- function ConnectFour:validMove(col)
- if self.columns[col][self.numberOfRows] == self.empty then
- return true
- else
- return false
- end
- end
- -- just a Get function
- function ConnectFour:numberOfMoves()
- return self.numMoves
- end
- -- do not pass this func 0. add a check if it becomes problematic.
- -- (when i was first testing, this function was the performance bottleneck
- -- and performance was terrible, so i omitted the check!)
- function ConnectFour:randomMove(numberOfPossibleMoves)
- local myMove = math.random(numberOfPossibleMoves)
- for i = 1, self.numberOfColumns do
- if self.columns[i][self.numberOfRows] == self.empty then
- myMove = myMove - 1
- if myMove == 0 then
- self:move(i)
- return
- end
- end
- end
- end
- -- could just call flipTurn(self) instead of this.
- -- actually, im not sure if this is called at all... delete it?
- function ConnectFour:changeTurn()
- if self.turn == self.player then self.turn = self.ai
- else self.turn = self.player end
- end
- function ConnectFour:move(selection)
- local done = false
- for i,disc in pairs(self.columns[selection]) do
- if done == false and disc == self.empty then
- self.columns[selection][i] = self.turn
- self:updateWinner(selection, i)
- done = true
- if i == self.numberOfRows then
- self.numMoves = self.numMoves - 1
- end
- end
- end
- flipTurn(self)
- end
- -- no protection against trying to make an invalid move. fix this.
- function ConnectFour:touched(t)
- local selection = t.x/(WIDTH/self.numberOfColumns)
- selection = math.ceil(selection)
- self:move(selection)
- end
- -- near optimal. only checks the minimal number of spots on the board
- function ConnectFour:updateWinner(x, y)
- if self.gameWon ~= nil then return end
- local winner = nil
- local goal = self.goal - 1
- for i = 1, 4 do
- self:resetChain()
- for j = -goal, goal do
- if i==1 then winner = self:countChain(x+j, y)
- elseif i==2 then winner = self:countChain(x, y+j)
- elseif i==3 then winner = self:countChain(x+j, y+j)
- elseif i==4 then winner = self:countChain(x+j, y-j) end
- if winner ~= nil then
- self.gameWon = winner
- return
- end
- end
- end
- end
- -- this and the following function work to count pieces in a row, to detect wins.
- function ConnectFour:countChain(i, j)
- if i < 1 or self.numberOfColumns < i then return nil end
- if j < 1 or self.numberOfRows < j then return nil end
- if self.type ~= self.columns[i][j] then
- self.type = self.columns[i][j]
- self.count = 0
- end
- if self.type ~= self.empty and self.type == self.columns[i][j] then
- self.count = self.count + 1
- if self.count == self.goal then
- return self.type
- end
- end
- return nil
- end
- function ConnectFour:resetChain()
- self.count = 0
- self.type = self.empty
- end
- function ConnectFour:gameOver()
- return self.gameWon
- end
- function ConnectFour:possibleMovesInterval()
- return vec2(1,self.numberOfColumns)
- end
- -- no efficient heuristic to my knowledge, so we just call it a draw.
- function ConnectFour:positionStrength()
- return 0.5
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement