Checker
Game logic
Game Logic code
def init_game(game_settings):
init_board = [
-1, 1, -1, 1, -1, 1, -1, 1,
1, -1, 1, -1, 1, -1, 1, -1,
-1, 1, -1, 1, -1, 1, -1, 1,
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1,
0, -1, 0, -1, 0, -1, 0, -1,
-1, 0, -1, 0, -1, 0, -1, 0,
0, -1, 0, -1, 0, -1, 0, -1
]
return {
"player_turn_idx": 0,
"board": init_board,
"valid_moves": _get_all_valid_moves(init_board, 0),
"no_piece_taken_count": 0
}
def move(state, start, end):
board = state['board']
if start < 0 or start >= 64:
raise InvalidActionError("Starting position is out of bound")
if end < 0 or end >= 64:
raise InvalidActionError("Ending position is out of bound")
if not _is_empty(board, end):
raise InvalidActionError("Ending position is not empty")
valid_moves = state['valid_moves']
valid_move_tuples = [(move['start'], move['end']) for move in valid_moves]
if (start, end) not in valid_move_tuples:
raise InvalidActionError("Not a valid move")
player_idx = state['player_turn_idx']
is_piece_taken = False
if abs(end - start) > 10: # jumped over something
state['board'][end] = state['board'][start]
state['board'][start] = -1
state['board'][int((start + end)/2)] = -1
is_piece_taken = True
else: # did not jump over something
state['board'][end] = state['board'][start]
state['board'][start] = -1
state['player_turn_idx'] = (player_idx + 1) % 2
if player_idx == 0:
if not _is_king(state['board'], end) and end <= 7:
state['board'][end] += 2
else:
if not _is_king(state['board'], end) and end >= 56:
state['board'][end] += 2
if is_piece_taken:
moves_after_jumping = _valid_move(state['board'], end, player_idx)
more_jump_moves = []
for next_move_end in moves_after_jumping:
if _is_jump_move(next_move_end, end):
more_jump_moves.append({
'start': end,
'end': next_move_end
})
if len(more_jump_moves) > 0:
state['valid_moves'] = more_jump_moves
else:
state['player_turn_idx'] = (player_idx + 1) % 2
state['valid_moves'] = _get_all_valid_moves(state['board'], state['player_turn_idx'])
state['no_piece_taken_count'] = 0
else:
state['no_piece_taken_count'] += 1
state['valid_moves'] = _get_all_valid_moves(state['board'], state['player_turn_idx'])
return state
def get_game_result(state):
if len(state['valid_moves']) == 0:
return {
"game_result": "Winner",
"winner_idx": 0 if state['player_turn_idx'] == 1 else 0
}
if state['no_piece_taken_count'] >= 40:
return {
"game_result": "Draw"
}
return {
"game_result": "NoWinnerYet"
}
def _is_player1_piece(board, index):
return board[index] == 0 or board[index] == 2
def _is_player2_piece(board, index):
return board[index] == 1 or board[index] == 3
def _is_empty(board, index):
return board[index] == -1
def _is_king(board, index):
return board[index] >= 2
def _index_to_row_column(index):
return (int(index / 8), index % 8)
def _to_index(row, column):
return row * 8 + column
def _is_jump_move(start, end):
return abs(start - end) > 10
def _valid_move(board, start, player_idx):
if _is_king(board, start):
directions = [(1, 1), (1, -1), (-1, 1), (-1, -1)]
elif player_idx == 0:
directions = [(-1, 1), (-1, -1)]
else:
directions = [(1, 1), (1, -1)]
def _within_bound(row, column):
return row >= 0 and column >= 0 and row < 8 and column < 8
def is_opponent(index):
if player_idx == 0:
return _is_player2_piece(board, index)
else:
return _is_player1_piece(board, index)
start_r, start_c = _index_to_row_column(start)
valid_ends = []
for d_r, d_c in directions:
if _within_bound(start_r + d_r, start_c + d_c):
end = _to_index(start_r + d_r, start_c + d_c)
if _is_empty(board, end):
valid_ends.append(end)
if _within_bound(start_r + d_r*2, start_c + d_c*2):
mid = _to_index(start_r + d_r, start_c + d_c)
end = _to_index(start_r + d_r*2, start_c + d_c*2)
if _is_empty(board, end) and is_opponent(mid):
valid_ends.append(end)
return valid_ends
def _get_all_valid_moves(board, player_idx):
is_player1 = (player_idx == 0)
is_self_func = _is_player1_piece if is_player1 else _is_player2_piece
moves = []
for i in range(64):
if is_self_func(board, i):
valid_ends = _valid_move(board, i, player_idx)
for end in valid_ends:
moves.append({
'start': i,
'end': end
})
jump_moves = []
for move in moves:
if _is_jump_move(move['start'], move['end']):
jump_moves.append(move)
if len(jump_moves) > 0:
return jump_moves
return moves
Game state schema
message State {
string user1 = 1;
string user2 = 2;
string user_turn = 3;
repeated int32 board = 4;
repeated ValidMove valid_moves = 5;
int32 no_piece_taken_count = 6;
}
message ValidMove {
int32 start = 1;
int32 end = 2;
}
Action schema
move(int start, int end)
Last updated