Yugioh-For-HoloLens
Yugioh-For-HoloLens copied to clipboard
Creating a instruction set for gameplay
I figured that running a list of if and else statements for effects would not be practical. A better way would be to include an instruction set that can be parsed and executed on runtime, The instruction set would be a stack that generalizes the effects so they can be chained. Literals would be enumerators for instance PLAYER could represent the number 32 or something like that.
<card>
<name>Dark Hole</name>
<type>Spell</type>
<id>123</id>
<property>Normal</property>
<actions>
PLAYER
1
DESTROY
MONSTERS
ALL
PLAYER
2
DESTROY
MONSTERS
ALL
</actions>
</card>
<card>
<name>Ookazi</name>
<type>Spell</type>
<id>122</id>
<property>normal</property>
<actions>
PLAYER
1
DAMAGE
800
LIFEPOINTS
</actions>
</card>
<card>
<name>Invigoration</name>
<type>Equip</type>
<id>121</id>
<property>normal</property>
<actions>
PLAYER
0
CARD
MONSTER
EARTH
NULL
INCREASE
200
ATK
DECREASE
400
DEF
</actions>
</card>
switch(instruction){
case PLAYER:
player = stack.pop()
break;
case DESTROY
type = stack.pop();
number = stack.pop();
break;
destroy(player, type, number);
case DAMAGE:
amount = stack.pop();
type = stack.pop();
damage(player,amount, destroy)
break;
case INCREASE:
amount = stack.pop();
type = stack.pop();
increase(amount, type, player, card)
break;
case DECREASE:
amount = stack.pop();
type = stack.pop();
decrease(amount, type, player, card)
case CARD:
card = new Card();
Card.type = stack.pop();
Card.atr = stack.pop();
Card.subtype = stack.pop();
break;
}
I wanted to hear your thoughts before I attempt to implement this.
Functionality has already been implemented for first ~100 cards. Might be useful if we ever get more than 100 cards, but since we haven't been able to get the first ~100 models yet practicality on card effects is least of our problems. Look at @bnm12 's branch. He is doing something like this.
I like your thinking, and I'm thinking about doing something similar, I've noticed by flipping some wiki pages that some of the effects have quite advanced conditions or events, and a lot of them are 'one-offs' in the sense that the similar cards have key differences in their behaviors. This unfortunately makes it hard to implement all behaviors using defined keywords unless we spend a very long time defining all the keywords and actions for those keywords, and then maybe only having one card using that specific keyword.
What I'm thinking about but haven't gotten around to implementing yet is leveraging the Roselyn compiler to runtime compile C# inheriting from a certain class which defines cards and has event handlers for e.g. OnTurnEnd, OnAttack, OnMonsterSummon, OnAcctivate etc. and then provide the game manager object to the card and letting the card implement it's own actions, or hell just precompiling them all. We could then implement some of the most used shared actions e.g. SubtractLifePoints and those things (though most of the common ones should already be in the game manager). Doing this avoids us having to do double work implementing all the common actions and allows us to implement the 'one-offs' as just that instead of trying to shoehorn them into some common action and thus limiting their effects artificially. And it doesn't require learning a new 'language' based on a stack or something to implement new cards, but C# which can be written in VS with intellisense and using robust methods which is already used by the rest of the code, making it more testable and reducing code duplication along with making it quick and easy for anyone familiar with the source code to add new cards and not impossible, or even too hard for new people to implement cards if they know C#.
I'm open to input, but these are my thoughts at the moment
This sounds like a much better idea then mind. I will look into the Roselyn compiler.
Here's a place to get started that I bookmarked when I looked at it last:
http://stackoverflow.com/a/29417053
@bnm12 So I checked out the link and it was great help in demonstrating how Roslyn can be used. I was able to create a sample project that would take an object instance and used that to manipulate data generated from code built onruntime.
//Program.cs
String line = readFile();
Manager manage = new Manager();
manage.x = 2;
manage.y = 3;
SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(line);
string assemblyName = Path.GetRandomFileName();
Compiler compile = new Compiler(assemblyName, syntaxTree, manage);
using (var ms = new MemoryStream())
{
try
{
compile.invokeMethod(ms, "Operator", "add", new object[] { manage, 2 });
Console.WriteLine("The actual value is " + (int)compile.returnValue + " and the expected value is 7");
} catch (Exception e)
{
Console.WriteLine("The file could not be assembled");
Console.WriteLine(e.Message);
}
}
//TextFile.txt
using System;
using RoslynCompileSample;
public class Operator
{public static int add(Manager manager,int z)
{return manager.x*manager.y+z;}}
Unfortunately I discovered that Micrsoft.CodeAnalysis is not supported for UAP/UWP. I know we can't use .dll
files to reference a library file so I am bit stuck. I will look into if there are any runtime compilers that is supported for UWP but it doesn't seem likely.
EDIT: 1/29.
I looked into other alternatives and it seems that we could use Lua. Lua is used in Yugioh Pro, a yugioh card game platform. I am going to look into how we can use it. Here are some of the repos that I am looking at.
https://github.com/soarqin/ygopro
https://github.com/Fluorohydride/ygopro-core