├── README ├── AI_Decks.rar ├── AI_ChangedDecks.rar ├── AI ├── ai-cheating.lua ├── mod │ ├── SelectChainOrder.lua │ ├── SelectSum.lua │ ├── DeclareAttribute.lua │ ├── SelectNumber.lua │ ├── DeclareCard.lua │ ├── DeclareMonsterType.lua │ ├── SelectYesNo.lua │ ├── SelectTribute.lua │ ├── SelectEffectYesNo.lua │ ├── SelectOption.lua │ ├── SelectPosition.lua │ ├── AIArchetypeID.lua │ ├── AICheckPossibleST.lua │ ├── AIOnDeckSelect.lua │ └── SelectChain.lua ├── decks │ ├── Fluffal │ │ ├── FluffalChain.lua │ │ ├── FluffalMaterial.lua │ │ ├── FluffalFilter.lua │ │ ├── FluffalBattle.lua │ │ └── FluffalTarget.lua │ ├── ExodiaLib.lua │ ├── Express.lua │ ├── Cth.lua │ ├── DDD.lua │ └── Constellar.lua └── ai.lua ├── .gitattributes ├── LICENSE.md └── .gitignore /README: -------------------------------------------------------------------------------- 1 | The AI script for YGOPro -------------------------------------------------------------------------------- /AI_Decks.rar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Snarkie/YGOProAIScript/HEAD/AI_Decks.rar -------------------------------------------------------------------------------- /AI_ChangedDecks.rar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Snarkie/YGOProAIScript/HEAD/AI_ChangedDecks.rar -------------------------------------------------------------------------------- /AI/ai-cheating.lua: -------------------------------------------------------------------------------- 1 | -- A cheating AI file, which draws additional cards and recovers LP each turn 2 | 3 | 4 | -- Configure these to your liking 5 | 6 | require("ai.ai") 7 | 8 | EXTRA_SUMMON = 1 9 | EXTRA_DRAW = 1 10 | LP_RECOVER = 1000 11 | 12 | GlobalCheating = true 13 | 14 | math.randomseed( require("os").time() ) 15 | function OnStartOfDuel() 16 | 17 | AI.Chat("AI script version "..Version) 18 | AI.Chat("You selected a cheating AI") 19 | AI.Chat("The AI will recover "..LP_RECOVER.." LP and draw "..EXTRA_DRAW.." additional cards each turn") 20 | end 21 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain 23 | -------------------------------------------------------------------------------- /AI/mod/SelectChainOrder.lua: -------------------------------------------------------------------------------- 1 | --- OnSelectChainOrder() --- 2 | -- 3 | -- Called when AI can select a chain order 4 | -- 5 | -- Parameters: 6 | -- cards = table of chain cards to select 7 | -- 8 | -- Return: 9 | -- result = table containing card indices 10 | 11 | function OnSelectChainOrder(cards) 12 | local result = {} 13 | local d = DeckCheck() 14 | if d and d.ChainOrder then 15 | result = d.ChainOrder(cards) 16 | end 17 | if result and #result>0 then 18 | return result 19 | end 20 | result = HEROChainOrder(cards) 21 | if result and #result>0 then 22 | return result 23 | end 24 | result = {} 25 | -- Example implementation: pick the same order as the cards 26 | for i=1,#cards do 27 | result[i]=i 28 | end 29 | return result 30 | end -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Snarkie 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /AI/mod/SelectSum.lua: -------------------------------------------------------------------------------- 1 | --- OnSelectSum --- 2 | -- 3 | -- Called when AI has to select a "sum". The sum can be the levels most of the time, but also something else. (This function is still in beta) 4 | -- Note: if incorrect sum is returned the game will try to adjust 5 | -- 6 | -- Example card(s): Machina Fortress, synchro summons 7 | -- 8 | -- Parameters: 9 | -- cards = table of cards to select 10 | -- sum = the expected sum to return 11 | -- 12 | -- Return: 13 | -- result = table containing target indices 14 | function OnSelectSum(cards,sum,triggeringCard) 15 | local result = nil 16 | local d=DeckCheck() 17 | if d and d.Sum then 18 | result = d.Sum(cards,sum,triggeringCard) 19 | end 20 | if result~=nil then return result end 21 | if DeckCheck(DECK_GADGET) then result = GadgetSum(cards,sum,triggeringCard) end 22 | if result then return result end 23 | if DeckCheck(DECK_NEKROZ) then result = NekrozSum(cards,sum,triggeringCard) end 24 | if result then return result end 25 | 26 | result = {} 27 | local num_levels = 0 28 | for i=1,#cards do 29 | num_levels = num_levels + cards[i].level 30 | result[i]=i 31 | if(num_levels >= sum) then 32 | --end the loop 33 | break 34 | end 35 | end 36 | return result 37 | end -------------------------------------------------------------------------------- /AI/mod/DeclareAttribute.lua: -------------------------------------------------------------------------------- 1 | --- OnDeclareAttribute --- 2 | -- 3 | -- Called when AI has to declare an attribute. 4 | -- Example card(s): DNA Transplant, Gozen Match, Earthshaker 5 | -- 6 | --[[ 7 | Check out the Attributes section in constants.lua 8 | 9 | ATTRIBUTE_EARTH =0x01 10 | ATTRIBUTE_WATER =0x02 11 | ATTRIBUTE_FIRE =0x04 12 | ATTRIBUTE_WIND =0x08 13 | ATTRIBUTE_LIGHT =0x10 14 | ATTRIBUTE_DARK =0x20 15 | ATTRIBUTE_DEVINE =0x40 16 | --]] 17 | -- 18 | -- Parameters (2): 19 | -- count = number of attributes to return 20 | -- choices = table of valid attributes 21 | -- 22 | -- Return: a number containing the selected attributes 23 | function OnDeclareAttribute(count, choices) 24 | local result = nil 25 | local d = DeckCheck() 26 | if d and d.Attribute then 27 | result = d.Attribute(count,choices) 28 | end 29 | if result~=nil then return result end 30 | result = 0 31 | local returnCount = 0 32 | 33 | -- Example implementation: Just return the first valid attribute(s) you come across 34 | while returnCount < count do 35 | result = result + choices[returnCount+1] --add attribute 36 | returnCount = returnCount + 1 37 | end 38 | 39 | return result 40 | 41 | --[[ 42 | --You can return a specific attribute like this: 43 | return ATTRIBUTE_LIGHT --returns the light attribute 44 | 45 | --If more attributes are required then return the sum: 46 | return ATTRIBUTE_WATER+ATTRIBUTE_FIRE --returns water and fire 47 | --]] 48 | end 49 | -------------------------------------------------------------------------------- /AI/mod/SelectNumber.lua: -------------------------------------------------------------------------------- 1 | --- OnSelectNumber --- 2 | -- 3 | -- Called when AI has to declare a number. 4 | -- Example card(s): Reasoning 5 | -- 6 | -- Parameters: 7 | -- choices = table containing the valid choices 8 | -- 9 | -- Return: index of the selected choice 10 | function OnSelectNumber(choices) 11 | local result = nil 12 | ------------------------------------------- 13 | -- The AI should always try to mill as many 14 | -- cards as possible with Card Trooper. 15 | ------------------------------------------- 16 | if GlobalActivatedCardID == 85087012 -- Card Trooper 17 | then 18 | GlobalActivatedCardID = nil 19 | if #AIDeck()>10 then 20 | return 1 21 | else 22 | return 3 23 | end 24 | end 25 | 26 | if GlobalActivatedCardID == 83531441 -- Dante 27 | then 28 | GlobalActivatedCardID = nil 29 | if #AIDeck()>10 30 | and ((OPTCheck(57143342) or OPTCheck(20758643)) 31 | or BattlePhaseCheck()) 32 | then 33 | return 1 34 | else 35 | return 3 36 | end 37 | end 38 | local e,c,id = EffectCheck(1-player_ai) 39 | if e and id == 58577036 then 40 | result = ReasoningNumber() 41 | for i,choice in pairs(choices) do 42 | if choice == result then 43 | return i 44 | end 45 | end 46 | end 47 | local d = DeckCheck() 48 | if d and d.Number then 49 | result = d.Number(id,available) 50 | end 51 | if result~=nil then return result end 52 | 53 | ------------------------------------------- 54 | -- Reset this variable if it gets this far. 55 | ------------------------------------------- 56 | GlobalActivatedCardID = nil 57 | 58 | 59 | -- Example implementation: pick one of the available choices randomly 60 | return math.random(#choices) 61 | end 62 | -------------------------------------------------------------------------------- /AI/mod/DeclareCard.lua: -------------------------------------------------------------------------------- 1 | --- OnDeclareCard --- 2 | -- 3 | -- Called when AI has to declare a card. 4 | -- Example card(s): Prohibition, Mind Crush 5 | -- 6 | -- Parameters: 7 | -- none 8 | -- 9 | -- Return: id of the selected card 10 | function OnDeclareCard() 11 | local result = nil 12 | local d = DeckCheck() 13 | if d and d.DeclareCard then 14 | result = d.DeclareCard() 15 | end 16 | if result~=nil then return result end 17 | result = 85138716 18 | if GlobalActivatedCardID == 10406322 then --Sylvan Alsei 19 | GlobalActivatedCardID = nil 20 | return 14141448 --return ID of Great Moth, to get his 2nd effect 21 | end 22 | -------------------------------------------------- 23 | -- Select random card in player's hand when using 24 | -- "Mind Crush". 25 | -------------------------------------------------- 26 | if GlobalActivatedCardID == 15800838 then 27 | local OppHand = AI.GetOppHand() 28 | for i=1,#OppHand do 29 | if OppHand[i] ~= false then 30 | GlobalActivatedCardID = nil 31 | Result = OppHand[math.random(#OppHand)].id 32 | AITrashTalk("Let's see what card should I chose...") 33 | return Result 34 | end 35 | end 36 | end 37 | 38 | ----------------------------------------------------------------------- 39 | -- Returns id of the card if it exist in any location of the field 40 | -- ** This will be used as a default implementation for now ** 41 | ----------------------------------------------------------------------- 42 | local AllCards = UseLists({OppGrave(),OppDeck(),OppHand(),OppExtra(),OppMon(),OppBanish(),AIMon(),AIDeck(),AIHand(),AIGrave(),AIExtra(),AIBanish()}) 43 | for i=1,#AllCards do 44 | if AllCards[i] ~= false then 45 | Result = AllCards[i].id 46 | return Result 47 | end 48 | end 49 | 50 | -- Example implementation: Return the card id of rescue rabbit 51 | return result 52 | end 53 | -------------------------------------------------------------------------------- /AI/mod/DeclareMonsterType.lua: -------------------------------------------------------------------------------- 1 | --- OnDeclareMonsterType --- 2 | -- 3 | -- Called when AI has to declare a monster type. 4 | -- Example card(s): DNA Surgery, Rivalry of Warlords 5 | -- 6 | --[[ 7 | Check out the Races section in constants.lua 8 | 9 | RACE_WARRIOR =0x1 -- 10 | RACE_SPELLCASTER =0x2 -- 11 | RACE_FAIRY =0x4 -- 12 | RACE_FIEND =0x8 -- 13 | RACE_ZOMBIE =0x10 -- 14 | RACE_MACHINE =0x20 -- 15 | RACE_AQUA =0x40 -- 16 | RACE_PYRO =0x80 -- 17 | RACE_ROCK =0x100 -- 18 | RACE_WINDBEAST =0x200 -- 19 | RACE_PLANT =0x400 -- 20 | RACE_INSECT =0x800 -- 21 | RACE_THUNDER =0x1000 -- 22 | RACE_DRAGON =0x2000 -- 23 | RACE_BEAST =0x4000 -- 24 | RACE_BEASTWARRIOR =0x8000 -- 25 | RACE_DINOSAUR =0x10000 -- 26 | RACE_FISH =0x20000 -- 27 | RACE_SEASERPENT =0x40000 -- 28 | RACE_REPTILE =0x80000 -- 29 | RACE_PSYCHO =0x100000 -- 30 | RACE_DEVINE =0x200000 -- 31 | RACE_CREATORGOD =0x400000 -- 32 | --]] 33 | -- 34 | -- Parameters (2): 35 | -- count = number of types to return 36 | -- choices = table of valid types 37 | -- 38 | -- Return: a number containing the selected types 39 | function OnDeclareMonsterType(count, choices) 40 | local result = nil 41 | local d = DeckCheck() 42 | if d and d.MonsterType then 43 | result = d.MonsterType(count,choices) 44 | end 45 | if result~=nil then return result end 46 | result = 0 47 | local returnCount = 0 48 | 49 | -- Example implementation: Just return the first valid type(s) you come across 50 | while returnCount < count do 51 | result = result + choices[returnCount+1] --add type 52 | returnCount = returnCount + 1 53 | end 54 | 55 | return result 56 | 57 | --[[ 58 | --You can return a specific type like this: 59 | return RACE_WARRIOR --returns the warrior type 60 | 61 | --If more types are required then return the sum: 62 | return RACE_SPELLCASTER+RACE_BEAST --returns spellcaster and beast 63 | --]] 64 | end 65 | -------------------------------------------------------------------------------- /AI/mod/SelectYesNo.lua: -------------------------------------------------------------------------------- 1 | --- OnSelectYesNo() --- 2 | -- 3 | -- Called when AI has to decide something 4 | -- 5 | -- Parameters: 6 | -- description_id = id of the text dialog that is normally shown to the player 7 | -- 8 | -- The descriptions can be found in strings.conf 9 | -- For example, description id 30 = 'Replay, do you want to continue the Battle?' 10 | -- 11 | -- Return: 12 | -- 1 = yes 13 | -- 0 = no 14 | -- -1 = let the ai decide 15 | function GetAttacker() 16 | return GetCardFromScript(Duel.GetAttacker(),AIMon()) 17 | end 18 | 19 | function OnSelectYesNo(description_id) 20 | local result = nil 21 | local d = DeckCheck() 22 | if d and d.YesNo then 23 | result = d.YesNo(description_id) 24 | end 25 | if result then 26 | if result == true then result = 1 end 27 | if result == false then result = 0 end 28 | return result 29 | end 30 | 31 | if description_id == 30 then 32 | local cards = nil 33 | local attacker = GetAttacker() 34 | local attack = 0 35 | if attacker then 36 | cards = {attacker} 37 | ApplyATKBoosts(cards) 38 | attacker = cards[1] 39 | attack = attacker.attack 40 | end 41 | cards=OppMon() 42 | if #cards == 0 then 43 | --return 1 44 | end 45 | if FilterAffected(attacker,EFFECT_DIRECT_ATTACK) then 46 | return 1 47 | end 48 | ApplyATKBoosts(cards) 49 | if CanWinBattle(attacker,cards) then 50 | GlobalCurrentAttacker = attacker.cardid 51 | GlobalAIIsAttacking = true 52 | return 1 53 | else 54 | return 0 55 | end 56 | end 57 | if description_id == 1457766049 then -- Star Seraph Sovereign 58 | if FieldCheck(4) == 1 then 59 | return 1 60 | else 61 | return 0 62 | end 63 | end 64 | if description_id == 1101042113 then -- Harpie Dancer 65 | return DancerYesNo() 66 | end 67 | if description_id == 1044887489 then -- F0 protect 68 | GlobalActivatedCardID = 65305468 69 | return 1 70 | end 71 | if description_id == 30100551*16 then -- Minerva 72 | if DestroyCheck(OppField(),true,true)>0 then 73 | return 1 74 | else 75 | return 0 76 | end 77 | end 78 | return -1 79 | end 80 | 81 | -------------------------------------------------------------------------------- /AI/mod/SelectTribute.lua: -------------------------------------------------------------------------------- 1 | --- OnSelectTribute --- 2 | -- 3 | -- Called when AI has to tribute monster(s). 4 | -- Example card(s): Caius the Shadow Monarch, Beast King Barbaros, Hieratic 5 | -- 6 | -- Parameters (3): 7 | -- cards = available tributes 8 | -- minTributes = minimum number of tributes 9 | -- maxTributes = maximum number of tributes 10 | -- 11 | -- Return: 12 | -- result = table containing tribute indices 13 | 14 | 15 | 16 | --------------------------------------------------- 17 | -- always prefer mind-controlled, whitelisted or 18 | -- token monsters, otherwise check for rank, 19 | -- attack and tribute exceptions. 20 | --------------------------------------------------- 21 | function OnSelectTribute(cards,minTributes, maxTributes) 22 | local preferred = {} 23 | local valid = {} 24 | local result = nil 25 | local d = DeckCheck() 26 | if d and d.Tribute then 27 | result = d.Tribute(cards,minTributes,maxTributes) 28 | end 29 | if result ~= nil then return result end 30 | result = QliphortTribute(cards,minTributes, maxTributes) 31 | if result ~= nil then return result end 32 | if DeckCheck(DECK_CHAOSDRAGON) then 33 | return Add(cards,PRIO_TOGRAVE,minTributes) 34 | end 35 | result = {} 36 | for i=1,#cards do 37 | if cards[i].owner == 2 or TributeWhitelist(cards[i].id) > 0 or 38 | bit32.band(cards[i].type,TYPE_TOKEN) > 0 then 39 | preferred[#preferred+1]=i 40 | elseif cards[i].rank == 0 and cards[i].level <= GlobalActivatedCardLevel and 41 | cards[i].attack < GlobalActivatedCardAttack and IsTributeException(cards[i].id) == 0 then 42 | valid[#valid+1]=i 43 | end 44 | end 45 | for i=1,minTributes do 46 | if preferred[i] then 47 | result[i]=preferred[i] 48 | else 49 | result[i]=valid[i-#preferred] 50 | end 51 | end 52 | return result 53 | end 54 | --from OnSelectCard 55 | function OnSelectMaterial(cards,min,max,id) 56 | local result = nil 57 | local d = DeckCheck() 58 | if d and d.Material then 59 | result = d.Material(cards,min,max,id) 60 | end 61 | if result ~= nil then return result end 62 | if id == 18326736 then -- Ptolemaios 63 | if GlobalPtolemaiosID == 10443957 -- Cyber Dragon Infinity 64 | then 65 | GlobalPtolemaiosID = nil 66 | return Add(cards,PRIO_TOGRAVE,math.max(min,math.min(3,max))) 67 | end 68 | if GlobalPtolemaiosID == 09272381 -- Constellarknight Diamond 69 | then 70 | GlobalPtolemaiosID = nil 71 | return Add(cards,PRIO_TOGRAVE,2) 72 | end 73 | end 74 | if id == 09272381 -- Constellarknight Diamond 75 | then 76 | return Add(cards,PRIO_TOGRAVE,min) 77 | end 78 | return Add(cards,PRIO_TOGRAVE,min) 79 | end 80 | 81 | 82 | 83 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /AI/mod/SelectEffectYesNo.lua: -------------------------------------------------------------------------------- 1 | --- OnSelectEffectYesNo() --- 2 | -- 3 | -- Called when AI has to decide whether to activate a card effect 4 | -- 5 | -- Parameters: 6 | -- id = card id of the effect 7 | -- 8 | -- Return: 9 | -- 1 = yes 10 | -- 0 = no 11 | 12 | function OnSelectEffectYesNo(id,triggeringCard) 13 | if not player_ai then player_ai = 1 end -- probably puzzle mode, so player goes first 14 | local result = nil 15 | if not InfiniteLoopCheck(triggeringCard) then 16 | return 0 17 | end 18 | local d = DeckCheck() 19 | if d and d.EffectYesNo then 20 | result = d.EffectYesNo(id,triggeringCard) 21 | end 22 | if result then 23 | if result == true then result = 1 end 24 | if result == false then result = 0 end 25 | return result 26 | end 27 | local YesNoFunctions = { 28 | FireFistOnSelectEffectYesNo,MermailOnSelectEffectYesNo, 29 | GadgetOnSelectEffectYesNo, 30 | HeraldicOnSelectEffectYesNo,SatellarknightOnSelectEffectYesNo, 31 | ChaosDragonOnSelectEffectYesNo,HATEffectYesNo,QliphortEffectYesNo, 32 | NobleEffectYesNo,NekrozEffectYesNo,BAEffectYesNo,DarkWorldEffectYesNo, 33 | BujinOnSelectEffectYesNo,GenericEffectYesNo,ConstellarEffectYesNo, 34 | BlackwingEffectYesNo,HarpieEffectYesNo,HEROEffectYesNo, 35 | } 36 | for i=1,#YesNoFunctions do 37 | local func = YesNoFunctions[i] 38 | if result == nil then 39 | result = func(id,triggeringCard) 40 | end 41 | end 42 | if result then 43 | if result == true then 44 | result = 1 45 | end 46 | if result == false then result = 0 end 47 | return result 48 | end 49 | if CardIsScripted(id)>0 then 50 | result = 0 51 | else 52 | result = 1 53 | end 54 | 55 | if id == 92661479 or id == 94283662 -- Bounzer, Trance Archfiend 56 | or id == 52624755 or id == 50091196 -- Peten, Formula 57 | or id == 80344569 or id == 78156759 -- Grand Mole, Zenmaines 58 | then 59 | result = 1 60 | end 61 | 62 | if id == 40619825 then -- Axe of Despair 63 | if Get_Card_Count(AIMon()) >= 2 then 64 | GlobalActivatedEffectID = id 65 | GlobalCardMode = 1 66 | result = 1 67 | end 68 | end 69 | 70 | if id == 73580471 then -- Black Rose Dragon 71 | if Get_Card_Att_Def(OppMon(),"attack",">",POS_FACEUP,"attack") > Get_Card_Att_Def(AIMon(),"attack",">",POS_FACEUP,"attack") or Card_Count_Affected_By(EFFECT_INDESTRUCTABLE_BATTLE,OppMon()) > 0 then 72 | result = 1 73 | end 74 | end 75 | 76 | if id == 15028680 then -- HTS Psyhemuth 77 | if Get_Card_Att_Def_Pos(OppMon()) >= 2400 then 78 | return 1 79 | end 80 | return 0 81 | end 82 | 83 | -- always activate Dragon Ruler's on banish effects 84 | if id==53804307 and FilterLocation(triggeringCard,LOCATION_REMOVED) then 85 | return 1,CurrentIndex 86 | end 87 | if id==26400609 and FilterLocation(triggeringCard,LOCATION_REMOVED) then 88 | return 1,CurrentIndex 89 | end 90 | if id==89399912 and FilterLocation(triggeringCard,LOCATION_REMOVED) then 91 | return 1,CurrentIndex 92 | end 93 | if id==90411554 and FilterLocation(triggeringCard,LOCATION_REMOVED) then 94 | return 1,CurrentIndex 95 | end 96 | if result==1 then 97 | GlobalActivatedEffectID = id 98 | end 99 | return result 100 | end 101 | 102 | -------------------------------------------------------------------------------- /AI/mod/SelectOption.lua: -------------------------------------------------------------------------------- 1 | --- OnSelectOption() --- 2 | -- 3 | -- Called when AI has to choose an option 4 | -- Example card(s): Elemental HERO Stratos 5 | -- 6 | -- Parameters: 7 | -- options = table of available options, this is one of the strings from the card database (str1, str2, str3, ..) 8 | -- 9 | -- Return: index of the selected option 10 | function OnSelectOption(options) 11 | local result = nil 12 | local d = DeckCheck() 13 | if d and d.Option then 14 | result = d.Option(options) 15 | end 16 | if result~=nil then return result end 17 | local optionfunctions={ 18 | HeraldicOnSelectOption,QliphortOption, 19 | NekrozOption,DarkWorldOption,ConstellarOption, 20 | HarpieOption 21 | } 22 | for i=1,#optionfunctions do 23 | local func = optionfunctions[i] 24 | result = func(options) 25 | if result ~= nil then 26 | return result 27 | end 28 | end 29 | 30 | if GlobalDimensionalBarrier then 31 | local BarrierType={ 32 | [TYPE_RITUAL]=1057, 33 | [TYPE_FUSION]=1056, 34 | [TYPE_SYNCHRO]=1063, 35 | [TYPE_XYZ]=1073, 36 | [TYPE_PENDULUM]=1074,} 37 | if GlobalDimensionalBarrier == true then 38 | local cards={} 39 | local highest=0 40 | result = nil 41 | for i,v in pairs(BarrierType) do 42 | cards[i]=CardsMatchingFilter(OppMon(),FilterType,i)*2 43 | + CardsMatchingFilter(SubGroup(OppGrave(),FilterType,TYPE_MONSTER),FilterType,i) 44 | + CardsMatchingFilter(SubGroup(OppExtra(),FilterPosition,POS_FACEUP),FilterType,i) 45 | if cards[i]>highest then 46 | highest=cards[i] 47 | result=v 48 | end 49 | end 50 | result=result or 1073 51 | else 52 | result = BarrierType[GlobalDimensionalBarrier] 53 | end 54 | GlobalDimensionalBarrier = nil 55 | for i,v in pairs(options) do 56 | if v==result then 57 | return i 58 | end 59 | end 60 | end 61 | 62 | 63 | for i=1,#options do -- Ptolemy M7 64 | if options[i]==38495396*16+2 65 | and HasPriorityTarget(OppMon(),false,nil,PtolemyFilter) 66 | then 67 | return i 68 | elseif options[i]==38495396*16+3 then 69 | return i 70 | end 71 | end 72 | 73 | result = 0 74 | ------------------------------------------------------ 75 | -- Return random result if it isn't specified below. 76 | ------------------------------------------------------ 77 | if GlobalActivatedCardID ~= 98045062 and GlobalActivatedCardID ~= 34086406 and -- Enemy Controller, Lavalval Chain 78 | GlobalActivatedCardID ~= 12014404 and GlobalActivatedCardID ~= 70908596 then -- Gagaga Gunman, Constellar Kaust 79 | result = math.random(#options) 80 | return result 81 | end 82 | 83 | if GlobalActivatedCardID == 98045062 then -- Enemy Controller 84 | for i=1,#options do 85 | if options[i] == 1568720992 then 86 | result = i 87 | end 88 | end 89 | end 90 | 91 | if GlobalActivatedCardID == 34086406 then -- Lavalval Chain 92 | for i=1,#options do 93 | if options[i] == 1 then 94 | result = i 95 | end 96 | end 97 | end 98 | 99 | if GlobalActivatedCardID == 12014404 then -- Gagaga Gunman 100 | for i=1,#options do 101 | if options[i] == 1 then 102 | result = i 103 | end 104 | end 105 | end 106 | 107 | end 108 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ################# 2 | ## Eclipse 3 | ################# 4 | 5 | *.pydevproject 6 | .project 7 | .metadata 8 | bin/ 9 | tmp/ 10 | *.tmp 11 | *.bak 12 | *.swp 13 | *~.nib 14 | local.properties 15 | .classpath 16 | .settings/ 17 | .loadpath 18 | 19 | # External tool builders 20 | .externalToolBuilders/ 21 | 22 | # Locally stored "Eclipse launch configurations" 23 | *.launch 24 | 25 | # CDT-specific 26 | .cproject 27 | 28 | # PDT-specific 29 | .buildpath 30 | 31 | 32 | ################# 33 | ## Visual Studio 34 | ################# 35 | 36 | ## Ignore Visual Studio temporary files, build results, and 37 | ## files generated by popular Visual Studio add-ons. 38 | 39 | # User-specific files 40 | *.suo 41 | *.user 42 | *.sln.docstates 43 | 44 | # Build results 45 | 46 | [Dd]ebug/ 47 | [Rr]elease/ 48 | x64/ 49 | build/ 50 | [Bb]in/ 51 | [Oo]bj/ 52 | 53 | # MSTest test Results 54 | [Tt]est[Rr]esult*/ 55 | [Bb]uild[Ll]og.* 56 | 57 | *_i.c 58 | *_p.c 59 | *.ilk 60 | *.meta 61 | *.obj 62 | *.pch 63 | *.pdb 64 | *.pgc 65 | *.pgd 66 | *.rsp 67 | *.sbr 68 | *.tlb 69 | *.tli 70 | *.tlh 71 | *.tmp 72 | *.tmp_proj 73 | *.log 74 | *.vspscc 75 | *.vssscc 76 | .builds 77 | *.pidb 78 | *.log 79 | *.scc 80 | 81 | # Visual C++ cache files 82 | ipch/ 83 | *.aps 84 | *.ncb 85 | *.opensdf 86 | *.sdf 87 | *.cachefile 88 | 89 | # Visual Studio profiler 90 | *.psess 91 | *.vsp 92 | *.vspx 93 | 94 | # Guidance Automation Toolkit 95 | *.gpState 96 | 97 | # ReSharper is a .NET coding add-in 98 | _ReSharper*/ 99 | *.[Rr]e[Ss]harper 100 | 101 | # TeamCity is a build add-in 102 | _TeamCity* 103 | 104 | # DotCover is a Code Coverage Tool 105 | *.dotCover 106 | 107 | # NCrunch 108 | *.ncrunch* 109 | .*crunch*.local.xml 110 | 111 | # Installshield output folder 112 | [Ee]xpress/ 113 | 114 | # DocProject is a documentation generator add-in 115 | DocProject/buildhelp/ 116 | DocProject/Help/*.HxT 117 | DocProject/Help/*.HxC 118 | DocProject/Help/*.hhc 119 | DocProject/Help/*.hhk 120 | DocProject/Help/*.hhp 121 | DocProject/Help/Html2 122 | DocProject/Help/html 123 | 124 | # Click-Once directory 125 | publish/ 126 | 127 | # Publish Web Output 128 | *.Publish.xml 129 | *.pubxml 130 | 131 | # NuGet Packages Directory 132 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line 133 | #packages/ 134 | 135 | # Windows Azure Build Output 136 | csx 137 | *.build.csdef 138 | 139 | # Windows Store app package directory 140 | AppPackages/ 141 | 142 | # Others 143 | sql/ 144 | *.Cache 145 | ClientBin/ 146 | [Ss]tyle[Cc]op.* 147 | ~$* 148 | *~ 149 | *.dbmdl 150 | *.[Pp]ublish.xml 151 | *.pfx 152 | *.publishsettings 153 | 154 | # RIA/Silverlight projects 155 | Generated_Code/ 156 | 157 | # Backup & report files from converting an old project file to a newer 158 | # Visual Studio version. Backup files are not needed, because we have git ;-) 159 | _UpgradeReport_Files/ 160 | Backup*/ 161 | UpgradeLog*.XML 162 | UpgradeLog*.htm 163 | 164 | # SQL Server files 165 | App_Data/*.mdf 166 | App_Data/*.ldf 167 | 168 | ############# 169 | ## Windows detritus 170 | ############# 171 | 172 | # Windows image file caches 173 | Thumbs.db 174 | ehthumbs.db 175 | 176 | # Folder config file 177 | Desktop.ini 178 | 179 | # Recycle Bin used on file shares 180 | $RECYCLE.BIN/ 181 | 182 | # Mac crap 183 | .DS_Store 184 | 185 | 186 | ############# 187 | ## Python 188 | ############# 189 | 190 | *.py[co] 191 | 192 | # Packages 193 | *.egg 194 | *.egg-info 195 | dist/ 196 | build/ 197 | eggs/ 198 | parts/ 199 | var/ 200 | sdist/ 201 | develop-eggs/ 202 | .installed.cfg 203 | 204 | # Installer logs 205 | pip-log.txt 206 | 207 | # Unit test / coverage reports 208 | .coverage 209 | .tox 210 | 211 | #Translations 212 | *.mo 213 | 214 | #Mr Developer 215 | .mr.developer.cfg 216 | AI/decks/Decklist.txt 217 | -------------------------------------------------------------------------------- /AI/decks/Fluffal/FluffalChain.lua: -------------------------------------------------------------------------------- 1 | ------------------------ 2 | -------- CHAIN --------- 3 | ------------------------ 4 | -- OtherM CHAIN 5 | function ChainMaxxCFluffal(c) 6 | return 7 | CardsMatchingFilter(OppField(),MaxxCAdvantageFilter) > 0 8 | or ( 9 | HasID(OppExtra(),90809975,true) -- Toadally Awesome 10 | and CardsMatchingFilter(OppMon(),FilterRace,RACE_AQUA) >= 2 11 | and CardsMatchingFilter(OppMon(),FilterLevel,2) >= 2 12 | ) 13 | or ( 14 | CardsMatchingFilter(OppMon(),FilterAttribute,ATTRIBUTE_WIND) > 0 15 | and HasID(OppHand(),53932291,true) -- Speedroid Taketomborg 16 | ) 17 | end 18 | -- Spell CHAIN 19 | function ChainMSpring(c) 20 | if FluffalRemovalCheckCard(c) 21 | or UseMSpring(c) and Duel.GetCurrentPhase()==PHASE_MAIN1 22 | then 23 | return true 24 | else 25 | return false 26 | end 27 | return false 28 | end 29 | -- Trap CHAIN 30 | function ChainFReserve(c) 31 | if FluffalRemovalCheckCard(c) 32 | then 33 | return true 34 | elseif Duel.GetCurrentPhase() == PHASE_END 35 | and CardsMatchingFilter(OppST(),MSTEndPhaseFilter) > 0 36 | and HasID(AIGrave(),24094653,true) -- Polymerization 37 | then 38 | return true 39 | else 40 | return false 41 | end 42 | end 43 | function ChainJAvarice(c) 44 | return 45 | FluffalRemovalCheckCard(c) 46 | or Duel.GetCurrentPhase() == PHASE_END 47 | --or UseJAvarice(c) 48 | end 49 | 50 | function FluffalRemovalCheckCard(c) 51 | return 52 | RemovalCheckCard(c,CATEGORY_DESTROY) 53 | or RemovalCheckCard(c,CATEGORY_REMOVE) 54 | or RemovalCheckCard(c,CATEGORY_TOGRAVE) 55 | or RemovalCheckCard(c,CATEGORY_TOHAND) 56 | or RemovalCheckCard(c,CATEGORY_REMOVE) 57 | end 58 | GlobalOppMaxxC = 0 59 | function FluffalChain(cards) -- FLUFFAL CHAIN 60 | --print("Fluffal Chain") 61 | if HasIDNotNegated(cards,90809975,false,(90809975*16)+1,ChainNegation) -- Toadally 62 | then 63 | OPTSet(cards[CurrentIndex].cardid) 64 | return {1,CurrentIndex} 65 | end 66 | if HasID(cards,40636712,UseFKrakenRepo) then 67 | return {1,CurrentIndex} 68 | end 69 | if HasID(cards,23434538,ChainMaxxCFluffal) then 70 | return {1,CurrentIndex} 71 | end 72 | if HasID(cards,43455065,ChainMSpring) then -- MSpring 73 | return {1,CurrentIndex} 74 | end 75 | if HasID(cards,43898403,ChainTwinTwister) then -- TwinTwisters 76 | return {1,CurrentIndex} 77 | end 78 | if HasIDNotNegated(cards,66127916,ChainFReserve) then -- FReserve 79 | return {1,CurrentIndex} 80 | end 81 | if HasIDNotNegated(cards,98954106,ChainJAvarice) then -- JAvarice 82 | return {1,CurrentIndex} 83 | end 84 | if HasIDNotNegated(cards,51452091,false) then -- RDecree 85 | return {1,CurrentIndex} 86 | end 87 | 88 | -- Opp Maxx "C" 89 | --if GlobalOppMaxxC ~= Duel.GetTurnCount() then 90 | --for i=1,Duel.GetCurrentChain() do 91 | --local p = Duel.GetChainInfo(i, CHAININFO_TRIGGERING_PLAYER) 92 | --local e = Duel.GetChainInfo(i, CHAININFO_TRIGGERING_EFFECT) 93 | --local c = nil 94 | --if e and p and (p == 1- player_ai) then 95 | --c=e:GetHandler() 96 | --if c then 97 | --if c:GetCode() == 23434538 then 98 | --print("OppMaxxC") 99 | --GlobalOppMaxxC = Duel.GetTurnCount() 100 | --end 101 | --end 102 | --end 103 | --end 104 | --end 105 | 106 | return nil 107 | end 108 | 109 | function FluffalChainOrder(cards) -- FLUFFAL CHAIN ORDER 110 | --print("FluffalChainOrder") 111 | local result = {} 112 | 113 | for i=1,#cards do 114 | local c = cards[i] 115 | if c.level > 4 then -- To protect Frightfur 116 | result[#result + 1] = i 117 | end 118 | end 119 | for i=1,#cards do 120 | local c = cards[i] 121 | if c.id == 39246582 then -- To protect Dog 122 | result[#result + 1] = i 123 | end 124 | end 125 | for i=1,#cards do 126 | local c = cards[i] 127 | if c.id == 13241004 then -- To protect Penguin 128 | result[#result + 1] = i 129 | end 130 | end 131 | for i=1,#cards do 132 | local c=cards[i] 133 | if c.level < 5 134 | and c.level > 0 135 | and not (c.id == 39246582) -- Exclude Dog 136 | and not (c.id == 13241004) -- Exclude Penguin 137 | then 138 | result[#result + 1] = i 139 | end 140 | end 141 | -- ST 142 | for i=1,#cards do 143 | local c=cards[i] 144 | if c.level < 1 145 | then 146 | result[#result + 1] = i 147 | end 148 | end 149 | 150 | return result 151 | end -------------------------------------------------------------------------------- /AI/ai.lua: -------------------------------------------------------------------------------- 1 | Version = "0.35" 2 | Experimental = false 3 | 4 | --[[ 5 | AI Script for YGOPro Percy: 6 | http://www.ygopro.co/ 7 | 8 | script by Snarky 9 | original script by Percival18 10 | 11 | GitHub repository: 12 | https://github.com/Snarkie/YGOProAIScript/ 13 | 14 | Check here for updates: 15 | http://www.ygopro.co/Forum/tabid/95/g/posts/t/7877/AI-Updates 16 | 17 | Contributors: ytterbite, Sebrian, Skaviory, francot514 18 | Optional decks: Yeon, Satone, rothayz, Ildana, Iroha, Postar, Nachk, Xaddgx, neftalimich 19 | You can find and download optional decks here: 20 | http://www.ygopro.co/Forum/tabid/95/g/posts/t/7877/AI-Updates 21 | 22 | for more information about the AI script, check the ai-template.lua 23 | 24 | 25 | 26 | The MIT License (MIT) 27 | 28 | Copyright (c) 2015 Snarky 29 | 30 | Permission is hereby granted, free of charge, to any person obtaining a copy 31 | of this software and associated documentation files (the "Software"), to deal 32 | in the Software without restriction, including without limitation the rights 33 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 34 | copies of the Software, and to permit persons to whom the Software is 35 | furnished to do so, subject to the following conditions: 36 | 37 | The above copyright notice and this permission notice shall be included in all 38 | copies or substantial portions of the Software. 39 | 40 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 41 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 42 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 43 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 44 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 45 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 46 | SOFTWARE. 47 | 48 | ]] 49 | 50 | GlobalCheating = false 51 | TRASHTALK = true -- some decks might comment their actions. Set to false, if you don't like that 52 | EXTRA_DRAW = 0 53 | EXTRA_SUMMON = 0 54 | LP_RECOVER = 0 55 | 56 | PRINT_DRAW = 1 -- for debugging 57 | 58 | function requireoptional(module) 59 | if not pcall(require,module) then 60 | --print("file missing or syntax error: "..module) 61 | end 62 | end 63 | require("ai.mod.AICheckList") 64 | require("ai.mod.AIHelperFunctions") 65 | require("ai.mod.AIHelperFunctions2") 66 | require("ai.mod.AICheckPossibleST") 67 | require("ai.mod.AIOnDeckSelect") 68 | require("ai.mod.DeclareAttribute") 69 | require("ai.mod.DeclareCard") 70 | require("ai.mod.DeclareMonsterType") 71 | require("ai.mod.SelectBattleCommand") 72 | require("ai.mod.SelectCard") 73 | require("ai.mod.SelectChain") 74 | require("ai.mod.SelectEffectYesNo") 75 | require("ai.mod.SelectInitCommand") 76 | require("ai.mod.SelectNumber") 77 | require("ai.mod.SelectOption") 78 | require("ai.mod.SelectPosition") 79 | require("ai.mod.SelectSum") 80 | require("ai.mod.SelectTribute") 81 | require("ai.mod.SelectYesNo") 82 | require("ai.mod.SelectChainOrder") 83 | require("ai.decks.Generic") 84 | require("ai.decks.FireFist") 85 | require("ai.decks.HeraldicBeast") 86 | require("ai.decks.Gadget") 87 | require("ai.decks.BLS") 88 | require("ai.decks.Bujin") 89 | require("ai.decks.Mermail") 90 | require("ai.decks.Shaddoll") 91 | require("ai.decks.Satellarknight") 92 | require("ai.decks.ChaosDragon") 93 | require("ai.decks.HAT") 94 | require("ai.decks.Qliphort") 95 | require("ai.decks.NobleKnight") 96 | require("ai.decks.Nekroz") 97 | require("ai.decks.BurningAbyss") 98 | require("ai.decks.DarkWorld") 99 | require("ai.decks.Constellar") 100 | require("ai.decks.Blackwing") 101 | require("ai.decks.Harpie") 102 | require("ai.decks.HERO") 103 | require("ai.decks.ExodiaLib") 104 | require("ai.decks.Boxer") 105 | require("ai.decks.Monarch") 106 | require("ai.decks.MegaMonarch") 107 | require("ai.decks.Kozmo") 108 | require("ai.decks.Lightsworn") 109 | require("ai.decks.DDD") 110 | require("ai.decks.GladBeast") 111 | require("ai.decks.ABC") 112 | require("ai.decks.Raidraptor") 113 | require("ai.decks.Eidolon") 114 | requireoptional("ai.decks.ZodiacBeast") 115 | requireoptional("ai.decks.Fluffal") 116 | requireoptional("ai.decks.Majespecter") 117 | requireoptional("ai.decks.Spellbook") 118 | requireoptional("ai.decks.X-Saber") 119 | requireoptional("ai.decks.Cth") 120 | requireoptional("ai.decks.Wizard") 121 | requireoptional("ai.decks.Express") 122 | 123 | math.randomseed( require("os").time() ) 124 | 125 | function OnStartOfDuel() 126 | AI.Chat("AI script version "..Version) 127 | --if Experimental then AI.Chat("This is an experimental AI version, it might contain bugs and misplays") end 128 | print("start of duel") 129 | Startup() 130 | end 131 | 132 | 133 | -------------------------------------------------------------------------------- /AI/mod/SelectPosition.lua: -------------------------------------------------------------------------------- 1 | --- OnSelectPosition --- 2 | -- 3 | -- Called when AI has to select the monster position. 4 | -- 5 | -- Parameters (2): 6 | -- id = card id 7 | -- available = available positions 8 | -- 9 | -- Return: the position 10 | --[[ 11 | From constants.lua 12 | POS_FACEUP_ATTACK =0x1 13 | POS_FACEDOWN_ATTACK =0x2 14 | POS_FACEUP_DEFENSE =0x4 15 | POS_FACEDOWN_DEFENSE =0x8 16 | --]] 17 | function OnSelectPosition(id, available) 18 | local result = 0 19 | local band = bit32.band --assign bit32.band() to a local variable 20 | result = POS_FACEUP_ATTACK 21 | 22 | ------------------------------------------------------- 23 | -- If a dragon is summoned by the effect of a Hieratic 24 | -- monster, always summon it in defense mode, as his 25 | -- attack and defense will be 0 26 | ------------------------------------------------------- 27 | if GlobalActivatedCardID == 27337596 -- Hieratic Dragon King of Atum 28 | or GlobalActivatedCardID == 07394770 -- Brilliant Fusion 29 | then 30 | result = POS_FACEUP_DEFENSE 31 | GlobalActivatedCardID = nil 32 | GlobalTributedCardID = nil 33 | return result 34 | end 35 | 36 | ------------------------------------------------------ 37 | -- Check if AI's monster's attack is lower than of strongest player's monster, 38 | -- or if any actions can be taken to gain advantage over player. 39 | -- Then summon or set monster in available position depending on results. 40 | ------------------------------------------------------ 41 | if band(POS_FACEDOWN_DEFENSE,available) > 0 and Get_Card_Count_Pos(OppMon(), POS_FACEUP) > 0 then 42 | if AIMonGetAttackById(id) < Get_Card_Att_Def(OppMon(),"attack",">",POS_FACEUP_ATTACK,"attack") and CanChangeOutcomeSS(id) == 0 and AIMonGetAttackById(id) < 2400 then -- Also check if any action can be taken by CanChangeOutcomeSS 43 | result = POS_FACEDOWN_DEFENSE 44 | end 45 | end 46 | if band(POS_FACEUP_DEFENSE,available) > 0 and Get_Card_Count_Pos(OppMon(), POS_FACEUP) > 0 then 47 | if AIMonGetAttackById(id) < Get_Card_Att_Def(OppMon(),"attack",">",POS_FACEUP_ATTACK,"attack") and CanChangeOutcomeSS(id) == 0 and AIMonGetAttackById(id) < 2400 then -- Also check if any action can be taken by CanChangeOutcomeSS 48 | result = POS_FACEUP_DEFENSE 49 | end 50 | end 51 | ------------------------------------------------------- 52 | -- If Treeborn Frog is being special summoned, check if 53 | -- Creature Swap is in hand, the opponent controls 1 54 | -- monster, and the AI controls no other monsters. 55 | -- 56 | -- If so, let the AI be a troll and special summon the 57 | -- frog in attack position! 58 | ------------------------------------------------------- 59 | if id == 12538374 then 60 | if Get_Card_Count_ID(AIHand(),31036355,nil) == 0 or 61 | Get_Card_Count(OppMon()) ~= 1 or 62 | Get_Card_Count(AIMon()) ~= 0 then 63 | result = POS_FACEUP_DEFENSE 64 | end 65 | end 66 | 67 | ------------------------------------ 68 | -- Cards to be always summoned in 69 | -- defense position. 70 | -- Expanding upon the above example. 71 | -- More cards to be added later. 72 | ------------------------------------ 73 | if id == 19665973 or id == 52624755 or -- Battle Fader, Peten the Dark Clown, 74 | id == 10002346 or id == 90411554 or -- Gachi Gachi, Redox 75 | id == 33420078 or id == 15394084 or -- Plaguespreader, Nordic Beast Token 76 | id == 58058134 or id == 10389142 or -- Slacker Magician, Tomahawk 77 | id == 46384403 or id == 14677495 then -- Nimble Manta, Tanngnjostr 78 | 79 | result = POS_FACEUP_DEFENSE 80 | end 81 | 82 | ------------------------------------ 83 | -- Cards to be always summoned in 84 | -- attack position. 85 | -- Expanding upon the above example. 86 | -- More cards to be added later. 87 | ------------------------------------ 88 | if id == 64631466 or id == 70908596 -- Relinquished, Constellar Kaust 89 | or id == 88241506 then -- Maiden with Eyes of Blue 90 | result = POS_FACEUP_ATTACK 91 | end 92 | local positionfunctions={ 93 | FireFistOnSelectPosition,HeraldicOnSelectPosition,GadgetOnSelectPosition, 94 | BujinOnSelectPosition,MermailOnSelectPosition, 95 | SatellarknightOnSelectPosition,ChaosDragonOnSelectPosition,HATPosition, 96 | QliphortPosition,NoblePosition,NekrozPosition,BAPosition, 97 | DarkWorldPosition,ConstellarPosition,BlackwingPosition, 98 | GenericPosition,HarpiePosition,HEROPosition, 99 | } 100 | for i=1,#positionfunctions do 101 | local func = positionfunctions[i] 102 | if func then 103 | local Position = func(id,available) 104 | if Position then result=Position end 105 | end 106 | end 107 | local d = DeckCheck() 108 | if d and d.Position then 109 | local Position = d.Position(id,available) 110 | if Position then result=Position end 111 | end 112 | if result == nil then result = POS_FACEUP_ATTACK end 113 | if band(result,available) == 0 then 114 | if band(POS_FACEUP_ATTACK,available) > 0 then 115 | result = POS_FACEUP_ATTACK 116 | elseif band(POS_FACEUP_DEFENSE,available) > 0 then 117 | result = POS_FACEUP_DEFENSE 118 | elseif band(POS_FACEDOWN_DEFENSE,available) > 0 then 119 | result = POS_FACEDOWN_DEFENSE 120 | else 121 | result = POS_FACEDOWN_ATTACK 122 | end 123 | end 124 | return result 125 | end 126 | -------------------------------------------------------------------------------- /AI/decks/ExodiaLib.lua: -------------------------------------------------------------------------------- 1 | -- ExodiaLib: 2 | function ExodiaInit(cards) 3 | local summon = cards.summonable_cards 4 | local activate = cards.activatable_cards 5 | local cardid = 0 6 | 7 | for i=1,#summon do 8 | if summon[i].id == 70791313 then --royal magic library 9 | return COMMAND_SUMMON,i 10 | end 11 | end 12 | 13 | for i=1,#activate do 14 | cardid = activate[i].id 15 | if cardid == 39910367 then --endymion 16 | return COMMAND_ACTIVATE,i 17 | end 18 | end 19 | 20 | for i=1,#activate do 21 | cardid = activate[i].id 22 | if cardid == 70791313 then --royal magic library 23 | return COMMAND_ACTIVATE,i 24 | end 25 | end 26 | for i=1,#activate do 27 | cardid = activate[i].id 28 | if cardid == 89997728 then --toon table of contents 29 | if HasID(AIMon(),70791313,true) then 30 | return COMMAND_ACTIVATE,i 31 | end 32 | end 33 | end 34 | local c = FindID(70791313,AIMon()) 35 | if HasID(activate,75014062) and c and c:get_counter(0x3001)<2 then -- Spell Power Grasp 36 | return COMMAND_ACTIVATE,CurrentIndex 37 | end 38 | if HasID(activate,55144522) then -- Pot of Greed 39 | return COMMAND_ACTIVATE,CurrentIndex 40 | end 41 | if HasID(activate,74029853) then -- Golden Bamboo Sword 42 | return COMMAND_ACTIVATE,CurrentIndex 43 | end 44 | if HasID(activate,41587307) then -- Broken Bamboo Sword 45 | return COMMAND_ACTIVATE,CurrentIndex 46 | end 47 | for i=1,#activate do 48 | cardid = activate[i].id 49 | if cardid == 39701395 then --cards of consonance 50 | return COMMAND_ACTIVATE,i 51 | end 52 | end 53 | for i=1,#activate do 54 | cardid = activate[i].id 55 | if cardid == 38120068 then --trade-in 56 | return COMMAND_ACTIVATE,i 57 | end 58 | end 59 | 60 | for i=1,#activate do 61 | cardid = activate[i].id 62 | if cardid == 98645731 then --pot of duality 63 | return COMMAND_ACTIVATE,i 64 | end 65 | end 66 | 67 | for i=1,#activate do 68 | cardid = activate[i].id 69 | if cardid == 70368879 then -- upstart 70 | return COMMAND_ACTIVATE,i 71 | end 72 | end 73 | if HasID(activate,33782437) then -- One Day of Piece 74 | return COMMAND_ACTIVATE,CurrentIndex 75 | end 76 | for i=1,#activate do 77 | cardid = activate[i].id 78 | if cardid == 85852291 then --magical mallet 79 | return COMMAND_ACTIVATE,i 80 | end 81 | end 82 | 83 | for i=1,#activate do 84 | cardid = activate[i].id 85 | if cardid == 15259703 then --toon world 86 | if HasID(AIMon(),70791313,true) then 87 | return COMMAND_ACTIVATE,i 88 | end 89 | end 90 | end 91 | if HasID(activate,75014062) then -- Spell Power Grasp 92 | return COMMAND_ACTIVATE,CurrentIndex 93 | end 94 | if #AIHand()>6 and #cards.st_setable_cards > 0 95 | then 96 | return COMMAND_SET_ST,1 97 | end 98 | --go to end phase 99 | return COMMAND_TO_END_PHASE,1 100 | end 101 | 102 | -- ExodiaLib 103 | function ExodiaCard(cards,minTargets,maxTargets,triggeringID,triggeringCard) 104 | local id = triggeringID 105 | local result = {} 106 | if triggeringCard then 107 | id = triggeringCard.id 108 | end 109 | if id == 89997728 then --toon table of contents 110 | for i=1,#cards do 111 | if cards[i].id == 89997728 then -- find toon table of contents 112 | result[1]=i 113 | return result 114 | end 115 | end 116 | elseif id == 98645731 then --duality 117 | if not HasID(AIMon(),70791313,true) then 118 | --ai does not control royal magic library, search for it 119 | for i=1,#cards do 120 | if cards[i].id == 70791313 then 121 | result[1]=i 122 | return result 123 | end 124 | end 125 | else 126 | --ai controls royal magic library, search for a spell card 127 | for i=1,#cards do 128 | if bit32.band(cards[i].type, TYPE_SPELL) > 0 then 129 | result[1]=i 130 | return result 131 | end 132 | end 133 | end 134 | elseif id == 85852291 then --mallet 135 | if not HasID(AIMon(),70791313,true)then 136 | for i=1,maxTargets do 137 | result[i]=i 138 | end 139 | else 140 | for i=1,#cards do 141 | if bit32.band(TYPE_MONSTER,cards[i].type) > 0 142 | or cards[i].id == 75014062 and not HasID(AIDeck(),75014062,true) 143 | or cards[i].id == 15259703 and HasID(AIHand(),89997728,true) 144 | or cards[i].id == 89997728 and CardsMatchingFilter(AIHand(),FilterID,89997728)>1 145 | then 146 | result[#result+1] = i 147 | end 148 | end 149 | end 150 | if #result < minTargets then 151 | for i=1,maxTargets do 152 | result[i]=i 153 | end 154 | end 155 | return result 156 | elseif id == 75014062 then 157 | result = {IndexByID(cards,70791313)} 158 | end 159 | if #result < minTargets then 160 | for i=1,minTargets do 161 | result[i]=i 162 | end 163 | end 164 | if triggeringID == 0 and not triggeringCard 165 | and Duel.GetTurnPlayer()==player_ai 166 | and Duel.GetCurrentPhase()==PHASE_END 167 | and minTargets==maxTargets and minTargets == #AIHand()-6 168 | and LocCheck(cards,LOCATION_HAND,true) 169 | then 170 | --probably end phase discard 171 | return Add(cards,PRIO_TOGRAVE,minTargets) 172 | end 173 | return result 174 | end -------------------------------------------------------------------------------- /AI/decks/Fluffal/FluffalMaterial.lua: -------------------------------------------------------------------------------- 1 | ------------------------ 2 | ------- MATERIAL ------- 3 | ------------------------ 4 | function MaterialFDaredevil(cards) 5 | if cards == nil then 6 | cards = UseLists({AIMon(),AIHand()}) 7 | end 8 | if GlobalEdgeImpMaterial > 0 9 | and GlobalFluffalMaterial > 0 10 | then 11 | return true 12 | end 13 | return false 14 | end 15 | function MaterialFDaredevilBanish(cards) 16 | if cards == nil then 17 | cards = UseLists({AIMon(),AIGrave()}) 18 | end 19 | return MaterialFDaredevil(cards) 20 | end 21 | function MaterialFSabreTooth(cards) 22 | if cards == nil then 23 | cards = UseLists({AIMon(),AIHand()}) 24 | end 25 | if ( 26 | HasID(AIMon(),40636712,true) -- FKraken 27 | or HasID(AIMon(),85545073,true) -- FBear 28 | or HasID(AIMon(),00464362,true) -- FTiger 29 | or HasID(AIMon(),57477163,true) -- FSheep 30 | ) 31 | and ( 32 | GlobalEdgeImpMaterial + GlobalFluffalMaterial > 1 33 | or 34 | GlobalEdgeImpMaterial + GlobalFluffalMaterial > 0 35 | and #OppField() < 2 36 | and BattlePhaseCheck() 37 | ) 38 | then 39 | return true 40 | end 41 | return false 42 | end 43 | function MaterialFSabreToothBanish(cards) 44 | if cards == nil then 45 | cards = UseLists({AIMon(),AIGrave()}) 46 | end 47 | if CardsMatchingFilter(AIGrave(),FrightfurMonFilter) > 1 48 | and GlobalEdgeImpMaterial + GlobalFluffalMaterial > 1 49 | then 50 | return true 51 | end 52 | return false 53 | end 54 | 55 | function MaterialFKraken(cards) 56 | if cards == nil then 57 | cards = UseLists({AIMon(),AIHand()}) 58 | end 59 | if GlobalEdgeImpMaterial > 0 60 | and GlobalFluffalMaterial > 0 61 | then 62 | return true 63 | end 64 | return false 65 | end 66 | function MaterialFKrakenBanish(cards) 67 | if cards == nil then 68 | cards = UseLists({AIMon(),AIGrave()}) 69 | end 70 | return MaterialFKraken(cards) 71 | end 72 | 73 | function MaterialFLeo(cards) 74 | if cards == nil then 75 | cards = UseLists({AIMon(),AIHand()}) 76 | end 77 | if ( 78 | HasID(cards,34688023,true) -- Saw 79 | or CardsMatchingFilter(cards,SubstituteMaterialFilter) > 0 80 | ) 81 | and GlobalFluffalMaterial > 0 82 | then 83 | return true 84 | end 85 | return false 86 | end 87 | function MaterialFLeoBanish(cards) 88 | if cards == nil then 89 | cards = UseLists({AIMon(),AIGrave()}) 90 | end 91 | return MaterialFLeo(cards) 92 | end 93 | 94 | function MaterialFBear(cards) 95 | if cards == nil then 96 | cards = UseLists({AIMon(),AIHand()}) 97 | end 98 | if 99 | HasID(cards,30068120,true) -- Sabres 100 | and HasID(cards,03841833,true) -- Bear 101 | or 102 | HasID(cards,30068120,true) -- Sabres 103 | and CardsMatchingFilter(cards,SubstituteMaterialFilter) > 0 104 | or 105 | HasID(cards,03841833,true) -- Bear 106 | and CardsMatchingFilter(cards,SubstituteMaterialFilter) > 0 107 | then 108 | return true 109 | end 110 | return false 111 | end 112 | function MaterialFBearBanish(cards) 113 | if cards == nil then 114 | cards = UseLists({AIMon(),AIGrave()}) 115 | end 116 | return MaterialFBear(cards) 117 | end 118 | 119 | function MaterialFWolf(cards) 120 | if cards == nil then 121 | cards = UseLists({AIMon(),AIHand()}) 122 | end 123 | if HasID(cards,30068120,true) -- Sabres 124 | and GlobalFluffalMaterial > 0 125 | then 126 | return true 127 | end 128 | return false 129 | end 130 | function MaterialFWolfBanish(cards) 131 | if cards == nil then 132 | cards = UseLists({AIMon(),AIGrave()}) 133 | end 134 | return MaterialFWolf(cards) 135 | end 136 | 137 | function MaterialFTiger(cards) 138 | if cards == nil then 139 | cards = UseLists({AIMon(),AIHand()}) 140 | end 141 | if ( 142 | HasID(cards,30068120,true) -- Sabres 143 | or 144 | CardsMatchingFilter(cards,SubstituteMaterialFilter) > 0 145 | ) 146 | and GlobalFluffalMaterial > 0 147 | then 148 | return true 149 | end 150 | return false 151 | end 152 | function MaterialFTigerBanish(cards) 153 | if cards == nil then 154 | cards = UseLists({AIMon(),AIGrave()}) 155 | end 156 | return MaterialFTiger(cards) 157 | end 158 | 159 | function MaterialFSheep(cards) 160 | if cards == nil then 161 | cards = UseLists({AIMon(),AIHand()}) 162 | end 163 | if ( 164 | HasID(cards,61173621,true) -- Chain 165 | or 166 | CardsMatchingFilter(cards,SubstituteMaterialFilter) > 0 167 | ) 168 | and GlobalFluffalMaterial > 0 169 | then 170 | return true 171 | end 172 | return false 173 | end 174 | function MaterialFSheepBanish(cards) 175 | if cards == nil then 176 | cards = UseLists({AIMon(),AIGrave()}) 177 | end 178 | return MaterialFSheep(cards) 179 | end 180 | 181 | function MaterialFStarve() 182 | --print("MaterialFStarve") 183 | local countStarveMaterial = 0 184 | local fsabre = CardsMatchingFilter(AIMon(),FilterID,80889750) -- FSabretooth 185 | local frightfurs = CardsMatchingFilter(AIMon(),FrightfurMonFilter) 186 | local monSubgroup = SubGroup(AIMon(),NotFrightfurMonFilter) 187 | countStarveMaterial = CardsMatchingFilter(monSubgroup,FilterAttribute,ATTRIBUTE_DARK) 188 | if (frightfurs - fsabre) > 0 189 | then 190 | countStarveMaterial = countStarveMaterial + 1 191 | end 192 | --print(fsabre,frightfurs,countStarveMaterial) 193 | if countStarveMaterial >= 2 194 | and GlobalPolymerization == 1 195 | then 196 | return true 197 | end 198 | return false 199 | end 200 | 201 | --[[ 202 | 91034681, -- Frightfur Daredevil 203 | 80889750, -- Frightfur Sabre-Tooth 204 | 40636712, -- Frightfur Kraken 205 | 10383554, -- Frightfur Leo 206 | 85545073, -- Frightfur Bear 207 | 11039171, -- Frightfur Wolf 208 | 00464362, -- Frightfur Tiger 209 | 57477163, -- Frightfur Sheep 210 | 41209827, -- Starve Venom Fusion Dragon 211 | ]] -------------------------------------------------------------------------------- /AI/mod/AIArchetypeID.lua: -------------------------------------------------------------------------------- 1 | --------------------------------------- 2 | -- AIArchetypeID.lua 3 | -- 4 | -- A set of functions to determine if a 5 | -- card is part of an archetype or list. 6 | --------------------------------------- 7 | 8 | ----------------------------- 9 | -- Checks if the card's ID is 10 | -- of a Tribute Exception monster. 11 | ----------------------------- 12 | function IsTributeException(CardId) 13 | if CardId == 64631466 or CardId == 63519819 or -- Relinquished, Thousand-Eyes Restrict 14 | CardId == 10000000 or CardId == 10000020 or -- Obelisk the Tormentor, Slifer the Sky Dragon 15 | CardId == 10000010 then -- The Winged Dragon of Ra 16 | return 1 17 | end 18 | return 0 19 | end 20 | 21 | function Is3TributeMonster(CardId) 22 | if CardId == 10000000 or CardId == 10000020 or -- Obelisk the Tormentor, Slifer the Sky Dragon 23 | CardId == 10000010 then -- The Winged Dragon of Ra 24 | return 1 25 | end 26 | return 0 27 | end 28 | 29 | function LegitDWMonster(CardId) 30 | if CardId == 34230233 or CardId == 32619583 or 31 | CardId == 33731070 or CardId == 79126789 then 32 | return 1 33 | end 34 | return 0 35 | end 36 | 37 | function IsUndestroyableByBattle(CardId) 38 | if CardId == 31305911 then -- Marshmallon 39 | return 1 40 | end 41 | return 0 42 | end 43 | 44 | --------------------------------------------------------- 45 | -- Some cards shouldn't be banished 46 | --------------------------------------------------------- 47 | function BanishBlacklist(CardId) 48 | if CardId == 65192027 or CardId == 88264978 or -- Dark Armed Dragon, REDMD 49 | CardId == 34230233 or CardId == 72989439 or -- Grapha, Black Luster Soldier 50 | CardId == 38495396 then -- Constellar Ptolemy M7 51 | return 1 52 | end 53 | return 0 54 | end 55 | 56 | --------------------------------------------------------- 57 | -- Cards that benefit from being banished 58 | --------------------------------------------------------- 59 | function BanishWhitelist(CardId) 60 | if CardId == 42216237 or CardId == 51858306 -- Angel of Zera, Eclipse Wyvern 61 | then 62 | return 1 63 | end 64 | return 0 65 | end 66 | 67 | ----------------------------- 68 | -- Checks if the card's ID is 69 | -- of a Nordic Tuner monster. 70 | ----------------------------- 71 | function IsNordicTuner(CardId) 72 | if CardId == 41788781 or CardId == 73417207 or -- Guldfaxe, Mara 73 | CardId == 77060848 or CardId == 40844552 or -- Svartalf, Valkyrie 74 | CardId == 61777313 then -- Vanadis 75 | return 1 76 | end 77 | return 0 78 | end 79 | 80 | ----------------------------- 81 | -- Checks if the card's ID is 82 | -- of a "Gladiator Beast" archetype monster. 83 | ----------------------------- 84 | function IsGladiatorArchetype(CardId) 85 | local AIMon = AI.GetAIMonsterZones() 86 | for i=1,#AIMon do 87 | if AIMon[i] ~= false then 88 | if AIMon[i].id == CardId then 89 | if CardId == 42592719 or CardId == 90582719 or -- Gladiator Beast Alexander, Gladiator Beast Andal 90 | CardId == 41470137 or CardId == 25924653 or -- Gladiator Beast Bestiari, Gladiator Beast Darius 91 | CardId == 31247589 or CardId == 57731460 or -- Gladiator Beast Dimacari, Gladiator Beast Equeste 92 | CardId == 73285669 or CardId == 90957527 or -- Gladiator Beast Essedarii, Gladiator Beast Gaiodiaz 93 | CardId == 48156348 or CardId == 27346636 or -- Gladiator Beast Gyzarus, Gladiator Beast Heraklinos 94 | CardId == 04253484 or CardId == 02067935 or -- Gladiator Beast Hoplomus, Gladiator Beast Lanista 95 | CardId == 78868776 or CardId == 05975022 or -- Gladiator Beast Laquari, Gladiator Beast Murmillo 96 | CardId == 29590752 or CardId == 00612115 or -- Gladiator Beast Octavius, Gladiator Beast Retiari 97 | CardId == 02619149 or CardId == 77642288 or -- Gladiator Beast Samnite, Gladiator Beast Secutor 98 | CardId == 79580323 or CardId == 65984457 or -- Gladiator Beast Spartacus, Gladiator Beast Torax 99 | CardId == 50893987 and -- Gladiator Beast Tygerius 100 | (AIMon[i].position == POS_FACEUP_ATTACK or AIMon[i].position == POS_FACEUP_DEFENSE) then 101 | return 1 102 | end 103 | end 104 | end 105 | end 106 | return 0 107 | end 108 | 109 | -------------------------------- 110 | -- Checks if the card's ID is of 111 | -- a main deck Nordic monster. 112 | -------------------------------- 113 | function IsNordicMonster(CardId) 114 | if IsNordicTuner(CardId) == 1 then 115 | return 1 116 | end 117 | if CardId == 13455953 or CardId == 88283496 or -- Dverg, Garmr 118 | CardId == 40666140 or CardId == 76348260 or -- Ljosalf, Mimir 119 | CardId == 15394083 or CardId == 14677495 or -- Tanngrisnir,Tanngnjostr 120 | CardId == 02333365 then -- Tyr 121 | return 1 122 | end 123 | return 0 124 | end 125 | 126 | 127 | ------------------------------------------------------- 128 | -- Checks if the card's ID is a Dark World monster that 129 | -- has an effect that activates when it is discarded 130 | -- by an effect controlled by the AI. 131 | ------------------------------------------------------- 132 | function IsDiscardEffDWMonster(CardId) 133 | if CardId == 33731070 or CardId == 79126789 or -- Beiige, Broww 134 | CardId == 07623640 or CardId == 78004197 or -- Ceruli, Goldd 135 | CardId == 34230233 or CardId == 51232472 or -- Grapha, Gren 136 | CardId == 25847467 or CardId == 15667446 or -- Kahkki, Latinum 137 | CardId == 32619583 or CardId == 60228941 then -- Sillva, Snoww 138 | return 1 139 | end 140 | return 0 141 | end 142 | 143 | 144 | -------------------------------- 145 | -- Checks if the card's ID is an 146 | -- Elemental HERO monster. 147 | -------------------------------- 148 | function IsEHeroMonster(CardId) 149 | if IsEHeroMainDeckMonster(CardId) == 1 or 150 | IsEHeroFusionMonster(CardId) == 1 then 151 | return 1 152 | end 153 | return 0 154 | end 155 | 156 | 157 | ------------------------------------ 158 | -- Checks if the card's ID is a 159 | -- main deck Elemental HERO monster. 160 | ------------------------------------ 161 | function IsEHeroMainDeckMonster(CardId) 162 | if CardId == 21844576 or CardId == 59793705 or -- Avian, Bladedge 163 | CardId == 79979666 or CardId == 58932615 or -- Bubbleman, Burstinatrix 164 | CardId == 80908502 or CardId == 84327329 or -- Captain Gold, Clayman 165 | CardId == 69572169 or CardId == 98266377 or -- Flash, Heat 166 | CardId == 41077745 or CardId == 62107981 or -- Ice Edge, Knospe 167 | CardId == 95362816 or CardId == 89252153 or -- Lady Heat, Necroshade 168 | CardId == 05285665 or CardId == 89943723 or -- Neo Bubbleman, Neos 169 | CardId == 69884162 or CardId == 37195861 or -- Neos Alius, Ocean 170 | CardId == 51085303 or CardId == 89312388 or -- Poison Rose, Prisma 171 | CardId == 20721928 or CardId == 40044918 or -- Sparkman, Stratos 172 | CardId == 09327502 or CardId == 86188410 or -- Voltic, Wildheart 173 | CardId == 75434695 then -- Woodsman 174 | return 1 175 | end 176 | return 0 177 | end 178 | 179 | --------------------------------- 180 | -- Checks if the card's ID is an 181 | -- Elemental HERO fusion monster. 182 | --------------------------------- 183 | function IsEHeroFusionMonster(CardId) 184 | if CardId == 40854197 or CardId == 11502550 or -- Absolute Zero, Air Neos 185 | CardId == 55171412 or CardId == 17032740 or -- Aqua Neos, Chaos Neos 186 | CardId == 28677304 or CardId == 41517968 or -- Dark Neos, Darkbright 187 | CardId == 31111109 or CardId == 29343734 or -- Divine Neos, Electrum 188 | CardId == 33574806 or CardId == 35809262 or -- Escuridao, Flame Wing 189 | CardId == 81566151 or CardId == 16304628 or -- Flare Neos, Gaia 190 | CardId == 85507811 or CardId == 48996569 or -- Glow Neos, Grand Neos 191 | CardId == 03642509 or CardId == 68745629 or -- Great Tornado, Inferno 192 | CardId == 78512663 or CardId == 05128859 or -- Magma Neos, Marine Neos 193 | CardId == 14225239 or CardId == 52031567 or -- Mariner, Mudballman 194 | CardId == 81003500 or CardId == 72926163 or -- Necroid Shaman, Neos K 195 | CardId == 01945387 or CardId == 41436536 or -- Nova Master, Phoenix E 196 | CardId == 60493189 or CardId == 47737087 or -- Plasma Vice, Rampart B 197 | CardId == 25366484 or CardId == 88820235 or -- Sh.Flare, Sh.Phoenix 198 | CardId == 81197327 or CardId == 49352945 or -- Steam Healer,Storm Neos 199 | CardId == 83121692 or CardId == 74711057 or -- Tempest, Terra Firma 200 | CardId == 22061412 or CardId == 61204971 or -- The Shining, Thunder G 201 | CardId == 13293158 or CardId == 55615891 or -- Wild Cyclone, Wild Wing 202 | CardId == 10526791 then -- Wildedge 203 | return 1 204 | end 205 | return 0 206 | end 207 | 208 | 209 | ----------------------------- 210 | -- Checks if the card's ID is 211 | -- a Synchron tuner monster. 212 | ----------------------------- 213 | function IsSynchronTunerMonster(CardId) 214 | if CardId == 52840598 or CardId == 25652655 or -- Bri, Changer 215 | CardId == 56286179 or CardId == 19642774 or -- Drill, Fleur 216 | CardId == 50091196 or CardId == 40348946 or -- Formula, Hyper 217 | CardId == 63977008 or CardId == 56897896 or -- Junk, Mono 218 | CardId == 96182448 or CardId == 20932152 or -- Nitro, Quickdraw 219 | CardId == 71971554 or CardId == 83295594 or -- Road, Steam 220 | CardId == 67270095 or CardId == 15310033 then -- Turbo, Unknown 221 | return 1 222 | end 223 | return 0 224 | end 225 | 226 | 227 | -------------------------- 228 | -- Checks if the card's ID 229 | -- is a Synchron monster. 230 | -------------------------- 231 | function IsSynchronMonster(CardId) 232 | if IsSynchronTunerMonster(CardId) == 1 or 233 | CardId == 36643046 then -- Synchron Explorer 234 | return 1 235 | end 236 | return 0 237 | end 238 | 239 | 240 | ----------------------------- 241 | -- Checks if the card's ID is 242 | -- a Destiny HERO monster. 243 | ----------------------------- 244 | function IsDHeroMonster(CardId) 245 | if CardId == 55461064 or CardId == 77608643 or -- Blade M, Captain T 246 | CardId == 100000275 or CardId == 81866673 or -- Celestial, Dasher 247 | CardId == 54749427 or CardId == 39829561 or -- Defender, Departed 248 | CardId == 13093792 or CardId == 56570271 or -- Diamond Dude, Disc 249 | CardId == 17132130 or CardId == 41613948 or -- Dogma, Doom Lord 250 | CardId == 28355718 or CardId == 36625827 or -- Double, Dread Serv 251 | CardId == 80744121 or CardId == 09411399 or -- Fear Monger, Mali 252 | CardId == 83965310 or CardId == 100000274 then -- Plasma, The Dark A 253 | return 1 254 | end 255 | return 0 256 | end 257 | 258 | 259 | ------------------------------------ 260 | -- Checks if every card in the index 261 | -- is that of a specified archetype. 262 | ------------------------------------ 263 | function AllCardsArchetype(Cards,SetCode) 264 | for i=1,#Cards do 265 | if Cards[i] ~= false then 266 | if Cards[i].setcode ~= SetCode then 267 | return 0 268 | end 269 | end 270 | end 271 | return 1 272 | end 273 | -------------------------------------------------------------------------------- /AI/mod/AICheckPossibleST.lua: -------------------------------------------------------------------------------- 1 | ----------------------------------------- 2 | -- AICheckPossibleST.lua 3 | -- 4 | -- A set of functions to check for possible spell or trap card activation or special summoning in specified situations, 5 | -- and returning possible outcome of doing so. 6 | ----------------------------------------- 7 | 8 | function CanChangeOutcome(cards,SummonableCards, ActivatableCards) 9 | local Result = 0 10 | local AIMons = AI.GetAIMonsterZones() 11 | local AIExtra = AI.GetAIExtraDeck() 12 | 13 | ------------------------------------------------------- 14 | -- Check if any XYZ or SYNCHRO monsters can be summoned. 15 | ------------------------------------------------------- 16 | for i=1,#SummonableCards do 17 | if isMonLevelEqualToRank(SummonableCards[i].level,SummonableCards[i].id) ~= 0 and SummonableCards[i].location == LOCATION_HAND and 18 | (AIMonCountLowerLevelAndAttack(SummonableCards[i].level,SummonableCards[i].attack) + GlobalAdditionalTributeCount) >= 19 | AIMonGetTributeCountByLevel(SummonableCards[i].level) then 20 | for x=1,#AIExtra do 21 | if AIExtra[x] ~= false then 22 | if (AIMonOnFieldMatCount(AIExtra[x].rank) + 1) >= GetXYZRequiredMatCount() then 23 | Result = 1 24 | end 25 | end 26 | end 27 | end 28 | end 29 | 30 | --------------------------------------------------------------- 31 | -- Check if player controls only 1 monster, and if it can be destroyed 32 | --------------------------------------------------------------- 33 | if Get_Card_Count_Pos(OppMon(), POS_FACEUP_ATTACK) == 1 and Get_Card_Att_Def(OppMon(),"attack",">",POS_FACEUP,"attack") < Get_Card_Att_Def(AIMon(),"attack",">",POS_FACEUP,"attack") then 34 | Result = 1 35 | end 36 | 37 | if Get_Card_Count_ID(UseLists({AIMon(),AIST()}), 72302403, POS_FACEUP) > 0 or Get_Card_Count_ID(AIMon(), 58775978, nil) > 0 then -- Swords of Revealing Light, Nightmare's Steelcage 38 | Result = 1 39 | end 40 | 41 | if Get_Card_Count_ID(AIMon(), 70908596, nil) > 0 then -- Constellar Kaust 42 | Result = 1 43 | end 44 | 45 | if Get_Card_Count_ID(UseLists({AIMon(),AIHand(),AIST()}), 40619825, nil) > 0 then -- Axe of Despair 46 | for i=1,#SummonableCards do 47 | if (SummonableCards[i].attack +1000) >= Get_Card_Att_Def(OppMon(),"attack",">",POS_FACEUP,"attack") then 48 | Result = 1 49 | end 50 | end 51 | end 52 | 53 | if Get_Card_Count_ID(UseLists({AIMon(),AIHand(),AIST()}), 83746708, nil) > 0 then -- Mage Power 54 | for i=1,#SummonableCards do 55 | if (SummonableCards[i].attack + 500 * (Get_Card_Count(AI.GetAISpellTrapZones()) +1)) >= Get_Card_Att_Def(OppMon(),"attack",">",POS_FACEUP,"attack") then 56 | Result = 1 57 | end 58 | end 59 | end 60 | 61 | for i=1,#SummonableCards do 62 | if SummonableCards[i].id == 70908596 then -- Constellar Kaust 63 | Result = 1 64 | end 65 | end 66 | 67 | if Get_Card_Count_ID(UseLists({AIMon(),AIHand(),AIST()}), 55713623, nil) > 0 then -- Shrink 68 | for i=1,#SummonableCards do 69 | if SummonableCards[i].attack > Get_Card_Att_Def(OppMon(),"attack",">",POS_FACEUP,"attack") / 2 then 70 | Result = 1 71 | end 72 | end 73 | end 74 | 75 | if Get_Card_Count_ID(UseLists({AIMon(),AIHand(),AIST()}), 67227834, nil) > 0 then -- Magic Formula 76 | for i=1,#SummonableCards do 77 | if SummonableCards[i].id == 46986414 or SummonableCards[i].id == 38033121 then -- Dark Magician, Dark Magician Girl 78 | if (SummonableCards[i].attack +700) >= Get_Card_Att_Def(OppMon(),"attack",">",POS_FACEUP,"attack") then 79 | Result = 1 80 | end 81 | end 82 | end 83 | end 84 | 85 | if Get_Card_Count_ID(UseLists({AIMon(),AIHand(),AIST()}), 22046459, nil) > 0 then -- Megamorph 86 | for i=1,#SummonableCards do 87 | if AI.GetPlayerLP(1) < AI.GetPlayerLP(2) and SummonableCards[i].attack >= 1500 then 88 | if SummonableCards[i].attack * 2 > Get_Card_Att_Def(OppMon(),"attack",">",POS_FACEUP,"attack") then 89 | Result = 1 90 | end 91 | end 92 | end 93 | end 94 | 95 | if Get_Card_Count_ID(UseLists({AIMon(),AIHand(),AIST()}), 98045062, nil) > 0 then -- Enemy Controller 96 | for i=1,#SummonableCards do 97 | if SummonableCards[i].attack > Get_Card_Att_Def(OppMon(), "attack", ">", POS_FACEUP_ATTACK, "defense") then 98 | Result = 1 99 | end 100 | end 101 | end 102 | 103 | if Get_Card_Count_ID(AIGrave(), 34230233, nil) > 0 then -- Grapha, Dragon Lord of Dark World 104 | for i=1,#SummonableCards do 105 | if IsDiscardEffDWMonster(SummonableCards[i].id) == 1 then 106 | Result = 1 107 | end 108 | end 109 | end 110 | 111 | if Get_Card_Count_ID(UseLists({AIMon(),AIHand(),AIST()}), 33017655, nil) > 0 then -- The Gates of Dark World 112 | for i=1,#SummonableCards do 113 | if SummonableCards[i].race == RACE_FIEND then 114 | if (SummonableCards[i].attack +300) >= Get_Card_Att_Def(OppMon(),"attack",">",POS_FACEUP,"attack") then 115 | Result = 1 116 | end 117 | end 118 | end 119 | end 120 | 121 | for i=1,#SummonableCards do 122 | if SummonableCards[i].id == 10000020 then -- Slifer the Sky Dragon 123 | if (SummonableCards[i].attack + 1000 * (Get_Card_Count(AIHand()) -1)) >= Get_Card_Att_Def(OppMon(),"attack",">",POS_FACEUP,"attack") then 124 | Result = 1 125 | end 126 | end 127 | end 128 | 129 | for i=1,#SummonableCards do 130 | if SummonableCards[i].id == 98777036 then -- Tragoedia 131 | if (SummonableCards[i].attack + 600 * (Get_Card_Count(AIHand()) -1)) >= Get_Card_Att_Def(OppMon(),"attack",">",POS_FACEUP,"attack") then 132 | Result = 1 133 | end 134 | end 135 | end 136 | 137 | for i=1,#SummonableCards do 138 | if SummonableCards[i].id == 10000010 then -- The Winged Dragon of Ra 139 | if (SummonableCards[i].attack + AI.GetPlayerLP(1) - 100) >= Get_Card_Att_Def(OppMon(),"attack",">",POS_FACEUP,"attack") then 140 | Result = 1 141 | end 142 | end 143 | end 144 | 145 | return Result 146 | end 147 | 148 | -------------------------------------------------- 149 | -- Copy of above function, to be used in SelectPosition, 150 | -- when AI has to special summon monsters. 151 | -------------------------------------------------- 152 | function CanChangeOutcomeSS(CardID) 153 | local Result = 0 154 | 155 | if Get_Card_Count_ID(UseLists({AIMon(),AIHand(),AIST()}), 22046459, nil) > 0 then -- Megamorph 156 | if AI.GetPlayerLP(1) < AI.GetPlayerLP(2) and AIMonGetAttackById(CardID) >= 1500 then 157 | if AIMonGetAttackById(CardID) * 2 > Get_Card_Att_Def(OppMon(),"attack",">",POS_FACEUP,"attack") then 158 | Result = 1 159 | end 160 | end 161 | end 162 | 163 | --------------------------------------------------------------- 164 | -- Check if player controls only 1 monster, and if it can be destroyed 165 | --------------------------------------------------------------- 166 | if Get_Card_Count_Pos(OppMon(), POS_FACEUP_ATTACK) > 0 and Get_Card_Att_Def(OppMon(),"attack",">",POS_FACEUP,"attack") < Get_Card_Att_Def(AIMon(),"attack",">",POS_FACEUP,"attack") then 167 | Result = 1 168 | end 169 | 170 | if Get_Card_Count_ID(UseLists({AIMon(),AIHand(),AIST()}), 67227834, nil) > 0 then -- Magic Formula 171 | if CardID == 46986414 or CardID == 38033121 then -- Dark Magician, Dark Magician Girl 172 | if (AIMonGetAttackById(CardID) +700) >= Get_Card_Att_Def(OppMon(),"attack",">",POS_FACEUP,"attack") then 173 | Result = 1 174 | end 175 | end 176 | end 177 | 178 | if Get_Card_Count_ID(AIMon(), 70908596, POS_FACEUP) > 0 then -- Constellar Kaust 179 | Result = 1 180 | end 181 | 182 | if Get_Card_Count_ID(UseLists({AIMon(),AIHand(),AIST()}), 40619825, nil) > 0 then -- Axe of Despair 183 | if (AIMonGetAttackById(CardID) +1000) >= Get_Card_Att_Def(OppMon(),"attack",">",POS_FACEUP,"attack") then 184 | Result = 1 185 | end 186 | end 187 | 188 | if Get_Card_Count_ID(UseLists({AIMon(),AIHand(),AIST()}), 83746708, nil) > 0 then -- Mage Power 189 | if (AIMonGetAttackById(CardID) + 500 * (Get_Card_Count(AI.GetAISpellTrapZones()) +1)) >= Get_Card_Att_Def(OppMon(),"attack",">",POS_FACEUP,"attack") then 190 | Result = 1 191 | end 192 | end 193 | 194 | if Get_Card_Count_ID(UseLists({AIMon(),AIHand(),AIST()}), 55713623, nil) > 0 then -- Shrink 195 | if AIMonGetAttackById(CardID) > Get_Card_Att_Def(OppMon(),"attack",">",POS_FACEUP,"attack") / 2 then 196 | Result = 1 197 | end 198 | end 199 | 200 | if Get_Card_Count_ID(UseLists({AIMon(),AIHand(),AIST()}), 33017655, nil) > 0 then -- The Gates of Dark World 201 | if AIMonGetRaceById(CardID) == RACE_FIEND then 202 | if (AIMonGetAttackById(CardID) +300) >= Get_Card_Att_Def(OppMon(),"attack",">",POS_FACEUP,"attack") then 203 | Result = 1 204 | end 205 | end 206 | end 207 | 208 | if Get_Card_Count_ID(AIGrave(), 34230233, nil) > 0 then -- Grapha, Dragon Lord of Dark World 209 | if IsDiscardEffDWMonster(CardID) == 1 then 210 | Result = 1 211 | end 212 | end 213 | 214 | if CardID == 10000020 then -- Slifer the Sky Dragon 215 | if (AIMonGetAttackById(CardID) + 1000 * (Get_Card_Count(AIHand()) -1)) >= Get_Card_Att_Def(OppMon(),"attack",">",POS_FACEUP,"attack") then 216 | Result = 1 217 | end 218 | end 219 | 220 | if CardID == 98777036 then -- Tragoedia 221 | if (AIMonGetAttackById(CardID) + 600 * (Get_Card_Count(AIHand()) -1)) >= Get_Card_Att_Def(OppMon(),"attack",">",POS_FACEUP,"attack") then 222 | Result = 1 223 | end 224 | end 225 | 226 | if CardID == 70908596 then -- Constellar Kaust 227 | Result = 1 228 | end 229 | 230 | if CardID == 10000010 then -- The Winged Dragon of Ra 231 | if (AIMonGetAttackById(CardID) + AI.GetPlayerLP(1) - 100) >= Get_Card_Att_Def(OppMon(),"attack",">",POS_FACEUP,"attack") then 232 | Result = 1 233 | end 234 | end 235 | 236 | if CardID == 12014404 then -- Gagaga Gunman 237 | if (AIMonGetAttackById(CardID) + 1500) >= Get_Card_Att_Def(OppMon(),"attack",">",POS_FACEUP,"attack") then 238 | Result = 1 239 | end 240 | end 241 | 242 | if Get_Card_Count_ID(UseLists({AIMon(),AIST()}), 72302403, POS_FACEUP) > 0 or Get_Card_Count_ID(AIMon(), 58775978, POS_FACEUP) > 0 then -- Swords of Revealing Light, Nightmare's Steelcage 243 | Result = 1 244 | end 245 | 246 | return Result 247 | end 248 | 249 | -------------------------------------------------- 250 | -- Checks if AI should change position of monster to allow XYZ summon 251 | -- used only in position changing function. 252 | -------------------------------------------------- 253 | function ChangePosToXYZSummon(cards, SummonableCards, RepositionableCards) 254 | local Result = 0 255 | local AIMons = AI.GetAIMonsterZones() 256 | local AIExtra = AI.GetAIExtraDeck() 257 | 258 | for i=1,#SummonableCards do 259 | if SummonableCards[i] ~= false then 260 | if isMonLevelEqualToRank(SummonableCards[i].level,SummonableCards[i].id) == 1 and SummonableCards[i].location == LOCATION_HAND and 261 | (AIMonCountLowerLevelAndAttack(SummonableCards[i].level,SummonableCards[i].attack) + GlobalAdditionalTributeCount) >= 262 | AIMonGetTributeCountByLevel(SummonableCards[i].level) then 263 | for x=1,#AIExtra do 264 | if AIExtra[x] ~= false then 265 | if (AIMonOnFieldMatCount(AIExtra[x].rank) + 1) >= GetXYZRequiredMatCount() or AIMonOnFieldMatCurrentCount() >= GetXYZRequiredMatCount() then 266 | Result = 1 267 | end 268 | end 269 | end 270 | end 271 | end 272 | end 273 | for x=1,#AIExtra do 274 | if AIExtra[x] ~= false then 275 | if AIMonOnFieldMatCount(AIExtra[x].rank) >= GetXYZRequiredMatCount() or AIMonOnFieldMatCurrentCount() >= GetXYZRequiredMatCount() then 276 | Result = 1 277 | end 278 | end 279 | end 280 | return Result 281 | end 282 | 283 | -------------------------------------------------------------------------------- /AI/decks/Fluffal/FluffalFilter.lua: -------------------------------------------------------------------------------- 1 | ------------------------ 2 | -------- FILTER -------- 3 | ------------------------ 4 | -- FluffalM FILTER 5 | function FluffalFilter(c) 6 | return FilterSet(c,0xA9) 7 | end 8 | function NotFluffalFilter(c) 9 | return not FluffalFilter(c) 10 | end 11 | function PenguinFilter(c) 12 | if c.id == 39246582 and OPTCheck(39246582) -- Dog 13 | or c.id == 65331686 and OPTCheck(65331686) -- Owl 14 | or c.id == 81481818 -- Patchwork 15 | or c.id == 06142488 -- Mouse 16 | then 17 | return true 18 | elseif c.id == 87246309 -- Octo 19 | then 20 | return UseOcto() 21 | else 22 | return false 23 | end 24 | end 25 | function FluffalFusionProtectFilter(c) 26 | return 27 | c.id == 02729285 -- Cat 28 | or c.id == 38124994 -- Rabit 29 | or c.id == 13241004 -- Penguin 30 | end 31 | -- EdgeImp FILTER 32 | function EdgeImpFilter(c) 33 | return FilterSet(c,0xC3) 34 | end 35 | -- Other FILTER 36 | function FluffalFusionMonFilter(c) 37 | return 38 | EdgeImpFilter(c) 39 | or 40 | SubstituteMaterialFilter(c) 41 | end 42 | function SubstituteMaterialFilter(c) 43 | return 44 | c.id == 81481818 -- Patchwork 45 | and FilterLocation(c,LOCATION_MZONE) 46 | or 47 | c.id == 79109599 -- KoS 48 | or 49 | c.id == 06205579 -- PFusioner 50 | end 51 | -- FluffalS FILTER 52 | function TVendorCheckFilter(c,canUse) 53 | if canUse then 54 | return 55 | c.id == 70245411 56 | and OPTCheck(c.cardid) 57 | else 58 | return 59 | c.id == 70245411 60 | and not OPTCheck(c.cardid) 61 | end 62 | end 63 | function FrightfurSTFilter(c) 64 | return 65 | FilterSet(c,0xAD) 66 | and FilterType(c,TYPE_SPELL+TYPE_TRAP) 67 | end 68 | -- Spell FILTER 69 | function FusionArchetypeFilter(c) 70 | return FilterSet(c,0x46) 71 | end 72 | function FluffalFusionSTFilter(c) 73 | return 74 | c.id == 24094653 -- Polymerization 75 | or 76 | c.id == 94820406 -- DFusion 77 | or 78 | c.id == 79109599 -- KoS 79 | and FilterLocation(c,LOCATION_HAND) 80 | or 81 | c.id == 43698897 -- FFactory 82 | and UseFFactoryAux(true) 83 | and OPTCheck(43698897) 84 | or 85 | c.id == 34773082 -- FPatchwork 86 | and OPTCheck(34773082) 87 | end 88 | function FluffalFusionSTFilter2(c) 89 | return 90 | FluffalFusionSTFilter(c) 91 | or 92 | c.id == 06077601 -- FFusion 93 | and OPTCheck(06077601) 94 | end 95 | -- Trap FILTER 96 | -- Frightfur FILTER 97 | function FrightfurMonFilter(c) 98 | return 99 | FilterSet(c,0xAD) 100 | and FilterType(c,TYPE_MONSTER) 101 | end 102 | function NotFrightfurMonFilter(c) 103 | return 104 | not FilterSet(c,0xAD) 105 | and FilterType(c,TYPE_MONSTER) 106 | end 107 | function FrightfurMonNegatedFilter(c) 108 | return 109 | FilterSet(c,0xAD) 110 | and FilterType(c,TYPE_MONSTER) 111 | and Negated(c) 112 | end 113 | function FSabreToothFilter(c) 114 | return 115 | c.id == 80889750 and NotNegated(c) 116 | end 117 | function FLeoFinishFilter(c,source) 118 | return 119 | AI.GetPlayerLP(2) <= c.base_attack -- Origial Attack 120 | and Targetable(c,TYPE_MONSTER) 121 | and FluffalDestroyFilter(c) 122 | and Affected(c,TYPE_MONSTER) 123 | end 124 | function FTigerDestroyFilter(c) 125 | return ( 126 | Targetable(c,TYPE_MONSTER) 127 | and Affected(c,TYPE_MONSTER) 128 | and FluffalDestroyFilter(c) 129 | and not IgnoreList(c) 130 | ) 131 | end 132 | function FKrakenSendFilter(c) 133 | return ( 134 | Targetable(c,TYPE_MONSTER) 135 | and Affected(c,TYPE_MONSTER) 136 | and FluffalSendFilter(c) 137 | and not IgnoreList(c) 138 | ) 139 | end 140 | -- Other Fusion FILTER 141 | function FluffalNordenFilter(c) 142 | return 143 | FilterAttribute(c,ATTRIBUTE_WATER) 144 | and FilterLevel(c,4) 145 | end 146 | -- Other XYZ FILTER 147 | function FluffalBahamutMaterialFilter(c) 148 | return Negated(c) 149 | or c.id == 17412721 150 | end 151 | 152 | -- Other Filter 153 | function FluffalDestroyFilter(c,nontarget,skipblacklist,skipignore) 154 | return DestroyFilter(c,nontarget,skipblacklist,skipignore) 155 | and not BypassDestroyFilter(c) 156 | end 157 | function FluffalSendFilter(c,nontarget) 158 | return not FilterStatus(c,STATUS_LEAVE_CONFIRMED) 159 | and (nontarget==true or not FilterAffected(c,EFFECT_CANNOT_BE_EFFECT_TARGET)) 160 | and not BypassSendFilter(c) 161 | end 162 | 163 | function ByPassDestroyFilter(c) 164 | return ( 165 | ( 166 | ( 167 | c.id==62541668 -- Number 77: Seven Sins 168 | or c.id==99469936 -- Crystalzero Lancer 169 | or c.id==67173574 -- Number C102 170 | or c.id==23998625 -- Number 53 171 | or c.id==01855932 -- Bujintei Kagotsuchi 172 | or c.id==49678559 -- Number 102 173 | or c.id==76067258 -- Number 66 174 | or c.id==23232295 -- BB Lead Joke 175 | or c.id==48739166 -- Number 101 176 | or c.id==25853045 -- Black Ray Lancer 177 | or c.id==25341652 -- Maestroke the Symphony Dijinn 178 | or c.id==78156759 -- Wind-Up Zenmaines 179 | or c.id==10002346 -- Gachi Gachi Gantetsu 180 | or c.id==65305468 -- Number F0: Utopic Future 181 | or c.id==15914410 -- Mechquipped Angineer 182 | ) 183 | and c.xyz_material_count>0 184 | ) 185 | or c.id==94977269 -- El Shaddoll Winda 186 | or c.id==93302695 -- Kozmol Wickedwitch 187 | ) 188 | and NotNegated(c) 189 | end 190 | function BypassSendFilter(c) 191 | return c.id==74586817 -- PSY-Framelord Omega 192 | end 193 | ------------------------ 194 | -------- COUNT --------- 195 | ------------------------ 196 | -- General Count 197 | function CountPrioTarget(cards,loc,minPrio,Type,filter,opt,debugMode) 198 | local result = 0 199 | if minPrio == nil then 200 | minPrio = 1 201 | end 202 | for i=1, #cards do 203 | local c = cards[i] 204 | if debugMode ~= nil then 205 | --print(debugMode.." - id: "..c.id) 206 | end 207 | c.prio = GetPriority(c,loc) 208 | if not FilterCheck(c,filter,opt) 209 | or not (Type == nil or bit32.band(c.type,Type) > 0) then 210 | c.prio = -1 211 | end 212 | if debugMode ~= nil then 213 | print(debugMode.." - Prio: "..c.prio,c.original_id.." - "..GetName(c)) 214 | end 215 | if c.prio > minPrio then 216 | result = result + 1 217 | end 218 | end 219 | if debugMode ~= nil then 220 | print(debugMode.." - Count: "..result) 221 | end 222 | return result 223 | end 224 | -- FluffalM COUNT 225 | function CountFluffal(cards) 226 | return CardsMatchingFilter(cards,FluffalFilter) 227 | end 228 | -- EdgeImp COUNT 229 | function CountEdgeImp(cards) 230 | return CardsMatchingFilter(cards,EdgeImpFilter) 231 | end 232 | -- Other COUNT 233 | -- FluffalS COUNT 234 | function CountFPatchworkTarget() 235 | return 236 | math.min(CardsMatchingFilter(AIDeck(),FilterID,24094653),CountEdgeImp(AIDeck())) -- Poly/EdgeImp 237 | end 238 | -- Spell COUNT 239 | -- Trap COUNT 240 | -- Frightfur COUNT 241 | function CountFrightfurMon(cards) 242 | return CardsMatchingFilter(cards,FrightfurMonFilter) 243 | end 244 | -- Other Fusion COUNT 245 | -- Other XYZ COUNT 246 | 247 | -- FUSION COUNT 248 | function CountFrighturFusion(prio) 249 | local result = 0 250 | if prio == nil then prio = 3 end 251 | --local fusionExtra = SubGroup(AIExtra(),FilterType,TYPE_FUSION) 252 | --CountPrioTarget(AIExtra(),PRIO_TOFIELD,3,nil,FilterType,TYPE_FUSION,"CountFrighturFusion") 253 | result = CountPrioTarget(AIExtra(),PRIO_TOFIELD,1) 254 | return result 255 | end 256 | function CountFluffalMaterial(cards,loc,safe) 257 | local result = 0 258 | local minPrio = FluffalPrioMode(safe) 259 | if loc == nil then loc = MATERIAL_TOGRAVE end 260 | --CountPrioTarget(cards,loc,minPrio,TYPE_MONSTER,FluffalFilter,nil,"CountFluffalMaterial: ") 261 | result = CountPrioTarget(cards,loc,minPrio,TYPE_MONSTER,FluffalFilter) 262 | return result 263 | end 264 | function CountEdgeImpMaterial(cards,loc,safe) 265 | local result = 0 266 | local minPrio = 1 267 | if loc == nil then loc = MATERIAL_TOGRAVE end 268 | --CountPrioTarget(cards,loc,1,TYPE_MONSTER,EdgeImpFilter,nil,"CountEdgeImpMaterial: ") 269 | result = CountPrioTarget(cards,loc,minPrio,TYPE_MONSTER,EdgeImpFilter) 270 | return result 271 | end 272 | 273 | ------------------------ 274 | -------- CHECK --------- 275 | ------------------------ 276 | -- Xyz CHECK 277 | function ToadallyPlayCheck() 278 | return 279 | HasID(AIExtra(),00440556,true) -- Bahamut 280 | and OPTCheck(00440556) 281 | and HasID(AIExtra(),90809975,true) -- Toadally 282 | end 283 | -- Flootgate CHECK 284 | function FlootGateCheatCheck() 285 | if HasID(OppHand(),05851097,true) -- Vanity 286 | or HasID(OppHand(),30241314,true) -- MacroCosmos 287 | or HasID(OppHand(),82732705,true) -- SkillDrain 288 | then 289 | return true 290 | end 291 | if HasID(OppDeck(),05851097,true) then 292 | return HasID(OppDeck(),05851097,true) > (#OppDeck() - 5) 293 | end 294 | if HasID(OppDeck(),30241314,true) then 295 | return HasID(OppDeck(),30241314,true) > (#OppDeck() - 5) 296 | end 297 | if HasID(OppDeck(),82732705,true) then 298 | return HasID(OppDeck(),82732705,true) > (#OppDeck() - 5) 299 | end 300 | return false 301 | end 302 | function FluffalFlootGateFilter(c) 303 | return 304 | ( 305 | c.id==05851097 -- Vanity's Emptiness 306 | or c.id==30241314 -- Macro Cosmos 307 | or c.id==82732705 -- Skill Drain 308 | or c.id==58481572 -- Masked HERO Dark Law 309 | ) 310 | and FilterPosition(c,POS_FACEUP) and NotNegated(c) 311 | end 312 | -- SpSummon FlootGate 313 | function VanityFilter(c) 314 | return 315 | ( 316 | c.id==05851097 -- Vanity's Emptiness 317 | or c.id==41855169 -- Jowgen the Spiritualist 318 | or c.id==42009836 -- Fossil Dyna Pachycephalo 319 | ) and FilterPosition(c,POS_FACEUP) and NotNegated(c) 320 | end 321 | -- SpExtra FlootGate 322 | function ExtraDeckBlockedFilter(c) 323 | return 324 | ( 325 | c.id==84171830 -- Monarch's Field 326 | or c.id==76218313 -- Dragon Buster 327 | ) 328 | and FilterPosition(c,POS_FACEUP) and NotNegated(c) 329 | end 330 | -- Spell FlootGate 331 | function SpellBlockedFilter(c) 332 | return 333 | ( 334 | c.id == 33198837 -- Naturia Beast 335 | or c.id == 58921041 -- Anti-Spell Fragance 336 | ) 337 | and FilterPosition(c,POS_FACEUP) and NotNegated(c) 338 | end 339 | 340 | -- BossMon 341 | function BossMonFilter(c) 342 | return ( 343 | c.id == 58481572 -- DarkLaw 344 | or c.id == 90809975 -- Treatoad 345 | or c.id == 01561110 -- BusterDragon 346 | or c.id == 10443957 -- Infinity 347 | or c.id == 48905153 -- Zodiac Beast Drancia 348 | ) and NotNegated(c) 349 | end 350 | function InfinityMonFilter(c) 351 | return ( 352 | c.id == 90809975 -- Treatoad 353 | or c.id == 10443957 -- Infinity 354 | ) and NotNegated(c) 355 | end 356 | 357 | -- Advantage Filter 358 | function FTigerAdvantageFilter(c) 359 | return 360 | BossMonFilter(c) 361 | end 362 | function FSheepAdvantageFilter(c) 363 | return 364 | BAFilter(c) 365 | or FluffalMetalfoesFilter(c) 366 | or FilterSet(c,0xf1) -- ZodiacBeast 367 | end 368 | 369 | function FluffalMetalfoesFilter(c) 370 | return 371 | --IsSetCode(c.setcode,0xe1) 372 | c.id == 28016193 -- Orichalc 373 | or c.id == 04688231 -- Mythriel 374 | --or c.id == 77693536 -- Alkahest 375 | end 376 | 377 | function MaxxCAdvantageFilter(c) 378 | return 379 | MaxxCZBAdvantageFilter(c) 380 | or (c.id == 58069384 and HasID(OppExtra(),10443957,true)) -- Cyber Dragon Nova 381 | 382 | end 383 | 384 | function MaxxCZBAdvantageFilter(c) 385 | return 386 | c.id == 78872731 -- ZBRat 387 | or c.id == 74393852 -- ZBWildbow 388 | or c.id == 11510448 -- ZBTigress 389 | end 390 | 391 | --[[ 392 | 39246582, -- Fluffal Dog 393 | 13241004, -- Fluffal Penguin 394 | 03841833, -- Fluffal Bear 395 | 65331686, -- Fluffal Owl 396 | 98280324, -- Fluffal Sheep 397 | 87246309, -- Fluffal Octo 398 | 02729285, -- Fluffal Cat 399 | 38124994, -- Fluffal Rabit 400 | 06142488, -- Fluffal Mouse 401 | 72413000, -- Fluffal Wings 402 | 81481818, -- Fluffal Patchwork 403 | 97567736, -- Edge Imp Tomahawk 404 | 61173621, -- Edge Imp Chain 405 | 30068120, -- Edge Imp Sabres 406 | 10802915, -- Tour Guide from the Underworld 407 | 79109599, -- King of the Swamp 408 | 06205579, -- Parasite Fusioner 409 | 67441435, -- Glow-Up Bulb 410 | 411 | 70245411, -- Toy Vendor 412 | 06077601, -- Frightfur Fusion 413 | 43698897, -- Frightfur Factory 414 | 34773082, -- Frightfur Patchwork 415 | 28039390, -- Frightfur Reborn 416 | 01845204, -- Instant Fusion 417 | 24094653, -- Polymerization 418 | 94820406, -- Dark Fusion 419 | 05133471, -- Galaxy Cyclone 420 | 35726888, -- Foolish Burial of Belongings 421 | 43455065, -- Magical Spring 422 | 43898403, -- Twin Twister 423 | 12580477, -- Raigeki 424 | 425 | 66127916, -- Fusion Reserve 426 | 98954106, -- Jar of Avarice 427 | 51452091, -- Royal Decree 428 | 429 | 80889750, -- Frightfur Sabre-Tooth 430 | 40636712, -- Frightfur Kraken 431 | 10383554, -- Frightfur Leo 432 | 85545073, -- Frightfur Bear 433 | 11039171, -- Frightfur Wolf 434 | 00464362, -- Frightfur Tiger 435 | 57477163, -- Frightfur Sheep 436 | 41209827, -- Starve Venom Fusion Dragon 437 | 42110604, -- Hi-Speedroid Chanbara 438 | 83531441, -- Dante 439 | ]] -------------------------------------------------------------------------------- /AI/decks/Fluffal/FluffalBattle.lua: -------------------------------------------------------------------------------- 1 | ------------------------ 2 | -------- BATTLE -------- 3 | ------------------------ 4 | FluffalAtt={ 5 | 39246582, -- Fluffal Dog 6 | 13241004, -- Fluffal Penguin 7 | 97567736, -- Edge Imp Tomahawk 8 | 9 | 91034681, -- Frightfur Daredevil 10 | 80889750, -- Frightfur Sabre-Tooth 11 | 40636712, -- Frightfur Kraken 12 | 10383554, -- Frightfur Leo 13 | 85545073, -- Frightfur Bear 14 | 11039171, -- Frightfur Wolf 15 | 00464362, -- Frightfur Tiger 16 | 57477163, -- Frightfur Sheep 17 | 41209827, -- Starve Venom Fusion Dragon 18 | 42110604, -- Hi-Speedroid Chanbara 19 | 83531441, -- Dante 20 | } 21 | FluffalDef={ 22 | 98280324, -- Fluffal Sheep 23 | 87246309, -- Fluffal Octo 24 | 02729285, -- Fluffal Cat 25 | 38124994, -- Fluffal Rabit 26 | 06142488, -- Fluffal Mouse 27 | 72413000, -- Fluffal Wings 28 | 81481818, -- Fluffal Patchwork 29 | 79109599, -- King of the Swamp 30 | 06205579, -- Parasite Fusioner 31 | 67441435, -- Glow-Up Bulb 32 | } 33 | function FluffalPosition(id,available) -- FLUFFAL POSITION 34 | result = nil 35 | for i=1,#FluffalAtt do 36 | if FluffalAtt[i]==id 37 | then 38 | result = POS_FACEUP_ATTACK 39 | end 40 | end 41 | for i=1,#FluffalDef do 42 | if FluffalDef[i]==id 43 | then 44 | result = 4 -- POS_FACEUP_DEFENSE? 45 | end 46 | end 47 | 48 | if id == 57477163 and GlobalIFusion == 1 then -- FSheep by IFusion 49 | return 4 -- POS_FACEUP_DEFENSE? 50 | end 51 | 52 | if id == 57477163 then -- FSheep 53 | local frightfurAtk = 2000 + FrightfurBoost(id) 54 | --print("FSheep - Atk: "..frightfurAtk) 55 | if FluffalCanAttack(OppMon(),frightfurAtk) == 0 56 | and FluffalCannotAttack(OppMon(),frightfurAtk,FilterPosition,POS_FACEUP_ATTACK) > 0 57 | and frightfurAtk < 3200 58 | then 59 | result = 4 -- POS_FACEUP_DEFENSE? 60 | else 61 | result = 1 -- POS_FACEUP_ATTACK 62 | end 63 | end 64 | 65 | if id == 40636712 then -- FKraken 66 | local frightfurAtk = 2200 + FrightfurBoost(40636712) 67 | print("FKraken Atk: "..frightfurAtk) 68 | if frightfurAtk < 3000 69 | and #OppMon() == 1 70 | and CardsMatchingFilter(OppMon(),FKrakenSendFilter) > 0 71 | and AIGetStrongestAttack() <= OppGetStrongestAttDef() 72 | and frightfurAtk <= OppGetStrongestAttDef() 73 | or 74 | #OppMon() > 1 75 | and FluffalCanAttack(OppMon(),frightfurAtk) == 0 76 | or 77 | not BattlePhaseCheck() 78 | and frightfurAtk < 3000 79 | then 80 | result = 4 -- POS_FACEUP_DEFENSE? 81 | end 82 | end 83 | 84 | if (not BattlePhaseCheck() or AI.GetCurrentPhase() == PHASE_MAIN2) 85 | and ( 86 | id == 65331686 -- Owl 87 | or id == 61173621 -- Chain 88 | or id == 30068120 -- Sabres 89 | or id == 40636712 -- FKraken 90 | or id == 83531441 -- Dante 91 | ) 92 | then 93 | result = 4 -- POS_FACEUP_DEFENSE? 94 | end 95 | 96 | if id == 03113836 -- GKSeraphinite 97 | and GlobalEffectId == 07394770 -- BFusion 98 | then 99 | result = 4 100 | end 101 | return result 102 | end 103 | 104 | function FluffalBattleCommand(cards,activatable) -- FLUFFAL BATTLE COMMAND 105 | ApplyATKBoosts(cards) 106 | for i=1,#cards do 107 | cards[i].index = i 108 | end 109 | 110 | local targets = OppMon() 111 | local attackable = {} 112 | local mustattack = {} 113 | for i=1,#targets do 114 | if targets[i]:is_affected_by(EFFECT_CANNOT_BE_BATTLE_TARGET)==0 then 115 | attackable[#attackable+1]=targets[i] 116 | end 117 | if targets[i]:is_affected_by(EFFECT_MUST_BE_ATTACKED)>0 then 118 | mustattack[#mustattack+1]=targets[i] 119 | end 120 | end 121 | 122 | if #mustattack>0 then 123 | targets = mustattack 124 | else 125 | targets = attackable 126 | end 127 | ApplyATKBoosts(targets) 128 | -- Frightfur Attack 129 | if HasIDNotNegated(cards,57477163) -- FSheep 130 | and CardsMatchingFilter(OppST(),FilterPosition,POS_FACEDOWN) > 0 131 | and ( 132 | CanWinBattle(cards[CurrentIndex],targets,false,false) 133 | or #targets == 0 134 | ) 135 | then 136 | return Attack(IndexByID(cards,57477163)) 137 | end 138 | if HasIDNotNegated(cards,85545073) -- FBear 139 | and CanWinBattle(cards[CurrentIndex],targets,true,false) 140 | then 141 | return Attack(IndexByID(cards,85545073)) 142 | end 143 | if HasIDNotNegated(cards,10383554) -- FLeo 144 | and CanWinBattle(cards[CurrentIndex],targets,false,false) 145 | then 146 | return Attack(IndexByID(cards,10383554)) 147 | end 148 | if HasIDNotNegated(cards,40636712) -- FKraken 149 | and CanWinBattle(cards[CurrentIndex],targets,false,false) 150 | and cards[CurrentIndex]:is_affected_by(EFFECT_CANNOT_DIRECT_ATTACK) > 0 151 | then 152 | return Attack(IndexByID(cards,40636712)) 153 | end 154 | if HasIDNotNegated(cards,57477163) -- FSheep 155 | and ( 156 | CanWinBattle(cards[CurrentIndex],targets,false,false) 157 | or #targets == 0 158 | ) 159 | then 160 | return Attack(IndexByID(cards,57477163)) 161 | end 162 | if HasIDNotNegated(cards,91034681) -- FDaredevil 163 | and CanWinBattle(cards[CurrentIndex],targets,false,false) 164 | and CardsMatchingFilter(targets,FilterPosition,POS_DEFENSE) == #targets 165 | then 166 | return Attack(IndexByID(cards,91034681)) 167 | end 168 | if HasIDNotNegated(cards,80889750) -- FSabreTooth 169 | and CanWinBattle(cards[CurrentIndex],targets,false,false) 170 | and CardsMatchingFilter(targets,FilterPosition,POS_ATTACK) == #targets 171 | then 172 | return Attack(IndexByID(cards,80889750)) 173 | end 174 | 175 | return nil 176 | end 177 | 178 | function FluffalAttackTarget(cards,attacker) -- FLUFFAL ATTACK TARGET 179 | local id = attacker.id 180 | local result ={attacker} 181 | --print("1",attacker.id,attacker.attack,attacker.bonus) 182 | result = {} 183 | local atk = attacker.attack 184 | if NotNegated(attacker) then 185 | -- Frightfur Sheep 186 | if id == 57477163 and CanWinBattle(attacker,cards,true,false) then 187 | return FrighfurAttackTarget(cards,attacker,false) 188 | end 189 | end 190 | return nil 191 | end 192 | 193 | function FluffalAttackBoost(cards) -- FLUFFAL BOOST 194 | for i=1,#cards do 195 | local c = cards[i] 196 | if c.id == 42110604 then -- Chanbara 197 | c.attack = c.attack + 200 198 | end 199 | if c.id == 57477163 then -- FSheep 200 | local boost = FrightfurBoost(0) 201 | if c.attack - boost == c.base_attack 202 | and OPTCheck(57477163) 203 | and AI.GetPlayerLP(1) > 800 204 | and CardsMatchingFilter(OppMon(),FilterPosition,POS_FACEUP_ATTACK) > 0 205 | then 206 | c.bonus = 800 207 | c.attack = c.attack + 800 208 | end 209 | end 210 | end 211 | end 212 | 213 | -- ATTACK FUNCTIONS 214 | function FrighfurAttackTarget(cards,source,ignorebonus,filter,opt) 215 | local atk = source.attack 216 | local bonus = 0 217 | --print("3",source.id,source.attack,source.bonus) 218 | if source.bonus and source.bonus > 0 then 219 | bonus = source.bonus 220 | end 221 | if ignorebonus then 222 | atk = math.max(0,atk - bonus) 223 | end 224 | local result = nil 225 | for i=1,#cards do 226 | local c = cards[i] 227 | c.index = i 228 | c.prio = 0 229 | if FilterPosition(c,POS_FACEUP_ATTACK) then 230 | if c.attackc.attack 237 | then 238 | c.prio = 1 239 | else 240 | c.prio = c.attack 241 | end 242 | else 243 | c.prio = c.attack * -1 244 | end 245 | -- FSheep own boost 246 | if source.id == 57477163 247 | and OPTCheck(57477163) 248 | then 249 | if c.attack >= atk-bonus and c.attack <= atk 250 | then 251 | c.prio = c.attack * 9999 - (atk-c.attack) 252 | end 253 | end 254 | end 255 | if FilterPosition(c,POS_DEFENSE) then 256 | -- FSheep own boost 257 | if source.id == 57477163 258 | and bonus == 800 259 | then 260 | if FilterPublic(c) then 261 | if c.defense<(atk-bonus) then 262 | c.prio = math.max(c.defense - 1,c.attack) 263 | else 264 | c.prio = (atk-bonus) - c.defense 265 | end 266 | end 267 | else 268 | if FilterPublic(c) then 269 | if c.defense0 and not BattleTargetCheck(c,source) then 282 | c.prio = -4 283 | end 284 | if not AttackBlacklistCheck(c,source) then 285 | c.prio = (c.prio or 0)-99999 286 | end 287 | if CanFinishGame(source,c) then 288 | c.prio=99999 289 | end 290 | if FilterPosition(c,POS_DEFENSE) and FilterPrivate(c) then 291 | if atk>=1500 then 292 | c.prio = -1 293 | else 294 | c.prio = -2 295 | end 296 | end 297 | if c.prio and c.prio>0 and FilterPublic(c) then 298 | if FilterType(c,TYPE_SYNCHRO+TYPE_RITUAL+TYPE_XYZ+TYPE_FUSION) then 299 | c.prio = c.prio + 1 300 | end 301 | if FilterType(c,TYPE_EFFECT) then 302 | c.prio = c.prio + 1 303 | end 304 | if c.level>4 then 305 | c.prio = c.prio + 1 306 | end 307 | end 308 | if CurrentOwner(c)==1 then 309 | c.prio = -1*c.prio 310 | end 311 | end 312 | table.sort(cards,function(a,b) return a.prio > b.prio end) 313 | --print("table:") 314 | --print("attacker: "..source.id..", atk: "..atk) 315 | --for i=1,#cards do 316 | --print(i..") id: "..cards[i].id.." index: "..cards[i].index.." prio: "..cards[i].prio) 317 | --end 318 | result={cards[1].index} 319 | return result 320 | end 321 | 322 | function FrightfurBoost(frightfurId) 323 | local boost = 0 324 | local frightufs = CountFrightfurMon(AIMon()) + 1 -- Own 325 | 326 | if frightfurId == 80889750 -- FSabreTooth 327 | then 328 | if CountFrightfurMon(AIGrave()) > 0 then 329 | frightufs = frightufs + 1 330 | if not HasIDNotNegated(AIMon(),00464362,true) -- FTiger Field 331 | and HasIDNotNegated(AIGrave(),00464362,true) -- FTiger Grave 332 | then 333 | boost = boost + (frightufs * 300) 334 | end 335 | end 336 | boost = boost + 400 337 | end 338 | 339 | if frightfurId == 00464362 -- FTiger 340 | then 341 | boost = boost + (frightufs * 300) 342 | end 343 | 344 | if frightfurId == 57477163 -- FSheep 345 | and CardsMatchingFilter(OppMon(),FilterPosition,POS_ATTACK) > 0 346 | and OPTCheck(57477163) 347 | and AI.GetPlayerLP(1) > 800 348 | then 349 | boost = boost + 800 350 | end 351 | 352 | boost = boost + (400 * CardsMatchingFilter(AIMon(),FSabreToothFilter)) --FSabreTooth 353 | 354 | if HasIDNotNegated(AIMon(),00464362,true) -- FTiger 355 | then 356 | boost = boost + (frightufs * 300) 357 | end 358 | 359 | return boost 360 | end 361 | 362 | function FluffalCanAttack(cards,attack,filter,opt) 363 | local result = 0 364 | for i=1, #cards do 365 | local c = cards[i] 366 | if ( 367 | FilterAttackMax(c,attack-1) and FilterPosition(c,POS_ATTACK) 368 | or 369 | FilterDefenseMax(c,attack-1) and FilterPosition(c,POS_DEFENSE) 370 | ) 371 | and FilterCheck(c,filter,opt) 372 | then 373 | result = result + 1 374 | end 375 | end 376 | return result 377 | end 378 | function FluffalCannotAttack(cards,attack,filter,opt) 379 | local result = 0 380 | for i=1, #cards do 381 | local c = cards[i] 382 | if ( 383 | FilterAttackMin(c,attack) and FilterPosition(c,POS_ATTACK) 384 | or 385 | FilterDefenseMin(c,attack) and FilterPosition(c,POS_DEFENSE) 386 | ) 387 | and FilterCheck(c,filter,opt) 388 | then 389 | result = result + 1 390 | end 391 | end 392 | return result 393 | end 394 | 395 | function ExpectedDamageMichelet(player,filter,opt) 396 | if player == nil then player = 1 end 397 | local oppMons = {} 398 | local aiAtts = {} 399 | local aiHasAttacked = 0 400 | 401 | aiAtts = SubGroup(AIMon(),FilterPosition,POS_ATTACK) 402 | oppMons = SubGroup(OppMon(),FilterLocation,LOCATION_MZONE) 403 | 404 | if player == 2 then 405 | aiAtts = SubGroup(OppMon(),FilterPosition,POS_ATTACK) 406 | oppMons = SubGroup(AIMon(),FilterLocation,LOCATION_MZONE) 407 | end 408 | 409 | if #aiAtts > 0 then 410 | table.sort(aiAtts, function(a,b) return a.attack < b.attack end) 411 | end 412 | 413 | if #oppMons > 0 then 414 | table.sort(oppMons, 415 | function(a,b) 416 | local attDefA = 0 417 | local attDefB = 0 418 | if FilterPosition(a,POS_ATTACK) then 419 | attDefA = a.attack 420 | else 421 | attDefA = a.defense 422 | end 423 | if FilterPosition(b,POS_ATTACK) then 424 | attDefB = b.attack 425 | else 426 | attDefB = b.defense 427 | end 428 | return attDefA > attDefB 429 | end 430 | ) 431 | end 432 | 433 | local damageExpectedInBattle = 0 434 | for i=1, #oppMons do 435 | local oppM = oppMons[i] 436 | local oppAttDef = oppM.defense 437 | 438 | local dealDamage = false 439 | if FilterPosition(oppM,POS_ATTACK) then 440 | dealDamage = true 441 | oppAttDef = oppM.attack 442 | end 443 | 444 | --print("oppMon - id: "..oppM.id.." - AttDef: "..oppAttDef) 445 | 446 | for j=1, #aiAtts do 447 | local aiM = aiAtts[j] 448 | local aiAtt = aiM.attack 449 | if FilterCheck(aiM,filter,opt) then 450 | if not oppM.HasBeenDefeated and not aiM.HasAttacked 451 | and AvailableAttacks(aiM) > 0 452 | then 453 | --print("aiAtt: "..aiAtt.." vs oppAttDef: "..oppAttDef) 454 | if aiAtt > oppAttDef then 455 | aiM.HasAttacked = true 456 | oppM.HasBeenDefeated = true 457 | aiHasAttacked = aiHasAttacked + 1 458 | if dealDamage then 459 | damageExpectedInBattle = damageExpectedInBattle + (aiAtt - oppAttDef) 460 | end 461 | end 462 | end 463 | end 464 | end 465 | if not oppM.HasBeenDefeated then 466 | damageExpectedInBattle = damageExpectedInBattle - oppAttDef 467 | end 468 | end 469 | 470 | --print("DamageExpected - In Battle: ".. damageExpectedInBattle) 471 | 472 | local damageExpectedDirect = 0 473 | if aiHasAttacked >= #oppMons 474 | or #oppMons == 0 475 | then 476 | for j=1, #aiAtts do 477 | local aiM = aiAtts[j] 478 | local aiAtt = aiM.attack 479 | --print("aiMon - id: "..aiM.id.." - Att: "..aiAtt) 480 | if FilterCheck(aiM,filter,opt) then 481 | if not aiM.HasAttacked 482 | and not FilterAffected(aiM,EFFECT_CANNOT_DIRECT_ATTACK) 483 | then 484 | --print("DirectDamage: "..(aiAtt * AvailableAttacks(aiM))) 485 | damageExpectedDirect = damageExpectedDirect + (aiAtt * AvailableAttacks(aiM)) 486 | end 487 | end 488 | end 489 | end 490 | 491 | --print("DamageExpected - Direct: ".. damageExpectedDirect) 492 | 493 | return damageExpectedInBattle + damageExpectedDirect 494 | end -------------------------------------------------------------------------------- /AI/decks/Express.lua: -------------------------------------------------------------------------------- 1 | function ExpressStartup(deck) 2 | AI.Chat("Express AI ver 0.0.1") 3 | AI.Chat("produced by Satone") 4 | deck.Init = ExpressInit 5 | deck.Card = ExpressCard 6 | deck.Chain = ExpressChain 7 | deck.EffectYesNo = ExpressEffectYesNo 8 | deck.Position = ExpressPosition 9 | deck.Option = ExpressOption 10 | deck.ActivateBlacklist = ExpressActivateBlacklist 11 | deck.SummonBlacklist = ExpressSummonBlacklist 12 | deck.RepositionBlacklist = ExpressRepositionBlacklist 13 | deck.PriorityList = ExpressPriorityList 14 | end 15 | DECK_EXPRESS = NewDeck("Express",76136345,ExpressStartup) 16 | ExpressActivateBlacklist= 17 | { 18 | 18144506, 19 | 13647631, 20 | 24919805, 21 | 73628505, 22 | 48130397, 23 | 76136345, 24 | 49032236, 25 | } 26 | ExpressSummonBlacklist= 27 | { 28 | 51126152, 29 | 24919805, 30 | 3814632, 31 | 49032236, 32 | 56910167, 33 | } 34 | ExpressRepositionBlacklist= 35 | { 36 | 49032236, 37 | } 38 | function SpSumGustavMax() 39 | return AI.GetPlayerLP(2)<=2000 40 | end 41 | function GangaridaiFilter1(c) 42 | return FilterPosition(c,POS_FACEUP) 43 | and c.id == 13647631 44 | end 45 | function GangaridaiFilter2(c) 46 | return ((c.attack >= 3200 and FilterPosition(c,POS_ATTACK)) 47 | or (c.defense >= 3200 and FilterPosition(c,POS_DEFENSE)) 48 | or c:is_affected_by(EFFECT_INDESTRUCTABLE_BATTLE) 49 | or (MP2Check() and c.attack > 4000)) and not c:is_affected_by(EFFECT_INDESTRUCTABLE_EFFECT) 50 | end 51 | function SpSumGangaridai() 52 | return CardsMatchingFilter(AIMon(),GangaridaiFilter1)<1 and CardsMatchingFilter(OppMon(),GangaridaiFilter2)>0 53 | end 54 | function SpSumSuperiorDora() 55 | return true 56 | end 57 | function ExpressUseShaddollFusion() 58 | return CardsMatchingFilter(AIMon(),FilterRank,10)<1 59 | and (CardsMatchingFilter(AIHand(),FilterSet,0x9d)>1 60 | or (HasID(AIHand(),24919805,true) and Has(AIHand(),23434538,true))) 61 | end 62 | function UseSwitchyard() 63 | return #AIHand()>1 or not HasID(AIHand(),51126152,true) 64 | end 65 | function ExpressInit(cards) 66 | local Act = cards.activatable_cards 67 | local Sum = cards.summonable_cards 68 | local SpSum = cards.spsummonable_cards 69 | local Rep = cards.repositionable_cards 70 | if HasIDNotNegated(Act,56910167) then 71 | return {COMMAND_ACTIVATE,CurrentIndex} 72 | end 73 | if HasIDNotNegated(Act,3814632) and MP2Check() then 74 | return {COMMAND_ACTIVATE,CurrentIndex} 75 | end 76 | if HasIDNotNegated(Act,18144506) and DestroyCheck(OppST(),true)>1 then 77 | return {COMMAND_ACTIVATE,CurrentIndex} 78 | end 79 | if HasIDNotNegated(SpSum,56910167) and SpSumGustavMax() then 80 | GlobalExpressSummon = true 81 | return {COMMAND_SPECIAL_SUMMON,CurrentIndex} 82 | end 83 | if HasIDNotNegated(SpSum,3814632) and SpSumGangaridai() then 84 | GlobalExpressSummon = true 85 | return {COMMAND_SPECIAL_SUMMON,CurrentIndex} 86 | end 87 | if HasIDNotNegated(SpSum,49032236) and SpSumSuperiorDora() then 88 | GlobalExpressSummon = true 89 | return {COMMAND_SPECIAL_SUMMON,CurrentIndex} 90 | end 91 | if HasID(Act,73628505) and not HasID(UseLists({AIHand(),AIST()}),76136345,true) then 92 | return {COMMAND_ACTIVATE,CurrentIndex} 93 | end 94 | if HasID(Act,76136345,nil,nil,LOCATION_HAND) and #AIHand()>1 and not HasID(AIST(),76136345,true) then 95 | return {COMMAND_ACTIVATE,CurrentIndex} 96 | end 97 | if HasID(Act,44394295) and CardsMatchingFilter(OppMon(),ShaddollFusionFilter)>0 then 98 | GlobalCardMode = 1 99 | return {COMMAND_ACTIVATE,CurrentIndex} 100 | end 101 | if HasID(Sum,51126152) and (HasID(AIHand(),13647631,true) 102 | or (HasID(AIST(),76136345,true) and OPTCheck(76136345)) 103 | or HasID(AIST(),82732705,true)) then 104 | return {COMMAND_SUMMON,CurrentIndex} 105 | end 106 | if HasID(Sum,24919805) and FieldCheck(10)>0 and HasID(AIST(),13647631,true) then 107 | return {COMMAND_SUMMON,CurrentIndex} 108 | end 109 | if HasID(Act,44394295) and ExpressUseShaddollFusion() then 110 | GlobalCardMode = 1 111 | return {COMMAND_ACTIVATE,CurrentIndex} 112 | end 113 | if HasID(Act,76136345,nil,nil,LOCATION_SZONE) and UseSwitchyard() then 114 | OPTSet(76136345) 115 | ExpressCardMode = 1 116 | return {COMMAND_ACTIVATE,CurrentIndex} 117 | end 118 | if HasID(Sum,24919805) and not HasID(AIHand(),4939890,true) then 119 | return {COMMAND_SUMMON,CurrentIndex} 120 | end 121 | if HasID(Rep,49032236,FilterPosition,POS_ATTACK) and (OppHasStrongestMonster() or MP2Check()) then 122 | return {COMMAND_CHANGE_POS,CurrentIndex} 123 | end 124 | if HasID(Rep,49032236,FilterPosition,POS_DEFENSE) and not OppHasStrongestMonster() then 125 | return {COMMAND_CHANGE_POS,CurrentIndex} 126 | end 127 | return nil 128 | end 129 | function SetExpressXyzPriority(cards) 130 | for i=1,#cards do 131 | local c = cards[i] 132 | c.index = i 133 | c.prio = - c.attack 134 | end 135 | end 136 | function ExpressXyzSelection(cards,count) 137 | local result = nil 138 | SetExpressXyzPriority(cards) 139 | if cards and #cards>=count then 140 | table.sort(cards,function(a,b)return a.prio>b.prio end) 141 | result = {} 142 | for i=1,count do 143 | result[i] = cards[i].index 144 | end 145 | end 146 | return result 147 | end 148 | function ExpressXyzTarget(cards,mi) 149 | local result = nil 150 | result = ExpressXyzSelection(cards,mi) 151 | return result 152 | end 153 | function SuperiorDoraTarget(cards) 154 | if LocCheck(cards,LOCATION_OVERLAY) then 155 | return Add(cards,PRIO_DISCARD) 156 | end 157 | return GlobalTargetGet(cards,true) 158 | end 159 | function GangaridaiTarget(cards) 160 | if LocCheck(cards,LOCATION_OVERLAY) then 161 | return Add(cards,PRIO_DISCARD) 162 | end 163 | return BestTargets(cards,1,true) 164 | end 165 | function ExpressSuperpolyTarget(cards,mi) 166 | if LocCheck(cards,LOCATION_HAND) then 167 | return Add(cards,PRIO_TOGRAVE) 168 | end 169 | if LocCheck(cards,LOCATION_EXTRA) then 170 | return Add(cards,PRIO_TOFIELD) 171 | end 172 | return BestTargets(cards,mi,TARGET_TOGRAVE) 173 | end 174 | function ExpressCard(cards,min,max,id,c) 175 | if GlobalExpressSummon then 176 | GlobalExpressSummon = nil 177 | return ExpressXyzTarget(cards,min) 178 | end 179 | if id == 76136345 and ExpressCardMode == 1 then 180 | ExpressCardMode = nil 181 | return Add(cards,PRIO_TOGRAVE,max) 182 | end 183 | if id == 76136345 and ExpressCardMode == nil then 184 | return Add(cards,PRIO_TOHAND,max) 185 | end 186 | if id == 13647631 then 187 | if HasID(OppMon(),56832966,true) then 188 | GlobalTargetSet(Duel.GetFirstMatchingCard(function(c) 189 | return c:IsCode(56832966) 190 | end,player_ai,0,LOCATION_SZONE,nil)) 191 | return GlobalTargetGet(cards,true) 192 | end 193 | return BestTargets(cards,max,true) 194 | end 195 | if id == 49032236 then 196 | return SuperiorDoraTarget(cards) 197 | end 198 | if id == 56910167 then 199 | return Add(cards,PRIO_DISCARD) 200 | end 201 | if id == 3814632 then 202 | return GangaridaiTarget(cards) 203 | end 204 | if id == 48130397 then 205 | return ExpressSuperpolyTarget(cards,min) 206 | end 207 | return nil 208 | end 209 | function RemovalCheckDora(target,category,type,chainlink,filter,opt) 210 | if Duel.GetCurrentChain() == 0 then return false end 211 | local cat={CATEGORY_DESTROY,CATEGORY_REMOVE, 212 | CATEGORY_TOGRAVE,CATEGORY_TOHAND, 213 | CATEGORY_TODECK,CATEGORY_CONTROL,CATEGORY_POSITION} 214 | if card and filter and (opt and not filter(card,opt) 215 | or opt==nil and not filter(card)) 216 | then 217 | return false 218 | end 219 | if category then cat={category} end 220 | local a=1 221 | local b=Duel.GetCurrentChain() 222 | if chainlink then 223 | a=chainlink 224 | b=chainlink 225 | end 226 | for i=1,#cat do 227 | for j=a,b do 228 | local ex,cg = Duel.GetOperationInfo(j,cat[i]) 229 | local e = Duel.GetChainInfo(j,CHAININFO_TRIGGERING_EFFECT) 230 | if ex and CheckNegated(j) and (type==nil 231 | or e and e:GetHandler():IsType(type)) 232 | then 233 | if target==nil then 234 | return cg 235 | end 236 | if cg and target then 237 | local card=false 238 | cg:ForEach(function(c) 239 | local c=GetCardFromScript(c,Field()) 240 | if CardsEqual(c,target) then 241 | card=c 242 | end end) 243 | return card 244 | end 245 | end 246 | end 247 | end 248 | return false 249 | end 250 | function ChainSuperiorDora(card) 251 | if RemovalCheckDora(card) then 252 | GlobalTargetSet(card,AIMon()) 253 | return true 254 | end 255 | if HasID(OppMon(),56832966,true) then 256 | local materials = card.xyz_materials 257 | for i=1,#materials do 258 | if materials[i].id == 13647631 then 259 | return true 260 | end 261 | end 262 | end 263 | return false 264 | end 265 | function ExpressChainSuperpoly() 266 | if CardsMatchingFilter(OppMon(),FilterType,TYPE_SYNCHRO+TYPE_XYZ)>1 then 267 | return true 268 | end 269 | if CardsMatchingFilter(OppMon(),FilterAttribute,ATTRIBUTE_LIGHT+ATTRIBUTE_EARTH+ATTRIBUTE_DARK+ATTRIBUTE_WATER)>0 then 270 | return true 271 | end 272 | if CardsMatchingFilter(OppMon(),FilterSet,0x8)>0 then 273 | return true 274 | end 275 | return false 276 | end 277 | function ExpressSkillFilter(c) 278 | return FilterRank(c,10) and c.xyz_material_count>0 279 | end 280 | function QliphortAttackBonus(id,level,c) 281 | if level == 4 then 282 | if id == 90885155 or id == 64496451 283 | or id == 13073850 284 | then 285 | return 1000 286 | elseif id == 37991342 or id == 91907707 then 287 | return 600 288 | end 289 | end 290 | if c and c:IsHasEffect(EFFECT_SET_BASE_ATTACK) then 291 | if id == 51126152 then 292 | return 3000 293 | elseif id == 13647631 then 294 | return 1400 295 | end 296 | end 297 | return 0 298 | end 299 | function ChainSkillDrain(card) 300 | if CardsMatchingFilter(AIMon(),ExpressSkillFilter)>0 then 301 | return false 302 | end 303 | local c = ChainCardNegation(card,false,false,FilterType,TYPE_MONSTER) 304 | if c then 305 | return true 306 | end 307 | if IsBattlePhase() then 308 | if Duel.GetTurnPlayer()==player_ai 309 | and not OppHasStrongestMonster() 310 | and CardsMatchingFilter(OppMon(),NegateBPCheck)>0 311 | then 312 | return true 313 | end 314 | local source = Duel.GetAttacker() 315 | local target = Duel.GetAttackTarget() 316 | if source and target then 317 | if source:IsControler(player_ai) then 318 | target = Duel.GetAttacker() 319 | source = Duel.GetAttackTarget() 320 | end 321 | if target:IsControler(player_ai) 322 | and (source:IsPosition(POS_FACEUP_ATTACK) 323 | and source:GetAttack() >= target:GetAttack() 324 | and source:GetAttack() <= target:GetAttack()+QliphortAttackBonus(target:GetCode(),target:GetLevel(),target) 325 | and not (source:GetAttack() == target:GetAttack() 326 | and QliphortAttackBonus(target:GetCode(),target:GetLevel(),target)==0) 327 | or source:IsPosition(POS_FACEUP_DEFENSE) 328 | and source:GetDefense() >= target:GetAttack() 329 | and source:GetDefense() < target:GetAttack()+QliphortAttackBonus(target:GetCode(),target:GetLevel(),target)) 330 | and target:IsPosition(POS_FACEUP_ATTACK) 331 | then 332 | return true 333 | end 334 | end 335 | end 336 | return false 337 | end 338 | function ExpressChainChalice() 339 | local e = Duel.GetChainInfo(Duel.GetCurrentChain(), CHAININFO_TRIGGERING_EFFECT) 340 | if e then 341 | local c = e:GetHandler() 342 | end 343 | if c and (c:GetCode()==27243130 or c:GetCode()==37742478) then 344 | return false 345 | end 346 | local source = Duel.GetAttacker() 347 | local target = Duel.GetAttackTarget() 348 | if source and target then 349 | if source:IsControler(player_ai) then 350 | target = Duel.GetAttacker() 351 | source = Duel.GetAttackTarget() 352 | end 353 | end 354 | if Duel.GetCurrentPhase() == PHASE_DAMAGE and source and target then 355 | if source:GetAttack() >= target:GetAttack() 356 | and source:GetAttack() <= target:GetAttack()+QliphortAttackBonus(target:GetCode(),target:GetLevel(),target)+400 357 | and source:IsPosition(POS_FACEUP_ATTACK) and target:IsPosition(POS_FACEUP_ATTACK) and target:IsControler(player_ai) 358 | and (not target:IsHasEffect(EFFECT_IMMUNE_EFFECT) or target:IsSetCard(0xaa) and target:GetCode()~=27279764) 359 | then 360 | GlobalTargetSet(target,AIMon()) 361 | return true 362 | end 363 | end 364 | return false 365 | end 366 | function ExpressChain(cards) 367 | if HasID(cards,24919805) then 368 | return {1,CurrentIndex} 369 | end 370 | if HasID(cards,49032236,ChainSuperiorDora) then 371 | return {1,CurrentIndex} 372 | end 373 | if HasID(cards,48130397,ExpressChainSuperPoly) then 374 | return {1,CurrentIndex} 375 | end 376 | if HasID(cards,25789292,ExpressChainChalice) then 377 | return {1,CurrentIndex} 378 | end 379 | if HasID(cards,13647631,FilterLocation,LOCATION_HAND) and FieldCheck(10)>0 then 380 | return {1,CurrentIndex} 381 | end 382 | if HasIDNotNegated(cards,74822425,ChainNegation) then 383 | return {1,CurrentIndex} 384 | end 385 | return nil 386 | end 387 | function ExpressOption(opt) 388 | for i=1,#opt do 389 | if opt[i] == 51126152 * 16 then 390 | return i 391 | end 392 | end 393 | return nil 394 | end 395 | function SuperiorDoraPosFilter(c) 396 | return c.attack >= 3200 397 | end 398 | function ExpressPosition(id,available) 399 | local result = nil 400 | if id == 49032236 and (CardsMatchingFilter(OppMon(),SuperiorDoraPosFilter)>0 401 | or AI.GetCurrentPhase() == PHASE_MAIN2 or Duel.GetTurnCount() ==1 402 | or not GlobalBPAllowed) then 403 | result = POS_FACEUP_DEFENSE 404 | end 405 | return result 406 | end 407 | function ExpressEffectYesNo(id,card) 408 | local result = nil 409 | if id == 76136345 or id == 13647631 or id == 74822425 then 410 | result = 1 411 | end 412 | return result 413 | end 414 | function NEKCond(loc,c) 415 | if loc == PRIO_TOHAND then 416 | return not HasID(AIHand(),51126152,true) 417 | end 418 | return true 419 | end 420 | function DerricCond(loc,c) 421 | if loc == PRIO_TOHAND then 422 | return not HasID(AIHand(),13647631,true) 423 | end 424 | if loc == PRIO_DISCARD then 425 | return DestroyCheck(OppField(),true)>0 426 | end 427 | return true 428 | end 429 | function BattrainGraveFilter(c) 430 | return c.id == 24919805 431 | and c.turnid == Duel.GetTurnCount() 432 | end 433 | function BattrainCond(loc,c) 434 | if loc == PRIO_GRAVE or loc == PRIO_DISCARD then 435 | return CardsMatchingFilter(AIGrave(),BattrainGraveFilter)==0 436 | end 437 | return true 438 | end 439 | function ExpressNagaCond(loc,c) 440 | if loc == PRIO_TOFIELD then 441 | return CardsMatchingFilter(OppMon(),ShaddollFusionFilter)>0 442 | or (HasID(AIHand(),24919805,true) and HasID(AIHand(),23434538,true)) 443 | end 444 | return true 445 | end 446 | function ExpressNodenCond(loc,c) 447 | if loc == PRIO_TOFIELD then 448 | return CardsMatchingFilter(OppMon(),FilterType,TYPE_SYNCHRO+TYPE_XYZ)>1 449 | end 450 | return true 451 | end 452 | ExpressPriorityList={ 453 | [51126152] = {12,8,1,1,-1,1,0,1,1,1,NEKCond}, 454 | [13647631] = {11,7,1,1,-1,1,12,-1,1,1,DerricCond}, 455 | [24919805] = {1,1,1,1,12,-1,11,-1,1,1,Battraincond}, 456 | [76136345] = {1,1,1,1,-1,1,1,1,1,1,nil}, 457 | [74822425] = {1,1,9,3,1,1,1,1,1,1,ExpressNagaCond}, 458 | [49032236] = {1,1,1,1,-12,1,1,1,1,1,nil}, 459 | [19261966] = {1,1,10,4,1,1,1,1,1,1,nil}, 460 | [45170821] = {1,1,11,5,1,1,1,1,1,1,nil}, 461 | [22061412] = {1,1,12,6,1,1,1,1,1,1,nil}, 462 | [17412721] = {1,1,13,1,1,1,1,1,1,1,ExpressNodenCond}, 463 | } -------------------------------------------------------------------------------- /AI/decks/Cth.lua: -------------------------------------------------------------------------------- 1 | function CthStartup(deck) 2 | AI.Chat("Cth AI ver -3.0.0") 3 | AI.Chat("produced by Ildana & Satone") 4 | deck.Init = CthOnSelectInit 5 | deck.Card = CthOnSelectCard 6 | deck.Chain = CthOnSelectChain 7 | deck.EffectYesNo = CthOnSelectEffectYesNo 8 | deck.Position = CthOnSelectPosition 9 | deck.Option = CthOnSelectOption 10 | -- deck.ActivateBlackList = CthActivateBlackList 11 | -- deck.SummonBlackList = CthSummonBlackList 12 | deck.PriorityList = CthPriorityList 13 | local e1=Effect.GlobalEffect() 14 | e1:SetType(EFFECT_TYPE_FIELD) 15 | e1:SetCode(EFFECT_PUBLIC) 16 | e1:SetTargetRange(LOCATION_HAND,0) 17 | --Duel.RegisterEffect(e1,player_ai) 18 | end 19 | DECK_CTH = NewDeck("Cth",12948099,CthStartup) 20 | CthPriorityList={ 21 | [15839054] = {1,1,-10,1,9.5,1,1,1,-10,1,nil}, 22 | [17412721] = {1,1,6,1,1.5,1,1,1,1,1,nil}, 23 | [11066358] = {1,1,0.5,1,1,1,1,1,1,1,nil}, 24 | [28985331] = {13,1,1,1,5,1,1,1,1,1,nil}, 25 | [12948099] = {1,1,2,1,2,1,0.5,1,1,1,nil}, 26 | [15981690] = {1,1,-10,1,10,1,1,1,1,1,nil}, 27 | [74694807] = {3,1,1,1,1,1,1,1,1,1,nil}, 28 | [67556500] = {1,1,1,1,-99,1,-99,1,1,1,nil}, 29 | [35952884] = {1,1,1,1,1,1,-99,1,1,1,nil}, 30 | [10443957] = {1,1,1,1,1,1,-99,1,1,1,nil}, 31 | } 32 | function AssignCthFusSub(cards) 33 | for i=1,#cards do 34 | local c = cards[i] 35 | c.index=i 36 | c.prio=GetPriority(c,PRIO_DISCARD) 37 | if c.level>4 then 38 | c.prio=-99 39 | end 40 | if c.rank>4 then 41 | c.prio=-99 42 | end 43 | if bit32.band(c.type,TYPE_XYZ+TYPE_SYNCHRO)==0 then 44 | c.prio=-99 45 | end 46 | end 47 | end 48 | function UseCthFusSub(cards,count) 49 | AssignCthFusSub(cards) 50 | table.sort(cards,function(a,b) return a.prio>b.prio end) 51 | return cards[count].prio>0 52 | end 53 | function AssignCthSC(cards) 54 | for i=1,#cards do 55 | local c = cards[i] 56 | c.index=i 57 | c.prio=GetPriority(c,PRIO_TOFIELD) 58 | if bit32.band(c.type,TYPE_MONSTER)==0 or c.id == 8903700 or c.rank == 4 then 59 | c.prio=-99 60 | end 61 | end 62 | end 63 | function UseCthSC(cards,count) 64 | AssignCthSC(cards) 65 | table.sort(cards,function(a,b) return a.prio>b.prio end) 66 | return cards[count].prio>0 67 | end 68 | function AssignCthXyz(cards) 69 | for i=1,#cards do 70 | local c = cards[i] 71 | c.index=i 72 | c.prio=GetPriority(c,PRIO_TOGRAVE) 73 | if c.level~=4 then 74 | c.prio=-99 75 | end 76 | end 77 | end 78 | function UseCthXyz(cards,count) 79 | AssignCthXyz(cards) 80 | table.sort(cards,function(a,b) return a.prio>b.prio end) 81 | return cards[count].prio>0 82 | end 83 | function UseCthDraw() 84 | return #AIDeck()>1 and #AIMon()<5 85 | end 86 | function CthRebornFilter(c) 87 | return bit32.band(c.type,TYPE_MONSTER)>0 88 | end 89 | function CthOnSelectInit(cards,to_bp_allowed,to_ep_allowed) 90 | local Activatable = cards.activatable_cards 91 | local Summonable = cards.summonable_cards 92 | local SpSummonable = cards.spsummonable_cards 93 | local SetableMon = cards.monster_setable_cards 94 | local SetableST = cards.st_setable_cards 95 | if CthVoid and CthVoidCount ~= Duel.GetTurnCount() then 96 | CthVoid = false 97 | end 98 | if HasID(Activatable,32807846) and not HasID(AIDeck(),99185129,true) then 99 | return {COMMAND_ACTIVATE,CurrentIndex} 100 | end 101 | if HasID(Activatable,54719828) then 102 | return {COMMAND_ACTIVATE,CurrentIndex} 103 | end 104 | if HasID(Activatable,18144506) then 105 | return {COMMAND_ACTIVATE,CurrentIndex} 106 | end 107 | if HasID(Activatable,99185129,false,99185129*16) and HasID(AIGrave(),79606837,true) then 108 | return {COMMAND_ACTIVATE,CurrentIndex} 109 | end 110 | if HasID(SpSummonable,79606837) then 111 | return {COMMAND_SPECIAL_SUMMON,CurrentIndex} 112 | end 113 | if HasID(SpSummonable,12948099) then 114 | return {COMMAND_SPECIAL_SUMMON,CurrentIndex} 115 | end 116 | if HasID(SpSummonable,67556500) then 117 | return {COMMAND_SPECIAL_SUMMON,CurrentIndex} 118 | end 119 | if HasID(Activatable,1845204) and (HasID(AIGrave(),11066358,true) or HasID(AIMon(),28985331,true)) and HasID(AIGrave(),15839054,true) then 120 | return {COMMAND_ACTIVATE,CurrentIndex} 121 | end 122 | if HasID(Activatable,74694807) then 123 | return {COMMAND_ACTIVATE,CurrentIndex} 124 | end 125 | if HasID(Activatable,24094653,false,nil,LOCATION_HAND) and UseCthFusSub(AIMon(),2) then 126 | return {COMMAND_ACTIVATE,CurrentIndex} 127 | end 128 | if HasID(Activatable,581014,false,581014*16+2) then 129 | return {COMMAND_ACTIVATE,CurrentIndex} 130 | end 131 | if HasID(SpSummonable,581014) then 132 | return {COMMAND_SPECIAL_SUMMON,CurrentIndex} 133 | end 134 | if HasID(Activatable,74845897) then 135 | return {COMMAND_ACTIVATE,CurrentIndex} 136 | end 137 | if HasID(Activatable,54447022) and UseCthSC(AIGrave(),1) then 138 | return {COMMAND_ACTIVATE,CurrentIndex} 139 | end 140 | if HasID(Activatable,83764718) and UseCthSC(AIGrave(),1) then 141 | return {COMMAND_ACTIVATE,CurrentIndex} 142 | end 143 | if HasID(SpSummonable,10443957) then 144 | return {COMMAND_SPECIAL_SUMMON,CurrentIndex} 145 | end 146 | if HasID(SpSummonable,18326736) and UseCthXyz(AIMon(),3) then 147 | CthPtolemai = true 148 | return {COMMAND_SPECIAL_SUMMON,CurrentIndex} 149 | end 150 | if HasID(SpSummonable,35952884) then 151 | return {COMMAND_SPECIAL_SUMMON,CurrentIndex} 152 | end 153 | if HasID(SpSummonable,54719828) then 154 | return {COMMAND_SPECIAL_SUMMON,CurrentIndex} 155 | end 156 | if HasID(Activatable,34086406,false,34086406*16+1) then 157 | return {COMMAND_ACTIVATE,CurrentIndex} 158 | end 159 | if HasID(SpSummonable,34086406) and UseCthXyz(AIMon(),2) and HasID(AIDeck(),8903700,true) then 160 | return {COMMAND_SPECIAL_SUMMON,CurrentIndex} 161 | end 162 | if HasID(SpSummonable,82633039) and UseCthXyz(AIMon(),2) then 163 | return {COMMAND_SPECIAL_SUMMON,CurrentIndex} 164 | end 165 | if HasID(Summonable,28985331) and (HasID(Activatable,15981690,true) or HasID(Activatable,81439173,true) or HasID(AIMon(),11066358,true)) and (HasID(Activatable,54447022,true) or HasID(Activatable,83764718,true) or HasID(Activatable,1845204,true)) then 166 | return {COMMAND_SUMMON,CurrentIndex} 167 | end 168 | if HasID(Activatable,32807846) and (HasID(Activatable,15981690,true) or HasID(Activatable,81439173,true) or HasID(AIMon(),11066358,true)) and (HasID(Activatable,54447022,true) or HasID(Activatable,83764718,true) or HasID(Activatable,1845204,true)) then 169 | return {COMMAND_ACTIVATE,CurrentIndex} 170 | end 171 | if HasID(Summonable,15839054) and HasID(AIMon(),11066358,true) then 172 | return {COMMAND_SUMMON,CurrentIndex} 173 | end 174 | if HasID(Activatable,81439173) and (HasID(Summonable,15839054,true) or HasID(AIMon(),15839054,true)) then 175 | return {COMMAND_ACTIVATE,CurrentIndex} 176 | end 177 | if HasID(Activatable,15981690) and (HasID(Summonable,15839054,true) or HasID(AIMon(),15839054,true)) then 178 | return {COMMAND_ACTIVATE,CurrentIndex} 179 | end 180 | if HasID(Activatable,911883) and HasID(Summonable,15839054,true) then 181 | return {COMMAND_ACTIVATE,CurrentIndex} 182 | end 183 | if HasID(Activatable,911883) and (HasID(Summonable,28985331,true) or HasID(Activatable,32807846,true)) and (HasID(Activatable,54447022,true) or HasID(Activatable,83764718,true) or HasID(Activatable,1845204,true)) then 184 | return {COMMAND_ACTIVATE,CurrentIndex} 185 | end 186 | if HasID(Activatable,70368879) and UseCthDraw() then 187 | return {COMMAND_ACTIVATE,CurrentIndex} 188 | end 189 | if HasID(Activatable,33782437) and UseCthDraw() then 190 | return {COMMAND_ACTIVATE,CurrentIndex} 191 | end 192 | if HasID(Activatable,74117290) and UseCthDraw() and not HasID(Activatable,72892473,true) then 193 | return {COMMAND_ACTIVATE,CurrentIndex} 194 | end 195 | if HasID(Activatable,24094653,false,nil,LOCATION_GRAVE) and UseCthDraw() then 196 | return {COMMAND_ACTIVATE,CurrentIndex} 197 | end 198 | if HasID(Activatable,93946239) and UseCthDraw() then 199 | CthVoid = true 200 | CthVoidCount = Duel.GetTurnCount() 201 | return {COMMAND_ACTIVATE,CurrentIndex} 202 | end 203 | if HasID(Summonable,15839054) and HasID(Activatable,72892473,true) and HasID(AIHand(),15981690,true) then 204 | return {COMMAND_SUMMON,CurrentIndex} 205 | end 206 | if HasID(SetableST,1845204) and HasID(Activatable,72892473,true) then 207 | return {COMMAND_SET_ST,CurrentIndex} 208 | end 209 | if HasID(SetableST,97211663) and HasID(AIMon(),10443957,true) then 210 | return {COMMAND_SET_ST,CurrentIndex} 211 | end 212 | if HasID(Activatable,72892473) and UseCthDraw() and #AIHand()<#AIDeck()+1 then 213 | return {COMMAND_ACTIVATE,CurrentIndex} 214 | end 215 | if HasID(Activatable,97211663) then 216 | return {COMMAND_ACTIVATE,CurrentIndex} 217 | end 218 | if HasID(SetableMon,8903700) then 219 | return {COMMAND_SET_MONSTER,CurrentIndex} 220 | end 221 | if HasID(SetableMon,15981690) then 222 | return {COMMAND_SET_MONSTER,CurrentIndex} 223 | end 224 | if HasID(SetableST,18144506) and CthVoid then 225 | return {COMMAND_SET_ST,CurrentIndex} 226 | end 227 | if HasID(SetableST,54447022) and CthVoid then 228 | return {COMMAND_SET_ST,CurrentIndex} 229 | end 230 | if HasID(SetableST,83764718) and CthVoid then 231 | return {COMMAND_SET_ST,CurrentIndex} 232 | end 233 | if HasID(SetableST,1845204) and CthVoid then 234 | return {COMMAND_SET_ST,CurrentIndex} 235 | end 236 | if HasID(SetableST,74845897) and CthVoid then 237 | return {COMMAND_SET_ST,CurrentIndex} 238 | end 239 | if HasID(SetableST,74694807) and CthVoid then 240 | return {COMMAND_SET_ST,CurrentIndex} 241 | end 242 | if HasID(SetableST,81439173) and CthVoid then 243 | return {COMMAND_SET_ST,CurrentIndex} 244 | end 245 | if HasID(SetableST,911883) and CthVoid then 246 | return {COMMAND_SET_ST,CurrentIndex} 247 | end 248 | if HasID(SetableST,97211663) and CthVoid then 249 | return {COMMAND_SET_ST,CurrentIndex} 250 | end 251 | if HasID(SetableST,32807846) and CthVoid then 252 | return {COMMAND_SET_ST,CurrentIndex} 253 | end 254 | if HasID(SetableST,24094653) and CthVoid then 255 | return {COMMAND_SET_ST,CurrentIndex} 256 | end 257 | if HasID(SetableST,93946239) and CthVoid then 258 | return {COMMAND_SET_ST,CurrentIndex} 259 | end 260 | if HasID(SetableST,98494543) and CthVoid then 261 | return {COMMAND_SET_ST,CurrentIndex} 262 | end 263 | return {COMMAND_TO_NEXT_PHASE,1} 264 | end 265 | function CthNodenTarget(cards) 266 | if HasID(cards,15839054) and HasID(AIExtra(),581014,true) then 267 | return {CurrentIndex} 268 | elseif HasID(cards,12948099) then 269 | return {CurrentIndex} 270 | else 271 | return Add(cards,PRIO_TOFIELD) 272 | end 273 | end 274 | function CthLavChainTarget(cards) 275 | if HasID(cards,8903700) then 276 | return {CurrentIndex} 277 | else 278 | return Add(cards,PRIO_TOGRAVE) 279 | end 280 | end 281 | function CthRebornTarget(cards) 282 | if HasID(cards,17412721) and #AIMon()<4 then 283 | return {CurrentIndex} 284 | else 285 | return Add(cards,PRIO_TOFIELD) 286 | end 287 | end 288 | function CthCycleTarget(cards) 289 | if HasID(cards,8903700) then 290 | return {CurrentIndex} 291 | else 292 | return Add(cards,PRIO_TOFIELD) 293 | end 294 | end 295 | function CthArmaTarget(cards) 296 | if HasID(cards,15839054) then 297 | return {CurrentIndex} 298 | else 299 | return Add(cards,PRIO_TOFIELD) 300 | end 301 | end 302 | function CthSoulChargeTarget(cards,max) 303 | return Add(cards,PRIO_TOFIELD,max) 304 | end 305 | cthdwd={} 306 | function SetCthDWDPriority(cards) 307 | cthdwd[911883]=0 308 | cthdwd[15839054]=0 309 | for i=1,#cards do 310 | local c = cards[i] 311 | c.index = i 312 | c.prio = 0 313 | if c.id == 15981690 then 314 | c.prio = 50 315 | end 316 | if c.id == 8903700 then 317 | c.prio = 49 318 | end 319 | if c.id == 99185129 then 320 | c.prio = 48 321 | end 322 | if c.id == 911883 then 323 | if cthdwd[c.id] == 0 then 324 | cthdwd[c.id] = 1 325 | else 326 | c.prio = 47 327 | end 328 | end 329 | if c.id == 11066358 and not HasID(AIGrave(),c.id,true) then 330 | c.prio = 46 331 | end 332 | if c.id == 15839054 then 333 | if cthdwd[c.id] == 0 then 334 | cthdwd[c.id] = 1 335 | else 336 | c.prio = 45 337 | end 338 | end 339 | if c.id == 18144506 then 340 | c.prio = 44 341 | end 342 | if c.id == 24094653 then 343 | c.prio = 43 344 | end 345 | if c.id == 98494543 then 346 | c.prio = 42 347 | end 348 | if c.id == 74694807 and not HasID(AIGrave(),c.id,true) then 349 | c.prio = 41 350 | end 351 | if c.id == 74845897 then 352 | c.prio = 40 353 | end 354 | if c.id == 74117290 then 355 | c.prio = 39 356 | end 357 | if c.id == 93946239 then 358 | c.prio = 38 359 | end 360 | end 361 | end 362 | function CthDWDDiscard(cards,count) 363 | local result={} 364 | SetCthDWDPriority(cards) 365 | if cards and #cards>0 then 366 | table.sort(cards,function(a,b)return a.prio>b.prio end) 367 | for i=1,count do 368 | result[i]=cards[i].index 369 | end 370 | end 371 | return result 372 | end 373 | function CthDWDTarget(cards,count) 374 | local result = nil 375 | result = CthDWDDiscard(cards,count) 376 | if result == nil then 377 | result = {} 378 | for i=1,count do 379 | result[i]=i 380 | end 381 | end 382 | return result 383 | end 384 | function CthOnSelectCard(cards, minTargets, maxTargets,ID,triggeringCard) 385 | if ID == 15839054 then 386 | return Add(cards,PRIO_TOHAND,maxTargets) 387 | end 388 | if ID == 81439173 or ID == 54719828 then 389 | return Add(cards,PRIO_TOGRAVE,maxTargets) 390 | end 391 | if ID == 24094653 then 392 | return Add(cards,PRIO_DISCARD,maxTargets) 393 | end 394 | if ID == 54447022 then 395 | local x = maxTargets 396 | if HasID(AIGrave(),17412721,true) and x>1 then 397 | x = x-1 398 | end 399 | return CthSoulChargeTarget(cards,x) 400 | end 401 | if ID == 34086406 then 402 | return CthLavChainTarget(cards) 403 | end 404 | if ID == 17412721 then 405 | return CthNodenTarget(cards) 406 | end 407 | if ID == 83764718 then 408 | return CthRebornTarget(cards) 409 | end 410 | if ID == 97211663 then 411 | return CthCycleTarget(cards) 412 | end 413 | if ID == 28985331 then 414 | return CthArmaTarget(cards) 415 | end 416 | if ID == 74117290 then 417 | return CthDWDTarget(cards,1) 418 | end 419 | if CthPtolemai then 420 | CthPtolemai = false 421 | local x = maxTargets 422 | if HasID(AIMon(),67556500,true) then 423 | x = x-1 424 | end 425 | return Add(cards,PRIO_TOGRAVE,x) 426 | end 427 | return nil 428 | end 429 | function CthOnSelectEffectYesNo(id,triggeringCard) 430 | if id == 67556500 then 431 | return 0 432 | end 433 | return nil 434 | end 435 | function CthNeverChain() 436 | local cc = Duel.GetCurrentChain() 437 | local p = Duel.GetChainInfo(cc,CHAININFO_TRIGGERING_PLAYER) 438 | if p == player_ai then 439 | return true 440 | end 441 | return false 442 | end 443 | function CthOnSelectChain(cards) 444 | if HasID(cards,79606837) and CthNeverChain() then 445 | return {0,CurrentIndex} 446 | end 447 | return nil 448 | end 449 | function CthOnSelectOption(options) 450 | for i=1,#options do 451 | if options[i] == 72 and Duel.GetTurnCount()<3 then 452 | return i 453 | end 454 | if options[i] == 71 and Duel.GetTurnCount()>2 then 455 | return i 456 | end 457 | end 458 | return nil 459 | end 460 | CthAtt={67556500,12948099} 461 | CthDef={15839054,79606837,11066358} 462 | function CthGetPos(id) 463 | result = nil 464 | for i=1,#CthAtt do 465 | if CthAtt[i]==id then return POS_FACEUP_ATTACK end 466 | end 467 | for i=1,#CthDef do 468 | if CthDef[i]==id then return POS_FACEUP_DEFENSE end 469 | end 470 | return result 471 | end 472 | function CthOnSelectPosition(id, available) 473 | return CthGetPos(id) 474 | end -------------------------------------------------------------------------------- /AI/decks/DDD.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | 74069667 -- Abyss Ragnarok 3 | 19302550 -- Newton 4 | 19808608 -- Berformet 5 | 72181263 -- Orthros 6 | 46796664 -- Copernicus 7 | 48210156 -- Night Howling 8 | 45206713 -- Swirl Slime 9 | 72291412 -- Necro Slime 10 | 19580308 -- Lamia 11 | 11609969 -- Kepler 12 | 02295440 -- One for one 13 | 12580477 -- Raigeki 14 | 43898403 -- Twin Twister 15 | 46372010 -- Gate 16 | 73360025 -- Swamp King 17 | 05851097 -- Vanity 18 | 40605147 -- Solemn Strike 19 | 84749824 -- Solemn Warning 20 | 21 | 27873305 -- Caesar Ragnarok 22 | 82956492 -- D'Arc 23 | 74583607 -- Temujin 24 | 52687916 -- Trishula 25 | 81020646 -- Void Ogre Dragon 26 | 50954680 -- Crystal Wing 27 | 44852429 -- Siegfried 28 | 00987311 -- Alexander 29 | 15939229 -- Kali Yuga 30 | 71612253 -- Tell 31 | 03758046 -- Caesar 32 | ]] 33 | 34 | function DDDStartup(deck) 35 | deck.Init = DDDInit 36 | deck.Card = DDDCard 37 | deck.Chain = DDDChain 38 | deck.EffectYesNo = DDDEffectYesNo 39 | deck.Position = DDDPosition 40 | deck.YesNo = DDDYesNo 41 | deck.BattleCommand = DDDBattleCommand 42 | deck.AttackTarget = DDDAttackTarget 43 | deck.AttackBoost = DDDAttackBoost 44 | deck.Tribute = DDDTribute 45 | deck.Option = DDDOption 46 | deck.ChainOrder = DDDChainOrder 47 | --[[ 48 | deck.Sum 49 | deck.DeclareCard 50 | deck.Number 51 | deck.Attribute 52 | deck.MonsterType 53 | ]] 54 | deck.ActivateBlacklist = DDDActivateBlacklist 55 | deck.SummonBlacklist = DDDSummonBlacklist 56 | deck.RepositionBlacklist = DDDRepoBlacklist 57 | deck.SetBlacklist = DDDSetBlacklist 58 | deck.Unchainable = DDDUnchainable 59 | --[[ 60 | 61 | ]] 62 | deck.PriorityList = DDDPriorityList 63 | 64 | DDDRegisterCombos() 65 | 66 | end 67 | 68 | 69 | DDDIdentifier = 11609969 -- DD Savant Kepler 70 | 71 | DECK_DDD = NewDeck("DDD",DDDIdentifier,DDDStartup) 72 | 73 | 74 | DDDActivateBlacklist={ 75 | 74069667, -- Abyss Ragnarok 76 | 19302550, -- Newton 77 | 19808608, -- Berformet 78 | 72181263, -- Orthros 79 | 46796664, -- Copernicus 80 | 48210156, -- Night Howling 81 | 45206713, -- Swirl Slime 82 | 72291412, -- Necro Slime 83 | 19580308, -- Lamia 84 | 11609969, -- Kepler 85 | 02295440, -- One for one 86 | 46372010, -- Gate 87 | 73360025, -- Swamp King 88 | 89 | 27873305, -- Caesar Ragnarok 90 | 82956492, -- D'Arc 91 | 74583607, -- Temujin 92 | 81020646, -- Void Ogre Dragon 93 | 50954680, -- Crystal Wing 94 | 44852429, -- Siegfried 95 | 00987311, -- Alexander 96 | 15939229, -- Kali Yuga 97 | 71612253, -- Tell 98 | 03758046, -- Caesar 99 | } 100 | DDDSummonBlacklist={ 101 | 74069667, -- Abyss Ragnarok 102 | 19302550, -- Newton 103 | 19808608, -- Berformet 104 | 72181263, -- Orthros 105 | 46796664, -- Copernicus 106 | 48210156, -- Night Howling 107 | 45206713, -- Swirl Slime 108 | 72291412, -- Necro Slime 109 | 19580308, -- Lamia 110 | 11609969, -- Kepler 111 | 112 | 27873305, -- Caesar Ragnarok 113 | 82956492, -- D'Arc 114 | 74583607, -- Temujin 115 | 52687916, -- Trishula 116 | 81020646, -- Void Ogre Dragon 117 | 50954680, -- Crystal Wing 118 | 44852429, -- Siegfried 119 | 00987311, -- Alexander 120 | 15939229, -- Kali Yuga 121 | 71612253, -- Tell 122 | 03758046, -- Caesar 123 | } 124 | DDDSetBlacklist={ 125 | 46372010, -- Gate 126 | } 127 | DDDRepoBlacklist={ 128 | } 129 | DDDUnchainable={ 130 | } 131 | function DDDFilter(c,exclude) 132 | local check = true 133 | if exclude then 134 | if type(exclude)=="table" then 135 | check = not CardsEqual(c,exclude) 136 | elseif type(exclude)=="number" then 137 | check = (c.id ~= exclude) 138 | end 139 | end 140 | return FilterSet(c,0x10af) and check 141 | end 142 | function DDDMonsterFilter(c,exclude) 143 | return FilterType(c,TYPE_MONSTER) 144 | and DDDFilter(c,exclude) 145 | end 146 | function DDFilter(c,exclude) 147 | local check = true 148 | if exclude then 149 | if type(exclude)=="table" then 150 | check = not CardsEqual(c,exclude) 151 | elseif type(exclude)=="number" then 152 | check = (c.id ~= exclude) 153 | end 154 | end 155 | return FilterSet(c,0xaf) and check 156 | end 157 | function DDMonsterFilter(c,exclude) 158 | return FilterType(c,TYPE_MONSTER) 159 | and DDFilter(c,exclude) 160 | end 161 | function ContractFilter(c,exclude) 162 | local check = true 163 | if exclude then 164 | if type(exclude)=="table" then 165 | check = not CardsEqual(c,exclude) 166 | elseif type(exclude)=="number" then 167 | check = (c.id ~= exclude) 168 | end 169 | end 170 | return FilterSet(c,0xae) and check 171 | end 172 | 173 | DDDPriorityList={ 174 | --[12345678] = {1,1,1,1,1,1,1,1,1,1,XXXCond}, -- Format 175 | 176 | -- DDD 177 | 178 | [74069667] = {1,1,1,1,1,1,1,1,1,1,AbyssRagCond}, -- Abyss Ragnarok 179 | [19302550] = {1,1,1,1,1,1,1,1,1,1,NewtonCond}, -- Newton 180 | [19808608] = {1,1,1,1,1,1,1,1,1,1,BerformetCond}, -- Berformet 181 | [72181263] = {1,1,1,1,1,1,1,1,1,1,OrthrosCond}, -- Orthros 182 | [46796664] = {1,1,1,1,1,1,1,1,1,1,CopernicusCond}, -- Copernicus 183 | [48210156] = {1,1,1,1,1,1,1,1,1,1,HowlingCond}, -- Night Howling 184 | [45206713] = {1,1,1,1,1,1,1,1,1,1,SwirlCond}, -- Swirl Slime 185 | [72291412] = {1,1,1,1,1,1,1,1,1,1,NecroCond}, -- Necro Slime 186 | [19580308] = {1,1,1,1,1,1,1,1,1,1,LamiaCond}, -- Lamia 187 | [11609969] = {1,1,1,1,1,1,1,1,1,1,KeplerCond}, -- Kepler 188 | [46372010] = {1,1,1,1,1,1,1,1,1,1,GateCond}, -- Gate 189 | [73360025] = {1,1,1,1,1,1,1,1,1,1,SwampCond}, -- Swamp King 190 | 191 | [27873305] = {1,1,1,1,1,1,1,1,1,1,CaesarRagCond}, -- Caesar Ragnarok 192 | [82956492] = {1,1,1,1,1,1,1,1,1,1,DArcCond}, -- D'Arc 193 | [74583607] = {1,1,1,1,1,1,1,1,1,1,TemujinCond}, -- Temujin 194 | [81020646] = {1,1,1,1,1,1,1,1,1,1,}, -- Void Ogre Dragon 195 | [50954680] = {1,1,1,1,1,1,1,1,1,1,}, -- Crystal Wing 196 | [44852429] = {1,1,1,1,1,1,1,1,1,1,SiegfriedCond}, -- Siegfried 197 | [00987311] = {1,1,1,1,1,1,1,1,1,1,AlexanderCond}, -- Alexander 198 | [15939229] = {1,1,1,1,1,1,1,1,1,1,KaliYugaCond}, -- Kali Yuga 199 | [71612253] = {1,1,1,1,1,1,1,1,1,1,TellCond}, -- Tell 200 | [03758046] = {1,1,1,1,1,1,1,1,1,1,CaesarCond}, -- Caesar 201 | 202 | } 203 | function SummonAbyssRag(c,mode) 204 | end 205 | function SummonNewton(c,mode) 206 | return false 207 | end 208 | function SummonBerformet(c,mode) 209 | end 210 | function SummonOrthros(c,mode) 211 | end 212 | function SummonCopernicus(c,mode) 213 | end 214 | function SummonHowling(c,mode) 215 | end 216 | function SummonSwirl(c,mode) 217 | end 218 | function UseSwirlHand(c,mode) 219 | end 220 | function UseSwirlGrave(c,mode) 221 | end 222 | function SummonNecro(c,mode) 223 | end 224 | function UseNecro(c,mode) 225 | end 226 | function SummonLamia(c,mode) 227 | end 228 | function UseLamia(c,mode) 229 | end 230 | function SummonKepler(c,mode) 231 | end 232 | function UseGate(c,mode) 233 | end 234 | function UseSwamp(c,mode) 235 | end 236 | function SummonVoidOgre(c,mode) 237 | end 238 | function SummonCrystalWing(c,mode) 239 | return true 240 | end 241 | function SummonSiegfried(c,mode) 242 | end 243 | function UseSiegfried(c,mode) 244 | end 245 | function SummonAlexander(c,mode) 246 | end 247 | function SummonKaliYuga(c,mode) 248 | end 249 | function UseKaliNuke(c,mode) 250 | end 251 | function UseKaliYuga(c,mode) 252 | end 253 | function SummonTell(c,mode) 254 | end 255 | function UseTell(c,mode) 256 | end 257 | function SummonCaesar(c,mode) 258 | end 259 | function UseCaesar(c,mode) 260 | end 261 | 262 | function ComboPieceCheck(cards,gatevar) 263 | local hasgate = HasIDNotNegated(AICards(),46372010,true,FilterOPT,true) 264 | if gatevar == 2 and not (hasgate and OPTCheck(46372010)) then return false end 265 | if gatevar == 1 and not OPTCheck(46372010) then return false end 266 | local hand = AIHand() 267 | local count = #cards 268 | if gatevar == 0 and hasgate or gatevar == 2 then 269 | count = count -1 270 | end 271 | for i,v in pairs(cards) do 272 | if HasID(AIHand(),v,true) then 273 | count = count-1 274 | table.remove(hand,FindID(v,hand,true)[1]) 275 | end 276 | end 277 | return count<=0 278 | end 279 | 280 | ComboList={} 281 | Combo={} 282 | Combo.__index = Combo 283 | DDDActiveCombo=nil 284 | function Combo.new(cards,gatevar,filter,steps) 285 | local self = setmetatable({},Combo) 286 | self.cards = cards or {} 287 | self.gatevar = gatevar or 0 288 | self.filter = filter or nil 289 | self.steps = steps or 0 290 | ComboList[#ComboList+1]=self 291 | print("registered combo: "..#ComboList) 292 | return self 293 | end 294 | function Combo:init() 295 | if ComboPieceCheck(self.cards,self.gatevar) then 296 | DDDActiveCombo=self 297 | self.step = 1 298 | return self 299 | end 300 | return false 301 | end 302 | function Combo:step() 303 | if self.step2 407 | and ComboPieceCheck(self.cards,self.gatevar) 408 | end 409 | if step == 2 then 410 | return SpaceCheck()>2 411 | and ComboPieceCheck(self.cards,self.gatevar) 412 | end 413 | return true 414 | end 415 | --[[DDDComboCommands1= 416 | { 417 | {COMMAND_ACTIVATE,FindID(46372010,params.activatable_cards,true,GateFilter)}, 418 | {Add(params,PRIO_TOHAND,MissingCardFilter 419 | }]] 420 | 421 | function DDDRegisterCombos() 422 | print("registering combos") 423 | local combo = Combo.new({19580308,45206713,72181263,46796664},2) 424 | combo.filter=DDDComboFilter1 425 | --combo.commands=DDDComboCommands1 426 | end 427 | 428 | 429 | function DDDComboCheck(cards) 430 | print("Combo Check") 431 | local Act = cards.activatable_cards 432 | local Sum = cards.summonable_cards 433 | local SpSum = cards.spsummonable_cards 434 | local combo = DDDActiveCombo 435 | if combo then 436 | print("have an active combo") 437 | if combo:checkIntegrity() then 438 | print("integrity intact, continue combo") 439 | return combo:command(Act) 440 | else 441 | print("integrity not intact, cancel combo") 442 | combo = nil 443 | end 444 | end 445 | if combo == nil then 446 | print("no active combo") 447 | for i,v in pairs(ComboList) do 448 | if v:init() then 449 | print("initializing combo "..i) 450 | return v:command(Act) 451 | end 452 | end 453 | end 454 | return nil 455 | end 456 | function DDDInit(cards) 457 | local Act = cards.activatable_cards 458 | local Sum = cards.summonable_cards 459 | local SpSum = cards.spsummonable_cards 460 | local Rep = cards.repositionable_cards 461 | local SetMon = cards.monster_setable_cards 462 | local SetST = cards.st_setable_cards 463 | print("Init") 464 | local ComboOverride,opt = DDDComboCheck(cards) 465 | print(ComboOverride) 466 | print(opt) 467 | if ComboOverride then 468 | print("combo override command:") 469 | print(ComboOverride) 470 | print(opt) 471 | return ComboOverride,opt 472 | end 473 | 474 | return nil 475 | end 476 | 477 | function DDDCard(cards,min,max,id,c) 478 | 479 | return nil 480 | end 481 | 482 | function DDDChain(cards) 483 | 484 | return nil 485 | end 486 | function DDDEffectYesNo(id,card) 487 | 488 | return nil 489 | end 490 | function DDDYesNo(desc) 491 | end 492 | function DDDTribute(cards,min, max) 493 | end 494 | function DDDBattleCommand(cards,targets,act) 495 | end 496 | function DDDAttackTarget(cards,attacker) 497 | end 498 | function DDDAttackBoost(cards) 499 | end 500 | function DDDOption(options) 501 | end 502 | function DDDChainOrder(cards) 503 | end 504 | DDDAtt={ 505 | 27873305, -- Caesar Ragnarok 506 | 82956492, -- D'Arc 507 | 74583607, -- Temujin 508 | 52687916, -- Trishula 509 | 81020646, -- Void Ogre Dragon 510 | 50954680, -- Crystal Wing 511 | 44852429, -- Siegfried 512 | 00987311, -- Alexander 513 | 15939229, -- Kali Yuga 514 | 71612253, -- Tell 515 | 03758046, -- Caesar 516 | } 517 | DDDVary={ 518 | 74069667, -- Abyss Ragnarok 519 | 19808608, -- Berformet 520 | } 521 | DDDDef={ 522 | 19302550, -- Newton 523 | 72181263, -- Orthros 524 | 46796664, -- Copernicus 525 | 48210156, -- Night Howling 526 | 45206713, -- Swirl Slime 527 | 72291412, -- Necro Slime 528 | 19580308, -- Lamia 529 | 11609969, -- Kepler 530 | } 531 | function DDDPosition(id,available) 532 | result = nil 533 | for i=1,#DDDAtt do 534 | if DDDAtt[i]==id 535 | then 536 | result=POS_FACEUP_ATTACK 537 | end 538 | end 539 | for i=1,#DDDVary do 540 | if DDDVary[i]==id 541 | then 542 | if (BattlePhaseCheck() or IsBattlePhase()) 543 | and Duel.GetTurnPlayer()==player_ai 544 | then 545 | result=POS_FACEUP_ATTACK 546 | else 547 | result=POS_FACEUP_DEFENSE 548 | end 549 | end 550 | end 551 | for i=1,#DDDDef do 552 | if DDDDef[i]==id 553 | then 554 | result=POS_FACEUP_DEFENSE 555 | end 556 | end 557 | return result 558 | end -------------------------------------------------------------------------------- /AI/mod/AIOnDeckSelect.lua: -------------------------------------------------------------------------------- 1 | -- Functions to check which deck the AI is playing 2 | 3 | GlobalDeck = nil 4 | Decks={} 5 | function NewDeck(name,identifier,startup) 6 | local deck={} 7 | deck.ID=#Decks+1 8 | deck.Name=name 9 | deck.Identifier=identifier 10 | deck.Startup=startup 11 | Decks[deck.ID]=deck 12 | return deck 13 | end 14 | 15 | DECK_SOMETHING = 0 16 | DECK_CHAOSDRAGON = NewDeck("Chaos Dragon" ,99365553) -- Lightpulsar Dragon 17 | DECK_FIREFIST = NewDeck("Fire Fist" ,01662004) -- Firefist Spirit 18 | DECK_HERALDIC = NewDeck("Heraldic Beast" ,82293134) -- Heraldic Beast Leo 19 | DECK_GADGET = NewDeck("Gadget" ,05556499) -- Machina Fortress 20 | DECK_BUJIN = NewDeck("Bujin" ,32339440) -- Bujin Yamato 21 | DECK_MERMAIL = NewDeck("Mermail" ,21954587) -- Mermail Abyssmegalo 22 | DECK_TELLARKNIGHT = NewDeck("Satellarknight" ,75878039) -- Satellarknight Deneb 23 | DECK_HAT = NewDeck("HAT" ,45803070) -- Traptrix Dionaea 24 | DECK_QLIPHORT = NewDeck("Qliphort" ,65518099) -- Qliphort Tool 25 | DECK_NOBLEKNIGHT = NewDeck("Noble Knight" ,59057152) -- Noble Knight Medraut 26 | DECK_NEKROZ = NewDeck("Nekroz" ,14735698) -- Nekroz Exomirror 27 | DECK_EXODIA = NewDeck("Exodia" ,{33396948,70791313}) -- Exodia the Forbidden One, Royal Magical Library 28 | DECK_DARKWORLD = NewDeck("Dark World" ,34230233) -- DW Grapha 29 | DECK_CONSTELLAR = NewDeck("Constellar" ,78358521) -- Constellar Sombre 30 | DECK_BLACKWING = NewDeck("Blackwing" ,91351370) -- Black Whirlwind 31 | DECK_HARPIE = NewDeck("Harpie" ,19337371) -- Hysteric Sign 32 | 33 | 34 | function IdentifierCheck(deck) 35 | if deck == nil or deck.Identifier == nil then return false end 36 | local ident = deck.Identifier 37 | if type(ident)=="table" then 38 | result = 0 39 | for i=1,#ident do 40 | local id = ident[i] 41 | if HasID(AIAll(),id,true) then 42 | result = result+1 43 | end 44 | end 45 | if result>=#ident then 46 | return true 47 | end 48 | else 49 | if HasID(AIAll(),ident,true) then 50 | return true 51 | end 52 | end 53 | return false 54 | end 55 | function DeckCheck(opt) 56 | if GlobalDeck == nil then 57 | for i=1,#Decks do 58 | local d = Decks[i] 59 | if IdentifierCheck(d) then 60 | GlobalDeck = i 61 | end 62 | end 63 | if GlobalDeck == nil then 64 | GlobalDeck = DECK_SOMETHING 65 | --print("AI deck is something else") 66 | else 67 | print("AI deck is "..Decks[GlobalDeck].Name) 68 | end 69 | DeckSetup() 70 | end 71 | if opt then 72 | if type(opt) == "table" then 73 | return GlobalDeck==opt.ID 74 | end 75 | return GlobalDeck==opt 76 | else 77 | return GetDeck() 78 | end 79 | end 80 | 81 | 82 | function GetDeck() 83 | if GlobalDeck == 0 then 84 | return nil 85 | end 86 | return Decks[GlobalDeck] 87 | end 88 | 89 | function DeckSetup() 90 | local deck = GetDeck() 91 | if deck then 92 | if deck.Startup then 93 | deck.Startup(deck) 94 | end 95 | BlacklistSetup(deck) 96 | end 97 | PrioritySetup() 98 | end 99 | 100 | PRIO_TOHAND = 1 101 | PRIO_TOFIELD = 3 102 | PRIO_TOGRAVE = 5 103 | PRIO_DISCARD,PRIO_TODECK,PRIO_EXTRA,PRIO_TRIBUTE = 7,7,7,7 104 | PRIO_BANISH = 9 105 | -- priority lists for decks: 106 | function PrioritySetup() 107 | 108 | DarkWorldPriority() 109 | ConstellarPriority() 110 | BlackwingPriority() 111 | HarpiePriority() 112 | MermailPriority() 113 | ChaosDragonPriority() 114 | QliphortPriority() 115 | SatellarknightPriority() 116 | --HEROPriority() 117 | --BAPriority() 118 | NekrozPriority() 119 | GadgetPriority() 120 | 121 | AddPriority({ 122 | -- HERO 123 | 124 | [69884162] = {3,1,1,1,1,1,1,1,1,1,AliusCond}, -- Neos Alius 125 | [63060238] = {1,1,1,1,1,1,1,1,1,1,BlazeCond}, -- Blazeman 126 | [50720316] = {7,1,7,1,1,1,1,1,1,1,MistCond}, -- Shadow Mist 127 | [00423585] = {4,1,1,1,1,1,1,1,1,1,MonkCond}, -- Summoner Monk 128 | [79979666] = {8,1,8,1,1,1,1,1,1,1,BubbleCond}, -- Bubbleman 129 | 130 | [00213326] = {1,1,1,1,8,1,1,1,1,1,nil}, -- E-Call 131 | [08949584] = {1,1,1,1,6,1,1,1,1,1,nil}, -- AHL 132 | [18511384] = {1,1,1,1,3,1,1,1,1,1,nil}, -- Fusion Recovery 133 | [24094653] = {1,1,1,1,3,1,1,1,1,1,nil}, -- Polymerization 134 | [45906428] = {1,1,1,1,3,1,1,1,1,1,nil}, -- Miracle Fusion 135 | [55428811] = {1,1,1,1,3,1,1,1,1,1,nil}, -- Fifth Hope 136 | [21143940] = {1,1,1,1,1,1,1,1,1,1,nil}, -- Mask Change 137 | [87819421] = {1,1,1,1,1,1,1,1,1,1,nil}, -- Mask Charge 138 | [87819421] = {1,1,1,1,9,1,1,1,1,1,nil}, -- Upstart 139 | [84536654] = {1,1,1,1,1,1,1,1,1,1,nil}, -- Form Change 140 | [84536654] = {1,1,1,1,2,1,1,1,1,1,nil}, -- Forbidden Lance 141 | [12580477] = {1,1,1,1,2,1,1,1,1,1,nil}, -- Raigeki 142 | [57728570] = {1,1,1,1,1,1,1,1,1,1,nil}, -- CCV 143 | [83555666] = {1,1,1,1,1,1,1,1,1,1,nil}, -- Ring of Destruction 144 | 145 | [95486586] = {1,1,1,1,1,1,1,1,1,1,nil}, -- Core 146 | [03642509] = {1,1,1,1,1,1,1,1,1,1,nil}, -- Great Tornado 147 | [22093873] = {1,1,1,1,1,1,1,1,1,1,nil}, -- Divine Wind 148 | [01945387] = {1,1,1,1,1,1,1,1,1,1,nil}, -- Nova Master 149 | [22061412] = {1,1,1,1,1,1,1,1,1,1,nil}, -- The Shining 150 | [29095552] = {1,1,1,1,1,1,1,1,1,1,nil}, -- Acid 151 | [33574806] = {1,1,1,1,1,1,1,1,1,1,nil}, -- Escuridao 152 | [40854197] = {1,1,1,1,1,1,1,1,1,1,nil}, -- Absolute Zero 153 | [50608164] = {1,1,1,1,1,1,1,1,1,1,nil}, -- Koga 154 | [58481572] = {1,1,1,1,1,1,1,1,1,1,nil}, -- Dark Law 155 | [16304628] = {1,1,1,1,1,1,1,1,1,1,nil}, -- Gaia 156 | }) 157 | 158 | 159 | AddPriority({ 160 | -- Noble Knight: 161 | [95772051] = {4,0,9,2,9,2,1,1,1,1,BlackSallyCond}, -- Black Sally 162 | [93085839] = {4,0,8,2,10,2,1,1,1,1,EachtarCond}, -- Eachtar 163 | [19680539] = {4,2,2,1,4,2,3,2,4,2,GawaynCond}, -- Gawayn 164 | [53550467] = {3,3,3,3,6,3,3,2,3,2,DrystanCond}, -- Drystan 165 | [59057152] = {7,2,7,2,4,2,5,3,3,2,MedrautCond}, -- Medraut 166 | [47120245] = {6,1,5,3,4,3,3,2,3,2,BorzCond}, -- Borz 167 | [13391185] = {5,2,4,2,5,2,3,2,5,2,ChadCond}, -- Chad 168 | [57690191] = {4,3,3,2,5,3,3,2,2,2,BrothersCond}, -- Brothers 169 | [19748583] = {8,1,1,1,11,3,1,1,1,1,GwenCond}, -- Gwen 170 | [10736540] = {6,0,1,1,12,3,1,1,1,1,LadyCond}, -- Lady 171 | 172 | [92125819] = {1,0,2,1,8,1,3,2,3,1,ArtorigusCond}, -- Artorigus 173 | [73359475] = {3,3,3,3,7,3,3,2,3,2,PeredurCond}, -- Peredur 174 | [03580032] = {9,2,4,2,3,2,1,1,1,1,nil}, -- Merlin 175 | [30575681] = {5,2,6,2,3,2,3,2,3,1,BedwyrCond}, -- Bedwyr 176 | 177 | [66970385] = {8,5,1,1,1,1,9,1,1,1,nil}, -- Chapter 178 | [07452945] = {7,1,7,1,4,1,2,1,1,1,RequipArmsCond}, -- Destiny 179 | [14745409] = {4,1,4,1,5,1,2,1,1,1,RequipArmsCond}, -- Gallatin 180 | [23562407] = {6,1,6,1,7,1,2,1,1,1,RequipArmsCond}, -- Caliburn 181 | [46008667] = {5,2,5,1,5,1,1,1,1,1,ExcaliburnCond}, -- Excaliburn 182 | [83438826] = {3,1,3,1,6,2,3,1,1,1,ArfCond}, -- Arfeudutyr 183 | [55742055] = {9,2,1,1,1,1,7,1,1,1,TableCond}, -- Table 184 | [92512625] = {4,1,1,1,1,1,1,1,1,1,nil}, -- Advice 185 | 186 | [48009503] = {1,1,1,1,1,1,1,1,1,1,nil}, -- Gandiva 187 | [82944432] = {1,1,1,1,1,1,1,1,1,1,nil}, -- Blade Armor Ninja 188 | [60645181] = {1,1,1,1,1,1,1,1,1,1,nil}, -- Excalibur 189 | [21223277] = {1,1,1,1,1,1,5,1,3,1,nil}, -- R4torigus 190 | [10613952] = {1,1,1,1,3,1,6,1,3,1,R5torigusCond}, -- R5torigus 191 | [83519853] = {1,1,6,1,1,1,1,1,1,1,nil}, -- High Sally 192 | [68618157] = {1,1,1,1,1,1,1,1,1,1,nil}, -- Amaterasu 193 | [73289035] = {1,1,1,1,1,1,1,1,1,1,nil}, -- Tsukuyomi 194 | }) 195 | 196 | 197 | 198 | 199 | AddPriority({ 200 | -- Stuff 201 | [73176465] = {1,1,1,1,6,5,1,1,1,1,FelisCond}, -- Lightsworn Felis 202 | [41386308] = {1,1,1,1,1,1,1,1,1,1,MathCond}, -- Mathematician 203 | 204 | -- Speedroid Engine 205 | 206 | [81275020] = {9,1,5,1,1,1,1,1,1,1}, -- Speedroid Terrortop 207 | [53932291] = {8,1,1,1,1,1,1,1,1,1}, -- Speedroid Taketomborg 208 | 209 | [05318639] = {1,1,1,1,1,1,1,1,1,1,nil}, -- Mystical Space Typhoon 210 | 211 | [82044279] = {1,1,1,1,1,1,1,1,1,1,ClearWingCond}, -- Clear Wing Synchro Dragon 212 | [72959823] = {1,1,1,1,1,1,1,1,1,1,nil}, -- Panzer Dragon 213 | [29669359] = {1,1,1,1,1,1,1,1,1,1,nil}, -- Number 61: Volcasaurus 214 | [82633039] = {1,1,1,1,6,1,1,1,1,1,CastelCond}, -- Skyblaster Castel 215 | [00581014] = {1,1,1,1,1,1,1,1,1,1,nil}, -- Daigusto Emeral 216 | [33698022] = {1,1,1,1,1,1,1,1,1,1,nil}, -- Moonlight Rose Dragon 217 | [31924889] = {1,1,1,1,1,1,1,1,1,1,nil}, -- Arcanite Magician 218 | [08561192] = {1,1,1,1,1,1,1,1,1,1,nil}, -- Leoh, Keeper of the Sacred Tree 219 | }) 220 | 221 | AddPriority({ 222 | -- HAT 223 | [91812341] = {6,3,5,1,1,1,1,1,1,1,MyrmeleoCond}, -- Traptrix Myrmeleo 224 | [45803070] = {7,4,4,1,1,1,1,1,1,1,DionaeaCond}, -- Traptrix Dionaea 225 | [68535320] = {5,2,2,1,1,1,1,1,1,1,FireHandCond}, -- Fire Hand 226 | [95929069] = {4,2,2,1,1,1,1,1,1,1,IceHandCond}, -- Ice Hand 227 | [85103922] = {4,1,6,4,3,1,3,1,1,1,MoralltachCond}, -- Artifact Moralltach 228 | [12697630] = {5,1,7,3,5,1,5,1,1,1,BeagalltachCond}, -- Artifact Beagalltach 229 | [20292186] = {4,1,5,3,4,1,4,1,1,1,ScytheCond}, -- Artifact Scythe 230 | 231 | [14087893] = {2,1,1,1,1,1,1,1,1,1,nil}, -- Book of Moon 232 | [98645731] = {2,1,1,1,1,1,1,1,1,1,nil}, -- Pot of Duality 233 | [29616929] = {2,1,1,1,1,1,1,1,1,1,nil}, -- Traptrix Trap Hole Nightmare 234 | [53582587] = {2,1,1,1,1,1,1,1,1,1,nil}, -- Torrential Tribute 235 | [29401950] = {3,1,1,1,1,1,1,1,1,1,nil}, -- Bottomless Trap Hole 236 | [84749824] = {3,1,1,1,1,1,1,1,1,1,nil}, -- Solemn Warning 237 | [94192409] = {2,1,1,1,1,1,1,1,1,1,nil}, -- Compulsory Evacuation Device 238 | [12444060] = {5,1,1,1,1,1,1,1,1,1,SanctumCond}, -- Artifact Sanctum 239 | [29223325] = {4,1,1,1,1,1,1,1,1,1,IgnitionCond}, -- Artifact Ignition 240 | [97077563] = {3,1,1,1,1,1,1,1,1,1,COTHCond}, -- Call of the Haunted 241 | [78474168] = {2,1,1,1,4,1,4,1,1,1,nil}, -- Breakthrough Skill 242 | 243 | [91949988] = {1,1,1,1,1,1,1,1,1,1,nil}, -- Gaia Dragon, the Thunder Charger 244 | [91499077] = {1,1,1,1,1,1,1,1,1,1,nil}, -- Gagaga Samurai 245 | [63746411] = {1,1,1,1,1,1,1,1,1,1,nil}, -- Giant Hand 246 | }) 247 | 248 | AddPriority({ 249 | --for backwards compatibility 250 | [05361647] = {1,1,1,1,9,1,1,1,1,1,nil}, -- Battlin' Boxer Glassjaw 251 | [68144350] = {1,1,1,1,5,1,1,1,1,1,nil}, -- Battlin' Boxer Switchhitter 252 | 253 | [44519536] = {1,1,-1,-1,-1,-1,-1,-1,1,1,nil}, 254 | [08124921] = {1,1,-1,-1,-1,-1,-1,-1,1,1,nil}, 255 | [07902349] = {1,1,-1,-1,-1,-1,-1,-1,1,1,nil}, -- Exodia pieces 256 | [70903634] = {1,1,-1,-1,-1,-1,-1,-1,1,1,nil}, 257 | [33396948] = {1,1,-1,-1,-1,-1,-1,-1,1,1,nil}, 258 | 259 | [05133471] = {1,1,1,1,4,1,1,1,1,1,nil}, -- Galaxy Cyclone 260 | 261 | }) 262 | 263 | local deck = GetDeck() 264 | if deck and deck.PriorityList then 265 | AddPriority(deck.PriorityList,true) 266 | end 267 | 268 | end 269 | 270 | Prio = {} 271 | function AddPriority(list,override) 272 | for i,v in pairs(list) do 273 | if Prio[i] and not override then print("warning: duplicate priority entry for ID: "..i) end 274 | Prio[i]=v 275 | end 276 | end 277 | function GetPriority(card,loc) 278 | card.prio=0 279 | local id=card.id 280 | if id == 76812113 then 281 | id=card.original_id 282 | end 283 | local checklist = nil 284 | local result = 0 285 | if loc == nil then 286 | loc = PRIO_TOHAND 287 | end 288 | checklist = Prio[id] 289 | if checklist then 290 | if checklist[11] and not(checklist[11](loc,card)) then 291 | loc = loc + 1 292 | end 293 | result = checklist[loc] 294 | if checklist[11] and checklist[11](loc,card) 295 | and type(checklist[11](loc,card))=="number" 296 | then 297 | result = checklist[11](loc,card) 298 | end 299 | else 300 | --print("no priority defined for id: "..id..", defaulting to 0") 301 | return 0 302 | end 303 | --print("got priority: "..result.." for "..GetName(card)) 304 | return result 305 | end 306 | function AssignPriority(cards,loc,filter,opt) 307 | local index = 0 308 | Multiple = nil 309 | for i,c in pairs(cards) do 310 | if not c.index then c.index=i end 311 | c.prio=GetPriority(c,loc) 312 | if loc==PRIO_TOFIELD and c.location==LOCATION_DECK then 313 | c.prio=c.prio+2 314 | end 315 | if loc==PRIO_TOGRAVE and c.location==LOCATION_DECK then 316 | c.prio=c.prio+2 317 | end 318 | if loc==PRIO_TOFIELD and c.location==LOCATION_GRAVE then 319 | c.prio=c.prio+1 320 | end 321 | if loc==PRIO_TOFIELD and c.location==LOCATION_EXTRA then 322 | c.prio=c.prio+5 323 | end 324 | if loc==PRIO_TOGRAVE and bit32.band(c.location,LOCATION_ONFIELD)>0 325 | and c.equip_count and c.equip_count>0 and HasID(c:get_equipped_cards(),17639150,true) 326 | then 327 | c.prio=10 328 | end 329 | if loc==PRIO_TOGRAVE and FilterLocation(c,LOCATION_ONFIELD) 330 | then 331 | if FilterCrippled(c) then 332 | c.prio=c.prio+5 333 | end 334 | if FilterPosition(c,POS_DEFENSE) 335 | and c.turnid==Duel.GetTurnCount() 336 | and c.attack>c.defense 337 | then 338 | c.prio=c.prio+2 339 | end 340 | if FilterType(c,TYPE_XYZ) 341 | and c.xyz_material_count==0 342 | then 343 | c.prio=c.prio+2 344 | end 345 | end 346 | if loc==PRIO_TOHAND and bit32.band(c.location,LOCATION_ONFIELD)>0 347 | and not DeckCheck(DECK_HARPIE) -- TODO: temp 348 | then 349 | c.prio=-1 350 | end 351 | if c.owner==2 then 352 | c.prio=-1*c.prio 353 | end 354 | if not TargetCheck(c) then 355 | c.prio=-1 356 | end 357 | if loc==PRIO_TOGRAVE and not MacroCheck() then 358 | c.prio=-1*c.prio 359 | end 360 | if loc==PRIO_TOGRAVE and HasID(AIMon(),17412721,true) --Norden 361 | then 362 | local norden = FindID(17412721,AIMon()) 363 | if CardTargetCheck(norden,c) then 364 | c.prio=12 365 | end 366 | if CardsEqual(norden,c) then 367 | c.prio=11 368 | end 369 | end 370 | c.prio=c.prio or 0 371 | if not FilterCheck(c,filter,opt) then 372 | c.prio=c.prio-9999 373 | end 374 | SetMultiple(c.original_id) 375 | end 376 | end 377 | function PriorityCheck(cards,loc,count,filter,opt) 378 | if count == nil then count = 1 end 379 | if loc==nil then loc=PRIO_TOHAND end 380 | if cards==nil or #cardsb.prio end) 383 | return cards[count].prio 384 | end 385 | function Add(cards,loc,count,filter,opt) 386 | local result={} 387 | if count==nil then count=1 end 388 | if loc==nil then loc=PRIO_TOHAND end 389 | local compare = function(a,b) return a.prio>b.prio end 390 | AssignPriority(cards,loc,filter,opt) 391 | table.sort(cards,compare) 392 | for i=1,count do 393 | result[i]=cards[i].index 394 | end 395 | --PrintList(cards,true) 396 | if #resultb.prio end) 405 | end 406 | -------------------------------------------------------------------------------- /AI/decks/Constellar.lua: -------------------------------------------------------------------------------- 1 | function ConstellarPriority() 2 | AddPriority({ 3 | [65367484] = {2,1,5,1,3,1,1,1,1,1,ThrasherCond}, -- Thrasher 4 | [70908596] = {8,3,9,1,8,1,1,1,5,1,KausCond}, -- Kaus 5 | [78364470] = {7,3,6,1,5,1,1,1,7,1,PolluxCond}, -- Pollux 6 | [41269771] = {6,2,7,1,6,1,1,1,8,1,AlgiediCond}, -- Algiedi 7 | [06353603] = {2,1,4,1,2,1,1,1,1,1,BearCond}, -- FF Bear 8 | [78358521] = {9,4,8,1,4,1,1,1,6,2,SombreCond}, -- Sombre 9 | [44635489] = {4,1,4,1,1,1,1,1,3,1,SiatCond}, -- Sombre 10 | 11 | [35544402] = {1,1,1,1,1,1,1,1,1,1,TwinkleCond}, -- Twinkle 12 | [57103969] = {1,1,1,1,1,1,1,1,1,1,TenkiCond}, -- Tenki 13 | 14 | [50078509] = {1,1,1,1,1,1,1,1,1,1,FiendishCond}, -- Fiendish 15 | 16 | [73964868] = {1,1,1,1,1,1,1,1,7,1,nil}, -- Constellar Pleiades 17 | [38495396] = {1,1,1,1,4,2,1,1,8,1,PtolemyCond}, -- Constellar Ptolemy M7 18 | [26329679] = {1,1,1,1,1,1,1,1,9,1,nil}, -- Constellar Omega 19 | [31386180] = {1,1,1,1,1,1,1,1,1,1,nil}, -- Tiras 20 | [56832966] = {1,1,1,1,1,1,1,1,1,1,nil}, -- Utopia Lightning 21 | [84013237] = {1,1,1,1,1,1,1,1,1,1,nil}, -- Utopia 22 | [31437713] = {1,1,1,1,1,1,1,1,1,1,nil}, -- Heartlanddraco 23 | }) 24 | end 25 | function ConstellarFilter(c,exclude) 26 | return IsSetCode(c.setcode,0x53) and (exclude == nil or c.id~=exclude) 27 | end 28 | function ConstellarMonsterFilter(c,exclude) 29 | return FilterType(c,TYPE_MONSTER) and ConstellarFilter(c,exclude) 30 | end 31 | function ConstellarNonXYZFilter(c,exclude) 32 | return FilterType(c,TYPE_MONSTER) and not FilterType(c,TYPE_XYZ) 33 | and ConstellarFilter(c,exclude) 34 | end 35 | function PolluxCond(loc,c) 36 | if loc == PRIO_TOHAND then 37 | return not HasID(AIHand(),78364470,true) 38 | and HasID(AIHand(),70908596,true) 39 | or CardsMatchingFilter(AIHand(),ConstellarMonsterFilter)==0 40 | end 41 | return true 42 | end 43 | function KausCond(loc,c) 44 | if loc == PRIO_TOHAND then 45 | return not HasID(AIHand(),70908596,true) 46 | and not HasID(AICards(),57103969,true,nil,nil,POS_FACEDOWN) 47 | and (HasID(AIHand(),78364470,true) or HasID(AIHand(),41269771,true) 48 | or HasID(AIMon(),78358521,true) and not OPTCheck(783585211) and OPTCheck(783585212)) 49 | or CardsMatchingFilter(AIHand(),ConstellarMonsterFilter)==0 and not HasAccess(70908596) 50 | end 51 | if loc == PRIO_TOGRAVE then 52 | return not HasID(AIGrave(),70908596,true) 53 | and FilterLocation(c,LOCATION_DECK) 54 | end 55 | if loc == PRIO_TOFIELD then 56 | return not HasID(AIMon(),70908596,true) 57 | end 58 | return true 59 | end 60 | function AlgiediCond(loc,c) 61 | if loc == PRIO_TOHAND then 62 | return not HasID(AIHand(),41269771,true) 63 | and HasID(AIHand(),70908596,true) 64 | end 65 | return true 66 | end 67 | function SombreCond(loc,c) 68 | if loc == PRIO_TOHAND then 69 | local cards = UseLists(AIMon(),AIMaterials(),AIGrave()) 70 | if (FilterLocation(c,LOCATION_GRAVE) and not OPTCheck(783585211) 71 | and OPTCheck(783585212) and HasIDNotNegated(AIMon(),78358521,true)) 72 | then 73 | if HasID(AICards(),70908596,true) then 74 | return true 75 | end 76 | return false 77 | end 78 | return CardsMatchingFilter(cards,ConstellarNonXYZFilter)>1 and HasAccess(70908596) 79 | end 80 | return true 81 | end 82 | function ThrasherCond(loc,c) 83 | if loc == PRIO_TOHAND then 84 | return true 85 | end 86 | return true 87 | end 88 | function BearCond(loc,c) 89 | if loc == PRIO_TOHAND then 90 | return true 91 | end 92 | return true 93 | end 94 | function PtolemyCond(loc,c) 95 | if loc == PRIO_TOGRAVE then 96 | return c.xyz_material_count==0 97 | end 98 | return true 99 | end 100 | function SummonThrasher(mode) 101 | if mode == 1 and (HasID(AIHand(),78364470,true) or HasID(AIHand(),41269771,true)) 102 | and HasID(AIHand(),78358521,true) and not HasID(AIHand(),70908596,true) 103 | then 104 | return true 105 | elseif mode == 2 and CardsMatchingFilter(AIHand(),FilterLevel,4)>1 then 106 | return true 107 | elseif mode == 3 and OppGetStrongestAttack()<2100 then 108 | return true 109 | end 110 | end 111 | function SummonPollux(mode) 112 | if mode == 1 and HasID(AIHand(),70908596,true) and DualityCheck() 113 | and FieldCheck(4)==0 and OverExtendCheck() 114 | then 115 | return true 116 | elseif mode == 2 and CardsMatchingFilter(AIHand(),ConstellarMonsterFilter)>1 117 | and FieldCheck(4)==0 and OverExtendCheck() 118 | then 119 | return true 120 | elseif mode == 3 and DualityCheck() 121 | and FieldCheck(4)==1 and OverExtendCheck() 122 | then 123 | return true 124 | end 125 | end 126 | function SummonAlgiedi(mode) 127 | if mode == 1 and HasID(AIHand(),70908596,true) and DualityCheck() 128 | and FieldCheck(4)==0 and OverExtendCheck() 129 | then 130 | return true 131 | elseif mode == 2 and CardsMatchingFilter(AIHand(),ConstellarMonsterFilter)>1 132 | and FieldCheck(4)==0 and OverExtendCheck() 133 | then 134 | return true 135 | elseif mode == 3 and DualityCheck() 136 | and FieldCheck(4)==1 and OverExtendCheck() 137 | then 138 | return true 139 | end 140 | end 141 | function SummonKaus(mode) 142 | if mode == 1 and DualityCheck() 143 | and CardsMatchingFilter(AIMon(),ConstellarNonXYZFilter)==1 144 | then 145 | return true 146 | elseif mode == 2 and DualityCheck() and OverExtendCheck() 147 | and (FieldCheck(4)==1 or HasIDNotNegated(AICards(),01845204,true) 148 | and HasID(AIExtra(),72959823,true) and WindaCheck()) 149 | then 150 | return true 151 | end 152 | return false 153 | end 154 | function UseKaus(c) 155 | local cards=SubGroup(AIMon(),FilterPosition,POS_FACEUP) 156 | return (CardsMatchingFilter(cards,ConstellarNonXYZFilter)>1 157 | or FieldCheck(5)==1 and c.level<5) 158 | and FieldCheck(5)~=2 159 | end 160 | function SombreFilter(c) 161 | return ConstellarMonsterFilter(c) 162 | end 163 | function SummonSombre(mode) 164 | if mode == 1 and DualityCheck() and CardsMatchingFilter(AIGrave(),SombreFilter)>1 165 | and HasID(UseLists(AIHand(),AIGrave()),70908596,true) and OverExtendCheck() 166 | then 167 | return true 168 | elseif mode == 2 and DualityCheck() 169 | and FieldCheck(4)==1 and OverExtendCheck() 170 | then 171 | return true 172 | end 173 | return false 174 | end 175 | function UseSombre(mode) 176 | if mode == 1 and OPTCheck(783585211) 177 | and CardsMatchingFilter(AIGrave(),SombreFilter)>1 178 | then 179 | GlobalCardMode = 2 180 | return true 181 | elseif mode == 2 and not OPTCheck(783585211) 182 | and CardsMatchingFilter(AIMon(),ConstellarNonXYZFilter)==1 183 | then 184 | return true 185 | end 186 | end 187 | function SummonBear(c) 188 | return DeckCheck(DECK_CONSTELLAR) and (UseBear() 189 | or CanDealBattleDamage(c,OppMon()) 190 | or FieldCheck(4)==1) 191 | end 192 | function UseChainConstellar(mode) 193 | if not DeckCheck(DECK_CONSTELLAR) then return false end 194 | if mode == 1 and HasID(AIHand(),78358521,true) 195 | and not HasAccess(70908596) and HasID(AIDeck(),70908596,true) 196 | then 197 | return true 198 | end 199 | if mode == 1 and HasID(AIMon(),78358521,true) and OPTCheck(783585211) 200 | and not HasID(UseLists(AIHand(),AIGrave()),78358521,true) 201 | and HasID(AIDeck(),70908596,true) 202 | then 203 | return true 204 | end 205 | if mode == 2 and (HasID(AIHand(),78364470,true) 206 | or HasID(AIHand(),41269771,true)) and TurnEndCheck() 207 | then 208 | return true 209 | end 210 | if mode == 3 and TurnEndCheck() then 211 | GlobalCardMode = 2 212 | return true 213 | end 214 | return false 215 | end 216 | function SummonChainConstellar(mode) 217 | if not (DeckCheck(DECK_CONSTELLAR) and HasID(AIExtra(),34086406,true)) then return false end 218 | if mode == 1 and HasID(AIHand(),78358521,true) and not HasAccess(70908596) 219 | and HasID(AIDeck(),70908596,true) and (not OppHasStrongestMonster() or OppGetStrongestAttDef()<1800) 220 | then 221 | return true 222 | end 223 | if mode == 1 and HasID(AIMon(),78358521,true) and OPTCheck(783585211) 224 | and not HasID(UseLists(AIHand(),AIGrave()),78358521,true) 225 | and FieldCheck(4)>2 226 | then 227 | return true 228 | end 229 | if mode == 2 and (HasID(AIHand(),78364470,true) 230 | or HasID(AIHand(),41269771,true)) and MP2Check(1800) 231 | and (not OppHasStrongestMonster() or OppGetStrongestAttDef()<1800) 232 | then 233 | return true 234 | end 235 | if mode == 3 and MP2Check(1800) 236 | and (not OppHasStrongestMonster() or OppGetStrongestAttDef()<1800) 237 | then 238 | return true 239 | end 240 | return false 241 | end 242 | function SummonConstellar(c) 243 | if #AIMon() == 0 and (#OppMon() == 0 244 | or c.attack>=OppGetStrongestAttDef() 245 | or CardsMatchingFilter(AIHand(),ConstellarMonsterFilter)>1 246 | or HasID(AIHand(),37742478,true)) 247 | then 248 | return true 249 | end 250 | return false 251 | end 252 | function SiatFilter(c,level) 253 | return ConstellarNonXYZFilter(c) 254 | and FilterLevel(c,level) 255 | end 256 | GlobalSiatLevel = 4 257 | function UseSiat(c,mode) 258 | if mode == 1 259 | and CardsMatchingFilter(UseLists(AIMon(),AIGrave()),SiatFilter,5)>0 260 | and FieldCheck(5) == 1 261 | then 262 | GlobalSiatLevel = 5 263 | return true 264 | end 265 | if mode == 2 266 | and CardsMatchingFilter(UseLists(AIMon(),AIGrave()),SiatFilter,4)>0 267 | and FieldCheck(4) == 1 268 | then 269 | GlobalSiatLevel = 4 270 | return true 271 | end 272 | end 273 | function SummonSiat(c,mode) 274 | if mode == 1 275 | and HasIDNotNegated(AIHand(),70908596,true) 276 | and not NormalSummonCheck() 277 | then 278 | return true 279 | end 280 | if mode == 2 281 | and CardsMatchingFilter(AIHand(),SiatFilter,4)>0 282 | and not NormalSummonCheck() 283 | then 284 | return true 285 | end 286 | if mode == 3 287 | and CardsMatchingFilter(AIMon(),SiatFilter,5)>0 288 | and FieldCheck(5)==1 289 | then 290 | return true 291 | end 292 | if mode == 4 293 | and CardsMatchingFilter(UseLists(AIMon(),AIGrave()),SiatFilter,4)>0 294 | and FieldCheck(4)==1 295 | then 296 | return true 297 | end 298 | end 299 | function ConstellarInit(cards) 300 | local Act = cards.activatable_cards 301 | local Sum = cards.summonable_cards 302 | local SpSum = cards.spsummonable_cards 303 | local Rep = cards.repositionable_cards 304 | local SetMon = cards.monster_setable_cards 305 | local SetST = cards.st_setable_cards 306 | if HasIDNotNegated(Act,32807846) and UseRotA() then 307 | return {COMMAND_ACTIVATE,CurrentIndex} 308 | end 309 | if HasIDNotNegated(Act,57103969) and DeckCheck(DECK_CONSTELLAR) then 310 | OPTSet(57103969) 311 | return {COMMAND_ACTIVATE,CurrentIndex} 312 | end 313 | if HasID(Act,44635489,UseSiat,1) then 314 | return Activate() 315 | end 316 | if HasIDNotNegated(Act,70908596) and UseKaus(Act[CurrentIndex]) then 317 | return {COMMAND_ACTIVATE,CurrentIndex} 318 | end 319 | if HasID(Act,44635489,UseSiat,2) then 320 | return Activate() 321 | end 322 | if HasIDNotNegated(Act,34086406,false,545382497) and UseChainConstellar(1) then 323 | return {COMMAND_ACTIVATE,CurrentIndex} 324 | end 325 | if HasIDNotNegated(Act,78358521) and UseSombre(1) then 326 | OPTSet(783585211) 327 | return {COMMAND_ACTIVATE,CurrentIndex} 328 | end 329 | if HasIDNotNegated(Act,78358521) and UseSombre(2) then 330 | OPTSet(783585212) 331 | return {COMMAND_ACTIVATE,CurrentIndex} 332 | end 333 | if HasIDNotNegated(SpSum,34086406) and SummonChainConstellar(1) then 334 | return {COMMAND_SPECIAL_SUMMON,CurrentIndex} 335 | end 336 | if HasID(SpSum,44635489,SummonSiat,1) then 337 | return SpSummon() 338 | end 339 | if HasID(SpSum,65367484) and SummonThrasher(1) then 340 | return {COMMAND_SPECIAL_SUMMON,CurrentIndex} 341 | end 342 | if HasIDNotNegated(Sum,78358521) and SummonSombre(1) then 343 | return {COMMAND_SUMMON,CurrentIndex} 344 | end 345 | if HasIDNotNegated(Sum,70908596) and SummonKaus(1) then 346 | return {COMMAND_SUMMON,CurrentIndex} 347 | end 348 | if HasIDNotNegated(Sum,78364470) and SummonPollux(1) then 349 | return {COMMAND_SUMMON,CurrentIndex} 350 | end 351 | if HasIDNotNegated(Sum,41269771) and SummonAlgiedi(1) then 352 | return {COMMAND_SUMMON,CurrentIndex} 353 | end 354 | if HasID(SpSum,65367484) and SummonThrasher(2) then 355 | return {COMMAND_SPECIAL_SUMMON,CurrentIndex} 356 | end 357 | if HasID(SpSum,44635489,SummonSiat,2) then 358 | return SpSummon() 359 | end 360 | if HasIDNotNegated(Sum,78364470) and SummonPollux(2) then 361 | return {COMMAND_SUMMON,CurrentIndex} 362 | end 363 | if HasIDNotNegated(Sum,41269771) and SummonAlgiedi(2) then 364 | return {COMMAND_SUMMON,CurrentIndex} 365 | end 366 | if HasIDNotNegated(Sum,41269771) and SummonAlgiedi(3) then 367 | return {COMMAND_SUMMON,CurrentIndex} 368 | end 369 | if HasIDNotNegated(Sum,78364470) and SummonPollux(3) then 370 | return {COMMAND_SUMMON,CurrentIndex} 371 | end 372 | if HasIDNotNegated(Sum,70908596) and SummonKaus(2) then 373 | return {COMMAND_SUMMON,CurrentIndex} 374 | end 375 | if HasIDNotNegated(Sum,78358521) and SummonSombre(2) then 376 | return {COMMAND_SUMMON,CurrentIndex} 377 | end 378 | if HasIDNotNegated(Sum,06353603) and SummonBear(Sum[CurrentIndex]) then 379 | return {COMMAND_SUMMON,CurrentIndex} 380 | end 381 | if HasID(SpSum,65367484) and SummonThrasher(3) then 382 | return {COMMAND_SPECIAL_SUMMON,CurrentIndex} 383 | end 384 | if HasID(Sum,44635489,SummonSiat,3) then 385 | return Summon() 386 | end 387 | if HasID(Sum,44635489,SummonSiat,4) then 388 | return Summon() 389 | end 390 | if HasID(Sum,41269771) and SummonConstellar(Sum[CurrentIndex]) then 391 | return {COMMAND_SUMMON,CurrentIndex} 392 | end 393 | if HasID(Sum,78364470) and SummonConstellar(Sum[CurrentIndex]) then 394 | return {COMMAND_SUMMON,CurrentIndex} 395 | end 396 | if HasID(Sum,70908596) and SummonConstellar(Sum[CurrentIndex]) then 397 | return {COMMAND_SUMMON,CurrentIndex} 398 | end 399 | if HasID(Sum,78358521) and SummonConstellar(Sum[CurrentIndex]) then 400 | return {COMMAND_SUMMON,CurrentIndex} 401 | end 402 | 403 | if HasIDNotNegated(Act,34086406,false,545382498) and UseChainConstellar(3) then 404 | return {COMMAND_ACTIVATE,CurrentIndex} 405 | end 406 | if HasIDNotNegated(SpSum,34086406) and SummonChainConstellar(3) then 407 | return {COMMAND_SPECIAL_SUMMON,CurrentIndex} 408 | end 409 | return nil 410 | end 411 | function KausTarget(cards) 412 | return BestTargets(cards,1,TARGET_PROTECT,FilterLevel,4) 413 | end 414 | function SombreTarget(cards) 415 | if GlobalCardMode == 2 then 416 | GlobalCardMode = 1 417 | return Add(cards,PRIO_BANISH) 418 | elseif GlobalCardMode == 1 then 419 | GlobalCardMode = nil 420 | return Add(cards) 421 | end 422 | return Add(cards,PRIO_TOFIELD) 423 | end 424 | function AlgiediTarget(cards) 425 | return Add(cards,PRIO_TOFIELD) 426 | end 427 | function SiatTarget(cards) 428 | return BestTargets(cards,1,TARGET_PROTECT,FilterLevel,GlobalSiatLevel) 429 | end 430 | function ConstellarCard(cards,min,max,id,c) 431 | if c then 432 | id = c.id 433 | end 434 | if id == 70908596 then 435 | return KausTarget(cards) 436 | end 437 | if id == 78358521 then 438 | return SombreTarget(cards) 439 | end 440 | if id == 41269771 then 441 | return AlgiediTarget(cards) 442 | end 443 | if id == 44635489 then 444 | return SiatTarget(cards) 445 | end 446 | return nil 447 | end 448 | function ChainAlgiedi() 449 | return FieldCheck(4)==1 and HasID(AIHand(),70908596,true) 450 | or FieldCheck(4)==2 and HasID(AIHand(),78358521,true) 451 | and SummonChainConstellar(1) 452 | or FieldCheck(4)==1 and CardsMatchingFilter(AIHand(),ConstellarMonsterFilter)>0 453 | and OverExtendCheck() 454 | end 455 | function ConstellarChain(cards) 456 | if HasID(cards,41269771) and ChainAlgiedi() then 457 | return {1,CurrentIndex} 458 | end 459 | return nil 460 | end 461 | 462 | function ConstellarEffectYesNo(id,card) 463 | local result = nil 464 | if id==41269771 and ChainAlgiedi() then 465 | result = 1 466 | end 467 | return result 468 | end 469 | 470 | function ConstellarOption(options) 471 | for i=1,#options do 472 | if options[i] == 1134537537 then 473 | return i 474 | end 475 | if options[i] == 1134537538 then 476 | --return i 477 | end 478 | end 479 | return nil 480 | end 481 | 482 | ConstellarAtt={ 483 | 70908596,78364470,41269771,78358521, 484 | 91949988,31386180,84013237,56832966, 485 | 26329679,31437713, 486 | } 487 | ConstellarDef={ 488 | 72959823,44635489, 489 | } 490 | function ConstellarPosition(id,available) 491 | result = nil 492 | for i=1,#ConstellarAtt do 493 | if ConstellarAtt[i]==id 494 | then 495 | result=POS_FACEUP_ATTACK 496 | end 497 | end 498 | for i=1,#ConstellarDef do 499 | if ConstellarDef[i]==id then result=POS_FACEUP_DEFENSE end 500 | end 501 | return result 502 | end 503 | -------------------------------------------------------------------------------- /AI/mod/SelectChain.lua: -------------------------------------------------------------------------------- 1 | --- OnSelectChain -- 2 | -- 3 | -- Called when AI can chain a card. 4 | -- This function is not completely implemented yet. The parameters will very likely change in the next version. 5 | -- 6 | -- Parameters: 7 | -- cards = table of cards to chain 8 | -- only_chains_by_player = returns true if all cards in the chain are used by the Player 9 | -- Return: 10 | -- result 11 | -- 1 = yes, chain a card 12 | -- 0 = no, don't chain 13 | -- index = index of the chain 14 | 15 | GlobalChain = 0 16 | function OnSelectChain(cards,only_chains_by_player,forced) 17 | if not player_ai then player_ai = 1 end -- probably puzzle mode, so player goes first 18 | if GlobalBPAllowed == nil and Duel.GetTurnCount()>1 then 19 | GlobalBPAllowed = true 20 | end 21 | if Duel.GetCurrentChain()<=GlobalChain then 22 | GlobalTargetList = {} -- reset variables for new chain 23 | GlobalNegatedChainLinks = {} 24 | end 25 | GlobalChain=Duel.GetCurrentChain() 26 | GlobalSummonNegated = nil 27 | local result = 0 28 | local index = 1 29 | local ChainAllowed = 0 30 | SurrenderCheck() 31 | DamageSet() 32 | ResetOncePerTurnGlobals() 33 | GlobalAIIsAttacking = nil 34 | --GetNegatePriority() 35 | 36 | if GlobalFeatherStorm~=Duel.GetTurnCount() 37 | and ChainCheck(00007704,1-player_ai) -- Feather Storm 38 | then 39 | GlobalFeatherStorm=Duel.GetTurnCount() 40 | end 41 | 42 | if GlobalMaxxC~=Duel.GetTurnCount() 43 | and ChainCheck(23434538,1-player_ai) -- Maxx "C" 44 | then 45 | GlobalMaxxC=Duel.GetTurnCount() 46 | end 47 | --------------------------------------------- 48 | -- Don't activate anything if the AI controls 49 | -- a face-up Light and Darkness Dragon. 50 | --------------------------------------------- 51 | if Get_Card_Count_ID(AIMon(), 47297616, POS_FACEUP) > 0 then 52 | return 0,0 53 | end 54 | 55 | --------------------------------------- 56 | -- Don't do anything if if the AI controls 57 | -- a face-up C106: Giant Hand Red with 58 | -- a "Number" monster as XYZ material, 59 | -- that didn't use its effect this turn 60 | --------------------------------------- 61 | 62 | local aimon = AIMon() 63 | local card = nil 64 | for i=1,#aimon do 65 | if aimon[i].id==55888045 then 66 | card = aimon[i] 67 | end 68 | end 69 | if card and bit32.band(card.position,POS_FACEUP)>0 70 | and Duel.GetTurnCount() ~= GlobalC106 71 | and NotNegated(card) 72 | then 73 | local materials = card.xyz_materials 74 | for i=1,#materials do 75 | if bit32.band(materials[i].setcode,0x48)>0 then 76 | return 0,0 77 | end 78 | end 79 | end 80 | 81 | -- Lancelot 82 | for i=1,#AIMon() do 83 | local c = AIMon()[i] 84 | if c.id == 66547759 and NotNegated(c) 85 | and OPTCheck(c.cardid) and c.xyz_material_count>0 86 | and FilterPosition(c,POS_FACEUP) 87 | then 88 | return 0,0 89 | end 90 | end 91 | 92 | local backup = CopyTable(cards) 93 | local d = DeckCheck() 94 | local result,result2 = nil,nil 95 | result = PriorityChain(cards) 96 | if result ~= nil then 97 | if type(result)=="table" then 98 | if (result[1]~=1 99 | or InfiniteLoopCheck(cards[result[2]])) 100 | and BlacklistCheckChain(result[1],result[2],d,backup) 101 | then 102 | return result[1],result[2] 103 | end 104 | else 105 | if (result~=1 106 | or InfiniteLoopCheck(cards[result2])) 107 | and BlacklistCheckChain(result,result2,d,backup) 108 | then 109 | return result,result2 110 | end 111 | end 112 | end 113 | if d and d.Chain then 114 | result,result2 = d.Chain(cards,only_chains_by_player) 115 | end 116 | if result ~= nil then 117 | if type(result)=="table" then 118 | if (result[1]~=1 119 | or InfiniteLoopCheck(cards[result[2]])) 120 | then 121 | return result[1],result[2] 122 | end 123 | else 124 | if (result~=1 125 | or InfiniteLoopCheck(cards[result2])) 126 | then 127 | return result,result2 128 | end 129 | end 130 | end 131 | 132 | backup = CopyTable(cards) 133 | d = DeckCheck() 134 | local SelectChainFunctions = { 135 | FireFistOnChain,HeraldicOnSelectChain, 136 | GadgetOnSelectChain,BujinOnSelectChain,MermailOnSelectChain, 137 | SatellarknightOnSelectChain, 138 | ChaosDragonOnSelectChain,HATChain,QliphortChain, 139 | NobleChain,NekrozChain,BAChain,DarkWorldChain, 140 | ConstellarChain,BlackwingChain,HarpieChain, 141 | HEROChain,GenericChain, 142 | } 143 | 144 | for i=1,#SelectChainFunctions do 145 | local func = SelectChainFunctions[i] 146 | result = func(cards,only_chains_by_player) 147 | if result ~= nil and (d == 0 148 | or BlacklistCheckChain(result[1],result[2],d,backup)) 149 | then 150 | if result[1]~=1 151 | or InfiniteLoopCheck(cards[result[2]]) 152 | then 153 | return result[1],result[2] 154 | end 155 | end 156 | end 157 | 158 | result = 0 159 | 160 | --------------------------------------------- 161 | -- Cocoon of Evolution on field turn counter 162 | --------------------------------------------- 163 | if Global1PTVariable ~= 1 and Duel.GetTurnPlayer() == player_ai then 164 | if Get_Card_Count_ID(UseLists({AIMon(),AIST()}), 40240595, POS_FACEUP) > 0 and Get_Card_Count_ID(UseLists({AIMon(),AIST()}),68144350,POS_FACEUP) > 0 and AI.GetCurrentPhase() == PHASE_END then -- Cocoon of Evolution, Petit Moth 165 | GlobalCocoonTurnCount = GlobalCocoonTurnCount +1 166 | Global1PTVariable = 1 167 | else if Get_Card_Count_ID(UseLists({AIMon(),AIST()}), 40240595, POS_FACEUP) == 0 or Get_Card_Count_ID(UseLists({AIMon(),AIST()}),58192742,POS_FACEUP) == 0 then 168 | GlobalCocoonTurnCount = 0 169 | end 170 | end 171 | end 172 | 173 | ----------------------------------------------------- 174 | -- Check if global chaining conditions are met, 175 | -- and set ChainAllowed variable to 1 if they are. 176 | ----------------------------------------------------- 177 | for i=1,#cards do 178 | local c = cards[i] 179 | if Get_Card_Count_ID(AIST(),c.id, POS_FACEUP) == 0 or MultiActivationOK(c.id) == 1 then 180 | if NotNegated(c) then 181 | if UnchainableCheck(c.id) then -- Checks if any cards from UnchainableTogether list are already in chain. 182 | if NecrovalleyCheck(c) then 183 | ChainAllowed = 1 184 | end 185 | end 186 | end 187 | end 188 | end 189 | 190 | ----------------------------------------------------- 191 | -- Proceed to chain any cards and check other chaining 192 | -- conditions, only if global restrictions above are met. 193 | ----------------------------------------------------- 194 | if ChainAllowed == 1 then 195 | 196 | ------------------------------------------------- 197 | -- Activate Torrential Tribute if the opponent 198 | -- controls at least 2 more monsters than the AI. 199 | ------------------------------------------------- 200 | for i=1,#cards do 201 | if cards[i].id == 53582587 202 | and Get_Card_Count(OppMon()) >= Get_Card_Count(AIMon()) + 2 203 | and not Duel.GetOperationInfo(Duel.GetCurrentChain(), CATEGORY_SPECIAL_SUMMON) 204 | and not Duel.GetOperationInfo(Duel.GetCurrentChain(), CATEGORY_NORMAL_SUMMON) 205 | then 206 | GlobalActivatedCardID = cards[i].id 207 | return 1,i 208 | end 209 | end 210 | 211 | --------------------------------- 212 | -- Activate Raigeki Break or Phoenix Wing Wind Blast only if 213 | -- the opponent controls a card. 214 | --------------------------------- 215 | for i=1,#cards do 216 | if cards[i].id == 04178474 then -- Raigeki B 217 | if Get_Card_Att_Def(AIMon(),"attack",">",POS_FACEUP,"attack") < Get_Card_Att_Def(OppMon(),"attack",">",POS_FACEUP,"attack") or Get_Card_Count(OppST()) > 0 then 218 | GlobalActivatedCardID = cards[i].id 219 | GlobalCardMode = 1 220 | return 1,i 221 | end 222 | end 223 | end 224 | 225 | ---------------------------------------------------------------- 226 | -- Activate Beckoning Light only if the number of LIGHT monsters 227 | -- in the AI's graveyard is 5 or more, and also greater than or 228 | -- equal to the number of cards in the AI's hand (at least 4) 229 | ---------------------------------------------------------------- 230 | for i=1,#cards do 231 | if cards[i].id == 16255442 then 232 | local AIHand = AI.GetAIHand() 233 | if Get_Card_Count_ATT(AIGrave(),"==",ATTRIBUTE_LIGHT,nil) >= 5 and 234 | #AIHand >= 4 then 235 | GlobalActivatedCardID = cards[i].id 236 | return 1,i 237 | end 238 | end 239 | end 240 | 241 | ------------------------------------------------------- 242 | -- Activate Zero Gardna's effect in the Draw Phase. 243 | -- This will help the AI to use this effect only on the 244 | -- opponent's turn. 245 | ------------------------------------------------------- 246 | if AI.GetCurrentPhase() == PHASE_DRAW then 247 | for i=1,#cards do 248 | if cards[i].id == 93816465 then 249 | return 1,i 250 | end 251 | end 252 | end 253 | 254 | ---------------------------------------------- 255 | -- Activate Formula Synchron's "Accel Synchro" 256 | -- effect if the AI hasn't already attempted 257 | -- it yet this turn. 258 | ---------------------------------------------- 259 | for i=1,#cards do 260 | if cards[i].id == 50091196 and 261 | Global1PTFormula ~= 1 then 262 | Global1PTFormula = 1 263 | GlobalActivatedCardID = cards[i].id 264 | return 1,i 265 | end 266 | end 267 | 268 | --------------------------------------------- 269 | -- Always try to activate Stardust Dragon's 270 | -- or SD/AM's "summon from graveyard" effect. 271 | --------------------------------------------- 272 | for i=1,#cards do 273 | if cards[i].id == 44508094 or cards[i].id == 61257789 then 274 | if cards[i].location == LOCATION_GRAVE then 275 | return 1,i 276 | end 277 | end 278 | end 279 | 280 | 281 | 282 | --------------------------------------------- 283 | -- AI should activate: Waboku, Negate Attack 284 | -- only if player has any face up attack position monsters 285 | -- with more attack points than AI's stronger attack pos monster 286 | --------------------------------------------- 287 | if Duel.GetTurnPlayer() == 1-player_ai and Global1PTWaboku ~= 1 then 288 | for i=1,#cards do 289 | if cards[i].id == 12607053 or cards[i].id == 14315573 then -- Waboku, Negate Attack 290 | if Get_Card_Att_Def(OppMon(),"attack",">",POS_FACEUP,"attack") > Get_Card_Att_Def_Pos(AIMon()) or 291 | Get_Card_Count(AIMon()) == 0 and Get_Card_Count_Pos(AIMon(), POS_FACEUP_ATTACK) > 0 then 292 | Global1PTWaboku = 1 293 | GlobalActivatedCardID = cards[i].id 294 | return 1,i 295 | end 296 | end 297 | end 298 | end 299 | 300 | 301 | --------------------------------------------- 302 | -- AI should activate: Shadow Spell, 303 | -- only if player has stronger attack position monster than any of AI's 304 | -- and player's monster has 2000 attack points or more. 305 | --------------------------------------------- 306 | for i=1,#cards do 307 | if cards[i].id == 29267084 then -- Shadow Spell 308 | if Get_Card_Att_Def(OppMon(),"attack",">",POS_FACEUP,"attack") >= 2000 and 309 | (Get_Card_Att_Def(AIMon(),"attack",">",POS_FACEUP,"attack") < Get_Card_Att_Def(OppMon(),"attack", ">",POS_FACEUP_ATTACK,"attack")) then 310 | GlobalActivatedCardID = cards[i].id 311 | return 1,i 312 | end 313 | end 314 | end 315 | 316 | --------------------------------------------- 317 | -- AI should activate: Return from the Different Dimension, 318 | -- only if AI can bring out strong tribute monster as result, 319 | -- or if player or AI has 0 monsters on the field (just in case) 320 | --------------------------------------------- 321 | for i=1,#cards do 322 | if cards[i].id == 27174286 then -- Return from the Different Dimension 323 | local AIHand = AIHand() 324 | local HandHighestATK = 0 325 | local Result = 0 326 | if IsBattlePhase() and Duel.GetTurnPlayer() == player_ai 327 | and Get_Card_Count_Type(AIBanish(),TYPE_MONSTER,">",nil) >= 3 328 | and Get_Card_Count(AIMon()) == 0 329 | then 330 | return 1,i 331 | end 332 | if AI.GetCurrentPhase() == PHASE_MAIN1 and Get_Card_Count_Type(AIBanish(),TYPE_MONSTER,">",nil) >= 3 and GlobalIsAIsTurn == 1 and Get_Card_Count(AIMon()) == 0 then 333 | for x=1,#AIHand do 334 | if AIHand[x].attack > HandHighestATK then 335 | HandHighestATK = AIHand[x].attack 336 | if AIHand[x].level >= 5 and 337 | HandHighestATK >= Get_Card_Att_Def(OppMon(),"attack",">",POS_FACEUP,"attack") then 338 | return 1,i 339 | end 340 | end 341 | end 342 | end 343 | end 344 | end 345 | 346 | --------------------------------------------- 347 | -- AI should activate: Zero Gravity, 348 | -- only if Player is about to attack or attacked. 349 | --------------------------------------------- 350 | for i=1,#cards do 351 | if cards[i].id == 83133491 then -- Zero Gravity 352 | if Get_Card_Count_ID(UseLists({AIMon(),AIST()}), 83133491, POS_FACEUP) == 0 353 | and AI.GetCurrentPhase() == PHASE_DAMAGE and Duel.GetTurnPlayer() == 1-player_ai 354 | then 355 | GlobalActivatedCardID = cards[i].id 356 | return 1,i 357 | end 358 | end 359 | end 360 | 361 | --------------------------------------------- 362 | -- AI should activate: Enemy Controller, if 363 | -- player's monster is stronger than AI's 364 | --------------------------------------------- 365 | for i=1,#cards do 366 | if cards[i].id == 98045062 then -- Enemy Controller 367 | if Get_Card_Att_Def(AIMon(),"attack",">",POS_FACEUP,"attack") < Get_Card_Att_Def(OppMon(),"attack",">",POS_FACEUP,"attack") and 368 | Get_Card_Att_Def(AIMon(),"attack",">",POS_FACEUP,"attack") > Get_Card_Att_Def(OppMon(), "attack", ">", POS_FACEUP_ATTACK, "defense") then 369 | --return 1,i 370 | end 371 | end 372 | end 373 | 374 | --------------------------------------------- 375 | -- AI should activate: Amazoness Archers, 376 | -- only if AI's monster can become stronger than 377 | -- any player's monster as result. 378 | --------------------------------------------- 379 | for i=1,#cards do 380 | if cards[i].id == 67987611 then -- Amazoness Archers 381 | if (Get_Card_Att_Def(AIMon(),"attack",">",POS_FACEUP,"attack") + 500) >= Get_Card_Att_Def(OppMon(),"attack",">",POS_FACEUP,"attack") then 382 | GlobalActivatedCardID = cards[i].id 383 | return 1,i 384 | end 385 | end 386 | end 387 | 388 | --------------------------------------------- 389 | -- Set global variable to 1 if player activates 390 | -- "Amazoness Archers" trap card 391 | --------------------------------------------- 392 | if Get_Card_Count_ID(OppST(), 67987611, POS_FACEUP) > 0 then 393 | if IsBattlePhase() then 394 | Global1PTAArchers = 1 395 | end 396 | end 397 | 398 | --------------------------------------------- 399 | -- AI should activate: Spellbinding Circle, Mirror Force, 400 | -- only if AI's monsters are weaker than players. 401 | --------------------------------------------- 402 | for i=1,#cards do 403 | if cards[i].id == 18807108 then-- Spellbinding Circle 404 | if Get_Card_Att_Def(OppMon(),"attack",">",POS_FACEUP,"attack") > Get_Card_Att_Def(AIMon(),"attack",">",POS_FACEUP,"attack") 405 | and Get_Card_Att_Def(OppMon(),"attack",">",POS_FACEUP,"attack") > Get_Card_Att_Def(OppMon(),"attack", ">", POS_FACEUP_ATTACK,"defense") 406 | and Get_Card_Att_Def(OppMon(),"attack",">",POS_FACEUP,"attack") >= 1600 or AI.GetPlayerLP(1) <= 2000 407 | then 408 | GlobalActivatedCardID = cards[i].id 409 | return 1,i 410 | end 411 | end 412 | end 413 | 414 | -- always activate Dragon Ruler's on banish effects 415 | if HasID(cards,53804307,FilterLocation,LOCATION_REMOVED) then 416 | return 1,CurrentIndex 417 | end 418 | if HasID(cards,26400609,FilterLocation,LOCATION_REMOVED) then 419 | return 1,CurrentIndex 420 | end 421 | if HasID(cards,89399912,FilterLocation,LOCATION_REMOVED) then 422 | return 1,CurrentIndex 423 | end 424 | if HasID(cards,90411554,FilterLocation,LOCATION_REMOVED) then 425 | return 1,CurrentIndex 426 | end 427 | --------------------------------------------- 428 | -- Mandatory effects the AI could potentially 429 | -- skip, if not handled here 430 | --------------------------------------------- 431 | for i=1,#cards do 432 | if MandatoryCheck(cards[i]) then 433 | return 1,i 434 | end 435 | end 436 | 437 | ---------------------------------------------------------- 438 | -- For now, chain anything else (not already listed above) 439 | -- that can be chained, except cards with the same ID as 440 | -- another existing face-up spell/trap card, cards that 441 | -- shouldn't be activated in a same chain, and cards that 442 | -- shouldn't be activated under certain conditions. 443 | ---------------------------------------------------------- 444 | 445 | for i=1,#cards do 446 | local c = cards[i] 447 | if (Get_Card_Count_ID(AIST(),c.id, POS_FACEUP) == 0 or MultiActivationOK(c.id) == 1) 448 | and UnchainableCheck(c.id) 449 | and NecrovalleyCheck(c) 450 | and CardIsScripted(c.id) == 0 451 | and NotNegated(c) 452 | and InfiniteLoopCheck(c) 453 | then 454 | GlobalActivatedCardID = c.id 455 | return 1,i 456 | end 457 | end 458 | 459 | ------------------------------------- 460 | -- Otherwise don't activate anything. 461 | ------------------------------------- 462 | return 0,0 463 | end 464 | end 465 | -------------------------------------------------------------------------------- /AI/decks/Fluffal/FluffalTarget.lua: -------------------------------------------------------------------------------- 1 | ------------------------ 2 | -------- TARGET -------- 3 | ------------------------ 4 | function DogTarget(cards,min,max,c) 5 | --CountPrioTarget(cards,PRIO_TOHAND,1,nil,nil,nil,"DogTarget") 6 | return Add(cards,PRIO_TOHAND,max) 7 | end 8 | GlobalPenguin = 0 9 | function PenguinTarget(cards,min,max,c) 10 | if GlobalPenguin == 1 then 11 | --CountPrioTarget(cards,PRIO_TOFIELD,1,nil,nil,nil,"PenguinTarget - Field") 12 | return Add(cards,PRIO_TOFIELD,max) 13 | end 14 | if GlobalPenguin == 0 then 15 | --CountPrioTarget(cards,PRIO_DISCARD,1,nil,nil,nil,"PenguinTarget - Grave") 16 | return Add(cards,PRIO_DISCARD,min) 17 | end 18 | end 19 | function OwlTarget(cards,min,max,c) 20 | local result 21 | if GlobalOwl == 1 then 22 | result = FusionSummonTarget(cards,min,max,c,MATERIAL_TOGRAVE) 23 | else 24 | result = Add(cards) 25 | end 26 | return result 27 | end 28 | function SheepTarget(cards,min,max,c) 29 | if LocCheck(cards,LOCATION_MZONE) then 30 | local result = {} 31 | for i=1, #cards do 32 | local c = cards[i] 33 | result[i] = c 34 | result[i].prio = GetPriority(c,PRIO_TOHAND) 35 | --print("SheepTarget - id: "..result[i].id.." prio: "..result[i].prio) 36 | result[i].index = i 37 | end 38 | local compare = function(a,b) return a.prio>b.prio end 39 | table.sort(result,compare) 40 | --print("SheepTarget - MZONE to HAND") 41 | --return Add(cards,PRIO_TOHAND,max) 42 | return {result[1].index} 43 | end 44 | if LocCheck(cards,LOCATION_GRAVE) 45 | or LocCheck(cards,LOCATION_HAND) 46 | then 47 | return Add(cards,PRIO_TOFIELD,max) 48 | end 49 | end 50 | function OctoTarget(cards,min,max,c) 51 | if LocCheck(cards,LOCATION_GRAVE) then 52 | if HasID(AIGrave(),72413000,true) -- Wings 53 | and OPTCheck(72413000) 54 | and CountFluffal(AIGrave()) <= 2 55 | and CountEdgeImp(AIGrave()) > 0 56 | then 57 | --CountPrioTarget(cards,PRIO_TOHAND,max,nil,EdgeImpFilter,nil,"OctoTarget") 58 | result = Add(cards,PRIO_TOHAND,max,EdgeImpFilter) 59 | else 60 | --CountPrioTarget(cards,PRIO_TOHAND,max,nil,nil,nil,"OctoTarget") 61 | result = Add(cards,PRIO_TOHAND,max) 62 | end 63 | GlobalOcto = 0 64 | return result 65 | end 66 | if LocCheck(cards,LOCATION_REMOVED) then 67 | return Add(cards,PRIO_TOGRAVE,max) 68 | end 69 | end 70 | function CatTarget(cards,min,max,c) 71 | return Add(cards,PRIO_TOHAND,max) 72 | end 73 | function RabitTarget(cards,min,max,c) 74 | return Add(cards,PRIO_TOHAND,max) 75 | end 76 | function MouseTarget(cards,min,max,c) 77 | return Add(cards,PRIO_TOFIELD,max) 78 | end 79 | function WingsTarget(cards,min,max,c) 80 | if LocCheck(cards,LOCATION_GRAVE) then 81 | return Add(cards,PRIO_BANISH,min) 82 | end 83 | if LocCheck(cards,LOCATION_SZONE) then 84 | return Add(cards,PRIO_TOGRAVE,min) 85 | end 86 | end 87 | -- EdgeImp TARGET 88 | function TomahawkTarget(cards,min,max,c) 89 | if LocCheck(cards,LOCATION_DECK) then 90 | --print("TomahawkTarget - DECK to GRAVE") 91 | return Add(cards,PRIO_TOGRAVE,max) 92 | end 93 | if LocCheck(cards,LOCATION_HAND) then 94 | --print("TomahawkTarget - HAND to GRAVE") 95 | return Add(cards,PRIO_DISCARD,min) 96 | end 97 | end 98 | function ChainTarget(cards,min,max,c) 99 | return Add(cards,PRIO_TOHAND,max) 100 | end 101 | GlobalSabres = 0 102 | function SabresTarget(cards,min,max,c) 103 | if GlobalSabres == 1 then -- SabresMouse 104 | return Add(cards,PRIO_DISCARD,min,FilterID,06142488) -- Mouse 105 | end 106 | if GlobalSabres == 2 then -- SabreFPatchwork 107 | if CountEdgeImp(AIDeck()) == 0 then 108 | return Add(cards,PRIO_DISCARD,min,EdgeImpFilter) -- EdgeImp 109 | end 110 | if not HasID(AIDeck(),24094653,true) then 111 | return Add(cards,PRIO_DISCARD,min,FilterID,24094653) -- Polymerization 112 | end 113 | end 114 | if ( 115 | CardsMatchingFilter(AIST(),TVendorCheckFilter,true) > 0 116 | or HasID(AIHand(),70245411,true) -- TVendor 117 | ) 118 | and PriorityCheck(AIHand(),PRIO_DISCARD) > 3 119 | then 120 | return Add(cards,PRIO_TOFIELD,min,FluffalFilter) 121 | end 122 | return Add(cards,PRIO_DISCARD) 123 | end 124 | -- Other TARGET 125 | function TGuideTarget(cards,min,max,c) 126 | return Add(cards,PRIO_TOFIELD,max) 127 | end 128 | function KoSTarget(cards,min,max,c) 129 | return Add(cards,PRIO_TOHAND,max) 130 | end 131 | function PFusionerTarget(cards,min,max,c) 132 | local result 133 | GlobalPolymerization = 1 134 | result = FusionSummonTarget(cards,min,max,c,MATERIAL_TOGRAVE) 135 | GlobalPolymerization = 0 136 | return result 137 | end 138 | -- FluffalS TARGET 139 | GlobalTVendor = 0 140 | function TVendorTarget(cards,min,max,c) 141 | if LocCheck(cards,LOCATION_DECK) then 142 | --print("TVendorTarget - DECK to HAND") 143 | GlobalTVendor = 0 144 | --CountPrioTarget(cards,PRIO_TOHAND,1,nil,nil,nil,"TVendorTarget - HAND") 145 | return Add(cards,PRIO_TOHAND) 146 | end 147 | if GlobalTVendor == 0 then 148 | --print("TVendorTarget - HAND to GRAVE") 149 | GlobalTVendor = 1 150 | return Add(cards,PRIO_DISCARD) 151 | end 152 | if GlobalTVendor == 1 then 153 | --print("TVendorTarget - HAND to FIELD") 154 | GlobalTVendor = 2 155 | --CountPrioTarget(cards,PRIO_TOFIELD,1,nil,nil,nil,"TVendorTarget - HAND to FIELD") 156 | return Add(cards,PRIO_TOFIELD) 157 | end 158 | if GlobalTVendor == 2 then 159 | GlobalTVendor = 0 160 | end 161 | end 162 | 163 | function FPatchworkTarget(cards,min,max,c) 164 | --CountPrioTarget(cards,PRIO_TOHAND,1,nil,nil,nil,"FPatchworkTarget") 165 | return Add(cards,PRIO_TOHAND,max) 166 | end 167 | function FRebornTarget(cards,min,max,c) 168 | if LocCheck(cards,LOCATION_GRAVE) then 169 | return Add(cards,PRIO_TOFIELD,max) 170 | end 171 | if LocCheck(cards,LOCATION_REMOVED) then 172 | return Add(cards,PRIO_TOGRAVE,max) 173 | end 174 | end 175 | 176 | -- FUSION TARGET 177 | GlobalFusionPerform = 0 -- Perform Only 178 | GlobalFusionId = 0 -- Fusion MonsterID 179 | 180 | GlobalPolymerization = 0 181 | function PolymerizationTarget(cards,min,max,c) 182 | if FilterLocation(c,LOCATION_GRAVE) then -- FSubstitute 183 | return Add(cards,PRIO_TODECK) 184 | end 185 | local result 186 | GlobalPolymerization = 1 187 | result = FusionSummonTarget(cards,min,max,c,MATERIAL_TOGRAVE) 188 | GlobalPolymerization = 0 189 | return result 190 | end 191 | GlobalDFusion = 0 192 | function DFusionTarget(cards,min,max,c) 193 | local result 194 | GlobalDFusion = 1 195 | result = FusionSummonTarget(cards,min,max,c,MATERIAL_TOGRAVE) 196 | GlobalDFusion = 0 197 | return result 198 | end 199 | GlobalFFactory = 0 200 | function FFactoryTarget(cards,min,max,c) 201 | if LocCheck(cards,LOCATION_GRAVE) then 202 | return Add(cards,PRIO_BANISH) 203 | end 204 | if LocCheck(cards,LOCATION_REMOVED) then 205 | return Add(cards,PRIO_TOHAND) 206 | end 207 | local result 208 | GlobalFFactory = 1 209 | result = FusionSummonTarget(cards,min,max,c,MATERIAL_TOGRAVE) 210 | GlobalFFactory = 0 211 | return result 212 | end 213 | GlobalFFusion = 0 214 | function FFusionTarget(cards,min,max,c) 215 | local result 216 | GlobalFFusion = 1 217 | result = FusionSummonTarget(cards,min,max,c,PRIO_BANISH) 218 | GlobalFFusion = 0 219 | return result 220 | end 221 | 222 | -- Spell TARGET 223 | GlobalIFusion = 0 224 | function IFusionTarget(cards,min,max,c) 225 | GlobalIFusion = 1 226 | CountPrioTarget(cards,PRIO_TOFIELD,1,nil,nil,nil,"IFusionTarget") 227 | local result = Add(cards,PRIO_TOFIELD,max) 228 | OPTSet(cards[1].cardid) 229 | return result 230 | end 231 | function FBoBTarget(cards,min,max,c) 232 | return Add(cards,PRIO_TOGRAVE,max) 233 | end 234 | function MSpringTarget(cards,min,max,c) 235 | return Add(cards,PRIO_DISCARD,min) 236 | end 237 | -- Trap TARGET 238 | function FReserveTarget(cards,min,max,c) 239 | if LocCheck(cards,LOCATION_EXTRA) then 240 | --print("FReserveTarget - EXTRA") 241 | return Add(cards,PRIO_TOHAND) 242 | end 243 | if LocCheck(cards,LOCATION_DECK) then 244 | --print("FReserveTarget - DECK to HAND") 245 | return Add(cards,PRIO_TOHAND) 246 | end 247 | end 248 | function JAvariceTarget(cards,min,max,c) 249 | return Add(cards,PRIO_TOHAND,5,FilterType,TYPE_SPELL+TYPE_TRAP) 250 | end 251 | 252 | -- Frightfur TARGET 253 | function FSabreToothTarget(cards,min,max,c) 254 | return Add(cards,PRIO_TOFIELD,max) 255 | end 256 | function FKrakenTarget(cards,min,max,c) 257 | return BestTargets(cards,max,TARGET_DESTROY,FKrakenSendFilter) 258 | end 259 | function FLeoTarget(cards,min,max,c) 260 | return BestTargets(cards,max,TARGET_DESTROY,FTigerDestroyFilter) 261 | end 262 | function FTigerTarget(cards,min,max,c) 263 | local maxTargets = CardsMatchingFilter(OppField(),FTigerDestroyFilter) 264 | --print("maxTargets: "..maxTargets) 265 | if maxTargets > max then 266 | maxTargets = max 267 | end 268 | local result = BestTargets(cards,maxTargets,TARGET_DESTROY,FTigerDestroyFilter) 269 | return result 270 | end 271 | -- OtherF TARGET 272 | function FStarveTarget(cards,min,max,c) 273 | return BestTargets(cards,max,TARGET_DESTROY) 274 | end 275 | function FNordenTarget(cards,min,max,c) 276 | if CardsMatchingFilter(AIGrave(),FluffalNordenFilter) > 0 then 277 | return Add(cards,PRIO_TOFIELD,max,FluffalNordenFilter) 278 | else 279 | return Add(cards,PRIO_TOFIELD,max) 280 | end 281 | end 282 | -- Other TARGET 283 | function BossMonsterTarget(cards,min,max,c) 284 | local bossIndex = 1 285 | if HasIDNotNegated(cards,58481572,true) 286 | then 287 | bossIndex = IndexByID(cards,58481572) -- DarkLaw 288 | elseif HasIDNotNegated(cards,90809975,true) 289 | then 290 | bossIndex = IndexByID(cards,90809975) -- Treatoad 291 | elseif HasIDNotNegated(cards,10443957,true) 292 | then 293 | bossIndex = IndexByID(cards,01561110) -- ABC Buster Dragon 294 | elseif HasIDNotNegated(cards,01561110,true) 295 | then 296 | bossIndex = IndexByID(cards,10443957) -- Infinity 297 | end 298 | if bossIndex then 299 | print("InfiniteIndex: "..bossIndex) 300 | return {bossIndex} 301 | else 302 | return BestTargets(cards,max,TARGET_DESTROY) 303 | end 304 | end 305 | 306 | -- FUSION FUNCTIONS 307 | function MaxMaterials(fusionId,min,max) 308 | local result = 1 309 | if fusionId == 80889750 -- FSabreTooth 310 | and GlobalFusionPerform == 3 311 | then 312 | result = 2 313 | else 314 | result = 1 315 | end 316 | 317 | if fusionId == 11039171 then -- FWolf 318 | result = 1 319 | local expectedDamage = ExpectedDamageMichelet(1,NotFluffalFilter) 320 | local oppRemainLP = AI.GetPlayerLP(2) - expectedDamage 321 | if oppRemainLP > 0 322 | then 323 | result = math.ceil(oppRemainLP / (2000 + FrightfurBoost(fusionId))) 324 | end 325 | end 326 | 327 | if fusionId == 00464362 then -- FTiger 328 | if CardsMatchingFilter(OppField(),FTigerAdvantageFilter) 329 | then 330 | return min 331 | end 332 | if CardsMatchingFilter(UseLists({AIHand(),AIST()}),FluffalFusionSTFilter) > 0 333 | then 334 | result = max - 2 335 | else 336 | result = max - 1 337 | end 338 | if #AIMon() > 4 then 339 | result = result + 1 340 | end 341 | 342 | if (result + 1) > CardsMatchingFilter(OppField(),FTigerDestroyFilter) then 343 | result = CardsMatchingFilter(OppField(),FTigerDestroyFilter) - 1 344 | end 345 | if HasID(UseLists({AIHand(),AIMon()}),02729285,true) -- Cat 346 | or GlobalFFusion == 0 347 | then 348 | if result > 3 then 349 | result = 3 350 | end 351 | end 352 | if CardsMatchingFilter(OppMon(),InfinityMonFilter) > 0 -- InfinityMon 353 | and CardsMatchingFilter(UseLists({AIHand(),AIMon()}),FluffalFusionProtectFilter) == 0 354 | then 355 | result = 1 356 | end 357 | if CardsMatchingFilter(OppField(),FluffalFlootGateFilter) > 0 then 358 | result = 1 359 | end 360 | if CardsMatchingFilter(OppST(),FilterPosition,POS_FACEDOWN) >= 3 361 | then 362 | result = 1 363 | elseif CardsMatchingFilter(OppST(),FilterPosition,POS_FACEDOWN) == 2 364 | then 365 | if result > 2 then 366 | if GlobalFFusion > 0 367 | then 368 | result = 3 369 | else 370 | result = 2 371 | end 372 | end 373 | elseif CardsMatchingFilter(OppST(),FilterPosition,POS_FACEDOWN) == 1 374 | then 375 | if result > 3 then 376 | result = 3 377 | end 378 | end 379 | end 380 | 381 | if result > max then 382 | result = max 383 | end 384 | if result < min then 385 | result = min 386 | end 387 | print("MaxMaterials - fusionId "..fusionId.." max: "..max.." - Result: "..result) 388 | return result 389 | end 390 | function FusionSummonTarget(cards,min,max,source,materialDest) 391 | if LocCheck(cards,LOCATION_EXTRA) then 392 | local result 393 | GlobalFusionPerform = 1 394 | result = Add(cards,PRIO_TOFIELD) 395 | GlobalFusionId = cards[1].id 396 | CountPrioTarget(cards,PRIO_TOFIELD,1,nil,nil,nil,"FusionTarget") 397 | print("FusionTarget: "..GlobalFusionId) 398 | return result 399 | end 400 | 401 | if GlobalFusionPerform == 1 then 402 | GlobalFusionPerform = 2 403 | --CountPrioTarget(cards,materialDest,1,nil,nil,nil,"FusionTarget1") 404 | return Add(cards,materialDest) 405 | end 406 | 407 | if GlobalFusionPerform >= 2 then 408 | GlobalFusionPerform = GlobalFusionPerform + 1 409 | --CountPrioTarget(cards,materialDest,MaxMaterials(GlobalFusionId,min,max),nil,nil,nil,"FusionTarget"..(GlobalFusionPerform-1)) 410 | return Add(cards,materialDest,MaxMaterials(GlobalFusionId,min,max)) 411 | end 412 | end 413 | 414 | function FluffalCard(cards,min,max,id,c) -- FLUFFAL CARD 415 | if c then 416 | --print("FluffalCard: "..c.id.." - min: "..min.." - max: "..max) 417 | end 418 | -- Fluffal TARGET 419 | if id == 39246582 then -- Dog 420 | return DogTarget(cards,min,max,c) 421 | end 422 | if id == 13241004 then -- Penguin 423 | return PenguinTarget(cards,min,max,c) 424 | end 425 | if id == 65331686 then -- Owl 426 | return OwlTarget(cards,min,max,c) 427 | end 428 | if id == 98280324 then -- Sheep 429 | return SheepTarget(cards) 430 | end 431 | if id == 87246309 then -- Octo 432 | return OctoTarget(cards,min,max,c) 433 | end 434 | if id == 02729285 then -- Cat 435 | return CatTarget(cards) 436 | end 437 | if id == 38124994 then -- Rabit 438 | return RabitTarget(cards) 439 | end 440 | if id == 06142488 then -- Mouse 441 | return MouseTarget(cards,min,max,c) 442 | end 443 | if id == 72413000 then -- Wings 444 | return WingsTarget(cards) 445 | end 446 | -- EdgeImp TARGET 447 | if id == 97567736 then -- Tomahawk 448 | return TomahawkTarget(cards) 449 | end 450 | if id == 61173621 then -- Chain 451 | return ChainTarget(cards,min,max,c) 452 | end 453 | if id == 30068120 then -- Sabres 454 | return SabresTarget(cards,min,max,c) 455 | end 456 | -- Other TARGET 457 | if id == 10802915 then -- TGuide 458 | return TGuideTarget(cards) 459 | end 460 | if id == 79109599 then -- KoS 461 | return KoSTarget(cards) 462 | end 463 | if id == 06205579 then -- PFusioner 464 | return PFusionerTarget(cards) 465 | end 466 | -- FluffalS TARGET 467 | if id == 70245411 then -- TVendor 468 | return TVendorTarget(cards,min,max,c) 469 | end 470 | if id == 34773082 then -- FPatchwork 471 | return FPatchworkTarget(cards,min,max,c) 472 | end 473 | if id == 28039390 then -- FReborn 474 | return FRebornTarget(cards,min,max,c) 475 | end 476 | -- Fusion TARGET 477 | if id == 24094653 then -- Polymerization 478 | return PolymerizationTarget(cards,min,max,c) 479 | end 480 | if id == 94820406 then -- DFusion 481 | return DFusionTarget(cards,min,max,c) 482 | end 483 | if id == 43698897 then -- FFactory 484 | return FFactoryTarget(cards,min,max,c) 485 | end 486 | if id == 06077601 then -- FFusion 487 | return FFusionTarget(cards,min,max,c) 488 | end 489 | if id == 01845204 then -- IFusion 490 | return IFusionTarget(cards,min,max,c) 491 | end 492 | if id == 17194258 then -- FConscription 493 | return FReserveTarget(cards,min,max,c) 494 | end 495 | -- Spell TARGET 496 | if id == 35726888 then -- FBoB 497 | return FBoBTarget(cards,min,max,c) 498 | end 499 | if id == 43455065 then -- MSpring 500 | return MSpringTarget(cards,min,max,c) 501 | end 502 | -- Trap TARGET 503 | if id == 66127916 then -- FReserve 504 | return FReserveTarget(cards) 505 | end 506 | if id == 98954106 then -- JAvarice 507 | return JAvariceTarget(cards) 508 | end 509 | if id == 78474168 then -- BTS 510 | return BossMonsterTarget(cards,min,max,c) 511 | end 512 | -- Frightfur TARGET 513 | if id == 80889750 then -- FSabreTooth 514 | return FSabreToothTarget(cards,min,max,c) 515 | end 516 | if id == 40636712 then -- FKraken 517 | return FKrakenTarget(cards,min,max,c) 518 | end 519 | if id == 10383554 then -- FLeo 520 | return FLeoTarget(cards) 521 | end 522 | if id == 00464362 then -- FTiger 523 | return FTigerTarget(cards,min,max,c) 524 | end 525 | -- OtherF TARGET 526 | if id == 41209827 then 527 | return FStarveTarget(cards,min,max,c) 528 | end 529 | if id == 17412721 then 530 | return FNordenTarget(cards,min,max,c) 531 | end 532 | -- OtherX TARGET 533 | if id == 90809975 then -- Toadally 534 | return Add(cards,PRIO_TODECK,max,FilterID,90809975) 535 | end 536 | if id == 00440556 then -- Bahamut Effect 537 | return Add(cards,PRIO_TOGRAVE) 538 | end 539 | if GlobalSummonId == 00440556 then -- Bahamut Summon 540 | return Add(cards,PRIO_TOGRAVE,min,FluffalBahamutMaterialFilter) 541 | end 542 | 543 | if GlobalKaiju == 1 then 544 | GlobajKaiju = 0 545 | return BossMonsterTarget(cards,min,max,c) 546 | end 547 | 548 | return nil 549 | end 550 | 551 | --[[ 552 | 39246582, -- Fluffal Dog 553 | 13241004, -- Fluffal Penguin 554 | 03841833, -- Fluffal Bear 555 | 65331686, -- Fluffal Owl 556 | 98280324, -- Fluffal Sheep 557 | 87246309, -- Fluffal Octo 558 | 02729285, -- Fluffal Cat 559 | 38124994, -- Fluffal Rabit 560 | 06142488, -- Fluffal Mouse 561 | 72413000, -- Fluffal Wings 562 | 81481818, -- Fluffal Patchwork 563 | 97567736, -- Edge Imp Tomahawk 564 | 61173621, -- Edge Imp Chain 565 | 30068120, -- Edge Imp Sabres 566 | 10802915, -- Tour Guide from the Underworld 567 | 79109599, -- King of the Swamp 568 | 06205579, -- Parasite Fusioner 569 | 67441435, -- Glow-Up Bulb 570 | 571 | 70245411, -- Toy Vendor 572 | 06077601, -- Frightfur Fusion 573 | 43698897, -- Frightfur Factory 574 | 34773082, -- Frightfur Patchwork 575 | 28039390, -- Frightfur Reborn 576 | 01845204, -- Instant Fusion 577 | 24094653, -- Polymerization 578 | 94820406, -- Dark Fusion 579 | 05133471, -- Galaxy Cyclone 580 | 35726888, -- Foolish Burial of Belongings 581 | 43455065, -- Magical Spring 582 | 43898403, -- Twin Twister 583 | 12580477, -- Raigeki 584 | 585 | 66127916, -- Fusion Reserve 586 | 98954106, -- Jar of Avarice 587 | 51452091, -- Royal Decree 588 | 589 | 91034681, -- Frightfur Daredevil 590 | 80889750, -- Frightfur Sabre-Tooth 591 | 40636712, -- Frightfur Kraken 592 | 10383554, -- Frightfur Leo 593 | 85545073, -- Frightfur Bear 594 | 11039171, -- Frightfur Wolf 595 | 00464362, -- Frightfur Tiger 596 | 57477163, -- Frightfur Sheep 597 | 41209827, -- Starve Venom Fusion Dragon 598 | 42110604, -- Hi-Speedroid Chanbara 599 | 83531441, -- Dante 600 | ]] --------------------------------------------------------------------------------