Skip to content

Instantly share code, notes, and snippets.

@rigibun
Last active August 29, 2015 14:04
Show Gist options
  • Save rigibun/b5e70ad6649f44d69a7a to your computer and use it in GitHub Desktop.
Save rigibun/b5e70ad6649f44d69a7a to your computer and use it in GitHub Desktop.
import std.stdio,
std.typecons;
import player;
enum boardDefault = (function char[8][] (){
auto ret = new char[8][](8);
foreach(ref line; ret)
foreach(ref cell; line)
cell = '.';
ret[3][3] = ret[4][4] = 'W';
ret[3][4] = ret[4][3] = 'B';
return ret;
})();
class Othello
{
enum Turn { black = 0, white = 1 }
enum Flags : uint { end = 1, skip = 2 }
alias Pos = Tuple!(int, "x", int, "y");
char[8][] board;
Player playerWhite, playerBlack;
Turn turnPlayer;
public this(Player pBlack, Player pWhite)
{
playerBlack = pBlack;
playerWhite = pWhite;
board = boardDefault;
turnPlayer = Turn.black;
}
public Tuple!(int, "black", int, "white") loop()
{
drawBoard();
while(gameHasContinued)
{
if(placeToPutExists(turnPlayer))
{
Pos pos;
while(pos = (turnPlayer == Turn.black ? playerBlack : playerWhite).getMove(this), !canPut(turnPlayer, pos))
writeln("Position", pos.x, " : ", pos.y, "is invalid.");
putStone(turnPlayer, pos);
drawBoard();
}
else
{
writeln("skip");
}
turnPlayer = turnPlayer == Turn.black ? Turn.white : Turn.black;
}
return count();
}
public Flags next()
{
Flags flag;
if(gameHasContinued)
{
if(placeToPutExists(turnPlayer))
{
Pos pos;
while(pos = (turnPlayer == Turn.black ? playerBlack : playerWhite).getMove(this), !canPut(turnPlayer, pos))
writeln("Position", pos.x, " : ", pos.y, "is invalid.");
putStone(turnPlayer, pos);
}
else
{
flag |= Flags.skip;
}
turnPlayer = turnPlayer == Turn.black ? Turn.white : Turn.black;
}
else
{
flag |= Flags.end;
}
return flag;
}
public Tuple!(int, "black", int, "white") count()
{
auto black = 0, white = 0;
foreach(line; board)
foreach(cell; line)
{
if(cell == 'B')
black++;
else if(cell == 'W')
white++;
}
return Tuple!(int, "black", int, "white")(black, white);
}
public char[8][] getBoard()
{
auto retBoard = new char[8][](8);
foreach(i; 0 .. 8)
foreach(j; 0 .. 8)
retBoard[i][j] = board[i][j];
return retBoard;
}
public bool canPut(Turn turn, Pos pos)
{
if(board[pos.y][pos.x] != '.')
return false;
static dx = [-1, 0, 1, -1, 1, -1, 0, 1];
static dy = [-1, -1, -1, 0, 0, 1, 1, 1];
auto stone = turn == Turn.black ? 'B' : 'W';
auto opStone = stone == 'B' ? 'W' : 'B';
auto flag = false;
foreach(i; 0 .. 8)
{
auto x = pos.x, y = pos.y;
if(x + dx[i] < 8UL && y + dy[i] < 8UL && board[y + dy[i]][x + dx[i]] == opStone)
{
while(x += dx[i], y += dy[i], !flag && x < 8UL && y < 8UL && board[y][x] != '.')
{
flag = board[y][x] == stone;
}
}
if(flag) break;
}
return flag;
}
private bool gameHasContinued()
{
return placeToPutExists(Turn.black) || placeToPutExists(Turn.white);
}
private bool placeToPutExists(Turn turn)
{
auto flag = false;
foreach(y; 0 .. 8)
{
foreach(x; 0 .. 8)
flag = flag || canPut(turn, Pos(x, y));
if(flag)
break;
}
return flag;
}
private void putStone(Turn turn, Pos pos)
{
static dx = [-1, 0, 1, -1, 1, -1, 0, 1];
static dy = [-1, -1, -1, 0, 0, 1, 1, 1];
auto stone = turn == Turn.black ? 'B' : 'W';
auto opStone = stone == 'B' ? 'W' : 'B';
board[pos.y][pos.x] = stone;
foreach(i; 0 .. 8)
{
auto flag = false;
auto x = pos.x, y = pos.y;
if(x + dx[i] < 8UL && y + dy[i] < 8UL && board[y + dy[i]][x + dx[i]] == opStone)
while(x += dx[i], y += dy[i], !flag && x < 8UL && y < 8UL && board[y][x] != '.')
flag = board[y][x] == stone;
x = pos.x, y = pos.y;
if(flag)
while(x += dx[i], y += dy[i], x < 8UL && y < 8UL && board[y][x] != stone)
board[y][x] = stone;
}
}
private void drawBoard()
{
writeln(" 01234567");
foreach(y, line; board)
{
y.write;
foreach(cell; line)
cell.write;
writeln;
}
}
}
import std.typecons;
import othello;
interface Player
{
public alias Pos = Tuple!(int, "x", int, "y");
Pos getMove(Othello);
}
class CliUser : Player
{
import std.stdio,
std.string,
std.conv;
override Pos getMove(Othello o)
{
writeln("Input you move:");
string[] input;
Pos move;
while(input = readln.split, input.length < 2){}
move.x = input[0].to!ubyte;
move.y = input[1].to!ubyte;
return move;
}
}
class RandomPlayer : Player
{
Othello.Turn mycolor;
this(Othello.Turn color)
{
mycolor = color;
}
override Pos getMove(Othello o)
{
import std.random;
Pos pos;
while(pos = Pos(uniform(0, 8), uniform(0, 8)), !o.canPut(mycolor, pos)){}
return pos;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment