Some checks failed
Android Build & Publish / android (push) Failing after 2m10s
- Replace minimax with PIMC (Perfect Information Monte Carlo) search - Add PIMC_SCOPE_BOOST=150 → effective scopa value 540 (was 390) → Master win rate: 67.5% → 72.5% vs legacy AI (target ≥60%) → Advanced win rate: 97.5% vs beginner AI (target ≥55%) → Scope gap in losses: 6.54 → 3.00 scopa/match - Add card inference engine for probabilistic hand tracking - Add ai-strategy, ai-legacy evaluation bridge - Add .gitea/workflows/android-build.yml: build debug + unsigned release APK and publish to Gitea generic package registry
85 lines
2.1 KiB
TypeScript
85 lines
2.1 KiB
TypeScript
import { chooseMove } from './ai';
|
|
import {
|
|
AIWorkerChooseMoveRequest,
|
|
AIWorkerErrorMessage,
|
|
AIWorkerRequestMessage,
|
|
AIWorkerResponseMessage,
|
|
} from './ai-worker-protocol';
|
|
import { CardInferenceEngine } from './card-inference';
|
|
import { CardTracker } from './card-tracker';
|
|
|
|
interface AIWorkerScope {
|
|
addEventListener(type: 'message', listener: (event: MessageEvent<AIWorkerRequestMessage>) => void): void;
|
|
postMessage(message: AIWorkerResponseMessage): void;
|
|
}
|
|
|
|
const workerScope = globalThis as unknown as AIWorkerScope;
|
|
|
|
function serializeError(requestId: string, error: unknown): AIWorkerErrorMessage {
|
|
if (error instanceof Error) {
|
|
return {
|
|
type: 'error',
|
|
requestId,
|
|
error: {
|
|
message: error.message,
|
|
name: error.name,
|
|
stack: error.stack,
|
|
},
|
|
};
|
|
}
|
|
|
|
return {
|
|
type: 'error',
|
|
requestId,
|
|
error: {
|
|
message: typeof error === 'string' ? error : 'Unknown AI worker error',
|
|
name: 'Error',
|
|
},
|
|
};
|
|
}
|
|
|
|
async function handleChooseMove(request: AIWorkerChooseMoveRequest): Promise<void> {
|
|
const tracker = request.trackerSnapshot
|
|
? CardTracker.fromSnapshot(request.trackerSnapshot)
|
|
: undefined;
|
|
|
|
const inference = request.inferenceSnapshot && tracker
|
|
? CardInferenceEngine.fromSnapshot(request.inferenceSnapshot, tracker)
|
|
: undefined;
|
|
|
|
try {
|
|
const move = await chooseMove(
|
|
request.state,
|
|
request.playerIdx,
|
|
request.difficulty,
|
|
tracker,
|
|
(progress) => {
|
|
workerScope.postMessage({
|
|
type: 'progress',
|
|
requestId: request.requestId,
|
|
progress,
|
|
});
|
|
},
|
|
inference ? { inference } : undefined,
|
|
);
|
|
|
|
workerScope.postMessage({
|
|
type: 'result',
|
|
requestId: request.requestId,
|
|
move,
|
|
});
|
|
} catch (error) {
|
|
workerScope.postMessage(serializeError(request.requestId, error));
|
|
}
|
|
}
|
|
|
|
workerScope.addEventListener('message', (event: MessageEvent<AIWorkerRequestMessage>) => {
|
|
const message = event.data;
|
|
if (message.type !== 'choose-move') {
|
|
return;
|
|
}
|
|
|
|
void handleChooseMove(message);
|
|
});
|
|
|
|
export {}; |