Skip to content

Commit 30c51d7

Browse files
committed
Only allow "Random" color selection for online public seeks
This change is due to lichess PR# 15969 deprecating the ability to choose your color on public seeks.
1 parent ab473d1 commit 30c51d7

File tree

9 files changed

+49
-31
lines changed

9 files changed

+49
-31
lines changed

src/cli_chess/core/game/game_model_base.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@
1010

1111

1212
class GameModelBase:
13-
def __init__(self, orientation: Color = WHITE, variant="standard", fen=""):
13+
def __init__(self, orientation: Color = WHITE, variant="standard", fen="", side_confirmed=True):
1414
self.game_metadata = GameMetadata()
1515

16-
self.board_model = BoardModel(orientation, variant, fen)
16+
self.board_model = BoardModel(orientation, variant, fen, side_confirmed)
1717
self.move_list_model = MoveListModel(self.board_model)
1818
self.material_diff_model = MaterialDifferenceModel(self.board_model)
1919

@@ -53,11 +53,11 @@ def _notify_game_model_updated(self, *args, **kwargs) -> None:
5353

5454

5555
class PlayableGameModelBase(GameModelBase, ABC):
56-
def __init__(self, play_as_color: str, variant="standard", fen=""):
56+
def __init__(self, play_as_color: str, variant="standard", fen="", side_confirmed=True):
5757
self.my_color = self._get_side_to_play_as(play_as_color)
5858
self.game_in_progress = False
5959

60-
super().__init__(orientation=self.my_color, variant=variant, fen=fen)
60+
super().__init__(orientation=self.my_color, variant=variant, fen=fen, side_confirmed=side_confirmed)
6161
self.premove_model = PremoveModel(self.board_model)
6262
self._assoc_models = self._assoc_models + [self.premove_model]
6363

src/cli_chess/core/game/game_options.py

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -105,31 +105,39 @@ def __init__(self):
105105
time_control_options_dict.update(additional_time_controls)
106106

107107

108-
class OnlineGameOptions(BaseGameOptions):
109-
"""Game Options class with defined options permitted for board API use"""
108+
class OnlinePublicGameOptions(BaseGameOptions):
109+
"""Game Options class with defined options permitted for public seek board API use"""
110110
def __init__(self):
111111
super().__init__()
112112
self.dict_map = {
113113
GameOption.VARIANT: BaseGameOptions.variant_options_dict,
114-
GameOption.TIME_CONTROL: self.time_control_options_dict,
115-
GameOption.COMPUTER_SKILL_LEVEL: BaseGameOptions.skill_level_options_dict,
114+
GameOption.TIME_CONTROL: BaseGameOptions.time_control_options_dict,
116115
GameOption.RATED: self.rated_options_dict,
117-
GameOption.RATING_RANGE: None,
118-
GameOption.COLOR: BaseGameOptions.color_options,
116+
GameOption.COLOR: self.color_options
119117
}
120118

119+
color_options = {
120+
"Random": "random" # Online public seeks must be random (lila PR# 15969)
121+
}
122+
121123
rated_options_dict = {
122124
"No": False,
123125
"Yes": True
124126
}
125127

126128

127-
class OnlineDirectChallengesGameOptions(OnlineGameOptions):
129+
class OnlineDirectChallengesGameOptions(BaseGameOptions):
128130
"""Game Options class with defined options for direct challenges.
129-
Brings in the additional permitted time controls.
131+
Brings in the additional side to play as and permitted time controls options.
130132
"""
131133
def __init__(self):
132134
super().__init__()
135+
self.dict_map = {
136+
GameOption.VARIANT: BaseGameOptions.variant_options_dict,
137+
GameOption.TIME_CONTROL: self.time_control_options_dict,
138+
GameOption.COMPUTER_SKILL_LEVEL: BaseGameOptions.skill_level_options_dict,
139+
GameOption.COLOR: BaseGameOptions.color_options,
140+
}
133141

134142
time_control_options_dict = dict(BaseGameOptions.time_control_options_dict)
135143
additional_time_controls = {

src/cli_chess/core/game/offline_game/offline_game_model.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,6 @@ def _update_game_metadata(self, *args, data: Optional[Dict] = None, **kwargs) ->
8181
return
8282
try:
8383
if EventTopics.GAME_PARAMS in args:
84-
self.game_metadata.my_color = self.my_color
8584
self.game_metadata.variant = data[GameOption.VARIANT]
8685
self.game_metadata.players[self.my_color].name = player_info_config.get_value(player_info_config.Keys.OFFLINE_PLAYER_NAME) # noqa: E501
8786

src/cli_chess/core/game/online_game/online_game_model.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ class OnlineGameModel(PlayableGameModelBase):
1919
Games not owned by this account must directly use the base model instead.
2020
"""
2121
def __init__(self, game_parameters: dict, is_vs_ai: bool):
22-
super().__init__(play_as_color=game_parameters[GameOption.COLOR], variant=game_parameters[GameOption.VARIANT], fen=None)
22+
super().__init__(play_as_color=game_parameters[GameOption.COLOR], variant=game_parameters[GameOption.VARIANT], fen=None, side_confirmed=is_vs_ai) # noqa: E501
2323
self.vs_ai = is_vs_ai
2424
self.playing_game_id = None
2525
self.searching = False
@@ -48,15 +48,15 @@ def create_game(self) -> None:
4848
self.api_client.challenges.create_ai(level=self.game_metadata.players[not self.my_color].ai_level,
4949
clock_limit=self.game_metadata.clocks[WHITE].time * 60, # challenges need time in seconds
5050
clock_increment=self.game_metadata.clocks[WHITE].increment,
51-
color=COLOR_NAMES[self.game_metadata.my_color],
51+
color=COLOR_NAMES[self.my_color],
5252
variant=self.game_metadata.variant)
5353
else: # Find a random opponent
5454
payload = {
5555
"rated": str(self.game_metadata.rated).lower(),
5656
"time": self.game_metadata.clocks[WHITE].time,
5757
"increment": self.game_metadata.clocks[WHITE].increment,
5858
"variant": self.game_metadata.variant,
59-
"color": COLOR_NAMES[self.game_metadata.my_color],
59+
"color": "random", # lila PR# 15969
6060
"ratingRange": "",
6161
}
6262
for _ in self.api_client.board._r.post("/api/board/seek", data=payload, fmt=TEXT, stream=True):
@@ -246,7 +246,6 @@ def _update_game_metadata(self, *args, sender: Optional[EventSender] = None, dat
246246
try:
247247
if sender is EventSender.LOCAL:
248248
if EventTopics.GAME_PARAMS in args: # This is the data that came from the menu selections
249-
self.game_metadata.my_color = self.my_color
250249
self.game_metadata.variant = data.get(GameOption.VARIANT)
251250
self.game_metadata.rated = data.get(GameOption.RATED, False)
252251
self.game_metadata.players[not self.my_color].ai_level = data.get(GameOption.COMPUTER_SKILL_LEVEL) if self.vs_ai else None
@@ -259,8 +258,9 @@ def _update_game_metadata(self, *args, sender: Optional[EventSender] = None, dat
259258
if EventTopics.GAME_START in args:
260259
self.game_metadata.reset()
261260
self.game_metadata.game_id = data.get('gameId')
262-
self.game_metadata.my_color = self.my_color
263261
self.game_metadata.rated = data.get('rated')
262+
# Since lila PR# 15969, color seeks can only be random. This resets `my_color` to the color received
263+
self.my_color = Color(COLOR_NAMES.index(data.get('color')))
264264
self.game_metadata.variant = data.get('variant', {}).get('name')
265265
self.game_metadata.speed = data['speed']
266266

src/cli_chess/menus/tv_channel_menu/tv_channel_menu_model.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from cli_chess.menus import MenuModel, MenuOption, MenuCategory
2-
from cli_chess.core.game.game_options import OnlineGameOptions
2+
from cli_chess.core.game.game_options import OnlinePublicGameOptions
33
from types import MappingProxyType
44
from enum import Enum
55

@@ -44,7 +44,7 @@ class TVChannelMenuOptions(Enum):
4444
@property
4545
def variant(self) -> str:
4646
"""Return the chess variant related to the enum"""
47-
variant = OnlineGameOptions.variant_options_dict.get(self.value)
47+
variant = OnlinePublicGameOptions.variant_options_dict.get(self.value)
4848
if not variant:
4949
variant = "standard"
5050
return variant

src/cli_chess/menus/versus_menus/versus_menu_models.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from cli_chess.menus import MultiValueMenuModel, MultiValueMenuOption, MenuCategory
2-
from cli_chess.core.game.game_options import GameOption, OfflineGameOptions, OnlineGameOptions, OnlineDirectChallengesGameOptions
2+
from cli_chess.core.game.game_options import GameOption, OfflineGameOptions, OnlinePublicGameOptions, OnlineDirectChallengesGameOptions
33

44

55
class VersusMenuModel(MultiValueMenuModel):
@@ -63,9 +63,9 @@ def __init__(self):
6363
def _create_menu() -> MenuCategory:
6464
"""Create the online menu options"""
6565
menu_options = [
66-
MultiValueMenuOption(GameOption.VARIANT, "Choose the variant to play", [option for option in OnlineGameOptions.variant_options_dict]), # noqa: E501
67-
MultiValueMenuOption(GameOption.TIME_CONTROL, "Choose the time control", [option for option in OnlineGameOptions.time_control_options_dict]), # noqa: E501
68-
MultiValueMenuOption(GameOption.RATED, "Choose if you'd like to play a casual or rated game", [option for option in OnlineGameOptions.rated_options_dict]), # noqa: E501
69-
MultiValueMenuOption(GameOption.COLOR, "Choose the side you would like to play as", [option for option in OnlineGameOptions.color_options]), # noqa: E501
66+
MultiValueMenuOption(GameOption.VARIANT, "Choose the variant to play", [option for option in OnlinePublicGameOptions.variant_options_dict]), # noqa: E501
67+
MultiValueMenuOption(GameOption.TIME_CONTROL, "Choose the time control", [option for option in OnlinePublicGameOptions.time_control_options_dict]), # noqa: E501
68+
MultiValueMenuOption(GameOption.RATED, "Choose if you'd like to play a casual or rated game", [option for option in OnlinePublicGameOptions.rated_options_dict]), # noqa: E501
69+
MultiValueMenuOption(GameOption.COLOR, "The side you play for an online public game is determined by Lichess", [option for option in OnlinePublicGameOptions.color_options]), # noqa: E501
7070
]
7171
return MenuCategory("Play Online vs Random Opponent", menu_options)

src/cli_chess/menus/versus_menus/versus_menu_presenters.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from __future__ import annotations
22
from cli_chess.menus.versus_menus import VersusMenuView
33
from cli_chess.menus import MultiValueMenuPresenter
4-
from cli_chess.core.game.game_options import GameOption, BaseGameOptions, OfflineGameOptions, OnlineGameOptions, OnlineDirectChallengesGameOptions
4+
from cli_chess.core.game.game_options import GameOption, BaseGameOptions, OfflineGameOptions, OnlinePublicGameOptions, OnlineDirectChallengesGameOptions # noqa: E501
55
from cli_chess.core.game import start_online_game, start_offline_game
66
from cli_chess.utils import log
77
from abc import ABC, abstractmethod
@@ -78,7 +78,7 @@ def value_cycled_handler(self, selected_option: int):
7878
def handle_start_game(self) -> None:
7979
"""Starts the game using the currently selected menu values"""
8080
try:
81-
game_parameters = super()._create_dict_of_selected_values(OnlineGameOptions if not self.is_vs_ai else OnlineDirectChallengesGameOptions)
81+
game_parameters = super()._create_dict_of_selected_values(OnlinePublicGameOptions if not self.is_vs_ai else OnlineDirectChallengesGameOptions) # noqa: E501
8282
start_online_game(game_parameters, is_vs_ai=self.is_vs_ai)
8383
except Exception as e:
8484
log.error(e)

src/cli_chess/modules/board/board_model.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,11 @@
77

88

99
class BoardModel:
10-
def __init__(self, orientation: chess.Color = chess.WHITE, variant="standard", fen="") -> None:
10+
def __init__(self, orientation: chess.Color = chess.WHITE, variant="standard", fen="", side_confirmed=True) -> None:
1111
self.board = self._initialize_board(variant, fen)
1212
self.initial_fen = self.board.fen()
1313
self.orientation = chess.WHITE if variant.lower() == "racingkings" else orientation
14+
self.side_confirmed = side_confirmed # flag to indicate if the users color is fully confirmed (e.g. online)
1415
self.highlight_move = chess.Move.null()
1516
self.premove_highlight = chess.Move.null()
1617
self._game_over_result: Optional[chess.Outcome] = None
@@ -41,16 +42,18 @@ def _initialize_board(variant: str, fen: str):
4142
else:
4243
return chess.variant.find_variant(variant)()
4344

44-
def reinitialize_board(self, variant: str, orientation: chess.Color, fen: str = "", uci_last_move=""):
45+
def reinitialize_board(self, variant: str, orientation: chess.Color, fen: str = "", uci_last_move="", is_side_confirmed=True):
4546
"""Reinitializes the existing board object to the new variant/fen.
4647
An optional uci_last_move can be passed in to highlight the last known move
48+
Sets the "side_confirmed" to the passed in "is_side_confirmed" value. Defaults to true.
4749
"""
4850
try:
4951
self.board = self._initialize_board(variant, fen)
5052
self.initial_fen = self.board.fen()
5153
self.set_board_orientation(chess.WHITE if variant.lower() == "racingkings" else orientation, notify=False)
5254
self.highlight_move = chess.Move.from_uci(uci_last_move) if uci_last_move else chess.Move.null()
5355
self._game_over_result = None
56+
self.side_confirmed = is_side_confirmed
5457

5558
self._log_init_info()
5659
self._notify_board_model_updated(EventTopics.GAME_START)
@@ -280,6 +283,14 @@ def is_white_orientation(self) -> bool:
280283
"""Returns True if the board orientation is set as white"""
281284
return self.orientation is chess.WHITE
282285

286+
def is_side_confirmed(self) -> bool:
287+
"""Returns true if the users playing color is confirmed. This should always
288+
be true once a game starts and an opponent is found. In Lichess online games
289+
versus a random opponent, we need to wait until Lichess responds with our
290+
starting color in order to know what color we start with
291+
"""
292+
return self.side_confirmed
293+
283294
def set_board_position(self, fen: str, uci_last_move=""):
284295
"""Sets up the board using the passed in FEN. In addition, optionally the
285296
board orientation and last move can also be passed in. The last move must be

src/cli_chess/modules/board/board_presenter.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ def get_file_labels(self) -> str:
7070
is disabled in the configuration.
7171
"""
7272
file_labels = ""
73-
show_board_coordinates = self.game_config_values[game_config.Keys.SHOW_BOARD_COORDINATES]
73+
show_board_coordinates = self.game_config_values[game_config.Keys.SHOW_BOARD_COORDINATES] and self.model.is_side_confirmed()
7474

7575
if show_board_coordinates:
7676
file_labels = self.model.get_file_labels()
@@ -83,7 +83,7 @@ def get_rank_label(self, square: chess.Square) -> str:
8383
"""
8484
rank_label = ""
8585
rank_index = self.model.get_square_rank_index(square)
86-
show_board_coordinates = self.game_config_values[game_config.Keys.SHOW_BOARD_COORDINATES]
86+
show_board_coordinates = self.game_config_values[game_config.Keys.SHOW_BOARD_COORDINATES] and self.model.is_side_confirmed()
8787

8888
if self.is_square_start_of_rank(square) and show_board_coordinates:
8989
rank_label = self.model.get_rank_label(rank_index)

0 commit comments

Comments
 (0)