-- Compiled with roblox-ts v1.2.7 local TS = _G[script] local TicTacToeMoveResult = TS.import(script, script.Parent, "enum", "TicTacToeMoveResult").TicTacToeMoveResult local TicTacToeState = TS.import(script, script.Parent, "enum", "TicTacToeState").TicTacToeState local TicTacToeSymbol = TS.import(script, script.Parent, "enum", "TicTacToeSymbol").TicTacToeSymbol local TicTacToeBoard = TS.import(script, script.Parent, "TicTacToeBoard").TicTacToeBoard local TicTacToeCell = TS.import(script, script.Parent, "TicTacToeCell").TicTacToeCell local TicTacToeMove = TS.import(script, script.Parent, "TicTacToeMove").TicTacToeMove --[[ * * The game of TicTacToe. * * @template X The type of the player that plays the X symbol. * @template O The type of the player that plays the O symbol, defaults to X. ]] local TicTacToeGame do TicTacToeGame = setmetatable({}, { __tostring = function() return "TicTacToeGame" end, }) TicTacToeGame.__index = TicTacToeGame function TicTacToeGame.new(...) local self = setmetatable({}, TicTacToeGame) return self:constructor(...) or self end function TicTacToeGame:constructor(playerX, playerO, firstPlayer, ...) if firstPlayer == nil then firstPlayer = TicTacToeSymbol.EMPTY end local outputs = { ... } self.playerX = playerX self.playerO = playerO self.board = TicTacToeBoard.new() self.state = TicTacToeState.IN_PROGRESS self.currentPlayer = self:getPlayerFromSymbol(firstPlayer) self.outputs = outputs local _outputs = self.outputs local _arg0 = function(output) local _self = output local _result = _self.onGameStart if _result ~= nil then _result = _result(_self, self) end return _result end -- ▼ ReadonlyArray.forEach ▼ for _k, _v in ipairs(_outputs) do _arg0(_v, _k - 1, _outputs) end -- ▲ ReadonlyArray.forEach ▲ end function TicTacToeGame:nextMove() if self:isOver() then return TicTacToeMoveResult.GAME_UNAVAILABLE end local moveLocation = self.currentPlayer:makeMove(self.board, self:getCurrentPlayerSymbol()) if not moveLocation then self:cancel() return TicTacToeMoveResult.NO_RESPONSE end local move = TicTacToeMove.new(moveLocation.row, moveLocation.col, self.currentPlayer) if not self.board:isValidMove(move) then return TicTacToeMoveResult.INVALID end local cell = TicTacToeCell.new(move:getRow(), move:getCol(), self:getCurrentPlayerSymbol()) self.board:setCell(cell) self:handleMoveMade(move) self.currentPlayer = self:getNextPlayer() return TicTacToeMoveResult.SUCCESS end function TicTacToeGame:getCurrentPlayerSymbol() return self.currentPlayer == self.playerX and TicTacToeSymbol.X or TicTacToeSymbol.O end function TicTacToeGame:handleMoveMade(move) local _binding = self.board:getCurrentState() local state = _binding[1] local winningCells = _binding[2] self.state = state self.winningCells = winningCells if state == TicTacToeState.X_WON then self.winner = self.playerX elseif state == TicTacToeState.O_WON then self.winner = self.playerO end self.lastMove = move if self:isOver() then local _outputs = self.outputs local _arg0 = function(output) local _self = output local _result = _self.onGameOver if _result ~= nil then _result = _result(_self, self) end return _result end -- ▼ ReadonlyArray.forEach ▼ for _k, _v in ipairs(_outputs) do _arg0(_v, _k - 1, _outputs) end -- ▲ ReadonlyArray.forEach ▲ end local _outputs = self.outputs local _arg0 = function(output) local _self = output local _result = _self.onMove if _result ~= nil then _result = _result(_self, self) end return _result end -- ▼ ReadonlyArray.forEach ▼ for _k, _v in ipairs(_outputs) do _arg0(_v, _k - 1, _outputs) end -- ▲ ReadonlyArray.forEach ▲ end function TicTacToeGame:cancel() if self:isOver() then return nil end self.state = TicTacToeState.CANCELLED local _outputs = self.outputs local _arg0 = function(output) local _self = output local _result = _self.onGameOver if _result ~= nil then _result = _result(_self, self) end return _result end -- ▼ ReadonlyArray.forEach ▼ for _k, _v in ipairs(_outputs) do _arg0(_v, _k - 1, _outputs) end -- ▲ ReadonlyArray.forEach ▲ end function TicTacToeGame:getNextPlayer() return self.currentPlayer == self.playerX and self.playerO or self.playerX end function TicTacToeGame:getRandomPlayer() local r = Random.new() return r:NextNumber() > 0.5 and self.playerX or self.playerO end function TicTacToeGame:getPlayerFromSymbol(symbol) return symbol == TicTacToeSymbol.X and self.playerX or (symbol == TicTacToeSymbol.O and self.playerO or self:getRandomPlayer()) end function TicTacToeGame:reset(firstPlayer) if firstPlayer == nil then firstPlayer = TicTacToeSymbol.EMPTY end self.board = TicTacToeBoard.new() self.currentPlayer = self:getPlayerFromSymbol(firstPlayer) self.state = TicTacToeState.IN_PROGRESS self.winningCells = nil self.winner = nil self.lastMove = nil local _outputs = self.outputs local _arg0 = function(output) local _self = output local _result = _self.onGameStart if _result ~= nil then _result = _result(_self, self) end return _result end -- ▼ ReadonlyArray.forEach ▼ for _k, _v in ipairs(_outputs) do _arg0(_v, _k - 1, _outputs) end -- ▲ ReadonlyArray.forEach ▲ end function TicTacToeGame:getCurrentPlayer() return self.currentPlayer end function TicTacToeGame:isOver() return self.state ~= TicTacToeState.IN_PROGRESS end function TicTacToeGame:getState() return self.state end function TicTacToeGame:getBoard() return self.board end function TicTacToeGame:getBoardCopy() return TicTacToeBoard.new(self.board:getCells()) end function TicTacToeGame:getLastMove() return self.lastMove end function TicTacToeGame:getWinner() return self.winner end function TicTacToeGame:getWinningCells() return self.winningCells end function TicTacToeGame:getPlayerX() return self.playerX end function TicTacToeGame:getPlayerO() return self.playerO end function TicTacToeGame:addOutputs(...) local outputs = { ... } local _array = {} local _length = #_array local _array_1 = self.outputs local _Length = #_array_1 table.move(_array_1, 1, _Length, _length + 1, _array) _length += _Length table.move(outputs, 1, #outputs, _length + 1, _array) self.outputs = _array end function TicTacToeGame:removeOutput(output) local i = (table.find(self.outputs, output) or 0) - 1 if i == -1 then return nil end table.remove(self.outputs, i + 1) end function TicTacToeGame:getOutputs() return self.outputs end end return { TicTacToeGame = TicTacToeGame, }