Files
NowChess-Frontend/src/app/services/bot-move.service.ts
T
2026-04-22 08:28:16 +02:00

79 lines
2.4 KiB
TypeScript

import { Injectable, DestroyRef, inject } from '@angular/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { delay, Subscription } from 'rxjs';
import { GameApiService } from './game-api.service';
import { getErrorMessage } from '../core/http/error-message.util';
import { GameFull, GameState } from '../models/game.models';
@Injectable({ providedIn: 'root' })
export class BotMoveService {
private readonly gameApi = inject(GameApiService);
private readonly destroyRef = inject(DestroyRef);
private botMoveSubscription: Subscription | null = null;
private isBotPlayer(playerId: string): boolean {
return playerId.startsWith('bot-');
}
isPlayingAgainstBot(game: GameFull | null): boolean {
if (!game) {
return false;
}
return this.isBotPlayer(game.white.id) || this.isBotPlayer(game.black.id);
}
isCurrentPlayerBot(game: GameFull | null, state: GameState | null): boolean {
if (!game || !state) {
return false;
}
const currentPlayer = state.turn === 'white' ? game.white : game.black;
return this.isBotPlayer(currentPlayer.id);
}
tryMakeBotMove(
gameId: string,
game: GameFull | null,
state: GameState | null,
onSuccess: (updatedState: GameState) => void,
onError: (error: string) => void
): void {
if (!this.isPlayingAgainstBot(game) || !this.isCurrentPlayerBot(game, state) || !state) {
return;
}
this.botMoveSubscription?.unsubscribe();
this.botMoveSubscription = this.gameApi
.getLegalMoves(gameId)
.pipe(
delay(1000),
takeUntilDestroyed(this.destroyRef)
)
.subscribe({
next: (response) => {
if (response.moves.length === 0) {
return;
}
const botMove = response.moves[Math.floor(Math.random() * response.moves.length)];
this.gameApi
.makeMove(gameId, botMove.uci)
.pipe(takeUntilDestroyed(this.destroyRef))
.subscribe({
next: (updatedState) => {
onSuccess(updatedState);
},
error: (error) => {
onError(getErrorMessage(error, 'Bot move failed.'));
}
});
},
error: () => {
onError('Could not get legal moves for bot move.');
}
});
}
cleanup(): void {
this.botMoveSubscription?.unsubscribe();
}
}