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
android.useAndroidX=true
android.enableJetifier=true
app.versionName=0.0.9
app.versionCode=9
app.versionName=0.0.10
app.versionCode=10
Add (naive) AI player.
Ajout d'une IA (naîve) comme joueur.
......@@ -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) {
......
......@@ -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 {
......
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:');
......
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';
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,
),
);
}
}
......@@ -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),
......
......@@ -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"
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment