Skip to content

Instantly share code, notes, and snippets.

@nateawelch
Forked from noman-land/BattleHash.sol
Created April 21, 2018 20:58
Show Gist options
  • Save nateawelch/94329e45a63b38dc457ce083a3a415f7 to your computer and use it in GitHub Desktop.
Save nateawelch/94329e45a63b38dc457ce083a3a415f7 to your computer and use it in GitHub Desktop.
Board is 2x2 for testing purposes, it will be 10x10 eventually.
pragma experimental ABIEncoderV2;
pragma solidity ^0.4.23;
contract BattleHash {
uint256 public numGames;
modifier validShot(uint256 gameId) {
Game storage game = games[gameId];
address lastShooter = getLastShooter(game);
// Can't fire a shot unless you're a player
require(
msg.sender == game.players[0].id ||
msg.sender == game.players[1].id
);
if (lastShooter == 0) {
// Player 2 goes first
require(msg.sender == game.players[1].id);
} else if (lastShooter > 0) {
// Players can't go twice in a row;
require(msg.sender != lastShooter);
}
// Can't fire shots into completed games
require(game.winner == 0);
// Can't fire shots if there aren't 2 players yet
require(game.players[0].id > 0 && game.players[1].id > 0);
_;
}
struct Shot {
address shooter;
uint8 x;
uint8 y;
uint256 secret;
bool hit;
}
struct Player {
address id;
bytes32[2][2] board;
}
struct Game {
Player[2] players;
Shot[] shotsFired;
address winner;
}
mapping (uint256 => Game) public games;
function getLastShooter(Game game)
internal
pure
returns(address lastShooter)
{
uint256 numShots = game.shotsFired.length;
return numShots > 0
? game.shotsFired[numShots - 1].shooter
: address(0);
}
function getLastShot(uint256 gameId, uint256 offset)
public
view
returns (address shooter, uint8 x, uint8 y, uint256 secret, bool hit)
{
Game storage game = games[gameId];
Shot storage lastShot = game.shotsFired[game.shotsFired.length - 1 - offset];
return (
lastShot.shooter,
lastShot.x,
lastShot.y,
lastShot.secret,
lastShot.hit
);
}
function getPlayer(uint256 gameId, uint8 playerNum)
public
view
returns (address id, bytes32[2][2] board)
{
Player storage player = games[gameId].players[playerNum];
return (player.id, player.board);
}
function revealShot(uint256 gameId, uint256 secret)
internal
validShot(gameId)
{
Game storage game = games[gameId];
Shot storage lastShot = game.shotsFired[game.shotsFired.length - 1];
uint8 x = lastShot.x;
uint8 y = lastShot.y;
bytes32 result = msg.sender == game.players[0].id
? game.players[0].board[x][y]
: game.players[1].board[x][y];
bytes32 maybeMiss = keccak256(uint8(0), secret);
if (result != maybeMiss) {
lastShot.hit = true;
}
lastShot.secret = secret;
}
function fireShot(uint256 gameId, uint8 x, uint8 y)
internal
validShot(gameId)
{
Game storage game = games[gameId];
game.shotsFired.push(Shot(msg.sender, x, y, 0, false));
}
function revealAndfire(uint256 gameId, uint256 secret, uint8 x, uint8 y)
public
validShot(gameId)
{
revealShot(gameId, secret);
fireShot(gameId, x, y);
}
function newGame(bytes32[2][2] board) public {
numGames = numGames + 1;
games[numGames].players[0].id = msg.sender;
games[numGames].players[0].board = board;
}
function joinGame(uint256 gameId, bytes32[2][2] board, uint8 x, uint8 y)
public
{
Game storage game = games[gameId];
// Can only join a game that is missing a second player
require(game.players[0].id > 0 && game.players[1].id == 0);
// Can't join a game with yourself
require(game.players[0].id != msg.sender);
game.players[1].id = msg.sender;
game.players[1].board = board;
fireShot(gameId, x, y);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment