Merge pull request #899 from universe-st/PR-Branch

AI性能优化
This commit is contained in:
Spmario233 2024-02-03 15:21:11 +08:00 committed by GitHub
commit 3a7bfd4092
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 210 additions and 98 deletions

View File

@ -24,15 +24,21 @@ export class Basic extends Uninstantable {
if (ui.selected.buttons.length >= range[0]) { if (ui.selected.buttons.length >= range[0]) {
ok = true; ok = true;
} }
CacheContext.setCacheContext(new CacheContext());
CacheContext.setInCacheEnvironment(true);
if (range[1] <= -1) { if (range[1] <= -1) {
j = 0; j = 0;
for (i = 0; i < ui.selected.buttons.length; i++) { for (i = 0; i < ui.selected.buttons.length; i++) {
j += check(ui.selected.buttons[i]); j += check(ui.selected.buttons[i]);
} }
CacheContext.setInCacheEnvironment(false);
CacheContext.removeCacheContext();
return (j > 0); return (j > 0);
} }
buttons = get.selectableButtons(); buttons = get.selectableButtons();
if (buttons.length == 0) { if (buttons.length == 0) {
CacheContext.setInCacheEnvironment(false);
CacheContext.removeCacheContext();
return ok; return ok;
} }
buttons2 = buttons.slice(0); buttons2 = buttons.slice(0);
@ -50,9 +56,13 @@ export class Basic extends Uninstantable {
// }); // });
if (check(buttons[ix]) <= 0) { if (check(buttons[ix]) <= 0) {
if (!forced || ok) { if (!forced || ok) {
CacheContext.setInCacheEnvironment(false);
CacheContext.removeCacheContext();
return ok; return ok;
} }
} }
CacheContext.setInCacheEnvironment(false);
CacheContext.removeCacheContext();
buttons[ix].classList.add('selected'); buttons[ix].classList.add('selected');
ui.selected.buttons.add(buttons[ix]); ui.selected.buttons.add(buttons[ix]);
game.check(); game.check();
@ -86,11 +96,13 @@ export class Basic extends Uninstantable {
if (ui.selected.cards.length == 0) return true; if (ui.selected.cards.length == 0) return true;
j = 0; j = 0;
CacheContext.setCacheContext(new CacheContext()); CacheContext.setCacheContext(new CacheContext());
CacheContext.setInCacheEnvironment(true);
for (i = 0; i < ui.selected.cards.length; i++) { for (i = 0; i < ui.selected.cards.length; i++) {
effect = check(ui.selected.cards[i]); effect = check(ui.selected.cards[i]);
if (effect < 0) j -= Math.sqrt(-effect); if (effect < 0) j -= Math.sqrt(-effect);
else j += Math.sqrt(effect); else j += Math.sqrt(effect);
} }
CacheContext.setInCacheEnvironment(false);
CacheContext.removeCacheContext(); CacheContext.removeCacheContext();
return (j > 0); return (j > 0);
} }
@ -109,6 +121,7 @@ export class Basic extends Uninstantable {
// }); // });
var ix = 0; var ix = 0;
CacheContext.setCacheContext(new CacheContext()); CacheContext.setCacheContext(new CacheContext());
CacheContext.setInCacheEnvironment(true);
var checkix = check(cards[0], cards2); var checkix = check(cards[0], cards2);
for (i = 1; i < cards.length; i++) { for (i = 1; i < cards.length; i++) {
var checkixtmp = check(cards[i], cards2); var checkixtmp = check(cards[i], cards2);
@ -119,10 +132,12 @@ export class Basic extends Uninstantable {
} }
if (check(cards[ix]) <= 0) { if (check(cards[ix]) <= 0) {
if (!forced || ok) { if (!forced || ok) {
CacheContext.setInCacheEnvironment(false);
CacheContext.removeCacheContext(); CacheContext.removeCacheContext();
return ok; return ok;
} }
} }
CacheContext.setInCacheEnvironment(false);
CacheContext.removeCacheContext(); CacheContext.removeCacheContext();
if (typeof cards[ix] == 'string') { if (typeof cards[ix] == 'string') {
ui.click.skill(cards[ix]); ui.click.skill(cards[ix]);
@ -168,11 +183,13 @@ export class Basic extends Uninstantable {
if (range[1] <= -1) { if (range[1] <= -1) {
j = 0; j = 0;
CacheContext.setCacheContext(new CacheContext()); CacheContext.setCacheContext(new CacheContext());
CacheContext.setInCacheEnvironment(true);
for (i = 0; i < ui.selected.targets.length; i++) { for (i = 0; i < ui.selected.targets.length; i++) {
effect = check(ui.selected.targets[i]); effect = check(ui.selected.targets[i]);
if (effect < 0) j -= Math.sqrt(-effect); if (effect < 0) j -= Math.sqrt(-effect);
else j += Math.sqrt(effect); else j += Math.sqrt(effect);
} }
CacheContext.setInCacheEnvironment(false);
CacheContext.removeCacheContext(); CacheContext.removeCacheContext();
return (j > 0); return (j > 0);
} }
@ -189,6 +206,7 @@ export class Basic extends Uninstantable {
// }); // });
let ix = 0; let ix = 0;
CacheContext.setCacheContext(new CacheContext()); CacheContext.setCacheContext(new CacheContext());
CacheContext.setInCacheEnvironment(true);
let checkix = check(targets[0], targets2); let checkix = check(targets[0], targets2);
for (i = 1; i < targets.length; i++) { for (i = 1; i < targets.length; i++) {
let checkixtmp = check(targets[i], targets2); let checkixtmp = check(targets[i], targets2);
@ -199,10 +217,12 @@ export class Basic extends Uninstantable {
} }
if (check(targets[ix]) <= 0) { if (check(targets[ix]) <= 0) {
if (!forced || ok) { if (!forced || ok) {
CacheContext.setInCacheEnvironment(false);
CacheContext.removeCacheContext(); CacheContext.removeCacheContext();
return ok; return ok;
} }
} }
CacheContext.setInCacheEnvironment(false);
CacheContext.removeCacheContext(); CacheContext.removeCacheContext();
targets[ix].classList.add('selected'); targets[ix].classList.add('selected');
ui.selected.targets.add(targets[ix]); ui.selected.targets.add(targets[ix]);

View File

@ -7496,7 +7496,7 @@ export class Game extends Uninstantable {
const argumentArray = Array.from(arguments), name = argumentArray[argumentArray.length - 2]; const argumentArray = Array.from(arguments), name = argumentArray[argumentArray.length - 2];
let skills = argumentArray[argumentArray.length - 1]; let skills = argumentArray[argumentArray.length - 1];
if (typeof skills.getModableSkills == 'function') { if (typeof skills.getModableSkills == 'function') {
skills = skills.getModableSkills(_status.event.useCache === true); skills = skills.getModableSkills();
} else if (typeof skills.getSkills == 'function') { } else if (typeof skills.getSkills == 'function') {
skills = skills.getSkills().concat(lib.skill.global); skills = skills.getSkills().concat(lib.skill.global);
game.expandSkills(skills); game.expandSkills(skills);
@ -7510,8 +7510,8 @@ export class Game extends Uninstantable {
skills.forEach(value => { skills.forEach(value => {
var mod = get.info(value).mod[name]; var mod = get.info(value).mod[name];
if (!mod) return; if (!mod) return;
const result = mod.apply(this, arg); const result = mod.call(this,...arg);
if (typeof arg[arg.length - 1] != 'object' && result != undefined) arg[arg.length - 1] = result; if (result != undefined && typeof arg[arg.length - 1] != 'object') arg[arg.length - 1] = result;
}); });
return arg[arg.length - 1]; return arg[arg.length - 1];
} }

View File

@ -2866,9 +2866,11 @@ export class Get extends Uninstantable {
if (!lib.characterInitFilter[node.name]) return true; if (!lib.characterInitFilter[node.name]) return true;
return lib.characterInitFilter[node.name](tag) !== false; return lib.characterInitFilter[node.name](tag) !== false;
}); });
if(initFilters.length){
const str = initFilters.reduce((strx, stry) => strx + lib.InitFilter[stry] + '<br>').slice(0, -4); const str = initFilters.reduce((strx, stry) => strx + lib.InitFilter[stry] + '<br>').slice(0, -4);
uiintro.addText(str); uiintro.addText(str);
} }
}
if (!node.noclick) { if (!node.noclick) {
const allShown = (node.isUnderControl() || (!game.observe && game.me && game.me.hasSkillTag('viewHandcard', null, node, true))); const allShown = (node.isUnderControl() || (!game.observe && game.me && game.me.hasSkillTag('viewHandcard', null, node, true)));
@ -4028,7 +4030,7 @@ export class Get extends Uninstantable {
if (!from || !to) return 0; if (!from || !to) return 0;
from = from._trueMe || from; from = from._trueMe || from;
arguments[0] = from; arguments[0] = from;
var att = get.rawAttitude.apply(this, arguments); var att = CacheContext.requireCacheContext().get.rawAttitude.apply(this, arguments);
if (from.isMad()) att = -att; if (from.isMad()) att = -att;
if (to.isMad() && att > 0) { if (to.isMad() && att > 0) {
if (to.identity == 'zhu') { if (to.identity == 'zhu') {
@ -4192,12 +4194,9 @@ export class Get extends Uninstantable {
return 1; return 1;
} }
static cacheOrder(item){ static cacheOrder(item){
let cache = CacheContext.getCacheContext(); let cache = CacheContext.requireCacheContext();
if(cache){
return cache.get.order(item); return cache.get.order(item);
} }
return get.order(item);
}
static order(item) { static order(item) {
let cache = CacheContext.requireCacheContext(); let cache = CacheContext.requireCacheContext();
var info = get.info(item); var info = get.info(item);
@ -4235,13 +4234,11 @@ export class Get extends Uninstantable {
return result; return result;
} }
static cacheEffectUse(target, card, player, player2, isLink){ static cacheEffectUse(target, card, player, player2, isLink){
let cache = CacheContext.getCacheContext(); let cache = CacheContext.requireCacheContext();
if(cache){
return cache.get.effect_use(target,card,player,player2,isLink); return cache.get.effect_use(target,card,player,player2,isLink);
} }
return get.effect_use(target,card,player,player2,isLink);
}
static effect_use(target, card, player, player2, isLink) { static effect_use(target, card, player, player2, isLink) {
let cache = CacheContext.requireCacheContext();
var event = _status.event; var event = _status.event;
var eventskill = null; var eventskill = null;
if (player == undefined) player = _status.event.player; if (player == undefined) player = _status.event.player;
@ -4262,7 +4259,7 @@ export class Get extends Uninstantable {
info.changeTarget(player, targets); info.changeTarget(player, targets);
var eff = 0; var eff = 0;
for (var i of targets) { for (var i of targets) {
eff += get.effect(i, card, player, player2, isLink); eff += cache.get.effect(i, card, player, player2, isLink);
} }
return eff; return eff;
} }
@ -4280,10 +4277,10 @@ export class Get extends Uninstantable {
for (var i = 0; i < skills1.length; i++) { for (var i = 0; i < skills1.length; i++) {
temp1 = get.info(skills1[i]).ai; temp1 = get.info(skills1[i]).ai;
if (temp1 && typeof temp1.effect == 'object' && typeof temp1.effect.player_use == 'function') { if (temp1 && typeof temp1.effect == 'object' && typeof temp1.effect.player_use == 'function') {
temp1 = temp1.effect.player_use(card, player, target, result1, isLink); temp1 = cache.delegate(temp1.effect).player_use(card, player, target, result1, isLink);
} }
else if (temp1 && typeof temp1.effect == 'object' && typeof temp1.effect.player == 'function') { else if (temp1 && typeof temp1.effect == 'object' && typeof temp1.effect.player == 'function') {
temp1 = temp1.effect.player(card, player, target, result1, isLink); temp1 = cache.delegate(temp1.effect).player(card, player, target, result1, isLink);
} }
else temp1 = undefined; else temp1 = undefined;
if (typeof temp1 == 'object') { if (typeof temp1 == 'object') {
@ -4323,7 +4320,7 @@ export class Get extends Uninstantable {
target: target, target: target,
skill: skills2[i], skill: skills2[i],
isLink: isLink, isLink: isLink,
})) temp2 = temp2.effect(card, player, target, result2, isLink); })) temp2 = cache.delegate(temp2).effect(card, player, target, result2, isLink);
else temp2 = undefined; else temp2 = undefined;
} }
else if (temp2 && typeof temp2.effect == 'object' && typeof temp2.effect.target_use == 'function') { else if (temp2 && typeof temp2.effect == 'object' && typeof temp2.effect.target_use == 'function') {
@ -4332,7 +4329,7 @@ export class Get extends Uninstantable {
target: target, target: target,
skill: skills2[i], skill: skills2[i],
isLink: isLink, isLink: isLink,
})) temp2 = temp2.effect.target_use(card, player, target, result2, isLink); })) temp2 = cache.delegate(temp2.effect).target_use(card, player, target, result2, isLink);
else temp2 = undefined; else temp2 = undefined;
} }
else if (temp2 && typeof temp2.effect == 'object' && typeof temp2.effect.target == 'function') { else if (temp2 && typeof temp2.effect == 'object' && typeof temp2.effect.target == 'function') {
@ -4341,7 +4338,7 @@ export class Get extends Uninstantable {
target: target, target: target,
skill: skills2[i], skill: skills2[i],
isLink: isLink, isLink: isLink,
})) temp2 = temp2.effect.target(card, player, target, result2, isLink); })) temp2 = cache.delegate(temp2.effect).target(card, player, target, result2, isLink);
else temp2 = undefined; else temp2 = undefined;
} }
else temp2 = undefined; else temp2 = undefined;
@ -4386,7 +4383,7 @@ export class Get extends Uninstantable {
result2 += temp02; result2 += temp02;
result1 += temp01; result1 += temp01;
if (typeof card == 'object' && !result.ignoreStatus) { if (typeof card == 'object' && !result.ignoreStatus) {
if (get.attitude(player, target) < 0) { if (cache.get.attitude(player, target) < 0) {
result2 *= Math.sqrt(threaten); result2 *= Math.sqrt(threaten);
} }
else { else {
@ -4394,7 +4391,7 @@ export class Get extends Uninstantable {
} }
if (target.hp == 1) result2 *= 2.5; if (target.hp == 1) result2 *= 2.5;
if (target.hp == 2) result2 *= 1.8; if (target.hp == 2) result2 *= 1.8;
let countTargetCards = target.cacheCountCards('h'); let countTargetCards = target.countCards('h');
if (countTargetCards == 0) { if (countTargetCards == 0) {
if (get.tag(card, 'respondSha') || get.tag(card, 'respondShan')) { if (get.tag(card, 'respondSha') || get.tag(card, 'respondShan')) {
result2 *= 1.7; result2 *= 1.7;
@ -4419,32 +4416,30 @@ export class Get extends Uninstantable {
if (zerotarget) result2 = 0; if (zerotarget) result2 = 0;
var final = 0; var final = 0;
if (player2) { if (player2) {
final = (result1 * get.attitude(player2, player) + (target ? result2 * get.attitude(player2, target) : 0)); final = (result1 * cache.get.attitude(player2, player) + (target ? result2 * cache.get.attitude(player2, target) : 0));
} }
else final = (result1 * get.attitude(player, player) + (target ? result2 * get.attitude(player, target) : 0)); else final = (result1 * cache.get.attitude(player, player) + (target ? result2 * cache.get.attitude(player, target) : 0));
if (!isLink && get.tag(card, 'natureDamage') && !zerotarget) { if (!isLink && get.tag(card, 'natureDamage') && !zerotarget) {
var info = get.info(card); var info = get.info(card);
if (!info || !info.ai || !info.ai.canLink) { if (!info || !info.ai || !info.ai.canLink) {
if (target.isLinked()) game.players.forEach(function (current) { if (target.isLinked()) game.players.forEach(function (current) {
if (current != target && current.isLinked()) final += get.effect(current, card, player, player2, true); if (current != target && current.isLinked()) final += cache.get.effect(current, card, player, player2, true);
}); });
} }
else if (info.ai.canLink(player, target, card)) { else if (info.ai.canLink(player, target, card)) {
game.players.forEach(function (current) { game.players.forEach(function (current) {
if (current != target && current.isLinked()) final += get.effect(current, card, player, player2, true); if (current != target && current.isLinked()) final += cache.get.effect(current, card, player, player2, true);
}); });
} }
} }
return final; return final;
} }
static cacheEffect(target, card, player, player2, isLink){ static cacheEffect(target, card, player, player2, isLink){
let cache = CacheContext.getCacheContext(); let cache = CacheContext.requireCacheContext();
if(cache){
return cache.get.effect(target,card,player,player2,isLink); return cache.get.effect(target,card,player,player2,isLink);
} }
return get.effect(target,card,player,player2,isLink);
}
static effect(target, card, player, player2, isLink) { static effect(target, card, player, player2, isLink) {
let cache = CacheContext.requireCacheContext();
var event = _status.event; var event = _status.event;
var eventskill = null; var eventskill = null;
if (player == undefined) player = _status.event.player; if (player == undefined) player = _status.event.player;
@ -4505,7 +4500,7 @@ export class Get extends Uninstantable {
game.expandSkills(skills2); game.expandSkills(skills2);
for (var i = 0; i < skills2.length; i++) { for (var i = 0; i < skills2.length; i++) {
temp2 = get.info(skills2[i]).ai; temp2 = get.info(skills2[i]).ai;
if (temp2 && temp2.threaten) temp3 = temp2.threaten; if (temp2 && temp2.threaten) temp3 = cache.delegate(temp2).threaten;
else temp3 = undefined; else temp3 = undefined;
if (temp2 && typeof temp2.effect == 'function') { if (temp2 && typeof temp2.effect == 'function') {
if (!player.hasSkillTag('ignoreSkill', true, { if (!player.hasSkillTag('ignoreSkill', true, {
@ -4513,7 +4508,7 @@ export class Get extends Uninstantable {
target: target, target: target,
skill: skills2[i], skill: skills2[i],
isLink: isLink, isLink: isLink,
})) temp2 = temp2.effect(card, player, target, result2, isLink); })) temp2 = cache.delegate(temp2).effect(card, player, target, result2, isLink);
else temp2 = undefined; else temp2 = undefined;
} }
else if (temp2 && typeof temp2.effect == 'object' && typeof temp2.effect.target == 'function') { else if (temp2 && typeof temp2.effect == 'object' && typeof temp2.effect.target == 'function') {
@ -4522,7 +4517,7 @@ export class Get extends Uninstantable {
target: target, target: target,
skill: skills2[i], skill: skills2[i],
isLink: isLink, isLink: isLink,
})) temp2 = temp2.effect.target(card, player, target, result2, isLink); })) temp2 = cache.delegate(temp2.effect).target(card, player, target, result2, isLink);
else temp2 = undefined; else temp2 = undefined;
} }
else temp2 = undefined; else temp2 = undefined;
@ -4567,7 +4562,7 @@ export class Get extends Uninstantable {
result2 += temp02; result2 += temp02;
result1 += temp01; result1 += temp01;
if (typeof card == 'object' && !result.ignoreStatus) { if (typeof card == 'object' && !result.ignoreStatus) {
if (get.attitude(player, target) < 0) { if (cache.get.attitude(player, target) < 0) {
result2 *= Math.sqrt(threaten); result2 *= Math.sqrt(threaten);
} }
else { else {
@ -4576,7 +4571,7 @@ export class Get extends Uninstantable {
// *** continue here *** // *** continue here ***
if (target.hp == 1) result2 *= 2.5; if (target.hp == 1) result2 *= 2.5;
if (target.hp == 2) result2 *= 1.8; if (target.hp == 2) result2 *= 1.8;
let targetCountCards = target.cacheCountCards('h'); let targetCountCards = target.countCards('h');
if (targetCountCards == 0) { if (targetCountCards == 0) {
if (get.tag(card, 'respondSha') || get.tag(card, 'respondShan')) { if (get.tag(card, 'respondSha') || get.tag(card, 'respondShan')) {
result2 *= 1.7; result2 *= 1.7;
@ -4601,19 +4596,19 @@ export class Get extends Uninstantable {
if (zerotarget) result2 = 0; if (zerotarget) result2 = 0;
var final = 0; var final = 0;
if (player2) { if (player2) {
final = (result1 * get.attitude(player2, player) + (target ? result2 * get.attitude(player2, target) : 0)); final = (result1 * cache.get.attitude(player2, player) + (target ? result2 * cache.get.attitude(player2, target) : 0));
} }
else final = (result1 * get.attitude(player, player) + (target ? result2 * get.attitude(player, target) : 0)); else final = (result1 * cache.get.attitude(player, player) + (target ? result2 * cache.get.attitude(player, target) : 0));
if (!isLink && get.tag(card, 'natureDamage') && !zerotarget) { if (!isLink && get.tag(card, 'natureDamage') && !zerotarget) {
var info = get.info(card); var info = get.info(card);
if (!info || !info.ai || !info.ai.canLink) { if (!info || !info.ai || !info.ai.canLink) {
if (target.isLinked()) game.players.forEach(function (current) { if (target.isLinked()) game.players.forEach(function (current) {
if (current != target && current.isLinked()) final += get.effect(current, card, player, player2, true); if (current != target && current.isLinked()) final += cache.get.effect(current, card, player, player2, true);
}); });
} }
else if (info.ai.canLink(player, target, card)) { else if (info.ai.canLink(player, target, card)) {
game.players.forEach(function (current) { game.players.forEach(function (current) {
if (current != target && current.isLinked()) final += get.effect(current, card, player, player2, true); if (current != target && current.isLinked()) final += cache.get.effect(current, card, player, player2, true);
}); });
} }
} }

View File

@ -9,24 +9,49 @@ import { hex_md5 } from "../crypt/md5.js";
export class CacheContext{ export class CacheContext{
constructor(){ constructor(){
this.lib = this.createCacheProxy(Library); this.lib = this._createCacheProxy(Library);
this.game = this.createCacheProxy(Game); this.game = this._createCacheProxy(Game);
this.get = this.createCacheProxy(Get); this.get = this._createCacheProxy(Get);
this.sourceMap = {}; this.sourceMap = new Map();
this.storageMap = new Map();
} }
/**
* 设置当前是否处于缓存环境当使用inject对类进行注入时只在缓存环境下会返回缓存值
* @param {boolean} cache
*/
static setInCacheEnvironment(cache){
_status.cacheEnvironment = cache;
}
/**
* 设置一个公有的缓存上下文缓存上下文持有期间假设所缓存的函数在参数相同时绝对不会注意是绝对不会返回不同的返回值
* 使用inject对类进行注入时将应用公有的缓存上下文
* @param {CacheContext} context
*/
static setCacheContext(context){ static setCacheContext(context){
_status.cacheContext = context; _status.cacheContext = context;
} }
/**
* 返回当前公有的缓存上下文
* @returns {CacheContext} 缓存上下文
*/
static getCacheContext(){ static getCacheContext(){
return _status.cacheContext; return _status.cacheContext;
} }
/**
* 移除当前公有的缓存上下文
*/
static removeCacheContext(){ static removeCacheContext(){
delete _status.cacheContext; delete _status.cacheContext;
} }
/**
* 返回公有的缓存上下文没有就创建一个新的返回不会设置为新的公有缓存上下文
* @returns {CacheContext} 缓存上下文
*/
static requireCacheContext(){ static requireCacheContext(){
let cache = CacheContext.getCacheContext(); let cache = CacheContext.getCacheContext();
if(!cache){ if(!cache){
@ -35,15 +60,57 @@ export class CacheContext{
return cache; return cache;
} }
/**
* 对一个对象进行代理对象的所有函数都将按条件返回缓存结果
* 注意以cache开头的方法依然保持原来的调用
* 如果所代理的对象拥有cacheSupportFunction方法返回一个方法名数组只有允许的方法才会返回缓存结果剩余方法依然保持原来的调用
* @param {any} source 需要代理的对象
* @returns
*/
delegate(source){ delegate(source){
if(source === null || source === undefined)return null; if(source === null || source === undefined)return source;
if(typeof source.getCacheKey !== 'function')return source; if(source._cacheDelegateSource)return source;
let cacheKey = source.getCacheKey(); let proxy = this.sourceMap.get(source);
if(this.sourceMap[cacheKey]){ if(proxy){
return this.sourceMap[cacheKey]; return proxy;
} }
this.sourceMap[cacheKey] = this.createCacheProxy(source); proxy = this._createCacheProxy(source);
return this.sourceMap[cacheKey]; this.sourceMap.set(source,proxy);
return proxy;
}
/**
* 对一个类进行注入methods为可以返回缓存的所有方法注入后此类的相关方法会在公有缓存上下文下返回缓存值
* @param {any} source
* @param {Array<string>} methods
* @returns
*/
static inject(source,methods){
if(source == null || source === undefined)return null;
for(let method of methods){
let func = source[method];
if(typeof func != 'function')continue;
source[method] = function(){
try{
if(!_status.cacheEnvironment){
return func.call(this,...arguments);
}
return CacheContext
._getCacheValueFromObject(CacheContext.requireCacheContext()._requireStorage(this),method,arguments,this,func);
}catch(e){
return func.call(this,...arguments);
}
}
}
}
_requireStorage(obj){
let storage = this.storageMap.get(obj);
if(!storage){
storage = {};
this.storageMap.set(obj,storage);
}
return storage;
} }
/** /**
@ -51,11 +118,12 @@ export class CacheContext{
* @param {T} delegateObject * @param {T} delegateObject
* @returns {T} * @returns {T}
*/ */
createCacheProxy(delegateObject){ _createCacheProxy(delegateObject){
const cacheFuncObj = {}; const cacheFuncObj = {};
const cacheStorage = {}; const cacheStorage = {};
return new Proxy(delegateObject,{ return new Proxy(delegateObject,{
get:(target,key)=>{ get:(target,key)=>{
if(key == '_cacheDelegateSource')return delegateObject;
let value = target[key]; let value = target[key];
if(key.indexOf('cache') == 0){ if(key.indexOf('cache') == 0){
return value; return value;
@ -71,9 +139,9 @@ export class CacheContext{
wrapFunc = function(){ wrapFunc = function(){
try{ try{
return CacheContext return CacheContext
.getCacheValueFromObject(cacheStorage,key,arguments,target); ._getCacheValueFromObject(cacheStorage,key,arguments,target);
}catch(e){ }catch(e){
return value.apply(target,arguments); return value.call(target,...arguments);
} }
}; };
cacheFuncObj[key] = wrapFunc; cacheFuncObj[key] = wrapFunc;
@ -85,20 +153,22 @@ export class CacheContext{
}); });
} }
static getCacheValueFromObject(storage,key,params,source){ static _getCacheValueFromObject(storage,key,params,source,func){
let cache = storage; let cache = storage;
let funcCache = CacheContext.ensureMember(cache,key); let funcCache = CacheContext._ensureMember(cache,key);
let cacheKey = CacheContext.wrapParametersToCacheKey(params); let cacheKey = CacheContext._wrapParametersToCacheKey(params);
let ret = funcCache[cacheKey]; let ret = funcCache[cacheKey];
if(ret === undefined){ if(ret === undefined){
ret = source[key](...params); ret = ((typeof func == 'function')?func:source[key]).call(source,...params);
funcCache[cacheKey] = ret; funcCache[cacheKey] = ret;
} //console.log('缓存未命中!'+key+":"+cacheKey+":"+params.length+":ret:"+ret);
}else{
//console.log(key+":"+cacheKey+":"+params.length+":ret:"+ret); //console.log(key+":"+cacheKey+":"+params.length+":ret:"+ret);
}
return ret; return ret;
} }
static ensureMember(obj,key){ static _ensureMember(obj,key){
let mem = obj[key]; let mem = obj[key];
if(!mem){ if(!mem){
mem = {}; mem = {};
@ -107,14 +177,14 @@ export class CacheContext{
return mem; return mem;
} }
static wrapParametersToCacheKey(params){ static _wrapParametersToCacheKey(params){
return Array.from(params) return Array.from(params)
.filter(p=>!(p instanceof CacheContext)) .filter(p=>!(p instanceof CacheContext))
.map(param=>CacheContext.wrapParameterToCacheKey(param)) .map(param=>CacheContext._wrapParameterToCacheKey(param))
.join('-'); .join('-');
} }
static wrapParameterToCacheKey(param){ static _wrapParameterToCacheKey(param){
if(param === null)return 'null'; if(param === null)return 'null';
if(param === undefined)return 'undefined'; if(param === undefined)return 'undefined';
if(typeof param === 'string')return `[str:${param}]`; if(typeof param === 'string')return `[str:${param}]`;
@ -122,11 +192,11 @@ export class CacheContext{
if(typeof param === 'boolean')return `[bl:${param}]`; if(typeof param === 'boolean')return `[bl:${param}]`;
if(typeof param.getCacheKey == 'function')return param.getCacheKey(); if(typeof param.getCacheKey == 'function')return param.getCacheKey();
if(Array.isArray(param)){ if(Array.isArray(param)){
return `[arr:[${param.filter(p=>!(p instanceof CacheContext)).map(p=>CacheContext.wrapParameterToCacheKey(p)).join('-')}]]`; return `[arr:[${param.filter(p=>!(p instanceof CacheContext)).map(p=>CacheContext._wrapParameterToCacheKey(p)).join('-')}]]`;
} }
if(typeof param === 'function')return `[f:${hex_md5(param.toString())}]`; if(typeof param === 'function')return `[f:${hex_md5(param.toString())}]`;
let entries = Object.entries(param); let entries = Object.entries(param);
entries.sort((a,b)=>a[0]<b[0]?-1:1); entries.sort((a,b)=>a[0]<b[0]?-1:1);
return `[obj:{${entries.map(e=>e[0]+":"+CacheContext.wrapParameterToCacheKey(e[1])).join(',')}}]`; return `[obj:{${entries.map(e=>e[0]+":"+CacheContext._wrapParameterToCacheKey(e[1])).join(',')}}]`;
} }
} }

View File

@ -3247,6 +3247,8 @@ export class Player extends HTMLDivElement {
if(arg2){ if(arg2){
if(typeof arg2 == 'string'){ if(typeof arg2 == 'string'){
filter = card=>(getCardName(card) == arg2); filter = card=>(getCardName(card) == arg2);
}else if(Array.isArray(arg2)){
filter = card=>arg2.includes(getCardName(card));
}else if(typeof arg2 == 'object'){ }else if(typeof arg2 == 'object'){
filter = card=>{ filter = card=>{
for (let j in arg2) { for (let j in arg2) {
@ -3355,13 +3357,6 @@ export class Player extends HTMLDivElement {
} }
return list; return list;
} }
cacheCountCards(arg1){
let cache = CacheContext.getCacheContext();
if(cache){
return cache.delegate(this).countCards(arg1);
}
return this.countCards(arg1);
}
countCards(arg1, arg2) { countCards(arg1, arg2) {
let count = 0; let count = 0;
for(let item of this.iterableGetCards(arg1,arg2)){ for(let item of this.iterableGetCards(arg1,arg2)){
@ -3398,9 +3393,8 @@ export class Player extends HTMLDivElement {
} }
return skills; return skills;
} }
getModableSkills(useCache) { getModableSkills() {
var func = function (player) { var skills = this.getSkills().concat(lib.skill.global);
var skills = player.getSkills().concat(lib.skill.global);
game.expandSkills(skills); game.expandSkills(skills);
skills = skills.filter(function (skill) { skills = skills.filter(function (skill) {
var info = get.info(skill); var info = get.info(skill);
@ -3408,9 +3402,6 @@ export class Player extends HTMLDivElement {
}); });
skills.sort((a, b) => get.priority(a) - get.priority(b)); skills.sort((a, b) => get.priority(a) - get.priority(b));
return skills; return skills;
};
if (!useCache) return func(this);
return game.callFuncUseStepCache("player.getModableSkills", func, [this]);
} }
getSkills(arg2, arg3, arg4) { getSkills(arg2, arg3, arg4) {
var skills = this.skills.slice(0); var skills = this.skills.slice(0);
@ -4760,9 +4751,6 @@ export class Player extends HTMLDivElement {
} }
}); });
} }
cacheSupportFunction(){
return ['hasCard','hasValueTarget','getCardIndex','countCards','getSkills','getUseValue','canUse'];
}
moveCard() { moveCard() {
var next = game.createEvent('moveCard'); var next = game.createEvent('moveCard');
next.player = this; next.player = this;
@ -4830,7 +4818,7 @@ export class Player extends HTMLDivElement {
this.logSkill(event.logSkill); this.logSkill(event.logSkill);
} }
else if (Array.isArray(event.logSkill)) { else if (Array.isArray(event.logSkill)) {
this.logSkill.apply(this, event.logSkill); this.logSkill.call(this,...event.logSkill);
} }
} }
if (result.card || !result.skill) { if (result.card || !result.skill) {
@ -6914,8 +6902,47 @@ export class Player extends HTMLDivElement {
return player.canUse(card, current, distance, includecard); return player.canUse(card, current, distance, includecard);
}); });
} }
hasValueTarget() { hasValueTarget(card, distance, includecard) {
return this.getUseValue.apply(this, arguments) > 0; if (typeof (card) == 'string') {
card = { name: card, isCard: true };
}
var player = this;
var targets = game.filterPlayer();
var value = [];
var min = 0;
var info = get.info(card);
if (!info || info.notarget) return false;
var range;
var select = get.copy(info.selectTarget);
if (select == undefined) {
if (info.filterTarget == undefined) return true;
range = [1, 1];
}
else if (typeof select == 'number') range = [select, select];
else if (get.itemtype(select) == 'select') range = select;
else if (typeof select == 'function') range = select(card, player);
if (info.singleCard) range = [1, 1];
game.checkMod(card, player, range, 'selectTarget', player);
if (!range) return false;
let cache = CacheContext.requireCacheContext();
for (var i = 0; i < targets.length; i++) {
if (player.canUse(card, targets[i], distance, includecard)) {
var eff = cache.get.effect(targets[i], card, player, player);
if(range[1]==1 && eff > 0){
return true;
}
value.push(eff);
}
}
value.sort(function (a, b) {
return b - a;
});
for (var i = 0; i < value.length; i++) {
if (i == range[1] || range[1] != -1 && value[i] <= 0) break;
min += value[i];
}
return min > 0;
} }
getUseValue(card, distance, includecard) { getUseValue(card, distance, includecard) {
if (typeof (card) == 'string') { if (typeof (card) == 'string') {
@ -6940,10 +6967,7 @@ export class Player extends HTMLDivElement {
game.checkMod(card, player, range, 'selectTarget', player); game.checkMod(card, player, range, 'selectTarget', player);
if (!range) return 0; if (!range) return 0;
let cache = CacheContext.getCacheContext(); let cache = CacheContext.requireCacheContext();
if(!cache){
cache = new CacheContext();
}
for (var i = 0; i < targets.length; i++) { for (var i = 0; i < targets.length; i++) {
if (player.canUse(card, targets[i], distance, includecard)) { if (player.canUse(card, targets[i], distance, includecard)) {
var eff = cache.get.effect(targets[i], card, player, player); var eff = cache.get.effect(targets[i], card, player, player);
@ -8076,7 +8100,7 @@ export class Player extends HTMLDivElement {
return targets; return targets;
} }
isEnemyOf() { isEnemyOf() {
return !this.isFriendOf.apply(this, arguments); return !this.isFriendOf.call(this,...arguments);
} }
isFriendOf(player) { isFriendOf(player) {
if (get.mode() == 'guozhan') { if (get.mode() == 'guozhan') {
@ -10154,3 +10178,6 @@ export class Player extends HTMLDivElement {
} }
} }
} }
CacheContext.inject(Player.prototype,
['hasCard','hasValueTarget','getModableSkills','getCardIndex','countCards','getSkills','getUseValue','canUse']);