diff --git a/deployments/goerli/ConnectFour.json b/deployments/goerli/ConnectFour.json index ad7ad5f..722baea 100644 --- a/deployments/goerli/ConnectFour.json +++ b/deployments/goerli/ConnectFour.json @@ -1,5 +1,5 @@ { - "address": "0x399d76Dbc75894b555395a0fCD546A74205EBC9E", + "address": "0x3664B997f3EECC7AadA65F7A1f883cdC4BcD851b", "abi": [ { "inputs": [], @@ -183,28 +183,28 @@ "type": "function" } ], - "transactionHash": "0x58e45de5005378b7828e8bb3a95aac7d19c8462fa4af20ca2a999d54a082813f", + "transactionHash": "0xa3a8fe8778f11fbb582cadfae7c52251f21491ecc66f94312c970700d6a65109", "receipt": { "to": null, "from": "0x629750317d320B8bB4d48D345A6d699Cc855c4a6", - "contractAddress": "0x399d76Dbc75894b555395a0fCD546A74205EBC9E", - "transactionIndex": 26, + "contractAddress": "0x3664B997f3EECC7AadA65F7A1f883cdC4BcD851b", + "transactionIndex": 18, "gasUsed": "823195", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x98f50c7c85cf1ff1fdf76e475b159147ee4f0e852e8b7945184503c7ebbbbcbd", - "transactionHash": "0x58e45de5005378b7828e8bb3a95aac7d19c8462fa4af20ca2a999d54a082813f", + "blockHash": "0xd5a25bc35e99d71848e19992dd4569d3216a0e5f5de0f25254006f2200ba4403", + "transactionHash": "0xa3a8fe8778f11fbb582cadfae7c52251f21491ecc66f94312c970700d6a65109", "logs": [], - "blockNumber": 8477318, - "cumulativeGasUsed": "3805772", + "blockNumber": 8477378, + "cumulativeGasUsed": "9695761", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 4, - "solcInputHash": "6e142bca9cf59327f5294aa83f5594b8", - "metadata": "{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"GameOver\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSelection\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotYourTurn\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gameId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"teamOne\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"teamTwo\",\"type\":\"address\"}],\"name\":\"GameCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gameId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"winner\",\"type\":\"address\"}],\"name\":\"GameFinished\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"gameId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"team\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"column\",\"type\":\"uint8\"}],\"name\":\"TurnTaken\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"opponent\",\"type\":\"address\"}],\"name\":\"challenge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"gameId\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"getGame\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"teamOne\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"teamTwo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"winner\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"turn\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"_gameId\",\"type\":\"uint8\"}],\"name\":\"getGameBoard\",\"outputs\":[{\"internalType\":\"uint8[7][6]\",\"name\":\"\",\"type\":\"uint8[7][6]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"_gameId\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"column\",\"type\":\"uint8\"}],\"name\":\"makeMove\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"challenge(address)\":{\"details\":\"opponent will go firstgame id is increated each time a new game is createdseason is over when timer (soon to be added) is past\",\"params\":{\"opponent\":\"challened\"}},\"makeMove(uint8,uint8)\":{\"params\":{\"_gameId\":\"id of game\",\"column\":\"selected column for move\"}}},\"stateVariables\":{\"gameId\":{\"details\":\"Initialised at 1 because it makes the first transaction slightly cheaper.\"},\"getGame\":{\"details\":\"This automatically generates a getter for us, which will return `Game.player1`, `Game.player2`, `Game.moves`, and `Game.finished` (the arrays are skipped)\"}},\"version\":1},\"userdoc\":{\"errors\":{\"GameOver()\":[{\"notice\":\"revert if game has been completed\"}],\"InvalidSelection()\":[{\"notice\":\"revert if column choice is invalid\"}],\"NotYourTurn()\":[{\"notice\":\"revert if caller isn't current team\"}]},\"events\":{\"GameCreated(uint256,address,address)\":{\"notice\":\"emiited when game is created\"},\"GameFinished(uint256,address)\":{\"notice\":\"emitted when game is complete\"},\"TurnTaken(uint256,address,uint8)\":{\"notice\":\"emitted after turn is successfully taken\"}},\"kind\":\"user\",\"methods\":{\"challenge(address)\":{\"notice\":\"challenge an address to a game of connect four\"},\"gameId()\":{\"notice\":\"Used as a counter for the next game index.\"},\"getGame(uint256)\":{\"notice\":\"An indexed list of games\"},\"makeMove(uint8,uint8)\":{\"notice\":\"current team plays a turn\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/ConnectFour/ConnectFour.sol\":\"ConnectFour\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/ConnectFour/ConnectFour.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\npragma solidity ^0.8.17;\\n\\ncontract ConnectFour {\\n /// @notice revert if caller isn't current team\\n error NotYourTurn();\\n /// @notice revert if column choice is invalid\\n error InvalidSelection();\\n /// @notice revert if game has been completed\\n error GameOver();\\n /// @notice emiited when game is created\\n\\n event GameCreated(uint gameId, address teamOne, address teamTwo);\\n /// @notice emitted after turn is successfully taken\\n event TurnTaken(uint indexed gameId, address team, uint8 column);\\n /// @notice emitted when game is complete\\n event GameFinished(uint gameId, address winner);\\n\\n /// @notice holds game data\\n /// @param teamOne address of challenger\\n /// @param teamTwo address of challenged\\n /// @param winner address of winning team; default: address(0)\\n /// @param turn current turn is calculated using bitwise for basically odd/even teamOne/teamTwo\\n /// @param board holds game board data; each 'square' holds current data; 0 = no chip; 1 = team one; 2 = team two\\n struct Game {\\n address teamOne;\\n address teamTwo;\\n address winner;\\n uint8 turn;\\n uint8[7][6] board;\\n }\\n\\n /// @notice Used as a counter for the next game index.\\n /// @dev Initialised at 1 because it makes the first transaction slightly cheaper.\\n uint public gameId;\\n\\n /// @notice An indexed list of games\\n /// @dev This automatically generates a getter for us, which will return `Game.player1`, `Game.player2`, `Game.moves`, and `Game.finished` (the arrays are skipped)\\n mapping(uint => Game) public getGame;\\n\\n /// @notice prevent move if column is invalid\\n modifier validColumn(uint8 column) {\\n if (column > 6) revert InvalidSelection();\\n _;\\n }\\n\\n /// @notice prevents gameplay if game is over\\n modifier gameOver(uint _gameId) {\\n if (getGame[_gameId].winner != address(0)) revert GameOver();\\n _;\\n }\\n\\n /// @notice prevents teams being the same address\\n modifier uniqueTeams(address opponent) {\\n require(msg.sender != opponent);\\n _;\\n }\\n\\n /**\\n * @notice challenge an address to a game of connect four\\n * @param opponent challened\\n * @dev opponent will go first\\n * @dev game id is increated each time a new game is created\\n * @dev season is over when timer (soon to be added) is past\\n */\\n function challenge(address opponent) public uniqueTeams(opponent) {\\n uint8[7][6] memory newBoard;\\n Game memory newGame = Game({\\n teamOne: msg.sender,\\n teamTwo: opponent,\\n turn: uint8(0),\\n winner: address(0),\\n board: newBoard\\n });\\n getGame[gameId] = newGame;\\n\\n emit GameCreated(gameId, msg.sender, opponent);\\n\\n gameId++;\\n }\\n\\n /**\\n * @notice current team plays a turn\\n * @param _gameId id of game\\n * @param column selected column for move\\n */\\n function makeMove(\\n uint8 _gameId,\\n uint8 column\\n ) external gameOver(_gameId) validColumn(column) {\\n Game storage game = getGame[_gameId];\\n\\n /// @notice row where chip will land\\n uint8 row;\\n /// @notice assigned team number for squares\\n uint8 teamNum = game.turn & 1 == 0 ? 2 : 1;\\n\\n /// @notice prevents plays being made by other addresses\\n /// @dev even or odd bitwise operator decides turn\\n /// @dev starts with team two\\n if (msg.sender != (game.turn & 1 == 0 ? game.teamTwo : game.teamOne)) {\\n revert NotYourTurn();\\n }\\n\\n /// @notice finds where chip will land\\n for (uint8 i = 0; i < 7; i++) {\\n if (i > 5) {\\n revert InvalidSelection();\\n }\\n uint8 square = game.board[i][column];\\n if (square == 0) {\\n row = i++;\\n break;\\n }\\n }\\n\\n /// @notice assigns chip to location onboard\\n game.board[row][column] = teamNum;\\n /// @notice increments turn\\n game.turn++;\\n\\n emit TurnTaken(_gameId, msg.sender, column);\\n\\n /// @notice checks surrounding squares for connected pieces\\n if (didPlayerWin(_gameId, column, row, teamNum)) {\\n game.winner = msg.sender;\\n emit GameFinished(_gameId, msg.sender);\\n }\\n }\\n\\n /// @notice checks square for team's chip\\n /// @param _gameId id of game\\n /// @param firstIndex column selected for new chip\\n /// @param secondIndex row where new chip lands\\n /// @param teamNum number assigned to team\\n function checkSquare(\\n uint8 _gameId,\\n uint8 firstIndex,\\n uint8 secondIndex,\\n uint8 teamNum\\n ) private view returns (bool) {\\n uint8[7][6] storage board = getGame[_gameId].board;\\n return board[firstIndex][secondIndex] == teamNum;\\n }\\n\\n /// @notice checks the horizontal win\\n /// @param _gameId id of game\\n /// @param column column selected for new chip\\n /// @param row row where new chip lands\\n /// @param teamNum number assigned to team\\n function checkHorizonalWin(\\n uint8 _gameId,\\n uint8 column,\\n uint8 row,\\n uint8 teamNum\\n ) private view returns (uint) {\\n uint connectedPiecesCount = 1;\\n\\n /// @dev checks to the right of new piece\\n for (uint8 i = column + 1; i < 7; i++) {\\n if (checkSquare(_gameId, row, i, teamNum)) {\\n connectedPiecesCount++;\\n } else {\\n break;\\n }\\n }\\n /// @dev checks to the left of new piece\\n if (column != 0) {\\n uint8 columnIndex = column - 1;\\n while (columnIndex >= 0) {\\n if (checkSquare(_gameId, row, columnIndex, teamNum)) {\\n connectedPiecesCount++;\\n } else {\\n break;\\n }\\n if (columnIndex == 0) {\\n break;\\n } else {\\n columnIndex--;\\n }\\n }\\n }\\n\\n return connectedPiecesCount;\\n }\\n\\n /// @notice checks the veritical win\\n /// @param _gameId id of game\\n /// @param column column selected for new chip\\n /// @param row row where new chip lands\\n /// @param teamNum number assigned to team\\n function checkVericalWin(\\n uint8 _gameId,\\n uint8 column,\\n uint8 row,\\n uint8 teamNum\\n ) private view returns (uint) {\\n uint connectedPiecesCount = 1;\\n\\n /// @dev checks rows above new piece\\n for (uint8 i = row + 1; i < 6; i++) {\\n if (checkSquare(_gameId, i, column, teamNum)) {\\n connectedPiecesCount++;\\n } else {\\n break;\\n }\\n }\\n /// @dev checks rows below new piece\\n if (row != 0) {\\n uint8 rowIndex = row - 1;\\n while (rowIndex >= 0) {\\n if (checkSquare(_gameId, rowIndex, column, teamNum)) {\\n connectedPiecesCount++;\\n } else {\\n break;\\n }\\n if (rowIndex == 0) {\\n break;\\n } else {\\n rowIndex--;\\n }\\n }\\n }\\n return connectedPiecesCount;\\n }\\n\\n /// @notice checks the forward angle win\\n /// @param _gameId id of game\\n /// @param column column selected for new chip\\n /// @param row row where new chip lands\\n /// @param teamNum number assigned to team\\n function checkForwardAngleWin(\\n uint8 _gameId,\\n uint8 column,\\n uint8 row,\\n uint8 teamNum\\n ) private view returns (uint) {\\n uint connectedPiecesCount = 1;\\n\\n /// @dev checks forward angle up\\n for (uint8 i = row + 1; i < 6 - row; i++) {\\n if (checkSquare(_gameId, i, i, teamNum)) {\\n connectedPiecesCount++;\\n } else {\\n break;\\n }\\n }\\n\\n /// @dev checks forward angle down\\n if (row != 0 && column != 0) {\\n uint8 rowIndex = row - 1;\\n uint8 columnIndex = column - 1;\\n while (rowIndex >= 0 && columnIndex >= 0) {\\n if (checkSquare(_gameId, rowIndex, columnIndex, teamNum)) {\\n connectedPiecesCount++;\\n } else {\\n break;\\n }\\n if (rowIndex == 0 || columnIndex == 0) {\\n break;\\n } else {\\n rowIndex--;\\n columnIndex--;\\n }\\n }\\n }\\n return connectedPiecesCount;\\n }\\n\\n /// @notice checks the backward angle win\\n /// @param _gameId id of game\\n /// @param column column selected for new chip\\n /// @param row row where new chip lands\\n /// @param teamNum number assigned to team\\n function checkBackwardAngleWin(\\n uint8 _gameId,\\n uint8 column,\\n uint8 row,\\n uint8 teamNum\\n ) private view returns (uint) {\\n uint connectedPiecesCount = 1;\\n\\n /// @dev checks backward angle down\\n if (row != 0) {\\n uint8 rowIndex = row - 1;\\n uint8 columnIndex = column + 1;\\n while (rowIndex >= 0 && columnIndex < 6) {\\n if (checkSquare(_gameId, rowIndex, columnIndex, teamNum)) {\\n connectedPiecesCount++;\\n } else {\\n break;\\n }\\n if (rowIndex == 0 || columnIndex >= 6) {\\n break;\\n } else {\\n rowIndex--;\\n columnIndex++;\\n }\\n }\\n }\\n\\n /// @dev checks forward angle down\\n if (column != 0) {\\n uint8 rowIndex = row + 1;\\n uint8 columnIndex = column - 1;\\n while (rowIndex < 6 && columnIndex >= 0) {\\n if (checkSquare(_gameId, rowIndex, columnIndex, teamNum)) {\\n connectedPiecesCount++;\\n } else {\\n break;\\n }\\n if (rowIndex >= 6 || columnIndex == 0) {\\n break;\\n } else {\\n rowIndex++;\\n columnIndex--;\\n }\\n }\\n }\\n return connectedPiecesCount;\\n }\\n\\n /// @notice checks to see if current play won the game\\n /// @param _gameId id of game\\n /// @param column column selected for new chip\\n /// @param row row where new chip lands\\n /// @param teamNum number assigned to team\\n function didPlayerWin(\\n uint8 _gameId,\\n uint8 column,\\n uint8 row,\\n uint8 teamNum\\n ) private view returns (bool) {\\n /// @dev using new chip location as middle == m\\n /// @dev [ [ C+1 | R-1 ] [ C+1 ] [ C+1 | R+1 ] ]\\n /// @dev [ [ R-1 ] [ C | R ] [ R+1 ]\\n /// @dev [ [ C-1 | R-1 ] [ C-1 ] [ C-1 | R+1 ] ]\\n\\n uint horionalCount = checkHorizonalWin(_gameId, column, row, teamNum);\\n if (horionalCount == 4) {\\n return true;\\n }\\n uint vericalCount = checkVericalWin(_gameId, column, row, teamNum);\\n if (vericalCount == 4) {\\n return true;\\n }\\n uint forwardAngleCount = checkForwardAngleWin(\\n _gameId,\\n column,\\n row,\\n teamNum\\n );\\n if (forwardAngleCount == 4) {\\n return true;\\n }\\n uint backwardAngleCount = checkBackwardAngleWin(\\n _gameId,\\n column,\\n row,\\n teamNum\\n );\\n if (backwardAngleCount == 4) {\\n return true;\\n }\\n return false;\\n }\\n\\n function getGameBoard(\\n uint8 _gameId\\n ) public view returns (uint8[7][6] memory) {\\n return getGame[_gameId].board;\\n }\\n}\\n\",\"keccak256\":\"0x9ce388b267c0be3d8f5b8f9cb04512110ee1e4b2ff803b05b27330d342e9caba\",\"license\":\"GPL-3.0\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b50610ded806100206000396000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c80635e24b0f11461005c57806372fb9703146100715780639b33b42914610084578063a2f77bcc146100ad578063d7c81b551461012b575b600080fd5b61006f61006a366004610c09565b610142565b005b61006f61007f366004610c3c565b610424565b610097610092366004610c6c565b61055a565b6040516100a49190610c87565b60405180910390f35b6100f86100bb366004610ce5565b60016020819052600091825260409091208054918101546002909101546001600160a01b039283169291821691811690600160a01b900460ff1684565b604080516001600160a01b0395861681529385166020850152919093169082015260ff90911660608201526080016100a4565b61013460005481565b6040519081526020016100a4565b60ff82166000818152600160205260409020600201546001600160a01b03161561017f5760405163df469ccb60e01b815260040160405180910390fd5b8160068160ff1611156101a557604051631efccef760e11b815260040160405180910390fd5b60ff84166000908152600160208190526040822060028101549092918291600160a01b900416156101d75760016101da565b60025b6002840154909150600160a01b9004600116156102015782546001600160a01b0316610210565b60018301546001600160a01b03165b6001600160a01b0316336001600160a01b03161461024157604051631cc191eb60e31b815260040160405180910390fd5b60005b60078160ff1610156102ec5760058160ff16111561027557604051631efccef760e11b815260040160405180910390fd5b6000846003018260ff166006811061028f5761028f610cfe565b018860ff16600781106102a4576102a4610cfe565b602081049091015460ff601f9092166101000a900416905060008190036102d957816102cf81610d2a565b92509350506102ec565b50806102e481610d2a565b915050610244565b5080836003018360ff166006811061030657610306610cfe565b018760ff166007811061031b5761031b610cfe565b60208104909101805460ff938416601f9093166101000a9283029284021916919091179055600284018054600160a01b900490911690601461035c83610d2a565b82546101009290920a60ff818102199093169183160217909155604080513381528983166020820152918a1692507fa6f41f711ea470b4b237d1b3e43b201e53517677308ae067a273fb1948ddbf0c910160405180910390a26103c1878784846105f9565b1561041b576002830180546001600160a01b031916339081179091556040805160ff8a16815260208101929092527fb7f35e624e036288272fbf3342c09219261ff29fdddd826989b289134e9ae535910160405180910390a15b50505050505050565b806001600160a01b038116330361043a57600080fd5b610442610aa7565b6040805160a0810182523381526001600160a01b038581166020808401918252600084860181815260608601828152608087018981528354845260019485905297909220865181549087166001600160a01b03199182161782559451938101805494871694909516939093179093559151600282018054935160ff16600160a01b026001600160a81b03199094169190941617919091179091559151909182916104f29060038301906006610ad4565b5050600054604080519182523360208301526001600160a01b038716908201527f8946648bc1dbc670d3f07e2c4de91731227b6d4ccc53b8ab1e951e84d960577e915060600160405180910390a160008054908061054f83610d49565b919050555050505050565b610562610aa7565b60ff8216600090815260016020526040808220815160c081019092529091600390910190600690835b828210156105ee576040805160e08101918290529085840190600790826000855b825461010083900a900460ff168152602060019283018181049485019490930390920291018084116105ac57905050505050508152602001906001019061058b565b505050509050919050565b60008061060886868686610699565b90508060040361061c576001915050610691565b600061062a87878787610759565b90508060040361063f57600192505050610691565b600061064d88888888610804565b9050806004036106635760019350505050610691565b60006106718989898961090a565b905080600403610688576001945050505050610691565b60009450505050505b949350505050565b60006001816106a88683610d62565b90505b60078160ff1610156106f1576106c387868387610a39565b156106da57816106d281610d49565b9250506106df565b6106f1565b806106e981610d2a565b9150506106ab565b5060ff851615610750576000610708600187610d81565b90505b61071787868387610a39565b1561072e578161072681610d49565b925050610733565b61074e565b60ff81161561074e578061074681610d9a565b91505061070b565b505b95945050505050565b60006001816107688583610d62565b90505b60068160ff1610156107b15761078387828887610a39565b1561079a578161079281610d49565b92505061079f565b6107b1565b806107a981610d2a565b91505061076b565b5060ff8416156107505760006107c8600186610d81565b90505b6107d787828887610a39565b1561072e57816107e681610d49565b92505060ff81161561074e57806107fc81610d9a565b9150506107cb565b60006001816108138583610d62565b90505b610821856006610d81565b60ff168160ff1610156108685761083a87828387610a39565b15610851578161084981610d49565b925050610856565b610868565b8061086081610d2a565b915050610816565b5060ff84161580159061087d575060ff851615155b1561075057600061088f600186610d81565b9050600061089e600188610d81565b90505b6108ad88838388610a39565b156108c457826108bc81610d49565b9350506108c9565b6108fe565b60ff821615806108da575060ff8116155b6108fe57816108e881610d9a565b92505080806108f690610d9a565b9150506108a1565b50509050949350505050565b6000600160ff8416156109a5576000610924600186610d81565b90506000610933876001610d62565b90505b60068160ff1610156109a25761094e88838388610a39565b15610965578261095d81610d49565b93505061096a565b6109a2565b60ff8216158061097e575060068160ff1610155b6109a2578161098c81610d9a565b925050808061099a90610d2a565b915050610936565b50505b60ff8516156107505760006109bb856001610d62565b905060006109ca600188610d81565b90505b60068260ff161080156109de575060015b156108fe576109ef88838388610a39565b156108c457826109fe81610d49565b93505060068260ff16101580610a15575060ff8116155b6108fe5781610a2381610d2a565b9250508080610a3190610d9a565b9150506109cd565b600080600160008760ff16815260200190815260200160002060030190508260ff16818660ff1660068110610a7057610a70610cfe565b018560ff1660078110610a8557610a85610cfe565b602081049091015460ff601f9092166101000a90041614915050949350505050565b6040518060c001604052806006905b610abe610b1e565b815260200190600190039081610ab65790505090565b8260068101928215610b0e579160200282015b82811115610b0e578251610afe9083906007610b3c565b5091602001919060010190610ae7565b50610b1a929150610bcb565b5090565b6040518060e001604052806007906020820280368337509192915050565b600183019183908215610bbf5791602002820160005b83821115610b9057835183826101000a81548160ff021916908360ff1602179055509260200192600101602081600001049283019260010302610b52565b8015610bbd5782816101000a81549060ff0219169055600101602081600001049283019260010302610b90565b505b50610b1a929150610bdf565b80821115610b1a5760008155600101610bcb565b80821115610b1a5760008155600101610bcb565b803560ff81168114610c0457600080fd5b919050565b60008060408385031215610c1c57600080fd5b610c2583610bf3565b9150610c3360208401610bf3565b90509250929050565b600060208284031215610c4e57600080fd5b81356001600160a01b0381168114610c6557600080fd5b9392505050565b600060208284031215610c7e57600080fd5b610c6582610bf3565b610540810181836000805b6006811015610cdb57825184835b6007811015610cc257825160ff16825260209283019290910190600101610ca0565b50505060e0939093019260209290920191600101610c92565b5050505092915050565b600060208284031215610cf757600080fd5b5035919050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600060ff821660ff8103610d4057610d40610d14565b60010192915050565b600060018201610d5b57610d5b610d14565b5060010190565b60ff8181168382160190811115610d7b57610d7b610d14565b92915050565b60ff8281168282160390811115610d7b57610d7b610d14565b600060ff821680610dad57610dad610d14565b600019019291505056fea2646970667358221220c5419c31ec2910d5969e867245a2e00372586e0cb9ae0ce6c3c59027fde0a42c64736f6c63430008110033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100575760003560e01c80635e24b0f11461005c57806372fb9703146100715780639b33b42914610084578063a2f77bcc146100ad578063d7c81b551461012b575b600080fd5b61006f61006a366004610c09565b610142565b005b61006f61007f366004610c3c565b610424565b610097610092366004610c6c565b61055a565b6040516100a49190610c87565b60405180910390f35b6100f86100bb366004610ce5565b60016020819052600091825260409091208054918101546002909101546001600160a01b039283169291821691811690600160a01b900460ff1684565b604080516001600160a01b0395861681529385166020850152919093169082015260ff90911660608201526080016100a4565b61013460005481565b6040519081526020016100a4565b60ff82166000818152600160205260409020600201546001600160a01b03161561017f5760405163df469ccb60e01b815260040160405180910390fd5b8160068160ff1611156101a557604051631efccef760e11b815260040160405180910390fd5b60ff84166000908152600160208190526040822060028101549092918291600160a01b900416156101d75760016101da565b60025b6002840154909150600160a01b9004600116156102015782546001600160a01b0316610210565b60018301546001600160a01b03165b6001600160a01b0316336001600160a01b03161461024157604051631cc191eb60e31b815260040160405180910390fd5b60005b60078160ff1610156102ec5760058160ff16111561027557604051631efccef760e11b815260040160405180910390fd5b6000846003018260ff166006811061028f5761028f610cfe565b018860ff16600781106102a4576102a4610cfe565b602081049091015460ff601f9092166101000a900416905060008190036102d957816102cf81610d2a565b92509350506102ec565b50806102e481610d2a565b915050610244565b5080836003018360ff166006811061030657610306610cfe565b018760ff166007811061031b5761031b610cfe565b60208104909101805460ff938416601f9093166101000a9283029284021916919091179055600284018054600160a01b900490911690601461035c83610d2a565b82546101009290920a60ff818102199093169183160217909155604080513381528983166020820152918a1692507fa6f41f711ea470b4b237d1b3e43b201e53517677308ae067a273fb1948ddbf0c910160405180910390a26103c1878784846105f9565b1561041b576002830180546001600160a01b031916339081179091556040805160ff8a16815260208101929092527fb7f35e624e036288272fbf3342c09219261ff29fdddd826989b289134e9ae535910160405180910390a15b50505050505050565b806001600160a01b038116330361043a57600080fd5b610442610aa7565b6040805160a0810182523381526001600160a01b038581166020808401918252600084860181815260608601828152608087018981528354845260019485905297909220865181549087166001600160a01b03199182161782559451938101805494871694909516939093179093559151600282018054935160ff16600160a01b026001600160a81b03199094169190941617919091179091559151909182916104f29060038301906006610ad4565b5050600054604080519182523360208301526001600160a01b038716908201527f8946648bc1dbc670d3f07e2c4de91731227b6d4ccc53b8ab1e951e84d960577e915060600160405180910390a160008054908061054f83610d49565b919050555050505050565b610562610aa7565b60ff8216600090815260016020526040808220815160c081019092529091600390910190600690835b828210156105ee576040805160e08101918290529085840190600790826000855b825461010083900a900460ff168152602060019283018181049485019490930390920291018084116105ac57905050505050508152602001906001019061058b565b505050509050919050565b60008061060886868686610699565b90508060040361061c576001915050610691565b600061062a87878787610759565b90508060040361063f57600192505050610691565b600061064d88888888610804565b9050806004036106635760019350505050610691565b60006106718989898961090a565b905080600403610688576001945050505050610691565b60009450505050505b949350505050565b60006001816106a88683610d62565b90505b60078160ff1610156106f1576106c387868387610a39565b156106da57816106d281610d49565b9250506106df565b6106f1565b806106e981610d2a565b9150506106ab565b5060ff851615610750576000610708600187610d81565b90505b61071787868387610a39565b1561072e578161072681610d49565b925050610733565b61074e565b60ff81161561074e578061074681610d9a565b91505061070b565b505b95945050505050565b60006001816107688583610d62565b90505b60068160ff1610156107b15761078387828887610a39565b1561079a578161079281610d49565b92505061079f565b6107b1565b806107a981610d2a565b91505061076b565b5060ff8416156107505760006107c8600186610d81565b90505b6107d787828887610a39565b1561072e57816107e681610d49565b92505060ff81161561074e57806107fc81610d9a565b9150506107cb565b60006001816108138583610d62565b90505b610821856006610d81565b60ff168160ff1610156108685761083a87828387610a39565b15610851578161084981610d49565b925050610856565b610868565b8061086081610d2a565b915050610816565b5060ff84161580159061087d575060ff851615155b1561075057600061088f600186610d81565b9050600061089e600188610d81565b90505b6108ad88838388610a39565b156108c457826108bc81610d49565b9350506108c9565b6108fe565b60ff821615806108da575060ff8116155b6108fe57816108e881610d9a565b92505080806108f690610d9a565b9150506108a1565b50509050949350505050565b6000600160ff8416156109a5576000610924600186610d81565b90506000610933876001610d62565b90505b60068160ff1610156109a25761094e88838388610a39565b15610965578261095d81610d49565b93505061096a565b6109a2565b60ff8216158061097e575060068160ff1610155b6109a2578161098c81610d9a565b925050808061099a90610d2a565b915050610936565b50505b60ff8516156107505760006109bb856001610d62565b905060006109ca600188610d81565b90505b60068260ff161080156109de575060015b156108fe576109ef88838388610a39565b156108c457826109fe81610d49565b93505060068260ff16101580610a15575060ff8116155b6108fe5781610a2381610d2a565b9250508080610a3190610d9a565b9150506109cd565b600080600160008760ff16815260200190815260200160002060030190508260ff16818660ff1660068110610a7057610a70610cfe565b018560ff1660078110610a8557610a85610cfe565b602081049091015460ff601f9092166101000a90041614915050949350505050565b6040518060c001604052806006905b610abe610b1e565b815260200190600190039081610ab65790505090565b8260068101928215610b0e579160200282015b82811115610b0e578251610afe9083906007610b3c565b5091602001919060010190610ae7565b50610b1a929150610bcb565b5090565b6040518060e001604052806007906020820280368337509192915050565b600183019183908215610bbf5791602002820160005b83821115610b9057835183826101000a81548160ff021916908360ff1602179055509260200192600101602081600001049283019260010302610b52565b8015610bbd5782816101000a81549060ff0219169055600101602081600001049283019260010302610b90565b505b50610b1a929150610bdf565b80821115610b1a5760008155600101610bcb565b80821115610b1a5760008155600101610bcb565b803560ff81168114610c0457600080fd5b919050565b60008060408385031215610c1c57600080fd5b610c2583610bf3565b9150610c3360208401610bf3565b90509250929050565b600060208284031215610c4e57600080fd5b81356001600160a01b0381168114610c6557600080fd5b9392505050565b600060208284031215610c7e57600080fd5b610c6582610bf3565b610540810181836000805b6006811015610cdb57825184835b6007811015610cc257825160ff16825260209283019290910190600101610ca0565b50505060e0939093019260209290920191600101610c92565b5050505092915050565b600060208284031215610cf757600080fd5b5035919050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600060ff821660ff8103610d4057610d40610d14565b60010192915050565b600060018201610d5b57610d5b610d14565b5060010190565b60ff8181168382160190811115610d7b57610d7b610d14565b92915050565b60ff8281168282160390811115610d7b57610d7b610d14565b600060ff821680610dad57610dad610d14565b600019019291505056fea2646970667358221220c5419c31ec2910d5969e867245a2e00372586e0cb9ae0ce6c3c59027fde0a42c64736f6c63430008110033", + "numDeployments": 5, + "solcInputHash": "6d21da006bc3ab8bcd3846174d2e1c6c", + "metadata": "{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"GameOver\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSelection\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotYourTurn\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gameId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"teamOne\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"teamTwo\",\"type\":\"address\"}],\"name\":\"GameCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gameId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"winner\",\"type\":\"address\"}],\"name\":\"GameFinished\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"gameId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"team\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"column\",\"type\":\"uint8\"}],\"name\":\"TurnTaken\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"opponent\",\"type\":\"address\"}],\"name\":\"challenge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"gameId\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"getGame\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"teamOne\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"teamTwo\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"winner\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"turn\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"_gameId\",\"type\":\"uint8\"}],\"name\":\"getGameBoard\",\"outputs\":[{\"internalType\":\"uint8[7][6]\",\"name\":\"\",\"type\":\"uint8[7][6]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"_gameId\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"column\",\"type\":\"uint8\"}],\"name\":\"makeMove\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"challenge(address)\":{\"details\":\"opponent will go firstgame id is increated each time a new game is createdseason is over when timer (soon to be added) is past\",\"params\":{\"opponent\":\"challened\"}},\"makeMove(uint8,uint8)\":{\"params\":{\"_gameId\":\"id of game\",\"column\":\"selected column for move\"}}},\"stateVariables\":{\"gameId\":{\"details\":\"Initialised at 1 because it makes the first transaction slightly cheaper.\"},\"getGame\":{\"details\":\"This automatically generates a getter for us, which will return `Game.player1`, `Game.player2`, `Game.moves`, and `Game.finished` (the arrays are skipped)\"}},\"version\":1},\"userdoc\":{\"errors\":{\"GameOver()\":[{\"notice\":\"revert if game has been completed\"}],\"InvalidSelection()\":[{\"notice\":\"revert if column choice is invalid\"}],\"NotYourTurn()\":[{\"notice\":\"revert if caller isn't current team\"}]},\"events\":{\"GameCreated(uint256,address,address)\":{\"notice\":\"emiited when game is created\"},\"GameFinished(uint256,address)\":{\"notice\":\"emitted when game is complete\"},\"TurnTaken(uint256,address,uint8)\":{\"notice\":\"emitted after turn is successfully taken\"}},\"kind\":\"user\",\"methods\":{\"challenge(address)\":{\"notice\":\"challenge an address to a game of connect four\"},\"gameId()\":{\"notice\":\"Used as a counter for the next game index.\"},\"getGame(uint256)\":{\"notice\":\"An indexed list of games\"},\"makeMove(uint8,uint8)\":{\"notice\":\"current team plays a turn\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/ConnectFour/ConnectFour.sol\":\"ConnectFour\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/ConnectFour/ConnectFour.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\npragma solidity ^0.8.17;\\n\\ncontract ConnectFour {\\n /// @notice revert if caller isn't current team\\n error NotYourTurn();\\n /// @notice revert if column choice is invalid\\n error InvalidSelection();\\n /// @notice revert if game has been completed\\n error GameOver();\\n /// @notice emiited when game is created\\n\\n event GameCreated(uint gameId, address teamOne, address teamTwo);\\n /// @notice emitted after turn is successfully taken\\n event TurnTaken(uint indexed gameId, address team, uint8 column);\\n /// @notice emitted when game is complete\\n event GameFinished(uint gameId, address winner);\\n\\n /// @notice holds game data\\n /// @param teamOne address of challenger\\n /// @param teamTwo address of challenged\\n /// @param winner address of winning team; default: address(0)\\n /// @param turn current turn is calculated using bitwise for basically odd/even teamOne/teamTwo\\n /// @param board holds game board data; each 'square' holds current data; 0 = no chip; 1 = team one; 2 = team two\\n struct Game {\\n address teamOne;\\n address teamTwo;\\n address winner;\\n uint8 turn;\\n uint8[7][6] board;\\n }\\n\\n /// @notice Used as a counter for the next game index.\\n /// @dev Initialised at 1 because it makes the first transaction slightly cheaper.\\n uint public gameId;\\n\\n /// @notice An indexed list of games\\n /// @dev This automatically generates a getter for us, which will return `Game.player1`, `Game.player2`, `Game.moves`, and `Game.finished` (the arrays are skipped)\\n mapping(uint => Game) public getGame;\\n\\n /// @notice prevent move if column is invalid\\n modifier validColumn(uint8 column) {\\n if (column > 6) revert InvalidSelection();\\n _;\\n }\\n\\n /// @notice prevents gameplay if game is over\\n modifier gameOver(uint _gameId) {\\n if (getGame[_gameId].winner != address(0)) revert GameOver();\\n _;\\n }\\n\\n /// @notice prevents teams being the same address\\n modifier uniqueTeams(address opponent) {\\n require(msg.sender != opponent);\\n _;\\n }\\n\\n /**\\n * @notice challenge an address to a game of connect four\\n * @param opponent challened\\n * @dev opponent will go first\\n * @dev game id is increated each time a new game is created\\n * @dev season is over when timer (soon to be added) is past\\n */\\n function challenge(address opponent) public uniqueTeams(opponent) {\\n uint8[7][6] memory newBoard;\\n Game memory newGame = Game({\\n teamOne: msg.sender,\\n teamTwo: opponent,\\n turn: uint8(0),\\n winner: address(0),\\n board: newBoard\\n });\\n getGame[gameId] = newGame;\\n\\n emit GameCreated(gameId, msg.sender, opponent);\\n\\n gameId++;\\n }\\n\\n /**\\n * @notice current team plays a turn\\n * @param _gameId id of game\\n * @param column selected column for move\\n */\\n function makeMove(\\n uint8 _gameId,\\n uint8 column\\n ) external gameOver(_gameId) validColumn(column) {\\n Game storage game = getGame[_gameId];\\n\\n /// @notice row where chip will land\\n uint8 row;\\n /// @notice assigned team number for squares\\n uint8 teamNum = game.turn & 1 == 0 ? 2 : 1;\\n\\n /// @notice prevents plays being made by other addresses\\n /// @dev even or odd bitwise operator decides turn\\n /// @dev starts with team two\\n if (msg.sender != (game.turn & 1 == 0 ? game.teamTwo : game.teamOne)) {\\n revert NotYourTurn();\\n }\\n\\n /// @notice finds where chip will land\\n for (uint8 i = 0; i < 7; i++) {\\n if (i > 5) {\\n revert InvalidSelection();\\n }\\n uint8 square = game.board[i][column];\\n if (square == 0) {\\n row = i++;\\n break;\\n }\\n }\\n\\n /// @notice assigns chip to location onboard\\n game.board[row][column] = teamNum;\\n /// @notice increments turn\\n game.turn++;\\n\\n emit TurnTaken(_gameId, msg.sender, column);\\n\\n /// @notice checks surrounding squares for connected pieces\\n if (didPlayerWin(_gameId, column, row, teamNum)) {\\n game.winner = msg.sender;\\n emit GameFinished(_gameId, msg.sender);\\n }\\n }\\n\\n /// @notice checks square for team's chip\\n /// @param _gameId id of game\\n /// @param firstIndex column selected for new chip\\n /// @param secondIndex row where new chip lands\\n /// @param teamNum number assigned to team\\n function checkSquare(\\n uint8 _gameId,\\n uint8 firstIndex,\\n uint8 secondIndex,\\n uint8 teamNum\\n ) private view returns (bool) {\\n uint8[7][6] storage board = getGame[_gameId].board;\\n return board[firstIndex][secondIndex] == teamNum;\\n }\\n\\n /// @notice checks the horizontal win\\n /// @param _gameId id of game\\n /// @param column column selected for new chip\\n /// @param row row where new chip lands\\n /// @param teamNum number assigned to team\\n function checkHorizonalWin(\\n uint8 _gameId,\\n uint8 column,\\n uint8 row,\\n uint8 teamNum\\n ) private view returns (uint) {\\n uint connectedPiecesCount = 1;\\n\\n /// @dev checks to the right of new piece\\n for (uint8 i = column + 1; i < 7; i++) {\\n if (checkSquare(_gameId, row, i, teamNum)) {\\n connectedPiecesCount++;\\n } else {\\n break;\\n }\\n }\\n /// @dev checks to the left of new piece\\n if (column != 0) {\\n uint8 columnIndex = column - 1;\\n while (columnIndex >= 0) {\\n if (checkSquare(_gameId, row, columnIndex, teamNum)) {\\n connectedPiecesCount++;\\n } else {\\n break;\\n }\\n if (columnIndex == 0) {\\n break;\\n } else {\\n columnIndex--;\\n }\\n }\\n }\\n\\n return connectedPiecesCount;\\n }\\n\\n /// @notice checks the veritical win\\n /// @param _gameId id of game\\n /// @param column column selected for new chip\\n /// @param row row where new chip lands\\n /// @param teamNum number assigned to team\\n function checkVericalWin(\\n uint8 _gameId,\\n uint8 column,\\n uint8 row,\\n uint8 teamNum\\n ) private view returns (uint) {\\n uint connectedPiecesCount = 1;\\n\\n /// @dev checks rows above new piece\\n for (uint8 i = row + 1; i < 6; i++) {\\n if (checkSquare(_gameId, i, column, teamNum)) {\\n connectedPiecesCount++;\\n } else {\\n break;\\n }\\n }\\n /// @dev checks rows below new piece\\n if (row != 0) {\\n uint8 rowIndex = row - 1;\\n while (rowIndex >= 0) {\\n if (checkSquare(_gameId, rowIndex, column, teamNum)) {\\n connectedPiecesCount++;\\n } else {\\n break;\\n }\\n if (rowIndex == 0) {\\n break;\\n } else {\\n rowIndex--;\\n }\\n }\\n }\\n return connectedPiecesCount;\\n }\\n\\n /// @notice checks the forward angle win\\n /// @param _gameId id of game\\n /// @param column column selected for new chip\\n /// @param row row where new chip lands\\n /// @param teamNum number assigned to team\\n function checkForwardAngleWin(\\n uint8 _gameId,\\n uint8 column,\\n uint8 row,\\n uint8 teamNum\\n ) private view returns (uint) {\\n uint connectedPiecesCount = 1;\\n\\n /// @dev checks forward angle up\\n for (uint8 i = row + 1; i < 6 - row; i++) {\\n if (checkSquare(_gameId, i, i, teamNum)) {\\n connectedPiecesCount++;\\n } else {\\n break;\\n }\\n }\\n\\n /// @dev checks forward angle down\\n if (row != 0 && column != 0) {\\n uint8 rowIndex = row - 1;\\n uint8 columnIndex = column - 1;\\n while (rowIndex >= 0 && columnIndex >= 0) {\\n if (checkSquare(_gameId, rowIndex, columnIndex, teamNum)) {\\n connectedPiecesCount++;\\n } else {\\n break;\\n }\\n if (rowIndex == 0 || columnIndex == 0) {\\n break;\\n } else {\\n rowIndex--;\\n columnIndex--;\\n }\\n }\\n }\\n return connectedPiecesCount;\\n }\\n\\n /// @notice checks the backward angle win\\n /// @param _gameId id of game\\n /// @param column column selected for new chip\\n /// @param row row where new chip lands\\n /// @param teamNum number assigned to team\\n function checkBackwardAngleWin(\\n uint8 _gameId,\\n uint8 column,\\n uint8 row,\\n uint8 teamNum\\n ) private view returns (uint) {\\n uint connectedPiecesCount = 1;\\n\\n /// @dev checks backward angle down\\n if (row != 0) {\\n uint8 rowIndex = row - 1;\\n uint8 columnIndex = column + 1;\\n while (rowIndex >= 0 && columnIndex < 7) {\\n if (checkSquare(_gameId, rowIndex, columnIndex, teamNum)) {\\n connectedPiecesCount++;\\n } else {\\n break;\\n }\\n if (rowIndex == 0 || columnIndex >= 6) {\\n break;\\n } else {\\n rowIndex--;\\n columnIndex++;\\n }\\n }\\n }\\n\\n /// @dev checks forward angle down\\n if (column != 0) {\\n uint8 rowIndex = row + 1;\\n uint8 columnIndex = column - 1;\\n while (rowIndex < 6 && columnIndex >= 0) {\\n if (checkSquare(_gameId, rowIndex, columnIndex, teamNum)) {\\n connectedPiecesCount++;\\n } else {\\n break;\\n }\\n if (rowIndex >= 6 || columnIndex == 0) {\\n break;\\n } else {\\n rowIndex++;\\n columnIndex--;\\n }\\n }\\n }\\n return connectedPiecesCount;\\n }\\n\\n /// @notice checks to see if current play won the game\\n /// @param _gameId id of game\\n /// @param column column selected for new chip\\n /// @param row row where new chip lands\\n /// @param teamNum number assigned to team\\n function didPlayerWin(\\n uint8 _gameId,\\n uint8 column,\\n uint8 row,\\n uint8 teamNum\\n ) private view returns (bool) {\\n /// @dev using new chip location as middle == m\\n /// @dev [ [ C+1 | R-1 ] [ C+1 ] [ C+1 | R+1 ] ]\\n /// @dev [ [ R-1 ] [ C | R ] [ R+1 ]\\n /// @dev [ [ C-1 | R-1 ] [ C-1 ] [ C-1 | R+1 ] ]\\n\\n uint horionalCount = checkHorizonalWin(_gameId, column, row, teamNum);\\n if (horionalCount == 4) {\\n return true;\\n }\\n uint vericalCount = checkVericalWin(_gameId, column, row, teamNum);\\n if (vericalCount == 4) {\\n return true;\\n }\\n uint forwardAngleCount = checkForwardAngleWin(\\n _gameId,\\n column,\\n row,\\n teamNum\\n );\\n if (forwardAngleCount == 4) {\\n return true;\\n }\\n uint backwardAngleCount = checkBackwardAngleWin(\\n _gameId,\\n column,\\n row,\\n teamNum\\n );\\n if (backwardAngleCount == 4) {\\n return true;\\n }\\n return false;\\n }\\n\\n function getGameBoard(\\n uint8 _gameId\\n ) public view returns (uint8[7][6] memory) {\\n return getGame[_gameId].board;\\n }\\n}\\n\",\"keccak256\":\"0x18a48c28f88d90b1e051578948cba806e3db8d53465a018b7c05e03599f0517d\",\"license\":\"GPL-3.0\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50610ded806100206000396000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c80635e24b0f11461005c57806372fb9703146100715780639b33b42914610084578063a2f77bcc146100ad578063d7c81b551461012b575b600080fd5b61006f61006a366004610c09565b610142565b005b61006f61007f366004610c3c565b610424565b610097610092366004610c6c565b61055a565b6040516100a49190610c87565b60405180910390f35b6100f86100bb366004610ce5565b60016020819052600091825260409091208054918101546002909101546001600160a01b039283169291821691811690600160a01b900460ff1684565b604080516001600160a01b0395861681529385166020850152919093169082015260ff90911660608201526080016100a4565b61013460005481565b6040519081526020016100a4565b60ff82166000818152600160205260409020600201546001600160a01b03161561017f5760405163df469ccb60e01b815260040160405180910390fd5b8160068160ff1611156101a557604051631efccef760e11b815260040160405180910390fd5b60ff84166000908152600160208190526040822060028101549092918291600160a01b900416156101d75760016101da565b60025b6002840154909150600160a01b9004600116156102015782546001600160a01b0316610210565b60018301546001600160a01b03165b6001600160a01b0316336001600160a01b03161461024157604051631cc191eb60e31b815260040160405180910390fd5b60005b60078160ff1610156102ec5760058160ff16111561027557604051631efccef760e11b815260040160405180910390fd5b6000846003018260ff166006811061028f5761028f610cfe565b018860ff16600781106102a4576102a4610cfe565b602081049091015460ff601f9092166101000a900416905060008190036102d957816102cf81610d2a565b92509350506102ec565b50806102e481610d2a565b915050610244565b5080836003018360ff166006811061030657610306610cfe565b018760ff166007811061031b5761031b610cfe565b60208104909101805460ff938416601f9093166101000a9283029284021916919091179055600284018054600160a01b900490911690601461035c83610d2a565b82546101009290920a60ff818102199093169183160217909155604080513381528983166020820152918a1692507fa6f41f711ea470b4b237d1b3e43b201e53517677308ae067a273fb1948ddbf0c910160405180910390a26103c1878784846105f9565b1561041b576002830180546001600160a01b031916339081179091556040805160ff8a16815260208101929092527fb7f35e624e036288272fbf3342c09219261ff29fdddd826989b289134e9ae535910160405180910390a15b50505050505050565b806001600160a01b038116330361043a57600080fd5b610442610aa7565b6040805160a0810182523381526001600160a01b038581166020808401918252600084860181815260608601828152608087018981528354845260019485905297909220865181549087166001600160a01b03199182161782559451938101805494871694909516939093179093559151600282018054935160ff16600160a01b026001600160a81b03199094169190941617919091179091559151909182916104f29060038301906006610ad4565b5050600054604080519182523360208301526001600160a01b038716908201527f8946648bc1dbc670d3f07e2c4de91731227b6d4ccc53b8ab1e951e84d960577e915060600160405180910390a160008054908061054f83610d49565b919050555050505050565b610562610aa7565b60ff8216600090815260016020526040808220815160c081019092529091600390910190600690835b828210156105ee576040805160e08101918290529085840190600790826000855b825461010083900a900460ff168152602060019283018181049485019490930390920291018084116105ac57905050505050508152602001906001019061058b565b505050509050919050565b60008061060886868686610699565b90508060040361061c576001915050610691565b600061062a87878787610759565b90508060040361063f57600192505050610691565b600061064d88888888610804565b9050806004036106635760019350505050610691565b60006106718989898961090a565b905080600403610688576001945050505050610691565b60009450505050505b949350505050565b60006001816106a88683610d62565b90505b60078160ff1610156106f1576106c387868387610a39565b156106da57816106d281610d49565b9250506106df565b6106f1565b806106e981610d2a565b9150506106ab565b5060ff851615610750576000610708600187610d81565b90505b61071787868387610a39565b1561072e578161072681610d49565b925050610733565b61074e565b60ff81161561074e578061074681610d9a565b91505061070b565b505b95945050505050565b60006001816107688583610d62565b90505b60068160ff1610156107b15761078387828887610a39565b1561079a578161079281610d49565b92505061079f565b6107b1565b806107a981610d2a565b91505061076b565b5060ff8416156107505760006107c8600186610d81565b90505b6107d787828887610a39565b1561072e57816107e681610d49565b92505060ff81161561074e57806107fc81610d9a565b9150506107cb565b60006001816108138583610d62565b90505b610821856006610d81565b60ff168160ff1610156108685761083a87828387610a39565b15610851578161084981610d49565b925050610856565b610868565b8061086081610d2a565b915050610816565b5060ff84161580159061087d575060ff851615155b1561075057600061088f600186610d81565b9050600061089e600188610d81565b90505b6108ad88838388610a39565b156108c457826108bc81610d49565b9350506108c9565b6108fe565b60ff821615806108da575060ff8116155b6108fe57816108e881610d9a565b92505080806108f690610d9a565b9150506108a1565b50509050949350505050565b6000600160ff8416156109a5576000610924600186610d81565b90506000610933876001610d62565b90505b60078160ff1610156109a25761094e88838388610a39565b15610965578261095d81610d49565b93505061096a565b6109a2565b60ff8216158061097e575060068160ff1610155b6109a2578161098c81610d9a565b925050808061099a90610d2a565b915050610936565b50505b60ff8516156107505760006109bb856001610d62565b905060006109ca600188610d81565b90505b60068260ff161080156109de575060015b156108fe576109ef88838388610a39565b156108c457826109fe81610d49565b93505060068260ff16101580610a15575060ff8116155b6108fe5781610a2381610d2a565b9250508080610a3190610d9a565b9150506109cd565b600080600160008760ff16815260200190815260200160002060030190508260ff16818660ff1660068110610a7057610a70610cfe565b018560ff1660078110610a8557610a85610cfe565b602081049091015460ff601f9092166101000a90041614915050949350505050565b6040518060c001604052806006905b610abe610b1e565b815260200190600190039081610ab65790505090565b8260068101928215610b0e579160200282015b82811115610b0e578251610afe9083906007610b3c565b5091602001919060010190610ae7565b50610b1a929150610bcb565b5090565b6040518060e001604052806007906020820280368337509192915050565b600183019183908215610bbf5791602002820160005b83821115610b9057835183826101000a81548160ff021916908360ff1602179055509260200192600101602081600001049283019260010302610b52565b8015610bbd5782816101000a81549060ff0219169055600101602081600001049283019260010302610b90565b505b50610b1a929150610bdf565b80821115610b1a5760008155600101610bcb565b80821115610b1a5760008155600101610bcb565b803560ff81168114610c0457600080fd5b919050565b60008060408385031215610c1c57600080fd5b610c2583610bf3565b9150610c3360208401610bf3565b90509250929050565b600060208284031215610c4e57600080fd5b81356001600160a01b0381168114610c6557600080fd5b9392505050565b600060208284031215610c7e57600080fd5b610c6582610bf3565b610540810181836000805b6006811015610cdb57825184835b6007811015610cc257825160ff16825260209283019290910190600101610ca0565b50505060e0939093019260209290920191600101610c92565b5050505092915050565b600060208284031215610cf757600080fd5b5035919050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600060ff821660ff8103610d4057610d40610d14565b60010192915050565b600060018201610d5b57610d5b610d14565b5060010190565b60ff8181168382160190811115610d7b57610d7b610d14565b92915050565b60ff8281168282160390811115610d7b57610d7b610d14565b600060ff821680610dad57610dad610d14565b600019019291505056fea2646970667358221220c6bed02514d044430679bd96da17f777697d9494240fe69dc1c4bc10a2f354ee64736f6c63430008110033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100575760003560e01c80635e24b0f11461005c57806372fb9703146100715780639b33b42914610084578063a2f77bcc146100ad578063d7c81b551461012b575b600080fd5b61006f61006a366004610c09565b610142565b005b61006f61007f366004610c3c565b610424565b610097610092366004610c6c565b61055a565b6040516100a49190610c87565b60405180910390f35b6100f86100bb366004610ce5565b60016020819052600091825260409091208054918101546002909101546001600160a01b039283169291821691811690600160a01b900460ff1684565b604080516001600160a01b0395861681529385166020850152919093169082015260ff90911660608201526080016100a4565b61013460005481565b6040519081526020016100a4565b60ff82166000818152600160205260409020600201546001600160a01b03161561017f5760405163df469ccb60e01b815260040160405180910390fd5b8160068160ff1611156101a557604051631efccef760e11b815260040160405180910390fd5b60ff84166000908152600160208190526040822060028101549092918291600160a01b900416156101d75760016101da565b60025b6002840154909150600160a01b9004600116156102015782546001600160a01b0316610210565b60018301546001600160a01b03165b6001600160a01b0316336001600160a01b03161461024157604051631cc191eb60e31b815260040160405180910390fd5b60005b60078160ff1610156102ec5760058160ff16111561027557604051631efccef760e11b815260040160405180910390fd5b6000846003018260ff166006811061028f5761028f610cfe565b018860ff16600781106102a4576102a4610cfe565b602081049091015460ff601f9092166101000a900416905060008190036102d957816102cf81610d2a565b92509350506102ec565b50806102e481610d2a565b915050610244565b5080836003018360ff166006811061030657610306610cfe565b018760ff166007811061031b5761031b610cfe565b60208104909101805460ff938416601f9093166101000a9283029284021916919091179055600284018054600160a01b900490911690601461035c83610d2a565b82546101009290920a60ff818102199093169183160217909155604080513381528983166020820152918a1692507fa6f41f711ea470b4b237d1b3e43b201e53517677308ae067a273fb1948ddbf0c910160405180910390a26103c1878784846105f9565b1561041b576002830180546001600160a01b031916339081179091556040805160ff8a16815260208101929092527fb7f35e624e036288272fbf3342c09219261ff29fdddd826989b289134e9ae535910160405180910390a15b50505050505050565b806001600160a01b038116330361043a57600080fd5b610442610aa7565b6040805160a0810182523381526001600160a01b038581166020808401918252600084860181815260608601828152608087018981528354845260019485905297909220865181549087166001600160a01b03199182161782559451938101805494871694909516939093179093559151600282018054935160ff16600160a01b026001600160a81b03199094169190941617919091179091559151909182916104f29060038301906006610ad4565b5050600054604080519182523360208301526001600160a01b038716908201527f8946648bc1dbc670d3f07e2c4de91731227b6d4ccc53b8ab1e951e84d960577e915060600160405180910390a160008054908061054f83610d49565b919050555050505050565b610562610aa7565b60ff8216600090815260016020526040808220815160c081019092529091600390910190600690835b828210156105ee576040805160e08101918290529085840190600790826000855b825461010083900a900460ff168152602060019283018181049485019490930390920291018084116105ac57905050505050508152602001906001019061058b565b505050509050919050565b60008061060886868686610699565b90508060040361061c576001915050610691565b600061062a87878787610759565b90508060040361063f57600192505050610691565b600061064d88888888610804565b9050806004036106635760019350505050610691565b60006106718989898961090a565b905080600403610688576001945050505050610691565b60009450505050505b949350505050565b60006001816106a88683610d62565b90505b60078160ff1610156106f1576106c387868387610a39565b156106da57816106d281610d49565b9250506106df565b6106f1565b806106e981610d2a565b9150506106ab565b5060ff851615610750576000610708600187610d81565b90505b61071787868387610a39565b1561072e578161072681610d49565b925050610733565b61074e565b60ff81161561074e578061074681610d9a565b91505061070b565b505b95945050505050565b60006001816107688583610d62565b90505b60068160ff1610156107b15761078387828887610a39565b1561079a578161079281610d49565b92505061079f565b6107b1565b806107a981610d2a565b91505061076b565b5060ff8416156107505760006107c8600186610d81565b90505b6107d787828887610a39565b1561072e57816107e681610d49565b92505060ff81161561074e57806107fc81610d9a565b9150506107cb565b60006001816108138583610d62565b90505b610821856006610d81565b60ff168160ff1610156108685761083a87828387610a39565b15610851578161084981610d49565b925050610856565b610868565b8061086081610d2a565b915050610816565b5060ff84161580159061087d575060ff851615155b1561075057600061088f600186610d81565b9050600061089e600188610d81565b90505b6108ad88838388610a39565b156108c457826108bc81610d49565b9350506108c9565b6108fe565b60ff821615806108da575060ff8116155b6108fe57816108e881610d9a565b92505080806108f690610d9a565b9150506108a1565b50509050949350505050565b6000600160ff8416156109a5576000610924600186610d81565b90506000610933876001610d62565b90505b60078160ff1610156109a25761094e88838388610a39565b15610965578261095d81610d49565b93505061096a565b6109a2565b60ff8216158061097e575060068160ff1610155b6109a2578161098c81610d9a565b925050808061099a90610d2a565b915050610936565b50505b60ff8516156107505760006109bb856001610d62565b905060006109ca600188610d81565b90505b60068260ff161080156109de575060015b156108fe576109ef88838388610a39565b156108c457826109fe81610d49565b93505060068260ff16101580610a15575060ff8116155b6108fe5781610a2381610d2a565b9250508080610a3190610d9a565b9150506109cd565b600080600160008760ff16815260200190815260200160002060030190508260ff16818660ff1660068110610a7057610a70610cfe565b018560ff1660078110610a8557610a85610cfe565b602081049091015460ff601f9092166101000a90041614915050949350505050565b6040518060c001604052806006905b610abe610b1e565b815260200190600190039081610ab65790505090565b8260068101928215610b0e579160200282015b82811115610b0e578251610afe9083906007610b3c565b5091602001919060010190610ae7565b50610b1a929150610bcb565b5090565b6040518060e001604052806007906020820280368337509192915050565b600183019183908215610bbf5791602002820160005b83821115610b9057835183826101000a81548160ff021916908360ff1602179055509260200192600101602081600001049283019260010302610b52565b8015610bbd5782816101000a81549060ff0219169055600101602081600001049283019260010302610b90565b505b50610b1a929150610bdf565b80821115610b1a5760008155600101610bcb565b80821115610b1a5760008155600101610bcb565b803560ff81168114610c0457600080fd5b919050565b60008060408385031215610c1c57600080fd5b610c2583610bf3565b9150610c3360208401610bf3565b90509250929050565b600060208284031215610c4e57600080fd5b81356001600160a01b0381168114610c6557600080fd5b9392505050565b600060208284031215610c7e57600080fd5b610c6582610bf3565b610540810181836000805b6006811015610cdb57825184835b6007811015610cc257825160ff16825260209283019290910190600101610ca0565b50505060e0939093019260209290920191600101610c92565b5050505092915050565b600060208284031215610cf757600080fd5b5035919050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600060ff821660ff8103610d4057610d40610d14565b60010192915050565b600060018201610d5b57610d5b610d14565b5060010190565b60ff8181168382160190811115610d7b57610d7b610d14565b92915050565b60ff8281168282160390811115610d7b57610d7b610d14565b600060ff821680610dad57610dad610d14565b600019019291505056fea2646970667358221220c6bed02514d044430679bd96da17f777697d9494240fe69dc1c4bc10a2f354ee64736f6c63430008110033", "devdoc": { "kind": "dev", "methods": { diff --git a/deployments/goerli/solcInputs/6d21da006bc3ab8bcd3846174d2e1c6c.json b/deployments/goerli/solcInputs/6d21da006bc3ab8bcd3846174d2e1c6c.json new file mode 100644 index 0000000..4dd6f7c --- /dev/null +++ b/deployments/goerli/solcInputs/6d21da006bc3ab8bcd3846174d2e1c6c.json @@ -0,0 +1,35 @@ +{ + "language": "Solidity", + "sources": { + "contracts/ConnectFour/ConnectFour.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.17;\n\ncontract ConnectFour {\n /// @notice revert if caller isn't current team\n error NotYourTurn();\n /// @notice revert if column choice is invalid\n error InvalidSelection();\n /// @notice revert if game has been completed\n error GameOver();\n /// @notice emiited when game is created\n\n event GameCreated(uint gameId, address teamOne, address teamTwo);\n /// @notice emitted after turn is successfully taken\n event TurnTaken(uint indexed gameId, address team, uint8 column);\n /// @notice emitted when game is complete\n event GameFinished(uint gameId, address winner);\n\n /// @notice holds game data\n /// @param teamOne address of challenger\n /// @param teamTwo address of challenged\n /// @param winner address of winning team; default: address(0)\n /// @param turn current turn is calculated using bitwise for basically odd/even teamOne/teamTwo\n /// @param board holds game board data; each 'square' holds current data; 0 = no chip; 1 = team one; 2 = team two\n struct Game {\n address teamOne;\n address teamTwo;\n address winner;\n uint8 turn;\n uint8[7][6] board;\n }\n\n /// @notice Used as a counter for the next game index.\n /// @dev Initialised at 1 because it makes the first transaction slightly cheaper.\n uint public gameId;\n\n /// @notice An indexed list of games\n /// @dev This automatically generates a getter for us, which will return `Game.player1`, `Game.player2`, `Game.moves`, and `Game.finished` (the arrays are skipped)\n mapping(uint => Game) public getGame;\n\n /// @notice prevent move if column is invalid\n modifier validColumn(uint8 column) {\n if (column > 6) revert InvalidSelection();\n _;\n }\n\n /// @notice prevents gameplay if game is over\n modifier gameOver(uint _gameId) {\n if (getGame[_gameId].winner != address(0)) revert GameOver();\n _;\n }\n\n /// @notice prevents teams being the same address\n modifier uniqueTeams(address opponent) {\n require(msg.sender != opponent);\n _;\n }\n\n /**\n * @notice challenge an address to a game of connect four\n * @param opponent challened\n * @dev opponent will go first\n * @dev game id is increated each time a new game is created\n * @dev season is over when timer (soon to be added) is past\n */\n function challenge(address opponent) public uniqueTeams(opponent) {\n uint8[7][6] memory newBoard;\n Game memory newGame = Game({\n teamOne: msg.sender,\n teamTwo: opponent,\n turn: uint8(0),\n winner: address(0),\n board: newBoard\n });\n getGame[gameId] = newGame;\n\n emit GameCreated(gameId, msg.sender, opponent);\n\n gameId++;\n }\n\n /**\n * @notice current team plays a turn\n * @param _gameId id of game\n * @param column selected column for move\n */\n function makeMove(\n uint8 _gameId,\n uint8 column\n ) external gameOver(_gameId) validColumn(column) {\n Game storage game = getGame[_gameId];\n\n /// @notice row where chip will land\n uint8 row;\n /// @notice assigned team number for squares\n uint8 teamNum = game.turn & 1 == 0 ? 2 : 1;\n\n /// @notice prevents plays being made by other addresses\n /// @dev even or odd bitwise operator decides turn\n /// @dev starts with team two\n if (msg.sender != (game.turn & 1 == 0 ? game.teamTwo : game.teamOne)) {\n revert NotYourTurn();\n }\n\n /// @notice finds where chip will land\n for (uint8 i = 0; i < 7; i++) {\n if (i > 5) {\n revert InvalidSelection();\n }\n uint8 square = game.board[i][column];\n if (square == 0) {\n row = i++;\n break;\n }\n }\n\n /// @notice assigns chip to location onboard\n game.board[row][column] = teamNum;\n /// @notice increments turn\n game.turn++;\n\n emit TurnTaken(_gameId, msg.sender, column);\n\n /// @notice checks surrounding squares for connected pieces\n if (didPlayerWin(_gameId, column, row, teamNum)) {\n game.winner = msg.sender;\n emit GameFinished(_gameId, msg.sender);\n }\n }\n\n /// @notice checks square for team's chip\n /// @param _gameId id of game\n /// @param firstIndex column selected for new chip\n /// @param secondIndex row where new chip lands\n /// @param teamNum number assigned to team\n function checkSquare(\n uint8 _gameId,\n uint8 firstIndex,\n uint8 secondIndex,\n uint8 teamNum\n ) private view returns (bool) {\n uint8[7][6] storage board = getGame[_gameId].board;\n return board[firstIndex][secondIndex] == teamNum;\n }\n\n /// @notice checks the horizontal win\n /// @param _gameId id of game\n /// @param column column selected for new chip\n /// @param row row where new chip lands\n /// @param teamNum number assigned to team\n function checkHorizonalWin(\n uint8 _gameId,\n uint8 column,\n uint8 row,\n uint8 teamNum\n ) private view returns (uint) {\n uint connectedPiecesCount = 1;\n\n /// @dev checks to the right of new piece\n for (uint8 i = column + 1; i < 7; i++) {\n if (checkSquare(_gameId, row, i, teamNum)) {\n connectedPiecesCount++;\n } else {\n break;\n }\n }\n /// @dev checks to the left of new piece\n if (column != 0) {\n uint8 columnIndex = column - 1;\n while (columnIndex >= 0) {\n if (checkSquare(_gameId, row, columnIndex, teamNum)) {\n connectedPiecesCount++;\n } else {\n break;\n }\n if (columnIndex == 0) {\n break;\n } else {\n columnIndex--;\n }\n }\n }\n\n return connectedPiecesCount;\n }\n\n /// @notice checks the veritical win\n /// @param _gameId id of game\n /// @param column column selected for new chip\n /// @param row row where new chip lands\n /// @param teamNum number assigned to team\n function checkVericalWin(\n uint8 _gameId,\n uint8 column,\n uint8 row,\n uint8 teamNum\n ) private view returns (uint) {\n uint connectedPiecesCount = 1;\n\n /// @dev checks rows above new piece\n for (uint8 i = row + 1; i < 6; i++) {\n if (checkSquare(_gameId, i, column, teamNum)) {\n connectedPiecesCount++;\n } else {\n break;\n }\n }\n /// @dev checks rows below new piece\n if (row != 0) {\n uint8 rowIndex = row - 1;\n while (rowIndex >= 0) {\n if (checkSquare(_gameId, rowIndex, column, teamNum)) {\n connectedPiecesCount++;\n } else {\n break;\n }\n if (rowIndex == 0) {\n break;\n } else {\n rowIndex--;\n }\n }\n }\n return connectedPiecesCount;\n }\n\n /// @notice checks the forward angle win\n /// @param _gameId id of game\n /// @param column column selected for new chip\n /// @param row row where new chip lands\n /// @param teamNum number assigned to team\n function checkForwardAngleWin(\n uint8 _gameId,\n uint8 column,\n uint8 row,\n uint8 teamNum\n ) private view returns (uint) {\n uint connectedPiecesCount = 1;\n\n /// @dev checks forward angle up\n for (uint8 i = row + 1; i < 6 - row; i++) {\n if (checkSquare(_gameId, i, i, teamNum)) {\n connectedPiecesCount++;\n } else {\n break;\n }\n }\n\n /// @dev checks forward angle down\n if (row != 0 && column != 0) {\n uint8 rowIndex = row - 1;\n uint8 columnIndex = column - 1;\n while (rowIndex >= 0 && columnIndex >= 0) {\n if (checkSquare(_gameId, rowIndex, columnIndex, teamNum)) {\n connectedPiecesCount++;\n } else {\n break;\n }\n if (rowIndex == 0 || columnIndex == 0) {\n break;\n } else {\n rowIndex--;\n columnIndex--;\n }\n }\n }\n return connectedPiecesCount;\n }\n\n /// @notice checks the backward angle win\n /// @param _gameId id of game\n /// @param column column selected for new chip\n /// @param row row where new chip lands\n /// @param teamNum number assigned to team\n function checkBackwardAngleWin(\n uint8 _gameId,\n uint8 column,\n uint8 row,\n uint8 teamNum\n ) private view returns (uint) {\n uint connectedPiecesCount = 1;\n\n /// @dev checks backward angle down\n if (row != 0) {\n uint8 rowIndex = row - 1;\n uint8 columnIndex = column + 1;\n while (rowIndex >= 0 && columnIndex < 7) {\n if (checkSquare(_gameId, rowIndex, columnIndex, teamNum)) {\n connectedPiecesCount++;\n } else {\n break;\n }\n if (rowIndex == 0 || columnIndex >= 6) {\n break;\n } else {\n rowIndex--;\n columnIndex++;\n }\n }\n }\n\n /// @dev checks forward angle down\n if (column != 0) {\n uint8 rowIndex = row + 1;\n uint8 columnIndex = column - 1;\n while (rowIndex < 6 && columnIndex >= 0) {\n if (checkSquare(_gameId, rowIndex, columnIndex, teamNum)) {\n connectedPiecesCount++;\n } else {\n break;\n }\n if (rowIndex >= 6 || columnIndex == 0) {\n break;\n } else {\n rowIndex++;\n columnIndex--;\n }\n }\n }\n return connectedPiecesCount;\n }\n\n /// @notice checks to see if current play won the game\n /// @param _gameId id of game\n /// @param column column selected for new chip\n /// @param row row where new chip lands\n /// @param teamNum number assigned to team\n function didPlayerWin(\n uint8 _gameId,\n uint8 column,\n uint8 row,\n uint8 teamNum\n ) private view returns (bool) {\n /// @dev using new chip location as middle == m\n /// @dev [ [ C+1 | R-1 ] [ C+1 ] [ C+1 | R+1 ] ]\n /// @dev [ [ R-1 ] [ C | R ] [ R+1 ]\n /// @dev [ [ C-1 | R-1 ] [ C-1 ] [ C-1 | R+1 ] ]\n\n uint horionalCount = checkHorizonalWin(_gameId, column, row, teamNum);\n if (horionalCount == 4) {\n return true;\n }\n uint vericalCount = checkVericalWin(_gameId, column, row, teamNum);\n if (vericalCount == 4) {\n return true;\n }\n uint forwardAngleCount = checkForwardAngleWin(\n _gameId,\n column,\n row,\n teamNum\n );\n if (forwardAngleCount == 4) {\n return true;\n }\n uint backwardAngleCount = checkBackwardAngleWin(\n _gameId,\n column,\n row,\n teamNum\n );\n if (backwardAngleCount == 4) {\n return true;\n }\n return false;\n }\n\n function getGameBoard(\n uint8 _gameId\n ) public view returns (uint8[7][6] memory) {\n return getGame[_gameId].board;\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/minified/deployments.json b/minified/deployments.json index a06e5c4..501113b 100644 --- a/minified/deployments.json +++ b/minified/deployments.json @@ -3,7 +3,7 @@ "chainId": "5", "contracts": { "ConnectFour": { - "address": "0x399d76Dbc75894b555395a0fCD546A74205EBC9E", + "address": "0x3664B997f3EECC7AadA65F7A1f883cdC4BcD851b", "abi": [ { "inputs": [], diff --git a/package.json b/package.json index 58ab6fa..4e8e6c8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "b3-curious-contracts", - "version": "0.1.9", + "version": "0.1.10", "description": "EVM contracts written in Solidity", "author": "David A Colon", "license": "MIT",