Git Product home page Git Product logo

grammarsystem's People

Contributors

cervator avatar skaldarnar avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

grammarsystem's Issues

Update documentation

I'm cleaning up the engine wiki and moving some doc to modules, especially if they're inactive like the grammar system. @skaldarnar save us from the lack of grammar! :-)

Old Grammar System page:

The Grammar System (or Grammar Building System) uses the [[Procedural Architecture Grammar]] to generate building structures. It
is included in versions starting from stable #22.

Building Generator

Building Generators are used to create a [[Block Collection]] which can then be placed in the world. For the generation process,
the structure's dimension and a proper [[grammar|Procedural Architecture Grammar]] is needed. Please refeer to the corresponding sites
for more information.

Console Commands

The Grammar System provides console commands to test the building generation. At the moment the system is quite restricted. You can only
call a pre defined generator with specifying width, depth and height of the building. To do so, just type
\build <width> <heigth> <depth>
in the [[Console|Console Help]]. The generated building will be placed right in front of the player.

Related Links

  • [[Procedural Architecture Grammar]]
  • [[Block Collection]]

Old PAG page:

This is a work in Progress

You read that right, this is a grammar for our grammar. That is, this defines the format for the grammars one can use for procedural generation.

PAG specification

PAG := Header 'grammar' Identifier ':' Section+

Header

The PAG-Header will store information for the grammar system, such as which type of structure is created by this grammar, and provide the possibility to assign constants you can later use in the grammar rules.

Header := Declaration*

Declaration := '#'? Identifier ':=' expr ';'

A header declaration that starts with a # will be interpreted as grammar info field, such as building type, or fitting biomes. You can define module dependencies for the grammar here as well:

    #dependencies := ["myModule", "otherAwesomeModule"];

You may have noticed that different forms of expressions are allowed on the right side, we will come to that later. Simple constants can be defined in a similar way:
floor_height := 3;

Sections

Sections make up the grammar and group the grammar rules with the same priority. The priority is used to control the order in which derivations are selected. Of course it is possible to have just one section for all rules.

Section := 'Priority' decimalLiteral ':' ruleStatement+

Each ruleStatement is of the form predecessor -> successor. Note that every rule has to be ended by a semicolon. Furthermore, you can specify guards (boolean expressions that guard whether the rule can be applied or not) and probabilities. Guards and probabilities are optional for every rule.

ruleStatement := Predecessor (':' expression)? '->' Successor (':' expression)? ('|' Successor (':' expression)?)+ ';'

Predecessor := Identifier

The successor can either be an identifier, which denotes another rule, a base rule or a sequence of the former enclosed in braces.

Successor := Identifier | Baserule | '{' (Identifier | BaseRule)* '}'

Expressions

The following set of expressions are supported by the grammar system. You can use standard Boolean and arithmetic operations, numbers (integer and decimal), identifiers and strings and lists of expressions. Furthermore, there are a few special operations/method calls.

expression := primary
        | functionCall
        | ('Shape' | 'Scope') '.' ('occ' | 'visible') '(' expression ')'
        | '[' expression ']'
        | ('+' | '-') expression
        | '!' expression
        | expression ('*' | '/' | '%') expression
        | expression ('+' | '-') expression
        | expression ('<=' | '>=' | '<' | '>') expression
        | expression ('==' | '!=') expression
        | expression '&&' expression
        | expression '||' expression

primary := '(' expression ')'  | literal 'r'? | Identifier

The only function call currently available is the random selection from either a list or a defined range.

    functionCall := randomSelection

    randomSelection := 'Random' '(' (exprList | rangeExpr) ')'

An expression list is simply a sequence of expressions:

    exprList := expression (',' expression)*

You can define a range of integers with the following notation:

    rangeExpr := expression '..' expression

E.g. you can select a random block type from a list or define a scale or measure of length randomly within a range from .. to.

    wall_mat := Random("cobblestone", "stonebricks", "stone");
    number_floors := Random(2..5);

The occlusion and visibility checks are useful as guards. They can be used to determine whether the current scope is occluded by any other shape or scope or if a specific shape is visible from the current scope. This can be used to place doors on walls that face to the street. Note that the occlusion test for scopes is faster but less accurate than the test against shapes.

    wall : Shape.visible("street") -> door_wall;
    wall : Scope.occ("nonparent") == "none" -> win_wall;

Base Rules

The following basic rules are supported by the grammar.

BaseRule := SetRule | DivideRule | SplitRule | RepeatRule | Invoke | TransformationRule

SetRule := 'set' '(' '"' qualifiedIdentifier '"' ')'

DivideRule := 'divide' Direction '{' ('[' Size ']' Successor)+  '}'

SplitRule := 'split' '{' ('[' SplitType ']' Successor)+ '}'

RepeatRule := 'repeat' Direction '['expression']' Successor

The invocation of other grammars is just a proposal for allowing the reuse of code. It may be erased from the specification if
it proves not to be practical.

Invoke := 'invoke' '(' qualifiedIdentifier ')'

Basic transformation of shapes is supported by the following rules.

TransformationRule := ScaleRule | TranslateRule | RotateRule

ScaleRule := 'S' '(' numericLiteral (',' numericLiteral ',' numericLiteral)? ')'

TranslateRule := 'T' '(' numericLiteral ',' numericLiteral ',' numericLiteral ')'

RotateRule := ('Rx' | 'Ry' | 'Rz') '(' numericLiteral ')'

Moreover, we need special rules for the roof construction:

Roof := 'Roof' '(' roofType ',' expression ')' '{' successor '}'

roofType := 'hipped' | ...

The following attributes are used in the base rules.

Direction := 'X' | 'x' | 'Y' | 'y' | 'Z' | 'z'

Size := decimalLiteral ('%')? | floatingPointLiteral

SplitType := 'faces' | 'sidefaces' | 'edges' | 'vertices' | 'walls' | 'floor'

Literals

literal := numericLiteral | booleanLiteral

booleanLiteral := 'true' | 'false'

numericLiteral := decimalLiteral | floatingPointLiteral

decimalLiteral := '0' | '1'..'9' Digit*

floatingPointLiteral := Digits '.' Digits? | '.' Digits | Digits 'f'

Digits := Digit*

Digit := '0'..'9'

Identifiers

Identifiers (such as predecessor and variable names) have to start with a letter, followed by any sequence of alphnumerical characters.
Qualified Identifiers will be used to specify assets (such as blocks or other grammar files).

Identifier := Letter (Letter | Digit)*

Letter := 'a'..'z' | 'A'..'Z' | '_'

qualifiedIdentifier := Identifier (':' Identifier)* 

Comments, Whitespaces, ...

Comments, whitespaces and such are skipped during parsing and have no influence on the actual grammar functionality.
The rules are denoted using a syntax similar to ANTLR.

COMMENT := '/*' (.*)? '*/' -> channel(HIDDEN)

LINE_COMMENT := '//' ~[\r\n]* -> channel(HIDDEN)

WS := ( '\r' | '\t' | ' ' | '\n' )+ -> channel(HIDDEN)

I use the regular expression notation for + (1 or more), ? (at most 1), brackets for characters ranges, * (for 0 or
more), __ for escaping, ' ' for literals and parenthesis for grouping. Furthermore, . is a wildcard character and
~ denotes "everything until ...".

Examples

The following code is an example of a PAG-grammar. It is closely related to a example provided by Müller, Wonka et al.

#type := house;

window_spacing  := 4;
window_width    := 2;
window_depth    := .5;
window_height   := 1;
door_height     := 2;
door_width      := 2;
roof_angle      := 45;

grammar TestHouse:

Priority 1:
    footprint -> {
        S(1r, building_height, 1r) facades
        T(0, building_height, 0) I("prism") roof
    };

    Priority 2:
        facades -> Split {
            ["sidefaces"] facade
        };

        facade : Shape.visible("street") 
            -> Divide "X" {
                [1r] tiles
                [door_width * 1.5] entrance
            } : 0.5
            -> Divide "X" {
                [door_width * 1.5] entrance
                [1r] tiles          
            } : 0.5
            ;
        facade -> tiles;

        tiles -> Repeat "X" [window_spacing] tile;

        tile -> Divide "X" {
            [1r] wall
            [window_width] Divide "Y" {
                    [window_height] window
                    [1r] wall
                }
            [1r] wall
        };

        window : Scope.occ("noparent") != "none" -> wall;
        window -> {
            S(1r, 1r, window_depth) Set("enginge.glass")
        };

        entrance -> Divide "X" {
            [1r] wall
            [door_width] Divide "Y" {
                    [door_height] door
                    [1r] wall
                }
            [1r] wall
        };

        door -> Set("core.door");

        wall -> Set(Random("cobblestone", "stonebricks"));

    Priority 3:
        roof -> Split {
            ["sidefaces"] covering
            ["sideedges"] roofedge
            ["topedge"] roofedge
        };

        covering -> Set("brick" : "stair");

        roofedge -> Set("stone");

--- Want to back this issue? **[Post a bounty on it!](https://www.bountysource.com/issues/30148170-update-documentation?utm_campaign=plugin&utm_content=tracker%2F1857106&utm_medium=issues&utm_source=github)** We accept bounties via [Bountysource](https://www.bountysource.com/?utm_campaign=plugin&utm_content=tracker%2F1857106&utm_medium=issues&utm_source=github).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.