Page 1 of 2

ZDCode II - The pretty language that compiles to DECORATE!

PostPosted: Sat Oct 13, 2018 11:12 pm
by Gustavo6046
ZDCode II
The language that compiles to ye olde DECORATE!

Take this example:
Code: Select allExpand view
class RunZombie inherits ZombieMan replaces ZombieMan #2055
{
    set Gravity to 0.4; // high up...
    set Speed to 0;
    is NOBLOCKMONST;
    set Speed to 0;

    label See
    {
        POSS AB 5 A_Recoil(-0.7);
        TNT1 A 0 A_Chase;
        POSS A 0 A_FaceTarget();
        POSS AB 4 A_Recoil(-0.7);
        TNT1 A 0 A_Chase;
        POSS A 0 A_FaceTarget();
        POSS ABCD 3 A_Recoil(-0.7);
        TNT1 A 0 A_Chase;
        POSS A 0 A_FaceTarget();
        goto RunLoop;
    };

    function Jump
    {
        while ( z == floorz )
        {
            POSS A 5 [Bright];
            POSS A 11 ThrustThingZ(0, 30, 0, 1);
        };
        POSS AB 2 A_Chase;
    };

    label RunLoop
    {
        x3
        {
            POSS ABCD 2 A_Recoil(-0.7);
            TNT1 A 0 A_Chase;
            POSS A 0 A_FaceTarget();
        };

        if ( health > 5 )
            call Jump;

        loop;
    };
}


This is what happens when that beauty goes through ZDCode II:

Code: Select allExpand view
Actor _Call0 : Inventory {Inventory.MaxAmount 1}


Actor RunZombie : ZombieMan replaces ZombieMan 2055
{
    Gravity 0.4
    Speed 0.0
   
    +NOBLOCKMONST
   
    States {
        F_Jump:
        _WhileBlock0:
            TNT1 A 0 A_JumpIf(!(z == floorz), 4)
            POSS A 5  Bright
            POSS A 11 ThrustThingZ(0.0, 30.0, 0.0, 1.0)
            TNT1 A 0 A_Jump(255, "_WhileBlock0")
            TNT1 A 0
            POSS A 2 A_Chase
            POSS B 2 A_Chase
       
       
        See:
            POSS A 5 A_Recoil(-0.7)
            POSS B 5 A_Recoil(-0.7)
            TNT1 A 0 A_Chase
            POSS A 0 A_FaceTarget
            POSS A 4 A_Recoil(-0.7)
            POSS B 4 A_Recoil(-0.7)
            TNT1 A 0 A_Chase
            POSS A 0 A_FaceTarget
            POSS A 3 A_Recoil(-0.7)
            POSS B 3 A_Recoil(-0.7)
            POSS C 3 A_Recoil(-0.7)
            POSS D 3 A_Recoil(-0.7)
            TNT1 A 0 A_Chase
            POSS A 0 A_FaceTarget
            goto RunLoop
       
        RunLoop:
            POSS A 2 A_Recoil(-0.7)
            POSS B 2 A_Recoil(-0.7)
            POSS C 2 A_Recoil(-0.7)
            POSS D 2 A_Recoil(-0.7)
            TNT1 A 0 A_Chase
            POSS A 0 A_FaceTarget
            POSS A 2 A_Recoil(-0.7)
            POSS B 2 A_Recoil(-0.7)
            POSS C 2 A_Recoil(-0.7)
            POSS D 2 A_Recoil(-0.7)
            TNT1 A 0 A_Chase
            POSS A 0 A_FaceTarget
            POSS A 2 A_Recoil(-0.7)
            POSS B 2 A_Recoil(-0.7)
            POSS C 2 A_Recoil(-0.7)
            POSS D 2 A_Recoil(-0.7)
            TNT1 A 0 A_Chase
            POSS A 0 A_FaceTarget
            TNT1 A 0 A_JumpIf(!(health > 5.0), 3)
                TNT1 A 0 A_GiveInventory("_Call0")
                Goto F_Jump
            _CLabel0:
                TNT1 A 0 A_TakeInventory("_Call0")
            TNT1 A 0
            loop
    }
}


Yes, I know – the output code is quite cryptic, but you're not meant to touch that – just slap the output in your WAD and... look at what happens!

Available on GitHub.

Re: ZDCode II: The language that compiles to DECORATE!

PostPosted: Mon Oct 15, 2018 6:29 am
by Nash
How is this better than just using ZScript, especially if one is programming-literate enough to learn ZDCode's syntax - wouldn't it be less hassle and more efficient for them to just do it directly in the engine with ZScript?

Re: ZDCode II: The language that compiles to DECORATE!

PostPosted: Fri Oct 19, 2018 4:21 pm
by Gustavo6046
This programming language targets older versions of ZDoom and ZDoom-derived source ports like Zandronum, most of which don't support ZScript. Thus, it is advised to use ZDCode only as a compatible alternative to DECORATE, not as a more flexible one (even though it is still more powerful).

Re: ZDCode II: The language that compiles to DECORATE!

PostPosted: Tue Oct 23, 2018 5:35 pm
by Gustavo6046
I've got to announce two cool new things:


Re: ZDCode II: The language that compiles to DECORATE!

PostPosted: Wed Jan 30, 2019 11:41 pm
by TDRR
This is really cool, i got to say, but is there any manual for it? I don't even know how to install it, and much less what are the available commands.

Re: ZDCode II: The language that compiles to DECORATE!

PostPosted: Fri Feb 08, 2019 1:52 pm
by Gustavo6046
TDRR wrote:This is really cool, i got to say, but is there any manual for it? I don't even know how to install it, and much less what are the available commands.


A more comprehensive documentation is currently on the to-do list for the language. To install it, one may simply use the Releases area in the repository, and download the source code zip. Currently, due to cross-platforming errors in the distribution script, we are unable to provide Windows binaries, so you will have to install Python 3 and use ZDCode as a module.

To be able to use ZDCode as a module from anywhere, first you need to install it, which can be done using two simple commands (assuming you have Python 3 installed, that it is executed as 'python' on Windows, and that you also have Git installed):

Code: Select allExpand view
git clone https://github.com/Gustavo6046/ZDCode
python -m pip install .


Then, you can use it using the following invocation:

Code: Select allExpand view
python -m zdcode LotsOfCode.zdc LotsOfCode.dec


where LotsOfCode.zdc is the input ZDCode file, which will be compiled, and stored into a new file called LotsOfCode.dec. You may, of course, use other filenames instead of LotsOfCode, but that's just an example. We don't even require the extensions to be those, though I would say using zdc for ZDCode and dec for ZDoom DECORATE is a good standard to follow.

Honestly, I wish I had written this in JavaScript, so it would be usable from the Web, and it would, as a bonus, be runnable offline using NodeJS.

Re: ZDCode II: The language that compiles to DECORATE!

PostPosted: Fri Feb 08, 2019 9:44 pm
by TDRR
Nice, got it installed. It would be really cool if Zandronum adopted this language as a natively accepted one, maybe in a ZDCODE lump that would be parsed similar to a DECORATE one?

Re: ZDCode II: The language that compiles to DECORATE!

PostPosted: Sat Feb 09, 2019 11:07 am
by Gustavo6046
TDRR wrote:Nice, got it installed. It would be really cool if Zandronum adopted this language as a natively accepted one, maybe in a ZDCODE lump that would be parsed similar to a DECORATE one?


Well, ZDCode isn't very different from DECORATE, it merely compiles to DECORATE. I don't think that would be necessary, unless maybe when including the original ZDCode source code, or when making the compilation process automatic. Additionally, the standard ZDCode compiler is in Python, while the vast majority of source ports are in C or C++.

Also, you can import other ZDCode definitions using preprocessor directives, e.g.:

Code: Select allExpand view
#INCLUDE Filename_Without_Spaces.zdc


Currently imported scripts can't import other scripts, and you can not import filenames with spaces, but a new version is on the works, with a much better preprocessor, and a few issues corrected.

It is not possible to compile ZDCode lumps within WADs, PK3s, or any other archive/container format yet. It is necessary to have them as separate files in the filesystem.

Re: ZDCode II: The language that compiles to DECORATE!

PostPosted: Sat Feb 09, 2019 11:22 am
by Enjay
Please forgive me for being obtuse here but, a bit like Nash wondering about what this offers versus ZSCRIPT, I'm actually wondering what it offers versus DECORATE. As far as I can see, it takes one set of text format, mostly human readable code (the ZDCode input) and converts it to another set of text format, mostly human readable code (i.e. the DECORATE output).

I'm obviously missing something here, but why is it better to code in ZDCode and compile it into DECORATE instead of just writing DECORATE code directly?

Re: ZDCode II: The language that compiles to DECORATE!

PostPosted: Sat Feb 09, 2019 1:48 pm
by Gustavo6046
Enjay wrote:I'm obviously missing something here, but why is it better to code in ZDCode and compile it into DECORATE instead of just writing DECORATE code directly?


With ZDCode, you can use a special set of blocks (like while, if, etc), and even functions, that make the code more readable and organized. They might not be very powerful (functions don't accept parameters, because compatible DECORATE doesn't know scope or even local variables), but they are a great improvement in terms of how the code looks. It can also be very useful, for example, when repeating the same state a large amount of times (using the repeat block, aka 'x'), or when waiting for a simple condition (e.g. 'while ( z > floorz )' to repeat a state (or block of) until the actor lands).

Additionally, the shiny new preprocessor, that was just today added to the GitHub repository, allows for powerful macro replacement, conditional inclusion (or exclusion) of codes centered around preprocessor definitions, and even the (recursive) inclusion of multiple ZDCode files into a single DECORATE file, along with error messages that are easier to understand and use.

Let's say we have an offending line:

Code: Select allExpand view
#DEFINE ANNOYING

class RunZombie inherits ZombieMan replaces ZombieMan #2055
{
    set Gravity to 0.4; // high up...
    set Speed to 0;
    is NOBLOCKMONST;
    set Speed to 0;

    Thanos snapped this code.
 
    label See {}
}


Which is obviously the line that doesn't follow the language's syntax.

If we try to compile this file with the latest version of ZDCode, the error message is sound and clear:

Code: Select allExpand view
Traceback (most recent call last):
  File "/usr/lib/python3.6/runpy.py", line 193, in _run_module_as_main
    "__main__", mod_spec)
  File "/usr/lib/python3.6/runpy.py", line 85, in _run_code
    exec(code, run_globals)
  File "zdcode/__main__.py", line 13, in <module>
    dec = zdcode.ZDCode.parse(open(sys.argv[1]).read(), os.path.dirname(sys.argv[1])).decorate()
  File "zdcode/__init__.py", line 518, in parse
    data = zdlexer.parse_code(code.strip(' \t\n'), dirname=dirname)
  File "zdcode/zdlexer.py", line 474, in parse_code
    return parse_postcode(preprocess_code(code, this_fname=filename, rel_dir=dirname))
  File "zdcode/zdlexer.py", line 471, in parse_postcode
    raise ZDParseError(m[1], postcode[int(m[2])])
zdlexer.ZDParseError: expected one of "'set' keyword", "isn't", '+', '-', '\\s+', 'combo', 'function ', 'is', 'label', 'method ', 'state', '}' at line 10 in "examples/JumpZombie.zc2"
>     Thanos snapped this code.


Of course, there is a traceback above, but always focus in the last few lines:

Code: Select allExpand view
zdlexer.ZDParseError: expected one of "'set' keyword", "isn't", '+', '-', '\\s+', 'combo', 'function ', 'is', 'label', 'method ', 'state', '}' at line 10 in "examples/JumpZombie.zc2"
>     Thanos snapped this code.

Re: ZDCode II: The language that compiles to DECORATE!

PostPosted: Sat Feb 09, 2019 2:21 pm
by Graf Zahl
Gustavo6046 wrote:If we try to compile this file with the latest version of ZDCode, the error message is sound and clear:

Code: Select allExpand view
Traceback (most recent call last):
  File "/usr/lib/python3.6/runpy.py", line 193, in _run_module_as_main
    "__main__", mod_spec)
  File "/usr/lib/python3.6/runpy.py", line 85, in _run_code
    exec(code, run_globals)
  File "zdcode/__main__.py", line 13, in <module>
    dec = zdcode.ZDCode.parse(open(sys.argv[1]).read(), os.path.dirname(sys.argv[1])).decorate()
  File "zdcode/__init__.py", line 518, in parse
    data = zdlexer.parse_code(code.strip(' \t\n'), dirname=dirname)
  File "zdcode/zdlexer.py", line 474, in parse_code
    return parse_postcode(preprocess_code(code, this_fname=filename, rel_dir=dirname))
  File "zdcode/zdlexer.py", line 471, in parse_postcode
    raise ZDParseError(m[1], postcode[int(m[2])])
zdlexer.ZDParseError: expected one of "'set' keyword", "isn't", '+', '-', '\\s+', 'combo', 'function ', 'is', 'label', 'method ', 'state', '}' at line 10 in "examples/JumpZombie.zc2"
>     Thanos snapped this code.


Sound and clear - yeah, right. I'd call that a lot of useless clutter that obstructs the real problem in a wall of text any normal person will have problems following through.

Re: ZDCode II: The language that compiles to DECORATE!

PostPosted: Sun Feb 10, 2019 1:11 pm
by Gustavo6046
Graf Zahl wrote:any normal person will have problems following through.


Well, I'm still looking for a way to eliminate the traceback. I guess I could print instead of raising an exception.

I just pushed to Git a commit that removes the ugly and unnecessary Python traceback from ZDCode parser errors.

Re: ZDCode II: The language that compiles to DECORATE!

PostPosted: Tue Oct 08, 2019 3:45 pm
by Gustavo6046
So I decided to revisit ZDCode, this time to add anonymous classes!

They're basically syntax sugar so you can quickly define a class you want to use, and that you know you will only use once. E.g. a RandomSpawner you define in the spot for A_SpawnItemEx:

Code: Select allExpand view
class AaaSpawner {
    label Spawn {
        TNT1 A 35;
        TNT1 A 0 A_SpawnItemEx(class extends TeleportFog {
            set Translation to "Ice";
        });
        TNT1 A 0 A_SpawnItemEx(class extends RandomSpawner {
            set DropItem to "ChaingunGuy", 128, 22;
            set DropItem to "Revenant", 200, 6;
            set DropItem to "ArchVile", 255, 1;
        });
        Loop;
    }
}


Unfortunately I am not able to update the VS Code plugin in the Marketplace. I will see what I can do about that.
But the new ZDCode compiler version should be up now.

Re: ZDCode II - The pretty language that compiles to DECORAT

PostPosted: Thu Nov 07, 2019 1:30 pm
by Gustavo6046
I added macro functions! Instead of creating internal DECORATE labels (like regular functions) to reuse code, they have their states added directly to inject statements that reference them. This might be a bit more efficient, at the cost of output size if there are many calls to a non-small macro.

See example below.
Code: Select allExpand view
class AaaSpawner {
    is NOGRAVITY;

    macro SpawnEither(A, B, C) {
        TNT1 A 0 A_SpawnItemEx(class extends TeleportFog {
            set Translation to "Ice";
        });
        TNT1 A 0 A_SpawnItemEx(class extends RandomSpawner {
            set DropItem to A, 128, 22;
            set DropItem to B, 200, 6;
            set DropItem to C, 255, 1;
        });
    };

    label Spawn {
        TNT1 A 35;

        x 3 {
            sometimes 60 inject SpawnEither("ChaingunGuy", "Revenant", "ArchVile");
            sometimes 60 inject SpawnEither("ChaingunGuy", "Revenant", "PainElemental");
        };

        Loop;
    };
}

Re: ZDCode II - The pretty language that compiles to DECORAT

PostPosted: Mon Nov 11, 2019 4:15 am
by CBM
looks interesting, it would be cool if it included a GUI editor with codecompletion and syntax highlighting as well as a complete reference to the language and code examples

anything in zcode II that will make generation of actors based soly on frame information very easy?
I am considering adding support for actor definitions to my md2modeldef tool