Botpot
Visit our website
  • Fundamentals
    • Botpot overview
    • Get action
      • Get action: game state
      • Get action: API object
      • Get action: action object
    • Specialized game concepts
      • Get action: ref data
      • Game settings
    • Botpot architecture
  • Games
    • Creating your first bot
    • Understanding game logic
    • Explore game documentations
      • Tic-Tac-Toe
      • Quoridor
      • Connect Four
      • Battleship
      • Virus War
      • Dots and Boxes
      • Hex
      • Reversi
      • Gomoku
      • Mancala
      • Uno
      • Big 2
      • Snake & Tetris
      • Checker
      • Generals
      • Blokus
      • Wordle
      • Chinese Checker
Powered by GitBook
On this page
  • Game logic
  • Game state schema
  • Action schema

Was this helpful?

  1. Games
  2. Explore game documentations

Chinese Checker

Game logic

Game Logic code
def init_game(game_settings):
    state = {
        "player_turn_idx": 0,
        "board": [[-1]*9 for i in range(9)],
        "players": [[None]*10, [None]*10],
        "last_jumped": None,
        "turn": 0
    }
    count = 0
    for i in range(4):
        for j in range(i+1):
            _set_piece(state, 0, count, 3 - i, j)
            _set_piece(state, 1, count, 5 + i, 8 - j)
            count += 1
    return state

def move(state, piece_idx, x, y):
    if not _within_bound(x, y):
        raise InvalidActionError("Coordinte out of bound. Should be between 0 and 8.")
    if piece_idx < 0 or piece_idx >= 10:
        raise InvalidActionError("piece_idx out of bound. Should be between 0 and 9.")
    board = state['board']
    if board[x][y] != -1:
        raise InvalidActionError("There is already a piece at this target coordinate.")
    player_turn_idx = state['player_turn_idx']
    start = state['players'][player_turn_idx][piece_idx]
    start_x = start['x']
    start_y = start['y']

    if _is_adjacent(start_x, start_y, x, y):
        if state['last_jumped'] is not None:
            raise InvalidActionError("This piece must be used to jump over another piece.")
        board[start_x][start_y] = -1
        _set_piece(state, player_turn_idx, piece_idx, x, y)
        state['player_turn_idx'] = (player_turn_idx + 1)%2
        state['turn'] += 1
        return state
    skipped = _is_skip_adjacent(start_x, start_y, x, y)
    if skipped and board[skipped[0]][skipped[1]] != -1:
        if state['last_jumped'] is not None:
            last_jumped = state['last_jumped']
            if last_jumped['piece_idx'] != piece_idx:
                raise InvalidActionError(f"Must use piece {piece_idx} to jump or make a done_move.")
            if last_jumped['last_x'] == x and last_jumped['last_y'] == y:
                raise InvalidActionError(f"Cannot jump back to a previous location.")
        state['board'][start_x][start_y] = -1
        _set_piece(state, player_turn_idx, piece_idx, x, y)
        state['last_jumped'] = {
            'piece_idx': piece_idx,
            'last_x': start_x,
            'last_y': start_y
        }
        return state
    raise InvalidActionError("Cannot move this piece to the target position.")

def done_move(state):
    if state['last_jumped'] is None:
        raise InvalidActionError(f"Cannot make a done_move when you haven't jumped previously.")
    state['player_turn_idx'] = (state['player_turn_idx'] + 1)%2
    state['last_jumped'] = None
    state['turn'] += 1
    return state

def get_game_result(state):
    board = state['board']
    count_player_1 = 0
    count_player_2 = 0
    for i in range(4):
        for j in range(i+1):
            if board[3-i][j] == 1:
                count_player_2 += 1
            if board[5+i][8-j] == 0:
                count_player_1 += 1
    if count_player_1 == 10:
        return {
            "game_result": "Winner",
            "winner_idx": 0
        }
    elif count_player_2 == 10:
        return {
            "game_result": "Winner",
            "winner_idx": 1
        }
    if state['turn'] >= 300:
        if count_player_1 == 0 and count_player_2 == 0:
            return {
                "game_result": "Draw",
            }
        return {
            "game_result": "Winner",
            "winner_idx": 0 if count_player_1 > count_player_2 else 1
        }
    return {
        "game_result": "NoWinnerYet",
    }


def _within_bound(x, y):
    if x < 0 or y < 0 or x >= 9 or y >= 9:
        return False
    return True

def _set_piece(state, player_idx, piece_idx, x, y):
    state["board"][x][y] = player_idx
    state["players"][player_idx][piece_idx] = {
        "x": x,
        "y": y
    }

def _is_adjacent(start_x, start_y, target_x, target_y):
    directions = [(0, 1), (0, -1), (1, 0), (-1, 0), (1, -1), (-1, 1)]
    for dir_x, dir_y in directions:
        if target_x - start_x == dir_x and target_y - start_y == dir_y:
            return True
    return False

def _is_skip_adjacent(start_x, start_y, target_x, target_y):
    directions = [(0, 1), (0, -1), (1, 0), (-1, 0), (1, -1), (-1, 1)]
    for dir_x, dir_y in directions:
        if target_x - start_x == dir_x*2 and target_y - start_y == dir_y*2:
            return (start_x + dir_x, start_y + dir_y)
    return None

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;

  repeated int32 board = 2;
}

Action schema

move(int piece_idx, int x, int y)
done_move()

Last updated 1 year ago

Was this helpful?

Start building now