Skip to content
Snippets Groups Projects
Commit 2976e3fe authored by Benoît Harrault's avatar Benoît Harrault
Browse files

Add "naive" AI player

parent 9ba2cdc3
No related branches found
No related tags found
1 merge request!10Resolve "Add basic AI"
Pipeline #5966 passed
org.gradle.jvmargs=-Xmx1536M org.gradle.jvmargs=-Xmx1536M
android.useAndroidX=true android.useAndroidX=true
android.enableJetifier=true android.enableJetifier=true
app.versionName=0.0.9 app.versionName=0.0.10
app.versionCode=9 app.versionCode=10
Add (naive) AI player.
Ajout d'une IA (naîve) comme joueur.
...@@ -8,12 +8,18 @@ class DefaultGameSettings { ...@@ -8,12 +8,18 @@ class DefaultGameSettings {
]; ];
// game mode: available values // 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 = [ static const List<String> allowedGameModeValues = [
gameModeDual, gameModeHumanVsHuman,
gameModeHumanVsRobot,
gameModeRobotVsHuman,
gameModeRobotVsRobot,
]; ];
// items count: default value // items count: default value
static const String defaultGameModeValue = gameModeDual; static const String defaultGameModeValue = gameModeHumanVsHuman;
// available values from parameter code // available values from parameter code
static List<String> getAvailableValues(String parameterCode) { static List<String> getAvailableValues(String parameterCode) {
......
...@@ -7,6 +7,7 @@ import 'package:hydrated_bloc/hydrated_bloc.dart'; ...@@ -7,6 +7,7 @@ import 'package:hydrated_bloc/hydrated_bloc.dart';
import 'package:awale/models/game/game.dart'; import 'package:awale/models/game/game.dart';
import 'package:awale/models/settings/settings_game.dart'; import 'package:awale/models/settings/settings_game.dart';
import 'package:awale/models/settings/settings_global.dart'; import 'package:awale/models/settings/settings_global.dart';
import 'package:awale/robot/robot_player.dart';
import 'package:awale/utils/tools.dart'; import 'package:awale/utils/tools.dart';
part 'game_state.dart'; part 'game_state.dart';
...@@ -59,6 +60,8 @@ class GameCubit extends HydratedCubit<GameState> { ...@@ -59,6 +60,8 @@ class GameCubit extends HydratedCubit<GameState> {
updateState(newGame); updateState(newGame);
refresh(); refresh();
robotPlay();
} }
void quitGame() { void quitGame() {
...@@ -80,6 +83,17 @@ class GameCubit extends HydratedCubit<GameState> { ...@@ -80,6 +83,17 @@ class GameCubit extends HydratedCubit<GameState> {
void toggleCurrentPlayer() { void toggleCurrentPlayer() {
state.currentGame.currentPlayer = 1 - state.currentGame.currentPlayer; state.currentGame.currentPlayer = 1 - state.currentGame.currentPlayer;
refresh(); 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 { void tapOnCell(int cellIndex) async {
......
import 'package:awale/config/default_game_settings.dart';
import 'package:awale/models/game/board.dart'; import 'package:awale/models/game/board.dart';
import 'package:awale/models/settings/settings_game.dart'; import 'package:awale/models/settings/settings_game.dart';
import 'package:awale/models/settings/settings_global.dart'; import 'package:awale/models/settings/settings_global.dart';
...@@ -137,6 +138,25 @@ class Game { ...@@ -137,6 +138,25 @@ class Game {
return false; 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() { void dump() {
printlog(''); printlog('');
printlog('## Current game dump:'); printlog('## Current game dump:');
......
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;
}
}
...@@ -2,6 +2,7 @@ import 'dart:math'; ...@@ -2,6 +2,7 @@ import 'dart:math';
import 'package:flutter/material.dart'; 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_game.dart';
import 'package:awale/models/settings/settings_global.dart'; import 'package:awale/models/settings/settings_global.dart';
import 'package:awale/utils/tools.dart'; import 'package:awale/utils/tools.dart';
...@@ -40,6 +41,9 @@ class ParameterPainter extends CustomPainter { ...@@ -40,6 +41,9 @@ class ParameterPainter extends CustomPainter {
// content // content
switch (code) { switch (code) {
case DefaultGameSettings.parameterCodeGameMode:
paintGameModeParameterItem(value, canvas, canvasSize);
break;
default: default:
printlog('Unknown parameter: $code/$value'); printlog('Unknown parameter: $code/$value');
paintUnknownParameterItem(value, canvas, canvasSize); paintUnknownParameterItem(value, canvas, canvasSize);
...@@ -87,4 +91,63 @@ class ParameterPainter extends CustomPainter { ...@@ -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,
),
);
}
} }
...@@ -25,8 +25,9 @@ class GamePlayerWidget extends StatelessWidget { ...@@ -25,8 +25,9 @@ class GamePlayerWidget extends StatelessWidget {
final bool isCurrentPlayer = (currentGame.currentPlayer == playerIndex); final bool isCurrentPlayer = (currentGame.currentPlayer == playerIndex);
final int seedsCount = isCurrentPlayer ? currentGame.currentHand : 0; final int seedsCount = isCurrentPlayer ? currentGame.currentHand : 0;
final Color baseColor = final Color baseColor = isCurrentPlayer
isCurrentPlayer ? Colors.pink : Theme.of(context).colorScheme.surface; ? (currentGame.isPlayerHuman(playerIndex) ? Colors.pink : Colors.grey)
: Theme.of(context).colorScheme.surface;
return Container( return Container(
margin: const EdgeInsets.all(2), margin: const EdgeInsets.all(2),
......
...@@ -3,7 +3,7 @@ description: Awale game ...@@ -3,7 +3,7 @@ description: Awale game
publish_to: "none" publish_to: "none"
version: 0.0.9+9 version: 0.0.10+10
environment: environment:
sdk: "^3.0.0" sdk: "^3.0.0"
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment