Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
W
windbot
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Locked Files
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Security & Compliance
Security & Compliance
Dependency List
License Compliance
Packages
Packages
Container Registry
Analytics
Analytics
CI / CD
Code Review
Insights
Issues
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
MyCard
windbot
Commits
f2f54c2a
Commit
f2f54c2a
authored
Nov 13, 2017
by
mercury233
Browse files
Options
Browse Files
Download
Plain Diff
Merge
https://github.com/IceYGO/windbot
parents
b489285e
c53428bc
Changes
16
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
1767 additions
and
1477 deletions
+1767
-1477
Game/AI/AIFunctions.cs
Game/AI/AIFunctions.cs
+81
-1
Game/AI/Decks/BlueEyesExecutor.cs
Game/AI/Decks/BlueEyesExecutor.cs
+14
-48
Game/AI/Decks/DoEveryThingExecutor.cs
Game/AI/Decks/DoEveryThingExecutor.cs
+47
-47
Game/AI/Decks/LightswornExecutor.cs
Game/AI/Decks/LightswornExecutor.cs
+10
-30
Game/AI/Decks/QliphortExecutor.cs
Game/AI/Decks/QliphortExecutor.cs
+3
-7
Game/AI/Decks/RainbowExecutor.cs
Game/AI/Decks/RainbowExecutor.cs
+437
-414
Game/AI/Decks/Rank5Executor.cs
Game/AI/Decks/Rank5Executor.cs
+13
-0
Game/AI/Decks/ToadallyAwesomeExecutor.cs
Game/AI/Decks/ToadallyAwesomeExecutor.cs
+581
-581
Game/AI/Decks/YosenjuExecutor.cs
Game/AI/Decks/YosenjuExecutor.cs
+319
-311
Game/AI/Decks/ZexalWeaponsExecutor.cs
Game/AI/Decks/ZexalWeaponsExecutor.cs
+13
-1
Game/AI/Decks/ZoodiacExecutor.cs
Game/AI/Decks/ZoodiacExecutor.cs
+32
-23
Game/AI/DefaultExecutor.cs
Game/AI/DefaultExecutor.cs
+2
-2
Game/AI/Executor.cs
Game/AI/Executor.cs
+38
-2
Game/GameAI.cs
Game/GameAI.cs
+115
-7
Game/GameBehavior.cs
Game/GameBehavior.cs
+28
-3
README.md
README.md
+34
-0
No files found.
Game/AI/AIFunctions.cs
View file @
f2f54c2a
...
...
@@ -247,7 +247,7 @@ namespace WindBot.Game.AI
foreach
(
ClientCard
ecard
in
spells
)
{
if
(
ecard
.
IsFaceup
())
if
(
ecard
.
IsFaceup
()
&&
ecard
.
HasType
(
CardType
.
Continuous
)
)
return
ecard
;
}
...
...
@@ -296,5 +296,85 @@ namespace WindBot.Game.AI
return
Duel
.
ChainTargets
.
Count
==
1
&&
card
.
Equals
(
Duel
.
ChainTargets
[
0
]);
}
/// <summary>
/// Select cards listed in preferred.
/// </summary>
public
void
SelectPreferredCards
(
IList
<
ClientCard
>
selected
,
ClientCard
preferred
,
IList
<
ClientCard
>
cards
,
int
min
,
int
max
)
{
if
(
cards
.
IndexOf
(
preferred
)
>
0
&&
selected
.
Count
<
max
)
{
selected
.
Add
(
preferred
);
}
}
/// <summary>
/// Select cards listed in preferred.
/// </summary>
public
void
SelectPreferredCards
(
IList
<
ClientCard
>
selected
,
int
preferred
,
IList
<
ClientCard
>
cards
,
int
min
,
int
max
)
{
foreach
(
ClientCard
card
in
cards
)
{
if
(
card
.
Id
==
preferred
&&
selected
.
Count
<
max
)
selected
.
Add
(
card
);
}
}
/// <summary>
/// Select cards listed in preferred.
/// </summary>
public
void
SelectPreferredCards
(
IList
<
ClientCard
>
selected
,
IList
<
ClientCard
>
preferred
,
IList
<
ClientCard
>
cards
,
int
min
,
int
max
)
{
IList
<
ClientCard
>
avail
=
new
List
<
ClientCard
>();
foreach
(
ClientCard
card
in
cards
)
{
// clone
avail
.
Add
(
card
);
}
while
(
preferred
.
Count
>
0
&&
avail
.
IndexOf
(
preferred
[
0
])
>
0
&&
selected
.
Count
<
max
)
{
ClientCard
card
=
preferred
[
0
];
preferred
.
Remove
(
card
);
avail
.
Remove
(
card
);
selected
.
Add
(
card
);
}
}
/// <summary>
/// Select cards listed in preferred.
/// </summary>
public
void
SelectPreferredCards
(
IList
<
ClientCard
>
selected
,
IList
<
int
>
preferred
,
IList
<
ClientCard
>
cards
,
int
min
,
int
max
)
{
for
(
int
i
=
0
;
i
<
preferred
.
Count
;
i
++)
{
foreach
(
ClientCard
card
in
cards
)
{
if
(
card
.
Id
==
preferred
[
i
]
&&
selected
.
Count
<
max
&&
selected
.
IndexOf
(
card
)
<=
0
)
selected
.
Add
(
card
);
}
if
(
selected
.
Count
>=
max
)
break
;
}
}
/// <summary>
/// Check and fix selected to make sure it meet the count requirement.
/// </summary>
public
void
CheckSelectCount
(
IList
<
ClientCard
>
selected
,
IList
<
ClientCard
>
cards
,
int
min
,
int
max
)
{
if
(
selected
.
Count
<
min
)
{
foreach
(
ClientCard
card
in
cards
)
{
if
(!
selected
.
Contains
(
card
))
selected
.
Add
(
card
);
if
(
selected
.
Count
>=
max
)
break
;
}
}
while
(
selected
.
Count
>
max
)
{
selected
.
RemoveAt
(
selected
.
Count
-
1
);
}
}
}
}
\ No newline at end of file
Game/AI/Decks/BlueEyesExecutor.cs
View file @
f2f54c2a
...
...
@@ -132,7 +132,7 @@ namespace WindBot.Game.AI.Decks
SoulChargeUsed
=
false
;
}
public
override
IList
<
ClientCard
>
OnSelectCard
(
IList
<
ClientCard
>
cards
,
int
min
,
int
max
,
bool
cancelable
)
public
override
IList
<
ClientCard
>
OnSelectCard
(
IList
<
ClientCard
>
cards
,
int
min
,
int
max
,
int
hint
,
bool
cancelable
)
{
Logger
.
DebugWriteLine
(
"OnSelectCard "
+
cards
.
Count
+
" "
+
min
+
" "
+
max
);
if
(
max
==
2
&&
cards
[
0
].
Location
==
CardLocation
.
Deck
)
...
...
@@ -157,60 +157,26 @@ namespace WindBot.Game.AI.Decks
result
.
Add
(
card
);
}
}
if
(
result
.
Count
<
min
)
{
foreach
(
ClientCard
card
in
cards
)
{
if
(!
result
.
Contains
(
card
))
result
.
Add
(
card
);
if
(
result
.
Count
>=
min
)
break
;
}
}
while
(
result
.
Count
>
max
)
{
result
.
RemoveAt
(
result
.
Count
-
1
);
}
return
result
;
}
if
(
max
==
2
&&
min
==
2
&&
cards
[
0
].
Location
==
CardLocation
.
MonsterZone
)
{
Logger
.
DebugWriteLine
(
"OnSelectCard XYZ"
);
IList
<
ClientCard
>
avail
=
new
List
<
ClientCard
>();
foreach
(
ClientCard
card
in
cards
)
{
// clone
avail
.
Add
(
card
);
}
IList
<
ClientCard
>
result
=
new
List
<
ClientCard
>();
while
(
UsedAlternativeWhiteDragon
.
Count
>
0
&&
avail
.
IndexOf
(
UsedAlternativeWhiteDragon
[
0
])
>
0
)
{
Logger
.
DebugWriteLine
(
"select UsedAlternativeWhiteDragon"
);
ClientCard
card
=
UsedAlternativeWhiteDragon
[
0
];
UsedAlternativeWhiteDragon
.
Remove
(
card
);
avail
.
Remove
(
card
);
result
.
Add
(
card
);
}
if
(
result
.
Count
<
2
)
{
foreach
(
ClientCard
card
in
cards
)
{
if
(!
result
.
Contains
(
card
))
result
.
Add
(
card
);
if
(
result
.
Count
>=
2
)
break
;
}
}
AI
.
Utils
.
CheckSelectCount
(
result
,
cards
,
min
,
max
);
return
result
;
}
Logger
.
DebugWriteLine
(
"Use default."
);
return
null
;
}
public
override
IList
<
ClientCard
>
OnSelectSum
(
IList
<
ClientCard
>
cards
,
int
sum
,
int
min
,
int
max
,
bool
mode
)
public
override
IList
<
ClientCard
>
OnSelectXyzMaterial
(
IList
<
ClientCard
>
cards
,
int
min
,
int
max
)
{
Logger
.
DebugWriteLine
(
"OnSelectXyzMaterial "
+
cards
.
Count
+
" "
+
min
+
" "
+
max
);
IList
<
ClientCard
>
result
=
new
List
<
ClientCard
>();
AI
.
Utils
.
SelectPreferredCards
(
result
,
UsedAlternativeWhiteDragon
,
cards
,
min
,
max
);
AI
.
Utils
.
CheckSelectCount
(
result
,
cards
,
min
,
max
);
return
result
;
}
public
override
IList
<
ClientCard
>
OnSelectSynchroMaterial
(
IList
<
ClientCard
>
cards
,
int
sum
,
int
min
,
int
max
)
{
Logger
.
DebugWriteLine
(
"OnSelectS
um
"
+
cards
.
Count
+
" "
+
sum
+
" "
+
min
+
" "
+
max
);
if
(
sum
!=
8
||
!
mode
)
Logger
.
DebugWriteLine
(
"OnSelectS
ynchroMaterial
"
+
cards
.
Count
+
" "
+
sum
+
" "
+
min
+
" "
+
max
);
if
(
sum
!=
8
)
return
null
;
foreach
(
ClientCard
AlternativeWhiteDragon
in
UsedAlternativeWhiteDragon
)
...
...
Game/AI/Decks/DoEveryThingExecutor.cs
View file @
f2f54c2a
using
YGOSharp.OCGWrapper.Enums
;
using
System.Collections.Generic
;
using
WindBot
;
using
WindBot.Game
;
using
WindBot.Game.AI
;
namespace
WindBot.Game.AI.Decks
{
[
Deck
(
"Test"
,
"AI_Test"
,
"Test"
)]
public
class
DoEverythingExecutor
:
DefaultExecutor
{
public
class
CardId
{
public
const
int
LeoWizard
=
4392470
;
public
const
int
Bunilla
=
69380702
;
}
public
DoEverythingExecutor
(
GameAI
ai
,
Duel
duel
)
:
base
(
ai
,
duel
)
{
AddExecutor
(
ExecutorType
.
SpSummon
);
AddExecutor
(
ExecutorType
.
Activate
,
DefaultDontChainMyself
);
AddExecutor
(
ExecutorType
.
SummonOrSet
);
AddExecutor
(
ExecutorType
.
Repos
,
DefaultMonsterRepos
);
AddExecutor
(
ExecutorType
.
SpellSet
);
}
public
override
IList
<
ClientCard
>
OnSelectCard
(
IList
<
ClientCard
>
cards
,
int
min
,
int
max
,
bool
cancelable
)
{
if
(
Duel
.
Phase
==
DuelPhase
.
BattleStart
)
return
null
;
IList
<
ClientCard
>
selected
=
new
List
<
ClientCard
>();
// select the last cards
for
(
int
i
=
1
;
i
<=
max
;
++
i
)
selected
.
Add
(
cards
[
cards
.
Count
-
i
]);
return
selected
;
}
public
override
int
OnSelectOption
(
IList
<
int
>
options
)
{
return
Program
.
Rand
.
Next
(
options
.
Count
);
}
}
using
YGOSharp.OCGWrapper.Enums
;
using
System.Collections.Generic
;
using
WindBot
;
using
WindBot.Game
;
using
WindBot.Game.AI
;
namespace
WindBot.Game.AI.Decks
{
[
Deck
(
"Test"
,
"AI_Test"
,
"Test"
)]
public
class
DoEverythingExecutor
:
DefaultExecutor
{
public
class
CardId
{
public
const
int
LeoWizard
=
4392470
;
public
const
int
Bunilla
=
69380702
;
}
public
DoEverythingExecutor
(
GameAI
ai
,
Duel
duel
)
:
base
(
ai
,
duel
)
{
AddExecutor
(
ExecutorType
.
SpSummon
);
AddExecutor
(
ExecutorType
.
Activate
,
DefaultDontChainMyself
);
AddExecutor
(
ExecutorType
.
SummonOrSet
);
AddExecutor
(
ExecutorType
.
Repos
,
DefaultMonsterRepos
);
AddExecutor
(
ExecutorType
.
SpellSet
);
}
public
override
IList
<
ClientCard
>
OnSelectCard
(
IList
<
ClientCard
>
cards
,
int
min
,
int
max
,
int
hint
,
bool
cancelable
)
{
if
(
Duel
.
Phase
==
DuelPhase
.
BattleStart
)
return
null
;
IList
<
ClientCard
>
selected
=
new
List
<
ClientCard
>();
// select the last cards
for
(
int
i
=
1
;
i
<=
max
;
++
i
)
selected
.
Add
(
cards
[
cards
.
Count
-
i
]);
return
selected
;
}
public
override
int
OnSelectOption
(
IList
<
int
>
options
)
{
return
Program
.
Rand
.
Next
(
options
.
Count
);
}
}
}
\ No newline at end of file
Game/AI/Decks/LightswornExecutor.cs
View file @
f2f54c2a
...
...
@@ -103,39 +103,19 @@ namespace WindBot.Game.AI.Decks
return
base
.
OnPreBattleBetween
(
attacker
,
defender
);
}
public
override
IList
<
ClientCard
>
OnSelect
Card
(
IList
<
ClientCard
>
cards
,
int
min
,
int
max
,
bool
cancelable
)
public
override
IList
<
ClientCard
>
OnSelect
XyzMaterial
(
IList
<
ClientCard
>
cards
,
int
min
,
int
max
)
{
if
(
max
==
2
&&
min
==
2
&&
cards
[
0
].
Location
==
CardLocation
.
MonsterZone
)
Logger
.
DebugWriteLine
(
"OnSelectXyzMaterial "
+
cards
.
Count
+
" "
+
min
+
" "
+
max
);
IList
<
ClientCard
>
result
=
new
List
<
ClientCard
>();
foreach
(
ClientCard
card
in
cards
)
{
Logger
.
DebugWriteLine
(
"OnSelectCard XYZ"
);
IList
<
ClientCard
>
avail
=
new
List
<
ClientCard
>();
foreach
(
ClientCard
card
in
cards
)
{
// clone
avail
.
Add
(
card
);
}
IList
<
ClientCard
>
result
=
new
List
<
ClientCard
>();
foreach
(
ClientCard
card
in
cards
)
{
if
(!
result
.
Contains
(
card
)
&&
(!
ClownUsed
||
card
.
Id
!=
CardId
.
PerformageTrickClown
))
result
.
Add
(
card
);
if
(
result
.
Count
>=
2
)
break
;
}
if
(
result
.
Count
<
2
)
{
foreach
(
ClientCard
card
in
cards
)
{
if
(!
result
.
Contains
(
card
))
result
.
Add
(
card
);
if
(
result
.
Count
>=
2
)
break
;
}
}
return
result
;
if
(!
result
.
Contains
(
card
)
&&
(!
ClownUsed
||
card
.
Id
!=
CardId
.
PerformageTrickClown
))
result
.
Add
(
card
);
if
(
result
.
Count
>=
max
)
break
;
}
Logger
.
DebugWriteLine
(
"Use default."
);
return
null
;
AI
.
Utils
.
CheckSelectCount
(
result
,
cards
,
min
,
max
);
return
result
;
}
private
bool
ReinforcementOfTheArmyEffect
()
...
...
Game/AI/Decks/QliphortExecutor.cs
View file @
f2f54c2a
...
...
@@ -132,14 +132,10 @@ namespace WindBot.Game.AI.Decks
CardOfDemiseUsed
=
false
;
}
public
override
IList
<
ClientCard
>
OnSelect
Card
(
IList
<
ClientCard
>
cards
,
int
min
,
int
max
,
bool
cancelable
)
public
override
IList
<
ClientCard
>
OnSelect
PendulumSummon
(
IList
<
ClientCard
>
cards
,
int
max
)
{
if
(
max
<=
min
)
{
return
null
;
}
// pendulum summon, select the last cards
Logger
.
DebugWriteLine
(
"OnSelectPendulumSummon"
);
// select the last cards
IList
<
ClientCard
>
selected
=
new
List
<
ClientCard
>();
for
(
int
i
=
1
;
i
<=
max
;
++
i
)
...
...
Game/AI/Decks/RainbowExecutor.cs
View file @
f2f54c2a
This diff is collapsed.
Click to expand it.
Game/AI/Decks/Rank5Executor.cs
View file @
f2f54c2a
...
...
@@ -118,6 +118,19 @@ namespace WindBot.Game.AI.Decks
Number61VolcasaurusUsed
=
false
;
}
public
override
IList
<
ClientCard
>
OnSelectXyzMaterial
(
IList
<
ClientCard
>
cards
,
int
min
,
int
max
)
{
IList
<
ClientCard
>
result
=
new
List
<
ClientCard
>();
AI
.
Utils
.
SelectPreferredCards
(
result
,
new
[]
{
CardId
.
MistArchfiend
,
CardId
.
PanzerDragon
,
CardId
.
SolarWindJammer
,
CardId
.
StarDrawing
},
cards
,
min
,
max
);
AI
.
Utils
.
CheckSelectCount
(
result
,
cards
,
min
,
max
);
return
result
;
}
private
bool
NormalSummon
()
{
NormalSummoned
=
true
;
...
...
Game/AI/Decks/ToadallyAwesomeExecutor.cs
View file @
f2f54c2a
This diff is collapsed.
Click to expand it.
Game/AI/Decks/YosenjuExecutor.cs
View file @
f2f54c2a
This diff is collapsed.
Click to expand it.
Game/AI/Decks/ZexalWeaponsExecutor.cs
View file @
f2f54c2a
...
...
@@ -136,6 +136,18 @@ namespace WindBot.Game.AI.Decks
return
base
.
OnPreBattleBetween
(
attacker
,
defender
);
}
public
override
IList
<
ClientCard
>
OnSelectXyzMaterial
(
IList
<
ClientCard
>
cards
,
int
min
,
int
max
)
{
IList
<
ClientCard
>
result
=
new
List
<
ClientCard
>();
AI
.
Utils
.
SelectPreferredCards
(
result
,
new
[]
{
CardId
.
StarDrawing
,
CardId
.
SolarWindJammer
,
CardId
.
Goblindbergh
},
cards
,
min
,
max
);
AI
.
Utils
.
CheckSelectCount
(
result
,
cards
,
min
,
max
);
return
result
;
}
private
bool
Number39Utopia
()
{
if
(!
HasChainedTrap
(
0
)
&&
Duel
.
Player
==
1
&&
Duel
.
Phase
==
DuelPhase
.
BattleStart
&&
Card
.
HasXyzMaterial
(
2
))
...
...
@@ -271,7 +283,7 @@ namespace WindBot.Game.AI.Decks
private
bool
MonsterRepos
()
{
if
(
Card
.
Id
==
CardId
.
NumberS39UtopiatheLightning
)
if
(
Card
.
Id
==
CardId
.
NumberS39UtopiatheLightning
&&
Card
.
IsAttack
()
)
return
false
;
return
base
.
DefaultMonsterRepos
();
}
...
...
Game/AI/Decks/ZoodiacExecutor.cs
View file @
f2f54c2a
...
...
@@ -168,6 +168,12 @@ namespace WindBot.Game.AI.Decks
return
true
;
IList
<
ClientCard
>
materials0
=
Bot
.
Graveyard
;
IList
<
ClientCard
>
materials1
=
Enemy
.
Graveyard
;
IList
<
ClientCard
>
mats
=
new
List
<
ClientCard
>();
ClientCard
aleister
=
GetAleisterInGrave
();
if
(
aleister
!=
null
)
{
mats
.
Add
(
aleister
);
}
ClientCard
mat
=
null
;
foreach
(
ClientCard
card
in
materials0
)
{
...
...
@@ -187,9 +193,9 @@ namespace WindBot.Game.AI.Decks
}
if
(
mat
!=
null
)
{
mats
.
Add
(
mat
);
AI
.
SelectCard
(
CardId
.
InvokedMechaba
);
SelectAleisterInGrave
();
AI
.
SelectThirdCard
(
mat
);
AI
.
SelectMaterials
(
mats
);
AI
.
SelectPosition
(
CardPosition
.
FaceUpAttack
);
return
true
;
}
...
...
@@ -211,41 +217,39 @@ namespace WindBot.Game.AI.Decks
}
if
(
mat
!=
null
)
{
mats
.
Add
(
mat
);
AI
.
SelectCard
(
CardId
.
InvokedMagellanica
);
SelectAleisterInGrave
();
AI
.
SelectThirdCard
(
mat
);
AI
.
SelectMaterials
(
mats
);
AI
.
SelectPosition
(
CardPosition
.
FaceUpAttack
);
return
true
;
}
return
false
;
}
private
void
Selec
tAleisterInGrave
()
private
ClientCard
Ge
tAleisterInGrave
()
{
foreach
(
ClientCard
card
in
Enemy
.
Graveyard
)
{
if
(
card
.
Id
==
CardId
.
AleisterTheInvoker
)
{
AI
.
SelectNextCard
(
card
);
return
;
return
card
;
}
}
foreach
(
ClientCard
card
in
Bot
.
Graveyard
)
{
if
(
card
.
Id
==
CardId
.
AleisterTheInvoker
)
{
AI
.
SelectNextCard
(
card
);
return
;
return
card
;
}
}
AI
.
SelectNextCard
(
CardId
.
AleisterTheInvoker
)
;
return
null
;
}
private
bool
ChakanineSummon
()
{
if
(
Bot
.
HasInMonstersZone
(
CardId
.
Ratpier
)
&&
!
ChakanineSpsummoned
)
{
AI
.
Select
Card
(
CardId
.
Ratpier
);
AI
.
Select
Materials
(
CardId
.
Ratpier
);
AI
.
SelectYesNo
(
true
);
AI
.
SelectPosition
(
CardPosition
.
FaceUpDefence
);
ChakanineSpsummoned
=
true
;
...
...
@@ -253,7 +257,7 @@ namespace WindBot.Game.AI.Decks
}
if
(
Bot
.
HasInMonstersZone
(
CardId
.
Broadbull
)
&&
!
ChakanineSpsummoned
)
{
AI
.
Select
Card
(
CardId
.
Broadbull
);
AI
.
Select
Materials
(
CardId
.
Broadbull
);
AI
.
SelectYesNo
(
true
);
AI
.
SelectPosition
(
CardPosition
.
FaceUpDefence
);
ChakanineSpsummoned
=
true
;
...
...
@@ -289,7 +293,7 @@ namespace WindBot.Game.AI.Decks
{
if
(
Bot
.
HasInMonstersZone
(
CardId
.
Chakanine
)
&&
!
TigermortarSpsummoned
)
{
AI
.
Select
Card
(
CardId
.
Chakanine
);
AI
.
Select
Materials
(
CardId
.
Chakanine
);
AI
.
SelectYesNo
(
true
);
AI
.
SelectPosition
(
CardPosition
.
FaceUpDefence
);
TigermortarSpsummoned
=
true
;
...
...
@@ -297,7 +301,7 @@ namespace WindBot.Game.AI.Decks
}
if
(
Bot
.
HasInMonstersZone
(
CardId
.
Ratpier
)
&&
!
TigermortarSpsummoned
)
{
AI
.
Select
Card
(
CardId
.
Ratpier
);
AI
.
Select
Materials
(
CardId
.
Ratpier
);
AI
.
SelectYesNo
(
true
);
AI
.
SelectPosition
(
CardPosition
.
FaceUpDefence
);
TigermortarSpsummoned
=
true
;
...
...
@@ -310,7 +314,7 @@ namespace WindBot.Game.AI.Decks
CardId
.
Ratpier
}))
{
AI
.
Select
Card
(
CardId
.
Thoroughblade
);
AI
.
Select
Materials
(
CardId
.
Thoroughblade
);
AI
.
SelectYesNo
(
true
);
TigermortarSpsummoned
=
true
;
return
true
;
...
...
@@ -318,7 +322,7 @@ namespace WindBot.Game.AI.Decks
if
(
Bot
.
HasInMonstersZone
(
CardId
.
Whiptail
)
&&
!
TigermortarSpsummoned
&&
Bot
.
HasInGraveyard
(
CardId
.
Ratpier
))
{
AI
.
Select
Card
(
CardId
.
Whiptail
);
AI
.
Select
Materials
(
CardId
.
Whiptail
);
AI
.
SelectYesNo
(
true
);
TigermortarSpsummoned
=
true
;
return
true
;
...
...
@@ -345,7 +349,7 @@ namespace WindBot.Game.AI.Decks
{
if
(
Bot
.
HasInMonstersZone
(
CardId
.
Tigermortar
)
&&
!
BroadbullSpsummoned
)
{
AI
.
Select
Card
(
CardId
.
Tigermortar
);
AI
.
Select
Materials
(
CardId
.
Tigermortar
);
AI
.
SelectYesNo
(
true
);
AI
.
SelectPosition
(
CardPosition
.
FaceUpDefence
);
BroadbullSpsummoned
=
true
;
...
...
@@ -353,7 +357,7 @@ namespace WindBot.Game.AI.Decks
}
if
(
Bot
.
HasInMonstersZone
(
CardId
.
Chakanine
)
&&
!
BroadbullSpsummoned
)
{
AI
.
Select
Card
(
CardId
.
Chakanine
);
AI
.
Select
Materials
(
CardId
.
Chakanine
);
AI
.
SelectYesNo
(
true
);
AI
.
SelectPosition
(
CardPosition
.
FaceUpDefence
);
BroadbullSpsummoned
=
true
;
...
...
@@ -361,7 +365,7 @@ namespace WindBot.Game.AI.Decks
}
if
(
Bot
.
HasInMonstersZone
(
CardId
.
Ratpier
)
&&
!
BroadbullSpsummoned
)
{
AI
.
Select
Card
(
CardId
.
Ratpier
);
AI
.
Select
Materials
(
CardId
.
Ratpier
);
AI
.
SelectYesNo
(
true
);
AI
.
SelectPosition
(
CardPosition
.
FaceUpDefence
);
BroadbullSpsummoned
=
true
;
...
...
@@ -369,7 +373,7 @@ namespace WindBot.Game.AI.Decks
}
if
(
Bot
.
HasInMonstersZone
(
CardId
.
Thoroughblade
)
&&
!
BroadbullSpsummoned
)
{
AI
.
Select
Card
(
CardId
.
Thoroughblade
);
AI
.
Select
Materials
(
CardId
.
Thoroughblade
);
AI
.
SelectYesNo
(
true
);
AI
.
SelectPosition
(
CardPosition
.
FaceUpDefence
);
BroadbullSpsummoned
=
true
;
...
...
@@ -399,7 +403,7 @@ namespace WindBot.Game.AI.Decks
{
AI
.
SelectYesNo
(
false
);
AI
.
SelectPosition
(
CardPosition
.
FaceUpDefence
);
AI
.
Select
Card
(
new
[]
AI
.
Select
Materials
(
new
[]
{
CardId
.
Ratpier
,
CardId
.
PhotonThrasher
,
...
...
@@ -411,7 +415,7 @@ namespace WindBot.Game.AI.Decks
private
bool
DridentSummon
()
{
AI
.
Select
Card
(
new
[]
AI
.
Select
Materials
(
new
[]
{
CardId
.
Broadbull
,
CardId
.
Tigermortar
,
...
...
@@ -502,6 +506,11 @@ namespace WindBot.Game.AI.Decks
private
bool
DaigustoEmeralSummon
()
{
AI
.
SelectMaterials
(
new
[]
{
CardId
.
PhotonThrasher
,
CardId
.
AleisterTheInvoker
});
return
Bot
.
GetGraveyardMonsters
().
Count
>=
3
;
}
...
...
@@ -595,7 +604,7 @@ namespace WindBot.Game.AI.Decks
private
bool
MonsterRepos
()
{
if
(
Card
.
Id
==
CardId
.
NumberS39UtopiatheLightning
)
if
(
Card
.
Id
==
CardId
.
NumberS39UtopiatheLightning
&&
Card
.
IsAttack
()
)
return
false
;
return
base
.
DefaultMonsterRepos
();
}
...
...
Game/AI/DefaultExecutor.cs
View file @
f2f54c2a
...
...
@@ -58,10 +58,10 @@ namespace WindBot.Game.AI
if
(
defender
.
IsMonsterDangerous
()
||
(
defender
.
IsMonsterInvincible
()
&&
defender
.
IsDefense
()))
return
false
;
if
(
defender
.
Id
==
_CardId
.
CrystalWingSynchroDragon
&&
!
defender
.
IsDisabled
()
&&
attacker
.
Level
>=
5
)
if
(
defender
.
Id
==
_CardId
.
CrystalWingSynchroDragon
&&
defender
.
IsAttack
()
&&
!
defender
.
IsDisabled
()
&&
attacker
.
Level
>=
5
)
return
false
;
if
(
defender
.
Id
==
_CardId
.
NumberS39UtopiaTheLightning
&&
!
defender
.
IsDisabled
()
&&
defender
.
HasXyzMaterial
(
2
,
_CardId
.
Number39Utopia
))
if
(
defender
.
Id
==
_CardId
.
NumberS39UtopiaTheLightning
&&
defender
.
IsAttack
()
&&
!
defender
.
IsDisabled
()
&&
defender
.
HasXyzMaterial
(
2
,
_CardId
.
Number39Utopia
))
defender
.
RealPower
=
5000
;
}
...
...
Game/AI/Executor.cs
View file @
f2f54c2a
...
...
@@ -124,13 +124,49 @@ namespace WindBot.Game.AI
// Some AI need do something on new turn
}
public
virtual
IList
<
ClientCard
>
OnSelectCard
(
IList
<
ClientCard
>
cards
,
int
min
,
int
max
,
bool
cancelable
)
public
virtual
IList
<
ClientCard
>
OnSelectCard
(
IList
<
ClientCard
>
cards
,
int
min
,
int
max
,
int
hint
,
bool
cancelable
)
{
// For overriding
return
null
;
}
public
virtual
IList
<
ClientCard
>
OnSelectSum
(
IList
<
ClientCard
>
cards
,
int
sum
,
int
min
,
int
max
,
bool
mode
)
public
virtual
IList
<
ClientCard
>
OnSelectSum
(
IList
<
ClientCard
>
cards
,
int
sum
,
int
min
,
int
max
,
int
hint
,
bool
mode
)
{
// For overriding
return
null
;
}
public
virtual
IList
<
ClientCard
>
OnSelectFusionMaterial
(
IList
<
ClientCard
>
cards
,
int
min
,
int
max
)
{
// For overriding
return
null
;
}
public
virtual
IList
<
ClientCard
>
OnSelectSynchroMaterial
(
IList
<
ClientCard
>
cards
,
int
sum
,
int
min
,
int
max
)
{
// For overriding
return
null
;
}
public
virtual
IList
<
ClientCard
>
OnSelectXyzMaterial
(
IList
<
ClientCard
>
cards
,
int
min
,
int
max
)
{
// For overriding
return
null
;
}
public
virtual
IList
<
ClientCard
>
OnSelectLinkMaterial
(
IList
<
ClientCard
>
cards
,
int
min
,
int
max
)
{
// For overriding
return
null
;
}
public
virtual
IList
<
ClientCard
>
OnSelectRitualTribute
(
IList
<
ClientCard
>
cards
,
int
sum
,
int
min
,
int
max
)
{
// For overriding
return
null
;
}
public
virtual
IList
<
ClientCard
>
OnSelectPendulumSummon
(
IList
<
ClientCard
>
cards
,
int
max
)
{
// For overriding
return
null
;
...
...
Game/GameAI.cs
View file @
f2f54c2a
...
...
@@ -85,6 +85,8 @@ namespace WindBot.Game
{
m_selector
=
null
;
m_nextSelector
=
null
;
m_thirdSelector
=
null
;
m_materialSelector
=
null
;
m_option
=
-
1
;
m_yesno
=
-
1
;
m_position
=
CardPosition
.
FaceUpAttack
;
...
...
@@ -158,17 +160,60 @@ namespace WindBot.Game
/// <param name="cards">List of available cards.</param>
/// <param name="min">Minimal quantity.</param>
/// <param name="max">Maximal quantity.</param>
/// <param name="hint">The hint message of the select.</param>
/// <param name="cancelable">True if you can return an empty list.</param>
/// <returns>A new list containing the selected cards.</returns>
public
IList
<
ClientCard
>
OnSelectCard
(
IList
<
ClientCard
>
cards
,
int
min
,
int
max
,
bool
cancelable
)
public
IList
<
ClientCard
>
OnSelectCard
(
IList
<
ClientCard
>
cards
,
int
min
,
int
max
,
int
hint
,
bool
cancelable
)
{
const
int
HINTMSG_FMATERIAL
=
511
;
const
int
HINTMSG_SMATERIAL
=
512
;
const
int
HINTMSG_XMATERIAL
=
513
;
const
int
HINTMSG_LMATERIAL
=
533
;
const
int
HINTMSG_SPSUMMON
=
509
;
// Check for the executor.
IList
<
ClientCard
>
result
=
Executor
.
OnSelectCard
(
cards
,
min
,
max
,
cancelable
);
IList
<
ClientCard
>
result
=
Executor
.
OnSelectCard
(
cards
,
min
,
max
,
hint
,
cancelable
);
if
(
result
!=
null
)
return
result
;
// Update the next selector.
CardSelector
selector
=
GetSelectedCards
();
if
(
hint
==
HINTMSG_SPSUMMON
&&
min
==
1
&&
max
>
min
)
// pendulum summon
{
result
=
Executor
.
OnSelectPendulumSummon
(
cards
,
max
);
if
(
result
!=
null
)
return
result
;
}
CardSelector
selector
=
null
;
if
(
hint
==
HINTMSG_FMATERIAL
||
hint
==
HINTMSG_SMATERIAL
||
hint
==
HINTMSG_XMATERIAL
||
hint
==
HINTMSG_LMATERIAL
)
{
if
(
m_materialSelector
!=
null
)
{
//Logger.DebugWriteLine("m_materialSelector");
selector
=
m_materialSelector
;
}
else
{
if
(
hint
==
HINTMSG_FMATERIAL
)
result
=
Executor
.
OnSelectFusionMaterial
(
cards
,
min
,
max
);
if
(
hint
==
HINTMSG_SMATERIAL
)
result
=
Executor
.
OnSelectSynchroMaterial
(
cards
,
0
,
min
,
max
);
if
(
hint
==
HINTMSG_XMATERIAL
)
result
=
Executor
.
OnSelectXyzMaterial
(
cards
,
min
,
max
);
if
(
hint
==
HINTMSG_LMATERIAL
)
result
=
Executor
.
OnSelectLinkMaterial
(
cards
,
min
,
max
);
if
(
result
!=
null
)
return
result
;
// Update the next selector.
selector
=
GetSelectedCards
();
}
}
else
{
// Update the next selector.
selector
=
GetSelectedCards
();
}
// If we selected a card, use this card.
if
(
selector
!=
null
)
...
...
@@ -373,14 +418,45 @@ namespace WindBot.Game
/// <param name="max">Maximum cards.</param>
/// <param name="mode">True for exact equal.</param>
/// <returns></returns>
public
IList
<
ClientCard
>
OnSelectSum
(
IList
<
ClientCard
>
cards
,
int
sum
,
int
min
,
int
max
,
bool
mode
)
public
IList
<
ClientCard
>
OnSelectSum
(
IList
<
ClientCard
>
cards
,
int
sum
,
int
min
,
int
max
,
int
hint
,
bool
mode
)
{
IList
<
ClientCard
>
selected
=
Executor
.
OnSelectSum
(
cards
,
sum
,
min
,
max
,
mode
);
const
int
HINTMSG_RELEASE
=
500
;
const
int
HINTMSG_SMATERIAL
=
512
;
IList
<
ClientCard
>
selected
=
Executor
.
OnSelectSum
(
cards
,
sum
,
min
,
max
,
hint
,
mode
);
if
(
selected
!=
null
)
{
return
selected
;
}
if
(
hint
==
HINTMSG_RELEASE
||
hint
==
HINTMSG_SMATERIAL
)
{
if
(
m_materialSelector
!=
null
)
{
selected
=
m_materialSelector
.
Select
(
cards
,
min
,
max
);
}
else
{
if
(
hint
==
HINTMSG_SMATERIAL
)
selected
=
Executor
.
OnSelectSynchroMaterial
(
cards
,
sum
,
min
,
max
);
if
(
hint
==
HINTMSG_RELEASE
)
selected
=
Executor
.
OnSelectRitualTribute
(
cards
,
sum
,
min
,
max
);
}
if
(
selected
!=
null
)
{
int
s1
=
0
,
s2
=
0
;
foreach
(
ClientCard
card
in
selected
)
{
s1
+=
card
.
OpParam1
;
s2
+=
(
card
.
OpParam2
!=
0
)
?
card
.
OpParam2
:
card
.
OpParam1
;
}
if
((
mode
&&
(
s1
==
sum
||
s2
==
sum
))
||
(!
mode
&&
(
s1
>=
sum
||
s2
>=
sum
)))
{
return
selected
;
}
}
}
if
(
mode
)
{
// equal
...
...
@@ -497,9 +573,10 @@ namespace WindBot.Game
/// <param name="cards">List of available cards.</param>
/// <param name="min">Minimal quantity.</param>
/// <param name="max">Maximal quantity.</param>
/// <param name="hint">The hint message of the select.</param>
/// <param name="cancelable">True if you can return an empty list.</param>
/// <returns>A new list containing the tributed cards.</returns>
public
IList
<
ClientCard
>
OnSelectTribute
(
IList
<
ClientCard
>
cards
,
int
min
,
int
max
,
bool
cancelable
)
public
IList
<
ClientCard
>
OnSelectTribute
(
IList
<
ClientCard
>
cards
,
int
min
,
int
max
,
int
hint
,
bool
cancelable
)
{
// Always choose the minimum and lowest atk.
List
<
ClientCard
>
sorted
=
new
List
<
ClientCard
>();
...
...
@@ -543,6 +620,7 @@ namespace WindBot.Game
private
CardSelector
m_selector
;
private
CardSelector
m_nextSelector
;
private
CardSelector
m_thirdSelector
;
private
CardSelector
m_materialSelector
;
private
CardPosition
m_position
=
CardPosition
.
FaceUpAttack
;
private
int
m_option
;
private
int
m_number
;
...
...
@@ -626,6 +704,36 @@ namespace WindBot.Game
m_thirdSelector
=
new
CardSelector
(
loc
);
}
public
void
SelectMaterials
(
ClientCard
card
)
{
m_materialSelector
=
new
CardSelector
(
card
);
}
public
void
SelectMaterials
(
IList
<
ClientCard
>
cards
)
{
m_materialSelector
=
new
CardSelector
(
cards
);
}
public
void
SelectMaterials
(
int
cardId
)
{
m_materialSelector
=
new
CardSelector
(
cardId
);
}
public
void
SelectMaterials
(
IList
<
int
>
ids
)
{
m_materialSelector
=
new
CardSelector
(
ids
);
}
public
void
SelectMaterials
(
CardLocation
loc
)
{
m_materialSelector
=
new
CardSelector
(
loc
);
}
public
void
CleanSelectMaterials
()
{
m_materialSelector
=
null
;
}
public
CardSelector
GetSelectedCards
()
{
CardSelector
selected
=
m_selector
;
...
...
Game/GameBehavior.cs
View file @
f2f54c2a
...
...
@@ -25,6 +25,7 @@ namespace WindBot.Game
private
Room
_room
;
private
Duel
_duel
;
private
int
_hand
;
private
int
_select_hint
;
public
GameBehavior
(
GameClient
game
)
{
...
...
@@ -42,6 +43,8 @@ namespace WindBot.Game
_ai
=
new
GameAI
(
Game
,
_duel
);
_ai
.
Executor
=
DecksManager
.
Instantiate
(
_ai
,
_duel
);
Deck
=
Deck
.
Load
(
_ai
.
Executor
.
Deck
);
_select_hint
=
0
;
}
public
int
GetLocalPlayer
(
int
player
)
...
...
@@ -80,6 +83,7 @@ namespace WindBot.Game
_messages
.
Add
(
GameMessage
.
Retry
,
OnRetry
);
_messages
.
Add
(
GameMessage
.
Start
,
OnStart
);
_messages
.
Add
(
GameMessage
.
Hint
,
OnHint
);
_messages
.
Add
(
GameMessage
.
Win
,
OnWin
);
_messages
.
Add
(
GameMessage
.
Draw
,
OnDraw
);
_messages
.
Add
(
GameMessage
.
ShuffleDeck
,
OnShuffleDeck
);
...
...
@@ -120,6 +124,9 @@ namespace WindBot.Game
_messages
.
Add
(
GameMessage
.
AnnounceRace
,
OnAnnounceRace
);
_messages
.
Add
(
GameMessage
.
AnnounceCardFilter
,
OnAnnounceCard
);
_messages
.
Add
(
GameMessage
.
RockPaperScissors
,
OnRockPaperScissors
);
_messages
.
Add
(
GameMessage
.
SpSummoning
,
OnSpSummon
);
_messages
.
Add
(
GameMessage
.
SpSummoned
,
OnSpSummon
);
}
private
void
OnJoinGame
(
BinaryReader
packet
)
...
...
@@ -295,6 +302,17 @@ namespace WindBot.Game
throw
new
Exception
(
"Got MSG_RETRY."
);
}
private
void
OnHint
(
BinaryReader
packet
)
{
int
type
=
packet
.
ReadByte
();
int
player
=
packet
.
ReadByte
();
int
data
=
packet
.
ReadInt32
();
if
(
type
==
3
)
// HINT_SELECTMSG
{
_select_hint
=
data
;
}
}
private
void
OnStart
(
BinaryReader
packet
)
{
int
type
=
packet
.
ReadByte
();
...
...
@@ -643,7 +661,7 @@ namespace WindBot.Game
Connection
.
Send
(
CtosMessage
.
Response
,
_ai
.
OnSelectBattleCmd
(
battle
).
ToValue
());
}
private
void
InternalOnSelectCard
(
BinaryReader
packet
,
Func
<
IList
<
ClientCard
>,
int
,
int
,
bool
,
IList
<
ClientCard
>>
func
)
private
void
InternalOnSelectCard
(
BinaryReader
packet
,
Func
<
IList
<
ClientCard
>,
int
,
int
,
int
,
bool
,
IList
<
ClientCard
>>
func
)
{
packet
.
ReadByte
();
// player
bool
cancelable
=
packet
.
ReadByte
()
!=
0
;
...
...
@@ -670,7 +688,8 @@ namespace WindBot.Game
cards
.
Add
(
card
);
}
IList
<
ClientCard
>
selected
=
func
(
cards
,
min
,
max
,
cancelable
);
IList
<
ClientCard
>
selected
=
func
(
cards
,
min
,
max
,
_select_hint
,
cancelable
);
_select_hint
=
0
;
if
(
selected
.
Count
==
0
&&
cancelable
)
{
...
...
@@ -1027,7 +1046,8 @@ namespace WindBot.Game
sumval
-=
mandatoryCards
[
k
].
OpParam1
;
}
IList
<
ClientCard
>
selected
=
_ai
.
OnSelectSum
(
cards
,
sumval
,
min
,
max
,
mode
);
IList
<
ClientCard
>
selected
=
_ai
.
OnSelectSum
(
cards
,
sumval
,
min
,
max
,
_select_hint
,
mode
);
_select_hint
=
0
;
byte
[]
result
=
new
byte
[
mandatoryCards
.
Count
+
selected
.
Count
+
1
];
int
index
=
0
;
...
...
@@ -1125,5 +1145,10 @@ namespace WindBot.Game
result
=
_ai
.
OnRockPaperScissors
();
Connection
.
Send
(
CtosMessage
.
Response
,
result
);
}
private
void
OnSpSummon
(
BinaryReader
packet
)
{
_ai
.
CleanSelectMaterials
();
}
}
}
\ No newline at end of file
README.md
View file @
f2f54c2a
...
...
@@ -111,6 +111,40 @@ The parameters are same as commandlines, but low cased.
*
If one chain includes two activation that use
`AI.SelectCard`
, the second one won't select correctly.
### Changelog
#### v0x1340 (2017-11-06)
-
Update YGOPro protrol to 0x1340
-
Add support for the New Master Rule
-
Decks update
-
New commandline parameters
-
Add support for Match and TAG duel
-
Add server mode
-
Bot dialogs now customable
-
Only use normal deck when random picking decks
-
Send sorry when the AI did something wrong that make the duel can't continue (for example, selected illegal card)
-
Send info when the deck of the AI is illegal (for example, lflist dismatch)
-
Fix the issue that the bot will attack _Dupe Frog_ with low attack monster when there is monster next to _Dupe Frog_
-
Fix the issue that synchro summon stuck in some condition
[
\#7
](
https://github.com/IceYGO/windbot/issues/7
)
-
Fix C#6.0 (VS2015) support
-
Fix
`OnUpdateData`
-
New and updated
`DefaultExecutor`
-
New and updated
`AI.Utils`
,
`ClientCard`
,
`ClientField`
functions
-
Add
`OnNewTurn`
,
`AI.SelectYesNo`
,
`AI.SelectThirdCard`
,
`Duel.ChainTargets`
,
`Duel.LastSummonPlayer`
-
Shortcut
`Bot`
for
`Duel.Fields[0]`
,
`Enemy`
for
`Duel.Fields[1]`
-
`CardId`
is now class instead of enum so
`(int)`
is no longer needed
-
Update the known card enums, add
`Floodgate`
,
`OneForXyz`
,
`FusionSpell`
,
`MonsterHasPreventActivationEffectInBattle`
-
Update
`OnPreBattleBetween`
to calculate the ATK of cards like _Number S39: Utopia the Lightning_
-
Update direct attack handling
#### v0x133D (2017-09-24)
-
Update YGOPro protrol to 0x133D
-
Use the latest YGOSharp.Network to improve performances
-
Update the namespace of
`YGOSharp.OCGWrapper`
-
Fix the default trap cards not always activating
### TODO list
*
More decks
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment