ZDCode II - The pretty language that compiles to DECORATE!

Any utility that assists in the creation of mods, assets, etc, go here.
Forum rules
The Projects forums are ONLY for YOUR PROJECTS! If you are asking questions about a project, either find that project's thread, or start a thread in the General section instead.

Got a cool project idea but nothing else? Put it in the project ideas thread instead!

Projects for any Doom-based engine (especially 3DGE) are perfectly acceptable here too.

Please read the full rules for more details.

ZDCode II - The pretty language that compiles to DECORATE!

Postby Gustavo6046 » Sat Oct 13, 2018 11:12 pm

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.
Last edited by Gustavo6046 on Tue Oct 08, 2019 3:58 pm, edited 1 time in total.
User avatar
Gustavo6046
 
Joined: 13 May 2017
Location: In an urban area in Brazil.
Discord: Gustavo6046#9009

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

Postby Nash » Mon Oct 15, 2018 6:29 am

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?
User avatar
Nash
 
 
 
Joined: 27 Oct 2003
Location: Kuala Lumpur, Malaysia
Github ID: nashmuhandes

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

Postby Gustavo6046 » Fri Oct 19, 2018 4:21 pm

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).
User avatar
Gustavo6046
 
Joined: 13 May 2017
Location: In an urban area in Brazil.
Discord: Gustavo6046#9009

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

Postby Gustavo6046 » Tue Oct 23, 2018 5:35 pm

I've got to announce two cool new things:

User avatar
Gustavo6046
 
Joined: 13 May 2017
Location: In an urban area in Brazil.
Discord: Gustavo6046#9009

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

Postby TDRR » Wed Jan 30, 2019 11:41 pm

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.
User avatar
TDRR
iDeas from the deep (pit of hacks)
 
Joined: 11 Mar 2018
Location: Venezuela
Operating System: Windows Vista/7 64-bit
Graphics Processor: Intel (Modern GZDoom)

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

Postby Gustavo6046 » Fri Feb 08, 2019 1:52 pm

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.
User avatar
Gustavo6046
 
Joined: 13 May 2017
Location: In an urban area in Brazil.
Discord: Gustavo6046#9009

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

Postby TDRR » Fri Feb 08, 2019 9:44 pm

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?
User avatar
TDRR
iDeas from the deep (pit of hacks)
 
Joined: 11 Mar 2018
Location: Venezuela
Operating System: Windows Vista/7 64-bit
Graphics Processor: Intel (Modern GZDoom)

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

Postby Gustavo6046 » Sat Feb 09, 2019 11:07 am

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.
User avatar
Gustavo6046
 
Joined: 13 May 2017
Location: In an urban area in Brazil.
Discord: Gustavo6046#9009

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

Postby Enjay » Sat Feb 09, 2019 11:22 am

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?
User avatar
Enjay
Everyone is a moon, and has a dark side which he never shows to anybody. Twain
 
 
 
Joined: 15 Jul 2003
Location: Scotland

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

Postby Gustavo6046 » Sat Feb 09, 2019 1:48 pm

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.
User avatar
Gustavo6046
 
Joined: 13 May 2017
Location: In an urban area in Brazil.
Discord: Gustavo6046#9009

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

Postby Graf Zahl » Sat Feb 09, 2019 2:21 pm

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.
User avatar
Graf Zahl
Lead GZDoom Developer
Lead GZDoom Developer
 
Joined: 19 Jul 2003
Location: Germany

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

Postby Gustavo6046 » Sun Feb 10, 2019 1:11 pm

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.
User avatar
Gustavo6046
 
Joined: 13 May 2017
Location: In an urban area in Brazil.
Discord: Gustavo6046#9009

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

Postby Gustavo6046 » Tue Oct 08, 2019 3:45 pm

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.
User avatar
Gustavo6046
 
Joined: 13 May 2017
Location: In an urban area in Brazil.
Discord: Gustavo6046#9009

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

Postby Gustavo6046 » Thu Nov 07, 2019 1:30 pm

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;
    };
}
User avatar
Gustavo6046
 
Joined: 13 May 2017
Location: In an urban area in Brazil.
Discord: Gustavo6046#9009

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

Postby CBM » Mon Nov 11, 2019 4:15 am

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
User avatar
CBM
Imp Slayer
 
Joined: 09 Oct 2019
Location: The Shores of Hell
Operating System: Windows 10/8.1/8 64-bit
Graphics Processor: nVidia with Vulkan support

Next

Return to Editors / Asset Manipulation

Who is online

Users browsing this forum: No registered users and 1 guest