Mancala
Game logic
Game Logic code
def init_game(game_settings):
state = {
'player_turn_idx': 0,
'board': [0, 4, 4, 4, 4, 4, 4, 0, 4, 4, 4, 4, 4, 4]
}
return state
"""
The last piece in Mancala has special rules. [__handle_last_piece] determines whether the piece lands in
a Mancala or an empty pocket on the player's own side. If landing on own Mancala, the player gains a second turn.
(state['player_turn_idx'] stays the same). If the piece lands on an empty pocket, and there are pieces in the
corresponding pocket on the opponent's side, the player gains both the last piece and those on the opponents side.
"""
def __handle_last_piece(state, index):
player_idx = state['player_turn_idx']
if player_idx == 0:
#Gain a turn if last piece lands on that user's own Mancala
if index == 7:
state['player_turn_idx'] = 0
return
#Take over pieces from other side if landing on empty space on user's own side
elif (1 <= index < 7) and state['board'][index] == 1 and state['board'][14 - index] != 0:
state['board'][7] += (state['board'][14 - index] + 1)
state['board'][14 - index] = 0
state['board'][index] = 0
state['player_turn_idx'] = 1
else:
if index == 0:
state['player_turn_idx'] = 1
return
elif (8 <= index < 14) and state['board'][index] == 1 and state['board'][14 - index] != 0:
state['board'][0] += (state['board'][14 - index] + 1)
state['board'][14 - index] = 0
state['board'][index] = 0
state['player_turn_idx'] = 0
"""
Function that moves the pieces on the board. Given the amount of pieces at the given index, this function will
loop around the board until the pieces run out. One piece goes into each pocket (except for the opponent's Mancala.)
"""
def __move_pieces(state, index):
pieces_left = state['board'][index]
state['board'][index] = 0 #Empty out chosen pocket
player_idx = state['player_turn_idx']
while pieces_left != 0:
index = (index + 1) % 14
#player 1 does not put pieces in pocket 0
#player 2 does not put pieces in pocket 7
if (player_idx == 0 and index == 0) or (player_idx == 1 and index == 7):
continue
state['board'][index] += 1
pieces_left -= 1
__handle_last_piece(state, index)
"""
Determines if the pocket the user chose is valid. Movies pieces around board and checks whether the current
user will have an extra turn.
Returns a new state.
"""
def choose_pocket(state, index):
if index < 0 or index > 13:
raise InvalidActionError("Index out of bound")
#Invalid action if user picks either Mancala.
if index == 0 or index == 7:
raise InvalidActionError("You cannot choose to move pieces out of a Mancala.")
#Invalid action if user tries to move pieces from the opponent's side
player_idx = state['player_turn_idx']
if (player_idx == 0 and index > 6) or (player_idx == 1 and index < 8):
raise InvalidActionError("You cannot choose a pocket from your opponent's side.")
#Invalid action if user picks pocket without pieces in it.
if state['board'][index] == 0:
raise InvalidActionError("There are no pieces in this pocket.")
__move_pieces(state, index)
return state
"""
Checks whether one of the sides is empty. If so, calculates the totals for both sides and returns
a game result. If neither side is empty, returns an ongoing result.
"""
def get_game_result(state):
#Detect if one of the sides is empty, otherwise, the game is ongoing
if (__side_empty(state, 2) or __side_empty(state, 1)):
player1_score = sum(state['board'][1:8])
player2_score = sum(state['board'][8:14]) + state['board'][0]
if player2_score > player1_score:
return {
"game_result": "Winner",
"winner_idx": 1
}
elif player1_score > player2_score:
return {
"game_result": "Winner",
"winner_idx": 0
}
else:
return {
"game_result": "Draw"
}
else:
return {
"game_result": "NoWinnerYet"
}
"""
Checks if one of the sides of the mancala board is empty.
Returns [True] if the side is empty, [False] otherwise.
"""
def __side_empty(state, side):
if side == 1:
for i in range(1, 7):
if state['board'][i] != 0:
return False
return True
else:
for i in range(8, 14):
if state['board'][i] != 0:
return False
return True
Game state schema
message State {
// Required field to indicate the player who should be making the next move
// Values = 0 or 1
int32 player_turn_idx = 1;
/*
Array of size 14, indicating the 12 pockets and 2 Mancala. The indices go
counter-counterclockwise where indices 1-7 is player_idx 0 and the remaining
are player_idx 1. Index 7 is player_idx 0's Mancala. Index 0 is player_idx 1's
Mancala. The values of the board indicate how many pieces are in them.
*************************
* 0 13 12 11 10 9 8 *
* 1 2 3 4 5 6 7 *
*************************
*/
repeated int32 board = 4;
}
Action schema
choose_pocket(int index)
Last updated