diff --git a/android/gradle.properties b/android/gradle.properties index 4bb5439f682100f8ef4ba80a557fe4f2f0ab14c2..6bf54a6ed821c19f76d860d4a24e7c85d440b575 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -1,5 +1,5 @@ org.gradle.jvmargs=-Xmx1536M android.useAndroidX=true android.enableJetifier=true -app.versionName=0.0.9 -app.versionCode=9 +app.versionName=0.0.10 +app.versionCode=10 diff --git a/fastlane/metadata/android/en-US/changelogs/10.txt b/fastlane/metadata/android/en-US/changelogs/10.txt new file mode 100644 index 0000000000000000000000000000000000000000..b69d84ed533d496820626e907d6a01f5978264e0 --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/10.txt @@ -0,0 +1 @@ +Add (naive) AI player. diff --git a/fastlane/metadata/android/fr-FR/changelogs/10.txt b/fastlane/metadata/android/fr-FR/changelogs/10.txt new file mode 100644 index 0000000000000000000000000000000000000000..24f44831d45dc0e86c8573ca80cb6891276e941c --- /dev/null +++ b/fastlane/metadata/android/fr-FR/changelogs/10.txt @@ -0,0 +1 @@ +Ajout d'une IA (naîve) comme joueur. diff --git a/lib/config/default_game_settings.dart b/lib/config/default_game_settings.dart index 8ffc2a18876cd93bd812d8be68b8bb64ec98be3b..668711ff2a8451759cdc8c812c92d98a0c105118 100644 --- a/lib/config/default_game_settings.dart +++ b/lib/config/default_game_settings.dart @@ -8,12 +8,18 @@ class DefaultGameSettings { ]; // game mode: available values - static const String gameModeDual = 'dual'; + static const String gameModeHumanVsHuman = 'human-vs-human'; + static const String gameModeHumanVsRobot = 'human-vs-robot'; + static const String gameModeRobotVsHuman = 'robot-vs-human'; + static const String gameModeRobotVsRobot = 'robot-vs-robot'; static const List<String> allowedGameModeValues = [ - gameModeDual, + gameModeHumanVsHuman, + gameModeHumanVsRobot, + gameModeRobotVsHuman, + gameModeRobotVsRobot, ]; // items count: default value - static const String defaultGameModeValue = gameModeDual; + static const String defaultGameModeValue = gameModeHumanVsHuman; // available values from parameter code static List<String> getAvailableValues(String parameterCode) { diff --git a/lib/cubit/game_cubit.dart b/lib/cubit/game_cubit.dart index 0cc2123da83e8389b6a58c0f174d381611ab53f8..77cbf85446e0fd8ba955cb13bfb4558aa971bafc 100644 --- a/lib/cubit/game_cubit.dart +++ b/lib/cubit/game_cubit.dart @@ -7,6 +7,7 @@ import 'package:hydrated_bloc/hydrated_bloc.dart'; import 'package:awale/models/game/game.dart'; import 'package:awale/models/settings/settings_game.dart'; import 'package:awale/models/settings/settings_global.dart'; +import 'package:awale/robot/robot_player.dart'; import 'package:awale/utils/tools.dart'; part 'game_state.dart'; @@ -59,6 +60,8 @@ class GameCubit extends HydratedCubit<GameState> { updateState(newGame); refresh(); + + robotPlay(); } void quitGame() { @@ -80,6 +83,17 @@ class GameCubit extends HydratedCubit<GameState> { void toggleCurrentPlayer() { state.currentGame.currentPlayer = 1 - state.currentGame.currentPlayer; refresh(); + + robotPlay(); + } + + void robotPlay() async { + if (!state.currentGame.isFinished && !state.currentGame.isCurrentPlayerHuman()) { + final int pickedCell = RobotPlayer.pickCell(state.currentGame); + await Future.delayed(const Duration(milliseconds: 500)); + + tapOnCell(pickedCell); + } } void tapOnCell(int cellIndex) async { diff --git a/lib/models/game/game.dart b/lib/models/game/game.dart index bb6ed6ceb097cc1257b92cb91fc8b66dfb8e2b88..269a01d680bd73bcb2ef62f9ef9393029b5ac7b4 100644 --- a/lib/models/game/game.dart +++ b/lib/models/game/game.dart @@ -1,3 +1,4 @@ +import 'package:awale/config/default_game_settings.dart'; import 'package:awale/models/game/board.dart'; import 'package:awale/models/settings/settings_game.dart'; import 'package:awale/models/settings/settings_global.dart'; @@ -137,6 +138,25 @@ class Game { return false; } + bool isPlayerHuman(int playerIndex) { + switch (gameSettings.gameMode) { + case DefaultGameSettings.gameModeHumanVsHuman: + return true; + case DefaultGameSettings.gameModeHumanVsRobot: + return (playerIndex == 0); + case DefaultGameSettings.gameModeRobotVsHuman: + return (playerIndex == 1); + case DefaultGameSettings.gameModeRobotVsRobot: + return false; + default: + } + return true; + } + + bool isCurrentPlayerHuman() { + return isPlayerHuman(currentPlayer); + } + void dump() { printlog(''); printlog('## Current game dump:'); diff --git a/lib/robot/robot_player.dart b/lib/robot/robot_player.dart new file mode 100644 index 0000000000000000000000000000000000000000..b14b50387ef3e96d4f403f11c67ff7d00d59441a --- /dev/null +++ b/lib/robot/robot_player.dart @@ -0,0 +1,20 @@ +import 'package:awale/models/game/game.dart'; + +class RobotPlayer { + static pickCell(Game currentGame) { + List<int> allowedMoves = []; + + for (int cellIndex = 0; cellIndex < currentGame.board.cells.length; cellIndex++) { + if (currentGame.isCurrentPlayerHouse(cellIndex) && + currentGame.isMoveAllowed(cellIndex)) { + allowedMoves.add(cellIndex); + } + } + + allowedMoves.shuffle(); + + final int pickedCellIndex = allowedMoves[0]; + + return pickedCellIndex; + } +} diff --git a/lib/ui/parameters/parameter_painter.dart b/lib/ui/parameters/parameter_painter.dart index 5e70ef5c6c90440fb607b823e52905652dac40c7..1a23f6bae5e9bad44fb896447887f756328c91e1 100644 --- a/lib/ui/parameters/parameter_painter.dart +++ b/lib/ui/parameters/parameter_painter.dart @@ -2,6 +2,7 @@ import 'dart:math'; import 'package:flutter/material.dart'; +import 'package:awale/config/default_game_settings.dart'; import 'package:awale/models/settings/settings_game.dart'; import 'package:awale/models/settings/settings_global.dart'; import 'package:awale/utils/tools.dart'; @@ -40,6 +41,9 @@ class ParameterPainter extends CustomPainter { // content switch (code) { + case DefaultGameSettings.parameterCodeGameMode: + paintGameModeParameterItem(value, canvas, canvasSize); + break; default: printlog('Unknown parameter: $code/$value'); paintUnknownParameterItem(value, canvas, canvasSize); @@ -87,4 +91,63 @@ class ParameterPainter extends CustomPainter { ), ); } + + void paintGameModeParameterItem( + final String value, + final Canvas canvas, + final double size, + ) { + String text = ''; + Color baseColor = Colors.grey; + + switch (value) { + case DefaultGameSettings.gameModeHumanVsHuman: + text = '🧑 🧑'; + baseColor = Colors.green; + break; + case DefaultGameSettings.gameModeHumanVsRobot: + text = '🧑 🤖'; + baseColor = Colors.pink; + break; + case DefaultGameSettings.gameModeRobotVsHuman: + text = '🤖 🧑'; + baseColor = Colors.pink; + break; + case DefaultGameSettings.gameModeRobotVsRobot: + text = '🤖 🤖'; + baseColor = Colors.brown; + break; + default: + } + + final paint = Paint(); + paint.strokeJoin = StrokeJoin.round; + paint.strokeWidth = 3; + + paint.color = baseColor; + paint.style = PaintingStyle.fill; + canvas.drawRect(Rect.fromPoints(const Offset(0, 0), Offset(size, size)), paint); + + final textSpan = TextSpan( + text: text, + style: const TextStyle( + color: Colors.black, + fontSize: 22, + fontWeight: FontWeight.bold, + ), + ); + final textPainter = TextPainter( + text: textSpan, + textDirection: TextDirection.ltr, + textAlign: TextAlign.center, + ); + textPainter.layout(); + textPainter.paint( + canvas, + Offset( + (size - textPainter.width) * 0.5, + (size - textPainter.height) * 0.5, + ), + ); + } } diff --git a/lib/ui/widgets/game/game_player.dart b/lib/ui/widgets/game/game_player.dart index 2806e67be491435ef99bb0026b0d3578b824a1a6..d7d484d3313331bb7de2c2fa9e9c207522f15bbf 100644 --- a/lib/ui/widgets/game/game_player.dart +++ b/lib/ui/widgets/game/game_player.dart @@ -25,8 +25,9 @@ class GamePlayerWidget extends StatelessWidget { final bool isCurrentPlayer = (currentGame.currentPlayer == playerIndex); final int seedsCount = isCurrentPlayer ? currentGame.currentHand : 0; - final Color baseColor = - isCurrentPlayer ? Colors.pink : Theme.of(context).colorScheme.surface; + final Color baseColor = isCurrentPlayer + ? (currentGame.isPlayerHuman(playerIndex) ? Colors.pink : Colors.grey) + : Theme.of(context).colorScheme.surface; return Container( margin: const EdgeInsets.all(2), diff --git a/pubspec.yaml b/pubspec.yaml index bf3eaabff1b368f5e00647ac13f7c523c895bc48..656ed76fae80c2d040f1d673b2e28aaa6b3a6963 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -3,7 +3,7 @@ description: Awale game publish_to: "none" -version: 0.0.9+9 +version: 0.0.10+10 environment: sdk: "^3.0.0"