Generalkidd / Yugioh-For-HoloLens

The popular card game Yugioh, now a reality!
Mozilla Public License 2.0
91 stars 26 forks source link

Creating a instruction set for gameplay #4

Open Aerex opened 7 years ago

Aerex commented 7 years ago

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.

SethKitchen commented 7 years ago

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.

bnm12 commented 7 years ago

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

Aerex commented 7 years ago

This sounds like a much better idea then mind. I will look into the Roselyn compiler.

bnm12 commented 7 years ago

Here's a place to get started that I bookmarked when I looked at it last:

http://stackoverflow.com/a/29417053

Aerex commented 7 years ago

@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