Skip to content

Instantly share code, notes, and snippets.

@IngwiePhoenix
Created April 5, 2020 07:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save IngwiePhoenix/9888e5945a45c13bb4df3d9738a6378c to your computer and use it in GitHub Desktop.
Save IngwiePhoenix/9888e5945a45c13bb4df3d9738a6378c to your computer and use it in GitHub Desktop.
Concept: Open-Source implementation of "Cardfight!! Vanguard Online"

In 2014, I first came into contact with the "Cardfight!! Vanguard" TCG and I was introduced to it while I was at my hights as a professional Yu-Gi-Oh player, playing at several turnaments and usually coming out at the upper third of the turnaments - not always the top 10 on bigger turnaments but about 3rd out of 22 in average at local events, with my highest official turnament placing being 129th at a YCS in Leipzig. I could've gone higher but fell asleep during the break and woke up way too late to make it to my game, and even had to clarify that I did not drop...kinda embarressing really but happens after playing 7h+ of competitive turnaments - with a visual impairment (almost blind, left eye 20% and right eye ~3%) which meant a lot of additional brainwork since I had to memorize all the common cards at the time since I couldn't just read them off the card as needed. One way, in which I had prepared for this was to use (unlicensed, non-endorsed) Yu-Gi-Oh simulators such as Dueling Network and YGOPro (Percy at that time).

So, when I first got in contact with Vanguard, my first question was, if I could play it online to pick out the cards I would actually want to play in turnaments and the like...and back then, rumors of a Vanguard Online were going around, and I feel like I even remember a beta version circling around as well. This was, obviously, way before it was officially canceled and thus no longer continued.

Now, thanks to the current Corona pandemic going around, I was about to fold my backlog in anime. One of the entries was, to finish the entirity of the Vanguard anime. So, for the last week, I quite literally burnt through "Cardfight!! Vanguard G", whilst having watched the original anime back when it was first aired. I seem to recall watching it on Youtube as well, but apparently the original episodes have been taken off Youtube by now, and I might have used another website to watch it anyway. But, what I noticed is, that even during the original Vanguard, there were a few instances shown, where players were obviously using a simulator to play the game with others instead of using physical cards. Even in the G-series.

Since I have a background in programming in PHP, JavaScript and C++ for server-side applications, it got me thinking - and soon, a small brainchild, a concept, was born in the back of my head. Unfortunately, due to my visual impairment, working with graphics is vastly difficult for me - and I would even call it impossible, since also my color-accuracy is off by quite a large margin, which is in part due to my glasses filtering out and distorting my view a little, which has to do with them being about as thick as my thumb, if not even bigger. I use perscription lenses with a rating of +23/-0,3 on both eyes. So, instead of trying to source developers that could possibly do this, I decided to post my entire concept online and see what comes from it. All that I would be good at is implementing the backend - and that is quite possibly it :)

Concent: Open Source Cardfight!! Vanguard Online

In the following concept, I am going to go over several aspects of a Vanguard TCG simulator that I have thought of whilst watching the anime and also in relation to libocgcore, the very core of what drives YGOPro and it's several forks. Even more modern interfaces to it, like YGO Omega or YGOPro2, still use libocgcore as a backend. It is sometimes also refered to as just OCGCore, but as it is often used as a library to implement the game's mechanics, I tend to prefix it with lib to treat it in the usecase it is most oftenly found as.

This concept does not have any license. It is merely an idea I am throwing out there - so feel free to do with this as you wish. You may treat it as CC-BY 3.0 at the most - I do like having my credit spelled out where it's due, obviously :)

I also want to prove a point: That Bushiroad was, in my view, too lazy. It is certainly possible, and it can be done with the right set of developers. For a big company like Bushiroad, it shouldn't have been an issue implementing it - so, I want to showcase what is possible, how, and what would be needed. As I do not know how graphical development (3D objects, environments, etc.) scale in time, I can't judge that very well though.

Key ingredients

For any card game simulator, that is specific to one game instead of many, like Tabletop Simulator, there are a few key ingredients that such a simulator would need:

  • The game mechanics (core providing the framework for the cards)
  • A database of card implementations (code representing the workings of an effect)
  • A database of cards (artworks, effect texts, ...)
  • An interface (to communicate with either a local or remote core to trigger and emit events, such as placing cards or showing animations unpon changes in the game state)

Each of those key ingredients may be represented as modules - and by doing so, it would be possible to implement the game not just on computers, but also on smartphones and even VR. But as for VR, I will talk about this at the very end of this concept, as it has it's own challenges and benefits that can be gained from previously implemented modules.

Core: Game Mechanics

Every object-oriented programmer already knows that OOP was originally designed to represent a physical object in a virtual environment. For instance:

// C++
class Car {
  private:
  std::string i_model;
  // ...etc...

  public:
  Car(string a_model) : i_model(a_model) {}
};

So, creating a Vanguard card would be quite easy:

// C++
class Card {
  private:
  int i_power;
  int i_grade;
  int i_critical;
  string i_name;
  string i_text;

  public:
  // ...
};

This could also be done for the deck, the field, the drop zone, the G zone and alike. With a set of classes like this, the foundation for the core would be implemented.

Now, with those classes alone, nothing is going to be play-able. You could programatically instantiate a class and assign it values - but, this won't do any good. Instead, this Card class would have to be defined as an abstract class to be inherited by other classes, and would thus instead be a CardBase. And for the ease of development, it would possibly make more sense to implement the cards as scripts. Since AngelScript plays extremely nicely with C++ and is also type-safe (thus easier to debug and error-trace), I will simply assume that C++ is used for the core itself and AngelScript for the cards alone, where the C++ core provides a base class that is to be inherited by each and every card.

During a game, many events occur; drawing, drive triggers, damage triggers and alike. So my proposal is, to implement the core as an event loop where events are used to control the flow with a global state (the game state). Assume this as a basic game state:

class State {
  private:
  Field i_field;
  Player i_player1; // holds damage, deck, drop zone, G-zone, bind zone
  Player i_player2;
};

Now, assume that each state can emit and and listen on several of the typical events. At this point, you would have essentially created an object, that holds several objects to itself, whith each card being currently loaded and designated to their current position on the board. Creating an instance of a card like Blaster Blade, adding it to the player 1's deck, and then triggering a draw event would move that Blaster Blade from the current player's deck into their hand. And with that, you have about the most basic implementation of the core mechanics.

Card effects

When I looked at some actual Vanguard cards after watching the G-Series, I noticed that, just like in Yu-Gi-Oh, effects habe become extremely diversified. Several automatic effects upon conditions being met (Brave, Unite, ...) are quite an addition on what I am used to, since they effectively create an effect-flavour, so to say, that spans across an entire archtype. However, each card may implement them differently, or check the conditions differently. Since this is the case, each card must implement a minimum subset of methods: A constructor when the card is initially loaded (which may query the loaded card database for it's entry to set it as a property) and methods that are triggered when the card is drawn, discarded or placed on the field. However, there would be three ways to achieve this:

  1. Implement an abstract CardBase with non-mandatory methods that reflect the respective events, such as onDraw, onReveal, onCall, onRide and alike.
  2. Implement a single method that receives ALL events. However, I feel like this would be an issue performance-wise as you would be repetitively calling the same method over and over.
  3. Create an abstract class which mandates the implementation of a constructor, destructor and a method to be called when the game itself is started (i.e. onLoad()). This last method may set up initial event listeners for the several events it wants to listen on and implements the various effects in those listeners. Each card, even if duplicated in a deck, may receive it's own instance in order to keep track of modified power levels and state of critical counters.

All of those must expose some way of obtaining a human readable reference to the card; a database record containing a copy of the artwork, and all of the text written on it, so it may be displayed to the user in the interface.

A more complex implementation would be to link each part of the effect to the event listeners being created, thus making it possible for an interface to highlight the effect that may be applied or in use. However, I don't think this feature is really neccessary and counts more towards a "nice to have" kind of feature. More important is that cards may implement their effects as event listeners and emit events as their effect occurs.

If a card requires the user to reveal a card, it may either emit an event to the respective player OR request user interaction. This could be implemented in the form of events, but since this would be an event that requires a response, I am leaning towards calling these "user actions" or "request for user action" instead, as the game is halted until the user has fulfilled the request. This might be selecting cards for a cost, a zone to call a unit to or selecting damage to be flipped for a counterblast.

Each card's definition may live in it's own class. In OCGCore, we use a serial number to represent those cards as Lua classes. As I am not aware if Vanguard cards have such a serial number, I am inclined to instead rely on set IDs, although reprints/reissues do happen, which would throw this idea immediately off-balance, as both the card database and the card objects would have to be made aware of which sets held their original and which held their respective reprints in the physical game. Alternatively, a snake-case version of the card name may be used, as those should, in theory, be unique.

Once a pattern for guaranteeing uniquely identifiable classes is established, they may either be implemented in several singular files, or in sets. In AngelScript, it is possible to group several classes together one file, pre-compile that into byte-code and load that. This would allow for entire sets of cards to be released as an amalgamation of cards represented as their set in which they were originally released in, or another form. Alternatively, amalgamating all classes into one file and periodicaly updating this bigger file would result in a cleaner update path, as each of those files may export a static value representing their version. This, together with a well-thoughtout resource compiler could even combine both card classes and the card database into a single file. For instance, a SQLite database holding both the card data and their pre-compiled card classes.

"Human readable" cards

Since an interface has to be able to display the game state to the user, it is cruical and self-explanatory that there must be a database holding information such as the name, text, power and an image of what the card is like int he physical game and what is represented in the virtualized environment. In YGOPro, we have a SQLite database containing this information, a folder containing card artwork, and another containing scripts. Since images can become quite vast, I would personally recommend to split the images from the database and possibly downloading them on-demand off a pre-defined server. This could also be bound together with an update-mechanism, where something like a Github repository is used soley for updating card effects and adjanced images. The card database may expose another static string which represents the Git commit used for the database, to ensure that images are always downloaded from the same commit as the card database. On further updates, revised images may be downloaded instead, overwriting existing ones, ensuring a form of integrity. Since static file URLs on Github are buildable off a commit hash, this seems like a viable option.

However, this requires an existing card database to exist. I haven't looked this up, but I am certain that there is an officially maintained database of all cards in existence that would serve as a resource for populating such a database. Unfortunately, some of the images I have come across do not look especially good. An alternative would be to simply post the raw card artwork and have the inferace dynamically render the card into it's complete state, effectively ensuring that the text is always readable and even allowing for things like customizing the backdrop behind effects to make the text more readable whilst not showing it while the card is on the field at all but only in a separate section of the view as the user selects it.

User Interface

By de-coupling the game's core, cards and database from the user interface, it would be possible to follow an approach that reminds me of RetroArch: By using a clever structure of events and actions, the user interface may only be aware of the methods the core exposes as to interact with the game, but leaving the inner workings to the core itself and only responding to the events emitted by the core. If a card is moved in the game and an according event is emitted, the interface my display such to the user.

But, this has another benefit: The game is actually highly portable now. Since the interface is split from the core, it would be possible to implement a touch interface for mobile phones, a controller-based interface for consoles and PCs and even a VR interface as well - because the core would still stay the same.

This would allow from interfaces ranging from a purely text-based interface to a fully featured, rich graphical interface, allowing people with absolutely no vision at all, to people with a headset strapped to their head, to play the same game - and possibly with others on a completely different platform as well. And yes - this is indeed where my impairment does come into play. I know a lot of blind people who never had a real chance of getting into TCGs simply because they couldn't work with the physical cards without some form of assistance or marking the physical cards - which made them turnament illegal - or because existing simulators were absolutely not accessible to them. By using a purely text-based interface, assistive technology like screen readers would be able to read the game to them as it progresses and allow them to use purely keyboard inputs to play the game. Imagine a terminal-ish window with a REPL running into which they can enter commands and control their actions in the game.

Local and remote core (Multiplayer)

Since the core would be decoupled from the rest of the resulting application, it would be possible to make the core available to be accessed over the internet, or any network in general. For this, just assume the regular TCP/IP stack - and in fact, assume WebSockets.

WebSockets has established itself as a great way to create interactive, networked applications in which events are sent to the server, and emitted from said server to be handled by the client. This would immediately enable things like local multiplayer, remote multiplayer over the internet - or even local multiplayer over Bluetooth, by simply using a suitable profile supporting the creation of something that resembles a TCP/IP socket through which data can be sent and received. Just sending the regular WebSocket traffic would be perfectly enough.

However, since Vanguard is a game of many events, you may wish to use something more suitable - like gRPC, Capt'n Proto or any of the other Protobuf based approaches. But I would HIGHLY recommend NOT creating a specific, "closed" system for communication, as it would make it harder for clients to be implemented. This is the reason I initially suggested WebSockets, as it is based on the HTTP protocol, only to leave it with a 201 Upgrade response and switch to the WebSockets protocol, which still uses the same socket and overal structure. It might not be as fast as a dedicated RPC channel such as gRPC but it has been battletested by many.

Portability

libocgcore is written in a very portable C++98/C99 mix, which makes it incredibly compatible across compilers and platforms. This also means, it technically can be compiled to any target, assuming that the APIs used do not rely on platform-specifics such as the file system. Those would have to be abstracted just enough to be cross-platform. Keeping the core itself as platform-independent as possible would also make it much easier to port it to other platforms in the future.

Keeping the game portable also has another benefit, aside from possibly being able to have an interface/client created for it on virtually any target platform: It also becomes modular. This comes from how RetroArch works: It consists of a core (i.e. VisualBoyAdvance) that communicates to an abstraction layer (libretro), which communicates to the frontend - and backwards. libretro effectively implements all the platform specific features like video, audio and the filesystem, so that the emulation core being used doe snot have to worry about any of this and can focus on running.

Do you see where I am getting at by now? :) Yes. Bushiroad does not just have Vanguard, but also many other TCGs. With a core set of events and actions established that may be streamlined across multiple TCGs, it might be possible to replicate libretro for Bushiroad's various games. However, this is a much more complicated kind of aproach and would require me to know about ALL the varous TCGs that there are (well, currently supported and continued, that is).

VR

Card games in VR are rare - they exist, but they don't feel too great. Now, here is an idea: What if you used one of the many existing MikuMikuDance-based stages, created a 3D model of a table, assigned parts of the table to the zones of the field and had the VR interface listen and respond to events and requests sent to and from by the core? The interface would just be responsible for rendering the game state, effectively making it possible for a player in VR to actually play with virtual cards in a possibly nice environment. By sending additional data (i.e. positional data) through the WebSockets connection already established, it would even be possible to create a completely interactive experience, backed by a local or remote core running. Sure, this is a whole different project - but, by going with the modular aproach described so far, VR would simply be "another interface". Yes, out of all that I described, this is possibly the least likely to be made - but hey, if I am dreaming so much already, I might just take the extra mile there.

Overall implementation

So far, I have described various aspects, possibilities and have sometimes poked at possible implementation details such as the abstract CardBase and the field state - which you might also refer to as game state. So, what would actually be needed?

  • Implement the core game mechanics as a set of classes, events and actions.
    • Game state, abstract Card class, ...
    • Each of those classes may be implemented independent of other parts of the software.
    • Keep the core as isolated as possible, to thus keep it as portable as possible.
  • Game mechanics relevant events and actions may be "public" to allow an interface to interact with it.
    • Drawing a card, calling a rear gard, ...
    • Decide on a RPC method to use for interacting with a remote core.
  • A card database that represents both a visual and human readable representation as well as a programatic version of the cards in the game.
    • This requires an existing card database which can be sourced from.
    • The core must provide game mechanic events and actions.
    • Each card has to be individually programmed.
    • Possibly make it possible for the interface to dynamically render cards by providing the raw artwork and a card template.
  • An interface that connects to the local or remote core and displays the state.
    • I.e.: Use Unity to create the objects and link individual zones displayed on the field to the zones used in the game state and listen to events for card movement and represent those changes within the rendered field.

Most of this is just putting together a solid core implementing the game mechanics and creating a public interface that can be used by both the interface and each individual card so it may programaticaly expose it's effects. The task that I believe is the most challenging is putting together a nice looking interface. Something that has nice animations, maybe plays some good background music and alike. I mean it could be as simple as some of the other TCGs looked like on a GameBoy - all it really needs to do is show the game state and make it possible for the user to interact with it.

The biggest part has to be the implementation of the cards. It has only started to exist in 2011 but I imagine there are easily more than 1000 cards already. And THIS is where I think the implementation of the official "Cardfight!! Vanguard Online" was hitting it's limit.

The strength of YGOPro is, that a whole community of several hundred people are creating card scripts and have created them since a very long time. The initial implementation was started at a company, which did possibly not think about involving it's community into this - but I believe this is where we could make a difference with an open source implementation.

I live alone, my card shop only offers Yu-Gi-Oh - and especially now, there is no way I can get into the card game. Sure, I could order a pack...but then what? Getting into a card game is not easy if you have literally nobody to play against. You first have to invest in a starter deck yourself, then convince someone to play it too and hope to convince more people as you do - and, that they stick around too. Plus, I live in germany...where card games don't seem to have an easy audience. Making the game available online would be a massive help for people in similiar situations as me. Or for turnament practice. What is the current metagame? Is card X viable for my deck and strategy? Is upcoming card Y good or bad? These things are best tested in a virtual environment, where you can't burn your pocket.

I believe it is possible - but I know that I am not the one that is capable of doing this. Well, I could implement the core, and I just might do it too out of boredom during self-quarantining, but there are many parts which I just can not do as much as I want to. Either due to the lack of talent in graphical design and modeling or due to the lack of game experience. Like most TCGs, there possibly are a lot of rules that are either not shown or explained in the anime, let alone properly used. Heck, I heared about "Legion Break", but because the "Legion Mate" arc was never dubbed, I quite frankly never saw it (because for me to read subs, I have to pause each time the text changes...so I am basically pausing every second which makes watching a subbed anime a pure massive pain in the ass).

So yeah... I hope someone can use this concept, this little brainchild of mine, and do something useful with it. I am all open to discussing possible implementations or other ideas. And maybe, just maybe, someone sees this, and feels like they could do it. :)

If you liked this, then you are free to upvote this and spread it; to game-dev forums or other subreddits. I have made sure to keep my Markdown formatting to the minimum so it should be compatible to every place that uses Connonmark or the default Markdown specification. Then again, I am used to GFM so...yeah.

You can hit me up on twitter: @IngwiePhoenix On Discord: IngwiePhoenix#6637 On Matrix: @ingwiephoenix:ingwie.io Or E-Mail: ingwie2000@gmail.com

I wish you a great day and happy self-quarantining :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment