Commit 437233f8 authored by biluo.shen's avatar biluo.shen

fix deck cards; intercept for test

parent 3a8c96b5
Pipeline #28112 failed with stages
in 31 seconds
...@@ -15,11 +15,38 @@ import { cardStore, matStore } from "@/stores"; ...@@ -15,11 +15,38 @@ import { cardStore, matStore } from "@/stores";
import { ActionMsgName, Global, convertPhase, convertCard, convertDeckCard, parsePlayerFromMsg, convertActionMsg, Input } from "@/api/ygoAgent/schema"; import { ActionMsgName, Global, convertPhase, convertCard, convertDeckCard, parsePlayerFromMsg, convertActionMsg, Input } from "@/api/ygoAgent/schema";
import { predictDuel } from "@/api/ygoAgent/predict"; import { predictDuel } from "@/api/ygoAgent/predict";
function computeSetDifference(a1: number[], a2: number[]): number[] {
const freq1 = new Map<number, number>();
const freq2 = new Map<number, number>();
for (const num of a1) {
freq1.set(num, (freq1.get(num) || 0) + 1);
}
for (const num of a2) {
freq2.set(num, (freq2.get(num) || 0) + 1);
}
for (const [num, count] of freq2) {
if (freq1.has(num)) {
freq1.set(num, freq1.get(num)! - count);
}
}
const difference: number[] = [];
for (const [num, count] of freq1) {
if (count > 0) {
difference.push(...Array(count).fill(num));
}
}
return difference;
}
export function genPredictReq(msg: ygopro.StocGameMessage): PredictReq { export function genPredictReq(msg: ygopro.StocGameMessage): PredictReq {
// 全局信息可以从 `matStore` 里面拿 // 全局信息可以从 `matStore` 里面拿
const mat = matStore; const mat = matStore;
// 卡片信息可以从 `cardStore` 里面拿 // 卡片信息可以从 `cardStore` 里面拿
// TODO (ygo-agent): TZONE
const zones = [ const zones = [
ygopro.CardZone.DECK, ygopro.CardZone.DECK,
ygopro.CardZone.HAND, ygopro.CardZone.HAND,
...@@ -45,16 +72,15 @@ export function genPredictReq(msg: ygopro.StocGameMessage): PredictReq { ...@@ -45,16 +72,15 @@ export function genPredictReq(msg: ygopro.StocGameMessage): PredictReq {
) )
.map((card) => convertCard(card, player)); .map((card) => convertCard(card, player));
const card_codes_me = new Set( const card_codes_me = cardStore.inner
cardStore.inner
.filter((card) => .filter((card) =>
zones.includes(card.location.zone) && card.location.controller === player zones.includes(card.location.zone) && card.location.controller === player
) )
.map((card) => card.code)); .map((card) => card.code);
const card_codes_me_deck = computeSetDifference(mat.main_deck, card_codes_me);
const deck_cards_me = matStore.main_deck_cards const main_deck_card_meta = mat.main_deck_card_meta;
.filter((meta) => card_codes_me.has(meta.id)) // TODO (ygo-agent): 临时方案,有很多边界情况未考虑
.map(convertDeckCard); const deck_cards_me = card_codes_me_deck.map((code) => convertDeckCard(main_deck_card_meta.get(code)!));
const turnPlayer = mat.currentPlayer; const turnPlayer = mat.currentPlayer;
const global: Global = { const global: Global = {
...@@ -79,23 +105,29 @@ export function genPredictReq(msg: ygopro.StocGameMessage): PredictReq { ...@@ -79,23 +105,29 @@ export function genPredictReq(msg: ygopro.StocGameMessage): PredictReq {
index: mat.agentIndex, index: mat.agentIndex,
input: input, input: input,
// TODO (ygo-agent): use real value // TODO (ygo-agent): use real value
prev_action_idx: 0, prev_action_idx: mat.prevActionIndex,
} }
} }
export async function sendAIPredictAsResponse(msg: ygopro.StocGameMessage) { export async function sendAIPredictAsResponse() {
const msg = matStore.actionMsg;
const req = genPredictReq(msg); const req = genPredictReq(msg);
console.log("Sending predict request:", req); console.log("Sending predict request:", req);
const duelId = matStore.duelId; const duelId = matStore.duelId;
const resp = await predictDuel(duelId, req); const resp = await predictDuel(duelId, req);
if (!resp) { console.log("Got predict response:", resp);
if (resp !== undefined) {
matStore.agentIndex = resp.index;
}
else {
console.error("Failed to get predict response"); console.error("Failed to get predict response");
return; return;
} }
const preds = resp.predict_results.action_preds; const preds = resp.predict_results.action_preds;
const action_idx = argmax(preds, (r) => r.prob); const action_idx = argmax(preds, (r) => r.prob);
matStore.prevActionIndex = action_idx;
const response = preds[action_idx].response; const response = preds[action_idx].response;
const msg_name = req.input.action_msg.name; const msg_name = req.input.action_msg.name;
switch (msg_name) { switch (msg_name) {
......
...@@ -100,58 +100,69 @@ export default async function handleGameMsg( ...@@ -100,58 +100,69 @@ export default async function handleGameMsg(
if (replayStore.isReplay && ReplayIgnoreMsg.includes(msg.gameMsg)) return; if (replayStore.isReplay && ReplayIgnoreMsg.includes(msg.gameMsg)) return;
console.log("Got " + msg.gameMsg);
switch (msg.gameMsg) { switch (msg.gameMsg) {
case "select_card": { case "announce": {
matStore.actionMsg = msg.select_card; matStore.actionMsg = msg.announce;
break; console.log("intercept announce");
} return;
case "select_tribute": {
matStore.actionMsg = msg.select_tribute;
break;
}
case "select_sum": {
matStore.actionMsg = msg.select_sum;
break;
} }
case "select_idle_cmd": { case "select_battle_cmd": {
matStore.actionMsg = msg.select_idle_cmd; matStore.actionMsg = msg.select_battle_cmd;
break; console.log("intercept select_battle_cmd");
return;
} }
case "select_chain": { case "select_chain": {
matStore.actionMsg = msg.select_chain; matStore.actionMsg = msg.select_chain;
break; console.log("intercept select_chain");
return;
} }
case "select_position": { case "select_yes_no": {
matStore.actionMsg = msg.select_position; matStore.actionMsg = msg.select_yes_no;
break; console.log("intercept select_yes_no");
return;
} }
case "select_effect_yn": { case "select_effect_yn": {
matStore.actionMsg = msg.select_effect_yn; matStore.actionMsg = msg.select_effect_yn;
break; console.log("intercept select_effect_yn");
return;
} }
case "select_yes_no": { case "select_idle_cmd": {
matStore.actionMsg = msg.select_yes_no; matStore.actionMsg = msg.select_idle_cmd;
break; console.log("intercept select_idle_cmd");
return;
} }
case "select_battle_cmd": { case "select_option": {
matStore.actionMsg = msg.select_battle_cmd; matStore.actionMsg = msg.select_option;
break; console.log("intercept select_option");
return;
}
case "select_position": {
matStore.actionMsg = msg.select_position;
console.log("intercept select_position");
return;
} }
case "select_unselect_card": { case "select_unselect_card": {
matStore.actionMsg = msg.select_unselect_card; matStore.actionMsg = msg.select_unselect_card;
break; break;
} }
case "select_option": {
matStore.actionMsg = msg.select_option;
break;
}
case "select_place": { case "select_place": {
matStore.actionMsg = msg.select_place; matStore.actionMsg = msg.select_place;
break; break;
} }
case "announce": case "select_card": {
matStore.actionMsg = msg.announce; matStore.actionMsg = msg.select_card;
break; break;
}
case "select_sum": {
matStore.actionMsg = msg.select_sum;
break;
}
case "select_tribute": {
matStore.actionMsg = msg.select_tribute;
break;
}
default: { default: {
break; break;
} }
......
...@@ -92,10 +92,13 @@ export default async (start: ygopro.StocGameMessage.MsgStart) => { ...@@ -92,10 +92,13 @@ export default async (start: ygopro.StocGameMessage.MsgStart) => {
const { duelId, index } = (await createDuel())!; const { duelId, index } = (await createDuel())!;
matStore.duelId = duelId; matStore.duelId = duelId;
matStore.agentIndex = index; matStore.agentIndex = index;
const main_deck_cards = matStore.main_deck.map((code) => { matStore.main_deck_card_meta = matStore.main_deck
return fetchCard(code); .reduce((map, item) => {
}); if (!map.has(item)) {
matStore.main_deck_cards = main_deck_cards; map.set(item, fetchCard(item));
}
return map;
}, new Map());
if (replayStore.isReplay) { if (replayStore.isReplay) {
replayStart(); replayStart();
......
...@@ -95,9 +95,10 @@ const initialState: Omit<MatState, "reset"> = { ...@@ -95,9 +95,10 @@ const initialState: Omit<MatState, "reset"> = {
isMe, isMe,
duelId: "", duelId: "",
agentIndex: 0, agentIndex: 0,
prevActionIndex: 0,
actionMsg: undefined, actionMsg: undefined,
main_deck: [], main_deck: [],
main_deck_cards: [], main_deck_card_meta: new Map(),
}; };
class MatStore implements MatState, NeosStore { class MatStore implements MatState, NeosStore {
...@@ -116,9 +117,10 @@ class MatStore implements MatState, NeosStore { ...@@ -116,9 +117,10 @@ class MatStore implements MatState, NeosStore {
duelEnd = initialState.duelEnd; duelEnd = initialState.duelEnd;
duelId = initialState.duelId; duelId = initialState.duelId;
agentIndex = initialState.agentIndex; agentIndex = initialState.agentIndex;
prevActionIndex = initialState.prevActionIndex;
actionMsg = initialState.actionMsg; actionMsg = initialState.actionMsg;
main_deck = initialState.main_deck; main_deck = initialState.main_deck;
main_deck_cards = initialState.main_deck_cards; main_deck_card_meta = initialState.main_deck_card_meta;
// methods // methods
isMe = initialState.isMe; isMe = initialState.isMe;
...@@ -150,9 +152,10 @@ class MatStore implements MatState, NeosStore { ...@@ -150,9 +152,10 @@ class MatStore implements MatState, NeosStore {
this.duelEnd = false; this.duelEnd = false;
this.duelId = ""; this.duelId = "";
this.agentIndex = 0; this.agentIndex = 0;
this.prevActionIndex = 0;
this.actionMsg = undefined; this.actionMsg = undefined;
this.main_deck = []; this.main_deck = [];
this.main_deck_cards = []; this.main_deck_card_meta = new Map();
} }
} }
......
...@@ -52,9 +52,10 @@ export interface MatState { ...@@ -52,9 +52,10 @@ export interface MatState {
duelId: string; duelId: string;
agentIndex: number; agentIndex: number;
prevActionIndex: number;
actionMsg?: any; actionMsg?: any;
main_deck: number[]; main_deck: number[];
main_deck_cards: CardMeta[]; main_deck_card_meta: Map<number, CardMeta>;
} }
export interface InitInfo { export interface InitInfo {
......
...@@ -29,8 +29,7 @@ import { ...@@ -29,8 +29,7 @@ import {
} from "@/api"; } from "@/api";
import { ChainSetting, matStore } from "@/stores"; import { ChainSetting, matStore } from "@/stores";
import { IconFont } from "@/ui/Shared"; import { IconFont } from "@/ui/Shared";
import { predictDuel } from "@/api/ygoAgent/predict"; import { sendAIPredictAsResponse } from "@/service/duel/agent";
import { genPredictReq } from "@/service/duel/agent";
import styles from "./index.module.scss"; import styles from "./index.module.scss";
import PhaseType = ygopro.StocGameMessage.MsgNewPhase.PhaseType; import PhaseType = ygopro.StocGameMessage.MsgNewPhase.PhaseType;
...@@ -301,12 +300,7 @@ export const Menu = () => { ...@@ -301,12 +300,7 @@ export const Menu = () => {
const globalDisable = !matStore.isMe(currentPlayer); const globalDisable = !matStore.isMe(currentPlayer);
const aiPredict = async () => { const aiPredict = async () => {
console.log("AI Predict"); await sendAIPredictAsResponse();
const req = genPredictReq(matStore.actionMsg);
console.log(req);
const duelId = matStore.duelId;
const predictRes = await predictDuel(duelId, req);
console.log(predictRes);
}; };
return ( return (
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment