Skip to content

Commit 12f9d5e

Browse files
committed
Add offline computer variant support
Except for crazyhouse in practice mode for now.
1 parent 8ca4163 commit 12f9d5e

File tree

3 files changed

+75
-16
lines changed

3 files changed

+75
-16
lines changed

lib/src/model/offline_computer/offline_computer_game_controller.dart

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
1010
import 'package:freezed_annotation/freezed_annotation.dart';
1111
import 'package:lichess_mobile/src/model/analysis/analysis_controller.dart';
1212
import 'package:lichess_mobile/src/model/common/chess.dart';
13+
import 'package:lichess_mobile/src/model/common/chess960.dart';
1314
import 'package:lichess_mobile/src/model/common/eval.dart';
1415
import 'package:lichess_mobile/src/model/common/id.dart';
1516
import 'package:lichess_mobile/src/model/common/perf.dart';
@@ -112,13 +113,15 @@ class OfflineComputerGameController extends Notifier<OfflineComputerGameState> {
112113
required Side playerSide,
113114
required bool casual,
114115
required bool practiceMode,
116+
Variant variant = Variant.standard,
115117
String? initialFen,
116118
}) {
117119
state = OfflineComputerGameState.initial(
118120
stockfishLevel: stockfishLevel,
119121
playerSide: playerSide,
120122
casual: casual,
121123
practiceMode: practiceMode,
124+
variant: variant,
122125
initialFen: initialFen,
123126
);
124127

@@ -383,7 +386,7 @@ class OfflineComputerGameController extends Notifier<OfflineComputerGameState> {
383386
return EvalWork(
384387
id: state.game.id,
385388
stockfishFlavor: _kComputerStockfishFlavor,
386-
variant: Variant.standard,
389+
variant: state.game.meta.variant,
387390
threads: numberOfCoresForEvaluation,
388391
hashSize: ref.read(evaluationServiceProvider).maxMemory,
389392
searchTime: _kMoveEvalMaxSearchTime,
@@ -640,7 +643,7 @@ class OfflineComputerGameController extends Notifier<OfflineComputerGameState> {
640643

641644
final work = MoveWork(
642645
id: state.game.id,
643-
variant: Variant.standard,
646+
variant: state.game.meta.variant,
644647
hashSize: evaluationService.maxMemory,
645648
initialPosition: state.game.initialPosition,
646649
steps: steps,
@@ -772,7 +775,7 @@ class OfflineComputerGameController extends Notifier<OfflineComputerGameState> {
772775
final work = EvalWork(
773776
id: state.game.id,
774777
stockfishFlavor: _kComputerStockfishFlavor,
775-
variant: Variant.standard,
778+
variant: state.game.meta.variant,
776779
threads: numberOfCoresForEvaluation,
777780
hashSize: evaluationService.maxMemory,
778781
searchTime: _kHintsMaxSearchTime,
@@ -868,26 +871,42 @@ sealed class OfflineComputerGameState with _$OfflineComputerGameState {
868871
factory OfflineComputerGameState.initial({
869872
required StockfishLevel stockfishLevel,
870873
required Side playerSide,
874+
Variant variant = Variant.standard,
871875
bool casual = true,
872876
bool practiceMode = false,
873877
String? initialFen,
874878
}) {
875-
final position = initialFen != null
876-
? Chess.fromSetup(Setup.parseFen(initialFen))
877-
: Chess.initial;
879+
final Position position;
880+
final Variant effectiveVariant;
881+
final String? effectiveInitialFen;
882+
883+
if (initialFen != null) {
884+
position = Chess.fromSetup(Setup.parseFen(initialFen));
885+
effectiveVariant = Variant.fromPosition;
886+
effectiveInitialFen = initialFen;
887+
} else if (variant == Variant.chess960) {
888+
position = randomChess960Position();
889+
effectiveVariant = Variant.chess960;
890+
effectiveInitialFen = position.fen;
891+
} else {
892+
position = variant.initialPosition;
893+
effectiveVariant = variant;
894+
effectiveInitialFen = null;
895+
}
896+
878897
final sessionId = StringId('ocg_${_random.nextInt(1 << 32).toRadixString(16).padLeft(8, '0')}');
879898
return OfflineComputerGameState(
880899
game: OfflineComputerGame(
881900
id: sessionId,
882901
steps: [GameStep(position: position)].lock,
883902
status: GameStatus.started,
884-
initialFen: initialFen,
903+
initialFen: effectiveInitialFen,
885904
meta: GameMeta(
886905
createdAt: DateTime.now(),
887906
rated: false,
888-
variant: initialFen != null ? Variant.fromPosition : Variant.standard,
907+
variant: effectiveVariant,
889908
speed: Speed.classical,
890-
perf: Perf.classical,
909+
perf: Perf.fromVariantAndSpeed(effectiveVariant, Speed.classical),
891910
),
892911
playerSide: playerSide,
893912
stockfishLevel: stockfishLevel,

lib/src/model/offline_computer/offline_computer_game_preferences.dart

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import 'package:dartchess/dartchess.dart';
22
import 'package:flutter_riverpod/flutter_riverpod.dart';
33
import 'package:freezed_annotation/freezed_annotation.dart';
4+
import 'package:lichess_mobile/src/model/common/chess.dart';
45
import 'package:lichess_mobile/src/model/game/offline_computer_game.dart';
56
import 'package:lichess_mobile/src/model/settings/preferences_storage.dart';
67

@@ -39,6 +40,10 @@ class OfflineComputerGamePreferences extends Notifier<OfflineComputerGamePrefs>
3940
return save(state.copyWith(sideChoice: sideChoice));
4041
}
4142

43+
Future<void> setVariant(Variant variant) {
44+
return save(state.copyWith(variant: variant));
45+
}
46+
4247
Future<void> setCasual(bool casual) {
4348
return save(state.copyWith(casual: casual));
4449
}
@@ -82,6 +87,7 @@ sealed class OfflineComputerGamePrefs with _$OfflineComputerGamePrefs implements
8287
const factory OfflineComputerGamePrefs({
8388
required StockfishLevel stockfishLevel,
8489
required SideChoice sideChoice,
90+
@Default(Variant.standard) Variant variant,
8591
@Default(true) bool casual,
8692
@Default(false) bool practiceMode,
8793
@Default(false) bool hideBestMove,
@@ -91,6 +97,7 @@ sealed class OfflineComputerGamePrefs with _$OfflineComputerGamePrefs implements
9197
static const defaults = OfflineComputerGamePrefs(
9298
stockfishLevel: StockfishLevel.defaultLevel,
9399
sideChoice: SideChoice.random,
100+
variant: Variant.standard,
94101
casual: true,
95102
practiceMode: false,
96103
hideBestMove: false,

lib/src/view/offline_computer/offline_computer_game_screen.dart

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@ class _BodyState extends ConsumerState<_Body> {
244244
lastMove: gameState.lastMove,
245245
shapes: _buildBoardShapes(gameState, boardColorScheme),
246246
boardParams: GameBoardParams.interactive(
247-
variant: Variant.standard,
247+
variant: gameState.game.meta.variant,
248248
position: gameState.currentPosition,
249249
playerSide: gameState.game.finished
250250
? PlayerSide.none
@@ -376,7 +376,7 @@ class _BottomBar extends ConsumerWidget {
376376
orientation: gameState.game.playerSide,
377377
pgn: gameState.game.makePgn(),
378378
isComputerAnalysisAllowed: true,
379-
variant: Variant.standard,
379+
variant: gameState.game.meta.variant,
380380
),
381381
),
382382
),
@@ -703,6 +703,7 @@ class _NewGameSheet extends ConsumerStatefulWidget {
703703
class _NewGameSheetState extends ConsumerState<_NewGameSheet> {
704704
late StockfishLevel _selectedLevel;
705705
late SideChoice _selectedSideChoice;
706+
late Variant _selectedVariant;
706707
late bool _casual;
707708
late bool _practiceMode;
708709

@@ -718,6 +719,7 @@ class _NewGameSheetState extends ConsumerState<_NewGameSheet> {
718719
final prefs = ref.read(offlineComputerGamePreferencesProvider);
719720
_selectedLevel = prefs.stockfishLevel;
720721
_selectedSideChoice = prefs.sideChoice;
722+
_selectedVariant = prefs.variant;
721723
_casual = prefs.casual;
722724
_practiceMode = prefs.practiceMode;
723725
}
@@ -798,14 +800,44 @@ class _NewGameSheetState extends ConsumerState<_NewGameSheet> {
798800
);
799801
},
800802
),
803+
if (widget.initialFen == null)
804+
SettingsListTile(
805+
settingsLabel: Text(context.l10n.variant),
806+
settingsValue: _selectedVariant.label,
807+
onTap: () {
808+
showChoicePicker(
809+
context,
810+
choices: playSupportedVariants
811+
.where((v) => v != Variant.fromPosition)
812+
.toList(),
813+
selectedItem: _selectedVariant,
814+
labelBuilder: (Variant variant) => Text(variant.label),
815+
onSelectedItemChanged: (Variant variant) {
816+
setState(() {
817+
_selectedVariant = variant;
818+
if (variant == Variant.crazyhouse) {
819+
_practiceMode = false;
820+
}
821+
});
822+
ref
823+
.read(offlineComputerGamePreferencesProvider.notifier)
824+
.setVariant(variant);
825+
},
826+
);
827+
},
828+
),
801829
SwitchSettingTile(
802830
title: const Text('Practice mode'),
803831
subtitle: const Text('Get feedback on your moves'),
804832
value: _practiceMode,
805-
onChanged: (value) {
806-
setState(() => _practiceMode = value);
807-
ref.read(offlineComputerGamePreferencesProvider.notifier).setPracticeMode(value);
808-
},
833+
onChanged: _selectedVariant == Variant.crazyhouse
834+
? null
835+
: (value) {
836+
setState(() => _practiceMode = value);
837+
ref
838+
.read(offlineComputerGamePreferencesProvider.notifier)
839+
.setPracticeMode(value);
840+
},
809841
),
810842
SwitchSettingTile(
811843
title: Text(context.l10n.casual),
@@ -832,6 +864,7 @@ class _NewGameSheetState extends ConsumerState<_NewGameSheet> {
832864
playerSide: side,
833865
casual: _practiceMode || _casual,
834866
practiceMode: _practiceMode,
867+
variant: _selectedVariant,
835868
initialFen: widget.initialFen,
836869
);
837870
Navigator.pop(context);
@@ -926,7 +959,7 @@ class OfflineComputerGameResultDialog extends StatelessWidget {
926959
orientation: game.playerSide,
927960
pgn: game.makePgn(),
928961
isComputerAnalysisAllowed: true,
929-
variant: Variant.standard,
962+
variant: game.meta.variant,
930963
),
931964
),
932965
);

0 commit comments

Comments
 (0)