475 lines
12 KiB
Lua
475 lines
12 KiB
Lua
-- 基本牌:杀,闪,桃
|
|
|
|
fk.ai_use_card["slash"] = function(self, pattern, prompt, cancelable, extra_data)
|
|
local slashes = self:getCards("slash", "use", extra_data)
|
|
if #slashes == 0 then return nil end
|
|
|
|
-- TODO: 目标合法性
|
|
local targets = {}
|
|
if self.enemies[1] then table.insert(targets, self.enemies[1].id) end
|
|
|
|
return self:buildUseReply(slashes[1].id, targets)
|
|
end
|
|
|
|
fk.ai_use_card["peach"] = function(self, _, _, _, extra_data)
|
|
local cards = self:getCards("peach", "use", extra_data)
|
|
if #cards == 0 then return nil end
|
|
|
|
return self:buildUseReply(cards[1].id)
|
|
end
|
|
|
|
-- 自救见军争卡牌AI
|
|
fk.ai_use_card["#AskForPeaches"] = function(self)
|
|
local room = self.room
|
|
local deathEvent = room.logic:getCurrentEvent()
|
|
local data = deathEvent.data[1] ---@type DyingStruct
|
|
|
|
-- TODO: 关于救不回来、神关羽之类的更复杂逻辑
|
|
-- TODO: 这些逻辑感觉不能写死在此函数里面,得想出更加多样的办法
|
|
if self:isFriend(room:getPlayerById(data.who)) then
|
|
return fk.ai_use_card["peach"](self)
|
|
end
|
|
return nil
|
|
end
|
|
|
|
--[[
|
|
fk.ai_card.slash = {
|
|
intention = 100, -- 身份值
|
|
value = 4, -- 卡牌价值
|
|
priority = 2.5 -- 使用优先值
|
|
}
|
|
fk.ai_card.peach = {
|
|
intention = -150,
|
|
value = 10,
|
|
priority = 0.5
|
|
}
|
|
fk.ai_card.dismantlement = {
|
|
intention = function(self, card, from)
|
|
if #self.player.player_cards[Player.Judge] < 1 then
|
|
return 80
|
|
elseif self.ai_role[from.id] == "neutral" then
|
|
return 30
|
|
end
|
|
end,
|
|
value = 3.5,
|
|
priority = 10.5
|
|
}
|
|
fk.ai_card.snatch = {
|
|
intention = function(self, card, from)
|
|
if #self.player.player_cards[Player.Judge] < 1 then
|
|
return 80
|
|
elseif self.ai_role[from.id] == "neutral" then
|
|
return 30
|
|
end
|
|
end,
|
|
value = 4.5,
|
|
priority = 10.4
|
|
}
|
|
fk.ai_card.duel = {
|
|
intention = 120,
|
|
value = 4.5,
|
|
priority = 3.5
|
|
}
|
|
fk.ai_card.collateral = {
|
|
intention = 20,
|
|
value = 3,
|
|
priority = 4.5
|
|
}
|
|
fk.ai_card.ex_nihilo = {
|
|
intention = -200,
|
|
value = 8,
|
|
priority = 10
|
|
}
|
|
fk.ai_card.savage_assault = {
|
|
intention = 20,
|
|
value = 2,
|
|
priority = 4
|
|
}
|
|
fk.ai_card.archery_attack = {
|
|
intention = 30,
|
|
value = 2,
|
|
priority = 3
|
|
}
|
|
fk.ai_card.god_salvation = {
|
|
intention = function(self, card, from)
|
|
if self.player.hp ~= self.player.maxHp then
|
|
return -45
|
|
end
|
|
end,
|
|
value = 1.5,
|
|
priority = 4
|
|
}
|
|
fk.ai_card.amazing_grace = {
|
|
intention = -30,
|
|
value = 2,
|
|
priority = 2
|
|
}
|
|
fk.ai_card.indulgence = {
|
|
intention = 150,
|
|
value = -1,
|
|
priority = 2
|
|
}
|
|
|
|
local function slashEeffect(slash, to)
|
|
for _, s in ipairs(to:getAllSkills()) do
|
|
if s.name == "#vine_skill" then
|
|
if slash.name == "slash" then
|
|
return
|
|
end
|
|
end
|
|
if s.name == "#nioh_shield_skill" then
|
|
if slash.color == Card.Black then
|
|
return
|
|
end
|
|
end
|
|
end
|
|
return true
|
|
end
|
|
|
|
fk.ai_use_play["slash"] = function(self, card)
|
|
self:sort(self.enemies)
|
|
for _, p in ipairs(self.enemies) do
|
|
if card.skill:targetFilter(p.id, self.use_tos, {}, card) and slashEeffect(card, p) and self:objectiveLevel(p) > 2 then
|
|
self.use_id = card.id
|
|
table.insert(self.use_tos, p.id)
|
|
end
|
|
end
|
|
end
|
|
|
|
fk.ai_use_card["#slash-jink"] = function(self, pattern, prompt, cancelable, extra_data)
|
|
local act = self:getActives(pattern)
|
|
if tonumber(prompt:split(":")[4]) > #act then
|
|
return
|
|
end
|
|
local cards =
|
|
table.map(
|
|
self.player:getCardIds("&he"),
|
|
function(id)
|
|
return Fk:getCardById(id)
|
|
end
|
|
)
|
|
self:sortValue(cards)
|
|
for _, sth in ipairs(act) do
|
|
if sth:isInstanceOf(Card) then
|
|
self.use_id = sth.id
|
|
break
|
|
else
|
|
local selected = {}
|
|
for _, c in ipairs(cards) do
|
|
if sth.cardFilter(sth, c.id, selected) then
|
|
table.insert(selected, c.id)
|
|
end
|
|
end
|
|
local tc = sth.viewAs(sth, selected)
|
|
if tc and tc:matchPattern(pattern) then
|
|
self.use_id =
|
|
json.encode {
|
|
skill = sth.name,
|
|
subcards = selected
|
|
}
|
|
break
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
fk.ai_use_card["#slash-jinks"] = fk.ai_use_card["#slash-jink"]
|
|
|
|
fk.ai_use_play["snatch"] = function(self, card)
|
|
for _, p in ipairs(self.friends_noself) do
|
|
if card.skill:targetFilter(p.id, self.use_tos, {}, card) and #p:getCardIds("j") > 0 then
|
|
self.use_id = card.id
|
|
table.insert(self.use_tos, p.id)
|
|
end
|
|
end
|
|
self:sort(self.enemies)
|
|
for _, p in ipairs(self.enemies) do
|
|
if card.skill:targetFilter(p.id, self.use_tos, {}, card) and #p:getCardIds("he") > 0 then
|
|
self.use_id = card.id
|
|
table.insert(self.use_tos, p.id)
|
|
end
|
|
end
|
|
end
|
|
|
|
fk.ai_nullification.snatch = function(self, card, to, from, positive)
|
|
if positive then
|
|
if self:isFriend(to) and not self:isFriend(from) and self.ai_role[from.id] ~= "neutral" then
|
|
if #self.avail_cards > 1 or self:isWeak(to) or to.id == self.player.id then
|
|
self.use_id = self.avail_cards[1]
|
|
end
|
|
end
|
|
else
|
|
if self:isEnemy(to) and self:isEnemy(from) then
|
|
if #self.avail_cards > 1 or self:isWeak(to) then
|
|
self.use_id = self.avail_cards[1]
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
fk.ai_use_play["dismantlement"] = function(self, card)
|
|
for _, p in ipairs(self.friends_noself) do
|
|
if card.skill:targetFilter(p.id, self.use_tos, {}, card) and #p:getCardIds("j") > 0 then
|
|
self.use_id = card.id
|
|
table.insert(self.use_tos, p.id)
|
|
end
|
|
end
|
|
self:sort(self.enemies)
|
|
for _, p in ipairs(self.enemies) do
|
|
if card.skill:targetFilter(p.id, self.use_tos, {}, card) and #p:getCardIds("he") > 0 then
|
|
self.use_id = card.id
|
|
table.insert(self.use_tos, p.id)
|
|
end
|
|
end
|
|
end
|
|
|
|
fk.ai_nullification.dismantlement = function(self, card, to, from, positive)
|
|
if positive then
|
|
if self:isFriend(to) and not self:isFriend(from) and self.ai_role[from.id] ~= "neutral" then
|
|
if #self.avail_cards > 1 or self:isWeak(to) or to.id == self.player.id then
|
|
self.use_id = self.avail_cards[1]
|
|
end
|
|
end
|
|
else
|
|
if self:isEnemy(to) and self:isEnemy(from) then
|
|
if #self.avail_cards > 1 or self:isWeak(to) then
|
|
self.use_id = self.avail_cards[1]
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
fk.ai_use_play["indulgence"] = function(self, card)
|
|
self:sort(self.enemies, nil, true)
|
|
for _, p in ipairs(self.enemies) do
|
|
if card.skill:targetFilter(p.id, self.use_tos, {}, card) then
|
|
self.use_id = card.id
|
|
table.insert(self.use_tos, p.id)
|
|
end
|
|
end
|
|
end
|
|
|
|
fk.ai_nullification.indulgence = function(self, card, to, from, positive)
|
|
if positive then
|
|
if self:isFriend(to) then
|
|
if #self.avail_cards > 1 or self:isWeak(to) or to.id == self.player.id then
|
|
self.use_id = self.avail_cards[1]
|
|
end
|
|
end
|
|
else
|
|
if self:isEnemy(to) then
|
|
if #self.avail_cards > 1 or self:isWeak(to) then
|
|
self.use_id = self.avail_cards[1]
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
fk.ai_use_play["collateral"] = function(self, card)
|
|
local max = (card.skill:getMaxTargetNum(self.player, card) - 1) * 2
|
|
self:sort(self.enemies)
|
|
for _, p in ipairs(self.enemies) do
|
|
if #self.use_tos < max and card.skill:targetFilter(p.id, {}, {}, card) then
|
|
for _, pt in ipairs(self.enemies) do
|
|
if p ~= pt and p:inMyAttackRange(pt) then
|
|
table.insert(self.use_tos, p.id)
|
|
table.insert(self.use_tos, pt.id)
|
|
self.use_id = card.id
|
|
break
|
|
end
|
|
end
|
|
end
|
|
end
|
|
for _, p in ipairs(self.friends_noself) do
|
|
if #self.use_tos < max and card.skill:targetFilter(p.id, {}, {}, card) then
|
|
for _, pt in ipairs(self.enemies) do
|
|
if p ~= pt and p:inMyAttackRange(pt) then
|
|
table.insert(self.use_tos, p.id)
|
|
table.insert(self.use_tos, pt.id)
|
|
self.use_id = card.id
|
|
break
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
fk.ai_nullification.collateral = function(self, card, to, from, positive)
|
|
if positive then
|
|
if self:isFriend(to) and self:isEnemy(from) then
|
|
if #self.avail_cards > 1 or self:isWeak(to) or to.id == self.player.id then
|
|
self.use_id = self.avail_cards[1]
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
fk.ai_nullification.ex_nihilo = function(self, card, to, from, positive)
|
|
if positive then
|
|
if self:isEnemy(to) then
|
|
if #self.avail_cards > 1 or self:isWeak(to) then
|
|
self.use_id = self.avail_cards[1]
|
|
end
|
|
end
|
|
else
|
|
if self:isFriend(to) then
|
|
if #self.avail_cards > 1 or self:isWeak(to) or to.id == self.player.id then
|
|
self.use_id = self.avail_cards[1]
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
fk.ai_nullification.savage_assault = function(self, card, to, from, positive)
|
|
if positive then
|
|
if self:isFriend(to) then
|
|
if #self.avail_cards > 1 or self:isWeak(to) or to.id == self.player.id then
|
|
self.use_id = self.avail_cards[1]
|
|
end
|
|
end
|
|
else
|
|
if self:isEnemy(to) then
|
|
if #self.avail_cards > 1 or self:isWeak(to) then
|
|
self.use_id = self.avail_cards[1]
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
fk.ai_nullification.archery_attack = function(self, card, to, from, positive)
|
|
if positive then
|
|
if self:isFriend(to) then
|
|
if #self.avail_cards > 1 or self:isWeak(to) or to.id == self.player.id then
|
|
self.use_id = self.avail_cards[1]
|
|
end
|
|
end
|
|
else
|
|
if self:isEnemy(to) then
|
|
if #self.avail_cards > 1 or self:isWeak(to) then
|
|
self.use_id = self.avail_cards[1]
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
fk.ai_nullification.god_salvation = function(self, card, to, from, positive)
|
|
if positive then
|
|
if self:isEnemy(to) and to.hp ~= to.maxHp then
|
|
if #self.avail_cards > 1 or self:isWeak(to) then
|
|
self.use_id = self.avail_cards[1]
|
|
end
|
|
end
|
|
else
|
|
if self:isFriend(to) and to.hp ~= to.maxHp then
|
|
if #self.avail_cards > 1 or self:isWeak(to) or to.id == self.player.id then
|
|
self.use_id = self.avail_cards[1]
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
fk.ai_use_play["god_salvation"] = function(self, card)
|
|
local can = 0
|
|
for _, p in ipairs(self.enemies) do
|
|
if p:isWounded()
|
|
then
|
|
can = can - 1
|
|
if self:isWeak(p)
|
|
then
|
|
can = can - 1
|
|
end
|
|
end
|
|
end
|
|
for _, p in ipairs(self.friends) do
|
|
if p:isWounded()
|
|
then
|
|
can = can + 1
|
|
if self:isWeak(p)
|
|
then
|
|
can = can + 1
|
|
end
|
|
end
|
|
end
|
|
self.use_id = can > 0 and card.id
|
|
end
|
|
|
|
fk.ai_use_play["amazing_grace"] = function(self, card)
|
|
self.use_id = #self.player:getCardIds("&h") <= self.player.hp and card.id
|
|
end
|
|
|
|
fk.ai_use_play["ex_nihilo"] = function(self, card)
|
|
self.use_id = card.id
|
|
end
|
|
|
|
fk.ai_use_play["lightning"] = function(self, card)
|
|
self.use_id = #self.enemies > #self.friends and card.id
|
|
end
|
|
|
|
fk.ai_use_play["peach"] = function(self, card)
|
|
if self.command == "PlayCard" then
|
|
self.use_id = self.player.hp ~= self.player.maxHp and self.player.hp < #self.player:getCardIds("h") and card.id
|
|
else
|
|
for _, p in ipairs(self.friends) do
|
|
if p.dying then
|
|
self.use_id = card.id
|
|
self.use_tos = { p.id }
|
|
break
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
fk.ai_use_play["duel"] = function(self, card)
|
|
self:sort(self.enemies)
|
|
for _, p in ipairs(self.enemies) do
|
|
if card.skill:targetFilter(p.id, self.use_tos, {}, card) then
|
|
self.use_id = card.id
|
|
table.insert(self.use_tos, p.id)
|
|
end
|
|
end
|
|
end
|
|
|
|
fk.ai_skill_invoke["#ice_sword_skill"] = function(self)
|
|
local damage = self:eventData("Damage")
|
|
return self:isFriend(damage.to) or not self:isWeak(damage.to) and #damage.to:getCardIds("e") > 1
|
|
end
|
|
|
|
fk.ai_skill_invoke["#double_swords_skill"] = function(self)
|
|
local use = self:eventData("UseCard")
|
|
for _, p in ipairs(TargetGroup:getRealTargets(use.tos)) do
|
|
if not self:isFriend(p) and self.room:getPlayerById(p).gender ~= self.player.gender then
|
|
return true
|
|
end
|
|
end
|
|
end
|
|
|
|
fk.ai_discard["#double_swords_skill"] = function(self, min_num, num, include_equip, cancelable, pattern, prompt)
|
|
local use = self:eventData("UseCard")
|
|
return self:isEnemy(use.from) and { self.player:getCardIds("h")[1] }
|
|
end
|
|
|
|
fk.ai_discard["#axe_skill"] = function(self, min_num, num, include_equip, cancelable, pattern, prompt)
|
|
local ids = {}
|
|
local effect = self:eventData("CardEffect")
|
|
for _, cid in ipairs(self.player:getCardIds("he")) do
|
|
if Fk:getCardById(cid):matchPattern(pattern) then
|
|
table.insert(ids, cid)
|
|
end
|
|
if #ids >= min_num and self:isEnemy(effect.to)
|
|
and (self:isWeak(effect.to) or #self.player:getCardIds("he") > 3) then
|
|
return ids
|
|
end
|
|
end
|
|
end
|
|
|
|
fk.ai_skill_invoke["#kylin_bow_skill"] = function(self)
|
|
local damage = self:eventData("Damage")
|
|
return not self:isFriend(damage.to)
|
|
end
|
|
|
|
fk.ai_skill_invoke["#eight_diagram_skill"] = function(self)
|
|
local effect = self:eventData("CardEffect")
|
|
return effect and self:isFriend(effect.to)
|
|
end
|
|
--]]
|